プロローグ解析

最初の部分( habrahabr.ru/post/274603 )の公開は、PROLOGUEの適用言語のさまざまな側面についてかなり広範で興味深い議論を引き起こしました。

目標は、Prologに複雑なものは何もないことをプログラマーに示すことであり、そうではないことを示し、誰でもそれを仕事で使用できることです。

何らかの理由で、出版物の本文に直接質問はありませんでした。 私はすべてがそこに明確であると思います。

Prolog言語でのプログラミングのより実用的な側面を検討し始めます。

このセクションでは、算術式の例での文脈自由言語のPROLOGUE言語翻訳の実装の主な側面を検討します。

ご存知のように、PROLOGは属性の文法から生まれました。 したがって、解析はこの言語の最初の自然なアプリケーションです。

正規表現などのツールとは異なり、より複雑でコンテキストのない言語の翻訳者をPROLOGで簡単に書くことができます。

翻訳者には、字句解析器、パーサー、およびオブジェクトコードジェネレーターが必要です。



1.字句解析



字句解析器には、入力に文字列があり、出力に字句単位のリストがあります。 算術式の字句解析を検討してください。

元のlexr / 2述語は、文字列を文字コードのリストに変換し、スペース(delb / 2)を削除してから、lexr1 / 2に進み、入力リストを再帰的にスキャンし、そこから字句単位を抽出します-サービス文字と整数-数字のシーケンス。

述語lexr1 / 2は、文字の入力リストが使い果たされると終了します。

文字の入力リストからのTerm / 4述語は、次の字句単位Hsを選択します。これは、呼び出し述語の出力リストの先頭に書き込まれます。 4番目の引数は残りのリストで、再帰の次のステップで処理されます。 2番目の引数は、整数の数字のリストを蓄積するサービス引数です。 最初は、[]に設定します。

用語/ 4述語は、入力リストを表示するときに発生する可能性のある4つの状況に対する4つの手順で構成されています。

リストの先頭にサービス文字がある場合、それを文字列に変換した後、出力リストに入れます。 これは、作業変数に空のリストが含まれている場合に提供されます。

リストの次の要素がサービスシンボルであるが、作業変数に値がある場合、2番目の引数の数字の累積リストを文字列に変換し、出力リストに入れます。 この場合、次の再帰的ステップで再検討するために、サービスシンボルが出力リストに入力されます。

次の文字が数字の場合、2番目の引数の最後に入力されます。サービスリストと再帰が続行されます。

4番目の手順は、数字の次の数字を検索するときに入力リストが使い果たされるときに含まれます。 リストの枯渇は、整数の表示の完了を意味します。

サービス述語spec / 1、digit / 1は、文字コードがサービス文字または数字に準拠しているかどうかを確認します。

メンバー/ 2述語は、アイテムがリストにあるかどうかをチェックします。

append / 3述語は、2つのリストを結合します。

lexr(S,R):- list_text(L,S), delb(L,L1),lexr1(L1,R),!.

lexr1(L,[Hs|T1]):-
        term(L,[],Hs,L1),
        lexr1(L1,T1).
lexr1([],[]).

term([H|T],[],Hs,T):- spec(H),list_text([H],Hs).
term([H|T],L,I,[H|T]):- 
       L\=[],        
        spec(H),
        list_text(L,Ls),
        int_text(I,Ls).
term([H|T],L,R,Lr):- 
       digit(H),        
        append(L,[H],L1),
        term(T,L1,R,Lr).
term([],L,I,[]):-
        L\=[],
        list_text(L,Ls),
        int_text(I,Ls).

delb([32|T],L):-delb(T,L).
delb([H|T],[H|T1]):-delb(T,T1).
delb([],[]).

spec(H):-member(H,"+-*/()").
digit(H):- H>47, H<58.
append([H|T],L,[H|L2]):-append(T,L,L2).
append([],L,L).
member(H,[H|T]).
member(H,[H1|T]):-H\=H1,member(H,T).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   
lr:-
        A = $(10-237*65+3/837467)-(342-678)$,
        lexr(A,L),
        write(A),nl,
        write(L),nl.

      
      





, lexr/2 — , .

, .

, , lexr/2 -"!", .



2.DCG –



DCG – Definite Clause Grammar , .

, DCG – .

, , , , , .



.

Ex = :: Sterm | Sterm AdSign Ex

Sterm = :: AdSign Term | Term

Term =:: Factor | Factor MuSign Term1

Term1 = :: Term | Term MuSign Term1

Factor =:: ( Ex) | Number

AdSign =:: ‘+’ | ‘-‘

MuSign =:: ‘*’ | ‘/’



DCG.

ex -->  sterm. 
ex -->  sterm, adsign,ex.
sterm --> adsign, term.
sterm --> term.
term --> factor.
term --> factor,musign,term1.
term1 --> term.
term1 --> term, musign, term1.
factor --> [N],{number(N)}.
factor --> lb,ex,rb.
adsign --> ['+']. adsign --> ['-'].
musign --> ['*']. musign --> ['/'].
lb --> ['(']. rb --> [')'].

      
      







.

e:-

