Ch. 4 – Semantic Analysis Errors can arise in syntax, static semantics, dynamic semantics Some PL features are impossible or infeasible to specify in grammar.

Slides:



Advertisements
Similar presentations
CPSC 388 – Compiler Design and Construction
Advertisements

Semantics Static semantics Dynamic semantics attribute grammars
Attribute Grammars Prabhaker Mateti ACK: Assembled from many sources.
Semantic Analysis Chapter 6. Two Flavors  Static (done during compile time) –C –Ada  Dynamic (done during run time) –LISP –Smalltalk  Optimization.
Chapter 5 Syntax Directed Translation. Outline Syntax Directed Definitions Evaluation Orders of SDD’s Applications of Syntax Directed Translation Syntax.
Semantic Analysis Chapter 4. Role of Semantic Analysis Following parsing, the next two phases of the "typical" compiler are – semantic analysis – (intermediate)
1 Pass Compiler 1. 1.Introduction 1.1 Types of compilers 2.Stages of 1 Pass Compiler 2.1 Lexical analysis 2.2. syntactical analyzer 2.3. Code generation.
Semantic analysis Parsing only verifies that the program consists of tokens arranged in a syntactically-valid combination, we now move on to semantic analysis,
CPSC Compiler Tutorial 9 Review of Compiler.
1 Semantic Processing. 2 Contents Introduction Introduction A Simple Compiler A Simple Compiler Scanning – Theory and Practice Scanning – Theory and Practice.
Environments and Evaluation
Slide 1 Chapter 3 Attribute Grammars. Slide 2 Attribute Grammars Certain language structures cannot be described using EBNF. Attribute grammars are extensions.
Yu-Chen Kuo1 Chapter 2 A Simple One-Pass Compiler.
Chapter 2 A Simple Compiler
2.2 A Simple Syntax-Directed Translator Syntax-Directed Translation 2.4 Parsing 2.5 A Translator for Simple Expressions 2.6 Lexical Analysis.
1 Abstract Syntax Tree--motivation The parse tree –contains too much detail e.g. unnecessary terminals such as parentheses –depends heavily on the structure.
1 Semantic Analysis Aaron Bloomfield CS 415 Fall 2005.
COP4020 Programming Languages Semantics Prof. Xin Yuan.
Lesson 3 CDT301 – Compiler Theory, Spring 2011 Teacher: Linus Källberg.
3-1 Chapter 3: Describing Syntax and Semantics Introduction Terminology Formal Methods of Describing Syntax Attribute Grammars – Static Semantics Describing.
Interpretation Environments and Evaluation. CS 354 Spring Translation Stages Lexical analysis (scanning) Parsing –Recognizing –Building parse tree.
Review 1.Lexical Analysis 2.Syntax Analysis 3.Semantic Analysis 4.Code Generation 5.Code Optimization.
Semantic Analysis CPSC 388 Ellen Walker Hiram College.
Copyright © 2006 Addison-Wesley. All rights reserved. Ambiguity in Grammars A grammar is ambiguous if and only if it generates a sentential form that has.
1 Compiler & its Phases Krishan Kumar Asstt. Prof. (CSE) BPRCE, Gohana.
1 A Simple Syntax-Directed Translator CS308 Compiler Theory.
Syntax and Semantics Form and Meaning of Programming Languages Copyright © by Curt Hill.
Overview of Previous Lesson(s) Over View 3 Model of a Compiler Front End.
LECTURE 3 Compiler Phases. COMPILER PHASES Compilation of a program proceeds through a fixed series of phases.  Each phase uses an (intermediate) form.
CSE 420 Lecture Program is lexically well-formed: ▫Identifiers have valid names. ▫Strings are properly terminated. ▫No stray characters. Program.
CS 404Ahmed Ezzat 1 CS 404 Introduction to Compiler Design Lecture Ahmed Ezzat.
LECTURE 10 Semantic Analysis. REVIEW So far, we’ve covered the following: Compilation methods: compilation vs. interpretation. The overall compilation.
Chapter4 Syntax-Directed Translation Introduction : 1.In the lexical analysis step, each token has its attribute , e.g., the attribute of an id is a pointer.
Chapter 3 – Describing Syntax
Describing Syntax and Semantics
Semantic analysis Jakub Yaghob
Compiler Design (40-414) Main Text Book:
CS 3304 Comparative Languages
A Simple Syntax-Directed Translator
Introduction to Parsing
CS510 Compiler Lecture 4.
Parsing and Parser Parsing methods: top-down & bottom-up
Introduction to Parsing (adapted from CS 164 at Berkeley)
Compilers Principles, Techniques, & Tools Taught by Jing Zhang
CS 363 – Chapter 1 What is a programming language? Kinds of languages
Chapter 5 Syntax Directed Translation
Abstract Syntax Trees Lecture 14 Mon, Feb 28, 2005.
Syntax-Directed Translation Part I
CS 3304 Comparative Languages
Syntax Questions 6. Define a left recursive grammar rule.
Syntax-Directed Translation
Syntax-Directed Translation Part I
Syntax-Directed Translation Part I
Chapter 6 Intermediate-Code Generation
Chapter 2: A Simple One Pass Compiler
Lecture 7: Introduction to Parsing (Syntax Analysis)
Compilers Principles, Techniques, & Tools Taught by Jing Zhang
Compiler design.
Chapter 4 Action Routines.
Syntax-Directed Translation Part I
Compiler Construction
The Recursive Descent Algorithm
Chapter 10: Compilers and Language Translation
Compilers Principles, Techniques, & Tools Taught by Jing Zhang
Syntax-Directed Translation Part I
COP4020 Programming Languages
COP4020 Programming Languages
Chapter 5 Syntax Directed Translation
Compiler Construction
Presentation transcript:

