CMPE 152: Compiler Design March 28 Class Meeting

Slides:



Advertisements
Similar presentations
JavaCUP JavaCUP (Construct Useful Parser) is a parser generator
Advertisements

1 JavaCUP JavaCUP (Construct Useful Parser) is a parser generator Produce a parser written in java, itself is also written in Java; There are many parser.
ITEC 320 C++ Examples.
Interpretation Environments and Evaluation. CS 354 Spring Translation Stages Lexical analysis (scanning) Parsing –Recognizing –Building parse tree.
CS 153: Concepts of Compiler Design September 9 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
COMP Parsing 3 of 4 Lectures 23. Using the Scanner Break input into tokens Use Scanner with delimiter: public void parse(String input ) { Scanner.
CS 153: Concepts of Compiler Design September 16 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design September 21 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design October 10 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design September 30 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 152: Programming Language Paradigms March 19 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak.
CS 153: Concepts of Compiler Design September 23 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
C++ Namespaces, Exceptions CSci 588: Data Structures, Algorithms and Software Design All material not from online sources copyright © Travis Desell, 2011.
LECTURE 10 Semantic Analysis. REVIEW So far, we’ve covered the following: Compilation methods: compilation vs. interpretation. The overall compilation.
CS 153: Concepts of Compiler Design September 14 Class Meeting
COMP261 Lecture 18 Parsing 3 of 4.
CMPE 135: Object-Oriented Analysis and Design September 26 Class Meeting Department of Computer Engineering San Jose State University Fall 2017 Instructor:
CMPE 135: Object-Oriented Analysis and Design October 3 Class Meeting
CS 3304 Comparative Languages
CS 153: Concepts of Compiler Design October 17 Class Meeting
CS 153: Concepts of Compiler Design October 5 Class Meeting
CS 153: Concepts of Compiler Design September 7 Class Meeting
CMPE 135: Object-Oriented Analysis and Design October 17 Class Meeting
CS 153: Concepts of Compiler Design December 5 Class Meeting
CMPE 135: Object-Oriented Analysis and Design October 17 Class Meeting
CS 153: Concepts of Compiler Design October 31 Class Meeting
CS 153: Concepts of Compiler Design November 30 Class Meeting
CMPE 152: Compiler Design December 5 Class Meeting
CMPE Data Structures and Algorithms in C++ February 22 Class Meeting
CMPE 152: Compiler Design April 5 Class Meeting
CMPE 152: Compiler Design February 6 Class Meeting
Compiler Design 22. ANTLR AST Traversal (AST as Input, AST Grammars)
CMPE 152: Compiler Design September 4 Class Meeting
CMPE 152: Compiler Design September 6 Class Meeting
CMPE 152: Compiler Design September 11 Class Meeting
CMPE 152: Compiler Design September 18 Class Meeting
CMPE 152: Compiler Design September 13 Class Meeting
CMPE 152: Compiler Design October 2 Class Meeting
CMPE 152: Compiler Design September 11/13 Lab
CMPE 152: Compiler Design October 4 Class Meeting
CMPE 152: Compiler Design August 21/23 Lab
CMPE 152: Compiler Design September 27 Class Meeting
ANTLR v3 Overview (for ANTLR v2 users)
CS 153: Concepts of Compiler Design October 30 Class Meeting
CMPE 152: Compiler Design February 14 Class Meeting
Engineering Problem Solving with C++ An Object Based Approach
Engineering Problem Solving with C++ An Object Based Approach
CMPE 152: Compiler Design April 9 Class Meeting
CMPE 152: Compiler Design February 12 Class Meeting
CMPE 152: Compiler Design February 7 Class Meeting
CMPE 152: Compiler Design March 21 Class Meeting
CMPE 152: Compiler Design February 21/26 Lab
CMPE 152: Compiler Design March 26 – April 16 Labs
CS 144 Advanced C++ Programming February 12 Class Meeting
CMPE 152: Compiler Design February 21 Class Meeting
CS 144 Advanced C++ Programming February 21 Class Meeting
CMPE 152: Compiler Design February 19 Class Meeting
CMPE 152: Compiler Design March 7 Class Meeting
CMPE 152: Compiler Design April 18 – 30 Labs
CMPE 152: Compiler Design March 5 Class Meeting
CS 144 Advanced C++ Programming March 21 Class Meeting
Introduction to ANTLR Jin Tianxing
CMPE 152: Compiler Design December 4 Class Meeting
CS 144 Advanced C++ Programming April 30 Class Meeting
CMPE 152: Compiler Design March 19 Class Meeting
CMPE 152: Compiler Design April 18 Class Meeting
CMPE 152: Compiler Design September 3 Class Meeting
CMPE 152: Compiler Design September 17 Class Meeting
CMPE 152: Compiler Design February 7 Class Meeting
CMPE 152: Compiler Design September 19 Class Meeting
Presentation transcript:

CMPE 152: Compiler Design March 28 Class Meeting Department of Computer Engineering San Jose State University Spring 2019 Instructor: Ron Mak www.cs.sjsu.edu/~mak

Parse Tree Processing Recall that after the frontend parser builds the parse tree, it’s the backend that processes it. ANTLR provides utilities to process the parse tree. ANTLR can generate code to process a parse tree with two types of tree walkers: listener interface (default) visitor interface

Parse Tree Listener Interface ANTLR generates code that automatically performs a depth-first walk of the parse tree. You do not have to write a tree walker. It generates a ParseTreeListener subclass that is specific to each grammar. The listener class has default enter and exit methods for each rule. You write a subclass that overrides the default enter and exit methods to do what you want. You do not have to explicitly visit child nodes.

Parse Tree Listener Interface, cont’d Tree walk and call sequence: The Definitive ANTLR 4 Reference by Terence Parr The Pragmatic Programmers, 2012

Listener Interface Example Parse a Java class definition and generate a Java interface with all the method signatures: demo.java public class Demo { void f(int x, String y) { } int[ ] g(/*no args*/) { return null; } List<Map<String, Integer>>[] h() { return null; } } interface IDemo { void f(int x, String y); int[ ] g(/*no args*/); List<Map<String, Integer>>[] h(); }

Listener Interface Example, cont’d We will use the Java grammar file Java.g4. Two pertinent rules: classDeclaration methodDeclaration Java.g4 classDeclaration     :   'class' Identifier typeParameters? ('extends' type)?         ('implements' typeList)?         classBody     ; methodDeclaration     :   type Identifier formalParameters ('[' ']')* methodDeclarationRest     |   'void' Identifier formalParameters methodDeclarationRest

Listener Interface Example, cont’d The generated JavaBaseListener.java has default do-nothing enter and exit methods. JavaBaseListener.h class JavaBaseListener : public JavaListener  { public: ...   virtual void enterClassDeclaration(JavaParser::ClassDeclarationContext *) override {}   virtual void exitClassDeclaration(JavaParser::ClassDeclarationContext *) override {}   virtual void enterMethodDeclaration(JavaParser::MethodDeclarationContext *) override {} } Default: Do nothing!

Listener Interface Example, cont’d Override the pertinent member functions. ExtractInterfaceListener.h #include "JavaBaseListener.h" #include "JavaParser.h" class ExtractInterfaceListener : public JavaBaseListener { public:     ExtractInterfaceListener(JavaParser *parser);     virtual ~ExtractInterfaceListener();     void enterClassDeclaration(JavaParser::ClassDeclarationContext *ctx) override;     void exitClassDeclaration(JavaParser::ClassDeclarationContext *ctx) override;     void enterMethodDeclaration(JavaParser::MethodDeclarationContext *ctx) override; private:     JavaParser *parser; };

Listener Interface Example, cont’d #include <iostream> #include "ExtractInterfaceListener.h" #include "antlr4-runtime.h" using namespace std; using namespace antlrcpp; using namespace antlr4; ExtractInterfaceListener::ExtractInterfaceListener(JavaParser *parser)     : parser(parser) {} ExtractInterfaceListener::~ExtractInterfaceListener() {} void ExtractInterfaceListener::enterClassDeclaration( JavaParser::ClassDeclarationContext *ctx) {     cout << "interface I" << ctx->Identifier()->getText() << " {" << endl; } void ExtractInterfaceListener::exitClassDeclaration(     cout << "}" << endl; ExtractInterfaceListener.cpp

Listener Interface Example, cont’d void ExtractInterfaceListener::enterMethodDeclaration( JavaParser::MethodDeclarationContext *ctx) {     TokenStream *tokens = parser->getTokenStream();     string type = (ctx->type() != nullptr)                         ? tokens->getText(ctx->type())                         : "void";     string args = tokens->getText(ctx->formalParameters());     cout << "\t" << type << " " << ctx->Identifier()->getText() << args << ":" << endl; } ExtractInterfaceListener.cpp

Listener Interface Example, cont’d public class ExtractInterfaceTool  {     public static void main(String[] args) throws Exception      {         String inputFile = null;         if ( args.length>0 ) inputFile = args[0];                  InputStream is = System.in;         if ( inputFile!=null ) {             is = new FileInputStream(inputFile);         }         ANTLRInputStream input = new ANTLRInputStream(is);         JavaLexer lexer = new JavaLexer(input);         CommonTokenStream tokens = new CommonTokenStream(lexer);         JavaParser parser = new JavaParser(tokens);         ParseTree tree = parser.compilationUnit();         ParseTreeWalker walker = new ParseTreeWalker();         ExtractInterfaceListener extractor = new ExtractInterfaceListener(parser);         walker.walk(extractor, tree);     } } Default parse tree walker. ExtractInterfaceTool.cpp

Listener Interface Example, cont’d import java.util.List; import java.util.Map; public class Demo { void f(int x, String y) { } int[ ] g(/*no args*/) { return null; } List<Map<String, Integer>>[] h() { return null; } } interface IDemo { void f(int x, String y); int[ ] g(/*no args*/); List<Map<String, Integer>>[] h(); } Demo

Parse Tree Visitor Interface The visitor interface give you more control over the tree walk. Specify -visitor on the antlr4 command. Also -no-listener ANTLR generates a grammar-specific visitor interface and a visitor method per rule. You must initiate the visit by calling visit() on the parse tree root. antlr4 -no-listener -visitor LabeledExpr.g4

Parse Tree Visitor Interface, cont’d The Definitive ANTLR 4 Reference by Terence Parr The Pragmatic Programmers, 2012

Visitor Interface Example Interpret arithmetic expressions by computing values in the back end. Label each rule alternative. ANTLR generates a different visitor per labeled alternative. Default: ANTLR generates only one visitor per rule.

Visitor Interface Example, cont’d LabeledExpr.g4 grammar LabeledExpr; prog:   stat+ ; stat:   expr NEWLINE                # printExpr     |   ID '=' expr NEWLINE         # assign     |   NEWLINE                     # blank     ; expr:   expr op=('*'|'/') expr      # MulDiv     |   expr op=('+'|'-') expr      # AddSub     |   INT                         # int     |   ID                          # id     |   '(' expr ')'                # parens MUL :   '*' ; // assigns token name to '*' used above in grammar DIV :   '/' ; ADD :   '+' ; SUB :   '-' ; ID  :   [a-zA-Z]+ ;      // match identifiers INT :   [0-9]+ ;         // match integers NEWLINE:'\r'? '\n' ;     // return newlines to parser (is end-statement signal) WS  :   [ \t]+ -> skip ; // toss out whitespace Labeled rules Named tokens

Visitor Interface Example, cont’d ANTLR-generated visitor interface Uses antlrcpp::Any to handle different result types. class LabeledExprVisitor : public antlr4::tree::AbstractParseTreeVisitor { public:     virtual antlrcpp::Any visitProg(LabeledExprParser::ProgContext *context) = 0;   virtual antlrcpp::Any visitPrintExpr(LabeledExprParser::PrintExprContext *context) = 0;     virtual antlrcpp::Any visitAssign(LabeledExprParser::AssignContext *context) = 0;     virtual antlrcpp::Any visitBlank(LabeledExprParser::BlankContext *context) = 0;     virtual antlrcpp::Any visitParens(LabeledExprParser::ParensContext *context) = 0;     virtual antlrcpp::Any visitMulDiv(LabeledExprParser::MulDivContext *context) = 0;     virtual antlrcpp::Any visitAddSub(LabeledExprParser::AddSubContext *context) = 0;     virtual antlrcpp::Any visitId(LabeledExprParser::IdContext *context) = 0;     virtual antlrcpp::Any visitInt(LabeledExprParser::IntContext *context) = 0; }; LabeledExprVisitor.h

Visitor Interface Example, cont’d Default implementation: During each visit, just visit the children. LabeledExprBaseVisitor.h class  LabeledExprBaseVisitor : public LabeledExprVisitor { public:   virtual antlrcpp::Any visitProg(LabeledExprParser::ProgContext *ctx) override     return visitChildren(ctx);   }   virtual antlrcpp::Any visitPrintExpr(LabeledExprParser::PrintExprContext *ctx) override   virtual antlrcpp::Any visitAssign(LabeledExprParser::AssignContext *ctx) override   virtual antlrcpp::Any visitBlank(LabeledExprParser::BlankContext *ctx) override

Visitor Interface Example, cont’d   virtual antlrcpp::Any visitParens(LabeledExprParser::ParensContext *ctx) override {     return visitChildren(ctx);   }   virtual antlrcpp::Any visitMulDiv(LabeledExprParser::MulDivContext *ctx) override   virtual antlrcpp::Any visitAddSub(LabeledExprParser::AddSubContext *ctx) override   virtual antlrcpp::Any visitId(LabeledExprParser::IdContext *ctx) override   virtual antlrcpp::Any visitInt(LabeledExprParser::IntContext *ctx) override }; LabeledExprBaseVisitor.h

