我有一组特定域(会计报告)的半结构化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>
请告诉我从哪里开始,阅读有关内容,或者您是否已经看过类似的内容。我真的很感激任何帮助。
答案 0 :(得分:4)
构建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
Tokenizer 将文本流分解为标记,通常是查找空格(标签,空格,新行)。
Lexer 基本上是一个标记化器,但它通常会为标记附加额外的上下文 - 这个标记是一个数字,该标记是一个字符串文字,另一个标记是一个相等运算符
Parser 从词法分析器获取标记流并将其转换为表示原始文本所代表的(通常)程序的抽象语法树。
源的抽象语法结构的树表示 用编程语言编写的代码。树的每个节点表示 源代码中出现的构造。语法是&#34; abstract&#34;在 不代表真实语法中出现的每个细节。对于 例如,分组括号隐含在树结构中,并且 像if-condition-then表达式这样的句法结构可能是 用具有两个分支的单个节点表示。
如果您正在考虑在DSL中使用表达式,它们适用于表达式而非指令。
使用图表符号表示可能存在的所有路径 在执行过程中遍历了一个程序。
每个节点都是一个带有属性的指令对象(声明,获取,读取......)。例如:
get {
target: customer_name,
from: line {n: 3}
}
PHP是一个非常糟糕的选择,因为没有高质量的库来构建词法分析器和解析器,比如C / C ++中的Flex / Bison。在这个问题中有一些工具,但我不推荐它们Flex/Bison-like functionality within PHP。
我建议您自己构建它:
LL(1)
(http://en.wikipedia.org/wiki/LL_grammar)