Ch. 4 – Semantic Analysis Errors can arise in syntax, static semantics, dynamic semantics Some PL features are impossible or infeasible to specify in grammar Correct number of parameters to function Every function must contain a return In fact, some rules can’t be checked at compile time! Source of many run-time errors  We’ll just focus on static semantics.

Semantic analysis We will revisit grammars…. We can check assertions And decorate them with attributes, to help us build symbol table Augment our grammars to contain “semantic actions” To evaluate expression To generate (intermediate) code We can check assertions Along way, can perform simple optimizations “safe” = change will have no effect on output/effect “speculative” = change may degrade performance “conservative” = safe & not speculative

Compilation overvew Scan Parse Semantic Checking Code Generation Create syntax tree Find semantic errors Code Generation Optimization

Semantic checking Chapter overview: Create syntax tree (4.2 – 4.4) Annotate CFG with attributes/actions Decorate parse tree OR start from token stream Find semantic errors (4.6) Grammar for syntax tree Define attributes/actions to propagate errors

Syntax vs. semantics In chapter 2, we just wanted to verify input was legal syntax. Now, we need output: syntax tree. What is difference between parse tree & syntax tree? Note: Syntax tree much better than parse tree for generating code, etc. Can proceed: directly from token stream from parse tree. And also check things like variable declarations.

Attribute grammar Purpose: give “meaning” to PL grammar How do we know we’re not defining molecular formula for mustard? Meaning = value, attribute to keep track of Ex. For expression grammar: We can parse to see if it’s valid  parse tree With attributes in the grammar we can: evaluate the expression. output expression’s structure as a syntax tree.

Attributes We add semantic rules to each production in the grammar. Rule takes effect when we “reduce.” Left side of each production keeps track of an attribute value (p. 186) E1  E2 + T E1.val = E2.val + T.val E1  E2 – T E1.val = E2.val – T.val E  T E1.val = T.val etc. (Subscripts only used to distinguish left/right sides)

Attribute values Tokens already got values from scanner. We just need to evaluate nonterminals. Propagation of attribute values can go in 2 directions Usually bottom-up towards the root. Sometimes left-to-right, right-to-left, etc.

Synthesized attributes A nonterminal’s value is computed only when it appears on left side of a production (common case) Evaluation is bottom-up (p. 187) parse tree with attributes E E(5) E + T E(2) + T(3) T F T(2) F(3) F const F(2) const(3) const 3 const(2) 3 2 2

Inherited attributes This happens when the associativity of an operator doesn’t match sense of recursion (unusual case) Ex. Left associative, but right recursive expr  const tail tail  – const tail | ε (p. 188) expr 5 tail  What do we subtract 2 from? – 2 tail ε

