1

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

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

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

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

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

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

<apostr> ::= '

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

3 回答 3

2

您需要一个具有无限前瞻功能的类 LL 无词法分析器。并且,即它是PEG。

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

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

于 2010-03-17T15:01:48.673 回答
2

First off, I'm a fan of LL parsers, so I approve of your approach heartily. Note that one of the newer popular parser generators (ANTLR) is LL. If you allow more look-ahead, rather that restricting yourself to LL(1), you can do pretty much anything you'd ever want to do with an LR(1) parser, but the code will be far clearer, more reliable, and easier to debug.

I don't know enough about your overall grammar to be able to tell. It is possible you might be able to design things so that the LL parser can always tell from context if it is an integer expression or a date constant. However, assuming you can't, yeah you'd need some kind of way to tell the difference. The only other thing I can think of would be to use backslash as a separator instead of slash, but that's kinda ugly.

于 2010-03-17T13:31:43.817 回答
0

当一种语言用于人类输入时,定义它同样是一个问题

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

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

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

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

完全使用另一种日期值格式;一种对用户来说足够“自然”但又足够独特以至于常规语法可以描述的语言。
例如,一个使用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-03-17T15:05:57.417 回答