grew_parser.mly 32.5 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 122 123 124 125

%left SEMIC
%left PLUS
%nonassoc STAR
%nonassoc DISEQUAL
pj2m's avatar
pj2m committed
126 127
%%

bguillaum's avatar
bguillaum committed
128 129 130 131

%public separated_list_final_opt(separator,X):
|                                                               { [] }
|   x=X                                                         { [x] }
132
|   x=X; separator; xs=separated_list_final_opt(separator,X)    { x :: xs }
bguillaum's avatar
bguillaum committed
133 134 135 136

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

pj2m's avatar
pj2m committed
139
/*=============================================================================================*/
140
/*  BASIC DEFINITIONS                                                                          */
pj2m's avatar
pj2m committed
141
/*=============================================================================================*/
142

143
label_ident:
144 145 146 147
        | x=ID        { Ast.parse_label_ident x }

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

bguillaum's avatar
bguillaum committed
149
simple_id:
150
        | id=ID       { Ast.parse_simple_ident id }
bguillaum's avatar
bguillaum committed
151

152
simple_id_with_loc:
153 154
        | id=ID       { localize (Ast.parse_simple_ident id) }

155 156 157 158 159 160
node_id:
        | id=ID       { Ast.parse_node_ident id }

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

161 162
feature_ident :
        | id=ID       { Ast.parse_feature_ident id }
bguillaum's avatar
bguillaum committed
163

164 165
feature_ident_with_loc :
        | id=ID      { localize (Ast.parse_feature_ident id) }
166

167 168 169 170
feature_value:
        | v=ID        { v }
        | v=STRING    { v }
        | v=FLOAT     { Printf.sprintf "%g" v }
pj2m's avatar
pj2m committed
171

bguillaum's avatar
bguillaum committed
172 173 174 175 176 177 178 179
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) }

180 181 182
/*=============================================================================================*/
/*  GREW GRAPH                                                                                 */
/*=============================================================================================*/
183 184
gr:
        | GRAPH LACC items=separated_list_final_opt(SEMIC,gr_item) RACC EOF
185 186
            {
             {
187
              Ast.meta = List_.opt_map (function Graph_meta n -> Some n | _ -> None) items;
bguillaum's avatar
bguillaum committed
188 189
              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;
190 191
            }
           }
bguillaum's avatar
bguillaum committed
192

pj2m's avatar
pj2m committed
193
gr_item:
194
        (* sentence = "Jean dort." *)
195
        | id=simple_id EQUAL value=feature_value
196
            { Graph_meta (id ^ " = " ^ value) }
197

bguillaum's avatar
bguillaum committed
198
        (* B (1) [phon="pense", lemma="penser", cat=v, mood=ind ] *)
199
        (* B [phon="pense", lemma="penser", cat=v, mood=ind ] *)
200
        | 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
201 202
            { let (id,loc) = id_loc in
              Graph_node ({Ast.node_id = id; position=position; fs=feats}, loc) }
pj2m's avatar
pj2m committed
203

bguillaum's avatar
bguillaum committed
204
        (* A -[x]-> B *)
205
        | n1_loc=node_id_with_loc label=delimited(LTR_EDGE_LEFT,label_ident,LTR_EDGE_RIGHT) n2=node_id
