/*********************************************************************
A converter for transforming the problem format XCSP 2.1 into B-Prolog
by Neng-Fa Zhou, Last updated, January 2, 2008.
To convert an XCSP file "zebra.xml" into Prolog,
1. load and run
?- cl(convert).
?- convert(zebra).
2. or run as a command-line
bp convert.out -g "convert_main(zebra),halt"
/*********************************************************************/
convert(File):-
xcsp2pl(File).
xcsp2pl(File):- %File is a base name
cputime(ConvStart),
writeln(user,'c converting'(File)),
atom_codes(File,MainString),
append(MainString,".xml",InFileString),
atom_codes(InFile,InFileString),
append(MainString,".pl",OutFileString),
atom_codes(OutFile,OutFileString),
(exists(InFile)->true;format("File not found:~w~n",[InFile]),halt),
see(InFile),
tell(OutFile),
process_xcsp_xml,
seen,told,
cputime(ConvEnd),
ConvTime is ConvEnd-ConvStart,
format("c Converted in ~w ms~n",[ConvTime]).
process_xcsp_xml:-
writeln('csp(Vs):-'),
read_next_key_token(Token),
process_sections(Token,_Preds),
writeln('true.').
process_sections(Token,_Preds), var(Token) => true. % end-of-file
process_sections(presentation,Preds) =>
b_NEXT_TOKEN_ff(_,Token),
skip_presentation(Token),
read_next_key_token(KeyToken),
process_sections(KeyToken,Preds).
process_sections(domain,Preds) =>
not(not(process_domain)),
read_next_key_token(KeyToken),
process_sections(KeyToken,Preds).
process_sections(variable,Preds) =>
process_variables([],Preds).
process_sections(relation,Preds) =>
not(not(process_relation)),
read_next_key_token(KeyToken),
process_sections(KeyToken,Preds).
process_sections(predicate,Preds) =>
process_predicate(Preds),
read_next_key_token(KeyToken),
process_sections(KeyToken,Preds).
process_sections(constraint,Preds) =>
closetail(Preds),
not(not(process_constraint(Preds))),
read_next_key_token(KeyToken),
process_sections(KeyToken,Preds).
skip_presentation('') =>
b_NEXT_TOKEN_ff(_,Token),
(Token==presentation -> true;
skip_presentation(Token)).
skip_presentation('/>') => true.
skip_presentation(_) =>
b_NEXT_TOKEN_ff(_,Token),
skip_presentation(Token).
process_variables(Vars,Preds):-
process_variable(Var),
Vars1=[Var|Vars],
read_next_key_token(KeyToken),
(KeyToken==variable->
process_variables(Vars1,Preds);
reverse(Vars1,Vars2),
format("Vs=[~@],~n",[output_vars(Vars2)]),
process_sections(KeyToken,Preds)).
%%%%
process_domain:-
b_NEXT_TOKEN_ff(_,AName), % name
process_attrs(AName,Attrs,NextToken),
assoc_member(name,NameCodes,Attrs),
format("D~s=[",[NameCodes]),
process_dom_items(NextToken,_IsFirst),
skip1(domain).
process_dom_items('-',IsFirst) =>
b_NEXT_TOKEN_ff(_,Token), % must be an int
Token1 is -Token,
process_dom_items(Token1,IsFirst).
process_dom_items('+',IsFirst) =>
b_NEXT_TOKEN_ff(_,Token), % must be an int
process_dom_items(Token,IsFirst).
process_dom_items('..-',IsFirst) =>
b_NEXT_TOKEN_ff(_,Token), % must be an int
Token1 is -Token,
writename(' .. '), writename(Token1),
b_NEXT_TOKEN_ff(_,NToken),
process_dom_items(NToken,IsFirst).
process_dom_items('..+',IsFirst) =>
b_NEXT_TOKEN_ff(_,Token), % must be an int
writename(' .. '), writename(Token),
b_NEXT_TOKEN_ff(_,NToken),
process_dom_items(NToken,IsFirst).
process_dom_items('..',IsFirst) =>
b_NEXT_TOKEN_ff(_,Token), % must be an int
writename(' .. '), writename(Token),
b_NEXT_TOKEN_ff(_,NToken),
process_dom_items(NToken,IsFirst).
process_dom_items(Elm,IsFirst), integer(Elm) =>
(var(IsFirst)->IsFirst=0;write(',')),
writename(Elm),
b_NEXT_TOKEN_ff(_,NToken),
process_dom_items(NToken,IsFirst).
process_dom_items(_Token,_IsFirst) =>
writename(']'),writename(','),nl.
%%%%
process_variable(Var):-
b_NEXT_TOKEN_ff(_,AName),
process_attrs(AName,Attrs,_NextToken),
assoc_member(name,VNameCodes,Attrs),
assoc_member(domain,DNameCodes,Attrs),
atom_codes(Var,VNameCodes),
format("V~s :: D~s,~n",[VNameCodes,DNameCodes]).
%%%%
process_relation:-
b_NEXT_TOKEN_ff(_,AName),
process_attrs(AName,Attrs,NextToken1),
assoc_member(name,RNameCodes,Attrs),
assoc_member(arity,ArityCodes,Attrs),
assoc_member(semantics,Semantics,Attrs),
(Semantics=="supports"->Type=sr;Type=cr),
format("~w(R~s,~s,[",[Type,RNameCodes,ArityCodes]),
process_tuples(NextToken1,NextToken2,_),
writeln(']),'),
(NextToken2='/>'->
(b_NEXT_TOKEN_ff(_,''),b_NEXT_TOKEN_ff(_,relation)->true;true);
skip1(relation)).
% handle empty relation
%
% nonempty 12 12
process_tuples('-',NToken,IsFirstTuple) =>
b_NEXT_TOKEN_ff(_,Token1), % must be an integer
Token2 is -Token1,
process_tuples(Token2,NToken,IsFirstTuple).
process_tuples('+',NToken,IsFirstTuple) =>
b_NEXT_TOKEN_ff(_,Token1), % must be an integer
process_tuples(Token1,NToken,IsFirstTuple).
process_tuples(Token,NToken,IsFirstTuple), integer(Token) =>
(var(IsFirstTuple)->IsFirstTuple=0;writename(',')),
process_tuple(Token,Token1,_),
process_tuples(Token1,NToken,IsFirstTuple).
process_tuples('|',NToken,IsFirstTuple) =>
b_NEXT_TOKEN_ff(_,Token),
process_tuples(Token,NToken,IsFirstTuple).
process_tuples(Token,NToken,_IsFirstTuple):-NToken=Token.
process_tuple('-',NToken,IsFirstElm) =>
b_NEXT_TOKEN_ff(_,Token1), % must be an integer
Token2 is -Token1,
process_tuple(Token2,NToken,IsFirstElm).
process_tuple('+',NToken,IsFirstElm) =>
b_NEXT_TOKEN_ff(_,Token1), % must be an integer
process_tuple(Token1,NToken,IsFirstElm).
process_tuple(Token,NToken,IsFirstElm), integer(Token) =>
(var(IsFirstElm)->writename('t('),IsFirstElm=0;writename(',')),
writename(Token),
b_NEXT_TOKEN_ff(_,Token1),
process_tuple(Token1,NToken,IsFirstElm).
process_tuple(Token,NToken,_IsFirstElm) =>
NToken=Token,
writename(')').
%%%%
process_constraint(Preds):-
b_NEXT_TOKEN_ff(_,AName),
process_attrs(AName,Attrs,NextToken),
assoc_member(scope,Scope,Attrs),
assoc_member(reference,RefCodes,Attrs),
process_constraint(RefCodes,Scope,Preds,NextToken).
process_constraint("global:allDifferent",Scope,_Preds,NextToken) =>
tokenize(Scope,ActualArgs),
format("call_all_distinct([~@]),~n",[output_vars(ActualArgs)]),
(NextToken=='/>'->true;skip1(constraint)).
process_constraint("global:alldifferent",Scope,Preds,NextToken) =>
process_constraint("global:allDifferent",Scope,Preds,NextToken).
process_constraint("global:cumulative",_Scope,_Preds,_) =>
'skip_until>'(_,PToken), %
process_cumulative_params(PToken,Os,Ds,Es,Hs,Limit),
format("call_cumulative([~@],[~@],[~@],[~@],~w),~n",[output_args(Os),output_args(Ds),output_args(Es),output_args(Hs),Limit]),
skip1(constraint).
process_constraint("global:element",_Scope,_Preds,_) =>
'skip_until>'(_,IToken), % I
read_int_or_id(IToken,I),
b_NEXT_TOKEN_ff(_,PToken), %
process_element_params(PToken,As), % [A1,...,An]
b_NEXT_TOKEN_ff(_,VToken), % V
read_int_or_id(VToken,V),
format("call_element(~@,[~@],~@),~n",[output_arg(I),output_args(As),output_arg(V)]),
skip1(constraint).
process_constraint("global:weightedSum",_Scope,_Preds,_) =>
'skip_until>'(_,PToken), %
process_sum_params(PToken,Coes,Vs,Rel,Rhs),
format("call_weightedSum([~@],[~@],~w,~w),~n",[output_args(Coes),output_args(Vs),Rel,Rhs]),
skip1(constraint).
process_constraint("global:weightedsum",_Scope,_Preds,_) =>
'skip_until>'(_,PToken), %
process_sum_params(PToken,Coes,Vs,Rel,Rhs),
format("call_weightedSum([~@],[~@],~w,~w),~n",[output_args(Coes),output_args(Vs),Rel,Rhs]),
skip1(constraint).
process_constraint(RefCodes,Scope,Preds,_):- true ? % predicate, must exist
member(pred(RefCodes,FormalArgs,Body),Preds),!,
tokenize(Scope,ScopeVars),
(ScopeVars=[_]->true;writename('constr_scope(['),output_vars(ScopeVars),writename(']),'),nl),
b_NEXT_TOKEN_ff(_,_), %
'skip_until>'(_,PToken), %
process_actual_params(PToken,ActualArgs),
copy_term((FormalArgs,Body),(FormalArgsCp,BodyCp)),
ActualArgs=FormalArgsCp,
output_constrs(BodyCp),
skip1(constraint).
process_constraint(RefCodes,Scope,_Preds,NextToken) => % extension
tokenize(Scope,ActualArgs),
format("ec(R~s,~@),~n",[RefCodes,output_vars_tuple(ActualArgs)]),
(NextToken=='/>'->true;skip1(constraint)).
process_actual_params('',Args) => Args=[].
process_actual_params(Token,Args), integer(Token) =>
Args=[Token|Args1],
b_NEXT_TOKEN_ff(_,Token1),
process_actual_params(Token1,Args1).
process_actual_params('-',Args) =>
b_NEXT_TOKEN_ff(_,Token1),
Token2 is -Token1,
process_actual_params(Token2,Args).
process_actual_params('+',Args) =>
b_NEXT_TOKEN_ff(_,Token1),
process_actual_params(Token1,Args).
process_actual_params(Token,Args) =>
atom_codes(Token,Codes),
atom_codes(VToken,[0'V|Codes]),
Args=[VToken|Args1],
b_NEXT_TOKEN_ff(_,Token1),
process_actual_params(Token1,Args1).
process_cumulative_params(']',Os,Ds,Es,Hs,Limit) =>
b_NEXT_TOKEN_ff(_,LimitToken),
read_int_or_id(LimitToken,Limit),
Os=[],Ds=[],Es=[],Hs=[].
process_cumulative_params('[',Os,Ds,Es,Hs,Limit) =>
b_NEXT_TOKEN_ff(_,NToken),
process_cumulative_params(NToken,Os,Ds,Es,Hs,Limit).
process_cumulative_params('{',Os,Ds,Es,Hs,Limit) =>
Os=[O|Os1],Ds=[D|Ds1],Es=[E|Es1],Hs=[H|Hs1],
process_cumulative_param(O),
process_cumulative_param(D),
process_cumulative_param(E),
process_cumulative_param(H),
b_NEXT_TOKEN_ff(_,_), % }
b_NEXT_TOKEN_ff(_,NToken),
process_cumulative_params(NToken,Os1,Ds1,Es1,Hs1,Limit).
process_cumulative_param(A):-
b_NEXT_TOKEN_ff(_,Token),
process_cumulative_param(Token,A).
process_cumulative_param('<',A) => A='_$dummy',
b_NEXT_TOKEN_ff(_,_), % nil
b_NEXT_TOKEN_ff(_,_). % />
process_cumulative_param(Token,A) =>
read_int_or_id(Token,A).
process_element_params('[',As) =>
b_NEXT_TOKEN_ff(_,Token),
process_element_params(Token,As).
process_element_params(']',As) => As=[].
process_element_params(AToken,As) => As=[A|As1],
read_int_or_id(AToken,A),
b_NEXT_TOKEN_ff(_,NToken),
process_element_params(NToken,As1).
process_sum_params('[',Coes,Vs,Rel,Rhs) =>
b_NEXT_TOKEN_ff(_,Token),
process_sum_params(Token,Coes,Vs,Rel,Rhs).
process_sum_params(']',Coes,Vs,Rel,Rhs) =>
Coes=[],Vs=[],
b_NEXT_TOKEN_ff(_,_), %<
b_NEXT_TOKEN_ff(_,Rel),
b_NEXT_TOKEN_ff(_,_), %/>
b_NEXT_TOKEN_ff(_,RhsToken),
read_int_or_id(RhsToken,Rhs).
process_sum_params('{',Coes,Vs,Rel,Rhs) =>
Coes=[Coe|Coes1],
Vs=[V|Vs1],
b_NEXT_TOKEN_ff(_,CoeToken),
read_int_or_id(CoeToken,Coe),
b_NEXT_TOKEN_ff(_,V),
b_NEXT_TOKEN_ff(_,_), % }
b_NEXT_TOKEN_ff(_,Token),
process_sum_params(Token,Coes1,Vs1,Rel,Rhs).
%%%%
process_predicate(Preds):-
b_NEXT_TOKEN_ff(_,AName),
process_attrs(AName,Attrs,_NextToken),
assoc_member(name,PNameCodes,Attrs),
'skip_until>'(_,PToken), %
process_formal_params(PToken,PredArgs,ArgsTab),
skip2(expression,'>'),
skip1(functional),
'skip_until>'(Type,EToken),
read_expression_tokens(Type,EToken,ETokens),
process_expression(ETokens,Constr,ArgsTab),
attach(pred(PNameCodes,PredArgs,Constr),Preds),
skip2(predicate,'>').
process_formal_params('',Args,_ArgsTab) => Args=[].
process_formal_params(int,Args,ArgsTab) =>
b_NEXT_TOKEN_ff(_,Token),
process_formal_params(Token,Args,ArgsTab).
process_formal_params(Token,Args,ArgsTab) =>
Args=[VArg|Args1],
attach(arg(Token,VArg),ArgsTab),
b_NEXT_TOKEN_ff(_,NToken),
process_formal_params(NToken,Args1,ArgsTab).
read_expression_tokens(_Type,'',ETokens) => ETokens=[].
read_expression_tokens(2,Token,ETokens) =>
ETokens=[Token,'('|ETokens1],
b_NEXT_TOKEN_ff(Type,Token1),
read_expression_tokens(Type,Token1,ETokens1).
read_expression_tokens(_,Token,ETokens) =>
ETokens=[Token|ETokens1],
b_NEXT_TOKEN_ff(Type,Token1),
read_expression_tokens(Type,Token1,ETokens1).
process_expression([],Constrs,_ArgsTab) => Constrs=[].
process_expression(ETokens,Constrs,ArgsTab) =>
process_bool_exp(ETokens,ETokens1,Constr,ArgsTab),
expand_and(Constr,Constrs,Constrs1),
process_expression(ETokens1,Constrs1,ArgsTab).
expand_and((Constr1 #/\ Constr2),Constrs,ConstrsR) =>
expand_and(Constr1,Constrs,Constrs1),
expand_and(Constr2,Constrs1,ConstrsR).
expand_and(1,Constrs,ConstrsR) => Constrs=ConstrsR.
expand_and(0,Constrs,ConstrsR) => Constrs=[fail|ConstrsR].
expand_and(Constr,Constrs,ConstrsR) => Constrs=[Constr|ConstrsR].
process_bool_exp([false|Tokens],TokensR,Constr,_ArgsTab) =>
Constr=0,TokensR=Tokens.
process_bool_exp([true|Tokens],TokensR,Constr,_ArgsTab) =>
Constr=1,TokensR=Tokens.
process_bool_exp([not,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_bool_exp(Tokens,Tokens1,Constr1,ArgsTab),
Tokens1=[')'|TokensR],
Constr=(#\ Constr1).
process_bool_exp([and,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_bool_exp(Tokens,Tokens1,Constr1,ArgsTab),
Tokens1=[','|Tokens2],
process_bool_exp(Tokens2,Tokens3,Constr2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Constr1 #/\ Constr2).
process_bool_exp([or,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_bool_exp(Tokens,Tokens1,Constr1,ArgsTab),
Tokens1=[','|Tokens2],
process_bool_exp(Tokens2,Tokens3,Constr2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Constr1 #\/ Constr2).
process_bool_exp([xor,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_bool_exp(Tokens,Tokens1,Constr1,ArgsTab),
Tokens1=[','|Tokens2],
process_bool_exp(Tokens2,Tokens3,Constr2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Constr1 #\ Constr2).
process_bool_exp([iff,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_bool_exp(Tokens,Tokens1,Constr1,ArgsTab),
Tokens1=[','|Tokens2],
process_bool_exp(Tokens2,Tokens3,Constr2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Constr1 #<=>Constr2).
process_bool_exp([eq,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Exp1 #= Exp2).
process_bool_exp([ne,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Exp1 #\= Exp2).
process_bool_exp([ge,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Exp1 #>= Exp2).
process_bool_exp([gt,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Exp1 #> Exp2).
process_bool_exp([le,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Exp1 #=< Exp2).
process_bool_exp([lt,'('|Tokens],TokensR,Constr,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Constr=(Exp1 #< Exp2).
process_int_exp([neg,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[')'|TokensR],
Exp=(-Exp1).
process_int_exp([abs,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[')'|TokensR],
Exp=abs(Exp1).
process_int_exp([add,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Exp=(Exp1+Exp2).
process_int_exp([sub,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Exp=(Exp1-Exp2).
process_int_exp([mul,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Exp=(Exp1*Exp2).
process_int_exp([div,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Exp=(Exp1//Exp2).
process_int_exp([mod,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Exp=(Exp1 mod Exp2).
process_int_exp([pow,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Exp=(Exp1 ** Exp2).
process_int_exp([min,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Exp=min(Exp1,Exp2).
process_int_exp([max,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_int_exp(Tokens,Tokens1,Exp1,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab),
Tokens3=[')'|TokensR],
Exp=max(Exp1,Exp2).
process_int_exp([if,'('|Tokens],TokensR,Exp,ArgsTab) =>
process_bool_exp(Tokens,Tokens1,Cond,ArgsTab),
Tokens1=[','|Tokens2],
process_int_exp(Tokens2,Tokens3,Exp1,ArgsTab),
Tokens3=[','|Tokens4],
process_int_exp(Tokens4,Tokens5,Exp2,ArgsTab),
Tokens5=[')'|TokensR],
Exp=if(Cond,Exp1,Exp2).
process_int_exp(['-',Token|Tokens],TokensR,Exp,_ArgsTab), integer(Token) =>
Exp is -Token,
Tokens=TokensR.
process_int_exp(['+',Token|Tokens],TokensR,Exp,_ArgsTab), integer(Token) =>
Exp is Token,
Tokens=TokensR.
process_int_exp([Token|Tokens],TokensR,Exp,_ArgsTab), integer(Token) =>
Exp=Token,
Tokens=TokensR.
process_int_exp([Token|Tokens],TokensR,Exp,ArgsTab) =>
Tokens=TokensR,
member(arg(Token,Exp),ArgsTab),!.
%%%%
process_attrs('>',Attrs,NextToken) => Attrs=[],b_NEXT_TOKEN_ff(_,NextToken).
process_attrs('>+',Attrs,NextToken) => Attrs=[],NextToken='+'.
process_attrs('>-',Attrs,NextToken) => Attrs=[],NextToken='-'.
process_attrs('/>',Attrs,NextToken) => Attrs=[],NextToken='/>'.
process_attrs(AName,Attrs,NextToken) =>
b_NEXT_TOKEN_ff(_,_), % =
b_NEXT_TOKEN_ff(_,Val),
(atom(Val)->atom_codes(Val,Value);
integer(Val)->number_codes(Val,Value);
Value=Val),
Attrs=[AName=Value|Attrs1],
b_NEXT_TOKEN_ff(_,AName1),
process_attrs(AName1,Attrs1,NextToken).
%%%%
'skip_until>'(Type,Token):-
b_NEXT_TOKEN_ff(_,Token1),
'skip_until>'(Token1,Type,Token).
'skip_until>'('>',Type,Token) =>
b_NEXT_TOKEN_ff(Type,Token).
'skip_until>'('>+',Type,Token) =>
Type=4,Token='+'.
'skip_until>'('>-',Type,Token) =>
Type=4,Token='-'.
'skip_until>'(_,Type,Token) =>
b_NEXT_TOKEN_ff(_Type1,Token1),
'skip_until>'(Token1,Type,Token).
skip1(Token):-
b_NEXT_TOKEN_ff(_,CurToken),
skip1(Token,CurToken).
skip1(Token,Token) => true.
skip1(Token,_) =>
b_NEXT_TOKEN_ff(_,CurToken),
skip1(Token,CurToken).
skip2(Token1,Token2):-
b_NEXT_TOKEN_ff(_,CurToken),
skip2(Token1,Token2,CurToken).
skip2(Token1,Token2,Token1) =>
b_NEXT_TOKEN_ff(_,CurToken),
(CurToken==Token2 -> true;
skip2(Token1,Token2,CurToken)).
skip2(Token1,Token2,_) =>
b_NEXT_TOKEN_ff(_,CurToken),
skip2(Token1,Token2,CurToken).
read_next_key_token(KeyToken):-
b_NEXT_TOKEN_ff(_, Token),
(key_token(Token)->
KeyToken=Token;
read_next_key_token(KeyToken)).
read_int_or_id('+',Val) =>
b_NEXT_TOKEN_ff(_, Val). % integer
read_int_or_id('-',Val) =>
b_NEXT_TOKEN_ff(_, Val1),
Val is -Val1.
read_int_or_id(Token,Val) => Val=Token.
key_token(EndOfFile), var(EndOfFile) => true.
key_token(domain) => true.
key_token(variable) => true.
key_token(relation) => true.
key_token(predicate) => true.
key_token(constraint) => true.
key_token(presentation) => true.
%%%%
tokenize([],Tokens) => Tokens=[].
tokenize([Code|Codes],Tokens):-true ?
is_space(Code),!,
tokenize(Codes,Tokens).
tokenize([Code|Codes],Tokens):-true ?
is_delimeter(Code),!,
char_code(Token,Code),
Tokens=[Token|TokensR],
tokenize(Codes,TokensR).
tokenize([Code|Codes],Tokens) =>
extract_token(Codes,Name,CodesR),
name(Token,[Code|Name]),
Tokens=[Token|TokensR],
tokenize(CodesR,TokensR).
extract_token([],Name,CodesR) => Name=[],CodesR=[].
extract_token([Code|Codes],Name,CodesR):-true ?
is_space(Code),!,
Name=[],
CodesR=Codes.
extract_token(Codes,Name,CodesR):-Codes=[Code|_] ?
is_delimeter(Code),!,
Name=[],
CodesR=Codes.
extract_token([Code|Codes],Name,CodesR) =>
Name=[Code|NameR],
extract_token(Codes,NameR,CodesR).
:-mode is_space(+).
is_space(0' ).
is_space(9). % tab
is_space(10).
is_space(13).
:-mode is_delimeter(+).
is_delimeter(0'().
is_delimeter(0')).
is_delimeter(0',).
is_delimeter(0'.).
is_delimeter(0'|).
output_vars([]) => true.
output_vars([V|Vs]) =>
(V=='_$dummy'->writename('_');writename('V'),writename(V)),
(Vs==[]->true;
writename(','),
output_vars(Vs)).
output_vars_tuple(Tuple) =>
writename('t('),
output_vars_tuple_rest(Tuple).
output_vars_tuple_rest([V]) =>
writename('V'),writename(V),writename(')').
output_vars_tuple_rest([V|Vs]) =>
writename('V'),writename(V),writename(','),
output_vars_tuple_rest(Vs).
output_constrs([]) => true.
output_constrs([Constr|Constrs]):-
write(Constr),writename(','),nl,
output_constrs(Constrs).
output_args([]) => true.
output_args([V|Vs]) =>
output_arg(V),
(Vs==[]->true;
writename(','),
output_args(Vs)).
output_arg('_$dummy') => writename('_').
output_arg(Arg), integer(Arg) => writename(Arg).
output_arg(Arg) => writename('V'),writename(Arg).
%%%%%
assoc_member(AName,AVal,[AName=AVal1|_]) => AVal=AVal1.
assoc_member(AName,AVal,[_|L]) => assoc_member(AName,AVal,L).