Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 112

Semantic Analysis

Where we are at
• So far, we’ve only defined
the structure of a
program—aka the syntax
• We are now diving into
the semantics of the
program

2
Semantic Analysis
• Two phases
• Name analysis (aka name resolution)
• For each scope
• Process declarations, add them to symbol table
• Process statements, update IDs to point to their entry
• Type analysis
• Process statements
• Use symbol table info to determine the type of each expression (and sub-expression)

7
Implementing Semantic Analysis
● Attribute Grammars
Augment rules to do checking during parsing.
Has its limitations.
● Recursive AST Walk
Construct the AST, then use functions and
recursion to explore the tree.
Scope
Simplified view of symbol table example 1
main(){ //line 1
char a[5]; //line 2
int x; //line 3
Simplified view of symbol table example 2
Possible Symbol Table Implementations
Why Two Interpretations?
•Spaghetti stack more accurately captures
the scoping structure
•Spaghetti stack is a static structure
•Explicit stack is a dynamic structure.
Scoping in Object-Oriented Languages
Explicit Disambiguation: Another Example
Single- and Multi-Pass Compilers
• Parsing methods such as LL(1), LR(0), LALR(1), etc. always
scan the input from left-to-right
• Since we only need one token of lookahead, we can do
lexical analysis and parsing simultaneously in one pass
over the file
• Some compilers can combine scanning, parsing,
semantic analysis, and code generation into the same
pass. These are called single-pass compilers
• Other compilers rescan the input multiple times. These
are called multi-pass compilers
Symbol table entries
• Table that binds a name to information we need

• What information do you think we need?


• Kind (struct, variable, function, class)
• Type (int, int × string → bool, struct)
• Nesting level
• Runtime location (where it’s stored in memory)

89
Symbol table implementation
• We want the symbol table to efficiently add an
entry when we need it, remove it when we’re
done with it
• A good choice is a list of Java HashMaps,
ArrayLists for ordered lists (parameters, etc.)
• This makes sense since we expect to remove a
lot of names from scope at once
90
Example

g: () -> void, 1

91
Symbol kinds
• Symbol kinds (= types of identifiers)
• Variables
• Carries a name, primitive type
• Function declarations
• Carries a name, return type, list of parameter types
• Struct definitions
• Carries a name, list of fields (types with names), size

92
Sym class implementation
• There are many ways to implement symbols
• Here’s one suggestion
• Sym class for variable definitions
• FnSym class for function declarations
• StructDefSym for struct type definitions
• Contains it’s OWN symbol table for it’s field definitions
• StructSym for when you want an instance of a struct

93
Implementing name analysis with an AST
• At this point, we’re done with the Parse Tree
- All subsequent processing done on the AST + symbol table

• Walk the AST


• Augment AST nodes where names are used (both declarations and uses) with
a link to the relevant object in the symbol table
• Put new entries into the symbol table when a declaration is encountered

94
Abstract Syntax Tree int a;
int f(bool r) {
DeclListNode struct b{
int q;
};
cout << a;
VarDeclNode FnDeclNode }

IntNode IdNode IntNode IdNode FormalListNode FnNodeBody

Id types: Var, Function, Struct VarDeclNode StructDeclNode WriteStmtNode

BoolNode IdNode DeclListNode IdNode


Symbol Table
VarDeclNode
Sym
a
Type: Int
Sym IntNode IdNode
r
Type: bool
FnSym
f RetType: Int
List<Type>: [bool] StructDeclSym q Sym
b
fields Type: Int
95
Symbol Table for Classes and Methods

You might also like