diff options
Diffstat (limited to 'parser')
| -rw-r--r-- | parser/decl.go | 23 | ||||
| -rw-r--r-- | parser/expr.go | 5 | ||||
| -rw-r--r-- | parser/parse.go | 17 | ||||
| -rw-r--r-- | parser/symbol.go | 89 | ||||
| -rw-r--r-- | parser/symkind_string.go | 30 | ||||
| -rw-r--r-- | parser/type.go | 17 |
6 files changed, 34 insertions, 147 deletions
diff --git a/parser/decl.go b/parser/decl.go index 876b2ca..f6e8102 100644 --- a/parser/decl.go +++ b/parser/decl.go @@ -10,6 +10,7 @@ import ( "github.com/mvertes/parscan/lang" "github.com/mvertes/parscan/scanner" + "github.com/mvertes/parscan/symbol" "github.com/mvertes/parscan/vm" ) @@ -57,7 +58,7 @@ func (p *Parser) parseConstLine(in Tokens) (out Tokens, err error) { for _, lt := range decl.Split(lang.Comma) { vars = append(vars, lt[0].Str) name := strings.TrimPrefix(p.scope+"/"+lt[0].Str, "/") - p.AddSymbol(UnsetAddr, name, nilValue, SymConst, nil, false) + p.Symbols.Add(symbol.UnsetAddr, name, nilValue, symbol.Const, nil, false) } } else { return out, err @@ -76,9 +77,9 @@ func (p *Parser) parseConstLine(in Tokens) (out Tokens, err error) { return out, err } name := strings.TrimPrefix(p.scope+"/"+vars[i], "/") - p.Symbols[name] = &Symbol{ - Kind: SymConst, - Index: UnsetAddr, + p.Symbols[name] = &symbol.Symbol{ + Kind: symbol.Const, + Index: symbol.UnsetAddr, Cval: cval, Value: vm.ValueOf(constValue(cval)), Local: p.funcScope != "", @@ -131,11 +132,11 @@ func (p *Parser) evalConstExpr(in Tokens) (cval constant.Value, length int, err case id.IsLiteral(): return constant.MakeFromLiteral(t.Str, gotok[id], 0), 1, err case id == lang.Ident: - s, _, ok := p.GetSym(t.Str, p.scope) + s, _, ok := p.Symbols.Get(t.Str, p.scope) if !ok { return nil, 0, errors.New("symbol not found") } - if s.Kind != SymConst { + if s.Kind != symbol.Const { return nil, 0, errors.New("symbol is not a constant") } return s.Cval, 1, err @@ -240,10 +241,10 @@ func (p *Parser) parseImportLine(in Tokens) (out Tokens, err error) { if n == "." { // Import package symbols in the current scope. for k, v := range pkg { - p.Symbols[k] = &Symbol{Index: UnsetAddr, PkgPath: pp, Value: v} + p.Symbols[k] = &symbol.Symbol{Index: symbol.UnsetAddr, PkgPath: pp, Value: v} } } else { - p.Symbols[n] = &Symbol{Kind: SymPkg, PkgPath: pp, Index: UnsetAddr} + p.Symbols[n] = &symbol.Symbol{Kind: symbol.Pkg, PkgPath: pp, Index: symbol.UnsetAddr} } return out, err } @@ -299,7 +300,7 @@ func (p *Parser) parseTypeLine(in Tokens) (out Tokens, err error) { return out, err } typ.Name = in[0].Str - p.AddSymbol(UnsetAddr, in[0].Str, vm.NewValue(typ), SymType, typ, p.funcScope != "") + p.Symbols.Add(symbol.UnsetAddr, in[0].Str, vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") return out, err } @@ -336,10 +337,10 @@ func (p *Parser) parseVarLine(in Tokens) (out Tokens, err error) { vars = append(vars, lt[0].Str) name := strings.TrimPrefix(p.scope+"/"+lt[0].Str, "/") if p.funcScope == "" { - p.AddSymbol(UnsetAddr, name, nilValue, SymVar, nil, false) + p.Symbols.Add(symbol.UnsetAddr, name, nilValue, symbol.Var, nil, false) continue } - p.AddSymbol(p.framelen[p.funcScope], name, nilValue, SymVar, nil, false) + p.Symbols.Add(p.framelen[p.funcScope], name, nilValue, symbol.Var, nil, false) p.framelen[p.funcScope]++ } } else { diff --git a/parser/expr.go b/parser/expr.go index 1732b8d..5958279 100644 --- a/parser/expr.go +++ b/parser/expr.go @@ -7,6 +7,7 @@ import ( "github.com/mvertes/parscan/lang" "github.com/mvertes/parscan/scanner" + "github.com/mvertes/parscan/symbol" "github.com/mvertes/parscan/vm" ) @@ -42,7 +43,7 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) { continue } // resolve symbol if not a selector rhs. - _, sc, ok := p.GetSym(t.Str, p.scope) + _, sc, ok := p.Symbols.Get(t.Str, p.scope) if ok { if sc != "" { t.Str = sc + "/" + t.Str @@ -111,7 +112,7 @@ func (p *Parser) parseExpr(in Tokens) (out Tokens, err error) { if err != nil { return out, ErrInvalidType } - p.AddSymbol(UnsetAddr, typ.String(), vm.NewValue(typ), SymType, typ, p.funcScope != "") + p.Symbols.Add(symbol.UnsetAddr, typ.String(), vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") out = append(out, t, scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: typ.String()}) i = ti vl += 2 diff --git a/parser/parse.go b/parser/parse.go index 6cfdc08..e7d5399 100644 --- a/parser/parse.go +++ b/parser/parse.go @@ -10,14 +10,15 @@ import ( "github.com/mvertes/parscan/lang" "github.com/mvertes/parscan/scanner" + "github.com/mvertes/parscan/symbol" ) // Parser represents the state of a parser. type Parser struct { *scanner.Scanner - Symbols map[string]*Symbol - function *Symbol + Symbols symbol.SymMap + function *symbol.Symbol scope string fname string pkgName string // current package name @@ -42,13 +43,15 @@ var ( // NewParser returns a new parser. func NewParser(spec *lang.Spec, noPkg bool) *Parser { - return &Parser{ + p := &Parser{ Scanner: scanner.NewScanner(spec), + Symbols: symbol.SymMap{}, noPkg: noPkg, - Symbols: initUniverse(), framelen: map[string]int{}, labelCount: map[string]int{}, } + p.Symbols.Init() + return p } // Scan performs lexical analysis on s and returns Tokens or an error. @@ -255,9 +258,9 @@ func (p *Parser) parseFunc(in Tokens) (out Tokens, err error) { p.fname = fname ofunc := p.function funcScope := p.funcScope - s, _, ok := p.GetSym(fname, p.scope) + s, _, ok := p.Symbols.Get(fname, p.scope) if !ok { - s = &Symbol{Used: true} + s = &symbol.Symbol{Used: true} p.Symbols[p.scope+fname] = s } p.pushScope(fname) @@ -282,7 +285,7 @@ func (p *Parser) parseFunc(in Tokens) (out Tokens, err error) { if err != nil { return out, err } - s.Kind = SymFunc + s.Kind = symbol.Func s.Type = typ p.function = s diff --git a/parser/symbol.go b/parser/symbol.go deleted file mode 100644 index 3ad8fda..0000000 --- a/parser/symbol.go +++ /dev/null @@ -1,89 +0,0 @@ -package parser - -import ( - "fmt" - "go/constant" - "strings" - - "github.com/mvertes/parscan/vm" -) - -// SymKind represents the symbol kind. -type SymKind int - -// Symbol kinds. -const ( - SymValue SymKind = iota // a value defined in the runtime - SymType // a type - SymLabel // a label indication a position in the VM code - SymConst // a constant - SymVar // a variable, located in the VM memory - SymFunc // a function, located in the VM code - SymPkg // a package -) - -//go:generate stringer -type=SymKind - -// UnsetAddr denotes an unset symbol index (vs 0). -const UnsetAddr = -65535 - -// Symbol structure used in parser and compiler. -type Symbol struct { - Kind SymKind - Index int // address of symbol in frame - PkgPath string // - Type *vm.Type // - Value vm.Value // - Cval constant.Value // - Local bool // if true address is relative to local frame, otherwise global - Used bool // -} - -// SymbolType returns the VM type of a symbol. -func SymbolType(s *Symbol) *vm.Type { - if s.Type != nil { - return s.Type - } - return vm.TypeOf(s.Value) -} - -// AddSymbol adds a new named value at memory position i in the parser symbol table. -func (p *Parser) AddSymbol(i int, name string, v vm.Value, k SymKind, t *vm.Type, local bool) { - name = strings.TrimPrefix(name, "/") - p.Symbols[name] = &Symbol{Kind: k, Index: i, Local: local, Value: v, Type: t} -} - -// GetSym searches for an existing symbol starting from the deepest scope. -func (p *Parser) GetSym(name, scope string) (sym *Symbol, sc string, ok bool) { - for { - if sym, ok = p.Symbols[scope+"/"+name]; ok { - return sym, scope, ok - } - i := strings.LastIndex(scope, "/") - if i == -1 { - i = 0 - } - if scope = scope[:i]; scope == "" { - break - } - } - sym, ok = p.Symbols[name] - return sym, scope, ok -} - -func initUniverse() map[string]*Symbol { - return map[string]*Symbol{ - "any": {Kind: SymType, Index: UnsetAddr, Type: vm.TypeOf((*any)(nil)).Elem()}, - "bool": {Kind: SymType, Index: UnsetAddr, Type: vm.TypeOf((*bool)(nil)).Elem()}, - "error": {Kind: SymType, Index: UnsetAddr, Type: vm.TypeOf((*error)(nil)).Elem()}, - "int": {Kind: SymType, Index: UnsetAddr, Type: vm.TypeOf((*int)(nil)).Elem()}, - "string": {Kind: SymType, Index: UnsetAddr, Type: vm.TypeOf((*string)(nil)).Elem()}, - - "nil": {Index: UnsetAddr}, - "iota": {Kind: SymConst, Index: UnsetAddr}, - "true": {Index: UnsetAddr, Value: vm.ValueOf(true), Type: vm.TypeOf(true)}, - "false": {Index: UnsetAddr, Value: vm.ValueOf(false), Type: vm.TypeOf(false)}, - - "println": {Index: UnsetAddr, Value: vm.ValueOf(func(v ...any) { fmt.Println(v...) })}, - } -} diff --git a/parser/symkind_string.go b/parser/symkind_string.go deleted file mode 100644 index dc6a33d..0000000 --- a/parser/symkind_string.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by "stringer -type=SymKind"; DO NOT EDIT. - -package parser - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[SymValue-0] - _ = x[SymType-1] - _ = x[SymLabel-2] - _ = x[SymConst-3] - _ = x[SymVar-4] - _ = x[SymFunc-5] - _ = x[SymPkg-6] -} - -const _SymKind_name = "SymValueSymTypeSymLabelSymConstSymVarSymFuncSymPkg" - -var _SymKind_index = [...]uint8{0, 8, 15, 23, 31, 37, 44, 50} - -func (i SymKind) String() string { - idx := int(i) - 0 - if i < 0 || idx >= len(_SymKind_index)-1 { - return "SymKind(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _SymKind_name[_SymKind_index[idx]:_SymKind_index[idx+1]] -} diff --git a/parser/type.go b/parser/type.go index 6f75f6f..12bc06b 100644 --- a/parser/type.go +++ b/parser/type.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/mvertes/parscan/lang" + "github.com/mvertes/parscan/symbol" "github.com/mvertes/parscan/vm" ) @@ -100,8 +101,8 @@ func (p *Parser) parseTypeExpr(in Tokens) (typ *vm.Type, err error) { case lang.Ident: // TODO: selector expression (pkg.type) - s, _, ok := p.GetSym(in[0].Str, p.scope) - if !ok || s.Kind != SymType { + s, _, ok := p.Symbols.Get(in[0].Str, p.scope) + if !ok || s.Kind != symbol.Type { return nil, fmt.Errorf("%w: %s", ErrInvalidType, in[0].Str) } return s.Type, nil @@ -174,16 +175,16 @@ func (p *Parser) addSymVar(index int, name string, typ *vm.Type, flag typeFlag, zv := vm.NewValue(typ) switch flag { case parseTypeIn: - p.AddSymbol(-index-2, name, zv, SymVar, typ, true) + p.Symbols.Add(-index-2, name, zv, symbol.Var, typ, true) case parseTypeOut: - p.AddSymbol(p.framelen[p.funcScope], name, zv, SymVar, typ, true) + p.Symbols.Add(p.framelen[p.funcScope], name, zv, symbol.Var, typ, true) p.framelen[p.funcScope]++ case parseTypeVar: if !local { - p.AddSymbol(UnsetAddr, name, zv, SymVar, typ, local) + p.Symbols.Add(symbol.UnsetAddr, name, zv, symbol.Var, typ, local) break } - p.AddSymbol(p.framelen[p.funcScope], name, zv, SymVar, typ, local) + p.Symbols.Add(p.framelen[p.funcScope], name, zv, symbol.Var, typ, local) p.framelen[p.funcScope]++ } } @@ -193,8 +194,8 @@ func (p *Parser) hasFirstParam(in Tokens) bool { if in[0].Tok != lang.Ident { return false } - s, _, ok := p.GetSym(in[0].Str, p.scope) - return !ok || s.Kind != SymType + s, _, ok := p.Symbols.Get(in[0].Str, p.scope) + return !ok || s.Kind != symbol.Type } // typeStartIndex returns the index of the start of type expression in tokens, or -1. |
