package odin_parser import "core:odin/tokenizer" import "core:odin/ast" import "core:path/filepath" import "core:fmt" import "core:os" import "core:slice" collect_package :: proc(path: string) -> (pkg: ^ast.Package, success: bool) { NO_POS :: tokenizer.Pos{} pkg_path, pkg_path_ok := filepath.abs(path) if !pkg_path_ok { return } path_pattern := fmt.tprintf("%s/*.odin", pkg_path) matches, err := filepath.glob(path_pattern) defer delete(matches) if err != nil { return } pkg = ast.new(ast.Package, NO_POS, NO_POS) pkg.fullpath = pkg_path for match in matches { src: []byte fullpath, ok := filepath.abs(match) if !ok { return } src, ok = os.read_entire_file(fullpath) if !ok { delete(fullpath) return } file := ast.new(ast.File, NO_POS, NO_POS) file.pkg = pkg file.src = string(src) file.fullpath = fullpath pkg.files[fullpath] = file } success = true return } parse_package :: proc(pkg: ^ast.Package, p: ^Parser = nil) -> bool { p := p if p == nil { p = &Parser{} p^ = default_parser() } ok := true files := make([]^ast.File, len(pkg.files), context.temp_allocator) i := 0 for _, file in pkg.files { files[i] = file i += 1 } slice.sort(files) for file in files { if !parse_file(p, file) { ok = false } if pkg.name == "" { pkg.name = file.pkg_decl.name } else if pkg.name != file.pkg_decl.name { error(p, file.pkg_decl.pos, "different package name, expected '%s', got '%s'", pkg.name, file.pkg_decl.name) } } return ok } parse_package_from_path :: proc(path: string, p: ^Parser = nil) -> (pkg: ^ast.Package, ok: bool) { pkg, ok = collect_package(path) if !ok { return } ok = parse_package(pkg, p) return }