tcl/tcl.go

98 lines
2.3 KiB
Go
Raw Permalink Normal View History

2019-06-16 20:45:30 +02:00
package tcl
import (
"log"
"os"
2021-05-08 11:43:02 +02:00
. "kesim.org/goparsify"
2019-06-16 20:45:30 +02:00
)
2019-06-17 12:06:19 +02:00
// Tcl tokenizer parser, using combinators
2019-06-16 20:45:30 +02:00
var (
2019-06-17 12:06:19 +02:00
word Parser
words Parser
subcommand Parser
command Parser
ltm Parser
script Parser
2019-06-16 20:45:30 +02:00
)
var (
comment = NewParser("comment", Merge(Seq("#", NotChars("\r\n"), Chars("\r\n")))).Map(drop)
2019-06-17 06:27:17 +02:00
wordExp = NewParser("{*}word", Seq("{*}", &word)).Map(resultchild(1))
wordSub = NewParser("[*]word", Seq("[*]", &word)).Map(resultchild(1))
wordQtd = NewParser(`"word"`, StringLit(`"`)).Map(token)
wordSmp = NewParser("simple", NotChars("{} \t\r\n")).Map(token)
2019-06-17 12:06:19 +02:00
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
})
2019-06-16 20:45:30 +02:00
)
func init() {
word = NewParser("word", Any(&wordQtd, &group, &wordSmp, &wordSub, &wordExp))
2019-06-17 06:27:17 +02:00
words = NewParser("words", Many(&word)).Map(collectchildren)
2019-06-17 12:06:19 +02:00
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, &ltm, &command))).Map(collectchildren)
ltm = NewParser("ltm", Seq("ltm", subcommand)).Map(resultchild(1))
2019-06-16 20:45:30 +02:00
}
func simpleWhitespace(s *State) {
for s.Pos < len(s.Input) {
switch s.Input[s.Pos] {
case '\t', '\v', '\f', ' ':
s.Pos++
default:
return
}
}
}
2019-06-16 20:45:30 +02:00
func Parse(input string) (data interface{}, e error) {
data, e = Run(&script, input, simpleWhitespace)
2019-06-16 20:45:30 +02:00
return
}
func ParseDebug(input string) (data interface{}, e error) {
EnableLogging(os.Stdout)
data, e = Run(&script, input, simpleWhitespace)
2019-06-16 20:45:30 +02:00
return
}
func found(typ string) func(*Result) {
return func(r *Result) {
2019-06-17 06:27:17 +02:00
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)
}
2019-06-16 20:45:30 +02:00
2019-06-17 06:27:17 +02:00
func collectchildren(r *Result) {
2019-06-17 12:06:19 +02:00
data := []interface{}{}
2019-06-17 06:27:17 +02:00
for _, ch := range r.Child {
switch v := ch.Result.(type) {
2019-06-17 12:06:19 +02:00
case string, []string, []interface{}:
2019-06-17 06:27:17 +02:00
data = append(data, v)
}
2019-06-16 20:45:30 +02:00
}
2019-06-17 06:27:17 +02:00
r.Result = data
2019-06-16 20:45:30 +02:00
}
2019-06-17 06:27:17 +02:00
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)
}
}