Visitor Interface Example, cont’d Override the pertinent visitor methods. EvalVisitor.h class EvalVisitor : public LabeledExprBaseVisitor { public:     antlrcpp::Any visitAssign(LabeledExprParser::AssignContext *ctx) override;     antlrcpp::Any visitPrintExpr(LabeledExprParser::PrintExprContext *ctx) override;     antlrcpp::Any visitInt(LabeledExprParser::IntContext *ctx) override;     antlrcpp::Any visitId(LabeledExprParser::IdContext *ctx) override;     antlrcpp::Any visitMulDiv(LabeledExprParser::MulDivContext *ctx) override;     antlrcpp::Any visitAddSub(LabeledExprParser::AddSubContext *ctx) override;     antlrcpp::Any visitParens(LabeledExprParser::ParensContext *ctx) override; private:     map<string, int> memory; };

Visitor Interface Example, cont’d antlrcpp::Any EvalVisitor::visitAssign(LabeledExprParser::AssignContext *ctx) {     string id = ctx->ID()->getText();     int value = visit(ctx->expr());     memory[id] = value;     return value; } antlrcpp::Any EvalVisitor::visitPrintExpr(LabeledExprParser::PrintExprContext *ctx)     cout << value << endl;     return 0; antlrcpp::Any EvalVisitor::visitInt(LabeledExprParser::IntContext *ctx)     return stoi(ctx->INT()->getText()); EvalVisitor.cpp

