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"},
28 {TOK_RWD_BREAK, "break"},
29 {TOK_RWD_CONTINUE, "continue"},
33 {TOK_RWD_ELSE, "else"},
35 {TOK_RWD_WHILE, "while"},
38 {TOK_RWD_NULL, "null"},
39 {TOK_RWD_VOID, "void"},
40 {TOK_RWD_OBJECT, "Object"},
41 {TOK_RWD_OPAQUE, "Opaque"},
42 {TOK_RWD_INTEGER, "Integer"},
43 {TOK_RWD_REAL, "Real"},
44 {TOK_RWD_STRING, "String"}
49 * \brief Read a token from a buffer
50 * \param File Parser state
52 int GetToken(tParser *File)
56 if( File->NextToken != -1 ) {
58 File->LastToken = File->Token;
59 File->LastTokenStr = File->TokenStr;
60 File->LastTokenLen = File->TokenLen;
61 File->LastLine = File->CurLine;
63 File->Token = File->NextToken;
64 File->TokenStr = File->NextTokenStr;
65 File->TokenLen = File->NextTokenLen;
66 File->CurLine = File->NextLine;
68 File->CurPos = File->TokenStr + File->TokenLen;
71 char buf[ File->TokenLen + 1];
72 memcpy(buf, File->TokenStr, File->TokenLen);
73 buf[File->TokenLen] = 0;
75 printf(" GetToken: FAST Return %i (%i long) (%s)\n", File->Token, File->TokenLen, buf);
81 //printf(" GetToken: File=%p, File->CurPos = %p\n", File, File->CurPos);
83 // Clear whitespace (including comments)
87 while( isspace( *File->CurPos ) )
89 //printf("whitespace 0x%x, line = %i\n", *File->CurPos, File->CurLine);
90 if( *File->CurPos == '\n' )
96 if( *File->CurPos == '#' ) {
97 while( *File->CurPos && *File->CurPos != '\n' )
102 // C-Style Line Comments
103 if( *File->CurPos == '/' && File->CurPos[1] == '/' ) {
104 while( *File->CurPos && *File->CurPos != '\n' )
109 // C-Style Block Comments
110 if( *File->CurPos == '/' && File->CurPos[1] == '*' ) {
111 File->CurPos += 2; // Eat the '/*'
112 while( *File->CurPos && !(File->CurPos[-1] == '*' && *File->CurPos == '/') )
114 if( *File->CurPos == '\n' ) File->CurLine ++;
117 File->CurPos ++; // Eat the '/'
121 // No more "whitespace"
125 // Save previous tokens (speeds up PutBack and LookAhead)
126 File->LastToken = File->Token;
127 File->LastTokenStr = File->TokenStr;
128 File->LastTokenLen = File->TokenLen;
129 File->LastLine = File->CurLine;
132 File->TokenStr = File->CurPos;
133 switch( *File->CurPos++ )
135 case '\0': ret = TOK_EOF; break;
139 if( *File->CurPos == '^' ) {
148 if( *File->CurPos == '|' ) {
157 if( *File->CurPos == '&' ) {
166 if( *File->CurPos == '=' ) {
168 ret = TOK_ASSIGN_DIV;
174 if( *File->CurPos == '=' ) {
176 ret = TOK_ASSIGN_MUL;
182 if( *File->CurPos == '+' ) {
187 if( *File->CurPos == '=' ) {
189 ret = TOK_ASSIGN_PLUS;
195 if( *File->CurPos == '-' ) {
200 if( *File->CurPos == '=' ) {
202 ret = TOK_ASSIGN_MINUS;
205 if( *File->CurPos == '>' ) {
215 while( *File->CurPos && !(*File->CurPos == '"' && *File->CurPos != '\\') )
227 case '(': ret = TOK_PAREN_OPEN; break;
228 case ')': ret = TOK_PAREN_CLOSE; break;
229 case '{': ret = TOK_BRACE_OPEN; break;
230 case '}': ret = TOK_BRACE_CLOSE; break;
231 case '[': ret = TOK_SQUARE_OPEN; break;
232 case ']': ret = TOK_SQUARE_CLOSE; break;
235 case ';': ret = TOK_SEMICOLON; break;
236 case ',': ret = TOK_COMMA; break;
238 case '.': ret = TOK_SCOPE; break;
244 if( *File->CurPos == '=' ) {
255 // Less-Than or Equal
256 if( *File->CurPos == '=' ) {
266 // Greater-Than or Equal
267 if( *File->CurPos == '=' ) {
277 if( *File->CurPos == '=' ) {
290 // \$[0-9]+ or \$[_a-zA-Z][_a-zA-Z0-9]*
293 if( isdigit( *File->CurPos ) ) {
294 while( isdigit(*File->CurPos) )
299 while( is_ident(*File->CurPos) || isdigit(*File->CurPos) )
305 // Default (Numbers and Identifiers)
310 if( isdigit(*File->CurPos) )
313 if( *File->CurPos == '0' && File->CurPos[1] == 'x' )
316 while(('0' <= *File->CurPos && *File->CurPos <= '9')
317 || ('A' <= *File->CurPos && *File->CurPos <= 'F')
318 || ('a' <= *File->CurPos && *File->CurPos <= 'f') )
325 while( isdigit(*File->CurPos) )
328 // printf("*File->CurPos = '%c'\n", *File->CurPos);
331 if( *File->CurPos == '.' )
335 while( isdigit(*File->CurPos) )
339 if( *File->CurPos == 'e' || *File->CurPos == 'E' )
343 if(*File->CurPos == '-' || *File->CurPos == '+')
345 while( isdigit(*File->CurPos) )
349 // printf(" ret = %i\n", ret);
355 if( is_ident(*File->CurPos) )
360 while( is_ident(*File->CurPos) || isdigit(*File->CurPos) )
363 // This is set later too, but we use it below
364 File->TokenLen = File->CurPos - File->TokenStr;
366 // Check if it's a reserved word
368 char buf[File->TokenLen + 1];
370 memcpy(buf, File->TokenStr, File->TokenLen);
371 buf[File->TokenLen] = 0;
372 for( i = 0; i < ARRAY_SIZE(csaReservedWords); i ++ )
374 if(strcmp(csaReservedWords[i].Name, buf) == 0) {
375 ret = csaReservedWords[i].Value;
380 // If there's no match, just keep ret as TOK_IDENT
385 File->Token = TOK_INVAL;
387 fprintf(stderr, "Syntax Error: Unknown symbol '%c'\n", *File->CurPos);
388 longjmp(File->JmpTarget, 1);
394 File->TokenLen = File->CurPos - File->TokenStr;
398 char buf[ File->TokenLen + 1];
399 memcpy(buf, File->TokenStr, File->TokenLen);
400 buf[File->TokenLen] = 0;
401 //printf(" GetToken: File->CurPos = %p\n", File->CurPos);
402 printf(" GetToken: Return %i (%i long) (%s)\n", ret, File->TokenLen, buf);
408 void PutBack(tParser *File)
410 if( File->LastToken == -1 ) {
412 fprintf(stderr, "INTERNAL ERROR: Putback when LastToken==-1\n");
413 longjmp( File->JmpTarget, -1 );
417 printf(" PutBack: Was on %i\n", File->Token);
420 File->NextLine = File->CurLine;
421 File->NextToken = File->Token;
422 File->NextTokenStr = File->TokenStr;
423 File->NextTokenLen = File->TokenLen;
425 File->CurLine = File->LastLine;
426 File->Token = File->LastToken;
427 File->TokenStr = File->LastTokenStr;
428 File->TokenLen = File->LastTokenLen;
429 File->CurPos = File->NextTokenStr;
431 File->LastToken = -1;
434 int LookAhead(tParser *File)
436 // TODO: Should I save the entire state here?
437 int ret = GetToken(File);
444 * \brief Check for ident characters
445 * \note Matches Regex [a-zA-Z_]
447 int is_ident(char ch)
449 if('a' <= ch && ch <= 'z') return 1;
450 if('A' <= ch && ch <= 'Z') return 1;
451 if(ch == '_') return 1;
453 if(ch == '.') return 1;
461 if('0' <= ch && ch <= '9') return 1;
467 if(' ' == ch) return 1;
468 if('\t' == ch) return 1;
469 if('\b' == ch) return 1;
470 if('\n' == ch) return 1;
471 if('\r' == ch) return 1;