Fixed behavior of VTerm when driver is set at runtime
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / lex.c
1 /*
2  * Acess2 init
3  * - Script Lexer
4  */
5 #include "tokens.h"
6 #include <stdlib.h>
7
8 // === PROTOTYPES ===
9  int    is_ident(char ch);
10  int    isdigit(char ch);
11  int    isspace(char ch);
12  int    GetToken(tParser *File);
13
14 // === CONSTANTS ===
15 const struct {
16         const  int      Value;
17         const char      *Name;
18 } csaReservedWords[] = {
19         {TOK_RWD_FUNCTION, "function"},
20         {TOK_RWD_INTEGER, "integer"},
21         {TOK_RWD_REAL, "string"}
22 };
23
24 // === CODE ===
25 /**
26  * \brief Read a token from a buffer
27  * \param File  Parser state
28  */
29 int GetToken(tParser *File)
30 {
31          int    ret;
32         
33         if( File->NextToken != -1 ) {
34                 File->Token = File->NextToken;
35                 File->TokenStr = File->NextTokenStr;
36                 File->TokenLen = File->NextTokenLen;
37                 File->NextToken = -1;
38                 return File->Token;
39         }
40         
41         // Clear whitespace (including comments)
42         for( ;; )
43         {
44                 // Whitespace
45                 while( isspace( *File->CurPos ) )
46                         File->CurPos ++;
47                 
48                 // # Line Comments
49                 if( *File->CurPos == '#' ) {
50                         while( *File->CurPos && *File->CurPos != '\n' )
51                                 File->CurPos ++;
52                         continue ;
53                 }
54                 
55                 // C-Style Line Comments
56                 if( *File->CurPos == '/' && File->CurPos[1] == '/' ) {
57                         while( *File->CurPos && *File->CurPos != '\n' )
58                                 File->CurPos ++;
59                         continue ;
60                 }
61                 
62                 // C-Style Block Comments
63                 if( *File->CurPos == '/' && File->CurPos[1] == '*' ) {
64                         File->CurPos += 2;
65                         while( *File->CurPos && !(File->CurPos[-1] == '*' && *File->CurPos == '/') )
66                                 File->CurPos ++;
67                         continue ;
68                 }
69                 
70                 // No more "whitespace"
71                 break;
72         }
73         
74         // Save previous tokens (speeds up PutBack and LookAhead)
75         File->LastToken = File->Token;
76         File->LastTokenStr = File->TokenStr;
77         File->LastTokenLen = File->TokenLen;
78         
79         // Read token
80         File->TokenStr = File->CurPos;
81         switch( *File->CurPos++ )
82         {
83         // Operations
84         case '/':       ret = TOK_DIV;  break;
85         case '*':       ret = TOK_MUL;  break;
86         case '+':       ret = TOK_PLUS; break;
87         case '-':
88                 if( *File->CurPos == '>' ) {
89                         File->CurPos ++;
90                         ret = TOK_ELEMENT;
91                 }
92                 else
93                         ret = TOK_MINUS;
94                 break;
95         
96         // Strings
97         case '"':
98                 File->TokenStr ++;
99                 while( *File->CurPos && !(*File->CurPos == '"' && *File->CurPos != '\\') )
100                         File->CurPos ++;
101                 ret = TOK_STR;
102                 break;
103         
104         // Brackets
105         case '(':       ret = TOK_PAREN_OPEN;   break;
106         case ')':       ret = TOK_PAREN_CLOSE;  break;
107         case '{':       ret = TOK_BRACE_OPEN;   break;
108         case '}':       ret = TOK_BRACE_CLOSE;  break;
109         case '[':       ret = TOK_SQUARE_OPEN;  break;
110         case ']':       ret = TOK_SQUARE_CLOSE; break;
111         
112         // Core symbols
113         case ';':       ret = TOK_SEMICOLON;    break;
114         case '.':       ret = TOK_SCOPE;        break;
115         
116         // Equals
117         case '=':
118                 // Comparison Equals
119                 if( *File->CurPos == '=' ) {
120                         File->CurPos ++;
121                         ret = TOK_EQUALS;
122                         break;
123                 }
124                 // Assignment Equals
125                 ret = TOK_ASSIGN;
126                 break;
127         
128         // Variables
129         // \$[0-9]+ or \$[_a-zA-Z][_a-zA-Z0-9]*
130         case '$':
131                 File->TokenStr ++;
132                 // Numeric Variable
133                 if( isdigit( *File->CurPos ) ) {
134                         while( isdigit(*File->CurPos) )
135                                 File->CurPos ++;
136                 }
137                 // Ident Variable
138                 else {
139                         while( is_ident(*File->CurPos) )
140                                 File->CurPos ++;
141                 }
142                 ret = TOK_VARIABLE;
143                 break;
144         
145         // Default (Numbers and Identifiers)
146         default:
147                 // Numbers
148                 if( isdigit(*File->CurPos) )
149                 {
150                         while( isdigit(*File->CurPos) )
151                                 File->CurPos ++;
152                         ret = TOK_INTEGER;
153                         break;
154                 }
155         
156                 // Identifier
157                 if( is_ident(*File->CurPos) )
158                 {
159                         // Identifier
160                         while( is_ident(*File->CurPos) || isdigit(*File->CurPos) )
161                                 File->CurPos ++;
162                         
163                         ret = TOK_IDENT;
164                         break;
165                 }
166                 // Syntax Error
167                 ret = 0;
168                 break;
169         }
170         // Return
171         File->Token = ret;
172         File->TokenLen = File->CurPos - File->TokenStr;
173         return ret;
174 }
175
176 void PutBack(tParser *File)
177 {
178         if( File->LastToken == -1 ) {
179                 // ERROR:
180                 return ;
181         }
182         // Save
183         File->NextToken = File->Token;
184         File->NextTokenStr = File->TokenStr;
185         File->NextTokenLen = File->TokenLen;
186         // Restore
187         File->Token = File->LastToken;
188         File->TokenStr = File->LastTokenStr;
189         File->TokenLen = File->LastTokenLen;
190         File->CurPos = File->NextTokenStr;
191         // Invalidate
192         File->LastToken = -1;
193 }
194
195 int LookAhead(tParser *File)
196 {
197          int    ret = GetToken(File);
198         PutBack(File);
199         return ret;
200 }
201
202 // --- Helpers ---
203 /**
204  * \brief Check for ident characters
205  * \note Matches Regex [a-zA-Z_]
206  */
207 int is_ident(char ch)
208 {
209         if('a' <= ch && ch <= 'z')      return 1;
210         if('Z' <= ch && ch <= 'Z')      return 1;
211         if(ch == '_')   return 1;
212         if(ch < 0)      return 1;
213         return 0;
214 }
215
216 int isdigit(char ch)
217 {
218         if('0' <= ch && ch <= '9')      return 1;
219         return 0;
220 }
221
222 int isspace(char ch)
223 {
224         if(' ' == ch)   return 1;
225         if('\t' == ch)  return 1;
226         if('\b' == ch)  return 1;
227         if('\n' == ch)  return 1;
228         if('\r' == ch)  return 1;
229         return 0;
230 }

UCC git Repository :: git.ucc.asn.au