grew_parser.mly 33.4 KB
Newer Older
bguillaum's avatar
bguillaum committed
1 2 3 4 5 6 7 8 9
(**********************************************************************************)
(*    Libcaml-grew - a Graph Rewriting library dedicated to NLP applications      *)
(*                                                                                *)
(*    Copyright 2011-2013 Inria, Université de Lorraine                           *)
(*                                                                                *)
(*    Webpage: http://grew.loria.fr                                               *)
(*    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 28 29 30
type ineq_item =
  | Ineq_sofi of Ast.simple_or_feature_ident
  | Ineq_float of float

bguillaum's avatar
bguillaum committed
31
let get_loc () = Loc.file_line !Global.current_file !Global.current_line
pj2m's avatar
pj2m committed
32 33 34
let localize t = (t,get_loc ())
%}

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

bguillaum's avatar
bguillaum committed
57 58 59
%token BEFORE                      /* :< */
%token AFTER                       /* :> */

60
%token PIPE                        /* | */
61

62
%token EDGE                        /* -> */
63 64 65 66 67
%token LTR_EDGE_LEFT               /* -[ */
%token LTR_EDGE_LEFT_NEG           /* -[^ */
%token LTR_EDGE_RIGHT              /* ]-> */
%token RTL_EDGE_LEFT               /* <-[ */
%token RTL_EDGE_RIGHT              /* ]- */
68 69 70 71 72

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

74
%token DOMAIN                      /* domain */
bguillaum's avatar
bguillaum committed
75
%token INCL                        /* include */
76
%token FEATURES                    /* features */
bguillaum's avatar
bguillaum committed
77 78
%token FEATURE                     /* feature */
%token FILE                        /* file */
79 80 81 82 83 84 85
%token LABELS                      /* labels */
%token MATCH                       /* match */
%token WITHOUT                     /* without */
%token COMMANDS                    /* commands */
%token MODULE                      /* module */
%token CONFLUENT                   /* confluent */
%token RULE                        /* rule */
86
%token FILTER                      /* filter */
87 88 89 90 91 92
%token SEQUENCES                   /* sequences */
%token GRAPH                       /* graph */

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

100 101 102
%token <string> DOLLAR_ID          /* $id */
%token <string> AROBAS_ID          /* @id */
%token <string> COLOR              /* @#89abCD */
bguillaum's avatar
bguillaum committed
103

104 105 106
%token <string> ID   /* the general notion of id */

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

bguillaum's avatar
bguillaum committed
108
%token <string>           STRING
109
%token <string>           REGEXP
110
%token <float>            FLOAT
bguillaum's avatar
bguillaum committed
111
%token <string list>      COMMENT
bguillaum's avatar
bguillaum committed
112
%token <string list>      LEX_PAR
pj2m's avatar
pj2m committed
113

114
%token EOF                         /* end of file */
pj2m's avatar
pj2m committed
115

116
%start <Grew_ast.Ast.grs_wi> grs_wi
bguillaum's avatar
bguillaum committed
117
%start <Grew_ast.Ast.gr> gr
118
%start <Grew_ast.Ast.module_or_include list> included
119
%start <Grew_ast.Ast.pattern> pattern
120
%start <Grew_ast.Ast.domain> domain
121
%start <Grew_types.Strategy.def> strategy
122

123 124
/* 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é))))))"    */
125
%start <Grew_ast.Ast.pst> phrase_structure_tree
126

127 128 129 130
%left SEMIC
%left PLUS
%nonassoc STAR
%nonassoc DISEQUAL
pj2m's avatar
pj2m committed
131 132
%%

bguillaum's avatar
bguillaum committed
133 134 135 136

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

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

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

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

pattern_label_ident:
        | x=ID        { Ast.parse_pattern_label_ident x }
153

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

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

160 161 162 163 164 165
node_id:
        | id=ID       { Ast.parse_node_ident id }

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

166 167
feature_ident :
        | id=ID       { Ast.parse_feature_ident id }
bguillaum's avatar
bguillaum committed
168

169 170
feature_ident_with_loc :
        | id=ID      { localize (Ast.parse_feature_ident id) }
171

172 173 174 175
feature_value:
        | v=ID        { v }
        | v=STRING    { v }
        | v=FLOAT     { Printf.sprintf "%g" v }
pj2m's avatar
pj2m committed
176

bguillaum's avatar
bguillaum committed
177 178 179 180 181 182 183 184
ineq_value:
        | v=ID    { Ineq_sofi (Ast.parse_simple_or_feature_ident v) }
        | v=FLOAT { Ineq_float v }

ineq_value_with_loc:
        | v=ID    { localize (Ineq_sofi (Ast.parse_simple_or_feature_ident v)) }
        | v=FLOAT { localize (Ineq_float v) }

185 186 187
/*=============================================================================================*/
/*  GREW GRAPH                                                                                 */
/*=============================================================================================*/
188 189
gr:
        | GRAPH LACC items=separated_list_final_opt(SEMIC,gr_item) RACC EOF
190
            {
191 192 193 194 195 196
              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;
              }
197
            }
