grew_parser.mly 30.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
%token EQUAL                       /* = */
bguillaum's avatar
bguillaum committed
47
%token REGEXP                      /* == */
48
%token DISEQUAL                    /* <> */
bguillaum's avatar
bguillaum committed
49
%token BANG                        /* ! */
50
%token STAR                        /* * */
bguillaum's avatar
bguillaum committed
51 52 53 54
%token LT                          /* < */
%token GT                          /* > */
%token LE                          /* <= or  */
%token GE                          /* >= or  */
bguillaum's avatar
bguillaum committed
55 56
%token LPREC                       /* << */
%token LSUCC                       /* >> */
bguillaum's avatar
bguillaum committed
57

58
%token PIPE                        /* | */
59

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

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

72
%token DOMAIN                      /* domain */
bguillaum's avatar
bguillaum committed
73
%token INCL                        /* include */
74
%token FEATURES                    /* features */
bguillaum's avatar
bguillaum committed
75 76
%token FEATURE                     /* feature */
%token FILE                        /* file */
77
%token LABELS                      /* labels */
78
%token SUFFIXES                    /* suffixes */
79
%token ACTIVATE                    /* activate */
80 81 82 83 84 85
%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 <float>            FLOAT
bguillaum's avatar
bguillaum committed
110
%token <string list>      COMMENT
bguillaum's avatar
bguillaum committed
111
%token <string list>      LEX_PAR
pj2m's avatar
pj2m committed
112

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

115
%start <Grew_ast.Ast.grs_wi> grs_wi
bguillaum's avatar
bguillaum committed
116
%start <Grew_ast.Ast.gr> gr
117
%start <Grew_ast.Ast.module_or_include list> included
118
%start <Grew_ast.Ast.pattern> pattern
119
%start <Grew_ast.Ast.domain> domain
120 121 122 123 124

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

bguillaum's avatar
bguillaum committed
127 128 129 130

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

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

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

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

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

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

151
simple_id_with_loc:
152 153 154 155 156 157 158 159 160 161
        | id=ID       { localize (Ast.parse_simple_ident id) }

command_node_ident :
        | id=ID       { Ast.parse_command_node_ident id }

command_node_ident_with_loc :
        | id=ID       { localize (Ast.parse_command_node_ident id) }

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

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

166 167 168 169 170 171 172
command_feature_ident_with_loc :
        | id=ID      { localize (Ast.parse_command_feature_ident id) }

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

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

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

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

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

bguillaum's avatar
bguillaum committed
206
        (* A -[x]-> B *)
bguillaum's avatar
bguillaum committed
207
        | n1_loc=simple_id_with_loc label=delimited(LTR_EDGE_LEFT,label_ident,LTR_EDGE_RIGHT) n2=simple_id
bguillaum's avatar
bguillaum committed
208
            { Graph_edge ({Ast.edge_id = None; src=fst n1_loc; edge_label_cst=([label],false); tar=n2}, snd n1_loc) }
pj2m's avatar
pj2m committed
209

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

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

240
module_or_include_list:
241
        | x=list(module_or_include) { x }
242 243

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

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

/*=============================================================================================*/
/* FEATURES DOMAIN DEFINITION                                                                  */
/*=============================================================================================*/
features_group:
254 255
        | FEATURES x=features { x }

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

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

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

pj2m's avatar
pj2m committed
273
feature_name:
274
        | ci=ID { ci }
pj2m's avatar
pj2m committed
275 276

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

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

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

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

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

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

315 316
suffixes:
        (* "suffixes {a, b, c}" *)
bguillaum's avatar
bguillaum committed
317 318
        | SUFFIXES x=delimited(LACC,separated_nonempty_list_final_opt(COMA,simple_id),RACC)
            { x }
319

pj2m's avatar
pj2m committed
320 321 322 323 324

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

327 328 329 330
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;
331
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
bguillaum's avatar
bguillaum committed
332
                commands = cmds;
bguillaum's avatar
bguillaum committed
333
                param = None;
bguillaum's avatar
bguillaum committed
334
                lex_par = None;
bguillaum's avatar
bguillaum committed
335
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
336
                rule_loc = snd id_loc;
337
              }
338
            }
339
        | 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)
340 341
            {
              { Ast.rule_id = fst id_loc;
342
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
bguillaum's avatar
bguillaum committed
343
                commands = cmds;
344
                param = Some param;
bguillaum's avatar
bguillaum committed
345
                lex_par = lex_par;
bguillaum's avatar
bguillaum committed
346
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
347
                rule_loc = snd id_loc;
bguillaum's avatar
bguillaum committed
348
              }
349 350 351 352
            }
        | 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;
