grew_parser.mly 35.8 KB
Newer Older
bguillaum's avatar
bguillaum committed
1 2 3
(**********************************************************************************)
(*    Libcaml-grew - a Graph Rewriting library dedicated to NLP applications      *)
(*                                                                                *)
Bruno Guillaume's avatar
Bruno Guillaume committed
4
(*    Copyright 2011-2018 Inria, Université de Lorraine                           *)
bguillaum's avatar
bguillaum committed
5
(*                                                                                *)
Bruno Guillaume's avatar
Bruno Guillaume committed
6
(*    Webpage: http://grew.fr                                                     *)
bguillaum's avatar
bguillaum committed
7 8 9
(*    License: CeCILL (see LICENSE folder or "http://www.cecill.info")            *)
(*    Authors: see AUTHORS file                                                   *)
(**********************************************************************************)
10

bguillaum's avatar
bguillaum committed
11
%{
bguillaum's avatar
bguillaum committed
12
open Grew_base
bguillaum's avatar
bguillaum committed
13
open Grew_types
bguillaum's avatar
bguillaum committed
14
open Grew_ast
pj2m's avatar
pj2m committed
15

16
(* Some intermediate sum types used in sub-functions when building the ast *)
17
type pat_item =
bguillaum's avatar
bguillaum committed
18 19 20
  | Pat_node of Ast.node
  | Pat_edge of Ast.edge
  | Pat_const of Ast.const
pj2m's avatar
pj2m committed
21 22

type graph_item =
23
  | Graph_meta of string
bguillaum's avatar
bguillaum committed
24 25
  | Graph_node of Ast.node
  | Graph_edge of Ast.edge
pj2m's avatar
pj2m committed
26

bguillaum's avatar
bguillaum committed
27
type ineq_item =
28
  | Ineq_sofi of Ast.simple_or_pointed
bguillaum's avatar
bguillaum committed
29 30
  | Ineq_float of float

Bruno Guillaume's avatar
Bruno Guillaume committed
31
let get_loc () = Global.get_loc ()
pj2m's avatar
pj2m committed
32 33 34
let localize t = (t,get_loc ())
%}

35 36
%token DUMMY

37 38 39 40 41 42 43
%token LACC                        /* { */
%token RACC                        /* } */
%token LBRACKET                    /* [ */
%token RBRACKET                    /* ] */
%token LPAREN                      /* ( */
%token RPAREN                      /* ) */
%token DDOT                        /* : */
44
%token COMMA                       /* , */
45
%token SEMIC                       /* ; */
bguillaum's avatar
bguillaum committed
46
%token SHARP                       /* # */
bguillaum's avatar
bguillaum committed
47
%token PLUS                        /* + */
48 49
%token EQUAL                       /* = */
%token DISEQUAL                    /* <> */
bguillaum's avatar
bguillaum committed
50
%token BANG                        /* ! */
Bruno Guillaume's avatar
Bruno Guillaume committed
51
%token SLASH                       /* / */
52
%token STAR                        /* * */
bguillaum's avatar
bguillaum committed
53 54 55 56
%token LT                          /* < */
%token GT                          /* > */
%token LE                          /* <= or  */
%token GE                          /* >= or  */
bguillaum's avatar
bguillaum committed
57 58
%token LPREC                       /* << */
%token LSUCC                       /* >> */
bguillaum's avatar
bguillaum committed
59

bguillaum's avatar
bguillaum committed
60 61 62
%token BEFORE                      /* :< */
%token AFTER                       /* :> */

63
%token PIPE                        /* | */
64

65
%token EDGE                        /* -> */
66 67 68
%token LTR_EDGE_LEFT               /* -[ */
%token LTR_EDGE_LEFT_NEG           /* -[^ */
%token LTR_EDGE_RIGHT              /* ]-> */
69 70 71 72 73

%token ARROW                       /* ==> */
%token ARROW_LEFT                  /* =[ */
%token ARROW_LEFT_NEG              /* =[^ */
%token ARROW_RIGHT                 /* ]=> */
74

bguillaum's avatar
bguillaum committed
75
%token INCL                        /* include */
76
%token IMPORT                      /* import */
77
%token FEATURES                    /* features */
Bruno Guillaume's avatar
Bruno Guillaume committed
78
%token FROM                        /* from */
79
%token LABELS                      /* labels */
80
%token PATTERN                     /* pattern */
81 82
%token WITHOUT                     /* without */
%token COMMANDS                    /* commands */
Bruno Guillaume's avatar
Bruno Guillaume committed
83
%token GLOBAL                      /* global */
84 85
%token STRAT                       /* strat */
%token PACKAGE                     /* package */
86 87 88 89 90
%token RULE                        /* rule */
%token GRAPH                       /* graph */

%token DEL_EDGE                    /* del_edge */
%token ADD_EDGE                    /* add_edge */
91 92
%token SHIFT_IN                    /* shift_in */
%token SHIFT_OUT                   /* shift_out */
93 94 95 96 97
%token SHIFT                       /* shift */
%token DEL_NODE                    /* del_node */
%token ADD_NODE                    /* add_node */
%token DEL_FEAT                    /* del_feat */

98 99 100 101 102
%token PICK                        /* Pick */
%token ALT                         /* Alt */
%token SEQ                         /* Seq */
%token ITER                        /* Iter */
%token IF                          /* If */
Bruno Guillaume's avatar
Bruno Guillaume committed
103
%token ONF                         /* Onf */
104 105
%token EMPTY                       /* Empty */
%token TRY                         /* Try */
106

107 108
%token <string> AROBAS_ID          /* @id */
%token <string> COLOR              /* @#89abCD */
bguillaum's avatar
bguillaum committed
109

110 111 112
%token <string> ID   /* the general notion of id */

/* %token <Grew_ast.Ast.complex_id>   COMPLEX_ID*/
113

114 115 116 117
%token <string>                STRING
%token <string>                REGEXP
%token <float>                 FLOAT
%token <string list>           COMMENT
Bruno Guillaume's avatar
Bruno Guillaume committed
118
%token <string * (int *string) list>  LEX_PAR
pj2m's avatar
pj2m committed
119

120
%token EOF                         /* end of file */
pj2m's avatar
pj2m committed
121

bguillaum's avatar
bguillaum committed
122
%start <Grew_ast.Ast.gr> gr
123
%start <Grew_ast.Ast.pattern> pattern
124
%start <Grew_ast.Ast.domain> domain
125

Bruno Guillaume's avatar
Bruno Guillaume committed
126
%start <Grew_ast.Ast.grs> grs
Bruno Guillaume's avatar
Bruno Guillaume committed
127
%start <Grew_ast.Ast.strat> strat_alone
128

129 130
/* parsing of the string representation of the constituent representation of Sequoia */
/* EX: "( (SENT (NP (NC Amélioration) (PP (P de) (NP (DET la) (NC sécurité))))))"    */
131
%start <Grew_ast.Ast.pst> phrase_structure_tree
132

pj2m's avatar
pj2m committed
133 134
%%

bguillaum's avatar
bguillaum committed
135 136 137
%public separated_list_final_opt(separator,X):
|                                                               { [] }
|   x=X                                                         { [x] }
138
|   x=X; separator; xs=separated_list_final_opt(separator,X)    { x :: xs }
bguillaum's avatar
bguillaum committed
139 140 141 142

%public separated_nonempty_list_final_opt(separator,X):
|   x=X                                                                  { [x] }
|   x=X; separator                                                       { [x] }
143
|   x=X; separator; xs=separated_nonempty_list_final_opt(separator,X)    { x :: xs }
144

pj2m's avatar
pj2m committed
145
/*=============================================================================================*/
146
/*  BASIC DEFINITIONS                                                                          */
pj2m's avatar
pj2m committed
147
/*=============================================================================================*/
148

149
label_ident:
150
        | x=ID        { Ast.parse_label_ident x }
151
        | s=STRING    { s }
152

bguillaum's avatar
bguillaum committed
153
simple_id:
154
        | id=ID       { Ast.parse_simple_ident id }
bguillaum's avatar
bguillaum committed
155

156
simple_id_with_loc:
157 158
        | id=ID       { localize (Ast.parse_simple_ident id) }

159 160 161 162
simple_id_or_float:
        | id=ID       { Ast.parse_simple_ident id }
        | v=FLOAT     { Printf.sprintf "%g" v }

163 164 165 166 167 168
node_id:
        | id=ID       { Ast.parse_node_ident id }

node_id_with_loc:
        | id=ID       { localize (Ast.parse_node_ident id) }

169 170
feature_ident :
        | id=ID       { Ast.parse_feature_ident id }
bguillaum's avatar
bguillaum committed
171

172 173
feature_ident_with_loc :
        | id=ID      { localize (Ast.parse_feature_ident id) }
174

175
feature_value:
176
        | v=ID        { Ast.parse_simple_ident v }
177 178
        | v=STRING    { v }
        | v=FLOAT     { Printf.sprintf "%g" v }
pj2m's avatar
pj2m committed
179

180 181 182 183 184
pattern_feature_value:
        | v=ID        { Ast.parse_simple_or_pointed v }
        | v=STRING    { Ast.Simple v }
        | v=FLOAT     { Ast.Simple (Printf.sprintf "%g" v) }

bguillaum's avatar
bguillaum committed
185
ineq_value:
186
        | v=ID    { Ineq_sofi (Ast.parse_simple_or_pointed v) }
bguillaum's avatar
bguillaum committed
187 188 189
        | v=FLOAT { Ineq_float v }

ineq_value_with_loc:
190
        | v=ID    { localize (Ineq_sofi (Ast.parse_simple_or_pointed v)) }
bguillaum's avatar
bguillaum committed
191 192
        | v=FLOAT { localize (Ineq_float v) }

193 194 195
/*=============================================================================================*/
/*  GREW GRAPH                                                                                 */
/*=============================================================================================*/
196 197
gr:
        | GRAPH LACC items=separated_list_final_opt(SEMIC,gr_item) RACC EOF
198
            {
199 200 201 202 203 204
              Ast.complete_graph
              {
                Ast.meta = List_.opt_map (function Graph_meta n -> Some n | _ -> None) items;
                Ast.nodes = List_.opt_map (function Graph_node n -> Some n | _ -> None) items;
                Ast.edges = List_.opt_map (function Graph_edge n -> Some n | _ -> None) items;
              }
205
            }
bguillaum's avatar
bguillaum committed
206

pj2m's avatar
pj2m committed
207
gr_item:
208
        /*  sentence = "Jean dort."   */
209
        | id=simple_id EQUAL value=feature_value
210
            { Graph_meta (id ^ " = " ^ value) }
211

212 213
        /*  B (1) [phon="pense", lemma="penser", cat=v, mood=ind ]   */
        /*  B [phon="pense", lemma="penser", cat=v, mood=ind ]   */
214
        | id_loc=node_id_with_loc position=option(delimited(LPAREN, FLOAT ,RPAREN)) feats=delimited(LBRACKET,separated_list_final_opt(COMMA,node_features),RBRACKET)
bguillaum's avatar
bguillaum committed
215 216
            { let (id,loc) = id_loc in
              Graph_node ({Ast.node_id = id; position=position; fs=feats}, loc) }
217
        /*   A   */
218 219 220
        | id_loc=node_id_with_loc
            { let (id,loc) = id_loc in
              Graph_node ({Ast.node_id = id; position=None; fs=Ast.default_fs ~loc id}, loc) }
pj2m's avatar
pj2m committed
221

222
        /*   A -[x]-> B   */
223
        | n1_loc=node_id_with_loc label=delimited(LTR_EDGE_LEFT,label_ident,LTR_EDGE_RIGHT) n2=node_id
224
            { Graph_edge ({Ast.edge_id = None; src=fst n1_loc; edge_label_cst=Ast.Pos_list [label]; tar=n2}, snd n1_loc) }
pj2m's avatar
pj2m committed
225

226 227 228 229
/*=============================================================================================*/
/*  DOMAIN DEFINITION                                                                          */
/*=============================================================================================*/
domain:
230
        | c=option(DUMMY) f=feature_group g=labels EOF
231 232 233 234 235 236
            {
              {  Ast.feature_domain = f;
                 label_domain = g;
              }
            }

pj2m's avatar
pj2m committed
237 238 239
/*=============================================================================================*/
/* FEATURES DOMAIN DEFINITION                                                                  */
/*=============================================================================================*/
240
feature_group:
241 242
        | FEATURES x=features { x }

243
features:
244
        | LACC x=separated_nonempty_list_final_opt(SEMIC,feature) RACC { x }
bguillaum's avatar
bguillaum committed
245

246
feature:
247 248
        /*   pos=#   */
        /*   m: ind,inf,part,subj,imp   */
249
        | feature_name=feature_name DDOT feature_values=feature_values
bguillaum's avatar
bguillaum committed
250
            {
251
              match feature_values with
252 253
                | ["#"] -> Ast.Num feature_name
                | _ -> Ast.build_closed feature_name feature_values
254
            }
pj2m's avatar
pj2m committed
255

256
        /*   phon:*   */
257
        | feature_name=feature_name DDOT STAR
258
            { Ast.Open feature_name }
259

pj2m's avatar
pj2m committed
260
feature_name:
261
        | ci=ID { to_uname ci }
pj2m's avatar
pj2m committed
262

263
feature_values:
264
        | SHARP                                         { ["#"] }
265
        | x=separated_nonempty_list(COMMA,feature_value) { x }
pj2m's avatar
pj2m committed
266 267 268 269

/*=============================================================================================*/
/* GLOBAL LABELS DEFINITION                                                                    */
/*=============================================================================================*/
270
labels:
271
        /*   labels { OBJ, SUBJ, DE_OBJ, ANT }   */
272
        | LABELS x=delimited(LACC,separated_nonempty_list_final_opt(COMMA,label),RACC) { x }
273

274
label:
275
        | x=label_ident display_list=list(display)  { (x, display_list) }
pj2m's avatar
pj2m committed
276

277
display:
278 279
        | dis=AROBAS_ID   { dis }
        | col=COLOR       { col }
pj2m's avatar
pj2m committed
280 281 282 283

/*=============================================================================================*/
/* RULES DEFINITION                                                                            */
/*=============================================================================================*/
284
rule:
Bruno Guillaume's avatar
Bruno Guillaume committed
285
        | doc=option(COMMENT) RULE id_loc=simple_id_with_loc file_lexicons = option(external_lexicons) LACC p=pos_item n=list(neg_item) cmds=commands RACC final_lexicons=list(final_lexicon)
286
            {
Bruno Guillaume's avatar
Bruno Guillaume committed
287 288 289
              let lexicons = match file_lexicons with
              | Some l -> l @ final_lexicons
              | None -> final_lexicons in
290
              { Ast.rule_id = fst id_loc;
Bruno Guillaume's avatar
Bruno Guillaume committed
291
                pattern = Ast.complete_pattern { Ast.pat_glob = ["TODO"]; Ast.pat_pos = p; Ast.pat_negs = n };
292
                commands = cmds;
Bruno Guillaume's avatar
Bruno Guillaume committed
293
                lexicon_info = lexicons;
bguillaum's avatar
bguillaum committed
294
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
295
                rule_loc = snd id_loc;
296
                rule_dir = None;
bguillaum's avatar
bguillaum committed
297
              }
298
            }
299

Bruno Guillaume's avatar
Bruno Guillaume committed
300
external_lexicons:
301
        | LPAREN external_lexicons= separated_nonempty_list_final_opt(COMMA, external_lexicon) RPAREN       { external_lexicons }
302

Bruno Guillaume's avatar
Bruno Guillaume committed
303 304
external_lexicon:
        | lex_name=simple_id FROM file=STRING { (lex_name, Ast.File file)}
bguillaum's avatar
bguillaum committed
305

Bruno Guillaume's avatar
Bruno Guillaume committed
306 307
final_lexicon:
        | final_lexicon = LEX_PAR  { (fst final_lexicon, Ast.Final (snd final_lexicon)) }
bguillaum's avatar
bguillaum committed
308

Bruno Guillaume's avatar
Bruno Guillaume committed
309 310 311 312 313 314
glob_decl:
        | GLOBAL l=delimited(LACC, separated_list_final_opt(SEMIC,glob_item),RACC) { l }

glob_item:
        | item = ID { item }

pj2m's avatar
pj2m committed
315
pos_item:
316
        | PATTERN i=pn_item   { i }
pj2m's avatar
pj2m committed
317 318

neg_item:
319 320 321 322
        | WITHOUT i=pn_item { i }

pn_item:
        | l=delimited(LACC,separated_list_final_opt(SEMIC,pat_item),RACC)
323 324
            {
             {
bguillaum's avatar
bguillaum committed
325 326 327
              Ast.pat_nodes = List_.opt_map (function Pat_node n -> Some n | _ -> None) l;
              Ast.pat_edges = List_.opt_map (function Pat_edge n -> Some n | _ -> None) l;
              Ast.pat_const = List_.opt_map (function Pat_const n -> Some n | _ -> None) l;
328 329
            }
           }
pj2m's avatar
pj2m committed
330 331

/*=============================================================================================*/
332
/* PATTERN DEFINITION                                                                            */
pj2m's avatar
pj2m committed
333
/*=============================================================================================*/
334 335 336 337 338 339 340

edge_item:
        | id=ID       { Ast.parse_node_ident id }
        | v=FLOAT     { Printf.sprintf "%g" v }

label_atom:
        | name=simple_id_or_float EQUAL l=separated_nonempty_list(PIPE,edge_item) { Ast.Atom_eq (name, l)}
341
        | name=simple_id_or_float EQUAL STAR { Ast.Atom_diseq (name, [])}
342 343 344
        | name=simple_id_or_float DISEQUAL l=separated_nonempty_list(PIPE,edge_item) { Ast.Atom_diseq (name, l)}
        | BANG name=simple_id_or_float { Ast.Atom_absent name }

pj2m's avatar
pj2m committed
345
pat_item:
346 347 348
        /* =================================== */
        /* node                                */
        /* =================================== */
349
        /*   R [cat=V, lemma=$lemma]   */
350
        | id_loc=simple_id_with_loc feats=delimited(LBRACKET,separated_list_final_opt(COMMA,node_features),RBRACKET)
351
            { Pat_node ({Ast.node_id = fst id_loc; position=None; fs= feats}, snd id_loc) }
bguillaum's avatar
bguillaum committed
352

353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
        /* =================================== */
        /* edge                                */
        /* =================================== */
        /*   A -> B   */
        | n1_loc=simple_id_with_loc EDGE n2=simple_id
            { let (n1,loc) = n1_loc in Pat_edge ({Ast.edge_id = None; src=n1; edge_label_cst=Ast.Neg_list []; tar=n2}, loc) }

        /*   A -[X|Y]-> B   */
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,label_ident),LTR_EDGE_RIGHT) n2=simple_id
            { let (n1,loc) = n1_loc in Pat_edge ({Ast.edge_id = None; src=n1; edge_label_cst=Ast.Pos_list labels; tar=n2}, loc) }

        /*   A -[^X|Y]-> B   */
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT_NEG,separated_nonempty_list(PIPE,label_ident),LTR_EDGE_RIGHT) n2=simple_id
            { let (n1,loc) = n1_loc in Pat_edge ({Ast.edge_id = None; src=n1; edge_label_cst=Ast.Neg_list labels; tar=n2}, loc) }

        /*   A -[re"regexp"]-> B   */
        | n1_loc=simple_id_with_loc LTR_EDGE_LEFT re=REGEXP LTR_EDGE_RIGHT n2=simple_id
            { let (n1,loc) = n1_loc in Pat_edge ({Ast.edge_id = None; src=n1; edge_label_cst=Ast.Regexp re; tar=n2}, loc) }

        /*   A -[1=subj, 2]-> B   */
        | n1_loc=simple_id_with_loc LTR_EDGE_LEFT atom_list = separated_nonempty_list(COMMA, label_atom) LTR_EDGE_RIGHT n2=simple_id
            { let (n1,loc) = n1_loc in Pat_edge ({Ast.edge_id = None; src=n1; edge_label_cst=Ast.Atom_list atom_list; tar=n2}, loc) }

        /*   e:A -[1=subj, 2]-> B   */
        | id_loc=simple_id_with_loc DDOT n1=simple_id LTR_EDGE_LEFT atom_list = separated_nonempty_list(COMMA, label_atom) LTR_EDGE_RIGHT n2=simple_id
            { let (id,loc) = id_loc in Pat_edge ({Ast.edge_id = Some id; src=n1; edge_label_cst=Ast.Atom_list atom_list; tar=n2}, loc) }

