问题描述
我正在Prolog中编写Commodore BASIC解释器,并且正在编写一些DCG进行解析.我已经验证了以下DCG可以正常工作,除了 variable
变量.我的目标是:对于不是布尔值,整数,浮点数或字符串的任何内容,它都是一个变量.但是,我通过 phrase
给出的任何内容只会导致 no
.
I am writing a Commodore BASIC interpreter in Prolog, and I am writing some DCGs to parse it. I have verified the DCGs below to work except for the variable
one. My goal is this: for anything which isn't a boolean, integer, float, or a string, it's a variable. However, anything that I give it via phrase
just results in no
.
bool --> [true].
bool --> [false].
integer --> [1]. % how to match nums?
float --> [0.1].
string --> [Str], {atom_chars(Str, ['"' | Chars]), last(Chars, '"')}.
literal --> bool; integer; float; string.
variable --> \+ literal.
我这样运行了堆栈跟踪(使用 gprolog
)
I ran a stack trace like this (with gprolog
)
main :- trace, phrase(variable, [bar]).
鉴于此,我无法弄清楚为什么 variable
失败了,因为在 literal
中每种情况下它都失败了.我猜错误很简单,但我仍然很困惑,所以擅长Prolog的人对我做错的事情有想法吗?
Looking at this, I cannot figure out why variable
fails, given that it fails for each case in literal
. I'm guessing that the error is pretty simple, but I'm still stumped, so does anyone who's good at Prolog have an idea of what I'm doing wrong?
| ?- main.
The debugger will first creep -- showing everything (trace)
1 1 Call: phrase(variable,[bar]) ?
2 2 Call: variable([bar],_321) ?
3 3 Call: \+literal([bar],_348) ?
4 4 Call: literal([bar],_348) ?
5 5 Call: bool([bar],_348) ?
5 5 Fail: bool([bar],_348) ?
5 5 Call: integer([bar],_348) ?
5 5 Fail: integer([bar],_348) ?
5 5 Call: float([bar],_348) ?
5 5 Fail: float([bar],_348) ?
5 5 Call: string([bar],_348) ?
6 6 Call: atom_chars(bar,['"'|_418]) ?
6 6 Fail: atom_chars(bar,['"'|_418]) ?
5 5 Fail: string([bar],_348) ?
4 4 Fail: literal([bar],_348) ?
3 3 Exit: \+literal([bar],_348) ?
2 2 Exit: variable([bar],[bar]) ?
1 1 Fail: phrase(variable,[bar]) ?
(2 ms) no
{trace}
推荐答案
要扩展另一个答案,关键问题是DCG规则(如 \ + literal
)不会消耗来自输入.仅检查下一项(如果有的话)不是文字
.
To expand a bit on the other answer, the key problem is that a DCG rule like \+ literal
does not consume items from the input. It only checks that the next item, if any, is not a literal
.
要实际消耗商品,您需要使用列表目标,类似于使用目标 [1]
来消耗 1
元素的方式.所以:
To actually consume an item, you need to use a list goal, similarly to how you use a goal [1]
to consume a 1
element. So:
variable -->
\+ literal, % if there is a next element, it's not a literal
[_Variable]. % consume this next element, which is a variable
例如:
?- phrase(variable, [bar]).
true.
?- phrase((integer, variable, float), [I, bar, F]).
I = 1,
F = 0.1.
具有单例变量 _Variable
有点奇怪-像这样解析时,您会丢失变量的名称.解析器稍作扩展后,您将需要使用DCG规则的参数来传达规则外的信息:
Having that singleton variable _Variable
is a bit strange -- when you parse like this, you lose the name of the variable. When your parser is expanded a bit, you will want to use arguments to your DCG rules to communicate information out of the rules:
variable(Variable) -->
\+ literal,
[Variable].
例如:
?- phrase((integer, variable(Var1), float, variable(Var2)), [I, bar, F, foo]).
Var1 = bar,
Var2 = foo,
I = 1,
F = 0.1.
这篇关于如何在Prolog中创建与另一个规则相反的DCG规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!