206
            { 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
207

208 209 210 211 212 213 214 215 216 217 218
/*=============================================================================================*/
/*  DOMAIN DEFINITION                                                                          */
/*=============================================================================================*/
domain:
        | f=features_group g=labels
            {
              {  Ast.feature_domain = f;
                 label_domain = g;
              }
            }

pj2m's avatar
pj2m committed
219
/*=============================================================================================*/
bguillaum's avatar
bguillaum committed
220
/*  GREW GRAPH REWRITING SYSTEM                                                                */
pj2m's avatar
pj2m committed
221
/*=============================================================================================*/
222
grs_wi:
bguillaum's avatar
bguillaum committed
223
        | d=option(domain) m=module_or_include_list s=option(sequences) EOF
224
            {
bguillaum's avatar
bguillaum committed
225
             { Ast.domain_wi=(match d with Some dom -> Some (Ast.Dom dom) | None -> None);
226
               modules_wi=m;
bguillaum's avatar
bguillaum committed
227
               strategies_wi=match s with Some seq -> seq | None -> [];
228 229
             }
           }
230
        | DOMAIN file=STRING m=module_or_include_list s=option(sequences) EOF
231
            {
bguillaum's avatar
bguillaum committed
232
             { Ast.domain_wi= Some (Ast.Dom_file file);
233
               modules_wi=m;
bguillaum's avatar
bguillaum committed
234
               strategies_wi=match s with Some seq -> seq | None -> [];
235 236
             }
           }
237

238
module_or_include_list:
239
        | x=list(module_or_include) { x }
240 241

module_or_include:
242
        | m=grew_module             { Ast.Modul m }
bguillaum's avatar
bguillaum committed
243
        | INCL sub=subfile SEMIC { Ast.Includ sub }
pj2m's avatar
pj2m committed
244

245
subfile:
246
        | f=STRING  { localize f }
pj2m's avatar
pj2m committed
247 248 249 250 251

/*=============================================================================================*/
/* FEATURES DOMAIN DEFINITION                                                                  */
/*=============================================================================================*/
features_group:
252 253
        | FEATURES x=features { x }

254
features:
255
        | LACC x=separated_nonempty_list_final_opt(SEMIC,feature) RACC { x }
bguillaum's avatar
bguillaum committed
256

257
feature:
258 259 260
        (* pos=# *)
        (* m: ind,inf,part,subj,imp *)
        | feature_name=feature_name DDOT feature_values=features_values
bguillaum's avatar
bguillaum committed
261
            {
262
              match feature_values with
bguillaum's avatar
bguillaum committed
263 264
                | ["#"] -> Feature_domain.Num feature_name
                | _ -> Feature_domain.build_closed feature_name feature_values
265
            }
pj2m's avatar
pj2m committed
266

267 268
        (* phon:* *)
        | feature_name=feature_name DDOT STAR
bguillaum's avatar
bguillaum committed
269
            { Feature_domain.Open feature_name }
270

pj2m's avatar
pj2m committed
271
feature_name:
272
        | ci=ID { ci }
pj2m's avatar
pj2m committed
273 274

features_values:
275 276
        | SHARP                                         { ["#"] }
        | x=separated_nonempty_list(COMA,feature_value) { x }
pj2m's avatar
pj2m committed
277 278 279 280

/*=============================================================================================*/
/* GLOBAL LABELS DEFINITION                                                                    */
/*=============================================================================================*/
281
labels:
282 283 284
        (* labels { OBJ, SUBJ, DE_OBJ, ANT } *)
        | LABELS x=delimited(LACC,separated_nonempty_list_final_opt(COMA,label),RACC) { x }

285
label:
286
        | x=label_ident display_list=list(display)  { (x, display_list) }
287
        | x=STRING                                  { (x,[]) }
pj2m's avatar
pj2m committed
288

289
display:
290 291
        | dis=AROBAS_ID   { dis }
        | col=COLOR       { col }
pj2m's avatar
pj2m committed
292 293 294 295

/*=============================================================================================*/
/* MODULE DEFINITION                                                                           */
/*=============================================================================================*/
296
included:
297
        | x=list(module_or_include) EOF { x }
298

299
grew_module:
bguillaum's avatar
bguillaum committed
300
        | doc=option(COMMENT) MODULE conf=boption(CONFLUENT) id_loc=simple_id_with_loc LACC l=option(labels) r=rules RACC
301
           {
302
            { Ast.module_id = fst id_loc;
bguillaum's avatar
bguillaum committed
303 304
              local_labels = (match l with None -> [] | Some x -> x);
              rules = r;
305
              confluent = conf;
bguillaum's avatar
bguillaum committed
306
              module_doc = (match doc with Some d -> d | None -> []);
bguillaum's avatar
bguillaum committed
307
              mod_loc = snd id_loc;
308
              mod_dir = "";
309 310
            }
          }
pj2m's avatar
pj2m committed
311 312 313 314 315

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

318 319 320 321
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;
322
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
bguillaum's avatar
bguillaum committed
323
                commands = Ast.replace_new_neighbour cmds;
bguillaum's avatar
bguillaum committed
324
                param = None;
bguillaum's avatar
bguillaum committed
325
                lex_par = None;
bguillaum's avatar
bguillaum committed
326
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
327
                rule_loc = snd id_loc;
328
              }
329
            }