380
        /*   e: A -> B   */
381
        | id_loc=simple_id_with_loc DDOT n1=simple_id EDGE n2=simple_id
382
            { let (id,loc) = id_loc in Pat_edge ({Ast.edge_id = Some id; src=n1; edge_label_cst=(Ast.Neg_list []); tar=n2}, loc) }
pj2m's avatar
pj2m committed
383

384
        /*   e: A -[X|Y]-> B   */
385
        | id_loc=simple_id_with_loc DDOT n1=simple_id labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,label_ident),LTR_EDGE_RIGHT) n2=simple_id
386
            { let (id,loc) = id_loc in Pat_edge ({Ast.edge_id = Some id; src=n1; edge_label_cst=(Ast.Pos_list labels); tar=n2}, loc) }
pj2m's avatar
pj2m committed
387

388
        /*   e: A -[^X|Y]-> B   */
389
        | id_loc=simple_id_with_loc DDOT n1=simple_id labels=delimited(LTR_EDGE_LEFT_NEG,separated_nonempty_list(PIPE,label_ident),LTR_EDGE_RIGHT) n2=simple_id
390 391
            { let (id,loc) = id_loc in Pat_edge ({Ast.edge_id = Some id; src=n1; edge_label_cst=(Ast.Neg_list labels); tar=n2}, loc) }

