parser.nim 80 KB

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