Java 的 Parser combinator 中最有名应该是 JParsec 了。随着 Java 8 的发布,我们也可以用 lambda 表达式来写规则了。刚开始的时候我以为它跟 C# 下面的 Sprache 会比较像,API 应该很容易。结果我错了。Sprache 的思想跟《Monadic Parser Combinators》这篇论文里的提到的设计方法如出一辙,是不区分 lexer 和 parser 的。但是 JParsec 区分。如果在 parser 对应的规则里面使用 lexer 的规则,会导致异常。可以参看 ParserState 类:
@Override CharSequence characters() {
throw new IllegalStateException(
"Cannot scan characters on tokens.");
}
如果你在尝试用 JParsec 写规则时遇到了不知道怎么在 parser 规则中引用 lexer 规则的问题,恭喜你,看完下面的代码你会应该知道怎么做了。
整体示意图:
比如解析一段 key/value 文本:
"update": "2014-10-28"
为了解析双引号的部分写一个 lexer 规则:
private static final
Parser<Tokens.Fragment> STRING_LITERAL =
Scanners.DOUBLE_QUOTE_STRING
.map(patchTag(Tag.STRING))
.label("string literal");
enum Tag {
STRING
}
private static
Map<String, Tokens.Fragment> patchTag(Object tag) {
return str -> new Tokens.Fragment(str, tag);
}
除 patchTag 函数和 Tag 枚举之外其它的都是 JParsec 的 API。patchTag 的作用就让 lexer 在运行的时候将 STRING_LITERAL 规则所解析出来的字符串打上 STRING 这个 tag。这样在后面的 parser 规则部分用这个 tag 将字符串规则取出来:
private final
Parser<String> stringLiteral =
Parsers.token(withTag(Tag.STRING))
// 除掉引号
.map(s -> s.substring(1, s.length() - 1))
.label("string literal");
private static TokenMap<String>
withTag(Object tag) {
return token -> {
Object value = token.value();
if (value instanceof Tokens.Fragment) {
Tokens.Fragment fragment =
(Tokens.Fragment) value;
if (tag.equals(fragment.tag())) {
return fragment.text();
}
}
return null;
};
}
这样就可以做一个规则来匹配 "update": "2014-10-28" 这样的文本了:
private Parser<StatAstKeyValue> keyValue =
Parsers.sequence(
stringLiteral,
OPERATORS.token(":"),
stringLiteral,
(k, ignored, v) ->
new StatAstKeyValue(k, v))
.label("keyValue");
private static final
Terminals OPERATORS =
Terminals.operators("{", "}", ",", ":");
文本中的空格部分要求在 lexer 中额外定义一个空白字符的规则:
private static final
Parser<Void> WHITESPACES = Scanners.WHITESPACES;
为了达到忽略空白字符的目的,我们可以用 Parser#skipMany() 这样的 combinator,也可以用 JParsec 的官方教程上的做法:
private Parser<List<Token>>
TERMINALS = TOKENIZER.lexer(
WHITESPACES.or(Parsers.always())
);
这里将 WHITESPACES.or(Parsers.always()) 作为分隔符来分隔 TOKENIZER 解析出来的 token。如果不加 Parsers.always(),会导致可以解析
"k" : "v"
但不能解析
"k": "v"
注意第 2 个例子中冒号的前面没有空格。
- 大小: 25.5 KB
分享到:
相关推荐
总结来说,文件内容涉及了使用Go语言从零开始实现Lexer和Parser的基础知识,并提到了在软件开发过程中如何面对快速迭代、内容管理、版本控制和自动化部署等实际问题。这些都是软件工程师在日常工作中可能遇到的典型...
标题中的"Rust VBScript lexer and parser"指的是一项使用Rust语言实现的VBScript的词法分析器和解析器。词法分析器(lexer),也称为扫描器,负责将源代码文本转换为一系列有意义的标记(tokens)。这些标记代表了...
编译器的设计与实现涉及多个阶段,其中“词法分析”(lexer)和“语法分析”(parser)是两个至关重要的步骤。这里我们将深入探讨利用JFlex和CUP这两个工具来完成这些任务。 **词法分析(Lexer)** 词法分析,也...
在 "Lexer-master" 中,你可以找到实现这一功能的源代码。它可能包含以下组件: 1. **词法规则定义**:这是Lexer的核心部分,定义了各种词法规则,每个规则对应一种词法单元。例如,定义一个规则匹配所有的数字字符...
在这个项目中,Parser.cpp 文件可能是实现解析逻辑的地方,它可能使用了LR、LL或递归下降等解析策略。把AST构造放到Parser内部使得一次扫描就能完成所有标记的处理,提高了效率。 Utils.cpp 和 Utils.h 可能包含了...
在解决方案属性中,需要配置VC++目录里的设置。包含目录、引用目录和库目录等。 * 包含目录:将*\Parser Generator 2\Cpp\Include添加到包含目录中。 * 引用目录:将*\Parser Generator 2\Cpp\Lib\mvsc32添加到引用...
enju parser enju parser
在"sql-parser-master.zip"这个压缩包中,我们很可能是得到了一个名为"Parser_SQL parser"的项目源码,它是一个SQL解析器的模拟实现。这个解析器可能用于分析、验证和转化SQL查询,以便于执行。 SQL解析器的工作...
要使用 JavaParser,你需要在项目中引入 `javaparser-core-3.6.16.jar`,然后可以创建 `JavaParser` 实例来解析 Java 文件。例如,以下代码演示了如何读取并打印一个 Java 类的 AST: ```java import ...
在IT行业中,XML(eXtensible Markup Language)是一种用于存储和传输数据的标准化格式,尤其在Web应用程序和数据交换中广泛应用。DOMParser是JavaScript中处理XML文档的主要工具,它允许我们将XML数据转换为DOM...
在 Eclipse 中,可以在“运行”-“运行配置”-“自变量”-“vm 参数”中添加“--Xmx1024m”以设置最大内存大小为 1024MB。其次,需要确保 Tokenize 选项被选中,并且文件格式为 utf-8,以便正确地分词。 二、命令行...
在这个项目中,`sql-lexer-parser`专注于SELECT语句的解析,这包括词法分析(lexer)和语法分析(parser)两个步骤。 2. **词法分析(Lexer)**: 词法分析是将输入的SQL字符串分解成一系列有意义的符号(tokens)...
Parser_Generator是一个在Windows操作系统环境下使用的工具,主要用于生成解析器(Parser)和生成器(Generator)。解析器是计算机科学中的一个重要组件,它处理输入源代码,将其转化为抽象语法树(AST),这是理解...
本篇文章将深入探讨如何在Node.js项目中结合`service-rule-parser`来构建规则判断引擎。 首先,`service-rule-parser`的核心功能是对JSON格式的规则进行解析和执行。这种规则通常包含了一系列条件(如变量比较、...
- **运行时调试**:在执行过程中查看lexer和parser的状态。 **优化模式**:提高lexer和parser的性能。 #### 5. 多个语法和词法分析器 - **多个 lexer 和 parser**:同时处理多种语言或文法。 #### 6. 使用 ...
在使用JavaParser时,经常需要解决代码中的符号和引用。教程中可能会讲到如何设置Java符号求解器,如何获取引用的类型,解决绝对名称的类型,以及在上下文中解决类型和方法调用。 9. 使用组合类型求解器和内存类型...
These tools comprise a lexer generator and a LALR(1) parser generator, written entirely in C# and generating C#.
- Token类型文件(如`PTokenTypes.java`)包含了Lexer中定义的Token类型,供Parser引用。 5. **执行流程** - 编写一个主程序(如`Main`类),创建Lexer和Parser对象,然后调用Parser的起始规则方法进行解析。 - ...
Parser中文API以及示例 Parser中文API是用于解析HTML网页的Java库,提供了一个强大且灵活的HTML解析引擎。下面是Parser中文API的详细介绍: Parser类 Parser类是Parser中文API的核心类,提供了多种构造函数用于...
C# SQLParser是一个用于解析和操作SQL语句的库,主要功能是帮助开发者在C#环境中分析SQL查询,特别是为了动态地添加`WHERE`和`ORDER BY`子句。这个库对于那些需要处理用户输入的SQL片段或者需要自定义SQL构建逻辑的...