如何在DCG中表示字母数字字符串?

时间:2020-11-06 21:38:21

标签: parsing prolog bnf

我正在尝试为解析为S表达式的命题演算编写一个解析器。

我已经取得了一些进展:

expression --> op.
op --> ['('], bin-op, bool, bool, [')'].
op --> ['('], unary-op, bool, [')'].
bool --> tok.
bool --> op.

bin-op --> ["IFF"].
bin-op --> ["IF"].
bin-op --> ["XOR"].
unary-op --> ["NOT"].

tok --> ["a"].

swipl中,我通过调用phrase得到了适当的响应:

?- phrase(expression, Ls).
Ls = ['(', "IFF", "a", "a", ')'] 

但这仅适用于tok“ a”。有没有办法在DCG中说“ tok是任何字母数字字符串”?我找到了this,但不确定如何将其应用于正在执行的操作。

1 个答案:

答案 0 :(得分:2)

如果您只想解析,则以下标记将起作用。

tok([A|B], B) :- an_code(A).

alpha_numeric(X) :- 
  between(0'0, 0'9, X); between(0'A, 0'Z, X); between(0'a, 0'z, X).
an_code(A) :- atom_codes(A, C), maplist(alpha_numeric, C).
?- phrase(expression, ['(', "IFF", "A1", "1A", ')']).
true 

?- phrase(expression, ['(', "IFF", ".A1", "1A", ')']).
false.

?- phrase(expression, ['(', "IFF", ".A1", "(1A", ')']).
false.

使用以下an_code,您也可以生成公式:

an_code(A) :- var(A) ->
                 length(C,L), L >= 1,
                 maplist(alpha_numeric, C),
                 string_codes(A, C);
               atom_codes(A, C), maplist(alpha_numeric, C).
?- phrase(expression, Ls).
Ls = ['(', "IFF", "0", "0", ')'] ;
Ls = ['(', "IFF", "0", "1", ')'] ;
Ls = ['(', "IFF", "0", "2", ')'] ;

?- nth0(1, Ls, "XOR"), phrase(expression, Ls).
Ls = ['(', "XOR", "0", "0", ')'] ;
Ls = ['(', "XOR", "0", "1", ')'] ;
Ls = ['(', "XOR", "0", "2", ')']

?- nth0(1, Ls, "NOT"), phrase(expression, Ls).
Ls = ['(', "NOT", "0", ')'] ;
Ls = ['(', "NOT", "1", ')'] ;
Ls = ['(', "NOT", "2", ')'] 

在生成版本中,使用的某些谓词是swi-prolog内置的,因此它们不能与其他实现一起使用。

内置char_type/2的swi-prolog也可以用作字母数字char_type(C, alnum)。以下是使用swi-prolog谓词的dcg样式代码。

tok -->
    [A],
    { string_codes(A, AC),
      maplist([C]>>char_type(C, alnum), AC)
    }.
相关问题