【问题标题】:Good grammar for date data type for recursive descent parser LL(1)递归下降解析器 LL(1) 的日期数据类型的良好语法
【发布时间】:2010-03-17 12:30:37
【问题描述】:

我正在为生产环境构建一个自定义表达式解析器和评估器,以向用户提供有限的 DSL。解析器本身作为 DSL,需要简单。解析器将使用一种不支持动态表达式解析的外来语言构建,也没有任何可用的解析器生成器工具。

我目前的决定是采用 LL(1) 语法的递归下降方法,这样即使以前没有评估表达式经验的程序员也可以快速了解代码的工作原理。

它必须处理由多种数据类型组成的混合表达式:小数、百分比、字符串和日期。而且dd/mm/yyyy格式的日期很容易和一串除法操作混淆。

哪里有解决这个问题的好办法?

我自己的解决方案旨在使解析器保持简单,并在日期前加上一个特殊符号,比如说撇号:

<date>   ::= <apostr><digit><digit>/<digit><digit>/<digit><digit><digit><digit>

<apostr> ::= '

<digit>  ::= '0'..'9'

【问题讨论】:

  • 这取决于你想做什么更多,留下不常见项目的前缀,例如如果日期更常见使用 =1/2/2010 来表示除法。

标签: parsing grammar dsl expressionengine recursive-descent


【解决方案1】:

首先,我是 LL 解析器的粉丝,所以我衷心赞同你的方法。请注意,较新的流行解析器生成器之一 (ANTLR) 是 LL。如果你允许更多的前瞻,而不是将自己限制在 LL(1),你几乎可以用 LR(1) 解析器做任何你想做的事情,但代码会更清晰、更可靠,并且更容易调试。

我对你的整体语法知之甚少,无法分辨。您可能可以设计一些东西,以便 LL 解析器始终可以从上下文中判断它是整数表达式还是日期常量。但是,假设你不能,是的,你需要某种方式来区分。我唯一能想到的另一件事是使用反斜杠而不是斜杠作为分隔符,但这有点难看。

【讨论】:

  • T.E.D 谢谢,不胜感激!例如,MS Excel 在这种情况下将根据上下文推断类型,即在单元格中写入 =01/01/2010 将导致 0.000497512。但是,将单元格数据类型显式或隐式设置为日期将产生一个日期。但是我觉得这种类型推断魔法会给解析器评估器增加很多复杂性,并且可能会使负责维护解析器的用户和程序员感到困惑(基于他们以前没有在解析器上工作过的假设)。
【解决方案2】:

您需要一个具有无限前瞻功能的类 LL 无词法分析器。也就是PEG。

http://en.wikipedia.org/wiki/Parsing_expression_grammar

通过有序的选择,很容易避免这个日期与常量文字划分混淆。

【讨论】:

  • 我还认为有序选择将是这里最干净(可能也是唯一)的解决方案。
  • 我不太确定。在某些情况下,如果不在日期前面添加撇号,他的语法很可能会模棱两可。 PEG 功能强大,但无法处理模棱两可的语法。
  • 他们可以解决歧义。如果某些东西看起来像日期,那么首先将其解析为日期。如果然后在预期其他内容的上下文中使用它,则将其回溯并以另一种方式重新解析。例如,1/2/3 将是一个日期,但 1/2/3/4 将是 1 除以 2 除以 3 等。
【解决方案3】:

当一种语言用于人类输入时,定义它同样重要

  • 添加语法约束以确保明确且易于解析
  • 删除/弯曲语法以确保语言对预期的人类受众而言具有直观、“自然”的感觉。

满足第二个要求比第一个要困难得多,并且需要深入了解

  • 语言的预期用例
    有哪些类型的键盘/输入设备可用?在允许的字符中是否有一些字符难以生成或在显示器上难以看到?
    哪些标记/表达式会经常使用,哪些只是偶尔需要? 用户是否经常输入简短的临时代码 sn-ps,或者这些程序是否需要长期重复使用和修改
    ...等等。
  • 目标受众的背景/文化
    如果可能,可以或应该重用来自其他常规(和普通自然)语言的哪些常见做法/习语?
    人们应该喜欢简洁但神秘的风格,还是更明确但更冗长的风格?
    ...等等。

基本上,如果不很好地掌握预期用途和用户,就很难就语言语法提出建议。
不过,对于日期格式问题,我想提出以下建议:

完全使用另一种日期值格式;对用户来说足够“自然”,但又足够独特,可以用常规语法来描述。
例如,使用 3 个字母的月份缩写 (下行 DSL 与英语或其他语言相关联,但也有优势,消除了人类关于哪个是日哪个是月的歧义) .暂定:

  dd-mmm-yyyy    (may seem unnatural in cultures where the prevailing date order 
                  starts with the month maybe yyyy-mmm-dd then ?)
  mmm-dd-yyyy    (better for the above mentioned cultures)
  ddmmmyyyy      (avoid the dashes, but impose leading zeros)

  MnnDnnYyyyy    (using "M", "D" and "Y" (or others) as explicit prefixes; now, 
                  this is completely culture neutral, but maybe a bit awkward...)

无论如何,只是想法......适用性会因提到的人类/文化因素而异,会随着语法的其余部分而变化。例如,上面可能暗示变量被显式标记(这是许多语言使用 $ 前缀的原因之一),以避免可能与 [odd, but possible] 变量标识符发生冲突。

简而言之,这个想法是通过使 12 个月标签成为解析器足够好的鉴别器来替代对特殊字符前缀的需求(这可能会与这些字符在数学和其他表达式中的使用发生冲突)。

【讨论】:

    猜你喜欢
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多