0% found this document useful (0 votes)
22 views

Lecture 6- Semantic Analysis

Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views

Lecture 6- Semantic Analysis

Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 26

Semantic Analysis

Compiler construction
Introduction to semantic analysis
Languages

• A language is a set of sentences (strings of


symbols) with well defined structures and
meaning

• Syntax of a language
• the rules specifying valid constructions of a
language
• e.g. syntax of algebra: x+2 is valid; x2+ is not valid
• Semantic of a language
• the interpretation of symbols and strings
• e.g. semantics of algebra: x+2 is the sum of the
values of x and 2
Compiler construction
Introduction to semantic analysis

• In the context of compilers, semantic analysis is a


crucial phase following lexical and syntactic
analysis, focusing on the meaning and validity of
the program's constructs according to the
programming language's rules.

• While lexical analysis identifies tokens and


syntactic analysis ensures the correct structure,
semantic analysis checks for logical correctness
and adherence to language-specific constraints.
• The semantic analysis phase in a compiler is
essential for detecting logical and contextual
errors in code, ensuring correctness, and laying
the groundwork for code optimization and error-
Compiler construction
Introduction to semantic analysis
Analysis Synthesis
of input program of output program
(front-end) (back-end)
Compiler Passes character
stream
Intermediate
Lexical Analysis Code Generation

token intermediate
stream form

Syntactic Analysis Optimization

abstract intermediate
syntax tree form

Semantic Analysis Code Generation

annotated target
AST language
Compiler construction
Introduction to semantic analysis
• Semantic analysis is the process of computing additional
information about a program's meaning after the syntactic
structure is known:
• Purpose: Semantic analysis ensures that a program's
statements and declarations are semantically correct,
meaning their meaning is clear and consistent.
• Process: Semantic analysis involves:
• Adding information to the symbol table
• Performing type checking
• Using attribute grammars to relate the program's
meaning to its syntactic structure
• Computing attribute values using semantic rules
• Evaluating semantic rules on the parse tree
• Output: The output of semantic analysis is the annotated
tree syntax.
• Phase in compilation: Semantic analysis is the third phase
of the compilation process.
Compiler construction
Introduction to semantic analysis
• Semantic analysis checks for various rules that
cannot be enforced by the syntax alone. These
include:
• Type Checking: Verifying that operands and
operators are compatible. E.g: Ensuring you don’t
add a string to an integer (3 + "hello" is invalid).
• Scope Resolution: Determining which variables,
functions, or identifiers are accessible in a given
part of the code (handling variable declarations,
shadowing, etc.).
• Name Resolution: Ensuring that every identifier
(variable, function, class, etc.) is declared before
it is used.
• Type Inference and Conversion: Handling implicit
type conversions or coercion when allowed, and
Compiler construction
Introduction to semantic analysis
• Semantic Rule Enforcement: Enforcing rules specific to
the language, such as:
• Function return type matches the declared type.
• The number and types of function arguments
match the declaration.
• Variables are initialized before use.
• Symbol Table Management: Maintaining a symbol
table where variable/function names are stored along
with their associated attributes (type, scope, etc.).
• Control Flow Checks:
• Ensuring proper use of control flow constructs like
break, continue, return, etc.
• Validating that all execution paths return a value in
non-void functions.
• Array and Pointer Checks: Verifying that array indices
are within bounds (if feasible at Compiler
compile time) and
construction
Introduction to semantic analysis
• Example

Semantic Analysis Process:


