parser.nim 68 KB

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