Chapter 4
Chapter 4
Chapter 4
Semantics analysis
and
Syntax Directed Translation (SDT)
Semantics analysis
• Parsing only verifies that the program consists of tokens arranged in a syntactically valid
combination.
• In semantic analysis check whether they form a sensible set of instructions in the
programming language.
• a program to be semantically valid, all variables, functions, classes, etc. must be properly
defined.
• Semantic analysis consists of tracking variable/function/type declarations and type
checking.
• the compiler encounters a new declaration, it records the type information assigned to that
identifier.
• Then, as it continues examining the rest of the program, it verifies that the type of an
identifier is respected in terms of the operations being performed.
Role of semantic analyzer/analysis
• checks for the semantic consistency.
• Type information is gathered and stored in symbol table or in syntax
tree.
• Performs type checking.
• It verifies the parse tree, whether it’s meaningful or not. It
furthermore produces a verified parse tree.
Sematic analysis
• Semantic analysis judges whether the syntax structure constructed in
the source program derives any meaning or not.
• For example: int a = “value”;
• should not issue an error in lexical and syntax analysis phase, as it
is lexically and structurally correct,
• but generates a semantic error as the type of the assignment differs.
Examples of Semantic Errors
• Example 1: Use of a non-initialized variable:
• int i; i++; // the variable i is not initialized
• Example 2: Type incompatibility:
• int a = "hello"; // the types String and int are not compatible
• Example 3: Errors in expressions:
• String s = "..."; int a = 5 - s; // the - operator does not support
arguments of type String
• Example 4: Unknown references:
• Strin x; // Strin is not defined system.out.println("hello");
Examples of Semantic Errors
• Example 5: Array index out of range (dynamic semantic error)
• int[] v = new int[10]; v[10] = 100; // 10 is not a legal index for an array of 10
elements
• The array v has been created with 10 elements (with indexes ranging from 0
to 9), and we are trying to access the element with index 10, which does not
exist.
• This type of error is not caught during compilation, but causes an exception to
be thrown at runtime
Sematic analysis
• The following tasks should be performed in semantic analysis:
• Scope resolution: Can't declare a variable with the same name twice
in the same scope .
• Type checking: check type e.g int x=12.5
• Array-bound checking: when boundaries of array exceed
• The main mechanism a semantic analysis uses to perform this check is
called as SDT.
Type Checking
• Type checking is the process of verifying that each operation executed in a
program respects the type system of the language.
• This generally means that all operands in any expression are of appropriate types
and number.
• E.g, Java's % operator
• int x = 3 % 4.5 is a type error.
• A language is considered strongly typed if each and every type error is detected
during compilation.
• Type checking can be occur either at compile time (i.e. statically) or at runtime
(i.e. dynamically).
Static and Dynamic Type Checking
• An inherited attribute : These are the attributes which derive their values from their parent or
sibling nodes, i.e if a node takes value from its parent or sibling :
• Eg. BACD A.i=B.i, A.i=C.i, A.i=D.i
Types of SDD: based on the types of attributes the SDD uses
divided into two
1.S-attribute
A SDD that uses only synthesis attributes is called as S- attribute.
Semantic action are always placed at right end of the production(it called as
postfix SDD).
Attributed is evaluated with bottom up parsing.
2.L-attribute
A SDD uses both synthesis and inherited attribute but each inherited attribute
inherits from parent and left sibling only.
Semantic action are place anywhere of RHs.
Attributes are evaluated traversing parse tree depth first ,left to right order.
Eg. AXYZ (Y.i=A.i, Y.i=X.i)
Annotated Parse Tree
• Annotated Parse Tree – The parse tree containing the values of
attributes at each node for given input string is called annotated or
decorated parse tree.
• In order to construct annotated parse tree we have to perform top to
down left to right traversing if there is a reduction then perform the
corresponding sematic action
SDD for evaluation of an expression
Production Semantic Rules
L→E print(E.val)
E → E1 + T E.val = E1.val + T.val
E → T E.val = T.val
T → T1 * F T.val = T1.val * F.val
T → F T.val = F.val
F → ( E ) F.val = E.val
F → digit F.val = digit.lexval
E.val=17
E.val=5 + T.val=12
digit.lexval=5 digit.lexval=3
val is synthesized attribute
18
Syntax-Directed Definition: Inherited Attributes
Inherited
Production Semantic Rules
D → T L L.inh = T.type
T → int T.type = integer
T → real T.type = real synthesized
L → L1 , id L1.inh = L.inh,
addtype(id.entry,L.inh)
L → id addtype(id.entry,L.inh)
D
Input: real id1,id2,id3
Id1.entry
20
Syntax-Directed Definition: Inherited Attributes
Production Semantic Rules
T → FT’ T’.inh = F.val
T.val = T’.syn
T’ → *FT1’ T1’.inh = T’.inh X F.val
T’.syn = T1’.syn
T’ → ε T’.syn = T’.inh
F → digit F.val = digit.lexval
Semantic Actions
23
Translation Schemes
• In translation schemes, we use semantic action terminology instead of
semantic rule terminology used in syntax-directed definitions.
• The position of the semantic action on the right side indicates when that
semantic action will be evaluated.
• SDTs are more efficient than SDDs as they indicate the order of evaluation
of semantic actions associated with a production rule.
• The general approach to Syntax-Directed Translation is First we need
construct parse tree, traverse the parse tree top to down left to right if you
have some reduction perform sematic action in order to get the
corresponding expression
24
SDT for evaluation of an expression
• Example:
• E -> E+T { E.val = E.val + T.val }
• E -> T { E.val = T.val }
• T -> T*F { T.val = T.val * F.val }
• T -> F { T.val = F.val }
• F -> num { F.val = num.lexval }
• Let’s take a string to see how semantic analysis happens – S = 2+3*4.
Parse tree corresponding to S would be
SDT for evaluation of an expression
A Translation Scheme Example
• translation scheme that converts infix expressions to the corresponding postfix
expressions.
E → E+T { print(“+”) }
E→ T{}
T → T*F { print(“ * ”) }
T→ F{}
F → num { print num.val }
2+3*4 234*+
E + T {print(“+”)}
T T * F {print(“*”)}
28
A Translation Scheme Example
• A simple translation scheme that converts infix expressions to the
corresponding postfix expressions.
E→TR
R → + T { print(“+”) } R1
R→
T → id { print(id.name) }
a+b+c ab+c+
29
A Translation Scheme: Example…
E
T R
id {print(“a”)} + T {print(“+”)} R
id {print(“b”)} + T {print(“+”)} R
id {print(“c”)}
• The depth first traversal of the parse tree (executing the semantic actions in that order)
will produce the postfix representation of the infix expression.
30
Exercise
• write SDT for infix to prefix translation and draw parse tree
• E,g 3 * 5 + 4 + * 3 5 4.
31