如何在Prolog中进行解析器? [英] How to do a parser in Prolog?

查看:94
本文介绍了如何在Prolog中进行解析器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在序言中做一个解析器.这应该可以解析如下内容:

I would like to do a parser in prolog. This one should be able to parse something like this:

a = 3 +(6 * 11);

a = 3 + (6 * 11);

目前,我仅完成了此语法.它正在运行,但我想对其进行改进,以使 id (例如(a..z)+)和数字(例如(0..9)+.)

For now I only have this grammar done. It's working but I would like to improve it in order to have id such as (a..z)+ and digit such as (0..9)+.

parse(-ParseTree, +Program, []):-
    parsor(+Program, []).

parsor --> [].
parsor --> assign.
assign --> id, [=], expr, [;].
id --> [a] | [b].
expr --> term, (add_sub, expr ; []).
term --> factor, (mul_div, term ; []).
factor --> digit | (['('], expr, [')'] ; []).
add_sub --> [+] | [-].
mul_div --> [*] | [/].
digit --> [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9].

第二,我想在ParseTree变量中存储一些内容,以便像这样打印ParseTree:

Secondly, I would like to store something in the ParseTree variable in order to print the ParseTree like this:

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

这是我要用来打印ParseTree的函数:

And this is the function I'm going use to print the 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).

我希望有人能够帮助我.谢谢!

I hope someone will be able to help me. Thank you !

推荐答案

以下是对您的解析器的增强,可以使您入门.这是@CapelliC表示的概念的详细说明.

Here's an enhancement of your parser as written which can get you started. It's an elaboration of the notions that @CapelliC indicated.

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) }.

我可能在这里有几个小问题,但是我添加到您的代码中的关键元素是:

I might have a couple of niggles in here, but the key elements I've added to your code are:

  • digit替换为num,该digit接受number(N)为真的任何Prolog术语N
  • 使用atom(X)标识有效的标识符
  • 添加了一个参数来保存解析给定表达式项的结果
  • Replaced digit with num which accepts any Prolog term N for which number(N) is true
  • Used atom(X) to identify a valid identifier
  • Added an argument to hold the result of parsing the given expression item

例如:

| ?- 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)]]]]]]]]] ? ;

这可能不是解析树的理想表示.它可能需要根据您的需求进行一些调整,您可以通过修改我所展示的内容来进行调整.然后,您可以编写一个谓词,以根据需要设置语法分析树的格式.

This may not be an ideal representation of the parse tree. It may need some adjustment per your needs, which you can do by modifying what I've shown a little. And then you can write a predicate which formats the parse tree as you like.

您还可以考虑使用嵌入式Prolog术语结构,而不是列表结构,如下所示:

You could also consider, instead of a list structure, an embedded Prolog term structure as follows:

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) }.

结果如下:

| ?- 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)))))))))) ? ;

这篇关于如何在Prolog中进行解析器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