Semantic Analysis #
Semantic analysis is the phase of the compilation process where the compiler checks the correctness of the program’s semantics, ensuring proper usage of language constructs, type compatibility, scope adherence, control flow, and other language-specific rules.
Semantic analysis is the third phase of the compilation process. After the parser constructs a parse tree (or an abstract syntax tree, AST) from the source code, the compiler performs semantic analysis to validate the correctness of the program’s semantics, i.e., its meaning.
While syntax analysis checks the program’s structure for adherence to the language’s grammar rules, semantic analysis checks for the correct usage of language constructs, variable and function declarations, type compatibility, and other context-sensitive rules.
Some common tasks performed during semantic analysis include:
Symbol table construction: The compiler creates a symbol table, a data structure that stores information about identifiers (e.g., variables, functions, classes) used in the source code. The symbol table associates each identifier with its type, scope, and other relevant attributes.
Type checking: The compiler ensures that operations and expressions are semantically valid by checking the compatibility of their types. For instance, it ensures that operands in arithmetic operations have numeric types, and that function arguments match the expected parameter types.
Scope checking: The compiler verifies that identifiers are used within their proper scope. For example, it ensures that local variables are not accessed outside the function in which they are declared, and that global variables are declared before they are used.
Control flow analysis: The compiler examines the program’s control flow, checking for unreachable code or potential infinite loops, and ensuring that all code paths in a function return a value if required.
Other language-specific rules: Depending on the programming language, the compiler may enforce additional semantic rules, such as the correct usage of inheritance and polymorphism in object-oriented languages or ensuring proper initialization of variables.
For example
int add(int a, int b) {
return a + b;
}
int main() {
int x = 10;
int y = "hello"; // Error: Type mismatch
if (x = 5) { // Error: Assignment instead of comparison
int z = add(x, y); // Error: Type mismatch in function call
}
int z = x * y; // Error: Undeclared variable 'y'
return 0;
}
During semantic analysis, the compiler would identify several errors:
- Type mismatch when assigning a string to an integer variable (y).
- Incorrect usage of assignment instead of comparison in the if statement.
- Type mismatch when calling the add function with an incorrect argument type.
- Use of undeclared variable y in the expression x * y.
To perform semantic analysis in a compiler, you would typically traverse the AST generated by the parser and apply a set of rules or checks based on the specific programming language. Some compiler tools, such as ANTLR or Bison, can help automate parts of the semantic analysis process by generating code based on the provided grammar and semantic rules.