Abstract Syntax Trees

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

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

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

JJTree. The Compilation Task. Automated? JJTree. An easier way to create an Abstract Syntax Tree

Fundamentals of Compilation

Compilation 2014 Warm-up project

CS 132 Compiler Construction

CPSC 411: Introduction to Compiler Construction

Compiler Construction

CS 352: Compilers: Principles and Practice

PART ONE Fundamentals of Compilation

Compiler Compiler Tutorial

Compiler Construction 1. Introduction. Oscar Nierstrasz

Compiler Construction 1. Introduction. Oscar Nierstrasz

Definition of AST AST and Static Code Analysis Design Patterns. AST Features Applicability of AST JTB JJTree

4. Parsing in Practice

Topic 3: Syntax Analysis I

Chapter 4. Abstract Syntax

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

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

JavaCC: SimpleExamples

PROGRAMMING FUNDAMENTALS

CA Compiler Construction

Abstract Syntax. Mooly Sagiv. html://

ASTs, Objective CAML, and Ocamlyacc

Compilers CS S-01 Compiler Basics & Lexical Analysis

Topic 5: Syntax Analysis III

Modern Compiler Implementation in ML

Compilers CS S-01 Compiler Basics & Lexical Analysis

CS S-01 Compiler Basics & Lexical Analysis 1

The Zephyr Abstract Syntax Description Language

CMPT 379 Compilers. Parse trees

LECTURE 3. Compiler Phases

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

A Simple Syntax-Directed Translator

EDA180: Compiler Construc6on. More Top- Down Parsing Abstract Syntax Trees Görel Hedin Revised:

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

Lecture 12: Parser-Generating Tools

CSE 413 Final Exam Spring 2011 Sample Solution. Strings of alternating 0 s and 1 s that begin and end with the same character, either 0 or 1.

Implementing Classes, Arrays, and Assignments

.jj file with actions

CA Compiler Construction

CS453 CLASSES, VARIABLES, ASSIGNMENTS

The Visitor Pattern. Design Patterns In Java Bob Tarr

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

CSE 401/M501 Compilers

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

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

Project Compiler. CS031 TA Help Session November 28, 2011

Error Detection in LALR Parsers. LALR is More Powerful. { b + c = a; } Eof. Expr Expr + id Expr id we can first match an id:

Think of drawing/diagramming editors. ECE450 Software Engineering II. The problem. The Composite pattern

Table-Driven Top-Down Parsers

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

CUP. Lecture 18 CUP User s Manual (online) Robb T. Koether. Hampden-Sydney College. Fri, Feb 27, 2015

Action Table for CSX-Lite. LALR Parser Driver. Example of LALR(1) Parsing. GoTo Table for CSX-Lite

Writing a Lexer. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Monday, February 6, Glenn G.

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

Abstract Syntax. Leonidas Fegaras. CSE 5317/4305 L5: Abstract Syntax 1

Grammars and Parsing, second week

Introduction to Programming Using Java (98-388)

Prof. Mohamed Hamada Software Engineering Lab. The University of Aizu Japan

Parser Combinators 11/3/2003 IPT, ICS 1

4. Semantic Processing and Attributed Grammars

Defining Program Syntax. Chapter Two Modern Programming Languages, 2nd ed. 1

Chapter 3. Parsing #1

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

CSE 413 Final Exam. June 7, 2011

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

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

Implementing Classes and Assignments

Compilers. Compiler Construction Tutorial The Front-end

CS 406: Syntax Directed Translation

BFH/HTA Biel/DUE/Course 355/ Software Engineering 2

CPSC 411, Fall 2010 Midterm Examination

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

Lecture 8 CS 412/413 Spring '00 -- Andrew Myers 2. Lecture 8 CS 412/413 Spring '00 -- Andrew Myers 4

Abstract Syntax Trees

JavaCC Parser. The Compilation Task. Automated? JavaCC Parser

Structure of a compiler. More detailed overview of compiler front end. Today we ll take a quick look at typical parts of a compiler.

Implementing Actions

CPSC 411, 2015W Term 2 Midterm Exam Date: February 25, 2016; Instructor: Ron Garcia

Build your own languages with

COMPUTER PROGRAMMING LOOPS

Semantic Analysis. Compiler Architecture

COMP3131/9102: Programming Languages and Compilers

Lexical Analysis. Introduction

Syntax Intro and Overview. Syntax

CSE 12 Abstract Syntax Trees

Languages and Compilers (SProg og Oversættere) Lecture 3 recap Bent Thomsen Department of Computer Science Aalborg University

Programming Languages. Dr. Philip Cannata 1

Lexical Scanning COMP360

CSEP 501 Compilers. Languages, Automata, Regular Expressions & Scanners Hal Perkins Winter /8/ Hal Perkins & UW CSE B-1

