- expressions can now be read from streams; the input expression can contain
[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-2000 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 #define yylex ginac_yylex
49 #define yyerror ginac_yyerror
50
51 // Parsed output expression
52 ex parsed_ex;
53
54 // Last error message returned by parser
55 static string parser_error;
56 %}
57
58 /* Tokens (T_LITERAL means a literal value returned by the parser, but not
59    of class numeric or symbol (e.g. a constant or the FAIL object)) */
60 %token T_NUMBER T_SYMBOL T_LITERAL T_DIGITS T_EQUAL T_NOTEQ T_LESSEQ T_GREATEREQ T_MATRIX_BEGIN T_MATRIX_END
61
62 /* Operator precedence and associativity */
63 %right '='
64 %left T_EQUAL T_NOTEQ
65 %left '<' '>' T_LESSEQ T_GREATEREQ
66 %left '+' '-'
67 %left '*' '/' '%'
68 %nonassoc NEG
69 %right '^'
70 %nonassoc '!'
71
72 %start input
73
74
75 /*
76  *  Grammar rules
77  */
78
79 %%
80 input   : exp {
81                 try {
82                         parsed_ex = $1;
83                         YYACCEPT;
84                 } catch (exception &e) {
85                         parser_error = e.what();
86                         YYERROR;
87                 }
88         }
89         | error         {yyclearin; yyerrok;}
90         ;
91
92 exp     : T_NUMBER              {$$ = $1;}
93         | T_SYMBOL              {$$ = $1.eval();}
94         | T_LITERAL             {$$ = $1;}
95         | T_DIGITS              {$$ = $1;}
96         | T_SYMBOL '(' exprseq ')' {
97                 unsigned i = function::find_function(ex_to_symbol($1).getname(), $3.nops());
98                 $$ = function(i, static_cast<const exprseq &>(*($3.bp)));
99         }
100         | exp T_EQUAL exp       {$$ = $1 == $3;}
101         | exp T_NOTEQ exp       {$$ = $1 != $3;}
102         | exp '<' exp           {$$ = $1 < $3;}
103         | exp T_LESSEQ exp      {$$ = $1 <= $3;}
104         | exp '>' exp           {$$ = $1 > $3;}
105         | exp T_GREATEREQ exp   {$$ = $1 >= $3;}
106         | exp '+' exp           {$$ = $1 + $3;}
107         | exp '-' exp           {$$ = $1 - $3;}
108         | exp '*' exp           {$$ = $1 * $3;}
109         | exp '/' exp           {$$ = $1 / $3;}
110         | exp '%' exp           {$$ = $1 % $3;}
111         | '-' exp %prec NEG     {$$ = -$2;}
112         | '+' exp %prec NEG     {$$ = $2;}
113         | exp '^' exp           {$$ = pow($1, $3);}
114         | exp '!'               {$$ = factorial($1);}
115         | '(' exp ')'           {$$ = $2;}
116         | '[' list_or_empty ']' {$$ = $2;}
117         | T_MATRIX_BEGIN matrix T_MATRIX_END    {$$ = lst_to_matrix($2);}
118         ;
119
120 exprseq : exp                   {$$ = exprseq($1);}
121         | exprseq ',' exp       {exprseq es(static_cast<exprseq &>(*($1.bp))); $$ = es.append($3);}
122         ;
123
124 list_or_empty: /* empty */      {$$ = *new lst;}
125         | list                  {$$ = $1;}
126         ;
127
128 list    : exp                   {$$ = lst($1);}
129         | list ',' exp          {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
130         ;
131
132 matrix  : T_MATRIX_BEGIN row T_MATRIX_END               {$$ = lst($2);}
133         | matrix ',' T_MATRIX_BEGIN row T_MATRIX_END    {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($4);}
134         ;
135
136 row     : exp                   {$$ = lst($1);}
137         | row ',' exp           {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
138         ;
139
140
141 /*
142  *  Routines
143  */
144
145 %%
146 // Get last error encountered by parser
147 string get_parser_error(void)
148 {
149         return parser_error;
150 }
151
152 #ifndef NO_NAMESPACE_GINAC
153 } // namespace GiNaC
154
155 using GiNaC::parser_error;
156 #endif // ndef NO_NAMESPACE_GINAC
157
158 // Error print routine (store error string in parser_error)
159 int ginac_yyerror(char *s)
160 {
161         parser_error = string(s) + " at " + string(ginac_yytext);
162 }