What Is Semantic Analysis
Parsing only verifies that the program consists of tokens arranged in a syntactically
Now we’ll move forward to
, where we delve even
deeper to check whether they form a sensible set of instructions in the programming
Whereas any old noun phrase followed by some verb phrase makes a
syntactically correct English sentence, a semantically correct one has subject-verb
agreement, proper use of gender, and the components go together to express an idea
that makes sense.
For a program to be semantically valid, all variables, functions,
classes, etc. must be properly defined, expressions and variables must be used in ways
that respect the type system, access control must be respected, and so forth.
analysis is the front end’s penultimate phase and the compiler’s last chance to weed out
We need to ensure the program is sound enough to carry on to
A large part of semantic analysis consists of tracking variable/function/type
declarations and type checking.
In many languages, identifiers have to be declared
before they’re used.
As 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
For example, the type of the right side expression of an assignment
statement should match the type of the left side, and the left side needs to be a properly
declared and assignable identifier.
The parameters of a function should match the
arguments of a function call in both number and type.
The language may require that
identifiers be unique, thereby forbidding two global declarations from sharing the same
Arithmetic operands will need to be of numeric—perhaps even the exact same
type (no automatic
conversion, for instance).
These are examples of the
things checked in the semantic analysis phase.
Some semantic analysis might be done right in the middle of parsing.
As a particular
construct is recognized, say an addition expression, the parser action could check the
two operands and verify they are of numeric type and compatible for this operation.
fact, in a one-pass compiler, the code is generated right then and there as well.
compiler that runs in more than one pass (such as the one we are building for Decaf),
the first pass digests the syntax and builds a parse tree representation of the program. A
second pass traverses the tree to verify that the program respects all semantic rules as
The single-pass strategy is typically more efficient, but multiple passes allow for
better modularity and flexibility (i.e., can often order things arbitrarily in the source