diff options
Diffstat (limited to 'src/pkg/exp/datafmt')
-rw-r--r-- | src/pkg/exp/datafmt/datafmt.go | 274 | ||||
-rw-r--r-- | src/pkg/exp/datafmt/datafmt_test.go | 270 | ||||
-rw-r--r-- | src/pkg/exp/datafmt/parser.go | 222 |
3 files changed, 383 insertions, 383 deletions
diff --git a/src/pkg/exp/datafmt/datafmt.go b/src/pkg/exp/datafmt/datafmt.go index 4ed9695ab..0a2354286 100644 --- a/src/pkg/exp/datafmt/datafmt.go +++ b/src/pkg/exp/datafmt/datafmt.go @@ -202,13 +202,13 @@ package datafmt import ( - "bytes"; - "fmt"; - "go/token"; - "io"; - "os"; - "reflect"; - "runtime"; + "bytes" + "fmt" + "go/token" + "io" + "os" + "reflect" + "runtime" ) @@ -238,35 +238,35 @@ type FormatterMap map[string]Formatter // A parsed format expression is built from the following nodes. // type ( - expr interface{}; + expr interface{} - alternatives []expr; // x | y | z + alternatives []expr // x | y | z - sequence []expr; // x y z + sequence []expr // x y z - literal [][]byte; // a list of string segments, possibly starting with '%' + literal [][]byte // a list of string segments, possibly starting with '%' - field struct { - fieldName string; // including "@", "*" - ruleName string; // "" if no rule name specified - }; + field struct { + fieldName string // including "@", "*" + ruleName string // "" if no rule name specified + } - group struct { - indent, body expr; // (indent >> body) - }; + group struct { + indent, body expr // (indent >> body) + } - option struct { - body expr; // [body] - }; + option struct { + body expr // [body] + } - repetition struct { - body, separator expr; // {body / separator} - }; + repetition struct { + body, separator expr // {body / separator} + } - custom struct { - ruleName string; - fun Formatter; - }; + custom struct { + ruleName string + fun Formatter + } ) @@ -290,7 +290,7 @@ type Format map[string]expr // the receiver, and thus can be very light-weight. // type Environment interface { - Copy() Environment; + Copy() Environment } @@ -298,24 +298,24 @@ type Environment interface { // It is provided as argument to custom formatters. // type State struct { - fmt Format; // format in use - env Environment; // user-supplied environment - errors chan os.Error; // not chan *Error (errors <- nil would be wrong!) - hasOutput bool; // true after the first literal has been written - indent bytes.Buffer; // current indentation - output bytes.Buffer; // format output - linePos token.Position; // position of line beginning (Column == 0) - default_ expr; // possibly nil - separator expr; // possibly nil + fmt Format // format in use + env Environment // user-supplied environment + errors chan os.Error // not chan *Error (errors <- nil would be wrong!) + hasOutput bool // true after the first literal has been written + indent bytes.Buffer // current indentation + output bytes.Buffer // format output + linePos token.Position // position of line beginning (Column == 0) + default_ expr // possibly nil + separator expr // possibly nil } func newState(fmt Format, env Environment, errors chan os.Error) *State { - s := new(State); - s.fmt = fmt; - s.env = env; - s.errors = errors; - s.linePos = token.Position{Line: 1}; + s := new(State) + s.fmt = fmt + s.env = env + s.errors = errors + s.linePos = token.Position{Line: 1} // if we have a default rule, cache it's expression for fast access if x, found := fmt["default"]; found { @@ -327,26 +327,26 @@ func newState(fmt Format, env Environment, errors chan os.Error) *State { s.separator = x } - return s; + return s } // Env returns the environment passed to Format.Apply. -func (s *State) Env() interface{} { return s.env } +func (s *State) Env() interface{} { return s.env } // LinePos returns the position of the current line beginning // in the state's output buffer. Line numbers start at 1. // -func (s *State) LinePos() token.Position { return s.linePos } +func (s *State) LinePos() token.Position { return s.linePos } // Pos returns the position of the next byte to be written to the // output buffer. Line numbers start at 1. // func (s *State) Pos() token.Position { - offs := s.output.Len(); - return token.Position{Line: s.linePos.Line, Column: offs - s.linePos.Offset, Offset: offs}; + offs := s.output.Len() + return token.Position{Line: s.linePos.Line, Column: offs - s.linePos.Offset, Offset: offs} } @@ -354,50 +354,50 @@ func (s *State) Pos() token.Position { // string after each newline or form feed character. It cannot return an error. // func (s *State) Write(data []byte) (int, os.Error) { - n := 0; - i0 := 0; + n := 0 + i0 := 0 for i, ch := range data { if ch == '\n' || ch == '\f' { // write text segment and indentation - n1, _ := s.output.Write(data[i0 : i+1]); - n2, _ := s.output.Write(s.indent.Bytes()); - n += n1 + n2; - i0 = i + 1; - s.linePos.Offset = s.output.Len(); - s.linePos.Line++; + n1, _ := s.output.Write(data[i0 : i+1]) + n2, _ := s.output.Write(s.indent.Bytes()) + n += n1 + n2 + i0 = i + 1 + s.linePos.Offset = s.output.Len() + s.linePos.Line++ } } - n3, _ := s.output.Write(data[i0:]); - return n + n3, nil; + n3, _ := s.output.Write(data[i0:]) + return n + n3, nil } type checkpoint struct { - env Environment; - hasOutput bool; - outputLen int; - linePos token.Position; + env Environment + hasOutput bool + outputLen int + linePos token.Position } func (s *State) save() checkpoint { - saved := checkpoint{nil, s.hasOutput, s.output.Len(), s.linePos}; + saved := checkpoint{nil, s.hasOutput, s.output.Len(), s.linePos} if s.env != nil { saved.env = s.env.Copy() } - return saved; + return saved } func (s *State) restore(m checkpoint) { - s.env = m.env; - s.output.Truncate(m.outputLen); + s.env = m.env + s.output.Truncate(m.outputLen) } func (s *State) error(msg string) { - s.errors <- os.NewError(msg); - runtime.Goexit(); + s.errors <- os.NewError(msg) + runtime.Goexit() } @@ -426,7 +426,7 @@ func typename(typ reflect.Type) string { case *reflect.PtrType: return "ptr" } - return typ.String(); + return typ.String() } func (s *State) getFormat(name string) expr { @@ -438,8 +438,8 @@ func (s *State) getFormat(name string) expr { return s.default_ } - s.error(fmt.Sprintf("no format rule for type: '%s'", name)); - return nil; + s.error(fmt.Sprintf("no format rule for type: '%s'", name)) + return nil } @@ -459,42 +459,42 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool { case alternatives: // append the result of the first alternative that evaluates to // a non-nil []byte to the state's output - mark := s.save(); + mark := s.save() for _, x := range t { if s.eval(x, value, index) { return true } - s.restore(mark); + s.restore(mark) } - return false; + return false case sequence: // append the result of all operands to the state's output // unless a nil result is encountered - mark := s.save(); + mark := s.save() for _, x := range t { if !s.eval(x, value, index) { - s.restore(mark); - return false; + s.restore(mark) + return false } } - return true; + return true case literal: // write separator, if any if s.hasOutput { // not the first literal if s.separator != nil { - sep := s.separator; // save current separator - s.separator = nil; // and disable it (avoid recursion) - mark := s.save(); + sep := s.separator // save current separator + s.separator = nil // and disable it (avoid recursion) + mark := s.save() if !s.eval(sep, value, index) { s.restore(mark) } - s.separator = sep; // enable it again + s.separator = sep // enable it again } } - s.hasOutput = true; + s.hasOutput = true // write literal segments for _, lit := range t { if len(lit) > 1 && lit[0] == '%' { @@ -511,7 +511,7 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool { s.Write(lit) } } - return true; // a literal never evaluates to nil + return true // a literal never evaluates to nil case *field: // determine field value @@ -526,13 +526,13 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool { if v.Len() <= index { return false } - value = v.Elem(index); + value = v.Elem(index) case *reflect.SliceValue: if v.IsNil() || v.Len() <= index { return false } - value = v.Elem(index); + value = v.Elem(index) case *reflect.MapValue: s.error("reflection support for maps incomplete") @@ -541,13 +541,13 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool { if v.IsNil() { return false } - value = v.Elem(); + value = v.Elem() case *reflect.InterfaceValue: if v.IsNil() { return false } - value = v.Elem(); + value = v.Elem() case *reflect.ChanValue: s.error("reflection support for chans incomplete") @@ -561,98 +561,98 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool { default: // value is value of named field - var field reflect.Value; + var field reflect.Value if sval, ok := value.(*reflect.StructValue); ok { - field = sval.FieldByName(t.fieldName); + field = sval.FieldByName(t.fieldName) if field == nil { // TODO consider just returning false in this case s.error(fmt.Sprintf("error: no field `%s` in `%s`", t.fieldName, value.Type())) } } - value = field; + value = field } // determine rule - ruleName := t.ruleName; + ruleName := t.ruleName if ruleName == "" { // no alternate rule name, value type determines rule ruleName = typename(value.Type()) } - fexpr = s.getFormat(ruleName); + fexpr = s.getFormat(ruleName) - mark := s.save(); + mark := s.save() if !s.eval(fexpr, value, index) { - s.restore(mark); - return false; + s.restore(mark) + return false } - return true; + return true case *group: // remember current indentation - indentLen := s.indent.Len(); + indentLen := s.indent.Len() // update current indentation - mark := s.save(); - s.eval(t.indent, value, index); + mark := s.save() + s.eval(t.indent, value, index) // if the indentation evaluates to nil, the state's output buffer // didn't change - either way it's ok to append the difference to // the current identation - s.indent.Write(s.output.Bytes()[mark.outputLen:s.output.Len()]); - s.restore(mark); + s.indent.Write(s.output.Bytes()[mark.outputLen:s.output.Len()]) + s.restore(mark) // format group body - mark = s.save(); - b := true; + mark = s.save() + b := true if !s.eval(t.body, value, index) { - s.restore(mark); - b = false; + s.restore(mark) + b = false } // reset indentation - s.indent.Truncate(indentLen); - return b; + s.indent.Truncate(indentLen) + return b case *option: // evaluate the body and append the result to the state's output // buffer unless the result is nil - mark := s.save(); - if !s.eval(t.body, value, 0) { // TODO is 0 index correct? + mark := s.save() + if !s.eval(t.body, value, 0) { // TODO is 0 index correct? s.restore(mark) } - return true; // an option never evaluates to nil + return true // an option never evaluates to nil case *repetition: // evaluate the body and append the result to the state's output // buffer until a result is nil for i := 0; ; i++ { - mark := s.save(); + mark := s.save() // write separator, if any if i > 0 && t.separator != nil { // nil result from separator is ignored - mark := s.save(); + mark := s.save() if !s.eval(t.separator, value, i) { s.restore(mark) } } if !s.eval(t.body, value, i) { - s.restore(mark); - break; + s.restore(mark) + break } } - return true; // a repetition never evaluates to nil + return true // a repetition never evaluates to nil case *custom: // invoke the custom formatter to obtain the result - mark := s.save(); + mark := s.save() if !t.fun(s, value.Interface(), t.ruleName) { - s.restore(mark); - return false; + s.restore(mark) + return false } - return true; + return true } - panic("unreachable"); - return false; + panic("unreachable") + return false } @@ -668,23 +668,23 @@ func (f Format) Eval(env Environment, args ...) ([]byte, os.Error) { return nil, os.NewError("format is nil") } - errors := make(chan os.Error); - s := newState(f, env, errors); + errors := make(chan os.Error) + s := newState(f, env, errors) go func() { - value := reflect.NewValue(args).(*reflect.StructValue); + value := reflect.NewValue(args).(*reflect.StructValue) for i := 0; i < value.NumField(); i++ { - fld := value.Field(i); - mark := s.save(); - if !s.eval(s.getFormat(typename(fld.Type())), fld, 0) { // TODO is 0 index correct? + fld := value.Field(i) + mark := s.save() + if !s.eval(s.getFormat(typename(fld.Type())), fld, 0) { // TODO is 0 index correct? s.restore(mark) } } - errors <- nil; // no errors - }(); + errors <- nil // no errors + }() - err := <-errors; - return s.output.Bytes(), err; + err := <-errors + return s.output.Bytes(), err } @@ -696,12 +696,12 @@ func (f Format) Eval(env Environment, args ...) ([]byte, os.Error) { // written and an os.Error, if any. // func (f Format) Fprint(w io.Writer, env Environment, args ...) (int, os.Error) { - data, err := f.Eval(env, args); + data, err := f.Eval(env, args) if err != nil { // TODO should we print partial result in case of error? return 0, err } - return w.Write(data); + return w.Write(data) } @@ -720,10 +720,10 @@ func (f Format) Print(args ...) (int, os.Error) { // partially formatted result followed by an error message. // func (f Format) Sprint(args ...) string { - var buf bytes.Buffer; - _, err := f.Fprint(&buf, nil, args); + var buf bytes.Buffer + _, err := f.Fprint(&buf, nil, args) if err != nil { fmt.Fprintf(&buf, "--- Sprint(%s) failed: %v", fmt.Sprint(args), err) } - return buf.String(); + return buf.String() } diff --git a/src/pkg/exp/datafmt/datafmt_test.go b/src/pkg/exp/datafmt/datafmt_test.go index 61c0a972d..d1c6222a0 100644 --- a/src/pkg/exp/datafmt/datafmt_test.go +++ b/src/pkg/exp/datafmt/datafmt_test.go @@ -5,27 +5,27 @@ package datafmt import ( - "fmt"; - "strings"; - "testing"; + "fmt" + "strings" + "testing" ) func parse(t *testing.T, form string, fmap FormatterMap) Format { - f, err := Parse("", strings.Bytes(form), fmap); + f, err := Parse("", strings.Bytes(form), fmap) if err != nil { - t.Errorf("Parse(%s): %v", form, err); - return nil; + t.Errorf("Parse(%s): %v", form, err) + return nil } - return f; + return f } func verify(t *testing.T, f Format, expected string, args ...) { if f == nil { - return // allow other tests to run + return // allow other tests to run } - result := f.Sprint(args); + result := f.Sprint(args) if result != expected { t.Errorf( "result : `%s`\nexpected: `%s`\n\n", @@ -37,54 +37,54 @@ func verify(t *testing.T, f Format, expected string, args ...) { func formatter(s *State, value interface{}, rule_name string) bool { switch rule_name { case "/": - fmt.Fprintf(s, "%d %d %d", s.Pos().Line, s.LinePos().Column, s.Pos().Column); - return true; + fmt.Fprintf(s, "%d %d %d", s.Pos().Line, s.LinePos().Column, s.Pos().Column) + return true case "blank": - s.Write([]byte{' '}); - return true; + s.Write([]byte{' '}) + return true case "int": if value.(int)&1 == 0 { fmt.Fprint(s, "even ") } else { fmt.Fprint(s, "odd ") } - return true; + return true case "nil": return false case "testing.T": - s.Write(strings.Bytes("testing.T")); - return true; + s.Write(strings.Bytes("testing.T")) + return true } - panic("unreachable"); - return false; + panic("unreachable") + return false } func TestCustomFormatters(t *testing.T) { - fmap0 := FormatterMap{"/": formatter}; - fmap1 := FormatterMap{"int": formatter, "blank": formatter, "nil": formatter}; - fmap2 := FormatterMap{"testing.T": formatter}; + fmap0 := FormatterMap{"/": formatter} + fmap1 := FormatterMap{"int": formatter, "blank": formatter, "nil": formatter} + fmap2 := FormatterMap{"testing.T": formatter} - f := parse(t, `int=`, fmap0); - verify(t, f, ``, 1, 2, 3); + f := parse(t, `int=`, fmap0) + verify(t, f, ``, 1, 2, 3) - f = parse(t, `int="#"`, nil); - verify(t, f, `###`, 1, 2, 3); + f = parse(t, `int="#"`, nil) + verify(t, f, `###`, 1, 2, 3) - f = parse(t, `int="#";string="%s"`, fmap0); - verify(t, f, "#1 0 1#1 0 7#1 0 13\n2 0 0foo2 0 8\n", 1, 2, 3, "\n", "foo", "\n"); + f = parse(t, `int="#";string="%s"`, fmap0) + verify(t, f, "#1 0 1#1 0 7#1 0 13\n2 0 0foo2 0 8\n", 1, 2, 3, "\n", "foo", "\n") - f = parse(t, ``, fmap1); - verify(t, f, `even odd even odd `, 0, 1, 2, 3); + f = parse(t, ``, fmap1) + verify(t, f, `even odd even odd `, 0, 1, 2, 3) - f = parse(t, `/ =@:blank; float="#"`, fmap1); - verify(t, f, `# # #`, 0.0, 1.0, 2.0); + f = parse(t, `/ =@:blank; float="#"`, fmap1) + verify(t, f, `# # #`, 0.0, 1.0, 2.0) - f = parse(t, `float=@:nil`, fmap1); - verify(t, f, ``, 0.0, 1.0, 2.0); + f = parse(t, `float=@:nil`, fmap1) + verify(t, f, ``, 0.0, 1.0, 2.0) - f = parse(t, `testing "testing"; ptr=*`, fmap2); - verify(t, f, `testing.T`, t); + f = parse(t, `testing "testing"; ptr=*`, fmap2) + verify(t, f, `testing.T`, t) // TODO needs more tests } @@ -94,11 +94,11 @@ func TestCustomFormatters(t *testing.T) { // Formatting of basic and simple composite types func check(t *testing.T, form, expected string, args ...) { - f := parse(t, form, nil); + f := parse(t, form, nil) if f == nil { - return // allow other tests to run + return // allow other tests to run } - result := f.Sprint(args); + result := f.Sprint(args) if result != expected { t.Errorf( "format : %s\nresult : `%s`\nexpected: `%s`\n\n", @@ -108,120 +108,120 @@ func check(t *testing.T, form, expected string, args ...) { func TestBasicTypes(t *testing.T) { - check(t, ``, ``); - check(t, `bool=":%v"`, `:true:false`, true, false); - check(t, `int="%b %d %o 0x%x"`, `101010 42 52 0x2a`, 42); - - check(t, `int="%"`, `%`, 42); - check(t, `int="%%"`, `%`, 42); - check(t, `int="**%%**"`, `**%**`, 42); - check(t, `int="%%%%%%"`, `%%%`, 42); - check(t, `int="%%%d%%"`, `%42%`, 42); - - const i = -42; - const is = `-42`; - check(t, `int ="%d"`, is, i); - check(t, `int8 ="%d"`, is, int8(i)); - check(t, `int16="%d"`, is, int16(i)); - check(t, `int32="%d"`, is, int32(i)); - check(t, `int64="%d"`, is, int64(i)); - - const u = 42; - const us = `42`; - check(t, `uint ="%d"`, us, uint(u)); - check(t, `uint8 ="%d"`, us, uint8(u)); - check(t, `uint16="%d"`, us, uint16(u)); - check(t, `uint32="%d"`, us, uint32(u)); - check(t, `uint64="%d"`, us, uint64(u)); - - const f = 3.141592; - const fs = `3.141592`; - check(t, `float ="%g"`, fs, f); - check(t, `float32="%g"`, fs, float32(f)); - check(t, `float64="%g"`, fs, float64(f)); + check(t, ``, ``) + check(t, `bool=":%v"`, `:true:false`, true, false) + check(t, `int="%b %d %o 0x%x"`, `101010 42 52 0x2a`, 42) + + check(t, `int="%"`, `%`, 42) + check(t, `int="%%"`, `%`, 42) + check(t, `int="**%%**"`, `**%**`, 42) + check(t, `int="%%%%%%"`, `%%%`, 42) + check(t, `int="%%%d%%"`, `%42%`, 42) + + const i = -42 + const is = `-42` + check(t, `int ="%d"`, is, i) + check(t, `int8 ="%d"`, is, int8(i)) + check(t, `int16="%d"`, is, int16(i)) + check(t, `int32="%d"`, is, int32(i)) + check(t, `int64="%d"`, is, int64(i)) + + const u = 42 + const us = `42` + check(t, `uint ="%d"`, us, uint(u)) + check(t, `uint8 ="%d"`, us, uint8(u)) + check(t, `uint16="%d"`, us, uint16(u)) + check(t, `uint32="%d"`, us, uint32(u)) + check(t, `uint64="%d"`, us, uint64(u)) + + const f = 3.141592 + const fs = `3.141592` + check(t, `float ="%g"`, fs, f) + check(t, `float32="%g"`, fs, float32(f)) + check(t, `float64="%g"`, fs, float64(f)) } func TestArrayTypes(t *testing.T) { - var a0 [10]int; - check(t, `array="array";`, `array`, a0); + var a0 [10]int + check(t, `array="array";`, `array`, a0) - a1 := [...]int{1, 2, 3}; - check(t, `array="array";`, `array`, a1); - check(t, `array={*}; int="%d";`, `123`, a1); - check(t, `array={* / ", "}; int="%d";`, `1, 2, 3`, a1); - check(t, `array={* / *}; int="%d";`, `12233`, a1); + a1 := [...]int{1, 2, 3} + check(t, `array="array";`, `array`, a1) + check(t, `array={*}; int="%d";`, `123`, a1) + check(t, `array={* / ", "}; int="%d";`, `1, 2, 3`, a1) + check(t, `array={* / *}; int="%d";`, `12233`, a1) - a2 := []interface{}{42, "foo", 3.14}; - check(t, `array={* / ", "}; interface=*; string="bar"; default="%v";`, `42, bar, 3.14`, a2); + a2 := []interface{}{42, "foo", 3.14} + check(t, `array={* / ", "}; interface=*; string="bar"; default="%v";`, `42, bar, 3.14`, a2) } func TestChanTypes(t *testing.T) { - var c0 chan int; - check(t, `chan="chan"`, `chan`, c0); + var c0 chan int + check(t, `chan="chan"`, `chan`, c0) - c1 := make(chan int); - go func() { c1 <- 42 }(); - check(t, `chan="chan"`, `chan`, c1); + c1 := make(chan int) + go func() { c1 <- 42 }() + check(t, `chan="chan"`, `chan`, c1) // check(t, `chan=*`, `42`, c1); // reflection support for chans incomplete } func TestFuncTypes(t *testing.T) { - var f0 func() int; - check(t, `func="func"`, `func`, f0); + var f0 func() int + check(t, `func="func"`, `func`, f0) - f1 := func() int { return 42 }; - check(t, `func="func"`, `func`, f1); + f1 := func() int { return 42 } + check(t, `func="func"`, `func`, f1) // check(t, `func=*`, `42`, f1); // reflection support for funcs incomplete } func TestInterfaceTypes(t *testing.T) { var i0 interface{} - check(t, `interface="interface"`, `interface`, i0); + check(t, `interface="interface"`, `interface`, i0) - i0 = "foo"; - check(t, `interface="interface"`, `interface`, i0); - check(t, `interface=*; string="%s"`, `foo`, i0); + i0 = "foo" + check(t, `interface="interface"`, `interface`, i0) + check(t, `interface=*; string="%s"`, `foo`, i0) } func TestMapTypes(t *testing.T) { - var m0 map[string]int; - check(t, `map="map"`, `map`, m0); + var m0 map[string]int + check(t, `map="map"`, `map`, m0) - m1 := map[string]int{}; - check(t, `map="map"`, `map`, m1); + m1 := map[string]int{} + check(t, `map="map"`, `map`, m1) // check(t, `map=*`, ``, m1); // reflection support for maps incomplete } func TestPointerTypes(t *testing.T) { - var p0 *int; - check(t, `ptr="ptr"`, `ptr`, p0); - check(t, `ptr=*`, ``, p0); - check(t, `ptr=*|"nil"`, `nil`, p0); - - x := 99991; - p1 := &x; - check(t, `ptr="ptr"`, `ptr`, p1); - check(t, `ptr=*; int="%d"`, `99991`, p1); + var p0 *int + check(t, `ptr="ptr"`, `ptr`, p0) + check(t, `ptr=*`, ``, p0) + check(t, `ptr=*|"nil"`, `nil`, p0) + + x := 99991 + p1 := &x + check(t, `ptr="ptr"`, `ptr`, p1) + check(t, `ptr=*; int="%d"`, `99991`, p1) } func TestDefaultRule(t *testing.T) { - check(t, `default="%v"`, `42foo3.14`, 42, "foo", 3.14); - check(t, `default="%v"; int="%x"`, `abcdef`, 10, 11, 12, 13, 14, 15); - check(t, `default="%v"; int="%x"`, `ab**ef`, 10, 11, "**", 14, 15); - check(t, `default="%x"; int=@:default`, `abcdef`, 10, 11, 12, 13, 14, 15); + check(t, `default="%v"`, `42foo3.14`, 42, "foo", 3.14) + check(t, `default="%v"; int="%x"`, `abcdef`, 10, 11, 12, 13, 14, 15) + check(t, `default="%v"; int="%x"`, `ab**ef`, 10, 11, "**", 14, 15) + check(t, `default="%x"; int=@:default`, `abcdef`, 10, 11, 12, 13, 14, 15) } func TestGlobalSeparatorRule(t *testing.T) { - check(t, `int="%d"; / ="-"`, `1-2-3-4`, 1, 2, 3, 4); - check(t, `int="%x%x"; / ="*"`, `aa*aa`, 10, 10); + check(t, `int="%d"; / ="-"`, `1-2-3-4`, 1, 2, 3, 4) + check(t, `int="%x%x"; / ="*"`, `aa*aa`, 10, 10) } @@ -229,22 +229,22 @@ func TestGlobalSeparatorRule(t *testing.T) { // Formatting of a struct type T1 struct { - a int; + a int } const F1 = `datafmt "datafmt";` + `int = "%d";` + `datafmt.T1 = "<" a ">";` -func TestStruct1(t *testing.T) { check(t, F1, "<42>", T1{42}) } +func TestStruct1(t *testing.T) { check(t, F1, "<42>", T1{42}) } // ---------------------------------------------------------------------------- // Formatting of a struct with an optional field (ptr) type T2 struct { - s string; - p *T1; + s string + p *T1 } const F2a = F1 + @@ -258,9 +258,9 @@ const F2b = F1 + `datafmt.T2 = s ("-" p "-" | "empty");` func TestStruct2(t *testing.T) { - check(t, F2a, "foo", T2{"foo", nil}); - check(t, F2a, "bar-<17>-", T2{"bar", &T1{17}}); - check(t, F2b, "fooempty", T2{"foo", nil}); + check(t, F2a, "foo", T2{"foo", nil}) + check(t, F2a, "bar-<17>-", T2{"bar", &T1{17}}) + check(t, F2b, "fooempty", T2{"foo", nil}) } @@ -268,8 +268,8 @@ func TestStruct2(t *testing.T) { // Formatting of a struct with a repetitive field (slice) type T3 struct { - s string; - a []int; + s string + a []int } const F3a = `datafmt "datafmt";` + @@ -286,10 +286,10 @@ const F3b = `datafmt "datafmt";` + `datafmt.T3 = s [a:empty ": " {a / "-"}]` func TestStruct3(t *testing.T) { - check(t, F3a, "foo", T3{"foo", nil}); - check(t, F3a, "foo 00, 11, 22", T3{"foo", []int{0, 1, 2}}); - check(t, F3b, "bar", T3{"bar", nil}); - check(t, F3b, "bal: 2-3-5", T3{"bal", []int{2, 3, 5}}); + check(t, F3a, "foo", T3{"foo", nil}) + check(t, F3a, "foo 00, 11, 22", T3{"foo", []int{0, 1, 2}}) + check(t, F3b, "bar", T3{"bar", nil}) + check(t, F3b, "bal: 2-3-5", T3{"bal", []int{2, 3, 5}}) } @@ -297,8 +297,8 @@ func TestStruct3(t *testing.T) { // Formatting of a struct with alternative field type T4 struct { - x *int; - a []int; + x *int + a []int } const F4a = `datafmt "datafmt";` + @@ -318,11 +318,11 @@ const F4b = `datafmt "datafmt";` + `datafmt.T4 = "<" (a:empty {a / ", "} | "-") ">" ` func TestStruct4(t *testing.T) { - x := 7; - check(t, F4a, "<->", T4{nil, nil}); - check(t, F4a, "<7>", T4{&x, nil}); - check(t, F4b, "<->", T4{nil, nil}); - check(t, F4b, "<2, 3, 7>", T4{nil, []int{2, 3, 7}}); + x := 7 + check(t, F4a, "<->", T4{nil, nil}) + check(t, F4a, "<7>", T4{&x, nil}) + check(t, F4b, "<->", T4{nil, nil}) + check(t, F4b, "<2, 3, 7>", T4{nil, []int{2, 3, 7}}) } @@ -330,8 +330,8 @@ func TestStruct4(t *testing.T) { // Formatting a struct (documentation example) type Point struct { - name string; - x, y int; + name string + x, y int } const FPoint = `datafmt "datafmt";` + @@ -341,8 +341,8 @@ const FPoint = `datafmt "datafmt";` + `datafmt.Point = name "{" x ", " y:hexInt "}";` func TestStructPoint(t *testing.T) { - p := Point{"foo", 3, 15}; - check(t, FPoint, "---foo---{3, 0xf}", p); + p := Point{"foo", 3, 15} + check(t, FPoint, "---foo---{3, 0xf}", p) } @@ -352,7 +352,7 @@ func TestStructPoint(t *testing.T) { const FSlice = `int = "%b";` + `array = { * / ", " }` -func TestSlice(t *testing.T) { check(t, FSlice, "10, 11, 101, 111", []int{2, 3, 5, 7}) } +func TestSlice(t *testing.T) { check(t, FSlice, "10, 11, 101, 111", []int{2, 3, 5, 7}) } // TODO add more tests diff --git a/src/pkg/exp/datafmt/parser.go b/src/pkg/exp/datafmt/parser.go index c8144d9f2..653771674 100644 --- a/src/pkg/exp/datafmt/parser.go +++ b/src/pkg/exp/datafmt/parser.go @@ -5,83 +5,83 @@ package datafmt import ( - "container/vector"; - "go/scanner"; - "go/token"; - "os"; - "strconv"; - "strings"; + "container/vector" + "go/scanner" + "go/token" + "os" + "strconv" + "strings" ) // ---------------------------------------------------------------------------- // Parsing type parser struct { - scanner.ErrorVector; - scanner scanner.Scanner; - pos token.Position; // token position - tok token.Token; // one token look-ahead - lit []byte; // token literal - - packs map[string]string; // PackageName -> ImportPath - rules map[string]expr; // RuleName -> Expression + scanner.ErrorVector + scanner scanner.Scanner + pos token.Position // token position + tok token.Token // one token look-ahead + lit []byte // token literal + + packs map[string]string // PackageName -> ImportPath + rules map[string]expr // RuleName -> Expression } func (p *parser) next() { - p.pos, p.tok, p.lit = p.scanner.Scan(); + p.pos, p.tok, p.lit = p.scanner.Scan() switch p.tok { case token.CHAN, token.FUNC, token.INTERFACE, token.MAP, token.STRUCT: // Go keywords for composite types are type names // returned by reflect. Accept them as identifiers. - p.tok = token.IDENT // p.lit is already set correctly + p.tok = token.IDENT // p.lit is already set correctly } } func (p *parser) init(filename string, src []byte) { - p.ErrorVector.Reset(); - p.scanner.Init(filename, src, p, scanner.AllowIllegalChars); // return '@' as token.ILLEGAL w/o error message - p.next(); // initializes pos, tok, lit - p.packs = make(map[string]string); - p.rules = make(map[string]expr); + p.ErrorVector.Reset() + p.scanner.Init(filename, src, p, scanner.AllowIllegalChars) // return '@' as token.ILLEGAL w/o error message + p.next() // initializes pos, tok, lit + p.packs = make(map[string]string) + p.rules = make(map[string]expr) } func (p *parser) errorExpected(pos token.Position, msg string) { - msg = "expected " + msg; + msg = "expected " + msg if pos.Offset == p.pos.Offset { // the error happened at the current position; // make the error message more specific - msg += ", found '" + p.tok.String() + "'"; + msg += ", found '" + p.tok.String() + "'" if p.tok.IsLiteral() { msg += " " + string(p.lit) } } - p.Error(pos, msg); + p.Error(pos, msg) } func (p *parser) expect(tok token.Token) token.Position { - pos := p.pos; + pos := p.pos if p.tok != tok { p.errorExpected(pos, "'"+tok.String()+"'") } - p.next(); // make progress in any case - return pos; + p.next() // make progress in any case + return pos } func (p *parser) parseIdentifier() string { - name := string(p.lit); - p.expect(token.IDENT); - return name; + name := string(p.lit) + p.expect(token.IDENT) + return name } func (p *parser) parseTypeName() (string, bool) { - pos := p.pos; - name, isIdent := p.parseIdentifier(), true; + pos := p.pos + name, isIdent := p.parseIdentifier(), true if p.tok == token.PERIOD { // got a package name, lookup package if importPath, found := p.packs[name]; found { @@ -89,10 +89,10 @@ func (p *parser) parseTypeName() (string, bool) { } else { p.Error(pos, "package not declared: "+name) } - p.next(); - name, isIdent = name+"."+p.parseIdentifier(), false; + p.next() + name, isIdent = name+"."+p.parseIdentifier(), false } - return name, isIdent; + return name, isIdent } @@ -102,99 +102,99 @@ func (p *parser) parseTypeName() (string, bool) { // single identifier only (and thus could be a package name). // func (p *parser) parseRuleName() (string, bool) { - name, isIdent := "", false; + name, isIdent := "", false switch p.tok { case token.IDENT: name, isIdent = p.parseTypeName() case token.DEFAULT: - name = "default"; - p.next(); + name = "default" + p.next() case token.QUO: - name = "/"; - p.next(); + name = "/" + p.next() default: - p.errorExpected(p.pos, "rule name"); - p.next(); // make progress in any case + p.errorExpected(p.pos, "rule name") + p.next() // make progress in any case } - return name, isIdent; + return name, isIdent } func (p *parser) parseString() string { - s := ""; + s := "" if p.tok == token.STRING { - s, _ = strconv.Unquote(string(p.lit)); + s, _ = strconv.Unquote(string(p.lit)) // Unquote may fail with an error, but only if the scanner found // an illegal string in the first place. In this case the error // has already been reported. - p.next(); - return s; + p.next() + return s } else { p.expect(token.STRING) } - return s; + return s } func (p *parser) parseLiteral() literal { - s := strings.Bytes(p.parseString()); + s := strings.Bytes(p.parseString()) // A string literal may contain %-format specifiers. To simplify // and speed up printing of the literal, split it into segments // that start with "%" possibly followed by a last segment that // starts with some other character. - var list vector.Vector; - i0 := 0; + var list vector.Vector + i0 := 0 for i := 0; i < len(s); i++ { if s[i] == '%' && i+1 < len(s) { // the next segment starts with a % format if i0 < i { // the current segment is not empty, split it off - list.Push(s[i0:i]); - i0 = i; + list.Push(s[i0:i]) + i0 = i } - i++; // skip %; let loop skip over char after % + i++ // skip %; let loop skip over char after % } } // the final segment may start with any character // (it is empty iff the string is empty) - list.Push(s[i0:]); + list.Push(s[i0:]) // convert list into a literal - lit := make(literal, list.Len()); + lit := make(literal, list.Len()) for i := 0; i < list.Len(); i++ { lit[i] = list.At(i).([]byte) } - return lit; + return lit } func (p *parser) parseField() expr { - var fname string; + var fname string switch p.tok { case token.ILLEGAL: if string(p.lit) != "@" { return nil } - fname = "@"; - p.next(); + fname = "@" + p.next() case token.MUL: - fname = "*"; - p.next(); + fname = "*" + p.next() case token.IDENT: fname = p.parseIdentifier() default: return nil } - var ruleName string; + var ruleName string if p.tok == token.COLON { - p.next(); - ruleName, _ = p.parseRuleName(); + p.next() + ruleName, _ = p.parseRuleName() } - return &field{fname, ruleName}; + return &field{fname, ruleName} } @@ -204,40 +204,40 @@ func (p *parser) parseOperand() (x expr) { x = p.parseLiteral() case token.LPAREN: - p.next(); - x = p.parseExpression(); + p.next() + x = p.parseExpression() if p.tok == token.SHR { - p.next(); - x = &group{x, p.parseExpression()}; + p.next() + x = &group{x, p.parseExpression()} } - p.expect(token.RPAREN); + p.expect(token.RPAREN) case token.LBRACK: - p.next(); - x = &option{p.parseExpression()}; - p.expect(token.RBRACK); + p.next() + x = &option{p.parseExpression()} + p.expect(token.RBRACK) case token.LBRACE: - p.next(); - x = p.parseExpression(); - var div expr; + p.next() + x = p.parseExpression() + var div expr if p.tok == token.QUO { - p.next(); - div = p.parseExpression(); + p.next() + div = p.parseExpression() } - x = &repetition{x, div}; - p.expect(token.RBRACE); + x = &repetition{x, div} + p.expect(token.RBRACE) default: - x = p.parseField() // may be nil + x = p.parseField() // may be nil } - return x; + return x } func (p *parser) parseSequence() expr { - var list vector.Vector; + var list vector.Vector for x := p.parseOperand(); x != nil; x = p.parseOperand() { list.Push(x) @@ -252,26 +252,26 @@ func (p *parser) parseSequence() expr { } // convert list into a sequence - seq := make(sequence, list.Len()); + seq := make(sequence, list.Len()) for i := 0; i < list.Len(); i++ { seq[i] = list.At(i).(expr) } - return seq; + return seq } func (p *parser) parseExpression() expr { - var list vector.Vector; + var list vector.Vector for { - x := p.parseSequence(); + x := p.parseSequence() if x != nil { list.Push(x) } if p.tok != token.OR { break } - p.next(); + p.next() } // no need for an alternatives if list.Len() < 2 @@ -283,23 +283,23 @@ func (p *parser) parseExpression() expr { } // convert list into a alternatives - alt := make(alternatives, list.Len()); + alt := make(alternatives, list.Len()) for i := 0; i < list.Len(); i++ { alt[i] = list.At(i).(expr) } - return alt; + return alt } func (p *parser) parseFormat() { for p.tok != token.EOF { - pos := p.pos; + pos := p.pos - name, isIdent := p.parseRuleName(); + name, isIdent := p.parseRuleName() switch p.tok { case token.STRING: // package declaration - importPath := p.parseString(); + importPath := p.parseString() // add package declaration if !isIdent { @@ -312,8 +312,8 @@ func (p *parser) parseFormat() { case token.ASSIGN: // format rule - p.next(); - x := p.parseExpression(); + p.next() + x := p.parseExpression() // add rule if _, found := p.rules[name]; !found { @@ -323,8 +323,8 @@ func (p *parser) parseFormat() { } default: - p.errorExpected(p.pos, "package declaration or format rule"); - p.next(); // make progress in any case + p.errorExpected(p.pos, "package declaration or format rule") + p.next() // make progress in any case } if p.tok == token.SEMICOLON { @@ -333,23 +333,23 @@ func (p *parser) parseFormat() { break } } - p.expect(token.EOF); + p.expect(token.EOF) } func remap(p *parser, name string) string { - i := strings.Index(name, "."); + i := strings.Index(name, ".") if i >= 0 { - packageName, suffix := name[0:i], name[i:]; + packageName, suffix := name[0:i], name[i:] // lookup package if importPath, found := p.packs[packageName]; found { name = importPath + suffix } else { - var invalidPos token.Position; - p.Error(invalidPos, "package not declared: "+packageName); + var invalidPos token.Position + p.Error(invalidPos, "package not declared: "+packageName) } } - return name; + return name } @@ -360,20 +360,20 @@ func remap(p *parser, name string) string { // func Parse(filename string, src []byte, fmap FormatterMap) (Format, os.Error) { // parse source - var p parser; - p.init(filename, src); - p.parseFormat(); + var p parser + p.init(filename, src) + p.parseFormat() // add custom formatters, if any for name, form := range fmap { - name = remap(&p, name); + name = remap(&p, name) if _, found := p.rules[name]; !found { p.rules[name] = &custom{name, form} } else { - var invalidPos token.Position; - p.Error(invalidPos, "formatter already declared: "+name); + var invalidPos token.Position + p.Error(invalidPos, "formatter already declared: "+name) } } - return p.rules, p.GetError(scanner.NoMultiples); + return p.rules, p.GetError(scanner.NoMultiples) } |