Java 为什么这个简单的jparsec lexer失败了?
我将编写一个简单的lexer,它可以识别没有数字和数字的单词,而忽略空格 我使用jparsec v3.0编写了以下代码:Java 为什么这个简单的jparsec lexer失败了?,java,parsing,tokenize,lexer,jparsec,Java,Parsing,Tokenize,Lexer,Jparsec,我将编写一个简单的lexer,它可以识别没有数字和数字的单词,而忽略空格 我使用jparsec v3.0编写了以下代码: final Parser words=Patterns.isChar(CharPredicates.IS_ALPHA).many1().toScanner(“word”).source(); 最终解析器nums=Patterns.isChar(CharPredicates.IS_DIGIT).many1().toScanner(“num”).source(); 最终解析器标记
final Parser words=Patterns.isChar(CharPredicates.IS_ALPHA).many1().toScanner(“word”).source();
最终解析器nums=Patterns.isChar(CharPredicates.IS_DIGIT).many1().toScanner(“num”).source();
最终解析器标记器=解析器。或(
words.map(it->Tokens.fragment(it,“WORD”)),
map(it->Tokens.fragment(it,“NUM”));
最终解析器lexer=tokenizer.lexer(Scanners.WHITESPACES);
但以下测试失败,出现异常org.jparsec.error.ParserException:第1行第7列:预期EOF,遇到1个
。相反,使用字符串“abc cd 123”解析是成功的
final List get=lexer.parse(“abc cd123”);
预期最终列表=Arrays.asList(
新令牌(0,3,令牌.fragment(“abc”,“WORD”),
新令牌(4,2,令牌.片段(“cd”,“WORD”),
新标记(6,3,Tokens.fragment(“123”,“NUM”));
assertEquals(预期、获得);
您认为有什么问题?以下测试通过:
public class SOTest {
final Parser<String> words = Patterns.isChar(CharPredicates.IS_ALPHA).many1().toScanner("word").source();
final Parser<String> nums = Patterns.isChar(CharPredicates.IS_DIGIT).many1().toScanner("num").source();
final Parser<Tokens.Fragment> tokenizer = Parsers.or(
words.map(it -> Tokens.fragment(it, "WORD")),
nums.map(it -> Tokens.fragment(it, "NUM")));
final Parser<List<Token>> lexer = tokenizer.lexer(Scanners.WHITESPACES);
@Test public void test(){
final List<Token> got = lexer.parse("abc cd 123");
Asserts.assertArrayEquals(got.toArray(new Token[0]),
new Token(0, 3, Tokens.fragment("abc", "WORD")),
new Token(4, 2, Tokens.fragment("cd", "WORD")),
new Token(7, 3, Tokens.fragment("123", "NUM")));
}
}
公共类SOTest{
最终解析器words=Patterns.isChar(CharPredicates.IS_ALPHA).many1().toScanner(“word”).source();
最终解析器nums=Patterns.isChar(CharPredicates.IS_DIGIT).many1().toScanner(“num”).source();
最终解析器标记器=解析器。或(
words.map(it->Tokens.fragment(it,“WORD”)),
map(it->Tokens.fragment(it,“NUM”));
最终解析器lexer=tokenizer.lexer(Scanners.WHITESPACES);
@测试公共无效测试(){
最终列表get=lexer.parse(“abc cd 123”);
Asserts.assertArrayEquals(got.toArray(新令牌[0]),
新令牌(0,3,令牌.fragment(“abc”,“WORD”),
新令牌(4,2,令牌.片段(“cd”,“WORD”),
新标记(7,3,Tokens.fragment(“123”,“NUM”));
}
}
您的令牌要么只是ALPHA
字符,要么只是数字
,因此无法解析abc cd123
是正常的
文档中说“在每次出现之前或之后忽略分隔符”这一事实应该解释为:在解析的
标记
列表之前或之后出现的分隔符被忽略。但是分隔符不会被忽略以分隔令牌,除非操作员(有关更多信息,请参见终端类)的情况除外。只需将分隔符设置为可选,即可解决此问题:
tokenizer.lexer(Scanners.WHITESPACES.optional(null))
既然您是基于空格进行词法分析,那么与您的令牌列表等价的不是“abc cd 123”
?根据文档,Parser.lexer(…)
应该反复运行解析器(tokenizer
),忽略delimeter(空格
)识别的模式每次发生前后。不清楚分隔符是否是可选的,因此我希望生成的lexer匹配“abc”,然后忽略空格,然后匹配“cd”,最后匹配“123”。感谢您的澄清。所以我误解了Parser.lexer方法,它不应该以这种方式使用。但最后,如何实现一个lexer,它接受“abccd123”和“abccd123”,生成相同的令牌序列(除了偏移量)?