Syntactic SpecificationsΒΆ

We use Extended BNF, with [ and ] for zero or once, and { and } for any number of repetition including zero.

program =
    exp
  | decs
  ;


exp =
  (* Literals. *)
    "nil"
  | integer
  | string

  (* Array and record creations. *)
  | type-id "[" exp "]" "of" exp
  | type-id "{" [ id "=" exp { "," id "=" exp } ] "}"

  (* Object creation. *)
  | "new" type-id

  (* Variables, field, elements of an array. *)
  | lvalue

  (* Function call. *)
  | id "(" [ exp { "," exp }] ")"

  (* Method call. *)
  | lvalue "." id "(" [ exp { "," exp }] ")"

  (* Operations. *)
  | "-" exp
  | exp op exp
  | "(" exps ")"

  (* Assignment. *)
  | lvalue ":=" exp

  (* Control structures. *)
  | "if" exp "then" exp ["else" exp]
  | "while" exp "do" exp
  | "for" id ":=" exp "to" exp "do" exp
  | "break"
  | "let" decs "in" exps "end"
  ;


lvalue = id
  | lvalue "." id
  | lvalue "[" exp "]"
  ;
exps = [ exp { ";" exp } ] ;


decs = { dec } ;
dec =
  (* Type declaration. *)
    "type" id "=" ty
  (* Class definition (alternative form). *)
  | "class" id [ "extends" type-id ] "{" classfields "}"
  (* Variable declaration. *)
  | vardec
  (* Function declaration. *)
  | "function" id "(" tyfields ")" [ ":" type-id ] "=" exp
  (* Primitive declaration. *)
  | "primitive" id "(" tyfields ")" [ ":" type-id ]
  (* Importing a set of declarations. *)
  | "import" string
  ;


vardec = "var" id [ ":" type-id ] ":=" exp ;


classfields = { classfield } ;
(* Class fields. *)
classfield =
  (* Attribute declaration. *)
    vardec
  (* Method declaration. *)
  | "method" id "(" tyfields ")" [ ":" type-id ] "=" exp
  ;


(* Types. *)
ty =
   (* Type alias. *)
     type-id
   (* Record type definition. *)
   | "{" tyfields  "}"
   (* Array type definition. *)
   | "array" "of" type-id
   (* Class definition (canonical form). *)
   | "class" [ "extends" type-id ] "{" classfields "}"
   ;
tyfields = [ id ":" type-id { "," id ":" type-id } ] ;
type-id = id ;


op = "+" | "-" | "*" | "/" | "=" | "<>" | ">" | "<" | ">=" | "<=" | "&" | "|" ;

Precedence of the op operators from high to low:

* /
+ -
>= <= = <> < >
&
|

Comparison operators (<, <=, =, <>, > and >=) are not associative. All the remaining operators are left-associative.

Warning

If you use the exp op exp and op rules as such, Bison will not be able to solve shift/reduce conflicts between operators using their precedences.

This is fixed by expliciting the rule exp op exp for each operator. For example with +, -, * and /, the grammar could look like the following:

exp =
  (* Previous rules ... *)

  (* Operations. *)
  | "-" exp
  | exp "+" exp
  | exp "-" exp
  | exp "*" exp
  | exp "/" exp
  | "(" exps ")"

  (* Next rules ... *)