Goでpegを使って構文解析をしてみた。
最初に peg コマンドをインストールするので、以下のコマンドを実行する。
make setupその後は以下のコマンドでビルドする。
make./configfile⟩ ./configifle
value = {0 31 }
value = {0 42 }
value = {1 0 hello world}| module configfile | |
| go 1.17 |
| package main | |
| type Parser Peg { | |
| ParserFunc | |
| } | |
| root <- (colors / text)* | |
| colors <- | |
| prefix color (delimiter color)* suffix | |
| prefix <- | |
| '\e' '[' | |
| color <- | |
| <([349] / '10') [0-7]> { p.pushColor(text) } | |
| text <- <[^\e]+> { p.pushText(text) } | |
| suffix <- 'm' | |
| delimiter <- ';' |
| package main | |
| import ( | |
| "fmt" | |
| "os" | |
| "strconv" | |
| ) | |
| type ParserFunc struct { | |
| data []Data | |
| currentKey string | |
| } | |
| type Data struct { | |
| Type DataType | |
| Color Color | |
| Text string | |
| } | |
| type DataType int | |
| type Color int | |
| const ( | |
| typeColor DataType = iota | |
| typeText | |
| colorForegroundBlack Color = 30 + iota | |
| colorForegroundRed | |
| colorForegroundGreen | |
| colorForegroundBrown | |
| colorForegroundBlue | |
| colorForegroundMagenta | |
| colorForegroundCyan | |
| colorForegroundWhite | |
| colorBackgroundBlack Color = 40 + iota | |
| colorBackgroundRed | |
| colorBackgroundGreen | |
| colorBackgroundBrown | |
| colorBackgroundBlue | |
| colorBackgroundMagenta | |
| colorBackgroundCyan | |
| colorBackgroundWhite | |
| // 90系、100系は省略 | |
| ) | |
| func (p *ParserFunc) pushColor(text string) { | |
| n, _ := strconv.Atoi(text) | |
| c := Color(n) | |
| d := Data{ | |
| Type: typeColor, | |
| Color: c, | |
| } | |
| p.data = append(p.data, d) | |
| } | |
| func (p *ParserFunc) pushText(text string) { | |
| d := Data{ | |
| Type: typeText, | |
| Text: text, | |
| } | |
| p.data = append(p.data, d) | |
| } | |
| func main() { | |
| b, err := os.ReadFile("sample.txt") | |
| if err != nil { | |
| panic(err) | |
| } | |
| pf := ParserFunc{ | |
| data: make([]Data, 0), | |
| } | |
| 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 _, v := range p.ParserFunc.data { | |
| fmt.Printf("value = %v\n", v) | |
| } | |
| } |
| configfile: *.go grammer.peg.go | |
| go build | |
| grammer.peg.go: grammer.peg | |
| peg grammer.peg | |
| .PHONY: setup | |
| setup: ## 開発時に使うツールをインストールする | |
| go install github.com/pointlander/peg@latest |
| [31;42mhello world |