如何使用分词器构建解析器?
How do I build a parser out of tokenizers?
我正在使用 jparsec 来解析如下字符串:
[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]"));
我正在使用 jparsec 来解析如下字符串:
[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]"));