fix single char class printing

This commit is contained in:
Arpad Ryszka 2017-12-29 21:23:45 +01:00
parent 78d08abb78
commit d7105cf396
3 changed files with 125 additions and 49 deletions

View File

@ -1,18 +1,56 @@
package treerack package treerack
import ( import (
"bytes"
"fmt" "fmt"
"testing" "testing"
) )
func TestCharFormat(t *testing.T) { type formatDefinitionTestItem struct {
type testItem struct { title string
title string definition string
definition string output string
output string }
func testDefinitionFormatItem(t *testing.T, treerack *Syntax, f formatFlags, test formatDefinitionTestItem) func(t *testing.T) {
return func(t *testing.T) {
nodes, err := treerack.Parse(bytes.NewBufferString(fmt.Sprintf("def = %s", test.definition)))
if err != nil {
t.Fatal(err)
}
s := &Syntax{}
if err := define(s, nodes); err != nil {
t.Fatal(err)
}
def, ok := s.registry.definition("def")
if !ok {
t.Fatal("failed to register definition")
}
output := def.format(s.registry, f)
if output != test.output {
t.Error("invalid definition format")
t.Log("got: ", output)
t.Log("expected:", test.output)
}
}
}
func testDefinitionFormat(t *testing.T, f formatFlags, tests []formatDefinitionTestItem) {
treerack, err := bootSyntax()
if err != nil {
t.Fatal(err)
} }
for _, test := range []testItem{{ for _, test := range tests {
t.Run(test.title, testDefinitionFormatItem(t, treerack, f, test))
}
}
func TestCharFormat(t *testing.T) {
testDefinitionFormat(t, formatNone, []formatDefinitionTestItem{{
title: "empty", title: "empty",
definition: "[]", definition: "[]",
output: "[]", output: "[]",
@ -56,27 +94,7 @@ func TestCharFormat(t *testing.T) {
title: "range and char mixed", title: "range and char mixed",
definition: "[a-z_\\-A-Z]", definition: "[a-z_\\-A-Z]",
output: "[_\\-a-zA-Z]", output: "[_\\-a-zA-Z]",
}} { }})
t.Run(test.title, func(t *testing.T) {
defString := fmt.Sprintf("def = %s", test.definition)
s, err := openSyntaxString(defString)
if err != nil {
t.Error(err)
return
}
def, ok := s.registry.definition(childName("def", 0))
if !ok {
t.Error("invalid syntax")
return
}
output := def.format(s.registry, formatNone)
if output != test.output {
t.Error("invalid output", output, test.output)
}
})
}
} }
func TestSequenceFormat(t *testing.T) { func TestSequenceFormat(t *testing.T) {
@ -103,45 +121,81 @@ func TestSequenceFormat(t *testing.T) {
syntax: `def = "abc" [a-z]`, syntax: `def = "abc" [a-z]`,
output: `"abc" [a-z]`, output: `"abc" [a-z]`,
}, { }, {
title: "quantifiers, 0-or-more", title: "quantifiers, 0-or-more, single char",
syntax: `def = "a"*`, syntax: `def = "a"*`,
output: `"a"*`, output: `[a]*`,
}, {
title: "quantifiers, 0-or-more",
syntax: `def = "abc"*`,
output: `"abc"*`,
}, {
title: "quantifiers, 1-or-more, single char",
syntax: `def = "a"+`,
output: `[a]+`,
}, { }, {
title: "quantifiers, 1-or-more", title: "quantifiers, 1-or-more",
syntax: `def = "a"+`, syntax: `def = "abc"+`,
output: `"a"+`, output: `"abc"+`,
}, {
title: "quantifiers, 0-or-one, single char",
syntax: `def = "a"?`,
output: `[a]?`,
}, { }, {
title: "quantifiers, 0-or-one", title: "quantifiers, 0-or-one",
syntax: `def = "a"?`, syntax: `def = "abc"?`,
output: `"a"?`, output: `"abc"?`,
}, {
title: "quantifiers, exact number, single char",
syntax: `def = "a"{3}`,
output: `[a]{3}`,
}, { }, {
title: "quantifiers, exact number", title: "quantifiers, exact number",
syntax: `def = "a"{3}`, syntax: `def = "abc"{3}`,
output: `"a"{3}`, output: `"abc"{3}`,
}, {
title: "quantifiers, max, single char",
syntax: `def = "a"{0, 3}`,
output: `[a]{,3}`,
}, { }, {
title: "quantifiers, max", title: "quantifiers, max",
syntax: `def = "a"{0, 3}`, syntax: `def = "abc"{0, 3}`,
output: `"a"{,3}`, output: `"abc"{,3}`,
}, {
title: "quantifiers, min, single char",
syntax: `def = "a"{3,}`,
output: `[a]{3,}`,
}, { }, {
title: "quantifiers, min", title: "quantifiers, min",
syntax: `def = "a"{3,}`, syntax: `def = "abc"{3,}`,
output: `"a"{3,}`, output: `"abc"{3,}`,
}, {
title: "quantifiers, range, single char",
syntax: `def = "a"{3, 9}`,
output: `[a]{3,9}`,
}, { }, {
title: "quantifiers, range", title: "quantifiers, range",
syntax: `def = "a"{3, 9}`, syntax: `def = "abc"{3, 9}`,
output: `"a"{3,9}`, output: `"abc"{3,9}`,
}, { }, {
title: "symbols", title: "symbols",
syntax: `a = "a"; b = "b"; c = "c"; def = a b c`, syntax: `a = "a"; b = "b"; c = "c"; def = a b c`,
output: "a b c", output: "a b c",
}, { }, {
title: "choice in sequence", title: "choice in sequence, single char",
syntax: `def = "a" ("b" | "c")`, syntax: `def = "a" ("b" | "c")`,
output: `"a" ("b" | "c")`, output: `[a] ([b] | [c])`,
}, {
title: "choice in sequence",
syntax: `def = "abc" ("def" | "ghi")`,
output: `"abc" ("def" | "ghi")`,
}, {
title: "grouped quantifier, single char",
syntax: `def = ("a" "b"){3}`,
output: `([a] [b]){3}`,
}, { }, {
title: "grouped quantifier", title: "grouped quantifier",
syntax: `def = ("a" "b"){3}`, syntax: `def = ("abc" "def"){3}`,
output: `("a" "b"){3}`, output: `("abc" "def"){3}`,
}} { }} {
t.Run(test.title, func(t *testing.T) { t.Run(test.title, func(t *testing.T) {
s, err := openSyntaxString(test.syntax) s, err := openSyntaxString(test.syntax)
@ -166,13 +220,21 @@ func TestChoiceFormat(t *testing.T) {
} }
for _, test := range []testItem{{ for _, test := range []testItem{{
title: "choice of char sequences", title: "choice of char sequences, single char",
syntax: `def = "a" | "b" | "c"`, syntax: `def = "a" | "b" | "c"`,
output: `"a" | "b" | "c"`, output: `[a] | [b] | [c]`,
}, {
title: "choice of char sequences",
syntax: `def = "abc" | "def" | "ghi"`,
output: `"abc" | "def" | "ghi"`,
}, {
title: "choice of inline sequences, single char",
syntax: `def = "a" "b" | "c" "d" | "e" "f"`,
output: `[a] [b] | [c] [d] | [e] [f]`,
}, { }, {
title: "choice of inline sequences", title: "choice of inline sequences",
syntax: `def = "a" "b" | "c" "d" | "e" "f"`, syntax: `def = "abc" "def" | "ghi" "jkl" | "mno" "pqr"`,
output: `"a" "b" | "c" "d" | "e" "f"`, output: `"abc" "def" | "ghi" "jkl" | "mno" "pqr"`,
}, { }, {
title: "choice of symbol", title: "choice of symbol",
syntax: `a = "a"; b = "b"; c = "c"; def = a | b | c`, syntax: `a = "a"; b = "b"; c = "c"; def = a | b | c`,
@ -192,3 +254,9 @@ func TestChoiceFormat(t *testing.T) {
}) })
} }
} }
func TestMultiLine(t *testing.T) {
}
func TestLineSplit(t *testing.T) {
}

View File

@ -28,6 +28,8 @@ streaming
verify choice and sequence preference verify choice and sequence preference
formatter formatter
pretty pretty
notes in formatting
format: test back and forth equivalence of char classes
[problems] [problems]
can the root be an alias? check the commit mechanism can the root be an alias? check the commit mechanism

View File

@ -202,6 +202,12 @@ func (d *sequenceDefinition) isCharSequence(r *registry) bool {
func (d *sequenceDefinition) format(r *registry, f formatFlags) string { func (d *sequenceDefinition) format(r *registry, f formatFlags) string {
if d.isCharSequence(r) { if d.isCharSequence(r) {
if len(d.originalItems) == 1 {
itemDef, _ := r.definition(d.originalItems[0].Name)
c, _ := itemDef.(*charParser)
return c.format(r, f)
}
var chars []rune var chars []rune
for i := range d.originalItems { for i := range d.originalItems {
itemDef, _ := r.definition(d.originalItems[i].Name) itemDef, _ := r.definition(d.originalItems[i].Name)