One buffer fits all
This commit is contained in:
parent
75ff8bf4d5
commit
fc170098e9
|
@ -0,0 +1,50 @@
|
||||||
|
package buffer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Buffer struct {
|
||||||
|
input *bufio.Reader
|
||||||
|
ready chan rune
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewBytesBuffer(b []byte) *Buffer {
|
||||||
|
return NewReaderBuffer(bytes.NewReader(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReaderBuffer(rd io.Reader) *Buffer {
|
||||||
|
return New(bufio.NewReader(rd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(input *bufio.Reader) *Buffer {
|
||||||
|
b := &Buffer{
|
||||||
|
input: input,
|
||||||
|
ready: make(chan rune, 100),
|
||||||
|
}
|
||||||
|
go b.stream()
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Buffer) Next() rune {
|
||||||
|
if next, ok := <-b.ready; ok {
|
||||||
|
return next
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Buffer) stream() {
|
||||||
|
for {
|
||||||
|
if r, _, err := b.input.ReadRune(); err != nil {
|
||||||
|
close(b.ready)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
b.ready <- r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
package buffer
|
|
||||||
|
|
||||||
type (
|
|
||||||
Bufferer interface {
|
|
||||||
Next() rune
|
|
||||||
}
|
|
||||||
)
|
|
|
@ -1,34 +0,0 @@
|
||||||
package buffer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
BytesBuffer struct {
|
|
||||||
input []byte
|
|
||||||
size uint64
|
|
||||||
pos uint64
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewBytesBuffer(input []byte) *BytesBuffer {
|
|
||||||
return &BytesBuffer{
|
|
||||||
input: input,
|
|
||||||
size: uint64(len(input)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BytesBuffer) Next() rune {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for b.pos < b.size {
|
|
||||||
buf.WriteByte(b.input[b.pos])
|
|
||||||
b.pos++
|
|
||||||
if ok := utf8.FullRune(buf.Bytes()); ok {
|
|
||||||
r, _ := utf8.DecodeRune(buf.Bytes())
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package buffer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
StreamBuffer struct {
|
|
||||||
input io.Reader
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewStreamBuffer(input io.Reader) *StreamBuffer {
|
|
||||||
return &StreamBuffer{
|
|
||||||
input: input,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *StreamBuffer) Next() rune {
|
|
||||||
var (
|
|
||||||
buf bytes.Buffer
|
|
||||||
)
|
|
||||||
for {
|
|
||||||
rbuf := make([]byte, 1)
|
|
||||||
if n, err := b.input.Read(rbuf); n != 1 || err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
buf.Write(rbuf)
|
|
||||||
if ok := utf8.FullRune(buf.Bytes()); ok {
|
|
||||||
r, _ := utf8.DecodeRune(buf.Bytes())
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
type (
|
type (
|
||||||
// Holds the state of the scanner
|
// Holds the state of the scanner
|
||||||
Lexer struct {
|
Lexer struct {
|
||||||
input buffer.Bufferer
|
input *buffer.Buffer
|
||||||
stack []rune // Lexer stack
|
stack []rune // Lexer stack
|
||||||
pos int // Current stack position
|
pos int // Current stack position
|
||||||
lineNum int // Line number
|
lineNum int // Line number
|
||||||
|
@ -59,10 +59,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Creates a new scanner for the input buffer
|
// Creates a new scanner for the input buffer
|
||||||
func New(input buffer.Bufferer) *Lexer {
|
func New(input *buffer.Buffer) *Lexer {
|
||||||
return &Lexer{
|
return &Lexer{
|
||||||
input: input,
|
input: input,
|
||||||
items: make(chan Item),
|
items: make(chan Item, 100),
|
||||||
lineNum: 1,
|
lineNum: 1,
|
||||||
colNum: 0,
|
colNum: 0,
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,8 +152,8 @@ func compare(t *testing.T, reality, expectations []Item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func lex(json string) []Item {
|
func lex(jstr string) []Item {
|
||||||
buf := buffer.NewBytesBuffer([]byte(json))
|
buf := buffer.NewBytesBuffer([]byte(jstr))
|
||||||
lex := New(buf)
|
lex := New(buf)
|
||||||
go lex.Run()
|
go lex.Run()
|
||||||
|
|
||||||
|
|
15
main.go
15
main.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/davecheney/profile"
|
||||||
"github.com/localhots/punk/buffer"
|
"github.com/localhots/punk/buffer"
|
||||||
"github.com/localhots/punk/parser"
|
"github.com/localhots/punk/parser"
|
||||||
)
|
)
|
||||||
|
@ -14,8 +15,11 @@ func main() {
|
||||||
var (
|
var (
|
||||||
sel string
|
sel string
|
||||||
verbose bool
|
verbose bool
|
||||||
|
prof string
|
||||||
)
|
)
|
||||||
|
|
||||||
flag.StringVar(&sel, "s", "", "Selector")
|
flag.StringVar(&sel, "s", "", "Selector")
|
||||||
|
flag.StringVar(&prof, "prof", "", "Performance profiling output")
|
||||||
flag.BoolVar(&verbose, "v", false, "Verbose parsing")
|
flag.BoolVar(&verbose, "v", false, "Verbose parsing")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
@ -24,15 +28,24 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if prof != "" {
|
||||||
|
defer profile.Start(&profile.Config{
|
||||||
|
CPUProfile: true,
|
||||||
|
ProfilePath: prof,
|
||||||
|
}).Stop()
|
||||||
|
}
|
||||||
|
|
||||||
sels := strings.Split(sel, " ")
|
sels := strings.Split(sel, " ")
|
||||||
if len(sel) == 0 {
|
if len(sel) == 0 {
|
||||||
sels = []string{}
|
sels = []string{}
|
||||||
}
|
}
|
||||||
buf := buffer.NewStreamBuffer(os.Stdin)
|
|
||||||
|
buf := buffer.NewReaderBuffer(os.Stdin)
|
||||||
pars := parser.New(buf, sels)
|
pars := parser.New(buf, sels)
|
||||||
if verbose {
|
if verbose {
|
||||||
pars.Debug()
|
pars.Debug()
|
||||||
}
|
}
|
||||||
|
|
||||||
res := pars.ParseStream()
|
res := pars.ParseStream()
|
||||||
for {
|
for {
|
||||||
if m, ok := <-res; ok {
|
if m, ok := <-res; ok {
|
||||||
|
|
|
@ -25,7 +25,7 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Creates a new parser
|
// Creates a new parser
|
||||||
func New(buf buffer.Bufferer, sels []string) *Parser {
|
func New(buf *buffer.Buffer, sels []string) *Parser {
|
||||||
return &Parser{
|
return &Parser{
|
||||||
lex: lexer.New(buf),
|
lex: lexer.New(buf),
|
||||||
ctx: &context{
|
ctx: &context{
|
||||||
|
|
Loading…
Reference in New Issue