From d9e28aac8ec35f7b3cd00d42a8515c04e72aafed Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 8 Jun 2026 11:32:04 +0200 Subject: [PATCH] parser: `concept of` (#25878) Co-authored-by: Gerke Max Preussner --- compiler/parser.nim | 12 ++++++++---- doc/grammar.txt | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/parser.nim b/compiler/parser.nim index 934db857b2..32bf4b3d52 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -2241,14 +2241,17 @@ proc parseTypeClassParam(p: var Parser): PNode = proc parseTypeClass(p: var Parser): PNode = #| conceptParam = ('var' | 'out' | 'ptr' | 'ref' | 'static' | 'type')? symbol - #| conceptDecl = 'concept' conceptParam ^* ',' (pragma)? ('of' typeDesc ^* ',')? + #| conceptDecl = 'concept' (conceptParam ^* ',' (pragma)?)? ('of' typeDesc ^* ',')? #| &IND{>} stmt result = newNodeP(nkTypeClassTy, p) getTok(p) if p.tok.tokType == tkComment: skipComment(p, result) - if p.tok.indent < 0: + if p.tok.tokType == tkOf and p.tok.indent < 0: + # new-styled `concept of A, B` on the same line as `concept` + result.add(p.emptyNode) + elif p.tok.indent < 0: var args = newNodeP(nkArgList, p) result.add(args) args.add(p.parseTypeClassParam) @@ -2274,9 +2277,10 @@ proc parseTypeClass(p: var Parser): PNode = result.add(p.emptyNode) if p.tok.tokType == tkComment: skipComment(p, result) - # an initial IND{>} HAS to follow: + # an initial IND{>} HAS to follow, unless this concept inherits requirements: if not realInd(p): - if result.isNewStyleConcept: + let hasParents = result[2].kind != nkEmpty + if result.isNewStyleConcept and not hasParents: parMessage(p, "routine expected, but found '$1' (empty new-styled concepts are not allowed)", p.tok) result.add(p.emptyNode) else: diff --git a/doc/grammar.txt b/doc/grammar.txt index 7d430019b1..a25ace34d6 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -188,7 +188,7 @@ objectPart = IND{>} objectPart^+IND{=} DED / objectWhen / objectCase / 'nil' / 'discard' / declColonEquals objectDecl = 'object' ('of' typeDesc)? COMMENT? objectPart conceptParam = ('var' | 'out' | 'ptr' | 'ref' | 'static' | 'type')? symbol -conceptDecl = 'concept' conceptParam ^* ',' (pragma)? ('of' typeDesc ^* ',')? +conceptDecl = 'concept' (conceptParam ^* ',' (pragma)?)? ('of' typeDesc ^* ',')? &IND{>} stmt typeDef = identVisDot genericParamList? pragma '=' optInd typeDefValue indAndComment?