330
        | 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)
331 332
            {
              { Ast.rule_id = fst id_loc;
333
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
334
                commands = Ast.replace_new_neighbour cmds;
335
                param = Some param;
bguillaum's avatar
bguillaum committed
336
                lex_par = lex_par;
bguillaum's avatar
bguillaum committed
337
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
338
                rule_loc = snd id_loc;
bguillaum's avatar
bguillaum committed
339
              }
340 341 342 343
            }
        | 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;
344
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
345 346
                commands = [];
                param = None;
bguillaum's avatar
bguillaum committed
347
                lex_par = None;
bguillaum's avatar
bguillaum committed
348
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
349
                rule_loc = snd id_loc;
350 351
              }
            }
352

bguillaum's avatar
bguillaum committed
353 354
lex_par:
        | lex_par = LEX_PAR  { lex_par }
355

bguillaum's avatar
bguillaum committed
356
param:
357 358
        | 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
359

360
file:
361
        | FILE f=STRING     { f }
bguillaum's avatar
bguillaum committed
362
var:
363 364
        | i=DOLLAR_ID       { i }
        | i=AROBAS_ID       { i }
bguillaum's avatar
bguillaum committed
365

pj2m's avatar
pj2m committed
366
pos_item:
367
        | MATCH i=pn_item   { i }
pj2m's avatar
pj2m committed
368 369

neg_item:
370 371 372 373
        | WITHOUT i=pn_item { i }

pn_item:
        | l=delimited(LACC,separated_list_final_opt(SEMIC,pat_item),RACC)
374 375
            {
             {
bguillaum's avatar
bguillaum committed
376 377 378
              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;
379 380
            }
           }
pj2m's avatar
pj2m committed
381 382 383 384 385

/*=============================================================================================*/
/* MATCH DEFINITION                                                                            */
/*=============================================================================================*/
pat_item:
386 387
        | n=pat_node           { Pat_node n }
        | ec=pat_edge_or_const { ec }
pj2m's avatar
pj2m committed
388

389
pat_node:
390
        (* "R [cat=V, lemma=$lemma]" *)
bguillaum's avatar
bguillaum committed
391 392
        | id_loc=simple_id_with_loc feats=delimited(LBRACKET,separated_list_final_opt(COMA,node_features),RBRACKET)
            { ({Ast.node_id = fst id_loc; position=None; fs= feats}, snd id_loc) }
pj2m's avatar
pj2m committed
393 394

node_features:
395
        (*  "cat = n|v|adj"     *)
bguillaum's avatar
bguillaum committed
396
        | name_loc=simple_id_with_loc EQUAL values=separated_nonempty_list(PIPE,feature_value)
397 398 399 400
            { let (name,loc) = name_loc in
              match values with
              | ["*"] -> ({Ast.kind = Ast.Disequality []; name},loc)
              | _ -> ({Ast.kind = Ast.Equality values; name }, loc) }
401

bguillaum's avatar
bguillaum committed
402 403 404 405
        (*  "cat = *"           *)
        | name_loc=simple_id_with_loc EQUAL STAR
            { let (name,loc) = name_loc in ({Ast.kind = Ast.Disequality []; name},loc) }

bguillaum's avatar
bguillaum committed
406 407 408 409
        (*  "cat"           *)
        | name_loc=simple_id_with_loc
            { let (name,loc) = name_loc in ({Ast.kind = Ast.Disequality []; name},loc) }

410
        (*   "cat<>n|v|adj"     *)
bguillaum's avatar
bguillaum committed
411 412
        | 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) }
413

414
        (*   "lemma=$lem"       *)
bguillaum's avatar
bguillaum committed
415 416
        | name_loc=simple_id_with_loc EQUAL p=DOLLAR_ID
            { let (name,loc) = name_loc in ( {Ast.kind = Ast.Equal_param p; name }, loc) }
pj2m's avatar
pj2m committed
417

418
        (*   "!lemma"           *)
