Course Overview PART I: overview material PART II: inside a compiler

Slides:



Advertisements
Similar presentations
Parsing 4 Dr William Harrison Fall 2008
Advertisements

Semantics Static semantics Dynamic semantics attribute grammars
Translator Architecture Code Generator ParserTokenizer string of characters (source code) string of tokens abstract program string of integers (object.
Análise Sintática – Parte 2 Árvores Sintáticas Abstratas (ASTs) Scanning.
UNIVERSITY OF SOUTH CAROLINA Department of Computer Science and Engineering CSCE 330 Programming Language Structures Ch.2: Syntax and Semantics Fall 2005.
1 Languages and Compilers (SProg og Oversættere) Lecture 3 Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to Norm.
UNIVERSITY OF SOUTH CAROLINA Department of Computer Science and Engineering CSCE 531 Compiler Construction Ch.4: Syntactic Analysis Spring 2007 Marco Valtorta.
Parsing Discrete Mathematics and Its Applications Baojian Hua
Parsing III (Eliminating left recursion, recursive descent parsing)
Environments and Evaluation
Parsing — Part II (Ambiguity, Top-down parsing, Left-recursion Removal)
Syntax Analysis (Chapter 4) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 3 Lexical and Syntactic Analysis Syntactic.
CSC3315 (Spring 2009)1 CSC 3315 Lexical and Syntax Analysis Hamid Harroud School of Science and Engineering, Akhawayn University
Syntax Analysis (Chapter 4) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
1 Languages and Compilers (SProg og Oversættere) Parsing.
Compilation (Chapter 3) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
Syntax Analysis (Chapter 4) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
CS 461 – Oct. 7 Applications of CFLs: Compiling Scanning vs. parsing Expression grammars –Associativity –Precedence Programming language (handout)
1 Top Down Parsing. CS 412/413 Spring 2008Introduction to Compilers2 Outline Top-down parsing SLL(1) grammars Transforming a grammar into SLL(1) form.
CS Describing Syntax CS 3360 Spring 2012 Sec Adapted from Addison Wesley’s lecture notes (Copyright © 2004 Pearson Addison Wesley)
PART I: overview material
Lesson 3 CDT301 – Compiler Theory, Spring 2011 Teacher: Linus Källberg.
Interpretation Environments and Evaluation. CS 354 Spring Translation Stages Lexical analysis (scanning) Parsing –Recognizing –Building parse tree.
TextBook Concepts of Programming Languages, Robert W. Sebesta, (10th edition), Addison-Wesley Publishing Company CSCI18 - Concepts of Programming languages.
COP 4620 / 5625 Programming Language Translation / Compiler Writing Fall 2003 Lecture 3, 09/11/2003 Prof. Roy Levow.
Lexical and Syntax Analysis
Review 1.Lexical Analysis 2.Syntax Analysis 3.Semantic Analysis 4.Code Generation 5.Code Optimization.
Introduction (Chapter 1) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
1 Languages and Compilers (SProg og Oversættere) Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to Norm Hutchinson.
UNIVERSITY OF SOUTH CAROLINA Department of Computer Science and Engineering CSCE 531 Compiler Construction Ch.4: Syntactic Analysis Spring 2013 Marco Valtorta.
1 Languages and Compilers (SProg og Oversættere) Lexical analysis.
1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture of a compiler PART II:
CPS 506 Comparative Programming Languages Syntax Specification.
1 Languages and Compilers (SProg og Oversættere) Lecture 3 recap Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to.
Contextual Analysis (Chapter 5) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
1 Languages and Compilers (SProg og Oversættere) Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to Norm Hutchinson.
Top-down Parsing lecture slides from C OMP 412 Rice University Houston, Texas, Fall 2001.
Parsing — Part II (Top-down parsing, left-recursion removal) Copyright 2003, Keith D. Cooper, Ken Kennedy & Linda Torczon, all rights reserved. Students.
Syntax Analysis (Chapter 4) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
Top-down Parsing. 2 Parsing Techniques Top-down parsers (LL(1), recursive descent) Start at the root of the parse tree and grow toward leaves Pick a production.
 Fall Chart 2  Translators and Compilers  Textbook o Programming Language Processors in Java, Authors: David A. Watts & Deryck F. Brown, 2000,
Lesson 4 CDT301 – Compiler Theory, Spring 2011 Teacher: Linus Källberg.
1 Languages and Compilers (SProg og Oversættere) Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to Norm Hutchinson.
CS 614: Theory and Construction of Compilers Lecture 4 Fall 2002 Department of Computer Science University of Alabama Joel Jones.
Introduction to Parsing
Comp 411 Principles of Programming Languages Lecture 3 Parsing
CSE 3302 Programming Languages
Syntax Analysis (a.k.a. Parsing)
Chapter 3 – Describing Syntax
Programming Languages 2nd edition Tucker and Noonan
Languages and Compilers (SProg og Oversættere)
Programming Languages Translator
Chapter 4 Lexical and Syntax Analysis.
Introduction to Parsing (adapted from CS 164 at Berkeley)
Parsing — Part II (Top-down parsing, left-recursion removal)
Chapter 4 Top-Down Parsing Part-1 September 8, 2018
CS 363 Comparative Programming Languages
Parsing Techniques.
Syntax Analysis Sections :.
Department of Software & Media Technology
Programming Language Syntax 7
CS 540 George Mason University
CSE 3302 Programming Languages
R.Rajkumar Asst.Professor CSE
CSCE 330 Programming Language Structures Ch.2: Syntax and Semantics
Introduction to Parsing
Introduction to Parsing
Chapter 4: Lexical and Syntax Analysis Sangho Ha
Course Overview PART I: overview material PART II: inside a compiler
Presentation transcript:

Course Overview PART I: overview material PART II: inside a compiler 1 Introduction 2 Language processors (tombstone diagrams, bootstrapping) 3 Architecture of a compiler PART II: inside a compiler 4 Syntax analysis 5 Contextual analysis 6 Runtime organization 7 Code generation PART III: conclusion Interpretation Review

Systematic Development of Rec. Descent Parser (1) Express grammar in EBNF (2) Grammar Transformations: Left factorization and Left recursion elimination (3) Create a parser class with private variable currentToken methods to call the scanner: accept and acceptIt (4) Implement a public method for main function to call: public parse method that fetches the first token from the scanner calls parseS (where S is start symbol of the grammar) verifies that scanner next produces the end–of–file token (5) Implement private parsing methods: add private parseN method for each non terminal N

Developing RD Parser for Mini Triangle Before we begin: The following non-terminals are recognized by the scanner They will be returned as tokens by the scanner Identifier := Letter (Letter|Digit)* Integer-Literal ::= Digit Digit* Operator ::= + | - | * | / | < | > | = Comment ::= ! Graphic* eol Assume scanner returns instances of this class: public class Token { byte kind; String spelling; final static byte IDENTIFIER = 0, INTLITERAL = 1; ...

(1)&(2) Developing RD Parser for Mini Triangle Program ::= single-Command Command ::= single-Command | Command ; single-Command single-Command ::= V-name := Expression | Identifier ( Expression ) | if Expression then single-Command else single-Command | while Expression do single-Command | let Declaration in single-Command | begin Command end V-name ::= Identifier ... Left recursion elimination needed Left factorization needed

(1)&(2) Express grammar in EBNF and transform After factorization etc. we get: Program ::= single-Command Command ::= single-Command (; single-Command)* single-Command ::= Identifier ( := Expression | ( Expression ) ) | if Expression then single-Command else single-Command | while Expression do single-Command | let Declaration in single-Command | begin Command end V-name ::= Identifier ...

(1)&(2) Developing RD Parser for Mini Triangle Expression ::= primary-Expression | Expression Operator primary-Expression primary-Expression ::= Integer-Literal | V-name | Operator primary-Expression | ( Expression ) Declaration ::= single-Declaration | Declaration ; single-Declaration single-Declaration ::= const Identifier ~ Expression | var Identifier : Type-denoter Type-denoter ::= Identifier Left recursion elimination needed Left recursion elimination needed

(1)&(2) Express grammar in EBNF and transform After factorization and recursion elimination : Expression ::= primary-Expression ( Operator primary-Expression )* primary-Expression ::= Integer-Literal | Identifier | Operator primary-Expression | ( Expression ) Declaration ::= single-Declaration (; single-Declaration)* single-Declaration ::= const Identifier ~ Expression | var Identifier : Type-denoter Type-denoter ::= Identifier

(3)&(4) Create a parser class and public parse method public class Parser { private Token currentToken; private void accept (byte expectedKind) { if (currentToken.kind == expectedKind) currentToken = scanner.scan( ); else report syntax error } private void acceptIt( ) { public void parse( ) { acceptIt( ); // get the first token parseProgram( ); // Program is the start symbol if (currentToken.kind != Token.EOT) ...

(5) Implement private parsing methods Program ::= single-Command private void parseProgram( ) { parseSingleCommand( ); }

(5) Implement private parsing methods single-Command ::= Identifier ( := Expression | ( Expression ) ) | if Expression then single-Command else single-Command | ... other alternatives ... private void parseSingleCommand( ) { switch (currentToken.kind) { case Token.IDENTIFIER : ... case Token.IF : ... ... other cases ... default: report a syntax error }

Algorithm to convert EBNF into a RD parser The conversion of an EBNF specification into a Java or C++ implementation for a recursive descent parser is so “mechanical” that it could easily be automated (such tools exist, but we won’t use them in this course) We can describe the algorithm by a set of mechanical rewrite rules private void parseN( ) { parse  // as explained on next two slides } N ::= 

Algorithm to convert EBNF into a RD parser parse t where t is a terminal accept(t); parse N where N is a non-terminal parseN( ); // a dummy statement parse e parse X Y parse X parse Y

Algorithm to convert EBNF into a RD parser parse X* while (currentToken.kind is in starters[X]) { parse X } parse X | Y switch (currentToken.kind) { cases in starters[X]: parse X break; cases in starters[Y]: parse Y default: if neither X nor Y generates  then report syntax error }

Example: “Generation” of parseCommand Command ::= single-Command ( ; single-Command )* private void parseCommand( ) { parseSingleCommand( ); while (currentToken.kind==Token.SEMICOLON) { parse ; parse single-Command } private void parseCommand( ) { parseSingleCommand( ); while (currentToken.kind==Token.SEMICOLON) { acceptIt( ); // because SEMICOLON has just been checked } private void parseCommand( ) { parseSingleCommand( ); while (currentToken.kind==Token.SEMICOLON) { parse ; single-Command } private void parseCommand( ) { parse single-Command parse ( ; single-Command )* } private void parseCommand( ) { parse single-Command ( ; single-Command )* } private void parseCommand( ) { parseSingleCommand( ); parse ( ; single-Command )* }

Example: Generation of parseSingleDeclaration ::= const Identifier ~ Expression | var Identifier : Type-denoter private void parseSingleDeclaration( ) { switch (currentToken.kind) { case Token.CONST: acceptIt( ); parseIdentifier( ); accept(Token.IS); parseExpression( ); case Token.VAR: accept(Token.COLON); parseTypeDenoter( ); default: report syntax error } private void parseSingleDeclaration( ) { switch (currentToken.kind) { case Token.CONST: acceptIt( ); parseIdentifier( ); accept(Token.IS); parseExpression( ); case Token.VAR: parse var Identifier : Type-denoter default: report syntax error } private void parseSingleDeclaration( ) { switch (currentToken.kind) { case Token.CONST: parse const Identifier ~ Expression case Token.VAR: parse var Identifier : Type-denoter default: report syntax error } private void parseSingleDeclaration( ) { parse const Identifier ~ Expression | var Identifier : Type-denoter } private void parseSingleDeclaration( ) { switch (currentToken.kind) { case Token.CONST: parse const parse Identifier parse ~ parse Expression case Token.VAR: parse var Identifier : Type-denoter default: report syntax error }

LL 1 Grammars The presented algorithm to convert EBNF into a parser does not work for all possible grammars. It only works for so called “LL 1” grammars. Basically, an LL 1 grammar is a grammar which can be parsed with a top-down parser with a lookahead (in the input stream of tokens) of one token. What grammars are LL 1? How can we recognize that a grammar is (or is not) LL 1? => We can deduce the necessary conditions from the parser generation algorithm.

LL 1 Grammars parse X* while (currentToken.kind is in starters[X]) { parse X } Condition: starters[X] must be disjoint from the set of tokens that can immediately follow X * parse X |Y switch (currentToken.kind) { cases in starters[X]: parse X break; cases in starters[Y]: parse Y default: if neither X nor Y generates  then report syntax error } Conditions: starters[X] and starters[Y] must be disjoint sets, and if either X or Y generates  then must also be disjoint from the set of tokens that can immediately follow X | Y

LL 1 grammars and left factorization The original Mini-Triangle grammar is not LL 1: For example: single-Command ::= V-name := Expression | Identifier ( Expression ) | ... V-name ::= Identifier Starters[V-name := Expression] = Starters[V-name] = Starters[Identifier] Starters[Identifier ( Expression )] = Starters[Identifier] NOT DISJOINT!

LL 1 grammars: left factorization What happens when we generate a RD parser from a non LL 1 grammar? single-Command ::= V-name := Expression | Identifier ( Expression ) | ... private void parseSingleCommand( ) { switch (currentToken.kind) { case Token.IDENTIFIER: parse V-name := Expression parse Identifier ( Expression ) ...other cases... default: report syntax error } wrong: overlapping cases

LL 1 grammars: left factorization single-Command ::= V-name := Expression | Identifier ( Expression ) | ... Left factorization (and substitution of V-name) single-Command ::= Identifier ( := Expression | ( Expression ) ) | ...

LL 1 Grammars: left recursion elimination Command ::= single-Command | Command ; single-Command What happens if we don’t perform left-recursion elimination? public void parseCommand( ) { switch (currentToken.kind) { case in starters[single-Command] parseSingleCommand( ); case in starters[Command] parseCommand( ); accept(Token.SEMICOLON); default: report syntax error } wrong: overlapping cases

LL 1 Grammars: left recursion elimination Command ::= single-Command | Command ; single-Command Left recursion elimination Command ::= single-Command (; single-Command)*

Abstract Syntax Trees So far we have talked about how to build a recursive descent parser which recognizes a given language described by an (LL 1) EBNF grammar. Next we will look at how to represent AST as data structures. how to modify the parser to construct an AST data structure. We make heavy use of Object–Oriented Programming! (classes, inheritance, dynamic method binding)