bguillaum's avatar
bguillaum committed
198

pj2m's avatar
pj2m committed
199
gr_item:
200
        /*  sentence = "Jean dort."   */
201
        | id=simple_id EQUAL value=feature_value
202
            { Graph_meta (id ^ " = " ^ value) }
203

204 205
        /*  B (1) [phon="pense", lemma="penser", cat=v, mood=ind ]   */
        /*  B [phon="pense", lemma="penser", cat=v, mood=ind ]   */
206
        | id_loc=node_id_with_loc position=option(delimited(LPAREN, FLOAT ,RPAREN)) feats=delimited(LBRACKET,separated_list_final_opt(COMA,node_features),RBRACKET)
bguillaum's avatar
bguillaum committed
207 208
            { let (id,loc) = id_loc in
              Graph_node ({Ast.node_id = id; position=position; fs=feats}, loc) }
209
        /*   A   */
210 211 212
        | 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
213

214
        /*   A -[x]-> B   */
215
        | n1_loc=node_id_with_loc label=delimited(LTR_EDGE_LEFT,label_ident,LTR_EDGE_RIGHT) n2=node_id
216
            { 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
217

218 219 220 221 222 223 224 225 226 227 228
/*=============================================================================================*/
/*  DOMAIN DEFINITION                                                                          */
/*=============================================================================================*/
domain:
        | f=features_group g=labels
            {
              {  Ast.feature_domain = f;
                 label_domain = g;
              }
            }

pj2m's avatar
pj2m committed
229
/*=============================================================================================*/
bguillaum's avatar
bguillaum committed
230
/*  GREW GRAPH REWRITING SYSTEM                                                                */
pj2m's avatar
pj2m committed
231
/*=============================================================================================*/
232
grs_wi:
bguillaum's avatar
bguillaum committed
233
        | d=option(domain) m=module_or_include_list s=option(sequences) EOF
234
            {
bguillaum's avatar
bguillaum committed
235
             { Ast.domain_wi=(match d with Some dom -> Some (Ast.Dom dom) | None -> None);
236
               modules_wi=m;
bguillaum's avatar
bguillaum committed
237
               strategies_wi=match s with Some seq -> seq | None -> [];
238 239
             }
           }
240
        | DOMAIN file=STRING m=module_or_include_list s=option(sequences) EOF
241
            {
bguillaum's avatar
bguillaum committed
242
             { Ast.domain_wi= Some (Ast.Dom_file file);
243
               modules_wi=m;
bguillaum's avatar
bguillaum committed
244
               strategies_wi=match s with Some seq -> seq | None -> [];
245 246
             }
           }
247

248
module_or_include_list:
249
        | x=list(module_or_include) { x }
250 251

module_or_include:
252
        | m=grew_module             { Ast.Modul m }
bguillaum's avatar
bguillaum committed
253
        | INCL sub=subfile SEMIC { Ast.Includ sub }
pj2m's avatar
pj2m committed
254

255
subfile:
256
        | f=STRING  { localize f }
pj2m's avatar
pj2m committed
257 258 259 260 261

/*=============================================================================================*/
/* FEATURES DOMAIN DEFINITION                                                                  */
/*=============================================================================================*/
features_group:
262 263
        | FEATURES x=features { x }

264
features:
265
        | LACC x=separated_nonempty_list_final_opt(SEMIC,feature) RACC { x }
bguillaum's avatar
bguillaum committed
266

267
feature:
268 269
        /*   pos=#   */
        /*   m: ind,inf,part,subj,imp   */
270
        | feature_name=feature_name DDOT feature_values=features_values
bguillaum's avatar
bguillaum committed
271
            {
272
              match feature_values with
bguillaum's avatar
bguillaum committed
273 274
                | ["#"] -> Feature_domain.Num feature_name
                | _ -> Feature_domain.build_closed feature_name feature_values
275
            }
pj2m's avatar
pj2m committed
276

277
        /*   phon:*   */
278
        | feature_name=feature_name DDOT STAR
bguillaum's avatar
bguillaum committed
279
            { Feature_domain.Open feature_name }
280

pj2m's avatar
pj2m committed
281
feature_name:
282
        | ci=ID { ci }
pj2m's avatar
pj2m committed
283 284

features_values:
285 286
        | SHARP                                         { ["#"] }
        | x=separated_nonempty_list(COMA,feature_value) { x }
pj2m's avatar
pj2m committed
287 288 289 290

/*=============================================================================================*/
/* GLOBAL LABELS DEFINITION                                                                    */
/*=============================================================================================*/
291
labels:
292
        /*   labels { OBJ, SUBJ, DE_OBJ, ANT }   */
293 294
        | LABELS x=delimited(LACC,separated_nonempty_list_final_opt(COMA,label),RACC) { x }

295
label:
296
        | x=label_ident display_list=list(display)  { (x, display_list) }
297
        | x=STRING                                  { (x,[]) }
pj2m's avatar
pj2m committed
298

299
display:
300 301
        | dis=AROBAS_ID   { dis }
        | col=COLOR       { col }
pj2m's avatar
pj2m committed
302 303 304 305

/*=============================================================================================*/
/* MODULE DEFINITION                                                                           */
/*=============================================================================================*/
306
included:
307
        | x=list(module_or_include) EOF { x }
308

309
grew_module:
bguillaum's avatar
bguillaum committed
310
        | doc=option(COMMENT) MODULE conf=boption(CONFLUENT) id_loc=simple_id_with_loc LACC l=option(labels) r=rules RACC
311
           {
312
            { Ast.module_id = fst id_loc;
bguillaum's avatar
bguillaum committed
313 314
              local_labels = (match l with None -> [] | Some x -> x);
              rules = r;
315
              confluent = conf;
bguillaum's avatar
bguillaum committed
316
              module_doc = (match doc with Some d -> d | None -> []);
bguillaum's avatar
bguillaum committed
317
              mod_loc = snd id_loc;
318
              mod_dir = "";
319 320
            }
          }
pj2m's avatar
pj2m committed
321 322 323 324 325

/*=============================================================================================*/
/* RULES DEFINITION                                                                            */
/*=============================================================================================*/
rules:
326
        | r = list(rule) { r }
pj2m's avatar
pj2m committed
327

328 329 330 331
rule:
        | doc=option(COMMENT) RULE id_loc=simple_id_with_loc LACC p=pos_item n=list(neg_item) cmds=commands RACC
            {
              { Ast.rule_id = fst id_loc;
332
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
bguillaum's avatar
bguillaum committed
333
                commands = Ast.replace_new_neighbour cmds;
bguillaum's avatar
bguillaum committed
334
                param = None;
bguillaum's avatar
bguillaum committed
335
                lex_par = None;
bguillaum's avatar
bguillaum committed
336
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
337
                rule_loc = snd id_loc;
338
              }
339
            }
340
        | doc=option(COMMENT) RULE id_loc=simple_id_with_loc param=param LACC p=pos_item n=list(neg_item) cmds=commands RACC lex_par=option(lex_par)
341 342
            {
              { Ast.rule_id = fst id_loc;
343
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
344
                commands = Ast.replace_new_neighbour cmds;
345
                param = Some param;
bguillaum's avatar
bguillaum committed
346
                lex_par = lex_par;
bguillaum's avatar
bguillaum committed
347
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
348
                rule_loc = snd id_loc;
bguillaum's avatar
bguillaum committed
349
              }
350 351 352 353
            }
        | doc=option(COMMENT) FILTER id_loc=simple_id_with_loc LACC p=pos_item n=list(neg_item) RACC
            {
              { Ast.rule_id = fst id_loc;
354
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
355 356
                commands = [];
                param = None;
bguillaum's avatar
bguillaum committed
357
                lex_par = None;
bguillaum's avatar
bguillaum committed
358
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
359
                rule_loc = snd id_loc;
360 361
              }
            }
362

bguillaum's avatar
bguillaum committed
363 364
lex_par:
        | lex_par = LEX_PAR  { lex_par }
365

bguillaum's avatar
bguillaum committed
366
param:
367 368
        | LPAREN FEATURE vars=separated_nonempty_list(COMA,var) RPAREN                                       { ([],vars) }
        | LPAREN FEATURE vars=separated_nonempty_list(COMA,var) SEMIC files=separated_list(COMA,file) RPAREN { (files,vars) }
bguillaum's avatar
bguillaum committed
369

370
file:
371
        | FILE f=STRING     { f }
bguillaum's avatar
bguillaum committed
372
var:
373 374
        | i=DOLLAR_ID       { i }
        | i=AROBAS_ID       { i }
bguillaum's avatar
bguillaum committed
375

pj2m's avatar
pj2m committed
376
pos_item:
377
        | MATCH i=pn_item   { i }
pj2m's avatar
pj2m committed
378 379

neg_item:
380 381 382 383
        | WITHOUT i=pn_item { i }

pn_item:
        | l=delimited(LACC,separated_list_final_opt(SEMIC,pat_item),RACC)
384 385
            {
             {
bguillaum's avatar
bguillaum committed
386 387 388
              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;
389 390
            }
           }
pj2m's avatar
pj2m committed
391 392 393 394 395

/*=============================================================================================*/
/* MATCH DEFINITION                                                                            */
/*=============================================================================================*/
pat_item:
396
        /*   R [cat=V, lemma=$lemma]   */
bguillaum's avatar
bguillaum committed
397
        | id_loc=simple_id_with_loc feats=delimited(LBRACKET,separated_list_final_opt(COMA,node_features),RBRACKET)
398
            { Pat_node ({Ast.node_id = fst id_loc; position=None; fs= feats}, snd id_loc) }
bguillaum's avatar
bguillaum committed
399

400
        /*   e: A -> B   */
401
        | id_loc=simple_id_with_loc DDOT n1=simple_id EDGE n2=simple_id
402
            { 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
403

404
        /*   e: A -[X|Y]-> B   */
405
        | id_loc=simple_id_with_loc DDOT n1=simple_id labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) n2=simple_id
406
            { 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
407

408
        /*   e: A -[^X|Y]-> B   */
409
        | id_loc=simple_id_with_loc DDOT n1=simple_id labels=delimited(LTR_EDGE_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) n2=simple_id
410 411
            { 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) }

412
        /*   e: A -[re"regexp"]-> B   */
413 414
        | 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) }
