【问题标题】:How do I create a DCG rule inverse to another in Prolog?如何在 Prolog 中创建与另一个相反的 DCG 规则?
【发布时间】:2021-04-05 17:24:42
【问题描述】:

我正在 Prolog 中编写 Commodore BASIC 解释器,并且正在编写一些 DCG 来解析它。除了variable 之外,我已经验证了下面的 DCG 可以正常工作。我的目标是:对于任何不是布尔值、整数、浮点数或字符串的东西,它都是一个变量。但是,我通过phrase 提供的任何内容都只会导致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

main :- trace, phrase(variable, [bar]).

看着这个,我不知道为什么variable 会失败,因为literal 中的每个案例都失败了。我猜这个错误很简单,但我仍然很难过,那么擅长 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}

【问题讨论】:

    标签: parsing prolog grammar dcg


    【解决方案1】:

    为了扩展另一个答案,关键问题是像\+ literal 这样的 DCG 规则不会消耗输入中的项目。它只检查下一项(如果有的话)不是literal

    要实际消费一个项目,您需要使用列表目标,类似于使用目标[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.
    

    拥有那个单例变量_Variable 有点奇怪——当你像这样解析时,你会丢失变量的名称。当你的解析器被扩展一点时,你会想要使用 DCG 规则的参数来传达规则之外的信息:

    variable(Variable) -->
        \+ literal,  
        [Variable].
    

    例如:

    ?- phrase((integer, variable(Var1), float, variable(Var2)), [I, bar, F, foo]).
    Var1 = bar,
    Var2 = foo,
    I = 1,
    F = 0.1.
    

    【讨论】:

      【解决方案2】:

      你可以像这样检测一串整数(我添加了一个参数来收集数字):

      integer([H|T]) --> digit(H), integer(T).
      integer([]) -->  [].
      digit(0) --> "0".
      digit(1) --> "1".
          ...
      digit(9) --> "9".
      

      至于variable——它需要使用文本,因此您需要类似于上面的integer,但将digit(H) 更改为能够识别作为“变量”一部分的字符的东西。

      如果您想要进一步的线索(尽管有时会使用稍微高级的技巧):https://www.swi-prolog.org/pldoc/man?section=basics 代码在这里:https://github.com/SWI-Prolog/swipl-devel/blob/master/library/dcg/basics.pl

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多