1 /**************************************************************************/
5 /* François Pottier, INRIA Rocquencourt */
6 /* Yann Régis-Gianas, PPS, Université Paris Diderot */
8 /* Copyright 2005-2008 Institut National de Recherche en Informatique */
9 /* et en Automatique. All rights reserved. This file is distributed */
10 /* under the terms of the Q Public License version 1.0, with the change */
11 /* described in file LICENSE. */
13 /**************************************************************************/
15 /* This is the crude version of the parser. It is meant to be processed
16 by ocamlyacc. Its existence is necessary for bootstrapping. It is kept
17 in sync with [fancy-parser]. The two parsers accept the same language,
18 but [fancy-parser] performs more refined error recovery. */
29 %token TOKEN TYPE LEFT RIGHT NONASSOC START PREC PUBLIC COLON BAR EOF EQUAL
30 %token INLINE LPAREN RPAREN COMMA QUESTION STAR PLUS PARAMETER
31 %token <string Positions.located> LID UID
32 %token <Stretch.t> HEADER
33 %token <Stretch.ocamltype> OCAMLTYPE
34 %token <string Lazy.t> PERCENTPERCENT
35 %token <Syntax.action> ACTION
37 %type <ConcreteSyntax.grammar> grammar
39 /* These declarations solve a shift-reduce conflict in favor of
40 shifting: when the declaration of a non-terminal symbol begins with
41 a leading bar, it is understood as an (insignificant) leading
42 optional bar, *not* as an empty right-hand side followed by a bar.
43 This ambiguity arises due to the existence of a new notation for
44 letting several productions share a single semantic action. */
46 %nonassoc no_optional_bar
51 /* ------------------------------------------------------------------------- */
52 /* A grammar consists of declarations and rules, followed by an optional
53 trailer, which we do not parse. */
56 declarations PERCENTPERCENT rules trailer
59 pg_filename = ""; (* filled in by the caller *)
60 pg_declarations = List.rev $1;
69 | PERCENTPERCENT /* followed by actual trailer */
70 { Some (Lazy.force $1) }
72 /* ------------------------------------------------------------------------- */
73 /* A declaration is an %{ Objective Caml header %}, or a %token, %start,
74 %type, %left, %right, or %nonassoc declaration. */
79 | declarations declaration
83 | HEADER /* lexically delimited by %{ ... %} */
84 { [ unknown_pos (DCode $1) ] }
86 | TOKEN optional_ocamltype terminals
87 { List.map (Positions.map (fun terminal -> DToken ($2, terminal))) $3 }
90 { List.map (Positions.map (fun nonterminal -> DStart nonterminal)) $2 }
92 | TYPE OCAMLTYPE actual_parameters
93 { List.map (Positions.map (fun nt -> DType ($2, nt)))
94 (List.map Parameters.with_pos $3) }
96 | START OCAMLTYPE nonterminals
97 /* %start <ocamltype> foo is syntactic sugar for %start foo %type <ocamltype> foo */
98 { Misc.mapd (fun ntloc ->
99 Positions.mapd (fun nt -> DStart nt, DType ($2, ParameterVar ntloc)) ntloc) $3 }
101 | priority_keyword symbols
102 { let prec = ParserAux.current_token_precedence (rhs_start_pos 1) (rhs_end_pos 1) in
103 List.map (Positions.map (fun symbol -> DTokenProperties (symbol, $1, prec))) $2 }
105 | PARAMETER OCAMLTYPE
106 { [ unknown_pos (DParameter $2) ] }
111 | OCAMLTYPE /* lexically delimited by angle brackets */
122 /* ------------------------------------------------------------------------- */
123 /* A symbol is a terminal or nonterminal symbol. One would like to
124 require nonterminal symbols to begin with a lowercase letter, so as
125 to lexically distinguish them from terminal symbols, which must
126 begin with an uppercase letter. However, for compatibility with
127 ocamlyacc, this is impossible. It can be required only for
128 nonterminal symbols that are also start symbols. */
133 | symbols optional_comma symbol
148 /* ------------------------------------------------------------------------- */
149 /* Terminals must begin with an uppercase letter. Nonterminals that are
150 declared to be start symbols must begin with a lowercase letter. */
155 | terminals optional_comma UID
164 /* ------------------------------------------------------------------------- */
165 /* A rule defines a symbol. It is optionally declared %public, and optionally
166 carries a number of formal parameters. The right-hand side of the definition
167 consists of a list of production groups. */
178 optional_formal_parameters
180 production_group production_groups
182 let public, inline = $1 in
183 { pr_public_flag = public;
184 pr_inline_flag = inline;
185 pr_nt = Positions.value $2;
186 pr_positions = [ Positions.position $2 ];
188 pr_branches = List.flatten ($6 :: List.rev $7)
204 /* ------------------------------------------------------------------------- */
205 /* Parameters are surroundered with parentheses and delimited by commas.
206 The syntax of actual parameters allows applications, whereas the syntax
207 of formal parameters does not. It also allows use of the "?", "+", and
210 optional_formal_parameters:
213 | LPAREN formal_parameters RPAREN
218 { [ Positions.value $1 ] }
219 | symbol COMMA formal_parameters
220 { Positions.value $1 :: $3 }
222 optional_actual_parameters:
225 | LPAREN actual_parameters_comma RPAREN
228 actual_parameters_comma:
231 | actual_parameter COMMA actual_parameters_comma
235 symbol optional_actual_parameters optional_modifier
236 { Parameters.oapp1 $3 (Parameters.app $1 $2) }
241 | actual_parameters optional_comma actual_parameter
245 /* epsilon */ %prec no_optional_bar
250 /* ------------------------------------------------------------------------- */
251 /* The "?", "+", and "*" modifiers are short-hands for applications of
252 certain parameterized nonterminals, defined in the standard library. */
262 { unknown_pos "option" }
264 { unknown_pos "nonempty_list" }
266 { unknown_pos "list" }
268 /* ------------------------------------------------------------------------- */
269 /* A production group consists of a list of productions, followed by a
270 semantic action and an optional precedence specification. */
275 | production_groups BAR production_group
279 productions ACTION /* action is lexically delimited by braces */ optional_precedence
281 let productions, action, oprec2 = $1, $2, $3 in
283 ParserAux.check_production_group
285 (rhs_start_pos 2) (rhs_end_pos 2) action;
287 List.map (fun (producers, oprec1, rprec, pos) -> {
288 pr_producers = producers;
290 pr_branch_shift_precedence = ParserAux.override pos oprec1 oprec2;
291 pr_branch_reduce_precedence = rprec;
292 pr_branch_position = pos
302 /* ------------------------------------------------------------------------- */
303 /* A production is a list of producers, optionally followed by a
304 precedence declaration. Lists of productions are nonempty and
305 separated with bars. */
310 | production bar_productions
316 | BAR production bar_productions
320 producers optional_precedence
323 ParserAux.current_reduce_precedence(),
324 Positions.lex_join (symbol_start_pos()) (symbol_end_pos())
333 /* ------------------------------------------------------------------------- */
334 /* A producer is an actual parameter, possibly preceded by a
340 | LID EQUAL actual_parameter