summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2025-12-04 13:28:22 +0100
committerMarc Vertes <mvertes@free.fr>2025-12-04 13:28:22 +0100
commitf07fc0178831432b68f1b9bd6c96b257aa2e9abe (patch)
treedc445dbf1b8946d09be7444b4f141a78e23a568f /parser
parent90284c5bedc5ab7bb442b34ef470744578dcd266 (diff)
chore: move symbol types and functions in its own package.HEADmain
Diffstat (limited to 'parser')
-rw-r--r--parser/decl.go23
-rw-r--r--parser/expr.go5
-rw-r--r--parser/parse.go17
-rw-r--r--parser/symbol.go89
-rw-r--r--parser/symkind_string.go30
-rw-r--r--parser/type.go17
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.