mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 01:44:37 +00:00
first step to get rid of nil in the AST
This commit is contained in:
18
rod/ast.nim
18
rod/ast.nim
@@ -577,12 +577,10 @@ proc newSons*(father: PNode, length: int)
|
||||
proc newSons*(father: PType, length: int)
|
||||
proc addSon*(father, son: PNode)
|
||||
proc addSon*(father, son: PType)
|
||||
proc addSonIfNotNil*(father, n: PNode)
|
||||
proc delSon*(father: PNode, idx: int)
|
||||
proc hasSonWith*(n: PNode, kind: TNodeKind): bool
|
||||
proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool
|
||||
proc replaceSons*(n: PNode, oldKind, newKind: TNodeKind)
|
||||
proc sonsNotNil*(n: PNode): bool
|
||||
proc copyNode*(src: PNode): PNode
|
||||
# does not copy its sons!
|
||||
proc copyTree*(src: PNode): PNode
|
||||
@@ -590,6 +588,10 @@ proc copyTree*(src: PNode): PNode
|
||||
|
||||
proc discardSons*(father: PNode)
|
||||
|
||||
var emptyNode* = newNode(nkEmpty)
|
||||
# There is a single empty node that is shared! Do not overwrite it!
|
||||
|
||||
|
||||
const # for all kind of hash tables:
|
||||
GrowthFactor* = 2 # must be power of 2, > 0
|
||||
StartSize* = 8 # must be power of 2, > 0
|
||||
@@ -868,6 +870,7 @@ proc len*(n: PNode): int {.inline.} =
|
||||
else: result = len(n.sons)
|
||||
|
||||
proc add*(father, son: PNode) =
|
||||
assert son != nil
|
||||
if isNil(father.sons): father.sons = @[]
|
||||
add(father.sons, son)
|
||||
|
||||
@@ -879,6 +882,7 @@ proc newSons(father: PNode, length: int) =
|
||||
setlen(father.sons, len(father.sons) + length)
|
||||
|
||||
proc addSon(father, son: PNode) =
|
||||
assert son != nil
|
||||
if isNil(father.sons): father.sons = @[]
|
||||
add(father.sons, son)
|
||||
|
||||
@@ -947,7 +951,7 @@ proc lastSon(n: PType): PType =
|
||||
|
||||
proc hasSonWith(n: PNode, kind: TNodeKind): bool =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
if (n.sons[i] != nil) and (n.sons[i].kind == kind):
|
||||
if n.sons[i].kind == kind:
|
||||
return true
|
||||
result = false
|
||||
|
||||
@@ -956,9 +960,8 @@ proc hasSubnodeWith(n: PNode, kind: TNodeKind): bool =
|
||||
of nkEmpty..nkNilLit: result = n.kind == kind
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
if n.sons[i] != nil:
|
||||
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
|
||||
return true
|
||||
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
|
||||
return true
|
||||
result = false
|
||||
|
||||
proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) =
|
||||
@@ -971,9 +974,6 @@ proc sonsNotNil(n: PNode): bool =
|
||||
return false
|
||||
result = true
|
||||
|
||||
proc addSonIfNotNil(father, n: PNode) =
|
||||
if n != nil: addSon(father, n)
|
||||
|
||||
proc getInt*(a: PNode): biggestInt =
|
||||
case a.kind
|
||||
of nkIntLit..nkInt64Lit: result = a.intVal
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# c2nim - C to Nimrod source converter
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -15,7 +15,7 @@ const
|
||||
Version = NimrodVersion
|
||||
Usage = """
|
||||
c2nim - C to Nimrod source converter
|
||||
(c) 2010 Andreas Rumpf
|
||||
(c) 2011 Andreas Rumpf
|
||||
Usage: c2nim [options] inputfile [options]
|
||||
Options:
|
||||
-o, --out:FILE set output filename
|
||||
|
||||
@@ -197,7 +197,7 @@ proc parLineInfo(p: TParser): TLineInfo =
|
||||
result = getLineInfo(p.lex)
|
||||
|
||||
proc skipComAux(p: var TParser, n: PNode) =
|
||||
if (n != nil):
|
||||
if n != nil and n.kind != nkEmpty:
|
||||
if pfSkipComments notin p.options.flags:
|
||||
if n.comment == nil: n.comment = p.tok.s
|
||||
else: add(n.comment, "\n" & p.tok.s)
|
||||
@@ -216,8 +216,7 @@ proc getTok(p: var TParser, n: PNode) =
|
||||
skipCom(p, n)
|
||||
|
||||
proc ExpectIdent(p: TParser) =
|
||||
if p.tok.xkind != pxSymbol:
|
||||
parMessage(p, errIdentifierExpected, $(p.tok^))
|
||||
if p.tok.xkind != pxSymbol: parMessage(p, errIdentifierExpected, $(p.tok^))
|
||||
|
||||
proc Eat(p: var TParser, xkind: TTokKind, n: PNode) =
|
||||
if p.tok.xkind == xkind: getTok(p, n)
|
||||
@@ -375,7 +374,7 @@ proc skipTypeIdentExport(p: var TParser, prefix='T'): PNode =
|
||||
proc markTypeIdent(p: var TParser, typ: PNode) =
|
||||
if pfTypePrefixes in p.options.flags:
|
||||
var prefix = ""
|
||||
if typ == nil:
|
||||
if typ == nil or typ.kind == nkEmpty:
|
||||
prefix = "T"
|
||||
else:
|
||||
var t = typ
|
||||
@@ -479,11 +478,12 @@ proc newProcPragmas(p: TParser): PNode =
|
||||
|
||||
proc addPragmas(father, pragmas: PNode) =
|
||||
if sonsLen(pragmas) > 0: addSon(father, pragmas)
|
||||
else: addSon(father, nil)
|
||||
else: addSon(father, ast.emptyNode)
|
||||
|
||||
proc addReturnType(params, rettyp: PNode) =
|
||||
if rettyp == nil or rettyp.kind != nkNilLit: addSon(params, rettyp)
|
||||
else: addson(params, nil)
|
||||
if rettyp == nil: addSon(params, ast.emptyNode)
|
||||
elif rettyp.kind != nkNilLit: addSon(params, rettyp)
|
||||
else: addson(params, ast.emptyNode)
|
||||
|
||||
proc parseFormalParams(p: var TParser, params, pragmas: PNode)
|
||||
|
||||
@@ -527,9 +527,6 @@ proc parseTypeSuffix(p: var TParser, typ: PNode): PNode =
|
||||
else: break
|
||||
|
||||
proc typeDesc(p: var TParser): PNode =
|
||||
#result = typeAtom(p)
|
||||
#if result != nil:
|
||||
# result = pointer(p, result)
|
||||
result = pointer(p, typeAtom(p))
|
||||
|
||||
proc parseField(p: var TParser, kind: TNodeKind): PNode =
|
||||
@@ -560,7 +557,7 @@ proc parseStructBody(p: var TParser, isUnion: bool,
|
||||
var t = pointer(p, baseTyp)
|
||||
var i = parseField(p, kind)
|
||||
t = parseTypeSuffix(p, t)
|
||||
addSon(def, i, t, nil)
|
||||
addSon(def, i, t, ast.emptyNode)
|
||||
if not takeOnlyFirstField(p, isUnion) or sonsLen(result) < 1:
|
||||
addSon(result, def)
|
||||
if p.tok.xkind != pxComma: break
|
||||
@@ -591,7 +588,7 @@ proc enumPragmas(p: TParser, name: PNode): PNode =
|
||||
|
||||
proc parseStruct(p: var TParser, isUnion: bool): PNode =
|
||||
result = newNodeP(nkObjectTy, p)
|
||||
addSon(result, nil, nil) # no pragmas, no inheritance
|
||||
addSon(result, ast.emptyNode, ast.emptyNode) # no pragmas, no inheritance
|
||||
if p.tok.xkind == pxCurlyLe:
|
||||
addSon(result, parseStructBody(p, isUnion))
|
||||
else:
|
||||
@@ -616,7 +613,7 @@ proc parseParam(p: var TParser, params: PNode) =
|
||||
getTok(p, x)
|
||||
addSon(x, assignmentExpression(p))
|
||||
else:
|
||||
addSon(x, nil)
|
||||
addSon(x, ast.emptyNode)
|
||||
addSon(params, x)
|
||||
|
||||
proc parseFormalParams(p: var TParser, params, pragmas: PNode) =
|
||||
@@ -662,15 +659,16 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
|
||||
if p.inTypeDef == 0:
|
||||
result = newNodeP(nkVarSection, p)
|
||||
var def = newNodeP(nkIdentDefs, p)
|
||||
addSon(def, name, procType, nil)
|
||||
addSon(def, name, procType, ast.emptyNode)
|
||||
addSon(result, def)
|
||||
else:
|
||||
result = newNodeP(nkTypeDef, p)
|
||||
addSon(result, name, nil, procType)
|
||||
addSon(result, name, ast.emptyNode, procType)
|
||||
assert result != nil
|
||||
|
||||
proc addTypeDef(section, name, t: PNode) =
|
||||
var def = newNodeI(nkTypeDef, name.info)
|
||||
addSon(def, name, nil, t)
|
||||
addSon(def, name, ast.emptyNode, t)
|
||||
addSon(section, def)
|
||||
|
||||
proc otherTypeDef(p: var TParser, section, typ: PNode) =
|
||||
@@ -705,7 +703,7 @@ proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) =
|
||||
|
||||
proc enumFields(p: var TParser): PNode =
|
||||
result = newNodeP(nkEnumTy, p)
|
||||
addSon(result, nil) # enum does not inherit from anything
|
||||
addSon(result, ast.emptyNode) # enum does not inherit from anything
|
||||
while true:
|
||||
var e = skipIdent(p)
|
||||
if p.tok.xkind == pxAsgn:
|
||||
@@ -846,7 +844,7 @@ proc addInitializer(p: var TParser, def: PNode) =
|
||||
getTok(p, def)
|
||||
addSon(def, parseInitializer(p))
|
||||
else:
|
||||
addSon(def, nil)
|
||||
addSon(def, ast.emptyNode)
|
||||
|
||||
proc parseVarDecl(p: var TParser, baseTyp, typ: PNode,
|
||||
origName: string): PNode =
|
||||
@@ -921,22 +919,24 @@ proc declaration(p: var TParser): PNode =
|
||||
addSon(pragmas, newIdentNodeP("cdecl", p))
|
||||
elif pfStdcall in p.options.flags:
|
||||
addSon(pragmas, newIdentNodeP("stdcall", p))
|
||||
addSon(result, exportSym(p, name, origName), nil) # no generics
|
||||
addSon(result, exportSym(p, name, origName), ast.emptyNode) # no generics
|
||||
addSon(result, params, pragmas)
|
||||
case p.tok.xkind
|
||||
of pxSemicolon:
|
||||
getTok(p)
|
||||
addSon(result, nil) # nobody
|
||||
addSon(result, ast.emptyNode) # nobody
|
||||
if p.scopeCounter == 0: DoImport(origName, pragmas, p)
|
||||
of pxCurlyLe:
|
||||
addSon(result, compoundStatement(p))
|
||||
else:
|
||||
parMessage(p, errTokenExpected, ";")
|
||||
if sonsLen(result.sons[pragmasPos]) == 0: result.sons[pragmasPos] = nil
|
||||
if sonsLen(result.sons[pragmasPos]) == 0:
|
||||
result.sons[pragmasPos] = ast.emptyNode
|
||||
of pxAsgn, pxSemicolon, pxComma:
|
||||
result = parseVarDecl(p, baseTyp, rettyp, origName)
|
||||
else:
|
||||
parMessage(p, errTokenExpected, ";")
|
||||
assert result != nil
|
||||
|
||||
proc createConst(name, typ, val: PNode, p: TParser): PNode =
|
||||
result = newNodeP(nkConstDef, p)
|
||||
@@ -963,7 +963,7 @@ proc enumSpecifier(p: var TParser): PNode =
|
||||
else:
|
||||
val = newIntNodeP(nkIntLit, i, p)
|
||||
inc(i)
|
||||
var c = createConst(name, nil, val, p)
|
||||
var c = createConst(name, ast.emptyNode, val, p)
|
||||
addSon(result, c)
|
||||
if p.tok.xkind != pxComma: break
|
||||
getTok(p, c)
|
||||
@@ -984,7 +984,7 @@ proc enumSpecifier(p: var TParser): PNode =
|
||||
var t = newNodeP(nkTypeDef, p)
|
||||
getTok(p, t)
|
||||
var e = enumFields(p)
|
||||
addSon(t, exportSym(p, name, origName), nil, e) # nil for generic params
|
||||
addSon(t, exportSym(p, name, origName), ast.emptyNode, e)
|
||||
addSon(result, t)
|
||||
eat(p, pxCurlyRi, result)
|
||||
eat(p, pxSemicolon)
|
||||
@@ -998,6 +998,7 @@ proc enumSpecifier(p: var TParser): PNode =
|
||||
else:
|
||||
closeContext(p)
|
||||
parMessage(p, errTokenExpected, "{")
|
||||
result = ast.emptyNode
|
||||
|
||||
# Expressions
|
||||
|
||||
@@ -1085,7 +1086,7 @@ proc primaryExpression(p: var TParser): PNode =
|
||||
of pxParLe:
|
||||
result = castExpression(p)
|
||||
else:
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
|
||||
proc multiplicativeExpression(p: var TParser): PNode =
|
||||
result = castExpression(p)
|
||||
@@ -1309,7 +1310,7 @@ proc andExpression(p: var TParser): PNode =
|
||||
getTok(p, result)
|
||||
var a = result
|
||||
var b = equalityExpression(p)
|
||||
result = newBinary("&", a, b, p)
|
||||
result = newBinary("and", a, b, p)
|
||||
|
||||
proc exclusiveOrExpression(p: var TParser): PNode =
|
||||
result = andExpression(p)
|
||||
@@ -1390,10 +1391,12 @@ proc expressionStatement(p: var TParser): PNode =
|
||||
# do not skip the comment after a semicolon to make a new nkCommentStmt
|
||||
if p.tok.xkind == pxSemicolon:
|
||||
getTok(p)
|
||||
result = ast.emptyNode
|
||||
else:
|
||||
result = expression(p)
|
||||
if p.tok.xkind == pxSemicolon: getTok(p)
|
||||
else: parMessage(p, errTokenExpected, ";")
|
||||
assert result != nil
|
||||
|
||||
proc parseIf(p: var TParser): PNode =
|
||||
# we parse additional "else if"s too here for better Nimrod code
|
||||
@@ -1431,7 +1434,7 @@ proc parseDoWhile(p: var TParser): PNode =
|
||||
# ``block: stmt``
|
||||
result = newNodeP(nkBlockStmt, p)
|
||||
getTok(p, result) # skip "do"
|
||||
addSon(result, nil, nestedStatement(p))
|
||||
addSon(result, ast.emptyNode, nestedStatement(p))
|
||||
eat(p, "while", result)
|
||||
eat(p, pxParLe, result)
|
||||
if p.tok.xkind == pxIntLit and p.tok.iNumber == 0: getTok(p, result)
|
||||
@@ -1465,6 +1468,7 @@ proc declarationOrStatement(p: var TParser): PNode =
|
||||
else:
|
||||
backtrackContext(p)
|
||||
result = expressionStatement(p)
|
||||
assert result != nil
|
||||
|
||||
proc parseTuple(p: var TParser, isUnion: bool): PNode =
|
||||
result = parseStructBody(p, isUnion, nkTupleTy)
|
||||
@@ -1516,15 +1520,16 @@ proc parseFor(p: var TParser, result: PNode) =
|
||||
getTok(p, result)
|
||||
eat(p, pxParLe, result)
|
||||
var initStmt = declarationOrStatement(p)
|
||||
addSonIfNotNil(result, initStmt)
|
||||
if initStmt.kind != nkEmpty:
|
||||
addSon(result, initStmt)
|
||||
var w = newNodeP(nkWhileStmt, p)
|
||||
var condition = expressionStatement(p)
|
||||
if condition == nil: condition = newIdentNodeP("true", p)
|
||||
if condition.kind == nkEmpty: condition = newIdentNodeP("true", p)
|
||||
addSon(w, condition)
|
||||
var step = if p.tok.xkind != pxParRi: expression(p) else: nil
|
||||
var step = if p.tok.xkind != pxParRi: expression(p) else: ast.emptyNode
|
||||
eat(p, pxParRi, step)
|
||||
var loopBody = nestedStatement(p)
|
||||
if step != nil:
|
||||
if step.kind != nkEmpty:
|
||||
loopBody = buildStmtList(loopBody)
|
||||
addSon(loopBody, step)
|
||||
addSon(w, loopBody)
|
||||
@@ -1604,7 +1609,7 @@ proc embedStmts(sl, a: PNode) =
|
||||
addStmt(sl, a)
|
||||
else:
|
||||
for i in 0..sonsLen(a)-1:
|
||||
if a[i] != nil: addStmt(sl, a[i])
|
||||
if a[i].kind != nkEmpty: addStmt(sl, a[i])
|
||||
|
||||
proc compoundStatement(p: var TParser): PNode =
|
||||
result = newNodeP(nkStmtList, p)
|
||||
@@ -1612,7 +1617,7 @@ proc compoundStatement(p: var TParser): PNode =
|
||||
inc(p.scopeCounter)
|
||||
while p.tok.xkind notin {pxEof, pxCurlyRi}:
|
||||
var a = statement(p)
|
||||
if a == nil: break
|
||||
if a.kind == nkEmpty: break
|
||||
embedStmts(result, a)
|
||||
if sonsLen(result) == 0:
|
||||
# translate ``{}`` to Nimrod's ``nil`` statement
|
||||
@@ -1644,12 +1649,12 @@ proc statement(p: var TParser): PNode =
|
||||
result = newNodeP(nkContinueStmt, p)
|
||||
getTok(p)
|
||||
eat(p, pxSemicolon)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
of "break":
|
||||
result = newNodeP(nkBreakStmt, p)
|
||||
getTok(p)
|
||||
eat(p, pxSemicolon)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
of "return":
|
||||
result = newNodeP(nkReturnStmt, p)
|
||||
getTok(p)
|
||||
@@ -1662,18 +1667,13 @@ proc statement(p: var TParser): PNode =
|
||||
elif p.tok.xkind != pxSemicolon:
|
||||
addSon(result, expression(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
eat(p, pxSemicolon)
|
||||
of "enum":
|
||||
result = enumSpecifier(p)
|
||||
of "typedef":
|
||||
result = parseTypeDef(p)
|
||||
of "struct":
|
||||
result = parseStandaloneStruct(p, isUnion=false)
|
||||
of "union":
|
||||
result = parseStandaloneStruct(p, isUnion=true)
|
||||
else:
|
||||
result = declarationOrStatement(p)
|
||||
of "enum": result = enumSpecifier(p)
|
||||
of "typedef": result = parseTypeDef(p)
|
||||
of "struct": result = parseStandaloneStruct(p, isUnion=false)
|
||||
of "union": result = parseStandaloneStruct(p, isUnion=true)
|
||||
else: result = declarationOrStatement(p)
|
||||
of pxCurlyLe:
|
||||
result = compoundStatement(p)
|
||||
of pxDirective, pxDirectiveParLe:
|
||||
@@ -1691,12 +1691,12 @@ proc statement(p: var TParser): PNode =
|
||||
result = newNodeP(nkNilLit, p)
|
||||
else:
|
||||
result = expressionStatement(p)
|
||||
#parMessage(p, errStmtExpected)
|
||||
assert result != nil
|
||||
|
||||
proc parseUnit(p: var TParser): PNode =
|
||||
result = newNodeP(nkStmtList, p)
|
||||
getTok(p) # read first token
|
||||
while p.tok.xkind != pxEof:
|
||||
var s = statement(p)
|
||||
if s != nil: embedStmts(result, s)
|
||||
if s.kind != nkEmpty: embedStmts(result, s)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ proc parseDefine(p: var TParser): PNode =
|
||||
eat(p, pxParLe)
|
||||
var params = newNodeP(nkFormalParams, p)
|
||||
# return type; not known yet:
|
||||
addSon(params, nil)
|
||||
addSon(params, ast.emptyNode)
|
||||
var identDefs = newNodeP(nkIdentDefs, p)
|
||||
while p.tok.xkind != pxParRi:
|
||||
addSon(identDefs, skipIdent(p))
|
||||
@@ -53,13 +53,13 @@ proc parseDefine(p: var TParser): PNode =
|
||||
if p.tok.xkind != pxComma: break
|
||||
getTok(p)
|
||||
addSon(identDefs, newIdentNodeP("expr", p))
|
||||
addSon(identDefs, nil)
|
||||
addSon(identDefs, ast.emptyNode)
|
||||
addSon(params, identDefs)
|
||||
eat(p, pxParRi)
|
||||
|
||||
addSon(result, nil) # no generic parameters
|
||||
addSon(result, ast.emptyNode) # no generic parameters
|
||||
addSon(result, params)
|
||||
addSon(result, nil) # no pragmas
|
||||
addSon(result, ast.emptyNode) # no pragmas
|
||||
var kind = parseDefineBody(p, result)
|
||||
params.sons[0] = newIdentNodeP(kind, p)
|
||||
eatNewLine(p, result)
|
||||
@@ -70,7 +70,7 @@ proc parseDefine(p: var TParser): PNode =
|
||||
getTok(p) # skip #define
|
||||
var c = newNodeP(nkConstDef, p)
|
||||
addSon(c, skipIdentExport(p))
|
||||
addSon(c, nil)
|
||||
addSon(c, ast.emptyNode)
|
||||
skipStarCom(p, c)
|
||||
if p.tok.xkind in {pxLineComment, pxNewLine, pxEof}:
|
||||
addSon(c, newIdentNodeP("true", p))
|
||||
@@ -78,6 +78,7 @@ proc parseDefine(p: var TParser): PNode =
|
||||
addSon(c, expression(p))
|
||||
addSon(result, c)
|
||||
eatNewLine(p, c)
|
||||
assert result != nil
|
||||
|
||||
proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) =
|
||||
m.body = @[]
|
||||
@@ -147,7 +148,7 @@ proc parseInclude(p: var TParser): PNode =
|
||||
skipLine(p)
|
||||
if sonsLen(result) == 0:
|
||||
# we only parsed includes that we chose to ignore:
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
|
||||
proc definedExprAux(p: var TParser): PNode =
|
||||
result = newNodeP(nkCall, p)
|
||||
@@ -226,6 +227,7 @@ proc parseIfdef(p: var TParser): PNode =
|
||||
case p.tok.s
|
||||
of "__cplusplus":
|
||||
skipUntilEndif(p)
|
||||
result = ast.emptyNode
|
||||
of c2nimSymbol:
|
||||
skipLine(p)
|
||||
result = parseStmtList(p)
|
||||
@@ -238,6 +240,7 @@ proc parseIfdef(p: var TParser): PNode =
|
||||
parseIfDirAux(p, result)
|
||||
|
||||
proc parseIfndef(p: var TParser): PNode =
|
||||
result = ast.emptyNode
|
||||
getTok(p) # skip #ifndef
|
||||
ExpectIdent(p)
|
||||
if p.tok.s == c2nimSymbol:
|
||||
@@ -295,6 +298,7 @@ proc parseMangleDir(p: var TParser) =
|
||||
eatNewLine(p, nil)
|
||||
|
||||
proc parseDir(p: var TParser): PNode =
|
||||
result = ast.emptyNode
|
||||
assert(p.tok.xkind in {pxDirective, pxDirectiveParLe})
|
||||
case p.tok.s
|
||||
of "define": result = parseDefine(p)
|
||||
|
||||
@@ -29,7 +29,6 @@ proc addDependencyAux(importing, imported: string) =
|
||||
|
||||
proc addDotDependency(c: PPassContext, n: PNode): PNode =
|
||||
result = n
|
||||
if n == nil: return
|
||||
var g = PGen(c)
|
||||
case n.kind
|
||||
of nkImportStmt:
|
||||
|
||||
@@ -771,7 +771,6 @@ proc traceDeps(d: PDoc, n: PNode) =
|
||||
"$1", [toRope(getModuleFile(n))])
|
||||
|
||||
proc generateDoc(d: PDoc, n: PNode) =
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkCommentStmt: app(d.modDesc, genComment(d, n))
|
||||
of nkProcDef: genItem(d, n, n.sons[namePos], skProc)
|
||||
|
||||
@@ -54,8 +54,6 @@ const
|
||||
evalMaxIterations = 10000000 # max iterations of all loops
|
||||
evalMaxRecDepth = 100000 # max recursion depth for evaluation
|
||||
|
||||
var emptyNode: PNode
|
||||
|
||||
proc newStackFrame(): PStackFrame =
|
||||
new(result)
|
||||
initIdNodeTable(result.mapping)
|
||||
@@ -136,7 +134,7 @@ proc evalWhile(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
case result.kind
|
||||
of nkBreakStmt:
|
||||
if result.sons[0] == nil:
|
||||
if result.sons[0].kind == nkEmpty:
|
||||
result = emptyNode # consume ``break`` token
|
||||
break
|
||||
of nkExceptBranch, nkReturnToken:
|
||||
@@ -153,7 +151,7 @@ proc evalBlock(c: PEvalContext, n: PNode): PNode =
|
||||
if result.kind == nkBreakStmt:
|
||||
if result.sons[0] != nil:
|
||||
assert(result.sons[0].kind == nkSym)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkempty:
|
||||
assert(n.sons[0].kind == nkSym)
|
||||
if result.sons[0].sym.id == n.sons[0].sym.id: result = emptyNode
|
||||
else:
|
||||
@@ -228,7 +226,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
|
||||
assert(a.kind == nkIdentDefs)
|
||||
assert(a.sons[0].kind == nkSym)
|
||||
var v = a.sons[0].sym
|
||||
if a.sons[2] != nil:
|
||||
if a.sons[2].kind != nkEmpty:
|
||||
result = evalAux(c, a.sons[2], {})
|
||||
if isSpecial(result): return
|
||||
else:
|
||||
@@ -507,7 +505,7 @@ proc evalConvCStrToStr(c: PEvalContext, n: PNode): PNode =
|
||||
result.typ = n.typ
|
||||
|
||||
proc evalRaise(c: PEvalContext, n: PNode): PNode =
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
result = evalAux(c, n.sons[0], {})
|
||||
if isSpecial(result): return
|
||||
var a = result
|
||||
@@ -519,17 +517,17 @@ proc evalRaise(c: PEvalContext, n: PNode): PNode =
|
||||
else:
|
||||
stackTrace(c, n, errExceptionAlreadyHandled)
|
||||
result = newNodeIT(nkExceptBranch, n.info, nil)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
|
||||
proc evalReturn(c: PEvalContext, n: PNode): PNode =
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
result = evalAsgn(c, n.sons[0])
|
||||
if isSpecial(result): return
|
||||
result = newNodeIT(nkReturnToken, n.info, nil)
|
||||
|
||||
proc evalProc(c: PEvalContext, n: PNode): PNode =
|
||||
if n.sons[genericParamsPos] == nil:
|
||||
if (resultPos < sonsLen(n)) and (n.sons[resultPos] != nil):
|
||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||
if (resultPos < sonsLen(n)) and (n.sons[resultPos].kind != nkEmpty):
|
||||
var v = n.sons[resultPos].sym
|
||||
result = getNullValue(v.typ, n.info)
|
||||
IdNodeTablePut(c.tos.mapping, v, result)
|
||||
@@ -740,8 +738,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
if isSpecial(result): return
|
||||
var k = getOrdValue(b)
|
||||
if (k >= 0) and (k < sonsLen(a)) and not (a.kind in {nkEmpty..nkNilLit}):
|
||||
if result.kind == nkEmpty: a.sons[int(k)] = nil
|
||||
else: a.sons[int(k)] = result
|
||||
a.sons[int(k)] = result
|
||||
else:
|
||||
stackTrace(c, n, errIndexOutOfBounds)
|
||||
result = emptyNode
|
||||
@@ -1055,4 +1052,3 @@ proc evalPass(): TPass =
|
||||
result.close = myProcess
|
||||
result.process = myProcess
|
||||
|
||||
emptyNode = newNode(nkEmpty)
|
||||
|
||||
@@ -109,6 +109,7 @@ proc CommandGenDepend(filename: string) =
|
||||
changeFileExt(filename, "dot"))
|
||||
|
||||
proc CommandCheck(filename: string) =
|
||||
msgs.gErrorMax = high(int) # do not stop after first error
|
||||
semanticPasses() # use an empty backend for semantic checking only
|
||||
compileProject(filename)
|
||||
|
||||
|
||||
391
rod/msgs.nim
391
rod/msgs.nim
@@ -62,7 +62,7 @@ type
|
||||
errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValue,
|
||||
errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice,
|
||||
errInvalidOrderInArrayConstructor,
|
||||
errInvalidOrderInEnumX, errEnumXHasWholes, errExceptExpected, errInvalidTry,
|
||||
errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry,
|
||||
errOptionExpected, errXisNoLabel, errNotAllCasesCovered,
|
||||
errUnkownSubstitionVar, errComplexStmtRequiresInd, errXisNotCallable,
|
||||
errNoPragmasAllowedForX, errNoGenericParamsAllowedForX,
|
||||
@@ -96,154 +96,245 @@ type
|
||||
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintUser
|
||||
|
||||
const
|
||||
MsgKindToStr*: array[TMsgKind, string] = ["unknown error",
|
||||
"illformed AST: $1", "cannot open \'$1\'", "internal error: $1", "$1",
|
||||
"\'$1\' compiler does not support C++", "string literal expected",
|
||||
"integer literal expected", "invalid character constant",
|
||||
"closing \"\"\" expected, but end of file reached", "closing \" expected",
|
||||
"tabulators are not allowed", "invalid token: $1", "line too long",
|
||||
"$1 is not a valid number", "number $1 out of valid range",
|
||||
"\\n not allowed in character literal",
|
||||
"closing \']\' expected, but end of file reached", "missing final \'",
|
||||
"identifier expected, but found \'$1\'",
|
||||
"operator expected, but found \'$1\'", "\'$1\' expected",
|
||||
"string after \'include\' expected", "recursive dependency: \'$1\'",
|
||||
"\'on\' or \'off\' expected", "\'none\', \'speed\' or \'size\' expected",
|
||||
"invalid pragma", "unknown pragma: \'$1\'", "invalid directive: \'$1\'",
|
||||
"\'pop\' without a \'push\' pragma", "empty asm statement",
|
||||
"invalid indentation", "exception expected", "exception already handled",
|
||||
"\'yield\' only allowed in a loop of an iterator",
|
||||
"invalid number of \'yield\' expresions",
|
||||
"current routine cannot return an expression", "attempt to redefine \'$1\'",
|
||||
"statement not allowed after \'return\', \'break\' or \'raise\'",
|
||||
"statement expected", "\'$1\' is no label",
|
||||
"invalid command line option: \'$1\'",
|
||||
"argument for command line option expected: \'$1\'",
|
||||
"invalid argument for command line option: \'$1\'",
|
||||
"invalid variable substitution in \'$1\'", "unknown variable: \'$1\'",
|
||||
"unknown C compiler: \'$1\'",
|
||||
"\'on\' or \'off\' expected, but \'$1\' found",
|
||||
"\'none\', \'boehm\' or \'refc\' expected, but \'$1\' found",
|
||||
"\'none\', \'speed\' or \'size\' expected, but \'$1\' found",
|
||||
"\'gui\', \'console\' or \'lib\' expected, but \'$1\' found",
|
||||
"unknown OS: \'$1\'", "unknown CPU: \'$1\'",
|
||||
"\'c\', \'c++\' or \'yaml\' expected, but \'$1\' found",
|
||||
"arguments can only be given if the \'--run\' option is selected",
|
||||
"multiple assignment is not allowed",
|
||||
"\':\' or \'=\' expected, but found \'$1\'",
|
||||
"expression expected, but found \'$1\'", "undeclared identifier: \'$1\'",
|
||||
"ambiguous identifier: \'$1\' -- use a qualifier", "type expected",
|
||||
"system module needs \'$1\'", "execution of an external program failed",
|
||||
"overloaded \'$1\' leads to ambiguous calls", "invalid argument for \'$1\'",
|
||||
"statement has no effect", "\'$1\' expects a type or value",
|
||||
"\'$1\' expects an array type",
|
||||
"\'$1\' cannot be instantiated because its body has not been compiled yet",
|
||||
"expression \'$1\' ambiguous in this context", "constant division by zero",
|
||||
"ordinal type expected", "ordinal or float type expected",
|
||||
"over- or underflow",
|
||||
"cannot evalutate \'$1\' because type is not defined completely",
|
||||
"\'chr\' expects an int in the range 0..255",
|
||||
"\'dynlib\' requires \'exportc\'", "undeclared field: \'$1\'",
|
||||
"attempt to access a nil address", "index out of bounds",
|
||||
"index types do not match", "\'[]\' operator invalid for this type",
|
||||
"value out of set bounds", "field initialized twice: \'$1\'",
|
||||
"field \'$1\' not initialized", "expression \'$1\' cannot be called",
|
||||
"expression has no type", "expression \'$1\' has no type (or is ambiguous)",
|
||||
"\'cast\' not allowed in safe mode", "expression cannot be casted to $1",
|
||||
"\',\' or \')\' expected", "\'{\' or \'(\' expected",
|
||||
"section (\'type\', \'proc\', etc.) expected", "range expected",
|
||||
"attempt to redefine \'$1\'", "\'magic\' only allowed in system module",
|
||||
"power of two expected", "string literal may not be empty",
|
||||
"calling convention expected",
|
||||
"a proc can only have one calling convention",
|
||||
"symbol must be imported if \'lib\' pragma is used",
|
||||
"expression must be of type \'bool\'", "constant expression expected",
|
||||
"duplicate case label", "range is empty",
|
||||
"selector must be of an ordinal type, real or string",
|
||||
"selector must be of an ordinal type", "ord($1) must not be negative",
|
||||
"len($1) must be less than 32768", "wrong number of variables",
|
||||
"only objects can be raised", "\'break\' only allowed in loop construct",
|
||||
"type \'$1\' has unknown size",
|
||||
"a constant can only be initialized with a constant expression",
|
||||
"a constant needs a value", "the result type cannot be on open array",
|
||||
"computing the type\'s size produced an overflow", "set is too large",
|
||||
"base type of a set must be an ordinal",
|
||||
"inheritance only works with non-final objects",
|
||||
"inheritance only works with an enum", "illegal recursion in type \'$1\'",
|
||||
"cannot instantiate: \'$1\'", "expression has no address",
|
||||
"for a \'var\' type a variable needs to be passed", "type mismatch",
|
||||
"type mismatch: got (", "but expected one of: ", "but expected \'$1\'",
|
||||
"ambiguous call; both $1 and $2 match for: $3", "wrong number of arguments",
|
||||
"\'$1\' cannot be passed to a procvar",
|
||||
"$1 cannot be declared in parameter declaration",
|
||||
"pragmas are only in the header of a proc allowed",
|
||||
"implementation of \'$1\' is not allowed",
|
||||
"implementation of \'$1\' expected", "no symbol to borrow from found",
|
||||
"value returned by statement has to be discarded",
|
||||
"statement returns no value that can be discarded",
|
||||
"conversion from $1 to $2 is invalid", "cannot bind parameter \'$1\' twice",
|
||||
"invalid order in array constructor",
|
||||
"invalid order in enum \'$1\'", "enum \'$1\' has wholes",
|
||||
"\'except\' or \'finally\' expected",
|
||||
"after catch all \'except\' or \'finally\' no section may follow",
|
||||
"option expected, but found \'$1\'", "\'$1\' is not a label",
|
||||
"not all cases are covered", "unknown substitution variable: \'$1\'",
|
||||
"complex statement requires indentation", "\'$1\' is not callable",
|
||||
"no pragmas allowed for $1", "no generic parameters allowed for $1",
|
||||
"invalid param kind: \'$1\'", "default argument invalid",
|
||||
"named parameter has to be an identifier", "no return type for $1 allowed",
|
||||
"a type conversion needs exactly one argument", "invalid pragma: $1",
|
||||
"$1 not allowed here", "invalid control flow: $1", "a type has no value",
|
||||
"invalid type: \'$1\'", "\'^\' needs a pointer or reference type",
|
||||
"invalid expression", "invalid expression: \'$1\'",
|
||||
"enum has no value \'$1\'", "named expression expected",
|
||||
"named expression not allowed here", "\'$1\' expects one type parameter",
|
||||
"array expects two type parameters", "invalid visibility: \'$1\'",
|
||||
"initialization not allowed here", "\'$1\' cannot be assigned to",
|
||||
"iterators can only be defined at the module\'s top level",
|
||||
"$1 needs a return type", "invalid command: \'$1\'",
|
||||
"\'$1\' is only allowed at top level",
|
||||
"'$1' needs a parameter that has an object type",
|
||||
"template/macro instantiation too nested", "instantiation from here",
|
||||
"invalid index value for tuple subscript",
|
||||
"command expects a filename argument", "\'$1\' expected",
|
||||
"invalid section start", "grid table is not implemented",
|
||||
"general parse error", "new section expected",
|
||||
"whitespace expected, got \'$1\'", "\'$1\' is no valid index file",
|
||||
"cannot render reStructuredText element \'$1\'",
|
||||
"type \'var var\' is not allowed", "\'is\' expects two arguments",
|
||||
"\'is\' expects object types", "\'$1\' can never be of this subtype",
|
||||
"interpretation requires too many iterations",
|
||||
"cannot interpret node kind \'$1\'", "field \'$1\' cannot be found",
|
||||
"invalid conversion from type \'$1\'", "assertion failed",
|
||||
"cannot generate code for \'$1\'", "$1 requires one parameter",
|
||||
"unhandled exception: $1", "macro returned a cyclic abstract syntax tree",
|
||||
"\'$1\' is no macro or template", "\'$1\' can have side effects",
|
||||
"iterator within for loop context expected", "$1",
|
||||
"cannot open \'$1\' [CannotOpenFile]", "octal escape sequences do not exist; leading zero is ignored [OctalEscape]",
|
||||
"\'$1\' is never read [XIsNeverRead]",
|
||||
"\'$1\' might not have been initialized [XmightNotBeenInit]",
|
||||
"cannot write file \'$1\' [CannotWriteMO2]",
|
||||
"cannot read file \'$1\' [CannotReadMO2]",
|
||||
"\'$1\' is deprecated [Deprecated]", "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]",
|
||||
"unknown magic \'$1\' might crash the compiler [UnknownMagic]",
|
||||
"redefinition of label \'$1\' [RedefinitionOfLabel]",
|
||||
"unknown substitution \'$1\' [UnknownSubstitutionX]",
|
||||
"language \'$1\' not supported [LanguageXNotSupported]",
|
||||
"comment \'$1\' ignored [CommentXIgnored]",
|
||||
"\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]",
|
||||
"$1 [User]", "operation successful [Success]",
|
||||
"operation successful ($1 lines compiled; $2 sec total) [SuccessX]",
|
||||
"line too long [LineTooLong]",
|
||||
"\'$1\' is declared but not used [XDeclaredButNotUsed]",
|
||||
"conversion to base object is not needed [ConvToBaseNotNeeded]",
|
||||
"conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]",
|
||||
"expression evaluates always to \'$1\' [ExprAlwaysX]",
|
||||
"quit() called [QuitCalled]", "$1 [Processing]",
|
||||
"generated code listing: [CodeBegin]", "end of listing [CodeEnd]",
|
||||
"used config file \'$1\' [Conf]",
|
||||
"added path: '$1' [Path]",
|
||||
"$1 [User]"]
|
||||
MsgKindToStr*: array[TMsgKind, string] = [
|
||||
errUnknown: "unknown error",
|
||||
errIllFormedAstX: "illformed AST: $1",
|
||||
errCannotOpenFile: "cannot open \'$1\'",
|
||||
errInternal: "internal error: $1",
|
||||
errGenerated: "$1",
|
||||
errXCompilerDoesNotSupportCpp: "\'$1\' compiler does not support C++",
|
||||
errStringLiteralExpected: "string literal expected",
|
||||
errIntLiteralExpected: "integer literal expected",
|
||||
errInvalidCharacterConstant: "invalid character constant",
|
||||
errClosingTripleQuoteExpected: "closing \"\"\" expected, but end of file reached",
|
||||
errClosingQuoteExpected: "closing \" expected",
|
||||
errTabulatorsAreNotAllowed: "tabulators are not allowed",
|
||||
errInvalidToken: "invalid token: $1",
|
||||
errLineTooLong: "line too long",
|
||||
errInvalidNumber: "$1 is not a valid number",
|
||||
errNumberOutOfRange: "number $1 out of valid range",
|
||||
errNnotAllowedInCharacter: "\\n not allowed in character literal",
|
||||
errClosingBracketExpected: "closing ']' expected, but end of file reached",
|
||||
errMissingFinalQuote: "missing final \'",
|
||||
errIdentifierExpected: "identifier expected, but found \'$1\'",
|
||||
errOperatorExpected: "operator expected, but found \'$1\'",
|
||||
errTokenExpected: "\'$1\' expected",
|
||||
errStringAfterIncludeExpected: "string after \'include\' expected",
|
||||
errRecursiveDependencyX: "recursive dependency: \'$1\'",
|
||||
errOnOrOffExpected: "\'on\' or \'off\' expected",
|
||||
errNoneSpeedOrSizeExpected: "\'none\', \'speed\' or \'size\' expected",
|
||||
errInvalidPragma: "invalid pragma",
|
||||
errUnknownPragma: "unknown pragma: \'$1\'",
|
||||
errInvalidDirectiveX: "invalid directive: \'$1\'",
|
||||
errAtPopWithoutPush: "\'pop\' without a \'push\' pragma",
|
||||
errEmptyAsm: "empty asm statement",
|
||||
errInvalidIndentation: "invalid indentation",
|
||||
errExceptionExpected: "exception expected",
|
||||
errExceptionAlreadyHandled: "exception already handled",
|
||||
errYieldNotAllowedHere: "\'yield\' only allowed in a loop of an iterator",
|
||||
errInvalidNumberOfYieldExpr: "invalid number of \'yield\' expresions",
|
||||
errCannotReturnExpr: "current routine cannot return an expression",
|
||||
errAttemptToRedefine: "attempt to redefine \'$1\'",
|
||||
errStmtInvalidAfterReturn: "statement not allowed after \'return\', \'break\' or \'raise\'",
|
||||
errStmtExpected: "statement expected",
|
||||
errInvalidLabel: "\'$1\' is no label",
|
||||
errInvalidCmdLineOption: "invalid command line option: \'$1\'",
|
||||
errCmdLineArgExpected: "argument for command line option expected: \'$1\'",
|
||||
errCmdLineNoArgExpected: "invalid argument for command line option: \'$1\'",
|
||||
errInvalidVarSubstitution: "invalid variable substitution in \'$1\'",
|
||||
errUnknownVar: "unknown variable: \'$1\'",
|
||||
errUnknownCcompiler: "unknown C compiler: \'$1\'",
|
||||
errOnOrOffExpectedButXFound: "\'on\' or \'off\' expected, but \'$1\' found",
|
||||
errNoneBoehmRefcExpectedButXFound: "'none', 'boehm' or 'refc' expected, but '$1' found",
|
||||
errNoneSpeedOrSizeExpectedButXFound: "'none', 'speed' or 'size' expected, but '$1' found",
|
||||
errGuiConsoleOrLibExpectedButXFound: "'gui', 'console' or 'lib' expected, but '$1' found",
|
||||
errUnknownOS: "unknown OS: '$1'",
|
||||
errUnknownCPU: "unknown CPU: '$1'",
|
||||
errGenOutExpectedButXFound: "'c', 'c++' or 'yaml' expected, but '$1' found",
|
||||
errArgsNeedRunOption: "arguments can only be given if the '--run' option is selected",
|
||||
errInvalidMultipleAsgn: "multiple assignment is not allowed",
|
||||
errColonOrEqualsExpected: "\':\' or \'=\' expected, but found \'$1\'",
|
||||
errExprExpected: "expression expected, but found \'$1\'",
|
||||
errUndeclaredIdentifier: "undeclared identifier: \'$1\'",
|
||||
errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier",
|
||||
errTypeExpected: "type expected",
|
||||
errSystemNeeds: "system module needs \'$1\'",
|
||||
errExecutionOfProgramFailed: "execution of an external program failed",
|
||||
errNotOverloadable: "overloaded \'$1\' leads to ambiguous calls",
|
||||
errInvalidArgForX: "invalid argument for \'$1\'",
|
||||
errStmtHasNoEffect: "statement has no effect",
|
||||
errXExpectsTypeOrValue: "\'$1\' expects a type or value",
|
||||
errXExpectsArrayType: "\'$1\' expects an array type",
|
||||
errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet",
|
||||
errExprXAmbiguous: "expression '$1' ambiguous in this context",
|
||||
errConstantDivisionByZero: "constant division by zero",
|
||||
errOrdinalTypeExpected: "ordinal type expected",
|
||||
errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
|
||||
errOverOrUnderflow: "over- or underflow",
|
||||
errCannotEvalXBecauseIncompletelyDefined: "cannot evalutate '$1' because type is not defined completely",
|
||||
errChrExpectsRange0_255: "\'chr\' expects an int in the range 0..255",
|
||||
errDynlibRequiresExportc: "\'dynlib\' requires \'exportc\'",
|
||||
errUndeclaredFieldX: "undeclared field: \'$1\'",
|
||||
errNilAccess: "attempt to access a nil address",
|
||||
errIndexOutOfBounds: "index out of bounds",
|
||||
errIndexTypesDoNotMatch: "index types do not match",
|
||||
errBracketsInvalidForType: "\'[]\' operator invalid for this type",
|
||||
errValueOutOfSetBounds: "value out of set bounds",
|
||||
errFieldInitTwice: "field initialized twice: \'$1\'",
|
||||
errFieldNotInit: "field \'$1\' not initialized",
|
||||
errExprXCannotBeCalled: "expression \'$1\' cannot be called",
|
||||
errExprHasNoType: "expression has no type",
|
||||
errExprXHasNoType: "expression \'$1\' has no type (or is ambiguous)",
|
||||
errCastNotInSafeMode: "\'cast\' not allowed in safe mode",
|
||||
errExprCannotBeCastedToX: "expression cannot be casted to $1",
|
||||
errCommaOrParRiExpected: "',' or ')' expected",
|
||||
errCurlyLeOrParLeExpected: "\'{\' or \'(\' expected",
|
||||
errSectionExpected: "section (\'type\', \'proc\', etc.) expected",
|
||||
errRangeExpected: "range expected",
|
||||
errAttemptToRedefineX: "attempt to redefine \'$1\'",
|
||||
errMagicOnlyInSystem: "\'magic\' only allowed in system module",
|
||||
errPowerOfTwoExpected: "power of two expected",
|
||||
errStringMayNotBeEmpty: "string literal may not be empty",
|
||||
errCallConvExpected: "calling convention expected",
|
||||
errProcOnlyOneCallConv: "a proc can only have one calling convention",
|
||||
errSymbolMustBeImported: "symbol must be imported if 'lib' pragma is used",
|
||||
errExprMustBeBool: "expression must be of type 'bool'",
|
||||
errConstExprExpected: "constant expression expected",
|
||||
errDuplicateCaseLabel: "duplicate case label",
|
||||
errRangeIsEmpty: "range is empty",
|
||||
errSelectorMustBeOfCertainTypes: "selector must be of an ordinal type, float or string",
|
||||
errSelectorMustBeOrdinal: "selector must be of an ordinal type",
|
||||
errOrdXMustNotBeNegative: "ord($1) must not be negative",
|
||||
errLenXinvalid: "len($1) must be less than 32768",
|
||||
errWrongNumberOfVariables: "wrong number of variables",
|
||||
errExprCannotBeRaised: "only objects can be raised",
|
||||
errBreakOnlyInLoop: "'break' only allowed in loop construct",
|
||||
errTypeXhasUnknownSize: "type \'$1\' has unknown size",
|
||||
errConstNeedsConstExpr: "a constant can only be initialized with a constant expression",
|
||||
errConstNeedsValue: "a constant needs a value",
|
||||
errResultCannotBeOpenArray: "the result type cannot be on open array",
|
||||
errSizeTooBig: "computing the type\'s size produced an overflow",
|
||||
errSetTooBig: "set is too large",
|
||||
errBaseTypeMustBeOrdinal: "base type of a set must be an ordinal",
|
||||
errInheritanceOnlyWithNonFinalObjects: "inheritance only works with non-final objects",
|
||||
errInheritanceOnlyWithEnums: "inheritance only works with an enum",
|
||||
errIllegalRecursionInTypeX: "illegal recursion in type \'$1\'",
|
||||
errCannotInstantiateX: "cannot instantiate: \'$1\'",
|
||||
errExprHasNoAddress: "expression has no address",
|
||||
errVarForOutParamNeeded: "for a \'var\' type a variable needs to be passed",
|
||||
errPureTypeMismatch: "type mismatch",
|
||||
errTypeMismatch: "type mismatch: got (",
|
||||
errButExpected: "but expected one of: ",
|
||||
errButExpectedX: "but expected \'$1\'",
|
||||
errAmbiguousCallXYZ: "ambiguous call; both $1 and $2 match for: $3",
|
||||
errWrongNumberOfArguments: "wrong number of arguments",
|
||||
errXCannotBePassedToProcVar: "\'$1\' cannot be passed to a procvar",
|
||||
errXCannotBeInParamDecl: "$1 cannot be declared in parameter declaration",
|
||||
errPragmaOnlyInHeaderOfProc: "pragmas are only in the header of a proc allowed",
|
||||
errImplOfXNotAllowed: "implementation of \'$1\' is not allowed",
|
||||
errImplOfXexpected: "implementation of \'$1\' expected",
|
||||
errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
|
||||
errDiscardValue: "value returned by statement has to be discarded",
|
||||
errInvalidDiscard: "statement returns no value that can be discarded",
|
||||
errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
|
||||
errCannotBindXTwice: "cannot bind parameter \'$1\' twice",
|
||||
errInvalidOrderInArrayConstructor: "invalid order in array constructor",
|
||||
errInvalidOrderInEnumX: "invalid order in enum \'$1\'",
|
||||
errEnumXHasHoles: "enum \'$1\' has holes",
|
||||
errExceptExpected: "\'except\' or \'finally\' expected",
|
||||
errInvalidTry: "after catch all \'except\' or \'finally\' no section may follow",
|
||||
errOptionExpected: "option expected, but found \'$1\'",
|
||||
errXisNoLabel: "\'$1\' is not a label",
|
||||
errNotAllCasesCovered: "not all cases are covered",
|
||||
errUnkownSubstitionVar: "unknown substitution variable: \'$1\'",
|
||||
errComplexStmtRequiresInd: "complex statement requires indentation",
|
||||
errXisNotCallable: "\'$1\' is not callable",
|
||||
errNoPragmasAllowedForX: "no pragmas allowed for $1",
|
||||
errNoGenericParamsAllowedForX: "no generic parameters allowed for $1",
|
||||
errInvalidParamKindX: "invalid param kind: \'$1\'",
|
||||
errDefaultArgumentInvalid: "default argument invalid",
|
||||
errNamedParamHasToBeIdent: "named parameter has to be an identifier",
|
||||
errNoReturnTypeForX: "no return type for $1 allowed",
|
||||
errConvNeedsOneArg: "a type conversion needs exactly one argument",
|
||||
errInvalidPragmaX: "invalid pragma: $1",
|
||||
errXNotAllowedHere: "$1 not allowed here",
|
||||
errInvalidControlFlowX: "invalid control flow: $1",
|
||||
errATypeHasNoValue: "a type has no value",
|
||||
errXisNoType: "invalid type: \'$1\'",
|
||||
errCircumNeedsPointer: "\'^\' needs a pointer or reference type",
|
||||
errInvalidExpression: "invalid expression",
|
||||
errInvalidExpressionX: "invalid expression: \'$1\'",
|
||||
errEnumHasNoValueX: "enum has no value \'$1\'",
|
||||
errNamedExprExpected: "named expression expected",
|
||||
errNamedExprNotAllowed: "named expression not allowed here",
|
||||
errXExpectsOneTypeParam: "\'$1\' expects one type parameter",
|
||||
errArrayExpectsTwoTypeParams: "array expects two type parameters",
|
||||
errInvalidVisibilityX: "invalid visibility: \'$1\'",
|
||||
errInitHereNotAllowed: "initialization not allowed here",
|
||||
errXCannotBeAssignedTo: "\'$1\' cannot be assigned to",
|
||||
errIteratorNotAllowed: "iterators can only be defined at the module\'s top level",
|
||||
errXNeedsReturnType: "$1 needs a return type",
|
||||
errInvalidCommandX: "invalid command: \'$1\'",
|
||||
errXOnlyAtModuleScope: "\'$1\' is only allowed at top level",
|
||||
errXNeedsParamObjectType: "'$1' needs a parameter that has an object type",
|
||||
errTemplateInstantiationTooNested: "template/macro instantiation too nested",
|
||||
errInstantiationFrom: "instantiation from here",
|
||||
errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
|
||||
errCommandExpectsFilename: "command expects a filename argument",
|
||||
errXExpected: "\'$1\' expected",
|
||||
errInvalidSectionStart: "invalid section start",
|
||||
errGridTableNotImplemented: "grid table is not implemented",
|
||||
errGeneralParseError: "general parse error",
|
||||
errNewSectionExpected: "new section expected",
|
||||
errWhitespaceExpected: "whitespace expected, got \'$1\'",
|
||||
errXisNoValidIndexFile: "\'$1\' is no valid index file",
|
||||
errCannotRenderX: "cannot render reStructuredText element \'$1\'",
|
||||
errVarVarTypeNotAllowed: "type \'var var\' is not allowed",
|
||||
errIsExpectsTwoArguments: "\'is\' expects two arguments",
|
||||
errIsExpectsObjectTypes: "\'is\' expects object types",
|
||||
errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype",
|
||||
errTooManyIterations: "interpretation requires too many iterations",
|
||||
errCannotInterpretNodeX: "cannot interpret node kind \'$1\'",
|
||||
errFieldXNotFound: "field \'$1\' cannot be found",
|
||||
errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'",
|
||||
errAssertionFailed: "assertion failed",
|
||||
errCannotGenerateCodeForX: "cannot generate code for \'$1\'",
|
||||
errXRequiresOneArgument: "$1 requires one parameter",
|
||||
errUnhandledExceptionX: "unhandled exception: $1",
|
||||
errCyclicTree: "macro returned a cyclic abstract syntax tree",
|
||||
errXisNoMacroOrTemplate: "\'$1\' is no macro or template",
|
||||
errXhasSideEffects: "\'$1\' can have side effects",
|
||||
errIteratorExpected: "iterator within for loop context expected",
|
||||
errUser: "$1",
|
||||
warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]",
|
||||
warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]",
|
||||
warnXIsNeverRead: "\'$1\' is never read [XIsNeverRead]",
|
||||
warnXmightNotBeenInit: "\'$1\' might not have been initialized [XmightNotBeenInit]",
|
||||
warnCannotWriteMO2: "cannot write file \'$1\' [CannotWriteMO2]",
|
||||
warnCannotReadMO2: "cannot read file \'$1\' [CannotReadMO2]",
|
||||
warnDeprecated: "\'$1\' is deprecated [Deprecated]",
|
||||
warnSmallLshouldNotBeUsed: "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]",
|
||||
warnUnknownMagic: "unknown magic \'$1\' might crash the compiler [UnknownMagic]",
|
||||
warnRedefinitionOfLabel: "redefinition of label \'$1\' [RedefinitionOfLabel]",
|
||||
warnUnknownSubstitutionX: "unknown substitution \'$1\' [UnknownSubstitutionX]",
|
||||
warnLanguageXNotSupported: "language \'$1\' not supported [LanguageXNotSupported]",
|
||||
warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]",
|
||||
warnXisPassedToProcVar: "\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]",
|
||||
warnUser: "$1 [User]",
|
||||
hintSuccess: "operation successful [Success]",
|
||||
hintSuccessX: "operation successful ($1 lines compiled; $2 sec total) [SuccessX]",
|
||||
hintLineTooLong: "line too long [LineTooLong]",
|
||||
hintXDeclaredButNotUsed: "\'$1\' is declared but not used [XDeclaredButNotUsed]",
|
||||
hintConvToBaseNotNeeded: "conversion to base object is not needed [ConvToBaseNotNeeded]",
|
||||
hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]",
|
||||
hintExprAlwaysX: "expression evaluates always to \'$1\' [ExprAlwaysX]",
|
||||
hintQuitCalled: "quit() called [QuitCalled]",
|
||||
hintProcessing: "$1 [Processing]",
|
||||
hintCodeBegin: "generated code listing: [CodeBegin]",
|
||||
hintCodeEnd: "end of listing [CodeEnd]",
|
||||
hintConf: "used config file \'$1\' [Conf]",
|
||||
hintPath: "added path: '$1' [Path]",
|
||||
hintUser: "$1 [User]"]
|
||||
|
||||
const
|
||||
WarningsToStr*: array[0..14, string] = ["CannotOpenFile", "OctalEscape",
|
||||
@@ -353,7 +444,7 @@ proc checkpoint(info: TLineInfo, filename: string, line: int): bool =
|
||||
(ChangeFileExt(extractFilename(filenames[info.fileIndex]), "") ==
|
||||
filename)
|
||||
|
||||
var checkPoints: seq[TLineInfo] = @ []
|
||||
var checkPoints: seq[TLineInfo] = @[]
|
||||
|
||||
proc addCheckpoint(info: TLineInfo) =
|
||||
var length: int
|
||||
|
||||
@@ -141,7 +141,7 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode
|
||||
|
||||
proc parseEmit(p: var TParser, definition: PNode): PNode =
|
||||
getTok(p) # skip 'emit'
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
if p.tok.xkind != pxCurlyDirRi:
|
||||
case p.context
|
||||
of conExpr:
|
||||
@@ -159,7 +159,7 @@ proc parseEmit(p: var TParser, definition: PNode): PNode =
|
||||
eat(p, pxCurlyDirRi)
|
||||
|
||||
proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
getTok(p)
|
||||
if p.tok.ident.id == getIdent("discard").id:
|
||||
result = newNodeP(nkDiscardStmt, p)
|
||||
@@ -170,8 +170,8 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
|
||||
getTok(p)
|
||||
eat(p, pxCurlyDirRi)
|
||||
result = parseExpr(p)
|
||||
if result.kind == nkEmpty: InternalError("emptyNode modified")
|
||||
result.kind = nkCurly
|
||||
assert(sonsNotNil(result))
|
||||
elif p.tok.ident.id == getIdent("cast").id:
|
||||
getTok(p)
|
||||
eat(p, pxCurlyDirRi)
|
||||
@@ -181,7 +181,7 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
|
||||
addSon(result, a.sons[0])
|
||||
addSon(result, a.sons[1])
|
||||
else:
|
||||
parMessage(p, errInvalidDirectiveX, $(p.tok))
|
||||
parMessage(p, errInvalidDirectiveX, $p.tok)
|
||||
result = a
|
||||
elif p.tok.ident.id == getIdent("emit").id:
|
||||
result = parseEmit(p, definition)
|
||||
@@ -216,12 +216,12 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
|
||||
getTok(p)
|
||||
eat(p, pxCurlyDirRi)
|
||||
else:
|
||||
parMessage(p, errInvalidDirectiveX, $(p.tok))
|
||||
parMessage(p, errInvalidDirectiveX, $p.tok)
|
||||
while true:
|
||||
getTok(p)
|
||||
if (p.tok.xkind == pxCurlyDirRi) or (p.tok.xkind == pxEof): break
|
||||
if p.tok.xkind == pxCurlyDirRi or p.tok.xkind == pxEof: break
|
||||
eat(p, pxCurlyDirRi)
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
|
||||
proc getPrecedence(kind: TTokKind): int =
|
||||
case kind
|
||||
@@ -295,7 +295,7 @@ proc qualifiedIdent(p: var TParser): PNode =
|
||||
result = createIdentNodeP(p.tok.ident, p)
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, $p.tok)
|
||||
return nil
|
||||
return ast.emptyNode
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
if p.tok.xkind == pxDot:
|
||||
@@ -390,15 +390,15 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||
else:
|
||||
parMessage(p, errExprExpected, $(p.tok))
|
||||
getTok(p) # we must consume a token here to prevend endless loops!
|
||||
result = nil
|
||||
if result != nil: skipCom(p, result)
|
||||
result = ast.emptyNode
|
||||
if result.kind != nkEmpty: skipCom(p, result)
|
||||
|
||||
proc primary(p: var TParser): PNode =
|
||||
# prefix operator?
|
||||
if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or
|
||||
(p.tok.xkind == pxPlus):
|
||||
result = newNodeP(nkPrefix, p)
|
||||
var a = newIdentNodeP(getIdent($(p.tok)), p)
|
||||
var a = newIdentNodeP(getIdent($p.tok), p)
|
||||
addSon(result, a)
|
||||
getTok(p)
|
||||
skipCom(p, a)
|
||||
@@ -406,7 +406,7 @@ proc primary(p: var TParser): PNode =
|
||||
return
|
||||
elif p.tok.xkind == pxAt:
|
||||
result = newNodeP(nkAddr, p)
|
||||
var a = newIdentNodeP(getIdent($(p.tok)), p)
|
||||
var a = newIdentNodeP(getIdent($p.tok), p)
|
||||
getTok(p)
|
||||
if p.tok.xkind == pxBracketLe:
|
||||
result = newNodeP(nkPrefix, p)
|
||||
@@ -433,7 +433,7 @@ proc primary(p: var TParser): PNode =
|
||||
addSon(result, createIdentNodeP(p.tok.ident, p))
|
||||
getTok(p)
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, $(p.tok))
|
||||
parMessage(p, errIdentifierExpected, $p.tok)
|
||||
of pxHat:
|
||||
var a = result
|
||||
result = newNodeP(nkDerefExpr, p)
|
||||
@@ -490,7 +490,6 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
|
||||
|
||||
proc fixExpr(n: PNode): PNode =
|
||||
result = n
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkInfix:
|
||||
if n.sons[1].kind == nkBracket: n.sons[1].kind = nkCurly
|
||||
@@ -559,7 +558,7 @@ proc parseUsesStmt(p: var TParser): PNode =
|
||||
skipCom(p, a)
|
||||
else:
|
||||
break
|
||||
if sonsLen(result) == 0: result = nil
|
||||
if sonsLen(result) == 0: result = ast.emptyNode
|
||||
|
||||
proc parseIncludeDir(p: var TParser): PNode =
|
||||
result = newNodeP(nkIncludeStmt, p)
|
||||
@@ -568,7 +567,7 @@ proc parseIncludeDir(p: var TParser): PNode =
|
||||
while true:
|
||||
case p.tok.xkind
|
||||
of pxSymbol, pxDot, pxDotDot, pxSlash:
|
||||
filename = filename & $(p.tok)
|
||||
add(filename, $p.tok)
|
||||
getTok(p)
|
||||
of pxStrLit:
|
||||
filename = p.tok.literal
|
||||
@@ -577,10 +576,10 @@ proc parseIncludeDir(p: var TParser): PNode =
|
||||
of pxCurlyDirRi:
|
||||
break
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, $(p.tok))
|
||||
parMessage(p, errIdentifierExpected, $p.tok)
|
||||
break
|
||||
addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, "nim"), p))
|
||||
if filename == "config.inc": result = nil
|
||||
if filename == "config.inc": result = ast.emptyNode
|
||||
|
||||
proc definedExprAux(p: var TParser): PNode =
|
||||
result = newNodeP(nkCall, p)
|
||||
@@ -590,7 +589,6 @@ proc definedExprAux(p: var TParser): PNode =
|
||||
getTok(p)
|
||||
|
||||
proc isHandledDirective(p: TParser): bool =
|
||||
result = false
|
||||
if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}:
|
||||
case toLower(p.tok.ident.s)
|
||||
of "else", "endif": result = false
|
||||
@@ -657,7 +655,7 @@ proc parseIfDir(p: var TParser, endMarker: TTokKind): PNode =
|
||||
parseIfDirAux(p, result)
|
||||
|
||||
proc parseDirective(p: var TParser): PNode =
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return
|
||||
var endMarker = succ(p.tok.xkind)
|
||||
if p.tok.ident != nil:
|
||||
@@ -680,7 +678,7 @@ proc parseRaise(p: var TParser): PNode =
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
if p.tok.xkind != pxSemicolon: addSon(result, parseExpr(p))
|
||||
else: addSon(result, nil)
|
||||
else: addSon(result, ast.emptyNode)
|
||||
|
||||
proc parseIf(p: var TParser): PNode =
|
||||
result = newNodeP(nkIfStmt, p)
|
||||
@@ -721,14 +719,14 @@ proc parseRepeat(p: var TParser): PNode =
|
||||
skipCom(p, result)
|
||||
addSon(result, newIdentNodeP(getIdent("true"), p))
|
||||
var s = newNodeP(nkStmtList, p)
|
||||
while (p.tok.xkind != pxEof) and (p.tok.xkind != pxUntil):
|
||||
while p.tok.xkind != pxEof and p.tok.xkind != pxUntil:
|
||||
addSon(s, parseStmt(p))
|
||||
eat(p, pxUntil)
|
||||
var a = newNodeP(nkIfStmt, p)
|
||||
skipCom(p, a)
|
||||
var b = newNodeP(nkElifBranch, p)
|
||||
var c = newNodeP(nkBreakStmt, p)
|
||||
addSon(c, nil)
|
||||
addSon(c, ast.emptyNode)
|
||||
addSon(b, parseExpr(p))
|
||||
skipCom(p, a)
|
||||
addSon(b, c)
|
||||
@@ -809,7 +807,7 @@ proc parseFor(p: var TParser): PNode =
|
||||
getTok(p)
|
||||
eat(p, pxAsgn)
|
||||
var a = parseExpr(p)
|
||||
var b: PNode = nil
|
||||
var b = ast.emptyNode
|
||||
var c = newNodeP(nkCall, p)
|
||||
if p.tok.xkind == pxTo:
|
||||
addSon(c, newIdentNodeP(getIdent("countup"), p))
|
||||
@@ -829,9 +827,9 @@ proc parseFor(p: var TParser): PNode =
|
||||
addSon(result, parseStmt(p))
|
||||
|
||||
proc parseParam(p: var TParser): PNode =
|
||||
var a, v: PNode
|
||||
var a: PNode
|
||||
result = newNodeP(nkIdentDefs, p)
|
||||
v = nil
|
||||
var v = ast.emptyNode
|
||||
case p.tok.xkind
|
||||
of pxConst:
|
||||
getTok(p)
|
||||
@@ -848,7 +846,7 @@ proc parseParam(p: var TParser): PNode =
|
||||
of pxSymbol: a = createIdentNodeP(p.tok.ident, p)
|
||||
of pxColon, pxEof, pxParRi, pxEquals: break
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, $(p.tok))
|
||||
parMessage(p, errIdentifierExpected, $p.tok)
|
||||
return
|
||||
getTok(p) # skip identifier
|
||||
skipCom(p, a)
|
||||
@@ -859,24 +857,24 @@ proc parseParam(p: var TParser): PNode =
|
||||
if p.tok.xkind == pxColon:
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
if v != nil: addSon(v, parseTypeDesc(p))
|
||||
if v.kind != nkEmpty: addSon(v, parseTypeDesc(p))
|
||||
else: v = parseTypeDesc(p)
|
||||
addSon(result, v)
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
if p.tok.xkind != pxEquals:
|
||||
parMessage(p, errColonOrEqualsExpected, $(p.tok))
|
||||
parMessage(p, errColonOrEqualsExpected, $p.tok)
|
||||
if p.tok.xkind == pxEquals:
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
addSon(result, parseExpr(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
|
||||
proc parseParamList(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkFormalParams, p)
|
||||
addSon(result, nil) # return type
|
||||
addSon(result, ast.emptyNode) # return type
|
||||
if p.tok.xkind == pxParLe:
|
||||
p.inParamList = true
|
||||
getTok(p)
|
||||
@@ -903,7 +901,7 @@ proc parseParamList(p: var TParser): PNode =
|
||||
result.sons[0] = parseTypeDesc(p)
|
||||
|
||||
proc parseCallingConvention(p: var TParser): PNode =
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
if p.tok.xkind == pxSymbol:
|
||||
case toLower(p.tok.ident.s)
|
||||
of "stdcall", "cdecl", "safecall", "syscall", "inline", "fastcall":
|
||||
@@ -935,7 +933,7 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
|
||||
of "importc":
|
||||
# This is a fake for platform module. There is no ``importc``
|
||||
# directive in Pascal.
|
||||
if result == nil: result = newNodeP(nkPragma, p)
|
||||
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
|
||||
addSon(result, newIdentNodeP(getIdent("importc"), p))
|
||||
noBody = true
|
||||
getTok(p)
|
||||
@@ -943,7 +941,7 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
|
||||
of "noconv":
|
||||
# This is a fake for platform module. There is no ``noconv``
|
||||
# directive in Pascal.
|
||||
if result == nil: result = newNodeP(nkPragma, p)
|
||||
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
|
||||
addSon(result, newIdentNodeP(getIdent("noconv"), p))
|
||||
noBody = true
|
||||
getTok(p)
|
||||
@@ -951,17 +949,17 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
|
||||
of "procvar":
|
||||
# This is a fake for the Nimrod compiler. There is no ``procvar``
|
||||
# directive in Pascal.
|
||||
if result == nil: result = newNodeP(nkPragma, p)
|
||||
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
|
||||
addSon(result, newIdentNodeP(getIdent("procvar"), p))
|
||||
getTok(p)
|
||||
opt(p, pxSemicolon)
|
||||
of "varargs":
|
||||
if result == nil: result = newNodeP(nkPragma, p)
|
||||
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
|
||||
addSon(result, newIdentNodeP(getIdent("varargs"), p))
|
||||
getTok(p)
|
||||
opt(p, pxSemicolon)
|
||||
of "external":
|
||||
if result == nil: result = newNodeP(nkPragma, p)
|
||||
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
|
||||
getTok(p)
|
||||
noBody = true
|
||||
e = newNodeP(nkExprColonExpr, p)
|
||||
@@ -981,8 +979,8 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
|
||||
opt(p, pxSemicolon)
|
||||
else:
|
||||
e = parseCallingConvention(p)
|
||||
if e == nil: break
|
||||
if result == nil: result = newNodeP(nkPragma, p)
|
||||
if e.kind == nkEmpty: break
|
||||
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
|
||||
addSon(result, e.sons[0])
|
||||
|
||||
proc parseRoutineType(p: var TParser): PNode =
|
||||
@@ -999,7 +997,7 @@ proc parseEnum(p: var TParser): PNode =
|
||||
result = newNodeP(nkEnumTy, p)
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
addSon(result, nil) # it does not inherit from any enumeration
|
||||
addSon(result, ast.emptyNode) # it does not inherit from any enumeration
|
||||
while true:
|
||||
case p.tok.xkind
|
||||
of pxEof, pxParRi: break
|
||||
@@ -1061,7 +1059,7 @@ proc parseIdentColonEquals(p: var TParser,
|
||||
skipCom(p, result)
|
||||
addSon(result, parseTypeDesc(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
if p.tok.xkind != pxEquals:
|
||||
parMessage(p, errColonOrEqualsExpected, $(p.tok))
|
||||
if p.tok.xkind == pxEquals:
|
||||
@@ -1069,20 +1067,20 @@ proc parseIdentColonEquals(p: var TParser,
|
||||
skipCom(p, result)
|
||||
addSon(result, parseExpr(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
if p.tok.xkind == pxSemicolon:
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
|
||||
proc parseRecordCase(p: var TParser): PNode =
|
||||
var a, b, c: PNode
|
||||
var b, c: PNode
|
||||
result = newNodeP(nkRecCase, p)
|
||||
getTok(p)
|
||||
a = newNodeP(nkIdentDefs, p)
|
||||
var a = newNodeP(nkIdentDefs, p)
|
||||
addSon(a, rawIdent(p))
|
||||
eat(p, pxColon)
|
||||
addSon(a, parseTypeDesc(p))
|
||||
addSon(a, nil)
|
||||
addSon(a, ast.emptyNode)
|
||||
addSon(result, a)
|
||||
eat(p, pxOf)
|
||||
skipCom(p, result)
|
||||
@@ -1116,9 +1114,9 @@ proc parseRecordCase(p: var TParser): PNode =
|
||||
if b.kind == nkElse: break
|
||||
|
||||
proc parseRecordPart(p: var TParser): PNode =
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd):
|
||||
if result == nil: result = newNodeP(nkRecList, p)
|
||||
if result.kind == nkEmpty: result = newNodeP(nkRecList, p)
|
||||
case p.tok.xkind
|
||||
of pxSymbol:
|
||||
addSon(result, parseIdentColonEquals(p, rawIdent))
|
||||
@@ -1129,8 +1127,8 @@ proc parseRecordPart(p: var TParser): PNode =
|
||||
of pxComment:
|
||||
skipCom(p, lastSon(result))
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, $(p.tok))
|
||||
break
|
||||
parMessage(p, errIdentifierExpected, $p.tok)
|
||||
break
|
||||
|
||||
proc exSymbol(n: var PNode) =
|
||||
case n.kind
|
||||
@@ -1146,7 +1144,6 @@ proc exSymbol(n: var PNode) =
|
||||
else: internalError(n.info, "exSymbol(): " & $n.kind)
|
||||
|
||||
proc fixRecordDef(n: var PNode) =
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkRecCase:
|
||||
fixRecordDef(n.sons[0])
|
||||
@@ -1157,7 +1154,7 @@ proc fixRecordDef(n: var PNode) =
|
||||
for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i])
|
||||
of nkIdentDefs:
|
||||
for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i])
|
||||
of nkNilLit: nil
|
||||
of nkNilLit, nkEmpty: nil
|
||||
else: internalError(n.info, "fixRecordDef(): " & $n.kind)
|
||||
|
||||
proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
|
||||
@@ -1202,7 +1199,7 @@ proc parseRecordOrObject(p: var TParser, kind: TNodeKind,
|
||||
definition: PNode): PNode =
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
if p.tok.xkind == pxParLe:
|
||||
var a = newNodeP(nkOfInherit, p)
|
||||
getTok(p)
|
||||
@@ -1210,7 +1207,7 @@ proc parseRecordOrObject(p: var TParser, kind: TNodeKind,
|
||||
addSon(result, a)
|
||||
eat(p, pxParRi)
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
parseRecordBody(p, result, definition)
|
||||
|
||||
proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
|
||||
@@ -1234,8 +1231,8 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
|
||||
else: addSon(result, a.sons[i])
|
||||
else:
|
||||
result = newNodeP(nkObjectTy, p)
|
||||
addSon(result, nil)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
addSon(result, ast.emptyNode)
|
||||
parseRecordBody(p, result, definition)
|
||||
if definition != nil:
|
||||
addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p))
|
||||
@@ -1288,13 +1285,13 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
|
||||
proc parseTypeDef(p: var TParser): PNode =
|
||||
result = newNodeP(nkTypeDef, p)
|
||||
addSon(result, identVis(p))
|
||||
addSon(result, nil) # generic params
|
||||
addSon(result, ast.emptyNode) # generic params
|
||||
if p.tok.xkind == pxEquals:
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
addSon(result, parseTypeDesc(p, result))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
if p.tok.xkind == pxSemicolon:
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
@@ -1314,7 +1311,7 @@ proc parseConstant(p: var TParser): PNode =
|
||||
skipCom(p, result)
|
||||
addSon(result, parseTypeDesc(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
if p.tok.xkind != pxEquals:
|
||||
parMessage(p, errColonOrEqualsExpected, $(p.tok))
|
||||
if p.tok.xkind == pxEquals:
|
||||
@@ -1322,7 +1319,7 @@ proc parseConstant(p: var TParser): PNode =
|
||||
skipCom(p, result)
|
||||
addSon(result, parseExpr(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
if p.tok.xkind == pxSemicolon:
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
@@ -1349,12 +1346,12 @@ proc parseRoutine(p: var TParser): PNode =
|
||||
skipCom(p, result)
|
||||
expectIdent(p)
|
||||
addSon(result, identVis(p))
|
||||
addSon(result, nil) # generic parameters
|
||||
addSon(result, ast.emptyNode) # generic parameters
|
||||
addSon(result, parseParamList(p))
|
||||
opt(p, pxSemicolon)
|
||||
addSon(result, parseRoutineSpecifiers(p, noBody))
|
||||
if (p.section == seInterface) or noBody:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
else:
|
||||
var stmts = newNodeP(nkStmtList, p)
|
||||
while true:
|
||||
@@ -1408,8 +1405,7 @@ proc exSymbols(n: PNode) =
|
||||
of nkTypeSection:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
exSymbol(n.sons[i].sons[0])
|
||||
if (n.sons[i].sons[2] != nil) and
|
||||
(n.sons[i].sons[2].kind == nkObjectTy):
|
||||
if n.sons[i].sons[2].kind == nkObjectTy:
|
||||
fixRecordDef(n.sons[i].sons[2])
|
||||
else: nil
|
||||
|
||||
@@ -1425,13 +1421,15 @@ proc parseBegin(p: var TParser, result: PNode) =
|
||||
break
|
||||
of pxSemicolon: getTok(p)
|
||||
of pxEof: parMessage(p, errExprExpected)
|
||||
else: addSonIfNotNil(result, parseStmt(p))
|
||||
else:
|
||||
var a = parseStmt(p)
|
||||
if a.kind != nkEmpty: addSon(result, a)
|
||||
if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p))
|
||||
|
||||
proc parseStmt(p: var TParser): PNode =
|
||||
var oldcontext = p.context
|
||||
p.context = conStmt
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
case p.tok.xkind
|
||||
of pxBegin:
|
||||
result = newNodeP(nkStmtList, p)
|
||||
@@ -1475,23 +1473,23 @@ proc parseStmt(p: var TParser): PNode =
|
||||
result = newNodeP(nkBreakStmt, p)
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
elif p.tok.ident.id == getIdent("continue").id:
|
||||
result = newNodeP(nkContinueStmt, p)
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
elif p.tok.ident.id == getIdent("exit").id:
|
||||
result = newNodeP(nkReturnStmt, p)
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
else:
|
||||
result = parseExprStmt(p)
|
||||
of pxDot: getTok(p) # BUGFIX for ``end.`` in main program
|
||||
else: result = parseExprStmt(p)
|
||||
opt(p, pxSemicolon)
|
||||
if result != nil: skipCom(p, result)
|
||||
if result.kind != nkEmpty: skipCom(p, result)
|
||||
p.context = oldcontext
|
||||
|
||||
proc parseUnit(p: var TParser): PNode =
|
||||
|
||||
@@ -104,7 +104,7 @@ proc processTopLevelStmtCached(n: PNode, a: var TPassContextArray) =
|
||||
if not isNil(gPasses[i].openCached): m = gPasses[i].process(a[i], m)
|
||||
|
||||
proc closePassesCached(a: var TPassContextArray) =
|
||||
var m: PNode = nil
|
||||
var m = ast.emptyNode
|
||||
for i in countup(0, gPassesLen - 1):
|
||||
if not isNil(gPasses[i].openCached) and not isNil(gPasses[i].close):
|
||||
m = gPasses[i].close(a[i], m)
|
||||
@@ -114,7 +114,6 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
|
||||
rd: PRodReader) =
|
||||
var
|
||||
p: TParsers
|
||||
n: PNode
|
||||
a: TPassContextArray
|
||||
s: PLLStream
|
||||
if rd == nil:
|
||||
@@ -129,8 +128,8 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
|
||||
while true:
|
||||
openParsers(p, filename, s)
|
||||
while true:
|
||||
n = parseTopLevelStmt(p)
|
||||
if n == nil: break
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty: break
|
||||
processTopLevelStmt(n, a)
|
||||
closeParsers(p)
|
||||
if s.kind != llsStdIn: break
|
||||
@@ -139,7 +138,7 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
|
||||
IDsynchronizationPoint(1000)
|
||||
else:
|
||||
openPassesCached(a, module, filename, rd)
|
||||
n = loadInitSection(rd) #MessageOut('init section' + renderTree(n));
|
||||
var n = loadInitSection(rd) #MessageOut('init section' + renderTree(n));
|
||||
for i in countup(0, sonsLen(n) - 1): processTopLevelStmtCached(n.sons[i], a)
|
||||
closePassesCached(a)
|
||||
|
||||
|
||||
183
rod/pnimsyn.nim
183
rod/pnimsyn.nim
@@ -28,8 +28,8 @@ proc ParseAll*(p: var TParser): PNode
|
||||
proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
|
||||
proc closeParser*(p: var TParser)
|
||||
proc parseTopLevelStmt*(p: var TParser): PNode
|
||||
# implements an iterator. Returns the next top-level statement or nil if end
|
||||
# of stream.
|
||||
# implements an iterator. Returns the next top-level statement or
|
||||
# emtyNode if end of stream.
|
||||
|
||||
# helpers for the other parsers
|
||||
proc getPrecedence*(tok: PToken): int
|
||||
@@ -94,7 +94,7 @@ proc optInd(p: var TParser, n: PNode) =
|
||||
skipInd(p)
|
||||
|
||||
proc expectIdentOrKeyw(p: TParser) =
|
||||
if (p.tok.tokType != tkSymbol) and not isKeyword(p.tok.tokType):
|
||||
if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType):
|
||||
lexMessage(p.lex^, errIdentifierExpected, tokToStr(p.tok))
|
||||
|
||||
proc ExpectIdent(p: TParser) =
|
||||
@@ -217,18 +217,17 @@ proc parseSymbol(p: var TParser): PNode =
|
||||
addSon(result, newIdentNodeP(id, p))
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
eat(p, tkAccent)
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
|
||||
proc accExpr(p: var TParser): PNode =
|
||||
var x, y: PNode
|
||||
result = newNodeP(nkAccQuoted, p)
|
||||
getTok(p) # skip `
|
||||
x = nil
|
||||
y = nil
|
||||
var x = ast.emptyNode
|
||||
var y = ast.emptyNode
|
||||
case p.tok.tokType
|
||||
of tkSymbol, tkOpr, tokKeywordLow..tokKeywordHigh:
|
||||
x = newIdentNodeP(p.tok.ident, p)
|
||||
@@ -255,9 +254,9 @@ proc optExpr(p: var TParser): PNode =
|
||||
(p.tok.tokType != tkDotDot):
|
||||
result = parseExpr(p)
|
||||
else:
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
|
||||
proc dotdotExpr(p: var TParser, first: PNode = nil): PNode =
|
||||
proc dotdotExpr(p: var TParser, first: PNode): PNode =
|
||||
result = newNodeP(nkRange, p)
|
||||
addSon(result, first)
|
||||
getTok(p)
|
||||
@@ -266,20 +265,19 @@ proc dotdotExpr(p: var TParser, first: PNode = nil): PNode =
|
||||
|
||||
proc indexExpr(p: var TParser): PNode =
|
||||
# indexExpr ::= '..' [expr] | expr ['=' expr | '..' expr]
|
||||
var a, b: PNode
|
||||
if p.tok.tokType == tkDotDot:
|
||||
result = dotdotExpr(p)
|
||||
result = dotdotExpr(p, ast.emptyNode)
|
||||
else:
|
||||
a = parseExpr(p)
|
||||
var a = parseExpr(p)
|
||||
case p.tok.tokType
|
||||
of tkEquals:
|
||||
result = newNodeP(nkExprEqExpr, p)
|
||||
addSon(result, a)
|
||||
getTok(p)
|
||||
if p.tok.tokType == tkDotDot:
|
||||
addSon(result, dotdotExpr(p))
|
||||
addSon(result, dotdotExpr(p, ast.emptyNode))
|
||||
else:
|
||||
b = parseExpr(p)
|
||||
var b = parseExpr(p)
|
||||
if p.tok.tokType == tkDotDot: b = dotdotExpr(p, b)
|
||||
addSon(result, b)
|
||||
of tkDotDot:
|
||||
@@ -305,7 +303,8 @@ proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode =
|
||||
var a = parseExpr(p)
|
||||
if p.tok.tokType == tok:
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p) #optInd(p, result);
|
||||
getTok(p)
|
||||
#optInd(p, result)
|
||||
addSon(result, a)
|
||||
addSon(result, parseExpr(p))
|
||||
else:
|
||||
@@ -481,14 +480,13 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||
else:
|
||||
parMessage(p, errExprExpected, tokToStr(p.tok))
|
||||
getTok(p) # we must consume a token here to prevend endless loops!
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
|
||||
proc primary(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
# prefix operator?
|
||||
if (p.tok.tokType == tkNot) or (p.tok.tokType == tkOpr):
|
||||
result = newNodeP(nkPrefix, p)
|
||||
a = newIdentNodeP(p.tok.ident, p)
|
||||
var a = newIdentNodeP(p.tok.ident, p)
|
||||
addSon(result, a)
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
@@ -504,12 +502,12 @@ proc primary(p: var TParser): PNode =
|
||||
while true:
|
||||
case p.tok.tokType
|
||||
of tkParLe:
|
||||
a = result
|
||||
var a = result
|
||||
result = newNodeP(nkCall, p)
|
||||
addSon(result, a)
|
||||
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
|
||||
of tkDot:
|
||||
a = result
|
||||
var a = result
|
||||
result = newNodeP(nkDotExpr, p)
|
||||
addSon(result, a)
|
||||
getTok(p) # skip '.'
|
||||
@@ -517,7 +515,7 @@ proc primary(p: var TParser): PNode =
|
||||
addSon(result, parseSymbol(p))
|
||||
result = parseGStrLit(p, result)
|
||||
of tkHat:
|
||||
a = result
|
||||
var a = result
|
||||
result = newNodeP(nkDerefExpr, p)
|
||||
addSon(result, a)
|
||||
getTok(p)
|
||||
@@ -549,30 +547,28 @@ proc lowestExpr(p: var TParser): PNode =
|
||||
discard lowestExprAux(p, result, - 1)
|
||||
|
||||
proc parseIfExpr(p: var TParser): PNode =
|
||||
var branch: PNode
|
||||
result = newNodeP(nkIfExpr, p)
|
||||
while true:
|
||||
getTok(p) # skip `if`, `elif`
|
||||
branch = newNodeP(nkElifExpr, p)
|
||||
var branch = newNodeP(nkElifExpr, p)
|
||||
addSon(branch, parseExpr(p))
|
||||
eat(p, tkColon)
|
||||
addSon(branch, parseExpr(p))
|
||||
addSon(result, branch)
|
||||
if p.tok.tokType != tkElif: break
|
||||
branch = newNodeP(nkElseExpr, p)
|
||||
var branch = newNodeP(nkElseExpr, p)
|
||||
eat(p, tkElse)
|
||||
eat(p, tkColon)
|
||||
addSon(branch, parseExpr(p))
|
||||
addSon(result, branch)
|
||||
|
||||
proc parsePragma(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkPragma, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
|
||||
(p.tok.tokType != tkEof) and (p.tok.tokType != tkSad):
|
||||
a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
|
||||
var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
|
||||
addSon(result, a)
|
||||
if p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
@@ -583,8 +579,7 @@ proc parsePragma(p: var TParser): PNode =
|
||||
|
||||
proc identVis(p: var TParser): PNode =
|
||||
# identifier with visability
|
||||
var a: PNode
|
||||
a = parseSymbol(p)
|
||||
var a = parseSymbol(p)
|
||||
if p.tok.tokType == tkOpr:
|
||||
result = newNodeP(nkPostfix, p)
|
||||
addSon(result, newIdentNodeP(p.tok.ident, p))
|
||||
@@ -594,8 +589,7 @@ proc identVis(p: var TParser): PNode =
|
||||
result = a
|
||||
|
||||
proc identWithPragma(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
a = identVis(p)
|
||||
var a = identVis(p)
|
||||
if p.tok.tokType == tkCurlyDotLe:
|
||||
result = newNodeP(nkPragmaExpr, p)
|
||||
addSon(result, a)
|
||||
@@ -617,7 +611,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
|
||||
of tkSymbol, tkAccent:
|
||||
if withPragma in flags: a = identWithPragma(p)
|
||||
else: a = parseSymbol(p)
|
||||
if a == nil: return
|
||||
if a.kind == nkEmpty: return
|
||||
else: break
|
||||
addSon(result, a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
@@ -628,7 +622,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
|
||||
optInd(p, result)
|
||||
addSon(result, parseTypeDesc(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
if (p.tok.tokType != tkEquals) and not (withBothOptional in flags):
|
||||
parMessage(p, errColonOrEqualsExpected, tokToStr(p.tok))
|
||||
if p.tok.tokType == tkEquals:
|
||||
@@ -636,16 +630,15 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
|
||||
optInd(p, result)
|
||||
addSon(result, parseExpr(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
|
||||
proc parseTuple(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkTupleTy, p)
|
||||
getTok(p)
|
||||
eat(p, tkBracketLe)
|
||||
optInd(p, result)
|
||||
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
|
||||
a = parseIdentColonEquals(p, {})
|
||||
var a = parseIdentColonEquals(p, {})
|
||||
addSon(result, a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
@@ -656,7 +649,7 @@ proc parseTuple(p: var TParser): PNode =
|
||||
proc parseParamList(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkFormalParams, p)
|
||||
addSon(result, nil) # return type
|
||||
addSon(result, ast.emptyNode) # return type
|
||||
if p.tok.tokType == tkParLe:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
@@ -689,11 +682,11 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
|
||||
getTok(p)
|
||||
params = parseParamList(p)
|
||||
if p.tok.tokType == tkCurlyDotLe: pragmas = parsePragma(p)
|
||||
else: pragmas = nil
|
||||
else: pragmas = ast.emptyNode
|
||||
if (p.tok.tokType == tkEquals) and isExpr:
|
||||
result = newNodeI(nkLambda, info)
|
||||
addSon(result, nil) # no name part
|
||||
addSon(result, nil) # no generic parameters
|
||||
addSon(result, ast.emptyNode) # no name part
|
||||
addSon(result, ast.emptyNode) # no generic parameters
|
||||
addSon(result, params)
|
||||
addSon(result, pragmas)
|
||||
getTok(p)
|
||||
@@ -744,12 +737,11 @@ proc isExprStart(p: TParser): bool =
|
||||
else: result = false
|
||||
|
||||
proc parseExprStmt(p: var TParser): PNode =
|
||||
var a, b, e: PNode
|
||||
a = lowestExpr(p)
|
||||
var a = lowestExpr(p)
|
||||
if p.tok.tokType == tkEquals:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
b = parseExpr(p)
|
||||
var b = parseExpr(p)
|
||||
result = newNodeI(nkAsgn, a.info)
|
||||
addSon(result, a)
|
||||
addSon(result, b)
|
||||
@@ -759,7 +751,7 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||
addSon(result, a)
|
||||
while true:
|
||||
if not isExprStart(p): break
|
||||
e = parseExpr(p)
|
||||
var e = parseExpr(p)
|
||||
addSon(result, e)
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
@@ -778,6 +770,7 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||
addSon(result, parseStmt(p))
|
||||
while true:
|
||||
if p.tok.tokType == tkSad: getTok(p)
|
||||
var b: PNode
|
||||
case p.tok.tokType
|
||||
of tkOf:
|
||||
b = newNodeP(nkOfBranch, p)
|
||||
@@ -871,7 +864,7 @@ proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
case p.tok.tokType
|
||||
of tkEof, tkSad, tkDed: addSon(result, nil)
|
||||
of tkEof, tkSad, tkDed: addSon(result, ast.emptyNode)
|
||||
else: addSon(result, parseExpr(p))
|
||||
|
||||
proc parseYieldOrDiscard(p: var TParser, kind: TNodeKind): PNode =
|
||||
@@ -885,15 +878,14 @@ proc parseBreakOrContinue(p: var TParser, kind: TNodeKind): PNode =
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
case p.tok.tokType
|
||||
of tkEof, tkSad, tkDed: addSon(result, nil)
|
||||
of tkEof, tkSad, tkDed: addSon(result, ast.emptyNode)
|
||||
else: addSon(result, parseSymbol(p))
|
||||
|
||||
proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
|
||||
var branch: PNode
|
||||
result = newNodeP(kind, p)
|
||||
while true:
|
||||
getTok(p) # skip `if`, `when`, `elif`
|
||||
branch = newNodeP(nkElifBranch, p)
|
||||
var branch = newNodeP(nkElifBranch, p)
|
||||
optInd(p, branch)
|
||||
addSon(branch, parseExpr(p))
|
||||
eat(p, tkColon)
|
||||
@@ -903,7 +895,7 @@ proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
|
||||
addSon(result, branch)
|
||||
if p.tok.tokType != tkElif: break
|
||||
if p.tok.tokType == tkElse:
|
||||
branch = newNodeP(nkElse, p)
|
||||
var branch = newNodeP(nkElse, p)
|
||||
eat(p, tkElse)
|
||||
eat(p, tkColon)
|
||||
skipComment(p, branch)
|
||||
@@ -954,13 +946,12 @@ proc parseCase(p: var TParser): PNode =
|
||||
if b.kind == nkElse: break
|
||||
|
||||
proc parseTry(p: var TParser): PNode =
|
||||
var b: PNode
|
||||
result = newNodeP(nkTryStmt, p)
|
||||
getTok(p)
|
||||
eat(p, tkColon)
|
||||
skipComment(p, result)
|
||||
addSon(result, parseStmt(p))
|
||||
b = nil
|
||||
var b: PNode = nil
|
||||
while true:
|
||||
if p.tok.tokType == tkSad: getTok(p)
|
||||
case p.tok.tokType
|
||||
@@ -979,11 +970,10 @@ proc parseTry(p: var TParser): PNode =
|
||||
if b == nil: parMessage(p, errTokenExpected, "except")
|
||||
|
||||
proc parseFor(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkForStmt, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
a = parseSymbol(p)
|
||||
var a = parseSymbol(p)
|
||||
addSon(result, a)
|
||||
while p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
@@ -1001,7 +991,7 @@ proc parseBlock(p: var TParser): PNode =
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
case p.tok.tokType
|
||||
of tkEof, tkSad, tkDed, tkColon: addSon(result, nil)
|
||||
of tkEof, tkSad, tkDed, tkColon: addSon(result, ast.emptyNode)
|
||||
else: addSon(result, parseSymbol(p))
|
||||
eat(p, tkColon)
|
||||
skipComment(p, result)
|
||||
@@ -1012,7 +1002,7 @@ proc parseAsm(p: var TParser): PNode =
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
||||
else: addSon(result, nil)
|
||||
else: addSon(result, ast.emptyNode)
|
||||
case p.tok.tokType
|
||||
of tkStrLit: addSon(result, newStrNodeP(nkStrLit, p.tok.literal, p))
|
||||
of tkRStrLit: addSon(result, newStrNodeP(nkRStrLit, p.tok.literal, p))
|
||||
@@ -1020,17 +1010,16 @@ proc parseAsm(p: var TParser): PNode =
|
||||
newStrNodeP(nkTripleStrLit, p.tok.literal, p))
|
||||
else:
|
||||
parMessage(p, errStringLiteralExpected)
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
return
|
||||
getTok(p)
|
||||
|
||||
proc parseGenericParamList(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkGenericParams, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
|
||||
a = parseIdentColonEquals(p, {withBothOptional})
|
||||
var a = parseIdentColonEquals(p, {withBothOptional})
|
||||
addSon(result, a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
@@ -1044,16 +1033,16 @@ proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
|
||||
optInd(p, result)
|
||||
addSon(result, identVis(p))
|
||||
if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
|
||||
else: addSon(result, nil)
|
||||
else: addSon(result, ast.emptyNode)
|
||||
addSon(result, parseParamList(p))
|
||||
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
||||
else: addSon(result, nil)
|
||||
else: addSon(result, ast.emptyNode)
|
||||
if p.tok.tokType == tkEquals:
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
addSon(result, parseStmt(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
indAndComment(p, result) # XXX: document this in the grammar!
|
||||
|
||||
proc newCommentStmt(p: var TParser): PNode =
|
||||
@@ -1065,13 +1054,12 @@ type
|
||||
|
||||
proc parseSection(p: var TParser, kind: TNodeKind,
|
||||
defparser: TDefParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
case p.tok.tokType
|
||||
of tkInd:
|
||||
pushInd(p.lex^ , p.tok.indent)
|
||||
pushInd(p.lex^, p.tok.indent)
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
while true:
|
||||
@@ -1079,7 +1067,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||
of tkSad:
|
||||
getTok(p)
|
||||
of tkSymbol, tkAccent:
|
||||
a = defparser(p)
|
||||
var a = defparser(p)
|
||||
skipComment(p, a)
|
||||
addSon(result, a)
|
||||
of tkDed:
|
||||
@@ -1088,13 +1076,13 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||
of tkEof:
|
||||
break # BUGFIX
|
||||
of tkComment:
|
||||
a = newCommentStmt(p)
|
||||
var a = newCommentStmt(p)
|
||||
skipComment(p, a)
|
||||
addSon(result, a)
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
||||
break
|
||||
popInd(p.lex^ )
|
||||
popInd(p.lex^)
|
||||
of tkSymbol, tkAccent, tkParLe:
|
||||
# tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
|
||||
addSon(result, defparser(p))
|
||||
@@ -1108,7 +1096,7 @@ proc parseConstant(p: var TParser): PNode =
|
||||
optInd(p, result)
|
||||
addSon(result, parseTypeDesc(p))
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
eat(p, tkEquals)
|
||||
optInd(p, result)
|
||||
addSon(result, parseExpr(p))
|
||||
@@ -1126,7 +1114,7 @@ proc parseEnum(p: var TParser): PNode =
|
||||
addSon(a, parseTypeDesc(p))
|
||||
addSon(result, a)
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
optInd(p, result)
|
||||
while true:
|
||||
case p.tok.tokType
|
||||
@@ -1148,11 +1136,10 @@ proc parseEnum(p: var TParser): PNode =
|
||||
|
||||
proc parseObjectPart(p: var TParser): PNode
|
||||
proc parseObjectWhen(p: var TParser): PNode =
|
||||
var branch: PNode
|
||||
result = newNodeP(nkRecWhen, p)
|
||||
while true:
|
||||
getTok(p) # skip `when`, `elif`
|
||||
branch = newNodeP(nkElifBranch, p)
|
||||
var branch = newNodeP(nkElifBranch, p)
|
||||
optInd(p, branch)
|
||||
addSon(branch, parseExpr(p))
|
||||
eat(p, tkColon)
|
||||
@@ -1162,7 +1149,7 @@ proc parseObjectWhen(p: var TParser): PNode =
|
||||
addSon(result, branch)
|
||||
if p.tok.tokType != tkElif: break
|
||||
if p.tok.tokType == tkElse:
|
||||
branch = newNodeP(nkElse, p)
|
||||
var branch = newNodeP(nkElse, p)
|
||||
eat(p, tkElse)
|
||||
eat(p, tkColon)
|
||||
skipComment(p, branch)
|
||||
@@ -1170,18 +1157,18 @@ proc parseObjectWhen(p: var TParser): PNode =
|
||||
addSon(result, branch)
|
||||
|
||||
proc parseObjectCase(p: var TParser): PNode =
|
||||
var a, b: PNode
|
||||
result = newNodeP(nkRecCase, p)
|
||||
getTok(p)
|
||||
a = newNodeP(nkIdentDefs, p)
|
||||
var a = newNodeP(nkIdentDefs, p)
|
||||
addSon(a, identWithPragma(p))
|
||||
eat(p, tkColon)
|
||||
addSon(a, parseTypeDesc(p))
|
||||
addSon(a, nil)
|
||||
addSon(a, ast.emptyNode)
|
||||
addSon(result, a)
|
||||
skipComment(p, result)
|
||||
while true:
|
||||
if p.tok.tokType == tkSad: getTok(p)
|
||||
var b: PNode
|
||||
case p.tok.tokType
|
||||
of tkOf:
|
||||
b = newNodeP(nkOfBranch, p)
|
||||
@@ -1200,7 +1187,7 @@ proc parseObjectPart(p: var TParser): PNode =
|
||||
case p.tok.tokType
|
||||
of tkInd:
|
||||
result = newNodeP(nkRecList, p)
|
||||
pushInd(p.lex^ , p.tok.indent)
|
||||
pushInd(p.lex^, p.tok.indent)
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
while true:
|
||||
@@ -1228,21 +1215,20 @@ proc parseObjectPart(p: var TParser): PNode =
|
||||
of tkNil:
|
||||
result = newNodeP(nkNilLit, p)
|
||||
getTok(p)
|
||||
else: result = nil
|
||||
else: result = ast.emptyNode
|
||||
|
||||
proc parseObject(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkObjectTy, p)
|
||||
getTok(p)
|
||||
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
||||
else: addSon(result, nil)
|
||||
else: addSon(result, ast.emptyNode)
|
||||
if p.tok.tokType == tkOf:
|
||||
a = newNodeP(nkOfInherit, p)
|
||||
var a = newNodeP(nkOfInherit, p)
|
||||
getTok(p)
|
||||
addSon(a, parseTypeDesc(p))
|
||||
addSon(result, a)
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
skipComment(p, result)
|
||||
addSon(result, parseObjectPart(p))
|
||||
|
||||
@@ -1253,14 +1239,14 @@ proc parseDistinct(p: var TParser): PNode =
|
||||
addSon(result, parseTypeDesc(p))
|
||||
|
||||
proc parseTypeDef(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkTypeDef, p)
|
||||
addSon(result, identWithPragma(p))
|
||||
if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
|
||||
else: addSon(result, nil)
|
||||
else: addSon(result, ast.emptyNode)
|
||||
if p.tok.tokType == tkEquals:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
var a: PNode
|
||||
case p.tok.tokType
|
||||
of tkObject: a = parseObject(p)
|
||||
of tkEnum: a = parseEnum(p)
|
||||
@@ -1268,21 +1254,20 @@ proc parseTypeDef(p: var TParser): PNode =
|
||||
else: a = parseTypeDesc(p)
|
||||
addSon(result, a)
|
||||
else:
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
indAndComment(p, result) # special extension!
|
||||
|
||||
proc parseVarTuple(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkVarTuple, p)
|
||||
getTok(p) # skip '('
|
||||
optInd(p, result)
|
||||
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
|
||||
a = identWithPragma(p)
|
||||
var a = identWithPragma(p)
|
||||
addSon(result, a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
addSon(result, nil) # no type desc
|
||||
addSon(result, ast.emptyNode) # no type desc
|
||||
optPar(p)
|
||||
eat(p, tkParRi)
|
||||
eat(p, tkEquals)
|
||||
@@ -1309,8 +1294,8 @@ proc simpleStmt(p: var TParser): PNode =
|
||||
of tkComment: result = newCommentStmt(p)
|
||||
else:
|
||||
if isExprStart(p): result = parseExprStmt(p)
|
||||
else: result = nil
|
||||
if result != nil: skipComment(p, result)
|
||||
else: result = ast.emptyNode
|
||||
if result.kind != nkEmpty: skipComment(p, result)
|
||||
|
||||
proc complexOrSimpleStmt(p: var TParser): PNode =
|
||||
case p.tok.tokType
|
||||
@@ -1334,10 +1319,9 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
|
||||
else: result = simpleStmt(p)
|
||||
|
||||
proc parseStmt(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
if p.tok.tokType == tkInd:
|
||||
result = newNodeP(nkStmtList, p)
|
||||
pushInd(p.lex^ , p.tok.indent)
|
||||
pushInd(p.lex^, p.tok.indent)
|
||||
getTok(p)
|
||||
while true:
|
||||
case p.tok.tokType
|
||||
@@ -1347,8 +1331,8 @@ proc parseStmt(p: var TParser): PNode =
|
||||
getTok(p)
|
||||
break
|
||||
else:
|
||||
a = complexOrSimpleStmt(p)
|
||||
if a == nil: break
|
||||
var a = complexOrSimpleStmt(p)
|
||||
if a.kind == nkEmpty: break
|
||||
addSon(result, a)
|
||||
popInd(p.lex^ )
|
||||
else:
|
||||
@@ -1357,14 +1341,13 @@ proc parseStmt(p: var TParser): PNode =
|
||||
of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkIterator,
|
||||
tkMacro, tkType, tkConst, tkWhen, tkVar:
|
||||
parMessage(p, errComplexStmtRequiresInd)
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
else:
|
||||
result = simpleStmt(p)
|
||||
if result == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
|
||||
if result.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
|
||||
if p.tok.tokType == tkSad: getTok(p)
|
||||
|
||||
proc parseAll(p: var TParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkStmtList, p)
|
||||
while true:
|
||||
case p.tok.tokType
|
||||
@@ -1372,20 +1355,20 @@ proc parseAll(p: var TParser): PNode =
|
||||
of tkDed, tkInd: parMessage(p, errInvalidIndentation)
|
||||
of tkEof: break
|
||||
else:
|
||||
a = complexOrSimpleStmt(p)
|
||||
if a == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
|
||||
var a = complexOrSimpleStmt(p)
|
||||
if a.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
|
||||
addSon(result, a)
|
||||
|
||||
proc parseTopLevelStmt(p: var TParser): PNode =
|
||||
result = nil
|
||||
result = ast.emptyNode
|
||||
while true:
|
||||
case p.tok.tokType
|
||||
of tkSad: getTok(p)
|
||||
of tkDed, tkInd:
|
||||
parMessage(p, errInvalidIndentation)
|
||||
break
|
||||
getTok(p)
|
||||
of tkEof: break
|
||||
else:
|
||||
result = complexOrSimpleStmt(p)
|
||||
if result == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
|
||||
if result.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
|
||||
break
|
||||
|
||||
@@ -323,13 +323,13 @@ proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int =
|
||||
|
||||
proc lsub(n: PNode): int =
|
||||
# computes the length of a tree
|
||||
if n == nil: return 0
|
||||
if n.comment != nil: return maxLineLen + 1
|
||||
case n.kind
|
||||
of nkEmpty: result = 0
|
||||
of nkTripleStrLit:
|
||||
if containsNL(n.strVal): result = maxLineLen + 1
|
||||
else: result = len(atom(n))
|
||||
of nkEmpty..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
||||
of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
||||
result = len(atom(n))
|
||||
of nkCall, nkBracketExpr, nkConv: result = lsub(n.sons[0]) + lcomma(n, 1) + 2
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
|
||||
@@ -348,8 +348,8 @@ proc lsub(n: PNode): int =
|
||||
of nkConstDef, nkIdentDefs:
|
||||
result = lcomma(n, 0, - 3)
|
||||
var L = sonsLen(n)
|
||||
if n.sons[L - 2] != nil: result = result + lsub(n.sons[L - 2]) + 2
|
||||
if n.sons[L - 1] != nil: result = result + lsub(n.sons[L - 1]) + 3
|
||||
if n.sons[L - 2].kind != nkEmpty: result = result + lsub(n.sons[L - 2]) + 2
|
||||
if n.sons[L - 1].kind != nkEmpty: result = result + lsub(n.sons[L - 1]) + 3
|
||||
of nkVarTuple: result = lcomma(n, 0, - 3) + len("() = ") + lsub(lastSon(n))
|
||||
of nkChckRangeF: result = len("chckRangeF") + 2 + lcomma(n)
|
||||
of nkChckRange64: result = len("chckRange64") + 2 + lcomma(n)
|
||||
@@ -401,7 +401,7 @@ proc lsub(n: PNode): int =
|
||||
of nkGenericParams: result = lcomma(n) + 2
|
||||
of nkFormalParams:
|
||||
result = lcomma(n, 1) + 2
|
||||
if n.sons[0] != nil: result = result + lsub(n.sons[0]) + 2
|
||||
if n.sons[0].kind != nkEmpty: result = result + lsub(n.sons[0]) + 2
|
||||
of nkExceptBranch:
|
||||
result = lcomma(n, 0, -2) + lsub(lastSon(n)) + len("except_:_")
|
||||
else: result = maxLineLen + 1
|
||||
@@ -430,7 +430,6 @@ proc gsub(g: var TSrcGen, n: PNode) =
|
||||
|
||||
proc hasCom(n: PNode): bool =
|
||||
result = false
|
||||
if n == nil: return
|
||||
if n.comment != nil: return true
|
||||
case n.kind
|
||||
of nkEmpty..nkNilLit: nil
|
||||
@@ -496,7 +495,7 @@ proc longMode(n: PNode, start: int = 0, theEnd: int = - 1): bool =
|
||||
break
|
||||
|
||||
proc gstmts(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
if n == nil: return
|
||||
if n.kind == nkEmpty: return
|
||||
if (n.kind == nkStmtList) or (n.kind == nkStmtListExpr):
|
||||
indentNL(g)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
@@ -598,7 +597,7 @@ proc gproc(g: var TSrcGen, n: PNode) =
|
||||
gsub(g, n.sons[2])
|
||||
gsub(g, n.sons[3])
|
||||
if not (renderNoBody in g.flags):
|
||||
if n.sons[4] != nil:
|
||||
if n.sons[4].kind != nkEmpty:
|
||||
put(g, tkSpaces, Space)
|
||||
putWithSpace(g, tkEquals, "=")
|
||||
indentNL(g)
|
||||
@@ -615,7 +614,7 @@ proc gproc(g: var TSrcGen, n: PNode) =
|
||||
proc gblock(g: var TSrcGen, n: PNode) =
|
||||
var c: TContext
|
||||
initContext(c)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
putWithSpace(g, tkBlock, "block")
|
||||
gsub(g, n.sons[0])
|
||||
else:
|
||||
@@ -656,11 +655,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
var
|
||||
L: int
|
||||
a: TContext
|
||||
if n == nil: return
|
||||
if n.comment != nil: pushCom(g, n)
|
||||
case n.kind # atoms:
|
||||
of nkTripleStrLit: putRawStr(g, tkTripleStrLit, n.strVal)
|
||||
of nkEmpty, nkType: put(g, tkInvalid, atom(n))
|
||||
of nkEmpty: nil
|
||||
of nkType: put(g, tkInvalid, atom(n))
|
||||
of nkSym, nkIdent: gident(g, n)
|
||||
of nkIntLit: put(g, tkIntLit, atom(n))
|
||||
of nkInt8Lit: put(g, tkInt8Lit, atom(n))
|
||||
@@ -765,7 +764,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref:
|
||||
gsub(g, n.sons[0])
|
||||
of nkLambda:
|
||||
assert(n.sons[genericParamsPos] == nil)
|
||||
assert(n.sons[genericParamsPos].kind == nkEmpty)
|
||||
putWithSpace(g, tkLambda, "lambda")
|
||||
gsub(g, n.sons[paramsPos])
|
||||
gsub(g, n.sons[pragmasPos])
|
||||
@@ -775,10 +774,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
of nkConstDef, nkIdentDefs:
|
||||
gcomma(g, n, 0, - 3)
|
||||
var L = sonsLen(n)
|
||||
if n.sons[L - 2] != nil:
|
||||
if n.sons[L - 2].kind != nkEmpty:
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n.sons[L - 2])
|
||||
if n.sons[L - 1] != nil:
|
||||
if n.sons[L - 1].kind != nkEmpty:
|
||||
put(g, tkSpaces, Space)
|
||||
putWithSpace(g, tkEquals, "=")
|
||||
gsub(g, n.sons[L - 1], c)
|
||||
@@ -855,7 +854,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
gsub(g, n.sons[0])
|
||||
gsub(g, n.sons[1])
|
||||
put(g, tkSpaces, Space)
|
||||
if n.sons[2] != nil:
|
||||
if n.sons[2].kind != nkEmpty:
|
||||
putWithSpace(g, tkEquals, "=")
|
||||
gsub(g, n.sons[2])
|
||||
of nkObjectTy:
|
||||
@@ -1029,7 +1028,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
put(g, tkParLe, "(")
|
||||
gcomma(g, n, 1)
|
||||
put(g, tkParRi, ")")
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n.sons[0])
|
||||
of nkTupleTy:
|
||||
@@ -1055,10 +1054,9 @@ proc renderModule(n: PNode, filename: string, renderFlags: TRenderFlags = {}) =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
gsub(g, n.sons[i])
|
||||
optNL(g)
|
||||
if n.sons[i] != nil:
|
||||
case n.sons[i].kind
|
||||
of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
|
||||
else: nil
|
||||
case n.sons[i].kind
|
||||
of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
|
||||
else: nil
|
||||
gcoms(g)
|
||||
if open(f, filename, fmWrite):
|
||||
write(f, g.buf)
|
||||
|
||||
@@ -175,7 +175,6 @@ proc findIdent(L: TLexer, indent: int): bool =
|
||||
for i in countdown(len(L.indentStack) - 1, 0):
|
||||
if L.indentStack[i] == indent:
|
||||
return true
|
||||
result = false
|
||||
|
||||
proc tokToStr(tok: PToken): string =
|
||||
case tok.tokType
|
||||
@@ -574,7 +573,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
|
||||
of '_':
|
||||
if buf[pos+1] notin SymChars:
|
||||
lexMessage(L, errInvalidToken, "_")
|
||||
return
|
||||
break
|
||||
else: break
|
||||
Inc(pos)
|
||||
h = h +% h shl 3
|
||||
@@ -587,11 +586,6 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
|
||||
tok.tokType = tkSymbol
|
||||
else:
|
||||
tok.tokType = TTokType(tok.ident.id + ord(tkSymbol))
|
||||
when false:
|
||||
if buf[pos] == '\"':
|
||||
getString(L, tok, true)
|
||||
if tok.tokType == tkRStrLit: tok.tokType = tkCallRStrLit
|
||||
else: tok.tokType = tkCallTripleStrLit
|
||||
|
||||
proc getOperator(L: var TLexer, tok: var TToken) =
|
||||
var pos = L.bufpos
|
||||
|
||||
@@ -133,7 +133,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
|
||||
liMessage(n.info, errOrdinalTypeExpected)
|
||||
if enumHasWholes(a.typ):
|
||||
liMessage(n.info, errEnumXHasWholes, a.typ.sym.name.s)
|
||||
liMessage(n.info, errEnumXHasHoles, a.typ.sym.name.s)
|
||||
if not leValue(a, b): liMessage(n.Info, errRangeIsEmpty)
|
||||
addSon(result.n, a)
|
||||
addSon(result.n, b)
|
||||
@@ -160,7 +160,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
if not isOrdinalType(indx):
|
||||
liMessage(n.sons[1].info, errOrdinalTypeExpected)
|
||||
if enumHasWholes(indx):
|
||||
liMessage(n.sons[1].info, errEnumXHasWholes, indx.sym.name.s)
|
||||
liMessage(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
|
||||
base = semTypeNode(c, n.sons[2], nil)
|
||||
addSon(result, base)
|
||||
else:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -59,6 +59,7 @@ proc parseAll(p: var TParsers): PNode =
|
||||
result = pbraces.parseAll(p.parser)
|
||||
of skinEndX:
|
||||
InternalError("parser to implement")
|
||||
result = ast.emptyNode
|
||||
# skinEndX: result := pendx.parseAll(p.parser);
|
||||
|
||||
proc parseTopLevelStmt(p: var TParsers): PNode =
|
||||
@@ -69,6 +70,7 @@ proc parseTopLevelStmt(p: var TParsers): PNode =
|
||||
result = pbraces.parseTopLevelStmt(p.parser)
|
||||
of skinEndX:
|
||||
InternalError("parser to implement")
|
||||
result = ast.emptyNode
|
||||
#skinEndX: result := pendx.parseTopLevelStmt(p.parser);
|
||||
|
||||
proc UTF8_BOM(s: string): int =
|
||||
@@ -84,6 +86,7 @@ proc containsShebang(s: string, i: int): bool =
|
||||
result = s[j] == '/'
|
||||
|
||||
proc parsePipe(filename: string, inputStream: PLLStream): PNode =
|
||||
result = ast.emptyNode
|
||||
var s = LLStreamOpen(filename, fmRead)
|
||||
if s != nil:
|
||||
var line = LLStreamReadLine(s)
|
||||
@@ -143,7 +146,7 @@ proc applyFilter(p: var TParsers, n: PNode, filename: string,
|
||||
proc evalPipe(p: var TParsers, n: PNode, filename: string,
|
||||
start: PLLStream): PLLStream =
|
||||
result = start
|
||||
if n == nil: return
|
||||
if n.kind == nkEmpty: return
|
||||
if (n.kind == nkInfix) and (n.sons[0].kind == nkIdent) and
|
||||
IdentEq(n.sons[0].ident, "|"):
|
||||
for i in countup(1, 2):
|
||||
|
||||
6
todo.txt
6
todo.txt
@@ -1,3 +1,8 @@
|
||||
- ban ``nil`` from the AST. This might also fix bugs concerning macros.
|
||||
TODO:
|
||||
* semantic checking (keep in mind incremental parsing!)
|
||||
* code generators
|
||||
|
||||
- thread support: threadvar on Windows seems broken;
|
||||
add --deadlock_prevention:on|off switch
|
||||
- built-in serialization
|
||||
@@ -68,7 +73,6 @@ Low priority
|
||||
- fast assignment optimization for TPeg
|
||||
- better error messages for used keywords as identifiers
|
||||
- case statement branches should support constant sets
|
||||
- ban ``nil`` from the AST. This might also fix bugs concerning macros.
|
||||
|
||||
|
||||
Library
|
||||
|
||||
Reference in New Issue
Block a user