• ↑↓ pour naviguer
  • pour ouvrir
  • pour sélectionner
  • ⌘ ⌥ ↵ pour ouvrir dans un panneau
  • ←→ pour naviguer
  • esc pour rejeter
⌘ '
raccourcis clavier

The Problem

Bottom-up parsers (LR) are powerful but complex to implement manually. For many programming languages, a simpler parsing strategy suffices — one that can be implemented by hand as a set of recursive functions without needing a parser generator.

Core Idea

Top-down parsing builds the parse tree from the root (start symbol) down to the leaves (tokens). At each step, the parser predicts which production to apply based on the current input token. Recursive descent parsers use mutually recursive functions for each non-terminal. Predictive (LL) parsers use a parsing table built from FIRST and FOLLOW sets.

How It Works

The parser starts with the start symbol. For each non-terminal, it looks at the current input token and chooses the production whose FIRST set contains that token. If a production can derive ε, the parser may take that branch when the current token is in the FOLLOW set. In recursive descent, each non-terminal becomes a function that calls other non-terminal functions.

Visual Explanation

top_down Start Start Symbol Choice1 Predict: E → T E' Start->Choice1 Token1 Token: id Token2 Token: + Token3 Token: id Choice2 Predict: T → id Choice1->Choice2 Choice3 Match: id Choice2->Choice3 Choice4 Predict: E' → + T E' Choice3->Choice4 Choice5 Match: + Choice4->Choice5

Key Properties

  • Direction of tree building: Root → leaves (top-down)
  • Derivation type: Leftmost derivation
  • Types: Recursive descent (manual), LL(1) (table-driven), LL(k) (k lookahead)
  • Requirements: Grammar must not be left-recursive; may need left-factoring
  • Implementation: Recursive descent is the most common hand-written parsing technique

Connections

Edge Cases & Gotchas

  • Left recursion: Top-down parsers loop infinitely on A → Aα — must be eliminated before parsing
  • Left factoring: Common prefixes in alternatives cause FIRST conflicts — factored out to create A → αB where B → β₁ | β₂
  • LL(1) limitation: Not all languages can be parsed with LL(1) — some require LL(k) or LR parsing
  • Backtracking: Naive recursive descent with backtracking has exponential worst-case time; predictive parsing avoids this