12 #define ARRAY_SIZE(x) ((sizeof(x))/(sizeof((x)[0])))
15 int is_ident(char ch);
18 int GetToken(tParser *File);
24 } csaReservedWords[] = {
25 {TOK_RWD_FUNCTION, "function"},
27 {TOK_RWD_RETURN, "return"},
31 {TOK_RWD_ELSE, "else"},
33 {TOK_RWD_WHILE, "while"},
36 {TOK_RWD_VOID, "void"},
37 {TOK_RWD_OBJECT, "Object"},
38 {TOK_RWD_OPAQUE, "Opaque"},
39 {TOK_RWD_INTEGER, "Integer"},
40 {TOK_RWD_REAL, "Real"},
41 {TOK_RWD_STRING, "String"}
46 * \brief Read a token from a buffer
47 * \param File Parser state
49 int GetToken(tParser *File)
53 if( File->NextToken != -1 ) {
55 File->LastToken = File->Token;
56 File->LastTokenStr = File->TokenStr;
57 File->LastTokenLen = File->TokenLen;
58 File->LastLine = File->CurLine;
60 File->Token = File->NextToken;
61 File->TokenStr = File->NextTokenStr;
62 File->TokenLen = File->NextTokenLen;
63 File->CurLine = File->NextLine;
65 File->CurPos = File->TokenStr + File->TokenLen;
68 char buf[ File->TokenLen + 1];
69 memcpy(buf, File->TokenStr, File->TokenLen);
70 buf[File->TokenLen] = 0;
72 printf(" GetToken: FAST Return %i (%i long) (%s)\n", File->Token, File->TokenLen, buf);
78 //printf(" GetToken: File=%p, File->CurPos = %p\n", File, File->CurPos);
80 // Clear whitespace (including comments)
84 while( isspace( *File->CurPos ) )
86 //printf("whitespace 0x%x, line = %i\n", *File->CurPos, File->CurLine);
87 if( *File->CurPos == '\n' )
93 if( *File->CurPos == '#' ) {
94 while( *File->CurPos && *File->CurPos != '\n' )
99 // C-Style Line Comments
100 if( *File->CurPos == '/' && File->CurPos[1] == '/' ) {
101 while( *File->CurPos && *File->CurPos != '\n' )
106 // C-Style Block Comments
107 if( *File->CurPos == '/' && File->CurPos[1] == '*' ) {
108 File->CurPos += 2; // Eat the '/*'
109 while( *File->CurPos && !(File->CurPos[-1] == '*' && *File->CurPos == '/') )
111 if( *File->CurPos == '\n' ) File->CurLine ++;
114 File->CurPos ++; // Eat the '/'
118 // No more "whitespace"
122 // Save previous tokens (speeds up PutBack and LookAhead)
123 File->LastToken = File->Token;
124 File->LastTokenStr = File->TokenStr;
125 File->LastTokenLen = File->TokenLen;
126 File->LastLine = File->CurLine;
129 File->TokenStr = File->CurPos;
130 switch( *File->CurPos++ )
132 case '\0': ret = TOK_EOF; break;
136 if( *File->CurPos == '^' ) {
145 if( *File->CurPos == '|' ) {
154 if( *File->CurPos == '&' ) {
163 if( *File->CurPos == '=' ) {
165 ret = TOK_ASSIGN_DIV;
171 if( *File->CurPos == '=' ) {
173 ret = TOK_ASSIGN_MUL;
179 if( *File->CurPos == '+' ) {
184 if( *File->CurPos == '=' ) {
186 ret = TOK_ASSIGN_PLUS;
192 if( *File->CurPos == '-' ) {
197 if( *File->CurPos == '=' ) {
199 ret = TOK_ASSIGN_MINUS;
202 if( *File->CurPos == '>' ) {
212 while( *File->CurPos && !(*File->CurPos == '"' && *File->CurPos != '\\') )
224 case '(': ret = TOK_PAREN_OPEN; break;
225 case ')': ret = TOK_PAREN_CLOSE; break;
226 case '{': ret = TOK_BRACE_OPEN; break;
227 case '}': ret = TOK_BRACE_CLOSE; break;
228 case '[': ret = TOK_SQUARE_OPEN; break;
229 case ']': ret = TOK_SQUARE_CLOSE; break;
232 case ';': ret = TOK_SEMICOLON; break;
233 case ',': ret = TOK_COMMA; break;
235 case '.': ret = TOK_SCOPE; break;
241 if( *File->CurPos == '=' ) {
252 // Less-Than or Equal
253 if( *File->CurPos == '=' ) {
263 // Greater-Than or Equal
264 if( *File->CurPos == '=' ) {
282 // \$[0-9]+ or \$[_a-zA-Z][_a-zA-Z0-9]*
285 if( isdigit( *File->CurPos ) ) {
286 while( isdigit(*File->CurPos) )
291 while( is_ident(*File->CurPos) || isdigit(*File->CurPos) )
297 // Default (Numbers and Identifiers)
302 if( isdigit(*File->CurPos) )
305 if( *File->CurPos == '0' && File->CurPos[1] == 'x' )
308 while(('0' <= *File->CurPos && *File->CurPos <= '9')
309 || ('A' <= *File->CurPos && *File->CurPos <= 'F')
310 || ('a' <= *File->CurPos && *File->CurPos <= 'f') )
317 while( isdigit(*File->CurPos) )
320 // printf("*File->CurPos = '%c'\n", *File->CurPos);
323 if( *File->CurPos == '.' )
327 while( isdigit(*File->CurPos) )
331 if( *File->CurPos == 'e' || *File->CurPos == 'E' )
335 if(*File->CurPos == '-' || *File->CurPos == '+')
337 while( isdigit(*File->CurPos) )
341 // printf(" ret = %i\n", ret);
347 if( is_ident(*File->CurPos) )
352 while( is_ident(*File->CurPos) || isdigit(*File->CurPos) )
355 // This is set later too, but we use it below
356 File->TokenLen = File->CurPos - File->TokenStr;
358 // Check if it's a reserved word
360 char buf[File->TokenLen + 1];
362 memcpy(buf, File->TokenStr, File->TokenLen);
363 buf[File->TokenLen] = 0;
364 for( i = 0; i < ARRAY_SIZE(csaReservedWords); i ++ )
366 if(strcmp(csaReservedWords[i].Name, buf) == 0) {
367 ret = csaReservedWords[i].Value;
372 // If there's no match, just keep ret as TOK_IDENT
379 fprintf(stderr, "Syntax Error: Unknown symbol '%c'\n", *File->CurPos);
380 longjmp(File->JmpTarget, 1);
386 File->TokenLen = File->CurPos - File->TokenStr;
390 char buf[ File->TokenLen + 1];
391 memcpy(buf, File->TokenStr, File->TokenLen);
392 buf[File->TokenLen] = 0;
393 //printf(" GetToken: File->CurPos = %p\n", File->CurPos);
394 printf(" GetToken: Return %i (%i long) (%s)\n", ret, File->TokenLen, buf);
400 void PutBack(tParser *File)
402 if( File->LastToken == -1 ) {
404 fprintf(stderr, "INTERNAL ERROR: Putback when LastToken==-1\n");
405 longjmp( File->JmpTarget, -1 );
409 printf(" PutBack: Was on %i\n", File->Token);
412 File->NextLine = File->CurLine;
413 File->NextToken = File->Token;
414 File->NextTokenStr = File->TokenStr;
415 File->NextTokenLen = File->TokenLen;
417 File->CurLine = File->LastLine;
418 File->Token = File->LastToken;
419 File->TokenStr = File->LastTokenStr;
420 File->TokenLen = File->LastTokenLen;
421 File->CurPos = File->NextTokenStr;
423 File->LastToken = -1;
426 int LookAhead(tParser *File)
428 // TODO: Should I save the entire state here?
429 int ret = GetToken(File);
436 * \brief Check for ident characters
437 * \note Matches Regex [a-zA-Z_]
439 int is_ident(char ch)
441 if('a' <= ch && ch <= 'z') return 1;
442 if('A' <= ch && ch <= 'Z') return 1;
443 if(ch == '_') return 1;
445 if(ch == '.') return 1;
453 if('0' <= ch && ch <= '9') return 1;
459 if(' ' == ch) return 1;
460 if('\t' == ch) return 1;
461 if('\b' == ch) return 1;
462 if('\n' == ch) return 1;
463 if('\r' == ch) return 1;