parser.nim 75 KB

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