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-2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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()"));
109 unsigned i = function::find_function(n, $3.nops());
110 $$ = function(i, ex_to<exprseq>($3)).eval(1);
113 | exp T_EQUAL exp {$$ = $1 == $3;}
114 | exp T_NOTEQ exp {$$ = $1 != $3;}
115 | exp '<' exp {$$ = $1 < $3;}
116 | exp T_LESSEQ exp {$$ = $1 <= $3;}
117 | exp '>' exp {$$ = $1 > $3;}
118 | exp T_GREATEREQ exp {$$ = $1 >= $3;}
119 | exp '+' exp {$$ = $1 + $3;}
120 | exp '-' exp {$$ = $1 - $3;}
121 | exp '*' exp {$$ = $1 * $3;}
122 | exp '/' exp {$$ = $1 / $3;}
123 | '-' exp %prec NEG {$$ = -$2;}
124 | '+' exp %prec NEG {$$ = $2;}
125 | exp '^' exp {$$ = pow($1, $3);}
126 | exp '.' exp {$$ = attach_index($1, $3, true);}
127 | exp '~' exp {$$ = attach_index($1, $3, false);}
128 | exp '!' {$$ = factorial($1);}
129 | '(' exp ')' {$$ = $2;}
130 | '{' list_or_empty '}' {$$ = $2;}
131 | '[' matrix ']' {$$ = lst_to_matrix(ex_to<lst>($2));}
134 exprseq : exp {$$ = exprseq($1);}
135 | exprseq ',' exp {exprseq es(ex_to<exprseq>($1)); $$ = es.append($3);}
138 list_or_empty: /* empty */ {$$ = *new lst;}
142 list : exp {$$ = lst($1);}
143 | list ',' exp {lst l(ex_to<lst>($1)); $$ = l.append($3);}
146 matrix : '[' row ']' {$$ = lst($2);}
147 | matrix ',' '[' row ']' {lst l(ex_to<lst>($1)); $$ = l.append($4);}
150 row : exp {$$ = lst($1);}
151 | row ',' exp {lst l(ex_to<lst>($1)); $$ = l.append($3);}
160 // Attach index to expression
161 ex attach_index(const ex & base, ex i, bool covariant)
163 // Toggle index variance if necessary
164 if (is_a<varidx>(i)) {
165 const varidx &vi = ex_to<varidx>(i);
166 if (vi.is_covariant() != covariant)
167 i = vi.toggle_variance();
168 } else if (!covariant)
169 throw (std::runtime_error("index '" + get_symbol_name(i) + "' is not a varidx and cannot be contravariant"));
171 // Add index to an existing indexed object, or create a new indexed
172 // object if there are no indices yet
173 if (is_a<indexed>(base)) {
174 const ex &b = base.op(0);
176 for (unsigned n=1; n<base.nops(); n++)
177 iv.push_back(base.op(n));
179 return indexed(b, iv);
181 return indexed(base, i);
184 // Get last error encountered by parser
185 std::string get_parser_error(void)
192 // Error print routine (store error string in parser_error)
193 int ginac_yyerror(char *s)
195 GiNaC::parser_error = std::string(s) + " at " + std::string(ginac_yytext);