diff --git a/tcl.go b/tcl.go index 47d7747..4bddee3 100644 --- a/tcl.go +++ b/tcl.go @@ -8,15 +8,15 @@ import ( . "github.com/oec/goparsify" ) -// Tcl parser, using combinators -// Based on the grammer in: -// https://wiki.tcl-lang.org/page/BNF+for+Tcl +// Tcl tokenizer parser, using combinators var ( - word Parser - words Parser - command Parser - script Parser + word Parser + words Parser + subcommand Parser + command Parser + ltm Parser + script Parser ) var ( @@ -25,14 +25,19 @@ var ( wordSub = NewParser("[*]word", Seq("[*]", &word)).Map(resultchild(1)) wordQtd = NewParser(`"word"`, StringLit(`"`)).Map(token) wordSmp = NewParser("simple", NotChars("{} \t\r\n")).Map(token) - group = NewParser("{group}", Seq("{", Maybe(Chars("\r\n")), Some(Any(&command, &words)), "}")).Map(func(r *Result) { collectchildren(&r.Child[2]); r.Result = r.Child[2].Result }) + group = NewParser("{group}", Seq("{", Maybe(Chars("\r\n")), Some(Any(&subcommand, &words)), "}")).Map(func(r *Result) { + collectchildren(&r.Child[2]) + r.Result = r.Child[2].Result + }) ) func init() { word = NewParser("word", Any(&wordQtd, &group, &wordSmp, &wordSub, &wordExp)) words = NewParser("words", Many(&word)).Map(collectchildren) - command = NewParser("command", Seq(&words, Any(";", Chars("\r\n")))).Map(resultchild(0)) - script = NewParser("script", Many(Any(&comment, &command))).Map(collectchildren) + subcommand = NewParser("subcommand", Seq(&words, Any(";", Chars("\r\n")))).Map(resultchild(0)) + command = NewParser("command", subcommand).Map(resultchild(0)) + script = NewParser("script", Many(Any(&comment, <m, &command))).Map(collectchildren) + ltm = NewParser("ltm", Seq("ltm", subcommand)).Map(resultchild(1)) } func simpleWhitespace(s *State) { @@ -75,18 +80,13 @@ func token(r *Result) { } func collectchildren(r *Result) { - data := []string{} + data := []interface{}{} for _, ch := range r.Child { switch v := ch.Result.(type) { - case string: + case string, []string, []interface{}: data = append(data, v) - case []string: - data = append(data, v...) - default: - // log.Println("oops:", r) } } - // log.Println("data: ", data) r.Result = data }