用于文本解析的DSL



我有一组特定领域(会计报告)的半结构化TEXT文档,它们在内容上都非常相似。但是,数据在每个文档模板上以不同的方式处理。

编写一些正则表达式并获得我想要的数据是相当容易的。但是对于每个新的文档布局都必须这样做。

我想建立一个通用的解析器,接收一个脚本,它应该如何读取一个特定布局的会计报告,所以对于每一个新的布局,我需要做的就是写一个新的脚本,这比写很多正则表达式更简单。

像这样:

解析脚本:

declare collection_name {
  date,
  description,
  amount
}
get customer_name from line 3
get account_id from "AccountID <number>"
read data as <collection_name> from <pattern> until <pattern>

请给我任何线索,从哪里开始,读什么关于它,或者如果你已经看到类似的东西。我将非常感谢您的帮助。

构建DSL并不是一件容易的事情,尤其是像你提议的那样使用丰富的语法,所以我认为你已经准备好了:)

管道为:

Script -> Compiler -> PHP code for specific template

然后使用PHP代码获取数据

TEXT -> PHP code for that template -> data(structured JSON,XML,...)

所以要构建编译器,你需要理解流程:

Script -> Lexer(Tokenizer) -> Parser -> AST/CFG -> PHP code generation

定义https://stackoverflow.com/a/380487/877594

  • Tokenizer将文本流分解为标记,通常通过查找空白(制表符,空格,新行)

  • Lexer基本上是一个标记器,但它通常为标记附加额外的上下文——这个标记是一个数字,那个标记是一个字符串文字,另一个标记是一个相等运算符。

  • Parser从词法分析器获取令牌流,并将其转换为抽象语法树,表示(通常)由原始文本表示的程序。

抽象语法树http://en.wikipedia.org/wiki/Abstract_syntax_tree

源代码抽象语法结构的树状表示用编程语言编写的代码。树的每个节点表示发生在源代码中的结构。语法是"抽象的"没有表示实际语法中出现的每个细节。为实例中,分组括号在树结构中是隐式的,并且像if-condition-then表达式这样的语法结构可能是用带有两个分支的单节点表示

如果您考虑在DSL中使用表达式,则它们适用于表达式而不是指令。

控制流图http://en.wikipedia.org/wiki/Control_flow_graph

使用图表示法表示所有可能的路径在程序执行过程中遍历的

每个节点是一个带有属性的指令对象(declare, get, read,…)。如:

get {
    target: customer_name,
    from: line {n: 3}
}

建设

PHP是一个非常糟糕的选择,因为没有高质量的库来构建词法分析器和解析器,比如C/c++中的Flex/Bison。在这个问题上有一些工具,但我不推荐他们在PHP中使用Flex/bison之类的功能。

我建议你自己构建它:

  • Lexer(Tokenizer)这可能有帮助http://nitschinger.at/Writing-a-simple-lexer-in-PHP
  • 修改语法,改成LL(1) (http://en.wikipedia.org/wiki/LL_grammar)
  • 编写带有错误检查和符号表的解析器来存储变量
  • 在解析
  • 时生成控制流图
  • 将控制流图转换为PHP代码,将每条指令转换为PHP代码

最新更新