add ParseString and refactor parse_test a bit
This commit is contained in:
parent
269d033fcb
commit
b307273223
@ -1,6 +1,10 @@
|
|||||||
|
// The parse package implements a syntax parser for the ginger syntax. It can
|
||||||
|
// read in any io.Reader and returns fully parsed Elem's from the types package
|
||||||
|
// that it finds.
|
||||||
package parse
|
package parse
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -60,6 +64,7 @@ type Parser struct {
|
|||||||
l *lex.Lexer
|
l *lex.Lexer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a NewParser, using the lex package as the tokenizer
|
||||||
func NewParser(r io.Reader) *Parser {
|
func NewParser(r io.Reader) *Parser {
|
||||||
p := Parser{
|
p := Parser{
|
||||||
l: lex.NewLexer(r),
|
l: lex.NewLexer(r),
|
||||||
@ -67,6 +72,9 @@ func NewParser(r io.Reader) *Parser {
|
|||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reads a full element, and any sub-elements (if the top-level element is a
|
||||||
|
// data-structure) into an Elem and returns it. Returns any errors, including
|
||||||
|
// io.EOF, if it runs into them instead
|
||||||
func (p *Parser) ReadElem() (types.Elem, error) {
|
func (p *Parser) ReadElem() (types.Elem, error) {
|
||||||
tok := p.l.Next()
|
tok := p.l.Next()
|
||||||
return p.parseToken(tok)
|
return p.parseToken(tok)
|
||||||
@ -139,3 +147,10 @@ func (p *Parser) readUntil(closer string) ([]types.Elem, error) {
|
|||||||
return series, nil
|
return series, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parses the first Elem it finds out of the given string and returns it
|
||||||
|
func ParseString(input string) (types.Elem, error) {
|
||||||
|
buf := bytes.NewBufferString(input)
|
||||||
|
p := NewParser(buf)
|
||||||
|
return p.ReadElem()
|
||||||
|
}
|
||||||
|
@ -9,19 +9,51 @@ import (
|
|||||||
"github.com/mediocregopher/ginger/types"
|
"github.com/mediocregopher/ginger/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseBareString(t *T) {
|
func TestParse(t *T) {
|
||||||
|
m := map[string]types.Elem{
|
||||||
|
"1": types.GoType{int(1)},
|
||||||
|
"-1": types.GoType{int(-1)},
|
||||||
|
"+1": types.GoType{int(1)},
|
||||||
|
|
||||||
|
"1.5": types.GoType{float32(1.5)},
|
||||||
|
"-1.5": types.GoType{float32(-1.5)},
|
||||||
|
"+1.5": types.GoType{float32(1.5)},
|
||||||
|
"1.5e1": types.GoType{float32(15)},
|
||||||
|
|
||||||
|
"foo": types.GoType{":foo"},
|
||||||
|
|
||||||
|
"()": seq.NewList(),
|
||||||
|
|
||||||
|
"(foo)": seq.NewList(
|
||||||
|
types.GoType{":foo"},
|
||||||
|
),
|
||||||
|
|
||||||
|
"(foo (bar))": seq.NewList(
|
||||||
|
types.GoType{":foo"},
|
||||||
|
seq.NewList(types.GoType{":bar"}),
|
||||||
|
),
|
||||||
|
|
||||||
|
"{}": seq.NewHashMap(),
|
||||||
|
|
||||||
|
"{foo bar}": seq.NewHashMap(
|
||||||
|
seq.KeyVal(types.GoType{":foo"}, types.GoType{":bar"}),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
for input, output := range m {
|
||||||
|
parsed, err := ParseString(input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !output.Equal(parsed) {
|
||||||
|
t.Fatalf("input: %q %#v != %#v", input, output, parsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseMulti(t *T) {
|
||||||
m := map[string][]types.Elem{
|
m := map[string][]types.Elem{
|
||||||
"1": {types.GoType{int(1)}},
|
|
||||||
"-1": {types.GoType{int(-1)}},
|
|
||||||
"+1": {types.GoType{int(1)}},
|
|
||||||
|
|
||||||
"1.5": {types.GoType{float32(1.5)}},
|
|
||||||
"-1.5": {types.GoType{float32(-1.5)}},
|
|
||||||
"+1.5": {types.GoType{float32(1.5)}},
|
|
||||||
"1.5e1": {types.GoType{float32(15)}},
|
|
||||||
|
|
||||||
"foo": {types.GoType{":foo"}},
|
|
||||||
|
|
||||||
"foo 4 bar": {
|
"foo 4 bar": {
|
||||||
types.GoType{":foo"},
|
types.GoType{":foo"},
|
||||||
types.GoType{4},
|
types.GoType{4},
|
||||||
@ -32,23 +64,6 @@ func TestParseBareString(t *T) {
|
|||||||
types.GoType{":foo"},
|
types.GoType{":foo"},
|
||||||
types.GoType{"bar"},
|
types.GoType{"bar"},
|
||||||
},
|
},
|
||||||
|
|
||||||
"()": {seq.NewList()},
|
|
||||||
|
|
||||||
"(foo)": {seq.NewList(
|
|
||||||
types.GoType{":foo"},
|
|
||||||
)},
|
|
||||||
|
|
||||||
"(foo (bar))": {seq.NewList(
|
|
||||||
types.GoType{":foo"},
|
|
||||||
seq.NewList(types.GoType{":bar"}),
|
|
||||||
)},
|
|
||||||
|
|
||||||
"{}": {seq.NewHashMap()},
|
|
||||||
|
|
||||||
"{foo bar}": {seq.NewHashMap(
|
|
||||||
seq.KeyVal(types.GoType{":foo"}, types.GoType{":bar"}),
|
|
||||||
)},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for input, output := range m {
|
for input, output := range m {
|
||||||
|
Loading…
Reference in New Issue
Block a user