|
/************************************************************************/
/* * The Rocq Prover / The Rocq Development Team */
/* v * Copyright INRIA, CNRS and contributors */
/* <O___,, * (see version control and CREDITS file for authors & dates) */
/* \VV/ **************************************************************/
/* // * This file is distributed under the terms of the */
/* * GNU Lesser General Public License Version 2.1 */
/* * (see LICENSE file for the text of the license) */
/************************************************************************/
%{
open Coqpp_ast
let starts s pat =
let len = String.length s in
let patlen = String.length pat in
if patlen <= len && String.sub s 0 patlen = pat then
Some (String.sub s patlen (len - patlen))
else None
let ends s pat =
let len = String.length s in
let patlen = String.length pat in
if patlen <= len && String.sub s (len - patlen) patlen = pat then
Some (String.sub s 0 (len - patlen))
else None
let between s pat1 pat2 = match starts s pat1 with
| None -> None
| Some s -> ends s pat2
let without_sep k sep r =
if sep <> "" then raise Parsing.Parse_error else k r
let parse_user_entry s sep =
let table = [
"ne_", "_list", without_sep (fun r -> Ulist1 r);
"ne_", "_list_sep", (fun sep r -> Ulist1sep (r, sep));
"", "_list", without_sep (fun r -> Ulist0 r);
"", "_list_sep", (fun sep r -> Ulist0sep (r, sep));
"", "_opt", without_sep (fun r -> Uopt r);
] in
let rec parse s sep = function
| [] ->
let () = without_sep ignore sep () in
begin match starts s "tactic" with
| Some ("0"|"1"|"2"|"3"|"4"|"5" as s) -> Uentryl ("tactic", int_of_string s)
| Some _ | None -> Uentry s
end
| (pat1, pat2, k) :: rem ->
match between s pat1 pat2 with
| None -> parse s sep rem
| Some s ->
let r = parse s "" table in
k sep r
in
parse s sep table
let rhs_loc n =
{ loc_start = Parsing.rhs_start_pos n; loc_end = Parsing.rhs_end_pos n }
%}
%token <Coqpp_ast.code> CODE
%token <string> COMMENT
%token <string> IDENT QUALID
%token <string> STRING
%token <int> INT
%token VERNAC TACTIC GRAMMAR DOC_GRAMMAR EXTEND END DECLARE PLUGIN DEPRECATED ARGUMENT
%token RAW_PRINTED GLOB_PRINTED
%token SYNTERP COMMAND CLASSIFIED STATE PRINTED TYPED INTERPRETED GLOBALIZED SUBSTITUTED BY AS
%token BANGBRACKET HASHBRACKET LBRACKET RBRACKET PIPE ARROW FUN COMMA EQUAL STAR
%token LPAREN RPAREN COLON SEMICOLON
%token GLOBAL TOP FIRST LAST BEFORE AFTER LEVEL LEFTA RIGHTA NONA
%token EOF
%type <Coqpp_ast.t> file
%start file
%%
file:
| nodes EOF
{ $1 }
;
nodes:
|
{ [] }
| node nodes
{ $1 :: $2 }
;
node:
| CODE { Code $1 }
| COMMENT { Comment $1 }
| declare_plugin { $1 }
| grammar_extend { $1 }
| vernac_extend { $1 }
| tactic_extend { $1 }
| argument_extend { $1 }
| doc_gram { $1 }
;
declare_plugin:
| DECLARE PLUGIN STRING { DeclarePlugin (Some $3) }
| DECLARE GLOBAL PLUGIN { DeclarePlugin None }
;
grammar_extend:
| GRAMMAR EXTEND qualid_or_ident globals gram_entries END
{ GramExt { gramext_name = $3; gramext_globals = $4; gramext_entries = $5 } }
;
argument_extend:
| ARGUMENT EXTEND IDENT
typed_opt
printed_opt
interpreted_opt
globalized_opt
substituted_opt
raw_printed_opt
glob_printed_opt
tactic_rules
END
{ ArgumentExt {
argext_name = $3;
argext_rules = $11;
argext_rprinter = $9;
argext_gprinter = $10;
argext_tprinter = $5;
argext_interp = $6;
argext_glob = $7;
argext_subst = $8;
argext_type = $4;
} }
| VERNAC ARGUMENT EXTEND IDENT printed_opt tactic_rules END
{ VernacArgumentExt {
vernacargext_name = $4;
vernacargext_printer = $5;
vernacargext_rules = $6;
} }
;
printed_opt:
| { None }
| PRINTED BY CODE { Some $3 }
;
raw_printed_opt:
| { None }
| RAW_PRINTED BY CODE { Some $3 }
;
glob_printed_opt:
| { None }
| GLOB_PRINTED BY CODE { Some $3 }
;
interpreted_modifier_opt:
| { None }
| LBRACKET IDENT RBRACKET { Some $2 }
;
interpreted_opt:
| { None }
| INTERPRETED interpreted_modifier_opt BY CODE { Some ($2,$4) }
;
globalized_opt:
| { None }
| GLOBALIZED BY CODE { Some $3 }
;
substituted_opt:
| { None }
| SUBSTITUTED BY CODE { Some $3 }
;
typed_opt:
| { None }
| TYPED AS argtype { Some $3 }
;
argtype:
| IDENT { ExtraArgType $1 }
| argtype IDENT {
match $2 with
| "list" -> ListArgType $1
| "option" -> OptArgType $1
| _ -> raise Parsing.Parse_error
}
| LPAREN argtype STAR argtype RPAREN { PairArgType ($2, $4) }
;
vernac_extend:
| VERNAC vernac_entry EXTEND IDENT vernac_classifier vernac_state vernac_rules END
{ VernacExt {
vernacext_name = $4;
vernacext_entry = $2;
vernacext_class = $5;
vernacext_state = $6;
vernacext_rules = $7;
} }
;
vernac_entry:
| COMMAND { None }
| CODE { Some $1 }
;
vernac_classifier:
| { ClassifDefault }
| CLASSIFIED BY CODE { ClassifCode $3 }
| CLASSIFIED AS IDENT { ClassifName $3 }
;
vernac_state:
| { None }
| STATE IDENT { Some $2 }
;
vernac_rules:
| vernac_rule { [$1] }
| vernac_rule vernac_rules { $1 :: $2 }
;
vernac_rule:
| PIPE vernac_attributes_opt rule_state LBRACKET ext_tokens RBRACKET rule_deprecation rule_classifier synterp_fun ARROW CODE
{ {
vernac_atts = $2;
vernac_state = $3;
vernac_toks = $5;
vernac_depr = $7;
vernac_class= $8;
vernac_synterp = $9;
vernac_body = $11;
} }
;
rule_state:
| { None }
| BANGBRACKET IDENT RBRACKET { Some $2 }
;
vernac_attributes_opt:
| { None }
| HASHBRACKET vernac_attributes RBRACKET { Some $2 }
;
vernac_attributes:
| vernac_attribute { [$1] }
| vernac_attribute SEMICOLON { [$1] }
| vernac_attribute SEMICOLON vernac_attributes { $1 :: $3 }
;
vernac_attribute:
| qualid_or_ident EQUAL qualid_or_ident {
($1, { code = $3; loc = Some (rhs_loc 3) }) }
| qualid_or_ident { ($1, { code = $1; loc = Some (rhs_loc 1) }) }
;
rule_deprecation:
| { false }
| DEPRECATED { true }
;
rule_classifier:
| { None }
| FUN CODE { Some $2 }
;
synterp_fun:
| { None }
| SYNTERP AS IDENT CODE { Some ($3,$4) }
tactic_extend:
| TACTIC EXTEND IDENT tactic_deprecated tactic_level tactic_rules END
{ TacticExt { tacext_name = $3; tacext_deprecated = $4; tacext_level = $5; tacext_rules = $6 } }
;
tactic_deprecated:
| { None }
| DEPRECATED CODE { Some $2 }
;
tactic_level:
| { None }
| LEVEL INT { Some $2 }
;
tactic_rules:
| { [] }
| tactic_rule tactic_rules { $1 :: $2 }
;
tactic_rule:
| PIPE LBRACKET ext_tokens RBRACKET ARROW CODE
{ { tac_toks = $3; tac_body = $6 } }
;
ext_tokens:
| { [] }
| ext_token ext_tokens { $1 :: $2 }
;
ext_token:
| STRING { ExtTerminal $1 }
| IDENT {
let e = parse_user_entry $1 "" in
ExtNonTerminal (e, TokNone)
}
| IDENT LPAREN IDENT RPAREN {
let e = parse_user_entry $1 "" in
ExtNonTerminal (e, TokName $3)
}
| IDENT LPAREN IDENT COMMA STRING RPAREN {
let e = parse_user_entry $1 $5 in
ExtNonTerminal (e, TokName $3)
}
;
qualid_or_ident:
| QUALID { $1 }
| IDENT { $1 }
;
globals:
| { [] }
| GLOBAL COLON idents SEMICOLON { $3 }
;
idents:
| { [] }
| qualid_or_ident idents { $1 :: $2 }
;
gram_entries:
| { [] }
| gram_entry gram_entries { $1 :: $2 }
;
gram_entry:
| qualid_or_ident COLON reuse LBRACKET LBRACKET rules_opt RBRACKET RBRACKET SEMICOLON
{ { gentry_name = $1; gentry_rules = GDataReuse ($3, $6); } }
| qualid_or_ident COLON position_opt LBRACKET levels RBRACKET SEMICOLON
{ { gentry_name = $1; gentry_rules = GDataFresh ($3, $5); } }
;
reuse:
| TOP { None }
| LEVEL STRING { Some $2 }
;
position_opt:
| { None }
| position { Some $1 }
;
position:
| FIRST { First }
| LAST { Last }
| BEFORE STRING { Before $2 }
| AFTER STRING { After $2 }
;
string_opt:
| { None }
| STRING { Some $1 }
;
assoc_opt:
| { None }
| assoc { Some $1 }
;
assoc:
| LEFTA { LeftA }
| RIGHTA { RightA }
| NONA { NonA }
;
levels:
| level { [$1] }
| level PIPE levels { $1 :: $3 }
;
level:
| string_opt assoc_opt LBRACKET rules_opt RBRACKET
{ { grule_label = $1; grule_assoc = $2; grule_prods = $4; } }
;
rules_opt:
| { [] }
| rules { $1 }
;
rules:
| rule { [$1] }
| rule PIPE rules { $1 :: $3 }
;
rule:
| symbols_opt ARROW CODE
{ { gprod_symbs = $1; gprod_body = $3; } }
;
symbols_opt:
| { [] }
| symbols { $1 }
;
symbols:
| symbol { [$1] }
| symbol SEMICOLON symbols { $1 :: $3 }
;
symbol:
| IDENT EQUAL gram_tokens { (Some $1, $3) }
| gram_tokens { (None, $1) }
;
gram_token:
| qualid_or_ident { GSymbQualid ($1, None) }
| qualid_or_ident LEVEL STRING { GSymbQualid ($1, Some $3) }
| LPAREN gram_tokens RPAREN { GSymbParen $2 }
| LBRACKET rules RBRACKET { GSymbProd $2 }
| STRING { GSymbString $1 }
;
gram_tokens:
| gram_token { [$1] }
| gram_token gram_tokens { $1 :: $2 }
;
doc_gram:
| DOC_GRAMMAR doc_gram_entries
{ GramExt { gramext_name = ""; gramext_globals=[]; gramext_entries = $2 } }
doc_gram_entries:
| { [] }
| doc_gram_entry doc_gram_entries { $1 :: $2 }
;
doc_gram_entry:
| qualid_or_ident COLON LBRACKET PIPE doc_gram_rules RBRACKET
{ { gentry_name = $1;
gentry_rules = GDataFresh (None, [{ grule_label = None; grule_assoc = None; grule_prods = $5; }]) } }
| qualid_or_ident COLON LBRACKET RBRACKET
{ { gentry_name = $1;
gentry_rules = GDataFresh (None, [{ grule_label = None; grule_assoc = None; grule_prods = []; }]) } }
;
doc_gram_rules:
| doc_gram_rule { [$1] }
| doc_gram_rule PIPE doc_gram_rules { $1 :: $3 }
;
/* hack: put the location in the dummy code data */
doc_gram_rule:
| doc_gram_symbols_opt { { gprod_symbs = $1; gprod_body = { code = ""; loc = Some (rhs_loc 1) }; } }
;
doc_gram_symbols_opt:
| { [] }
| doc_gram_symbols { $1 }
| doc_gram_symbols SEMICOLON { $1 }
;
doc_gram_symbols:
| doc_gram_symbol { [$1] }
| doc_gram_symbols SEMICOLON doc_gram_symbol { $1 @ [$3] }
;
doc_gram_symbol:
| IDENT EQUAL doc_gram_gram_tokens { (Some $1, $3) }
| doc_gram_gram_tokens { (None, $1) }
;
doc_gram_gram_tokens:
| doc_gram_gram_token { [$1] }
| doc_gram_gram_token doc_gram_gram_tokens { $1 :: $2 }
;
doc_gram_gram_token:
| qualid_or_ident { GSymbQualid ($1, None) }
| LPAREN doc_gram_gram_tokens RPAREN { GSymbParen $2 }
| LBRACKET doc_gram_rules RBRACKET { GSymbProd $2 }
| STRING { GSymbString $1 }
;
[ Dauer der Verarbeitung: 0.5 Sekunden
(vorverarbeitet)
]
|