# Can this Shift/Reduce conflict with nested + be resolved

**URL:** <https://discuss.codemirror.net/t/can-this-shift-reduce-conflict-with-nested-be-resolved/9391>\
**Category:** Lezer\
**Created:** [August 15, 2025, 3:40pm UTC](https://discuss.codemirror.net/t/can-this-shift-reduce-conflict-with-nested-be-resolved/9391 "2025-08-15T15:40:37Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![kwibus](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/kwibus/32/5222_2.png) [@kwibus](https://discuss.codemirror.net/u/kwibus)\
**Post date:** [August 15, 2025, 3:40pm UTC](https://discuss.codemirror.net/t/can-this-shift-reduce-conflict-with-nested-be-resolved/9391/1 "2025-08-15T15:40:37Z")

</div>

I am working on a parser for rst. And there have trouble getting Text inside InlineMarkup.  
But to keep the question simple. This most simplified representative syntax

```lezer
@top Document { InlineMarkup "\n" }

InlineMarkup { (Text | "Bold")+}

Text { "T"+ }

```

This syntax has shift reduce conflict. Because with input of “TT” it does not know if It is: InlineMarkup(Text,Text), or InlineMarkup(Text(“TT”))

> **Error messages**
>
> ```auto
> shift/reduce conflict between
> "T"+ -> · "T"
> and
> Text -> "T"+
> With input:
> "T"+ · "T" …
> The reduction of Text is allowed before "T" because of this rule:
> (Text | "Bold")+ -> (Text | "Bold")+ · (Text | "Bold")+
> Shared origin: (Text | "Bold")+ -> · Text
> via Text -> · "T"+
> via "T"+ -> "T"+ · "T"+
> "T"+ -> · "T"
> 
> ```

I could Resolve this by remove `+` inside `Text`

```lezer
InlineMarkup { (Text { "T" } | "Bold")+}

```

But i dislike this Solution: This would lead to a lot of `Text` Nodes inside `InlineMarkup`.  
And it would be nice if consecutive text ("T"s) could be grouped under 1 node.

**So my question is:** Is there a way to tell the parser generator. That it should delay Reducing the inner `"T"+` as late as possible.

> **My current full syntax**
>
> @external tokens indentationTokens from “./tokens.js” { indent, dedent }  
> @external tokens newlineTokens from “./tokens.js” { newline, blankline }  
> @external tokens headingLookahead from “./tokens.js” {  
> startSection1, startSection2, startSection3, startSection4, startSection5, startSection6  
> }
> 
> @external tokens adormentTokens from “./tokens.js” {  
> Adornment  
> }
> 
> @context trackBoth from “./tokens.js”
> 
> @precedence {directiveBlock, eagerBlanklines, directiveSimple, markupClose, markupOpen }
> 
> @top Document { blankline\* bodyElement\* Section1\* eof?}
> 
> bodyElement {  
> BlockQuote |  
> LiteralBlock |  
> BulletList |  
> DefinitionList |  
> Directive |  
> Paragraph  
> // Transition  
> }
> 
> Section1 { startSection1 Heading1 blankline\* bodyElement\* Section2\* }  
> Section2 { startSection2 Heading2 blankline\* bodyElement\* Section3\* }  
> Section3 { startSection3 Heading3 blankline\* bodyElement\* Section4\* }  
> Section4 { startSection4 Heading4 blankline\* bodyElement\* Section5\* }  
> Section5 { startSection5 Heading5 blankline\* bodyElement\* Section6\* }  
> Section6 { startSection6 Heading6 blankline\* bodyElement\* }
> 
> Heading1 { (Adornment newline)? Title Adornment (newline | eof)}  
> Heading2 { (Adornment newline)? Title Adornment (newline | eof)}  
> Heading3 { (Adornment newline)? Title Adornment (newline | eof)}  
> Heading4 { (Adornment newline)? Title Adornment (newline | eof)}  
> Heading5 { (Adornment newline)? Title Adornment (newline | eof)}  
> Heading6 { (Adornment newline)? Title Adornment (newline | eof)}
> 
> Title {line}
> 
> // Transition{ Adornment blankline}
> 
> // TODO  
> BlockQuote {indent bodyElement+ blockEnd }
> 
> LiteralBlock { “::” newline blanklines indent (LiteralLine | blanklines )+ blockEnd }
> 
> BulletList { BulletListItem+ paragraphEnd}  
> BulletListItem { BulletListMarker ListContent }
> 
> DefinitionList { DefinitionListItem+ paragraphEnd }  
> DefinitionListItem {  
> Term{ inlineMarkup newline}  
> Definition{ indent bodyElement+ blockEnd }  
> }
> 
> ListContent { inlineMarkup (newline | eof) (indent bodyElement+ blockEnd)? }
> 
> Directive { directiveMarker DirectiveArgument? newline blanklines (!directiveBlock DirectiveContent | !directiveSimple “”) }
> 
> directiveMarker {“..” whitespace+ DirectiveType{word} “::” }  
> DirectiveArgument{ Text }  
> DirectiveContent { indent bodyElement+ blockEnd }
> 
> Paragraph { inlineMarkup (newline inlineMarkup )\* newline? paragraphEnd }
> 
> line { inlineMarkup newline }
> 
> LiteralLine { LiteralText (newline | eof) }
> 
> blockEnd { dedent | eof }
> 
> paragraphEnd { blanklines | eof | LiteralBlock }
> 
> inlineMarkup {  
> (  
> Text |  
> Strong |  
> Emphasis |  
> InterpretedText |  
> Literal |  
> SubstitutionReference  
> )+  
> }
> 
> Strong { strongDelim Text strongDelim }  
> Emphasis { emphasisDelim Text emphasisDelim }  
> InterpretedText { interpretedDelim Text interpretedDelim }  
> Literal{literalDelim LiteralText literalDelim }  
> SubstitutionReference { substituteDelim Text substituteDelim }
> 
> LiteralText { (text | specialChar )+ }
> 
> Text { ( text | specialChar | Escape ) } // # TODO would like to add + here
> 
> blanklines { !eagerBlanklines blankline+ }
> 
> @tokens {  
> BulletListMarker { (“-” | “_" | “+”) " " }  
> emphasisDelim{ "_” }  
> strongDelim{ “\*\*” }  
> interpretedDelim {"`"} literalDelim{"``"} substituteDelim{"|"} Escape { "\\" _ } specialChar { $[:*|`\] }  
> text { ![:_`|\\n]+ }  
> // alphanumerics plus isolated internal hyphens, underscores, plus signs, colons, and periods; no whitespace  
> whitespace {@whitespace}  
> alphanumeric { (@asciiLetter | @digit)+ }  
> word { alphanumeric ($[-\_+|:,] alphanumeric)_ }  
> eof { @eof }
> 
> @precedence { strongDelim,emphasisDelim, specialChar }  
> @precedence { literalDelim, interpretedDelim, specialChar }  
> @precedence { substituteDelim , specialChar }  
> @precedence { Escape, BulletListMarker, “..”, “::”, text}  
> }  
> @detectDelim  
> @external propSource rstHighlighting from “./highlight.js”

---

<div class="post-metadata">

**Author:** ![marijn](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/marijn/32/136_2.png) [@marijn](https://discuss.codemirror.net/u/marijn)\
**Post date:** [August 15, 2025, 6:30pm UTC](https://discuss.codemirror.net/t/can-this-shift-reduce-conflict-with-nested-be-resolved/9391/2 "2025-08-15T18:30:15Z")

</div>

I think that just defining a preference (named, say, `@precedence { text }`) and using it (`(!text "T")+`) in the `Text` rule should do the trick.

---

<div class="post-metadata">

**Author:** ![kwibus](https://discuss.codemirror.net/user_avatar/discuss.codemirror.net/kwibus/32/5222_2.png) [@kwibus](https://discuss.codemirror.net/u/kwibus)\
**Post date:** [August 15, 2025, 7:20pm UTC](https://discuss.codemirror.net/t/can-this-shift-reduce-conflict-with-nested-be-resolved/9391/3 "2025-08-15T19:20:37Z")

</div>

Thank, That worked.  
I thought i tried that already, probably made a mistake then. and ruled that option out.