415

416
        /*   A -> B   */
417
        | n1_loc=simple_id_with_loc EDGE n2=simple_id
418
            { let (n1,loc) = n1_loc in Pat_edge ({Ast.edge_id = None; src=n1; edge_label_cst=Ast.Neg_list []; tar=n2}, loc) }
419

420
        /*   A -> *   */
421
        | n1_loc=simple_id_with_loc EDGE STAR
422
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Neg_list []), loc) }
423

424
        /*   * -> B   */
425
        | STAR EDGE n2_loc=simple_id_with_loc
426
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,Ast.Neg_list []), loc) }
427

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

432
        /*   A -[X|Y]-> *   */
433
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) STAR
434
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Pos_list labels), loc) }
435

436
        /*   * -[X|Y]-> B   */
437
        | STAR labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) n2_loc=simple_id_with_loc
438
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,Ast.Pos_list labels), loc) }
439

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

444
        /*   A -[re"regexp"]-> B   */
445 446
        | 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) }
447

448
        /*   A -[^X|Y]-> *   */
449
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) STAR
450
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Neg_list labels), loc) }
451

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

456 457
        /*   X.cat = Y.cat   */
        /*   X.cat = value   */
bguillaum's avatar
bguillaum committed
458 459 460 461 462 463 464
        | feat_id1_loc=feature_ident_with_loc EQUAL rhs=ID
            { let (feat_id1,loc)=feat_id1_loc in
              match Ast.parse_simple_or_feature_ident rhs with
              | (node_id, Some feat_name) -> Pat_const (Ast.Feature_eq (feat_id1, (node_id,feat_name)), loc)
              | (value, None) -> Pat_const (Ast.Feature_cst (feat_id1, value), loc)
            }

