Search code examples
parsingocamlmenhir

Using OCaml Menhir, is there a way to access something before it is processed?


I am writing a parser to parse and compute function derivatives in a calculator.

I got a problem with implementing product and quotient rules : for a product the derivation formula is (u*v)' = u'v+uv', thus I need the value of u and u' in the final output. And with the parser I currently have, whenever comes the need to write u, it has already been replaced by u' and I quite don't know how to save its value, nor if it's even possible...

Here's the parser :

%token <string> VAR FUNCTION CONST
%token LEFT_B RIGHT_B PLUS MINUS TIMES DIV
%token DERIV
%token EOL

%start<string> main

%%

main:
t = toDeriv; EOL {t}
;

toDeriv:
DERIV; LEFT_B; e = expr; RIGHT_B {e}
;

expr:
u = expr; PLUS v = hat_funct {u^"+"^v}
  | u = expr; MINUS; v = hat_funct {u^"-"^v}
  | u = hat_funct {u}
;

hat_funct:
u = hat_funct TIMES v = funct {Printf.sprintf "%s * %s + %s * %s" u (A way to save v) v (A way to save u)}
  | u = hat_funct DIV v = funct {Printf.sprintf "(%s * %s - %s * %s)/%s^2" u (A way to save v) (A way to save u) v (A way to save v)}
  | u = funct {u}
;

funct:
f = func; LEFT_B; c = content; RIGHT_B {Derivatives.deriv_func f c}
;

content:
e = expr {e}
  | x = VAR {x}
  | k = CONST {k}

func:
f = FUNCTION {f}
  | k = CONST {k}
;

P.S : I know it might not be the greatest grammar definition at all, it's still a work in progress


Solution

  • Answering directly your question, yes you can maintain the state of what is being already processed. But that is not how things are done. The idiomatic solution is to write a parser that parses the input language into the abstract syntax tree and then write a solver that will take this tree as input and computes it. You shouldn't do anything in the parser, this is a simple automaton which shall not have any side-effects.

    To keep it less abstract, what you want from the parser is the function string -> expr, where expr type is defined something like

    type expr = 
      | Var of string
      | Const of string 
      | Binop of binop * expr * expr
    and binop = Add | Mul | Sub | Div