Download presentation
Presentation is loading. Please wait.
Published byOliver Smith Modified over 6 years ago
1
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.
2
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
3
Compilation overvew Scan Parse Semantic Checking Code Generation
Create syntax tree Find semantic errors Code Generation Optimization
4
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
5
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.
6
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.
7
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)
8
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.
9
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 const(2)
10
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 tail What do we subtract 2 from? – tail ε
11
Inherited attr (2) Left-to-right, then bottom up (see p. 189):
expr tail What do we subtract 2 from? – 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
12
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”
13
Syntax trees Check semantics Generate intermediate code How to create a syntax tree
14
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
15
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
16
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)
17
Attributes Once you have tree grammar:
For each production, specify actions for: symbol table: propagate info LR/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 Propagate errors bottom-up so we can save list of errors for later
18
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.)
19
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.
20
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”.
21
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
22
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)
23
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)
24
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
25
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
26
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”
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.