#include #include #include #include #include #include #include #include #include "lalex.h" #include "exprpar.h" extern fileReader *currFile; reservWords resWords[] = { {"int", 200}, {"char", 201}, {"string", 202}, {"real", 203}, {"double", 204}, {"for", 301}, {"to", 302}, {"step", 303}, {"next", 304} }; int getToken(tokenRec *_tokRec); int getChar(); int getCharEx(int *_nl); void putBack(char _ch); int lookAhead(int _match_ch, int _remove); void parserError(char *_msg); int openFile(fileReader *fr) { fr->charbuf[0] = '\0'; fr->linenum = 0; fr->tokbuf.count = 0; fr->tokbuf.next = -1; memset(fr->backtoken, '\0', 10 * sizeof(tokenRec)); if ((fr->fd = open(fr->name, O_RDONLY)) == -1) { fprintf(stderr, "Cannot open file %s\n", fr->name); return 0; } return 1; } int matchTokenId(int _tokid, int _remove) { static tokenRec t; getToken(&t); if (t.stype == _tokid) { if (!_remove) putTokenBack(&t); return 1; } putTokenBack(&t); return 0; } int getToken(tokenRec *_tokRec) { int newline; char ch; char ch2 = 0; char buf[256]; char *cPtr; // Read next token from the file memset(_tokRec, sizeof(tokenRec), '\0'); _tokRec->mtype = _tokRec->stype = 0; // Get next char. Remove also white spaces and comments ch = getCharEx(&newline); // Check if it's an operator switch (ch) { case '=': _tokRec->stype = TOK_ASSIGN; // == if (lookAhead('=',1)) _tokRec->stype = TOK_EQ; break; case '+': // += if (lookAhead('=',1)) _tokRec->stype = TOK_ASPLUS; // ++ else if (lookAhead('+',1)) _tokRec->stype = TOK_INCR; // + else _tokRec->stype = TOK_PLUS; break; case '-': // -= if (lookAhead('=',1)) _tokRec->stype = TOK_ASMINUS; // -- else if (lookAhead('-',1)) _tokRec->stype = TOK_DECR; // - else _tokRec->stype = TOK_MINUS; break; case '*': // *= if (lookAhead('=',1)) _tokRec->stype = TOK_ASMUL; // * else _tokRec->stype = TOK_MUL; break; case '/': // "/=" if (lookAhead('=',1)) _tokRec->stype = TOK_ASDIV; // "/" else _tokRec->stype = TOK_DIV; break; case '%': // %= (modulus) if (lookAhead('=',1)) _tokRec->stype = TOK_ASMOD; // % else _tokRec->stype = TOK_MOD; break; case '>': // >= if (lookAhead('=',1)) _tokRec->stype = TOK_GE; // > else _tokRec->stype = TOK_GT; break; case '<': // <= if (lookAhead('=',1)) _tokRec->stype = TOK_LE; // < else _tokRec->stype = TOK_LT; break; } // Is operator if (_tokRec->stype) { *(_tokRec->val.ident) = ch; *(_tokRec->val.ident+1) = '\0'; _tokRec->mtype = TOK_OPER; // DEBUG printf("tok:%c\n", _tokRec->stype); return _tokRec->mtype; } // An identifier ch2 = tolower(ch); if ((ch2 >= 'a' && ch2 <= 'z') || strchr("_$", ch)) { *buf = ch; cPtr = buf +1; ch = getChar(); while ((isalnum(ch) || strchr("_$", ch)) && ch != EOF) { *cPtr++ = ch; ch = getChar(); } *cPtr = '\0'; _tokRec->mtype = TOK_IDENT; _tokRec->stype = TOK_IDENT; strcpy(_tokRec->val.ident, buf); printf("Identifier:<%s>\n", buf); } // Is a string else if (ch == '"' || ch == '\'') { char chStart = ch; cPtr = buf; ch2 = '\0'; // Handle ".....\"...." while (1) { ch = getChar(); if (ch == EOF) break; // Check for \" and \' if (ch == chStart && ch2 != '\\') { break; } else { ch2 = *cPtr; *cPtr++ = ch; } } *cPtr = '\0'; _tokRec->val.s = E2MALLOC(strlen(buf)+1); strcpy(_tokRec->val.s, buf); _tokRec->mtype = TOK_STRING; _tokRec->stype = TOK_STRING; } // Is a number else if (strchr("0123456789+-.", ch)) { int hasDecimal = 0; int hasExp = 0; int hasExpSign = 0; cPtr = buf; *cPtr++ = ch; if (ch == '.') { hasDecimal = 1; } // .67, -2.67, +89, -4e3, +2e-9 // while (1) { ch = getChar(); if (ch == EOF) break; if (ch == '.' && !hasDecimal) { *cPtr++ = ch; hasDecimal = 1; } else if (tolower(ch) == 'e' && !hasExp) { *cPtr++ = ch; hasExp= 1; } else if (strchr("+-", ch) && hasExp && (!hasExpSign)) { *cPtr++ = ch; hasExpSign = ch; } else if (strchr("0123456789", ch)) { *cPtr++ = ch; } else break; } *cPtr = '\0'; double d = atof(buf); _tokRec->mtype = TOK_NUMERIC; if (hasDecimal || hasExpSign == (int)'-') { _tokRec->val.d = d; _tokRec->stype = TOK_REAL; } else { _tokRec->val.i = (long)d; _tokRec->stype = TOK_INT; } printf("tok integer:%ld\n", _tokRec->val.i); } else { return EOF; } return _tokRec->mtype; } void putBack(char _ch) { size_t len = strlen(currFile->charbuf); if (len < 128 - 1 ) { *(currFile->charbuf + len) = _ch; *(currFile->charbuf + len+1) = '\0'; } else { parserError("Parser error ! FileReader backbuffer is full."); } } int getCharEx(int *_nl) { int ch; int ch2; int move; *_nl = 0; ch = getChar(); while (ch != EOF) { move = 0; // Remove white spaces while (isspace(ch)) { if (ch == '\n'|| ch == '\r') *_nl++; ch = getChar(); } // Comment to EOL if (ch == '/') { ch2 = getChar(); if (ch2 == '/') { // Read to EOL ch = getChar(); while (ch != EOF && ch != '\n') { ch = getChar(); } *_nl++; move = 1; printf("REMOVED COMMENT // \n"); } else if (ch2 == '*') { int count = 1; // Count inner /* /* /*... */ */ */ ch = getChar(); ch2 = 0; while (ch != EOF) { printf("%c", ch); // Comment end '*/' if (ch == '/' && ch2 == '*') { if (--count <= 0) { printf("REMOVED COMMENT /* */ \n"); move = 1; break; } } // Beg inner /* else if (ch == '*' && ch2 == '/') { count++; } else if (ch == '\n'|| ch == '\r') { *_nl++; } // Prev. char ch2 = ch; ch = getChar(); } if (ch == EOF && count) { parserError("Multi line comment /* ... */ is not closed"); } } else { putBack(ch2); } } if (move) ch = getChar(); else break; } return ch; } int lookAhead(int _match_ch, int _remove) { int ret; int ch = getChar(); if (ch == _match_ch) { if (!_remove) putBack(ch); ret = 1; } else { putBack(ch); ret = 0; } return ret; } int getChar() { size_t c; int ch = '\0'; // Check back buffer if (currFile->backbuf[0] != '\0') { size_t len = strlen(currFile->backbuf); ch = *(currFile->backbuf + len-1); *(currFile->backbuf + len-1) = '\0'; return ch; } // Read from the file c = read(currFile->fd, (char*)&ch, 1); if (!c) return EOF; else if (ch == '\n') currFile->linenum++ ; return ch; } int putTokenBack(tokenRec *_tr) { // TODO: WRONG ORDER. FIX IT if (currFile->numbacktok >= 10) { fprintf(stderr, "putTokenBack: Cannot add tokens to backbuffer.\n"); return 0; } currFile->backtoken[currFile->numbacktok++] = *_tr; return 1; } int getBackToken(tokenRec *_tr) { // TODO: WRONG ORDER. FIX IT if (currFile->numbacktok <= 0) return 0; *_tr = currFile->backtoken[--currFile->numbacktok]; return 1; } void parserError(char *_msg) { fprintf(stderr, "%s %d: %s\n", currFile->name, (int)currFile->linenum, _msg); } // ---------------------------------------------- lalex.h fila er her: ^^^^^^^^^^^^^^^^^^^^ #ifndef LALEX_H #define LALEX_H #define TOK_NUMERIC 150 // ---------------------- #define TOK_INT 151 #define TOK_REAL 152 #define TOK_CHAR 153 #define TOK_STRING 170 #define TOK_RESERVWORD 200 // ---------------------- #define TOK_IDENT 300 // ---------------------- #define TOK_COMMENT 370 #define TOK_OPER 400 #define TOK_ASSIGN '=' // = #define TOK_EQ 401 // == #define TOK_MINUS '-' // - #define TOK_ASMINUS 403 // -= #define TOK_DECR 404 // -- #define TOK_PLUS '+' // + #define TOK_ASPLUS 409 // += #define TOK_INCR 410 // ++ #define TOK_DIV '/' // / #define TOK_ASDIV 416 // /= #define TOK_MUL '*' // * #define TOK_ASMUL 419 // *= #define TOK_MOD '%' // % a Modulus b #define TOK_ASMOD 421 // %= #define TOK_AND 430 // && Boolean AND #define TOK_BITAND '&' // & Bitwise AND #define TOK_ASBITAND 432 // &= Bitwise AND #define TOK_EXP '^' // ^ expoonet, a^2 #define TOK_OR 435 // || Boolean OR #define TOK_BITOR '|' // | Bitwise OR #define TOK_ASBITOR 437 // |= Bitwise OR #define TOK_GT '>' // > Greater than #define TOK_GE 451 // >= Greater or equal #define TOK_LT '<' // < Less than #define TOK_LE 456 // <= Less or equal #define TOK_PAROPEN '(' // ( #define TOK_PARCLOSE ')' // ) #define TOK_IF 480 // IF condition THEN... | expr IF condition THEN... #define TOK_THEN 481 // THEN #define TOK_ELSE 482 // ELSE #define TOK_UNLESS 483 // UNLESS (a=expr UNLESS condition) #endif