summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
Diffstat (limited to 'parser')
-rw-r--r--parser/README.md2
-rw-r--r--parser/decl.go42
-rw-r--r--parser/interpreter_test.go11
-rw-r--r--parser/parse.go4
-rw-r--r--parser/type.go31
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
}