adapted to change symbol::getname() -> symbol::get_name()
[ginac.git] / ginac / input_parser.yy
1 /** @file input_parser.yy
2  *
3  *  Input grammar definition for reading expressions.
4  *  This file must be processed with yacc/bison. */
5
6 /*
7  *  GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
8  *
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.
13  *
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.
18  *
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
22  */
23
24
25 /*
26  *  Definitions
27  */
28
29 %{
30 #include <stdexcept>
31
32 #include "input_lexer.h"
33 #include "ex.h"
34 #include "relational.h"
35 #include "symbol.h"
36 #include "lst.h"
37 #include "power.h"
38 #include "exprseq.h"
39 #include "matrix.h"
40 #include "inifcns.h"
41
42 #ifndef NO_NAMESPACE_GINAC
43 namespace GiNaC {
44 #endif // ndef NO_NAMESPACE_GINAC
45
46 #define YYERROR_VERBOSE 1
47
48 // Parsed output expression
49 ex parsed_ex;
50
51 // Last error message returned by parser
52 static std::string parser_error;
53 %}
54
55 /* Tokens (T_LITERAL means a literal value returned by the parser, but not
56    of class numeric or symbol (e.g. a constant or the FAIL object)) */
57 %token T_NUMBER T_SYMBOL T_LITERAL T_DIGITS T_EQUAL T_NOTEQ T_LESSEQ T_GREATEREQ T_MATRIX_BEGIN T_MATRIX_END
58
59 /* Operator precedence and associativity */
60 %right '='
61 %left T_EQUAL T_NOTEQ
62 %left '<' '>' T_LESSEQ T_GREATEREQ
63 %left '+' '-'
64 %left '*' '/' '%'
65 %nonassoc NEG
66 %right '^'
67 %nonassoc '!'
68
69 %start input
70
71
72 /*
73  *  Grammar rules
74  */
75
76 %%
77 input   : exp {
78                 try {
79                         parsed_ex = $1;
80                         YYACCEPT;
81                 } catch (std::exception &err) {
82                         parser_error = err.what();
83                         YYERROR;
84                 }
85         }
86         | error         {yyclearin; yyerrok;}
87         ;
88
89 exp     : T_NUMBER              {$$ = $1;}
90         | T_SYMBOL {
91                 if (is_lexer_symbol_predefined($1))
92                         $$ = $1.eval();
93                 else
94                         throw (std::runtime_error("unknown symbol '" + ex_to_symbol($1).get_name() + "'"));
95         }
96         | T_LITERAL             {$$ = $1;}
97         | T_DIGITS              {$$ = $1;}
98         | T_SYMBOL '(' exprseq ')' {
99                 unsigned i = function::find_function(ex_to_symbol($1).get_name(), $3.nops());
100                 $$ = function(i, static_cast<const exprseq &>(*($3.bp))).eval(1);
101         }
102         | exp T_EQUAL exp       {$$ = $1 == $3;}
103         | exp T_NOTEQ exp       {$$ = $1 != $3;}
104         | exp '<' exp           {$$ = $1 < $3;}
105         | exp T_LESSEQ exp      {$$ = $1 <= $3;}
106         | exp '>' exp           {$$ = $1 > $3;}
107         | exp T_GREATEREQ exp   {$$ = $1 >= $3;}
108         | exp '+' exp           {$$ = $1 + $3;}
109         | exp '-' exp           {$$ = $1 - $3;}
110         | exp '*' exp           {$$ = $1 * $3;}
111         | exp '/' exp           {$$ = $1 / $3;}
112         | '-' exp %prec NEG     {$$ = -$2;}
113         | '+' exp %prec NEG     {$$ = $2;}
114         | exp '^' exp           {$$ = pow($1, $3);}
115         | exp '!'               {$$ = factorial($1);}
116         | '(' exp ')'           {$$ = $2;}
117         | '[' list_or_empty ']' {$$ = $2;}
118         | T_MATRIX_BEGIN matrix T_MATRIX_END    {$$ = lst_to_matrix(ex_to_lst($2));}
119         ;
120
121 exprseq : exp                   {$$ = exprseq($1);}
122         | exprseq ',' exp       {exprseq es(static_cast<exprseq &>(*($1.bp))); $$ = es.append($3);}
123         ;
124
125 list_or_empty: /* empty */      {$$ = *new lst;}
126         | list                  {$$ = $1;}
127         ;
128
129 list    : exp                   {$$ = lst($1);}
130         | list ',' exp          {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
131         ;
132
133 matrix  : T_MATRIX_BEGIN row T_MATRIX_END               {$$ = lst($2);}
134         | matrix ',' T_MATRIX_BEGIN row T_MATRIX_END    {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($4);}
135         ;
136
137 row     : exp                   {$$ = lst($1);}
138         | row ',' exp           {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
139         ;
140
141
142 /*
143  *  Routines
144  */
145
146 %%
147 // Get last error encountered by parser
148 std::string get_parser_error(void)
149 {
150         return parser_error;
151 }
152
153 #ifndef NO_NAMESPACE_GINAC
154 } // namespace GiNaC
155
156 using GiNaC::parser_error;
157 #endif // ndef NO_NAMESPACE_GINAC
158
159 // Error print routine (store error string in parser_error)
160 int ginac_yyerror(char *s)
161 {
162         parser_error = std::string(s) + " at " + std::string(ginac_yytext);
163         return 0;
164 }