392
        /*   e: A -[re"regexp"]-> B   */
393 394
        | id_loc=simple_id_with_loc DDOT n1=simple_id LTR_EDGE_LEFT re=REGEXP LTR_EDGE_RIGHT n2=simple_id
            { let (id,loc) = id_loc in Pat_edge ({Ast.edge_id = Some id; src=n1; edge_label_cst=Ast.Regexp re; tar=n2}, loc) }
395

396 397 398
        /* =================================== */
        /* edge constraints                    */
        /* =================================== */
399

400
        /*   A -[X|Y]-> *   */
401
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,label_ident),LTR_EDGE_RIGHT) STAR
402
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Pos_list labels), loc) }
403

404
        /*   * -[X|Y]-> B   */
405
        | STAR labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,label_ident),LTR_EDGE_RIGHT) n2_loc=simple_id_with_loc
406
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,Ast.Pos_list labels), loc) }
407

408 409 410
        /*   A -> *   */
        | n1_loc=simple_id_with_loc EDGE STAR
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Neg_list []), loc) }
411

412 413 414
        /*   * -> B   */
        | STAR EDGE n2_loc=simple_id_with_loc
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,Ast.Neg_list []), loc) }
415

416
        /*   A -[^X|Y]-> *   */
417
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT_NEG,separated_nonempty_list(PIPE,label_ident),LTR_EDGE_RIGHT) STAR
418
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Neg_list labels), loc) }
419

