- the ex stream >> operator is gone
[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-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 "config.h"
31
32 #include "ginsh.h"
33 #include "ginsh_parser.h"
34
35 #define YY_INPUT(buf, result, max_size) (result = ginsh_input(buf, max_size))
36
37 // Table of all used symbols
38 sym_tab syms;
39
40 // lex input function
41 static int ginsh_input(char *buf, int max_size);
42 %}
43
44         /* Abbreviations */
45 D       [0-9]
46 E       [elEL][-+]?{D}+
47 A       [a-zA-Z_]
48 AN      [0-9a-zA-Z_]
49
50
51 /*
52  *  Lexical rules
53  */
54
55 %%
56 [ \t\n]+                /* skip whitespace */
57 \\$                     /* skip line continuations */
58 "#".*                   /* skip comments starting with "#" */
59 ^"!".*                  system(yytext + 1);     /* execute shell command */
60
61                         /* special values */
62 Pi                      yylval = Pi; return T_LITERAL;
63 Euler                   yylval = Euler; return T_LITERAL;
64 Catalan                 yylval = Catalan; return T_LITERAL;
65 FAIL                    yylval = *new fail(); return T_LITERAL;
66 I                       yylval = I; return T_NUMBER;
67 Digits                  yylval = (long)Digits; return T_DIGITS;
68
69                         /* keywords */
70 quit|exit               return T_QUIT;
71 warranty                return T_WARRANTY;
72 print                   return T_PRINT;
73 read                    return T_READ;
74 write                   return T_WRITE;
75 time                    return T_TIME;
76 xyzzy                   return T_XYZZY;
77 inventory               return T_INVENTORY;
78 look                    return T_LOOK;
79 score                   return T_SCORE;
80
81                         /* comparison */
82 "=="                    return T_EQUAL;
83 "!="                    return T_NOTEQ;
84 "<="                    return T_LESSEQ;
85 ">="                    return T_GREATEREQ;
86
87                         /* last 1..3 expressions */
88 \"                      return T_QUOTE;
89 \"\"                    return T_QUOTE2;
90 \"\"\"                  return T_QUOTE3;
91
92                         /* matrix delimiters */
93 \[\[                    return T_MATRIX_BEGIN;
94 \]\]                    return T_MATRIX_END;
95
96                         /* numbers */
97 {D}+                    |
98 {D}+"."{D}*({E})?       |
99 {D}*"."{D}+({E})?       |
100 {D}+{E}                 yylval = numeric(yytext); return T_NUMBER;
101
102                         /* symbols */
103 {A}{AN}*                {
104                                 sym_tab::const_iterator i = syms.find(yytext);
105                                 if (i == syms.end()) {
106                                         yylval = syms[yytext] = *(new symbol(yytext));
107                                 } else
108                                         yylval = i->second;
109                                 return T_SYMBOL;
110                         }
111
112                         /* everything else */
113 .                       return *yytext;
114
115 %%
116
117
118 /*
119  *  Routines
120  */
121
122 static int line_length = 0;
123 static char *line_read = NULL;
124 static char *line_ptr;
125
126 // Input function that uses libreadline for interactive input
127 static int ginsh_input(char *buf, int max_size)
128 {
129         int result;
130         if (yy_current_buffer->yy_is_interactive) {
131 #ifdef HAVE_LIBREADLINE
132                 // Do we need to read a new line?
133                 int actual;
134                 if (line_length == 0) {
135
136                         // Free old line
137                         if (line_read)
138                                 free(line_read);
139
140                         // Read new line, prompt "> "
141                         line_read = line_ptr = readline("> ");
142
143                         // EOF?
144                         if (!line_read) {
145                                 line_length = 0;
146                                 return YY_NULL;
147                         }
148
149                         // Add non-empty lines to history
150                         line_length = strlen(line_read) + 1;
151                         if (line_length > 1)
152                                 add_history(line_read);
153
154                         // Reappend trailing '\n' which is stripped by readline()
155                         line_read[line_length - 1] = '\n';
156                 }
157
158                 // Copy data to lex buffer
159                 actual = line_length > max_size ? max_size : line_length;
160                 memcpy(buf, line_ptr, actual);
161                 line_length -= actual;
162                 line_ptr += actual;
163                 result = actual;
164 #else
165                 printf("> "); fflush(stdout);
166                 int c = '*', n;
167                 for (n = 0; n < max_size && (c = getc(yyin)) != EOF && c != '\n'; ++n)
168                         buf[n] = (char)c;
169                 if (c == '\n')
170                         buf[n++] = (char)c;
171                 if (c == EOF && ferror(yyin))
172                         YY_FATAL_ERROR("input in flex scanner failed");
173                 result = n;
174 #endif
175         } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin))
176                 YY_FATAL_ERROR("input in flex scanner failed");
177
178         return result;
179 }
180
181 // List of input files to be processed
182 int num_files = 0;
183 char **file_list = NULL;
184
185 // EOF encountered, connect to next file. If this was the last file,
186 // connect to stdin. If this was stdin, terminate the scanner.
187 int yywrap()
188 {
189         if (yyin == stdin)
190                 return 1;
191
192         fclose(yyin);
193         if (num_files) {
194                 yyin = fopen(*file_list, "r");
195                 if (yyin == NULL) {
196                         cerr << "Can't open " << *file_list << endl;
197                         return 1;
198                 }
199                 num_files--;
200                 file_list++;
201         } else
202                 yyin = stdin;
203         return 0;
204 }