在prolog中构建解析器

时间:2016-03-27 21:23:30

标签: prolog dcg

我正在尝试构建一个解析器,但我似乎无法理解它是如何工作的。我需要帮助指向正确方向的人,以便我可以从那里拿起它。

所以我有一个标记器和一个词法分析器。

Tokenizer输出:

[INT,添加,(,INT,一个,,, INT,B,)=中,a,+,B,INT,letin,(,INT,一,),=,让,B,=图10,在,添加,(中,,,, b,),INT,等于,(,INT,一个,,, INT,b,),=,如果,一,==,b,则,letin,(中,a,),否则,1,INT,主,(,INT,输入,),=,等于,(,输入,,, 2,)]

Lexer输出:

[TYPE_INT,IDENTIFIER,OPEN_P,TYPE_INT,IDENTIFIER,COMMA,TYPE_INT,IDENTIFIER,CLOSE_P,ASSIGN IDENTIFIER,ARITH_ADD,IDENTIFIER,TYPE_INT,IDENTIFIER,OPEN_P,TYPE_INT,IDENTIFIER,CLOSE_P,ASSIGN,LET,IDENTIFIER,ASSIGN标识,LET_IN,标识,OPEN_P,标识,逗号,标识,CLOSE_P,TYPE_INT,标识,OPEN_P,TYPE_INT,标识,逗号,TYPE_INT,标识,CLOSE_P,转让,COND_IF,标识,LOGIC_EQ,标识,COND_THEN,标识,OPEN_P, IDENTIFIER,CLOSE_P,COND_ELSE,INTEGER,TYPE_INT,IDENTIFIER,OPEN_P,TYPE_INT,IDENTIFIER,CLOSE_P,ASSIGN IDENTIFIER,OPEN_P,IDENTIFIER,COMMA,INTEGER,CLOSE_P]

现在我必须构建一个解析器。我不知道如何开始以及如何包含参数化构造。

我的规则应该是这样的。

program --> functionList.
functionList --> function,functionListCollection.
functionListCollection --> functionList | [].
function --> typeID(typeIdList),[=],expression.
typeID --> [int],[id] | [bool],[id].
typeIdList --> typeID,typeIdListCollection.
typeIdListCollection --> [,], typeIdList | [].
expression --> [if], comparison, [then], value, [else], value.
expression --> [let],[id],[=], value, [in], expression.
expression --> value, extraExpression.
extraExpression --> arithmetic | [].
arithmetic --> [+], value | [-], value.
comparison --> value, comparisonRight.
comparisonRight --> [=],[=],value.
comparisonRight --> [!], [=], value.
comparisonRight --> [>], value.
comparisonRight --> [>], [=], value.
value --> [number].
value --> [id], valueParameters.
valueParameters --> [(],parameters,[)]. | [].
parameters --> value, parametersList.
parametersList --> [,], parameters | [].

我正在构建一个谓词,它接受lexed列表并从解析器中提供列表。然后,我将通过查看令牌列表来替换数字和标识符。一些关于如何开始的帮助将非常感激。谢谢。

2 个答案:

答案 0 :(得分:2)

您的Lexer输出'似乎不仅没用,而且实际上很危险。它(任意?)重命名已经是解析器一部分的重要符号(如int)(btw,tokenizer和lexer是同义词 afaik)。因此,只需使用tokenizer输出提供DCG(经过更正,见下文):

tokens_test :-
    Tokens = [
        int,add,=,a,+,33
        % ...more source code to test - but please use writeq to show it  ...
        %,int,let,in,'(',int,a,')',=,let,b,=,10
        %,in,add,'(',a,',',b,')',int,equal,'(',int,a,',',int,b,')',=
        %,if,a,==,b,then,let,in,'(',a,')',else,1
        %,int,main,'(',int,input,')',=,equal,'(',input,',',2,')'
    ], phrase(program, Tokens).

?- tokens_test.
true 

我更改了你的DCG,因为你有[id]和[number]作为终端:

id --> [I], {atom(I)}.
number --> [N], {number(N)}.

program --> functionList.
functionList --> function,functionListCollection.
functionListCollection --> functionList | [].
function --> typeID,[=],expression.
typeID --> [int],id | [bool],id.
typeIdList --> typeID,typeIdListCollection.
typeIdListCollection --> [,], typeIdList | [].
expression --> [if], comparison, [then], value, [else], value.
expression --> [let], id, [=], value, [in], expression.
expression --> value, extraExpression.
extraExpression --> arithmetic | [].
arithmetic --> [+], value | [-], value.
comparison --> value, comparisonRight.
comparisonRight --> [=],[=],value.
comparisonRight --> [!], [=], value.
comparisonRight --> [>], value.
comparisonRight --> [>], [=], value.
value --> number.
value --> id, valueParameters.
valueParameters --> ['('],parameters,[')'] | [].
parameters --> value, parametersList.
parametersList --> [,], parameters | [].

如果你有一个分隔符(下面的逗号),你可以避免像

这样的服务谓词
typeIdList --> typeID,typeIdListCollection.
typeIdListCollection --> [,], typeIdList | [].

可能是

typeIdList --> typeID, ( [,], typeIdList | [] ).

但这方便的简化'可能取决于其他因素。

  

如何包含参数化构造

id // 0和number // 0是非终端,应该“返回”#39;它们的价值:它们变为id // 1和数字// 1,而传统上,我们习惯于标记'非终端的值(所以我们备用符号: - )

id(id(I)) --> [I],   % better to filter out keywords here...
  {atom(I), \+memberchk(I,[let, etc etc])}.
number(number(N,integer)) --> [N], {integer(N)}.
number(number(N,float)) --> [N], {float(N)}.

现在他们被调用,我们必须改为

...
typeID --> [int],id(_) | [bool],id(_).
...
很明显,typeID // 0现在应该回来了#39;值(所谓的语义属性),否则它们会丢失:

...
typeID(typeID(T,I)) --> [int],id(I),{T=int} | [bool],id(I),{T=bool}.
...

显示了编写typeID // 1的更好方法。可能是

typeID(typeID(T,I)) --> type(T),id(I).

type(int) --> [int].
type(bool) --> [bool].

希望你能得到图片: - )

答案 1 :(得分:1)

为您输出词法分析器(*),而不是数据

[type(int), id(add), open_p, type(int), id(a), .....

因此您可以在规则中获得完整信息,例如

....
typeID(T,A) --> [type(T)], { memberchk(T, [int,bool]) }, [id(A)],
....

测试:

32 ?- phrase( typeID(X,Y), [type(int), id(i)], []).
X = int,
Y = i.

33 ?- phrase( typeID(X,Y), [type(bool), id(i)], []).
X = bool,
Y = i.

34 ?- phrase( typeID(X,Y), [type(float), id(i)], []).
false.

(*)或者您可以只使用maplist组合您的令牌和当前的词法分析器输出以获取组合数据。