mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
type string parser; now handles all types
R=rsc DELTA=253 (153 added, 81 deleted, 19 changed) OCL=17331 CL=17331
This commit is contained in:
parent
7cb6b6788c
commit
060f157dc8
3 changed files with 169 additions and 97 deletions
|
|
@ -10,29 +10,6 @@ import (
|
|||
|
||||
func main() {
|
||||
var s string;
|
||||
|
||||
if false {
|
||||
s = reflect.ToString(reflect.Int8); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Int16); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Int32); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Int64); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Uint8); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Uint16); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Uint32); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Uint64); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Float32); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Float64); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Float80); print(s, "\n");
|
||||
s = reflect.ToString(reflect.String); print(s, "\n");
|
||||
|
||||
s = reflect.ToString(reflect.PtrInt8); print(s, "\n");
|
||||
s = reflect.ToString(reflect.PtrPtrInt8); print(s, "\n");
|
||||
s = reflect.ToString(reflect.ArrayFloat32); print(s, "\n");
|
||||
s = reflect.ToString(reflect.MapStringInt16); print(s, "\n");
|
||||
s = reflect.ToString(reflect.ChanArray); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Structure); print(s, "\n");
|
||||
s = reflect.ToString(reflect.Function); print(s, "\n");
|
||||
}
|
||||
var t reflect.Type;
|
||||
|
||||
t = reflect.ParseTypeString("int8");
|
||||
|
|
@ -52,4 +29,16 @@ func main() {
|
|||
|
||||
t = reflect.ParseTypeString("map[string]int32");
|
||||
s = reflect.ToString(t); print(s, "\n");
|
||||
|
||||
t = reflect.ParseTypeString("*chan<-string");
|
||||
s = reflect.ToString(t); print(s, "\n");
|
||||
|
||||
t = reflect.ParseTypeString("struct {c *chan *int32; d float32}");
|
||||
s = reflect.ToString(t); print(s, "\n");
|
||||
|
||||
t = reflect.ParseTypeString("*(a int8, b int32)");
|
||||
s = reflect.ToString(t); print(s, "\n");
|
||||
|
||||
t = reflect.ParseTypeString("struct {c *(? *chan *int32, ? *int8)}");
|
||||
s = reflect.ToString(t); print(s, "\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ import (
|
|||
|
||||
export func ToString(typ Type) string
|
||||
|
||||
func FieldsToString(t Type) string {
|
||||
func FieldsToString(t Type, sep string) string {
|
||||
s := t.(StructType);
|
||||
var str string;
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
str1, t := s.Field(i);
|
||||
str1 += " " + ToString(t);
|
||||
if i < s.Len() - 1 {
|
||||
str1 += "; ";
|
||||
str1 += sep + " ";
|
||||
}
|
||||
str += str1;
|
||||
}
|
||||
|
|
@ -86,16 +86,15 @@ func ToString(typ Type) string {
|
|||
}
|
||||
return str + ToString(c.Elem());
|
||||
case StructKind:
|
||||
return "struct{" + FieldsToString(typ) + "}";
|
||||
return "struct{" + FieldsToString(typ, ";") + "}";
|
||||
case InterfaceKind:
|
||||
return "interface{" + FieldsToString(typ, ";") + "}";
|
||||
case FuncKind:
|
||||
f := typ.(FuncType);
|
||||
str = "func";
|
||||
if f.Receiver() != nil {
|
||||
str += "(" + FieldsToString(f.Receiver()) + ")";
|
||||
}
|
||||
str += "(" + FieldsToString(f.In()) + ")";
|
||||
str += "(" + FieldsToString(f.In(), ",") + ")";
|
||||
if f.Out() != nil {
|
||||
str += "(" + FieldsToString(f.Out()) + ")";
|
||||
str += "(" + FieldsToString(f.Out(), ",") + ")";
|
||||
}
|
||||
return str;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export const (
|
|||
Int32Kind;
|
||||
Int64Kind;
|
||||
Int8Kind;
|
||||
InterfaceKind;
|
||||
MapKind;
|
||||
PtrKind;
|
||||
StringKind;
|
||||
|
|
@ -241,26 +242,45 @@ func (t *StructTypeStruct) Len() int {
|
|||
return len(t.field)
|
||||
}
|
||||
|
||||
func Struct(field *[]Field) *StructTypeStruct {
|
||||
t := new(StructTypeStruct);
|
||||
t.field = field;
|
||||
return t;
|
||||
}
|
||||
|
||||
func NewStructTypeStruct(field *[]Field) *StructTypeStruct {
|
||||
t := new(StructTypeStruct);
|
||||
t.field = field;
|
||||
return t;
|
||||
}
|
||||
|
||||
export type InterfaceType interface {
|
||||
Field(int) (name string, typ Type);
|
||||
Len() int;
|
||||
}
|
||||
|
||||
type InterfaceTypeStruct struct {
|
||||
field *[]Field;
|
||||
}
|
||||
|
||||
func (t *InterfaceTypeStruct) Field(i int) (name string, typ Type) {
|
||||
return t.field[i].name, t.field[i].typ.Get()
|
||||
}
|
||||
|
||||
func (t *InterfaceTypeStruct) Len() int {
|
||||
return len(t.field)
|
||||
}
|
||||
|
||||
func NewInterfaceTypeStruct(field *[]Field) *InterfaceTypeStruct {
|
||||
t := new(InterfaceTypeStruct);
|
||||
t.field = field;
|
||||
return t;
|
||||
}
|
||||
|
||||
func (t *InterfaceTypeStruct) Kind() int {
|
||||
return InterfaceKind
|
||||
}
|
||||
|
||||
export type FuncType interface {
|
||||
Receiver() StructType;
|
||||
In() StructType;
|
||||
Out() StructType;
|
||||
}
|
||||
|
||||
type FuncTypeStruct struct {
|
||||
receiver *StructTypeStruct;
|
||||
in *StructTypeStruct;
|
||||
out *StructTypeStruct;
|
||||
}
|
||||
|
|
@ -269,45 +289,24 @@ func (t *FuncTypeStruct) Kind() int {
|
|||
return FuncKind
|
||||
}
|
||||
|
||||
func (t *FuncTypeStruct) Receiver() StructType {
|
||||
return t.receiver
|
||||
}
|
||||
|
||||
func (t *FuncTypeStruct) In() StructType {
|
||||
return t.in
|
||||
}
|
||||
|
||||
func (t *FuncTypeStruct) Out() StructType {
|
||||
if t.out == nil { // nil.(StructType) != nil so make sure caller sees real nil
|
||||
return nil
|
||||
}
|
||||
return t.out
|
||||
}
|
||||
|
||||
func NewFuncTypeStruct(receiver, in, out *StructTypeStruct) *FuncTypeStruct {
|
||||
func NewFuncTypeStruct(in, out *StructTypeStruct) *FuncTypeStruct {
|
||||
t := new(FuncTypeStruct);
|
||||
t.receiver = receiver;
|
||||
t.in = in;
|
||||
t.out = out;
|
||||
return t;
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
//helpers for early bootstrap and debugging
|
||||
func Stub(n string, t Type) *StubType {
|
||||
s := new(StubType);
|
||||
s.name = n;
|
||||
s.typ = t;
|
||||
return s;
|
||||
}
|
||||
export var PtrInt8 Type = NewPtrTypeStruct(Stub("i", Int8));
|
||||
export var PtrPtrInt8 Type = NewPtrTypeStruct(Stub("i", PtrInt8));
|
||||
export var ArrayFloat32 Type = NewArrayTypeStruct(100, Stub("f", Float32));
|
||||
export var MapStringInt16 Type = NewMapTypeStruct(Stub("s", String), Stub("i", Int16));
|
||||
export var ChanArray Type = NewChanTypeStruct(RecvDir, Stub("a", ArrayFloat32));
|
||||
var F1 = Field{"i", Stub("i", Int64)};
|
||||
var Fields = []Field{F1};
|
||||
export var Structure = NewStructTypeStruct(&Fields);
|
||||
export var Function Type = NewFuncTypeStruct(Structure, Structure, Structure);
|
||||
////////////////////////
|
||||
|
||||
// Cache of expanded types keyed by type name.
|
||||
var types *map[string] *Type // BUG TODO: should be Type not *Type
|
||||
// List of typename, typestring pairs
|
||||
|
|
@ -380,7 +379,7 @@ func init() {
|
|||
typename =
|
||||
name '.' name
|
||||
fieldlist =
|
||||
[ field { ',' field } ]
|
||||
[ field { [ ',' | ';' ] field } ]
|
||||
field =
|
||||
identifier stubtype
|
||||
arraytype =
|
||||
|
|
@ -402,12 +401,13 @@ func init() {
|
|||
|
||||
*/
|
||||
|
||||
// Helper functions for token scanning
|
||||
func isdigit(c uint8) bool {
|
||||
return '0' <= c && c <= '9'
|
||||
}
|
||||
|
||||
func special(c uint8) bool {
|
||||
s := "*[](){}<"; // Note: '.' is not in this list. "P.T" is an identifer, as is "?".
|
||||
s := "*[](){}<;,"; // Note: '.' is not in this list. "P.T" is an identifer, as is "?".
|
||||
for i := 0; i < len(s); i++ {
|
||||
if c == s[i] {
|
||||
return true
|
||||
|
|
@ -416,12 +416,14 @@ func special(c uint8) bool {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Simple parser for type strings
|
||||
type Parser struct {
|
||||
str string;
|
||||
index int;
|
||||
token string;
|
||||
str string; // string being parsed
|
||||
token string; // the token being parsed now
|
||||
index int; // next character position in str
|
||||
}
|
||||
|
||||
// Load next token into p.token
|
||||
func (p *Parser) Next() {
|
||||
token := "";
|
||||
for ; p.index < len(p.str) && p.str[p.index] == ' '; p.index++ {
|
||||
|
|
@ -434,28 +436,15 @@ func (p *Parser) Next() {
|
|||
c, w := sys.stringtorune(p.str, p.index);
|
||||
p.index += w;
|
||||
switch {
|
||||
case c == '*':
|
||||
p.token = "*";
|
||||
return;
|
||||
case c == '[':
|
||||
p.token = "[";
|
||||
return;
|
||||
case c == ']':
|
||||
p.token = "]";
|
||||
return;
|
||||
case c == '(':
|
||||
p.token = "(";
|
||||
return;
|
||||
case c == ')':
|
||||
p.token = ")";
|
||||
return;
|
||||
case c == '<':
|
||||
if p.index < len(p.str) && p.str[p.index+1] == '-' {
|
||||
if p.index < len(p.str) && p.str[p.index] == '-' {
|
||||
p.index++;
|
||||
p.token = "<-";
|
||||
return;
|
||||
}
|
||||
p.token = "<"; // shouldn't happen but let the parser figure it out
|
||||
fallthrough; // shouldn't happen but let the parser figure it out
|
||||
case special(uint8(c)):
|
||||
p.token = string(c);
|
||||
return;
|
||||
case isdigit(uint8(c)):
|
||||
for p.index < len(p.str) && isdigit(p.str[p.index]) {
|
||||
|
|
@ -464,7 +453,7 @@ func (p *Parser) Next() {
|
|||
p.token = p.str[start : p.index];
|
||||
return;
|
||||
}
|
||||
for p.index < len(p.str) && !special(p.str[p.index]) {
|
||||
for p.index < len(p.str) && p.str[p.index] != ' ' && !special(p.str[p.index]) {
|
||||
p.index++
|
||||
}
|
||||
p.token = p.str[start : p.index];
|
||||
|
|
@ -507,27 +496,127 @@ func (p *Parser) Map() *StubType {
|
|||
return NewStubType(NewMapTypeStruct(keytype, elemtype));
|
||||
}
|
||||
|
||||
func (p *Parser) Simple() *StubType {
|
||||
func (p *Parser) Chan(dir int) *StubType {
|
||||
if p.token == "<-" {
|
||||
if dir != BothDir {
|
||||
return MissingStub
|
||||
}
|
||||
p.Next();
|
||||
dir = SendDir;
|
||||
}
|
||||
elemtype := p.Type();
|
||||
return NewStubType(NewChanTypeStruct(dir, elemtype));
|
||||
}
|
||||
|
||||
// Parse array of fields for struct, interface, and func arguments
|
||||
func (p *Parser) Fields(sep string) *[]Field {
|
||||
a := new([]Field, 10);
|
||||
nf := 0;
|
||||
for p.token != "" && !special(p.token[0]) {
|
||||
if nf == len(a) {
|
||||
a1 := new([]Field, 2*nf);
|
||||
for i := 0; i < nf; i++ {
|
||||
a1[i] = a[i];
|
||||
}
|
||||
a = a1;
|
||||
}
|
||||
a[nf].name = p.token;
|
||||
p.Next();
|
||||
a[nf].typ = p.Type();
|
||||
nf++;
|
||||
if p.token != sep {
|
||||
break;
|
||||
}
|
||||
p.Next(); // skip separator
|
||||
}
|
||||
return a[0:nf];
|
||||
}
|
||||
|
||||
func (p *Parser) Struct() *StubType {
|
||||
f := p.Fields(";");
|
||||
if p.token != "}" {
|
||||
return MissingStub;
|
||||
}
|
||||
p.Next();
|
||||
return NewStubType(NewStructTypeStruct(f));
|
||||
}
|
||||
|
||||
func (p *Parser) Interface() *StubType {
|
||||
f := p.Fields(";");
|
||||
if p.token != "}" {
|
||||
return MissingStub;
|
||||
}
|
||||
p.Next();
|
||||
return NewStubType(NewInterfaceTypeStruct(f));
|
||||
}
|
||||
|
||||
func (p *Parser) Func() *StubType {
|
||||
// may be 1 or 2 parenthesized lists
|
||||
f1 := NewStructTypeStruct(p.Fields(","));
|
||||
if p.token != ")" {
|
||||
return MissingStub;
|
||||
}
|
||||
p.Next();
|
||||
if p.token != "(" {
|
||||
// 1 list: the in parameters only
|
||||
return NewStubType(NewFuncTypeStruct(f1, nil));
|
||||
}
|
||||
p.Next();
|
||||
f2 := NewStructTypeStruct(p.Fields(","));
|
||||
if p.token != ")" {
|
||||
return MissingStub;
|
||||
}
|
||||
p.Next();
|
||||
// 2 lists: the in and out parameters are present
|
||||
return NewStubType(NewFuncTypeStruct(f1, f2));
|
||||
}
|
||||
|
||||
func (p *Parser) Type() *StubType {
|
||||
dir := BothDir;
|
||||
switch {
|
||||
case p.token == "":
|
||||
return nil;
|
||||
case p.token == "*":
|
||||
p.Next();
|
||||
return NewStubType(NewPtrTypeStruct(p.Simple()));
|
||||
return NewStubType(NewPtrTypeStruct(p.Type()));
|
||||
case p.token == "[":
|
||||
p.Next();
|
||||
return p.Array();
|
||||
case p.token == "map":
|
||||
p.Next();
|
||||
return p.Map();
|
||||
case p.token == "<-":
|
||||
p.Next();
|
||||
dir = RecvDir;
|
||||
if p.token != "chan" {
|
||||
return MissingStub;
|
||||
}
|
||||
fallthrough;
|
||||
case p.token == "chan":
|
||||
p.Next();
|
||||
return p.Chan(dir);
|
||||
case p.token == "struct":
|
||||
p.Next();
|
||||
if p.token != "{" {
|
||||
return MissingStub
|
||||
}
|
||||
p.Next();
|
||||
return p.Struct();
|
||||
case p.token == "interface":
|
||||
p.Next();
|
||||
if p.token != "{" {
|
||||
return MissingStub
|
||||
}
|
||||
p.Next();
|
||||
return p.Interface();
|
||||
case p.token == "(":
|
||||
p.Next();
|
||||
return p.Func();
|
||||
case isdigit(p.token[0]):
|
||||
p.Next();
|
||||
print("reflect.Simple: number encountered\n"); // TODO: remove
|
||||
return MissingStub;
|
||||
case special(p.token[0]):
|
||||
// TODO: get chans right
|
||||
p.Next();
|
||||
print("reflect.Simple: special character encountered\n"); // TODO: remove
|
||||
return MissingStub;
|
||||
}
|
||||
// must be an identifier. is it basic? if so, we have a stub
|
||||
|
|
@ -543,7 +632,6 @@ func (p *Parser) Simple() *StubType {
|
|||
}
|
||||
}
|
||||
if ndot != 1 {
|
||||
print("reflect.Simple: illegal identifier ", p.token, "\n"); // TODO: remove
|
||||
p.Next();
|
||||
return MissingStub;
|
||||
}
|
||||
|
|
@ -553,10 +641,6 @@ func (p *Parser) Simple() *StubType {
|
|||
return s;
|
||||
}
|
||||
|
||||
func (p *Parser) Type() *StubType {
|
||||
return p.Simple();
|
||||
}
|
||||
|
||||
export func ParseTypeString(str string) Type {
|
||||
p := new(Parser);
|
||||
p.str = str;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue