luc*_*scn 3 php regex dsl parsing
我有一组特定领域的半结构化文本文档(会计报告),它们的内容非常相似。但是,数据在每个文档模板上的处理方式不同。
编写一些正则表达式并获取我想要的数据相当容易。但必须对每个新文档布局进行此操作。
我想构建一个通用解析器,它接收一个脚本,说明如何读取特定布局的会计报告,这样对于每个新布局,我需要做的就是编写一个新脚本,这比编写大量正则表达式更简单。
像这样的东西:
解析脚本:
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>
Run Code Online (Sandbox Code Playgroud)
请给我任何线索,告诉我从哪里开始,阅读了哪些内容,或者您是否已经看过类似的内容。我真的很感激任何帮助。
构建 DSL 并不是一件容易的事,尤其是像您建议的那样具有丰富的语法,所以我假设您已经准备好了:)
管道是:
Script -> Compiler -> PHP code for specific template
Run Code Online (Sandbox Code Playgroud)
然后你将使用PHP代码来获取数据
TEXT -> PHP code for that template -> data(structured JSON,XML,...)
Run Code Online (Sandbox Code Playgroud)
因此,要构建编译器,您需要了解流程:
Script -> Lexer(Tokenizer) -> Parser -> AST/CFG -> PHP code generation
Run Code Online (Sandbox Code Playgroud)
分词器通常通过查找空白(制表符、空格、换行符)将文本流分解为标记。
Lexer基本上是一个记号生成器,但它通常会为记号附加额外的上下文——这个记号是一个数字,那个记号是一个字符串文字,另一个记号是一个相等运算符。
解析器从词法分析器获取标记流,并将其转换为代表由原始文本表示的(通常)程序的抽象语法树。
用编程语言编写的源代码的抽象语法结构的树表示。树的每个节点表示源代码中出现的构造。该语法是“抽象的”,因为它不代表真实语法中出现的每个细节。例如,分组括号隐含在树结构中,并且像 if-condition-then 表达式这样的语法结构可以通过具有两个分支的单个节点来表示。
如果您考虑在 DSL 中使用表达式,那么它们适用于表达式而不是指令。
使用图形表示法表示程序在执行期间可能遍历的所有路径。
每个节点都是一个带有属性的指令对象(声明、获取、读取……)。例如:
get {
target: customer_name,
from: line {n: 3}
}
Run Code Online (Sandbox Code Playgroud)
PHP 是一个非常糟糕的选择,因为没有高质量的库来构建词法分析器和解析器,例如 C/C++ 中的 Flex/Bison。在这个问题中,有一些工具,但我不推荐它们在 PHP 中使用类似 Flex/Bison 的功能。
我建议你自己构建:
LL(1)(http://en.wikipedia.org/wiki/LL_grammar)