next steps for the new parser/grammar
This commit is contained in:
parent
04216fc750
commit
2796121dd7
6 changed files with 286 additions and 266 deletions
|
|
@ -237,7 +237,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
||||||
of tkSymbol:
|
of tkSymbol:
|
||||||
dispA(result, "<span class=\"Identifier\">$1</span>",
|
dispA(result, "<span class=\"Identifier\">$1</span>",
|
||||||
"\\spanIdentifier{$1}", [toRope(esc(d.target, literal))])
|
"\\spanIdentifier{$1}", [toRope(esc(d.target, literal))])
|
||||||
of tkInd, tkSpaces, tkInvalid:
|
of tkSpaces, tkInvalid:
|
||||||
app(result, literal)
|
app(result, literal)
|
||||||
of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi,
|
of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi,
|
||||||
tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi, tkParDotLe,
|
tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi, tkParDotLe,
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ type
|
||||||
tkParDotLe, tkParDotRi, # (. and .)
|
tkParDotLe, tkParDotRi, # (. and .)
|
||||||
tkComma, tkSemiColon,
|
tkComma, tkSemiColon,
|
||||||
tkColon, tkColonColon, tkEquals, tkDot, tkDotDot,
|
tkColon, tkColonColon, tkEquals, tkDot, tkDotDot,
|
||||||
tkOpr, tkComment, tkAccent, tkInd,
|
tkOpr, tkComment, tkAccent,
|
||||||
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr,
|
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr,
|
||||||
|
|
||||||
TTokTypes* = set[TTokType]
|
TTokTypes* = set[TTokType]
|
||||||
|
|
@ -90,7 +90,7 @@ const
|
||||||
")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)",
|
")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)",
|
||||||
",", ";",
|
",", ";",
|
||||||
":", "::", "=", ".", "..",
|
":", "::", "=", ".", "..",
|
||||||
"tkOpr", "tkComment", "`", "[new indentation]",
|
"tkOpr", "tkComment", "`",
|
||||||
"tkSpaces", "tkInfixOpr",
|
"tkSpaces", "tkInfixOpr",
|
||||||
"tkPrefixOpr", "tkPostfixOpr"]
|
"tkPrefixOpr", "tkPostfixOpr"]
|
||||||
|
|
||||||
|
|
@ -154,7 +154,7 @@ proc tokToStr*(tok: TToken): string =
|
||||||
of tkIntLit..tkInt64Lit: result = $tok.iNumber
|
of tkIntLit..tkInt64Lit: result = $tok.iNumber
|
||||||
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
|
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
|
||||||
of tkInvalid, tkStrLit..tkCharLit, tkComment: result = tok.literal
|
of tkInvalid, tkStrLit..tkCharLit, tkComment: result = tok.literal
|
||||||
of tkParLe..tkColon, tkEof, tkInd, tkAccent:
|
of tkParLe..tkColon, tkEof, tkAccent:
|
||||||
result = tokTypeToStr[tok.tokType]
|
result = tokTypeToStr[tok.tokType]
|
||||||
else:
|
else:
|
||||||
if tok.ident != nil:
|
if tok.ident != nil:
|
||||||
|
|
@ -411,9 +411,10 @@ proc GetNumber(L: var TLexer): TToken =
|
||||||
result.tokType = tkInt64Lit
|
result.tokType = tkInt64Lit
|
||||||
elif result.tokType != tkInt64Lit:
|
elif result.tokType != tkInt64Lit:
|
||||||
lexMessage(L, errInvalidNumber, result.literal)
|
lexMessage(L, errInvalidNumber, result.literal)
|
||||||
except EInvalidValue: lexMessage(L, errInvalidNumber, result.literal)
|
except EInvalidValue:
|
||||||
except EOverflow: lexMessage(L, errNumberOutOfRange, result.literal)
|
lexMessage(L, errInvalidNumber, result.literal)
|
||||||
except EOutOfRange: lexMessage(L, errNumberOutOfRange, result.literal)
|
except EOverflow, EOutOfRange:
|
||||||
|
lexMessage(L, errNumberOutOfRange, result.literal)
|
||||||
L.bufpos = endpos
|
L.bufpos = endpos
|
||||||
|
|
||||||
proc handleHexChar(L: var TLexer, xi: var int) =
|
proc handleHexChar(L: var TLexer, xi: var int) =
|
||||||
|
|
@ -628,10 +629,6 @@ proc getOperator(L: var TLexer, tok: var TToken) =
|
||||||
Inc(pos)
|
Inc(pos)
|
||||||
endOperator(L, tok, pos, h)
|
endOperator(L, tok, pos, h)
|
||||||
|
|
||||||
proc handleIndentation(tok: var TToken, indent: int) {.inline.} =
|
|
||||||
tok.indent = indent
|
|
||||||
tok.tokType = tkInd
|
|
||||||
|
|
||||||
proc scanComment(L: var TLexer, tok: var TToken) =
|
proc scanComment(L: var TLexer, tok: var TToken) =
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
var buf = L.buf
|
var buf = L.buf
|
||||||
|
|
@ -680,7 +677,7 @@ proc skip(L: var TLexer, tok: var TToken) =
|
||||||
Inc(pos)
|
Inc(pos)
|
||||||
of Tabulator:
|
of Tabulator:
|
||||||
lexMessagePos(L, errTabulatorsAreNotAllowed, pos)
|
lexMessagePos(L, errTabulatorsAreNotAllowed, pos)
|
||||||
inc(pos) # BUGFIX
|
inc(pos)
|
||||||
of CR, LF:
|
of CR, LF:
|
||||||
pos = HandleCRLF(L, pos)
|
pos = HandleCRLF(L, pos)
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
|
|
@ -688,8 +685,8 @@ proc skip(L: var TLexer, tok: var TToken) =
|
||||||
while buf[pos] == ' ':
|
while buf[pos] == ' ':
|
||||||
Inc(pos)
|
Inc(pos)
|
||||||
Inc(indent)
|
Inc(indent)
|
||||||
if (buf[pos] > ' '):
|
if buf[pos] > ' ':
|
||||||
handleIndentation(tok, indent)
|
tok.indent = indent
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
break # EndOfFile also leaves the loop
|
break # EndOfFile also leaves the loop
|
||||||
|
|
@ -698,17 +695,14 @@ proc skip(L: var TLexer, tok: var TToken) =
|
||||||
proc rawGetTok(L: var TLexer, tok: var TToken) =
|
proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
fillToken(tok)
|
fillToken(tok)
|
||||||
if L.indentAhead >= 0:
|
if L.indentAhead >= 0:
|
||||||
handleIndentation(tok, L.indentAhead)
|
tok.indent = L.indentAhead
|
||||||
L.indentAhead = - 1
|
L.indentAhead = -1
|
||||||
return
|
else:
|
||||||
|
tok.indent = -1
|
||||||
skip(L, tok)
|
skip(L, tok)
|
||||||
# got an documentation comment or tkIndent, return that:
|
|
||||||
if tok.toktype != tkInvalid: return
|
|
||||||
var c = L.buf[L.bufpos]
|
var c = L.buf[L.bufpos]
|
||||||
if c in SymStartChars - {'r', 'R', 'l'}:
|
if c in SymStartChars - {'r', 'R', 'l'}:
|
||||||
getSymbol(L, tok)
|
getSymbol(L, tok)
|
||||||
elif c in {'0'..'9'}:
|
|
||||||
tok = getNumber(L)
|
|
||||||
else:
|
else:
|
||||||
case c
|
case c
|
||||||
of '#':
|
of '#':
|
||||||
|
|
@ -727,7 +721,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
of 'l':
|
of 'l':
|
||||||
# if we parsed exactly one character and its a small L (l), this
|
# if we parsed exactly one character and its a small L (l), this
|
||||||
# is treated as a warning because it may be confused with the number 1
|
# is treated as a warning because it may be confused with the number 1
|
||||||
if not (L.buf[L.bufpos + 1] in (SymChars + {'_'})):
|
if L.buf[L.bufpos+1] notin (SymChars + {'_'}):
|
||||||
lexMessage(L, warnSmallLshouldNotBeUsed)
|
lexMessage(L, warnSmallLshouldNotBeUsed)
|
||||||
getSymbol(L, tok)
|
getSymbol(L, tok)
|
||||||
of 'r', 'R':
|
of 'r', 'R':
|
||||||
|
|
@ -738,7 +732,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
getSymbol(L, tok)
|
getSymbol(L, tok)
|
||||||
of '(':
|
of '(':
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
if (L.buf[L.bufPos] == '.') and (L.buf[L.bufPos + 1] != '.'):
|
if L.buf[L.bufPos] == '.' and L.buf[L.bufPos+1] != '.':
|
||||||
tok.toktype = tkParDotLe
|
tok.toktype = tkParDotLe
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
else:
|
else:
|
||||||
|
|
@ -748,7 +742,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
of '[':
|
of '[':
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
if (L.buf[L.bufPos] == '.') and (L.buf[L.bufPos + 1] != '.'):
|
if L.buf[L.bufPos] == '.' and L.buf[L.bufPos+1] != '.':
|
||||||
tok.toktype = tkBracketDotLe
|
tok.toktype = tkBracketDotLe
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
else:
|
else:
|
||||||
|
|
@ -757,20 +751,20 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
tok.toktype = tkBracketRi
|
tok.toktype = tkBracketRi
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
of '.':
|
of '.':
|
||||||
if L.buf[L.bufPos + 1] == ']':
|
if L.buf[L.bufPos+1] == ']':
|
||||||
tok.tokType = tkBracketDotRi
|
tok.tokType = tkBracketDotRi
|
||||||
Inc(L.bufpos, 2)
|
Inc(L.bufpos, 2)
|
||||||
elif L.buf[L.bufPos + 1] == '}':
|
elif L.buf[L.bufPos+1] == '}':
|
||||||
tok.tokType = tkCurlyDotRi
|
tok.tokType = tkCurlyDotRi
|
||||||
Inc(L.bufpos, 2)
|
Inc(L.bufpos, 2)
|
||||||
elif L.buf[L.bufPos + 1] == ')':
|
elif L.buf[L.bufPos+1] == ')':
|
||||||
tok.tokType = tkParDotRi
|
tok.tokType = tkParDotRi
|
||||||
Inc(L.bufpos, 2)
|
Inc(L.bufpos, 2)
|
||||||
else:
|
else:
|
||||||
getOperator(L, tok)
|
getOperator(L, tok)
|
||||||
of '{':
|
of '{':
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
if (L.buf[L.bufPos] == '.') and (L.buf[L.bufPos+1] != '.'):
|
if L.buf[L.bufPos] == '.' and L.buf[L.bufPos+1] != '.':
|
||||||
tok.toktype = tkCurlyDotLe
|
tok.toktype = tkCurlyDotLe
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
else:
|
else:
|
||||||
|
|
@ -796,13 +790,15 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
tok.tokType = tkCharLit
|
tok.tokType = tkCharLit
|
||||||
getCharacter(L, tok)
|
getCharacter(L, tok)
|
||||||
tok.tokType = tkCharLit
|
tok.tokType = tkCharLit
|
||||||
|
of '0'..'9':
|
||||||
|
tok = getNumber(L)
|
||||||
else:
|
else:
|
||||||
if c in OpChars:
|
if c in OpChars:
|
||||||
getOperator(L, tok)
|
getOperator(L, tok)
|
||||||
elif c == lexbase.EndOfFile:
|
elif c == lexbase.EndOfFile:
|
||||||
tok.toktype = tkEof
|
tok.toktype = tkEof
|
||||||
else:
|
else:
|
||||||
tok.literal = c & ""
|
tok.literal = $c
|
||||||
tok.tokType = tkInvalid
|
tok.tokType = tkInvalid
|
||||||
lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
|
lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import
|
||||||
proc ppGetTok(L: var TLexer, tok: var TToken) =
|
proc ppGetTok(L: var TLexer, tok: var TToken) =
|
||||||
# simple filter
|
# simple filter
|
||||||
rawGetTok(L, tok)
|
rawGetTok(L, tok)
|
||||||
while tok.tokType in {tkInd, tkComment}: rawGetTok(L, tok)
|
while tok.tokType in {tkComment}: rawGetTok(L, tok)
|
||||||
|
|
||||||
proc parseExpr(L: var TLexer, tok: var TToken): bool
|
proc parseExpr(L: var TLexer, tok: var TToken): bool
|
||||||
proc parseAtom(L: var TLexer, tok: var TToken): bool =
|
proc parseAtom(L: var TLexer, tok: var TToken): bool =
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ import
|
||||||
type
|
type
|
||||||
TParser*{.final.} = object # a TParser object represents a module that
|
TParser*{.final.} = object # a TParser object represents a module that
|
||||||
# is being parsed
|
# is being parsed
|
||||||
|
currInd: int # current indentation (for skipInd)
|
||||||
lex*: TLexer # the lexer that is used for parsing
|
lex*: TLexer # the lexer that is used for parsing
|
||||||
tok*: TToken # the current token
|
tok*: TToken # the current token
|
||||||
currInd: int # current indentation (for skipInd)
|
|
||||||
|
|
||||||
proc ParseAll*(p: var TParser): PNode
|
proc ParseAll*(p: var TParser): PNode
|
||||||
proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
|
proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
|
||||||
|
|
@ -97,10 +97,10 @@ template withInd(p: expr, body: stmt) {.immediate.} =
|
||||||
body
|
body
|
||||||
p.currInd = oldInd
|
p.currInd = oldInd
|
||||||
|
|
||||||
template realInd(p): bool = p.tok.tokType == tkInd and p.tok.ident > p.currInd
|
template realInd(p): bool = p.tok.indent > p.currInd
|
||||||
template sameInd(p): bool = p.tok.tokType == tkInd and p.tok.ident == p.currInd
|
template sameInd(p): bool = p.tok.indent == p.currInd
|
||||||
|
|
||||||
proc skipComment(p: var TParser, node: PNode) =
|
proc rawSkipComment(p: var TParser, node: PNode) =
|
||||||
if p.tok.tokType == tkComment:
|
if p.tok.tokType == tkComment:
|
||||||
if node != nil:
|
if node != nil:
|
||||||
if node.comment == nil: node.comment = ""
|
if node.comment == nil: node.comment = ""
|
||||||
|
|
@ -109,17 +109,27 @@ proc skipComment(p: var TParser, node: PNode) =
|
||||||
parMessage(p, errInternal, "skipComment")
|
parMessage(p, errInternal, "skipComment")
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
||||||
|
proc skipComment(p: var TParser, node: PNode) =
|
||||||
|
if p.tok.indent < 0: rawSkipComment(p, node)
|
||||||
|
|
||||||
proc skipInd(p: var TParser) =
|
proc skipInd(p: var TParser) =
|
||||||
if realInd(p): getTok(p)
|
if p.tok.indent >= 0:
|
||||||
|
if not realInd(p): parMessage(p, errInvalidIndentation)
|
||||||
|
|
||||||
proc optPar(p: var TParser) =
|
proc optPar(p: var TParser) =
|
||||||
if p.tok.tokType == tkInd and p.tok.indent >= p.currInd: getTok(p)
|
if p.tok.indent >= 0:
|
||||||
|
if p.tok.indent < p.currInd: parMessage(p, errInvalidIndentation)
|
||||||
|
|
||||||
proc optInd(p: var TParser, n: PNode) =
|
proc optInd(p: var TParser, n: PNode) =
|
||||||
skipComment(p, n)
|
skipComment(p, n)
|
||||||
skipInd(p)
|
skipInd(p)
|
||||||
|
|
||||||
proc ExpectNl(p: TParser) =
|
proc getTokNoInd(p: var TParser) =
|
||||||
|
getTok(p)
|
||||||
|
if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)
|
||||||
|
|
||||||
|
when false:
|
||||||
|
proc ExpectNl(p: TParser) =
|
||||||
if p.tok.tokType notin {tkEof, tkInd, tkComment}:
|
if p.tok.tokType notin {tkEof, tkInd, tkComment}:
|
||||||
lexMessage(p.lex, errNewlineExpected, prettyTok(p.tok))
|
lexMessage(p.lex, errNewlineExpected, prettyTok(p.tok))
|
||||||
|
|
||||||
|
|
@ -139,11 +149,9 @@ proc parLineInfo(p: TParser): TLineInfo =
|
||||||
result = getLineInfo(p.lex)
|
result = getLineInfo(p.lex)
|
||||||
|
|
||||||
proc indAndComment(p: var TParser, n: PNode) =
|
proc indAndComment(p: var TParser, n: PNode) =
|
||||||
if p.tok.tokType == tkInd and p.tok.indent > p.currInd:
|
if p.tok.indent > p.currInd:
|
||||||
var info = parLineInfo(p)
|
if p.tok.tokType == tkComment: rawSkipComment(p, n)
|
||||||
getTok(p)
|
else: parMessage(p, errInvalidIndentation)
|
||||||
if p.tok.tokType == tkComment: skipComment(p, n)
|
|
||||||
else: LocalError(info, errInvalidIndentation)
|
|
||||||
else:
|
else:
|
||||||
skipComment(p, n)
|
skipComment(p, n)
|
||||||
|
|
||||||
|
|
@ -214,7 +222,7 @@ proc getPrecedence(tok: TToken): int =
|
||||||
proc isOperator(tok: TToken): bool =
|
proc isOperator(tok: TToken): bool =
|
||||||
result = getPrecedence(tok) >= 0
|
result = getPrecedence(tok) >= 0
|
||||||
|
|
||||||
#| module = stmt? (IND{=} stmt)*
|
#| module = stmt ^* (';' / IND{=})
|
||||||
#|
|
#|
|
||||||
#| comma = ',' COMMENT? IND?
|
#| comma = ',' COMMENT? IND?
|
||||||
#| semicolon = ';' COMMENT IND?
|
#| semicolon = ';' COMMENT IND?
|
||||||
|
|
@ -242,6 +250,10 @@ proc isOperator(tok: TToken): bool =
|
||||||
#| mulExpr = dollarExpr (OP8 optInd dollarExpr)*
|
#| mulExpr = dollarExpr (OP8 optInd dollarExpr)*
|
||||||
#| dollarExpr = primary (OP9 optInd primary)*
|
#| dollarExpr = primary (OP9 optInd primary)*
|
||||||
|
|
||||||
|
proc colcom(p: var TParser, n: PNode) =
|
||||||
|
eat(p, tkColon)
|
||||||
|
skipComment(p, n)
|
||||||
|
|
||||||
proc parseSymbol(p: var TParser): PNode =
|
proc parseSymbol(p: var TParser): PNode =
|
||||||
#| symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`'
|
#| symbol = '`' (KEYW|IDENT|operator|'(' ')'|'[' ']'|'{' '}'|'='|literal)+ '`'
|
||||||
#| | IDENT
|
#| | IDENT
|
||||||
|
|
@ -291,7 +303,7 @@ proc indexExpr(p: var TParser): PNode =
|
||||||
|
|
||||||
proc indexExprList(p: var TParser, first: PNode, k: TNodeKind,
|
proc indexExprList(p: var TParser, first: PNode, k: TNodeKind,
|
||||||
endToken: TTokType): PNode =
|
endToken: TTokType): PNode =
|
||||||
#| indexExprList = indexExpr (comma indexExpr)* comma?
|
#| indexExprList = indexExpr ^+ comma
|
||||||
result = newNodeP(k, p)
|
result = newNodeP(k, p)
|
||||||
addSon(result, first)
|
addSon(result, first)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
@ -324,7 +336,7 @@ proc exprColonEqExpr(p: var TParser): PNode =
|
||||||
result = a
|
result = a
|
||||||
|
|
||||||
proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
|
proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
#| exprList = expr (comma expr)* comma?
|
#| exprList = expr ^+ comma
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
||||||
|
|
@ -363,8 +375,7 @@ proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
|
assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while p.tok.tokType != endTok and p.tok.tokType != tkEof and
|
while p.tok.tokType != endTok and p.tok.tokType != tkEof:
|
||||||
not (p.tok.tokType == tkInd and p.tok.indent >= p.currInd):
|
|
||||||
var a = exprColonEqExpr(p)
|
var a = exprColonEqExpr(p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
|
|
@ -388,7 +399,7 @@ proc setOrTableConstr(p: var TParser): PNode =
|
||||||
getTok(p) # skip ':'
|
getTok(p) # skip ':'
|
||||||
result.kind = nkTableConstr
|
result.kind = nkTableConstr
|
||||||
else:
|
else:
|
||||||
while p.tok.tokType notin {tkCurlyRi, tkEof, tkInd}:
|
while p.tok.tokType notin {tkCurlyRi, tkEof}:
|
||||||
var a = exprColonEqExpr(p)
|
var a = exprColonEqExpr(p)
|
||||||
if a.kind == nkExprColonExpr: result.kind = nkTableConstr
|
if a.kind == nkExprColonExpr: result.kind = nkTableConstr
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
|
|
@ -722,7 +733,6 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode =
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
if realInd(p):
|
if realInd(p):
|
||||||
withInd(p):
|
withInd(p):
|
||||||
getTok(p)
|
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
while true:
|
while true:
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
|
|
@ -735,16 +745,15 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode =
|
||||||
parMessage(p, errIdentifierExpected, p.tok)
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
if not sameInd(p): break
|
if not sameInd(p): break
|
||||||
getTok(p)
|
|
||||||
|
|
||||||
proc parseParamList(p: var TParser, retColon = true): PNode =
|
proc parseParamList(p: var TParser, retColon = true): PNode =
|
||||||
#| paramList = '(' (identColonEquals (comma/semicolon identColonEquals)*)? ')'
|
#| paramList = '(' identColonEquals ^* (comma/semicolon) ')'
|
||||||
#| paramListArrow = paramList? ('->' optInd typeDesc)?
|
#| paramListArrow = paramList? ('->' optInd typeDesc)?
|
||||||
#| paramListColon = paramList? (':' optInd typeDesc)?
|
#| paramListColon = paramList? (':' optInd typeDesc)?
|
||||||
var a: PNode
|
var a: PNode
|
||||||
result = newNodeP(nkFormalParams, p)
|
result = newNodeP(nkFormalParams, p)
|
||||||
addSon(result, ast.emptyNode) # return type
|
addSon(result, ast.emptyNode) # return type
|
||||||
if p.tok.tokType == tkParLe:
|
if p.tok.tokType == tkParLe and p.tok.indent < 0:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -764,14 +773,16 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
|
||||||
eat(p, tkParRi)
|
eat(p, tkParRi)
|
||||||
let hasRet = if retColon: p.tok.tokType == tkColon
|
let hasRet = if retColon: p.tok.tokType == tkColon
|
||||||
else: p.tok.tokType == tkOpr and IdentEq(p.tok.ident, "->")
|
else: p.tok.tokType == tkOpr and IdentEq(p.tok.ident, "->")
|
||||||
if hasRet:
|
if hasRet and p.tok.indent < 0:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
result.sons[0] = parseTypeDesc(p)
|
result.sons[0] = parseTypeDesc(p)
|
||||||
|
|
||||||
proc optPragmas(p: var TParser): PNode =
|
proc optPragmas(p: var TParser): PNode =
|
||||||
if p.tok.tokType == tkCurlyDotLe: result = parsePragma(p)
|
if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)):
|
||||||
else: result = ast.emptyNode
|
result = parsePragma(p)
|
||||||
|
else:
|
||||||
|
result = ast.emptyNode
|
||||||
|
|
||||||
proc parseDoBlock(p: var TParser): PNode =
|
proc parseDoBlock(p: var TParser): PNode =
|
||||||
#| doBlock = 'do' paramListArrow pragmas? colcom stmt
|
#| doBlock = 'do' paramListArrow pragmas? colcom stmt
|
||||||
|
|
@ -786,21 +797,20 @@ proc parseDoBlock(p: var TParser): PNode =
|
||||||
pragmas = pragmas)
|
pragmas = pragmas)
|
||||||
|
|
||||||
proc parseDoBlocks(p: var TParser, call: PNode) =
|
proc parseDoBlocks(p: var TParser, call: PNode) =
|
||||||
#| doBlocks = doBlock*
|
#| doBlocks = doBlock ^* IND{=}
|
||||||
while p.tok.tokType == tkDo:
|
if p.tok.tokType == tkDo:
|
||||||
|
addSon(call, parseDoBlock(p))
|
||||||
|
while sameInd(p) and p.tok.tokType == tkDo:
|
||||||
addSon(call, parseDoBlock(p))
|
addSon(call, parseDoBlock(p))
|
||||||
|
|
||||||
proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
|
proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
|
||||||
#| procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
|
#| procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
|
||||||
# either a proc type or a anonymous proc
|
# either a proc type or a anonymous proc
|
||||||
var
|
let info = parLineInfo(p)
|
||||||
pragmas, params: PNode
|
|
||||||
info: TLineInfo
|
|
||||||
info = parLineInfo(p)
|
|
||||||
getTok(p)
|
getTok(p)
|
||||||
let hasSignature = p.tok.tokType in {tkParLe, tkColon}
|
let hasSignature = p.tok.tokType in {tkParLe, tkColon} and p.tok.indent < 0
|
||||||
params = parseParamList(p)
|
let params = parseParamList(p)
|
||||||
pragmas = optPragmas(p)
|
let pragmas = optPragmas(p)
|
||||||
if p.tok.tokType == tkEquals and isExpr:
|
if p.tok.tokType == tkEquals and isExpr:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
|
|
@ -831,10 +841,10 @@ proc parseTypeDescKAux(p: var TParser, kind: TNodeKind,
|
||||||
addSon(result, primary(p, mode))
|
addSon(result, primary(p, mode))
|
||||||
|
|
||||||
proc parseExpr(p: var TParser): PNode =
|
proc parseExpr(p: var TParser): PNode =
|
||||||
#| expr = lowestExpr
|
#| expr = (ifExpr
|
||||||
#| | ifExpr
|
|
||||||
#| | whenExpr
|
#| | whenExpr
|
||||||
#| | caseExpr
|
#| | caseExpr)
|
||||||
|
#| / lowestExpr
|
||||||
case p.tok.tokType:
|
case p.tok.tokType:
|
||||||
of tkIf: result = parseIfExpr(p, nkIfExpr)
|
of tkIf: result = parseIfExpr(p, nkIfExpr)
|
||||||
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
|
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
|
||||||
|
|
@ -907,11 +917,11 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
of tkAddr:
|
of tkAddr:
|
||||||
result = newNodeP(nkAddr, p)
|
result = newNodeP(nkAddr, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
addSon(result, primary(p, pmNormal))
|
addSon(result, primary(p, pmNormal))
|
||||||
of tkStatic:
|
of tkStatic:
|
||||||
result = newNodeP(nkStaticExpr, p)
|
result = newNodeP(nkStaticExpr, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
addSon(result, primary(p, pmNormal))
|
addSon(result, primary(p, pmNormal))
|
||||||
of tkBind:
|
of tkBind:
|
||||||
result = newNodeP(nkBind, p)
|
result = newNodeP(nkBind, p)
|
||||||
|
|
@ -933,10 +943,10 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||||
#| exprStmt = lowestExpr (
|
#| exprStmt = lowestExpr (
|
||||||
#| '=' optInd expr
|
#| '=' optInd expr
|
||||||
#| / doBlocks
|
#| / doBlocks
|
||||||
#| / ':' stmt? ('of' exprList ':' stmt
|
#| / ':' stmt? ( IND{=} 'of' exprList ':' stmt
|
||||||
#| | 'elif' expr ':' stmt
|
#| | IND{=} 'elif' expr ':' stmt
|
||||||
#| | 'except' exprList ':' stmt
|
#| | IND{=} 'except' exprList ':' stmt
|
||||||
#| | 'else' ':' stmt )?
|
#| | IND{=} 'else' ':' stmt )*
|
||||||
#| )
|
#| )
|
||||||
var a = lowestExpr(p)
|
var a = lowestExpr(p)
|
||||||
if p.tok.tokType == tkEquals:
|
if p.tok.tokType == tkEquals:
|
||||||
|
|
@ -966,12 +976,10 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||||
result = call
|
result = call
|
||||||
getTok(p)
|
getTok(p)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
if sameInd(p): getTok(p)
|
|
||||||
if p.tok.TokType notin {tkOf, tkElif, tkElse, tkExcept}:
|
if p.tok.TokType notin {tkOf, tkElif, tkElse, tkExcept}:
|
||||||
let body = parseStmt(p)
|
let body = parseStmt(p)
|
||||||
addSon(result, newProcNode(nkDo, body.info, body))
|
addSon(result, newProcNode(nkDo, body.info, body))
|
||||||
while true:
|
while sameInd(p):
|
||||||
if sameInd(p): getTok(p)
|
|
||||||
var b: PNode
|
var b: PNode
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkOf:
|
of tkOf:
|
||||||
|
|
@ -999,7 +1007,7 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||||
proc parseImport(p: var TParser, kind: TNodeKind): PNode =
|
proc parseImport(p: var TParser, kind: TNodeKind): PNode =
|
||||||
#| importStmt = 'import' optInd expr
|
#| importStmt = 'import' optInd expr
|
||||||
#| ((comma expr)*
|
#| ((comma expr)*
|
||||||
#| / 'except' optInd expr (comma expr)*)
|
#| / 'except' optInd (expr ^+ comma))
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(kind, p)
|
||||||
getTok(p) # skip `import` or `export`
|
getTok(p) # skip `import` or `export`
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
|
|
@ -1018,10 +1026,10 @@ proc parseImport(p: var TParser, kind: TNodeKind): PNode =
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
expectNl(p)
|
#expectNl(p)
|
||||||
|
|
||||||
proc parseIncludeStmt(p: var TParser): PNode =
|
proc parseIncludeStmt(p: var TParser): PNode =
|
||||||
#| includeStmt = 'include' optInd expr (comma expr)*
|
#| includeStmt = 'include' optInd expr ^+ comma
|
||||||
result = newNodeP(nkIncludeStmt, p)
|
result = newNodeP(nkIncludeStmt, p)
|
||||||
getTok(p) # skip `import` or `include`
|
getTok(p) # skip `import` or `include`
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
|
|
@ -1033,7 +1041,7 @@ proc parseIncludeStmt(p: var TParser): PNode =
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
expectNl(p)
|
#expectNl(p)
|
||||||
|
|
||||||
proc parseFromStmt(p: var TParser): PNode =
|
proc parseFromStmt(p: var TParser): PNode =
|
||||||
#| fromStmt = 'from' expr 'import' optInd expr (comma expr)*
|
#| fromStmt = 'from' expr 'import' optInd expr (comma expr)*
|
||||||
|
|
@ -1052,7 +1060,7 @@ proc parseFromStmt(p: var TParser): PNode =
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
expectNl(p)
|
#expectNl(p)
|
||||||
|
|
||||||
proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
|
proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
|
||||||
#| returnStmt = 'return' optInd expr?
|
#| returnStmt = 'return' optInd expr?
|
||||||
|
|
@ -1063,15 +1071,16 @@ proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
|
||||||
#| continueStmt = 'break' optInd expr?
|
#| continueStmt = 'break' optInd expr?
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(kind, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
if p.tok.indent >= 0 and p.tok.indent <= p.currInd or p.tok.tokType == tkEof:
|
||||||
case p.tok.tokType
|
# NL terminates:
|
||||||
of tkEof, tkInd: addSon(result, ast.emptyNode)
|
addSon(result, ast.emptyNode)
|
||||||
else: addSon(result, parseExpr(p))
|
else:
|
||||||
|
addSon(result, parseExpr(p))
|
||||||
|
|
||||||
proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
|
proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
|
||||||
#| condStmt = expr colcom stmt COMMENT?
|
#| condStmt = expr colcom stmt COMMENT?
|
||||||
#| ('elif' expr colcom stmt)*
|
#| (IND{=} 'elif' expr colcom stmt)*
|
||||||
#| ('else' colcom stmt)?
|
#| (IND{=} 'else' colcom stmt)?
|
||||||
#| ifStmt = 'if' condStmt
|
#| ifStmt = 'if' condStmt
|
||||||
#| whenStmt = 'when' condStmt
|
#| whenStmt = 'when' condStmt
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(kind, p)
|
||||||
|
|
@ -1085,8 +1094,8 @@ proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
|
||||||
addSon(branch, parseStmt(p))
|
addSon(branch, parseStmt(p))
|
||||||
skipComment(p, branch)
|
skipComment(p, branch)
|
||||||
addSon(result, branch)
|
addSon(result, branch)
|
||||||
if p.tok.tokType != tkElif: break
|
if p.tok.tokType != tkElif or not sameInd(p): break
|
||||||
if p.tok.tokType == tkElse:
|
if p.tok.tokType == tkElse and sameInd(p):
|
||||||
var branch = newNodeP(nkElse, p)
|
var branch = newNodeP(nkElse, p)
|
||||||
eat(p, tkElse)
|
eat(p, tkElse)
|
||||||
eat(p, tkColon)
|
eat(p, tkColon)
|
||||||
|
|
@ -1100,8 +1109,7 @@ proc parseWhile(p: var TParser): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
addSon(result, parseExpr(p))
|
addSon(result, parseExpr(p))
|
||||||
eat(p, tkColon)
|
colcom(p, result)
|
||||||
skipComment(p, result)
|
|
||||||
addSon(result, parseStmt(p))
|
addSon(result, parseStmt(p))
|
||||||
|
|
||||||
proc parseCase(p: var TParser): PNode =
|
proc parseCase(p: var TParser): PNode =
|
||||||
|
|
@ -1128,8 +1136,7 @@ proc parseCase(p: var TParser): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
wasIndented = true
|
wasIndented = true
|
||||||
|
|
||||||
while true:
|
while sameInd(p):
|
||||||
if sameInd(p): getTok(p)
|
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkOf:
|
of tkOf:
|
||||||
if inElif: break
|
if inElif: break
|
||||||
|
|
@ -1156,24 +1163,23 @@ proc parseCase(p: var TParser): PNode =
|
||||||
p.currInd = oldInd
|
p.currInd = oldInd
|
||||||
|
|
||||||
proc parseTry(p: var TParser): PNode =
|
proc parseTry(p: var TParser): PNode =
|
||||||
#| tryStmt = 'try' colcom stmt &('except'|'finally')
|
#| tryStmt = 'try' colcom stmt &(IND{=} 'except'|'finally')
|
||||||
#| ('except' exprList colcom stmt)*
|
#| (IND{=} 'except' exprList colcom stmt)*
|
||||||
#| ('finally' colcom stmt)?
|
#| (IND{=} 'finally' colcom stmt)?
|
||||||
result = newNodeP(nkTryStmt, p)
|
result = newNodeP(nkTryStmt, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
eat(p, tkColon)
|
eat(p, tkColon)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
addSon(result, parseStmt(p))
|
addSon(result, parseStmt(p))
|
||||||
var b: PNode = nil
|
var b: PNode = nil
|
||||||
while true:
|
while sameInd(p):
|
||||||
if p.tok.tokType == tkSad: getTok(p)
|
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkExcept:
|
of tkExcept:
|
||||||
b = newNodeP(nkExceptBranch, p)
|
b = newNodeP(nkExceptBranch, p)
|
||||||
exprList(p, tkColon, b)
|
exprList(p, tkColon, b)
|
||||||
of tkFinally:
|
of tkFinally:
|
||||||
b = newNodeP(nkFinally, p)
|
b = newNodeP(nkFinally, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
eat(p, tkColon)
|
eat(p, tkColon)
|
||||||
else: break
|
else: break
|
||||||
skipComment(p, b)
|
skipComment(p, b)
|
||||||
|
|
@ -1185,15 +1191,14 @@ proc parseTry(p: var TParser): PNode =
|
||||||
proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode =
|
proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode =
|
||||||
#| exceptBlock = 'except' colcom stmt
|
#| exceptBlock = 'except' colcom stmt
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(kind, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
eat(p, tkColon)
|
colcom(p, result)
|
||||||
skipComment(p, result)
|
|
||||||
addSon(result, parseStmt(p))
|
addSon(result, parseStmt(p))
|
||||||
|
|
||||||
proc parseFor(p: var TParser): PNode =
|
proc parseFor(p: var TParser): PNode =
|
||||||
#| forStmt = 'for' symbol (comma symbol)* 'in' expr colcom stmt
|
#| forStmt = 'for' symbol (comma symbol)* 'in' expr colcom stmt
|
||||||
result = newNodeP(nkForStmt, p)
|
result = newNodeP(nkForStmt, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
var a = parseSymbol(p)
|
var a = parseSymbol(p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
while p.tok.tokType == tkComma:
|
while p.tok.tokType == tkComma:
|
||||||
|
|
@ -1203,32 +1208,29 @@ proc parseFor(p: var TParser): PNode =
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
eat(p, tkIn)
|
eat(p, tkIn)
|
||||||
addSon(result, parseExpr(p))
|
addSon(result, parseExpr(p))
|
||||||
eat(p, tkColon)
|
colcom(p, result)
|
||||||
skipComment(p, result)
|
|
||||||
addSon(result, parseStmt(p))
|
addSon(result, parseStmt(p))
|
||||||
|
|
||||||
proc parseBlock(p: var TParser): PNode =
|
proc parseBlock(p: var TParser): PNode =
|
||||||
#| blockStmt = 'block' symbol? colcom stmt
|
#| blockStmt = 'block' symbol? colcom stmt
|
||||||
result = newNodeP(nkBlockStmt, p)
|
result = newNodeP(nkBlockStmt, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
if p.tok.tokType = tkColon: addSon(result, ast.emptyNode)
|
if p.tok.tokType == tkColon: addSon(result, ast.emptyNode)
|
||||||
else: addSon(result, parseSymbol(p))
|
else: addSon(result, parseSymbol(p))
|
||||||
eat(p, tkColon)
|
colcom(p, result)
|
||||||
skipComment(p, result)
|
|
||||||
addSon(result, parseStmt(p))
|
addSon(result, parseStmt(p))
|
||||||
|
|
||||||
proc parseStatic(p: var TParser): PNode =
|
proc parseStatic(p: var TParser): PNode =
|
||||||
#| staticStmt = 'static' colcom stmt
|
#| staticStmt = 'static' colcom stmt
|
||||||
result = newNodeP(nkStaticStmt, p)
|
result = newNodeP(nkStaticStmt, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
eat(p, tkColon)
|
colcom(p, result)
|
||||||
skipComment(p, result)
|
|
||||||
addSon(result, parseStmt(p))
|
addSon(result, parseStmt(p))
|
||||||
|
|
||||||
proc parseAsm(p: var TParser): PNode =
|
proc parseAsm(p: var TParser): PNode =
|
||||||
#| asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLE_STR_LIT)
|
#| asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLE_STR_LIT)
|
||||||
result = newNodeP(nkAsmStmt, p)
|
result = newNodeP(nkAsmStmt, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
||||||
else: addSon(result, ast.emptyNode)
|
else: addSon(result, ast.emptyNode)
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
|
|
@ -1271,11 +1273,11 @@ proc parseGenericParam(p: var TParser): PNode =
|
||||||
|
|
||||||
proc parseGenericParamList(p: var TParser): PNode =
|
proc parseGenericParamList(p: var TParser): PNode =
|
||||||
#| genericParamList = '[' optInd
|
#| genericParamList = '[' optInd
|
||||||
#| (genericParam (comma/semicolon genericParam)*)? optPar ']'
|
#| genericParam ^* (comma/semicolon) optPar ']'
|
||||||
result = newNodeP(nkGenericParams, p)
|
result = newNodeP(nkGenericParams, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
|
while p.tok.tokType in {tkSymbol, tkAccent}:
|
||||||
var a = parseGenericParam(p)
|
var a = parseGenericParam(p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType notin {tkComma, tkSemicolon}: break
|
if p.tok.tokType notin {tkComma, tkSemicolon}: break
|
||||||
|
|
@ -1290,6 +1292,9 @@ proc parsePattern(p: var TParser): PNode =
|
||||||
result = parseStmt(p)
|
result = parseStmt(p)
|
||||||
eat(p, tkCurlyRi)
|
eat(p, tkCurlyRi)
|
||||||
|
|
||||||
|
proc validInd(p: var TParser): bool =
|
||||||
|
result = p.tok.indent < 0 or p.tok.indent > p.currInd
|
||||||
|
|
||||||
proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
|
proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
|
||||||
#| indAndComment = (IND{>} COMMENT)? | COMMENT?
|
#| indAndComment = (IND{>} COMMENT)? | COMMENT?
|
||||||
#| routine = optInd identVis pattern? genericParamList?
|
#| routine = optInd identVis pattern? genericParamList?
|
||||||
|
|
@ -1298,16 +1303,18 @@ proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
addSon(result, identVis(p))
|
addSon(result, identVis(p))
|
||||||
if p.tok.tokType == tkCurlyLe: addSon(result, parsePattern(p))
|
if p.tok.tokType == tkCurlyLe and p.validInd: addSon(result, p.parsePattern)
|
||||||
else: addSon(result, ast.emptyNode)
|
else: addSon(result, ast.emptyNode)
|
||||||
if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
|
if p.tok.tokType == tkBracketLe and p.validInd:
|
||||||
else: addSon(result, ast.emptyNode)
|
result.add(p.parseGenericParamList)
|
||||||
addSon(result, parseParamList(p))
|
else:
|
||||||
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
addSon(result, ast.emptyNode)
|
||||||
|
addSon(result, p.parseParamList)
|
||||||
|
if p.tok.tokType == tkCurlyDotLe and p.validInd: addSon(result, p.parsePragma)
|
||||||
else: addSon(result, ast.emptyNode)
|
else: addSon(result, ast.emptyNode)
|
||||||
# empty exception tracking:
|
# empty exception tracking:
|
||||||
addSon(result, ast.emptyNode)
|
addSon(result, ast.emptyNode)
|
||||||
if p.tok.tokType == tkEquals:
|
if p.tok.tokType == tkEquals and p.validInd:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
addSon(result, parseStmt(p))
|
addSon(result, parseStmt(p))
|
||||||
|
|
@ -1329,22 +1336,15 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(kind, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
case p.tok.tokType
|
if realInd(p):
|
||||||
of tkInd:
|
|
||||||
if not realInd(p): parMessage(p, errInvalidIndentation)
|
|
||||||
withInd(p):
|
withInd(p):
|
||||||
getTok(p)
|
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
while true:
|
while sameInd(p):
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkSad:
|
|
||||||
getTok(p)
|
|
||||||
of tkSymbol, tkAccent:
|
of tkSymbol, tkAccent:
|
||||||
var a = defparser(p)
|
var a = defparser(p)
|
||||||
skipComment(p, a)
|
skipComment(p, a)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
of tkEof:
|
|
||||||
break
|
|
||||||
of tkComment:
|
of tkComment:
|
||||||
var a = newCommentStmt(p)
|
var a = newCommentStmt(p)
|
||||||
skipComment(p, a)
|
skipComment(p, a)
|
||||||
|
|
@ -1352,10 +1352,12 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, p.tok)
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
of tkSymbol, tkAccent, tkParLe:
|
if result.len == 0: parMessage(p, errIdentifierExpected, p.tok)
|
||||||
|
elif p.tok.tokType in {tkSymbol, tkAccent, tkParLe} and p.tok.indent < 0:
|
||||||
# tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
|
# tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
|
||||||
addSon(result, defparser(p))
|
addSon(result, defparser(p))
|
||||||
else: parMessage(p, errIdentifierExpected, p.tok)
|
else:
|
||||||
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
|
|
||||||
proc parseConstant(p: var TParser): PNode =
|
proc parseConstant(p: var TParser): PNode =
|
||||||
#| constant = identWithPragma (colon typedesc)? '=' optInd expr indAndComment
|
#| constant = identWithPragma (colon typedesc)? '=' optInd expr indAndComment
|
||||||
|
|
@ -1378,7 +1380,7 @@ proc parseEnum(p: var TParser): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
addSon(result, ast.emptyNode)
|
addSon(result, ast.emptyNode)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while p.tok.tokType notin {tkEof, tkInd}:
|
while true:
|
||||||
var a = parseSymbol(p)
|
var a = parseSymbol(p)
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
if p.tok.tokType == tkEquals:
|
if p.tok.tokType == tkEquals:
|
||||||
|
|
@ -1393,6 +1395,8 @@ proc parseEnum(p: var TParser): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
|
if p.tok.indent > 0 and p.tok.indent <= p.currInd or p.tok.tokType == tkEof:
|
||||||
|
break
|
||||||
if result.len <= 1:
|
if result.len <= 1:
|
||||||
lexMessage(p.lex, errIdentifierExpected, prettyTok(p.tok))
|
lexMessage(p.lex, errIdentifierExpected, prettyTok(p.tok))
|
||||||
|
|
||||||
|
|
@ -1402,24 +1406,22 @@ proc parseObjectWhen(p: var TParser): PNode =
|
||||||
#| ('elif' expr colcom objectPart COMMENT?)*
|
#| ('elif' expr colcom objectPart COMMENT?)*
|
||||||
#| ('else' colcom objectPart COMMENT?)?
|
#| ('else' colcom objectPart COMMENT?)?
|
||||||
result = newNodeP(nkRecWhen, p)
|
result = newNodeP(nkRecWhen, p)
|
||||||
while true:
|
while sameInd(p):
|
||||||
getTok(p) # skip `when`, `elif`
|
getTok(p) # skip `when`, `elif`
|
||||||
var branch = newNodeP(nkElifBranch, p)
|
var branch = newNodeP(nkElifBranch, p)
|
||||||
optInd(p, branch)
|
optInd(p, branch)
|
||||||
addSon(branch, parseExpr(p))
|
addSon(branch, parseExpr(p))
|
||||||
eat(p, tkColon)
|
colcom(p, branch)
|
||||||
skipComment(p, branch)
|
|
||||||
addSon(branch, parseObjectPart(p))
|
addSon(branch, parseObjectPart(p))
|
||||||
skipComment(p, branch)
|
skipComment(p, branch)
|
||||||
addSon(result, branch)
|
addSon(result, branch)
|
||||||
if p.tok.tokType != tkElif: break
|
if p.tok.tokType != tkElif: break
|
||||||
if p.tok.tokType == tkElse:
|
if p.tok.tokType == tkElse and sameInd(p):
|
||||||
var branch = newNodeP(nkElse, p)
|
var branch = newNodeP(nkElse, p)
|
||||||
eat(p, tkElse)
|
eat(p, tkElse)
|
||||||
eat(p, tkColon)
|
colcom(p, branch)
|
||||||
skipComment(p, branch)
|
|
||||||
addSon(branch, parseObjectPart(p))
|
addSon(branch, parseObjectPart(p))
|
||||||
# XXX no skipComment(p, branch) here?
|
skipComment(p, branch)
|
||||||
addSon(result, branch)
|
addSon(result, branch)
|
||||||
|
|
||||||
proc parseObjectCase(p: var TParser): PNode =
|
proc parseObjectCase(p: var TParser): PNode =
|
||||||
|
|
@ -1427,11 +1429,11 @@ proc parseObjectCase(p: var TParser): PNode =
|
||||||
#| objectBranches = objectBranch (IND{=} objectBranch)*
|
#| objectBranches = objectBranch (IND{=} objectBranch)*
|
||||||
#| (IND{=} 'elif' expr colcom objectPart)*
|
#| (IND{=} 'elif' expr colcom objectPart)*
|
||||||
#| (IND{=} 'else' colcom objectPart)?
|
#| (IND{=} 'else' colcom objectPart)?
|
||||||
#| objectCase = 'case' identWithPragma ':'? COMMENT?
|
#| objectCase = 'case' identWithPragma ':' typeDesc ':'? COMMENT?
|
||||||
#| (IND{>} objectBranches
|
#| (IND{>} objectBranches
|
||||||
#| | IND{=} objectBranches)
|
#| | IND{=} objectBranches)
|
||||||
result = newNodeP(nkRecCase, p)
|
result = newNodeP(nkRecCase, p)
|
||||||
getTok(p)
|
getTokNoInd(p)
|
||||||
var a = newNodeP(nkIdentDefs, p)
|
var a = newNodeP(nkIdentDefs, p)
|
||||||
addSon(a, identWithPragma(p))
|
addSon(a, identWithPragma(p))
|
||||||
eat(p, tkColon)
|
eat(p, tkColon)
|
||||||
|
|
@ -1441,12 +1443,11 @@ proc parseObjectCase(p: var TParser): PNode =
|
||||||
if p.tok.tokType == tkColon: getTok(p)
|
if p.tok.tokType == tkColon: getTok(p)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
var wasIndented = false
|
var wasIndented = false
|
||||||
if p.tok.tokType == tkInd:
|
let oldInd = p.currInd
|
||||||
pushInd(p.lex, p.tok.indent)
|
if realInd(p):
|
||||||
getTok(p)
|
p.currInd = p.tok.indent
|
||||||
wasIndented = true
|
wasIndented = true
|
||||||
while true:
|
while sameInd(p):
|
||||||
if p.tok.tokType == tkSad: getTok(p)
|
|
||||||
var b: PNode
|
var b: PNode
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkOf:
|
of tkOf:
|
||||||
|
|
@ -1466,31 +1467,24 @@ proc parseObjectCase(p: var TParser): PNode =
|
||||||
addSon(result, b)
|
addSon(result, b)
|
||||||
if b.kind == nkElse: break
|
if b.kind == nkElse: break
|
||||||
if wasIndented:
|
if wasIndented:
|
||||||
eat(p, tkDed)
|
p.currInd = oldInd
|
||||||
popInd(p.lex)
|
|
||||||
|
|
||||||
proc parseObjectPart(p: var TParser): PNode =
|
proc parseObjectPart(p: var TParser): PNode =
|
||||||
case p.tok.tokType
|
#| objectPart = IND{>} objectPart^+IND{=} DED
|
||||||
of tkInd:
|
#| / objectWhen / objectCase / 'nil' / declColonEquals
|
||||||
|
if realInd(p):
|
||||||
result = newNodeP(nkRecList, p)
|
result = newNodeP(nkRecList, p)
|
||||||
pushInd(p.lex, p.tok.indent)
|
withInd(p):
|
||||||
getTok(p)
|
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
while true:
|
while sameInd(p):
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkSad:
|
|
||||||
getTok(p)
|
|
||||||
of tkCase, tkWhen, tkSymbol, tkAccent, tkNil:
|
of tkCase, tkWhen, tkSymbol, tkAccent, tkNil:
|
||||||
addSon(result, parseObjectPart(p))
|
addSon(result, parseObjectPart(p))
|
||||||
of tkDed:
|
|
||||||
getTok(p)
|
|
||||||
break
|
|
||||||
of tkEof:
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, p.tok)
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
popInd(p.lex)
|
else:
|
||||||
|
case p.tok.tokType
|
||||||
of tkWhen:
|
of tkWhen:
|
||||||
result = parseObjectWhen(p)
|
result = parseObjectWhen(p)
|
||||||
of tkCase:
|
of tkCase:
|
||||||
|
|
@ -1501,14 +1495,18 @@ proc parseObjectPart(p: var TParser): PNode =
|
||||||
of tkNil:
|
of tkNil:
|
||||||
result = newNodeP(nkNilLit, p)
|
result = newNodeP(nkNilLit, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
else: result = ast.emptyNode
|
else:
|
||||||
|
result = ast.emptyNode
|
||||||
|
|
||||||
proc parseObject(p: var TParser): PNode =
|
proc parseObject(p: var TParser): PNode =
|
||||||
|
#| object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
|
||||||
result = newNodeP(nkObjectTy, p)
|
result = newNodeP(nkObjectTy, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
|
if p.tok.tokType == tkCurlyDotLe and p.validInd:
|
||||||
else: addSon(result, ast.emptyNode)
|
addSon(result, parsePragma(p))
|
||||||
if p.tok.tokType == tkOf:
|
else:
|
||||||
|
addSon(result, ast.emptyNode)
|
||||||
|
if p.tok.tokType == tkOf and p.tok.indent < 0:
|
||||||
var a = newNodeP(nkOfInherit, p)
|
var a = newNodeP(nkOfInherit, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
addSon(a, parseTypeDesc(p))
|
addSon(a, parseTypeDesc(p))
|
||||||
|
|
@ -1526,10 +1524,14 @@ proc parseDistinct(p: var TParser): PNode =
|
||||||
addSon(result, parseTypeDesc(p))
|
addSon(result, parseTypeDesc(p))
|
||||||
|
|
||||||
proc parseTypeDef(p: var TParser): PNode =
|
proc parseTypeDef(p: var TParser): PNode =
|
||||||
|
#| typeDef = identWithPragma genericParamList? '=' optInd typeDefAux
|
||||||
|
#| indAndComment?
|
||||||
result = newNodeP(nkTypeDef, p)
|
result = newNodeP(nkTypeDef, p)
|
||||||
addSon(result, identWithPragma(p))
|
addSon(result, identWithPragma(p))
|
||||||
if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
|
if p.tok.tokType == tkBracketLe and p.validInd:
|
||||||
else: addSon(result, ast.emptyNode)
|
addSon(result, parseGenericParamList(p))
|
||||||
|
else:
|
||||||
|
addSon(result, ast.emptyNode)
|
||||||
if p.tok.tokType == tkEquals:
|
if p.tok.tokType == tkEquals:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
|
|
@ -1539,10 +1541,11 @@ proc parseTypeDef(p: var TParser): PNode =
|
||||||
indAndComment(p, result) # special extension!
|
indAndComment(p, result) # special extension!
|
||||||
|
|
||||||
proc parseVarTuple(p: var TParser): PNode =
|
proc parseVarTuple(p: var TParser): PNode =
|
||||||
|
#| varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
|
||||||
result = newNodeP(nkVarTuple, p)
|
result = newNodeP(nkVarTuple, p)
|
||||||
getTok(p) # skip '('
|
getTok(p) # skip '('
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
|
while p.tok.tokType in {tkSymbol, tkAccent}:
|
||||||
var a = identWithPragma(p)
|
var a = identWithPragma(p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
|
|
@ -1556,12 +1559,14 @@ proc parseVarTuple(p: var TParser): PNode =
|
||||||
addSon(result, parseExpr(p))
|
addSon(result, parseExpr(p))
|
||||||
|
|
||||||
proc parseVariable(p: var TParser): PNode =
|
proc parseVariable(p: var TParser): PNode =
|
||||||
|
#| variable = (varTuple / identColonEquals) indAndComment
|
||||||
if p.tok.tokType == tkParLe: result = parseVarTuple(p)
|
if p.tok.tokType == tkParLe: result = parseVarTuple(p)
|
||||||
else: result = parseIdentColonEquals(p, {withPragma})
|
else: result = parseIdentColonEquals(p, {withPragma})
|
||||||
indAndComment(p, result) # special extension!
|
indAndComment(p, result)
|
||||||
|
|
||||||
proc parseBind(p: var TParser, k: TNodeKind): PNode =
|
proc parseBind(p: var TParser, k: TNodeKind): PNode =
|
||||||
#| bindStmt = 'bind' optInd qualifiedIdent (comma qualifiedIdent)*
|
#| bindStmt = 'bind' optInd qualifiedIdent ^+ comma
|
||||||
|
#| mixinStmt = 'mixin' optInd qualifiedIdent ^+ comma
|
||||||
result = newNodeP(k, p)
|
result = newNodeP(k, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
|
|
@ -1571,12 +1576,12 @@ proc parseBind(p: var TParser, k: TNodeKind): PNode =
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
expectNl(p)
|
#expectNl(p)
|
||||||
|
|
||||||
proc parseStmtPragma(p: var TParser): PNode =
|
proc parseStmtPragma(p: var TParser): PNode =
|
||||||
#| pragmaStmt = pragma (':' COMMENT? stmt)?
|
#| pragmaStmt = pragma (':' COMMENT? stmt)?
|
||||||
result = parsePragma(p)
|
result = parsePragma(p)
|
||||||
if p.tok.tokType == tkColon:
|
if p.tok.tokType == tkColon and p.tok.indent < 0:
|
||||||
let a = result
|
let a = result
|
||||||
result = newNodeI(nkPragmaBlock, a.info)
|
result = newNodeI(nkPragmaBlock, a.info)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
@ -1585,6 +1590,10 @@ proc parseStmtPragma(p: var TParser): PNode =
|
||||||
result.add parseStmt(p)
|
result.add parseStmt(p)
|
||||||
|
|
||||||
proc simpleStmt(p: var TParser): PNode =
|
proc simpleStmt(p: var TParser): PNode =
|
||||||
|
#| simpleStmt = ((returnStmt | raiseStmt | yieldStmt | discardStmt | breakStmt
|
||||||
|
#| | continueStmt | pragmaStmt | importStmt | exportStmt | fromStmt
|
||||||
|
#| | includeStmt | commentStmt) / exprStmt) COMMENT?
|
||||||
|
#|
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkReturn: result = parseReturnOrRaise(p, nkReturnStmt)
|
of tkReturn: result = parseReturnOrRaise(p, nkReturnStmt)
|
||||||
of tkRaise: result = parseReturnOrRaise(p, nkRaiseStmt)
|
of tkRaise: result = parseReturnOrRaise(p, nkRaiseStmt)
|
||||||
|
|
@ -1604,6 +1613,20 @@ proc simpleStmt(p: var TParser): PNode =
|
||||||
if result.kind != nkEmpty: skipComment(p, result)
|
if result.kind != nkEmpty: skipComment(p, result)
|
||||||
|
|
||||||
proc complexOrSimpleStmt(p: var TParser): PNode =
|
proc complexOrSimpleStmt(p: var TParser): PNode =
|
||||||
|
#| complexOrSimpleStmt = (ifStmt | whenStmt | whileStmt
|
||||||
|
#| | tryStmt | finallyStmt | exceptStmt | forStmt
|
||||||
|
#| | blockStmt | staticStmt | asmStmt
|
||||||
|
#| | 'proc' routine
|
||||||
|
#| | 'method' routine
|
||||||
|
#| | 'iterator' routine
|
||||||
|
#| | 'macro' routine
|
||||||
|
#| | 'template' routine
|
||||||
|
#| | 'converter' routine
|
||||||
|
#| | 'type' section(typeDef)
|
||||||
|
#| | 'const' section(constant)
|
||||||
|
#| | ('let' | 'var') section(variable)
|
||||||
|
#| | bindStmt | mixinStmt)
|
||||||
|
#| / simpleStmt
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkIf: result = parseIfOrWhen(p, nkIfStmt)
|
of tkIf: result = parseIfOrWhen(p, nkIfStmt)
|
||||||
of tkWhile: result = parseWhile(p)
|
of tkWhile: result = parseWhile(p)
|
||||||
|
|
@ -1631,25 +1654,22 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
|
||||||
else: result = simpleStmt(p)
|
else: result = simpleStmt(p)
|
||||||
|
|
||||||
proc parseStmt(p: var TParser): PNode =
|
proc parseStmt(p: var TParser): PNode =
|
||||||
if p.tok.tokType == tkInd:
|
#| stmt = (IND{>} complexOrSimpleStmt^+(IND{=} / ';') DED)
|
||||||
|
#| / simpleStmt
|
||||||
|
if p.tok.indent > p.currInd:
|
||||||
result = newNodeP(nkStmtList, p)
|
result = newNodeP(nkStmtList, p)
|
||||||
pushInd(p.lex, p.tok.indent)
|
withInd(p):
|
||||||
getTok(p)
|
|
||||||
while true:
|
while true:
|
||||||
case p.tok.tokType
|
if p.tok.indent == p.currInd:
|
||||||
of tkSad, tkSemicolon: getTok(p)
|
nil
|
||||||
of tkEof: break
|
elif p.tok.tokType == tkSemicolon:
|
||||||
of tkDed:
|
while p.tok.tokType == tkSemicolon: getTok(p)
|
||||||
getTok(p)
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
var a = complexOrSimpleStmt(p)
|
if p.tok.indent > p.currInd:
|
||||||
if a.kind == nkEmpty:
|
parMessage(p, errInvalidIndentation)
|
||||||
# XXX this needs a proper analysis;
|
|
||||||
if isKeyword(p.tok.tokType): parMessage(p, errInvalidIndentation)
|
|
||||||
break
|
break
|
||||||
addSon(result, a)
|
var a = complexOrSimpleStmt(p)
|
||||||
popInd(p.lex)
|
if a.kind != nkEmpty: addSon(result, a)
|
||||||
else:
|
else:
|
||||||
# the case statement is only needed for better error messages:
|
# the case statement is only needed for better error messages:
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
|
|
@ -1660,34 +1680,27 @@ proc parseStmt(p: var TParser): PNode =
|
||||||
else:
|
else:
|
||||||
result = simpleStmt(p)
|
result = simpleStmt(p)
|
||||||
if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
|
if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
|
||||||
if p.tok.tokType == tkSemicolon: getTok(p)
|
while p.tok.tokType == tkSemicolon: getTok(p)
|
||||||
if p.tok.tokType == tkSad: getTok(p)
|
|
||||||
|
|
||||||
proc parseAll(p: var TParser): PNode =
|
proc parseAll(p: var TParser): PNode =
|
||||||
result = newNodeP(nkStmtList, p)
|
result = newNodeP(nkStmtList, p)
|
||||||
while true:
|
while p.tok.tokType != tkEof:
|
||||||
case p.tok.tokType
|
if p.tok.indent != p.currInd:
|
||||||
of tkSad: getTok(p)
|
|
||||||
of tkDed, tkInd:
|
|
||||||
parMessage(p, errInvalidIndentation)
|
parMessage(p, errInvalidIndentation)
|
||||||
getTok(p)
|
|
||||||
of tkEof: break
|
|
||||||
else:
|
|
||||||
var a = complexOrSimpleStmt(p)
|
var a = complexOrSimpleStmt(p)
|
||||||
if a.kind == nkEmpty:
|
if a.kind != nkEmpty:
|
||||||
|
addSon(result, a)
|
||||||
|
else:
|
||||||
parMessage(p, errExprExpected, p.tok)
|
parMessage(p, errExprExpected, p.tok)
|
||||||
# bugfix: consume a token here to prevent an endless loop:
|
# bugfix: consume a token here to prevent an endless loop:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
addSon(result, a)
|
|
||||||
|
|
||||||
proc parseTopLevelStmt(p: var TParser): PNode =
|
proc parseTopLevelStmt(p: var TParser): PNode =
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
while true:
|
while true:
|
||||||
|
if p.tok.indent > 0: parMessage(p, errInvalidIndentation)
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkSad, tkSemicolon: getTok(p)
|
of tkSemicolon: getTok(p)
|
||||||
of tkDed, tkInd:
|
|
||||||
parMessage(p, errInvalidIndentation)
|
|
||||||
getTok(p)
|
|
||||||
of tkEof: break
|
of tkEof: break
|
||||||
else:
|
else:
|
||||||
result = complexOrSimpleStmt(p)
|
result = complexOrSimpleStmt(p)
|
||||||
|
|
@ -1703,4 +1716,3 @@ proc parseString(s: string, filename: string = "", line: int = 0): PNode =
|
||||||
|
|
||||||
result = parser.parseAll
|
result = parser.parseAll
|
||||||
CloseParser(parser)
|
CloseParser(parser)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,13 +81,13 @@ proc addTok(g: var TSrcGen, kind: TTokType, s: string) =
|
||||||
|
|
||||||
proc addPendingNL(g: var TSrcGen) =
|
proc addPendingNL(g: var TSrcGen) =
|
||||||
if g.pendingNL >= 0:
|
if g.pendingNL >= 0:
|
||||||
addTok(g, tkInd, "\n" & repeatChar(g.pendingNL))
|
addTok(g, tkSpaces, "\n" & repeatChar(g.pendingNL))
|
||||||
g.lineLen = g.pendingNL
|
g.lineLen = g.pendingNL
|
||||||
g.pendingNL = - 1
|
g.pendingNL = - 1
|
||||||
|
|
||||||
proc putNL(g: var TSrcGen, indent: int) =
|
proc putNL(g: var TSrcGen, indent: int) =
|
||||||
if g.pendingNL >= 0: addPendingNL(g)
|
if g.pendingNL >= 0: addPendingNL(g)
|
||||||
else: addTok(g, tkInd, "\n")
|
else: addTok(g, tkSpaces, "\n")
|
||||||
g.pendingNL = indent
|
g.pendingNL = indent
|
||||||
g.lineLen = indent
|
g.lineLen = indent
|
||||||
|
|
||||||
|
|
|
||||||
12
todo.txt
12
todo.txt
|
|
@ -7,6 +7,18 @@ version 0.9.2
|
||||||
- acyclic vs prunable; introduce GC hints
|
- acyclic vs prunable; introduce GC hints
|
||||||
- CGEN: ``restrict`` pragma + backend support; computed goto support
|
- CGEN: ``restrict`` pragma + backend support; computed goto support
|
||||||
- document NimMain and check whether it works for threading
|
- document NimMain and check whether it works for threading
|
||||||
|
- parser/grammar: enforce 'simpleExpr' more often --> doesn't work; tkProc is
|
||||||
|
part of primary!
|
||||||
|
* check that of branches can only receive even simpler expressions, don't
|
||||||
|
allow of (var x = 23; nkIdent)
|
||||||
|
* document the new grammar: ^+ ^* operators; indentation handling
|
||||||
|
* remove rules in the manual as it's too hard to keep it up to date
|
||||||
|
* improve rules to contain the AST structure
|
||||||
|
* the typeDesc/expr unification is weird and only necessary because of
|
||||||
|
the ambiguous a[T] construct: It would be easy to support a[expr] for
|
||||||
|
generics but require a[.typeDesc] if that's required; this would also
|
||||||
|
allow [.ref T.](x) for a more general type conversion construct; for
|
||||||
|
templates that would work too: T([.ref int])
|
||||||
|
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue