Building Parsers and Interpreters with BNF

Classified in Computers

Written on in English with a size of 2.67 KB

Understanding Parsers and Abstract Syntax

A Parser is a program that translates terms in concrete syntax into abstract syntax.

  • In our language (PLAI, not Racket), we use {braces} instead of (parentheses) to distinguish concrete syntax from Scheme by looking at the delimiters.
  • The parser identifies the program structure and converts it to the appropriate abstract syntax. This requires a clear specification of the concrete syntax using Backus-Naur Form (BNF).

Arithmetic BNF Specification

<AE> ::= <num>
      | {+ <AE> <AE>}
      | {- <AE> <AE>}
  • The <AE> in BNF is a non-terminal, meaning it can be rewritten as one of the items on the right-hand side.
  • The ::= symbol means “can be rewritten as.”
  • Each | presents an additional choice, called a production.
  • Everything in a production not enclosed in <> is literal syntax.

Implementing a Simple Parser

(define (parse sexp)
  (cond
    [(number? sexp) (num sexp)]
    [(list? sexp)
     (case (first sexp)
       [(+) (add (parse (second sexp)) (parse (third sexp)))]
       [(-) (sub (parse (second sexp)) (parse (third sexp)))])]))

Building an Interpreter

The calc function consumes an AE and computes the corresponding number:

(define (calc an-ae)
  (type-case AE an-ae
    [num (n) n]
    [add (l r) (+ (calc l) (calc r))]
    [sub (l r) (- (calc l) (calc r))]))

Identifiers and WAE

Identifiers are variables. Since our language initially lacks a way to change associated values, we use the term “identifier.”

WAE stands for “with arithmetic expressions.” Its BNF is:

<WAE> ::= <num>
        | {+ <WAE> <WAE>}
        | {- <WAE> <WAE>}
        | {with {<id> <WAE>} <WAE>}
  • We added rules for associating values with identifiers and using them. The <id> non-terminal represents a sequence of alphanumeric characters.

WAE Data Definition

(define-type WAE
  [num (n number?)]
  [add (lhs WAE?) (rhs WAE?)]
  [sub (lhs WAE?) (rhs WAE?)]
  [with (name symbol?) (named-expr WAE?) (body WAE?)]
  [id (name symbol?)])

The with construct functions like passing an argument into a function (e.g., f(x) = x+x, f(2) = 4):

{with {x 5} {+ x x}} becomes {with {x 5} {+ 5 5}} after substitution.

Related entries: