Symbol Table in Compiler Design: Errors, Passes and Worked Examples

Follow one scoped program from symbol-table insertion to type checking and error recovery, then see why a compiler phase is not the same thing as a pass.

KnowledgeGate Team

Exam prep & CS education

Updated 3 Sep 20266 min read

A symbol table is often drawn as if it were one compiler phase. Error handling appears as a box, with no explanation of how analysis continues, while a pass is mistaken for a phase. The governing distinction is simple: a phase is a logical job, a pass is a traversal, while symbol-table management and error handling are shared services used across jobs. One scoped C-like program, carrying a shadowed variable, an undeclared identifier and a forward function call, exercises all three.

1. Place symbol tables, errors and passes on the compiler map

A compact compiler pipeline is:

source characters -> tokens -> syntax tree -> typed tree -> intermediate representation -> optimised IR -> target code

Front-end work analyses the source language. Back-end work constructs target-machine code. Not every compiler splits these jobs into the same physical programs.

The symbol table stores identifier facts that several phases need. The error handler reports invalid input, supports recovery, and limits follow-on messages. A pass reads an entire representation once to analyse or transform it. Several phases can share one pass, while one optimisation phase may need several. Compiler design sits beside operating systems, DBMS and computer networks in CS Fundamentals.

2. What a symbol table stores, with an exact scoped program

Use this program throughout the lookup and typing work:

int g = 5;
int f(int x) {
    int y;
    {
        float x = 2.5;
        y = x + g;
    }
    return y + z;
}

In this toy layout, int and float each occupy 4 bytes. Global and function-local offsets each begin at 0. Parameters use named slots, not a real ABI. The nested block shares f's local sequence, so its x follows y at offset 4.

Scope

Parent

Entries

S0, global

none

g: variable, int, global offset 0, initialiser 5; f: function, int(int)

S1, function f

S0

x: parameter, int, slot P0; y: variable, int, local offset 0

S2, inner block

S1

x: variable, float, local offset 4, initialiser 2.5

Useful fields include name or lexeme, kind, type, scope, storage location, declaration location, and function-parameter signature. This schema is not universal. A hash table with a scope stack is common, but other structures work.

Scope tree with global S0, function scope S1 and inner block S2, showing lookups for y = x + g and a failed search for undeclared z.

3. Work the program through lookup, typing and diagnostics

For y = x + g;, lookup starts in S2. It finds the inner x, whose type is float. It does not find g there or in S1, but finds g:int in S0. The addition converts g to float, so the result type is float. Narrowing in this toy language requires an explicit cast, so assigning that result to y:int produces a semantic diagnostic.

Lookup and type checking do not require evaluation. If later constant propagation is permitted, the illustrative trail is 2.5 + 5 = 7.5.

For return y + z;, lookup finds y in S1, then searches S1 and S0 unsuccessfully for z. It reports undeclared identifier z and gives the failed expression an internal error type. This suppresses extra complaints about y + z and the return type.

The inner x legally shadows parameter x in this toy language because they occupy different scopes. Another int y; directly inside S1 would instead be a same-scope redeclaration.

4. Which stage detects which error

Input

Classification

Reason

int rate = 5 @ 2;

Lexical error

In this C-like language, @ is not in the alphabet.

int rate = ;

Syntax error

The grammar expects an expression after =.

return y + z;

Semantic error

The identifier z has no declaration in a visible scope.

int helper(int); followed by a call but no linked definition

Linker error

The declaration permits checking, but no definition is available during linking.

The earliest root cause controls the classification. A parser may complain after a lexer discards an illegal character, and semantic analysis may receive an error-marked subtree after syntax failure. Those effects do not reclassify the root error. Diagnostic wording varies, so learn the stage and reason, not one tool's message.

5. Error recovery: continue without causing a cascade

A missing semicolon produces this input:

int a = 3
int b = a + 2;
print(b);

After 3, the parser expects ; but sees int. Phrase-level recovery can insert one virtual semicolon, report once, and continue. Analysis then obtains b = 3 + 2 = 5. The compiler adjusts its internal stream, not the source file.

Panic mode differs. In a = (b + ; c = 4;, the parser discards input after the malformed + through the synchronising semicolon, then resumes at c = 4;. Tokens such as ; and } are grammar choices, not universal magic tokens.

Keep the four methods distinct:

  • Panic mode skips input until a synchronising token.

  • Phrase-level recovery inserts, deletes, or replaces a small number of tokens.

  • Error productions encode common mistakes directly in the grammar.

  • Global correction searches for a minimum-edit repair and is usually too costly for routine compilation.

6. Passes explained with a forward-call example

A forward call has this form:

int f() { return g(3); }
int g(int n) { return n + 1; }

In a two-pass teaching compiler, Pass 1 records f: int() at line 1 and g: int(int) at line 2. Pass 2 checks that 3:int matches parameter n:int, then moves to IR, as explored in syntax-directed translation and code optimisation:

L_f: t0 = call L_g, 3; return t0;
L_g: t1 = n + 1; return t1

If executed, n + 1 = 3 + 1 = 4, so g(3) returns 4.

In a one-pass design, g may be unknown at instruction I1. A compiler permitting forward references records I1 on g's unresolved-use list, later binds g to L_g, and patches I1 to call L_g, 3. A language requiring declaration before use can reject it. Pass count is an implementation and language-design choice, not the count of named phases. Repeated optimisation traversals are multiple passes within one phase.

Two-pass diagram for the forward call: Pass 1 records f and g in the symbol table, Pass 2 type-checks and emits IR, giving g(3) = 4.

7. Traps and GATE-style ways these concepts are tested

Avoid these traps: a symbol table stores more than variable values and is not one sequential phase. A pass is not a phase. The parser does not normally decide whether z was declared. Recovery aims to continue analysis, not guarantee an executable program. More passes do not automatically mean a better compiler.

Four checks distinguish the concepts:

  1. Where do identifier attributes belong? In the symbol table.

  2. How do int x = ; and undeclared z differ? The first is syntactic; the second is semantic.

  3. Which x applies inside the nested block? The inner x:float, because nearest-scope lookup wins.

  4. Why can Pass 2 resolve the forward call? Pass 1 has already collected g:int(int).

When comparing parser families, use the focused SLR, CLR and LALR comparison for GATE. For guided practice on symbol tables, error classification and passes, a structured next step is GATE Guidance by Sanchit Sir. In an exam, answer each of these by naming the stage first, then the scope in which the identifier resolves.

8. The short version and a concrete next step

  • Symbol table means shared identifier facts.

  • Error handling means detect, report, recover, and suppress cascades.

  • Pass means one traversal of source or IR.

In the worked examples, x resolves in S2, z is not found, the recovered program computes b = 5, and the two-pass forward call computes g(3) = 4.

Redraw the three scopes and two passes from memory. Then change float x = 2.5 to int x = 2. The new type and value trail is 2 + 5 = 7, which fits y:int without a narrowing diagnostic, although z still fails lookup.

Use the Zero to Hero complete CS course for a broader core-CS learning path. Rebuild the examples, then practise classification and lookup questions.