解析一个"简单"的语法

She*_*ohn 12 python grammar parsing

提前抱歉; 我相信这个问题对于习惯使用解析器和语法的人来说几乎是愚蠢的,但这些对我来说都是外国话题,这是我试图轻轻地踩到需要它们的实际案例.

我想为下面的"语言"编写一个解析器,它包含一个看起来像这样的"特殊结构":

\command[ options ]{ contents }
Run Code Online (Sandbox Code Playgroud)

内容可以是任何内容,包括嵌套命令,并且可以包含转义括号或反斜杠\{ \} \\.我意识到"任何事情"并不具体,但理想情况下,如果可能的话,应该通过匹配括号(不包括转义的括号)来确定它们.

选项应该是逗号分隔的赋值表达式如列表name = value,但该值也可以是含有一个引用字符串=,字符.最后是前一个name并且command应该验证正则表达式\w[\w\d\._-+*]*- 也就是说,第一个字符应该是一个字母,剩下的字符应该是字母,数字或其中一个. _ - + *.

用正则表达式写这个似乎过于复杂(例如,因为值可能包含带引号的字符, =,否则它们将分配赋值或名称/值对).所以我认为这里最合适的工具是语法,但是尽管有表面的读数,我只是不确定如何写它(BNF,PEG等?),使用哪种类型的解析器(LR,递归正确等等?) ,以及如何在实际程序中使用解析输出.

我更喜欢Python的答案,它解释了标签,但当然如果必要/更适合我会非常满意的工具组合.


注意:这不是关于LaTeX.我认识到当然是相似的,但是LaTeX比以前的语言复杂得多,例如字符代码根据上下文而变化.我只是要求一个实际的例子(我认为)对于SO来说很简单,但在我的日常工作中对我来说已经很有用了.

geo*_*org 7

首先用正式表达你的语法,用你喜欢的任何表示法.例如,根据您的描述,EBNF将是这样的:

program := element+
element := command | literal
literal := (not '\')+

command := '\'identifier options? '{' program '}'
options := option | options ',' option
option  := identifier '=' value
value   := number | string

string  := '"' (escape | not '\' or '"')* '"'
escape  : = '\' char
Run Code Online (Sandbox Code Playgroud)

然后将其提供给解析器生成器(pyParsing,pyYACC,ANTLR)或手动编写解析器.在后一种情况下,自上而下是最简单的选项:从语法顶部开始,将每个规则转换为一个函数,该函数将返回一个解析的AST节点并使用输入或返回任何内容或抛出.例:

 def program():
    elements = []
    while next_sym():
        elements.append(element())
    return {'type': 'program', 'children': elements}

 def element():
     return command() or literal()

 def command():
     if next_sym() == '\\':
         get_sym()
         ...parse command here
         return {'type': 'command', 'children': ...}
     return None 
Run Code Online (Sandbox Code Playgroud)

where next_sym返回输入中的下一个符号(或NoneEOF)并get_sym使用符号并前进输入缓冲区.