parser.nim 83 KB

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