Yasir Explains/Compiler Design/Syntax Analysis/Error Recovery
Syntax Analysis

Error Recovery

On this page

Why Does Error Recovery Matter?Types of Errors in a CompilerPanic Mode RecoveryPhrase-Level RecoveryError ProductionsGlobal Correction
Syntax Analysis

Error Recovery

Learn how parsers detect syntax errors and recover from them to continue parsing — so the compiler can report multiple errors in one pass rather than stopping at the first one.

Why Does Error Recovery Matter?

When a parser encounters a token it did not expect, it has found a syntax error. The simplest approach is to stop immediately and report the error — but this is bad for the developer.

Imagine compiling a file with 10 syntax errors. A compiler that stops at the first error forces you to fix one error, recompile, find the next error, fix it, recompile... 10 times.

A good compiler detects one error, recovers, and continues parsing to find as many subsequent errors as possible. This way, the developer sees all problems at once.

Example
Bad strategy (stop-on-first-error):
Compile → Error on line 5 → Stop.
Good strategy (error recovery):
Compile → Error on line 5 → Recover → Error on line 12 → Recover → Error on line 27 → Done.
3 errors reported in one pass.

Error recovery is the difference between a frustrating compiler and a helpful one.

Types of Errors in a Compiler

Before looking at recovery strategies, it helps to know what kinds of errors a compiler can encounter:

Error TypePhaseExample
Lexical errorLexerIllegal character @ in code
Syntax errorParserMissing semicolon, unbalanced parenthesis
Semantic errorSemantic analysisUsing undeclared variable
Logical error(Not caught by compiler)Wrong algorithm, off-by-one

The parser handles syntax errors. It knows what token it expected (based on the grammar) and what it actually received — and uses that information to recover.


How the Parser Detects an Error

A parser reports an error when the current input token does not match any valid production for the current grammar rule.

Example
Grammar: stmt → if ( expr ) stmt
Input: if expr ) stmt ← missing opening '('
Parser expected: '('
Parser received: id (the expression)
→ Syntax error: expected '(' after 'if'

Panic Mode Recovery

Panic mode is the simplest and most widely used error recovery strategy. When an error is found, the parser:

  1. Discards input tokens one at a time until it finds a synchronisation token — a token that is likely to start a new valid statement (like ;, }, or a keyword like if, while, return).
  2. Resumes parsing from that synchronisation point.

Example — Panic Mode in Action

Grammar (simplified C-like statements):

Example
stmt → assign_stmt | if_stmt | while_stmt
assign_stmt → id = expr ;

Input with error:

Example
x = + 5 ;
y = 10 ;

What happens:

Example
Parser reads: x = +
→ "+" is not valid as the start of an expression after "="
→ Error reported: unexpected token "+"
Panic mode:
→ Discard "+" and keep reading...
→ Discard "5"...
→ Found ";", a synchronisation token — stop discarding
Parser resumes after ";" and correctly parses: y = 10 ;

Choosing Synchronisation Tokens

The choice of synchronisation tokens is critical:

Language FeatureTypical Synchronisation Tokens
Statement-based (C, Java);, }, {
Block-basedKeywords: end, fi, else
Declaration-basedint, void, class

Good synchronisation tokens are ones that cannot appear inside most expressions — they clearly mark the boundary between statements.


Pros and Cons

AspectDetail
✓ Simple to implementNo complex state tracking needed
✓ Never enters infinite loopAlways makes forward progress
✗ May miss errorsSkipping tokens hides nearby errors
✗ Can skip too muchLarge chunks of valid code may be discarded

Phrase-Level Recovery

Phrase-level recovery is more precise than panic mode. Instead of blindly skipping tokens, the parser makes a local correction — inserting or deleting a single token to make the input valid.


Common Corrections

ProblemCorrection
Missing tokenInsert the expected token into the input stream
Extra tokenDelete the unexpected token
Misspelled keywordReplace the token with the correct one

Example — Inserting a Missing Token

Example
Input: if x > 0 ) ← missing opening '('
Expected: if ( x > 0 )
Phrase-level recovery:
→ Parser detects error: expected '(' after 'if', found 'x'
→ Inserts '(' into the input stream
→ Continues parsing as if the input was: if ( x > 0 )

Example — Deleting an Extra Token

Example
Input: return ; ; ← duplicate semicolon
Expected: return ;
Phrase-level recovery:
→ Parser sees the second ";"
→ Deletes it
→ Continues parsing

Pros and Cons

AspectDetail
✓ PreciseMinimal disruption to the parse
✓ Good error messages"Expected '(' here" is actionable
✗ Can loopInserting the wrong token may cause another error immediately
✗ Harder to implementMust choose corrections carefully

Error Productions

Error productions augment the grammar with special rules that match common mistakes. The grammar explicitly handles known error patterns so the parser can report a useful message and continue.


How It Works

You add extra productions to the grammar of the form:

Example
normal_rule → correct_form
| error_form ← new "error production"

When the parser matches the error form, it reports a specific, targeted error message.


Example — Common Mistake: Exponent Operator

In some languages, beginners confuse ^ (bitwise XOR in C) with the power operator. We can add an error production:

Example
expr → expr + term
| expr - term
| term
term → term * factor
| term / factor
| term ^ factor ← error production for misused '^'
| factor

When the parser sees term ^ factor, it reports:

Example
Error: '^' is bitwise XOR, not exponentiation. Did you mean 'pow(a, b)'?

Example — Missing Operator

Example
expr → expr + term
| expr term ← error production: two adjacent terms, probably missing an operator

Error message: Missing operator between expressions on line 7


Pros and Cons

AspectDetail
✓ Very user-friendlyError messages target specific common mistakes
✓ Compiler can still build a partial treeGood for IDEs
✗ Grammar grows largerMore productions to maintain
✗ Only handles anticipated mistakesDoes not catch unexpected errors

Global Correction

Global correction is the theoretically ideal strategy. Given the erroneous input string, find the minimum number of insertions, deletions, and replacements needed to turn it into a valid string, and report those as the errors.

This is similar to computing the edit distance between two strings.

Example
Erroneous input: int x = + 5
Closest valid: int x = 5 ← one deletion (remove '+')
Edit distance: 1 (delete '+')

Why Global Correction is Rarely Used

ReasonDetail
Very slowComputing the minimum edit is expensive — O(n ·
Not always useful"Minimum edits" may not match the programmer's intent
Complex to implementRequires powerful dynamic programming algorithms

Global correction is mainly a theoretical concept. Real compilers use panic mode or phrase-level recovery because they are fast and good enough in practice.


Summary of Recovery Strategies

StrategyApproachWhen to Use
Panic modeSkip tokens until a sync tokenFast, simple — most common
Phrase-levelInsert or delete a single tokenWhen precise messages are needed
Error productionsAdd grammar rules for common mistakesWhen you know the typical errors
Global correctionFind minimum editsTheoretical; rarely practical