353
                pattern = Ast.complete_pattern { Ast.pat_pos = p; Ast.pat_negs = n };
354 355
                commands = [];
                param = None;
bguillaum's avatar
bguillaum committed
356
                lex_par = None;
bguillaum's avatar
bguillaum committed
357
                rule_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
358
                rule_loc = snd id_loc;
359 360
              }
            }
361

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

bguillaum's avatar
bguillaum committed
365
param:
366 367
        | 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
368

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

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

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

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

/*=============================================================================================*/
/* MATCH DEFINITION                                                                            */
/*=============================================================================================*/
pat_item:
395 396
        | n=pat_node           { Pat_node n }
        | ec=pat_edge_or_const { ec }
pj2m's avatar
pj2m committed
397

398
pat_node:
399
        (* "R [cat=V, lemma=$lemma]" *)
bguillaum's avatar
bguillaum committed
400 401
        | 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
402 403

node_features:
404 405
        (*  "cat = n|v|adj"     *)
        (*  "cat = *"           *)
bguillaum's avatar
bguillaum committed
406
        | name_loc=simple_id_with_loc EQUAL values=separated_nonempty_list(PIPE,feature_value)
407 408 409 410
            { let (name,loc) = name_loc in
              match values with
              | ["*"] -> ({Ast.kind = Ast.Disequality []; name},loc)
              | _ -> ({Ast.kind = Ast.Equality values; name }, loc) }
411

bguillaum's avatar
bguillaum committed
412 413 414 415
        (*  "cat = *"           *)
        | name_loc=simple_id_with_loc EQUAL STAR
            { let (name,loc) = name_loc in ({Ast.kind = Ast.Disequality []; name},loc) }

416
        (*   "cat<>n|v|adj"     *)
bguillaum's avatar
bguillaum committed
417 418
        | 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) }
419

420
        (*   "lemma=$lem"       *)
bguillaum's avatar
bguillaum committed
421 422
        | 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
423

424
        (*   "!lemma"           *)
bguillaum's avatar
bguillaum committed
425 426
        | BANG name_loc=simple_id_with_loc
            { let (name,loc) = name_loc in ({Ast.kind = Ast.Absent; name}, loc) }
bguillaum's avatar
bguillaum committed
427

428 429
pat_edge_or_const:
        (*   "e: A -> B"           *)
430
        | id_loc=simple_id_with_loc DDOT n1=simple_id EDGE n2=simple_id
bguillaum's avatar
bguillaum committed
431
            { let (id,loc) = id_loc in Pat_edge ({Ast.edge_id = Some id; src=n1; edge_label_cst=([],true); tar=n2}, loc) }
pj2m's avatar
pj2m committed
432

433
        (* "e: A -[X|Y]-> B" *)
434
        | 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
bguillaum's avatar
bguillaum committed
435
            { let (id,loc) = id_loc in Pat_edge ({Ast.edge_id = Some id; src=n1; edge_label_cst=(labels,false); tar=n2}, loc) }
pj2m's avatar
pj2m committed
436

437 438
        (* "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
bguillaum's avatar
bguillaum committed
439
            { let (id,loc) = id_loc in Pat_edge ({Ast.edge_id = Some id; src=n1; edge_label_cst=(labels,true); tar=n2}, loc) }
440 441

        (*   "A -> B"           *)
442 443 444
        | 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=([],true); tar=n2}, loc) }

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

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

453
        (*   "A -[X|Y]-> B"   *)
454 455 456
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,pattern_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=(labels,false); tar=n2}, loc) }

