From 7cd65a4025d9bb25280d7c53555633043237933b Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Fri, 27 Mar 2015 19:09:41 -0400 Subject: [PATCH] numbers are back, yay --- node.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++ parse.go | 38 ++++------------------- tests/parse/01.in | 1 + tests/parse/01.out | 2 ++ tests/parse/02.in | 17 +++++++++++ tests/parse/02.out | 50 +++++++++++++++++++++++++++++++ 6 files changed, 151 insertions(+), 32 deletions(-) create mode 100644 tests/parse/01.in create mode 100644 tests/parse/01.out create mode 100644 tests/parse/02.in create mode 100644 tests/parse/02.out diff --git a/node.go b/node.go index ed54d0c..7c6122a 100644 --- a/node.go +++ b/node.go @@ -5,6 +5,7 @@ import ( "bytes" "fmt" "io" + "strconv" "strings" ) @@ -16,6 +17,7 @@ const ( n_comment n_assignment n_string + n_number ) var indent = " " @@ -216,5 +218,78 @@ func (s *stringNode) eval(ctx map[string]interface{}) (interface{}, error) { return string(*s), nil } +type numberType int + +const ( + num_int numberType = iota + num_float + num_complex +) + +type numberNode struct { + t numberType + c complex128 + i int + f float64 +} + +func (n *numberNode) Type() nodeType { + return n_number +} + +func (n *numberNode) parse(p *parser) error { + t := p.next() + if t.t != t_real_number { + return fmt.Errorf("unexpected %s token while parsing number", t.t) + } + + if p.peek().t == t_imaginary_number { + n.t = num_complex + s := t.s + p.next().s + if _, err := fmt.Sscan(s, &n.c); err != nil { + return fmt.Errorf("ungood imaginary number format %s: %s", s, err) + } + return nil + } + + i, err := strconv.ParseInt(t.s, 0, 64) + if err == nil { + n.t = num_int + n.i = int(i) + return nil + } + + f, err := strconv.ParseFloat(t.s, 64) + if err == nil { + n.t = num_float + n.f = f + return nil + } + + return fmt.Errorf("this token broke the number parser: %s", t) +} + +func (n *numberNode) pretty(w io.Writer, prefix string) error { + v, err := n.eval(nil) + if err != nil { + return err + } + fmt.Fprintf(w, "%s%v\n", prefix, v) + return nil +} + +func (n *numberNode) eval(ctx map[string]interface{}) (interface{}, error) { + switch n.t { + case num_int: + return n.i, nil + case num_float: + return n.f, nil + case num_complex: + return n.c, nil + default: + panic("whoerps") + } +} + type list []interface{} type object map[string]interface{} diff --git a/parse.go b/parse.go index 4f4a8d7..3a1da86 100644 --- a/parse.go +++ b/parse.go @@ -3,7 +3,6 @@ package main import ( "fmt" "io" - "strconv" ) const () @@ -87,9 +86,12 @@ func (p *parser) parseValue() (node, error) { return nil, err } return n, nil - // case t_real_number, t_imaginary_number: - // p.unread(t) - // return p.number() + case t_real_number: + n := new(numberNode) + if err := n.parse(p); err != nil { + return nil, err + } + return n, nil // case t_list_start: // return p.parseList(make(list, 0, 4)) // case t_object_start: @@ -149,31 +151,3 @@ func (p *parser) parseObject(obj object) (object, error) { return p.parseObject(obj) } } - -func (p *parser) number() (interface{}, error) { - t := p.next() - if t.t != t_real_number { - return nil, fmt.Errorf("unexpected %s token while parsing number", t.t) - } - - if p.peek().t == t_imaginary_number { - var c complex128 - s := t.s + p.next().s - if _, err := fmt.Sscan(s, &c); err != nil { - return nil, fmt.Errorf("ungood imaginary number format %s: %s", s, err) - } - return c, nil - } - - i, err := strconv.ParseInt(t.s, 0, 64) - if err == nil { - return int(i), nil - } - - f, err := strconv.ParseFloat(t.s, 64) - if err == nil { - return f, nil - } - - return nil, fmt.Errorf("this token broke the number parser: %s", t) -} diff --git a/tests/parse/01.in b/tests/parse/01.in new file mode 100644 index 0000000..1747fba --- /dev/null +++ b/tests/parse/01.in @@ -0,0 +1 @@ +# comments should be removed from the parse tree diff --git a/tests/parse/01.out b/tests/parse/01.out new file mode 100644 index 0000000..02e1f1b --- /dev/null +++ b/tests/parse/01.out @@ -0,0 +1,2 @@ +root{ +} diff --git a/tests/parse/02.in b/tests/parse/02.in new file mode 100644 index 0000000..6cc08a6 --- /dev/null +++ b/tests/parse/02.in @@ -0,0 +1,17 @@ +a_string: "a string value" + +an_int: 1 +another_int: +9 +moar_int: -12 + +a_float: 1.0 +another_float: -.9 +extra_floaty: +1.2 + +complex1: 1+1i +complex2: 1+0i +complex3: 1.3+4.7i +complex4: -4.2+8.9i +complex5: +4.2-8.9i + + diff --git a/tests/parse/02.out b/tests/parse/02.out new file mode 100644 index 0000000..0a43708 --- /dev/null +++ b/tests/parse/02.out @@ -0,0 +1,50 @@ +root{ + assign{ + name: a_string + value: a string value + } + assign{ + name: an_int + value: 1 + } + assign{ + name: another_int + value: 9 + } + assign{ + name: moar_int + value: -12 + } + assign{ + name: a_float + value: 1 + } + assign{ + name: another_float + value: -0.9 + } + assign{ + name: extra_floaty + value: 1.2 + } + assign{ + name: complex1 + value: (1+1i) + } + assign{ + name: complex2 + value: (1+0i) + } + assign{ + name: complex3 + value: (1.3+4.7i) + } + assign{ + name: complex4 + value: (-4.2+8.9i) + } + assign{ + name: complex5 + value: (4.2-8.9i) + } +}