parser.nim 79 KB

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