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 |