/* 
maxrec: 2
max_depth: 4
maxnondeterm: 10
maxpropleft: 3
maxlevel: 0
maxfinite: 7
quickpe: 0
tracing: unset
delayoutput: unset
handle_freeze: set
cyclic: set
comments: set
tracegoalstack: unset
arithopt: set
fold_instance: set
preserve_loops: unset
unfold_cut: set
unfold_cut2: unset
print_settings: set
if2cut: unset
rename_VAR: unset
indexargs: set
*/
parse(o(A,B,C)) :-
        parseo1(A, B, C).

% parseo1(A,B,C):-parse(o(A,B,C))
parseo1(O, Q, _) :-
        length(Q, P),
        C is P+1,
        assertz(table_item:max(C)),
        result_cat(O, D),
        result_tree(O, E),
        count_edges:reset_program_space,
        parse1(D, C, M),
        (   M=gap(N),
            C=1,
            E=tree(N,_,[]),
            lc_in:gap_i(N, D)
        ;   M='$ref'(A,B),
            (   table_item:reconstructed(A, B) ->
                true
            ;   table_item:assertz(table_item:reconstructed(A,B)),
                (   table_item:'MEMO_HIS'(A, B, L, G),
                    L=lex(K,1,I),
                    lists:member(J, K),
                    lex_in:total_lex(J, H, _, _),
                    left_corner_2nd1(G, H, I, C, J, E, F),
                    table_item:assertz(table_item:reconstructed(A,B,1,C,F,E)),
                    fail
                ;   true
                )
            ),
            table_item:reconstructed(A, B, 1, C, D, E)
        ).

% parse1(A,B,C):-parse(A,1,B,C)
parse1(A, 1, gap(B)) :-
        lc_in:gap(A, B).
parse1(_, _, _) :-
        table_item:max(1), !,
        fail.
parse1(F, D, A) :-
        functor(F, T, S),
        functor(E, T, S),
        E=..[Q|R],
        G=..[Q,1,S],
        B=..[Q,1,C|R],
        (   table_goal:call(table_goal:G) ->
            true
        ;   lc_in:left_corner_table_lex(E, P),
            lex:lex(1, L, P, K),
            left_corner1(P, E, L, C, J),
            (   copy_term(B, O),
                table_item:clause(O, _, M),
                table_item:clause(N, _, M),
                terms:subsumes_chk(N, B) ->
                true
            ;   table_item:assertz(B, M)
            ),
            M='$ref'(H,I),
            (   table_item:'MEMO_HIS'(H, I, lex(K,1,L), J) ->
                true
            ;   table_item:assertz('MEMO_HIS'(H,I,lex(K,1,L),J))
            ),
            fail
        ;   assertz(table_goal:G)
        ),
        E=F,
        C=D,
        table_item:clause(table_item:B, _, A).

% left_corner1(A,B,C,D,E):-left_corner(A,B,C,D,E)
left_corner1(A, A, B, B, []).
left_corner1(I, B, G, D, [rule(J,H)|E]) :-
        lc_in:lc_rule(I, A, F, J),
        lc_in:left_corner_table(B, A),
        parse_right_ds1(F, G, C, H),
        left_corner1(A, B, C, D, E).

% parse_right_ds1(A,B,C,D):-parse_right_ds(A,B,C,D)
parse_right_ds1([], A, A, []).
parse_right_ds1([E|A], B, C, [gap(F)|D]) :-
        lc_in:gap(E, F),
        parse_right_ds1(A, B, C, D).
parse_right_ds1([_|_], A, _, [_|_]) :-
        table_item:max(A), !,
        fail.
parse_right_ds1([G|A], N, C, [E|D]) :-
        functor(G, W, V),
        functor(H, W, V),
        H=..[T|U],
        I=..[T,N,V],
        F=..[T,N,B|U],
        (   table_goal:call(table_goal:I) ->
            true
        ;   lc_in:left_corner_table_lex(H, S),
            lex:lex(N, O, S, M),
            left_corner1(S, H, O, B, L),
            (   copy_term(F, R),
                table_item:clause(R, _, P),
                table_item:clause(Q, _, P),
                terms:subsumes_chk(Q, F) ->
                true
            ;   table_item:assertz(F, P)
            ),
            P='$ref'(J,K),
            (   table_item:'MEMO_HIS'(J, K, lex(M,N,O), L) ->
                true
            ;   table_item:assertz('MEMO_HIS'(J,K,lex(M,N,O),L))
            ),
            fail
        ;   assertz(table_goal:I)
        ),
        G=H,
        table_item:clause(table_item:F, _, E),
        parse_right_ds1(A, B, C, D).

