summaryrefslogtreecommitdiff
path: root/parser/decl.go
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2024-03-22 16:59:25 +0100
committerGitHub <noreply@github.com>2024-03-22 16:59:25 +0100
commit362f7c9c45598b429c92e67756f41b690043e0c4 (patch)
tree59dd897446880912b4a2ca4a3a8d8c49e3553211 /parser/decl.go
parentbf2d6438e95c60946c64a6692e3dae1d836364a6 (diff)
feat: add initial support for import, provide minimal fmt (#6)
The `import` statement is now parsed. It only provides minimal support for the `fmt` package (only `Println` symbol is defined). This should be sufficient to pass a few tests. Full support of package namespaces, source and binary imports will be supported later, based on this work.
Diffstat (limited to 'parser/decl.go')
-rw-r--r--parser/decl.go59
1 files changed, 59 insertions, 0 deletions
diff --git a/parser/decl.go b/parser/decl.go
index d794131..7638b75 100644
--- a/parser/decl.go
+++ b/parser/decl.go
@@ -2,8 +2,10 @@ package parser
import (
"errors"
+ "fmt"
"go/constant"
"go/token"
+ "path"
"strings"
"github.com/mvertes/parscan/lang"
@@ -189,6 +191,63 @@ var gotok = map[lang.TokenId]token.Token{
lang.Not: token.NOT,
}
+func (p *Parser) ParseImport(in Tokens) (out Tokens, err error) {
+ if p.fname != "" {
+ return out, errors.New("unexpected import")
+ }
+ if len(in) < 2 {
+ return out, errors.New("missing expression")
+ }
+ if in[1].Id != lang.ParenBlock {
+ return p.parseImportLine(in[1:])
+ }
+ if in, err = p.Scan(in[1].Block(), false); err != nil {
+ return out, err
+ }
+ for _, li := range in.Split(lang.Semicolon) {
+ ot, err := p.parseImportLine(li)
+ if err != nil {
+ return out, err
+ }
+ out = append(out, ot...)
+ }
+ return out, err
+}
+
+func (p *Parser) parseImportLine(in Tokens) (out Tokens, err error) {
+ l := len(in)
+ if l != 1 && l != 2 {
+ return out, errors.New("invalid number of arguments")
+ }
+ if in[l-1].Id != lang.String {
+ return out, fmt.Errorf("invalid argument %v", in[0])
+ }
+ pp := in[l-1].Block()
+ pkg, ok := packages[pp]
+ if !ok {
+ // TODO: try to import source package from here.
+ return out, fmt.Errorf("package not found: %s", pp)
+ }
+ n := in[0].Str
+ if l == 1 {
+ // Derive package name from package path.
+ d, f := path.Split(pp)
+ n = f
+ if ok, _ := path.Match(f, "v[0-9]*"); d != "" && ok {
+ n = path.Base(d)
+ }
+ }
+ if n == "." {
+ // Import package symbols in the current scope.
+ for k, v := range pkg {
+ p.symbols[k] = &symbol{index: unsetAddr, pkgPath: pp, value: v}
+ }
+ } else {
+ p.symbols[n] = &symbol{kind: symPkg, pkgPath: pp, index: unsetAddr}
+ }
+ return out, err
+}
+
func (p *Parser) ParseType(in Tokens) (out Tokens, err error) {
if len(in) < 2 {
return out, MissingTypeErr