Syntax tree now stores map of require names -> full paths

This commit is contained in:
Sasha Koshka 2022-09-07 17:12:46 -04:00
parent 596deaf0c3
commit 7e972e2132
6 changed files with 47 additions and 8 deletions

View File

@ -15,6 +15,14 @@ func (tree SyntaxTree) Sections () (iterator types.Iterator[Section]) {
return
}
// ResolveRequire returns the full path, from the filesystem root, of an import.
// This method will return false for exists if the module has not been
// imported.
func (tree SyntaxTree) ResolveRequire (name string) (path string, exists bool) {
path, exists = tree.requires[name]
return
}
// Kind returns the section's kind (SectionKindType).
func (section TypeSection) Kind () (kind SectionKind) {
kind = SectionKindType

View File

@ -1,10 +1,14 @@
package parser
import "os"
import "path/filepath"
import "git.tebibyte.media/arf/arf/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
// parseMeta parsese the metadata header at the top of an arf file.
func (parser *ParsingOperation) parseMeta () (err error) {
cwd, _ := os.Getwd()
for {
err = parser.expect (
lexer.TokenKindName,
@ -31,7 +35,30 @@ func (parser *ParsingOperation) parseMeta () (err error) {
case "license":
parser.tree.license = value
case "require":
parser.tree.requires = append(parser.tree.requires, value)
// if import path is relative, get absolute path.
if value[0] == '.' {
value = filepath.Join(cwd, value)
} else if value[0] != '/' {
// TODO: get arf import path from an env
// variable, and default to this if not found.
// then, search all paths.
value = filepath.Join (
"/usr/local/include/arf/",
value)
}
basename := filepath.Base(value)
_, exists := parser.tree.requires[basename]
if exists {
err = parser.token.NewError (
"cannot require \"" + basename +
"\" multiple times",
infoerr.ErrorKindError)
return
}
parser.tree.requires[basename] = value
default:
parser.token.NewError (
"unrecognized metadata field: " + field,

View File

@ -1,14 +1,18 @@
package parser
import "os"
import "testing"
import "path/filepath"
func TestMeta (test *testing.T) {
cwd, _ := os.Getwd()
checkTree ("../tests/parser/meta", false,
`:arf
author "Sasha Koshka"
license "GPLv3"
require "someModule"
require "otherModule"
require "` + filepath.Join(cwd, "./some/local/module") + `"
require "/some/absolute/path/to/someModule"
require "/usr/include/arf/someLibraryInstalledInStandardLocation"
---
`, test)
}

View File

@ -38,6 +38,7 @@ func Fetch (modulePath string, skim bool) (tree SyntaxTree, err error) {
modulePath: modulePath,
skimming: skim,
tree: SyntaxTree {
requires: make(map[string] string),
sections: make(map[string] Section),
},
}

View File

@ -4,8 +4,6 @@ import "git.tebibyte.media/arf/arf/file"
import "git.tebibyte.media/arf/arf/types"
import "git.tebibyte.media/arf/arf/infoerr"
// TODO: implement table of import names -> full paths from /. perhaps replace
// requires[] with this, and build it when parsing the meta section.
// SyntaxTree represents an abstract syntax tree. It covers an entire module. It
// can be expected to be syntactically correct, but it might not be semantically
// correct (because it has not been analyzed yet.)
@ -13,7 +11,7 @@ type SyntaxTree struct {
license string
author string
requires []string
requires map[string] string
sections map[string] Section
}

View File

@ -1,6 +1,7 @@
:arf
author "Sasha Koshka"
license "GPLv3"
require "someModule"
require "otherModule"
require "./some/local/module"
require "/some/absolute/path/to/someModule"
require "someLibraryInstalledInStandardLocation"
---