420
        /*   * -[^X|Y]-> B   */
421
        | STAR labels=delimited(LTR_EDGE_LEFT_NEG,separated_nonempty_list(PIPE,label_ident),LTR_EDGE_RIGHT) n2_loc=simple_id_with_loc
422
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,Ast.Neg_list labels), loc) }
pj2m's avatar
pj2m committed
423

424 425 426 427
        /* =================================== */
        /* other constraints                   */
        /* =================================== */

428
        /*   X.cat = Y.cat   */
Bruno Guillaume's avatar
Bruno Guillaume committed
429
        /*   X.cat = value   */
430
        /*   X.cat = lex.value   */
bguillaum's avatar
bguillaum committed
431
        | feat_id1_loc=feature_ident_with_loc EQUAL rhs=ID
432 433 434 435 436
             { let (feat_id1,loc)=feat_id1_loc in
              match Ast.parse_simple_or_pointed rhs with
              | Ast.Simple value ->
                Pat_const (Ast.Feature_eq_cst (feat_id1, value), loc)
              | Ast.Pointed (s1, s2) ->
437
                Pat_const (Ast.Feature_eq_lex_or_fs (feat_id1, (s1, to_uname s2)), loc)
438
             }
bguillaum's avatar
bguillaum committed
439

440
        /*   X.cat = "value"   */
