Initial revision
[ginac.git] / ginsh / ginsh.l
1 /*
2  *  ginsh.l - GiNaC Interactive Shell, lexical analyzer definition
3  *
4  *  This file must be processed with flex
5  */
6
7
8 /*
9  *  Definitions
10  */
11
12 %{
13 #include "config.h"
14
15 #if STDC_HEADERS
16 #include <stdio.h>
17 #endif
18
19 extern "C" {
20 #include <readline/readline.h>
21 #include <readline/history.h>
22 }
23 #include <map>
24
25 #include <ginac.h>
26
27 #include "ginsh.h"
28 #include "y.tab.h"
29
30 #define YY_INPUT(buf, result, max_size) (result = ginsh_input(buf, max_size))
31
32 // Table of all used symbols
33 sym_tab syms;
34
35 // lex input function
36 static int ginsh_input(char *buf, int max_size);
37 %}
38
39         /* Abbreviations */
40 D       [0-9]
41 E       [elEL][-+]?{D}+
42 A       [a-zA-Z_]
43 AN      [0-9a-zA-Z_]
44
45
46 /*
47  *  Lexical rules
48  */
49
50 %%
51 [ \t\n]+                /* skip whitespace */
52 \\$                     /* skip line continuations */
53 "#".*                   /* skip comments starting with "#" */
54 ^"!".*                  system(yytext + 1);     /* execute shell command */
55
56                         /* special values */
57 Pi                      yylval = Pi; return T_LITERAL;
58 EulerGamma              yylval = EulerGamma; return T_LITERAL;
59 Catalan                 yylval = Catalan; return T_LITERAL;
60 FAIL                    yylval = *new fail(); return T_LITERAL;
61 I                       yylval = I; return T_NUMBER;
62 Digits                  yylval = (long)Digits; return T_DIGITS;
63
64                         /* keywords */
65 quit|exit               return T_QUIT;
66 print                   return T_PRINT;
67 time                    return T_TIME;
68 xyzzy                   return T_XYZZY;
69 inventory               return T_INVENTORY;
70 look                    return T_LOOK;
71 score                   return T_SCORE;
72
73                         /* comparison */
74 "=="                    return T_EQUAL;
75 "!="                    return T_NOTEQ;
76 "<="                    return T_LESSEQ;
77 ">="                    return T_GREATEREQ;
78
79                         /* last 1..3 expressions */
80 \"                      return T_QUOTE;
81 \"\"                    return T_QUOTE2;
82 \"\"\"                  return T_QUOTE3;
83
84                         /* matrix delimiters */
85 \[\[                    return T_MATRIX_BEGIN;
86 \]\]                    return T_MATRIX_END;
87
88                         /* numbers */
89 {D}+                    |
90 {D}+"."{D}*({E})?       |
91 {D}*"."{D}+({E})?       |
92 {D}+{E}                 yylval = numeric(yytext); return T_NUMBER;
93
94                         /* symbols */
95 {A}{AN}*                {
96                                 if (syms.find(yytext) == syms.end())
97                                         syms[yytext] = *(new symbol(yytext));
98                                 yylval = syms[yytext];
99                                 return T_SYMBOL;
100                         }
101
102                         /* everything else */
103 .                       return *yytext;
104
105 %%
106
107
108 /*
109  *  Routines
110  */
111
112 static int line_length = 0;
113 static char *line_read = NULL;
114 static char *line_ptr;
115
116 // Input function that uses libreadline for interactive input
117 static int ginsh_input(char *buf, int max_size)
118 {
119         int result;
120         if (yy_current_buffer->yy_is_interactive) {
121                 int actual;
122
123                 // Do we need to read a new line?
124                 if (line_length == 0) {
125
126                         // Free old line
127                         if (line_read)
128                                 free(line_read);
129
130                         // Read new line, prompt "> "
131                         line_read = line_ptr = readline("> ");
132
133                         // EOF?
134                         if (!line_read) {
135                                 line_length = 0;
136                                 return YY_NULL;
137                         }
138
139                         // Add non-empty lines to history
140                         line_length = strlen(line_read) + 1;
141                         if (line_length > 1)
142                                 add_history(line_read);
143
144                         // Reappend trailing '\n' which is stripped by readline()
145                         line_read[line_length - 1] = '\n';
146                 }
147
148                 // Copy data to lex buffer
149                 actual = line_length > max_size ? max_size : line_length;
150                 memcpy(buf, line_ptr, actual);
151                 line_length -= actual;
152                 line_ptr += actual;
153                 result = actual;
154
155         } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin))
156                 YY_FATAL_ERROR("input in flex scanner failed");
157
158         return result;
159 }