Work on this exercise locally

This web app is a reference guide — you can read instructions, browse starter code, and view tests here. To actually complete the exercise, you need to work in your local development environment.

1Clone the repo: git clone https://github.com/weihaoqu/program-analysis-bootcamp-student
2Edit the starter file in your editor (VS Code, Vim, etc.) — replace failwith "TODO" with your implementation.
3Run the tests: dune runtest modules/module0-warmup/exercises/calculator-parser

Calculator Parser

7. Exercise 5: Calculator Parser (~25 min)

File: exercises/calculator-parser/starter/main.ml (TODO: printing + eval) File: exercises/calculator-parser/starter/parser.mly (TODO: grammar rules) Run:

dune exec modules/module0-warmup/exercises/calculator-parser/starter/main.exe

What You'll Implement

This exercise has two files to edit:

parser.mly -- add grammar rules:

RuleWhat It ProducesProvided?
expr PLUS exprBinOp(Add, e1, e2)Yes (example)
expr MINUS exprBinOp(Sub, e1, e2)EXERCISE
expr STAR exprBinOp(Mul, e1, e2)EXERCISE
expr SLASH exprBinOp(Div, e1, e2)EXERCISE
atom fallthroughaYes (provided)
INT literalNum nYes (provided)
IDENT variableVar idEXERCISE
LPAREN expr RPARENeEXERCISE
MINUS atom %prec UMINUSNeg aEXERCISE

main.ml -- implement:

FunctionWhat It DoesConcept
string_of_opConverts op to "+"/"-"/"*"/"/"Pattern matching
string_of_exprPretty-prints ASTRecursive pattern matching
evalEvaluates expressionOption + division by zero

Hints

  • The lexer (lexer.mll) is fully provided -- you do not need to edit it.
  • Parser rules follow this pattern:
    | e1 = expr MINUS e2 = expr  { BinOp (Sub, e1, e2) }
    
  • %prec UMINUS tells Menhir to use the UMINUS precedence for unary minus:
    | MINUS a = atom %prec UMINUS  { Neg a }
    
  • In main.ml, the types are defined in ast.ml:
    type op = Add | Sub | Mul | Div
    type expr = Num of int | Var of string | BinOp of op * expr * expr | Neg of expr
    

Expected Output

=== Exercise 5: Calculator Parser ===

Input:  42
AST:    42
Result: 42

Input:  1 + 2
AST:    (1 + 2)
Result: 3

Input:  3 * 4 + 5
AST:    ((3 * 4) + 5)
Result: 17

Input:  (3 + 4) * 5
AST:    ((3 + 4) * 5)
Result: 35

Input:  10 - 3 - 2
AST:    ((10 - 3) - 2)
Result: 5

Input:  -7
AST:    (- 7)
Result: -7

Input:  x + 1
AST:    (x + 1)
Result: <cannot evaluate>

Done!