2017-01-08 12 views
1

数字を認識する単純なレクサーを書きます。数字はで、数字は空白を無視します。なぜこの単純なjparsecレクサーが失敗するのですか?

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

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

+0

は、あなたのトークンリストと同等には、 '「ABCのCD 123」'と思いませんか? – Aurora0001

+0

文書によると、 'Parser.lexer(...)'は、パーサー( 'tokenizer')を各文字列の前と後に区切り文字(' WHITESPACES')で認識されるパターンを繰り返し無視して実行する必要があります。区切り文字がオプションかどうかは分かりませんので、結果のレクサーが "abc"にマッチし、その後空白を無視して "cd"にマッチし、最後に "123"にマッチすると期待します。 – maurocchi

答えて

0

問題は区切り文字をオプションにするだけで解決されている:あなたは空白に基づく字句しているので、

tokenizer.lexer(Scanners.WHITESPACES.optional(null)) 
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"))); 
    }  
} 

あなたのトークンは、したがって、あなたがabc cd123を解析することはできません正常です、唯一ALPHA文字のみDIGITSのどちらかです。

ドキュメントはが解析Token秒のリスト前または後に現れる区切り文字が無視されるという意味で解釈されるべきである「とは、各出現の前か後に区切り文字は無視されている」と言う事実が。ただし、区切り文字は、演算子(詳細はTerminalsクラスを参照)の場合を除いて、トークンを分離するために無視されません。

+0

説明をありがとう。だから、私は 'Parser.lexer'メソッドを誤解してしまい、このように使うべきではありません。しかし、最後に、 "abc cd123"と "abc cd 123"を受け入れるレクサーを実装する方法(オフセットを除く)は同じシーケンスを生成する方法はありますか? – maurocchi

関連する問題