10 #define USE_SCOPE_CHAR 0
14 #define ARRAY_SIZE(x) ((sizeof(x))/(sizeof((x)[0])))
17 int is_ident(char ch);
20 int GetToken(tParser *File);
26 } csaReservedWords[] = {
27 {TOK_RWD_FUNCTION, "function"},
28 {TOK_RWD_RETURN, "return"},
29 {TOK_RWD_VOID, "void"},
30 {TOK_RWD_OBJECT, "Object"},
31 {TOK_RWD_INTEGER, "Integer"},
32 {TOK_RWD_REAL, "Real"},
33 {TOK_RWD_STRING, "String"}
38 * \brief Read a token from a buffer
39 * \param File Parser state
41 int GetToken(tParser *File)
45 if( File->NextToken != -1 ) {
47 File->LastToken = File->Token;
48 File->LastTokenStr = File->TokenStr;
49 File->LastTokenLen = File->TokenLen;
50 File->LastLine = File->CurLine;
52 File->Token = File->NextToken;
53 File->TokenStr = File->NextTokenStr;
54 File->TokenLen = File->NextTokenLen;
55 File->CurLine = File->NextLine;
57 File->CurPos = File->TokenStr + File->TokenLen;
60 char buf[ File->TokenLen + 1];
61 memcpy(buf, File->TokenStr, File->TokenLen);
62 buf[File->TokenLen] = 0;
64 printf(" GetToken: FAST Return %i (%i long) (%s)\n", File->Token, File->TokenLen, buf);
70 //printf(" GetToken: File=%p, File->CurPos = %p\n", File, File->CurPos);
72 // Clear whitespace (including comments)
76 while( isspace( *File->CurPos ) )
78 //printf("whitespace 0x%x, line = %i\n", *File->CurPos, File->CurLine);
79 if( *File->CurPos == '\n' )
85 if( *File->CurPos == '#' ) {
86 while( *File->CurPos && *File->CurPos != '\n' )
91 // C-Style Line Comments
92 if( *File->CurPos == '/' && File->CurPos[1] == '/' ) {
93 while( *File->CurPos && *File->CurPos != '\n' )
98 // C-Style Block Comments
99 if( *File->CurPos == '/' && File->CurPos[1] == '*' ) {
100 File->CurPos += 2; // Eat the '/*'
101 while( *File->CurPos && !(File->CurPos[-1] == '*' && *File->CurPos == '/') )
103 if( *File->CurPos == '\n' ) File->CurLine ++;
106 File->CurPos ++; // Eat the '/'
110 // No more "whitespace"
114 // Save previous tokens (speeds up PutBack and LookAhead)
115 File->LastToken = File->Token;
116 File->LastTokenStr = File->TokenStr;
117 File->LastTokenLen = File->TokenLen;
118 File->LastLine = File->CurLine;
121 File->TokenStr = File->CurPos;
122 switch( *File->CurPos++ )
124 case '\0': ret = TOK_EOF; break;
127 case '/': ret = TOK_DIV; break;
128 case '*': ret = TOK_MUL; break;
129 case '+': ret = TOK_PLUS; break;
131 if( *File->CurPos == '>' ) {
141 while( *File->CurPos && !(*File->CurPos == '"' && *File->CurPos != '\\') )
148 case '(': ret = TOK_PAREN_OPEN; break;
149 case ')': ret = TOK_PAREN_CLOSE; break;
150 case '{': ret = TOK_BRACE_OPEN; break;
151 case '}': ret = TOK_BRACE_CLOSE; break;
152 case '[': ret = TOK_SQUARE_OPEN; break;
153 case ']': ret = TOK_SQUARE_CLOSE; break;
156 case ';': ret = TOK_SEMICOLON; break;
157 case ',': ret = TOK_COMMA; break;
159 case '.': ret = TOK_SCOPE; break;
165 if( *File->CurPos == '=' ) {
175 // \$[0-9]+ or \$[_a-zA-Z][_a-zA-Z0-9]*
178 if( isdigit( *File->CurPos ) ) {
179 while( isdigit(*File->CurPos) )
184 while( is_ident(*File->CurPos) || isdigit(*File->CurPos) )
190 // Default (Numbers and Identifiers)
194 if( isdigit(*File->CurPos) )
196 while( isdigit(*File->CurPos) )
203 if( is_ident(*File->CurPos) )
206 while( is_ident(*File->CurPos) || isdigit(*File->CurPos) )
209 // This is set later too, but we use it below
210 File->TokenLen = File->CurPos - File->TokenStr;
213 // Check if it's a reserved word
215 char buf[File->TokenLen + 1];
217 memcpy(buf, File->TokenStr, File->TokenLen);
218 buf[File->TokenLen] = 0;
219 for( i = 0; i < ARRAY_SIZE(csaReservedWords); i ++ )
221 if(strcmp(csaReservedWords[i].Name, buf) == 0) {
222 ret = csaReservedWords[i].Value;
227 // If there's no match, just keep ret as TOK_IDENT
234 fprintf(stderr, "Syntax Error: Unknown symbol '%c'\n", *File->CurPos);
235 longjmp(File->JmpTarget, 1);
241 File->TokenLen = File->CurPos - File->TokenStr;
245 char buf[ File->TokenLen + 1];
246 memcpy(buf, File->TokenStr, File->TokenLen);
247 buf[File->TokenLen] = 0;
248 //printf(" GetToken: File->CurPos = %p\n", File->CurPos);
249 printf(" GetToken: Return %i (%i long) (%s)\n", ret, File->TokenLen, buf);
255 void PutBack(tParser *File)
257 if( File->LastToken == -1 ) {
259 fprintf(stderr, "INTERNAL ERROR: Putback when LastToken==-1\n");
260 longjmp( File->JmpTarget, -1 );
264 printf(" PutBack: Was on %i\n", File->Token);
267 File->NextLine = File->CurLine;
268 File->NextToken = File->Token;
269 File->NextTokenStr = File->TokenStr;
270 File->NextTokenLen = File->TokenLen;
272 File->CurLine = File->LastLine;
273 File->Token = File->LastToken;
274 File->TokenStr = File->LastTokenStr;
275 File->TokenLen = File->LastTokenLen;
276 File->CurPos = File->NextTokenStr;
278 File->LastToken = -1;
281 int LookAhead(tParser *File)
283 // TODO: Should I save the entire state here?
284 int ret = GetToken(File);
291 * \brief Check for ident characters
292 * \note Matches Regex [a-zA-Z_]
294 int is_ident(char ch)
296 if('a' <= ch && ch <= 'z') return 1;
297 if('A' <= ch && ch <= 'Z') return 1;
298 if(ch == '_') return 1;
300 if(ch == '.') return 1;
308 if('0' <= ch && ch <= '9') return 1;
314 if(' ' == ch) return 1;
315 if('\t' == ch) return 1;
316 if('\b' == ch) return 1;
317 if('\n' == ch) return 1;
318 if('\r' == ch) return 1;