parser.nim 78 KB

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