// AttrGram.cpp // A simple parser for the grammar // // -> = $ // -> + // -> // -> A | B | ... | Z #include #include #include #include enum TYPE { REAL, INTEGER }; enum TOKEN { VAR, ASSIGNOP, PLUSOP, ERRTOK, EOFTOK }; struct SYMBOL_TABLE { char name; TYPE vartype; }; SYMBOL_TABLE SYMTAB[3] = {{'A', INTEGER}, {'B', REAL}, {'C', INTEGER}}; TYPE lookup(char name) { int i; for (i = 0; i < 3; i++) if (SYMTAB[i].name == name) return SYMTAB[i].vartype; } struct TOK { TOKEN tok; char name; }; TOK curtok; // nexttoken is the scanner void nexttoken() { char ch; while (cin >> ch) { if (isspace(ch)) continue; // eat up white space else if (isalpha(ch) && ch >= 'A' && ch <= 'C') { curtok.name = ch; curtok.tok = VAR; break; } else if (ch == '=') { curtok.tok = ASSIGNOP; break; } else if (ch == '+') { curtok.tok = PLUSOP; break; } else if (ch == '$') { curtok.tok = EOFTOK; break; } else { cout << "Lexical error: " << ch << endl; curtok.tok = ERRTOK; break; } } } // returns a printable version of tok char* tok2str(TOKEN tok) { switch (tok) { case VAR : return "variable"; case ASSIGNOP : return "\"=\""; case PLUSOP : return "\"+\""; case EOFTOK : return "\"$\""; } } void match(TOKEN tok) { if (curtok.tok == tok) { nexttoken(); } else { cout << "Error: " << tok2str(tok) << " expected\n"; exit(1); } } void assign(); void expr(TYPE &var_type); void var(TYPE &expr_type); void assign() { TYPE lhs_type, expr_type; var(lhs_type); match(ASSIGNOP); expr(expr_type); if (lhs_type == expr_type) cout << "Type check ok\n"; else cout << "Type mismatch\n"; } void expr(TYPE &expr_type) { TYPE var1type, var2type; var(var1type); if (curtok.tok == PLUSOP) { match(PLUSOP); var(var2type); if (var1type == var2type) expr_type = var1type; else expr_type = REAL; } else expr_type = var1type; } void var(TYPE &var_type) { char name = curtok.name; match(VAR); var_type = lookup(name); } void main() { cout << "Assignment statement parser" << endl; cout << "Enter a statement: "; nexttoken(); assign(); if (curtok.tok == EOFTOK) cout << "Syntax check ok\n"; else cout << "End of file expected\n"; }