bguillaum's avatar
bguillaum committed
441
        | feat_id1_loc=feature_ident_with_loc EQUAL rhs=STRING
442
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_eq_cst (feat_id1, rhs), loc) }
bguillaum's avatar
bguillaum committed
443

444
        /*   X.cat = 12.34   */
bguillaum's avatar
bguillaum committed
445
        | feat_id1_loc=feature_ident_with_loc EQUAL rhs=FLOAT
446
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_eq_float (feat_id1, rhs), loc) }
bguillaum's avatar
bguillaum committed
447

448 449
        /*   X.cat <> Y.cat   */
        /*   X.cat <> value   */
450
        /*   X.cat <> lex.value   */
bguillaum's avatar
bguillaum committed
451
        | feat_id1_loc=feature_ident_with_loc DISEQUAL rhs=ID
452 453 454 455 456
             { let (feat_id1,loc)=feat_id1_loc in
              match Ast.parse_simple_or_pointed rhs with
              | Ast.Simple value ->
                Pat_const (Ast.Feature_diff_cst (feat_id1, value), loc)
              | Ast.Pointed (s1, s2) ->
457
                Pat_const (Ast.Feature_diff_lex_or_fs (feat_id1, (s1, to_uname s2)), loc)
458
             }
bguillaum's avatar
bguillaum committed
459

