/* * JavaCC source of a * parser for the Oberon-2 Programming Language * * Author: James Power, * Affiliation: Dept. of Computer Science, National University of Ireland, * Maynooth, Co. Kildare, Ireland. * Last Revised: 17 November 1998 * * Based on: "The Programming Language Oberon" * H. Mossenbock, N. Wirth, ETH Zurich, 1992-1996 * * For more information on Oberon see http://www.oberon.ethz.ch/language.html */ PARSER_BEGIN(OberonParser) public final class OberonParser { // Standard parser class setup... public static void main(String args[]) { OberonParser parser; java.io.InputStream input; if (args.length==1) { System.out.print(args[args.length-1] + ": "); try { input = new java.io.FileInputStream(args[args.length-1]); } catch (java.io.FileNotFoundException e) { System.out.println("File not found."); return; } } else if (args.length==0) { System.out.println("Reading from standard input..."); input = System.in; } else { System.out.println("Usage: java OberonParser [inputfile]"); return; } try { parser = new OberonParser(input); parser.translation_unit(); System.out.println("Successful parse!"); } catch (ParseException e) { String msg = e.getMessage(); msg = msg.substring(0,msg.indexOf("\n")); System.out.println("Syntax Error: "+msg); } } } PARSER_END(OberonParser) /***************************************/ /********** TOKEN DEFINITIONS **********/ /***************************************/ TOKEN_MGR_DECLS : { static int commentNesting; // Current level of nesting of comments } /*** Skip whitespace and comments ***/ SKIP : { " " | "\t" | "\n" | "\r" | "(*" { commentNesting=1; } : IN_COMMENT } MORE: { < ~[] > } SKIP: { < "(*" > { commentNesting++; } | < "*)" > { commentNesting--; if (commentNesting==0) SwitchTo(DEFAULT); } } /*** The keywords ***/ TOKEN : { | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | } TOKEN : { < DOTDOT : ".." > } /* The hack: if we see digits followed by "..", trap it here, otherwise * the digits and first dot will be gobbled up to make a REAL below, * and the second dot will give a syntax error */ TOKEN : { < DIGIT_DOT_HACK : ()+ ".." > { // Create the new token and initialise its fields properly Token newTok = new Token(); newTok.kind = DOTDOT; newTok.beginLine = newTok.endLine = matchedToken.endLine; newTok.beginColumn = matchedToken.endColumn-1; newTok.endColumn = matchedToken.endColumn; newTok.image=".."; newTok.next = matchedToken.next; newTok.specialToken = null; // Now fix up matchedToken: matchedToken.kind = INTEGER; matchedToken.endColumn -= 2; matchedToken.image = matchedToken.image.substring(0,matchedToken.image.length()-2); matchedToken.next = newTok; } } /*** Basic constants: numbers, idents, chars and strings ***/ TOKEN : { < #DIGIT : ["0"-"9"] > | < #SCALEFACTOR : ("E" | "D") ("+" | "-")? ()+ > | < #HEXDIGIT : ["0"-"9","A"-"F"] > | < INTEGER : ()+ | ()* "H" > | < REAL : ()+ "." ()* ()? > | < #LETTER : ["A"-"Z","a"-"z"] > | < IDENT : ( | )* > | < CHARACTER : ()* "X" > | < STRING : "\"" (~["\""])* "\"" | "'" (~["'"])* "'" > } /**************************************/ /********** START OF GRAMMAR **********/ /**************************************/ void translation_unit() : {} { Module() } void Module() : {} { ";" (ImportList())? DeclSeq() ( StatementSeq())? "." } void ImportList() : {} { ImportSpec() ("," ImportSpec())* ";" } void ImportSpec() : {} { (":=" )? } void DeclSeq() : {} { ( VarTypeDecl() )* ( ProcedureDecl() )* } void VarTypeDecl() : {} { (ConstDecl() ";")* | (TypeDecl() ";")* | (VarDecl() ";")* } void ConstDecl() : {} { IdentDef() "=" ConstExpr() } void TypeDecl() : {} { IdentDef() "=" Type() } void VarDecl() : {} { IdentList() ":" Type() } void ProcedureDecl() : {} { (ForwardDecl() | ProcDecl()) ";" } void ProcDecl() : {} { (Receiver())? IdentDef() (FormalPars())? ";" DeclSeq() ( StatementSeq())? } void ForwardDecl() : {} { "^" (Receiver())? IdentDef() (FormalPars())? } void FormalPars() : {} { "(" (FPSection() (";" FPSection())*)? ")" (":" Qualident())? } void FPSection() : {} { ()? ("," )* ":" Type() } void Receiver() : {} { "(" ()? ":" ")" } void Type() : {} { Qualident() | (ConstExpr() ("," ConstExpr())*)? Type() | ("("Qualident()")")? FieldList() (";" FieldList())* | Type() | (FormalPars())? } void FieldList() : {} { (IdentList() ":" Type())? } void StatementSeq() : {} { optStatement() (";" optStatement())* } void optStatement() : {} { (Statement())? } void Statement() : {} { Designator() ((":=" Expr()) | Arguments() ) | Expr() StatementSeq() ( Expr() StatementSeq())* ( StatementSeq())? | Expr() Case() ("|" Case())* ( StatementSeq())? | Expr() StatementSeq() | StatementSeq() Expr() | ":=" Expr() Expr() ( ConstExpr())? StatementSeq() | StatementSeq() | Guard() StatementSeq() ("|" Guard() StatementSeq())* ( StatementSeq())? | | (Expr())? } void Case() : {} { (CaseLabels() ("," CaseLabels())* ":" StatementSeq())? } void CaseLabels() : {} { ConstExpr() ( ConstExpr())? } void Guard() : {} { Qualident() ":" Qualident() } void ConstExpr() : {} { Expr() } void Expr() : {} { SimpleExpr() (Relation() SimpleExpr())? } void SimpleExpr() : {} { ("+" | "-")? Term() (AddOp() Term())* } void Term() : {} { Factor() (MulOp() Factor())* } void Factor() : {} { Designator() Arguments() | Number() | | | | Set() | "(" Expr() ")" | "~" Factor() } void Set() : {} { "{" (Element() ("," Element())* )? "}" } void Element() : {} { Expr() ( Expr())? } void Relation() : {} { "=" | "#" | "<" | "<=" | ">" | ">=" | | } void AddOp() : {} { "+" | "-" | } void MulOp() : {} { "*" | "/" |
| | "&" } /* NB: Because Arguments() always appears after Designator(), there * will be a conflict if we get "(" Qualident() ")" - do we consume * this as part of the Designator(), or leave it for the Arguments() * The disambiguation in Designator() chooses the former, so the * semantic phase will have to disentangle this for function calls * with one (qualified) identifier as an argument. */ void Arguments() : {} { ( "(" (ExprList())? ")" )? } void Designator() : {} { (LOOKAHEAD("." | "[" | "^" | ("(" Qualident() ")")) ( "." | "[" ExprList() "]" | "^" | "(" Qualident() ")") )* } void ExprList() : {} { Expr() ("," Expr())* } void IdentList() : {} { IdentDef() ("," IdentDef())* } void Qualident() : {} { // ( ".")? ("." )? } void IdentDef() : {} { ("*" | "-")? } void Number() : {} { | }