465
        /*   X.cat = "value"   */
bguillaum's avatar
bguillaum committed
466 467 468
        | feat_id1_loc=feature_ident_with_loc EQUAL rhs=STRING
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_cst (feat_id1, rhs), loc) }

469
        /*   X.cat = 12.34   */
bguillaum's avatar
bguillaum committed
470 471 472
        | feat_id1_loc=feature_ident_with_loc EQUAL rhs=FLOAT
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_float (feat_id1, rhs), loc) }

473 474
        /*   X.cat <> Y.cat   */
        /*   X.cat <> value   */
bguillaum's avatar
bguillaum committed
475 476 477 478 479 480 481
        | feat_id1_loc=feature_ident_with_loc DISEQUAL rhs=ID
            { let (feat_id1,loc)=feat_id1_loc in
              match Ast.parse_simple_or_feature_ident rhs with
              | (node_id, Some feat_name) -> Pat_const (Ast.Feature_diseq (feat_id1, (node_id,feat_name)), loc)
              | (value, None) -> Pat_const (Ast.Feature_diff_cst (feat_id1, value), loc)
            }

482
        /*   X.cat <> "value"   */
bguillaum's avatar
bguillaum committed
483 484 485
        | 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) }

486
        /*   X.cat <> 12.34   */
bguillaum's avatar
bguillaum committed
487 488
        | 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) }
