]> www.ginac.de Git - ginac.git/blob - ginac/input_lexer.ll
"(x+1).subs(x==x-1)" now returns the correct result "x" instead of "x-1"
[ginac.git] / ginac / input_lexer.ll
1 /** @file input_lexer.ll
2  *
3  *  Lexical analyzer definition for reading expressions.
4  *  This file must be processed with flex. */
5
6 /*
7  *  GiNaC Copyright (C) 1999-2002 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 <iostream>
31 #include <string>
32 #include <map>
33 #include <stdexcept>
34
35 #include "input_lexer.h"
36 #include "ex.h"
37 #include "constant.h"
38 #include "fail.h"
39 #include "numeric.h"
40 #include "symbol.h"
41 #include "lst.h"
42
43 using namespace GiNaC;
44 namespace GiNaC {
45
46 #include "input_parser.h"
47
48 } // namespace GiNaC
49
50 // Table of all used symbols
51 struct sym_def {
52         sym_def() : predefined(false) {}
53         sym_def(const ex &s, bool predef) : sym(s), predefined(predef) {}
54         ~sym_def() {}
55
56         sym_def(const sym_def &other) {sym = other.sym; predefined = other.predefined;}
57         const sym_def &operator=(const sym_def &other)
58         {
59                 if (this != &other) {
60                         sym = other.sym;
61                         predefined = other.predefined;
62                 }
63                 return *this;
64         }
65
66         ex sym;
67         bool predefined;        // true = user supplied symbol, false = lexer generated symbol
68 };
69 typedef std::map<std::string, sym_def> sym_tab;
70 static sym_tab syms;
71
72 // lex input function
73 static int lexer_input(char *buf, int max_size);
74 #define YY_INPUT(buf, result, max_size) (result = lexer_input(buf, max_size))
75 %}
76
77         /* Abbreviations */
78 D       [0-9]
79 E       [elEL][-+]?{D}+
80 A       [a-zA-Z_]
81 AN      [0-9a-zA-Z_]
82
83
84 /*
85  *  Lexical rules
86  */
87
88 %%
89 [ \t]+                  /* skip whitespace */
90
91                         /* special values */
92 Pi                      ginac_yylval = Pi; return T_LITERAL;
93 Euler                   ginac_yylval = Euler; return T_LITERAL;
94 Catalan                 ginac_yylval = Catalan; return T_LITERAL;
95 FAIL                    ginac_yylval = *new fail(); return T_LITERAL;
96 I                       ginac_yylval = I; return T_NUMBER;
97 Digits                  ginac_yylval = (long)Digits; return T_DIGITS;
98
99                         /* comparison */
100 "=="                    return T_EQUAL;
101 "!="                    return T_NOTEQ;
102 "<="                    return T_LESSEQ;
103 ">="                    return T_GREATEREQ;
104
105                         /* numbers */
106 {D}+                    |
107 "#"{D}+"R"{AN}+         |
108 "#b"([01])+             |
109 "#o"[0-7]+              |
110 "#x"[0-9a-fA-F]+        |
111 {D}+"."{D}*({E})?       |
112 {D}*"."{D}+({E})?       |
113 {D}+{E}                 ginac_yylval = numeric(yytext); return T_NUMBER;
114
115                         /* symbols */
116 {A}{AN}*                {
117                                 sym_tab::const_iterator i = syms.find(yytext);
118                                 if (i == syms.end()) {
119                                         syms[yytext] = sym_def(ginac_yylval = *(new symbol(yytext)), false);
120                                 } else
121                                         ginac_yylval = (*i).second.sym;
122                                 return T_SYMBOL;
123                         }
124
125                         /* everything else */
126 .                       return *yytext;
127
128 %%
129
130
131 /*
132  *  Routines
133  */
134
135 // The string from which we will read
136 static std::string lexer_string;
137
138 // The current position within the string
139 static int curr_pos = 0;
140
141 // Input function that reads from string
142 static int lexer_input(char *buf, int max_size)
143 {
144         int actual = lexer_string.length() - curr_pos;
145         if (actual > max_size)
146                 actual = max_size;
147         if (actual <= 0)
148                 return YY_NULL;
149         lexer_string.copy(buf, actual, curr_pos);
150         curr_pos += actual;
151         return actual;
152 }
153
154 // EOF encountered, terminate the scanner
155 int ginac_yywrap()
156 {
157         return 1;
158 }
159
160 namespace GiNaC {
161
162 // Set the input string
163 void set_lexer_string(const std::string &s)
164 {
165         lexer_string = s;
166         curr_pos = 0;
167 }
168
169 // Set the list of predefined symbols
170 void set_lexer_symbols(ex l)
171 {
172         syms.clear();
173         if (!is_exactly_a<lst>(l))
174                 return;
175         for (unsigned i=0; i<l.nops(); i++) {
176                 if (is_exactly_a<symbol>(l.op(i)))
177                         syms[ex_to<symbol>(l.op(i)).get_name()] = sym_def(l.op(i), true);
178         }
179 }
180
181 // Check whether symbol was predefined
182 bool is_lexer_symbol_predefined(const ex &s)
183 {
184         sym_tab::const_iterator i = syms.find(ex_to<symbol>(s).get_name());
185         if (i == syms.end())
186                 return false;
187         else
188                 return (*i).second.predefined;
189 }
190
191 } // namespace GiNaC