我正在序言中编写一个解析器,该解析器应该能够解析此数学公式:
a = 1 * 2 + (3 - 4) / 5;
并从中打印出一个解析树,该解析树应如下所示:
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
expression
term
factor
int(4)
right_paren
div_op
term
factor
int(5)
semicolon
我有此功能,当我运行代码run('program1.txt', 'myparsetree1.txt')
时,将打印出解析树。它将从program1.txt
文件中读取数学公式,并在myparsetree1.txt
文件上打印出分析树。
到目前为止,我已经尝试为解析器编写此语法,但是由于我不断遇到letter_code
和来自tokenizer
的digit_code而不断出现存在和实例化错误,而prolog
却无法正常工作抱怨其中的论点太少。
/*Loads the tokenizer*/
:- [tokenizer].
parse(I) --> assign(I).
assign(assign(I,'=', Expr,';')) -->
letter_code(I), '=', expr(Expr), ';'.
expr(expr(Term, add_op, Expr)) -->
term(Term), add_op, expr(Expr).
expr(expr(Term, sub_op, Expr)) -->
term(Term), sub_op, expr(Expr).
expr(expr(Term)) --> term(Term).
term(term(Factor, mul_op, Term)) -->
factor(Factor), mul_op, term(Term).
term(term(Factor, div_op, Term)) -->
factor(Factor), div_op, term(Term).
term(term(Factor)) --> factor(Factor).
factor(factor('(', Expr, ')')) --> '(', expr(Expr), ')'.
factor(factor(Digit)) --> digit_code(Digit).
add_op --> ['+'].
sub_op --> ['-'].
mul_op --> ['*'].
div_op --> ['/'].
letter_code和digit_code是来自名为tokenizer.pl的单独文件的谓词
digit_code(Code):-
Code >= 48, /* 48 = '0' 57 = '9' */
Code =< 57.
letter_code(Code):-
Code >= 97, /* 97 = 'a' 122 = 'z' */
Code =< 122.
当我运行程序时,通常会出现存在错误:letter_code / 3,与数字代码相同,在其中抱怨theere不是带有3个参数的谓词。我尝试将谓词更改为具有三个参数,但随后却收到实例化错误。这就是我所做的事,它的结果是:
letter_code(Code, Xs, Xs):-
Code >= 97,
Code =< 122.
| ?- run('program1.txt','myparsetree1.txt').
! Existence error in user:letter_code/1
! procedure user:letter_code/1 does not exist
! goal: user:letter_code(97)
//------------------------------------------------
letter_code(Code, Xs, Xs):-
Code >= 97,
Code =< 122.
letter_code(Code):-
Code >= 97,
Code =< 122.
| ?- run('program1.txt','myparsetree1.txt').
! Instantiation error in argument 1 of (>=)/2
! goal: _293>=97
有人知道如何解决这个问题吗?我希望我比第一次提出这个问题时更清楚。
答案 0 :(得分:0)
在DCG正文中,letter_code(C)
将扩展为对letter_code/3
的调用。具有三个参数的实现不会从列表中删除任何内容,因此我认为这不太可能实现所需的效果,您可能需要这样的东西:
letter_code(Code) -->
[Code],
{
Code >= 97,
Code =< 122
}.
DCG规则扩展为带有两个额外参数的谓词;例如,listing(letter_code//1)
将此显示为已解析的值:
?- listing(letter_code//1).
letter_code(A, [A|C], B) :-
A>=97,
A=<122,
B=C.
true.
当您用letter_code/3
重新定义letter_code(Code, Xs, Xs) :- ...
时,您应该做出可以编译但在运行时失败的内容。因此,您无法找到已明确定义的谓词的问题就在其他地方。
答案 1 :(得分:0)
在DCG中,您将Prolog代码括在括号中:
parse(I) --> assign(I).
assign(assign(I,'=', Expr,';')) -->
{letter_code(I)}, '=', expr(Expr), ';'.
...
那是