%-----------------------------------------------------------------------------% % Copyright (C) 1995-1999, 2006 The University of Melbourne. % This file may only be copied under the terms of the GNU General % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % file: zparser.m % main author: philip :- module zparser. :- interface. :- import_module list. :- import_module word. :- import_module zabstract. :- import_module ztoken. :- type parseResult ---> ok(spec) ; error(list(string)). % Error list in reverse so caller can add to it :- type schema_table. :- func init_schema_table = schema_table. :- pred specification(ztoken_list, parseResult, schema_table, schema_table, flags, flags). :- mode specification(in, out, in, out, in, out) is det. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% :- implementation. :- import_module assoc_list. :- import_module int. :- import_module map. % Used only in add_operat/4---should be in word.m :- import_module maybe. :- import_module pair. :- import_module require. :- import_module string. :- type schema_name == pair(maybe(operation), word). :- type schema_table == assoc_list(schema_name, int). init_schema_table = []. :- type default_defn ---> default_defn(zcontext, operation, word, int). :- type pstate ---> p( string, % input stream name list(string), % warning/error messages status, % error indicator ztoken_list, % tokens being parsed flags, % debugging flags schema_table, % declared schema names + #gen parameters list(default_defn), % delta and xi schemas defined by default ref % for generating unque refs to indentifier references ). :- pred new_ref(ref::out, pstate::in, pstate::out) is det. new_ref(R, p(SN, IO, S, TL, F, SL, D, R), p(SN, IO, S, TL, F, SL, D, R + 1)). :- pred make_ref(zcontext::in, ident::in, maybe(list(expr))::in, expr::out, pstate::in, pstate::out) is det. make_ref(C, I, M, ref(Ref, I, M)-C) --> new_ref(Ref). :- pred make_sexpr(zcontext::in, sexpr1::in, sexpr::out, pstate::in, pstate::out) is det. make_sexpr(C, S, sexpr(Ref, S, C)) --> new_ref(Ref). % :- import_module unsafe, io. :- pred schema_declared(schema_name, int, pstate, pstate). :- mode schema_declared(in, out, in, out) is semidet. schema_declared(W, I) --> =(p(_, _, _, _, _, SL, _, _)), % {unsafe_perform_io(io.write(W)), % unsafe_perform_io(io.nl), % unsafe_perform_io(io.write(SL)), % unsafe_perform_io(io.nl)}, {assoc_list.search(SL, W, I)}. :- pred schema_declare(schema_name, int, pstate, pstate). :- mode schema_declare(in, in, in, out) is det. schema_declare(W, I, p(SN, IO, S, TL, F, SL, D, R), p(SN, IO, S, TL, F, [W-I | SL], D, R)). :- pred schema_define(zcontext, operation, word, int, pstate, pstate). :- mode schema_define(in, in, in, in, in, out) is det. schema_define(C, O, W, I, p(SN, IO, S, TL, F, SL, D , R), p(SN, IO, S, TL, F, SL, [default_defn(C, O, W, I) | D], R)). :- pred add_abbrev(list(ident), pstate, pstate). :- mode add_abbrev(in, in, out) is det. add_abbrev(IdentL, p(SN, IO, S, TL, F0, SL, D, R), p(SN, IO, S, TL, F, SL, D, R)) :- list.append(IdentL, abbreviations(F0), Abbreviations), set_abbreviations(Abbreviations, F0, F). :- pred add_monot(list(ident), pstate, pstate). :- mode add_monot(in, in, out) is det. add_monot(IdentL, p(SN, IO, S, TL, F0, SL, D, R), p(SN, IO, S, TL, F, SL, D, R)) :- list.append(IdentL, monotonics(F0), Monotonics), set_monotonics(Monotonics, F0, F). :- pred add_operat(op, list(ident), pstate, pstate). :- mode add_operat(in, in, in, out) is det. add_operat(Op, IdentL, p(SN, IO, S, TL, F0, SL, D, R), p(SN, IO, S, TL, F, SL, D, R)) :- add_operators(Op, IdentL, F0, F). :- pred add_loglib(list(ident), pstate, pstate). :- mode add_loglib(in, in, out) is det. add_loglib(IdentL, p(SN, IO, S, TL, F0, SL, D, R), p(SN, IO, S, TL, F, SL, D, R)) :- list.append(IdentL, loglib_ids(F0), Loglib_ids), set_loglib_ids(Loglib_ids, F0, F). :- pred set_generate(flag, pstate, pstate). :- mode set_generate(in, in, out) is det. set_generate(Flag, p(SN, IO, S, TL, F0, SL, D, R), p(SN, IO, S, TL, F, SL, D, R)) :- set_generating_logic(Flag, F0, F). % :- pred zdebugging(pstate, pstate). % :- mode zdebugging(in, out) is semidet. % zdebugging --> =(p(_, _, _, _, F, _, _, _)), {debugging(F)}. :- pragma inline(pred(x/3)). :- pred x(ztoken, pstate, pstate). :- mode x(out, in, out) is semidet. x(T, p(SN, IO, S, [T-_ | TL], F, SL, D, R), p(SN, IO, S, TL, F, SL, D, R)). :- pragma inline(pred(x/4)). :- pred x(ztoken, zcontext, pstate, pstate). :- mode x(out, out, in, out) is semidet. x(T, C, p(SN, IO, S, [T-C | TL], F, SL, D, R), p(SN, IO, S, TL, F, SL, D, R)). :- pragma inline(pred(add_tokens/3)). :- pred add_tokens(ztoken_list, pstate, pstate). :- mode add_tokens(in, in, out) is det. add_tokens(L, p(SN, IO, S, TL0, F, SL, D, R), p(SN, IO, S, TL, F, SL, D, R)) :- append(L, TL0, TL). :- pragma inline(pred(c/3)). % A context of 0 should never be added to a construct, % because there must have been some tokens from which % to derive the construct. The 0 case is only to make c/3 det. :- pred c(zcontext, pstate, pstate). %:- mode c(out, in, out) is semidet. :- mode c(out, in, out) is det. %c(C) --> =(p(_, _, _, [_-C | _], _, _, _, _)). c(C) --> =(p(_, _, _, TL, _, _, _, _)), {TL = [_-C | _] ; TL = [], C = 0}. :- pred expect(ztoken, pstate, pstate). :- mode expect(in, in, out) is det. expect(T) --> ( if x(T) then {true} else {ztokenPortray(T, ST)}, zerror(ST) ). :- pred parserError(string, ztoken_list, string, string). :- mode parserError(in, in, in, out) is det. parserError(SN, Input, Mesg, EMesg) :- ( if list.split_list(10, Input, L0, R) then L = L0, ( R = [], End = "" ; R = [_ | _], End = " .." ) else L = Input, End = "" ), ( L = [], LNS = "eof" ; L = [_ - LN | _], string.int_to_base_string(LN, 10, LNS) ), list.length(L, N), ztokenPortrayL(L, TL), list.duplicate(N, " ", SL), list.zip(SL, TL, STL), string.append_list(STL, ST), % string.append_list([SN,":",LNS,": ... >>",ST,End, string.append_list([SN,LNS,": ... >>",ST,End,".\nError: ",Mesg], EMesg). :- pred zerror(string, pstate, pstate, pstate). :- mode zerror(in, in, in, out) is det. zerror(S0, p(_, _, _, ETL, _, _, _, _), p(SN, E , _, TL, F, SL, D, R), p(SN, [S | E], error, TL, F, SL, D, R)) :- parserError(SN, ETL, S0, S). :- pred zerror(string, pstate, pstate). :- mode zerror(in, in, out) is det. zerror(S0, p(SN, E , _, TL, F, SL, D, R), p(SN, [S | E], error, TL, F, SL, D, R)) :- string.append(S0, " expected", S1), parserError(SN, TL, S1, S). %%% % B.1.1 SPECIFICATION specification(TL, Result, Schemas0, Schemas, F0, F) :- SN = "", % SN and Status fields MARKED FOR DELETION P0 = p(SN, [], ok, TL, F0, Schemas0, [], 1), % Ref = 1 (0 reserved) specification1([], S0, P0, P), P = p(_, Errors, Status, _, F, Schemas, _, _), ( Status = ok, list.reverse(S0, S), Result = ok(S) ; Status = error, Result = error(Errors) ). :- pred specification1(spec, spec, pstate, pstate). :- mode specification1(in, out, in, out) is det. specification1(L0, L) --> ( if =(I0), x(B), {paragraph(B)} then ( if c(C), paragraph(B, MP) then ( if x(zEND) then {true} else ( if =(p(_, _, ok, _, _, _, _, _)) then zerror("Z paragraph end") else {true} ) ), add_default_ops(L0, L1), { MP = no, L2 = L1 ; MP = yes(P), L2 = [P-C | L1] }, specification1(L2, L) else zerror("paragraph not parsed", I0), consume_to_end, % consume_to_end(B), specification1(L0, L) ) else if x(_) then % Remove tokens before next par specification1(L0, L) else {L = L0} ). %%% % PARAGRAPHS :- pred paragraph(ztoken). :- mode paragraph(in) is semidet. paragraph(pragma(_)). paragraph(zBEGIN). paragraph(zAX). paragraph(zSCH). paragraph(zGEN). :- pred paragraph(ztoken, maybe(par1), pstate, pstate). :- mode paragraph(in, out, in, out) is semidet. paragraph(pragma(Pragma), no) --> pragma(Pragma). paragraph(zBEGIN, yes(P)) --> item(P), ( if semicolon then c(C), add_tokens([zEND-C, zBEGIN-C]) else {true} ). paragraph(zAX , yes(P)) --> axiomatic_def(P). paragraph(zSCH , yes(P)) --> schema_box(P). paragraph(zGEN , yes(P)) --> generic_def(P). :- pred pragma(pragma, pstate, pstate). :- mode pragma(in, in, out) is semidet. pragma(abbrev) --> nameOrOpList(L), add_abbrev(L). pragma(monot) --> nameOrOpList(L), add_monot(L). pragma(syntax) --> op_type(Op), nameOrOpList(L), add_operat(Op, L). pragma(loglib) --> nameOrOpList(L), add_loglib(L). pragma(logicgen) --> set_generate(on). pragma(nologicgen) --> set_generate(off). % pragma(email) --> :- pred nameOrOpList(list(ident), pstate, pstate). :- mode nameOrOpList(out, in, out) is det. nameOrOpList(L) --> ( if x(name(I)) then nameOrOpList(L1), {L = [I | L1]} else if x(op(_, I)) then nameOrOpList(L1), {L = [I | L1]} else {L = []} ). :- pred op_type(op, pstate, pstate). :- mode op_type(out, in, out) is semidet. op_type(Op) --> x(name(id(no, S, []))), op_type(S, Op). :- pred op_type(string, op, pstate, pstate). :- mode op_type(in, out, in, out) is semidet. op_type("infun", infun(N)) --> x(number(NS)), {string.to_int(NS, N), 1 =< N, N =< 6}. op_type("postfun", postfun) --> []. op_type("inrel", inrel) --> []. op_type("prerel", prerel) --> []. op_type("ingen", ingen) --> []. op_type("pregen", pregen) --> []. :- pred semicolon(pstate, pstate). :- mode semicolon(in, out) is semidet. semicolon --> x(T), {T = zSEMICOLON ; T = newline}. %%% % B.1.2 GIVEN SET :- pred item(par1, pstate, pstate). :- mode item(out, in, out) is semidet. item(I) --> ( if x(zSQBRA) then identL1(IL), expect(zSQKET), {I = given(IL)} else if ident(Id), x(zFREEEQUALS) then branchL1(BL), new_ref(Ref), {I = data(Ref, Id, BL)} else if schema_name(Ident), gen_formals(F), x(defs) then {Ident = id(Op, Name, _), list.length(F, N)}, schema_declare(Op-Name, N), ( if schema_exp(S1) then {S = S1} else zerror("schema expression"), consume_to([zSEMICOLON, newline]), c(C), make_sexpr(C, text([], []), S) ), {I = sdef(Ident, F, S)} else if def_lhs(D, F), x(zDEFINEEQUAL) then ( if expression(X1) then {X = X1} else zerror("expression"), {X = number("")-0} % arbitrary token ), {I = eqeq(D, F, X)} else predicate(P), {I = zpred(P)} ). :- pred identL1(list(ident), pstate, pstate). :- mode identL1(out, in, out) is det. identL1(L) --> parse_list1(x(zCOMMA), ident, zerror("ident"), L). %%% % B.1.3 STRUCTURED SET :- pred branchL1(list(branch), pstate, pstate). :- mode branchL1(out, in, out) is det. branchL1(L) --> parse_list1(x(zVBAR), branch, zerror("branch"), L). :- pred branch(branch, pstate, pstate). :- mode branch(out, in, out) is semidet. branch(branch(Ref, I, M)) --> ( if x(zBRA) then op_name(I), expect(zKET), expect(zFREEBRA), expression(X), expect(zFREEKET), {M = yes(X)} else ident(I), ( if x(zFREEBRA) then expression(X), expect(zFREEKET), {M = yes(X)} else {M = no} ) ), new_ref(Ref). %%% % B.1.4 GLOBAL DEFINITION :- pred axiomatic_def(par1, pstate, pstate). :- mode axiomatic_def(out, in, out) is det. axiomatic_def(define([], S)) --> text(S). %%% % B.1.5 GENERIC DEFINITION :- pred generic_def(par1, pstate, pstate). :- mode generic_def(out, in, out) is det. generic_def(define(F, S)) --> gen_formals(F), text(S). :- pred def_lhs(ident, formals, pstate, pstate). :- mode def_lhs(out, out, in, out) is semidet. def_lhs(I, F) --> ( if x(op(pregen, I0)) then ident(I1), {I = I0, F = [I1]} else if ident(I1), x(op(ingen, I0)) then ident(I2), {I = I0, F = [I1, I2]} else var_name(I), gen_formals(F) ). %%% % B.1.6 SCHEMA DEFINITION :- pred schema_box(par1, pstate, pstate). :- mode schema_box(out, in, out) is det. schema_box(sdef(Ident, F, S)) --> expect(left_brace), ( if schema_name(Ident0) then expect(right_brace), {Ident = Ident0, Ident = id(Op, Name, _)}, gen_formals(F), {list.length(F, N)}, schema_declare(Op-Name, N), text(S) else zerror("schema_name"), {Ident = id(no, "*error name*", []), F = []}, make_sexpr(0, text([], []), S) ). :- pred text(sexpr, pstate, pstate). :- mode text(out, in, out) is det. text(S) --> c(C), decl_part(L), opt_predicate(Pred), make_sexpr(C, text(L, Pred), S). %%% % B.1.7 DECLARATION :- pred decl_part(list(decl), pstate, pstate). :- mode decl_part(out, in, out) is det. decl_part(L) --> parse_list1(semicolon, decl_elem, zerror("decl_elem"), L). :- pred decl_elem(decl, pstate, pstate). :- mode decl_elem(out, in, out) is semidet. decl_elem(D) --> % More than one name, or the colon, will distinguish a % basic declaration from a schema reference. ( if decl_nameL(L), {L = [_ | _]}, x(zCOLON) then % basic_decl ( if expression(X) then {D = decl(L, X)} else zerror("expression"), c(C), {D = decl(L, number("Err")-C)} ) else schema_exp(S), {D = include(S)} ). :- pred decl_nameL(list(ident), pstate, pstate). :- mode decl_nameL(out, in, out) is det. decl_nameL(L) --> parse_list(x(zCOMMA), decl_name, zerror("decl_name"), L). :- pred decl_nameL1(list(ident), pstate, pstate). :- mode decl_nameL1(out, in, out) is det. decl_nameL1(L) --> parse_list1(x(zCOMMA), decl_name, zerror("decl_name"), L). %%% % B.1.8 SCHEMA TEXT %%% % B.1.9 SCHEMA :- pred schema_exp(sexpr, pstate, pstate). :- mode schema_exp(out, in, out) is semidet. schema_exp(S) --> c(C), ( if quantifier(Q) then schema_text(T), expect(zDOT), schema_exp(S0), make_sexpr(C, quantification(Q, T, S0), S) else log_sch(S) ). :- pred log_sch(sexpr::out, pstate::in, pstate::out) is semidet. log_sch(P) --> parse_left1(x(zIFF), log_sch1, s_lbpred(equivalence), P). :- pred log_sch1(sexpr::out, pstate::in, pstate::out) is semidet. log_sch1(P) --> parse_right1(x(zIMPLIES), log_sch2, s_lbpred(implication), P). :- pred log_sch2(sexpr::out, pstate::in, pstate::out) is semidet. log_sch2(P) --> parse_left1(x(zOR), log_sch3, s_lbpred(disjunction), P). :- pred log_sch3(sexpr::out, pstate::in, pstate::out) is semidet. log_sch3(P) --> parse_left1(x(zAND), logsch4, s_lbpred(conjunction), P). :- pred s_lbpred(lconn, zcontext, sexpr, sexpr, sexpr, pstate, pstate). :- mode s_lbpred(in, in, in, in, out, in, out) is det. s_lbpred(T, C, S0, S1, S) --> make_sexpr(C, lbpred(T, S0, S1), S). :- pred logsch4(sexpr, pstate, pstate). :- mode logsch4(out, in, out) is semidet. logsch4(S) --> ( if x(zNOT, C) then % SNegation logsch4(S0), make_sexpr(C, negation(S0), S) else cmpndsch(S) ). :- pred cmpndsch(sexpr::out, pstate::in, pstate::out) is semidet. cmpndsch(S) --> parse_left1(sconn_op, cmpndsch1, bsexpr, S). :- pred bsexpr(pair(sconn, zcontext), sexpr, sexpr, sexpr, pstate, pstate). :- mode bsexpr(in, in, in, out, in, out) is det. bsexpr(SConn-C, S0, S1, S) --> new_ref(Ref), make_sexpr(C, bsexpr(Ref, SConn, S0, S1), S). :- pred sconn_op(pair(sconn, zcontext), pstate, pstate). :- mode sconn_op(out, in, out) is semidet. sconn_op(sconn(T)-C) --> x(T, C). :- func sconn(ztoken) = sconn. :- mode sconn(in) = out is semidet. sconn(zCOMPOSE) = composition. sconn(pipe) = piping. :- pred cmpndsch1(sexpr, pstate, pstate). :- mode cmpndsch1(out, in, out) is semidet. cmpndsch1(S) --> cmpndsch2(S0), cmpndsch1_tail(S0, S). :- pred cmpndsch1_tail(sexpr, sexpr, pstate, pstate). :- mode cmpndsch1_tail(in, out, in, out) is semidet. cmpndsch1_tail(S0, S) --> ( if x(zSQBRA, C), renameL1(RL) then % SRenaming expect(zSQKET), make_sexpr(C, renaming(S0, RL), S1), cmpndsch1_tail(S1, S) else if x(zHIDING, C) then % SHiding expect(zBRA), decl_nameL1(L), expect(zKET), new_ref(Ref), make_sexpr(C, hide(Ref, S0, L), S1), cmpndsch1_tail(S1, S) else {S = S0} ). :- pred cmpndsch2(sexpr, pstate, pstate). :- mode cmpndsch2(out, in, out) is semidet. cmpndsch2(S) --> cmpndsch3(S0), cmpndsch2_tail(S0, S). :- pred cmpndsch2_tail(sexpr, sexpr, pstate, pstate). :- mode cmpndsch2_tail(in, out, in, out) is semidet. cmpndsch2_tail(S0, S) --> ( if x(zPROJECTION, C) then log_sch(S1), new_ref(Ref), make_sexpr(C, projection(Ref, S0, S1), S2), cmpndsch2_tail(S2, S) else {S = S0} ). :- pred cmpndsch3(sexpr, pstate, pstate). :- mode cmpndsch3(out, in, out) is semidet. cmpndsch3(S) --> c(C), ( if x(zPRESCH) then cmpndsch3(S0), new_ref(Ref), make_sexpr(C, pre(Ref, S0), S) else cmpndsch4(S) ). :- pred cmpndsch4(sexpr, pstate, pstate). :- mode cmpndsch4(out, in, out) is semidet. cmpndsch4(S) --> basicsch(S0), cmpndsch4_tail(S0, S). :- pred cmpndsch4_tail(sexpr, sexpr, pstate, pstate). :- mode cmpndsch4_tail(in, out, in, out) is semidet. cmpndsch4_tail(S0, S) --> ( if x(decoration(D), C) then make_sexpr(C, decoration(S0, D), S1), cmpndsch4_tail(S1, S) else {S = S0} ). :- pred basicsch(sexpr, pstate, pstate). :- mode basicsch(out, in, out) is semidet. basicsch(S) --> c(C), ( if x(zSQBRA) then % SConstruction schema_text(S0), expect(zSQKET), make_sexpr(C, text([include(S0)], []), S) % This otherwise redundant wrapper is put around S0 % so that we can distingush between eg. % \lambda x, y: \nat @ ... and % \lambda [x, y: \nat] @ ... % where the first has two args and the second one schema arg. else if x(zBRA) then schema_exp(S), expect(zKET) else schema_ref(S) ). :- pred schema_text(sexpr, pstate, pstate). :- mode schema_text(out, in, out) is det. schema_text(SExpr) --> c(C), decl_part(D), ( if x(zVBAR) then predicate1(P0), {P = [P0]} else {P = []} ), ( if {D = [include(SExpr0)], P = []} then {SExpr = SExpr0} else make_sexpr(C, text(D, P), SExpr) ). :- pred add_default_ops(spec::in, spec::out, pstate::in, pstate::out) is det. add_default_ops(L0, L, p(SN0, IO0, S0, TL, F0, SL0, D0, R0), p(SN, IO, S, TL, F, SL, [], R)) :- list.map(default_op, D0, LLD), list.condense(LLD, LD0), specification1(L0, L, p(SN0, IO0, S0, LD0, F0, SL0, [], R0), p(SN , IO , S , LD , F , SL , D , R )), ( if LD = [] then true else error("add_default_ops/4: tokens left over") ), ( if D = [] then true else error("add_default_ops/4: defaults added") ). :- pred default_op(default_defn::in, ztoken_list::out) is det. default_op(default_defn(C, Op, S, NGen), Tokens) :- N = name(id(no, S, [])), N_p = [N, decoration([prime])], % N_p = name(id(no, S, [prime])), ( if NGen = 0 then ArgTokens = [] else list.duplicate(NGen, S, Gens0), P = ( pred(Base::in, Param::out, I::in, I+1::out) is det :- string.int_to_string(I, Suffix), string.append(Base, Suffix, Param0), Param = name(id(no, Param0, [])) ), list.map_foldl(P, Gens0, Gens, 1, _), list.append([zSQBRA | Gens], [zSQKET], ArgTokens) ), ( Op = delta, OpToken = 'Delta', PredTokens = [] ; Op = xi, OpToken = 'Xi', list.condense([[zST, zTHETA, N], ArgTokens, [zEQUALS, zTHETA | N_p], ArgTokens], PredTokens) ), list.condense( [[zSCH, left_brace, OpToken, N, right_brace], ArgTokens, [N], ArgTokens, [zSEMICOLON | N_p], ArgTokens, PredTokens, [zEND]], Tokens0), list.map( ( pred(I::in, O::out) is det :- O = I-C ), Tokens0, Tokens). :- pred schema_ref(sexpr, pstate, pstate). :- mode schema_ref(out, in, out) is semidet. schema_ref(SREF) --> c(C), =(I), schema_name(Ident), {Ident = id(M, Name, _D)}, % _D is always [] --- change ( if schema_declared(M-Name, _) then {true} else {M = yes(Op)}, % Must fail if M = no since % schema_declared(no-Name, NGen), % Ident may not be a schema name % schema_define(C, Op, Name, NGen), % schema_declare(M-Name, NGen) ( if schema_declared(no-Name, NGen) then schema_define(C, Op, Name, NGen), schema_declare(M-Name, NGen) else zerror("undefined schema name", I) ) ), ( if not (x(zSQBRA), rename(_)) then % actuals look a lot like renaming opt_gen_actuals(A) else {A = no} ), % opt_renaming(R), make_sexpr(C, ref(id(M, Name, []), A), SREF). % The above can be improved by reporting `actuals expected' after [ % in opt_gen_actuals, and by having an opt_renaming and expected_renaming. %%% % RENAMING :- pred opt_renaming(maybe(renaming), pstate, pstate). :- mode opt_renaming(out, in, out) is det. opt_renaming(L ) --> ( if x(zSQBRA) then {L = yes(L0)}, renameL1(L0), expect(zSQKET) else {L = no} ). :- pred renameL(renaming, pstate, pstate). :- mode renameL(out, in, out) is det. renameL(L) --> parse_list(x(zCOMMA), rename, zerror("rename"), L). :- pred renameL1(renaming, pstate, pstate). :- mode renameL1(out, in, out) is det. renameL1(L) --> parse_list1(x(zCOMMA), rename, zerror("rename"), L). :- pred rename(pair(ident), pstate, pstate). :- mode rename(out, in, out) is semidet. rename(N1 - N0) --> decl_name(N0), x(zRENAME), decl_name(N1). % rename from N1 to N0 %%% % B.1.10 PREDICATE :- pred opt_predicate(list(zpred), pstate, pstate). :- mode opt_predicate(out, in, out) is det. opt_predicate(P) --> ( if x(zST) then opt_predicate1(P) else {P = []} ). :- pred opt_predicate1(list(zpred), pstate, pstate). :- mode opt_predicate1(out, in, out) is det. opt_predicate1(L) --> parse_list1(x(newline), predicate, zerror("predicate"), L). :- pred predicate1(zpred, pstate, pstate). :- mode predicate1(out, in, out) is det. predicate1(P) --> ( if predicate(P0) then {P = P0} else zerror("predicate"), {P = truth-0} ). :- pred predicate(zpred, pstate, pstate). :- mode predicate(out, in, out) is semidet. predicate(P) --> c(C), ( if quantifier(Q) then schema_text(S), expect(zDOT), predicate1(P0), {P = quantification(Q, S, P0)-C} else if x(zLET) then let_defL1(L), expect(zDOT), predicate(P0), {P = let(L, P0)-C} else log_pred(P) ). :- pred log_pred(zpred::out, pstate::in, pstate::out) is semidet. log_pred(P) --> c(C), parse_left(x(zIFF), log_pred1, lbpred(C, equivalence), P). :- pred log_pred1(zpred::out, pstate::in, pstate::out) is semidet. log_pred1(P) --> c(C), parse_right(x(zIMPLIES), log_pred2, lbpred(C, implication), P). :- pred log_pred2(zpred::out, pstate::in, pstate::out) is semidet. log_pred2(P) --> c(C), parse_left(x(zOR), log_pred3, lbpred(C, disjunction), P). :- pred log_pred3(zpred::out, pstate::in, pstate::out) is semidet. log_pred3(P) --> c(C), parse_left(x(zAND), basic_pred, lbpred(C, conjunction), P). :- pred lbpred(zcontext, lconn, zpred, zpred, zpred). :- mode lbpred(in, in, in, in, out) is det. lbpred(C, T, P0, P1, lbpred(T, P0, P1)-C). :- pred basic_pred(zpred, pstate, pstate). :- mode basic_pred(out, in, out) is semidet. basic_pred(P) --> c(C), ( if x(op(prerel, Op)) then % pre_rel_pred expression0(X), % 0 safe? make_ref(C, Op, no, REF), {P = membership(X, REF)-C} else if x(zTRUE) then {P = truth-C} else if x(zFALSE) then {P = falsehood-C} else if x(zNOT) then basic_pred(P0), {P = negation(P0)-C} else if x(zSQBRA) then schema_text(S), expect(zSQKET), {P = sexpr(S)-C} % ; x(zPRESCH) then % schema_pred - ( schema ) % basicsch(S0), new_ref(Ref), make_sexpr(C, pre(Ref, S0), S), % {P = sexpr(S)-C} else if x(zBRA), predicate(P0) then expect(zKET), {P = P0} % BUG: (expr) or (pred) else if expression0(X), rel_tail(X, M), {M = yes(_)} then % 0 safe? {M = yes(P)} % actually want to do this if X is not just an ident % ; expression(X), x(odot), predicate(P0), {P = subst(X, P0)-C} % ; schema_ref(R), {P = sexpr(R)-C} % Limited form of schema expression below (with schema_ref prefix) else cmpndsch(S), {P = sexpr(S)-C} % schema_pred - ( schema ) ). :- pred rel_tail(expr, maybe(zpred), pstate, pstate). :- mode rel_tail(in, out, in, out) is semidet. rel_tail(X0, P) --> c(C), ( if x(zEQUALS) then expression01(X1), % simpler with partial modes! % 0 safe? rel_tail_tail(equality(X0, X1)-C, X1, P) else if x(zMEMBER) then expression01(X1), % 0 safe? rel_tail_tail(membership(X0, X1)-C, X1, P) else if x(inrel), expect(left_brace), c(CI), ident(I), expect(right_brace) then {X0 = _-C0}, expression01(X1), % 0 safe? make_ref(CI, I, no, REF), rel_tail_tail(membership(tuple([X0, X1])-C0, REF)-C, X1, P) else if x(op(inrel, R)) then {X0 = _-C0}, expression01(X1), % 0 safe? make_ref(C, R, no, REF), rel_tail_tail(membership(tuple([X0, X1])-C0, REF)-C, X1, P) else {P = no} ). :- pred rel_tail_tail(zpred, expr, maybe(zpred), pstate, pstate). :- mode rel_tail_tail(in, in, out, in, out) is semidet. rel_tail_tail(P0, X, yes(P)) --> c(C), rel_tail(X, M), { if M = yes(P1) then P = lbpred(conjunction, P0, P1) - C else P = P0 }. %%% % LET DEFINITIONS :- pred let_defL1(assoc_list(ident, expr), pstate, pstate). :- mode let_defL1(out, in, out) is det. let_defL1(L) --> parse_list1(x(zSEMICOLON), let_def, zerror("let_def"), L). :- pred let_def(pair(ident, expr), pstate, pstate). :- mode let_def(out, in, out) is semidet. let_def(N-X) --> var_name(N), x(zDEFINEEQUAL), expression(X). %%% % B.1.11 EXPRESSION :- pred expression01(expr, pstate, pstate). :- mode expression01(out, in, out) is det. expression01(X) --> ( if expression0(X0) then {X = X0} else zerror("expression0"), {X = number("")-0} ). :- pred expression0(expr, pstate, pstate). :- mode expression0(out, in, out) is semidet. expression0(X) --> ( if x(zIF, C) then % if_then_else predicate(P), expect(zTHEN), expression(X0), expect(zELSE), expression(X1), {X = if(P, X0, X1)-C} else if x(zMU, C) then % defn_descr schema_text(T), opt_at_exp(X1), {X = mu(T, X1)-C} else if x(zLET, C) then % let expression let_defL1(L), expect(zDOT), expression(X0), {X = let(L, X0)-C} else expression(X) ). :- pred opt_at_exp(maybe(expr), pstate, pstate). :- mode opt_at_exp(out, in, out) is semidet. opt_at_exp(X) --> ( if x(zDOT) then expression(X0), {X = yes(X0)} else {X = no} ). :- pred expression(expr, pstate, pstate). :- mode expression(out, in, out) is semidet. expression(X) --> expression1(X1), expression_tail(X1, X). :- pred expression_tail(expr, expr, pstate, pstate). :- mode expression_tail(in, out, in, out) is det. expression_tail(X0, X) --> ( if x(op(ingen, Op), C) then % in_gen_exp %%% TESTING % expression(X1), % make_ref(C, Op, yes([X0, X1]), X) ( if expression(X1) then make_ref(C, Op, yes([X0, X1]), X) else zerror("expression"), {X = X0} ) else {X = X0} ). :- pred expression1(expr, pstate, pstate). :- mode expression1(out, in, out) is semidet. expression1(X) --> expression2L(X0, L0), { L0 = [], X = X0 ; L0 = [_ | _], X0 = _-C, X = product([X0 | L0])-C }. :- pred expression2L(expr, list(expr), pstate, pstate). :- mode expression2L(out, out, in, out) is semidet. expression2L(X, L) --> expression2(X), ( if x(zCROSS) then % cart_product ( if expression2L(X1, L1) then {L = [X1 | L1]} else zerror("expression"), {L = []} ) else {L = []} ). :- pred expression2(expr, pstate, pstate). :- mode expression2(out, in, out) is semidet. expression2(X) --> expression2(1, X). :- pred expression2(word.priority, expr, pstate, pstate). :- mode expression2(in, out, in, out) is semidet. expression2(P, X) --> expression3(X1), expression2_tail(P, X1, X). :- pred expression2_tail(word.priority, expr, expr, pstate, pstate). :- mode expression2_tail(in, in, out, in, out) is det. expression2_tail(P, X0, X) --> % ( x(op(infun(P), Op), C) then % in_fun_exp % % Special case---see func minus below ( if ( if x(op(infun(P2), Op0), CT) then {Op = Op0, C = CT, P1 = P2} else x(minus, C), {P1 = 3, Op = id(no, "- (binary)", [])} ), {P1 >= P} then % in_fun_exp % TESTING % expression2(P1+1, X1), % make_ref(C, Op, no, REF), % {X0 = _-C0}, % new_ref(R), {X2 = zapply(R, REF, tuple([X0, X1])-C0)-C}, ( if expression2(P1+1, X1) then make_ref(C, Op, no, REF), {X0 = _-C0}, new_ref(R), {X2 = zapply(R, REF, tuple([X0, X1])-C0)-C} else zerror("expression"), % Message could be more specific {X2 = X0} ), expression2_tail(P, X2, X) else {X = X0} ). :- pred expression3(expr, pstate, pstate). :- mode expression3(out, in, out) is semidet. expression3(X) --> ( if x(zPSET, C) then % power_set is treated like a prefix generic expression5(X0), {X = powerset(X0)-C} % special case for unary minus else if x(minus, C) then decoration(D), expression5(X0), make_ref(C, id(no, "- (unary)", D), no, REF), new_ref(R), {X = zapply(R, REF, X0)-C} else if x(op(pregen, Op), C) then % pre_gen_exp expression5(X0), make_ref(C, Op, yes([X0]), X) else expression4(X) ). :- pred expression4(expr, pstate, pstate). :- mode expression4(out, in, out) is semidet. expression4(X) --> expression5(X0), expression4_tail(X0, X). :- pred expression4_tail(expr, expr, pstate, pstate). :- mode expression4_tail(in, out, in, out) is semidet. expression4_tail(X0, X) --> %( expression4(X1) then ( if expression5(X1) then {X1 = _-C}, new_ref(R), expression4_tail(zapply(R, X0, X1)-C, X) else {X = X0} ). :- pred expression5(expr, pstate, pstate). :- mode expression5(out, in, out) is semidet. expression5(X) --> expression5_head(X0), expression5_tail(X0, X). :- pred expression5_head(expr, pstate, pstate). :- mode expression5_head(out, in, out) is semidet. expression5_head(X) --> % if_then_else not yet implemented % ( c(C), schema_ref_expr(S) then % schema_exp ( if c(C), schema_ref(S) then % schema_exp {X = sexp(S)-C} % schema_ref fails if name not declared else if c(C), var_name(V) then % ident, gen_instance % can start with a zBRA so before bracketed expression opt_gen_actuals(A), make_ref(C, V, A, X) else if x(zSETBRA, C) then % set_extn, set_comp ( if expressionL(L), x(zSETKET) then % order important here new_ref(REF), {X = display(REF, set, L)-C} else schema_text(T), opt_at_exp(X0), {X = setcomp(T, X0)-C}, expect(zSETKET) ) else if x(zBRA, C) then expression0(X0), ( if x(zKET) then {X = X0} else if {X0 = lambda(_, _)-_ ; X0 = mu(_, _)-_ ; X0 = let(_, _)-_} then =(I), zerror("`)' expected after lambda, mu or LET", I), {X = X0} else if x(zCOMMA) then % tuple expressionL1(L), expect(zKET), {X = tuple([X0 | L])-C} else =(I), zerror("comma expected after tuple element", I), {X = X0} ) else if x(langle, C) then expressionL(L), expect(rangle), new_ref(REF), {X = display(REF, seq, L)-C} else if x(lbag, C) then expressionL(L), expect(rbag), new_ref(REF), {X = display(REF, bag, L)-C} else if x(zTHETA, C) then basicsch(S), decoration(D), new_ref(REF), {X = theta(REF, S, D)-C} else if x(zLAMBDA, C) then schema_text(T), expect(zDOT), expression0(X0), % is this safe? {X = lambda(T, X0)-C} else if x(number(N), C) then {X = number(N)-C} else x(string(N), C), {X = stringl(N)-C} ). :- pred expression5_tail(expr, expr, pstate, pstate). :- mode expression5_tail(in, out, in, out) is semidet. expression5_tail(X0, X) --> ( if x(limg, C) then expression0(X1), expect(rimg), decoration(D), make_ref(C, id(no, "_(|_|)", D), no, REF), new_ref(R), {X2 = zapply(R, REF, tuple([X0,X1])-C)-C}, expression5_tail(X2, X) else if x(op(postfun, Op), C) then % post_fun_exp make_ref(C, Op, no, REF), new_ref(R), {X2 = zapply(R, REF, X0)-C}, expression5_tail(X2, X) else if x(caret, C) then % superscript expect(left_brace), expression(X1), expect(right_brace), make_ref(C, id(no, "iter", []), no, REF), new_ref(R), new_ref(R1), {X2 = zapply(R1, zapply(R, REF, X1)-C, X0)-C}, expression5_tail(X2, X) else if x(zSELECT, C) then % bind_selection ( if x(number(N)) then {X2 = tupleselection(X0, N)-C} else var_name(VN), new_ref(R), {X2 = select(R, X0, VN)-C} ), expression5_tail(X2, X) else {X = X0} ). %%% % NAMES AND IDENTIFIERS :- pred ident(ident, pstate, pstate). :- mode ident(out, in, out) is semidet. % ident(id(no, W, D)) --> x(word(W)), decoration(D). ident(I) --> x(name(I)). :- pred decl_name(ident, pstate, pstate). :- mode decl_name(out, in, out) is semidet. decl_name(N) --> ( if op_name(N1) then {N = N1} else ident(N) ). :- pred var_name(ident, pstate, pstate). :- mode var_name(out, in, out) is semidet. % YUK: minus needs to revert to being a special token if this is required % (ambiguity between unary and binary operator `-' requires special handling) var_name(N) --> ( if x(zBRA) then op_name(N), x(zKET) else ident(N) ). % var_name(N) --> ( x(zBRA) then op_name(N), x(zKET) ; ident(N), {name(N) \= minus} ). :- pred op_name(ident, pstate, pstate). :- mode op_name(out, in, out) is semidet. op_name(Op) --> ( if x(underscore) then ( if x(limg), x(underscore), x(rimg) then {Op = id(no, "_(|_|)", D)}, decoration(D) else if x(minus) then {Op = id(no, "- (binary)", D)}, decoration(D), x(underscore) else if in_sym(Op1) then {Op = Op1}, x(underscore) else if post_sym(Op1) then {Op = Op1} else {Op = id(no, "don't handle wrong op_names", [])} ) else if x(minus) then {Op = id(no, "- (unary)", D)}, decoration(D) % {Op = id(no, "-", D)}, decoration(D) else pre_sym(Op), x(underscore) ). :- pred in_sym(ident, pstate, pstate). :- mode in_sym(out, in, out) is semidet. in_sym(Op) --> x(op(O, Op)), {O=infun(_) ; O=ingen ; O=inrel}. :- pred pre_sym(ident, pstate, pstate). :- mode pre_sym(out, in, out) is semidet. pre_sym(Op) --> x(op(O, Op)), {O=pregen ; O=prerel}. :- pred post_sym(ident, pstate, pstate). :- mode post_sym(out, in, out) is semidet. post_sym(Op) --> x(op(postfun, Op)). %:- func minus = ztoken. % If minus is a binary operator, any newlines before it are soft % and therefore ignored. This would mean that a line couldn't start % with a unary minus, eg. a negative number. We therefore treat minus as a % special case. % minus = op(prefun(3), id(no, "-", [])). % minus = name(id(no, "-", [])). :- pred gen_formals(formals, pstate, pstate). :- mode gen_formals(out, in, out) is det. gen_formals(L) --> ( if x(zSQBRA) then identL1(L), expect(zSQKET) else {L = []} ). :- pred opt_gen_actuals(maybe(list(expr)), pstate, pstate). :- mode opt_gen_actuals(out, in, out) is det. opt_gen_actuals(L) --> ( if x(zSQBRA) then expressionL1(L0), expect(zSQKET), {L = yes(L0)} else {L = no} ). :- pred decoration(decoration, pstate, pstate). :- mode decoration(out, in, out) is det. decoration(D) --> ( if x(decoration(D0)) then {D = D0} else {D = []} ). :- pred schema_name(ident, pstate, pstate). :- mode schema_name(out, in, out) is semidet. schema_name(id(M, S, [])) --> x(T), ( {T = 'Delta', M = yes(delta)}, x(name(I), C) ; {T = 'Xi', M = yes(xi)}, x(name(I), C) ; {T = name(I), M = no}, c(C) ), {I = id(M0, S, D)}, { if M0 = no then true else error("schema_name/3--operation in lexer ident") }, % Remove decoration from schema name if any ( {D = []} ; {D = [_ | _]}, add_tokens([decoration(D)-C]) ). %%% % Utilities :- pred quantifier(quantifier::out, pstate::in, pstate::out) is semidet. quantifier(Q) --> x(T), {quantifierToken(T, Q)}. :- pred quantifierToken(ztoken::in, quantifier::out) is semidet. quantifierToken(zFORALL, universal). quantifierToken(zEXISTS, exists). quantifierToken(zEXISTS1, unique). :- pred consume_to(list(ztoken), pstate, pstate). :- mode consume_to(in, in, out) is det. consume_to(L) --> ( if x(T), {list.member(T, [zEND | L])} then {true} else if x(_) then consume_to(L) else zerror("paragraph end") ). :- pred consume_to_end(pstate, pstate). :- mode consume_to_end(in, out) is det. consume_to_end --> ( if x(zEND) then {true} else if x(_) then consume_to_end else zerror("paragraph end") ). :- pred expressionL(list(expr), pstate, pstate). :- mode expressionL(out, in, out) is det. expressionL(L) --> parse_list(x(zCOMMA), expression, zerror("expression"), L). :- pred expressionL1(list(expr), pstate, pstate). :- mode expressionL1(out, in, out) is det. expressionL1(L) --> parse_list1(x(zCOMMA), expression, zerror("expression"), L). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Higher order parsing % :- pred parse_right1( pred(Z, Y, Y)::pred(out, in, out) is semidet, % parse infix operator pred(X, Y, Y)::pred(out, in, out) is semidet, % parse operand pred(Z, X, X, X, Y, Y)::pred(in, in, in, out, in, out) is det, % use Z and two X's to construct new X X::out, Y::in, Y::out) is semidet. parse_right1(Infix, Operand, Construct, Tree) --> Operand(Left), parse_right1(Left, Infix, Operand, Construct, Tree). % parse_right1/7 is a service routine for parse_right1/6 :- pred parse_right1(X, pred(Z, Y, Y), pred(X, Y, Y), pred(Z, X, X, X, Y, Y), X, Y, Y). :- mode parse_right1(in, pred(out, in, out) is semidet, pred(out, in, out) is semidet, pred(in, in, in, out, in, out) is det, out, in, out) is semidet. parse_right1(Left, Infix, Operand, Construct, Tree) --> ( if Infix(Result) then Operand(Left_of_Right), parse_right1(Left_of_Right, Infix, Operand, Construct, Right), Construct(Result, Left, Right, Tree) else {Tree = Left} ). :- pred parse_right(pred(Y, Y), pred(X, Y, Y), pred(X, X, X), X, Y, Y). :- mode parse_right(pred(in, out) is semidet, pred(out, in, out) is semidet, pred(in, in, out) is det, out, in, out) is semidet. parse_right(Infix, Operand, Construct, Tree) --> Operand(Left), parse_right(Left, Infix, Operand, Construct, Tree). % parse_right/7 is a service routine for parse_right/6 :- pred parse_right(X, pred(Y, Y), pred(X, Y, Y), pred(X, X, X), X, Y, Y). :- mode parse_right(in, pred(in, out) is semidet, pred(out, in, out) is semidet, pred(in, in, out) is det, out, in, out) is semidet. parse_right(Left, Infix, Operand, Construct, Tree) --> ( if Infix then Operand(Left_of_Right), parse_right(Left_of_Right, Infix, Operand, Construct, Right), {Construct(Left, Right, Tree)} else {Tree = Left} ). :- pred parse_left1( pred(Z, Y, Y)::pred(out, in, out) is semidet, % parse infix operator pred(X, Y, Y)::pred(out, in, out) is semidet, % parse operand pred(Z, X, X, X, Y, Y)::pred(in, in, in, out, in, out) is det, % use Z and two X's to construct new X X::out, Y::in, Y::out) is semidet. parse_left1(Infix, Operand, Construct, Tree) --> Operand(Left), parse_left1(Left, Infix, Operand, Construct, Tree). % parse_left1/7 is a service routine for parse_left1/6 :- pred parse_left1(X, pred(Z, Y, Y), pred(X, Y, Y), pred(Z, X, X, X, Y, Y), X, Y, Y). :- mode parse_left1(in, pred(out, in, out) is semidet, pred(out, in, out) is semidet, pred(in, in, in, out, in, out) is det, out, in, out) is semidet. parse_left1(Left, Infix, Operand, Construct, Tree) --> ( if Infix(Result) then Operand(Right), Construct(Result, Left, Right, Tree1), parse_left1(Tree1, Infix, Operand, Construct, Tree) else {Tree = Left} ). :- pred parse_left(pred(Y, Y), pred(X, Y, Y), pred(X, X, X), X, Y, Y). :- mode parse_left(pred(in, out) is semidet, pred(out, in, out) is semidet, pred(in, in, out) is det, out, in, out) is semidet. parse_left(Infix, Operand, Construct, Tree) --> Operand(Left), parse_left(Left, Infix, Operand, Construct, Tree). % parse_left/7 is a service routine for parse_left/6 :- pred parse_left(X, pred(Y, Y), pred(X, Y, Y), pred(X, X, X), X, Y, Y). :- mode parse_left(in, pred(in, out) is semidet, pred(out, in, out) is semidet, pred(in, in, out) is det, out, in, out) is semidet. parse_left(Left, Infix, Operand, Construct, Tree) --> ( if Infix then Operand(Right), {Construct(Left, Right, Tree1)}, parse_left(Tree1, Infix, Operand, Construct, Tree) else {Tree = Left} ). :- pred parse_list(pred(Y, Y), pred(X, Y, Y), pred(Y, Y), list(X), Y, Y). :- mode parse_list(pred(in, out) is semidet, pred(out, in, out) is semidet, pred(in, out) is det, out, in, out) is det. parse_list(Separator, Element, Error, L) --> ( if Element(E) then {L = [E | L1]}, ( if Separator then parse_list1(Separator, Element, Error, L1) else {L1 = []} ) else {L = []} ). :- pred parse_list1(pred(Y, Y), pred(X, Y, Y), pred(Y, Y), list(X), Y, Y). :- mode parse_list1(pred(in, out) is semidet, pred(out, in, out) is semidet, pred(in, out) is det, out, in, out) is det. parse_list1(Separator, Element, Error, L) --> ( if Element(E) then {L = [E | L1]}, ( if Separator then parse_list1(Separator, Element, Error, L1) else {L1 = []} ) else {L = []}, Error ).