CSC448: Further examples: Arithmetic [21/22] |
EBNF/BNF for arithmetic expressions.
Precedence and associativity.
Ignore semantic actions (code in braces) for now.
file:arithmetic.flex [source]
00001: import java_cup.runtime.SymbolFactory; 00002: 00003: %% 00004: 00005: %class ArithmeticLexer 00006: %public 00007: %{ 00008: private SymbolFactory sf; 00009: public ArithmeticLexer (java.io.InputStream r, SymbolFactory sf) 00010: { 00011: this (r); 00012: this.sf = sf; 00013: } 00014: %} 00015: %eofval{ 00016: return sf.newSymbol ("EOF", sym.EOF); 00017: %eofval} 00018: 00019: %unicode 00020: 00021: %cup 00022: %cupdebug 00023: 00024: %char 00025: %column 00026: %line 00027: 00028: 00029: ALPHA=[A-Za-z_] 00030: DIGIT=[0-9] 00031: NONNEWLINE_WHITE_SPACE_CHAR=[\ \t\b\012] 00032: NEWLINE=\r|\n|\r\n 00033: IDENT={ALPHA}({ALPHA}|{DIGIT}|_)* 00034: 00035: %% 00036: 00037: <YYINITIAL> { 00038: "(" { return sf.newSymbol ("LeftParen", sym.LPAREN); } 00039: ")" { return sf.newSymbol ("RightParen", sym.RPAREN); } 00040: ";" { return sf.newSymbol ("Semicolon", sym.SEMI); } 00041: "=" { return sf.newSymbol ("Equals", sym.EQUALS); } 00042: "+" { return sf.newSymbol ("Plus", sym.PLUS); } 00043: "-" { return sf.newSymbol ("Minus", sym.MINUS); } 00044: "*" { return sf.newSymbol ("Times", sym.TIMES); } 00045: "/" { return sf.newSymbol ("Divide", sym.DIVIDE); } 00046: 00047: {NONNEWLINE_WHITE_SPACE_CHAR}+ { } 00048: 00049: {IDENT} 00050: { return sf.newSymbol ("Identifier", sym.IDENTIFIER, yytext ()); } 00051: 00052: {DIGIT}+ 00053: { 00054: int i = Integer.parseInt (yytext ()); 00055: return sf.newSymbol ("IntegerConstant", sym.INTEGER_CONSTANT, new Integer (i)); 00056: } 00057: } 00058: 00059: {NEWLINE} { } 00060: 00061: . { 00062: System.out.println ("Illegal character: <" + yytext () + ">"); 00063: } 00064: 00065:
file:arithmetic.cup [source]
00001: import java_cup.runtime.*; 00002: 00003: import java.util.ArrayList; 00004: import java.util.List; 00005: 00006: 00007: terminal LPAREN, RPAREN; 00008: terminal SEMI, EQUALS; 00009: terminal PLUS, MINUS, TIMES, DIVIDE; 00010: 00011: terminal String IDENTIFIER; 00012: terminal Integer INTEGER_CONSTANT; 00013: 00014: non terminal List<Decl> decl_list; 00015: non terminal Decl decl; 00016: non terminal Exp expression; 00017: 00018: precedence left PLUS, MINUS; 00019: precedence left TIMES, DIVIDE; 00020: 00021: 00022: decl_list ::= decl_list:l decl:d 00023: {: l.add (d); RESULT = l; :} 00024: | 00025: {: RESULT = new ArrayList<Decl> (); :} 00026: ; 00027: 00028: decl ::= IDENTIFIER:id EQUALS expression:e SEMI 00029: {: RESULT = new Decl (id, e); :} 00030: ; 00031: 00032: expression ::= INTEGER_CONSTANT:i 00033: {: RESULT = new ExpInt (i.intValue ()); :} 00034: | IDENTIFIER:id 00035: {: RESULT = new ExpVar (id); :} 00036: | expression:e1 PLUS expression:e2 00037: {: RESULT = new ExpBinOp (ExpBinOp.BinOp.PLUS, e1, e2); :} 00038: | expression:e1 MINUS expression:e2 00039: {: RESULT = new ExpBinOp (ExpBinOp.BinOp.MINUS, e1, e2); :} 00040: | expression:e1 TIMES expression:e2 00041: {: RESULT = new ExpBinOp (ExpBinOp.BinOp.TIMES, e1, e2); :} 00042: | expression:e1 DIVIDE expression:e2 00043: {: RESULT = new ExpBinOp (ExpBinOp.BinOp.DIVIDE, e1, e2); :} 00044: | LPAREN expression:e RPAREN 00045: {: RESULT = e; :} 00046: ; 00047: 00048: