24
Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters http://helios.hud.ac.uk/scomtlm/cis2380 Tutorial / Practical 1. Run JavaCup on Linux / Ouranos following the “self study” file in the website 2. Continue to do paper based exercises creating SR parsers

Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Embed Size (px)

Citation preview

Page 1: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

LANGUAGE TRANSLATORS: WEEK 21

LECTURE:

Using JavaCup to create simple interpreters

http://helios.hud.ac.uk/scomtlm/cis2380

Tutorial / Practical

1. Run JavaCup on Linux / Ouranos following the “self study” file in the website

2. Continue to do paper based exercises creating SR parsers

Page 2: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

JavaCup

Grammar in“parser.cup” PLUS action code

JavaCup

Parsing Table in “parser.java”and “sym.java” PLUS action code

Scanner in “scanner.java”

javac Library Classes for Interpreting Parsing Table

Interpreter

Page 3: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

An Interpreter for an expression evaluator

stm ::= ID:id ASSIGNS expr:e {: put(id,e.intValue()); :} SEMI | PRINT expr:e {: System.out.println("= " + e); :} SEMI ; expr ::= expr:e1 SQUARED {: RESULT = new Integer(e1.intValue() * e1.intValue());:} | ID:id {:RESULT = new Integer(get(id));:} | expr:e1 PLUS expr:e2 {: RESULT = new Integer(e1.intValue() + e2.intValue());:}

The left hand side of each production is always implicitly labelled as RESULT.

Page 4: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

Problem with evaluation during parsing:Imagine trying to implement Java’s

“DO <stm> WHILE <expr>”

“IF (<exp>) <stm>”

using option 2 (evaluating code while parsing).

These are examples of compound statements

The problem is that repetition or branching cannot be easily dealt with when interpreting the program at the same time as parsing it. We can execute an assignment statement after we parse it … but not so easy with parts of compound statements.

Page 5: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

A better option..

RECALL Option 3 from previous week:

- Use JavaCup to build up a Parse Tree; Attach ACTION CODE to production rules to do this.

- Once parsing has finished, pass this Parse Tree to the next part of the interpreter/ compiler/ translator

eg to a Java interpreter or Compiler.

Page 6: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

LPL

(See code in Q3parser directory for definition).

Using Javacup + interpreter code we can easily create an interpreter for code such as the following example

x = 23;repeat x = x-1; y = x*x; print(x,y)until x; print(x)

Page 7: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

Part of LPL’s parser.cup file

stm::= ID:id ASSIGNS exp:e

{: RESULT = new AssignStm(id,e); :} |

REPEAT stm:s1 UNTIL exp:e

{: RESULT = new RepeatStm(s1,e); :} |

exp ::= INT:n

{: RESULT = new NumExp(n.intValue()); :} |

ID:id

{:RESULT = new IdExp(id);:} |

exp:e1 PLUS exp:e2

{: RESULT = new OpExp(e1,OpExp.Plus,e2); :}

Page 8: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

LPL – build up of syntax tree

stm(new AssignStm(new IdExp(“x”), new NumExp(9)))

PARSINGexpr(new IdExp(“x”)) expr(new NumExp(9))

ID,"x" ASSIGNS INT,9 SEMI

SCANNING

x = 9;

TOKEN STREAM