489

490

491
        /*   X.cat = re"regexp"   */
492
        | feat_id_loc=feature_ident_with_loc EQUAL regexp=REGEXP
bguillaum's avatar
bguillaum committed
493 494
            { let (feat_id,loc)=feat_id_loc in Pat_const (Ast.Feature_re (feat_id, regexp), loc) }

bguillaum's avatar
bguillaum committed
495 496 497
        | id1_loc=ineq_value_with_loc LT id2=ineq_value
            { let (id1,loc)=id1_loc in
              match (id1, id2) with
498
              (*   X.feat < Y.feat   *)
bguillaum's avatar
bguillaum committed
499
              | (Ineq_sofi (n1, Some f1), Ineq_sofi (n2, Some f2)) -> Pat_const (Ast.Feature_ineq (Ast.Lt, (n1,f1), (n2,f2)), loc)
500
              (*   X.feat < 12.34   *)
bguillaum's avatar
bguillaum committed
501
              | (Ineq_sofi (n1, Some f1), Ineq_float num) -> Pat_const (Ast.Feature_ineq_cst (Ast.Lt, (n1,f1), num), loc)
502
              (*   12.34 < Y.feat   *)
bguillaum's avatar
bguillaum committed
503
              | (Ineq_float num, Ineq_sofi (n1, Some f1)) -> Pat_const (Ast.Feature_ineq_cst (Ast.Gt, (n1,f1), num), loc)
504
              (*   X < Y   *)
bguillaum's avatar
bguillaum committed
505 506 507 508
              | (Ineq_sofi (n1, None), Ineq_sofi (n2, None)) -> Pat_const (Ast.Prec (n1,n2), loc)
              | (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
509

bguillaum's avatar
bguillaum committed
510 511 512
        | id1_loc=ineq_value_with_loc GT id2=ineq_value
            { let (id1,loc)=id1_loc in
              match (id1, id2) with
513
              (*   X.feat > Y.feat   *)
bguillaum's avatar
bguillaum committed
514
              | (Ineq_sofi (n1, Some f1), Ineq_sofi (n2, Some f2)) -> Pat_const (Ast.Feature_ineq (Ast.Gt, (n1,f1), (n2,f2)), loc)
515
              (*   X.feat > 12.34   *)
bguillaum's avatar
bguillaum committed
516
              | (Ineq_sofi (n1, Some f1), Ineq_float num) -> Pat_const (Ast.Feature_ineq_cst (Ast.Gt, (n1,f1), num), loc)
517
              (*   12.34 > Y.feat   *)
bguillaum's avatar
bguillaum committed
518
              | (Ineq_float num, Ineq_sofi (n1, Some f1)) -> Pat_const (Ast.Feature_ineq_cst (Ast.Lt, (n1,f1), num), loc)
519
              (*   X > Y   *)
bguillaum's avatar
bguillaum committed
520 521 522 523
              | (Ineq_sofi (n1, None), Ineq_sofi (n2, None)) -> Pat_const (Ast.Prec (n2,n1), loc)
              | (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
524

525
        /*   X.position <= Y.position   */
bguillaum's avatar
bguillaum committed
526
        | feat_id1_loc=feature_ident_with_loc LE feat_id2=feature_ident
527
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_ineq (Ast.Le, feat_id1, feat_id2), loc) }
bguillaum's avatar
bguillaum committed
528

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

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

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

543
        /*   A << B   */
bguillaum's avatar
bguillaum committed
544 545 546
        | n1_loc=simple_id_with_loc LPREC n2=simple_id
            { let (n1,loc) = n1_loc in Pat_const (Ast.Lprec (n1,n2), loc) }

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

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
node_features:
        /*   cat = n|v|adj   */
        | name_loc=simple_id_with_loc EQUAL values=separated_nonempty_list(PIPE,feature_value)
            { let (name,loc) = name_loc in
              match values with
              | ["*"] -> ({Ast.kind = Ast.Disequality []; name},loc)
              | _ -> ({Ast.kind = Ast.Equality values; name }, loc) }

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

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

        /*    cat<>n|v|adj   */
        | name_loc=simple_id_with_loc DISEQUAL values=separated_nonempty_list(PIPE,feature_value)
            { let (name,loc) = name_loc in ( {Ast.kind = Ast.Disequality values; name}, loc) }

        /*    lemma=$lem   */
        | name_loc=simple_id_with_loc EQUAL p=DOLLAR_ID
            { let (name,loc) = name_loc in ( {Ast.kind = Ast.Equal_param p; name }, loc) }

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

pj2m's avatar
pj2m committed
579 580 581 582
/*=============================================================================================*/
/* COMMANDS DEFINITION                                                                         */
/*=============================================================================================*/
commands:
583
        | COMMANDS x=delimited(LACC,separated_nonempty_list_final_opt(SEMIC,command),RACC) { x }
584

pj2m's avatar
pj2m committed
585
command:
586
        /*   del_edge e   */
bguillaum's avatar
bguillaum committed
587 588
        | 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
589

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

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

598
        /*   "shift_in m ==> n"   */
bguillaum's avatar
bguillaum committed
599
        | SHIFT_IN src_loc=simple_id_with_loc ARROW tar=simple_id
600
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, Ast.Neg_list []), loc) }
601

