2016-06-12 43 views
2

我正在使用Sprache構建一個簡單的命令式語法。我試圖找出是否有一種方法可以在缺少關閉字符(例如,),})時獲得更好的錯誤報告。如何改進Sprache解析器錯誤消息與丟失的左大括號?

如果缺少結尾字符,我的語法會正確報告錯誤。但是,消息傳遞導致難以理解真正的問題。考慮下面的字符串被解析:

sum 10 [multiply 5 4

SPRACHE報告以下錯誤:

Sprache.ParseException : Parsing failure: unexpected '['; expected newline or end of input (Line 1, Column 8); recently consumed: sum 10

這似乎是發生的是,解析器嘗試匹配我的CommandSubstitution並不能找到一個關閉']'。這會導致解析器回退並嘗試備用。由於該命令不能再匹配Things,因此它會嘗試匹配CommandTerminator。因爲它無法匹配'[',因此它會報告抱怨預期的newlineend of input的錯誤,而不是說「嘿,夥計,您的支架不匹配!」

是否有任何解決方法或建議如何改進語法以使報告更好地使用像Sprache這樣的解析庫?

public static readonly Parser<Word> Word = Parse.Char(IsWordChar, "word character").AtLeastOnce().Text() 
               .Select(str => new Word(str)); 

public static readonly Parser<CommandSubstitution> CommandSubstitution = from open in Parse.Char('[').Once() 
                      from body in Parse.Ref(() => Things) 
                      from close in Parse.Char(']').Once() 
                      select new CommandSubstitution(body.ToList()); 


public static readonly Parser<Thing> Thing = CommandSubstitution.Or<Thing>(Word); 

public static readonly Parser<IEnumerable<Thing>> Things = (from ignoreBefore in WordSeparator.Optional() 
                  from thing in Thing 
                  from ignoreAfter in WordSeparator.Optional() 
                  select thing).Many(); 

public static readonly Parser<IEnumerable<Thing>> Command = from things in Things 
                  from terminator in CommandTerminator 
                  select things; 

回答

3

這聽起來像整體的問題是,SPRACHE失敗,試圖替代品,並再次失敗,當它應該乾脆放棄了第一次失敗,而不是了。

您正在使用Parse.Many擴展方法定義Things解析器。關於Parse.Many解析器的事情是,無論內部解析器是成功還是失敗,它都會成功。如果內部解析器失敗,Parse.Many只是假設沒有更多的輸入需要使用。

這似乎是在這裏發生的事情。首先,Parse.Many消耗片段"sum 10 "。然後它嘗試解析更多輸入,但失敗。由於它沒有解析任何更多的輸入,它假定沒有更多的輸入需要消耗。但是,然後錯誤的結果,因爲片段[multiply 5 4尚未消耗。

要解決此問題,請使用Parse.XMany而不是Parse.Many。如果Parse.XMany的內部解析器在消耗至少一個字符後失敗,則Parse.XMany將立即放棄並報告失敗。