parser.nim 73 KB

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