以自定义格式解析数据的良好做法

时间:2014-10-22 15:20:57

标签: parsing format bison flex-lexer

我正在编写一个程序,以自定义格式输入直接播放,然后对其进行一些分析(如每个字符的行数和单词数)。它只是为了好玩,是学习很酷的东西的借口。 该过程的第一步是为该格式编写解析器。它是:

####Play
###Act I
##Scene 1
CHARACTER 1. Line 1, he's saying some stuff.
#Comment, stage direction
CHARACTER 2, doing some stuff. Line 2, she's saying some stuff too.

这是一种非常简单的格式。我广泛阅读了关于CFG等基本解析器的内容,所以我现在准备完成一些工作了。

我已经在EBNF中编写了我的语法并开始使用flex / bison但它提出了一些问题:

  • 对于这样一个简单的解析器来说,flex / bison太多了吗?我应该按照此处所述自己编写:Is there an alternative for flex/bison that is usable on 8-bit embedded systems?
  • 关于tokenizer和解析器本身的各个任务有什么好的做法?从来没有一个解决方案,对于这种简单的语言,它们经常重叠。对于flex / bison来说尤其如此,其中flex可以通过正则表达式匹配执行一些强烈的事情。例如,“#”应该是一个标记吗? “####”应该也是一个标记吗?我应该创建带有语义信息的类型,以便我可以直接识别例如一个字符吗?或者我应该用flex以最简单的方式处理它,然后让bison中定义的语法决定什么是什么?
  • 使用flex / bison,在解析时执行分析是否有意义,或者首先解析是否更优雅,然后使用其他工具再次对文件进行操作?

这让我很困惑。我正在寻找一个优雅,或许简单的解决方案。任何指南?

顺便说一下,关于编程语言,我并不在意。现在我因为flex / bison而使用C,但只要它是一种广泛使用的语言,我就可以随意告诉我更实用的东西。

1 个答案:

答案 0 :(得分:2)

在不知道解析期望是什么的情况下回答这些问题非常困难。也就是说,几行文本的例子并没有清楚地理解预期的解析是什么;词汇和句法单位是什么;你想提取什么样的关系;等等。

然而,一个粗略的猜测可能是您打算生成嵌套解析,其中##{i}指示嵌套级别(反向),i≥1,因为单个#不是结构。这违反了语言设计的一个原则(“不要让用户计算计算机可以更准确计算的东西”),这可能表明结构更像是:

@play {
@act {
@scene {
@location: Elsinore. A platform before the castle.
@direction: FRANCISCO at his post. Enter to him BERNARDO 
BERNARDO: Who's there?
FRANCISCO: Nay, answer me: stand, and unfold yourself.
BERNARDO: Long live the king!
FRANCISCO: Bernardo?

甚至是类似XML的东西。但那将是一种不同的语言:)

使用经典扫描器/解析器组合解析其中任何一个的问题是词法结构不一致;一行中的第一个标记是特殊的,但大部分文件都包含未解析的文本。这几乎不可避免地导致在扫描程序和解析器之间传播语法信息,因为扫描程序需要知道语法上下文以确定它是否正在扫描原始文本。

您可以避免该问题。例如,您可能要求延续行以空格开头,以便以#标记的每一行都以字符的名称开头。这比识别对话线更可靠,因为它以字符和句点的名称开头,因为字符的名字很可能用于对话,即使在句子结尾处(因此可能是延续线中的第一个单词。)

如果您打算通过以字符名称和一些标点符号开头来区分对话行,那么您肯定必须让扫描程序访问字符列表(作为一种符号表),是一个众所周知但不是特别受人尊敬的黑客。

考虑上面关于你的第二个问题的反思(“扫描仪和解析器的角色是什么?”),这不符合答案,但希望至少可以考虑。至于你的其他问题,并认识到所有这些都是自以为是:

  

对于这样一个简单的解析器来说,flex / bison太多了吗?我应该自己写一下......

flex和bison(可能)比解析特定语言所需的功能更强大这一事实是一个红色的鲱鱼。 C编写阶乘函数比编写函数更有用 - 你可以在汇编程序中轻松完成 - 但是编写阶乘函数是学习C的一个很好的练习。同样,如果你想学习如何编写解析器,这是一个很好的想法从简单的语言开始;很明显,这不会解析解析器/扫描器生成器中的每个选项,但它会让你开始。问题在于你所设计的语言是否适合这种解析方式,而不是它是否过于简单。

  

使用flex / bison,在解析时执行分析是否有意义,或者首先解析是否更优雅,然后使用其他工具再次对文件进行操作?

要么是优雅的,要么是灾难性的;优雅更多地与你如何构建对手头问题的思考结构有关。话虽如此,通常最好在解析阶段构建语义结构(通常称为AST - 抽象语法树),然后使用其他函数分析该结构。

重新扫描输入文件不太可能优雅或有效。