]> www.ginac.de Git - ginac.git/blob - ginsh/ginsh_lexer.ll
Allow user to disable GiNaC::compile_ex (e.g. for security reasons).
[ginac.git] / ginsh / ginsh_lexer.ll
1 /** @file ginsh_lexer.ll
2  *
3  *  Lexical analyzer definition for ginsh.
4  *  This file must be processed with flex. */
5
6 /*
7  *  GiNaC Copyright (C) 1999-2008 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24
25 /*
26  *  Definitions
27  */
28
29 %pointer
30
31 %{
32 #include "config.h"
33
34 #include "ginsh.h"
35 #include "ginsh_parser.h"
36
37 #define YY_INPUT(buf, result, max_size) (result = ginsh_input(buf, max_size))
38
39 // Table of all used symbols
40 sym_tab syms;
41
42 // Type of symbols to generate (real or complex)
43 unsigned symboltype = domain::complex;
44
45 // lex input function
46 static int ginsh_input(char *buf, int max_size);
47 %}
48
49         /* Abbreviations */
50 D       [0-9]
51 E       [elEL][-+]?{D}+
52 A       [a-zA-Z_]
53 AN      [0-9a-zA-Z_]
54
55
56 /*
57  *  Lexical rules
58  */
59
60 %%
61 [ \t\n]+                /* skip whitespace */
62 \\$                     /* skip line continuations */
63 "//".*                  /* skip comments starting with "//" */
64 ^"#".*                  /* skip lines starting with "#" */
65 ^"!".*                  system(yytext + 1);     /* execute shell command */
66
67                         /* special values */
68 Pi                      yylval = Pi; return T_LITERAL;
69 Euler                   yylval = Euler; return T_LITERAL;
70 Catalan                 yylval = Catalan; return T_LITERAL;
71 FAIL                    yylval = *new fail(); return T_LITERAL;
72 I                       yylval = I; return T_NUMBER;
73 Digits                  yylval = (long)Digits; return T_DIGITS;
74
75                         /* keywords */
76 quit|exit               return T_QUIT;
77 warranty                return T_WARRANTY;
78 print                   return T_PRINT;
79 iprint                  return T_IPRINT;
80 print_latex             return T_PRINTLATEX;
81 print_csrc              return T_PRINTCSRC;
82 time                    return T_TIME;
83 xyzzy                   return T_XYZZY;
84 inventory               return T_INVENTORY;
85 look                    return T_LOOK;
86 score                   return T_SCORE;
87 complex_symbols return T_COMPLEX_SYMBOLS;
88 real_symbols    return T_REAL_SYMBOLS;
89
90                         /* comparison */
91 "=="                    return T_EQUAL;
92 "!="                    return T_NOTEQ;
93 "<="                    return T_LESSEQ;
94 ">="                    return T_GREATEREQ;
95
96                         /* last 1..3 expressions */
97 \%                      return T_QUOTE;
98 \%\%                    return T_QUOTE2;
99 \%\%\%                  return T_QUOTE3;
100
101                         /* numbers */
102 {D}+                    |
103 "#"{D}+"R"{AN}+         |
104 "#b"([01])+             |
105 "#o"[0-7]+              |
106 "#x"[0-9a-fA-F]+        |
107 {D}+"."{D}*({E})?       |
108 {D}*"."{D}+({E})?       |
109 {D}+{E}                 yylval = numeric(yytext); return T_NUMBER;
110
111                         /* symbols */
112 {A}{AN}*                {
113                                 sym_tab::const_iterator i = syms.find(yytext);
114                                 if (i == syms.end()) {
115                                         if (symboltype == domain::complex) {
116                                                 yylval = syms[yytext] = *(new symbol(yytext));
117                                         } else {
118                                                 yylval = syms[yytext] = *(new symbol(yytext, domain::real));
119                                         }
120                                 } else
121                                         yylval = i->second;
122                                 return T_SYMBOL;
123                         }
124
125                         /* wildcards */
126 \${D}+                  yylval = wild(atoi(yytext + 1)); return T_LITERAL;
127
128                         /* everything else */
129 .                       return *yytext;
130
131 %%
132
133
134 /*
135  *  Routines
136  */
137
138 static int line_length = 0;
139 static char *line_read = NULL;
140 static char *line_ptr;
141
142 // Input function that uses libreadline for interactive input
143 static int ginsh_input(char *buf, int max_size)
144 {
145         int result;
146 #if defined(YY_CURRENT_BUFFER)
147         if (YY_CURRENT_BUFFER->yy_is_interactive) {
148 #else
149         if (yy_current_buffer->yy_is_interactive) {
150 #endif
151 #ifdef HAVE_LIBREADLINE
152                 // Do we need to read a new line?
153                 int actual;
154                 if (line_length == 0) {
155
156                         // Free old line
157                         if (line_read)
158                                 free(line_read);
159
160                         // Read new line, prompt "> "
161                         line_read = line_ptr = readline("> ");
162
163                         // EOF?
164                         if (!line_read) {
165                                 line_length = 0;
166                                 return YY_NULL;
167                         }
168
169                         // Add non-empty lines to history
170                         line_length = strlen(line_read) + 1;
171                         if (line_length > 1)
172                                 add_history(line_read);
173
174                         // Reappend trailing '\n' which is stripped by readline()
175                         line_read[line_length - 1] = '\n';
176                 }
177
178                 // Copy data to lex buffer
179                 actual = line_length > max_size ? max_size : line_length;
180                 memcpy(buf, line_ptr, actual);
181                 line_length -= actual;
182                 line_ptr += actual;
183                 result = actual;
184 #else
185                 printf("> "); fflush(stdout);
186                 int c = '*', n;
187                 for (n = 0; n < max_size && (c = getc(yyin)) != EOF && c != '\n'; ++n)
188                         buf[n] = (char)c;
189                 if (c == '\n')
190                         buf[n++] = (char)c;
191                 if (c == EOF && ferror(yyin))
192                         YY_FATAL_ERROR("input in flex scanner failed");
193                 result = n;
194 #endif
195         } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin))
196                 YY_FATAL_ERROR("input in flex scanner failed");
197
198         return result;
199 }
200
201 // List of input files to be processed
202 int num_files = 0;
203 char **file_list = NULL;
204
205 // EOF encountered, connect to next file. If this was the last file,
206 // connect to stdin. If this was stdin, terminate the scanner.
207 int yywrap()
208 {
209         if (yyin == stdin)
210                 return 1;
211
212         fclose(yyin);
213         if (num_files) {
214                 yyin = fopen(*file_list, "r");
215                 if (yyin == NULL) {
216                         cerr << "Can't open " << *file_list << endl;
217                         return 1;
218                 }
219                 num_files--;
220                 file_list++;
221         } else
222                 yyin = stdin;
223         return 0;
224 }