Goでpegを使って構文解析をしてみた。
最初に peg コマンドをインストールするので、以下のコマンドを実行する。
make setupその後は以下のコマンドでビルドする。
make./configfile⟩ ./configifle
key = debug, value = true, type = bool
key = name, value = test_app, type = string
key = port, value = 1234, type = int| module configfile | |
| go 1.17 |
| package main | |
| type Parser Peg { | |
| ParserFunc | |
| } | |
| root <- pair+ | |
| pair <- space key space '=' space value space delimiter | |
| key <- <[a-zA-Z] [-_a-zA-Z0-9]*> { p.pushKey(text) } | |
| value <- atom | |
| atom <- bool / int / string | |
| string <- '"' <('\\' '"' / [^"])*> '"' { p.pushString(text) } | |
| int <- <'0' / [1-9] [0-9]*> { p.pushInt(text) } | |
| bool <- <'true' / 'false'> { p.pushBool(text) } | |
| space <- (' ' / ' ' / '\t')* | |
| delimiter <- '\n' / ';' |
| package main | |
| import ( | |
| "fmt" | |
| "os" | |
| "reflect" | |
| "strconv" | |
| ) | |
| type ParserFunc struct { | |
| data map[string]interface{} | |
| currentKey string | |
| } | |
| func (p *ParserFunc) pushKey(key string) { | |
| p.data[key] = nil | |
| p.currentKey = key | |
| } | |
| func (p *ParserFunc) pushString(text string) { | |
| p.data[p.currentKey] = text | |
| } | |
| func (p *ParserFunc) pushInt(text string) { | |
| n, _ := strconv.Atoi(text) | |
| p.data[p.currentKey] = n | |
| } | |
| func (p *ParserFunc) pushBool(text string) { | |
| b, _ := strconv.ParseBool(text) | |
| p.data[p.currentKey] = b | |
| } | |
| func main() { | |
| b, err := os.ReadFile("sample.conf") | |
| if err != nil { | |
| panic(err) | |
| } | |
| pf := ParserFunc{ | |
| data: make(map[string]interface{}), | |
| } | |
| p := &Parser{ | |
| Buffer: string(b), | |
| ParserFunc: pf, | |
| } | |
| if err := p.Init(); err != nil { | |
| panic(err) | |
| } | |
| if err := p.Parse(); err != nil { | |
| panic(err) | |
| } | |
| p.Execute() | |
| for k, v := range p.ParserFunc.data { | |
| fmt.Printf("key = %s, value = %v, type = %s\n", k, v, reflect.TypeOf(v)) | |
| } | |
| } |
| configfile: grammer.peg.go | |
| go build | |
| grammer.peg.go: grammer.peg | |
| peg grammer.peg | |
| .PHONY: setup | |
| setup: ## 開発時に使うツールをインストールする | |
| go install github.com/pointlander/peg@latest |
| name = "test_app" | |
| port = 1234 | |
| debug = true |