Skip to main content

Overview

The Semantic Analyzer is the third phase of compilation. After the Parser creates a syntactically correct AST, the Semantic Analyzer verifies that the program makes sense logically.
Analogy: Grammar vs. MeaningGrammatically correct but meaningless: “Colorless green ideas sleep furiously.”Semantically correct: “The cat sleeps quietly.”Similarly, let x = y + 1; is syntactically valid, but meaningless if y doesn’t exist.

Semantic Checks

The analyzer performs two main validations:

Variable Declaration

Rule: Variables must be declared before use.Example Error:
print x;  // Error: 'x' not declared
let x = 5;

Division by Zero

Rule: Cannot divide by literal zero.Example Error:
let x = 10 / 0;  // Error: division by zero
Only literal zero is caught. Runtime checks (e.g., 10 / x where x = 0) are not performed.

Symbol Table

The analyzer maintains a set of declared variables:
class AnalizadorSemantico:
    def __init__(self):
        self.variables_declaradas: set = set()
        self.errores: List[str] = []
Why a set?
  • Fast lookup: O(1) membership testing
  • No duplicates: Automatically handles redeclarations
  • Simple: No need to store types or values (this is a simple language)

Variable Lifecycle

1

Declaration

When encountering let x = expression;:
  1. Analyze the expression first (may reference other variables)
  2. Add 'x' to variables_declaradas
  3. Continue to next statement
def _analizar_declaracion(self, decl: DeclaracionVariable):
    nombre = decl.nombre.lexema
    
    # Check expression first
    self._analizar_expresion(decl.expresion)
    
    # Then register variable
    self.variables_declaradas.add(nombre)
2

Usage

When encountering an identifier in an expression:
  1. Check if variable is in variables_declaradas
  2. If not, add error to self.errores
  3. Continue analysis (don’t stop)
def _analizar_expresion(self, expr: Expresion):
    if isinstance(expr, Identificador):
        if expr.nombre not in self.variables_declaradas:
            self.errores.append(
                f"Error semántico: la variable '{expr.nombre}' no ha sido declarada"
            )

Analysis Algorithm

The analyzer traverses the AST recursively:
def analizar(self, programa: Programa) -> bool:
    for sentencia in programa.sentencias:
        self._analizar_sentencia(sentencia)
    
    return len(self.errores) == 0

Traversal Pattern

def _analizar_sentencia(self, sentencia: Sentencia):
    if isinstance(sentencia, DeclaracionVariable):
        self._analizar_declaracion(sentencia)
    elif isinstance(sentencia, SentenciaPrint):
        self._analizar_print(sentencia)

Error Examples

Undeclared Variable

let x = 5;
let y = x + z;  // z is not declared
print y;

Division by Zero

let x = 10 / 0;  // Literal zero
let y = 10 / z;  // Variable (not caught)

Variable Redeclaration

let x = 5;
let x = 10;  // Redeclaration (warning, not error)
print x;

Order-Dependent Analysis

Variables must be declared BEFORE use - order matters!
let x = 5;
let y = x + 1;  // ✓ x already declared
Result: No errors

Why Continue After Errors?

The analyzer collects all errors in one pass:
def _analizar_expresion(self, expr: Expresion):
    if isinstance(expr, Identificador):
        if expr.nombre not in self.variables_declaradas:
            # Add error but DON'T raise exception
            self.errores.append(...)
            # Continue analyzing
Benefits:

Better UX

User sees all errors at once, not just the first one.Saves time: fix multiple issues in one iteration.

More Context

Multiple errors can reveal root cause.Example: 5 “undeclared variable” errors → likely missing one let statement.
Example:
let x = a + b;  // 2 errors
let y = c * d;  // 2 errors
print z;        // 1 error
Output:
Error semántico en línea 1, columna 9: la variable 'a' no ha sido declarada
Error semántico en línea 1, columna 13: la variable 'b' no ha sido declarada
Error semántico en línea 2, columna 9: la variable 'c' no ha sido declarada
Error semántico en línea 2, columna 13: la variable 'd' no ha sido declarada
Error semántico en línea 3, columna 7: la variable 'z' no ha sido declarada

5 errores encontrados
User can fix all 5 declarations at once.

Limitations

What the semantic analyzer CANNOT detect:
  1. Runtime division by zero:
    let x = 0;
    let y = 10 / x;  // x is variable, not literal
    
    No error - only literal 0 is caught.
  2. Integer overflow:
    let x = 999999 * 999999;  // Result exceeds int range
    
    No overflow checking.
  3. Type mismatches: All values are integers - no type system to check.
  4. Infinite loops: Language has no loops, but if it did, they wouldn’t be analyzed.
  5. Unused variables:
    let x = 5;  // Never used
    
    No warnings for unused variables.

Complete Analysis Example

let a = 5;
let b = 10;
let c = a + b * 2;
print c;
Analysis:
✓ Statement 1: Declare 'a', value: 5
✓ Statement 2: Declare 'b', value: 10
✓ Statement 3: Declare 'c', uses 'a' and 'b' (both exist)
✓ Statement 4: Print 'c' (exists)

[FASE 3] Análisis Semántico...
         (Verificando que el código tenga sentido)
  ✓ Completado: 3 variables verificadas

Performance

Time Complexity

O(n) where n = AST node countEach node visited exactly once in DFS traversal.

Space Complexity

O(v + e) where:
  • v = number of declared variables
  • e = number of errors found
Plus O(d) for recursion stack (d = max nesting depth).

Source Code Reference

Implementation

File: compfinal.pyLines: 968-1085Key Class:
  • AnalizadorSemantico - Main semantic analyzer
Main Methods:
  • analizar(programa) - Entry point, returns boolean success
  • _analizar_sentencia(sentencia) - Dispatch by statement type
  • _analizar_declaracion(decl) - Handle let statements
  • _analizar_print(stmt) - Handle print statements
  • _analizar_expresion(expr) - Recursive expression validation
Data Structures:
  • variables_declaradas: set - Symbol table
  • errores: List[str] - Error accumulator

Next Steps

IR Generation

See how validated AST is converted to intermediate representation

API Reference

Detailed API documentation for the AnalizadorSemantico class