Recently I'm trying to write a compiler for a modified subset of OCaml, through the official documentation I've written a similar grammar given below as what they do to the expressions:(since its a slightly modified version so there will be some differences)
Statement ::= LetDef Statement | ε
LetDef ::= 'let' Definition.
Definition ::= 'rec' LetBinding | LetBinding
LetBinding ::= 'ident' '=' Expr
Constant ::= 'int_literal' | 'float_literal' | 'string_literal' | 'char_literal' | 'bool_literal' | 'unit_literal'
InfixOp ::= '&&' | '||' | '=' | '!=' | '+' | '-' | '*' | '/' | '+.' | '-.' | '*.' | '/.'
Expr ::= Constant
| '(' Expr ')'
| LetDef 'in' Expr
| 'fun' 'ident' '->' Expr
| 'if' Expr 'then' Expr 'else' Expr
| Expr 'as' 'ident'
| Expr ';' Expr
| Expr InfixOp Expr
Apparently, this grammar is neither LL nor any kind of LR. It seems that the last three productions, Expr 'as' 'ident'
, Expr ';' Expr
, and Expr InfixOp Expr
caused this problem, but I don't know how to correctly translate it into a LL(1) grammar(I believe it can be done at all because such structures are common to see in a wide variety of programming languages, including those have claimed themselves are using LL(1) grammar, e.g., Java), I've tried things like left factor elimination and left recursion elimination and resolve first/follow set conflict but the problem still happens, as a beginner at grammar design, I may know where the problem is, but I don't know how to fix it. Suppose that, for now, the precedence of the operators doesn't matter, how could I translate it into a LL(1) grammar correctly?