1

空白を無視して数字と数字のない単語を認識する単純なレクサーを作成します。

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);

あなたの意見では、何が間違っていますか?

4

2 に答える 2

1

次のテスト パス:

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

ドキュメンテーションに「出現するたびに区切り記号は無視される」と記載されているという事実は、解析されるsのリストのToken前後に表示される区切り記号は無視されるという意味で解釈する必要があります。ただし、トークンを区切るために区切り文字は無視されません。ただし、演​​算子の場合 (詳細については、Terminalsクラスを参照してください) を除きます。

于 2017-01-10T04:07:58.603 に答える
0

この問題は、区切り文字をオプションにすることで簡単に解決されました。

tokenizer.lexer(Scanners.WHITESPACES.optional(null))
于 2017-01-10T22:36:38.380 に答える