457
        (*   "A -[X|Y]-> *"   *)
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
        | n1_loc=simple_id_with_loc labels=delimited(LTR_EDGE_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),LTR_EDGE_RIGHT) STAR
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,(labels,false)), loc) }

        (*   "* -[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
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,(labels,false)), loc) }


        (* "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
            { let (n1,loc) = n1_loc in Pat_edge ({Ast.edge_id = None; src=n1; edge_label_cst=(labels,true); tar=n2}, loc) }

        (* "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
            { let (n1,loc) = n1_loc in Pat_const (Ast.Cst_out (n1,(labels,true)), loc) }

        (* "* -[^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
            { let (n2,loc) = n2_loc in Pat_const (Ast.Cst_in (n2,(labels,true)), loc) }
pj2m's avatar
pj2m committed
477

478 479 480
        (* "X.cat = Y.cat" *)
        | feat_id1_loc=feature_ident_with_loc EQUAL feat_id2=feature_ident
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_eq (feat_id1, feat_id2), loc) }
481

482 483 484 485
        (* "X.cat <> Y.cat" *)
        | feat_id1_loc=feature_ident_with_loc DISEQUAL feat_id2=feature_ident
            { let (feat_id1,loc)=feat_id1_loc in Pat_const (Ast.Feature_diseq (feat_id1, feat_id2), loc) }

bguillaum's avatar
bguillaum committed
486 487 488 489
        (* "X.cat == "regexp" " *)
        | feat_id_loc=feature_ident_with_loc REGEXP regexp=STRING
            { let (feat_id,loc)=feat_id_loc in Pat_const (Ast.Feature_re (feat_id, regexp), loc) }

bguillaum's avatar
bguillaum committed
490 491 492 493 494 495 496 497 498 499 500 501 502 503
        | 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
504

bguillaum's avatar
bguillaum committed
505 506 507 508 509 510 511 512 513 514 515 516 517 518
        | 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
519

520
        (* "X.position <= Y.position" *)
bguillaum's avatar
bguillaum committed
521
        | feat_id1_loc=feature_ident_with_loc LE feat_id2=feature_ident
522
            { 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
523

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

528
        (* "X.feat >= 12.34" *)
bguillaum's avatar
bguillaum committed
529 530
        | feat_id1_loc=feature_ident_with_loc GE num=FLOAT
        | num=FLOAT LE feat_id1_loc=feature_ident_with_loc
531 532 533
            { 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
534 535
        | feat_id1_loc=feature_ident_with_loc LE num=FLOAT
        | num=FLOAT GE feat_id1_loc=feature_ident_with_loc
536 537
            { 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
538 539 540 541 542 543 544
        (*   "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
545

pj2m's avatar
pj2m committed
546 547 548 549
/*=============================================================================================*/
/* COMMANDS DEFINITION                                                                         */
/*=============================================================================================*/
commands:
550
        | COMMANDS x=delimited(LACC,separated_nonempty_list_final_opt(SEMIC,command),RACC) { x }
551

pj2m's avatar
pj2m committed
552
command:
Bruno Guillaume's avatar
Bruno Guillaume committed
553
        (* del_edge e *)
bguillaum's avatar
bguillaum committed
554 555
        | 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
556 557

        (* del_edge m -[x]-> n *)
558 559
        | DEL_EDGE src_loc=command_node_ident_with_loc label=delimited(LTR_EDGE_LEFT,label_ident,LTR_EDGE_RIGHT) tar=command_node_ident
            { let (src,loc) = src_loc in (Ast.Del_edge_expl (src, tar, label), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
560 561

        (* add_edge m -[x]-> n *)
562 563
        | ADD_EDGE src_loc=command_node_ident_with_loc label=delimited(LTR_EDGE_LEFT,label_ident,LTR_EDGE_RIGHT) tar=command_node_ident
            { let (src,loc) = src_loc in (Ast.Add_edge (src, tar, label), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
564

565 566
        (* "shift_in m ==> n" *)
        | SHIFT_IN src_loc=command_node_ident_with_loc ARROW tar=command_node_ident
bguillaum's avatar
bguillaum committed
567
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, ([], true)), loc) }
568 569 570 571 572

        (* "shift_in m =[x*|y]=> n" *)
        | SHIFT_IN src_loc=command_node_ident_with_loc 
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
          tar=command_node_ident
bguillaum's avatar
bguillaum committed
573
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, (labels, false)), loc) }
574 575 576 577 578

        (* "shift_in m =[^x*|y]=> n" *)
        | SHIFT_IN src_loc=command_node_ident_with_loc 
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
          tar=command_node_ident
bguillaum's avatar
bguillaum committed
579
            { let (src,loc) = src_loc in (Ast.Shift_in (src, tar, (labels, true)), loc) }
580 581 582 583


        (* "shift_out m ==> n" *)
        | SHIFT_OUT src_loc=command_node_ident_with_loc ARROW tar=command_node_ident
bguillaum's avatar
bguillaum committed
584
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, ([], true)), loc) }
585 586 587 588 589

        (* "shift_out m =[x*|y]=> n" *)
        | SHIFT_OUT src_loc=command_node_ident_with_loc 
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
          tar=command_node_ident
bguillaum's avatar
bguillaum committed
590
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, (labels, false)), loc) }
591 592 593 594 595

        (* "shift_out m =[^x*|y]=> n" *)
        | SHIFT_OUT src_loc=command_node_ident_with_loc 
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
          tar=command_node_ident
bguillaum's avatar
bguillaum committed
596
            { let (src,loc) = src_loc in (Ast.Shift_out (src, tar, (labels, true)), loc) }
597 598 599 600


        (* "shift m ==> n" *)
        | SHIFT src_loc=command_node_ident_with_loc ARROW tar=command_node_ident
