Skip to content

Instantly share code, notes, and snippets.

@jiro4989
Last active April 28, 2022 01:40
Show Gist options
  • Save jiro4989/668bd841e484eda7959bc027fb891da0 to your computer and use it in GitHub Desktop.
Save jiro4989/668bd841e484eda7959bc027fb891da0 to your computer and use it in GitHub Desktop.
Go言語でpegを使って構文解析をする
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

PEGのサンプル

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment