From d7105cf3964b760196f431fdd3dddce00be27b34 Mon Sep 17 00:00:00 2001 From: Arpad Ryszka Date: Fri, 29 Dec 2017 21:23:45 +0100 Subject: [PATCH] fix single char class printing --- format_test.go | 166 ++++++++++++++++++++++++++++++++++--------------- notes.txt | 2 + sequence.go | 6 ++ 3 files changed, 125 insertions(+), 49 deletions(-) diff --git a/format_test.go b/format_test.go index 2ac06a5..1733a63 100644 --- a/format_test.go +++ b/format_test.go @@ -1,18 +1,56 @@ package treerack import ( + "bytes" "fmt" "testing" ) -func TestCharFormat(t *testing.T) { - type testItem struct { - title string - definition string - output string +type formatDefinitionTestItem struct { + title string + definition 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", definition: "[]", output: "[]", @@ -56,27 +94,7 @@ func TestCharFormat(t *testing.T) { title: "range and char mixed", definition: "[a-z_\\-A-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) { @@ -103,45 +121,81 @@ func TestSequenceFormat(t *testing.T) { syntax: `def = "abc" [a-z]`, output: `"abc" [a-z]`, }, { - title: "quantifiers, 0-or-more", + title: "quantifiers, 0-or-more, single char", 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", - syntax: `def = "a"+`, - output: `"a"+`, + syntax: `def = "abc"+`, + output: `"abc"+`, + }, { + title: "quantifiers, 0-or-one, single char", + syntax: `def = "a"?`, + output: `[a]?`, }, { title: "quantifiers, 0-or-one", - syntax: `def = "a"?`, - output: `"a"?`, + syntax: `def = "abc"?`, + output: `"abc"?`, + }, { + title: "quantifiers, exact number, single char", + syntax: `def = "a"{3}`, + output: `[a]{3}`, }, { title: "quantifiers, exact number", - syntax: `def = "a"{3}`, - output: `"a"{3}`, + syntax: `def = "abc"{3}`, + output: `"abc"{3}`, + }, { + title: "quantifiers, max, single char", + syntax: `def = "a"{0, 3}`, + output: `[a]{,3}`, }, { title: "quantifiers, max", - syntax: `def = "a"{0, 3}`, - output: `"a"{,3}`, + syntax: `def = "abc"{0, 3}`, + output: `"abc"{,3}`, + }, { + title: "quantifiers, min, single char", + syntax: `def = "a"{3,}`, + output: `[a]{3,}`, }, { title: "quantifiers, min", - syntax: `def = "a"{3,}`, - output: `"a"{3,}`, + syntax: `def = "abc"{3,}`, + output: `"abc"{3,}`, + }, { + title: "quantifiers, range, single char", + syntax: `def = "a"{3, 9}`, + output: `[a]{3,9}`, }, { title: "quantifiers, range", - syntax: `def = "a"{3, 9}`, - output: `"a"{3,9}`, + syntax: `def = "abc"{3, 9}`, + output: `"abc"{3,9}`, }, { title: "symbols", syntax: `a = "a"; b = "b"; c = "c"; def = a b c`, output: "a b c", }, { - title: "choice in sequence", + title: "choice in sequence, single char", 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", - syntax: `def = ("a" "b"){3}`, - output: `("a" "b"){3}`, + syntax: `def = ("abc" "def"){3}`, + output: `("abc" "def"){3}`, }} { t.Run(test.title, func(t *testing.T) { s, err := openSyntaxString(test.syntax) @@ -166,13 +220,21 @@ func TestChoiceFormat(t *testing.T) { } for _, test := range []testItem{{ - title: "choice of char sequences", + title: "choice of char sequences, single char", 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", - syntax: `def = "a" "b" | "c" "d" | "e" "f"`, - output: `"a" "b" | "c" "d" | "e" "f"`, + syntax: `def = "abc" "def" | "ghi" "jkl" | "mno" "pqr"`, + output: `"abc" "def" | "ghi" "jkl" | "mno" "pqr"`, }, { title: "choice of symbol", 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) { +} diff --git a/notes.txt b/notes.txt index bb50ad2..7836bb0 100644 --- a/notes.txt +++ b/notes.txt @@ -28,6 +28,8 @@ streaming verify choice and sequence preference formatter pretty +notes in formatting +format: test back and forth equivalence of char classes [problems] can the root be an alias? check the commit mechanism diff --git a/sequence.go b/sequence.go index b1358f3..e4605ec 100644 --- a/sequence.go +++ b/sequence.go @@ -202,6 +202,12 @@ func (d *sequenceDefinition) isCharSequence(r *registry) bool { func (d *sequenceDefinition) format(r *registry, f formatFlags) string { 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 for i := range d.originalItems { itemDef, _ := r.definition(d.originalItems[i].Name)