3

我正在使用 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

似乎正在发生的事情是解析器试图匹配 myCommandSubstitution并且未能找到关闭的']'. 这会导致解析器回退并尝试备用。由于它无法再匹配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;
4

1 回答 1

5

听起来整体问题是 Sprache 正在失败,尝试替代方案,然后再次失败,而它应该在第一次失败后放弃。

您正在使用扩展方法定义Things解析器。Parse.Many解析器的问题Parse.Many在于,无论其内部解析器是成功还是失败,它总是会成功。如果内部解析器失败,Parse.Many则简单地假设没有更多需要消耗的输入。

这似乎是这里发生的事情。首先,Parse.Many消耗片段"sum 10 "。然后它尝试解析更多输入,但失败了。由于它无法解析更多输入,因此它假定没有更多输入需要消耗。但是随后出现错误,因为该片段[multiply 5 4尚未被消耗。

要解决此问题,请使用Parse.XMany而不是Parse.Many. 如果内部解析器在消耗至少一个字符后Parse.XMany失败,则将立即放弃并报告失败。Parse.XMany

于 2016-08-18T02:27:21.273 回答