Parsing 如何在Prolog中创建与另一个相反的DCG规则?
我正在用Prolog编写Commodore BASIC解释器,我正在编写一些DCG来解析它。我已验证以下DCG是否正常工作,除了Parsing 如何在Prolog中创建与另一个相反的DCG规则?,parsing,prolog,grammar,dcg,Parsing,Prolog,Grammar,Dcg,我正在用Prolog编写Commodore BASIC解释器,我正在编写一些DCG来解析它。我已验证以下DCG是否正常工作,除了变量一个。我的目标是:对于任何不是布尔、整数、浮点或字符串的对象,它都是变量。然而,我通过短语给出的任何信息只会导致否 bool --> [true]. bool --> [false]. integer --> [1]. % how to match nums? float --> [0.1]. string --> [Str], {at
变量
一个。我的目标是:对于任何不是布尔、整数、浮点或字符串的对象,它都是变量。然而,我通过短语
给出的任何信息只会导致否
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
)
看看这个,我无法理解为什么变量
失败,因为它在文本
中的每种情况下都失败了。我猜这个错误很简单,但我还是被难住了,所以任何擅长Prolog的人都知道我做错了什么吗
| ?- 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}
您可以检测这样的整数字符串(我添加了一个参数来收集数字): 至于
variable
——它需要使用文本,因此您可能需要类似于上面的integer
的内容,但将digit(H)
更改为识别作为“变量”一部分的字符的内容
如果您想要进一步的线索(尽管有时会使用稍微高级的技巧):代码如下:要在另一个答案上展开一点,关键问题是像
\+literal
这样的DCG规则不会使用输入中的项。它只检查下一个项目(如果有)是否不是文本
要实际消费某个项目,需要使用列表目标,类似于使用目标[1]
消费1
元素。因此:
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.
?- phrase((integer, variable(Var1), float, variable(Var2)), [I, bar, F, foo]).
Var1 = bar,
Var2 = foo,
I = 1,
F = 0.1.
使用单例变量\u variable
有点奇怪——当您这样解析时,您会丢失变量的名称。当您的解析器稍微展开时,您将希望使用DCG规则的参数来传递规则之外的信息:
variable(Variable) -->
\+ literal,
[Variable].
例如:
?- phrase(variable, [bar]).
true.
?- phrase((integer, variable, float), [I, bar, F]).
I = 1,
F = 0.1.
?- phrase((integer, variable(Var1), float, variable(Var2)), [I, bar, F, foo]).
Var1 = bar,
Var2 = foo,
I = 1,
F = 0.1.