parser.nim 84 KB

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