bguillaum's avatar
bguillaum committed
419 420
        | BANG name_loc=simple_id_with_loc
            { let (name,loc) = name_loc in ({Ast.kind = Ast.Absent; name}, loc) }
bguillaum's avatar
bguillaum committed
421

422 423
pat_edge_or_const:
        (*   "e: A -> B"           *)
424
        | id_loc=simple_id_with_loc DDOT n1=simple_id EDGE n2=simple_id
425
            { 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
426

427
        (* "e: A -[X|Y]-> B" *)
428
        | 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
429
            { 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
430

431 432
        (* "e: A -[^X|Y]-> B" *)
        | 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
433 434 435 436 437
            { 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) }

        (* "e: A -[re"regexp"]-> B" *)
        | 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) }
438 439

        (*   "A -> B"           *)
440
        | n1_loc=simple_id_with_loc EDGE n2=simple_id
441
            { let (n1,loc) = n1_loc in Pat_edge ({Ast.edge_id = None; src=n1; edge_label_cst=Ast.Neg_list []; tar=n2}, loc) }
442

443
        (*   "A -> *"           *)
444
        | n1_loc=simple_id_with_loc EDGE STAR
445
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Neg_list []), loc) }
446 447 448

        (*   "* -> B"           *)
        | STAR EDGE n2_loc=simple_id_with_loc
449
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,Ast.Neg_list []), loc) }
450

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

455
        (*   "A -[X|Y]-> *"   *)
456
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) STAR
457
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Pos_list labels), loc) }
458 459 460

        (*   "* -[X|Y]-> B"   *)
        | STAR labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) n2_loc=simple_id_with_loc
461
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,Ast.Pos_list labels), loc) }
462 463 464

        (* "A -[^X|Y]-> B" *)
        | 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
465 466 467 468 469
            { 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) }
470 471 472

        (* "A -[^X|Y]-> *" *)
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) STAR
473
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,Ast.Neg_list labels), loc) }
474 475 476

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

bguillaum's avatar
bguillaum committed
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
        (* X.cat = Y.cat *)
        (* X.cat = value *)
        | 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)
            }

        (* X.cat = "value" *)
        | 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) }

        (* X.cat = 12.34 *)
        | 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) }

        (* X.cat <> Y.cat *)
        (* X.cat <> value *)
        | 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)
            }

        (* X.cat <> "value" *)
        | 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) }

        (* X.cat <> 12.34 *)
        | 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) }
512

513

514 515
        (* "X.cat = re"regexp" " *)
        | feat_id_loc=feature_ident_with_loc EQUAL regexp=REGEXP
bguillaum's avatar
bguillaum committed
516 517
            { let (feat_id,loc)=feat_id_loc in Pat_const (Ast.Feature_re (feat_id, regexp), loc) }