% left_corner_2nd1(A,B,C,D,E,F,G):-left_corner_2nd(A,B,G,C,D,tree(E,H,[]),F)
left_corner_2nd1([], A, B, B, C, tree(C,_,[]), A).
left_corner_2nd1([rule(F,J)|A], M, L, E, G, I, C) :-
        lc_in:lc_rule_i(F, M, B, K),
        parse_rds_2nd1(J, K, L, D, H),
        left_corner_2nd1(A, B, C, D, E, F, _, G, _, [], H, I).

% parse_rds_2nd1(A,B,C,D,E):-parse_rds_2nd(A,B,C,D,E)
parse_rds_2nd1([], [], A, A, []).
parse_rds_2nd1([gap(F)|A], [G|B], C, D, [tree(F,_,[])|E]) :-
        lc_in:gap_i(F, G),
        parse_rds_2nd1(A, B, C, D, E).
parse_rds_2nd1(['$ref'(F,G)|A], [I|B], H, D, [J|E]) :-
        (   table_item:reconstructed(F, G) ->
            true
        ;   table_item:assertz(table_item:reconstructed(F,G)),
            (   table_item:'MEMO_HIS'(F, G, Q, L),
                Q=lex(P,H,N),
                lists:member(O, P),
                lex_in:total_lex(O, M, _, _),
                left_corner_2nd1(L, M, N, C, O, J, K),
                table_item:assertz(table_item:reconstructed(F,G,H,C,K,J)),
                fail
            ;   true
            )
        ),
        table_item:reconstructed(F, G, H, C, I, J),
        parse_rds_2nd1(A, B, C, D, E).

% left_corner_2nd1(A,B,C,D,E,F,G,H,I,[],J,K):-left_corner_2nd(A,B,C,D,E,tree(F,G,[tree(H,I,[])|J]),K)
left_corner_2nd1([], A, A, B, B, C, D, E, F, G, H, tree(C,D,[tree(E,F,G)|H])).
left_corner_2nd1([rule(F,O)|A], R, C, Q, E, G, H, L, M, N, K, J) :-
        lc_in:lc_rule_i(F, R, B, P),
        parse_rds_2nd1(O, P, Q, D, I),
        left_corner_2nd1(A, B, C, D, E, F, _, G, H, [tree(L,M,N)|K], I, J).
dump_grammar :-
        dump_grammar1.

% dump_grammar1:-dump_grammar
dump_grammar1 :-
        lc_compile:dump_grammar.
count :-
        count1.

% count1:-count
count1 :-
        (   flags:flag(debug, 1) ->
            count_edges:report_program_space,
            count_edges:count_edges((table_goal:current_predicate(_,H),table_goal:H), G),
            format(user_error, [126,119,32,103,111,97,108,115,126,110], [G]),
            count_edges:count_edges((table_item:current_predicate(_,D),functor(D,E,F),E/F\=='MEMO_HIS'/4,E/F\==reconstructed/2,E/F\==reconstructed/6,table_item:D), C),
            format(user_error, [126,119,32,105,116,101,109,115,126,110], [C]),
            count_edges:report_count_edges(table_item:'MEMO_HIS'(_,_,_,_)),
            count_edges:report_count_edges(table_item:reconstructed(_,_)),
            count_edges:report_count_edges(table_item:reconstructed(_,_,_,_,_,_))
        ;   flags:flag(debug, 2) ->
            count_edges:report_program_space,
            (   format(user_error, [103,111,97,108,115,58,32,126,110], []),
                table_goal:current_predicate(_, table_goal:B),
                count_edges:report_count_edges(table_goal:B),
                fail
            ;   format(user_error, [126,110,105,116,101,109,115,58,32,126,110], []),
                table_item:current_predicate(_, table_item:A),
                count_edges:report_count_edges(table_item:A),
                fail
            ;   true
            )
        ;   true
        ).
count(A) :-
        count1(A).

% count1(A):-count(A)
count1(A) :-
        count_edges:program_space(A).
clean :-
        clean1.

% clean1:-clean
clean1 :-
        table_goal:current_predicate(_, table_goal:C),
        functor(C, A, B),
        table_goal:abolish(table_goal:A/B),
        fail.
clean1 :-
        table_item:current_predicate(_, table_item:C),
        functor(C, A, B),
        table_item:abolish(table_item:A/B),
        fail.
clean1.
compile_grammar(A) :-
        compile_grammar1(A).

% compile_grammar1(A):-compile_grammar(A)
compile_grammar1(_) :-
        lc_compile:compile_grammar.
