diff options
| -rw-r--r-- | parser/README.md | 2 | ||||
| -rw-r--r-- | parser/decl.go | 42 | ||||
| -rw-r--r-- | parser/interpreter_test.go | 11 | ||||
| -rw-r--r-- | parser/parse.go | 4 | ||||
| -rw-r--r-- | parser/type.go | 31 |
5 files changed, 72 insertions, 18 deletions
diff --git a/parser/README.md b/parser/README.md index ecb7c41..54fead3 100644 --- a/parser/README.md +++ b/parser/README.md @@ -52,7 +52,7 @@ Go language support: - [x] var defined by assign := - [x] var assign = - [x] var declaration -- [ ] type declaration +- [x] type declaration - [x] func declaration - [ ] const declaration - [ ] iota expression diff --git a/parser/decl.go b/parser/decl.go index fa07c17..6c10363 100644 --- a/parser/decl.go +++ b/parser/decl.go @@ -9,8 +9,48 @@ import ( "github.com/gnolang/parscan/scanner" ) +func (p *Parser) ParseType(in Tokens) (out Tokens, err error) { + if len(in) < 2 { + return out, missingTypeError + } + if in[1].Id != lang.ParenBlock { + return p.parseTypeLine(in[1:]) + } + if in, err = p.Scan(in[1].Block(), false); err != nil { + return out, err + } + for _, lt := range in.Split(lang.Semicolon) { + ot, err := p.parseTypeLine(lt) + if err != nil { + return out, err + } + out = append(out, ot...) + } + return out, err +} + +func (p *Parser) parseTypeLine(in Tokens) (out Tokens, err error) { + if len(in) < 2 { + return out, missingTypeError + } + if in[0].Id != lang.Ident { + return out, errors.New("not an ident") + } + isAlias := in[1].Id == lang.Assign + toks := in[1:] + if isAlias { + toks = toks[1:] + } + typ, err := p.ParseTypeExpr(toks) + if err != nil { + return out, err + } + p.addSym(unsetAddr, in[0].Str, nil, symType, typ, p.funcScope != "") + return out, err +} + func (p *Parser) ParseVar(in Tokens) (out Tokens, err error) { - if len(in) < 1 { + if len(in) < 2 { return out, errors.New("missing expression") } if in[1].Id != lang.ParenBlock { diff --git a/parser/interpreter_test.go b/parser/interpreter_test.go index edb6b0d..3a5598e 100644 --- a/parser/interpreter_test.go +++ b/parser/interpreter_test.go @@ -164,6 +164,17 @@ func TestSwitch(t *testing.T) { }) } +func TestType(t *testing.T) { + run(t, []etest{ + {src: "type t int; var a t = 1; a", res: "1"}, + {src: "type t = int; var a t = 1; a", res: "1"}, + {src: `type ( + I int + S string +); var s S = "xx"; s`, res: "xx"}, + }) +} + func TestVar(t *testing.T) { run(t, []etest{ {src: "var a int; a", res: "0"}, diff --git a/parser/parse.go b/parser/parse.go index a7675b4..7de73b6 100644 --- a/parser/parse.go +++ b/parser/parse.go @@ -87,6 +87,8 @@ func (p *Parser) ParseStmt(in Tokens) (out Tokens, err error) { return p.ParseReturn(in) case lang.Switch: return p.ParseSwitch(in) + case lang.Type: + return p.ParseType(in) case lang.Var: return p.ParseVar(in) case lang.Ident: @@ -226,7 +228,7 @@ func (p *Parser) ParseFunc(in Tokens) (out Tokens, err error) { if bi < 0 { return out, fmt.Errorf("no function body") } - typ, err := p.ParseType(in[:bi]) + typ, err := p.ParseTypeExpr(in[:bi]) if err != nil { return out, err } diff --git a/parser/type.go b/parser/type.go index 00aedc8..41bcfe1 100644 --- a/parser/type.go +++ b/parser/type.go @@ -3,17 +3,28 @@ package parser import ( "errors" "fmt" - "log" "reflect" "strings" "github.com/gnolang/parscan/lang" ) -// ParseType parses a list of tokens defining a type expresssion and returns +type typeFlag int + +const ( + parseTypeIn typeFlag = iota + parseTypeOut + parseTypeVar + parseTypeType +) + +var ( + missingTypeError = errors.New("Missing type") +) + +// ParseTypeExpr parses a list of tokens defining a type expresssion and returns // the corresponding runtime type or an error. -func (p *Parser) ParseType(in Tokens) (typ reflect.Type, err error) { - log.Println("ParseType", in) +func (p *Parser) ParseTypeExpr(in Tokens) (typ reflect.Type, err error) { switch in[0].Id { case lang.Func: // Get argument and return token positions depending on function pattern: @@ -65,16 +76,6 @@ func (p *Parser) ParseType(in Tokens) (typ reflect.Type, err error) { return typ, err } -type typeFlag int - -const ( - parseTypeIn typeFlag = iota - parseTypeOut - parseTypeVar -) - -var missingTypeError = errors.New("Missing type") - // parseParamTypes parses a list of comma separated typed parameters and returns a list of // runtime types. Implicit parameter names and types are supported. func (p *Parser) parseParamTypes(in Tokens, flag typeFlag) (types []reflect.Type, vars []string, err error) { @@ -101,7 +102,7 @@ func (p *Parser) parseParamTypes(in Tokens, flag typeFlag) (types []reflect.Type continue } } - typ, err := p.ParseType(t) + typ, err := p.ParseTypeExpr(t) if err != nil { return nil, nil, err } |
