parser.nim 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This module implements the parser of the standard Nim syntax.
  10. # The parser strictly reflects the grammar ("doc/grammar.txt"); however
  11. # it uses several helper routines to keep the parser small. A special
  12. # efficient algorithm is used for the precedence levels. The parser here can
  13. # be seen as a refinement of the grammar, as it specifies how the AST is built
  14. # from the grammar and how comments belong to the AST.
  15. # In fact the grammar is generated from this file:
  16. when isMainModule:
  17. # Leave a note in grammar.txt that it is generated:
  18. #| # This file is generated by compiler/parser.nim.
  19. import pegs
  20. var outp = open("doc/grammar.txt", fmWrite)
  21. for line in lines("compiler/parser.nim"):
  22. if line =~ peg" \s* '#| ' {.*}":
  23. outp.write matches[0], "\L"
  24. outp.close
  25. import
  26. llstream, lexer, idents, strutils, ast, astalgo, msgs, options, lineinfos,
  27. pathutils
  28. when defined(nimpretty2):
  29. import layouter
  30. type
  31. TParser* = object # A TParser object represents a file that
  32. # is being parsed
  33. currInd: int # current indentation level
  34. firstTok: bool # Has the first token been read?
  35. hasProgress: bool # some while loop requires progress ensurance
  36. lex*: TLexer # The lexer that is used for parsing
  37. tok*: TToken # The current token
  38. inPragma*: int # Pragma level
  39. inSemiStmtList*: int
  40. emptyNode: PNode
  41. when defined(nimpretty2):
  42. em*: Emitter
  43. SymbolMode = enum
  44. smNormal, smAllowNil, smAfterDot
  45. TPrimaryMode = enum
  46. pmNormal, pmTypeDesc, pmTypeDef, pmSkipSuffix
  47. proc parseAll*(p: var TParser): PNode
  48. proc closeParser*(p: var TParser)
  49. proc parseTopLevelStmt*(p: var TParser): PNode
  50. # helpers for the other parsers
  51. proc isOperator*(tok: TToken): bool
  52. proc getTok*(p: var TParser)
  53. proc parMessage*(p: TParser, msg: TMsgKind, arg: string = "")
  54. proc skipComment*(p: var TParser, node: PNode)
  55. proc newNodeP*(kind: TNodeKind, p: TParser): PNode
  56. proc newIntNodeP*(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode
  57. proc newFloatNodeP*(kind: TNodeKind, floatVal: BiggestFloat, p: TParser): PNode
  58. proc newStrNodeP*(kind: TNodeKind, strVal: string, p: TParser): PNode
  59. proc newIdentNodeP*(ident: PIdent, p: TParser): PNode
  60. proc expectIdentOrKeyw*(p: TParser)
  61. proc expectIdent*(p: TParser)
  62. proc parLineInfo*(p: TParser): TLineInfo
  63. proc eat*(p: var TParser, tokType: TTokType)
  64. proc skipInd*(p: var TParser)
  65. proc optPar*(p: var TParser)
  66. proc optInd*(p: var TParser, n: PNode)
  67. proc indAndComment*(p: var TParser, n: PNode)
  68. proc setBaseFlags*(n: PNode, base: TNumericalBase)
  69. proc parseSymbol*(p: var TParser, mode = smNormal): PNode
  70. proc parseTry(p: var TParser; isExpr: bool): PNode
  71. proc parseCase(p: var TParser): PNode
  72. proc parseStmtPragma(p: var TParser): PNode
  73. proc parsePragma(p: var TParser): PNode
  74. proc postExprBlocks(p: var TParser, x: PNode): PNode
  75. proc parseExprStmt(p: var TParser): PNode
  76. proc parseBlock(p: var TParser): PNode
  77. proc primary(p: var TParser, mode: TPrimaryMode): PNode
  78. proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode
  79. # implementation
  80. proc getTok(p: var TParser) =
  81. ## Get the next token from the parser's lexer, and store it in the parser's
  82. ## `tok` member.
  83. rawGetTok(p.lex, p.tok)
  84. p.hasProgress = true
  85. when defined(nimpretty2):
  86. emitTok(p.em, p.lex, p.tok)
  87. while p.tok.tokType == tkComment:
  88. rawGetTok(p.lex, p.tok)
  89. emitTok(p.em, p.lex, p.tok)
  90. proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream,
  91. cache: IdentCache; config: ConfigRef) =
  92. ## Open a parser, using the given arguments to set up its internal state.
  93. ##
  94. initToken(p.tok)
  95. openLexer(p.lex, fileIdx, inputStream, cache, config)
  96. when defined(nimpretty2):
  97. openEmitter(p.em, cache, config, fileIdx)
  98. getTok(p) # read the first token
  99. p.firstTok = true
  100. p.emptyNode = newNode(nkEmpty)
  101. proc openParser*(p: var TParser, filename: AbsoluteFile, inputStream: PLLStream,
  102. cache: IdentCache; config: ConfigRef) =
  103. openParser(p, fileInfoIdx(config, filename), inputStream, cache, config)
  104. proc closeParser(p: var TParser) =
  105. ## Close a parser, freeing up its resources.
  106. closeLexer(p.lex)
  107. when defined(nimpretty2):
  108. closeEmitter(p.em)
  109. proc parMessage(p: TParser, msg: TMsgKind, arg = "") =
  110. ## Produce and emit the parser message `arg` to output.
  111. lexMessageTok(p.lex, msg, p.tok, arg)
  112. proc parMessage(p: TParser, msg: string, tok: TToken) =
  113. ## Produce and emit a parser message to output about the token `tok`
  114. parMessage(p, errGenerated, msg % prettyTok(tok))
  115. proc parMessage(p: TParser, arg: string) =
  116. ## Produce and emit the parser message `arg` to output.
  117. lexMessageTok(p.lex, errGenerated, p.tok, arg)
  118. template withInd(p, body: untyped) =
  119. let oldInd = p.currInd
  120. p.currInd = p.tok.indent
  121. body
  122. p.currInd = oldInd
  123. template realInd(p): bool = p.tok.indent > p.currInd
  124. template sameInd(p): bool = p.tok.indent == p.currInd
  125. template sameOrNoInd(p): bool = p.tok.indent == p.currInd or p.tok.indent < 0
  126. proc rawSkipComment(p: var TParser, node: PNode) =
  127. if p.tok.tokType == tkComment:
  128. if node != nil:
  129. when not defined(nimNoNilSeqs):
  130. if node.comment == nil: node.comment = ""
  131. when defined(nimpretty):
  132. if p.tok.commentOffsetB > p.tok.commentOffsetA:
  133. add node.comment, fileSection(p.lex.config, p.lex.fileIdx, p.tok.commentOffsetA, p.tok.commentOffsetB)
  134. else:
  135. add node.comment, p.tok.literal
  136. else:
  137. add(node.comment, p.tok.literal)
  138. else:
  139. parMessage(p, errInternal, "skipComment")
  140. getTok(p)
  141. proc skipComment(p: var TParser, node: PNode) =
  142. if p.tok.indent < 0: rawSkipComment(p, node)
  143. proc flexComment(p: var TParser, node: PNode) =
  144. if p.tok.indent < 0 or realInd(p): rawSkipComment(p, node)
  145. const
  146. errInvalidIndentation = "invalid indentation"
  147. errIdentifierExpected = "identifier expected, but got '$1'"
  148. errExprExpected = "expression expected, but found '$1'"
  149. errTokenExpected = "'$1' expected"
  150. proc skipInd(p: var TParser) =
  151. if p.tok.indent >= 0:
  152. if not realInd(p): parMessage(p, errInvalidIndentation)
  153. proc optPar(p: var TParser) =
  154. if p.tok.indent >= 0:
  155. if p.tok.indent < p.currInd: parMessage(p, errInvalidIndentation)
  156. proc optInd(p: var TParser, n: PNode) =
  157. skipComment(p, n)
  158. skipInd(p)
  159. proc getTokNoInd(p: var TParser) =
  160. getTok(p)
  161. if p.tok.indent >= 0: parMessage(p, errInvalidIndentation)
  162. proc expectIdentOrKeyw(p: TParser) =
  163. if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType):
  164. lexMessage(p.lex, errGenerated, errIdentifierExpected % prettyTok(p.tok))
  165. proc expectIdent(p: TParser) =
  166. if p.tok.tokType != tkSymbol:
  167. lexMessage(p.lex, errGenerated, errIdentifierExpected % prettyTok(p.tok))
  168. proc eat(p: var TParser, tokType: TTokType) =
  169. ## Move the parser to the next token if the current token is of type
  170. ## `tokType`, otherwise error.
  171. if p.tok.tokType == tokType:
  172. getTok(p)
  173. else:
  174. lexMessage(p.lex, errGenerated,
  175. "expected: '" & TokTypeToStr[tokType] & "', but got: '" & prettyTok(p.tok) & "'")
  176. proc parLineInfo(p: TParser): TLineInfo =
  177. ## Retrieve the line information associated with the parser's current state.
  178. result = getLineInfo(p.lex, p.tok)
  179. proc indAndComment(p: var TParser, n: PNode) =
  180. if p.tok.indent > p.currInd:
  181. if p.tok.tokType == tkComment: rawSkipComment(p, n)
  182. else: parMessage(p, errInvalidIndentation)
  183. else:
  184. skipComment(p, n)
  185. proc newNodeP(kind: TNodeKind, p: TParser): PNode =
  186. result = newNodeI(kind, parLineInfo(p))
  187. proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode =
  188. result = newNodeP(kind, p)
  189. result.intVal = intVal
  190. proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat,
  191. p: TParser): PNode =
  192. result = newNodeP(kind, p)
  193. result.floatVal = floatVal
  194. proc newStrNodeP(kind: TNodeKind, strVal: string, p: TParser): PNode =
  195. result = newNodeP(kind, p)
  196. result.strVal = strVal
  197. proc newIdentNodeP(ident: PIdent, p: TParser): PNode =
  198. result = newNodeP(nkIdent, p)
  199. result.ident = ident
  200. proc parseExpr(p: var TParser): PNode
  201. proc parseStmt(p: var TParser): PNode
  202. proc parseTypeDesc(p: var TParser): PNode
  203. proc parseParamList(p: var TParser, retColon = true): PNode
  204. proc isSigilLike(tok: TToken): bool {.inline.} =
  205. result = tok.tokType == tkOpr and tok.ident.s[0] == '@'
  206. proc isRightAssociative(tok: TToken): bool {.inline.} =
  207. ## Determines whether the token is right assocative.
  208. result = tok.tokType == tkOpr and tok.ident.s[0] == '^'
  209. # or (let L = tok.ident.s.len; L > 1 and tok.ident.s[L-1] == '>'))
  210. proc isOperator(tok: TToken): bool =
  211. ## Determines if the given token is an operator type token.
  212. tok.tokType in {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
  213. tkIsnot, tkNot, tkOf, tkAs, tkDotDot, tkAnd, tkOr, tkXor}
  214. proc isUnary(p: TParser): bool =
  215. ## Check if the current parser token is a unary operator
  216. if p.tok.tokType in {tkOpr, tkDotDot} and
  217. p.tok.strongSpaceB == 0 and
  218. p.tok.strongSpaceA > 0:
  219. result = true
  220. proc checkBinary(p: TParser) {.inline.} =
  221. ## Check if the current parser token is a binary operator.
  222. # we don't check '..' here as that's too annoying
  223. if p.tok.tokType == tkOpr:
  224. if p.tok.strongSpaceB > 0 and p.tok.strongSpaceA != p.tok.strongSpaceB:
  225. parMessage(p, warnInconsistentSpacing, prettyTok(p.tok))
  226. #| module = stmt ^* (';' / IND{=})
  227. #|
  228. #| comma = ',' COMMENT?
  229. #| semicolon = ';' COMMENT?
  230. #| colon = ':' COMMENT?
  231. #| colcom = ':' COMMENT?
  232. #|
  233. #| operator = OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9
  234. #| | 'or' | 'xor' | 'and'
  235. #| | 'is' | 'isnot' | 'in' | 'notin' | 'of'
  236. #| | 'div' | 'mod' | 'shl' | 'shr' | 'not' | 'static' | '..'
  237. #|
  238. #| prefixOperator = operator
  239. #|
  240. #| optInd = COMMENT? IND?
  241. #| optPar = (IND{>} | IND{=})?
  242. #|
  243. #| simpleExpr = arrowExpr (OP0 optInd arrowExpr)* pragma?
  244. #| arrowExpr = assignExpr (OP1 optInd assignExpr)*
  245. #| assignExpr = orExpr (OP2 optInd orExpr)*
  246. #| orExpr = andExpr (OP3 optInd andExpr)*
  247. #| andExpr = cmpExpr (OP4 optInd cmpExpr)*
  248. #| cmpExpr = sliceExpr (OP5 optInd sliceExpr)*
  249. #| sliceExpr = ampExpr (OP6 optInd ampExpr)*
  250. #| ampExpr = plusExpr (OP7 optInd plusExpr)*
  251. #| plusExpr = mulExpr (OP8 optInd mulExpr)*
  252. #| mulExpr = dollarExpr (OP9 optInd dollarExpr)*
  253. #| dollarExpr = primary (OP10 optInd primary)*
  254. proc colcom(p: var TParser, n: PNode) =
  255. eat(p, tkColon)
  256. skipComment(p, n)
  257. const tkBuiltInMagics = {tkType, tkStatic, tkAddr}
  258. proc parseSymbol(p: var TParser, mode = smNormal): PNode =
  259. #| symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
  260. #| | IDENT | KEYW
  261. case p.tok.tokType
  262. of tkSymbol:
  263. result = newIdentNodeP(p.tok.ident, p)
  264. getTok(p)
  265. of tokKeywordLow..tokKeywordHigh:
  266. if p.tok.tokType in tkBuiltInMagics or mode == smAfterDot:
  267. # for backwards compatibility these 2 are always valid:
  268. result = newIdentNodeP(p.tok.ident, p)
  269. getTok(p)
  270. elif p.tok.tokType == tkNil and mode == smAllowNil:
  271. result = newNodeP(nkNilLit, p)
  272. getTok(p)
  273. else:
  274. parMessage(p, errIdentifierExpected, p.tok)
  275. result = p.emptyNode
  276. of tkAccent:
  277. result = newNodeP(nkAccQuoted, p)
  278. getTok(p)
  279. # progress guaranteed
  280. while true:
  281. case p.tok.tokType
  282. of tkAccent:
  283. if result.len == 0:
  284. parMessage(p, errIdentifierExpected, p.tok)
  285. break
  286. of tkOpr, tkDot, tkDotDot, tkEquals, tkParLe..tkParDotRi:
  287. let lineinfo = parLineinfo(p)
  288. var accm = ""
  289. while p.tok.tokType in {tkOpr, tkDot, tkDotDot, tkEquals,
  290. tkParLe..tkParDotRi}:
  291. accm.add(tokToStr(p.tok))
  292. getTok(p)
  293. let node = newNodeI(nkIdent, lineinfo)
  294. node.ident = p.lex.cache.getIdent(accm)
  295. result.add(node)
  296. of tokKeywordLow..tokKeywordHigh, tkSymbol, tkIntLit..tkCharLit:
  297. result.add(newIdentNodeP(p.lex.cache.getIdent(tokToStr(p.tok)), p))
  298. getTok(p)
  299. else:
  300. parMessage(p, errIdentifierExpected, p.tok)
  301. break
  302. eat(p, tkAccent)
  303. else:
  304. parMessage(p, errIdentifierExpected, p.tok)
  305. # BUGFIX: We must consume a token here to prevent endless loops!
  306. # But: this really sucks for idetools and keywords, so we don't do it
  307. # if it is a keyword:
  308. #if not isKeyword(p.tok.tokType): getTok(p)
  309. result = p.emptyNode
  310. proc colonOrEquals(p: var TParser, a: PNode): PNode =
  311. if p.tok.tokType == tkColon:
  312. result = newNodeP(nkExprColonExpr, p)
  313. getTok(p)
  314. #optInd(p, result)
  315. addSon(result, a)
  316. addSon(result, parseExpr(p))
  317. elif p.tok.tokType == tkEquals:
  318. result = newNodeP(nkExprEqExpr, p)
  319. getTok(p)
  320. #optInd(p, result)
  321. addSon(result, a)
  322. addSon(result, parseExpr(p))
  323. else:
  324. result = a
  325. proc exprColonEqExpr(p: var TParser): PNode =
  326. #| exprColonEqExpr = expr (':'|'=' expr)?
  327. var a = parseExpr(p)
  328. if p.tok.tokType == tkDo:
  329. result = postExprBlocks(p, a)
  330. else:
  331. result = colonOrEquals(p, a)
  332. proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
  333. #| exprList = expr ^+ comma
  334. when defined(nimpretty2):
  335. inc p.em.doIndentMore
  336. getTok(p)
  337. optInd(p, result)
  338. # progress guaranteed
  339. while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
  340. var a = parseExpr(p)
  341. addSon(result, a)
  342. if p.tok.tokType != tkComma: break
  343. getTok(p)
  344. optInd(p, a)
  345. when defined(nimpretty2):
  346. dec p.em.doIndentMore
  347. proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
  348. assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
  349. getTok(p)
  350. optInd(p, result)
  351. # progress guaranteed
  352. while p.tok.tokType != endTok and p.tok.tokType != tkEof:
  353. var a = exprColonEqExpr(p)
  354. addSon(result, a)
  355. if p.tok.tokType != tkComma: break
  356. getTok(p)
  357. # (1,) produces a tuple expression
  358. if endTok == tkParRi and p.tok.tokType == tkParRi and result.kind == nkPar:
  359. result.kind = nkTupleConstr
  360. skipComment(p, a)
  361. optPar(p)
  362. eat(p, endTok)
  363. proc exprColonEqExprList(p: var TParser, kind: TNodeKind,
  364. endTok: TTokType): PNode =
  365. #| exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
  366. result = newNodeP(kind, p)
  367. exprColonEqExprListAux(p, endTok, result)
  368. proc dotExpr(p: var TParser, a: PNode): PNode =
  369. #| dotExpr = expr '.' optInd (symbol | '[:' exprList ']')
  370. #| explicitGenericInstantiation = '[:' exprList ']' ( '(' exprColonEqExpr ')' )?
  371. var info = p.parLineInfo
  372. getTok(p)
  373. result = newNodeI(nkDotExpr, info)
  374. optInd(p, result)
  375. addSon(result, a)
  376. addSon(result, parseSymbol(p, smAfterDot))
  377. if p.tok.tokType == tkBracketLeColon and p.tok.strongSpaceA <= 0:
  378. var x = newNodeI(nkBracketExpr, p.parLineInfo)
  379. # rewrite 'x.y[:z]()' to 'y[z](x)'
  380. x.add result[1]
  381. exprList(p, tkBracketRi, x)
  382. eat(p, tkBracketRi)
  383. var y = newNodeI(nkCall, p.parLineInfo)
  384. y.add x
  385. y.add result[0]
  386. if p.tok.tokType == tkParLe and p.tok.strongSpaceA <= 0:
  387. exprColonEqExprListAux(p, tkParRi, y)
  388. result = y
  389. proc qualifiedIdent(p: var TParser): PNode =
  390. #| qualifiedIdent = symbol ('.' optInd symbol)?
  391. result = parseSymbol(p)
  392. if p.tok.tokType == tkDot: result = dotExpr(p, result)
  393. proc setOrTableConstr(p: var TParser): PNode =
  394. #| setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}'
  395. result = newNodeP(nkCurly, p)
  396. getTok(p) # skip '{'
  397. optInd(p, result)
  398. if p.tok.tokType == tkColon:
  399. getTok(p) # skip ':'
  400. result.kind = nkTableConstr
  401. else:
  402. # progress guaranteed
  403. while p.tok.tokType notin {tkCurlyRi, tkEof}:
  404. var a = exprColonEqExpr(p)
  405. if a.kind == nkExprColonExpr: result.kind = nkTableConstr
  406. addSon(result, a)
  407. if p.tok.tokType != tkComma: break
  408. getTok(p)
  409. skipComment(p, a)
  410. optPar(p)
  411. eat(p, tkCurlyRi) # skip '}'
  412. proc parseCast(p: var TParser): PNode =
  413. #| castExpr = 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')'
  414. result = newNodeP(nkCast, p)
  415. getTok(p)
  416. eat(p, tkBracketLe)
  417. optInd(p, result)
  418. addSon(result, parseTypeDesc(p))
  419. optPar(p)
  420. eat(p, tkBracketRi)
  421. eat(p, tkParLe)
  422. optInd(p, result)
  423. addSon(result, parseExpr(p))
  424. optPar(p)
  425. eat(p, tkParRi)
  426. proc setBaseFlags(n: PNode, base: TNumericalBase) =
  427. case base
  428. of base10: discard
  429. of base2: incl(n.flags, nfBase2)
  430. of base8: incl(n.flags, nfBase8)
  431. of base16: incl(n.flags, nfBase16)
  432. proc parseGStrLit(p: var TParser, a: PNode): PNode =
  433. case p.tok.tokType
  434. of tkGStrLit:
  435. result = newNodeP(nkCallStrLit, p)
  436. addSon(result, a)
  437. addSon(result, newStrNodeP(nkRStrLit, p.tok.literal, p))
  438. getTok(p)
  439. of tkGTripleStrLit:
  440. result = newNodeP(nkCallStrLit, p)
  441. addSon(result, a)
  442. addSon(result, newStrNodeP(nkTripleStrLit, p.tok.literal, p))
  443. getTok(p)
  444. else:
  445. result = a
  446. proc complexOrSimpleStmt(p: var TParser): PNode
  447. proc simpleExpr(p: var TParser, mode = pmNormal): PNode
  448. proc semiStmtList(p: var TParser, result: PNode) =
  449. inc p.inSemiStmtList
  450. result.add(complexOrSimpleStmt(p))
  451. # progress guaranteed
  452. while p.tok.tokType == tkSemiColon:
  453. getTok(p)
  454. optInd(p, result)
  455. result.add(complexOrSimpleStmt(p))
  456. dec p.inSemiStmtList
  457. result.kind = nkStmtListExpr
  458. proc parsePar(p: var TParser): PNode =
  459. #| parKeyw = 'discard' | 'include' | 'if' | 'while' | 'case' | 'try'
  460. #| | 'finally' | 'except' | 'for' | 'block' | 'const' | 'let'
  461. #| | 'when' | 'var' | 'mixin'
  462. #| par = '(' optInd
  463. #| ( &parKeyw complexOrSimpleStmt ^+ ';'
  464. #| | ';' complexOrSimpleStmt ^+ ';'
  465. #| | pragmaStmt
  466. #| | simpleExpr ( ('=' expr (';' complexOrSimpleStmt ^+ ';' )? )
  467. #| | (':' expr (',' exprColonEqExpr ^+ ',' )? ) ) )
  468. #| optPar ')'
  469. #
  470. # unfortunately it's ambiguous: (expr: expr) vs (exprStmt); however a
  471. # leading ';' could be used to enforce a 'stmt' context ...
  472. result = newNodeP(nkPar, p)
  473. getTok(p)
  474. optInd(p, result)
  475. flexComment(p, result)
  476. if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase,
  477. tkTry, tkDefer, tkFinally, tkExcept, tkFor, tkBlock,
  478. tkConst, tkLet, tkWhen, tkVar, tkFor,
  479. tkMixin}:
  480. # XXX 'bind' used to be an expression, so we exclude it here;
  481. # tests/reject/tbind2 fails otherwise.
  482. semiStmtList(p, result)
  483. elif p.tok.tokType == tkSemiColon:
  484. # '(;' enforces 'stmt' context:
  485. getTok(p)
  486. optInd(p, result)
  487. semiStmtList(p, result)
  488. elif p.tok.tokType == tkCurlyDotLe:
  489. result.add(parseStmtPragma(p))
  490. elif p.tok.tokType != tkParRi:
  491. var a = simpleExpr(p)
  492. if p.tok.tokType == tkDo:
  493. result = postExprBlocks(p, a)
  494. elif p.tok.tokType == tkEquals:
  495. # special case: allow assignments
  496. let asgn = newNodeP(nkAsgn, p)
  497. getTok(p)
  498. optInd(p, result)
  499. let b = parseExpr(p)
  500. asgn.add a
  501. asgn.add b
  502. result.add(asgn)
  503. if p.tok.tokType == tkSemiColon:
  504. semiStmtList(p, result)
  505. elif p.tok.tokType == tkSemiColon:
  506. # stmt context:
  507. result.add(a)
  508. semiStmtList(p, result)
  509. else:
  510. a = colonOrEquals(p, a)
  511. result.add(a)
  512. if p.tok.tokType == tkComma:
  513. getTok(p)
  514. skipComment(p, a)
  515. # (1,) produces a tuple expression:
  516. if p.tok.tokType == tkParRi:
  517. result.kind = nkTupleConstr
  518. # progress guaranteed
  519. while p.tok.tokType != tkParRi and p.tok.tokType != tkEof:
  520. var a = exprColonEqExpr(p)
  521. addSon(result, a)
  522. if p.tok.tokType != tkComma: break
  523. getTok(p)
  524. skipComment(p, a)
  525. optPar(p)
  526. eat(p, tkParRi)
  527. proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode =
  528. #| literal = | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
  529. #| | UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
  530. #| | FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
  531. #| | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
  532. #| | CHAR_LIT
  533. #| | NIL
  534. #| generalizedLit = GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
  535. #| identOrLiteral = generalizedLit | symbol | literal
  536. #| | par | arrayConstr | setOrTableConstr
  537. #| | castExpr
  538. #| tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
  539. #| arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']'
  540. case p.tok.tokType
  541. of tkSymbol, tkBuiltInMagics, tkOut:
  542. result = newIdentNodeP(p.tok.ident, p)
  543. getTok(p)
  544. result = parseGStrLit(p, result)
  545. of tkAccent:
  546. result = parseSymbol(p) # literals
  547. of tkIntLit:
  548. result = newIntNodeP(nkIntLit, p.tok.iNumber, p)
  549. setBaseFlags(result, p.tok.base)
  550. getTok(p)
  551. of tkInt8Lit:
  552. result = newIntNodeP(nkInt8Lit, p.tok.iNumber, p)
  553. setBaseFlags(result, p.tok.base)
  554. getTok(p)
  555. of tkInt16Lit:
  556. result = newIntNodeP(nkInt16Lit, p.tok.iNumber, p)
  557. setBaseFlags(result, p.tok.base)
  558. getTok(p)
  559. of tkInt32Lit:
  560. result = newIntNodeP(nkInt32Lit, p.tok.iNumber, p)
  561. setBaseFlags(result, p.tok.base)
  562. getTok(p)
  563. of tkInt64Lit:
  564. result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p)
  565. setBaseFlags(result, p.tok.base)
  566. getTok(p)
  567. of tkUIntLit:
  568. result = newIntNodeP(nkUIntLit, p.tok.iNumber, p)
  569. setBaseFlags(result, p.tok.base)
  570. getTok(p)
  571. of tkUInt8Lit:
  572. result = newIntNodeP(nkUInt8Lit, p.tok.iNumber, p)
  573. setBaseFlags(result, p.tok.base)
  574. getTok(p)
  575. of tkUInt16Lit:
  576. result = newIntNodeP(nkUInt16Lit, p.tok.iNumber, p)
  577. setBaseFlags(result, p.tok.base)
  578. getTok(p)
  579. of tkUInt32Lit:
  580. result = newIntNodeP(nkUInt32Lit, p.tok.iNumber, p)
  581. setBaseFlags(result, p.tok.base)
  582. getTok(p)
  583. of tkUInt64Lit:
  584. result = newIntNodeP(nkUInt64Lit, p.tok.iNumber, p)
  585. setBaseFlags(result, p.tok.base)
  586. getTok(p)
  587. of tkFloatLit:
  588. result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p)
  589. setBaseFlags(result, p.tok.base)
  590. getTok(p)
  591. of tkFloat32Lit:
  592. result = newFloatNodeP(nkFloat32Lit, p.tok.fNumber, p)
  593. setBaseFlags(result, p.tok.base)
  594. getTok(p)
  595. of tkFloat64Lit:
  596. result = newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p)
  597. setBaseFlags(result, p.tok.base)
  598. getTok(p)
  599. of tkFloat128Lit:
  600. result = newFloatNodeP(nkFloat128Lit, p.tok.fNumber, p)
  601. setBaseFlags(result, p.tok.base)
  602. getTok(p)
  603. of tkStrLit:
  604. result = newStrNodeP(nkStrLit, p.tok.literal, p)
  605. getTok(p)
  606. of tkRStrLit:
  607. result = newStrNodeP(nkRStrLit, p.tok.literal, p)
  608. getTok(p)
  609. of tkTripleStrLit:
  610. result = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
  611. getTok(p)
  612. of tkCharLit:
  613. result = newIntNodeP(nkCharLit, ord(p.tok.literal[0]), p)
  614. getTok(p)
  615. of tkNil:
  616. result = newNodeP(nkNilLit, p)
  617. getTok(p)
  618. of tkParLe:
  619. # () constructor
  620. if mode in {pmTypeDesc, pmTypeDef}:
  621. result = exprColonEqExprList(p, nkPar, tkParRi)
  622. else:
  623. result = parsePar(p)
  624. of tkCurlyLe:
  625. # {} constructor
  626. result = setOrTableConstr(p)
  627. of tkBracketLe:
  628. # [] constructor
  629. result = exprColonEqExprList(p, nkBracket, tkBracketRi)
  630. of tkCast:
  631. result = parseCast(p)
  632. else:
  633. parMessage(p, errExprExpected, p.tok)
  634. getTok(p) # we must consume a token here to prevend endless loops!
  635. result = p.emptyNode
  636. proc namedParams(p: var TParser, callee: PNode,
  637. kind: TNodeKind, endTok: TTokType): PNode =
  638. let a = callee
  639. result = newNodeP(kind, p)
  640. addSon(result, a)
  641. # progress guaranteed
  642. exprColonEqExprListAux(p, endTok, result)
  643. proc commandParam(p: var TParser, isFirstParam: var bool; mode: TPrimaryMode): PNode =
  644. if mode == pmTypeDesc:
  645. result = simpleExpr(p, mode)
  646. else:
  647. result = parseExpr(p)
  648. if p.tok.tokType == tkDo:
  649. result = postExprBlocks(p, result)
  650. elif p.tok.tokType == tkEquals and not isFirstParam:
  651. let lhs = result
  652. result = newNodeP(nkExprEqExpr, p)
  653. getTok(p)
  654. addSon(result, lhs)
  655. addSon(result, parseExpr(p))
  656. isFirstParam = false
  657. const
  658. tkTypeClasses = {tkRef, tkPtr, tkVar, tkStatic, tkType,
  659. tkEnum, tkTuple, tkObject, tkProc}
  660. proc commandExpr(p: var TParser; r: PNode; mode: TPrimaryMode): PNode =
  661. result = newNodeP(nkCommand, p)
  662. addSon(result, r)
  663. var isFirstParam = true
  664. # progress NOT guaranteed
  665. p.hasProgress = false
  666. addSon result, commandParam(p, isFirstParam, mode)
  667. proc primarySuffix(p: var TParser, r: PNode,
  668. baseIndent: int, mode: TPrimaryMode): PNode =
  669. #| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
  670. #| | doBlocks
  671. #| | '.' optInd symbol generalizedLit?
  672. #| | '[' optInd indexExprList optPar ']'
  673. #| | '{' optInd indexExprList optPar '}'
  674. #| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
  675. result = r
  676. # progress guaranteed
  677. while p.tok.indent < 0 or
  678. (p.tok.tokType == tkDot and p.tok.indent >= baseIndent):
  679. case p.tok.tokType
  680. of tkParLe:
  681. # progress guaranteed
  682. if p.tok.strongSpaceA > 0:
  683. # inside type sections, expressions such as `ref (int, bar)`
  684. # are parsed as a nkCommand with a single tuple argument (nkPar)
  685. if mode == pmTypeDef:
  686. result = newNodeP(nkCommand, p)
  687. result.addSon r
  688. result.addSon primary(p, pmNormal)
  689. else:
  690. result = commandExpr(p, result, mode)
  691. break
  692. result = namedParams(p, result, nkCall, tkParRi)
  693. if result.len > 1 and result.sons[1].kind == nkExprColonExpr:
  694. result.kind = nkObjConstr
  695. of tkDot:
  696. # progress guaranteed
  697. result = dotExpr(p, result)
  698. result = parseGStrLit(p, result)
  699. of tkBracketLe:
  700. # progress guaranteed
  701. if p.tok.strongSpaceA > 0:
  702. result = commandExpr(p, result, mode)
  703. break
  704. result = namedParams(p, result, nkBracketExpr, tkBracketRi)
  705. of tkCurlyLe:
  706. # progress guaranteed
  707. if p.tok.strongSpaceA > 0:
  708. result = commandExpr(p, result, mode)
  709. break
  710. result = namedParams(p, result, nkCurlyExpr, tkCurlyRi)
  711. of tkSymbol, tkAccent, tkIntLit..tkCharLit, tkNil, tkCast,
  712. tkOpr, tkDotDot, tkTypeClasses - {tkRef, tkPtr}:
  713. # XXX: In type sections we allow the free application of the
  714. # command syntax, with the exception of expressions such as
  715. # `foo ref` or `foo ptr`. Unfortunately, these two are also
  716. # used as infix operators for the memory regions feature and
  717. # the current parsing rules don't play well here.
  718. if p.inPragma == 0 and (isUnary(p) or p.tok.tokType notin {tkOpr, tkDotDot}):
  719. # actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
  720. # solution, but pragmas.nim can't handle that
  721. result = commandExpr(p, result, mode)
  722. break
  723. else:
  724. break
  725. proc parseOperators(p: var TParser, headNode: PNode,
  726. limit: int, mode: TPrimaryMode): PNode =
  727. result = headNode
  728. # expand while operators have priorities higher than 'limit'
  729. var opPrec = getPrecedence(p.tok, false)
  730. let modeB = if mode == pmTypeDef: pmTypeDesc else: mode
  731. # the operator itself must not start on a new line:
  732. # progress guaranteed
  733. while opPrec >= limit and p.tok.indent < 0 and not isUnary(p):
  734. checkBinary(p)
  735. var leftAssoc = 1-ord(isRightAssociative(p.tok))
  736. var a = newNodeP(nkInfix, p)
  737. var opNode = newIdentNodeP(p.tok.ident, p) # skip operator:
  738. getTok(p)
  739. optInd(p, a)
  740. # read sub-expression with higher priority:
  741. var b = simpleExprAux(p, opPrec + leftAssoc, modeB)
  742. addSon(a, opNode)
  743. addSon(a, result)
  744. addSon(a, b)
  745. result = a
  746. opPrec = getPrecedence(p.tok, false)
  747. proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
  748. result = primary(p, mode)
  749. if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)) and
  750. mode == pmNormal:
  751. var pragmaExp = newNodeP(nkPragmaExpr, p)
  752. pragmaExp.addSon result
  753. pragmaExp.addSon p.parsePragma
  754. result = pragmaExp
  755. result = parseOperators(p, result, limit, mode)
  756. proc simpleExpr(p: var TParser, mode = pmNormal): PNode =
  757. when defined(nimpretty2):
  758. inc p.em.doIndentMore
  759. result = simpleExprAux(p, -1, mode)
  760. when defined(nimpretty2):
  761. dec p.em.doIndentMore
  762. proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
  763. #| condExpr = expr colcom expr optInd
  764. #| ('elif' expr colcom expr optInd)*
  765. #| 'else' colcom expr
  766. #| ifExpr = 'if' condExpr
  767. #| whenExpr = 'when' condExpr
  768. when true:
  769. result = newNodeP(kind, p)
  770. while true:
  771. getTok(p) # skip `if`, `when`, `elif`
  772. var branch = newNodeP(nkElifExpr, p)
  773. optInd(p, branch)
  774. addSon(branch, parseExpr(p))
  775. colcom(p, branch)
  776. addSon(branch, parseStmt(p))
  777. skipComment(p, branch)
  778. addSon(result, branch)
  779. if p.tok.tokType != tkElif: break # or not sameOrNoInd(p): break
  780. if p.tok.tokType == tkElse: # and sameOrNoInd(p):
  781. var branch = newNodeP(nkElseExpr, p)
  782. eat(p, tkElse)
  783. colcom(p, branch)
  784. addSon(branch, parseStmt(p))
  785. addSon(result, branch)
  786. else:
  787. var
  788. b: PNode
  789. wasIndented = false
  790. result = newNodeP(kind, p)
  791. getTok(p)
  792. let branch = newNodeP(nkElifExpr, p)
  793. addSon(branch, parseExpr(p))
  794. colcom(p, branch)
  795. let oldInd = p.currInd
  796. if realInd(p):
  797. p.currInd = p.tok.indent
  798. wasIndented = true
  799. addSon(branch, parseExpr(p))
  800. result.add branch
  801. while sameInd(p) or not wasIndented:
  802. case p.tok.tokType
  803. of tkElif:
  804. b = newNodeP(nkElifExpr, p)
  805. getTok(p)
  806. optInd(p, b)
  807. addSon(b, parseExpr(p))
  808. of tkElse:
  809. b = newNodeP(nkElseExpr, p)
  810. getTok(p)
  811. else: break
  812. colcom(p, b)
  813. addSon(b, parseStmt(p))
  814. addSon(result, b)
  815. if b.kind == nkElseExpr: break
  816. if wasIndented:
  817. p.currInd = oldInd
  818. proc parsePragma(p: var TParser): PNode =
  819. #| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
  820. result = newNodeP(nkPragma, p)
  821. inc p.inPragma
  822. getTok(p)
  823. optInd(p, result)
  824. while p.tok.tokType notin {tkCurlyDotRi, tkCurlyRi, tkEof}:
  825. p.hasProgress = false
  826. var a = exprColonEqExpr(p)
  827. if not p.hasProgress: break
  828. addSon(result, a)
  829. if p.tok.tokType == tkComma:
  830. getTok(p)
  831. skipComment(p, a)
  832. optPar(p)
  833. if p.tok.tokType in {tkCurlyDotRi, tkCurlyRi}:
  834. when defined(nimpretty2):
  835. if p.tok.tokType == tkCurlyRi: curlyRiWasPragma(p.em)
  836. getTok(p)
  837. else:
  838. parMessage(p, "expected '.}'")
  839. dec p.inPragma
  840. proc identVis(p: var TParser; allowDot=false): PNode =
  841. #| identVis = symbol opr? # postfix position
  842. #| identVisDot = symbol '.' optInd symbol opr?
  843. var a = parseSymbol(p)
  844. if p.tok.tokType == tkOpr:
  845. when defined(nimpretty2):
  846. starWasExportMarker(p.em)
  847. result = newNodeP(nkPostfix, p)
  848. addSon(result, newIdentNodeP(p.tok.ident, p))
  849. addSon(result, a)
  850. getTok(p)
  851. elif p.tok.tokType == tkDot and allowDot:
  852. result = dotExpr(p, a)
  853. else:
  854. result = a
  855. proc identWithPragma(p: var TParser; allowDot=false): PNode =
  856. #| identWithPragma = identVis pragma?
  857. #| identWithPragmaDot = identVisDot pragma?
  858. var a = identVis(p, allowDot)
  859. if p.tok.tokType == tkCurlyDotLe:
  860. result = newNodeP(nkPragmaExpr, p)
  861. addSon(result, a)
  862. addSon(result, parsePragma(p))
  863. else:
  864. result = a
  865. type
  866. TDeclaredIdentFlag = enum
  867. withPragma, # identifier may have pragma
  868. withBothOptional # both ':' and '=' parts are optional
  869. withDot # allow 'var ident.ident = value'
  870. TDeclaredIdentFlags = set[TDeclaredIdentFlag]
  871. proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
  872. #| declColonEquals = identWithPragma (comma identWithPragma)* comma?
  873. #| (':' optInd typeDesc)? ('=' optInd expr)?
  874. #| identColonEquals = ident (comma ident)* comma?
  875. #| (':' optInd typeDesc)? ('=' optInd expr)?)
  876. var a: PNode
  877. result = newNodeP(nkIdentDefs, p)
  878. # progress guaranteed
  879. while true:
  880. case p.tok.tokType
  881. of tkSymbol, tkAccent:
  882. if withPragma in flags: a = identWithPragma(p, allowDot=withdot in flags)
  883. else: a = parseSymbol(p)
  884. if a.kind == nkEmpty: return
  885. else: break
  886. addSon(result, a)
  887. if p.tok.tokType != tkComma: break
  888. getTok(p)
  889. optInd(p, a)
  890. if p.tok.tokType == tkColon:
  891. getTok(p)
  892. optInd(p, result)
  893. addSon(result, parseTypeDesc(p))
  894. else:
  895. addSon(result, newNodeP(nkEmpty, p))
  896. if p.tok.tokType != tkEquals and withBothOptional notin flags:
  897. parMessage(p, "':' or '=' expected, but got '$1'", p.tok)
  898. if p.tok.tokType == tkEquals:
  899. getTok(p)
  900. optInd(p, result)
  901. addSon(result, parseExpr(p))
  902. else:
  903. addSon(result, newNodeP(nkEmpty, p))
  904. proc parseTuple(p: var TParser, indentAllowed = false): PNode =
  905. #| inlTupleDecl = 'tuple'
  906. #| [' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
  907. #| extTupleDecl = 'tuple'
  908. #| COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?
  909. #| tupleClass = 'tuple'
  910. result = newNodeP(nkTupleTy, p)
  911. getTok(p)
  912. if p.tok.tokType == tkBracketLe:
  913. getTok(p)
  914. optInd(p, result)
  915. # progress guaranteed
  916. while p.tok.tokType in {tkSymbol, tkAccent}:
  917. var a = parseIdentColonEquals(p, {})
  918. addSon(result, a)
  919. if p.tok.tokType notin {tkComma, tkSemiColon}: break
  920. when defined(nimpretty2):
  921. commaWasSemicolon(p.em)
  922. getTok(p)
  923. skipComment(p, a)
  924. optPar(p)
  925. eat(p, tkBracketRi)
  926. elif indentAllowed:
  927. skipComment(p, result)
  928. if realInd(p):
  929. withInd(p):
  930. rawSkipComment(p, result)
  931. # progress guaranteed
  932. while true:
  933. case p.tok.tokType
  934. of tkSymbol, tkAccent:
  935. var a = parseIdentColonEquals(p, {})
  936. if p.tok.indent < 0 or p.tok.indent >= p.currInd:
  937. rawSkipComment(p, a)
  938. addSon(result, a)
  939. of tkEof: break
  940. else:
  941. parMessage(p, errIdentifierExpected, p.tok)
  942. break
  943. if not sameInd(p): break
  944. elif p.tok.tokType == tkParLe:
  945. parMessage(p, errGenerated, "the syntax for tuple types is 'tuple[...]', not 'tuple(...)'")
  946. else:
  947. result = newNodeP(nkTupleClassTy, p)
  948. proc parseParamList(p: var TParser, retColon = true): PNode =
  949. #| paramList = '(' declColonEquals ^* (comma/semicolon) ')'
  950. #| paramListArrow = paramList? ('->' optInd typeDesc)?
  951. #| paramListColon = paramList? (':' optInd typeDesc)?
  952. var a: PNode
  953. result = newNodeP(nkFormalParams, p)
  954. addSon(result, p.emptyNode) # return type
  955. when defined(nimpretty2):
  956. inc p.em.doIndentMore
  957. inc p.em.keepIndents
  958. let hasParLe = p.tok.tokType == tkParLe and p.tok.indent < 0
  959. if hasParLe:
  960. getTok(p)
  961. optInd(p, result)
  962. # progress guaranteed
  963. while true:
  964. case p.tok.tokType
  965. of tkSymbol, tkAccent:
  966. a = parseIdentColonEquals(p, {withBothOptional, withPragma})
  967. of tkParRi:
  968. break
  969. of tkVar:
  970. parMessage(p, errGenerated, "the syntax is 'parameter: var T', not 'var parameter: T'")
  971. break
  972. else:
  973. parMessage(p, "expected closing ')'")
  974. break
  975. addSon(result, a)
  976. if p.tok.tokType notin {tkComma, tkSemiColon}: break
  977. when defined(nimpretty2):
  978. commaWasSemicolon(p.em)
  979. getTok(p)
  980. skipComment(p, a)
  981. optPar(p)
  982. eat(p, tkParRi)
  983. let hasRet = if retColon: p.tok.tokType == tkColon
  984. else: p.tok.tokType == tkOpr and p.tok.ident.s == "->"
  985. if hasRet and p.tok.indent < 0:
  986. getTok(p)
  987. optInd(p, result)
  988. result.sons[0] = parseTypeDesc(p)
  989. elif not retColon and not hasParle:
  990. # Mark as "not there" in order to mark for deprecation in the semantic pass:
  991. result = p.emptyNode
  992. when defined(nimpretty2):
  993. dec p.em.doIndentMore
  994. dec p.em.keepIndents
  995. proc optPragmas(p: var TParser): PNode =
  996. if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)):
  997. result = parsePragma(p)
  998. else:
  999. result = p.emptyNode
  1000. proc parseDoBlock(p: var TParser; info: TLineInfo): PNode =
  1001. #| doBlock = 'do' paramListArrow pragmas? colcom stmt
  1002. let params = parseParamList(p, retColon=false)
  1003. let pragmas = optPragmas(p)
  1004. colcom(p, result)
  1005. result = parseStmt(p)
  1006. if params.kind != nkEmpty:
  1007. result = newProcNode(nkDo, info,
  1008. body = result, params = params, name = p.emptyNode, pattern = p.emptyNode,
  1009. genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
  1010. proc parseProcExpr(p: var TParser; isExpr: bool; kind: TNodeKind): PNode =
  1011. #| procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
  1012. # either a proc type or a anonymous proc
  1013. let info = parLineInfo(p)
  1014. getTok(p)
  1015. let hasSignature = p.tok.tokType in {tkParLe, tkColon} and p.tok.indent < 0
  1016. let params = parseParamList(p)
  1017. let pragmas = optPragmas(p)
  1018. if p.tok.tokType == tkEquals and isExpr:
  1019. getTok(p)
  1020. skipComment(p, result)
  1021. result = newProcNode(kind, info, body = parseStmt(p),
  1022. params = params, name = p.emptyNode, pattern = p.emptyNode,
  1023. genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
  1024. else:
  1025. result = newNodeI(nkProcTy, info)
  1026. if hasSignature:
  1027. addSon(result, params)
  1028. addSon(result, pragmas)
  1029. proc isExprStart(p: TParser): bool =
  1030. case p.tok.tokType
  1031. of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkFor,
  1032. tkProc, tkFunc, tkIterator, tkBind, tkBuiltInMagics,
  1033. tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
  1034. tkTuple, tkObject, tkWhen, tkCase, tkOut:
  1035. result = true
  1036. else: result = false
  1037. proc parseSymbolList(p: var TParser, result: PNode) =
  1038. # progress guaranteed
  1039. while true:
  1040. var s = parseSymbol(p, smAllowNil)
  1041. if s.kind == nkEmpty: break
  1042. addSon(result, s)
  1043. if p.tok.tokType != tkComma: break
  1044. getTok(p)
  1045. optInd(p, s)
  1046. proc parseTypeDescKAux(p: var TParser, kind: TNodeKind,
  1047. mode: TPrimaryMode): PNode =
  1048. #| distinct = 'distinct' optInd typeDesc
  1049. result = newNodeP(kind, p)
  1050. getTok(p)
  1051. if p.tok.indent != -1 and p.tok.indent <= p.currInd: return
  1052. optInd(p, result)
  1053. if not isOperator(p.tok) and isExprStart(p):
  1054. addSon(result, primary(p, mode))
  1055. if kind == nkDistinctTy and p.tok.tokType == tkSymbol:
  1056. # XXX document this feature!
  1057. var nodeKind: TNodeKind
  1058. if p.tok.ident.s == "with":
  1059. nodeKind = nkWith
  1060. elif p.tok.ident.s == "without":
  1061. nodeKind = nkWithout
  1062. else:
  1063. return result
  1064. getTok(p)
  1065. let list = newNodeP(nodeKind, p)
  1066. result.addSon list
  1067. parseSymbolList(p, list)
  1068. proc parseVarTuple(p: var TParser): PNode
  1069. proc parseFor(p: var TParser): PNode =
  1070. #| forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt
  1071. #| forExpr = forStmt
  1072. getTokNoInd(p)
  1073. result = newNodeP(nkForStmt, p)
  1074. if p.tok.tokType == tkParLe:
  1075. addSon(result, parseVarTuple(p))
  1076. else:
  1077. var a = identWithPragma(p)
  1078. addSon(result, a)
  1079. while p.tok.tokType == tkComma:
  1080. getTok(p)
  1081. optInd(p, a)
  1082. if p.tok.tokType == tkParLe:
  1083. addSon(result, parseVarTuple(p))
  1084. break
  1085. a = identWithPragma(p)
  1086. addSon(result, a)
  1087. eat(p, tkIn)
  1088. addSon(result, parseExpr(p))
  1089. colcom(p, result)
  1090. addSon(result, parseStmt(p))
  1091. proc parseExpr(p: var TParser): PNode =
  1092. #| expr = (blockExpr
  1093. #| | ifExpr
  1094. #| | whenExpr
  1095. #| | caseExpr
  1096. #| | forExpr
  1097. #| | tryExpr)
  1098. #| / simpleExpr
  1099. case p.tok.tokType:
  1100. of tkBlock: result = parseBlock(p)
  1101. of tkIf: result = parseIfExpr(p, nkIfExpr)
  1102. of tkFor: result = parseFor(p)
  1103. of tkWhen: result = parseIfExpr(p, nkWhenExpr)
  1104. of tkCase: result = parseCase(p)
  1105. of tkTry: result = parseTry(p, isExpr=true)
  1106. else: result = simpleExpr(p)
  1107. proc parseEnum(p: var TParser): PNode
  1108. proc parseObject(p: var TParser): PNode
  1109. proc parseTypeClass(p: var TParser): PNode
  1110. proc primary(p: var TParser, mode: TPrimaryMode): PNode =
  1111. #| typeKeyw = 'var' | 'out' | 'ref' | 'ptr' | 'shared' | 'tuple'
  1112. #| | 'proc' | 'iterator' | 'distinct' | 'object' | 'enum'
  1113. #| primary = typeKeyw typeDescK
  1114. #| / prefixOperator* identOrLiteral primarySuffix*
  1115. #| / 'bind' primary
  1116. if isOperator(p.tok):
  1117. let isSigil = isSigilLike(p.tok)
  1118. result = newNodeP(nkPrefix, p)
  1119. var a = newIdentNodeP(p.tok.ident, p)
  1120. addSon(result, a)
  1121. getTok(p)
  1122. optInd(p, a)
  1123. if isSigil:
  1124. #XXX prefix operators
  1125. let baseInd = p.lex.currLineIndent
  1126. addSon(result, primary(p, pmSkipSuffix))
  1127. result = primarySuffix(p, result, baseInd, mode)
  1128. else:
  1129. addSon(result, primary(p, pmNormal))
  1130. return
  1131. case p.tok.tokType:
  1132. of tkTuple: result = parseTuple(p, mode == pmTypeDef)
  1133. of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda)
  1134. of tkFunc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkFuncDef)
  1135. of tkIterator:
  1136. result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda)
  1137. if result.kind == nkLambda: result.kind = nkIteratorDef
  1138. else: result.kind = nkIteratorTy
  1139. of tkEnum:
  1140. if mode == pmTypeDef:
  1141. result = parseEnum(p)
  1142. else:
  1143. result = newNodeP(nkEnumTy, p)
  1144. getTok(p)
  1145. of tkObject:
  1146. if mode == pmTypeDef:
  1147. result = parseObject(p)
  1148. else:
  1149. result = newNodeP(nkObjectTy, p)
  1150. getTok(p)
  1151. of tkConcept:
  1152. if mode == pmTypeDef:
  1153. result = parseTypeClass(p)
  1154. else:
  1155. parMessage(p, "the 'concept' keyword is only valid in 'type' sections")
  1156. of tkBind:
  1157. result = newNodeP(nkBind, p)
  1158. getTok(p)
  1159. optInd(p, result)
  1160. addSon(result, primary(p, pmNormal))
  1161. of tkVar: result = parseTypeDescKAux(p, nkVarTy, mode)
  1162. of tkRef: result = parseTypeDescKAux(p, nkRefTy, mode)
  1163. of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, mode)
  1164. of tkDistinct: result = parseTypeDescKAux(p, nkDistinctTy, mode)
  1165. else:
  1166. let baseInd = p.lex.currLineIndent
  1167. result = identOrLiteral(p, mode)
  1168. if mode != pmSkipSuffix:
  1169. result = primarySuffix(p, result, baseInd, mode)
  1170. proc binaryNot(p: var TParser; a: PNode): PNode =
  1171. if p.tok.tokType == tkNot:
  1172. let notOpr = newIdentNodeP(p.tok.ident, p)
  1173. getTok(p)
  1174. optInd(p, notOpr)
  1175. let b = parseExpr(p)
  1176. result = newNodeP(nkInfix, p)
  1177. result.add notOpr
  1178. result.add a
  1179. result.add b
  1180. else:
  1181. result = a
  1182. proc parseTypeDesc(p: var TParser): PNode =
  1183. #| typeDesc = simpleExpr ('not' expr)?
  1184. result = simpleExpr(p, pmTypeDesc)
  1185. result = binaryNot(p, result)
  1186. proc parseTypeDefAux(p: var TParser): PNode =
  1187. #| typeDefAux = simpleExpr ('not' expr)?
  1188. #| | 'concept' typeClass
  1189. result = simpleExpr(p, pmTypeDef)
  1190. result = binaryNot(p, result)
  1191. proc makeCall(n: PNode): PNode =
  1192. ## Creates a call if the given node isn't already a call.
  1193. if n.kind in nkCallKinds:
  1194. result = n
  1195. else:
  1196. result = newNodeI(nkCall, n.info)
  1197. result.add n
  1198. proc postExprBlocks(p: var TParser, x: PNode): PNode =
  1199. #| postExprBlocks = ':' stmt? ( IND{=} doBlock
  1200. #| | IND{=} 'of' exprList ':' stmt
  1201. #| | IND{=} 'elif' expr ':' stmt
  1202. #| | IND{=} 'except' exprList ':' stmt
  1203. #| | IND{=} 'else' ':' stmt )*
  1204. result = x
  1205. if p.tok.indent >= 0: return
  1206. var
  1207. openingParams = p.emptyNode
  1208. openingPragmas = p.emptyNode
  1209. if p.tok.tokType == tkDo:
  1210. getTok(p)
  1211. openingParams = parseParamList(p, retColon=false)
  1212. openingPragmas = optPragmas(p)
  1213. if p.tok.tokType == tkColon:
  1214. result = makeCall(result)
  1215. getTok(p)
  1216. skipComment(p, result)
  1217. if p.tok.tokType notin {tkOf, tkElif, tkElse, tkExcept}:
  1218. var stmtList = newNodeP(nkStmtList, p)
  1219. stmtList.add parseStmt(p)
  1220. # to keep backwards compatibility (see tests/vm/tstringnil)
  1221. if stmtList[0].kind == nkStmtList: stmtList = stmtList[0]
  1222. stmtList.flags.incl nfBlockArg
  1223. if openingParams.kind != nkEmpty:
  1224. result.add newProcNode(nkDo, stmtList.info, body = stmtList,
  1225. params = openingParams,
  1226. name = p.emptyNode, pattern = p.emptyNode,
  1227. genericParams = p.emptyNode,
  1228. pragmas = openingPragmas,
  1229. exceptions = p.emptyNode)
  1230. else:
  1231. result.add stmtList
  1232. while sameInd(p):
  1233. var nextBlock: PNode
  1234. let nextToken = p.tok.tokType
  1235. if nextToken == tkDo:
  1236. let info = parLineInfo(p)
  1237. getTok(p)
  1238. nextBlock = parseDoBlock(p, info)
  1239. else:
  1240. case nextToken:
  1241. of tkOf:
  1242. nextBlock = newNodeP(nkOfBranch, p)
  1243. exprList(p, tkColon, nextBlock)
  1244. of tkElif:
  1245. nextBlock = newNodeP(nkElifBranch, p)
  1246. getTok(p)
  1247. optInd(p, nextBlock)
  1248. nextBlock.addSon parseExpr(p)
  1249. of tkExcept:
  1250. nextBlock = newNodeP(nkExceptBranch, p)
  1251. exprList(p, tkColon, nextBlock)
  1252. of tkElse:
  1253. nextBlock = newNodeP(nkElse, p)
  1254. getTok(p)
  1255. else: break
  1256. eat(p, tkColon)
  1257. nextBlock.addSon parseStmt(p)
  1258. nextBlock.flags.incl nfBlockArg
  1259. result.add nextBlock
  1260. if nextBlock.kind == nkElse: break
  1261. else:
  1262. if openingParams.kind != nkEmpty:
  1263. parMessage(p, "expected ':'")
  1264. proc parseExprStmt(p: var TParser): PNode =
  1265. #| exprStmt = simpleExpr
  1266. #| (( '=' optInd expr colonBody? )
  1267. #| / ( expr ^+ comma
  1268. #| doBlocks
  1269. #| / macroColon
  1270. #| ))?
  1271. var a = simpleExpr(p)
  1272. if p.tok.tokType == tkEquals:
  1273. result = newNodeP(nkAsgn, p)
  1274. getTok(p)
  1275. optInd(p, result)
  1276. var b = parseExpr(p)
  1277. b = postExprBlocks(p, b)
  1278. addSon(result, a)
  1279. addSon(result, b)
  1280. else:
  1281. # simpleExpr parsed 'p a' from 'p a, b'?
  1282. var isFirstParam = false
  1283. if p.tok.indent < 0 and p.tok.tokType == tkComma and a.kind == nkCommand:
  1284. result = a
  1285. while true:
  1286. getTok(p)
  1287. optInd(p, result)
  1288. addSon(result, commandParam(p, isFirstParam, pmNormal))
  1289. if p.tok.tokType != tkComma: break
  1290. elif p.tok.indent < 0 and isExprStart(p):
  1291. result = newNode(nkCommand, a.info, @[a])
  1292. while true:
  1293. addSon(result, commandParam(p, isFirstParam, pmNormal))
  1294. if p.tok.tokType != tkComma: break
  1295. getTok(p)
  1296. optInd(p, result)
  1297. else:
  1298. result = a
  1299. result = postExprBlocks(p, result)
  1300. proc parseModuleName(p: var TParser, kind: TNodeKind): PNode =
  1301. result = parseExpr(p)
  1302. when false:
  1303. # parseExpr already handles 'as' syntax ...
  1304. if p.tok.tokType == tkAs and kind == nkImportStmt:
  1305. let a = result
  1306. result = newNodeP(nkImportAs, p)
  1307. getTok(p)
  1308. result.add(a)
  1309. result.add(parseExpr(p))
  1310. proc parseImport(p: var TParser, kind: TNodeKind): PNode =
  1311. #| importStmt = 'import' optInd expr
  1312. #| ((comma expr)*
  1313. #| / 'except' optInd (expr ^+ comma))
  1314. result = newNodeP(kind, p)
  1315. getTok(p) # skip `import` or `export`
  1316. optInd(p, result)
  1317. var a = parseModuleName(p, kind)
  1318. addSon(result, a)
  1319. if p.tok.tokType in {tkComma, tkExcept}:
  1320. if p.tok.tokType == tkExcept:
  1321. result.kind = succ(kind)
  1322. getTok(p)
  1323. optInd(p, result)
  1324. while true:
  1325. # was: while p.tok.tokType notin {tkEof, tkSad, tkDed}:
  1326. p.hasProgress = false
  1327. a = parseModuleName(p, kind)
  1328. if a.kind == nkEmpty or not p.hasProgress: break
  1329. addSon(result, a)
  1330. if p.tok.tokType != tkComma: break
  1331. getTok(p)
  1332. optInd(p, a)
  1333. #expectNl(p)
  1334. proc parseIncludeStmt(p: var TParser): PNode =
  1335. #| includeStmt = 'include' optInd expr ^+ comma
  1336. result = newNodeP(nkIncludeStmt, p)
  1337. getTok(p) # skip `import` or `include`
  1338. optInd(p, result)
  1339. while true:
  1340. # was: while p.tok.tokType notin {tkEof, tkSad, tkDed}:
  1341. p.hasProgress = false
  1342. var a = parseExpr(p)
  1343. if a.kind == nkEmpty or not p.hasProgress: break
  1344. addSon(result, a)
  1345. if p.tok.tokType != tkComma: break
  1346. getTok(p)
  1347. optInd(p, a)
  1348. #expectNl(p)
  1349. proc parseFromStmt(p: var TParser): PNode =
  1350. #| fromStmt = 'from' moduleName 'import' optInd expr (comma expr)*
  1351. result = newNodeP(nkFromStmt, p)
  1352. getTok(p) # skip `from`
  1353. optInd(p, result)
  1354. var a = parseModuleName(p, nkImportStmt)
  1355. addSon(result, a) #optInd(p, a);
  1356. eat(p, tkImport)
  1357. optInd(p, result)
  1358. while true:
  1359. # p.tok.tokType notin {tkEof, tkSad, tkDed}:
  1360. p.hasProgress = false
  1361. a = parseExpr(p)
  1362. if a.kind == nkEmpty or not p.hasProgress: break
  1363. addSon(result, a)
  1364. if p.tok.tokType != tkComma: break
  1365. getTok(p)
  1366. optInd(p, a)
  1367. #expectNl(p)
  1368. proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
  1369. #| returnStmt = 'return' optInd expr?
  1370. #| raiseStmt = 'raise' optInd expr?
  1371. #| yieldStmt = 'yield' optInd expr?
  1372. #| discardStmt = 'discard' optInd expr?
  1373. #| breakStmt = 'break' optInd expr?
  1374. #| continueStmt = 'break' optInd expr?
  1375. result = newNodeP(kind, p)
  1376. getTok(p)
  1377. if p.tok.tokType == tkComment:
  1378. skipComment(p, result)
  1379. addSon(result, p.emptyNode)
  1380. elif p.tok.indent >= 0 and p.tok.indent <= p.currInd or not isExprStart(p):
  1381. # NL terminates:
  1382. addSon(result, p.emptyNode)
  1383. else:
  1384. var e = parseExpr(p)
  1385. e = postExprBlocks(p, e)
  1386. addSon(result, e)
  1387. proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
  1388. #| condStmt = expr colcom stmt COMMENT?
  1389. #| (IND{=} 'elif' expr colcom stmt)*
  1390. #| (IND{=} 'else' colcom stmt)?
  1391. #| ifStmt = 'if' condStmt
  1392. #| whenStmt = 'when' condStmt
  1393. result = newNodeP(kind, p)
  1394. while true:
  1395. getTok(p) # skip `if`, `when`, `elif`
  1396. var branch = newNodeP(nkElifBranch, p)
  1397. optInd(p, branch)
  1398. addSon(branch, parseExpr(p))
  1399. colcom(p, branch)
  1400. addSon(branch, parseStmt(p))
  1401. skipComment(p, branch)
  1402. addSon(result, branch)
  1403. if p.tok.tokType != tkElif or not sameOrNoInd(p): break
  1404. if p.tok.tokType == tkElse and sameOrNoInd(p):
  1405. var branch = newNodeP(nkElse, p)
  1406. eat(p, tkElse)
  1407. colcom(p, branch)
  1408. addSon(branch, parseStmt(p))
  1409. addSon(result, branch)
  1410. proc parseWhile(p: var TParser): PNode =
  1411. #| whileStmt = 'while' expr colcom stmt
  1412. result = newNodeP(nkWhileStmt, p)
  1413. getTok(p)
  1414. optInd(p, result)
  1415. addSon(result, parseExpr(p))
  1416. colcom(p, result)
  1417. addSon(result, parseStmt(p))
  1418. proc parseCase(p: var TParser): PNode =
  1419. #| ofBranch = 'of' exprList colcom stmt
  1420. #| ofBranches = ofBranch (IND{=} ofBranch)*
  1421. #| (IND{=} 'elif' expr colcom stmt)*
  1422. #| (IND{=} 'else' colcom stmt)?
  1423. #| caseStmt = 'case' expr ':'? COMMENT?
  1424. #| (IND{>} ofBranches DED
  1425. #| | IND{=} ofBranches)
  1426. var
  1427. b: PNode
  1428. inElif = false
  1429. wasIndented = false
  1430. result = newNodeP(nkCaseStmt, p)
  1431. getTok(p)
  1432. addSon(result, parseExpr(p))
  1433. if p.tok.tokType == tkColon: getTok(p)
  1434. skipComment(p, result)
  1435. let oldInd = p.currInd
  1436. if realInd(p):
  1437. p.currInd = p.tok.indent
  1438. wasIndented = true
  1439. while sameInd(p):
  1440. case p.tok.tokType
  1441. of tkOf:
  1442. if inElif: break
  1443. b = newNodeP(nkOfBranch, p)
  1444. exprList(p, tkColon, b)
  1445. of tkElif:
  1446. inElif = true
  1447. b = newNodeP(nkElifBranch, p)
  1448. getTok(p)
  1449. optInd(p, b)
  1450. addSon(b, parseExpr(p))
  1451. of tkElse:
  1452. b = newNodeP(nkElse, p)
  1453. getTok(p)
  1454. else: break
  1455. colcom(p, b)
  1456. addSon(b, parseStmt(p))
  1457. addSon(result, b)
  1458. if b.kind == nkElse: break
  1459. if wasIndented:
  1460. p.currInd = oldInd
  1461. proc parseTry(p: var TParser; isExpr: bool): PNode =
  1462. #| tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
  1463. #| (IND{=}? 'except' exprList colcom stmt)*
  1464. #| (IND{=}? 'finally' colcom stmt)?
  1465. #| tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
  1466. #| (optInd 'except' exprList colcom stmt)*
  1467. #| (optInd 'finally' colcom stmt)?
  1468. result = newNodeP(nkTryStmt, p)
  1469. getTok(p)
  1470. colcom(p, result)
  1471. addSon(result, parseStmt(p))
  1472. var b: PNode = nil
  1473. while sameOrNoInd(p) or isExpr:
  1474. case p.tok.tokType
  1475. of tkExcept:
  1476. b = newNodeP(nkExceptBranch, p)
  1477. exprList(p, tkColon, b)
  1478. of tkFinally:
  1479. b = newNodeP(nkFinally, p)
  1480. getTok(p)
  1481. else: break
  1482. colcom(p, b)
  1483. addSon(b, parseStmt(p))
  1484. addSon(result, b)
  1485. if b == nil: parMessage(p, "expected 'except'")
  1486. proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode =
  1487. #| exceptBlock = 'except' colcom stmt
  1488. result = newNodeP(kind, p)
  1489. getTok(p)
  1490. colcom(p, result)
  1491. addSon(result, parseStmt(p))
  1492. proc parseBlock(p: var TParser): PNode =
  1493. #| blockStmt = 'block' symbol? colcom stmt
  1494. #| blockExpr = 'block' symbol? colcom stmt
  1495. result = newNodeP(nkBlockStmt, p)
  1496. getTokNoInd(p)
  1497. if p.tok.tokType == tkColon: addSon(result, p.emptyNode)
  1498. else: addSon(result, parseSymbol(p))
  1499. colcom(p, result)
  1500. addSon(result, parseStmt(p))
  1501. proc parseStaticOrDefer(p: var TParser; k: TNodeKind): PNode =
  1502. #| staticStmt = 'static' colcom stmt
  1503. #| deferStmt = 'defer' colcom stmt
  1504. result = newNodeP(k, p)
  1505. getTok(p)
  1506. colcom(p, result)
  1507. addSon(result, parseStmt(p))
  1508. proc parseAsm(p: var TParser): PNode =
  1509. #| asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLESTR_LIT)
  1510. result = newNodeP(nkAsmStmt, p)
  1511. getTokNoInd(p)
  1512. if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
  1513. else: addSon(result, p.emptyNode)
  1514. case p.tok.tokType
  1515. of tkStrLit: addSon(result, newStrNodeP(nkStrLit, p.tok.literal, p))
  1516. of tkRStrLit: addSon(result, newStrNodeP(nkRStrLit, p.tok.literal, p))
  1517. of tkTripleStrLit: addSon(result,
  1518. newStrNodeP(nkTripleStrLit, p.tok.literal, p))
  1519. else:
  1520. parMessage(p, "the 'asm' statement takes a string literal")
  1521. addSon(result, p.emptyNode)
  1522. return
  1523. getTok(p)
  1524. proc parseGenericParam(p: var TParser): PNode =
  1525. #| genericParam = symbol (comma symbol)* (colon expr)? ('=' optInd expr)?
  1526. var a: PNode
  1527. result = newNodeP(nkIdentDefs, p)
  1528. # progress guaranteed
  1529. while true:
  1530. case p.tok.tokType
  1531. of tkIn, tkOut:
  1532. let x = p.lex.cache.getIdent(if p.tok.tokType == tkIn: "in" else: "out")
  1533. a = newNodeP(nkPrefix, p)
  1534. a.addSon newIdentNodeP(x, p)
  1535. getTok(p)
  1536. expectIdent(p)
  1537. a.addSon(parseSymbol(p))
  1538. of tkSymbol, tkAccent:
  1539. a = parseSymbol(p)
  1540. if a.kind == nkEmpty: return
  1541. else: break
  1542. addSon(result, a)
  1543. if p.tok.tokType != tkComma: break
  1544. getTok(p)
  1545. optInd(p, a)
  1546. if p.tok.tokType == tkColon:
  1547. getTok(p)
  1548. optInd(p, result)
  1549. addSon(result, parseExpr(p))
  1550. else:
  1551. addSon(result, p.emptyNode)
  1552. if p.tok.tokType == tkEquals:
  1553. getTok(p)
  1554. optInd(p, result)
  1555. addSon(result, parseExpr(p))
  1556. else:
  1557. addSon(result, p.emptyNode)
  1558. proc parseGenericParamList(p: var TParser): PNode =
  1559. #| genericParamList = '[' optInd
  1560. #| genericParam ^* (comma/semicolon) optPar ']'
  1561. result = newNodeP(nkGenericParams, p)
  1562. getTok(p)
  1563. optInd(p, result)
  1564. # progress guaranteed
  1565. while p.tok.tokType in {tkSymbol, tkAccent, tkIn, tkOut}:
  1566. var a = parseGenericParam(p)
  1567. addSon(result, a)
  1568. if p.tok.tokType notin {tkComma, tkSemiColon}: break
  1569. when defined(nimpretty2):
  1570. commaWasSemicolon(p.em)
  1571. getTok(p)
  1572. skipComment(p, a)
  1573. optPar(p)
  1574. eat(p, tkBracketRi)
  1575. proc parsePattern(p: var TParser): PNode =
  1576. #| pattern = '{' stmt '}'
  1577. eat(p, tkCurlyLe)
  1578. result = parseStmt(p)
  1579. eat(p, tkCurlyRi)
  1580. proc validInd(p: var TParser): bool =
  1581. result = p.tok.indent < 0 or p.tok.indent > p.currInd
  1582. proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
  1583. #| indAndComment = (IND{>} COMMENT)? | COMMENT?
  1584. #| routine = optInd identVis pattern? genericParamList?
  1585. #| paramListColon pragma? ('=' COMMENT? stmt)? indAndComment
  1586. result = newNodeP(kind, p)
  1587. getTok(p)
  1588. optInd(p, result)
  1589. addSon(result, identVis(p))
  1590. if p.tok.tokType == tkCurlyLe and p.validInd: addSon(result, p.parsePattern)
  1591. else: addSon(result, p.emptyNode)
  1592. if p.tok.tokType == tkBracketLe and p.validInd:
  1593. result.add(p.parseGenericParamList)
  1594. else:
  1595. addSon(result, p.emptyNode)
  1596. addSon(result, p.parseParamList)
  1597. if p.tok.tokType == tkCurlyDotLe and p.validInd: addSon(result, p.parsePragma)
  1598. else: addSon(result, p.emptyNode)
  1599. # empty exception tracking:
  1600. addSon(result, p.emptyNode)
  1601. if p.tok.tokType == tkEquals and p.validInd:
  1602. getTok(p)
  1603. skipComment(p, result)
  1604. addSon(result, parseStmt(p))
  1605. else:
  1606. addSon(result, p.emptyNode)
  1607. indAndComment(p, result)
  1608. proc newCommentStmt(p: var TParser): PNode =
  1609. #| commentStmt = COMMENT
  1610. result = newNodeP(nkCommentStmt, p)
  1611. result.comment = p.tok.literal
  1612. getTok(p)
  1613. type
  1614. TDefParser = proc (p: var TParser): PNode {.nimcall.}
  1615. proc parseSection(p: var TParser, kind: TNodeKind,
  1616. defparser: TDefParser): PNode =
  1617. #| section(p) = COMMENT? p / (IND{>} (p / COMMENT)^+IND{=} DED)
  1618. result = newNodeP(kind, p)
  1619. if kind != nkTypeSection: getTok(p)
  1620. skipComment(p, result)
  1621. if realInd(p):
  1622. withInd(p):
  1623. skipComment(p, result)
  1624. # progress guaranteed
  1625. while sameInd(p):
  1626. case p.tok.tokType
  1627. of tkSymbol, tkAccent, tkParLe:
  1628. var a = defparser(p)
  1629. skipComment(p, a)
  1630. addSon(result, a)
  1631. of tkComment:
  1632. var a = newCommentStmt(p)
  1633. addSon(result, a)
  1634. else:
  1635. parMessage(p, errIdentifierExpected, p.tok)
  1636. break
  1637. if result.len == 0: parMessage(p, errIdentifierExpected, p.tok)
  1638. elif p.tok.tokType in {tkSymbol, tkAccent, tkParLe} and p.tok.indent < 0:
  1639. # tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
  1640. addSon(result, defparser(p))
  1641. else:
  1642. parMessage(p, errIdentifierExpected, p.tok)
  1643. proc parseEnum(p: var TParser): PNode =
  1644. #| enum = 'enum' optInd (symbol optPragmas optInd ('=' optInd expr COMMENT?)? comma?)+
  1645. result = newNodeP(nkEnumTy, p)
  1646. getTok(p)
  1647. addSon(result, p.emptyNode)
  1648. optInd(p, result)
  1649. flexComment(p, result)
  1650. # progress guaranteed
  1651. while true:
  1652. var a = parseSymbol(p)
  1653. if a.kind == nkEmpty: return
  1654. var symPragma = a
  1655. var pragma: PNode
  1656. if p.tok.tokType == tkCurlyDotLe:
  1657. pragma = optPragmas(p)
  1658. symPragma = newNodeP(nkPragmaExpr, p)
  1659. addSon(symPragma, a)
  1660. addSon(symPragma, pragma)
  1661. if p.tok.indent >= 0 and p.tok.indent <= p.currInd:
  1662. add(result, symPragma)
  1663. break
  1664. if p.tok.tokType == tkEquals and p.tok.indent < 0:
  1665. getTok(p)
  1666. optInd(p, symPragma)
  1667. var b = symPragma
  1668. symPragma = newNodeP(nkEnumFieldDef, p)
  1669. addSon(symPragma, b)
  1670. addSon(symPragma, parseExpr(p))
  1671. if p.tok.indent < 0 or p.tok.indent >= p.currInd:
  1672. rawSkipComment(p, symPragma)
  1673. if p.tok.tokType == tkComma and p.tok.indent < 0:
  1674. getTok(p)
  1675. rawSkipComment(p, symPragma)
  1676. else:
  1677. if p.tok.indent < 0 or p.tok.indent >= p.currInd:
  1678. rawSkipComment(p, symPragma)
  1679. addSon(result, symPragma)
  1680. if p.tok.indent >= 0 and p.tok.indent <= p.currInd or
  1681. p.tok.tokType == tkEof:
  1682. break
  1683. if result.len <= 1:
  1684. parMessage(p, errIdentifierExpected, p.tok)
  1685. proc parseObjectPart(p: var TParser): PNode
  1686. proc parseObjectWhen(p: var TParser): PNode =
  1687. #| objectWhen = 'when' expr colcom objectPart COMMENT?
  1688. #| ('elif' expr colcom objectPart COMMENT?)*
  1689. #| ('else' colcom objectPart COMMENT?)?
  1690. result = newNodeP(nkRecWhen, p)
  1691. # progress guaranteed
  1692. while sameInd(p):
  1693. getTok(p) # skip `when`, `elif`
  1694. var branch = newNodeP(nkElifBranch, p)
  1695. optInd(p, branch)
  1696. addSon(branch, parseExpr(p))
  1697. colcom(p, branch)
  1698. addSon(branch, parseObjectPart(p))
  1699. flexComment(p, branch)
  1700. addSon(result, branch)
  1701. if p.tok.tokType != tkElif: break
  1702. if p.tok.tokType == tkElse and sameInd(p):
  1703. var branch = newNodeP(nkElse, p)
  1704. eat(p, tkElse)
  1705. colcom(p, branch)
  1706. addSon(branch, parseObjectPart(p))
  1707. flexComment(p, branch)
  1708. addSon(result, branch)
  1709. proc parseObjectCase(p: var TParser): PNode =
  1710. #| objectBranch = 'of' exprList colcom objectPart
  1711. #| objectBranches = objectBranch (IND{=} objectBranch)*
  1712. #| (IND{=} 'elif' expr colcom objectPart)*
  1713. #| (IND{=} 'else' colcom objectPart)?
  1714. #| objectCase = 'case' identWithPragma ':' typeDesc ':'? COMMENT?
  1715. #| (IND{>} objectBranches DED
  1716. #| | IND{=} objectBranches)
  1717. result = newNodeP(nkRecCase, p)
  1718. getTokNoInd(p)
  1719. var a = newNodeP(nkIdentDefs, p)
  1720. addSon(a, identWithPragma(p))
  1721. eat(p, tkColon)
  1722. addSon(a, parseTypeDesc(p))
  1723. addSon(a, p.emptyNode)
  1724. addSon(result, a)
  1725. if p.tok.tokType == tkColon: getTok(p)
  1726. flexComment(p, result)
  1727. var wasIndented = false
  1728. let oldInd = p.currInd
  1729. if realInd(p):
  1730. p.currInd = p.tok.indent
  1731. wasIndented = true
  1732. # progress guaranteed
  1733. while sameInd(p):
  1734. var b: PNode
  1735. case p.tok.tokType
  1736. of tkOf:
  1737. b = newNodeP(nkOfBranch, p)
  1738. exprList(p, tkColon, b)
  1739. of tkElse:
  1740. b = newNodeP(nkElse, p)
  1741. getTok(p)
  1742. else: break
  1743. colcom(p, b)
  1744. var fields = parseObjectPart(p)
  1745. if fields.kind == nkEmpty:
  1746. parMessage(p, errIdentifierExpected, p.tok)
  1747. fields = newNodeP(nkNilLit, p) # don't break further semantic checking
  1748. addSon(b, fields)
  1749. addSon(result, b)
  1750. if b.kind == nkElse: break
  1751. if wasIndented:
  1752. p.currInd = oldInd
  1753. proc parseObjectPart(p: var TParser): PNode =
  1754. #| objectPart = IND{>} objectPart^+IND{=} DED
  1755. #| / objectWhen / objectCase / 'nil' / 'discard' / declColonEquals
  1756. if realInd(p):
  1757. result = newNodeP(nkRecList, p)
  1758. withInd(p):
  1759. rawSkipComment(p, result)
  1760. while sameInd(p):
  1761. case p.tok.tokType
  1762. of tkCase, tkWhen, tkSymbol, tkAccent, tkNil, tkDiscard:
  1763. addSon(result, parseObjectPart(p))
  1764. else:
  1765. parMessage(p, errIdentifierExpected, p.tok)
  1766. break
  1767. else:
  1768. case p.tok.tokType
  1769. of tkWhen:
  1770. result = parseObjectWhen(p)
  1771. of tkCase:
  1772. result = parseObjectCase(p)
  1773. of tkSymbol, tkAccent:
  1774. result = parseIdentColonEquals(p, {withPragma})
  1775. if p.tok.indent < 0 or p.tok.indent >= p.currInd:
  1776. rawSkipComment(p, result)
  1777. of tkNil, tkDiscard:
  1778. result = newNodeP(nkNilLit, p)
  1779. getTok(p)
  1780. else:
  1781. result = p.emptyNode
  1782. proc parseObject(p: var TParser): PNode =
  1783. #| object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
  1784. result = newNodeP(nkObjectTy, p)
  1785. getTok(p)
  1786. if p.tok.tokType == tkCurlyDotLe and p.validInd:
  1787. # Deprecated since v0.20.0
  1788. parMessage(p, warnDeprecated, "type pragmas follow the type name; this form of writing pragmas is deprecated")
  1789. addSon(result, parsePragma(p))
  1790. else:
  1791. addSon(result, p.emptyNode)
  1792. if p.tok.tokType == tkOf and p.tok.indent < 0:
  1793. var a = newNodeP(nkOfInherit, p)
  1794. getTok(p)
  1795. addSon(a, parseTypeDesc(p))
  1796. addSon(result, a)
  1797. else:
  1798. addSon(result, p.emptyNode)
  1799. if p.tok.tokType == tkComment:
  1800. skipComment(p, result)
  1801. # an initial IND{>} HAS to follow:
  1802. if not realInd(p):
  1803. addSon(result, p.emptyNode)
  1804. return
  1805. addSon(result, parseObjectPart(p))
  1806. proc parseTypeClassParam(p: var TParser): PNode =
  1807. let modifier = case p.tok.tokType
  1808. of tkOut, tkVar: nkVarTy
  1809. of tkPtr: nkPtrTy
  1810. of tkRef: nkRefTy
  1811. of tkStatic: nkStaticTy
  1812. of tkType: nkTypeOfExpr
  1813. else: nkEmpty
  1814. if modifier != nkEmpty:
  1815. result = newNodeP(modifier, p)
  1816. getTok(p)
  1817. result.addSon(p.parseSymbol)
  1818. else:
  1819. result = p.parseSymbol
  1820. proc parseTypeClass(p: var TParser): PNode =
  1821. #| typeClassParam = ('var' | 'out')? symbol
  1822. #| typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
  1823. #| &IND{>} stmt
  1824. result = newNodeP(nkTypeClassTy, p)
  1825. getTok(p)
  1826. var args = newNodeP(nkArgList, p)
  1827. addSon(result, args)
  1828. addSon(args, p.parseTypeClassParam)
  1829. while p.tok.tokType == tkComma:
  1830. getTok(p)
  1831. addSon(args, p.parseTypeClassParam)
  1832. if p.tok.tokType == tkCurlyDotLe and p.validInd:
  1833. addSon(result, parsePragma(p))
  1834. else:
  1835. addSon(result, p.emptyNode)
  1836. if p.tok.tokType == tkOf and p.tok.indent < 0:
  1837. var a = newNodeP(nkOfInherit, p)
  1838. getTok(p)
  1839. # progress guaranteed
  1840. while true:
  1841. addSon(a, parseTypeDesc(p))
  1842. if p.tok.tokType != tkComma: break
  1843. getTok(p)
  1844. addSon(result, a)
  1845. else:
  1846. addSon(result, p.emptyNode)
  1847. if p.tok.tokType == tkComment:
  1848. skipComment(p, result)
  1849. # an initial IND{>} HAS to follow:
  1850. if not realInd(p):
  1851. addSon(result, p.emptyNode)
  1852. else:
  1853. addSon(result, parseStmt(p))
  1854. proc parseTypeDef(p: var TParser): PNode =
  1855. #|
  1856. #| typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux
  1857. #| indAndComment? / identVisDot genericParamList? pragma '=' optInd typeDefAux
  1858. #| indAndComment?
  1859. result = newNodeP(nkTypeDef, p)
  1860. var identifier = identVis(p, allowDot=true)
  1861. var identPragma = identifier
  1862. var pragma: PNode
  1863. var genericParam: PNode
  1864. var noPragmaYet = true
  1865. if p.tok.tokType == tkCurlyDotLe:
  1866. pragma = optPragmas(p)
  1867. identPragma = newNodeP(nkPragmaExpr, p)
  1868. addSon(identPragma, identifier)
  1869. addSon(identPragma, pragma)
  1870. noPragmaYet = false
  1871. if p.tok.tokType == tkBracketLe and p.validInd:
  1872. if not noPragmaYet:
  1873. # Deprecated since v0.20.0
  1874. parMessage(p, warnDeprecated, "pragma before generic parameter list is deprecated")
  1875. genericParam = parseGenericParamList(p)
  1876. else:
  1877. genericParam = p.emptyNode
  1878. if noPragmaYet:
  1879. pragma = optPragmas(p)
  1880. if pragma.kind != nkEmpty:
  1881. identPragma = newNodeP(nkPragmaExpr, p)
  1882. addSon(identPragma, identifier)
  1883. addSon(identPragma, pragma)
  1884. elif p.tok.tokType == tkCurlyDotLe:
  1885. parMessage(p, errGenerated, "pragma already present")
  1886. addSon(result, identPragma)
  1887. addSon(result, genericParam)
  1888. if p.tok.tokType == tkEquals:
  1889. result.info = parLineInfo(p)
  1890. getTok(p)
  1891. optInd(p, result)
  1892. addSon(result, parseTypeDefAux(p))
  1893. else:
  1894. addSon(result, p.emptyNode)
  1895. indAndComment(p, result) # special extension!
  1896. proc parseVarTuple(p: var TParser): PNode =
  1897. #| varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
  1898. result = newNodeP(nkVarTuple, p)
  1899. getTok(p) # skip '('
  1900. optInd(p, result)
  1901. # progress guaranteed
  1902. while p.tok.tokType in {tkSymbol, tkAccent}:
  1903. var a = identWithPragma(p, allowDot=true)
  1904. addSon(result, a)
  1905. if p.tok.tokType != tkComma: break
  1906. getTok(p)
  1907. skipComment(p, a)
  1908. addSon(result, p.emptyNode) # no type desc
  1909. optPar(p)
  1910. eat(p, tkParRi)
  1911. proc parseVariable(p: var TParser): PNode =
  1912. #| colonBody = colcom stmt doBlocks?
  1913. #| variable = (varTuple / identColonEquals) colonBody? indAndComment
  1914. if p.tok.tokType == tkParLe:
  1915. result = parseVarTuple(p)
  1916. eat(p, tkEquals)
  1917. optInd(p, result)
  1918. addSon(result, parseExpr(p))
  1919. else: result = parseIdentColonEquals(p, {withPragma, withDot})
  1920. result[^1] = postExprBlocks(p, result[^1])
  1921. indAndComment(p, result)
  1922. proc parseConstant(p: var TParser): PNode =
  1923. #| constant = (parseVarTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment
  1924. if p.tok.tokType == tkParLe: result = parseVarTuple(p)
  1925. else:
  1926. result = newNodeP(nkConstDef, p)
  1927. addSon(result, identWithPragma(p))
  1928. if p.tok.tokType == tkColon:
  1929. getTok(p)
  1930. optInd(p, result)
  1931. addSon(result, parseTypeDesc(p))
  1932. else:
  1933. addSon(result, p.emptyNode)
  1934. eat(p, tkEquals)
  1935. optInd(p, result)
  1936. addSon(result, parseExpr(p))
  1937. indAndComment(p, result)
  1938. proc parseBind(p: var TParser, k: TNodeKind): PNode =
  1939. #| bindStmt = 'bind' optInd qualifiedIdent ^+ comma
  1940. #| mixinStmt = 'mixin' optInd qualifiedIdent ^+ comma
  1941. result = newNodeP(k, p)
  1942. getTok(p)
  1943. optInd(p, result)
  1944. # progress guaranteed
  1945. while true:
  1946. var a = qualifiedIdent(p)
  1947. addSon(result, a)
  1948. if p.tok.tokType != tkComma: break
  1949. getTok(p)
  1950. optInd(p, a)
  1951. #expectNl(p)
  1952. proc parseStmtPragma(p: var TParser): PNode =
  1953. #| pragmaStmt = pragma (':' COMMENT? stmt)?
  1954. result = parsePragma(p)
  1955. if p.tok.tokType == tkColon and p.tok.indent < 0:
  1956. let a = result
  1957. result = newNodeI(nkPragmaBlock, a.info)
  1958. getTok(p)
  1959. skipComment(p, result)
  1960. result.add a
  1961. result.add parseStmt(p)
  1962. proc simpleStmt(p: var TParser): PNode =
  1963. #| simpleStmt = ((returnStmt | raiseStmt | yieldStmt | discardStmt | breakStmt
  1964. #| | continueStmt | pragmaStmt | importStmt | exportStmt | fromStmt
  1965. #| | includeStmt | commentStmt) / exprStmt) COMMENT?
  1966. #|
  1967. case p.tok.tokType
  1968. of tkReturn: result = parseReturnOrRaise(p, nkReturnStmt)
  1969. of tkRaise: result = parseReturnOrRaise(p, nkRaiseStmt)
  1970. of tkYield: result = parseReturnOrRaise(p, nkYieldStmt)
  1971. of tkDiscard: result = parseReturnOrRaise(p, nkDiscardStmt)
  1972. of tkBreak: result = parseReturnOrRaise(p, nkBreakStmt)
  1973. of tkContinue: result = parseReturnOrRaise(p, nkContinueStmt)
  1974. of tkCurlyDotLe: result = parseStmtPragma(p)
  1975. of tkImport: result = parseImport(p, nkImportStmt)
  1976. of tkExport: result = parseImport(p, nkExportStmt)
  1977. of tkFrom: result = parseFromStmt(p)
  1978. of tkInclude: result = parseIncludeStmt(p)
  1979. of tkComment: result = newCommentStmt(p)
  1980. else:
  1981. if isExprStart(p): result = parseExprStmt(p)
  1982. else: result = p.emptyNode
  1983. if result.kind notin {nkEmpty, nkCommentStmt}: skipComment(p, result)
  1984. proc complexOrSimpleStmt(p: var TParser): PNode =
  1985. #| complexOrSimpleStmt = (ifStmt | whenStmt | whileStmt
  1986. #| | tryStmt | forStmt
  1987. #| | blockStmt | staticStmt | deferStmt | asmStmt
  1988. #| | 'proc' routine
  1989. #| | 'method' routine
  1990. #| | 'iterator' routine
  1991. #| | 'macro' routine
  1992. #| | 'template' routine
  1993. #| | 'converter' routine
  1994. #| | 'type' section(typeDef)
  1995. #| | 'const' section(constant)
  1996. #| | ('let' | 'var' | 'using') section(variable)
  1997. #| | bindStmt | mixinStmt)
  1998. #| / simpleStmt
  1999. case p.tok.tokType
  2000. of tkIf: result = parseIfOrWhen(p, nkIfStmt)
  2001. of tkWhile: result = parseWhile(p)
  2002. of tkCase: result = parseCase(p)
  2003. of tkTry: result = parseTry(p, isExpr=false)
  2004. of tkFinally: result = parseExceptBlock(p, nkFinally)
  2005. of tkExcept: result = parseExceptBlock(p, nkExceptBranch)
  2006. of tkFor: result = parseFor(p)
  2007. of tkBlock: result = parseBlock(p)
  2008. of tkStatic: result = parseStaticOrDefer(p, nkStaticStmt)
  2009. of tkDefer: result = parseStaticOrDefer(p, nkDefer)
  2010. of tkAsm: result = parseAsm(p)
  2011. of tkProc: result = parseRoutine(p, nkProcDef)
  2012. of tkFunc: result = parseRoutine(p, nkFuncDef)
  2013. of tkMethod: result = parseRoutine(p, nkMethodDef)
  2014. of tkIterator: result = parseRoutine(p, nkIteratorDef)
  2015. of tkMacro: result = parseRoutine(p, nkMacroDef)
  2016. of tkTemplate: result = parseRoutine(p, nkTemplateDef)
  2017. of tkConverter: result = parseRoutine(p, nkConverterDef)
  2018. of tkType:
  2019. getTok(p)
  2020. if p.tok.tokType == tkParLe:
  2021. getTok(p)
  2022. result = newNodeP(nkTypeOfExpr, p)
  2023. result.addSon(primary(p, pmTypeDesc))
  2024. eat(p, tkParRi)
  2025. result = parseOperators(p, result, -1, pmNormal)
  2026. else:
  2027. result = parseSection(p, nkTypeSection, parseTypeDef)
  2028. of tkConst: result = parseSection(p, nkConstSection, parseConstant)
  2029. of tkLet: result = parseSection(p, nkLetSection, parseVariable)
  2030. of tkWhen: result = parseIfOrWhen(p, nkWhenStmt)
  2031. of tkVar: result = parseSection(p, nkVarSection, parseVariable)
  2032. of tkBind: result = parseBind(p, nkBindStmt)
  2033. of tkMixin: result = parseBind(p, nkMixinStmt)
  2034. of tkUsing: result = parseSection(p, nkUsingStmt, parseVariable)
  2035. else: result = simpleStmt(p)
  2036. proc parseStmt(p: var TParser): PNode =
  2037. #| stmt = (IND{>} complexOrSimpleStmt^+(IND{=} / ';') DED)
  2038. #| / simpleStmt ^+ ';'
  2039. if p.tok.indent > p.currInd:
  2040. result = newNodeP(nkStmtList, p)
  2041. withInd(p):
  2042. while true:
  2043. if p.tok.indent == p.currInd:
  2044. discard
  2045. elif p.tok.tokType == tkSemiColon:
  2046. getTok(p)
  2047. if p.tok.indent < 0 or p.tok.indent == p.currInd: discard
  2048. else: break
  2049. else:
  2050. if p.tok.indent > p.currInd and p.tok.tokType != tkDot:
  2051. parMessage(p, errInvalidIndentation)
  2052. break
  2053. if p.tok.tokType in {tkCurlyRi, tkParRi, tkCurlyDotRi, tkBracketRi}:
  2054. # XXX this ensures tnamedparamanonproc still compiles;
  2055. # deprecate this syntax later
  2056. break
  2057. p.hasProgress = false
  2058. var a = complexOrSimpleStmt(p)
  2059. if a.kind != nkEmpty:
  2060. addSon(result, a)
  2061. else:
  2062. # This is done to make the new 'if' expressions work better.
  2063. # XXX Eventually we need to be more strict here.
  2064. if p.tok.tokType notin {tkElse, tkElif}:
  2065. parMessage(p, errExprExpected, p.tok)
  2066. getTok(p)
  2067. else:
  2068. break
  2069. if not p.hasProgress and p.tok.tokType == tkEof: break
  2070. else:
  2071. # the case statement is only needed for better error messages:
  2072. case p.tok.tokType
  2073. of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkFunc,
  2074. tkIterator, tkMacro, tkType, tkConst, tkWhen, tkVar:
  2075. parMessage(p, "complex statement requires indentation")
  2076. result = p.emptyNode
  2077. else:
  2078. if p.inSemiStmtList > 0:
  2079. result = simpleStmt(p)
  2080. if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
  2081. else:
  2082. result = newNodeP(nkStmtList, p)
  2083. while true:
  2084. if p.tok.indent >= 0:
  2085. parMessage(p, errInvalidIndentation)
  2086. p.hasProgress = false
  2087. let a = simpleStmt(p)
  2088. let err = not p.hasProgress
  2089. if a.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
  2090. result.add(a)
  2091. if p.tok.tokType != tkSemiColon: break
  2092. getTok(p)
  2093. if err and p.tok.tokType == tkEof: break
  2094. proc parseAll(p: var TParser): PNode =
  2095. ## Parses the rest of the input stream held by the parser into a PNode.
  2096. result = newNodeP(nkStmtList, p)
  2097. while p.tok.tokType != tkEof:
  2098. p.hasProgress = false
  2099. var a = complexOrSimpleStmt(p)
  2100. if a.kind != nkEmpty and p.hasProgress:
  2101. addSon(result, a)
  2102. else:
  2103. parMessage(p, errExprExpected, p.tok)
  2104. # bugfix: consume a token here to prevent an endless loop:
  2105. getTok(p)
  2106. if p.tok.indent != 0:
  2107. parMessage(p, errInvalidIndentation)
  2108. proc parseTopLevelStmt(p: var TParser): PNode =
  2109. ## Implements an iterator which, when called repeatedly, returns the next
  2110. ## top-level statement or emptyNode if end of stream.
  2111. result = p.emptyNode
  2112. # progress guaranteed
  2113. while true:
  2114. if p.tok.indent != 0:
  2115. if p.firstTok and p.tok.indent < 0: discard
  2116. elif p.tok.tokType != tkSemiColon:
  2117. # special casing for better error messages:
  2118. if p.tok.tokType == tkOpr and p.tok.ident.s == "*":
  2119. parMessage(p, errGenerated,
  2120. "invalid indentation; an export marker '*' follows the declared identifier")
  2121. else:
  2122. parMessage(p, errInvalidIndentation)
  2123. p.firstTok = false
  2124. case p.tok.tokType
  2125. of tkSemiColon:
  2126. getTok(p)
  2127. if p.tok.indent <= 0: discard
  2128. else: parMessage(p, errInvalidIndentation)
  2129. p.firstTok = true
  2130. of tkEof: break
  2131. else:
  2132. result = complexOrSimpleStmt(p)
  2133. if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
  2134. break
  2135. proc parseString*(s: string; cache: IdentCache; config: ConfigRef;
  2136. filename: string = ""; line: int = 0;
  2137. errorHandler: TErrorHandler = nil): PNode =
  2138. ## Parses a string into an AST, returning the top node.
  2139. ## `filename` and `line`, although optional, provide info so that the
  2140. ## compiler can generate correct error messages referring to the original
  2141. ## source.
  2142. var stream = llStreamOpen(s)
  2143. stream.lineOffset = line
  2144. var parser: TParser
  2145. parser.lex.errorHandler = errorHandler
  2146. openParser(parser, AbsoluteFile filename, stream, cache, config)
  2147. result = parser.parseAll
  2148. closeParser(parser)