parser.nim 69 KB

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