我正在使用 Sprache 构建一个简单的命令式语法。我正在尝试找出是否有一种方法可以在缺少结束字符(例如 ]、, })时获得更好的错误报告。
如果缺少结束字符,我的语法会正确报告错误。然而,消息传递导致难以理解真正的问题。给定以下要解析的字符串:
求和 10 [乘以 5 4
Sprache 报告以下错误:
Sprache.ParseException:解析失败:意外的“[”;预期的换行符或输入结尾(第 1 行,第 8 列);最近消费:总和 10
似乎正在发生的事情是,解析器试图匹配我的 CommandSubstitution
,但未能找到结束的 ']'
。这会导致解析器回退并尝试替代。由于它无法再为命令匹配任何 Things
,因此它会尝试匹配 CommandTerminator
。由于无法匹配 '['
,它会报告错误,提示预期的 newline
或 end 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;
最佳答案
听起来总体问题是 Sprache 正在失败,尝试替代方案,然后再次失败,而它应该在第一次失败后放弃。
您正在使用 Parse.Many
扩展方法定义 Things
解析器。 Parse.Many
解析器的特点是它总是成功,无论其内部解析器是成功还是失败。如果内部解析器失败,Parse.Many
会简单地假设没有更多的输入需要处理。
这似乎就是这里发生的事情。首先,Parse.Many
使用片段 "sum 10 "
。然后它尝试解析更多输入,但失败了。由于它无法解析更多输入,因此它假定不再需要使用更多输入。但是随后会出现错误,因为片段 [multiply 5 4
尚未被使用。
要解决此问题,请使用 Parse.XMany
而不是 Parse.Many
。如果Parse.XMany
的内部解析器在消耗至少一个字符后 失败,则Parse.XMany
将立即放弃并报告失败。
关于c# - 如何改进缺少右大括号的 Sprache 解析器错误消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37778472/