File: parser.go

package info (click to toggle)
bombadillo 2.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 412 kB
  • sloc: makefile: 59
file content (112 lines) | stat: -rw-r--r-- 2,381 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package config

import (
	"fmt"
	"io"
	"strings"
)

//------------------------------------------------\\
// + + +             T Y P E S               + + + \\
//--------------------------------------------------\\

type Parser struct {
	s      *scanner
	row    int
	buffer struct {
		token Token
		size  int
	}
}

type Config struct {
	// Bookmarks gopher.Bookmarks
	Bookmarks struct {
		Titles, Links []string
	}
	Settings []KeyValue
	Certs    []KeyValue
}

type KeyValue struct {
	Key   string
	Value string
}

//------------------------------------------------\\
// + + +           R E C E I V E R S         + + + \\
//--------------------------------------------------\\

func (p *Parser) scan() (current Token) {
	if p.buffer.size != 0 {
		p.buffer.size = 0
		return p.buffer.token
	}

	current = p.s.scan()
	p.buffer.token = current
	return
}

func (p *Parser) parseKeyValue() (KeyValue, error) {
	kv := KeyValue{}
	t1 := p.scan()
	kv.Key = strings.TrimSpace(t1.val)

	if t := p.scan(); t.kind == TOK_VALUE {
		kv.Value = strings.TrimSpace(t.val)
	} else {
		return kv, fmt.Errorf("Got non-value expected VALUE on row %d", p.row)
	}

	if t := p.scan(); t.kind != TOK_NEWLINE {
		return kv, fmt.Errorf("Expected NEWLINE, got %q on row %d", t.kind, p.row)
	}

	return kv, nil
}

func (p *Parser) unscan() { p.buffer.size = 1 }

func (p *Parser) Parse() (Config, error) {
	p.row = 1
	section := ""
	c := Config{}

	for {
		if t := p.scan(); t.kind == TOK_NEWLINE {
			p.row++
		} else if t.kind == TOK_SECTION {
			section = strings.ToUpper(t.val)
		} else if t.kind == TOK_EOF {
			break
		} else if t.kind == TOK_KEY {
			p.unscan()
			keyval, err := p.parseKeyValue()
			if err != nil {
				return Config{}, err
			}
			switch section {
			case "BOOKMARKS":
				c.Bookmarks.Titles = append(c.Bookmarks.Titles, keyval.Value)
				c.Bookmarks.Links = append(c.Bookmarks.Links, keyval.Key)
			case "CERTS":
				c.Certs = append(c.Certs, keyval)
			case "SETTINGS":
				c.Settings = append(c.Settings, keyval)
			}
		} else if t.kind == TOK_ERROR {
			return Config{}, fmt.Errorf("Error on row %d: %s", p.row, t.val)
		}
	}

	return c, nil
}

//------------------------------------------------\\
// + + +          F U N C T I O N S          + + + \\
//--------------------------------------------------\\

func NewParser(r io.Reader) *Parser {
	return &Parser{s: NewScanner(r)}
}