parser.nim 83 KB

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