A=[12,’-‘,98,’*’,’(‘,19,’+’,34,’*’,’(‘,200,’-‘,23,’)’,’)’, ],

ex(A,[]).



, :



es:-

read_line(0,S),

lexr(S,L),

ex(L,[]).



, . expand_term/2, , DCG – .



expand_term((a--> b,c,d),L).

:

L = a(A,B):-b(A,C),c(C,D),d(D,B)







expand_term((a--> [‘+’]),L).



:

L= a([‘+’|T],T)



, – , . , , «» .

, , , , .

, DCG – , – .

, «» DCG – , . DCG , .

, , «Yes» «No».

– . .



3.



, . , , .

ex(R) -->  sterm(R). 
ex([S,R1,R2]) -->  sterm(R1), adsign(S),ex(R2).
sterm([S,R,[]]) --> adsign(S), term(R).
sterm(R) --> term(R).
term(R) --> factor(R).
term([S,R1,R2]) --> factor(R1),musign(S),term1(R2).
term1(R) --> term(R).
term1([S,R1,R2]) --> term(R1), musign(S), term1(R2).
factor(N) --> [N],{number(N)}.
factor(R) --> lb,ex(R),rb.
adsign('+') --> ['+']. adsign('-') --> ['-'].
musign('*') --> ['*']. musign('/') --> ['/'].
lb --> ['(']. rb --> [')'].

      
      







e3:-
        S='10-3-5+4',
        lexr(S,L),
        ex(R,L,[]),
        calc(R,Res),
        write(S),nl,
        write(R),nl,
        write(Res),nl.

      
      





:



[-,10,[-,3,[+,5,4]]]



calc/2 .

calc([S,A1,A2],Nr):-calc(A1,N1),calc(A2,N2),calc1(S,N1,N2,Nr),!.
calc(A1,A1):-A1\=[_|_].
calc1(*,N1,N2,Nr):- Nr is N1*N2.
calc1(/,N1,N2,Nr):- Nr is N1/N2.
calc1(+,N1,N2,Nr):- Nr is N1+N2.
calc1(-,N1,N2,Nr):- Nr is N1-N2.

      
      





– «16». , «6»! – – . , .

, , .



ex([S,R1,R2]) --> sterm(R1), adsign(S),ex1(R2).







ex([S,R1,R2]) --> ex(R1), adsign(S),term(R2).



. ? – «» , – !

ex(E)-->eterm(E).
ex([S,E1,E2])-->sterm(E1),sn(S),eterm(E2).

sterm(E)-->eterm(E).
sterm([S,E1,E2])-->eterm(E1),sn(S),eterm(E2).
sterm([S2,[S1,E1,E2],E3])--> eterm(E1),sn(S1),sterm(E2),sn(S2),eterm(E3).

eterm(E)-->fct(E).
eterm([S2,[S1,E1,E2],E3])--> fct(E1),sn2(S1),eterm(E2),sn2(S2),fct(E3).
eterm([S,E1,E2])-->fct(E1),sn2(S),fct(E2).
sn2(*)-->[*]. sn2(/)-->[/]. sn2(div)-->[div]. sn2(mod)-->[mod]. sn2(and)-->[and]. 
fct(E)-->number(E).
fct(E)-->lb,ex(E),rb.
fct(E)-->snot,fct(E).
number(X)-->[X],{number(X)}.
lb-->['('].
rb-->[')'].
sg(+)-->[+].
sg(-)-->[-].
sn(E)-->sg(E).

      
      









[+,[-,[-,10,3],5],4]



«6».



4.



, calc/2.

, , , .

ex(E)-->eterm(E).
ex(R)-->sterm(E1),sn(S),eterm(E2),{clc([S,E1,E2],R)}.

sterm(E)-->eterm(E).
sterm(R)-->eterm(E1),sn(S),eterm(E2),{clc([S,E1,E2],R)}.
sterm(R)-->eterm(E1),sn(S1),sterm(E2),sn(S2),eterm(E3),{clc([S1,E1,E2],N),
        clc([S2,N,E3],R)}.

eterm(E)-->fct(E).
eterm(R)-->fct(E1),sn2(S1),eterm(E2),sn2(S2),fct(E3),{clc([S1,E1,E2],N),
        clc([S2,N,E3],R)}.
eterm(R)-->fct(E1),sn2(S),fct(E2),{clc([S,E1,E2],R)}.
sn2(*)-->[*]. sn2(/)-->[/]. sn2(div)-->[div]. sn2(mod)-->[mod]. sn2(and)-->[and]. 
fct(E)-->number(E).
fct(E)-->lb,ex(E),rb.
number(X)-->[X],{number(X)}.
lb-->['('].
rb-->[')'].
sg(+)-->[+].
sg(-)-->[-].
sn(E)-->sg(E).
clc(A1,A1):-A1\=[_|_].
clc([*,N1,N2],Nr):- Nr is N1*N2.
clc([/,N1,N2],Nr):- Nr is N1/N2.
clc([+,N1,N2],Nr):- Nr is N1+N2.
clc([-,N1,N2],Nr):- Nr is N1-N2.   

      
      





. «» , .. .

- , , HTML, XML.



— .



All Articles