parser.nim 73 KB

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