【问题标题】:Difficulties implementing DSL in Prolog from EBNF using DCG使用 DCG 在 EBNF 的 Prolog 中实现 DSL 的困难
【发布时间】:2017-04-28 06:31:56
【问题描述】:

我正在为 Prolog 中的 proto 文件实施 Google Protobuf 编译器,以生成 Prolog 程序。 Prolog 是 SWI-Prolog

我正在将 EBNF 定义翻译成 DCG,但遇到了一些问题:

  1. 我必须处理 [ ... ]{ ... } EBNF 构造 - 意思是 optional(可执行零次或一次)和 repeatative(可执行任意次数);

    李>
  2. 我必须将 回调 插入到 DCG 代码中,以使用 DCG 的构造 { ... } 实现编译器功能的一部分(语法切换/导入/等),这允许 Prolog 中的目标DCG 规则中的语法。

我正在申请 optionalrepeatative 元谓词:$$rep/1$$opt/1

EBNF
decimals  = decimalDigit { decimalDigit }
exponent  = ( "e" | "E" ) [ "+" | "-" ] decimals 

DCG
decimals  --> decimalDigit, '$$rep'( decimalDigit ).
exponent  --> ( "e"; "E" ), '$$opt'( "+"; "-" ), decimals.

'$$rep'( Goal ) :- repeat, call(Goal); !, fail.

'$$opt'( Goal ) :- once(Goal) ; \+ Goal.

"Callback:"
import --> "import", opt(( "weak" ; "public", { record(public)} )), strLit,
{
     import(public, strlit )
}, ";".

对我来说看起来很尴尬(如果不是说丑的话)......

问题:

我的解决方案有什么问题?

我是否应该在不使用元谓词的情况下手动将 EBNG 翻译成 DCG?

对于 DCG 规则的尴尬渗透,有什么替代方法?

【问题讨论】:

    标签: parsing prolog dsl dcg ebnf


    【解决方案1】:

    乍一看,主要问题是您不干净地混合 DCG 与常规 Prolog 谓词。

    留在 DCG 内以定义所有非终结符。例如:

    可选(NT)--> [] |新台币。 once_or_more(NT) --> NT,or_more(NT)。 or_more(NT) --> [] |新台币,或_more(新台币)。

    使用以下示例定义:

    一-> [一]。

    我们可以发帖:

    ?- 短语(可选(a),Ls)。 LS = [] ; LS = [a]。 ?- 短语(once_or_more(a), Ls)。 LS = [一] ; Ls = [a, a] ; Ls = [a, a, a] ; Ls = [a, a, a, a] ; Ls = [a, a, a, a, a] 。

    这似乎可以满足您的需要。

    对于回调,您可以简单地传递您需要调用的谓词,并带有大致轮廓:

    parse_with_callback(目标) --> ..., {目标}, ...

    这看起来还不错。

    如果此类模式频繁出现,您始终可以考虑生成这样的 DCG,从不同的表示中更清晰地表示任务。

    【讨论】:

    • 感谢您的回复。值得注意的是,repeatatives(零个或多个)通常是这样的:decimals([]) --> []。小数([ D | Ds ])--> 小数(D),!,小数(Ds)。
    • 不客气!使用!/0 可以防止您在所有方向使用语法,例如生成 答案。如果您将decimal//1 泛化,这将是可能的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多