1% nal_reader.pl
    2% Read Non_Axiomatic Logic from Prolog
    3:-module(nal_reader,[
    4            nal_test/0,
    5            nal_test/1,
    6            nal_read_clause/2,
    7           % nal_test/2,
    8          %  nal_call/2,
    9            nal_call/3                   
   10         ]).   11
   12:- set_module(class(library)).   13:- set_module(base(system)).   14
   15:- use_module(library(logicmoo_common)).   16
   17:- use_module(library(logicmoo/dcg_meta)).   18:- use_module(library(narsese)).   19
   20
   21
   22/*
   23                task ::= [budget] sentence                       (* task to be processed *)
   24
   25         sentence ::= statement"." [tense] [truth]            (* judgement to be absorbed into beliefs *)
   26                    | statement"?" [tense] [truth]            (* question on thuth-value to be answered *)
   27                    | statement"!" [desire]                   (* goal to be realized by operations *)
   28                    | statement"@" [desire]                   (* question on desire-value to be answered *)
   29
   30        statement ::= <"<">term copula term<">">              (* two terms related to each other *)
   31                    | <"(">term copula term<")">              (* two terms related to each other, new notation *)
   32                    | term                                    (* a term can name a statement *)
   33                    | "(^"word {","term} ")"                  (* an operation to be executed *)
   34                    | word"("term {","term} ")"               (* an operation to be executed, new notation *)
   35
   36           copula ::= "-->"                                   (* inheritance *)
   37                    | "<->"                                   (* similarity *)
   38                    | "{--"                                   (* instance *)
   39                    | "--]"                                   (* property *)
   40                    | "{-]"                                   (* instance-property *)
   41                    | "==>"                                   (* implication *)
   42                    | "=/>"                                   (* predictive implication *)
   43                    | "=|>"                                   (* concurrent implication *)
   44                    | "=\\>"                                  (* =\> retrospective implication *)
   45                    | "<=>"                                   (* equivalence *)
   46                    | "</>"                                   (* predictive equivalence *)
   47                    | "<|>"                                   (* concurrent equivalence *)
   48
   49             term ::= word                                    (* an atomic constant term *)
   50                    | variable                                (* an atomic variable term *)
   51                    | compound-term                           (* a term with internal structure *)
   52                    | statement                               (* a statement can serve as a term *)
   53
   54    compound-term ::= op-ext-set term {"," term} "}"          (* extensional set *)
   55                    | op-int-set term {"," term} "]"          (* intensional set *)
   56                    | "("op-multi"," term {"," term} ")"      (* with prefix operator *)
   57                    | "("op-single"," term "," term ")"       (* with prefix operator *)
   58                    | "(" term {op-multi term} ")"            (* with infix operator *)
   59                    | "(" term op-single term ")"             (* with infix operator *)
   60                    | "(" term {","term} ")"                  (* product, new notation *)
   61                    | "(" op-ext-image "," term {"," term} ")"(* special case, extensional image *)
   62                    | "(" op-int-image "," term {"," term} ")"(* special case, \ intensional image *)
   63                    | "(" op-negation "," term ")"            (* negation *)
   64                    | op-negation term                        (* negation, new notation *)
   65
   66        op-int-set::= "["                                     (* intensional set *)
   67        op-ext-set::= "{"                                     (* extensional set *)
   68       op-negation::= "--"                                    (* negation *)
   69      op-int-image::= "\\"                                    (* \ intensional image *)
   70      op-ext-image::= "/"                                     (* extensional image *)
   71         op-multi ::= "&&"                                    (* conjunction *)
   72                    | "*"                                     (* product *)
   73                    | "||"                                    (* disjunction *)
   74                    | "&|"                                    (* parallel events *)
   75                    | "&/"                                    (* sequential events *)
   76                    | "|"                                     (* intensional intersection *)
   77                    | "&"                                     (* extensional intersection *)
   78        op-single ::= "-"                                     (* extensional difference *)
   79                    | "~"                                     (* intensional difference *)
   80
   81         variable ::= "$"word                                 (* independent variable *)
   82                    | "#"word                                 (* dependent variable *)
   83                    | "?"word                                 (* query variable in question *)
   84
   85            tense ::= ":/:"                                   (* future event *)
   86                    | ":|:"                                   (* present event *)
   87                    | ":\\:"                                  (* :\: past event *)
   88          
   89           desire ::= truth                                   (* same format, different interpretations *)
   90            truth ::= <"%">frequency[<";">confidence]<"%">    (* two numbers in [0,1]x(0,1) *)
   91           budget ::= <"$">priority[<";">durability][<";">quality]<"$"> (* three numbers in [0,1]x(0,1)x[0,1] *)
   92
   93               word : #"[^\ ]+"                               (* unicode string *)    
   94           priority : #"([0]?\.[0-9]+|1\.[0]*|1|0)"           (* 0 <= x <= 1 *)
   95         durability : #"[0]?\.[0]*[1-9]{1}[0-9]*"             (* 0 <  x <  1 *)
   96            quality : #"([0]?\.[0-9]+|1\.[0]*|1|0)"           (* 0 <= x <= 1 *)
   97          frequency : #"([0]?\.[0-9]+|1\.[0]*|1|0)"           (* 0 <= x <= 1 *)
   98         confidence : #"[0]?\.[0]*[1-9]{1}[0-9]*"             (* 0 <  x <  1 *)
   99*/
  100
  101
  102
  103
  104nal_task(S)--> cwhite,!,nal_task(S),!.
  105nal_task(task(X,S,T,O,B)) --> nal_task(X,S,T,O,B),!.
  106
  107
  108
  109nal_task(X,S,T,O,B) --> optional(B, nal_budget),!, nal_sentence(X,S,T,O).  % task to be processed 
  110
  111
  112nal_sentence(X,S,T,O)--> nal_statement(S), nal_post_statement(X,T,O).
  113
  114nal_post_statement(X,T,O)--> 
  115          /*nal_statement(S),*/ nal_o(`.` ,X, judgement)-> optional(T,nal_tense)-> optional(O,nal_truth),!   % judgement to be absorbed into beliefs 
  116        ; /*nal_statement(S),*/ nal_o(`?` ,X, question_truth)-> optional(T,nal_tense)-> optional(O,nal_truth),! % question on truth_value to be answered 
  117        ; /*nal_statement(S),*/ nal_o(`!` ,X, goal), optional(O,nal_desire)                  % goal to be realized by operations 
  118        ; /*nal_statement(S),*/ nal_o(`@` ,X, question_desire), optional(O,nal_desire)       % question on desire_value to be answered 
  119        .
  120
  121nal_statement(S)--> mw(nal_statement_0(S)),!.
  122nal_statement_0(S)--> 
  123        mw(`<`) ,!, nal_term(A), nal_copula(R), nal_term(B), mw(`>`) ,   {S=..[R,A,B]}   % two, terms related to each other 
  124      ;  nal_l_paren, `^` , nal_term_list_comma(L), nal_paren_r,       {S= exec(L)}            % an operation to be executed 
  125      ;  nal_l_paren, nal_term(A), nal_copula(R), nal_term(B), nal_paren_r,  {S=..[R,A,B]}       % two, terms related to each other, new notation 
  126      ;  nal_word(A), nal_l_paren, nal_term_list_comma(L), nal_paren_r,    {S= exec([A|L])}        % an operation to be executed, new notation 
  127      ;  nal_term_1(X),             {S= nal_named_statement(X)}                       % a, term, can name a statement(S) 
  128      .
  129         
  130
  131nal_copula(X) -->      
  132            nal_o(`-->` ,X,                          inheritance )
  133         ;  nal_o(`<->` ,X,                          similarity )
  134         ;  nal_o(`{--` ,X,                          instance )
  135         ;  nal_o(`--]` ,X,                          property )
  136         ;  nal_o(`{-]` ,X,                          inst_prop )
  137         ;  nal_o(`==>` ,X,                          implication )
  138         ;  nal_o(`=/>` ,X,                          predictive_impl )
  139         ;  nal_o(`=|>` ,X,                          concurrent_impl )
  140         ;  nal_o(`=\\>` ,X,                         retrospective_impl )
  141         ;  nal_o(`<=>` ,X,                          equiv )
  142         ;  nal_o(`</>` ,X,                          predictive_equiv )
  143         ;  nal_o(`<|>` ,X,                          concurrent_equiv )
  144         ;  nal_o(`=>` ,X,                           unknown_impl )
  145         .
  146
  147nal_term(N) --> nal_term_old(O), {old_to_new(O,N)}.
  148nal_term_old(S)
  149       --> nal_word(S)                         % an atomic constant, term,         
  150        ;  nal_variable(S)                     % an atomic variable, term, 
  151        ;  nal_compound_term(S)                % a, term, with internal structure 
  152        ;  nal_statement(S)                    % a statement can serve as a, term, 
  153        .
  154
  155nal_term_0(N) --> nal_term_0_old(O), {old_to_new(O,N)}.
  156nal_term_0_old(S) 
  157        -->  nal_word_0(S)                       % an atomic constant, term,         
  158        ;  nal_variable_0(S)                     % an atomic variable, term, 
  159        ;  nal_compound_term_0(S)                % a, term, with internal structure 
  160        ;  nal_statement_0(S)                    % a statement can serve as a, term, 
  161        .
  162
  163nal_term_1(N) --> nal_term_1_old(O), {old_to_new(O,N)}.
  164nal_term_1_old(S)
  165        --> nal_word(S)                        % an atomic constant, term,         
  166        ;  nal_variable(S)                     % an atomic variable, term, 
  167        ;  nal_compound_term(S)                % a, term, with internal structure 
  168        .
  169
  170old_to_new(rel([R, var(arg, L) | B]), ext_image(New)):- length(Left,L), append(Left,Right,[R|B]), append(Left,['_'|Right],New).
  171old_to_new(rel([R, var(int, L) | B]), int_image(New)):- length(Left,L), append(Left,Right,[R|B]), append(Left,['_'|Right],New).
  172old_to_new(X,X).
  173nal_compound_term(X)--> mw(nal_compound_term_0(X)).
  174
  175nal_compound_term_0('exec'([S]))--> `^`,!,nal_term_1(S).
  176nal_compound_term_0(S)--> \+ dcg_peek(`<`),!,
  177   (  nal_o(nal_op_ext_set,X,ext_set), nal_term_list_comma(L), `}`                % extensional set 
  178   ;  nal_o(nal_op_int_set,X,int_set), nal_term_list_comma(L), `]`                % intensional set 
  179
  180   ;  nal_word_0(A), `[`, nal_term_list_comma(L), `]`,  {S= v(A,L)}            % @TODO notation 
  181   ;  nal_o(nal_op_negation,X,negation), nal_term(AB),{L=[AB]}              % negation, new notation 
  182   ;   nal_l_paren, nal_paren_compound_term(X,L), nal_paren_r 
  183   ), {S=..[X,L]}.
  184
  185nal_paren_compound_term(X,L) --> 
  186      nal_op_multi(X), nal_comma, nal_term_list_comma(L)                        % with prefix operator 
  187   ;  nal_op_single(X), nal_comma, nal_term(A), nal_comma, nal_term(B), {L=[A,B]} % with prefix operator 
  188   ;  nal_o(nal_op_ext_image,X,ext_image), nal_comma, nal_term_list_comma(L)        % special case, extensional image 
  189   ;  nal_o(nal_op_int_image,X,int_image), nal_comma, nal_term_list_comma(L)        % special case, \ intensional image 
  190   ;  nal_o(nal_op_negation,X,negation), nal_comma, nal_term(AB),{L=[AB]}     % negation 
  191   ;  nal_term(A), nal_op_multi(X), nal_term(B),{L=[A,B]}                 % with infix operator 
  192   ;  nal_term(A), nal_op_single(X), nal_term(B),{L=[A,B]}                % with infix operator 
  193   ;  nal_preserve_whitespace((nal_term_0(A), cspace,  {X=rel}, nal_term_list_white(SL, ` `))),{L=[A|SL]}
  194   ;  {X=product}, nal_term_list_comma(L)                               % product, new notation 
  195   .
  196
  197nal_op_int_set-->`[`.                          % intensional set 
  198nal_op_ext_set-->`{`.                          % extensional set 
  199nal_op_negation-->`--`.                        % negation 
  200nal_op_int_image-->`\\`.                       % \ intensional image 
  201nal_op_ext_image-->`/`.                        % / extensional image 
  202
  203
  204nal_preserve_whitespace(DCG,S,E) :- locally(b_setval(whitespace,preserve),phrase(DCG,S,E)).
  205% nal_no_preserve_whitespace(DCG,S,E) :- phrase(DCG,S,E).
  206
  207
  208nal_op_multi(X)-->   
  209        nal_o(`&&` ,X, and)                          % conjunction 
  210      ; nal_o(`*` ,X, product)                       % product 
  211      ; nal_o(`||` ,X, or)                           % disjunction 
  212      ; nal_o(`#` ,X, sequence_spatial)              % patham9 "sequence", wasn't really useful for NLP, it was called PART
  213      ; nal_o(`&|` ,X, parallel_evnts)               % parallel events 
  214      ; nal_o(`&/` ,X, sequence_evnts)               % sequential events 
  215      ; nal_o(`|` ,X, int_intersection)              % intensional intersection 
  216      ; nal_o(`&` ,X, ext_intersection)              % extensional intersection 
  217      .
  218nal_op_single(X) --> 
  219          nal_o(`-`, X, ext_difference)              % extensional difference 
  220       ;  nal_o(`~`, X, int_difference)              % intensional difference 
  221       .
  222
  223nal_variable(V)--> mw(nal_variable_0(V)).
  224
  225nal_variable_0(var(X,W))
  226    -->nal_o(`$`, X, ind), nal_word_0(W)      % independent variable 
  227      ;nal_o(`#`, X, dep), nal_word_0(W)      % dependent variable 
  228      ;nal_o(`?`, X, query), nal_word_0(W)    % query variable in question 
  229      ;nal_o(`/`, X, arg), nal_word_0(W)      % query variable in params 
  230      ;nal_o(`\\`,X, int), nal_word_0(W)      % query variable in .... 
  231      .
  232
  233nal_variable_0(('_')) --> `_`.
  234nal_variable_0(('#')) --> `#`.
  235nal_variable_0(('$')) --> `$`.
  236
  237
  238nal_tense(X) -->
  239      nal_o(`:/:`, X, future)                        % future event 
  240   ;  nal_o(`:|:`, X, present)                       % present event 
  241   ;  nal_o(`:\\:`, X, past)                         % :\: past event 
  242   .
  243nal_tense('t!'(X)) --> `:!`, number(X), `:`.
  244nal_tense('t'(X)) --> `:`, nal_term_1(X), `:`.
  245
  246% Desire is same format of Truth, but different interpretations 
  247nal_desire(D)-->nal_truth(D).									
  248% Truth is two numbers in [0,1]x(0,1) 
  249nal_truth([F,C])--> `%`, !, nal_frequency(F), optional((`;`, nal_confidence(C))), `%`.	                
  250nal_truth([F,C])--> `{`, !, nal_frequency(F), nal_confidence(C), `}`.	                
  251% Budget is three numbers in optional(O,0,1]x(0,1)x[0,1] 
  252nal_budget(nal_budget_pdq(P,D,Q))--> `$`,!, nal_priority(P), optional(( `;`, nal_durability(D))), optional((`;`, nal_quality(Q))), `$`.  
  253
  254
  255nal_word(E) --> mw(nal_word_0(E)).
  256
  257nal_word_0('+'(E)) --> `+`,dcg_basics:integer(E),!.
  258nal_word_0(E) --> dcg_basics:number(E),!.
  259nal_word_0(E) --> quoted_string(E),!.
  260nal_word_0(E) --> dcg_peek([C]),{char_type(C,alpha)},!, nal_rsymbol([],E),!.
  261
  262
  263  nal_priority(F) --> nal_float_inclusive(0,1,F).           %  0 <= x <= 1       
  264nal_durability(F) --> nal_float_exclusive(0,1,F).           %  0 <  x <  1 
  265   nal_quality(F) --> nal_float_inclusive(0,1,F).           %  0 <= x <= 1 
  266 nal_frequency(F) --> nal_float_inclusive(0,1,F).           %  0 <= x <= 1 
  267nal_confidence(F) --> nal_float_exclusive(0,1,F).           %  0 <  x <  1 
  268
  269nal_o(S,X,X) --> owhite,S,owhite.
  270nal_o(X,X) --> nal_o(X,X,X).
  271
  272nal_float_inclusive(L,H,F)--> mw((dcg_basics:number(F) -> {nal_warn_if_strict((L=< F,F=< H))})).
  273nal_float_exclusive(L,H,F)--> mw((dcg_basics:number(F) -> {nal_warn_if_strict((L < F,F < H))})).
  274
  275
  276
  277nal_warn_if_strict(G):- call(G),!.
  278nal_warn_if_strict(G):- dmsg(nal_warn_if_strict(G)),!.
  279
  280:- set_dcg_meta_reader_options(file_comment_reader, nal_comment_expr).  281
  282
  283nal_comment_expr(X) --> cspace,!,nal_comment_expr(X).
  284nal_comment_expr('$COMMENT'(Expr,I,CP)) --> nal_comment_expr_3(Expr,I,CP),!.
  285
  286nal_comment_expr_3(T,N,CharPOS) --> `/*`, !, my_lazy_list_location(file(_,_,N,CharPOS)),!, zalwayz(read_string_until_no_esc(S,`*/`)),!,
  287  {text_to_string_safe(S,T)},!.
  288nal_comment_expr_3(T,N,CharPOS) -->  {nal_cmt_until_eoln(Text)},Text,!, my_lazy_list_location(file(_,_,N,CharPOS)),!,zalwayz(read_string_until_no_esc(S,eoln)),!,
  289 {text_to_string_safe(S,T)},!.
  290
  291
  292nal_cmt_until_eoln(`//`).
  293nal_cmt_until_eoln(`'`).
  294nal_cmt_until_eoln(`**`).
  295
  296
  297nal_comma --> mw(`,`).
  298nal_l_paren --> mw(`(`).
  299nal_paren_r --> mw(`)`).
  300
  301nal_term_list_white([H|T], Sep) --> nal_term_0(H), ( (Sep,owhite) ->  nal_term_list_white(T, Sep) ; ({T=[]},owhite)).
  302nal_term_list_comma([H|T]) --> nal_term(H), ( nal_comma ->  nal_term_list_comma(T) ; {T=[]} ).
  303
  304
  305nal_rsymbol(Chars,E) --> [C], {notrace(nal_sym_char(C))},!, nal_sym_continue(S), {append(Chars,[C|S],AChars),string_to_atom(AChars,E)},!.
  306nal_sym_continue([]) --> nal_peek_symbol_breaker,!.
  307nal_sym_continue([H|T]) --> [H], {nal_sym_char(H)},!, nal_sym_continue(T).
  308nal_sym_continue([]) --> [].
  309
  310nal_peek_symbol_breaker --> dcg_peek(`--`).
  311nal_peek_symbol_breaker --> dcg_peek(`-`),!,{fail}.
  312nal_peek_symbol_breaker --> dcg_peek(one_blank).
  313nal_peek_symbol_breaker --> dcg_peek([C]),{\+ nal_sym_char(C)},!.
  314
  315nal_sym_char(C):- \+ integer(C),!,char_code(C,D),!,nal_sym_char(D).
  316nal_sym_char(C):- bx(C =<  32),!,fail.
  317%nal_sym_char(44). % allow comma in middle of symbol
  318% word is: #"[^\ ]+"   %  unicode string     
  319nal_sym_char(C):- nal_never_symbol_char(NeverSymbolList),memberchk(C,NeverSymbolList),!,fail.  % maybe 44 ? nal_comma
  320%nal_sym_char(C):- nb_current('$maybe_string',t),memberchk(C,`,.:;!%`),!,fail.
  321nal_sym_char(_):- !.
  322
  323nal_never_symbol_char(`";()~'[]<>``{},=\\^`).
  324
  325
  326nal_rsymbol_cont(Prepend,E) --> nal_sym_continue(S), {append(Prepend,S,AChars),string_to_atom(AChars,E)},!.
  327
  328
  329nal_is_test_file(X):-filematch('../../nal-tests/**/*',X), \+ nal_non_file(X). 
  330nal_is_test_file(X):-filematch('../../examples/**/*',X), \+ nal_non_file(X). 
  331nal_non_file(X):- downcase_atom(X,DC),X\==DC,!,nal_non_file(DC).
  332nal_non_file(X):- atom_concat(readme,_,X).
  333nal_non_file(X):- atom_concat(_,'.pl',X).
  334
  335nal_test_file:- 
  336 make,
  337 catch((
  338   forall(nal_is_test_file(X),((dmsg(file_begin(X)),ignore(nal_test_file(X)),dmsg(file_end(X)))))),
  339    '$aborted',true).
  340
  341nal_test_file(File):- (\+ atom(File); \+ is_absolute_file_name(File)),
  342  absolute_file_name(File,Absolute), !, nal_test_file(Absolute).
  343nal_test_file(File):- open(File,read,In),
  344  nal_read_clauses(In, Expr),!,
  345  must_or_rtrace(nal_call(nal_test_file,Expr,OutL)),!,
  346  flatten([OutL],Out),
  347  maplist(wdmsg,Out),!.
  348
  349% NAL file reader
  350nal_file(end_of_file) --> file_eof,!.
  351nal_file(O) --> cspace, !, nal_file(O).
  352nal_file([]) -->  \+ dcg_peek([_]), !.
  353nal_file(Comment) --> nal_comment_expr(Comment).
  354nal_file(O) --> nal_file_element(O), !, owhite.
  355% fallback to english in a file
  356nal_file(unk_english(Text)) --> read_string_until_no_esc(Str,eoln), 
  357  {atom_string(Str,Text)},!. %split_string(Str, "", "\s\t\r\n", Text).
  358
  359% nal_file(planStepLPG(Name,Expr,Value)) --> owhite,sym_or_num(Name),`:`,owhite, nal(Expr),owhite, `[`,sym_or_num(Value),`]`,owhite.  %   0.0003:   (PICK-UP ANDY IBM-R30 CS-LOUNGE) [0.1000]
  360% nal_file(Term,Left,Right):- eoln(EOL),append(LLeft,[46,EOL|Right],Left),read_term_from_codes(LLeft,Term,[double_quotes(string),syntax_errors(fail)]),!.
  361% nal_file(Term,Left,Right):- append(LLeft,[46|Right],Left), ( \+ member(46,Right)),read_term_from_codes(LLeft,Term,[double_quotes(string),syntax_errors(fail)]),!.
  362
  363% non-standard
  364nal_file_element(outputMustContain(O)) --> `''outputMustContain('`, !, trace, read_string_until(Str,`')`),{fmt(Str),phrase(nal_task(O),Str,[])}. 
  365nal_file_element('1Answer'(O) ) --> `' Answer `, read_string_until(Str,(`{`,read_string_until(_,eoln))),{phrase(nal_task(O),Str,[])}. 
  366nal_file_element(N=V          ) -->  `*`, nal_word(N), mw(`=`), nal_term(V).
  367nal_file_element(nal_in(H,V3))  -->  `IN:`,   nal_task(H), optional(nal_three_vals(V3)).
  368nal_file_element(nal_out(H,V3)) -->  `OUT:`,  nal_task(H), optional(nal_three_vals(V3)).
  369% standard
  370nal_file_element(do_steps(N)) --> dcg_basics:number(N),!.
  371nal_file_element(H) --> nal_task(H).
  372nal_file_element(nal_term(H)) --> nal_term(H).
  373% nal_read_clause("'the detective claims that tim lives in graz",A)
  374
  375
  376% {1 : 4;3} 
  377nal_three_vals(V3)--> `{`, read_string_until_no_esc(Str,(`}`;eoln)), 
  378  {read_term_from_codes(Str,V3,[double_quotes(string),syntax_errors(fail)])},!.
  379
  380
  381%nal_file_with_comments(O,with_text(O,Txt),S,E):- copy_until_tail(S,Copy),text_to_string_safe(Copy,Txt),!.
  382
  383
  384:- thread_local(t_l:sreader_options/2).  385
  386
  387
  388nal_test:- fmt('\nNAL TEST'), forall(nal_is_test(_,Test),nal_test(Test)).
  389
  390
  391:- use_module(library(dcg/basics)).  392
  393% try_reader_test(Test):- is_stream(Test), !, \+ is_compound(Test), open_string(Test,Stream), try_reader_test(Stream).
  394nal_test(Test):- 
  395  fmt("\n-----------------------------\n"),
  396  fmt(Test), 
  397  fmt("-----------------------------\n"),
  398  nal_call('dmsg',Test,Out),dmsg(Out).
  399
  400
  401nal_zave_varname(N,V):- debug_var(N,V),!.
  402%nal_zave_varname(N,V):- V = '$VAR'(N).
  403
  404/*
  405implode_varnames(Vs):- (var(Vs) ; Vs==[]),!.
  406implode_varnames([NV|Vs]) :- implode_varnames(Vs),
  407  (var(NV) -> ignore((nal_variable_name(NV,Name),nal_zave_varname(Name,NV))); 
  408  ignore((NV=(N=V),nal_zave_varname(N,V)))).
  409*/
  410
  411nal_read_clauses( Text, Out):-
  412 findall(Cl,nal_read_clause(Text, Cl), OutL),
  413 flatten([OutL],Out).
  414
  415nal_read_clause( NonStream, Out):- \+ is_stream(NonStream), !, % wdmsg(NonStream),
  416  must_or_rtrace((open_string(NonStream,Stream), nal_read_clause(Stream, Out))).
  417
  418nal_read_clause(Stream, Out):-
  419 '$current_typein_module'(M),
  420  M\== input, !,
  421  setup_call_cleanup(
  422   '$set_typein_module'(input),
  423   nal_read_clause(Stream, Out),
  424   '$set_typein_module'(M)).
  425
  426nal_read_clause(Stream, Out):-
  427 op(601, xfx, input:(/)),
  428 op(601, xfx, input:(\\)),
  429 (at_end_of_stream(Stream)-> Out=[]; 
  430   (nal_read_term(Stream, Term),
  431    (Term == end_of_file -> Out=[];
  432      (Term = (:- Exec) -> (input:call(Exec), Out=More) ; Out = [Term|More]),
  433       nal_read_clause(Stream, More)))).
  434
  435nal_read_term(In,Expr):- 
  436 notrace(( is_stream(In), 
  437  remove_pending_buffer_codes(In,Codes), 
  438  read_codes_from_pending_input(In,Text), Text\==[])), !,
  439  call_cleanup(parse_meta_ascii(nal_file, Text,Expr),
  440    append_buffer_codes(In,Codes)).
  441nal_read_term(Text,Expr):- 
  442 notrace(( =( ascii_,In),
  443  remove_pending_buffer_codes(In,Codes))),   
  444  call_cleanup(parse_meta_ascii(nal_file, Text,Expr),
  445    append_buffer_codes(In,Codes)).
  446
  447% Expand Stream or String
  448nal_call(Ctx, Stream, Out):- \+ compound(Stream),
  449  must_or_rtrace(nal_read_clauses(Stream, List)), !,
  450  nal_call(Ctx, List, Out).
  451
  452nal_call(Ctx, List, Out):- is_list(List),!, maplist(nal_call(Ctx),List, OutL),flatten(OutL,Out).
  453nal_call(Ctx, InnerCtx=json(List), Out):- !,  nal_call([InnerCtx|Ctx], List, Out).
  454
  455nal_call(Ctx, List, Out):- 
  456   sub_term(Sub, List), nonvar(Sub), 
  457   nal_rule_rewrite(Ctx, Sub, NewSub),
  458   % ignore((NewSub=='$',wdmsg(nal_rule_rewrite(_Ctx, Sub, NewSub)))),
  459   nonvar(NewSub), Sub\==NewSub,
  460   subst(List, Sub, NewSub, NewList), 
  461   List\==NewList, !, 
  462   nal_call(Ctx, NewList, Out).
  463
  464nal_call(_Ctx, List, Out):- flatten([List], Out),!.
  465
  466
  467
  468
  469nal_rule_rewrite(_Ctx, json(Replace), Replace):- nonvar(Replace),!.
  470
  471
  472nal_join_atomics(Sep,List,Joined):- atomics_to_string(List,Sep,Joined).
  473
  474/*
  475nal_into_tokenized(Text,TokenizedText):- \+ string(Text),!, 
  476  any_to_string(Text,String), nal_into_tokenized(String,TokenizedText).
  477nal_into_tokenized(Text,TokenizedText):-
  478 split_string(Text, "", "\s\t\r\n", [L]), L\==Text,!,
  479 nal_into_tokenized(L,M), 
  480 %string_concat(M,"\n",TokenizedText).
  481 string_concat(M,"",TokenizedText).
  482nal_into_tokenized(Text,TokenizedText):-   L=[_S1,_S2|_SS],    
  483  member(Split,["\n'","'\n","<META>'","<META>","\n"]),  
  484  atomic_list_concat(L,Split,Text),  
  485  maplist(nal_into_tokenized,L,LO),
  486  atomics_to_string(LO,Split, TokenizedText).
  487nal_into_tokenized(Text,TokenizedText):-   
  488  split_string(Text, "\n", "\s\t\n\r",StringList),
  489  maplist(into_text80_atoms,StringList,SentenceList),
  490  maplist(nal_join_atomics(' '),SentenceList,ListOfStrings),
  491  nal_join_atomics('\n',ListOfStrings,TokenizedText),!.
  492*/
  493
  494:- fixup_exports.  495
  496nal_is_test(read, "'the detective claims that tim lives in graz").
  497nal_is_test(read, "<{tim} --> (/,livingIn,_,{graz})>.").
  498nal_is_test(read, "<bird --> swimmer>. %0.87;0.91%").
  499nal_is_test(read, "''outputMustContain('<bird --> swimmer>. %0.87;0.91%')").
  500nal_is_test(read, "1").
  501
  502nal_is_test(read, "$1").
  503nal_is_test(read, "#1").
  504nal_is_test(read, "?1").
  505nal_is_test(read, "/1").
  506nal_is_test(read, "\\1").
  507% like to distinguish 
  508%         "eaten by tiger" vs. "eating tiger"  
  509% before:  (/,eat,tiger,_) vs. (/,eat,_,tiger)
  510% now:      (eat /2 tiger) vs. (eat /1 tiger)
  511nal_is_test(read, "'eating tiger").
  512nal_is_test(read, "(eat /1 tiger)").
  513nal_is_test(read, "(/,eat,_,tiger)").
  514nal_is_test(read, "'eaten by tiger").
  515nal_is_test(read, "(eat /2 tiger)").
  516nal_is_test(read, "(/,eat,tiger,_)").
  517nal_is_test(read, "'intensional eating").
  518nal_is_test(read, "(eat \\1 tiger)").
  519nal_is_test(read, "(\\,eat,_,tiger)").
  520nal_is_test(read, "(eat \\2 tiger)").
  521nal_is_test(read, "(\\,eat,tiger,_)").
  522
  523% 
  524nal_is_test(exec, "'Revision ------
  525
  526'Bird is a type of swimmer.
  527<bird --> swimmer>.
  528
  529'Bird is probably not a type of swimmer.
  530<bird --> swimmer>. %0.10;0.60%
  531
  5321
  533
  534'Bird is very likely to be a type of swimmer.
  535''outputMustContain('<bird --> swimmer>. %0.87;0.91%')").
  536
  537nal_is_test(exec, "
  538********** revision
  539  IN: <bird --> swimmer>. %1.00;0.90% {0 : 1} 
  540  IN: <bird --> swimmer>. %0.10;0.60% {0 : 2} 
  5411
  542 OUT: <bird --> swimmer>. %0.87;0.91% {1 : 1;2} 
  543").
  544
  545nal_is_test(exec, "********** deduction
  546  IN: <bird --> animal>. %1.00;0.90% {0 : 1} 
  547  IN: <robin --> bird>. %1.00;0.90% {0 : 2} 
  5481
  549 OUT: <robin --> animal>. %1.00;0.81% {1 : 2;1} 
  550 OUT: <animal --> robin>. %1.00;0.45% {1 : 2;1} ").
  551
  552nal_is_test(exec, "
  553********** abduction
  554  IN: <sport --> competition>. %1.00;0.90% {0 : 1} 
  555  IN: <chess --> competition>. %0.90;0.90% {0 : 2} 
  5561
  557 OUT: <sport --> chess>. %1.00;0.42% {1 : 2;1} 
  558 OUT: <chess --> sport>. %0.90;0.45% {1 : 2;1} 
  559 OUT: <chess <-> sport>. %0.90;0.45% {1 : 2;1} 
  560 OUT: <(&,chess,sport) --> competition>. %1.00;0.81% {1 : 2;1} 
  561 OUT: <(|,chess,sport) --> competition>. %0.90;0.81% {1 : 2;1} 
  562 OUT: <<sport --> $1> ==> <chess --> $1>>. %0.90;0.45% {1 : 2;1} 
  563 OUT: <<chess --> $1> ==> <sport --> $1>>. %1.00;0.42% {1 : 2;1} 
  564 OUT: <<chess --> $1> <=> <sport --> $1>>. %0.90;0.45% {1 : 2;1} 
  565 OUT: (&&,<chess --> #1>,<sport --> #1>). %0.90;0.81% {1 : 2;1} 
  566").
  567
  568nal_is_test(exec, "
  569********* induction
  570  IN: <swan --> swimmer>. %0.90;0.90% {0 : 1} 
  571  IN: <swan --> bird>. %1.00;0.90% {0 : 2} 
  5721
  573 OUT: <bird --> swimmer>. %0.90;0.45% {1 : 2;1} 
  574 OUT: <swimmer --> bird>. %1.00;0.42% {1 : 2;1} 
  575 OUT: <bird <-> swimmer>. %0.90;0.45% {1 : 2;1} 
  576 OUT: <swan --> (|,bird,swimmer)>. %1.00;0.81% {1 : 2;1} 
  577 OUT: <swan --> (&,bird,swimmer)>. %0.90;0.81% {1 : 2;1} 
  578 OUT: <<$1 --> swimmer> ==> <$1 --> bird>>. %1.00;0.42% {1 : 2;1} 
  579 OUT: <<$1 --> bird> ==> <$1 --> swimmer>>. %0.90;0.45% {1 : 2;1} 
  580 OUT: <<$1 --> bird> <=> <$1 --> swimmer>>. %0.90;0.45% {1 : 2;1} 
  581 OUT: (&&,<#1 --> bird>,<#1 --> swimmer>). %0.90;0.81% {1 : 2;1} 
  582").
  583
  584nal_is_test(exec, "
  585********** exemplification
  586  IN: <robin --> bird>. %1.00;0.90% {0 : 1} 
  587  IN: <bird --> animal>. %1.00;0.90% {0 : 2} 
  5881
  589 OUT: <robin --> animal>. %1.00;0.81% {1 : 2;1} 
  590 OUT: <animal --> robin>. %1.00;0.45% {1 : 2;1} 
  591").
  592
  593nal_is_test(exec, "
  594********** conversion
  595  IN: <bird --> swimmer>. %1.00;0.90% {0 : 1} 
  596  IN: <swimmer --> bird>?  {0 : 2} 
  5972
  598 OUT: <swimmer --> bird>. %1.00;0.47% {2 : 1} 
  599").
  600
  601nal_is_test(exec, "
  602********** y/n question
  603  IN: <bird --> swimmer>. %1.00;0.90% {0 : 1} 
  604  IN: <bird --> swimmer>?  {0 : 2} 
  6051
  606 OUT: <bird --> swimmer>. %1.00;0.90% {0 : 1} 
  607").
  608
  609nal_is_test(exec, "
  610********** wh-question
  611  IN: <bird --> swimmer>. %1.00;0.80% {0 : 1} 
  612  IN: <?1 --> swimmer>?  {0 : 2} 
  6131
  614 OUT: <bird --> swimmer>. %1.00;0.80% {0 : 1} 
  615").
  616
  617nal_is_test(exec, "
  618
  619'the detective claims that tim lives in graz
  620'<{tim} --> (/,livingIn,_,{graz})>.
  621'and lawyer claims that this is not the case
  622<{tim} --> (/,livingIn,_,{graz})>. %0%
  623100
  624'the first deponent, a psychologist,
  625'claims that people with sunglasses are more aggressive
  626<<(*,$1,sunglasses) --> own> ==> <$1 --> [aggressive]>>.
  627'the third deponent claims, that he has seen tom with sunglasses on:
  628<(*,{tom},sunglasses) --> own>.
  629'the teacher claims, that people who are aggressive tend to be murders
  630<<$1 --> [aggressive]> ==> <$1 --> murder>>.
  631'the second deponent claims, that if the person lives in Graz, he is surely the murder
  632<<$1 --> (/,livingIn,_,{graz})> ==> <$1 --> murder>>.
  633'who is the murder?
  634<{?who} --> murder>?
  635''outputMustContain('<{tom} --> murder>. %1.00;0.73%')
  636
  637").
  638
  639nal_is_test(read, "
  640' Custom truth values These are added by appending {0.0 0.9} instead of %0.0;0.9% as we believe this increased the readability.
  641
  642' Example
  643
  644********** wh-question
  645  IN: <bird --> swimmer>. %1.00;0.80% {0 : 1} 
  646  IN: <?1 --> swimmer>?  {0 : 2} 
  6471
  648 OUT: <bird --> swimmer>. %1.00;0.80% {0 : 1} 
  649
  650' can now be
  651
  652
  653********** wh-question
  654  IN: <bird --> swimmer>. {1.0 0.80} {0 : 1} 
  655  IN: <?1 --> swimmer>?  {0 : 2} 
  6561
  657 OUT: <bird --> swimmer>. {1.0 0.80} {0 : 1} 
  658
  659").
  660
  661nal_is_test(read, "
  662'Images
  663
  664(/,rel,_,b) 
  665
  666' has to be written as
  667
  668(rel /1 b), 
  669
  670' and image as
  671
  672(/,rel,a,_) 
  673
  674' as
  675
  676(rel /2 a)
  677
  678' same for \\ with \\1 and \\2.
  679
  680").
  681
  682nal_is_test(read, "
  683'Intervals, to measure expected time distances between events, are always learned by ONA and stored as meta-data, they are not part of the Narsese I/O format anymore. Hence a sequence
  684
  685(&/,a,+5,b)
  686
  687' becomes
  688
  689(&/,a,b)
  690
  691' or
  692
  693(a &/ b)
  694
  695' and also the interval for implications is not used anymore.
  696
  697").
  698
  699nal_is_test(read, "
  700'Operators The syntactic sugar
  701
  702(^op,arg_1,arg_2,arg_3,arg_n)
  703
  704' is not supported anymore, instead the full notation has to be used which is supported by both systems:
  705
  706<(*,arg_1,arg_2,arg_3,arg_n) --> ^op>
  707
  708' though for operations without arguments, the following shortcut can be used:
  709
  710^op
  711
  712").
  713
  714nal_is_test(read, "
  715'Restrictions
  716
  717'1. Copulas in ONA are binary, since it's using an array-based heap for terms. 
  718' While there are ways to encode n-ary relations in a binary heap, the ONA philosophy, following KISS, 
  719' encourages the use of left-nesting, which is also used by the system itself to compose sequences of events:
  720
  721((a &/ b) &/ c).
  722
  723").
  724
  725nal_is_test(read, "
  726'2. The parallel temporal copula &| is not implemented, please use &/ for now, again due to KISS. 
  727' If the order does not matter in some background knowledge we want to give the system, in addition to
  728
  729<(a &/ b) =/> c>
  730
  731' also give it
  732
  733<(b &/ a) =/> c>
  734
  735' to achieve the same as with &| for now.
  736").
  737
  738nal_is_test(read, "
  739'Optional syntactic improvements
  740' The ONA parser does not require commas, and doesn't distinguish between < and (, also it supports infix format.
  741
  742<(|,a,b) --> M>. 
  743
  744' can be written as
  745
  746<(a | b) --> M>. 
  747
  748' or even as
  749
  750((a | b) --> M).
  751
  752' Note: Spaces cannot be omitted.
  753").
  754
  755nal_is_test(read, "
  756'Tim is alive.
  757
  758<{Tim} --> [alive]>.
  759
  760'Tim is a human.
  761
  762<{Tim} --> human>.
  763").
  764
  765nal_is_test(read, "
  766'Humans are a lifeform.
  767
  768<human --> lifeform>.
  769
  770'Lifeforms are like machines.
  771
  772<lifeform <-> machine>.
  773").
  774
  775nal_is_test(read, "
  776'Tom eats chocolate.
  777
  778<(*,{Tom},chocolate) --> eat>.
  779
  780<{Tom} --> (/,eat,_,chocolate)>.
  781
  782<chocolate --> (/,eat,{Tom},_)>.
  783")