可能无限递归(循环):用DCG解析规则
Probable infinite recursion (cycle): with DCG parsing rule
我正在努力为一种命令式语言开发一个小型解析器,但我坚持使用非递归语法的定义。
我阅读了 this post 的解决方案,但我无法理解它,我将终端调用移到我的声明之上,但我对用于表达的不同语法感到困惑同一个意思。
我输入的token是下面一个[word(x),punct(:),punct(=),number(1)]
这是我用来解析这个列表的代码
parse(ListTokens, ListStmt) :-
phrase(commands(ListStmt), ListTokens).
commands([]) --> [].
commands(Command) --> command(Command).
commands(Commands) --> [punct("(")], commands(Commands), [punct(")")].
commands([Command | Commands]) --> command(Command), [punct(";")], commands(Commands).
command(Skip) --> [keyword("skip")],
{Skip = skip()}.
command(Assign) --> a_expr(X), !, [punct(":")], [punct("=")], a_expr(Y), !,
{Assign = assign(X, Y)}.
command(While) --> [keyword("while")], b_expr(X), !, [keyword("do")], command(Commands), !,
{While = while(X, Commands)}.
a_expr(word(Name)) --> [var(Name)].
a_expr(number(Val)) --> [Val].
a_expr(Expr) --> a_expr(X), !, [punct("+")], a_expr(Y), !, {Expr = increment(X, Y)}.
a_expr(Expr) --> a_expr(X), !, [punct("-")], a_expr(Y), !, {Expr = decrement(X, Y)}.
a_expr(Expr) --> a_expr(X), !, [punct("*")], a_expr(Y), !, {Expr = multipl(X, Y)}.
b_expr(Expr) --> [punct("(")], b_expr(Expr), [punct(")")].
b_expr(True) --> [keyword("true")], {True = bool(1)}.
b_expr(False) --> [keyword("false")], {False = bool(0)}.
b_expr(Cmp) --> a_expr(X), !, [punct("=")], a_expr(Y), !, {Cmp = cmp(X, Y)}.
b_expt(Gt) --> a_expr(X), !, [punct(">")], a_expr(Y), !, {Gt = gt(X, Y)}.
结果报告如下,但我想有以下一个assign(x,1)
assign(number(word(x)),number(number(1)))
我认为问题出在以下几行,但我找不到错误,因为这是来自 this post 的解决方案,它使用了不同的语法
a_expr(word(Name)) --> [var(Name)].
a_expr(number(Val)) --> [Val].
你能帮我解决这个问题吗?
基本上,您的代码有两个问题。
一个是停止回溯的 bang 运算符 !
。它是一个反模式,所以我建议不要使用它。
我非常喜欢可读代码,我认为您需要在语法中接受左递归,主要是因为您使用的语法非常可读。
我建议换
parse(ListTokens, ListStmt) :-
phrase(commands(ListStmt), ListTokens).
commands([]) --> [].
commands(Command) --> command(Command).
commands(Commands) --> [punct("(")], commands(Commands), [punct(")")].
commands([Command | Commands]) --> command(Command), [punct(";")], commands(Commands).
command(Skip) --> [keyword("skip")],
{Skip = skip()}.
command(Assign) --> a_expr(X), !, [punct(":")], [punct("=")], a_expr(Y), !,
{Assign = assign(X, Y)}.
command(While) --> [keyword("while")], b_expr(X), !, [keyword("do")], command(Commands), !,
{While = while(X, Commands)}.
a_expr(word(Name)) --> [var(Name)].
a_expr(number(Val)) --> [Val].
a_expr(Expr) --> a_expr(X), !, [punct("+")], a_expr(Y), !, {Expr = increment(X, Y)}.
a_expr(Expr) --> a_expr(X), !, [punct("-")], a_expr(Y), !, {Expr = decrement(X, Y)}.
a_expr(Expr) --> a_expr(X), !, [punct("*")], a_expr(Y), !, {Expr = multipl(X, Y)}.
b_expr(Expr) --> [punct("(")], b_expr(Expr), [punct(")")].
b_expr(True) --> [keyword("true")], {True = bool(1)}.
b_expr(False) --> [keyword("false")], {False = bool(0)}.
b_expr(Cmp) --> a_expr(X), !, [punct("=")], a_expr(Y), !, {Cmp = cmp(X, Y)}.
b_expt(Gt) --> a_expr(X), !, [punct(">")], a_expr(Y), !, {Gt = gt(X, Y)}.
对于这一行,基本上,添加以下行 :- table a_expr//1.
以使用制表并接受左递归。 (注意,你需要去掉所有的 bang 运算符)
:- table a_expr//1.
% other rules
% add this one, it is left recursion, but tanks to tabling
a_expr(Var) --> [word(Name)], {Var = var(Name)}.
a_expr(Val) --> [number(X)], {Val = X}.
a_expr(Expr) --> a_expr(X), [punct("+")], a_expr(Y), {Expr = increment(X, Y)}.
a_expr(Expr) --> a_expr(X), [punct("-")], a_expr(Y), {Expr = decrement(X, Y)}.
a_expr(Expr) --> a_expr(X), [punct("*")], a_expr(Y), {Expr = multipl(X, Y)}.
P.S:正如一个评论所建议的,您需要按照以下规则进行打字错误
b_expt(Gt) --> a_expr(X), !, [punct(">")], a_expr(Y), !, {Gt = gt(X, Y)}.
是b_expr
我正在努力为一种命令式语言开发一个小型解析器,但我坚持使用非递归语法的定义。
我阅读了 this post 的解决方案,但我无法理解它,我将终端调用移到我的声明之上,但我对用于表达的不同语法感到困惑同一个意思。
我输入的token是下面一个[word(x),punct(:),punct(=),number(1)]
这是我用来解析这个列表的代码
parse(ListTokens, ListStmt) :-
phrase(commands(ListStmt), ListTokens).
commands([]) --> [].
commands(Command) --> command(Command).
commands(Commands) --> [punct("(")], commands(Commands), [punct(")")].
commands([Command | Commands]) --> command(Command), [punct(";")], commands(Commands).
command(Skip) --> [keyword("skip")],
{Skip = skip()}.
command(Assign) --> a_expr(X), !, [punct(":")], [punct("=")], a_expr(Y), !,
{Assign = assign(X, Y)}.
command(While) --> [keyword("while")], b_expr(X), !, [keyword("do")], command(Commands), !,
{While = while(X, Commands)}.
a_expr(word(Name)) --> [var(Name)].
a_expr(number(Val)) --> [Val].
a_expr(Expr) --> a_expr(X), !, [punct("+")], a_expr(Y), !, {Expr = increment(X, Y)}.
a_expr(Expr) --> a_expr(X), !, [punct("-")], a_expr(Y), !, {Expr = decrement(X, Y)}.
a_expr(Expr) --> a_expr(X), !, [punct("*")], a_expr(Y), !, {Expr = multipl(X, Y)}.
b_expr(Expr) --> [punct("(")], b_expr(Expr), [punct(")")].
b_expr(True) --> [keyword("true")], {True = bool(1)}.
b_expr(False) --> [keyword("false")], {False = bool(0)}.
b_expr(Cmp) --> a_expr(X), !, [punct("=")], a_expr(Y), !, {Cmp = cmp(X, Y)}.
b_expt(Gt) --> a_expr(X), !, [punct(">")], a_expr(Y), !, {Gt = gt(X, Y)}.
结果报告如下,但我想有以下一个assign(x,1)
assign(number(word(x)),number(number(1)))
我认为问题出在以下几行,但我找不到错误,因为这是来自 this post 的解决方案,它使用了不同的语法
a_expr(word(Name)) --> [var(Name)].
a_expr(number(Val)) --> [Val].
你能帮我解决这个问题吗?
基本上,您的代码有两个问题。
一个是停止回溯的 bang 运算符 !
。它是一个反模式,所以我建议不要使用它。
我非常喜欢可读代码,我认为您需要在语法中接受左递归,主要是因为您使用的语法非常可读。
我建议换
parse(ListTokens, ListStmt) :-
phrase(commands(ListStmt), ListTokens).
commands([]) --> [].
commands(Command) --> command(Command).
commands(Commands) --> [punct("(")], commands(Commands), [punct(")")].
commands([Command | Commands]) --> command(Command), [punct(";")], commands(Commands).
command(Skip) --> [keyword("skip")],
{Skip = skip()}.
command(Assign) --> a_expr(X), !, [punct(":")], [punct("=")], a_expr(Y), !,
{Assign = assign(X, Y)}.
command(While) --> [keyword("while")], b_expr(X), !, [keyword("do")], command(Commands), !,
{While = while(X, Commands)}.
a_expr(word(Name)) --> [var(Name)].
a_expr(number(Val)) --> [Val].
a_expr(Expr) --> a_expr(X), !, [punct("+")], a_expr(Y), !, {Expr = increment(X, Y)}.
a_expr(Expr) --> a_expr(X), !, [punct("-")], a_expr(Y), !, {Expr = decrement(X, Y)}.
a_expr(Expr) --> a_expr(X), !, [punct("*")], a_expr(Y), !, {Expr = multipl(X, Y)}.
b_expr(Expr) --> [punct("(")], b_expr(Expr), [punct(")")].
b_expr(True) --> [keyword("true")], {True = bool(1)}.
b_expr(False) --> [keyword("false")], {False = bool(0)}.
b_expr(Cmp) --> a_expr(X), !, [punct("=")], a_expr(Y), !, {Cmp = cmp(X, Y)}.
b_expt(Gt) --> a_expr(X), !, [punct(">")], a_expr(Y), !, {Gt = gt(X, Y)}.
对于这一行,基本上,添加以下行 :- table a_expr//1.
以使用制表并接受左递归。 (注意,你需要去掉所有的 bang 运算符)
:- table a_expr//1.
% other rules
% add this one, it is left recursion, but tanks to tabling
a_expr(Var) --> [word(Name)], {Var = var(Name)}.
a_expr(Val) --> [number(X)], {Val = X}.
a_expr(Expr) --> a_expr(X), [punct("+")], a_expr(Y), {Expr = increment(X, Y)}.
a_expr(Expr) --> a_expr(X), [punct("-")], a_expr(Y), {Expr = decrement(X, Y)}.
a_expr(Expr) --> a_expr(X), [punct("*")], a_expr(Y), {Expr = multipl(X, Y)}.
P.S:正如一个评论所建议的,您需要按照以下规则进行打字错误
b_expt(Gt) --> a_expr(X), !, [punct(">")], a_expr(Y), !, {Gt = gt(X, Y)}.
是b_expr