]> www.ginac.de Git - ginac.git/blob - ginsh/ginsh_lexer.ll
- Some minor clarifications.
[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  *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23
24 /*
25  *  Definitions
26  */
27
28 %{
29 #include "config.h"
30
31 #include "ginsh.h"
32 #include "ginsh_parser.h"
33
34 #define YY_INPUT(buf, result, max_size) (result = ginsh_input(buf, max_size))
35
36 // Table of all used symbols
37 sym_tab syms;
38
39 // lex input function
40 static int ginsh_input(char *buf, int max_size);
41 %}
42
43         /* Abbreviations */
44 D       [0-9]
45 E       [elEL][-+]?{D}+
46 A       [a-zA-Z_]
47 AN      [0-9a-zA-Z_]
48
49
50 /*
51  *  Lexical rules
52  */
53
54 %%
55 [ \t\n]+                /* skip whitespace */
56 \\$                     /* skip line continuations */
57 "#".*                   /* skip comments starting with "#" */
58 ^"!".*                  system(yytext + 1);     /* execute shell command */
59
60                         /* special values */
61 Pi                      yylval = Pi; return T_LITERAL;
62 EulerGamma              yylval = EulerGamma; return T_LITERAL;
63 Catalan                 yylval = Catalan; return T_LITERAL;
64 FAIL                    yylval = *new fail(); return T_LITERAL;
65 I                       yylval = I; return T_NUMBER;
66 Digits                  yylval = (long)Digits; return T_DIGITS;
67
68                         /* keywords */
69 quit|exit               return T_QUIT;
70 warranty                return T_WARRANTY;
71 print                   return T_PRINT;
72 read                    return T_READ;
73 write                   return T_WRITE;
74 time                    return T_TIME;
75 xyzzy                   return T_XYZZY;
76 inventory               return T_INVENTORY;
77 look                    return T_LOOK;
78 score                   return T_SCORE;
79
80                         /* comparison */
81 "=="                    return T_EQUAL;
82 "!="                    return T_NOTEQ;
83 "<="                    return T_LESSEQ;
84 ">="                    return T_GREATEREQ;
85
86                         /* last 1..3 expressions */
87 \"                      return T_QUOTE;
88 \"\"                    return T_QUOTE2;
89 \"\"\"                  return T_QUOTE3;
90
91                         /* matrix delimiters */
92 \[\[                    return T_MATRIX_BEGIN;
93 \]\]                    return T_MATRIX_END;
94
95                         /* numbers */
96 {D}+                    |
97 {D}+"."{D}*({E})?       |
98 {D}*"."{D}+({E})?       |
99 {D}+{E}                 yylval = numeric(yytext); return T_NUMBER;
100
101                         /* symbols */
102 {A}{AN}*                {
103                                 if (syms.find(yytext) == syms.end())
104                                         syms[yytext] = *(new symbol(yytext));
105                                 yylval = syms[yytext];
106                                 return T_SYMBOL;
107                         }
108
109                         /* everything else */
110 .                       return *yytext;
111
112 %%
113
114
115 /*
116  *  Routines
117  */
118
119 static int line_length = 0;
120 static char *line_read = NULL;
121 static char *line_ptr;
122
123 // Input function that uses libreadline for interactive input
124 static int ginsh_input(char *buf, int max_size)
125 {
126         int result;
127         if (yy_current_buffer->yy_is_interactive) {
128 #ifdef HAVE_LIBREADLINE
129                 // Do we need to read a new line?
130                 int actual;
131                 if (line_length == 0) {
132
133                         // Free old line
134                         if (line_read)
135                                 free(line_read);
136
137                         // Read new line, prompt "> "
138                         line_read = line_ptr = readline("> ");
139
140                         // EOF?
141                         if (!line_read) {
142                                 line_length = 0;
143                                 return YY_NULL;
144                         }
145
146                         // Add non-empty lines to history
147                         line_length = strlen(line_read) + 1;
148                         if (line_length > 1)
149                                 add_history(line_read);
150
151                         // Reappend trailing '\n' which is stripped by readline()
152                         line_read[line_length - 1] = '\n';
153                 }
154
155                 // Copy data to lex buffer
156                 actual = line_length > max_size ? max_size : line_length;
157                 memcpy(buf, line_ptr, actual);
158                 line_length -= actual;
159                 line_ptr += actual;
160                 result = actual;
161 #else
162                 printf("> "); fflush(stdout);
163                 int c = '*', n;
164                 for (n = 0; n < max_size && (c = getc(yyin)) != EOF && c != '\n'; ++n)
165                         buf[n] = (char)c;
166                 if (c == '\n')
167                         buf[n++] = (char)c;
168                 if (c == EOF && ferror(yyin))
169                         YY_FATAL_ERROR("input in flex scanner failed");
170                 result = n;
171 #endif
172         } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin))
173                 YY_FATAL_ERROR("input in flex scanner failed");
174
175         return result;
176 }
177
178 // List of input files to be processed
179 int num_files = 0;
180 char **file_list = NULL;
181
182 // EOF encountered, connect to next file. If this was the last file,
183 // connect to stdin. If this was stdin, terminate the scanner.
184 int yywrap()
185 {
186         if (yyin == stdin)
187                 return 1;
188
189         fclose(yyin);
190         if (num_files) {
191                 yyin = fopen(*file_list, "r");
192                 if (yyin == NULL) {
193                         cerr << "Can't open " << *file_list << endl;
194                         return 1;
195                 }
196                 num_files--;
197                 file_list++;
198         } else
199                 yyin = stdin;
200         return 0;
201 }