• Variable Declarations: x and y are declared; a is not.
• Type Checking: Addition x + y involves a type mismatch. If
the language allows implicit conversion, y may be cast to an
integer or x to a float.
• Name Resolution: Error reported for using a without
declaration.
• Initialization Check: z is declared and later initialized, so no
error.
Compiler construction
Introduction to semantic analysis
• Semantic analysis is the phase in which the compiler adds
semantic information to the parse tree and uses a symbol
table to identify and validate semantic information used in
the program.
• The symbol table is a dictionary containing information
about all the identifiers defined in a program.
• This phase performs semantic checks such as type
checking (checking for type errors), or static binding
(associating variable and function references with their
definitions/types), or definite assignment (requiring all local
variables to be initialized before use), rejecting semantically
incorrect programs.
• This phase follows the parsing phase, and precedes the
code generation phase, though it is often possible to fold
multiple phases into one pass over the code in a compiler
implementation, which is known as syntax-directed
translation.
• Not all rules defining programming languages can be
Compiler construction
Semantic analysis
Semantic rules are divided into:
• Static semantics — can be analyzed at
compile-time/enforced at compile time
• Dynamic semantics — analyzed at
runtime. the compiler generates code to
enforce dynamic semantic rules at run
time (or calls libraries to do it)(for errors
like division by zero, out-of-bounds index
in array)
• The principal job of the semantic analyzer
is to enforce static semantic rules, plus:
• constructs a syntax tree
• information gathered isCompiler
needed by the
construction
Introduction to semantic analysis
• Once semantic analysis is done, semantic translation may
traverse the parse tree and generate an intermediate code
representation.

Compiler construction
Symbol Tables
• Purpose: To hold information (i.e., attribute
values) about identifiers that get computed
at one point and used later.
• E.g.: type information:
• computed during parsing;
• used during type checking, code
generation.
• Operations:
• create, delete a symbol table;
• insert, lookup an identifier
• Typical implementations: linked list, hash 12

table. Compiler construction


Type checking
• An important component of semantic analysis is type
checking hence the compiler checks that each operator
has operands that are permitted by the source
language specification.
• For example, many programming language definitions
require a compiler to report an error every time a real
number is used to index an array.
• Types of Type Checking
• Static Type Checking: - Performed during compilation.
Examples: C, C++, Java, Rust.
• Benefits:
• Detects type errors early.
• Provides better optimization opportunities.
• Example:
• int a = "hello"; // Error: Incompatible types
13

Compiler construction
Type checking
• Dynamic Type Checking: Performed at runtime.
• Examples: Python, JavaScript.
• Benefits:
• Allows more flexible code (e.g., duck typing).
• Drawback:
• Type errors are discovered only during execution.
• Example:
• a = 5 + "hello" # Error: Cannot add integer and string
• Optional Type Checking:
• Some languages support both static and dynamic type
checking (e.g., TypeScript for JavaScript).

14

Compiler construction
Type checking
Type Systems
• A type system defines the set of rules governing type
compatibility in a programming language.
• Characteristics:
• Strongly-Typed: Prohibits mixing types without
explicit conversion (e.g., Java, Python).
• Weakly-Typed: Allows implicit type conversions
(e.g., C).

• Static vs. Dynamic: Determines when type checking


occurs.
• Key Concepts:
• Primitive Types: int, float, char, etc.
• Composite Types: Arrays, structures, classes, etc.
• User-Defined Types: Enums, typedefs, generics. 15
Compiler construction
Operator Overloading
• Overloading refers to the use of the same
syntax to refer to different operations,
depending on the operand types.
• E.g.: in Java, ‘+’ can refer to integer
addition, floating point addition, or
string concatenation.
• The compiler uses operand type information
to resolve the overloading, i.e., figure out
which operation is actually referred to.
• If there is insufficient information to
resolve overloading, the compiler may
give an error. 16

Compiler construction
Semantic Analysis
• Semantic Analysis computes additional information related to the meaning
of the program once the syntactic structure is known.
• In typed languages as C, semantic analysis involves

• adding information to the symbol table and

• performing type checking.

• The information to be computed is beyond the capabilities of standard


parsing techniques, therefore it is not regarded as syntax.

• As for Lexical and Syntax analysis, also for Semantic Analysis we need both
a Representation Formalism and an Implementation Mechanism.

Compiler construction
Syntax Directed Translation: Intro

• The Principle of Syntax Directed Translation states that the meaning