Prog(interpStm(<SYNTAX TREE>, new NumExp(9 Table("",0,null));

REST OFTREE

Page 9: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

Example from lecture 3...Eg <SYNTAX TREE> might be something like this …

new CompoundStm(

new AssignStm("b",new NumExp(5)),

new CompoundStm(

new AssignStm("a", new OpExp(new NumExp(5),

OpExp.Times,

new IdExp("b"))),

new PrintStm(new ExpList(new OpExp(new IdExp("b"),

OpExp.Times, new IdExp("a"))))

)

);

Page 10: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

LPL – how the interpreter worksOnce the input program is parsed successfully, the program’s

parse tree is passed to the interpreter to be interpreted! The interpreter code is situated at the beginning of parser.cup and is copied to parser.java verbatim.

Sequence:1. When executed with an input program P, the Parser

creates a Syntax (or ‘parse’) Tree representing P.2. The Syntax Tree together with an empty Table is passed

to the interpreter in the action code.3. The entries in the Table correspond to variable’s current

values as P is interpreted (the Table is called the ‘Store’)4. Commands in P change the Store

Page 11: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

LPL - the StoreTable represents the STORE of the program

class Table {

String id; int value; Table tail;

Table(String i, int v, Table t)

{id =i; value=v; tail=t;}

etc - it is a RECURSIVE type

Page 12: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

LPL - INTERPRETERinterpStm applies a statement s to a store t

(t is represented as a Table)

interpStm is called initially with an empty store …

prog ::= stm: s

{: RESULT = interpStm(s,new Table("",0,null)); :} ;

interpStm’s input is the parse tree in Java Constructor form. This could be processed in many ways e.g. a SYMBOL TABLE can be extracted from it and used to track variable DECLARATIONS.

Page 13: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

interpStm - compound

If s is a compound statement then we want to apply the first statement to the current store t getting store t’, then apply the second statement to t’. That is what this piece of code does:

else if (s instanceof CompoundStm)

return interpStm(s.get2(), interpStm(s.get1(),t));

Here t’ = interpStm(s.get1(),t)

Page 14: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

interpStm - assignment

ASSIGNMENT:

else if (s instanceof AssignStm)

return update(t,s.getLHS(),interpExp(s.getRHS(), t));

If s is an assignment then it has a LHS (the variable) and a RHS (the expression). update takes the current store t, the LHS, the

VALUE of the RHS in the current store, and returns a NEW store.

Table update(Table t,String str, int i) {

return (new Table(str, i, t));}

Page 15: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

interpStm - repeat

Apply the inside of the loop to obtain a new store. If the repeat expression is 0 in this new store then end, otherwise recursively call InterpStm with the new store.

else if (s instanceof RepeatStm)

{ Table table_temp = interpStm(s.getRepStm(),t);

int int_temp = interpExp(s.getRepExp(),table_temp);

if (int_temp == 0) return table_temp; else

return interpStm(s, table_temp); }

Page 16: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

InterExp

InterExp is a recursive method for evaluating Expressions in the context of a certain store.

InterpExp takes expression e and store t and returns a VALUE. Note a VALUE in LPL is always ‘int’ - we don’t allow booleans, strings etc

Page 17: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

Conclusions...

The definition of LPL in parser.cup contains the syntax specification and the Java Code implementing LPL’s interpreter

Page 18: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

APPENDIX:Steps to Updating/improving the JavaCup-generated Interpreter

Each time you make an addition to the language go through the following steps.

As an example, we will use the

WHILE COMMAND

Page 19: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

STEP 1

Work out what concrete syntax you want for your new command or other extension. Write down its semantics.

WHILE <exp> DO <stm>

Evaluate <exp>.

If it is zero skip and goto the next statement after WHILE in the program.

Otherwise execute <stm>, then execute

WHILE <exp> DO <stm> again.

Page 20: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

STEP 2

Put the new syntax in scanner.java

Eg add the following to scanner.java:

case ’W': advance(); advance(); advance(); advance(); advance(); return new Symbol(sym.WHILE);

case ’D': advance(); advance(); return new Symbol(sym.DO);

Page 21: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

Step 3: Add abstract syntax to parser.cup

- the non-terminals/terminals, the production rule, and the attached action code

terminal REPEAT, UNTIL, SEMI, PLUS, WHILE, DO

...

Stm ::=

WHILE exp:e DO stm:s

{: RESULT = new WhileStm(s,e); :}

Page 22: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

Step 4: Add the new Syntax Class for the While

Statement to the action codeclass WhileStm extends Stm {

Stm s; Exp exp;

WhileStm(Stm a, Exp e) {s=a; exp=e;}

public Stm getWhileStm() {return s;}

public Exp getWhileExp() {return exp;}

}

Page 23: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

Step 5: Add to the action code statements that

interpret the WHILE Stm

Table interpStm(Stm s, Table t) {

...

else if (s instanceof WhileStm)

int temp = interpExp(s.getWhileExp(),t);

if (temp == 0) return t; else

return interpStm(s, interpStm(s.getWhileStm(),t))

...

Page 24: Language Translators - Lee McCluskey LANGUAGE TRANSLATORS: WEEK 21 LECTURE: Using JavaCup to create simple interpreters

Language Translators - Lee McCluskey

Step 6:

Follow the steps to create the interpreter in the READ - ME file as usual.