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
@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
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
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”