Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file parser_config.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163(* elpi: embedded lambda prolog interpreter *)(* license: GNU Lesser General Public License Version 2.1 or later *)(* ------------------------------------------------------------------------- *)openElpi_utilopenElpi_lexer_config.Lexer_configexceptionParseErrorofUtil.Loc.t*string(* this is the input of the parser functor in grammar.mly, it ties the knot:
accumulate requires to call the same parser on another file, but file/module
resolution is not a parser business *)moduletypeParseFile=sigvalparse_file:?cwd:string->string->Ast.Program.parser_outputlistvalget_current_client_loc_payload:unit->Obj.toptionvalset_current_clent_loc_pyload:Obj.t->unitendletrecsubstringsilen_ss=iflen_s-i>=0thenString.subs0i::substrings(i+1)len_sselse[]letsubstringss=List.rev@@substrings1(String.lengths)sletfind_subtabs=letrecaux=function|[]->raiseNot_found|x::xs->tryHashtbl.findtabxwithNot_found->auxxsinaux(substringss)letprecedence_of,umax_precedence,appl_precedence,inf_precedence=lettab=Hashtbl.create21inList.iteri(funlevel{tokens;fixity}->List.iter(function|Extensible{start;fixed;_}->Hashtbl.addtabstart(fixity,level);List.iter(funtok->Hashtbl.addtabtok(fixity,level))fixed|Fixed{the_token;_}->Hashtbl.addtabthe_token(fixity,level))tokens;)mixfix_symbols;letumax_precedence=List.lengthmixfix_symbolsinletappl_precedence=umax_precedence+1inletinf_precedence=appl_precedence+1in(* greater than any used precedence*)(funs->tryletfixity,prec=find_subtabsin(*Format.eprintf "Printer: found %s %a %d\n%!" s pp_fixity (fst x) (snd x);*)Somefixity,precwithNot_found->(*Format.eprintf "Printer: not found: %s\n%!" s;*)None,appl_precedence),umax_precedence,appl_precedence,inf_precedenceletcomma_precedence=1+(snd@@precedence_of",")letmin_precedence=-1(* minimal precedence in use *)letlam_precedence=-1(* precedence of lambda abstraction *)letumin_precedence=0(* minimal user defined precedence *)letpp_fixedfmtl=l|>List.iter(funx->Format.fprintffmt"%s @ "x)letpp_non_enclosedfmt=function|false->()|true->Format.fprintffmt" [*]"letpp_tok_listfmtl=List.iter(function|Extensible{start;fixed;non_enclosed;_}->Format.fprintffmt"%a%s..%a @ "pp_fixedfixedstartpp_non_enclosednon_enclosed|Fixed{the_token;comment=None;_}->Format.fprintffmt"%s @ "the_token|Fixed{the_token;comment=Some(id,_);_}->Format.fprintffmt"%s (* see note %d *) @ "the_tokenid)lletpp_tok_list_commentsfmtl=List.iter(function|Extensible_->()|Fixed{comment=None;_}->()|Fixed{comment=Some(id,txt);_}->Format.fprintffmt"%d: %s@ "idtxt)lletlegacy_parser_compat_error=letopenFormatinletb=Buffer.create80inletfmt=formatter_of_bufferbinfprintffmt"@[<v>";fprintffmt"%s@;""Mixfix directives are not supported by this parser.";fprintffmt"%s@;""";fprintffmt"%s@;""The parser is based on token families.";fprintffmt"%s@;""A family is identified by some starting characters, for example";fprintffmt"%s@;""a token '+-->' belongs to the family of '+'. There is no need";fprintffmt"%s@;""to declare it.";fprintffmt"%s@;""";fprintffmt"%s@;""All the tokens of a family are parsed with the same precedence and";fprintffmt"%s@;""associativity, for example 'x +--> y *--> z' is parsed as";fprintffmt"%s@;""'x +--> (y *--> z)' since the family of '*' has higher precedence";fprintffmt"%s@;""than the family of '+'.";fprintffmt"%s@;""";fprintffmt"%s@;""Here the table of tokens and token families.";fprintffmt"%s@;""Token families are represented by the start symbols followed by '..'.";fprintffmt"%s@;""Tokens of families marked with [*] cannot end with the starting symbol,";fprintffmt"%s@;""eg `foo` is not an infix, while `foo is.";fprintffmt"%s@;""The listing is ordered by increasing precedence.";fprintffmt"%s@;""";pp_open_tboxfmt();pp_set_tabfmt();fprintffmt"%-25s ""fixity";pp_set_tabfmt();fprintffmt"| %s""tokens / token families";pp_print_tabfmt();letcol1="--------------------------"infprintffmt"%s"col1;pp_print_tabfmt();fprintffmt"+ -----------------------------------";pp_print_tabfmt();List.iter(fun{tokens;fixity;_}->fprintffmt"%a"pp_fixityfixity;pp_print_tabfmt();lets=letb=Buffer.create80inletfmt=formatter_of_bufferbinpp_set_marginfmt40;fprintffmt"| ";pp_open_hovboxfmt1;fprintffmt"%a"pp_tok_listtokens;pp_close_boxfmt();pp_print_flushfmt();lets=Buffer.contentsbinletpad="\n"^String.(make(lengthcol1)' ')inRe.Str.(global_replace(regexp_string"\n")pads)infprintffmt"%s"s;pp_print_tabfmt();)mixfix_symbols;pp_close_tboxfmt();fprintffmt"%s@;""";fprintffmt"%s@;""If the token is a valid mixfix, and you want the file to stay compatible";fprintffmt"%s@;""with Teyjus, you can ask Elpi to skip the directive. Eg:";fprintffmt"%s@;""";fprintffmt"%s@;""% elpi:skip 2 // skips the next two lines";fprintffmt"%s@;""infixr ==> 120.";fprintffmt"%s@;""infixr || 120.";fprintffmt"%s@;""";fprintffmt"%s@;""As a debugging facility one can ask Elpi to print the AST in order to";fprintffmt"%s@;""verify how the text was parsed. Eg:";fprintffmt"%s@;""";fprintffmt"%s@;""echo 'MyFormula = a || b ==> c && d' | elpi -parse-term";fprintffmt"%s@;""";fprintffmt"%s@;""Notes:";List.iter(fun{tokens;_}->fprintffmt"%a"pp_tok_list_commentstokens;)mixfix_symbols;fprintffmt"@]";pp_print_flushfmt();Buffer.contentsb;;leterror_mixfixloc=raise(ParseError(loc,legacy_parser_compat_error))