Skip to content
This repository has been archived by the owner on Jan 5, 2019. It is now read-only.

Commit

Permalink
refactored map field
Browse files Browse the repository at this point in the history
Change-Id: Iaf399df54da3f0ea9e54926f0b6e3ee8a7249c9a
  • Loading branch information
emicklei committed Jan 31, 2017
1 parent 03deda8 commit 72d7e16
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 39 deletions.
69 changes: 41 additions & 28 deletions field.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
package proto3

import (
"fmt"
"strconv"
)
import "strconv"

// Field is a message field.
// Field is an abstract message field.
type Field struct {
Name string
Type string
Repeated bool
Sequence int
Options []*Option
}

// NormalField
type NormalField struct {
*Field
Repeated bool
}

func newNormalField() *NormalField { return &NormalField{Field: new(Field)} }

// Accept dispatches the call to the visitor.
func (f *Field) Accept(v Visitor) {
v.VisitField(f)
func (f *NormalField) Accept(v Visitor) {
v.VisitNormalField(f)
}

// parse expects:
// [ "repeated" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
func (f *Field) parse(p *Parser) error {
func (f *NormalField) parse(p *Parser) error {
for {
tok, lit := p.scanIgnoreWhitespace()
switch tok {
Expand All @@ -30,7 +34,7 @@ func (f *Field) parse(p *Parser) error {
return f.parse(p)
case tIDENT:
f.Type = lit
return parseFieldAfterType(f, p)
return parseFieldAfterType(f.Field, p)
default:
goto done
}
Expand All @@ -39,18 +43,6 @@ done:
return nil
}

// parseMapField continues after scanning "map"
func parseMapField(f *Field, p *Parser) error {
tok, lit := p.scanIgnoreWhitespace()
if tLESS != tok {
return p.unexpected(lit, "<")
}
// TODO proper parsing key-value type
kvtypes := p.s.scanUntil('>')
f.Type = fmt.Sprintf("map<%s>", kvtypes)
return parseFieldAfterType(f, p)
}

// parseFieldAfterType expects:
// fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";
func parseFieldAfterType(f *Field, p *Parser) error {
Expand Down Expand Up @@ -98,13 +90,12 @@ func parseFieldAfterType(f *Field, p *Parser) error {

// MapField represents a map entry in a message.
type MapField struct {
Name string
KeyType string
Type string
Sequence int
Options []*Option
*Field
KeyType string
}

func newMapField() *MapField { return &MapField{Field: new(Field)} }

// Accept dispatches the call to the visitor.
func (f *MapField) Accept(v Visitor) {
v.VisitMapField(f)
Expand All @@ -115,5 +106,27 @@ func (f *MapField) Accept(v Visitor) {
// keyType = "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" |
// "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string"
func (f *MapField) parse(p *Parser) error {
return nil
tok, lit := p.scanIgnoreWhitespace()
if tLESS != tok {
return p.unexpected(lit, "<")
}
tok, lit = p.scanIgnoreWhitespace()
if tIDENT != tok {
return p.unexpected(lit, "identifier")
}
f.KeyType = lit
tok, lit = p.scanIgnoreWhitespace()
if tCOMMA != tok {
return p.unexpected(lit, ",")
}
tok, lit = p.scanIgnoreWhitespace()
if tIDENT != tok {
return p.unexpected(lit, "identifier")
}
f.Type = lit
tok, lit = p.scanIgnoreWhitespace()
if tGREATER != tok {
return p.unexpected(lit, ">")
}
return parseFieldAfterType(f.Field, p)
}
16 changes: 13 additions & 3 deletions field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "testing"
func TestField(t *testing.T) {
proto := `repeated foo.bar lots = 1 [option1=a, option2=b, option3="happy"];`
p := newParserOn(proto)
f := new(Field)
f := newNormalField()
err := f.parse(p)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -42,7 +42,7 @@ func TestField(t *testing.T) {
func TestFieldSimple(t *testing.T) {
proto := `string optional_string_piece = 24 [ctype=STRING_PIECE];`
p := newParserOn(proto)
f := new(Field)
f := newNormalField()
err := f.parse(p)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -72,9 +72,19 @@ func TestFieldSyntaxErrors(t *testing.T) {
`repeatet foo.bar lots = 1;`,
`string lots === 1;`,
} {
f := new(Field)
f := newNormalField()
if f.parse(newParserOn(each)) == nil {
t.Errorf("uncaught syntax error in test case %d, %#v", i, f)
}
}
}

func TestMapField(t *testing.T) {
proto := ` <string, Project> projects = 3;`
p := newParserOn(proto)
f := newMapField()
err := f.parse(p)
if err != nil {
t.Fatal(err)
}
}
6 changes: 3 additions & 3 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func (m *Message) parse(p *Parser) error {
}
m.Elements = append(m.Elements, o)
case tMAP:
f := new(Field)
if err := parseMapField(f, p); err != nil {
f := newMapField()
if err := f.parse(p); err != nil {
return err
}
m.Elements = append(m.Elements, f)
Expand All @@ -69,7 +69,7 @@ func (m *Message) parse(p *Parser) error {
default:
// tFIELD
p.unscan()
f := new(Field)
f := newNormalField()
if err := f.parse(p); err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import "testing"

func TestMessage(t *testing.T) {
proto := `
message Out {
message Out {
// identifier
string id = 1;
// size
int64 size = 2;
oneof foo {
string name = 4;
SubMessage sub_message = 9;
oneof foo {
string name = 4;
SubMessage sub_message = 9;
}
message Inner { // Level 2
int64 ival = 1;
Expand Down
2 changes: 2 additions & 0 deletions scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ func (s *scanner) scan() (tok token, lit string) {
return tCOMMA, string(ch)
case '.':
return tDOT, string(ch)
case '>':
return tGREATER, string(ch)
}
return tILLEGAL, string(ch)
}
Expand Down
1 change: 1 addition & 0 deletions token.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
tRIGHTSQUARE // ]
tCOMMENT // /
tLESS // <
tGREATER // >
tCOMMA // ,
tDOT // .

Expand Down
2 changes: 1 addition & 1 deletion visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type Visitor interface {
VisitPackage(p *Package)
VisitOption(o *Option)
VisitImport(i *Import)
VisitField(i *Field)
VisitNormalField(i *NormalField)
VisitEnumField(i *EnumField)
VisitEnum(e *Enum)
VisitComment(e *Comment)
Expand Down

0 comments on commit 72d7e16

Please sign in to comment.