1 Star 1 Fork 1

U语言组织 / U语言

forked from 秋来冬风 / U语言 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
package.go 5.38 KB
一键复制 编辑 原始数据 按行查看 历史
package parser
import (
"bufio"
"bytes"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"gitee.com/u-language/u-language/ucom/ast"
"gitee.com/u-language/u-language/ucom/check"
"gitee.com/u-language/u-language/ucom/config"
"gitee.com/u-language/u-language/ucom/data"
"gitee.com/u-language/u-language/ucom/errcode"
"gitee.com/u-language/u-language/ucom/internal/time"
"gitee.com/u-language/u-language/ucom/internal/utils"
"gitee.com/u-language/u-language/ucom/lex"
)
var NoUFileErr = errors.New("没有U文件")
var ImportLimit = errors.New("目前import只支持相对路径导入")
var PathNotFound = errors.New("找不到的路径")
var notest bool
// ParserPackage 转换一个目录下所有扩展名为.u的源代码文件为抽象语法树
func ParserPackage(dir string, thread bool, errctx *errcode.ErrCtx, sbt *ast.Sbt, ImportPackage *map[string]*ast.Package) (*ast.Package, error) {
paths, err := utils.FindU(dir)
if err != nil {
return nil, err
}
if len(paths) == 0 {
return nil, fmt.Errorf("%s目录%w", dir, NoUFileErr)
}
p := ast.NewPackage(dir, thread, errctx, sbt, ImportPackage)
var wg = utils.NewWaitGroup(thread)
var t time.Time
var result = make(chan error, len(paths))
for _, v := range paths { //将所有源文件进行词法分析后加入包中
v := v
wg.Go(func() {
defer wg.Done()
file, size, buf, err := openfileAndInfo(v)
if err != nil {
result <- fmt.Errorf("path=%s \t err=%w", v, err)
return
}
var r *bufio.Reader
if !test || notest { //如果非测试
r = bufio.NewReaderSize(file, int(size))
} else {
r = bufio.NewReaderSize(bytes.NewBuffer(buf), int(size))
}
Filestr, err := utils.ReadAllLine(r)
if err != nil {
result <- fmt.Errorf("path=%s \t err=%w", v, err)
return
}
if !test { //如果非测试
file.Close()
}
FT := lex.Lex(v, Filestr, errctx, false) //进行词法分析
if FT == nil {
fmt.Println(v, "是空文件")
return
}
if errctx.Errbol() { //如果词法分析有错误·
return
}
p.AddFile(FT)
})
}
wg.Wait()
select {
case err = <-result:
if err != nil {
return nil, err
}
default:
}
p.Parser()
try_print(p)
err = loadAllImport(dir, p.ImportTable, p.ImportPackage, &p.ImportLoacl, thread, errctx, p.Sbt)
if err != nil {
return nil, err
}
//进行语义检查
try_new_print_check(&t)
check.CheckPackage(p, errctx, thread)
try_Print_Time(&t)
return p, nil
}
// try_new_print_LexTime 尝试设置词法分析用时统计标题
func try_new_print_LexTime(t *time.Time) {
if config.PrintTime == "on" { //如果启用打印用时
*t = time.NewTime("词法分析用时:")
}
}
// try_Print_Time 尝试打印用时
func try_Print_Time(t *time.Time) {
if config.PrintTime == "on" { //如果启用打印用时
t.PrintlnSubNow()
}
}
// try_print_FT 尝试打印词法分析结果
func try_print_FT(FT *lex.FileToken) {
if Debug && config.Debug_PrintLex == "on" { //调试操作
fmt.Println(FT)
}
}
// try_new_print_AstTime 尝试设置构建抽象语法树用时统计标题
func try_new_print_AstTime(t *time.Time) {
if config.PrintTime == "on" { //如果启用打印用时
*t = time.NewTime("构建抽象语法树用时:")
}
}
// try_print 尝试打印
func try_print(result fmt.Stringer) {
if Debug && config.Debug_PrintAst == "on" { //调试操作
fmt.Println(result.String())
}
}
// try_new_print_check 尝试设置语义检查用时统计标题
func try_new_print_check(t *time.Time) {
if config.PrintTime == "on" { //如果启用打印用时
*t = time.NewTime("语义检查用时:")
}
}
// loadAllImport 获取导入包的Ast
// - ImportTable 是导入表
// - ImportPackage 是自己及依赖导入的包
// - thread 控制是否并发
// - errctx 是错误处理上下文
// - importLoacl 自己导入的包
func loadAllImport(dir string, ImportTable *ast.Sbt, ImportPackage *map[string]*ast.Package, importLoacl *[]data.IsItARecursiveType, thread bool, errctx *errcode.ErrCtx, sbt *ast.Sbt) error {
var importPath []string
ImportTable.Range(func(key string, value ast.SymbolInfo) bool { //获取所有导入路径
importPath = append(importPath, value.Info.(ast.ImportInfo).Path)
return true
})
if *ImportPackage == nil {
*ImportPackage = make(map[string]*ast.Package, len(importPath))
}
var err error
for _, v := range importPath { //获取每个被导入的包
v, err = importPathToAbs(dir, v)
if err != nil {
return err
}
p, ok := (*ImportPackage)[v]
if ok { //如果已经被导入
*importLoacl = append(*importLoacl, p)
continue
}
p, err := loadImport(dir, v, thread, errctx, sbt, ImportPackage)
if err != nil {
return err
}
(*ImportPackage)[v] = p
*importLoacl = append(*importLoacl, p)
err = loadAllImport(p.Dir, p.ImportTable, ImportPackage, &p.ImportLoacl, thread, errctx, sbt) //导入被导入包导入的包
if err != nil {
return err
}
}
return nil
}
func importPathToAbs(dir, path string) (string, error) {
if !(strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../")) {
return "", ImportLimit
}
return filepath.Join(dir, path), nil
}
func loadImport(dir string, path string, thread bool, errctx *errcode.ErrCtx, sbt *ast.Sbt, ImportPackage *map[string]*ast.Package) (p *ast.Package, err error) {
p, err = ParserPackage(path, thread, errctx, sbt, ImportPackage)
if errors.Is(err, os.ErrNotExist) {
return nil, fmt.Errorf("%w %s", PathNotFound, path)
}
return
}
Go
1
https://gitee.com/u-language/u-language.git
git@gitee.com:u-language/u-language.git
u-language
u-language
U语言
a214d6007862

搜索帮助