我将编写一个简单的词法分析器,该词法可以识别没有数字和数字且忽略空格的单词。
我使用jparsec v3.0编写了以下代码:
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);
但是以下测试失败,但
org.jparsec.error.ParserException: line 1, column 7: EOF expected, 1 encountered
例外。而是使用字符串“ abc cd 123”来成功解析。final List<Token> got = lexer.parse("abc cd123");
final List<Token> expected = Arrays.asList(
new Token(0, 3, Tokens.fragment("abc", "WORD")),
new Token(4, 2, Tokens.fragment("cd", "WORD")),
new Token(6, 3, Tokens.fragment("123", "NUM")));
assertEquals(expected, got);
您认为出了什么问题?
最佳答案
以下测试通过:
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")));
}
}
您的令牌只能是
ALPHA
字符,也只能是DIGITS
,因此不能解析abc cd123
是正常的。文档说“分隔符在每次出现之前或之后都被忽略”这一事实应在某种意义上解释,即在解析的
Token
列表之前或之后出现的分隔符将被忽略。但是分隔符不会被忽略以分隔标记,除非在运算符的情况下(有关更多信息,请参见Terminals
类)。