到目前为止,我必须解析一个宽泛的语法(为了创建一个语法分析器),问题是我在代码中的某处有冗余,但我不知道它在哪里。
语法的一部分;
Grammar_types
Type :: = Basic_Type
| "PP" "(" Type ")"
| Type "*" Type
| "struct" "(" (Ident ":" Type)+"," ")"
| "(" Type ")" .
Basic_Type :: = "ZZ"| "BOOL" | "STRING" | Ident .
我尝试在没有DCG的情况下分析这个gramar,例如解析Id :: = Id ((Id) * ",") *
Example_1
"id","id_0(id1,id2,..)"
Code_1
Entete_ (ID, Id, Ids) - atom_concat(XY,')', ID),
atom_concat(XX,Ids, XY),check_ids(Ids),
atom_concat(Id,'(',XX),check_id(Id) ,!.
...
但在某些搜索过程中,我发现DCG是最有效的解析器之一,所以我回过头来获取下面的代码;
CODE_2
type(Type) --> "struct(", idents_types(Type),")"
| "PP(",ident(Type),")"
| "(",type(Type),")"
| type(Type),"*",type(Type)
| basic_type(Type)
| "error1_type".
...
Example_Syntaxe;
"ZZ" ; "PP(ZZ*STRING)" ; "struct(x:personne,struct(y:PP(PP))" ; "ZZ*ZZ" ...
测试
| ?- phrase(type(L),"struct(aa:struct())").
! Resource error: insufficient memory
% source_info
我认为这里的问题(idents_types)
| ?- phrase(idents_types(L),"struct(aa:STRING)").
! Resource error: insufficient memory
预期结果
| ?- type('ZZ*struct(p1:STRING,p2:PP(STRING),p3:(BOOL*PP(STRING)),p4:PP(personne*BOOL))').
p1-STRING
STRING
p2-PP(STRING)
STRING
p3-(BOOL*PP(STRING))
STRING
BOOL
p4-PP(personne*BOOL)
BOOL
personne
ZZ
yes
所以我的问题是,为什么我会收到此冗余错误,我该如何解决?
答案 0 :(得分:2)
您在类型// 1上有left recursion。
type(Type) --> ... | type(Type),"*",type(Type) | ...
您可以查看this question以获取更多信息。
DCG借用的自上而下的解析器必须具有预测的平均值一个符号,以便在正确的方向上驱动分析。
正如上面的链接所示,这个问题的通常解决方案是引入一个服务非终结符,它离开了罪犯规则的关联递归应用程序,或者是epsilon(终止递归)。
epsilon规则类似于
rule --> [].
转换可能需要相当多的思考......在this answer我建议采用自下而上的替代实现,如果语法无法转换,那么对于实际或理论问题(LR语法更多)可能是值得的一般而不是LL)。
您可能想要尝试这种简单的转换,但肯定会留下一些细节需要解决。
type([Type,T]) --> "struct(", idents_types(Type),")", type_1(T)
| "PP(",ident(Type),")", type_1(T)
| "(",type(Type),")", type_1(T)
| basic_type(Type), type_1(T)
| "error1_type", type_1(T).
type_1([Type1,Type2,T]) --> type(Type1),"*",type(Type2), type_1(T).
type_1([]) --> [].
修改的
我修复了你和我的代码中的几个问题。现在它解析了这个例子......
type([Type,T]) --> "struct(", idents_types(Type), ")", type_1(T)
| "PP(", type(Type), ")", type_1(T)
| "(", type(Type), ")", type_1(T)
| basic_type(Type), type_1(T)
| "error1_type", type_1(T).
% my mistake here...
type_1([]) --> [].
type_1([Type,T]) --> "*",type(Type), type_1(T).
% the output Type was unbound on ZZ,etc
basic_type('ZZ') --> "ZZ".
basic_type('BOOL') --> "BOOL".
basic_type('STRING') --> "STRING".
basic_type(Type) --> ident(Type).
% here would be better to factorize ident(Ident),":",type(Type)
idents_types([Ident,Type|Ids]) --> ident(Ident),":",type(Type),",",
idents_types(Ids).
idents_types([Ident,Type]) --> ident(Ident),":",type(Type).
idents_types([]) --> [].
% ident//1 forgot to 'eat' a character
ident(Id) --> [C], { between(0'a,0'z,C),C\=0'_},ident_1(Cs),{ atom_codes(Id,[C|Cs]),last(Cs,L),L\=0'_}.
ident_1([C|Cs]) --> [C], { between(0'a,0'z,C);between(0'0,0'9,C);C=0'_ },
ident_1(Cs).
ident_1([]) --> [].