bguillaum's avatar
bguillaum committed
518 519 520 521 522 523 524 525 526 527 528 529 530 531
        | id1_loc=ineq_value_with_loc LT id2=ineq_value
            { let (id1,loc)=id1_loc in
              match (id1, id2) with
              (* "X.feat < Y.feat" *)
              | (Ineq_sofi (n1, Some f1), Ineq_sofi (n2, Some f2)) -> Pat_const (Ast.Feature_ineq (Ast.Lt, (n1,f1), (n2,f2)), loc)
              (* "X.feat < 12.34" *)
              | (Ineq_sofi (n1, Some f1), Ineq_float num) -> Pat_const (Ast.Feature_ineq_cst (Ast.Lt, (n1,f1), num), loc)
              (* "12.34 < Y.feat" *)
              | (Ineq_float num, Ineq_sofi (n1, Some f1)) -> Pat_const (Ast.Feature_ineq_cst (Ast.Gt, (n1,f1), num), loc)
              (* "X < Y" *)
              | (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
532

bguillaum's avatar
bguillaum committed
533 534 535 536 537 538 539 540 541 542 543 544 545 546
        | id1_loc=ineq_value_with_loc GT id2=ineq_value
            { let (id1,loc)=id1_loc in
              match (id1, id2) with
              (* "X.feat > Y.feat" *)
              | (Ineq_sofi (n1, Some f1), Ineq_sofi (n2, Some f2)) -> Pat_const (Ast.Feature_ineq (Ast.Gt, (n1,f1), (n2,f2)), loc)
              (* "X.feat > 12.34" *)
              | (Ineq_sofi (n1, Some f1), Ineq_float num) -> Pat_const (Ast.Feature_ineq_cst (Ast.Gt, (n1,f1), num), loc)
              (* "12.34 > Y.feat" *)
              | (Ineq_float num, Ineq_sofi (n1, Some f1)) -> Pat_const (Ast.Feature_ineq_cst (Ast.Lt, (n1,f1), num), loc)
              (* "X > Y" *)
              | (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
547

548
        (* "X.position <= Y.position" *)
bguillaum's avatar
bguillaum committed
549
        | feat_id1_loc=feature_ident_with_loc LE feat_id2=feature_ident
550
            { 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
551

552
        (* "X.position >= Y.position" *)
bguillaum's avatar
bguillaum committed
553
        | feat_id1_loc=feature_ident_with_loc GE feat_id2=feature_ident
554
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_ineq (Ast.Ge, feat_id1, feat_id2), loc) }
555

556
        (* "X.feat >= 12.34" *)
bguillaum's avatar
bguillaum committed
557 558
        | feat_id1_loc=feature_ident_with_loc GE num=FLOAT
        | num=FLOAT LE feat_id1_loc=feature_ident_with_loc
559 560 561
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_ineq_cst (Ast.Ge, feat_id1, num), loc)  }

        (* "X.feat <= 12.34" *)
bguillaum's avatar
bguillaum committed
562 563
        | feat_id1_loc=feature_ident_with_loc LE num=FLOAT
        | num=FLOAT GE feat_id1_loc=feature_ident_with_loc
564 565
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_ineq_cst (Ast.Le, feat_id1, num), loc)  }

bguillaum's avatar
bguillaum committed
566 567 568 569 570 571 572
        (*   "A << B"           *)
        | n1_loc=simple_id_with_loc LPREC n2=simple_id
            { let (n1,loc) = n1_loc in Pat_const (Ast.Lprec (n1,n2), loc) }

        (*   "A >> B"           *)
        | 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
573

pj2m's avatar
pj2m committed
574 575 576 577
/*=============================================================================================*/
/* COMMANDS DEFINITION                                                                         */
/*=============================================================================================*/
commands:
578
        | COMMANDS x=delimited(LACC,separated_nonempty_list_final_opt(SEMIC,command),RACC) { x }
579

pj2m's avatar
pj2m committed
580
command:
Bruno Guillaume's avatar
Bruno Guillaume committed
581
        (* del_edge e *)
bguillaum's avatar
bguillaum committed
582 583
        | 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
584 585

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

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

593
        (* "shift_in m ==> n" *)
bguillaum's avatar
bguillaum committed
594
        | SHIFT_IN src_loc=simple_id_with_loc ARROW tar=simple_id
595
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, Ast.Neg_list []), loc) }
596 597

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

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

        (* "shift_out m ==> n" *)
bguillaum's avatar
bguillaum committed
610
        | SHIFT_OUT src_loc=simple_id_with_loc ARROW tar=simple_id
611
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, Ast.Neg_list []), loc) }
612 613

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

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

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

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

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

        (* merge m ==> n *)
bguillaum's avatar
bguillaum committed
642
        | MERGE src_loc=simple_id_with_loc ARROW tar=simple_id