Visitor Interface Example, cont’d EvalVisitor.cpp antlrcpp::Any EvalVisitor::visitId(LabeledExprParser::IdContext *ctx) {     string id = ctx->ID()->getText();     return (memory.find(id) != memory.end())     ? memory[id] : 0; } antlrcpp::Any EvalVisitor::visitMulDiv(LabeledExprParser::MulDivContext *ctx) int left  = visit(ctx->expr(0)); int right = visit(ctx->expr(1)); return (ctx->op->getType() == LabeledExprParser::MUL)             ? left*right : left/right;

Visitor Interface Example, cont’d EvalVisitor.cpp antlrcpp::Any EvalVisitor::visitAddSub(LabeledExprParser::AddSubContext *ctx) {     int left  = visit(ctx->expr(0));     int right = visit(ctx->expr(1));     return (ctx->op->getType() == LabeledExprParser::ADD)             ? left + right : left - right; } antlrcpp::Any EvalVisitor::visitParens(LabeledExprParser::ParensContext *ctx)     return visit(ctx->expr());

Visitor Interface Example, cont’d The main program: Calc.cpp int main(int argc, const char *args[]) {     ifstream ins;     ins.open(args[1]);     ANTLRInputStream input(ins);     LabeledExprLexer lexer(&input);     CommonTokenStream tokens(&lexer);     LabeledExprParser parser(&tokens);     tree::ParseTree *tree = parser.prog();     cout << "Parse tree:" << endl;     cout << tree->toStringTree(&parser) << endl;     cout << endl << "Evaluation:" << endl;     EvalVisitor eval;     eval.visit(tree);     delete tree;     return 0; } Demo

Assignment #5 Grammar Recall the minimum compiler project: At least two data types with type checking. Basic arithmetic operations with operator precedence. Assignment statements. At least one conditional control statement (e.g., IF). At least one looping control statement. Procedures or functions with calls and returns. Parameters passed by value or by reference. Basic error recovery (skip to semicolon or end of line).