Little Language [Grand]

COMP3131/9102: Programming Languages and Compilers

CSE 401 Midterm Exam Sample Solution 2/11/15

Programming Languages. Dr. Philip Cannata 1

Syntax. A. Bellaachia Page: 1

Question Points Score

Tree visitors. Context classes. CS664 Compiler Theory and Design LIU 1 of 11. Christopher League* 24 February 2016

CSE450. Translation of Programming Languages. Lecture 11: Semantic Analysis: Types & Type Checking

Transcription:

Parse trees tell us exactly how a string was parsed Parse trees contain more information than we need We only need the basic shape of the tree, not where every non-terminal is Non-terminals are necessary for parsing, not for meaning An Abstract Syntax Tree is a simplifed version of a parse tree basically a parse tree without non-terminals Compiler Construction 1 1

Example 1 <goal> ::= <expr> 2 <expr> ::= <expr> + <term> 3 <expr> - <term> 4 <term> 5 <term> ::= <term> * <factor> 6 <term> / <factor> 7 <factor> 8 <factor> ::= num 9 id Syntax Tree Abstract Syntax Tree goal expr expr + term term term * factor ; factor factor <id,y> hid:xi <id,x> <num,2> hnum:2i hid:yi Compiler Construction 1 2

Creating Syntax Trees Using JJTree JJTree is a preprocessor for JavaCC that inserts parse tree building actions at various places in the JavaCC source. The output of JJTree is run through JavaCC to create the parser. By default JJTree generates code to construct parse tree nodes for each nonterminal in the language; this behavior can be modified so that some nonterminals do not have nodes generated, or so that a node is generated for a part of a production s expansion. JJTree defines a Java interface Node that all parse tree nodes must implement. The interface provides methods for operations such as setting the parent of the node, and for adding children and retrieving them. JJTree operates in one of two modes, simple and multi. In simple mode each parse tree node is of concrete type SimpleNode; in multi mode the type of the parse tree node is derived from the name of the node. Compiler Construction 1 3

Decorations JJTree provides decorations for definite and conditional nodes. A definite node is constructed with a specific number of children. For example: #ADefiniteNode(INTEGER EXPRESSION) A conditional node is constructed if and only if its condition evaluates to true. For example: #ConditionalNode(BOOLEAN EXPRESSION) By default JJTree treats each nonterminal as a separate node and derives the name of the node from the name of its production. You can give it a different name with the following syntax: void P1() #MyNode :...... If you want to suppress the creation of a node for a production you can use the following syntax: void P2() #void :...... You can make this the default behavior for non-decorated nodes by using the NODE_DEFAULT_VOID option. The current node can be accessed using the identifier jjtthis Compiler Construction 1 4

Creating Syntax Trees for the Straight Line Programming Language /******************************* ***** SECTION 1 - OPTIONS ***** *******************************/ options MULTI = true; NODE_DEFAULT_VOID = true; NODE_PREFIX = ""; /********************************* ***** SECTION 2 - USER CODE ***** *********************************/ 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; Compiler Construction 1 5

Creating Syntax Trees for the Straight Line Programming Language 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 Stm p = parser.prog(); p.dump(""); catch (ParseException e) System.out.println(e.getMessage()); System.out.println("SLP Parser: Encountered errors during parse."); PARSER_END(SLPParser) Compiler Construction 1 6

Creating Syntax Trees 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); <~[]> Compiler Construction 1 7

Creating Syntax Trees for the Straight Line Programming Language 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 8

Creating Syntax Trees for the Straight Line Programming Language /*************************** * SECTION 4 - THE GRAMMAR * ***************************/ Stm Prog() #Stm : Stm() <EOF> return jjtthis; void Stm() #Stm : (SimpleStm() [<SEMIC> Stm() #CompoundStm] ) void SimpleStm() : (Ident() <ASSIGN> Exp()) #AssignStm (<PRINT> <LBR> ExpList() <RBR>) #PrintStm void Exp() #Exp : int oper; (SimpleExp() [oper = BinOp() Exp() jjtthis.setoper(oper); #OpExp] ) void SimpleExp() : IdExp() NumExp() (<LBR> Stm() <COMMA> Exp() <RBR>) #EseqExp Compiler Construction 1 9

Creating Syntax Trees for the Straight Line Programming Language void Ident() : <ID> void IdExp() #IdExp : Token t; t = <ID> jjtthis.setname(t.image); void NumExp() #NumExp : Token t; t = <NUM> jjtthis.setnum(integer.parseint(t.image)); void ExpList() #ExpList : (Exp() (<COMMA> ExpList() #PairExpList #LastExpList) ) int BinOp() : <PLUS_SIGN> return 1; <MINUS_SIGN> return 2; <MULT_SIGN> return 3; <DIV_SIGN> return 4; Compiler Construction 1 10

