我正在尝试构建一个解析器,但我似乎无法理解它是如何工作的。我需要帮助指向正确方向的人,以便我可以从那里拿起它。
所以我有一个标记器和一个词法分析器。
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列表并从解析器中提供列表。然后,我将通过查看令牌列表来替换数字和标识符。一些关于如何开始的帮助将非常感激。谢谢。
答案 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
组合您的令牌和当前的词法分析器输出以获取组合数据。