diff --git a/tcl.go b/tcl.go index 3eef16e..c4a4baa 100644 --- a/tcl.go +++ b/tcl.go @@ -13,25 +13,26 @@ import ( // https://wiki.tcl-lang.org/page/BNF+for+Tcl var ( - word Parser - commands Parser - script Parser + word Parser + words Parser + command Parser + script Parser ) var ( - comment = NewParser("comment", Merge(NoAutoWS(Seq("#", NotChars("\r\n"))))).Map(found("comment")) - wordExp = NewParser("{*}word", NoAutoWS(Seq("{*}", &word))).Map(found("wordExp")) - wordSub = NewParser("[*]word", NoAutoWS(Seq("[*]", &word))).Map(found("wordSub")) - wordBrc = NewParser("{word}", Seq("{", &word, "}")).Map(found("wordBrc")) - wordQtd = NewParser(`"word"`, StringLit(`"`)).Map(found("wordQtd")) - wordSmp = NewParser("simple", NotChars("{}[]*")).Map(found("simple")) - command = NewParser("command", Many(&word)).Map(found("command")).Map(found("command")) + comment = NewParser("comment", Merge(Seq("#", NotChars("\r\n")))).Map(drop) + wordExp = NewParser("{*}word", Seq("{*}", &word)).Map(resultchild(1)) + wordSub = NewParser("[*]word", Seq("[*]", &word)).Map(resultchild(1)) + wordBrc = NewParser("{command}", Seq("{", Many(&command), "}")).Map(func(r *Result) { collectchildren(&r.Child[1]); r.Result = r.Child[1].Result }) + wordQtd = NewParser(`"word"`, StringLit(`"`)).Map(token) + wordSmp = NewParser("simple", NotChars("{}[]* ;\t\r\n")).Map(token) ) func init() { - word = NewParser("word", Any(&wordSmp, &wordQtd, &wordBrc, &wordSub, &wordExp)).Map(found("word")) - commands = NewParser("commands", Any(&command, Maybe(Chars(";")))) - script = NewParser("script", Many(Any(&comment, &commands))) + word = NewParser("word", Any(&wordSmp, &wordQtd, &wordBrc, &wordSub, &wordExp)) + words = NewParser("words", Many(&word)).Map(collectchildren) + command = NewParser("command", Seq(&words, Maybe(";"))).Map(resultchild(0)) + script = NewParser("script", Many(Any(&comment, &command))).Map(collectchildren) } func Parse(input string) (data interface{}, e error) { @@ -47,11 +48,44 @@ func ParseDebug(input string) (data interface{}, e error) { func found(typ string) func(*Result) { return func(r *Result) { - log.Println("found a", typ) - spew.Dump(r) - + log.Printf("found a %s: %q (r.R: %v)\n", typ, r.Token, r.Result) + r.Result = r.Token } } + +func drop(r *Result) { + r.Token = "" + r.Result = nil +} + +func token(r *Result) { + r.Result = r.Token + // log.Println("token:", r.Token) +} + +func collectchildren(r *Result) { + data := []string{} + for _, ch := range r.Child { + switch v := ch.Result.(type) { + case string: + data = append(data, v) + case []string: + data = append(data, v...) + default: + // log.Println("oops:", r) + } + } + // log.Println("data: ", data) + r.Result = data +} + +func resultchild(c int) func(*Result) { + return func(r *Result) { + r.Result = r.Child[c].Result + // log.Printf("child[%d]: %v\n", c, r.Result) + } +} + func dump(r *Result) { spew.Dump(r) }