代码拉取完成,页面将自动刷新
同步操作将从 秋来冬风/U语言 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
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
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。