643
            { let (src,loc) = src_loc in (Ast.Merge_node (src, tar), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
644 645

        (* del_node n *)
bguillaum's avatar
bguillaum committed
646
        | DEL_NODE ci_loc=simple_id_with_loc
647
            { let (ci,loc) = ci_loc in (Ast.Del_node (ci), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
648 649

        (* add_node n: <-[x]- m *)
bguillaum's avatar
bguillaum committed
650
        | ADD_NODE new_ci_loc=simple_id_with_loc DDOT label=delimited(RTL_EDGE_LEFT,label_ident,RTL_EDGE_RIGHT) anc_ci=simple_id
651
            { let (new_ci,loc) = new_ci_loc in (Ast.New_neighbour (new_ci, anc_ci,label), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
652

bguillaum's avatar
bguillaum committed
653 654 655 656 657 658 659 660 661 662 663 664
        (* add_node n *)
        | ADD_NODE new_ci_loc=simple_id_with_loc
            { let (new_ci,loc) = new_ci_loc in (Ast.New_node new_ci, loc) }

        (* add_node n :< m *)
        | 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) }

        (* add_node n :> m *)
        | 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) }

Bruno Guillaume's avatar
Bruno Guillaume committed
665
        (* del_feat m.cat *)
bguillaum's avatar
bguillaum committed
666
        | DEL_FEAT com_fead_id_loc= feature_ident_with_loc
667
            { let (com_fead_id,loc) = com_fead_id_loc in (Ast.Del_feat com_fead_id, loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
668 669

        (* m.cat = n.x + "_" + nn.y *)
bguillaum's avatar
bguillaum committed
670
        | com_fead_id_loc= feature_ident_with_loc EQUAL items=separated_nonempty_list (PLUS, concat_item)
671
            { let (com_fead_id,loc) = com_fead_id_loc in (Ast.Update_feat (com_fead_id, items), loc) }
672 673

concat_item:
674
        | gi=ID            { if Ast.is_simple_ident gi then Ast.String_item gi else Ast.Qfn_item (Ast.parse_feature_ident gi) }
675
        | s=STRING         { Ast.String_item s }
676
        | f=FLOAT          { Ast.String_item (Printf.sprintf "%g" f) }
677 678 679
        | p=AROBAS_ID      { Ast.Param_item p }
        | p=DOLLAR_ID      { Ast.Param_item p }

pj2m's avatar
pj2m committed
680 681 682 683 684

/*=============================================================================================*/
/* SEQUENCE DEFINITION                                                                         */
/*=============================================================================================*/
sequences:
685
        | SEQUENCES seq=delimited(LACC,list(sequence),RACC) { seq }
pj2m's avatar
pj2m committed
686 687

sequence:
688
        (* sequence { ant; p7_to_p7p-mc} *)
689
/*        | doc=option(COMMENT) id_loc=simple_id_with_loc mod_names=delimited(LACC,separated_list_final_opt(SEMIC,simple_id),RACC)
690 691
            {
              { Ast.seq_name = fst id_loc;
692 693
                seq_mod = mod_names;*/

694
        | doc = option(COMMENT) id_loc=simple_id_with_loc mod_names=delimited(LACC,separated_list_final_opt(SEMIC,simple_id),RACC)
bguillaum's avatar
bguillaum committed
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
            { let (name,loc) = id_loc in
              {
                Strategy.name;
                def = Strategy.Seq (List.map (fun m -> Strategy.Ref m) mod_names);
                doc = begin match doc with Some d -> d | None -> [] end;
                loc;
              }
            }
        | doc = option(COMMENT) id_loc=simple_id_with_loc EQUAL def=op_seq
            { let (name,loc) = id_loc in
              {
                Strategy.name;
                def;
                doc = begin match doc with Some d -> d | None -> [] end;
                loc;
710
              }
711
            }
712 713

op_seq:
bguillaum's avatar
bguillaum committed
714
        | m=simple_id               { Strategy.Ref m }
715
        | LPAREN s=op_seq RPAREN    { s }
bguillaum's avatar
bguillaum committed
716 717 718 719
        | s=op_seq STAR             { Strategy.Star (s) }
        | s1=op_seq PLUS s2=op_seq  { Strategy.Plus [s1; s2] }
        | s1=op_seq SEMIC s2=op_seq { Strategy.Seq [s1; s2] }
        | DISEQUAL s=op_seq         { Strategy.Diamond s }
720

bguillaum's avatar
bguillaum committed
721 722

/*=============================================================================================*/
bguillaum's avatar
bguillaum committed
723
/* ISOLATED PATTERN (grep mode)                                                                */
bguillaum's avatar
bguillaum committed
724
/*=============================================================================================*/
725
pattern:
726
        | p=pos_item n=list(neg_item) EOF { Ast.complete_pattern {Ast.pat_pos=p; pat_negs=n} }
pj2m's avatar
pj2m committed
727
%%