460
        /*   X.cat <> "value"   */
bguillaum's avatar
bguillaum committed
461 462 463
        | feat_id1_loc=feature_ident_with_loc DISEQUAL rhs=STRING
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_diff_cst (feat_id1, rhs), loc) }

464
        /*   X.cat <> 12.34   */
bguillaum's avatar
bguillaum committed
465 466
        | feat_id1_loc=feature_ident_with_loc DISEQUAL rhs=FLOAT
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_diff_float (feat_id1, rhs), loc) }
467

468

469
        /*   X.cat = re"regexp"   */
470
        | feat_id_loc=feature_ident_with_loc EQUAL regexp=REGEXP
471
            { let (feat_id,loc)=feat_id_loc in Pat_const (Ast.Feature_eq_regexp (feat_id, regexp), loc) }
bguillaum's avatar
bguillaum committed
472

473 474
        /*   X.feat < Y.feat    */
        /*   X < Y     */
bguillaum's avatar
bguillaum committed
475 476 477
        | id1_loc=ineq_value_with_loc LT id2=ineq_value
            { let (id1,loc)=id1_loc in
              match (id1, id2) with
478
              (*   X.feat < Y.feat   *)
479 480 481
              | (Ineq_sofi (Ast.Pointed (n1, f1)), Ineq_sofi (Ast.Pointed (n2, f2))) ->
                Pat_const (Ast.Features_ineq (Ast.Lt, (n1,f1), (n2,f2)), loc)

482
              (*   X.feat < 12.34   *)
483 484 485
              | (Ineq_sofi (Ast.Pointed (n1, f1)), Ineq_float num) ->
                Pat_const (Ast.Feature_ineq_cst (Ast.Lt, (n1,f1), num), loc)

486
              (*   12.34 < Y.feat   *)
487 488 489
              | (Ineq_float num, Ineq_sofi (Ast.Pointed (n1, f1))) ->
                Pat_const (Ast.Feature_ineq_cst (Ast.Gt, (n1,f1), num), loc)

490
              (*   X < Y   *)
491 492 493
              | (Ineq_sofi (Ast.Simple n1), Ineq_sofi (Ast.Simple n2)) ->
                Pat_const (Ast.Immediate_prec (n1,n2), loc)

494
 (* TODO : axe lex_field *)
495 496

              (*  __ERRORS__   *)
bguillaum's avatar
bguillaum committed
497 498 499
              | (Ineq_float _, Ineq_float _) -> Error.build "the '<' symbol can be used with 2 constants"
              | _ -> Error.build "the '<' symbol can be used with 2 nodes or with 2 features but not in a mix inequality"
            }
bguillaum's avatar
bguillaum committed
500

501 502
        /*   X.feat > Y.feat    */
        /*   X > Y     */
bguillaum's avatar
bguillaum committed
503 504 505
        | id1_loc=ineq_value_with_loc GT id2=ineq_value
            { let (id1,loc)=id1_loc in
              match (id1, id2) with
506
              (*   X.feat > Y.feat   *)
507 508 509
              | (Ineq_sofi (Ast.Pointed (n1, f1)), Ineq_sofi (Ast.Pointed (n2, f2))) ->
                Pat_const (Ast.Features_ineq (Ast.Gt, (n1,f1), (n2,f2)), loc)

510
              (*   X.feat > 12.34   *)
511 512 513
              | (Ineq_sofi (Ast.Pointed (n1, f1)), Ineq_float num) ->
                Pat_const (Ast.Feature_ineq_cst (Ast.Gt, (n1,f1), num), loc)

514
              (*   12.34 > Y.feat   *)
515 516 517
              | (Ineq_float num, Ineq_sofi (Ast.Pointed (n1, f1))) ->
                Pat_const (Ast.Feature_ineq_cst (Ast.Lt, (n1,f1), num), loc)

518
              (*   X > Y   *)
519 520 521 522 523 524
              | (Ineq_sofi (Ast.Simple n1), Ineq_sofi (Ast.Simple n2)) ->
                Pat_const (Ast.Immediate_prec (n2,n1), loc)

(* TODO : axe lex_field *)

              (*  __ERRORS__   *)
bguillaum's avatar
bguillaum committed
525 526 527
              | (Ineq_float _, Ineq_float _) -> Error.build "the '>' symbol can be used with 2 constants"
              | _ -> Error.build "the '>' symbol can be used with 2 nodes or with 2 features but not in a mix inequality"
            }
bguillaum's avatar
bguillaum committed
528

529
        /*   X.position <= Y.position   */
bguillaum's avatar
bguillaum committed
530
        | feat_id1_loc=feature_ident_with_loc LE feat_id2=feature_ident
531
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Features_ineq (Ast.Le, feat_id1, feat_id2), loc) }
bguillaum's avatar
bguillaum committed
532

533
        /*   X.position >= Y.position   */
bguillaum's avatar
bguillaum committed
534
        | feat_id1_loc=feature_ident_with_loc GE feat_id2=feature_ident
