04b71e832b2f17bd17b17090811d357607541ba5
[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-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 <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
42 #ifndef NO_NAMESPACE_GINAC
43 using namespace GiNaC;
44 namespace GiNaC {
45 #endif // ndef NO_NAMESPACE_GINAC
46
47 #include "input_parser.h"
48
49 #ifndef NO_NAMESPACE_GINAC
50 } // namespace GiNaC
51 #endif // ndef NO_NAMESPACE_GINAC
52
53 // Table of all used symbols
54 struct sym_def {
55         sym_def() : predefined(false) {}
56         sym_def(const ex &s, bool predef) : sym(s), predefined(predef) {}
57         ~sym_def() {}
58
59         sym_def(const sym_def &other) {sym = other.sym; predefined = other.predefined;}
60         const sym_def &operator=(const sym_def &other)
61         {
62                 if (this != &other) {
63                         sym = other.sym;
64                         predefined = other.predefined;
65                 }
66                 return *this;
67         }
68
69         ex sym;
70         bool predefined;        // true = user supplied symbol, false = lexer generated symbol
71 };
72 typedef map<string, sym_def> sym_tab;
73 static sym_tab syms;
74
75 // lex input function
76 static int lexer_input(char *buf, int max_size);
77 #define YY_INPUT(buf, result, max_size) (result = lexer_input(buf, max_size))
78 %}
79
80         /* Abbreviations */
81 D       [0-9]
82 E       [elEL][-+]?{D}+
83 A       [a-zA-Z_]
84 AN      [0-9a-zA-Z_]
85
86
87 /*
88  *  Lexical rules
89  */
90
91 %%
92 [ \t]+                  /* skip whitespace */
93
94                         /* special values */
95 Pi                      ginac_yylval = Pi; return T_LITERAL;
96 Euler                   ginac_yylval = Euler; return T_LITERAL;
97 Catalan                 ginac_yylval = Catalan; return T_LITERAL;
98 FAIL                    ginac_yylval = *new fail(); return T_LITERAL;
99 I                       ginac_yylval = I; return T_NUMBER;
100 Digits                  ginac_yylval = (long)Digits; return T_DIGITS;
101
102                         /* comparison */
103 "=="                    return T_EQUAL;
104 "!="                    return T_NOTEQ;
105 "<="                    return T_LESSEQ;
106 ">="                    return T_GREATEREQ;
107
108                         /* matrix delimiters */
109 \[\[                    return T_MATRIX_BEGIN;
110 \]\]                    return T_MATRIX_END;
111
112                         /* numbers */
113 {D}+                    |
114 {D}+"."{D}*({E})?       |
115 {D}*"."{D}+({E})?       |
116 {D}+{E}                 ginac_yylval = numeric(yytext); return T_NUMBER;
117
118                         /* symbols */
119 {A}{AN}*                {
120                                 sym_tab::const_iterator i = syms.find(yytext);
121                                 if (i == syms.end()) {
122                                         syms[yytext] = sym_def(ginac_yylval = *(new symbol(yytext)), false);
123                                 } else
124                                         ginac_yylval = i->second.sym;
125                                 return T_SYMBOL;
126                         }
127
128                         /* everything else */
129 .                       return *yytext;
130
131 %%
132
133
134 /*
135  *  Routines
136  */
137
138 // The string from which we will read
139 static string lexer_string;
140
141 // The current position within the string
142 static int curr_pos = 0;
143
144 // Input function that reads from string
145 static int lexer_input(char *buf, int max_size)
146 {
147         int actual = lexer_string.length() - curr_pos;
148         if (actual > max_size)
149                 actual = max_size;
150         if (actual <= 0)
151                 return YY_NULL;
152         lexer_string.copy(buf, actual, curr_pos);
153         curr_pos += actual;
154         return actual;
155 }
156
157 // EOF encountered, terminate the scanner
158 int ginac_yywrap()
159 {
160         return 1;
161 }
162
163 #ifndef NO_NAMESPACE_GINAC
164 namespace GiNaC {
165 #endif // ndef NO_NAMESPACE_GINAC
166
167 // Set the input string
168 void set_lexer_string(const string &s)
169 {
170         lexer_string = s;
171         curr_pos = 0;
172 }
173
174 // Set the list of predefined symbols
175 void set_lexer_symbols(ex l)
176 {
177         syms.clear();
178         if (!is_ex_exactly_of_type(l, lst))
179                 return;
180         for (int i=0; i<l.nops(); i++) {
181                 if (is_ex_exactly_of_type(l.op(i), symbol))
182                         syms[ex_to_symbol(l.op(i)).getname()] = sym_def(l.op(i), true);
183         }
184 }
185
186 // Check whether symbol was predefined
187 bool is_lexer_symbol_predefined(const ex &s)
188 {
189         sym_tab::const_iterator i = syms.find(ex_to_symbol(s).getname());
190         if (i == syms.end())
191                 return false;
192         else
193                 return i->second.predefined;
194 }
195
196 #ifndef NO_NAMESPACE_GINAC
197 } // namespace GiNaC
198 #endif // ndef NO_NAMESPACE_GINAC