parser.nim 81 KB

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