Parsing 如何在Prolog中执行解析器?
我想用prolog做一个解析器。这个应该能够解析如下内容:Parsing 如何在Prolog中执行解析器?,parsing,prolog,dcg,Parsing,Prolog,Dcg,我想用prolog做一个解析器。这个应该能够解析如下内容: PARSE TREE: assignment ident(a) assign_op expression term factor int(1) mult_op term factor int(2) add_o
PARSE TREE:
assignment
ident(a)
assign_op
expression
term
factor
int(1)
mult_op
term
factor
int(2)
add_op
expression
term
factor
left_paren
expression
term
factor
int(3)
sub_op
...
| ?- phrase(parser(T), [a, =, 3, +, '(', 6, *, 11, ')', ;]).
T = assignment(ident(a),=,expression(term(factor(int(3))),+,expression(term(factor(expression(term(factor(int(6)),*,term(factor(int(11)))))))))) ? ;
a=3+(6*11)
现在我只完成了这个语法。它正在工作,但我想改进它,以便有id如(a..z)+和数字如(0..9)+
其次,我想在ParseTree变量中存储一些内容,以便像这样打印ParseTree:
PARSE TREE:
assignment
ident(a)
assign_op
expression
term
factor
int(1)
mult_op
term
factor
int(2)
add_op
expression
term
factor
left_paren
expression
term
factor
int(3)
sub_op
...
| ?- phrase(parser(T), [a, =, 3, +, '(', 6, *, 11, ')', ;]).
T = assignment(ident(a),=,expression(term(factor(int(3))),+,expression(term(factor(expression(term(factor(int(6)),*,term(factor(int(11)))))))))) ? ;
这是我用来打印ParseTree的函数:
output_result(OutputFile,ParseTree):-
open(OutputFile,write,OutputStream),
write(OutputStream,'PARSE TREE:'),
nl(OutputStream),
writeln_term(OutputStream,0,ParseTree),
close(OutputStream).
writeln_term(Stream,Tabs,int(X)):-
write_tabs(Stream,Tabs),
writeln(Stream,int(X)).
writeln_term(Stream,Tabs,ident(X)):-
write_tabs(Stream,Tabs),
writeln(Stream,ident(X)).
writeln_term(Stream,Tabs,Term):-
functor(Term,_Functor,0), !,
write_tabs(Stream,Tabs),
writeln(Stream,Term).
writeln_term(Stream,Tabs1,Term):-
functor(Term,Functor,Arity),
write_tabs(Stream,Tabs1),
writeln(Stream,Functor),
Tabs2 is Tabs1 + 1,
writeln_args(Stream,Tabs2,Term,1,Arity).
writeln_args(Stream,Tabs,Term,N,N):-
arg(N,Term,Arg),
writeln_term(Stream,Tabs,Arg).
writeln_args(Stream,Tabs,Term,N1,M):-
arg(N1,Term,Arg),
writeln_term(Stream,Tabs,Arg),
N2 is N1 + 1,
writeln_args(Stream,Tabs,Term,N2,M).
write_tabs(_,0).
write_tabs(Stream,Num1):-
write(Stream,'\t'),
Num2 is Num1 - 1,
write_tabs(Stream,Num2).
writeln(Stream,Term):-
write(Stream,Term),
nl(Stream).
write_list(_Stream,[]).
write_list(Stream,[Ident = Value|Vars]):-
write(Stream,Ident),
write(Stream,' = '),
format(Stream,'~1f',Value),
nl(Stream),
write_list(Stream,Vars).
我希望有人能帮助我。谢谢大家! id//0的递归规则,使其更加通用:
id --> [First], {char_type(First,lower)}, id ; [].
构建树可以“手工”完成,用适当的术语扩充每个非终端,如
...
assign(assign(Id, Expr)) --> id(Id), [=], expr(Expr), [;].
...
id//0可能成为id//1
id(id([First|Rest])) --> [First], {memberchk(First, [a,b])}, id(Rest) ; [], {Rest=[]}.
如果您要经常编写这样的解析器,重写规则可以很容易地实现…这里是对您编写的解析器的一个增强,它可以帮助您开始编写。这是对@capelical所表示的概念的详细阐述
parser([]) --> [].
parser(Tree) --> assign(Tree).
assign([assignment, ident(X), '=', Exp]) --> id(X), [=], expr(Exp), [;].
id(X) --> [X], { atom(X) }.
expr([expression, Term]) --> term(Term).
expr([expression, Term, Op, Exp]) --> term(Term), add_sub(Op), expr(Exp).
term([term, F]) --> factor(F).
term([term, F, Op, Term]) --> factor(F), mul_div(Op), term(Term).
factor([factor, int(N)]) --> num(N).
factor([factor, Exp]) --> ['('], expr(Exp), [')'].
add_sub(Op) --> [Op], { memberchk(Op, ['+', '-']) }.
mul_div(Op) --> [Op], { memberchk(Op, ['*', '/']) }.
num(N) --> [N], { number(N) }.
这里可能有一些小问题,但我添加到代码中的关键元素是:
- 将
替换为digit
,它接受num
为真的任何序言术语N
number(N)
- 用于
标识有效标识符atom(X)
- 添加了一个参数以保存解析给定表达式项的结果
| ?- phrase(parser(Tree), [a, =, 3, +, '(', 6, *, 11, ')', ;]).
Tree = [assignment,ident(a),=,[expression,[term,[factor,int(3)]],+,[expression,[term,[factor,[expression,[term,[factor,int(6)],*,[term,[factor,int(11)]]]]]]]]] ? ;
这可能不是解析树的理想表示形式。它可能需要根据您的需要进行一些调整,您可以通过修改我展示的内容来实现。然后,您可以编写一个谓词,根据需要格式化解析树
您也可以考虑,而不是列表结构,嵌入Prolog的术语结构如下:
parser([]) --> [].
parser(Tree) --> assign(Tree).
assign(assignment(ident(X), '=', Exp)) --> id(X), [=], expr(Exp), [;].
id(X) --> [X], { atom(X) }.
expr(expression(Term)) --> term(Term).
expr(expression(Term, Op, Exp)) --> term(Term), add_sub(Op), expr(Exp).
term(term(F)) --> factor(F).
term(term(F, Op, Term)) --> factor(F), mul_div(Op), term(Term).
factor(factor(int(N))) --> num(N).
factor(factor(Exp)) --> ['('], expr(Exp), [')'].
add_sub(Op) --> [Op], { memberchk(Op, ['+', '-']) }.
mul_div(Op) --> [Op], { memberchk(Op, ['*', '/']) }.
num(N) --> [N], { number(N) }.
其结果如下:
PARSE TREE:
assignment
ident(a)
assign_op
expression
term
factor
int(1)
mult_op
term
factor
int(2)
add_op
expression
term
factor
left_paren
expression
term
factor
int(3)
sub_op
...
| ?- phrase(parser(T), [a, =, 3, +, '(', 6, *, 11, ')', ;]).
T = assignment(ident(a),=,expression(term(factor(int(3))),+,expression(term(factor(expression(term(factor(int(6)),*,term(factor(int(11)))))))))) ? ;
如何使用id-->[X],{atom(X)}。
和digit-->[N],{integer(N)}。
来处理更通用的标识符和数字?