diff --git a/choice.go b/choice.go index 1e4d94d..f64fe99 100644 --- a/choice.go +++ b/choice.go @@ -230,7 +230,8 @@ func (p *choiceParser) parse(c *context) { c.failingParser = failingParser if c.failingParser == nil && p.commitType()&userDefined != 0 && - p.commitType()&Whitespace == 0 { + p.commitType()&Whitespace == 0 && + p.commitType()&FailPass == 0 { c.failingParser = p } } diff --git a/context.go b/context.go index 5a65898..8071e93 100644 --- a/context.go +++ b/context.go @@ -2,6 +2,7 @@ package treerack import ( "io" + "strings" "unicode" ) @@ -128,6 +129,11 @@ func findLine(tokens []rune, offset int) (line, column int) { func (c *context) parseError(p parser) error { definition := p.nodeName() + flagIndex := strings.Index(definition, ":") + if flagIndex > 0 { + definition = definition[:flagIndex] + } + if c.failingParser == nil { c.failOffset = c.consumed } diff --git a/define.go b/define.go index 6823358..e46cc16 100644 --- a/define.go +++ b/define.go @@ -20,6 +20,8 @@ func flagsToCommitType(n []*Node) CommitType { ct |= Whitespace case "nows": ct |= NoWhitespace + case "failpass": + ct |= FailPass case "root": ct |= Root } diff --git a/errors_test.go b/errors_test.go index c0febcc..0392ee0 100644 --- a/errors_test.go +++ b/errors_test.go @@ -305,9 +305,34 @@ func TestLongestFail(t *testing.T) { doc:root = (expression (statement-separator+ expression)*)? ` + const doc = `f(a b c)` + testParseError(t, syntax, []errorTestItem{{ - title: "choice", - doc: "f(a b c)", + title: "fail on longest failing parser", + doc: doc, + perr: ParseError{ + Offset: 4, + Line: 0, + Column: 4, + Definition: "function-application", + }, + }}) +} + +func TestFailPass(t *testing.T) { + const syntax = ` + space:ws = " "; + symbol:nows = [a-z]+; + list-separator:failpass = ","; + argument-list:failpass = (symbol (list-separator+ symbol)*); + function-application = symbol "(" argument-list? ")"; + ` + + const doc = `f(a b c)` + + testParseError(t, syntax, []errorTestItem{{ + title: "fail in outer definition", + doc: doc, perr: ParseError{ Offset: 4, Line: 0, diff --git a/sequence.go b/sequence.go index 2f95495..b9bcb65 100644 --- a/sequence.go +++ b/sequence.go @@ -314,7 +314,8 @@ func (p *sequenceParser) parse(c *context) { if currentCount < p.ranges[itemIndex][0] { if c.failingParser == nil && p.commitType()&userDefined != 0 && - p.commitType()&Whitespace == 0 { + p.commitType()&Whitespace == 0 && + p.commitType()&FailPass == 0 { c.failingParser = p }