1 Star 1 Fork 1

U语言组织 / U语言

forked from 秋来冬风 / U语言 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Parser.go 46.32 KB
一键复制 编辑 原始数据 按行查看 历史
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349
package ast
import (
"fmt"
"path/filepath"
"strings"
"gitee.com/u-language/u-language/ucom/astdata"
"gitee.com/u-language/u-language/ucom/enum"
"gitee.com/u-language/u-language/ucom/errcode"
"gitee.com/u-language/u-language/ucom/internal/errutil"
"gitee.com/u-language/u-language/ucom/internal/utils"
"gitee.com/u-language/u-language/ucom/lex"
)
// 有测试依赖函数体外的非声明语句,设置为true可以恢复之前的行为
// 缩写 Non declarative statements outside of a function 缩写成NdSotf
var NdSotfOn = false
// 缩写 The first line does not have a package declaration 缩写成FirstLineNoPackageDecl
// 控制是否允许第一行没有包声明
var FirstLineNoPackageDeclOn = false
// ParserNode 解析几行已经完成词法分析的代码,并返回自动生成的节点
// - tree是抽象语法树, Tree.LVarTable Tree.Sbt 不能为空
// - lines是词法分析结果
// - sbt是被使用的符号表
// - index是被解析开始行偏移量
// - end是被结束开始行偏移量
// - ret是结果保存切片,为nil将自动分配一个长度为len(lines)的
// - IsFunc是被解析结果是否在函数内
// - Thread控制是否并发
//
// 对同一个 [Tree] 同时调用 [ParserNode] 有数据竞争可能
func ParserNode(tree *Tree, lines []lex.Line, sbt *Sbt, state ParserNodeState) []Node {
vlen := len(lines)
//首先解析第一行是不是包声明,以保证接下来肯定知道抽象语法树被声明属于那个包
if state.Index == 0 && !state.IsRecursion { //如果是第一行且非递归
if len(lines[0].Value) != 0 {
if lines[0].Value[0].TYPE == lex.Package { //如果第一行是包声明
parser_package(tree, &lines[0])
state.Index = 1
} else { //如果第一行不是包声明
if !FirstLineNoPackageDeclOn {
tree.Panic(&lines[0], nil, errcode.PackageDeclMustFirstLine)
}
}
} else { //如果第一行不是包声明
if !FirstLineNoPackageDeclOn {
tree.Panic(&lines[0], nil, errcode.PackageDeclMustFirstLine)
}
}
}
if state.Ret == nil {
state.Ret = make([]Node, vlen)
}
if state.End == 0 {
state.End = vlen
}
for i := state.Index; i < state.End; i++ {
if lines[i].Value == nil || len(lines[i].Value) == 0 { //是空行
continue
}
switch lines[i].Value[0].TYPE {
case lex.VAR: //是变量声明
ret := ParserVAR(tree, &lines[i], state.FuncInfo, sbt, state.InAutoFree)
if state.FuncInfo == nil {
tree.CHeaderFile.Add(CHeaderFile{ret, lines[i].Linenum})
}
state.Ret[i] = ret
case lex.FUNC: //是函数声明
autoCodeBlock(tree, enum.Func, &i, vlen, lines, state.Ret, sbt, state.FuncInfo, state.InAutoFree)
case lex.NAME, lex.Deref, lex.LEA, lex.MoreThanJustTokensWithBrackts:
if state.FuncInfo == nil && !NdSotfOn { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
state.Ret[i] = parserSece(tree, &lines[i], state.InAutoFree, state.FuncInfo)
case lex.IF:
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
autoCodeBlock(tree, "if", &i, vlen, lines, state.Ret, sbt, state.FuncInfo, state.InAutoFree)
case lex.ELSE:
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
autoCodeBlock(tree, "else", &i, vlen, lines, state.Ret, sbt, state.FuncInfo, state.InAutoFree)
case lex.FOR:
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
autoCodeBlock(tree, "for", &i, vlen, lines, state.Ret, sbt, state.FuncInfo, state.InAutoFree)
case lex.RBRACE: //是右大括号
state.Ret[i] = NewRbraceNode()
case lex.MLCStart: //是多行注释开头
for i < vlen-1 { //遍历lines后边的
i++
//直到发现多行注释结束,多行注释之间一并处理
if len(lines[i].Value) != 0 && lines[i].Value[0].TYPE == lex.MLCEnd {
break
}
}
case lex.Return:
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
state.Ret[i] = parserReturn(tree, &lines[i], state.InAutoFree, state.FuncInfo)
case lex.GOTO:
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
state.Ret[i] = parserGoto(tree, &lines[i])
case lex.Break:
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
state.Ret[i] = parserBreak(tree, &lines[i])
case lex.Continue:
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
state.Ret[i] = parserContinue(tree, &lines[i])
case lex.Const: //是常量声明
ret := parserConst(tree, &lines[i], sbt, state.InAutoFree, state.FuncInfo)
if state.FuncInfo == nil {
tree.CHeaderFile.Add(CHeaderFile{ret, lines[i].Linenum})
}
state.Ret[i] = ret
case lex.Struct: //是结构体声明
old := i
ret := parserStruct(tree, &i, lines, sbt, state.FuncInfo)
if state.FuncInfo == nil {
tree.CHeaderFile.Add(CHeaderFile{ret, lines[i].Linenum})
}
state.Ret[old] = ret
case lex.Package: //是包声明
parser_package(tree, &lines[i])
case lex.Switch: //是switch语句
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
autoCodeBlock(tree, enum.Switch, &i, vlen, lines, state.Ret, sbt, state.FuncInfo, state.InAutoFree)
case lex.Case: //是case语句
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
old := i
cn := parserCase(tree, &lines[old], sbt, state.InAutoFree, state.FuncInfo)
if cn == nil {
continue
}
state.Ret[old] = cn
parserCaseOrDefaultBlock(tree, lines, &i, old, vlen, cn.Sbt, errcode.CaseErr, state)
cn.Left, cn.Right = old, i
i-- //当前的偏移量位于右大括号或case
case lex.Default: //是default语句
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
old := i
dn := parserDefault(tree, &lines[old], sbt)
if dn == nil {
continue
}
state.Ret[old] = dn
parserCaseOrDefaultBlock(tree, lines, &i, old, vlen, dn.Sbt, errcode.DefaultErr, state)
dn.Left, dn.Right = old, i
i-- //当前的偏移量位于右大括号或default
case lex.Method: //是方法声明
autoCodeBlock(tree, enum.Method, &i, vlen, lines, state.Ret, sbt, state.FuncInfo, state.InAutoFree)
case lex.AutoFree: //是自动释放块
if state.FuncInfo == nil { //是函数体外的非声明语句
tree.Panic(&lines[i], nil, errcode.NdSotf)
continue
}
autoCodeBlock(tree, enum.AutoFree, &i, vlen, lines, state.Ret, sbt, state.FuncInfo, state.InAutoFree)
case lex.Import: //是import
parserImport(tree, lines, &i, state.FuncInfo)
case lex.Enum: //是枚举
old := i
ret := parserEnum(tree, &i, lines, sbt)
if state.FuncInfo == nil {
tree.CHeaderFile.Add(CHeaderFile{ret, lines[i].Linenum})
continue
}
state.Ret[old] = ret
default: //无法识别
parserSece(tree, &lines[i], state.InAutoFree, state.FuncInfo)
}
}
if tree != nil && state.FuncInfo == nil {
tree.Nodes = state.Ret
if tree.PackageName != "" {
tree.overwrite_ident()
}
}
return state.Ret
}
// ParserNodeState 是 [ParserNode] 的可选参数
type ParserNodeState struct {
//解析结果的保存切片,如果为nil,[ParserNode]会自动创建一个
Ret []Node
//被解析的词法分析结果开头偏移量
Index int
//被解析的词法分析结果结尾偏移量(解析时这个偏移量的词法分析结果不会被处理)
End int
//是否在解析函数内,如果是,函数信息
FuncInfo *FuncInfo
//is recursion 是否递归
IsRecursion bool
//是否在自动释放块
InAutoFree bool
}
// 解析变量
// 实现假定 line[0].Value[0].TYPE==VAR
func ParserVAR(t *Tree, line *lex.Line, FuncInfo *FuncInfo, sbt *Sbt, InAutoFree bool) *VarNode {
llen := len(line.Value)
if llen < 2 { //只有变量标识符
t.Panic(line, nil, errcode.VARErr, errcode.NoName)
return nil
}
if llen == 2 { //没有类型
t.Panic(line, nil, errcode.VARErr, errcode.NoType)
return nil
}
if llen == 3 && line.Value[1].TYPE == lex.NAME && check_is_type_token(line.Value[2].TYPE) { //声明但未初始化变量
return checkVarNameAndType(t, line, line.Value[1].Value, &line.Value[2], sbt, FuncInfo)
} else if llen >= 5 && line.Value[1].TYPE == lex.NAME && check_is_type_token(line.Value[2].TYPE) && line.Value[3].TYPE == lex.ASSIGN { //声明但初始化变量
ret := checkVarNameAndType(t, line, line.Value[1].Value, &line.Value[2], sbt, FuncInfo)
if ret == nil {
return nil
}
ret.IsFunc = FuncInfo != nil
// dest =(*line).Value[1]
// src =(*line).Value[3:]
expr := lex.NewLine(line.Linenum, append(append([]lex.Token(nil), (*line).Value[1]), (*line).Value[3:]...))
asnode := parserASSIGN(t, &expr, InAutoFree, FuncInfo) //解析赋值
if asnode == nil { //如果初始化赋值不符合语法
return nil
}
ret.Value = asnode.Src //变量节点记录源操作数
if t.PackageName != "" {
overwrite_ident_node(t, asnode)
}
if FuncInfo == nil { //不在函数内的赋值,就是全局变量初始化
t.VarInitTable_File.Add(ASSIGNInfo{Ptr: asnode, LineNum: line.Linenum})
}
return ret
} else { //无法识别
t.Panic(line, nil, errcode.VARErr, errcode.OPbug)
}
return nil
}
// checkVarNameAndType 检查变量的名字和类型,检查通过记录的符号表
func checkVarNameAndType(t *Tree, line *lex.Line, varname string, typename *lex.Token, sbt *Sbt, FuncInfo *FuncInfo) *VarNode {
if t.PackageName != "" {
varname = utils.GeneratePackageSymbol(t.PackageName, varname)
}
var typ = parserTypeName(t, line, typename, errcode.VARErr, FuncInfo)
if g, ok := typ.(*GenericInstantiation); ok && !utils.IsNil(g) { //记录泛型实例化
if FuncInfo == nil || (FuncInfo != nil && isHaveType(FuncInfo.TypeParame, g.ActualType, FuncInfo.TypeParame)) {
t.GenericTable.AddGenInst(g)
}
}
code := check_name(varname) //检查名字
if code != errcode.NoErr {
t.Panic(line, nil, errcode.VARErr, code)
return nil
}
if strings.HasPrefix(varname, enum.Generate) { //如果开头是generate
t.Panic(line, nil, errcode.VARErr, errcode.NameCannotStartWithGenerate)
return nil
}
n := NewVarNode(varname, typ, FuncInfo != nil, t.Filename, line.Linenum)
code = sbt.add(n.Name, enum.SymbolNoParameVar, n) //符号表记录
if code != errcode.NoErr { //如果变量重名
info := sbt.Have(varname)
var FileName string
var LineNum int
if v, ok := info.Info.(VarInfoSbt); ok {
FileName = v.FileName
} else {
FileName = info.Info.(*VarNode).FileName
}
if v, ok := info.Info.(VarInfoSbt); ok {
LineNum = v.LineNum
} else {
LineNum = info.Info.(*VarNode).LineNum
}
t.Panic(line, errcode.NewMsgSymbolRepeat(varname, FileName, t.Filename, LineNum, line.Linenum), errcode.VARErr, code)
return nil
}
return n
}
// checkConstNameAndType 检查常量的名字和类型,检查通过记录的符号表
func checkConstNameAndType(t *Tree, line *lex.Line, constname string, typename *lex.Token, sbt *Sbt, FuncInfo *FuncInfo) *ConstNode {
constname = utils.GeneratePackageSymbol(t.PackageName, constname)
code := check_name(constname)
if code != errcode.NoErr {
t.Panic(line, nil, errcode.ConstErr, code)
return nil
}
if strings.HasPrefix(constname, enum.Generate) { //如果开头是generate
t.Panic(line, nil, errcode.ConstErr, errcode.NameCannotStartWithGenerate)
return nil
}
typ := parserTypeName(t, line, typename, errcode.ConstErr, FuncInfo)
ret := NewConstNode(constname, typ)
code = sbt.AddConst(ret) //符号表记录
if code != errcode.NoErr { //如果常量重名
t.Panic(line, errcode.NewMsgSymbol(constname), errcode.ConstErr, code)
return nil
}
return ret
}
// parserContinuityTypeOrGenericInstantiation 解析连续类型或泛型实例化
// 假设 tk.TYPE=MoreThanJustTokensWithBrackts
func parserContinuityTypeOrGenericInstantiation(t *Tree, tk *lex.Token, line *lex.Line, err errcode.ErrCode, FuncInfo *FuncInfo) astdata.Typ {
tks := *tk.PtrMoreThanJustTokensWithBracktsS().Ptr
var typ astdata.Typ
if len(tks) == 2 && tks[0].TYPE == lex.TokenWithBrackets && (tks[1].TYPE == lex.NAME || tks[1].TYPE == lex.LEA) { //如果是 []T 或 [expr]T
typ = parserTypeName(t, line, &tks[1], err, FuncInfo)
if typ == nil {
return nil
}
token := lex_scan(t, ret_middle_str(tks[0].Value), line)
expr := parserExprNode(t, lex.NewLine(line.Linenum, token), err, false, FuncInfo)
if expr == nil {
return nil
}
return NewContinuityType(expr, typ, tks[0].Value+tks[1].Value)
} else if len(tks) == 2 && tks[0].TYPE == lex.TokenWithBrackets && tks[1].TYPE == lex.MoreThanJustTokensWithBrackts { //如果是 多维数组
typ = parserContinuityTypeOrGenericInstantiation(t, &tks[1], line, err, FuncInfo)
if typ == nil {
return nil
}
token := lex_scan(t, ret_middle_str(tks[0].Value), line)
expr := parserExprNode(t, lex.NewLine(line.Linenum, token), err, false, FuncInfo)
if expr == nil {
return nil
}
var buf strings.Builder
generateTokenStr(&buf, tks...)
return NewContinuityType(expr, typ, buf.String())
} else if len(tks) == 2 && (tks[0].TYPE == lex.NAME || tks[0].TYPE == lex.LEA) && tks[1].TYPE == lex.TokenWithBrackets { //如果是 T[T1] 或&T[T1]这种泛型实例化
return parserGenericInstantiation(t, tks, line, err, FuncInfo)
}
return nil
}
func lex_scan(t *Tree, s string, line *lex.Line) []lex.Token {
scan := lex.NewScan(s, lex.ScanConfig{File: t.Filename, Errctx: t.errctx, Line: line.Linenum})
return scan.AllScan()
}
func generateTokenStr(buf *strings.Builder, tks ...lex.Token) {
for _, v := range tks {
if v.TYPE == lex.MoreThanJustTokensWithBrackts {
s := *v.PtrMoreThanJustTokensWithBracktsS().Ptr
generateTokenStr(buf, s...)
} else {
buf.WriteString(v.Value)
}
}
}
// ret_middle_str 对于 [x] 返回 x
// 假设输入是一个前后为中括号的字符串
func ret_middle_str(s string) string {
return s[1 : len(s)-1]
}
// parserTypeName 解析类型名
func parserTypeName(t *Tree, line *lex.Line, tk *lex.Token, err errcode.ErrCode, FuncInfo *FuncInfo) (typ astdata.Typ) {
if tk.TYPE == lex.MoreThanJustTokensWithBrackts { //如果是连续类型
typ = parserContinuityTypeOrGenericInstantiation(t, tk, line, err, FuncInfo)
if typ == nil {
t.Panic(line, nil, err, errcode.UnknownType)
return nil
}
typ.SetTyp()
return typ
}
//解析类型
typ, ok := parserSelector(t, tk, line, FuncInfo)
if !ok {
kind := SymbolObj
switch tk.TYPE {
case lex.LEA:
kind = LeaObj
case lex.NAME:
default: //如果既不是 T 也不是 &T
t.Panic(line, nil, err, errcode.UnknownType)
return nil
}
o := NewObject(kind, tk.Value)
rewriteTypeName(t, &o.Name)
typ = o
}
typ.SetTyp()
return typ
}
// 解析函数
//
// 实现假定 line[0].Value[0].TYPE==FUNC
func parserFunc(t *Tree, line *lex.Line, FuncInfo *FuncInfo) *FuncNode {
if FuncInfo != nil { //如果是在函数中声明函数
t.Panic(line, nil, errcode.DeclFuncNoInFunc)
return nil
}
if !check_lex_LBRACE(t, line, errcode.FUNCErr) { //语法规定位置没有左大括号
return nil
}
funcinfo := check_func_decl(t, line, errcode.FUNCErr)
if funcinfo == nil { //有错
return nil
}
if t.PackageName != "" {
for i := 0; i < len(funcinfo.Parame); i++ {
funcinfo.Parame[i].Name = utils.GeneratePackageSymbol(t.PackageName, funcinfo.Parame[i].Name)
}
}
if funcinfo.Name == "init" {
t.IsInitFunc.Store(true)
// init函数重命名为init__user
funcinfo.Name = "init__user"
}
if t.PackageName != "" && funcinfo.Name != enum.Main {
_, ok := Builtin_func_info[funcinfo.Name]
if !ok { //如果不是内置函数
funcinfo.Name = utils.GeneratePackageSymbol(t.PackageName, funcinfo.Name)
}
}
if t.PackageName != "" && t.PackageName != enum.Main && funcinfo.Name == enum.Main { //如果非main包有main函数
t.Panic(line, nil, errcode.NoMainPackageMustHaveNoMainFunc)
}
code := t.Sbt.AddFunc(funcinfo)
if code != errcode.NoErr {
t.Panic(line, errcode.NewMsgSymbol(funcinfo.Name), errcode.FUNCErr, code)
return nil
}
ret := NewFuncNode(funcinfo) //返回函数节点
ret.Sbt.seniorSbt(t.Sbt)
for i := 0; i < len(funcinfo.Parame); i++ { //将每个参数视为局部变量,记录到符号表
ret.Sbt.AddVar(funcinfo.Parame[i].Name, funcinfo.Parame[i].Type, true, line.Linenum, t.Filename)
}
return ret
}
//缩写: sentence缩写成 sece
// parserSece 解析语句
// 实现假定 line[0].Value[0].TYPE==NAME
func parserSece(t *Tree, line *lex.Line, InAutoFree bool, FuncInfo *FuncInfo) Node {
if len(line.Value) < 2 { //如果只有一个符号
t.Panic(line, nil, errcode.OPbug)
return nil
}
switch line.Value[1].TYPE {
case lex.ASSIGN: //是赋值
return parserASSIGN(t, line, InAutoFree, FuncInfo)
case lex.LPAREN: //有左小括号,如果前面是符号,视为函数调用
if line.Value[0].TYPE != lex.NAME {
break
}
c := parserCall(t, line, InAutoFree, FuncInfo)
if c != nil {
c.(*CallNode).nosemicolon = false
}
return c
case lex.Colon: //是冒号,视为标签
return parserLabel(t, line)
case lex.Inc: //是自增语句
ret := NewSelfOpStmt(enum.IncOP, parserObject(t, &line.Value[0], line, FuncInfo))
return ret
case lex.Dec: //是自增语句
ret := NewSelfOpStmt(enum.DecOP, parserObject(t, &line.Value[0], line, FuncInfo))
return ret
}
t.Panic(line, nil, errcode.OPbug)
return nil
}
// 解析赋值表达式
//
// 对于不符合语法的赋值,返回nil
func parserASSIGN(t *Tree, line *lex.Line, InAutoFree bool, FuncInfo *FuncInfo) *ASSIGNNode {
llen := len(line.Value)
if llen == 3 { //是 dest = src
dest := parserObject(t, &line.Value[0], line, FuncInfo)
if dest == nil {
return nil
}
src := parserObject(t, &line.Value[2], line, FuncInfo)
if src == nil {
return nil
}
ret := NewASSIGNNode(dest, src)
return ret
} else { //是 dest = expr expr=运算表达式
exprstack := newstack(FuncInfo, InAutoFree)
ret := exprstack.AutoExpr(t, line)
exprstack.Close()
return ret
}
}
// parserObject 解析一个对象
//
// 如果是未知的变量,返回nil;不能解析的,panic
func parserObject(t *Tree, tk *lex.Token, line *lex.Line, FuncInfo *FuncInfo) Expr {
var ret *Object
switch tk.TYPE {
case lex.NAME: //是符号
selector, ok := parserSelector(t, tk, line, FuncInfo)
if ok {
return selector
}
ret = NewObject(SymbolObj, tk.Value)
case lex.NUMBER: //是数字
ret = NewObject(INTOBJ, tk.Value)
case lex.FLOAT: //是浮点数
ret = NewObject(FLOATOBJ, tk.Value)
case lex.TRUE, lex.FALSE: //是布尔值
ret = NewObject(BoolObj, tk.Value)
case lex.String: //是字符串
ret = NewObject(StringObj, tk.Value)
case lex.LEA: //是取地址
selector, ok := parserSelector(t, tk, line, FuncInfo)
if selector != nil && ok {
selector.Slice[0].Kind = LeaObj
return selector
}
if selector == nil && ok {
return nil
}
ret = NewObject(LeaObj, tk.Value[1:])
case lex.Deref: //是解引用
selector, ok := parserSelector(t, tk, line, FuncInfo)
if ok {
return selector
}
ret = NewObject(DerefObj, tk.Value[1:])
case lex.Nil: //是指针的零值
ret = NewObject(NilObj, tk.Value)
case lex.MoreThanJustTokensWithBrackts:
tks := *tk.PtrMoreThanJustTokensWithBracktsS().Ptr
return parserIndexExpr(t, line, &tks[0], &tks[1], FuncInfo)
default:
panic(errutil.NewErr2(errutil.CompileErr, fmt.Sprintf("未知的类型 %+v", tk)))
}
return ret
}
// parserIndexExpr 解析索引表达式
func parserIndexExpr(t *Tree, line *lex.Line, x, exprt *lex.Token, FuncInfo *FuncInfo) *IndexExpr {
var X, expr Expr
if (x.TYPE == lex.NAME || x.TYPE == lex.MoreThanJustTokensWithBrackts) && exprt.TYPE == lex.TokenWithBrackets {
X = parserObject(t, x, line, FuncInfo)
if X == nil {
return nil
}
token := lex_scan(t, ret_middle_str(exprt.Value), line)
expr = parserExprNode(t, lex.NewLine(line.Linenum, token), errcode.NoErr, false, FuncInfo)
if expr == nil {
return nil
}
return NewIndexExpr(X, expr)
}
return nil
}
// parserSelector 解析选择器,如果不是选择器,返回nil,true
func parserSelector(t *Tree, tk *lex.Token, line *lex.Line, FuncInfo *FuncInfo) (*Objects, bool) {
left := 0
var ret *Objects
for i := 0; i < len(tk.Value); i++ {
switch tk.Value[i] {
case '.':
if ret == nil {
ret = NewObjects(make([]*Object, 0, 2))
}
token := lex_scan(t, tk.Value[left:i], line)
if len(token) == 0 {
t.Panic(line, nil, errcode.LeftOrRightValueSelectorEmpty)
return nil, true
}
if token[0].TYPE != lex.NAME && token[0].TYPE != lex.LEA && token[0].TYPE != lex.Deref {
t.Panic(line, nil, errcode.SelectorLeftAndRightValueMustSymbol)
return nil, true
}
ret.Slice = append(ret.Slice, parserObject(t, &token[0], line, FuncInfo).(*Object))
left = i + 1
}
}
if ret == nil {
return nil, false
}
if left <= len(tk.Value) {
token := lex_scan(t, tk.Value[left:], line)
if len(token) == 0 {
t.Panic(line, nil, errcode.LeftOrRightValueSelectorEmpty)
return nil, true
}
if token[0].TYPE != lex.NAME && token[0].TYPE != lex.LEA && token[0].TYPE != lex.Deref {
t.Panic(line, nil, errcode.SelectorLeftAndRightValueMustSymbol)
return nil, true
}
ret.Slice = append(ret.Slice, parserObject(t, &token[0], line, FuncInfo).(*Object))
}
return ret, true
}
// 解析if
//
// 实现假定 line[0].Value[0].TYPE==IF
func parserIf(t *Tree, line *lex.Line, sbt *Sbt, InAutoFree bool, FuncInfo *FuncInfo) *IfNode {
if !check_lex_LBRACE(t, line, errcode.IfErr) { //语法规定位置没有左大括号
return nil
}
llen := len(line.Value)
if llen == 2 { //有 if 和右大括号,就是没有名字
t.Panic(line, nil, errcode.IfErr, errcode.NoBoolExpr)
return nil
}
//创建 if节点
ret := NewIfNode()
ret.Sbt.seniorSbt(sbt)
//解析布尔表达式
if autoParserBoolExpr(t, *line, &ret.BoolExpr, "if", InAutoFree, FuncInfo) {
return ret
}
return nil
}
// ParserExprNode 解析表达式节点
// - tree是抽象语法树, Tree.LVarTable Tree.Sbt 不能为空
// - line 是被解析的表达式
// - typ是如果出错的错误类型
// - IsAutoFree 是否在自动是否块内
func parserExprNode(t *Tree, line lex.Line, err errcode.ErrCode, InAutoFree bool, FuncInfo *FuncInfo) Expr {
llen := len(line.Value)
if llen == 1 { //不是表达式
return parserObject(t, &line.Value[0], &line, FuncInfo)
}
stack := newstack(FuncInfo, InAutoFree) //获取表达式值
stack.err = err
return stack.AutoExprNode(t, &line)
}
// parserCodeBlock 解析代码块内的代码
// - tree是抽象语法树, Tree.LVarTable Tree.Sbt 不能为空
// - i 是调用者 [ParserNode] 的for循环中i的地址
// - old是函数声明在lines的偏移量加1
// - vlen是lines的长度
// - wg是传递调用者 [ParserNode] 的wg参数
// - lines是传递调用者 [ParserNode] 的lines参数
// - ret是传递调用者 [ParserNode] 的ret参数
// - Left是代码块节点的Left字段的地址
// - Right是代码块节点的Right字段的地址
// - Sbt是代码块节点的Sbt字段的地址
// - check是传递调用者 [ParserNode] 的for循环中check的地址
// - IsFunc是传递调用者 [ParserNode] 的IsFunc参数
func parserCodeBlock(tree *Tree, i *int, old, vlen int, lines []lex.Line, ret []Node, Left, Right *int, sbt *Sbt, check *braceStack, FuncInfo *FuncInfo, InAutoFree bool) {
for *i < vlen-1 { //遍历lines
*i++
//如果左大括号和右大括号匹配
if len(lines[*i].Value) != 0 && check.AutoAdd(lines[*i].Value) {
ret[*i] = NewRbraceNode()
//记录代码块内代码,第一个节点偏移量,结尾右大括号节点偏移量
*Left = old
*Right = *i
// 实际解析解析代码块内的代码
ParserNode(tree, lines, sbt, ParserNodeState{Index: old, End: *i, Ret: ret, FuncInfo: FuncInfo, IsRecursion: true, InAutoFree: InAutoFree})
break
}
}
}
// autoCodeBlock 解析代码块节点和代码块内的代码
// - tree是抽象语法树, Tree.LVarTable Tree.Sbt 不能为空
// - typ是生成的代码块类型
// - i 是调用者 [ParserNode] 的for循环中i的地址
// - vlen是lines的长度
// - wg是传递调用者 [ParserNode] 的wg参数
// - lines是传递调用者 [ParserNode] 的lines参数
// - ret是传递调用者 [ParserNode] 的ret参数
// - sbt是传递调用者 [ParserNode] 的sbt参数
// - IsFunc是被解析的部分否在函数内
func autoCodeBlock(tree *Tree, typ string, i *int, vlen int, lines []lex.Line, ret []Node, sbt *Sbt, FuncInfo *FuncInfo, InAutoFree bool) {
var node codeBlockIface
old := *i
switch typ {
case enum.Func: //是函数
f := parserFunc(tree, &lines[*i], FuncInfo)
if f == nil {
return
}
tree.CHeaderFile.Add(CHeaderFile{f, lines[old].Linenum})
FuncInfo, node = f.FuncInfo, f
case "if": //是if
node = parserIf(tree, &lines[*i], sbt, InAutoFree, FuncInfo)
case "else": //是else
node = parserElse(tree, &lines[*i], sbt, InAutoFree, FuncInfo)
case "for": //是for
node = parserFor(tree, &lines[*i], sbt, FuncInfo, InAutoFree)
case enum.Switch: //是switch
node = parserSwitch(tree, &lines[*i], sbt, InAutoFree, FuncInfo)
case enum.Method: //是方法
f := parserMethod(tree, &lines[*i], FuncInfo)
if f == nil {
return
}
tree.CHeaderFile.Add(CHeaderFile{f, lines[old].Linenum})
FuncInfo, node = f.FuncInfo, f
case enum.AutoFree: //是自动释放块
node = parserAutoFree(tree, &lines[*i], sbt, InAutoFree, FuncInfo)
InAutoFree = true
}
if utils.IsNil(node) {
//没有成功生成代码块节点(接口值为nil说明typ不是已知的)
return
}
ret[*i] = node
check := newbraceStack(1)
//解析代码块内的代码
parserCodeBlock(tree, i, *i+1, vlen, lines, ret, node.getLeft(), node.getRight(), node.getSbt(), &check, FuncInfo, InAutoFree)
if !check.Ok() { //缺失右大括号
tree.Panic(&lines[*i], errcode.NewMsgBracesNoEqual(check.leftNum, check.rightNum), codeBlock_errmap[typ], errcode.EmptyRbrace)
} else {
if typ == enum.AutoFree {
mempool := NewObject(LeaObj, utils.Generate_mempool_Name(old+1, tree.Filename))
c := NewCallExpr(NewObject(SymbolObj, enum.MemPoolFree), true, mempool)
c.nosemicolon = false
ret[*i] = c
try_AutoFreeIn(old, *i, ret, mempool)
}
}
}
// 解析else
//
// 实现假定 line[0].Value[0].TYPE==ELSE
func parserElse(t *Tree, line *lex.Line, sbt *Sbt, InAutoFree bool, FuncInfo *FuncInfo) *ElseNode {
ok := check_lex_LBRACE(t, line, errcode.ElseErr)
if !ok { //语法规定位置没有左大括号
return nil
}
//创建 else节点
ret := NewElseNode()
ret.Sbt.seniorSbt(sbt)
llen := len(line.Value)
if llen == 2 { //如果是 else {
return ret
}
if autoParserBoolExpr(t, *line, &ret.BoolExpr, "else", InAutoFree, FuncInfo) { //如果是 else if boolexpr {
return ret
}
return nil
}
// autoParserBoolExpr 解析 if或else if 或for的布尔表达式
func autoParserBoolExpr(t *Tree, line lex.Line, BoolExpr *Expr, typ string, InAutoFree bool, FuncInfo *FuncInfo) bool {
var exprline []lex.Token
switch typ {
case "if": //如果是if,表达式在关键字if后
exprline = line.Value[1:]
case "else": //如果是else if,表达式在关键字else if后
exprline = line.Value[2:]
case "for": //如果是for,表达式是输入全部
exprline = line.Value
}
if typ != "for" {
//有左大括号排除在表达式外
exprline = exprline[:len(exprline)-1]
}
boolexpr := parserExprNode(t, lex.NewLine(line.Linenum, exprline), codeBlock_errmap[typ], InAutoFree, FuncInfo)
if utils.IsNil(boolexpr) { //值为nil,表示生成布尔表达式失败
return false
}
*BoolExpr = boolexpr
if t.PackageName != "" {
overwrite_ident_node(t, boolexpr)
}
return true
}
// 解析for
//
// 实现假定 line[0].Value[0].TYPE==FOR
func parserFor(t *Tree, line *lex.Line, sbt *Sbt, FuncInfo *FuncInfo, InAutoFree bool) *ForNode {
ok := check_lex_LBRACE(t, line, errcode.ForErr)
if !ok { //语法规定位置没有左大括号
return nil
}
llen := len(line.Value)
if llen == 2 { //只有 for 和右大括号
t.Panic(line, errcode.NewMsgNumberOfSemicolons(0), errcode.ForErr)
return nil
}
retstr, num := splitFor(line)
if num != 2 { //如果分号的数量不是2
t.Panic(line, errcode.NewMsgNumberOfSemicolons(num), errcode.ForErr)
return nil
}
// for语句确定是for initstmt;boolexpr;endstmt {
ret := NewForNode() //创建 for节点
ret.Sbt.seniorSbt(sbt)
//解析初始化语句
if len(retstr[0].Value) != 0 { //初始化语句非空
initstmt := ParserNode(t, []lex.Line{retstr[0]}, ret.Sbt, ParserNodeState{Index: 0, End: 0, Ret: nil, FuncInfo: FuncInfo, IsRecursion: true, InAutoFree: InAutoFree})
ret.InitStmt = initstmt[0]
overwrite_ident_node(t, ret.InitStmt)
}
//解析结束语句
if len(retstr[2].Value) != 0 { //结束语句非空
endstmt := ParserNode(t, []lex.Line{retstr[2]}, ret.Sbt, ParserNodeState{Index: 0, End: 0, Ret: nil, FuncInfo: FuncInfo, IsRecursion: true, InAutoFree: InAutoFree})
ret.EndStmt = endstmt[0]
overwrite_ident_node(t, ret.EndStmt)
}
//解析布尔表达式
if len(retstr[1].Value) != 0 { //布尔表达式非空
autoParserBoolExpr(t, retstr[1], &ret.BoolExpr, "for", InAutoFree, FuncInfo)
}
return ret
}
// splitFor 将for语句按分号分割,返回被for和分号,以及分号和分号,以及末尾分隔的字符串
//
// 例如对于 for var i int=0 ; i<3 ; i=i+1 {
// 将返回的值等价于 Lex("",1,[]string{"var i int = 0 ","i < 3 ","i = i + 1"},nil)
func splitFor(line *lex.Line) ([]lex.Line, int) {
SEMICOLONnum := 0
old := 1
ret := make([]lex.Line, 0, 3)
llen := len(line.Value) - 1
for i := 1; i < llen; i++ { //对于for initstmt;boolexpr;endstmt [{],从1开始遍历词法分析结果
if line.Value[i].TYPE == lex.SEMICOLON { //如果发现分号
// 将最后未遍历和分号之间的词法分析结果用空格连接
var buf = make([]lex.Token, 0, i-old)
for index := old; index < i; index++ {
buf = append(buf, line.Value[index])
}
ret = append(ret, lex.NewLine(line.Linenum, buf))
SEMICOLONnum++ //分号计数加1
old = i + 1 //更新最后未遍历的偏移量
}
}
// 将最后未遍历和分号之间的词法分析结果用空格连接
var buf = make([]lex.Token, 0, llen-old)
for index := old; index < llen; index++ {
buf = append(buf, line.Value[index])
}
ret = append(ret, lex.NewLine(line.Linenum, buf))
return ret, SEMICOLONnum
}
// parserCall 解析函数调用或语法形式相同的解引用表达式
// 实现假定如果是函数调用函数调用 line.Value[0].TYPE==NAME
func parserCall(t *Tree, line *lex.Line, InAutoFree bool, FuncInfo *FuncInfo) Expr {
if line.Value[0].Value == "@" { //如果是解引用表达式
nline := lex.NewLine(line.Linenum, line.Value[1:])
n := parserExprNode(t, nline, errcode.NoErr, InAutoFree, FuncInfo)
if n == nil {
return nil
}
return &Dereference{Value: n}
}
builtin := false
switch line.Value[0].Value { //检查是否是禁止调用的函数
case "main":
t.Panic(line, nil, errcode.ProhibitCallMainFunc)
return nil
case "init":
t.Panic(line, nil, errcode.ProhibitCallInitFunc)
return nil
}
_, builtin = Builtin_func_info[line.Value[0].Value]
if InAutoFree && !builtin {
line.Value[0].Value = line.Value[0].Value + enum.AutoFreeInFunc
}
var funcname FuncNameNode
if line.Value[0].TYPE == lex.MoreThanJustTokensWithBrackts {
g := parserGenericInstantiation(t, *line.Value[0].PtrMoreThanJustTokensWithBracktsS().Ptr, line, errcode.CallErr, FuncInfo) //记录泛型实例化
if FuncInfo == nil {
t.GenericTable.AddGenInst(g)
}
if FuncInfo != nil && !isUseType(g.ActualType, FuncInfo.TypeParame) {
t.GenericTable.AddGenInst(g)
}
funcname = g
} else {
funcname = parserObject(t, &line.Value[0], line, FuncInfo).(FuncNameNode)
}
ret := NewCallExpr(funcname, InAutoFree)
s := newstack(FuncInfo, InAutoFree)
ret.Parame = s.AutoParameList(t, line)
s.Close()
for i := 0; i < len(ret.Parame); i++ {
overwrite_ident_node(t, ret.Parame[i])
}
return ret
}
// parserReturn 解析返回语句
// 实现假定 line.Value[0].TYPE==Return
func parserReturn(t *Tree, line *lex.Line, InAutoFree bool, FuncInfo *FuncInfo) *ReturnNode {
ret := NewReturnNode()
ret.RetValue = parserReturnValue(t, line, InAutoFree, FuncInfo)
overwrite_ident_node(t, ret.RetValue)
return ret
}
// parserReturnValue 解析返回值
// 实现假定 line.Value[0].TYPE==Return
func parserReturnValue(t *Tree, line *lex.Line, InAutoFree bool, FuncInfo *FuncInfo) Expr {
if len(line.Value) == 1 { //如果没有返回值
return nil
}
l := *line
l.Value = l.Value[1:]
return parserExprNode(t, l, errcode.ReturnErr, InAutoFree, FuncInfo)
}
// parserGoto 解析goto语句
// 实现假定 line.Value[0].TYPE==GOTO
func parserGoto(t *Tree, line *lex.Line) *GotoStmt {
llen := len(line.Value)
if llen != 2 {
if llen < 2 { //小于2说明只有goto关键字,没有标签
t.Panic(line, nil, errcode.GotoErr, errcode.NoLabel)
} else { //又不等于2又不小于2,就是大于2
t.Panic(line, nil, errcode.GotoErr, errcode.OPbug)
}
return nil
}
if line.Value[1].TYPE != lex.NAME { //标签应该被词法分析识别为符号,如果不是
t.Panic(line, nil, errcode.GotoErr, errcode.NoLabel)
return nil
}
ret := NewGotoStmt(line.Value[1].Value)
return ret
}
// parserLabel 解析标签
// 实现假定 line.Value[1].TYPE==Colon
func parserLabel(t *Tree, line *lex.Line) *LabelNode {
llen := len(line.Value)
if llen > 2 { //一个标签的词法分析应该只分析出两个单词 从左到右是符号 冒号
t.Panic(line, nil, errcode.LabelErr, errcode.OPbug)
return nil
}
if line.Value[0].TYPE != lex.NAME { //一个标签的词法分析应该只分析出两个单词 从左到右是符号 冒号
t.Panic(line, nil, errcode.LabelErr, errcode.NoName)
return nil
}
return NewLabelNode(line.Value[0].Value)
}
// parserBreak 解析break
// 实现假定 line.Value[0].TYPE==Break
func parserBreak(t *Tree, line *lex.Line) BreakStmt {
llen := len(line.Value)
if llen > 1 { //break语句一行应该只有一个break
t.Panic(line, nil, errcode.BreakErr, errcode.OPbug)
}
return NewBreakStmt()
}
// parserContinue 解析continue
// 实现假定 line.Value[0].TYPE==Continue
func parserContinue(t *Tree, line *lex.Line) ContinueStmt {
llen := len(line.Value)
if llen > 1 { //continue语句一行应该只有一个continue
t.Panic(line, nil, errcode.ContinueErr, errcode.OPbug)
}
return NewContinueStmt()
}
// 解析常量
// 实现假定 line.Value[0].TYPE==Const
func parserConst(t *Tree, line *lex.Line, sbt *Sbt, InAutoFree bool, FuncInfo *FuncInfo) *ConstNode {
llen := len(line.Value)
if llen < 2 { //只有常量标识符
t.Panic(line, nil, errcode.ConstErr, errcode.NoName)
return nil
}
if llen == 2 { //没有类型
t.Panic(line, nil, errcode.ConstErr, errcode.NoType)
return nil
}
if llen == 3 { //常量没有初始化
t.Panic(line, nil, errcode.ConstErr, errcode.NoConstInit)
return nil
}
if llen >= 5 && line.Value[1].TYPE == lex.NAME && line.Value[2].TYPE == lex.NAME && line.Value[3].TYPE == lex.ASSIGN { //声明并初始化常量
ret := checkConstNameAndType(t, line, line.Value[1].Value, &line.Value[2], sbt, FuncInfo)
if ret == nil {
return nil
}
// dest =(*line).Value[1]
// src =(*line).Value[3:]
expr := lex.NewLine(line.Linenum, append(append([]lex.Token(nil), (*line).Value[1]), (*line).Value[3:]...))
asnode := parserASSIGN(t, &expr, InAutoFree, FuncInfo) //解析赋值
if asnode == nil { //如果初始化赋值不符合语法
return nil
}
overwrite_ident_node(t, asnode)
ret.Value = asnode.Src //常量节点记录源操作数
return ret
}
//无法识别
t.Panic(line, nil, errcode.ConstErr, errcode.OPbug)
return nil
}
func isName(typ lex.TokenType) bool {
return typ == lex.NAME || typ == lex.MoreThanJustTokensWithBrackts
}
// parserName 解析可能带类型参数的名字
func parserName(t *Tree, tk *lex.Token, line *lex.Line, err errcode.ErrCode, FuncInfo *FuncInfo) (name string, Typeparame []astdata.NameAndType, ok bool) {
if tk.TYPE == lex.NAME {
name, ok = tk.Value, true
} else { //如果使用了
Typeparame, name = check_TypeParame(t, tk, line, err, FuncInfo)
if len(Typeparame) == 0 || len(name) == 0 { //如果类型参数列表和符号名称至少一个获取失败
return "", nil, false
}
ok = true
}
return
}
// parserStruct 解析结构体
// 实现假定 line.Value[0].TYPE==Struct
func parserStruct(t *Tree, i *int, lines []lex.Line, sbt *Sbt, FuncInfo *FuncInfo) *StructDecl {
ok := check_lex_LBRACE(t, &lines[*i], errcode.StructErr)
if !ok { //语法规定位置没有左大括号
return nil
}
llen := len(lines[*i].Value)
if llen != 3 { //如果不是 struct name {
if llen == 2 { //既有struct 又有{ 就是没有名
t.Panic(&lines[*i], nil, errcode.StructErr, errcode.NoName)
} else {
t.Panic(&lines[*i], nil, errcode.StructErr, errcode.OPbug)
}
return nil
}
var ret = new(StructDecl)
ret.Name, ret.TypeParame, ok = parserName(t, &lines[*i].Value[1], &lines[*i], errcode.StructErr, FuncInfo)
if !ok {
return nil
}
ret.LineNum, ret.sbt, ret.FileName, ret.InFunc = lines[*i].Linenum, sbt, t.Filename, FuncInfo != nil
start := *i + 1
end := rbraceIndex(i, lines) //如果和start合并在一行,测试会失败,所以写两行
if end == 0 {
t.Panic(&lines[*i], nil, errcode.StructErr, errcode.EmptyRbrace)
return nil
}
ret.FieldTable = check_struct_field(t, lines[start:end], FuncInfo) //解析所有字段
ret.Name = utils.GeneratePackageSymbol(t.PackageName, ret.Name)
code := sbt.AddStruct(ret.Name, ret)
if code != errcode.NoErr { //符号表记录结构体如果重名
t.Panic(&lines[start-1], errcode.NewMsgSymbol(ret.Name), errcode.StructErr, code)
}
return ret
}
// parser_package 解析包声明
// 实现假定 line.Value[0].TYPE==Package
func parser_package(t *Tree, line *lex.Line) {
if len(line.Value) == 1 { //如果只有package
t.Panic(line, nil, errcode.PackageDeclMustName)
return
}
if len(line.Value) > 2 { //如果不止package name
t.Panic(line, nil, errcode.PackageDeclOnlyName)
return
}
if line.Value[1].Value == "unsafe" { //如果包名等于 unsafe
t.Panic(line, nil, errcode.PackageNameCannotBeEqualUnsafe)
return
}
if line.Linenum != 1 { //如果不是在第一行
t.Panic(line, nil, errcode.PackageDeclMustFirstLine)
return
}
t.PackageName = line.Value[1].Value
}
// 解析switch 语句
//
// 实现假定 line[0].Value[0].TYPE==Switch
func parserSwitch(t *Tree, line *lex.Line, sbt *Sbt, InAutoFree bool, FuncInfo *FuncInfo) *SwitchNode {
if !check_lex_LBRACE(t, line, errcode.SwitchErr) { //语法规定位置没有左大括号
return nil
}
llen := len(line.Value)
if llen == 2 { //只有 switch 和 { 就是没有表达式
t.Panic(line, nil, errcode.SwitchErr, errcode.NoExpr)
return nil
}
//创建 switch节点
ret := NewSwitchNode()
ret.Sbt.seniorSbt(sbt)
ret.Expr = parserExprNode(t, lex.NewLine(line.Linenum, line.Value[1:len(line.Value)-1]), errcode.SwitchErr, InAutoFree, FuncInfo)
overwrite_ident_node(t, ret.Expr)
return ret
}
// 解析case 语句
//
// 实现假定 line[0].Value[0].TYPE==Case
func parserCase(t *Tree, line *lex.Line, sbt *Sbt, InAutoFree bool, FuncInfo *FuncInfo) *CaseNode {
llen := len(line.Value)
if llen < 3 { //正确的 case 语句 case expr : 至少三个token
if line.Value[llen-1].TYPE != lex.Colon { //如果末尾不是冒号
t.Panic(line, nil, errcode.CaseErr, errcode.ExpectColonAtEnd)
} else {
t.Panic(line, nil, errcode.CaseErr, errcode.NoExpr)
}
return nil
}
ret := NewCaseNode()
ret.Sbt.seniorSbt(sbt)
ret.Expr = parserExprNode(t, lex.NewLine(line.Linenum, line.Value[1:llen-1]), errcode.CaseErr, InAutoFree, FuncInfo)
overwrite_ident_node(t, ret.Expr)
return ret
}
// parserCaseOrDefaultBlock 解析case或default的代码块
func parserCaseOrDefaultBlock(tree *Tree, lines []lex.Line, i *int, old int, vlen int, sbt *Sbt, err errcode.ErrCode, state ParserNodeState) {
check := newbraceStack(1) //Note:设置左大括号为1是为了在,按语法只有一个右大括号时可以check.Ok()==true,以及case或default中有右大括号时,能不把右大括号的位置可能不正确的视为代码块的范围
CheckMatch:
for *i < vlen-1 { //遍历lines后边的
*i++
if len(lines[*i].Value) != 0 {
switch lines[*i].Value[0].TYPE { //如果开头是case或default
case lex.Case, lex.Default:
break CheckMatch
}
switch lines[*i].Value[len(lines[*i].Value)-1].TYPE { //如果结束是左大括号或右大括号
case lex.LBRACE:
check.leftNum++
case lex.RBRACE:
check.rightNum++
if check.Ok() { //左右括号匹配或只有一个右大括号(在switch最后的case或default只会发现一个右大括号)
break CheckMatch
}
default:
continue CheckMatch
}
}
}
if !check.Ok() && check.leftNum != 1 { //如果左右大括号数量不匹配
//Note:check.leftNum-1时因为左大括号多算了1个
tree.Panic(&lines[old], errcode.NewMsgBracesNoEqual(check.leftNum-1, check.rightNum), err)
return
}
ParserNode(tree, lines, sbt, ParserNodeState{Index: old + 1, End: *i, Ret: state.Ret, FuncInfo: state.FuncInfo, IsRecursion: true, InAutoFree: state.InAutoFree})
}
// 解析default 语句
//
// 实现假定 line[0].Value[0].TYPE==Default
func parserDefault(t *Tree, line *lex.Line, sbt *Sbt) *DefaultNode {
llen := len(line.Value)
if llen != 2 { //正确的 default 语句 default : 两个token
if llen == 1 { //如果末尾不是冒号
t.Panic(line, nil, errcode.DefaultErr, errcode.ExpectColonAtEnd)
} else {
t.Panic(line, nil, errcode.DefaultErr, errcode.OPbug)
}
return nil
}
ret := NewDefaultNode()
ret.Sbt.seniorSbt(sbt)
return ret
}
// 解析方法
//
// 实现假定 line[0].Value[0].TYPE==Method
func parserMethod(t *Tree, line *lex.Line, FuncInfo *FuncInfo) *MethodNode {
if FuncInfo != nil { //如果是在函数中声明方法,方法相当于函数
t.Panic(line, nil, errcode.DeclMethodInFunc)
return nil
}
if !check_lex_LBRACE(t, line, errcode.MethodErr) { //语法规定位置没有左大括号
return nil
}
funcinfo := check_func_decl(t, line, errcode.MethodErr)
if funcinfo == nil { //有错
return nil
}
if len(funcinfo.Parame) == 0 { //如果方法的第一个参数类型不是自定义类型
t.Panic(line, nil, errcode.MethodErr, errcode.FirstParameTypeOfMethodACustomType)
return nil
}
var typ string
if g, ok := funcinfo.Parame[0].Type.(*GenericInstantiation); ok {
typ = g.BaseName.Typ()
} else {
typ = funcinfo.Parame[0].Type.Typ()
}
typ = utils.Ret_no_lea(typ)
_, isnoCustomType := TypeEnumStrMap[typ]
if isnoCustomType { //如果方法的第一个参数类型不是自定义类型
t.Panic(line, nil, errcode.MethodErr, errcode.FirstParameTypeOfMethodACustomType)
return nil
}
//重写字段名
for i := 0; i < len(funcinfo.Parame); i++ {
funcinfo.Parame[i].Name = utils.GeneratePackageSymbol(t.PackageName, funcinfo.Parame[i].Name)
}
ret := NewMethodNode(typ, funcinfo) //返回方法节点
code := t.Sbt.AddMethod(typ, ret)
if code != errcode.NoErr {
t.Panic(line, nil, errcode.MethodErr, code)
return nil
}
ret.Sbt.seniorSbt(t.Sbt)
for i := 0; i < len(funcinfo.Parame); i++ { //将每个参数视为局部变量,记录到符号表
ret.Sbt.AddVar(funcinfo.Parame[i].Name, funcinfo.Parame[i].Type, true, line.Linenum, t.Filename)
}
return ret
}
// 解析import语句
//
// 实现假定 line[0].Value[0].TYPE==Import
func parserImport(t *Tree, lines []lex.Line, i *int, FuncInfo *FuncInfo) {
if FuncInfo != nil { //如果在函数内
t.Panic(&lines[*i], nil, errcode.ImportErr, errcode.ImportShouldBeOutSideOfTheFunc)
return
}
if !check_lex_LBRACE(t, &lines[*i], errcode.ImportErr) { //语法规定位置没有左大括号
return
}
if len(lines[*i].Value) != 2 { //如果不是 import {
t.Panic(&lines[*i], nil, errcode.ImportErr, errcode.OPbug)
return
}
old := *i + 1
end := rbraceIndex(i, lines)
if end == 0 { //如果没找到右大括号
t.Panic(&lines[*i], nil, errcode.ImportErr, errcode.EmptyRbrace)
return
}
for ; old < end; old++ {
if len(lines[old].Value) == 0 { //如果是空行
continue
}
if lines[old].Value[0].TYPE != lex.String { //如果导入路径不是字符串
t.Panic(&lines[old], nil, errcode.ImportErr, errcode.ImportPathMustString)
continue
}
basename := clean_path(lines[old].Value[0].Value)
t.ImportTable.add(basename, enum.SymbolImport, ImportInfo{Path: ret_string_value(lines[old].Value[0].Value)})
t.Sbt.add(basename, enum.SymbolImport, ImportInfo{Path: ret_string_value(lines[old].Value[0].Value)})
}
}
func ret_string_value(s string) string {
return s[1 : len(s)-1]
}
func clean_path(s string) string {
s = filepath.Base(s)
s = s[:len(s)-1]
return s
}
// parserEnum 解析枚举
// 实现假定 line.Value[0].TYPE==Enum
func parserEnum(t *Tree, i *int, lines []lex.Line, sbt *Sbt) *EnumDecl {
ok := check_lex_LBRACE(t, &lines[*i], errcode.EnumErr)
if !ok { //语法规定位置没有左大括号
return nil
}
llen := len(lines[*i].Value)
if llen != 3 { //如果不是 enum name {
if llen == 2 { //如果既有enum又有 { 就是没有名字
t.Panic(&lines[*i], nil, errcode.EnumErr, errcode.NoName)
} else {
t.Panic(&lines[*i], nil, errcode.EnumErr, errcode.OPbug)
}
return nil
}
ret, start := NewEnumDecl(lines[*i].Value[1].Value), *i+1
end := rbraceIndex(i, lines)
if end == 0 {
t.Panic(&lines[*i], nil, errcode.EnumErr, errcode.EmptyRbrace)
return nil
}
ret.Enums = check_enums(t, lines[start:end]) //解析所有字段
if len(ret.Enums) == 0 { //如果是空枚举
t.Panic(&lines[*i], nil, errcode.EnumErr, errcode.EmptyEnum)
return nil
}
for i := 0; i < len(ret.Enums); i++ { //重写标识符
var buf strings.Builder
buf.WriteString(t.PackageName)
buf.WriteString(enum.PackageSep)
buf.WriteString(ret.Name)
buf.WriteString(enum.PackageSep)
buf.WriteString(ret.Enums[i])
ret.Enums[i] = buf.String()
}
ret.Name = utils.GeneratePackageSymbol(t.PackageName, ret.Name)
code := sbt.AddEnum(ret)
if code != errcode.NoErr { //符号表记录结构体,如果重名
t.Panic(&lines[start-1], errcode.NewMsgSymbol(ret.Name), errcode.EnumErr, code)
}
return ret
}
// rbraceIndex 获取右大括号所在的下标
func rbraceIndex(i *int, lines []lex.Line) int {
vlen := len(lines)
for *i < vlen-1 { //遍历lines
*i++
//如果发现右大括号
if len(lines[*i].Value) != 0 && lines[*i].Value[0].TYPE == lex.RBRACE {
return *i
}
}
return 0
}
Go
1
https://gitee.com/u-language/u-language.git
git@gitee.com:u-language/u-language.git
u-language
u-language
U语言
a214d6007862

搜索帮助

53164aa7 5694891 3bd8fe86 5694891