of an input sentence is related to its syntactic structure, i.e., to its
Parse-Tree.
• By Syntax Directed Translations we indicate those formalisms for
specifying translations for programming language constructs guided
by context-free grammars.
– We associate Attributes to the grammar symbols representing
the language constructs.
– Values for attributes are computed by Semantic Rules associated
with grammar productions.

Compiler construction
Syntax Directed Translation: Intro

• Syntax-Directed Translation (SDT) is a formalism for defining


translations of programming languages during compilation.

• It uses syntax-directed definitions or translation schemes to


associate semantic rules with the grammar of the source language.

• It involves associating:
• Attributes with grammar symbols.
• Semantic Actions with grammar productions.

• SDT is typically used in the semantic analysis phase to generate


intermediate code, perform type checking, or construct a syntax tree.

Compiler construction
Syntax Directed Translation: Intro (Cont.)
• Evaluation of Semantic Rules may:
– Generate Code;
– Insert information into the Symbol Table;
– Perform Semantic Check;
– Issue error messages; etc.

• There are two notations for attaching semantic rules:


1. Syntax Directed Definitions. High-level specification hiding
many implementation details (also called Attribute Grammars).
2. Translation Schemes. More implementation oriented: Indicate the order
in which semantic rules are to be evaluated.

Compiler construction
Syntax Directed Definitions

• Syntax Directed Definitions are a generalization of context-free


grammars in which:
1. Grammar symbols have an associated set of Attributes;
2. Productions are associated with Semantic Rules for computing
the values of attributes.
• Such formalism generates Annotated Parse-Trees where each node of
the tree is a record with a field for each attribute (e.g., X . a indicates
the attribute a of the grammar symbol X ) .

Compiler construction
Syntax Directed Definitions (Cont.)

• The value of an attribute of a grammar symbol at a given parse-tree


node is defined by a semantic rule associated with the production used
at that node.
• We distinguish between two kinds of attributes:
1. Synthesized Attributes. They are computed from the
values of the attributes of the children nodes.
2. Inherited Attributes. They are computed from the values
of the attributes of both the siblings and the parent nodes.

Compiler construction
Form of Syntax Directed Definitions
• Each production, A → α, is associated with a set of semantic rules:
b : = f (c 1 , c2 , . . . , c k ), where f is a function and either
1. b is a synthesized attribute of A , and c1 , c2 , . . . , c k are attributes of the
grammar symbols of the production, or
2. b is an inherited attribute of a grammar symbol in α, and c1 , c2 , . . . , c k
are attributes of grammar symbols in α or attributes of A .

• Note. Terminal symbols are assumed to have synthesized attributes supplied


by the lexical analyzer.

• Procedure calls (e.g. print in the next slide) define values of Dummy
synthesized attributes of the non terminal on the left-hand side of the
production.

Compiler construction
Syntax Directed Definitions: An
Example
• Example. Let us consider the Grammar for arithmetic expressions.
The Syntax Directed Definition associates to each non terminal a
synthesized attribute called val.
P RODUCTION S EMANTIC R ULE
L → En print(E.val)
E → E1 + E . v a l : = E 1 .val +
T
T.val E . v a l : = T.val
E → T
T.val : = T 1 .val ∗ F.val
T → T1 ∗ T.val : = F.val
F T → F F.val : = E . v a l
F → (E)
F.val :=digit.lexva
Compiler construction
S-Attributed Definitions

Definition. An S-Attributed Definition is a Syntax Directed


Definition that uses only synthesized attributes.
• Evaluation Order.Semantic rules in a S-Attributed
Definition can be evaluated by a bottom-up, or PostOrder,
traversal of the parse-tree.

Compiler construction
S-Attributed Definitions
 Example. The above arithmetic grammar is an example of an S-Attributed Definition. The annotated parse-tree for the
input 3*5+4n is:

L
E.val = n
19
E.val = + T.val =
15 4
F.val = 4
T.val =
T.val =1 5 * F.val = 5 digit.lexval=
3 4
F.val = 3 digit.lexval=
5
digit.lexval=
3

Compiler construction

You might also like