Parsing 如何在Prolog中创建与另一个相反的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

我正在用Prolog编写Commodore BASIC解释器,我正在编写一些DCG来解析它。我已验证以下DCG是否正常工作,除了
变量
一个。我的目标是:对于任何不是布尔、整数、浮点或字符串的对象,它都是变量。然而,我通过
短语
给出的任何信息只会导致

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.