From 032da90ed1eda03b837145d711b756cb897c099e Mon Sep 17 00:00:00 2001 From: metagn Date: Fri, 18 Apr 2025 06:34:21 +0300 Subject: [PATCH] implement parser for new case objects (#24885) refs https://github.com/nim-lang/RFCs/issues/559 Parses as an `nkIdentDefs` with an `nkEmpty` name. Pragma is allowed, can remove this if necessary. Fine to close and postpone for later --- compiler/parser.nim | 22 ++++++-- doc/grammar.txt | 2 +- tests/parser/tparsenewcaseobject.nim | 81 ++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 tests/parser/tparsenewcaseobject.nim diff --git a/compiler/parser.nim b/compiler/parser.nim index 03c3ac2648..4af56f2103 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -2110,12 +2110,28 @@ proc parseObjectCase(p: var Parser): PNode = #| objectBranches = objectBranch (IND{=} objectBranch)* #| (IND{=} 'elif' expr colcom objectPart)* #| (IND{=} 'else' colcom objectPart)? - #| objectCase = 'case' declColonEquals ':'? COMMENT? + #| objectCase = 'case' (declColonEquals / pragma)? ':'? COMMENT? #| (IND{>} objectBranches DED #| | IND{=} objectBranches) result = newNodeP(nkRecCase, p) - getTokNoInd(p) - var a = parseIdentColonEquals(p, {withPragma}) + getTok(p) + if p.tok.tokType != tkOf: + # of case will be handled later + if p.tok.indent >= 0: parMessage(p, errInvalidIndentation) + var a: PNode + if p.tok.tokType in {tkSymbol, tkAccent}: + a = parseIdentColonEquals(p, {withPragma}) + else: + a = newNodeP(nkIdentDefs, p) + if p.tok.tokType == tkCurlyDotLe: + var prag = newNodeP(nkPragmaExpr, p) + prag.add(p.emptyNode) + prag.add(parsePragma(p)) + a.add(prag) + else: + a.add(p.emptyNode) + a.add(p.emptyNode) + a.add(p.emptyNode) result.add(a) if p.tok.tokType == tkColon: getTok(p) flexComment(p, result) diff --git a/doc/grammar.txt b/doc/grammar.txt index 51b3e0053c..7d430019b1 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -181,7 +181,7 @@ objectBranch = 'of' exprList colcom objectPart objectBranches = objectBranch (IND{=} objectBranch)* (IND{=} 'elif' expr colcom objectPart)* (IND{=} 'else' colcom objectPart)? -objectCase = 'case' declColonEquals ':'? COMMENT? +objectCase = 'case' (declColonEquals / pragma)? ':'? COMMENT? (IND{>} objectBranches DED | IND{=} objectBranches) objectPart = IND{>} objectPart^+IND{=} DED diff --git a/tests/parser/tparsenewcaseobject.nim b/tests/parser/tparsenewcaseobject.nim new file mode 100644 index 0000000000..884b85dff7 --- /dev/null +++ b/tests/parser/tparsenewcaseobject.nim @@ -0,0 +1,81 @@ +discard """ + nimout: ''' +StmtList + TypeSection + TypeDef + Ident "Node" + Empty + RefTy + ObjectTy + Empty + Empty + RecList + RecCase + IdentDefs + Empty + Empty + Empty + OfBranch + Ident "AddOpr" + Ident "SubOpr" + Ident "MulOpr" + Ident "DivOpr" + RecList + IdentDefs + Ident "a" + Ident "b" + Ident "Node" + Empty + OfBranch + Ident "Value" + RecList + NilLit + IdentDefs + Ident "info" + Ident "LineInfo" + Empty + RecCase + IdentDefs + PragmaExpr + Empty + Pragma + ExprColonExpr + Ident "size" + IntLit 1 + Empty + Empty + OfBranch + Ident "Foo" + NilLit + +type + Node = ref object + case + of AddOpr, SubOpr, MulOpr, DivOpr: + a, b: Node + of Value: + nil + info: LineInfo + case {.size: 1.} + of Foo: + nil +''' +""" + +import std/macros + +macro foo(x: untyped) = + echo x.treeRepr + echo x.repr + +foo: + type + Node = ref object + case + of AddOpr, SubOpr, MulOpr, DivOpr: + a, b: Node + of Value: + discard + info: LineInfo + case {.size: 1.} + of Foo: discard