JavaCC Rules. Structure of JavaCC File. JavaCC rules correspond to EBNF rules. JavaCC rules have the form:

Similar documents
Structure of JavaCC File. JavaCC Rules. Lookahead. Example JavaCC File. JavaCC rules correspond to EBNF rules. JavaCC rules have the form:

Abstract Syntax Trees

JavaCC. JavaCC File Structure. JavaCC is a Lexical Analyser Generator and a Parser Generator. The structure of a JavaCC file is as follows:

Compilation 2014 Warm-up project

CS Parsing 1

CPSC 411: Introduction to Compiler Construction

Fundamentals of Compilation

Topic 3: Syntax Analysis I

CS 132 Compiler Construction

Topic 5: Syntax Analysis III

PART ONE Fundamentals of Compilation

Abstract Syntax. Mooly Sagiv. html://

CS 352: Compilers: Principles and Practice

Compiler Construction

4. Parsing in Practice

JavaCC: SimpleExamples

Lecture 12: Parser-Generating Tools

Automated Tools. The Compilation Task. Automated? Automated? Easier ways to create parsers. The final stages of compilation are language dependant

JavaCC Parser. The Compilation Task. Automated? JavaCC Parser

ASTs, Objective CAML, and Ocamlyacc

Compiler Construction 1. Introduction. Oscar Nierstrasz

Compilers CS S-01 Compiler Basics & Lexical Analysis

Compilers CS S-01 Compiler Basics & Lexical Analysis

CS S-01 Compiler Basics & Lexical Analysis 1

Simple LR (SLR) LR(0) Drawbacks LR(1) SLR Parse. LR(1) Start State and Reduce. LR(1) Items 10/3/2012

EDAN65: Compilers, Lecture 06 A LR parsing. Görel Hedin Revised:

Compiler Construction 1. Introduction. Oscar Nierstrasz

COP 3402 Systems Software Top Down Parsing (Recursive Descent)

CA Compiler Construction

Modern Compiler Implementation in ML

COMP3131/9102: Programming Languages and Compilers

EDA180: Compiler Construc6on. Top- down parsing. Görel Hedin Revised: a

Part III : Parsing. From Regular to Context-Free Grammars. Deriving a Parser from a Context-Free Grammar. Scanners and Parsers.

10/4/18. Lexical and Syntactic Analysis. Lexical and Syntax Analysis. Tokenizing Source. Scanner. Reasons to Separate Lexical and Syntactic Analysis

CPS 506 Comparative Programming Languages. Syntax Specification

CPSC 411, Fall 2010 Midterm Examination

Compiler Compiler Tutorial

8 Parsing. Parsing. Top Down Parsing Methods. Parsing complexity. Top down vs. bottom up parsing. Top down vs. bottom up parsing

Parser Combinators 11/3/2003 IPT, ICS 1

A simple syntax-directed

The Zephyr Abstract Syntax Description Language

Left to right design 1

Project 1: Scheme Pretty-Printer

Chapter 4. Abstract Syntax

LL(k) Compiler Construction. Choice points in EBNF grammar. Left recursive grammar

LL(k) Compiler Construction. Top-down Parsing. LL(1) parsing engine. LL engine ID, $ S 0 E 1 T 2 3

PROGRAMMING FUNDAMENTALS

EDAN65: Compilers, Lecture 04 Grammar transformations: Eliminating ambiguities, adapting to LL parsing. Görel Hedin Revised:

Top down vs. bottom up parsing

CSE P 501 Compilers. Implementing ASTs (in Java) Hal Perkins Winter /22/ Hal Perkins & UW CSE H-1

G53CMP: Lecture 4. Syntactic Analysis: Parser Generators. Henrik Nilsson. University of Nottingham, UK. G53CMP: Lecture 4 p.1/32

Lexical and Syntax Analysis

CSE P 501 Compilers. Implementing ASTs (in Java) Hal Perkins Autumn /20/ Hal Perkins & UW CSE H-1