Inherited attr (2) Left-to-right, then bottom up (see p. 189): expr 5 tail1  What do we subtract 2 from? – 2 tail2 ε Each node may have “subtotal” preliminary value. Start at the 5, and pass it to the right! This means tail1.subtotal = 5 Subtract 2, tail2.subtotal = 3 Base case, copy subtotal to value: tail2.val = 3 Pass 3 up to tail1.val Pass 3 up to expr.val

Next Attribute grammars for expressions are nice, but for entire PL we need to create syntax tree. At each production in grammar, we’ll create a node of the tree, either a leaf or subtree. Study handout “Creating a Syntax Tree”

Syntax trees  Check semantics  Generate intermediate code How to create a syntax tree

Syntax tree What does a syntax tree look like? Depends on input. Example p. 202… tree has 3 parts “program” node at the root Interior nodes for sequence of statements Could represent as linked list instead! Read left-to-right or top-down. Expression subtree in 1 statement Evaluate bottom-up

Syntax tree What do we do with syntax trees? Check semantics Write a tree grammar Annotate with actions to capture errors Generate intermediate code Traverse list of statements, and expression operators to output list of instructions

Tree grammar Special grammar to describe syntax tree Not same as PL’s grammar! Need productions for Root Interior nodes representing statements Expression elements (+, const, etc.) (same example, p. 202)

Attributes Once you have tree grammar: For each production, specify actions for: symbol table: propagate info LR/top-down (because variables are declared before use!) errors: propagate bottom-up, or output immediately Root: initialize both to empty Declaration stmt: add var to symbol table Other stmts & expressions: check against symbol table, and generate error as needed. Example. p. 204-206. Propagate errors bottom-up so we can save list of errors for later 

Common actions Much work done by routines given p. 206 that are called at many places in grammar. Declare_name Check for re-declaration of same variable! Add variable to symbol table Check_types For all variables in this statement/expression, look them up to see if declared and types appropriate. Convert_type (int  float, float  int, etc.)

Intermediate Code With syntax tree we can also generate intermediate code Look at example p. 202 again: Typically a node has up to 3 parts: self and 1 or 2 children Each node can become a “triple” In assembly code, instructions limited to 1 operation So our sequence of “instructions” could be: begin; int_decl; read; real_decl; read; float; +; /; write; quit The “float + / write” triples can be in one node in the linked list: evaluate BOTTOM UP. For brevity, I left out operands of intermediate inst.

Creating syntax tree See handout. Here’s a relatively simple approach: 1. Create bottom-up parse table 2. Write semantic actions to create subtree whenever we reduce. For example, “E  E + T ●” can have a node with root “+”. 3. Trace according to parse table, and also maintain stack/linked list of subtrees. 4. When done parsing, stack will contain syntax tree. “Linked list” concept convenient for sequences, although still a “tree”.

Alternative to syntax tree Syntax tree examples declaration grammar (from lab 2) postfix expressions Alternative to syntax tree Why not a linear structure? Reusing nodes

Declaration grammar Parse table (done) Semantic actions Trace Create node for “a = 5” Create node for “b = 6” Combine into a sequence  syntax tree See page 7 of handwritten notes. (page 8 for original parse table)

Postfix First, need a grammar (handle + and –) Follow steps to make syntax tree…. Good review of bottom-up parsing We could create parse tree & syntax tree, although the parse tree more complex! (Just consider what just 2+3 would look like)

Syntax tree alternatives Why a tree instead of purely linear? Structure is hierarchical (except for sequence of statements) More efficient to traverse Easier to optimize 

Saving nodes a + a * (b – c) + (b – c) * d Sometimes in a tree, the same node is created twice. Allow node to have more than one parent. Check to see if an identical node already exists, and avoid duplication.  Avoid generating redundant code. Ex. What would syntax tree look like for this? a + a * (b – c) + (b – c) * d

Example + + * * d a – b c p1=make_leaf(a) p2=make_leaf(a) = p1 a + a * (b – c) + (b – c) * d + + * * d a – b c p1=make_leaf(a) p2=make_leaf(a) = p1 p3=make_leaf(b) p4=make_leaf(c) p5=make_node(-,p3,p4) p6=make_node(*,p2,p5) p7=make_node(+,p1,p6) p8=make_leaf(b) = p3 p9=make_leaf(c) = p4 p10=make_node(-,p8,p9) etc. “directed acyclic graph”