File: sexp.go

package info (click to toggle)
golang-github-twstrike-otr3 0.0~git20161015.0.744856d-3.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 1,080 kB
  • sloc: ansic: 127; makefile: 76
file content (107 lines) | stat: -rw-r--r-- 1,924 bytes parent folder | download | duplicates (3)
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
package sexp

import (
	"bufio"
	"io"
)

// Value is an S-Expression value
type Value interface {
	First() Value
	Second() Value
	Value() interface{}
	String() string
}

func peek(r *bufio.Reader) (c byte, e error) {
	c, e = r.ReadByte()
	if e != io.EOF {
		r.UnreadByte()
	}
	return
}

// Read will read an S-Expression from the given reader
func Read(r *bufio.Reader) Value {
	res, _ := ReadValue(r)
	return res
}

// ReadWhitespace will read from the reader until no whitespace is encountered
func ReadWhitespace(r *bufio.Reader) {
	c, e := peek(r)
	for e != io.EOF && isWhitespace(c) {
		r.ReadByte()
		c, e = peek(r)
	}
}

// ReadValue will read and return an S-Expression value from the reader
func ReadValue(r *bufio.Reader) (Value, bool) {
	ReadWhitespace(r)
	c, err := peek(r)
	if err != nil {
		return nil, true
	}
	switch c {
	case '(':
		return ReadList(r), false
	case ')':
		return nil, true
	case '"':
		return ReadString(r), false
	case '#':
		return ReadBigNum(r), false
	default:
		return ReadSymbol(r), false
	}
}

func isWhitespace(c byte) bool {
	switch c {
	case ' ', '\t', '\n', '\r':
		return true
	default:
		return false
	}
}

func isNotSymbolCharacter(c byte) bool {
	if isWhitespace(c) {
		return true
	}
	switch c {
	case '(', ')':
		return true
	default:
		return false
	}
}

func expect(r *bufio.Reader, c byte) bool {
	ReadWhitespace(r)
	res, err := r.ReadByte()
	if res != c {
		r.UnreadByte()
	}

	return res == c && err != io.EOF
}

func untilFixed(b byte) func(byte) bool {
	return func(until byte) bool {
		return until == b
	}
}

// ReadDataUntil will read and collect bytes from the reader until it encounters EOF or the given function returns true.
func ReadDataUntil(r *bufio.Reader, until func(byte) bool) []byte {
	result := make([]byte, 0, 10)
	c, err := peek(r)
	for err != io.EOF && !until(c) {
		r.ReadByte()
		result = append(result, c)
		c, err = peek(r)
	}
	return result
}