如何使用分词器构建解析器?

How do I build a parser out of tokenizers?

我正在使用 来解析如下字符串:

[1,2, 3]
[ 3, 4]
[3   ,4,56, 7 ]
[]

我已经实现了一些 classes(继承自我的 Token 接口)来表示标记:

final class OpenListToken
final class CommaToken
final class CloseListToken
final class NumberToken // Has a public final property "value" that contains the int

我还为每个实现了分词器:

static final Parser<OpenListToken> openListTokenParser
static final Parser<CommaToken> commaTokenParser
static final Parser<CloseListToken> closeListTokenParser
static final Parser<NumberToken> numberTokenParser

这些都在角色级别上起作用。例如:

final NumberToken t = numberTokenParser.parse("123");
// t.value == 123

final OpenListToken u = openListToken.parse("[");
// Succeeds

现在我想将它们结合起来制作一个 ListExpression 的解析器,它是一个 class,代表一个数字列表。我试过类似的东西:

openListTokenParser
    .next(numberTokenParser.sepBy(commaTokenParser))
    .followedBy(closeListTokenParser)

这适用于 [1,2,3] 这样的字符串,但显然不适用于 [ 1, 2 ].

这样的字符串

是否有一个运算符接受一些解析器并在它们之间放置 whitespace*

或者是否可以让我的 ListExpression 解析器在我的 Token 接口实例而不是字符流上工作?

您可以使用 Terminals class 中的函数直接构建分词器。在您的情况下,这将如下所示:

首先定义我们的终端集合,例如运算符、关键字、词...

Terminals terminals = operators("[", "]", ",");

我们的代币然后由我们的终端或 IntegerLiteral 分词器进行代币化:

Parser<?> tokens = Parsers.or(terminals.tokenizer(), IntegerLiteral.TOKENIZER);

我们的最终结果来自整数语法分析器(由标记为 INTEGER 的标记构建),由我们的逗号标记分隔,在我们的括号标记之间。我们忽略所有标记之间的任何空格(这是 from:

的第二个参数
Parser<?> parser = IntegerLiteral.PARSER.sepBy(terminals.token(",")).between(terminals.token("["), terminals.token("]"))
  .from(tokens, Scanners.WHITESPACES.many().cast());

瞧瞧:

System.out.println(parser.parse( "[1,2,3]"));
System.out.println(parser.parse( "[ 1, 2 , 3 ]   "));
System.out.println(parser.parse( "   [1,2,3   ]"));
System.out.println(parser.parse( "[1, 2   ,    3]"));