diff options
| author | Marc Vertes <mvertes@free.fr> | 2024-03-22 16:59:25 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-22 16:59:25 +0100 |
| commit | 362f7c9c45598b429c92e67756f41b690043e0c4 (patch) | |
| tree | 59dd897446880912b4a2ca4a3a8d8c49e3553211 /parser/decl.go | |
| parent | bf2d6438e95c60946c64a6692e3dae1d836364a6 (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.go | 59 |
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 |
