parser.nim 79 KB

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