1 /** @file input_parser.yy
3 * Input grammar definition for reading expressions.
4 * This file must be processed with yacc/bison. */
7 * GiNaC Copyright (C) 1999-2007 Johannes Gutenberg University Mainz, Germany
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "input_lexer.h"
34 #include "relational.h"
35 #include "operators.h"
47 #define YYERROR_VERBOSE 1
49 // Parsed output expression
52 // Last error message returned by parser
53 static std::string parser_error;
56 ex attach_index(const ex & base, ex i, bool covariant);
59 /* Tokens (T_LITERAL means a literal value returned by the parser, but not
60 of class numeric or symbol (e.g. a constant or the FAIL object)) */
61 %token T_EOF T_NUMBER T_SYMBOL T_LITERAL T_DIGITS T_EQUAL T_NOTEQ T_LESSEQ T_GREATEREQ
63 /* Operator precedence and associativity */
66 %left '<' '>' T_LESSEQ T_GREATEREQ
86 } catch (std::exception &err) {
87 parser_error = err.what();
93 exp : T_NUMBER {$$ = $1;}
95 if (is_lexer_symbol_predefined($1))
98 throw (std::runtime_error("unknown symbol '" + get_symbol_name($1) + "'"));
100 | T_LITERAL {$$ = $1;}
101 | T_DIGITS {$$ = $1;}
102 | T_SYMBOL '(' exprseq ')' {
103 std::string n = get_symbol_name($1);
106 throw (std::runtime_error("too many arguments to sqrt()"));
108 } else if (n == "pow" || n == "power") {
110 throw std::invalid_argument("wrong number of arguments to pow()");
111 $$ = power($3.op(0), $3.op(0));
113 unsigned i = function::find_function(n, $3.nops());
114 $$ = function(i, ex_to<exprseq>($3)).eval(1);
117 | exp T_EQUAL exp {$$ = $1 == $3;}
118 | exp T_NOTEQ exp {$$ = $1 != $3;}
119 | exp '<' exp {$$ = $1 < $3;}
120 | exp T_LESSEQ exp {$$ = $1 <= $3;}
121 | exp '>' exp {$$ = $1 > $3;}
122 | exp T_GREATEREQ exp {$$ = $1 >= $3;}
123 | exp '+' exp {$$ = $1 + $3;}
124 | exp '-' exp {$$ = $1 - $3;}
125 | exp '*' exp {$$ = $1 * $3;}
126 | exp '/' exp {$$ = $1 / $3;}
127 | '-' exp %prec NEG {$$ = -$2;}
128 | '+' exp %prec NEG {$$ = $2;}
129 | exp '^' exp {$$ = pow($1, $3);}
130 | exp '.' exp {$$ = attach_index($1, $3, true);}
131 | exp '~' exp {$$ = attach_index($1, $3, false);}
132 | exp '!' {$$ = factorial($1);}
133 | '(' exp ')' {$$ = $2;}
134 | '{' list_or_empty '}' {$$ = $2;}
135 | '[' matrix ']' {$$ = lst_to_matrix(ex_to<lst>($2));}
138 exprseq : exp {$$ = exprseq($1);}
139 | exprseq ',' exp {exprseq es(ex_to<exprseq>($1)); $$ = es.append($3);}
142 list_or_empty: /* empty */ {$$ = *new lst;}
146 list : exp {$$ = lst($1);}
147 | list ',' exp {lst l(ex_to<lst>($1)); $$ = l.append($3);}
150 matrix : '[' row ']' {$$ = lst($2);}
151 | matrix ',' '[' row ']' {lst l(ex_to<lst>($1)); $$ = l.append($4);}
154 row : exp {$$ = lst($1);}
155 | row ',' exp {lst l(ex_to<lst>($1)); $$ = l.append($3);}
164 // Attach index to expression
165 ex attach_index(const ex & base, ex i, bool covariant)
167 // Toggle index variance if necessary
168 if (is_a<varidx>(i)) {
169 const varidx &vi = ex_to<varidx>(i);
170 if (vi.is_covariant() != covariant)
171 i = vi.toggle_variance();
172 } else if (!covariant)
173 throw (std::runtime_error("index '" + get_symbol_name(i) + "' is not a varidx and cannot be contravariant"));
175 // Add index to an existing indexed object, or create a new indexed
176 // object if there are no indices yet
177 if (is_a<indexed>(base)) {
178 const ex &b = base.op(0);
180 for (unsigned n=1; n<base.nops(); n++)
181 iv.push_back(base.op(n));
183 return indexed(b, iv);
185 return indexed(base, i);
188 // Get last error encountered by parser
189 std::string get_parser_error(void)
196 // Error print routine (store error string in parser_error)
197 int ginac_yyerror(char *s)
199 GiNaC::parser_error = std::string(s) + " at " + std::string(ginac_yytext);