使用Prolog进行前缀解析

时间:2011-11-02 12:21:00

标签: parsing prolog

所以我有这个语法:

  expr(op(T,B,E)) => [term(T), binop(B), expr(E)].
  expr(T) => [term(T)].

  term(N) => [num(N)].
  term(L) => [lvalue(L)].
  term(pre(O,L)) => [incrop(O), lvalue(L)].
  term(post(L,O)) => [lvalue(L), incrop(O)].
  term(E) => ['(', expr(E), ')'].

  lvalue($(E)) => [$, expr(E)].

  incrop(++) => [++].
  incrop(--) => [--].

  binop(+) => [+].
  binop(-) => [-].

  num(0) => [0].
  num(1) => [1].
  num(2) => [2].
  num(3) => [3].
  num(4) => [4].
  num(5) => [5].
  num(6) => [6].
  num(7) => [7].
  num(8) => [8].
  num(9) => [9].

目标是根据规则解析输入,并分离剩余的后缀。例如,

| ?- parse_prefix(expr(E), [$,1,+,2], S).

E = op($(1),+,2)
S = [] ? ;

E = $(op(1,+,2))
S = [] ? ;

E = $(1)
S = [+,2] ? ;

no

| ?- parse_prefix(expr(E), [9], S).

E = 9
S = [] ? ;

no


| ?- parse_prefix(expr(E), [9,+,$,1,+], S).

E = op(9,+,$(1))
S = [+] ? ;

E = 9
S = [+,$,1,+] ? ;

我写了以下谓词:

%Base Case: No Token, No Suffix
parse_prefix(_,[],[]).

%Direct Matching: ex) parse_prefix(num(9),[9],S)
parse_prefix(NT,[Head|Tail],S):-
    NT =>[Head],
    write('two '),
    parse_prefix(expr(E),Tail,S).
%General Matching: ex) parse_prefix(expr(E),_,S)
parse_prefix(NT,[Head|Tail],S):-
    NT => [Head1|Tail1],
    %write(Head1),
    %write('one\n'),
    parse_prefix(Head1,[Head|Tail],S).

我对递归和回溯感到很困惑..

我会永远爱任何可以帮助我的人。

提前谢谢。

1 个答案:

答案 0 :(得分:2)

您已接近解决方案。最好定义你自己的operator => / 2来表示你自己的gammar规则,而不是与 - > / 2发生冲突。但我在语法规则体的表示方面遇到了问题。我没有看到你在语法规则体中区分终端和非终端。

一个建议是投票给(A1,......,An)代表身体中的一个连词,而不是[A1,..,An]。然后将[T]用于终端,将NT用于非终端。所以遵循以下规则,

term(E) => ['(', expr(E), ')'].

然后会读到:

term(E) => ['('], expr(E), [')'].

然后,您可以调整规则并定义parse_prefix / 3,如下所示。我告诉你终端和连接以及非终端案例:

parse_prefix([T],I,O) :- !, I=[T|O].
parse_prefix((A,B),I,O) :- !, parse_prefix(A,I,H), parse_prefix(B,H,O).
parse_prefix(NT,I,O) :- (NT => Body), parse_prefix(Body,I,O).

您可以为空生产([])和辅助条件({})添加其他案例,或者使其更灵活,以便能够使用终端列表([T1,..,Tn])。还有进一步的控制结构是可能的,但是当你尝试进行切换(!)时,在遵循元解释器方法时,事情会变得有些讨厌。

除了编写元解释器parse_prefix / 3之外,您还可以烹饪自己的术语重写,最终得到一种方法,将给定的gammar规则首先转换为普通的Prolog,然后从那里执行它们。你在这里找到一个简单的食谱:

http://www.jekejeke.ch/idatab/doclet/blog/en/docs/int/jan/098_2011/097_dcg_expansion/package.html

再见