mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 22:10:33 +00:00
@@ -1532,6 +1532,55 @@ proc parseUntilNewline(p: var RstParser, father: PRstNode) =
|
||||
of tkEof, tkIndent: break
|
||||
|
||||
proc parseSection(p: var RstParser, result: PRstNode) {.gcsafe.}
|
||||
|
||||
proc tokenAfterNewline(p: RstParser, start: int): int =
|
||||
result = start
|
||||
while true:
|
||||
case p.tok[result].kind
|
||||
of tkEof:
|
||||
break
|
||||
of tkIndent:
|
||||
inc result
|
||||
break
|
||||
else: inc result
|
||||
|
||||
proc tokenAfterNewline(p: RstParser): int {.inline.} =
|
||||
result = tokenAfterNewline(p, p.idx)
|
||||
|
||||
proc getWrappableIndent(p: RstParser): int =
|
||||
## Gets baseline indentation for bodies of field lists and directives.
|
||||
## Handles situations like this (with possible de-indent in [case.3])::
|
||||
##
|
||||
## :field: definition [case.1]
|
||||
##
|
||||
## currInd currentTok(p).col
|
||||
## | |
|
||||
## v v
|
||||
##
|
||||
## .. Note:: defItem: [case.2]
|
||||
## definition
|
||||
##
|
||||
## ^
|
||||
## |
|
||||
## nextIndent
|
||||
##
|
||||
## .. Note:: - point1 [case.3]
|
||||
## - point 2
|
||||
##
|
||||
## ^
|
||||
## |
|
||||
## nextIndent
|
||||
if currentTok(p).kind == tkIndent:
|
||||
result = currentTok(p).ival
|
||||
else:
|
||||
var nextIndent = p.tok[tokenAfterNewline(p)-1].ival
|
||||
if nextIndent <= currInd(p): # parse only this line [case.1]
|
||||
result = currentTok(p).col
|
||||
elif nextIndent >= currentTok(p).col: # may be a definition list [case.2]
|
||||
result = currentTok(p).col
|
||||
else:
|
||||
result = nextIndent # [case.3]
|
||||
|
||||
proc parseField(p: var RstParser): PRstNode =
|
||||
## Returns a parsed rnField node.
|
||||
##
|
||||
@@ -1541,13 +1590,12 @@ proc parseField(p: var RstParser): PRstNode =
|
||||
var fieldname = newRstNode(rnFieldName)
|
||||
parseUntil(p, fieldname, ":", false)
|
||||
var fieldbody = newRstNode(rnFieldBody)
|
||||
if currentTok(p).kind != tkIndent: parseLine(p, fieldbody)
|
||||
if currentTok(p).kind == tkIndent:
|
||||
var indent = currentTok(p).ival
|
||||
if indent > col:
|
||||
pushInd(p, indent)
|
||||
parseSection(p, fieldbody)
|
||||
popInd(p)
|
||||
if currentTok(p).kind == tkWhite: inc p.idx
|
||||
let indent = getWrappableIndent(p)
|
||||
if indent > col:
|
||||
pushInd(p, indent)
|
||||
parseSection(p, fieldbody)
|
||||
popInd(p)
|
||||
result.add(fieldname)
|
||||
result.add(fieldbody)
|
||||
|
||||
@@ -1652,20 +1700,6 @@ proc countTitles(p: var RstParser, n: PRstNode) =
|
||||
if p.s.hTitleCnt >= 2:
|
||||
break
|
||||
|
||||
proc tokenAfterNewline(p: RstParser, start: int): int =
|
||||
result = start
|
||||
while true:
|
||||
case p.tok[result].kind
|
||||
of tkEof:
|
||||
break
|
||||
of tkIndent:
|
||||
inc result
|
||||
break
|
||||
else: inc result
|
||||
|
||||
proc tokenAfterNewline(p: RstParser): int {.inline.} =
|
||||
result = tokenAfterNewline(p, p.idx)
|
||||
|
||||
proc isAdornmentHeadline(p: RstParser, adornmentIdx: int): bool =
|
||||
## check that underline/overline length is enough for the heading.
|
||||
## No support for Unicode.
|
||||
@@ -1752,7 +1786,7 @@ proc whichSection(p: RstParser): RstNodeKind =
|
||||
return rnCodeBlock
|
||||
elif currentTok(p).symbol == "::":
|
||||
return rnLiteralBlock
|
||||
elif currentTok(p).symbol == ".." and predNL(p) and
|
||||
elif currentTok(p).symbol == ".." and
|
||||
nextTok(p).kind in {tkWhite, tkIndent}:
|
||||
return rnDirective
|
||||
case currentTok(p).kind
|
||||
@@ -1780,10 +1814,9 @@ proc whichSection(p: RstParser): RstNodeKind =
|
||||
elif match(p, tokenAfterNewline(p), "aI") and
|
||||
isAdornmentHeadline(p, tokenAfterNewline(p)):
|
||||
result = rnHeadline
|
||||
elif predNL(p) and
|
||||
currentTok(p).symbol in ["+", "*", "-"] and nextTok(p).kind == tkWhite:
|
||||
elif currentTok(p).symbol in ["+", "*", "-"] and nextTok(p).kind == tkWhite:
|
||||
result = rnBulletList
|
||||
elif match(p, p.idx, ":w:E") and predNL(p):
|
||||
elif match(p, p.idx, ":w:E"):
|
||||
# (currentTok(p).symbol == ":")
|
||||
result = rnFieldList
|
||||
elif match(p, p.idx, "(e) ") or match(p, p.idx, "e) ") or
|
||||
@@ -2350,9 +2383,11 @@ proc parseDirective(p: var RstParser, k: RstNodeKind, flags: DirFlags): PRstNode
|
||||
parseLine(p, args)
|
||||
result.add(args)
|
||||
if hasOptions in flags:
|
||||
if currentTok(p).kind == tkIndent and currentTok(p).ival >= 3 and
|
||||
if currentTok(p).kind == tkIndent and currentTok(p).ival > currInd(p) and
|
||||
nextTok(p).symbol == ":":
|
||||
pushInd(p, currentTok(p).ival)
|
||||
options = parseFields(p)
|
||||
popInd(p)
|
||||
result.add(options)
|
||||
|
||||
proc indFollows(p: RstParser): bool =
|
||||
@@ -2363,11 +2398,9 @@ proc parseBlockContent(p: var RstParser, father: var PRstNode,
|
||||
## parse the final content part of explicit markup blocks (directives,
|
||||
## footnotes, etc). Returns true if succeeded.
|
||||
if currentTok(p).kind != tkIndent or indFollows(p):
|
||||
var nextIndent = p.tok[tokenAfterNewline(p)-1].ival
|
||||
if nextIndent <= currInd(p): # parse only this line
|
||||
nextIndent = currentTok(p).col
|
||||
pushInd(p, nextIndent)
|
||||
var content = contentParser(p)
|
||||
let blockIndent = getWrappableIndent(p)
|
||||
pushInd(p, blockIndent)
|
||||
let content = contentParser(p)
|
||||
popInd(p)
|
||||
father.add content
|
||||
result = true
|
||||
|
||||
@@ -350,7 +350,7 @@ proc renderRstToJson*(node: PRstNode): string =
|
||||
proc renderRstToStr*(node: PRstNode, indent=0): string =
|
||||
## Writes the parsed RST `node` into a compact string
|
||||
## representation in the format (one line per every sub-node):
|
||||
## ``indent - kind - text - level - order - anchor (if non-zero)``
|
||||
## ``indent - kind - [text|level|order|adType] - anchor (if non-zero)``
|
||||
## (suitable for debugging of RST parsing).
|
||||
if node == nil:
|
||||
result.add " ".repeat(indent) & "[nil]\n"
|
||||
@@ -358,21 +358,23 @@ proc renderRstToStr*(node: PRstNode, indent=0): string =
|
||||
result.add " ".repeat(indent) & $node.kind
|
||||
case node.kind
|
||||
of rnLeaf, rnSmiley:
|
||||
result.add (if node.text == "": "" else: "\t'" & node.text & "'")
|
||||
result.add (if node.text == "": "" else: " '" & node.text & "'")
|
||||
of rnEnumList:
|
||||
result.add "\tlabelFmt=" & node.labelFmt
|
||||
result.add " labelFmt=" & node.labelFmt
|
||||
of rnLineBlockItem:
|
||||
var txt: string
|
||||
if node.lineIndent == "\n": txt = "\t(blank line)"
|
||||
else: txt = "\tlineIndent=" & $node.lineIndent.len
|
||||
if node.lineIndent == "\n": txt = " (blank line)"
|
||||
else: txt = " lineIndent=" & $node.lineIndent.len
|
||||
result.add txt
|
||||
of rnAdmonition:
|
||||
result.add " adType=" & node.adType
|
||||
of rnHeadline, rnOverline, rnMarkdownHeadline:
|
||||
result.add "\tlevel=" & $node.level
|
||||
result.add " level=" & $node.level
|
||||
of rnFootnote, rnCitation, rnFootnoteRef, rnOptionListItem:
|
||||
result.add (if node.order == 0: "" else: "\torder=" & $node.order)
|
||||
result.add (if node.order == 0: "" else: " order=" & $node.order)
|
||||
else:
|
||||
discard
|
||||
result.add (if node.anchor == "": "" else: "\tanchor='" & node.anchor & "'")
|
||||
result.add (if node.anchor == "": "" else: " anchor='" & node.anchor & "'")
|
||||
result.add "\n"
|
||||
for son in node.sons:
|
||||
result.add renderRstToStr(son, indent=indent+2)
|
||||
|
||||
Reference in New Issue
Block a user