Previous Up Next

9  Parse

The module is a simple wrapper around the lex/yacc generated parser, exporting a function to parse a file. It’s not intended for usage, it’s more for testing or as a template to use a parser, as the errors are swallowed.

[Parse error] How can one react upon a general parse error? Is the parse-module a serious module at all or rather a test for the parser? To make it usable, mustn’t we let through the exceptions?

[Parse error] Why is My_Parse_error part of the abstract syntax?

Answer:
It cannot be defined within parser.mly, it seems as it is not exported and therefore it cannot be caught outside. Conversely, it cannot be defined in the “wrapper” around the lex and yacc definitions, since it must already be known within the grammar. Therefore I have put it currently into the abstract syntax. It should be reconsideredin the end.
!?
To do:
Check this position-stuff, probably it’s pretty wrong in the meantime. Especially remove the Pos.p_dummy, it’s cheating. Remove the dummy also from assignments, variable declarations, type fields, l-values,
!?
To do:
[Field variable] Is the clause for field variables ok, i.e. can the first part of a x.y only be a simple variable? The abstract syntax allows more general things.

[Operator precedence] It seems that the yacc of Ocaml is more powerful than the one of Java. It can resolve the operator precedeces, even if the operators are combined in separate rules and not “inlined” in the rules for expression.

[Nil and skip] The expression () is not the nil-value, it’s not a value at all. It’s an expression “without” a value (cf. page 516), i.e., of type Unit. We represent it in the abstract syntax as empty sequence.

[S/R] There is a shift/reduce conflict for type declarations and the same one for function declarations.

The reason is that one connected list of type declarations is not separated by anything and since the list of type declarations is itself part of a list of declarations, the parser does not know whether the next phrase starting with the TYPE-keyword belongs to the inner list of type declarations or is the first element of the next list of type declarations. According to the specification, the type declarations belong together until there’s an intervening other declation, i.e., a variable or a function declaration.

A shift-reduce conflict is resolved by shifting. In our case this means that the list of type declarations is extended, as we intend, so the shift-reduce conflict is harmless.

One could make those conflicts go away to introduce some separating tokens between single type declarations but not between general declarations. Likewise one could do it the other way around or to introduce two different kind of separating tokens.

[Parsing l-values] Writing the grammar for l-values straightforwardly, gives a shift-reduce conflict.

expr:
|  lvalue                   
|  vl_expr
|  id  LBRACKET expr RBRACKET   OF expr FO     // array creation
...

vl_expr:
..
| lvalue ASSGN expr              

lvalue:                                      
   id                            
|  lvalue DOT id                 
|  lvalue LBRACKET expr RBRACKET 
; 

Probably this is also the error mentioned at page 82 of [App98b]. The solution is to splice out the clause id LBRACKET expr RBRACKET.

!?
To do:
[Type id] What is type_id on page 513?
!?
To do:
If I remove the FI-clause, I get 25 S/R conflicts! That’s intolerable. So for the time being, I live with the additional FI. A similar remark holds for array creation, which has to be closed by a FO-delimiter, otherwise we get loads of conflicts.

I can parse the following:

let type T1 = int type T2 = int type t3 = int var x := 5 var y := 6 var z : int := z var z : int := 6 type t3 = int type t3 = int var z : int := 6 var z := 6 var diag1 := intArray [n] of 0 fo function f () = 5 function g () = () function g () = 5 type any = {any : int} var buffer := getchar() function g () : int = 5 function g () : int = "dies ist ein string" function g (x:x) = (((5))) type intArray = array of int function g (x:int) = (((5))) function g (x:int,y:int,z:int) = (((5))) function g (x:int,y:int,z:int) : z = let type T = int var z:= 5 in x:= x+1 end function f(v:int) = let var v := 6 in print(v); let var v := 7 in print (v) end; print (v); let var v := 8 in print (v) end; print (v) end function treeLeaves (t: tree) : int = (if t=nil then 1 else treelistLeaves (t.children) fi) var a : my_record := nil var a := nil in x := 6 + 5 + 5; x := 6 + 5 + 5; x := 1 + 2 * 5; x := 1 * 2 + 5; a := nil; if a <> nil then 1 else e fi; if true then 1 else e fi; x := -1; x := a & b; y := a | b | c & d; y := a | b | c; 4 - - 5; - 5 - - - 5; while buffer = 5 do buffer := getchar(); any.any := isdigit(biffer) od end
!?
To do:
The following program gives a “parse” error: Invalid_argument(Array.get)
let x := 0 in nil end
 ,
Previous Up Next