parser.nim 75 KB

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