On Oct 30, 2007, at 9:18 AM, Oliver Bandel wrote: > Zitat von Angela Zhu : > >> Hi all, >> >> I have some problem with precedence declaration in OCaml parser. >> If I what to say exponential(ATOB) is prior to *(STAR) and / >> (DIVIDE), >> * and / are prior to +(PLUS) and -(MINUS), >> I wrote the following in the parser: >> >> >> /***** Precedence Rules *****/ >> ... >> %left PLUS MINUS >> %left STAR DIVIDE >> %left ATOB >> ... >> >> But I still have the following problems: >> (1) It appears that the parser >> reads "test = 2^2 + 7;" as "test = 2^9" instead of "test = 4+7", >> which >> would follow the conventional order of operations. >> >> (2)It also interprets "test = (1^2)/3 + 1;" as "test = (1 ^ 2 >> / (3 + 1));" >> >> Can any one help me to see why it happens? Why the precedence rules >> doesn't work? > [...] > > Precedences also can be created by sophisticated > organization of the grammar rules. But I want to avoid this. > > So, if your grammar rules may have a contradictory > meaning, then your parser works not as expected. > > In general I would use the precedence-declarations only, > when you run into parser conflicts, if you don't use them. > When developing a grammr, I would recommend, first to start > with the grammar rules, and add precedence-/associatitivity- > declarations, at the end, if really necessary. > > > What is the rest of your mly-file? > > A complete example would be helpful. Here is part of my .mly file: Beside the precedence issue, everything works fine. %{ open Past open Parsing open ParseError let pi = 4.0 *. atan 1.0;; let get_range n = { pos_start = Parsing.rhs_start_pos n; pos_end = Parsing.rhs_end_pos n; } let unclosed opening_name opening_num closing_name closing_num = raise(Error(Unclosed(get_range opening_num, opening_name, get_range closing_num, closing_name))) %} /* List of all tokens the lexer can output */ ... %token PLUS %token STAR %token MINUS %token DIVIDE %token AND %token OR ... %token ATOB /* A^B: exponential */ ... /***** Precedence Rules *****/ %left PLUS MINUS %left STAR DIVIDE %left ATOB %nonassoc prec_unary_minus %start prog %type prog %% /* Rules for parsing. The parsing rules should generally be in a */ /* one-to-one correspondence with the BNF */ /* type prog = Prog of consDeclare list * varDeclare list * inpDeclare list * sysDeclare list */ prog: exp: LPAREN exp RPAREN { $2 } | LPAREN exp error { unclosed "(" 1 ")" 3 } | exp PLUS exp { Add($1, $3) } | MINUS exp { Sub(Value(VFloat(0.0)), $2) } | exp MINUS exp { Sub($1, $3) } | exp DIVIDE exp { Divide($1, $3) } | exp STAR exp { Mult($1, $3) } | exp ATOB exp { Atob($1, $3) } | value PLUS exp { Add(Value($1), $3) } | value MINUS exp { Sub(Value($1), $3) } | value DIVIDE exp { Divide(Value($1), $3) } | value STAR exp { Mult(Value($1), $3) } | value ATOB exp { Atob(Value($1), $3) } ... | IDENT { Id($1) } | value { Value($1) } ; ...