602
        /*   "shift_in m =[x*|y]=> n"   */
bguillaum's avatar
bguillaum committed
603
        | SHIFT_IN src_loc=simple_id_with_loc
604
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
605
          tar=simple_id
606
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, Ast.Pos_list labels), loc) }
607

608
        /*   "shift_in m =[^x*|y]=> n"   */
bguillaum's avatar
bguillaum committed
609
        | SHIFT_IN src_loc=simple_id_with_loc
610
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
611
          tar=simple_id
612
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, Ast.Neg_list labels), loc) }
613

614
        /*   "shift_out m ==> n"   */
bguillaum's avatar
bguillaum committed
615
        | SHIFT_OUT src_loc=simple_id_with_loc ARROW tar=simple_id
616
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, Ast.Neg_list []), loc) }
617

618
        /*   "shift_out m =[x*|y]=> n"   */
bguillaum's avatar
bguillaum committed
619
        | SHIFT_OUT src_loc=simple_id_with_loc
620
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
621
          tar=simple_id
622
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, Ast.Pos_list labels), loc) }
623

624
        /*   "shift_out m =[^x*|y]=> n"   */
bguillaum's avatar
bguillaum committed
625
        | SHIFT_OUT src_loc=simple_id_with_loc
626
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
627
          tar=simple_id
628
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, Ast.Neg_list labels), loc) }
629

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

634
        /*   "shift m =[x*|y]=> n"   */
bguillaum's avatar
bguillaum committed
635
        | SHIFT src_loc=simple_id_with_loc
636
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
637
          tar=simple_id
638
            { let (src,loc) = src_loc in (Ast.Shift_edge (src, tar, Ast.Pos_list labels), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
639

640
        /*   "shift m =[^x*|y]=> n"   */
bguillaum's avatar
bguillaum committed
641
        | SHIFT src_loc=simple_id_with_loc
642
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
bguillaum's avatar
bguillaum committed
643
          tar=simple_id
644
            { let (src,loc) = src_loc in (Ast.Shift_edge (src, tar, Ast.Neg_list labels), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
645

646
        /*   merge m ==> n   */
bguillaum's avatar
bguillaum committed
647
        | MERGE src_loc=simple_id_with_loc ARROW tar=simple_id
648
            { let (src,loc) = src_loc in (Ast.Merge_node (src, tar), loc) }