bguillaum's avatar
bguillaum committed
601
            { let (src,loc) = src_loc in (Ast.Shift_edge (src, tar, ([], true)), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
602

603 604 605 606
        (* "shift m =[x*|y]=> n" *)
        | SHIFT src_loc=command_node_ident_with_loc 
          labels=delimited(ARROW_LEFT,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
          tar=command_node_ident
bguillaum's avatar
bguillaum committed
607
            { let (src,loc) = src_loc in (Ast.Shift_edge (src, tar, (labels, false)), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
608

609 610 611 612
        (* "shift m =[^x*|y]=> n" *)
        | SHIFT src_loc=command_node_ident_with_loc 
          labels=delimited(ARROW_LEFT_NEG,separated_nonempty_list(PIPE,pattern_label_ident),ARROW_RIGHT)
          tar=command_node_ident
bguillaum's avatar
bguillaum committed
613
            { let (src,loc) = src_loc in (Ast.Shift_edge (src, tar, (labels, true)), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
614 615

        (* merge m ==> n *)
616
        | MERGE src_loc=command_node_ident_with_loc ARROW tar=command_node_ident
617
            { let (src,loc) = src_loc in (Ast.Merge_node (src, tar), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
618 619

        (* del_node n *)
620 621
        | DEL_NODE ci_loc=command_node_ident_with_loc
            { let (ci,loc) = ci_loc in (Ast.Del_node (ci), loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
622 623

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

627
        (* activate n#a *)
628 629
        | ACTIVATE ci_loc= command_node_ident_with_loc
            { let (ci,loc) = ci_loc in (Ast.Activate ci, loc) }
630

Bruno Guillaume's avatar
Bruno Guillaume committed
631
        (* del_feat m.cat *)
632 633
        | DEL_FEAT com_fead_id_loc= command_feature_ident_with_loc
            { let (com_fead_id,loc) = com_fead_id_loc in (Ast.Del_feat com_fead_id, loc) }
Bruno Guillaume's avatar
Bruno Guillaume committed
634 635

        (* m.cat = n.x + "_" + nn.y *)
636 637
        | com_fead_id_loc= command_feature_ident_with_loc EQUAL items=separated_nonempty_list (PLUS, concat_item)
            { let (com_fead_id,loc) = com_fead_id_loc in (Ast.Update_feat (com_fead_id, items), loc) }
638 639

concat_item:
640
        | gi=ID            { if Ast.is_simple_ident gi then Ast.String_item gi else Ast.Qfn_item (Ast.parse_feature_ident gi) }
641
        | s=STRING         { Ast.String_item s }
642
        | f=FLOAT          { Ast.String_item (Printf.sprintf "%g" f) }
643 644 645
        | p=AROBAS_ID      { Ast.Param_item p }
        | p=DOLLAR_ID      { Ast.Param_item p }

pj2m's avatar
pj2m committed
646 647 648 649 650

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

sequence:
654
        (* sequence { ant; p7_to_p7p-mc} *)
655
/*        | doc=option(COMMENT) id_loc=simple_id_with_loc mod_names=delimited(LACC,separated_list_final_opt(SEMIC,simple_id),RACC)
656 657
            {
              { Ast.seq_name = fst id_loc;
658 659
                seq_mod = mod_names;*/

660
        | doc = option(COMMENT) id_loc=simple_id_with_loc mod_names=delimited(LACC,separated_list_final_opt(SEMIC,simple_id),RACC)
661 662
            {
              Ast.Old { Ast.seq_name = fst id_loc;
663
                seq_mod = mod_names ;
664
                seq_doc = begin match doc with Some d -> d | None -> [] end;
bguillaum's avatar
bguillaum committed
665
                seq_loc = snd id_loc;
666
              }
667
            }
668 669 670
        | doc = option(COMMENT) id_loc=simple_id_with_loc EQUAL s=op_seq { Ast.New (id_loc, s) }

op_seq:
671
        | m=simple_id               { Ast.Ref m }
672 673 674 675 676 677
        | LPAREN s=op_seq RPAREN    { s }
        | s=op_seq STAR             { Ast.Star (s) }
        | s1=op_seq PLUS s2=op_seq  { Ast.Plus [s1; s2] }
        | s1=op_seq SEMIC s2=op_seq { Ast.List [s1; s2] }
        | DISEQUAL s=op_seq         { Ast.Diamond s }

bguillaum's avatar
bguillaum committed
678 679 680 681

/*=============================================================================================*/
/* ISOLATED PATTERN (grep mode)                                                                 */
/*=============================================================================================*/
682
pattern:
683
        | p=pos_item n=list(neg_item) EOF { Ast.complete_pattern {Ast.pat_pos=p; pat_negs=n} }
pj2m's avatar
pj2m committed
684
%%