535
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Features_ineq (Ast.Ge, feat_id1, feat_id2), loc) }
536

537
        /*   X.feat >= 12.34   */
bguillaum's avatar
bguillaum committed
538 539
        | feat_id1_loc=feature_ident_with_loc GE num=FLOAT
        | num=FLOAT LE feat_id1_loc=feature_ident_with_loc
540 541
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_ineq_cst (Ast.Ge, feat_id1, num), loc)  }

542
        /*   X.feat <= 12.34   */
bguillaum's avatar
bguillaum committed
543 544
        | feat_id1_loc=feature_ident_with_loc LE num=FLOAT
        | num=FLOAT GE feat_id1_loc=feature_ident_with_loc
545 546
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_ineq_cst (Ast.Le, feat_id1, num), loc)  }

547
        /*   A << B   */
bguillaum's avatar
bguillaum committed
548
        | n1_loc=simple_id_with_loc LPREC n2=simple_id
549
            { let (n1,loc) = n1_loc in Pat_const (Ast.Large_prec (n1,n2), loc) }
bguillaum's avatar
bguillaum committed
550

551
        /*   A >> B   */
bguillaum's avatar
bguillaum committed
552
        | n1_loc=simple_id_with_loc LSUCC n2=simple_id
553
            { let (n1,loc) = n1_loc in Pat_const (Ast.Large_prec (n2,n1), loc) }
bguillaum's avatar
bguillaum committed
554

555 556
node_features:
        /*   cat = n|v|adj   */
557 558 559
        | name_loc=simple_id_with_loc EQUAL values=separated_nonempty_list(PIPE,pattern_feature_value)
            {
              let (name,loc) = name_loc in
560
              let uname = to_uname name in
561
              match values with
562 563 564 565 566 567 568 569 570 571
              | [Ast.Simple "*"] ->
                ({Ast.kind = Ast.Disequality []; name=uname},loc)
              | [Ast.Pointed (lex,fn)] ->
                ({Ast.kind = Ast.Equal_lex (lex,fn); name=uname }, loc)
              | l ->
                let value_list = List.map (function
                  | Ast.Simple x -> x
                  | Ast.Pointed (lex,fn) -> Error.build "Lexical reference '%s.%s' cannot be used in a disjunction" lex fn
                ) l in ({Ast.kind = Ast.Equality value_list; name=uname }, loc)
            }
572 573 574

        /*   cat = *   */
        | name_loc=simple_id_with_loc EQUAL STAR
575
            { let (name,loc) = name_loc in
576
              ({Ast.kind = Ast.Disequality []; name=to_uname name},loc) }
577 578 579

        /*   cat   */
        | name_loc=simple_id_with_loc
580
            { let (name,loc) = name_loc in
581
              ({Ast.kind = Ast.Disequality []; name=to_uname name},loc) }
582 583

        /*    cat<>n|v|adj   */
584 585 586
        | name_loc=simple_id_with_loc DISEQUAL values=separated_nonempty_list(PIPE,pattern_feature_value)
            {
              let (name,loc) = name_loc in
587
              let uname = to_uname name in
588 589 590 591 592 593 594 595 596
              match values with
              | [Ast.Pointed (lex,fn)] ->
                ({Ast.kind = Ast.Disequal_lex (lex,fn); name=uname }, loc)
              | l ->
                let value_list = List.map (function
                  | Ast.Simple x -> x
                  | Ast.Pointed (lex,fn) -> Error.build "Lexical reference '%s.%s' cannot be used in a disjunction" lex fn
                ) l in ({Ast.kind = Ast.Disequality value_list; name=uname }, loc)
            }
597 598 599 600


        /*   !lemma   */
        | BANG name_loc=simple_id_with_loc
601
            { let (name,loc) = name_loc in ({Ast.kind = Ast.Absent; name=to_uname name}, loc) }
602

Bruno Guillaume's avatar
Bruno Guillaume committed
603 604
        /*   mwepos=ADV/upos=ADV   */
        | name1_loc=simple_id_with_loc EQUAL fv1=feature_value SLASH name2=simple_id EQUAL fv2=feature_value
