/* The grammar for lexer definitions */

%{
open List Syntax Gram_aux;
%}

%token <Syntax.location> Taction
%token Tand Tcaret
%token <char> Tchar
%token Tdash Tend Teof Tequal
%token <string> Tident
%token Tlbracket Tlet Tlparen Tmaybe Tor Tparse Tplus
%token Trbracket Trparen Trule Tstar
%token <string> Tstring
%token Tunderscore

%left Tor
%left CONCAT
%nonassoc Tmaybe
%left Tstar
%left Tplus

%start lexer_definition
%type <Syntax.lexer_definition> lexer_definition
%type <Syntax.location> header
%type <(string * (Syntax.regular_expression * Syntax.location) list) list>
	other_definitions
%type <string * (Syntax.regular_expression * Syntax.location) list>
	definition
%type <(Syntax.regular_expression * Syntax.location) list>
	entry rest_of_entry
%type <(string * Syntax.regular_expression) list>
	letdef_list
%type <(string * Syntax.regular_expression)>
	letdef
%type <Syntax.regular_expression * Syntax.location> case
%type <Syntax.regular_expression> regexp
%type <char list> char_class char_class1

%%

lexer_definition:
    header letdef_list Trule definition other_definitions Tend
        { Lexdef($1, $2, $4::(rev $5)) }
;
header:
    Taction
        { $1 }
  |
        { Location(0,0) }
;
letdef_list:
    letdef letdef_list 
	{ $1::$2 }
  | 
	{ [] }
;
letdef:
    Tlet Tident Tequal regexp
	{ ($2,$4) }
;

other_definitions:
    other_definitions Tand definition
        { $3::$1 }
  |
        { [] }
;
definition:
    Tident Tequal entry
        { ($1,$3) }
;
entry:
    Tparse case rest_of_entry
        { $2::rev $3 }
;
rest_of_entry:
    rest_of_entry Tor case
        { $3::$1 }
  |
        { [] }
;
case:
    regexp Taction
        { ($1,$2) }
;
regexp:
    Tunderscore
        { Characters all_chars }
  | Teof
        { Characters [#"\000"] }
  | Tchar
        { Characters [$1] }
  | Tstring
        { regexp_for_string $1 }
  | Tident
	{ Name $1 }
  | Tlbracket char_class Trbracket
        { Characters $2 }
  | regexp Tstar
        { Repetition $1 }
  | regexp Tmaybe
        { Alternative($1, Epsilon) }
  | regexp Tplus
        { Sequence($1, Repetition $1) }
  | regexp Tor regexp
        { Alternative($1,$3) }
  | regexp regexp %prec CONCAT
        { Sequence($1,$2) }
  | Tlparen regexp Trparen
        { $2 }
;
char_class:
    Tcaret char_class1
        { subtract all_chars $2 }
  | char_class1
        { $1 }
;
char_class1:
    Tchar Tdash Tchar char_class1
        { char_class $1 $3 @ $4 }
  | Tchar char_class1
        { $1 :: $2 }
  | /* */
        { [] }
;

%%

