在prolog中构建解析器

在prolog中构建解析器,prolog,dcg,Prolog,Dcg,我正在尝试构建一个解析器,但我似乎无法理解它是如何工作的。我需要有人帮我指出正确的方向,这样我就可以从那里捡起来 所以我有一个标记器和一个lexer 标记器输出: [int,add,(,int,a,,,int,b,),=,a,+,b,int,letin,(,int,a,),=,let,b,=,10,in,add,(,a,,,b,,),int,equal,(,int,a,,,int,b,),=,if,a,=,b,then,letin,(,a,),else,1,int,main,(,int,inpu

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

所以我有一个标记器和一个lexer

标记器输出:

[int,add,(,int,a,,,int,b,),=,a,+,b,int,letin,(,int,a,),=,let,b,=,10,in,add,(,a,,,b,,),int,equal,(,int,a,,,int,b,),=,if,a,=,b,then,letin,(,a,),else,1,int,main,(,int,input,,,,,,,,,,,,,,,,,,,,,,equal

Lexer输出:

[TYPE_-INT、IDENTIFIER、OPEN_-P、TYPE_-INT、IDENTIFIER、IDENTIFIER、CLOSE_-P、ASSIGN、IDENTIFIER、ARITH_-ADD、IDENTIFIER、TYPE_-INT、IDENTIFIER、CLOSE_-P、ASSIGN、LET、IDENTIFIER、OPEN_-P、IDENTIFIER、逗号、IDENTIFIER、CLOSE_-P、TYPE_-INT、IDENTIFIER、OPEN_-P、TYPE_-INT、IDENTIFIER、逗号、TYPE_-INT、IDENTIFIER,CLOSE\u P,ASSIGN,COND\u IF,IDENTIFIER,LOGIC\u EQ,IDENTIFIER,COND\u THEN,IDENTIFIER,OPEN\u P,COND\u ELSE,INTEGER,TYPE\u INT,IDENTIFIER,OPEN\u P,TYPE\u INT,IDENTIFIER,CLOSE\u P,ASSIGN,IDENTIFIER,OPEN\u P,IDENTIFIER,IDENTIFIER,IDENTIFIER,逗号,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 | [].
我正在寻找一个构建一个谓词,它获取词法列表并从解析器中给出列表。然后,我将通过查看标记列表来替换数字和标识符。非常感谢您提供一些关于如何开始的帮助。谢谢。

将您的词法器(*)作为数据输出

[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.

(*)或者你可以将你的标记和你当前的lexer输出组合起来得到组合数据,使用
maplist

你的“lexer输出”看起来不仅没用,而且实际上很危险。它(任意地)重命名已经是解析器一部分的重要符号(如
int
)(顺便说一句,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是应该“返回”其值的非端子:它们成为id//1和number//1,并且按照惯例,我们使用非端子“标记”该值(因此我们保留符号:-)

现在,他们被称为,我们必须改变到

...
typeID --> [int],id(_) | [bool],id(_).
...
很明显,typeID//0现在应该“获取”值(所谓的语义属性),否则它们将丢失:

...
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].
希望你能理解:-)

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

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