605
            { let (name1,loc) = name1_loc in ({Ast.kind = Ast.Else (fv1,name2,fv2); name=to_uname name1}, loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
606 607


pj2m's avatar
pj2m committed
608 609 610 611
/*=============================================================================================*/
/* COMMANDS DEFINITION                                                                         */
/*=============================================================================================*/
commands:
612
        | COMMANDS x=delimited(LACC,separated_nonempty_list_final_opt(SEMIC,command),RACC) { x }
613

614 615 616
sub_edges:
        | name=simple_id_or_float EQUAL value=edge_item { (name, value) }

pj2m's avatar
pj2m committed
617
command:
618
        /*   del_edge e   */
bguillaum's avatar
bguillaum committed
619 620
        | DEL_EDGE n_loc=simple_id_with_loc
            { let (n,loc) = n_loc in (Ast.Del_edge_name n, loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
621

622
        /*   del_edge m -[x]-> n   */
bguillaum's avatar
bguillaum committed
623
        | DEL_EDGE src_loc=simple_id_with_loc label=delimited(LTR_EDGE_LEFT,label_ident,LTR_EDGE_RIGHT) tar=simple_id
624
            { let (src,loc) = src_loc in (Ast.Del_edge_expl (src, tar, label), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
625

626
        /*   add_edge m -[x]-> n   */
bguillaum's avatar
bguillaum committed
627
        | ADD_EDGE src_loc=simple_id_with_loc label=delimited(LTR_EDGE_LEFT,label_ident,LTR_EDGE_RIGHT) tar=simple_id
628
            { let (src,loc) = src_loc in (Ast.Add_edge (src, tar, label), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
629

630 631 632 633
        /*   add_edge e: m -> n   */
        | ADD_EDGE id_loc=simple_id_with_loc DDOT src=simple_id EDGE tar=simple_id
            { let (id,loc) = id_loc in (Ast.Add_edge_expl (src, tar, id), loc) }

634 635 636 637
        /*   add_edge m -[1=obj, 2=e.2]-> n   */
        | ADD_EDGE src_loc=simple_id_with_loc label=delimited(LTR_EDGE_LEFT,separated_list_final_opt(COMMA,sub_edges),LTR_EDGE_RIGHT) tar=simple_id
            { let (src,loc) = src_loc in (Ast.Add_edge_items (src, tar, label), loc) }

bguillaum's avatar
bguillaum committed
638
        /*   shift_in m ==> n   */
bguillaum's avatar
bguillaum committed
639
        | SHIFT_IN src_loc=simple_id_with_loc ARROW tar=simple_id
640
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, Ast.Neg_list []), loc) }
641

642
        /*   shift_in m =[x|y]=> n   */
bguillaum's avatar
bguillaum committed
643
        | SHIFT_IN src_loc=simple_id_with_loc
644
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
645
          tar=simple_id
646
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, Ast.Pos_list labels), loc) }
647

648
        /*   shift_in m =[^x|y]=> n   */
bguillaum's avatar
bguillaum committed
649
        | SHIFT_IN src_loc=simple_id_with_loc
650
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
651
          tar=simple_id
652
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, Ast.Neg_list labels), loc) }
653

bguillaum's avatar
bguillaum committed
654
        /*   shift_out m ==> n   */
bguillaum's avatar
bguillaum committed
655
        | SHIFT_OUT src_loc=simple_id_with_loc ARROW tar=simple_id
656
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, Ast.Neg_list []), loc) }
657

658
        /*   shift_out m =[x|y]=> n   */
bguillaum's avatar
bguillaum committed
659
        | SHIFT_OUT src_loc=simple_id_with_loc
660
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
661
          tar=simple_id
662
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, Ast.Pos_list labels), loc) }
663

664
        /*   shift_out m =[^x|y]=> n   */
bguillaum's avatar
bguillaum committed
665
        | SHIFT_OUT src_loc=simple_id_with_loc
666
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
667
          tar=simple_id
668
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, Ast.Neg_list labels), loc) }
669

bguillaum's avatar
bguillaum committed
670
        /*   shift m ==> n   */
bguillaum's avatar
bguillaum committed
671
        | SHIFT src_loc=simple_id_with_loc ARROW tar=simple_id
672
            { let (src,loc) = src_loc in (Ast.Shift_edge (src, tar, Ast.Neg_list []), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
673

674
        /*   shift m =[x|y]=> n   */
bguillaum's avatar
bguillaum committed
675
        | SHIFT src_loc=simple_id_with_loc
676
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
677
          tar=simple_id
678
            { let (src,loc) = src_loc in (Ast.Shift_edge (src, tar, Ast.Pos_list labels), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
679

680
        /*   shift m =[^x|y]=> n   */
bguillaum's avatar
bguillaum committed
681
        | SHIFT src_loc=simple_id_with_loc
682
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
683
          tar=simple_id
684
            { let (src,loc) = src_loc in (Ast.Shift_edge (src, tar, Ast.Neg_list labels), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
685

686
        /*   del_node n   */
bguillaum's avatar
bguillaum committed
687
        | DEL_NODE ci_loc=simple_id_with_loc
688
            { let (ci,loc) = ci_loc in (Ast.Del_node (ci), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
689

690
        /*   add_node n   */
bguillaum's avatar
bguillaum committed
691 692 693
        | ADD_NODE new_ci_loc=simple_id_with_loc
            { let (new_ci,loc) = new_ci_loc in (Ast.New_node new_ci, loc) }

694
        /*   add_node n :< m   */
bguillaum's avatar
bguillaum committed
695 696 697
        | ADD_NODE new_ci_loc=simple_id_with_loc BEFORE old_ci=simple_id
            { let (new_ci,loc) = new_ci_loc in (Ast.New_before (new_ci,old_ci), loc) }

698
        /*   add_node n :> m   */
bguillaum's avatar
bguillaum committed
699 700 701
        | ADD_NODE new_ci_loc=simple_id_with_loc AFTER old_ci=simple_id
            { let (new_ci,loc) = new_ci_loc in (Ast.New_after (new_ci,old_ci), loc) }

702
        /*   del_feat m.cat   */
bguillaum's avatar
bguillaum committed
703
        | DEL_FEAT com_fead_id_loc= feature_ident_with_loc
704
            { let (com_fead_id,loc) = com_fead_id_loc in (Ast.Del_feat com_fead_id, loc) }