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