Tree Nodes The implementation of some of the tree nodes are as follows: public class NumExp extends SimpleNode private int num; public void setnum(int n) num = n; public NumExp(int id) super(id); public NumExp(SLPParser p, int id) super(p, id); public class IdExp extends SimpleNode private String name; public void setname(string n) name = n; public IdExp(int id) super(id); public IdExp(SLPParser p, int id) super(p, id); public class OpExp extends SimpleNode private int oper; public void setoper(int o) oper = o; public OpExp(int id) super(id); public OpExp(SLPParser p, int id) super(p, id); Compiler Construction 1 11

Traversing Trees Want to write a function that calculates the value of an expression tree: int Calculate(Exp tree, Table t)... How do we determine what kind of expression we are traversing (identifier, number, sequence expression or binary expression)? IntAndTable evaluate(exp tree,table t) if (tree instanceof NumExp) return new IntAndTable(((NumExp)tree).num,t); else if (tree instanceof IdExp) return new IntAndTable(t.lookup(t,((IdExp)tree).name),t); else if (tree instanceof EseqExp) return evaluate((exp)tree.getchild(1),interpret((stm)tree.getchild else // Binary Operator Expression IntAndTable arg1 = evaluate((exp)tree.getchild(0),t); IntAndTable arg2 = evaluate((exp)tree.getchild(1),arg1.t); switch ((OpExp)tree.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); Compiler Construction 1 12

Using Instanceof and Type Casts The code constantly uses type casts and instanceof to determine what class of object it is considering. This is not object-oriented. There is a better way the Visitor design pattern A Visitor is used to traverse the tree Visitor contains a Visit method for each kind of node in the tree The visit method determines how to process that node Each node in the AST has an accept method Takes as input a visitor Calls the appropriate method of the visitor to handle the node, passing in a pointer to itself Returns whatever the visitor tells it to return Compiler Construction 1 13

Using the Visitor Pattern With JJTree JJTree provides some basic support for the visitor design pattern. If the VISITOR option is set to true JJTree will insert an jjtaccept() method into all of the node classes it generates. It also generates a visitor interface that can be implemented and passed to the nodes to accept: public interface SLPParserVisitor public Object visit(simplenode node, Object data); public Object visit(stm node, Object data); public Object visit(compoundstm node, Object data); public Object visit(assignstm node, Object data); public Object visit(printstm node, Object data); public Object visit(exp node, Object data); public Object visit(opexp node, Object data); public Object visit(eseqexp node, Object data); public Object visit(idexp node, Object data); public Object visit(numexp node, Object data); public Object visit(explist node, Object data); public Object visit(pairexplist node, Object data); public Object visit(lastexplist node, Object data); Compiler Construction 1 14

Visitor Implementation public Object visit(numexp n, Table t) return new IntAndTable(n.num,t); public Object visit(idexp i,table t) return new IntAndTable(t.lookup(t,i.name),t); public Object visit(eseqexp e, Table t) Table t = e.getchild(0).jjtaccept(this,t); return e.getchild(1).jjtaccept(this,t ); public Object visit(opexp o, Table t) IntAndTable arg1 = o.getchild(0).jjtaccept(this,t); IntAndTable arg2 = o.getchild(1).jjtaccept(this,arg1.t); switch (o.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); Compiler Construction 1 15

Tree Nodes The implementation of some of the tree nodes are as follows: public class NumExp extends SimpleNode private int num; public void setnum(int n) num = n; public NumExp(int id) super(id); public NumExp(SLPParser p, int id) super(p, id); public Object jjtaccept(slpparservisitor visitor, Object data) return visitor.visit(this, data); public class IdExp extends SimpleNode private String name; public void setname(string n) name = n; public IdExp(int id) super(id); public IdExp(SLPParser p, int id) super(p, id); public Object jjtaccept(slpparservisitor visitor, Object data) return visitor.visit(this, data); public class OpExp extends SimpleNode private int oper; public void setoper(int o) oper = o; public OpExp(int id) super(id); public OpExp(SLPParser p, int id) super(p, id); public Object jjtaccept(slpparservisitor visitor, Object data) return visitor.visit(this, data); The control flow goes back and forth between the visit methods in the Visitor and the jjtaccept methods in the object structure. Compiler Construction 1 16

Visitors Visitor makes adding new operations easy: simply write a new visitor. A visitor gathers related operations: separates unrelated ones. it also Adding new classes to the object structure is hard. Key consideration:are you most likely to change the algorithm applied over an object structure, or are you most like to change the classes of objects that make up the structure? Visitor can break encapsulation: Visitor s approach assumes that the interface of the data structure classes is powerful enough to let visitors do their job. As a result, the pattern often forces you to provide public operations that access internal state, which may compromise its encapsulation. Compiler Construction 1 17