CIT 3136 Lecture 7. Top-Down Parsing

MP 3 A Lexer for MiniJava

Types of parsing. CMSC 430 Lecture 4, Page 1

MP 3 A Lexer for MiniJava

SML-SYNTAX-LANGUAGE INTERPRETER IN JAVA. Jiahao Yuan Supervisor: Dr. Vijay Gehlot

Chapter 3. Parsing #1

10/5/17. Lexical and Syntactic Analysis. Lexical and Syntax Analysis. Tokenizing Source. Scanner. Reasons to Separate Lexical and Syntax Analysis

Defining syntax using CFGs

Comp 411 Principles of Programming Languages Lecture 3 Parsing. Corky Cartwright January 11, 2019

CA Compiler Construction

Course Overview. Introduction (Chapter 1) Compiler Frontend: Today. Compiler Backend:

Name EID. (calc (parse '{+ {with {x {+ 5 5}} {with {y {- x 3}} {+ y y} } } z } ) )

CS 4240: Compilers and Interpreters Project Phase 1: Scanner and Parser Due Date: October 4 th 2015 (11:59 pm) (via T-square)

In this simple example, it is quite clear that there are exactly two strings that match the above grammar, namely: abc and abcc

Parsing and Pattern Recognition

CSE 3302 Programming Languages Lecture 2: Syntax

A Simple Syntax-Directed Translator

Compilers. Predictive Parsing. Alex Aiken

Outline. Top Down Parsing. SLL(1) Parsing. Where We Are 1/24/2013

Build your own languages with

COMPILER (CSE 4120) (Lecture 6: Parsing 4 Bottom-up Parsing )

3. Parsing. 3.1 Context-Free Grammars and Push-Down Automata 3.2 Recursive Descent Parsing 3.3 LL(1) Property 3.4 Error Handling

shift-reduce parsing

Projects for Compilers

Question Points Score

Compilers - Chapter 2: An introduction to syntax analysis (and a complete toy compiler)

Building Compilers with Phoenix

Programming Languages. Dr. Philip Cannata 1

Part II : Lexical Analysis

LECTURE 3. Compiler Phases

Last Time. What do we want? When do we want it? An AST. Now!

The role of semantic analysis in a compiler

Syntax Analysis, III Comp 412

Compilation 2010 SableCC

LL(k) Parsing. Predictive Parsers. LL(k) Parser Structure. Sample Parse Table. LL(1) Parsing Algorithm. Push RHS in Reverse Order 10/17/2012

RYERSON UNIVERSITY DEPARTMENT OF COMPUTER SCIENCE CPS 710 FINAL EXAM FALL 2016

Name SOLUTIONS EID NOTICE: CHEATING ON THE MIDTERM WILL RESULT IN AN F FOR THE COURSE.

4. Semantic Processing and Attributed Grammars

Compiler Design Concepts. Syntax Analysis

Chapter 4: Syntax Analyzer

A lexical analyzer generator for Standard ML. Version 1.6.0, October 1994

Compiler Theory. (Semantic Analysis and Run-Time Environments)

UNIVERSITY OF CALIFORNIA Department of Electrical Engineering and Computer Sciences Computer Science Division

LL parsing Nullable, FIRST, and FOLLOW

Building a Parser III. CS164 3:30-5:00 TT 10 Evans. Prof. Bodik CS 164 Lecture 6 1

Last time. What are compilers? Phases of a compiler. Scanner. Parser. Semantic Routines. Optimizer. Code Generation. Sunday, August 29, 2010

Semantic Analysis. Outline. The role of semantic analysis in a compiler. Scope. Types. Where we are. The Compiler Front-End

Transcription:

Structure of JavaCC File JavaCC Rules options /* Code to set various options flags */ PARSER_BEGIN(MyParser) public class MyParser /* Java program is placed here */ PARSER_END(MyParser) TOKEN_MGR_DECLS : /* Declarations used by lexical analyser */ /* Token Rules and Actions */ /* JavaCC Rules and Actions - EBNF for language */ JavaCC rules correspond to EBNF rules JavaCC rules have the form: void nonterminalname() : /* Java Declarations */ /* Rule definition */ Non-terminals in JavaCC rules have the form of a Java method call Terminals in JavaCC rules are between < and > Forexample,theCFGrules: S while (E) S S V = E; Would be represented by the JavaCC rule: void statement() : <WHILE> <LPAREN> expression() <RPAREN> statement() variable() <ASSIGN> expression() <SEMICOLON> Compiler Construction 1 1 Compiler Construction 1 2

Example JavaCC File Lookahead We now examine a JavaCC file that parses prefix expressions Prefix expression examples: Prefix expression Equivalent infix expression +34 3+4 +-215 (2-1) + 5 +-34*56 (3-4) + (5 * 6) +-*3456 ((3*4)-5)+6 +3-4*56 3+(4-(5*6)) CFG for prefix expressions: E + EE E EE E EE E /EE E num In JavaCC: void expression(): <PLUS> expression() expression() <MINUS> expression() expression() <TIMES> expression() expression() <DIVIDE> expression() expression() <INTEGER_LITERAL> Consider the following JavaCC fragment: void S(): "a" "b" "c" "a" "d" "c" Is this grammar LL(1)? A LOOKAHEAD directive, placed at a choice point, will allow JavaCC to use a lookahead > 1: void S(): LOOKAHEAD(2) "a" "b" "c" "a" "d" "c" JavaCC will look at the next two symbols, before deciding which rule for S to use Compiler Construction 1 3 Compiler Construction 1 4

Lookahead JavaCC and Non-LL(k) LOOKAHEAD directives are placed at choice points - places in the grammar where there is more than one possible rule that can match. Problem grammar: void S(): "A" (("B" "C") ("B" "D")) Solution using LOOKAHEAD: void S(): "A" ( LOOKAHEAD(2) ("B" "C") ("B" "D")) Another possible solution? void S(): LOOKAHEAD(2) "A" (("B" "C") ("B" "D")) JavaCC will produce a parser for grammars that are not LL(1) (and even for grammars that are not LL(k), for any k) The parser that is produced is not guaranteed to correctly parse the language described by the grammar A warning will be issued when JavaCC is run on a non-ll(1) grammar For a non-ll(1) grammar, the rule that appears first will be used: void S() : "a" "b" "c" "a" "b" "d" If not, why not? Compiler Construction 1 5 Compiler Construction 1 6

JavaCC and Non-LL(k) JavaCC and Non-LL(k) Infamous dangling else. Why doesn t the following grammar work? void statement(): <IF> expression() <THEN> statement() <IF> expression() <THEN> statement() <ELSE> statement() /* Other statement definitions */ The following grammar will work, but a warning will be given by JavaCC: void statement() : <IF> expression() <THEN> statement() optionalelse() /* Other statement definitions */ void optionalelse() : <ELSE> statement() /* nothing */ What about this grammar? void statement() : <IF> expression() <THEN> statement() optionalelse() /* Other statement definitions */ void optionalelse() : /* nothing */ <ELSE> statement() Why doesn t this grammar work? The following grammar works correctly, but also produces a warning: void statement() : <IF> expression() <THEN> statement() (<ELSE> statement /* Other statement definitions */ Compiler Construction 1 7 Compiler Construction 1 8

JavaCC and Non-LL(k) Specifying the Grammar of the Straight The following grammar works correctly: void statement() : <IF> expression() <THEN> statement() (LOOKAHEAD(1) <ELSE> statement)? /* Other statement definitions */ This grammar produces no warnings - not because it is any more safe - if you include a LOOKAHEAD directive, JavaCC assumes you know what you are doing. As a reminder, the grammar for the straight line programming language is as follows: Stm Stm ; Stm (CompoundStm Stm id := Exp (AssignStm Stm print ( ExpList ) (PrintStm Exp id (IdExp Exp num (NumExp Exp Exp Binop Exp (OpExp Exp ( Stm, Exp ) (EseqExp ExpList Exp, ExpList (PairExpList ExpList Exp (LastExpList Binop + (Plus Binop - (Minus Binop (Times Binop / (Div Compiler Construction 1 9 Compiler Construction 1 10

Specifying the Grammar of the Straight Specifying the Grammar of the Straight options JAVA_UNICODE_ESCAPE = true; PARSER_BEGIN(SLPParser) public class SLPParser public static void main(string args[]) SLPParser parser; if (args.length == 0) System.out.println("SLP Parser: Reading from standard input..."); parser = new SLPParser(System.in); else if (args.length == 1) System.out.println("SLP Parser: Reading from file " + args[0] + "..."); try parser = new SLPParser(new java.io.fileinputstream(args[0])); catch (java.io.filenotfoundexception e) System.out.println("SLP Parser: File " + args[0] + " not found."); return; else System.out.println("SLP Parser: Usage is one of:"); System.out.println(" java SLPParser < inputfile"); System.out.println("OR"); System.out.println(" java SLPParser inputfile"); return; try parser.prog(); System.out.println("SLP Parser: SLP program parsed successfully."); catch (ParseException e) System.out.println(e.getMessage()); System.out.println("SLP Parser: Encountered errors during parse."); PARSER_END(SLPParser) /***************************************** ***** SECTION 3 - TOKEN DEFINITIONS ***** *****************************************/ TOKEN_MGR_DECLS : static int commentnesting = 0; SKIP : /*** Ignoring spaces/tabs/newlines ***/ " " "\t" "\n" "\r" "\f" SKIP : /* COMMENTS */ "/*" commentnesting++; : IN_COMMENT <IN_COMMENT> SKIP : "/*" commentnesting++; "*/" commentnesting--; if (commentnesting == 0) SwitchTo(DEFAULT); <~[]> Compiler Construction 1 11 Compiler Construction 1 12

Specifying the Grammar of the Straight Specifying the Grammar of the Straight TOKEN : /* Keywords and punctuation */ < SEMIC : ";" > < ASSIGN : ":=" > < PRINT : "print" > < LBR : "(" > < RBR : ")" > < COMMA : "," > < PLUS_SIGN : "+" > < MINUS_SIGN : "-" > < MULT_SIGN : "*" > < DIV_SIGN : "/" > TOKEN : /* Numbers and identifiers */ < NUM : (<DIGIT>)+ > < #DIGIT : ["0" - "9"] > < ID : (<LETTER>)+ > < #LETTER : ["a" - "z", "A" - "Z"] > TOKEN : /* Anything not recognised so far */ < OTHER : ~[] > /*********************************** ***** SECTION 4 - THE GRAMMAR ***** ***********************************/ void Prog() : Stm() <EOF> void Stm() : (SimpleStm() [<SEMIC> Stm()] ) void SimpleStm() : (Ident() <ASSIGN> Exp()) (<PRINT> <LBR> ExpList() <RBR>) void Exp() : (SimpleExp() [BinOp() Exp()] ) void SimpleExp() : IdExp() NumExp() (<LBR> Stm() <COMMA> Exp() <RBR>) Compiler Construction 1 13 Compiler Construction 1 14

Specifying the Grammar of the Straight JavaCC Actions void Ident() : <ID> void IdExp() : <ID> void NumExp() : <NUM> void ExpList() : (Exp() [<COMMA> ExpList()] ) void BinOp() : <PLUS_SIGN> <MINUS_SIGN> <MULT_SIGN> <DIV_SIGN> Each JavaCC rule is converted into a parsing method (just like a recursive descent parser created by hand) We can add arbitrary Java code to these methods We can also add instance variables and helper methods that every parser method can access Adding instance variables: PARSER_BEGIN(MyParser) public class MyParser /* instance variables and helper methods */ /* Optional main method (the main method can also be in a separate file) PARSER_END(MyParser) Compiler Construction 1 15 Compiler Construction 1 16

JavaCC Rules JavaCC Rules <return type> <rule name>() : /* local variables */ Rule1 Rule2... Each rule can contain arbitrary Java code between and JavaCC rules can also return values (work just like any other method) Building A JavaCC Calculator How would we change the following JavaCC file so that it computed the value of the expression, as well as parsing the expression? void expression(): term() <EOF> void term(): factor() ((<MULTIPLY> <DIVIDE>) factor())* Use <variable> = syntax to obtain values of method calls void factor(): <INTEGER_LITERAL> <MINUS> factor() <LPAREN> term() <RPAREN> Compiler Construction 1 17 Compiler Construction 1 18

JavaCC Rules Parsing an Expression int expression(): int result; result = term() <EOF> return result; int term(): Token t; int result; int rhs; result = factor() ((t = <MULTIPLY> t = <DIVIDE>) rhs = factor() if (t.kind == MULTIPLY) result = result * rhs; else result = result / rhs; )* return result; int factor(): int value; Token t; t = <INTEGER_LITERAL> return Integer.parseInt(t.image); <MINUS> value = factor() return 0 - value; <LPAREN> value = term() <RPAREN> return value; Function to parse a factor is called, result is stored in result The next token is observed, to see if it is a * or /. If so, function to parse a factor is called again, storing the result in rhs. The value of result is updated The next token is observed to see if it is a * or /.... Some example expressions: 4 3*4 1*2/3 Compiler Construction 1 19 Compiler Construction 1 20

Input Parameters Input Parameters JavaCC rules function calls in generated parser JavaCC rules can have input parameters as well as return values Syntax for rules with parameters is the same as standard method calls Consider the following JavaCC file for expressions: void expression(): term() expressionprime() void expressionprime(): <PLUS> term() expressionprime() <MINUS> term() expressionprime() What should <PLUS> term() expressionprime return? Get the value of the previous term Add that value to term() Combine the result with whatever expressionp returns How can we get the value of the previous term? Have it passed in as a parameter How can we combine the result with whatever expressionprime() returns? Pass the result into expressionprime(), and have expressionprime() do the combination Compiler Construction 1 21 Compiler Construction 1 22

Input Parameters int expression(): int firstterm; int result; firstterm = term() result = expressionprime(firstterm) return result; int expressionprime(int firstterm): int nextterm; int result; <PLUS> nextterm = term() result = expressionprime(firstterm + nextterm) return result; <MINUS> nextterm = term() result = expressionprime(firstterm - nextterm) return result; return firstterm; An Interpreter for the Straight Line Programming Language options JAVA_UNICODE_ESCAPE = true; PARSER_BEGIN(SLPInterpreter) public class SLPInterpreter public static void main(string args[]) SLPInterpreter interpreter; if (args.length == 0) System.out.println("SLP Interpreter: Reading from standard input. interpreter = new SLPInterpreter(System.in); else if (args.length == 1) System.out.println("SLP Interpreter: Reading from file " + args[0] try interpreter = new SLPInterpreter(new java.io.fileinputstream(args catch (java.io.filenotfoundexception e) System.out.println("SLP Interpreter: File " + args[0] + " not fo return; else System.out.println("SLP Interpreter: Usage is one of:"); System.out.println(" java SLPInterpreter < inputfile"); System.out.println("OR"); System.out.println(" java SLPInterpreter inputfile"); return; try interpreter.prog(); catch (ParseException e) System.out.println(e.getMessage()); System.out.println("SLP Interpreter: Encountered errors during par PARSER_END(SLPInterpreter) Compiler Construction 1 23 Compiler Construction 1 24

An Interpreter for the Straight Line Programming Language An Interpreter For the Straight Line Programming Language /***************************************** ***** SECTION 3 - TOKEN DEFINITIONS ***** *****************************************/ TOKEN_MGR_DECLS : static int commentnesting = 0; SKIP : /*** Ignoring spaces/tabs/newlines ***/ " " "\t" "\n" "\r" "\f" SKIP : /* COMMENTS */ "/*" commentnesting++; : IN_COMMENT <IN_COMMENT> SKIP : "/*" commentnesting++; "*/" commentnesting--; if (commentnesting == 0) SwitchTo(DEFAULT); <~[]> TOKEN : /* Keywords and punctuation */ < SEMIC : ";" > < ASSIGN : ":=" > < PRINT : "print" > < LBR : "(" > < RBR : ")" > < COMMA : "," > < PLUS_SIGN : "+" > < MINUS_SIGN : "-" > < MULT_SIGN : "*" > < DIV_SIGN : "/" > TOKEN : /* Numbers and identifiers */ < NUM : (<DIGIT>)+ > < #DIGIT : ["0" - "9"] > < ID : (<LETTER>)+ > < #LETTER : ["a" - "z", "A" - "Z"] > TOKEN : /* Anything not recognised so far */ < OTHER : ~[] > Compiler Construction 1 25 Compiler Construction 1 26

An Interpreter for the Straight Line Programming Language An Interpreter for the Straight Line Programming Language /*********************************** ***** SECTION 4 - THE GRAMMAR ***** ***********************************/ void Prog() : Table t; t=stm(null) <EOF> Table Stm(Table t) : (t=simplestm(t) [<SEMIC> t=stm(t)] ) return t; Table SimpleStm(Table t) : String id; IntAndTable it; IntListAndTable ilt; (id=ident() <ASSIGN> it=exp(t)) if (t == null) return new Table(id,it.i,t); else return t.update(t,id,it.i); (<PRINT> <LBR> ilt=explist(t) <RBR>) ilt.il.print(); return ilt.t; IntAndTable Exp(Table t) : IntAndTable arg1, arg2; int oper; (arg1=simpleexp(t) [oper=binop() arg2=exp(arg1.t) switch(oper) case 1: return new IntAndTable(arg1.i+arg2.i,arg2.t); case 2: return new IntAndTable(arg1.i-arg2.i,arg2.t); case 3: return new IntAndTable(arg1.i*arg2.i,arg2.t); case 4: return new IntAndTable(arg1.i/arg2.i,arg2.t); ] ) return arg1; IntAndTable SimpleExp(Table t) : IntAndTable it; it=idexp(t) return it; it=numexp(t) return it; (<LBR> t=stm(t) <COMMA> it=exp(t) <RBR>) return it; String Ident() : Token tok; tok=<id> return tok.image; Compiler Construction 1 27 Compiler Construction 1 28

An Interpreter for the Straight Line Programming Language Building ASTs With JavaCC IntAndTable IdExp(Table t) : Token tok; tok=<id> return new IntAndTable(t.lookup(t,tok.image),t); IntAndTable NumExp(Table t) : Token tok; tok=<num> return new IntAndTable(Integer.parseInt(tok.image),t); IntListAndTable ExpList(Table t) : IntAndTable it;intlistandtable ilt; (it=exp(t) [<COMMA> ilt=explist(it.t) return new IntListAndTable(new IntList(it.i,ilt.il),ilt.t); ]) return new IntListAndTable(new IntList(it.i,null),it.t); int BinOp() : <PLUS_SIGN> return 1; <MINUS_SIGN> return 2; <MULT_SIGN> return 3; <DIV_SIGN> return 4; Instead of returning values, return trees Call constructors to build subtrees Combine subtrees into larger trees ASTExpression term(): Token t; ASTExpression result; ASTExpression rhs; result = factor() ((t = <MULTIPLY> t = <DIVIDE>) rhs = f result = new ASTOperatorExpression(result,rhs,t.imag )* return result; ASTExpression factor(): ASTExpression value; Token t; t = <INTEGER_LITERAL> return new ASTIntegerLiteral(Integer.parseInt(t.imag <MINUS> value = factor() return new ASTOperatorExpression(new ASTIntegerLiter value,astoperatorexpression.minus); <LPAREN> value = term() <RPAREN> return value; Compiler Construction 1 29 Compiler Construction 1 30

A Syntax Tree Builder for the Straight A Syntax Tree Builder for the Straight PARSER_BEGIN(SLPTreeBuilder) public class SLPTreeBuilder /***************************************** ***** SECTION 3 - TOKEN DEFINITIONS ***** *****************************************/ public static void main(string args[]) SLPTreeBuilder treebuilder; if (args.length == 0) System.out.println("SLP Tree Builder: Reading from standard input..."); treebuilder = new SLPTreeBuilder(System.in); else if (args.length == 1) System.out.println("SLP Tree Builder: Reading from file " + args[0] + ".. try treebuilder = new SLPTreeBuilder(new java.io.fileinputstream(args[0])); catch (java.io.filenotfoundexception e) System.out.println("SLP Tree Builder: File " + args[0] + " not found."); return; else System.out.println("SLP Tree Builder: Usage is one of:"); System.out.println(" java SLPTreeBuilder < inputfile"); System.out.println("OR"); System.out.println(" java SLPTreeBuilder inputfile"); return; try Stm s = treebuilder.prog(); s.interp(); catch (ParseException e) System.out.println(e.getMessage()); System.out.println("SLP Tree Builder: Encountered errors during parse."); TOKEN_MGR_DECLS : static int commentnesting = 0; SKIP : /*** Ignoring spaces/tabs/newlines ***/ " " "\t" "\n" "\r" "\f" SKIP : /* COMMENTS */ "/*" commentnesting++; : IN_COMMENT <IN_COMMENT> SKIP : "/*" commentnesting++; "*/" commentnesting--; if (commentnesting == 0) SwitchTo(DEFAULT); <~[]> PARSER_END(SLPTreeBuilder) Compiler Construction 1 31 Compiler Construction 1 32

An Interpreter For the Straight Line Programming Language A Syntax Tree Builder for the Straight TOKEN : /* Keywords and punctuation */ < SEMIC : ";" > < ASSIGN : ":=" > < PRINT : "print" > < LBR : "(" > < RBR : ")" > < COMMA : "," > < PLUS_SIGN : "+" > < MINUS_SIGN : "-" > < MULT_SIGN : "*" > < DIV_SIGN : "/" > TOKEN : /* Numbers and identifiers */ < NUM : (<DIGIT>)+ > < #DIGIT : ["0" - "9"] > < ID : (<LETTER>)+ > < #LETTER : ["a" - "z", "A" - "Z"] > TOKEN : /* Anything not recognised so far */ < OTHER : ~[] > Stm Prog() : Stm s; s=stm() <EOF> return s; Stm Stm() : Stm s1,s2; (s1=simplestm() [<SEMIC> s2=stm() return new CompoundStm(s1,s2); ] ) return s1; Stm SimpleStm() : String s; Exp e; ExpList el; (s=ident() <ASSIGN> e=exp()) return new AssignStm(s,e); (<PRINT> <LBR> el=explist() <RBR>) return new PrintStm(el); Exp Exp() : Exp e1,e2; int o; (e1=simpleexp() [o=binop() e2=exp() return new OpExp(e1,o,e2); ] return e1; Exp SimpleExp() : Stm s; Exp e; e=idexp() return e; e=numexp() return e; (<LBR> s=stm() <COMMA> e=exp() <RBR>) return new EseqExp(s,e); Compiler Construction 1 33 Compiler Construction 1 34

A Syntax Tree Builder for the Straight String Ident() : Token t; t=<id> return t.image; IdExp IdExp() : Token t; t=<id> return new IdExp(t.image); NumExp NumExp() : Token t; t=<num> return new NumExp(Integer.parseInt(t.image)); ExpList ExpList() : Exp e; ExpList el; (e=exp() [<COMMA> el=explist() return new PairExpList(e,el); ] ) return new LastExpList(e); int BinOp() : <PLUS_SIGN> return 1; <MINUS_SIGN> return 2; <MULT_SIGN> return 3; <DIV_SIGN> return 4; Compiler Construction 1 35