Back to the 2023 paper

Module 3: Semantic Analysis, Symbol Table, Run-time environment

20237m

Explain how type checking and error reporting are performed in compiler. Draw syntax tree and DAG for the statement:
a=(a∗b+c)↑(b+c)∗b+ca = (a * b + c) \uparrow (b + c) * b + c

Worked SolutionAI Assisted

Type checking, error reporting, and the syntax tree / DAG for
a=(a∗b+c)↑(b+c)∗b+ca = (a*b + c) \uparrow (b+c)*b + c

Part 1 — Type checking

  • Type checking verifies each operator's operands have the expected type and computes/infers the result type while traversing the syntax tree.
  • It is typically performed in the semantic-analysis phase using a syntax-directed definition where each expression node carries a synthesized type attribute, e.g. TE=f(TE1,TT)T_E = f(T_{E_1}, T_T) for E→E1+TE \to E_1+T.
  • Type synthesis: int + int → int, float op … → float; conversions (e.g. int → float) may be inserted automatically as a unary node inttofloat (type coercion).
  • Checking can be static (compile time) or dynamic (run time).

Part 2 — Error reporting

  • Each phase reports its errors to a central error handler: lexical (illegal token), syntactic (parse errors, e.g. mismatched brackets), semantic (type mismatch, undeclared/unused variable).
  • The parser uses error-recovery strategies (panic mode, error productions, phrase-level recovery) so it can report more than one syntax error in a single run.
  • Semantic errors are reported with line number, offending token, and message; code generation is attempted only when there are no fatal errors.

Part 3 — Syntax tree for the statement

a = (a*b + c) ↑ (b + c)*b + c

Precedence order: ↑ > * > +. So the RHS reads as:

(a∗b+c) ↑ ((b+c)∗b) + c(a*b + c)\ \uparrow\ ((b+c)*b)\ +\ c

Syntax tree (AST):

                  =
                 / \
                a   +
                   / \
                ↑     c
               / \
        (a*b + c)  ( (b+c) * b )
          /   \         /  \
      (a*b)  + c     (b+c)  b
      / \           /  \
     a   b         b    c

 Equivalently, using operator-labelled nodes:

                  =
                 / \
                a   +
                   / \
             (↑)      c
             /   \
          (a*b+c)   * (mul)
             |        / \
          (a*b)+c    (b+c)  b
          /  \      / \
        (a*b) c   b   c
        /   \
       a     b

DAG (Directed Acyclic Graph)

In the DAG, each unique subexpression appears exactly once; repeated uses share the same node.

The statement contains these distinct nodes (reading bottom-up):

  1. a*b — node * with leaves (a, b)
  2. (a*b)+c — node + over (1) and leaf c
  3. b+c — node + with leaves (b, c)
  4. (b+c)*b — node * over (3) and leaf b
  5. ↑ — node ↑ over (2) and (4)
  6. RHS + c — node + over (5) and leaf c
  7. a = RHS — node = with leaves (a, 6)
                =
               / \
              a   +                     ← (6)
                 / \
              ↑     c
             / \
        (a*b)+c   (b+c)*b               ← nodes (2), (4)
          / \         / \
       (a*b) c     (b+c) b              ← nodes (1), (3)
        / \          / \
       a   b        b   c

Note the leaf b and c are each single nodes shared by all their uses (this is what makes it a DAG rather than a tree).

Similar questions

Official AppAndroid App

PYQDeck for Android

Solve BEU previous-year exam papers anywhere, anytime. Fast search, offline paper viewing, and step-by-step solutions designed specifically for your phone.