diff options
author | Araq <rumpf_a@web.de> | 2012-05-06 01:16:36 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-05-06 01:16:36 +0200 |
commit | c323ec0155cc426e604e0c53a6baf00b17e439d7 (patch) | |
tree | 1f585f7bd06fd7b25b12e1d7329a33d093abaa4f | |
parent | c3770ebd061649717d50bc74f718427af5be0ed5 (diff) | |
download | Nim-c323ec0155cc426e604e0c53a6baf00b17e439d7.tar.gz |
added system.getStackTrace; docgen refactoring (incomplete)
-rwxr-xr-x | compiler/docgen.nim | 320 | ||||
-rwxr-xr-x | compiler/lexer.nim | 2 | ||||
-rwxr-xr-x | compiler/msgs.nim | 2 | ||||
-rwxr-xr-x | compiler/nimrod.cfg | 2 | ||||
-rwxr-xr-x | compiler/nimrod.ini | 12 | ||||
-rwxr-xr-x | compiler/options.nim | 2 | ||||
-rwxr-xr-x | lib/system.nim | 3 | ||||
-rwxr-xr-x | lib/system/excpt.nim | 7 | ||||
-rwxr-xr-x | packages/docutils/highlite.nim (renamed from compiler/highlite.nim) | 68 | ||||
-rwxr-xr-x | packages/docutils/rst.nim (renamed from compiler/rst.nim) | 457 | ||||
-rw-r--r-- | packages/docutils/rstast.nim | 288 | ||||
-rw-r--r-- | packages/docutils/rstgen.nim | 87 | ||||
-rwxr-xr-x | web/news.txt | 3 |
13 files changed, 744 insertions, 509 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 2bcb397c3..50abcfc4e 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -13,11 +13,14 @@ import ast, astalgo, strutils, hashes, options, nversion, msgs, os, ropes, idents, - wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite, importer + wordrecg, syntaxes, renderer, lexer, rstast, rst, rstgen, times, highlite, + importer proc CommandDoc*() proc CommandRst2Html*() proc CommandRst2TeX*() + +#proc CommandBuildIndex*() # implementation type @@ -29,9 +32,9 @@ type TMetaEnum = enum metaNone, metaTitle, metaSubtitle, metaAuthor, metaVersion TDocumentor {.final.} = object # contains a module's documentation + target: TOutputTarget options: TRstParseOptions filename*: string # filename of the source file; without extension - basedir*: string # base directory (where to put the documentation) modDesc*: PRope # module description id*: int # for generating IDs splitAfter*: int # split too long entries in the TOC @@ -40,13 +43,10 @@ type toc*, section*: TSections indexFile*, theIndex*: PRstNode indexValFilename*: string - indent*, verbatim*: int # for code generation meta*: array[TMetaEnum, PRope] PDoc = ref TDocumentor -var splitter: string = "<wbr />" - proc findIndexNode(n: PRstNode): PRstNode = if n == nil: result = nil @@ -59,10 +59,31 @@ proc findIndexNode(n: PRstNode): PRstNode = result = result.sons[0] else: result = nil - for i in countup(0, rsonsLen(n) - 1): + for i in countup(0, len(n) - 1): result = findIndexNode(n.sons[i]) if result != nil: return +proc compilerMsgHandler(filename: string, line, col: int, + msgKind: rst.TMsgKind, arg: string) {.procvar.} = + # translate msg kind: + var k: msgs.TMsgKind + case msgKind + of meCannotOpenFile: k = errCannotOpenFile + of meExpected: k = errXExpected + of meGridTableNotImplemented: k = errGridTableNotImplemented + of meNewSectionExpected: k = errNewSectionExpected + of meGeneralParseError: k = errGeneralParseError + of meInvalidDirective: k = errInvalidDirectiveX + of mwRedefinitionOfLabel: k = warnRedefinitionOfLabel + of mwUnknownSubstitution: k = warnUnknownSubstitutionX + GlobalError(newLineInfo(filename, line, col), k, arg) + +proc parseRst(text, filename: string, + line, column: int, hasToc: var bool, + rstOptions: TRstParseOptions): PRstNode = + result = rstParse(text, filename, line, column, hasToc, rstOptions, + options.FindFile, compilerMsgHandler) + proc initIndexFile(d: PDoc) = var h: PRstNode @@ -71,7 +92,7 @@ proc initIndexFile(d: PDoc) = gIndexFile = addFileExt(gIndexFile, "txt") d.indexValFilename = changeFileExt(extractFilename(d.filename), HtmlExt) if ExistsFile(gIndexFile): - d.indexFile = rstParse(readFile(gIndexFile), gIndexFile, 0, 1, + d.indexFile = parseRst(readFile(gIndexFile), gIndexFile, 0, 1, dummyHasToc, {roSupportRawDirective}) d.theIndex = findIndexNode(d.indexFile) if (d.theIndex == nil) or (d.theIndex.kind != rnDefList): @@ -81,17 +102,19 @@ proc initIndexFile(d: PDoc) = d.indexFile = newRstNode(rnInner) h = newRstNode(rnOverline) h.level = 1 - addSon(h, newRstNode(rnLeaf, "Index")) - addSon(d.indexFile, h) + add(h, newRstNode(rnLeaf, "Index")) + add(d.indexFile, h) h = newRstNode(rnIndex) - addSon(h, nil) # no argument - addSon(h, nil) # no options + add(h, nil) # no argument + add(h, nil) # no options d.theIndex = newRstNode(rnDefList) - addSon(h, d.theIndex) - addSon(d.indexFile, h) + add(h, d.theIndex) + add(d.indexFile, h) proc newDocumentor(filename: string): PDoc = new(result) + if gCmd != cmdRst2Tex: result.target = outHtml + else: result.target = outLatex result.tocPart = @[] result.filename = filename result.id = 100 @@ -159,72 +182,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openarray[string], if (frmt[i] != '$'): inc(i) else: break if i - 1 >= start: app(result, substr(frmt, start, i - 1)) - -proc addXmlChar(dest: var string, c: Char) = - case c - of '&': add(dest, "&") - of '<': add(dest, "<") - of '>': add(dest, ">") - of '\"': add(dest, """) - else: add(dest, c) - -proc addRtfChar(dest: var string, c: Char) = - case c - of '{': add(dest, "\\{") - of '}': add(dest, "\\}") - of '\\': add(dest, "\\\\") - else: add(dest, c) - -proc addTexChar(dest: var string, c: Char) = - case c - of '_': add(dest, "\\_") - of '{': add(dest, "\\symbol{123}") - of '}': add(dest, "\\symbol{125}") - of '[': add(dest, "\\symbol{91}") - of ']': add(dest, "\\symbol{93}") - of '\\': add(dest, "\\symbol{92}") - of '$': add(dest, "\\$") - of '&': add(dest, "\\&") - of '#': add(dest, "\\#") - of '%': add(dest, "\\%") - of '~': add(dest, "\\symbol{126}") - of '@': add(dest, "\\symbol{64}") - of '^': add(dest, "\\symbol{94}") - of '`': add(dest, "\\symbol{96}") - else: add(dest, c) - -proc escChar(dest: var string, c: Char) = - if gCmd != cmdRst2Tex: addXmlChar(dest, c) - else: addTexChar(dest, c) - -proc nextSplitPoint(s: string, start: int): int = - result = start - while result < len(s) + 0: - case s[result] - of '_': return - of 'a'..'z': - if result + 1 < len(s) + 0: - if s[result + 1] in {'A'..'Z'}: return - else: nil - inc(result) - dec(result) # last valid index - -proc esc(s: string, splitAfter: int = - 1): string = - result = "" - if splitAfter >= 0: - var partLen = 0 - var j = 0 - while j < len(s): - var k = nextSplitPoint(s, j) - if (splitter != " ") or (partLen + k - j + 1 > splitAfter): - partLen = 0 - add(result, splitter) - for i in countup(j, k): escChar(result, s[i]) - inc(partLen, k - j + 1) - j = k + 1 - else: - for i in countup(0, len(s) + 0 - 1): escChar(result, s[i]) - + proc disp(xml, tex: string): string = if gCmd != cmdRst2Tex: result = xml else: result = tex @@ -241,17 +199,17 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope proc renderAux(d: PDoc, n: PRstNode, outer: string = "$1"): PRope = result = nil - for i in countup(0, rsonsLen(n) - 1): app(result, renderRstToOut(d, n.sons[i])) + for i in countup(0, len(n) - 1): app(result, renderRstToOut(d, n.sons[i])) result = ropef(outer, [result]) proc setIndexForSourceTerm(d: PDoc, name: PRstNode, id: int) = if d.theIndex == nil: return var h = newRstNode(rnHyperlink) var a = newRstNode(rnLeaf, d.indexValFilename & disp("#", "") & $id) - addSon(h, a) - addSon(h, a) + add(h, a) + add(h, a) a = newRstNode(rnIdx) - addSon(a, name) + add(a, name) setIndexPair(d.theIndex, a, h) proc renderIndexTerm(d: PDoc, n: PRstNode): PRope = @@ -260,14 +218,14 @@ proc renderIndexTerm(d: PDoc, n: PRstNode): PRope = [toRope(d.id), renderAux(d, n)]) var h = newRstNode(rnHyperlink) var a = newRstNode(rnLeaf, d.indexValFilename & disp("#", "") & $d.id) - addSon(h, a) - addSon(h, a) + add(h, a) + add(h, a) setIndexPair(d.theIndex, n, h) proc genComment(d: PDoc, n: PNode): PRope = var dummyHasToc: bool if n.comment != nil and startsWith(n.comment, "##"): - result = renderRstToOut(d, rstParse(n.comment, toFilename(n.info), + result = renderRstToOut(d, parseRst(n.comment, toFilename(n.info), toLineNumber(n.info), toColumn(n.info), dummyHasToc, d.options + {roSkipPounds})) @@ -294,16 +252,16 @@ proc isVisible(n: PNode): bool = elif n.kind == nkPragmaExpr: result = isVisible(n.sons[0]) -proc getName(n: PNode, splitAfter: int = - 1): string = +proc getName(d: PDoc, n: PNode, splitAfter: int = - 1): string = case n.kind - of nkPostfix: result = getName(n.sons[1], splitAfter) - of nkPragmaExpr: result = getName(n.sons[0], splitAfter) - of nkSym: result = esc(n.sym.name.s, splitAfter) - of nkIdent: result = esc(n.ident.s, splitAfter) + of nkPostfix: result = getName(d, n.sons[1], splitAfter) + of nkPragmaExpr: result = getName(d, n.sons[0], splitAfter) + of nkSym: result = esc(d.target, n.sym.name.s, splitAfter) + of nkIdent: result = esc(d.target, n.ident.s, splitAfter) of nkAccQuoted: - result = esc("`") - for i in 0.. <n.len: result.add(getName(n[i], splitAfter)) - result.add esc("`") + result = esc(d.target, "`") + for i in 0.. <n.len: result.add(getName(d, n[i], splitAfter)) + result.add esc(d.target, "`") else: internalError(n.info, "getName()") result = "" @@ -323,7 +281,7 @@ proc getRstName(n: PNode): PRstNode = proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) = if not isVisible(nameNode): return - var name = toRope(getName(nameNode)) + var name = toRope(getName(d, nameNode)) var result: PRope = nil var literal = "" var kind = tkEof @@ -338,28 +296,28 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) = break of tkComment: dispA(result, "<span class=\"Comment\">$1</span>", "\\spanComment{$1}", - [toRope(esc(literal))]) + [toRope(esc(d.target, literal))]) of tokKeywordLow..tokKeywordHigh: dispA(result, "<span class=\"Keyword\">$1</span>", "\\spanKeyword{$1}", [toRope(literal)]) of tkOpr: dispA(result, "<span class=\"Operator\">$1</span>", "\\spanOperator{$1}", - [toRope(esc(literal))]) + [toRope(esc(d.target, literal))]) of tkStrLit..tkTripleStrLit: dispA(result, "<span class=\"StringLit\">$1</span>", - "\\spanStringLit{$1}", [toRope(esc(literal))]) + "\\spanStringLit{$1}", [toRope(esc(d.target, literal))]) of tkCharLit: dispA(result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}", - [toRope(esc(literal))]) + [toRope(esc(d.target, literal))]) of tkIntLit..tkInt64Lit: dispA(result, "<span class=\"DecNumber\">$1</span>", - "\\spanDecNumber{$1}", [toRope(esc(literal))]) + "\\spanDecNumber{$1}", [toRope(esc(d.target, literal))]) of tkFloatLit..tkFloat64Lit: dispA(result, "<span class=\"FloatNumber\">$1</span>", - "\\spanFloatNumber{$1}", [toRope(esc(literal))]) + "\\spanFloatNumber{$1}", [toRope(esc(d.target, literal))]) of tkSymbol: dispA(result, "<span class=\"Identifier\">$1</span>", - "\\spanIdentifier{$1}", [toRope(esc(literal))]) + "\\spanIdentifier{$1}", [toRope(esc(d.target, literal))]) of tkInd, tkSad, tkDed, tkSpaces, tkInvalid: app(result, literal) of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, @@ -368,19 +326,19 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) = tkAccent, tkColonColon, tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr: dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}", - [toRope(esc(literal))]) + [toRope(esc(d.target, literal))]) inc(d.id) app(d.section[k], ropeFormatNamedVars(getConfigVar("doc.item"), ["name", "header", "desc", "itemID"], [name, result, comm, toRope(d.id)])) app(d.toc[k], ropeFormatNamedVars(getConfigVar("doc.item.toc"), ["name", "header", "desc", "itemID"], [ - toRope(getName(nameNode, d.splitAfter)), result, comm, toRope(d.id)])) + toRope(getName(d, nameNode, d.splitAfter)), result, comm, toRope(d.id)])) setIndexForSourceTerm(d, getRstName(nameNode), d.id) proc renderHeadline(d: PDoc, n: PRstNode): PRope = result = nil - for i in countup(0, rsonsLen(n) - 1): app(result, renderRstToOut(d, n.sons[i])) + for i in countup(0, len(n) - 1): app(result, renderRstToOut(d, n.sons[i])) var refname = toRope(rstnodeToRefname(n)) if d.hasToc: var length = len(d.tocPart) @@ -400,7 +358,7 @@ proc renderHeadline(d: PDoc, n: PRstNode): PRope = proc renderOverline(d: PDoc, n: PRstNode): PRope = var t: PRope = nil - for i in countup(0, rsonsLen(n) - 1): app(t, renderRstToOut(d, n.sons[i])) + for i in countup(0, len(n) - 1): app(t, renderRstToOut(d, n.sons[i])) result = nil if d.meta[metaTitle] == nil: d.meta[metaTitle] = t @@ -411,123 +369,7 @@ proc renderOverline(d: PDoc, n: PRstNode): PRope = "\\rstov$4{$3}\\label{$2}$n", [toRope(n.level), toRope(rstnodeToRefname(n)), t, toRope($chr(n.level - 1 + ord('A')))]) -proc renderRstToRst(d: PDoc, n: PRstNode): PRope -proc renderRstSons(d: PDoc, n: PRstNode): PRope = - for i in countup(0, rsonsLen(n) - 1): - app(result, renderRstToRst(d, n.sons[i])) - -proc renderRstToRst(d: PDoc, n: PRstNode): PRope = - # this is needed for the index generation; it may also be useful for - # debugging, but most code is already debugged... - const - lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+'] - result = nil - if n == nil: return - var ind = toRope(repeatChar(d.indent)) - case n.kind - of rnInner: - result = renderRstSons(d, n) - of rnHeadline: - result = renderRstSons(d, n) - var L = ropeLen(result) - result = ropef("$n$1$2$n$1$3", - [ind, result, toRope(repeatChar(L, lvlToChar[n.level]))]) - of rnOverline: - result = renderRstSons(d, n) - var L = ropeLen(result) - result = ropef("$n$1$3$n$1$2$n$1$3", - [ind, result, toRope(repeatChar(L, lvlToChar[n.level]))]) - of rnTransition: - result = ropef("$n$n$1$2$n$n", [ind, toRope(repeatChar(78-d.indent, '-'))]) - of rnParagraph: - result = renderRstSons(d, n) - result = ropef("$n$n$1$2", [ind, result]) - of rnBulletItem: - inc(d.indent, 2) - result = renderRstSons(d, n) - if result != nil: result = ropef("$n$1* $2", [ind, result]) - dec(d.indent, 2) - of rnEnumItem: - inc(d.indent, 4) - result = renderRstSons(d, n) - if result != nil: result = ropef("$n$1(#) $2", [ind, result]) - dec(d.indent, 4) - of rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName, - rnFieldBody, rnStandaloneHyperlink, rnBulletList, rnEnumList: - result = renderRstSons(d, n) - of rnDefName: - result = renderRstSons(d, n) - result = ropef("$n$n$1$2", [ind, result]) - of rnDefBody: - inc(d.indent, 2) - result = renderRstSons(d, n) - if n.sons[0].kind != rnBulletList: result = ropef("$n$1 $2", [ind, result]) - dec(d.indent, 2) - of rnField: - result = renderRstToRst(d, n.sons[0]) - var L = max(ropeLen(result) + 3, 30) - inc(d.indent, L) - result = ropef("$n$1:$2:$3$4", [ind, result, toRope( - repeatChar(L - ropeLen(result) - 2)), renderRstToRst(d, n.sons[1])]) - dec(d.indent, L) - of rnLineBlockItem: - result = renderRstSons(d, n) - result = ropef("$n$1| $2", [ind, result]) - of rnBlockQuote: - inc(d.indent, 2) - result = renderRstSons(d, n) - dec(d.indent, 2) - of rnRef: - result = renderRstSons(d, n) - result = ropef("`$1`_", [result]) - of rnHyperlink: - result = ropef("`$1 <$2>`_", - [renderRstToRst(d, n.sons[0]), renderRstToRst(d, n.sons[1])]) - of rnGeneralRole: - result = renderRstToRst(d, n.sons[0]) - result = ropef("`$1`:$2:", [result, renderRstToRst(d, n.sons[1])]) - of rnSub: - result = renderRstSons(d, n) - result = ropef("`$1`:sub:", [result]) - of rnSup: - result = renderRstSons(d, n) - result = ropef("`$1`:sup:", [result]) - of rnIdx: - result = renderRstSons(d, n) - result = ropef("`$1`:idx:", [result]) - of rnEmphasis: - result = renderRstSons(d, n) - result = ropef("*$1*", [result]) - of rnStrongEmphasis: - result = renderRstSons(d, n) - result = ropef("**$1**", [result]) - of rnTripleEmphasis: - result = renderRstSons(d, n) - result = ropef("***$1***", [result]) - of rnInterpretedText: - result = renderRstSons(d, n) - result = ropef("`$1`", [result]) - of rnInlineLiteral: - inc(d.verbatim) - result = renderRstSons(d, n) - result = ropef("``$1``", [result]) - dec(d.verbatim) - of rnSmiley: - result = toRope(n.text) - of rnLeaf: - if (d.verbatim == 0) and (n.text == "\\"): - result = toRope("\\\\") # XXX: escape more special characters! - else: - result = toRope(n.text) - of rnIndex: - inc(d.indent, 3) - if n.sons[2] != nil: result = renderRstSons(d, n.sons[2]) - dec(d.indent, 3) - result = ropef("$n$n$1.. index::$n$2", [ind, result]) - of rnContents: - result = ropef("$n$n$1.. contents::", [ind]) - else: rawMessage(errCannotRenderX, $n.kind) - + proc renderTocEntry(d: PDoc, e: TTocEntry): PRope = result = dispF( "<li><a class=\"reference\" id=\"$1_toc\" href=\"#$1\">$2</a></li>$n", @@ -537,10 +379,10 @@ proc renderTocEntries(d: PDoc, j: var int, lvl: int): PRope = result = nil while j <= high(d.tocPart): var a = abs(d.tocPart[j].n.level) - if (a == lvl): + if a == lvl: app(result, renderTocEntry(d, d.tocPart[j])) inc(j) - elif (a > lvl): + elif a > lvl: app(result, renderTocEntries(d, j, a)) else: break @@ -566,7 +408,7 @@ proc renderImage(d: PDoc, n: PRstNode): PRope = if options != nil: options = dispF("$1", "[$1]", [options]) result = dispF("<img src=\"$1\"$2 />", "\\includegraphics$2{$1}", [toRope(getArgument(n)), options]) - if rsonsLen(n) >= 3: app(result, renderRstToOut(d, n.sons[2])) + if len(n) >= 3: app(result, renderRstToOut(d, n.sons[2])) proc renderSmiley(d: PDoc, n: PRstNode): PRope = result = dispF( @@ -596,13 +438,13 @@ proc renderCodeBlock(d: PDoc, n: PRstNode): PRope = case g.kind of gtEof: break of gtNone, gtWhitespace: - app(result, substr(m.text, g.start + 0, g.length + g.start - 1)) + app(result, substr(m.text, g.start, g.length + g.start - 1)) else: dispA(result, "<span class=\"$2\">$1</span>", "\\span$2{$1}", [ - toRope(esc(substr(m.text, g.start + 0, g.length + g.start - 1))), - toRope(tokenClassToStr[g.kind])]) + toRope(esc(d.target, substr(m.text, g.start, g.length+g.start-1))), + toRope(tokenClassToStr[g.kind])]) deinitGeneralTokenizer(g) - if result != nil: + if result != nil: result = dispF("<pre>$1</pre>", "\\begin{rstpre}$n$1$n\\end{rstpre}$n", [result]) @@ -614,13 +456,13 @@ proc renderContainer(d: PDoc, n: PRstNode): PRope = proc texColumns(n: PRstNode): string = result = "" - for i in countup(1, rsonsLen(n)): add(result, "|X") + for i in countup(1, len(n)): add(result, "|X") proc renderField(d: PDoc, n: PRstNode): PRope = var b = false if gCmd == cmdRst2Tex: var fieldname = addNodes(n.sons[0]) - var fieldval = toRope(esc(strip(addNodes(n.sons[1])))) + var fieldval = toRope(esc(d.target, strip(addNodes(n.sons[1])))) if cmpIgnoreStyle(fieldname, "author") == 0: if d.meta[metaAuthor] == nil: d.meta[metaAuthor] = fieldval @@ -657,7 +499,7 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope = of rnDefBody: result = renderAux(d, n, disp("<dd>$1</dd>\n", "$1\n")) of rnFieldList: result = nil - for i in countup(0, rsonsLen(n) - 1): + for i in countup(0, len(n) - 1): app(result, renderRstToOut(d, n.sons[i])) if result != nil: result = dispf( @@ -705,9 +547,9 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope = "\\begin{table}\\begin{rsttab}{" & texColumns(n) & "|}$n\\hline$n$1\\end{rsttab}\\end{table}")) of rnTableRow: - if rsonsLen(n) >= 1: + if len(n) >= 1: result = renderRstToOut(d, n.sons[0]) - for i in countup(1, rsonsLen(n) - 1): + for i in countup(1, len(n) - 1): dispa(result, "$1", " & $1", [renderRstToOut(d, n.sons[i])]) result = dispf("<tr>$1</tr>$n", "$1\\\\$n\\hline$n", [result]) else: @@ -770,7 +612,7 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope = "<tt class=\"docutils literal\"><span class=\"pre\">$1</span></tt>", "\\texttt{$1}")) of rnSmiley: result = renderSmiley(d, n) - of rnLeaf: result = toRope(esc(n.text)) + of rnLeaf: result = toRope(esc(d.target, n.text)) of rnContents: d.hasToc = true of rnTitle: d.meta[metaTitle] = renderRstToOut(d, n.sons[0]) @@ -863,7 +705,9 @@ proc genOutFile(d: PDoc): PRope = proc generateIndex(d: PDoc) = if d.theIndex != nil: sortIndex(d.theIndex) - writeRope(renderRstToRst(d, d.indexFile), gIndexFile) + var content = newStringOfCap(2_000_000) + renderRstToRst(d.indexFile, content) + writeFile(gIndexFile, content) proc writeOutput(d: PDoc, filename, outExt: string) = var content = genOutFile(d) @@ -886,7 +730,7 @@ proc CommandRstAux(filename, outExt: string) = var filen = addFileExt(filename, "txt") var d = newDocumentor(filen) initIndexFile(d) - var rst = rstParse(readFile(filen), filen, 0, 1, d.hasToc, + var rst = parseRst(readFile(filen), filen, 0, 1, d.hasToc, {roSupportRawDirective}) d.modDesc = renderRstToOut(d, rst) writeOutput(d, filename, outExt) diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 496f7d2f1..a17871e3a 100755 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -27,6 +27,8 @@ const OpChars*: TCharSet = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', '.', '|', '=', '%', '&', '$', '@', '~', ':', '\x80'..'\xFF'} +# don't forget to update the 'highlite' module if these charsets should change + type TTokType* = enum tkInvalid, tkEof, # order is important here! diff --git a/compiler/msgs.nim b/compiler/msgs.nim index a0058ebe3..17cfeae4d 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -663,7 +663,7 @@ proc InternalError*(errMsg: string) = rawMessage(errInternal, errMsg) template AssertNotNil*(e: expr): expr = - if(e == nil): InternalError($InstantiationInfo()) + if e == nil: InternalError($InstantiationInfo()) e template InternalAssert*(e: bool): stmt = diff --git a/compiler/nimrod.cfg b/compiler/nimrod.cfg index 7d8d4d94f..f47143527 100755 --- a/compiler/nimrod.cfg +++ b/compiler/nimrod.cfg @@ -4,6 +4,8 @@ path="llvm" path="$projectPath/.." +path="$nimrod/packages/docutils" + @if llvm_gcc or gcc: # GCC, LLVM and Visual C++ have a problem to optimize some modules. # This is really strange. diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 9fd6f0ce6..da87d957d 100755 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -33,6 +33,7 @@ Files: "doc/*.pdf" Files: "doc/*.ini" Start: "doc/overview.html" + [Other] Files: "readme.txt;install.txt;contributors.txt" Files: "configure;makefile" @@ -56,6 +57,9 @@ Files: "compiler/*.nim" Files: "build/empty.txt" Files: "bin/empty.txt" +Files: "packages/docutils/*.nim" + + [Lib] Files: "lib/nimbase.h;lib/cycle.h" Files: "lib/*.nim" @@ -72,6 +76,7 @@ Files: "lib/wrappers/cairo/*.nim" Files: "lib/wrappers/gtk/*.nim" Files: "lib/wrappers/lua/*.nim" Files: "lib/wrappers/opengl/*.nim" +Files: "lib/wrappers/readline/*.nim" Files: "lib/wrappers/sdl/*.nim" Files: "lib/wrappers/x11/*.nim" Files: "lib/wrappers/zip/*.nim" @@ -81,6 +86,7 @@ Files: "lib/windows/*.nim" Files: "lib/posix/*.nim" Files: "lib/ecmas/*.nim" + [Other] Files: "examples/*.nim" Files: "examples/gtk/*.nim" @@ -99,6 +105,7 @@ Files: "examples/*.txt" Files: "examples/*.cfg" Files: "examples/*.tmpl" + [Windows] Files: "bin/nimrod.exe" Files: "bin/c2nim.exe" @@ -112,21 +119,26 @@ Files: "start.bat" BinPath: r"bin;dist\mingw\bin;dist" InnoSetup: "Yes" + [UnixBin] Files: "bin/nimrod" + [Unix] InstallScript: "yes" UninstallScript: "yes" + [InnoSetup] path = r"c:\programme\inno setup 5\iscc.exe" flags = "/Q" + [C_Compiler] path = r"" flags = "-w" + [deb] buildDepends: "gcc (>= 4:4.3.2)" pkgDepends: "gcc (>= 4:4.3.2)" diff --git a/compiler/options.nim b/compiler/options.nim index 3a2352c7f..9d7b41180 100755 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -199,7 +199,7 @@ proc rawFindFile(f: string): string = return result.canonicalizePath result = "" -proc FindFile*(f: string): string = +proc FindFile*(f: string): string {.procvar.} = result = rawFindFile(f) if len(result) == 0: result = rawFindFile(toLower(f)) diff --git a/lib/system.nim b/lib/system.nim index ae6e4dc9f..0b89cc5fe 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -1897,6 +1897,9 @@ when not defined(EcmaScript) and not defined(NimrodVM): proc writeStackTrace*() ## writes the current stack trace to ``stderr``. This is only works ## for debug builds. + + proc getStackTrace*(): string + ## gets the current stack trace. This is only works for debug builds. {.push stack_trace: off.} when hostCPU == "avr": diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 2df7fe4ad..a523e4e04 100755 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -246,6 +246,13 @@ proc WriteStackTrace() = else: writeToStdErr("No stack traceback available\n") +proc getStackTrace(): string = + when hasSomeStackTrace: + result = "" + rawWriteStackTrace(result) + else: + result = "No stack traceback available\n" + when defined(endb): var dbgAborting: bool # whether the debugger wants to abort diff --git a/compiler/highlite.nim b/packages/docutils/highlite.nim index ff4b27086..21dd1543a 100755 --- a/compiler/highlite.nim +++ b/packages/docutils/highlite.nim @@ -1,18 +1,18 @@ # # -# The Nimrod Compiler +# Nimrod's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -# Source highlighter for programming or markup languages. -# Currently only few languages are supported, other languages may be added. -# The interface supports one language nested in another. +## Source highlighter for programming or markup languages. +## Currently only few languages are supported, other languages may be added. +## The interface supports one language nested in another. -import - hashes, options, msgs, strutils, platform, idents, lexbase, wordrecg, lexer +import + strutils type TTokenClass* = enum @@ -44,19 +44,15 @@ const "Assembler", "Preprocessor", "Directive", "Command", "Rule", "Hyperlink", "Label", "Reference", "Other"] -proc getSourceLanguage*(name: string): TSourceLanguage -proc initGeneralTokenizer*(g: var TGeneralTokenizer, buf: string) -proc deinitGeneralTokenizer*(g: var TGeneralTokenizer) -proc getNextToken*(g: var TGeneralTokenizer, lang: TSourceLanguage) -# implementation + nimrodKeywords = slurp("doc/keywords.txt").split -proc getSourceLanguage(name: string): TSourceLanguage = +proc getSourceLanguage*(name: string): TSourceLanguage = for i in countup(succ(low(TSourceLanguage)), high(TSourceLanguage)): if cmpIgnoreStyle(name, sourceLanguageToStr[i]) == 0: return i result = langNone -proc initGeneralTokenizer(g: var TGeneralTokenizer, buf: string) = +proc initGeneralTokenizer*(g: var TGeneralTokenizer, buf: string) = g.buf = cstring(buf) g.kind = low(TTokenClass) g.start = 0 @@ -66,16 +62,20 @@ proc initGeneralTokenizer(g: var TGeneralTokenizer, buf: string) = while g.buf[pos] in {' ', '\x09'..'\x0D'}: inc(pos) g.pos = pos -proc deinitGeneralTokenizer(g: var TGeneralTokenizer) = +proc deinitGeneralTokenizer*(g: var TGeneralTokenizer) = nil proc nimGetKeyword(id: string): TTokenClass = - var i = getIdent(id) - if (i.id >= ord(tokKeywordLow) - ord(tkSymbol)) and - (i.id <= ord(tokKeywordHigh) - ord(tkSymbol)): - result = gtKeyword - else: - result = gtIdentifier + for k in nimrodKeywords: + if cmpIgnoreStyle(id, k) == 0: return gtKeyword + result = gtIdentifier + when false: + var i = getIdent(id) + if (i.id >= ord(tokKeywordLow) - ord(tkSymbol)) and + (i.id <= ord(tokKeywordHigh) - ord(tkSymbol)): + result = gtKeyword + else: + result = gtIdentifier proc nimNumberPostfix(g: var TGeneralTokenizer, position: int): int = var pos = position @@ -111,11 +111,16 @@ proc nimNumber(g: var TGeneralTokenizer, position: int): int = while g.buf[pos] in decChars: inc(pos) result = nimNumberPostfix(g, pos) +const + OpChars = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', '.', + '|', '=', '%', '&', '$', '@', '~', ':', '\x80'..'\xFF'} + proc nimNextToken(g: var TGeneralTokenizer) = const hexChars = {'0'..'9', 'A'..'F', 'a'..'f', '_'} octChars = {'0'..'7', '_'} binChars = {'0'..'1', '_'} + SymChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'} var pos = g.pos g.start = g.pos if g.state == gtStringLit: @@ -154,7 +159,7 @@ proc nimNextToken(g: var TGeneralTokenizer) = while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): inc(pos) of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF': var id = "" - while g.buf[pos] in lexer.SymChars + {'_'}: + while g.buf[pos] in SymChars + {'_'}: add(id, g.buf[pos]) inc(pos) if (g.buf[pos] == '\"'): @@ -247,15 +252,15 @@ proc nimNextToken(g: var TGeneralTokenizer) = of '\0': g.kind = gtEof else: - if g.buf[pos] in lexer.OpChars: + if g.buf[pos] in OpChars: g.kind = gtOperator - while g.buf[pos] in lexer.OpChars: inc(pos) + while g.buf[pos] in OpChars: inc(pos) else: inc(pos) g.kind = gtNone g.length = pos - g.pos - if (g.kind != gtEof) and (g.length <= 0): - InternalError("nimNextToken: " & $(g.buf)) + if g.kind != gtEof and g.length <= 0: + assert false, "nimNextToken: produced an empty token" g.pos = pos proc generalNumber(g: var TGeneralTokenizer, position: int): int = @@ -407,7 +412,7 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openarray[string], inc(pos) if hasPreprocessor in flags: g.kind = gtPreprocessor - while g.buf[pos] in {' ', Tabulator}: inc(pos) + while g.buf[pos] in {' ', '\t'}: inc(pos) while g.buf[pos] in symChars: inc(pos) else: g.kind = gtOperator @@ -462,14 +467,15 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openarray[string], of '\0': g.kind = gtEof else: - if g.buf[pos] in lexer.OpChars: + if g.buf[pos] in OpChars: g.kind = gtOperator - while g.buf[pos] in lexer.OpChars: inc(pos) + while g.buf[pos] in OpChars: inc(pos) else: inc(pos) g.kind = gtNone g.length = pos - g.pos - if (g.kind != gtEof) and (g.length <= 0): InternalError("clikeNextToken") + if g.kind != gtEof and g.length <= 0: + assert false, "clikeNextToken: produced an empty token" g.pos = pos proc cNextToken(g: var TGeneralTokenizer) = @@ -520,12 +526,12 @@ proc javaNextToken(g: var TGeneralTokenizer) = "try", "void", "volatile", "while"] clikeNextToken(g, keywords, {}) -proc getNextToken(g: var TGeneralTokenizer, lang: TSourceLanguage) = +proc getNextToken*(g: var TGeneralTokenizer, lang: TSourceLanguage) = case lang + of langNone: assert false of langNimrod: nimNextToken(g) of langCpp: cppNextToken(g) of langCsharp: csharpNextToken(g) of langC: cNextToken(g) of langJava: javaNextToken(g) - else: InternalError("getNextToken") diff --git a/compiler/rst.nim b/packages/docutils/rst.nim index 5cb9c3b6a..cd385ccac 100755 --- a/compiler/rst.nim +++ b/packages/docutils/rst.nim @@ -1,95 +1,61 @@ # # -# The Nimrod Compiler +# Nimrod's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -# This module implements a *reStructuredText* parser. A large -# subset is provided. +## This module implements a `reStructuredText`:idx parser. A large +## subset is implemented. Some features of the `markdown`:idx: wiki syntax are +## also supported. import - os, msgs, strutils, hashes, options - -type - TRstNodeKind* = enum - rnInner, # an inner node or a root - rnHeadline, # a headline - rnOverline, # an over- and underlined headline - rnTransition, # a transition (the ------------- <hr> thingie) - rnParagraph, # a paragraph - rnBulletList, # a bullet list - rnBulletItem, # a bullet item - rnEnumList, # an enumerated list - rnEnumItem, # an enumerated item - rnDefList, # a definition list - rnDefItem, # an item of a definition list consisting of ... - rnDefName, # ... a name part ... - rnDefBody, # ... and a body part ... - rnFieldList, # a field list - rnField, # a field item - rnFieldName, # consisting of a field name ... - rnFieldBody, # ... and a field body - rnOptionList, rnOptionListItem, rnOptionGroup, rnOption, rnOptionString, - rnOptionArgument, rnDescription, rnLiteralBlock, rnQuotedLiteralBlock, - rnLineBlock, # the | thingie - rnLineBlockItem, # sons of the | thing - rnBlockQuote, # text just indented - rnTable, rnGridTable, rnTableRow, rnTableHeaderCell, rnTableDataCell, - rnLabel, # used for footnotes and other things - rnFootnote, # a footnote - rnCitation, # similar to footnote - rnStandaloneHyperlink, rnHyperlink, rnRef, rnDirective, # a directive - rnDirArg, rnRaw, rnTitle, rnContents, rnImage, rnFigure, rnCodeBlock, - rnRawHtml, rnRawLatex, - rnContainer, # ``container`` directive - rnIndex, # index directve: - # .. index:: - # key - # * `file#id <file#id>`_ - # * `file#id <file#id>'_ - rnSubstitutionDef, # a definition of a substitution - rnGeneralRole, # Inline markup: - rnSub, rnSup, rnIdx, - rnEmphasis, # "*" - rnStrongEmphasis, # "**" - rnTripleEmphasis, # "***" - rnInterpretedText, # "`" - rnInlineLiteral, # "``" - rnSubstitutionReferences, # "|" - rnSmiley, # some smiley - rnLeaf # a leaf; the node's text field contains the - # leaf val + os, strutils, rstast type TRstParseOption* = enum ## options for the RST parser roSkipPounds, ## skip ``#`` at line beginning (documentation ## embedded in Nimrod comments) roSupportSmilies, ## make the RST parser support smilies like ``:)`` - roSupportRawDirective ## support the ``raw`` directive (don't support + roSupportRawDirective, ## support the ``raw`` directive (don't support ## it for sandboxing) + roSupportMarkdown ## support additional features of markdown TRstParseOptions* = set[TRstParseOption] - PRSTNode* = ref TRstNode - TRstNodeSeq* = seq[PRstNode] - TRSTNode*{.acyclic, final.} = object - kind*: TRstNodeKind - text*: string # valid for leafs in the AST; and the title of - # the document or the section - level*: int # valid for some node kinds - sons*: TRstNodeSeq # the node's sons + TMsgClass* = enum + mcHint = "Hint", + mcWarning = "Warning", + mcError = "Error" + TMsgKind* = enum ## the possible messages + meCannotOpenFile, + meExpected, + meGridTableNotImplemented, + meNewSectionExpected, + meGeneralParseError, + meInvalidDirective, + mwRedefinitionOfLabel, + mwUnknownSubstitution + + TMsgHandler* = proc (filename: string, line, col: int, msgKind: TMsgKind, + arg: string) ## what to do in case of an error + TFindFileHandler* = proc (filename: string): string + +const + messages: array [TMsgKind, string] = [ + meCannotOpenFile: "cannot open '$1'", + meExpected: "'$1' expected", + meGridTableNotImplemented: "grid table is not implemented", + meNewSectionExpected: "new section expected", + meGeneralParseError: "general parse error", + meInvalidDirective: "invalid directive: '$1'", + mwRedefinitionOfLabel: "redefinition of label '$1'", + mwUnknownSubstitution: "unknown substitution '$1'" + ] -proc rstParse*(text, filename: string, - line, column: int, hasToc: var bool, - options: TRstParseOptions): PRstNode -proc rsonsLen*(n: PRstNode): int -proc newRstNode*(kind: TRstNodeKind): PRstNode -proc newRstNode*(kind: TRstNodeKind, s: string): PRstNode -proc addSon*(father, son: PRstNode) proc rstnodeToRefname*(n: PRstNode): string proc addNodes*(n: PRstNode): string proc getFieldValue*(n: PRstNode, fieldname: string): string @@ -281,46 +247,27 @@ proc getTokens(buffer: string, skipPounds: bool, tokens: var TTokenSeq) = tokens[0].ival = len(tokens[0].symbol) tokens[0].kind = tkIndent -proc addSon(father, son: PRstNode) = - add(father.sons, son) - -proc addSonIfNotNil(father, son: PRstNode) = - if son != nil: addSon(father, son) - -proc rsonsLen(n: PRstNode): int = - result = len(n.sons) - -proc newRstNode(kind: TRstNodeKind): PRstNode = - new(result) - result.sons = @[] - result.kind = kind - -proc newRstNode(kind: TRstNodeKind, s: string): PRstNode = - result = newRstNode(kind) - result.text = s - -proc lastSon*(n: PRstNode): PRstNode = - result = n.sons[len(n.sons)-1] - -type +type TLevelMap = array[Char, int] TSubstitution{.final.} = object key*: string value*: PRstNode TSharedState {.final.} = object - options: TRstParseOptions # parsing options - uLevel*, oLevel*: int # counters for the section levels - subs*: seq[TSubstitution] # substitutions - refs*: seq[TSubstitution] # references - underlineToLevel*: TLevelMap # Saves for each possible title adornment - # character its level in the - # current document. - # This is for single underline adornments. - overlineToLevel*: TLevelMap # Saves for each possible title adornment - # character its level in the current - # document. - # This is for over-underline adornments. + options: TRstParseOptions # parsing options + uLevel, oLevel: int # counters for the section levels + subs: seq[TSubstitution] # substitutions + refs: seq[TSubstitution] # references + underlineToLevel: TLevelMap # Saves for each possible title adornment + # character its level in the + # current document. + # This is for single underline adornments. + overlineToLevel: TLevelMap # Saves for each possible title adornment + # character its level in the current + # document. + # This is for over-underline adornments. + msgHandler: TMsgHandler # How to handle errors. + findFile: TFindFileHandler # How to find files. PSharedState = ref TSharedState TRstParser = object of TObject @@ -332,21 +279,57 @@ type line*, col*: int hasToc*: bool + EParseError* = object of EInvalidValue + +when false: + proc tokInfo(p: TRstParser, tok: TToken): TLineInfo = + result = newLineInfo(p.filename, p.line + tok.line, p.col + tok.col) + + proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string) = + GlobalError(tokInfo(p, p.tok[p.idx]), msgKind, arg) + + proc rstMessage(p: TRstParser, msgKind: TMsgKind) = + GlobalError(tokInfo(p, p.tok[p.idx]), msgKind, p.tok[p.idx].symbol) + -proc newSharedState(options: TRstParseOptions): PSharedState = +proc whichMsgClass*(k: TMsgKind): TMsgClass = + ## returns which message class `k` belongs to. + case ($k)[1] + of 'e', 'E': result = mcError + of 'w', 'W': result = mcWarning + of 'h', 'H': result = mcHint + else: assert false, "msgkind does not fit naming scheme" + +proc defaultMsgHandler(filename: string, line, col: int, msgkind: TMsgKind, + arg: string) = + let mc = msgKind.whichMsgClass + let a = messages[msgKind] % arg + let message = "$1($2, $3) $4: $5" % [filename, $line, $col, $mc, a] + if mc == mcError: raise newException(EParseError, message) + else: Writeln(stdout, message) + +proc defaultFindFile(filename: string): string = + if existsFile(filename): result = filename + else: result = "" + +proc newSharedState(options: TRstParseOptions, + findFile: TFindFileHandler, + msgHandler: TMsgHandler): PSharedState = new(result) result.subs = @[] result.refs = @[] result.options = options - -proc tokInfo(p: TRstParser, tok: TToken): TLineInfo = - result = newLineInfo(p.filename, p.line + tok.line, p.col + tok.col) - + result.msgHandler = if isNil(msgHandler): defaultMsgHandler else: msgHandler + result.findFile = if isNil(findFile): defaultFindFile else: findFile + proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string) = - GlobalError(tokInfo(p, p.tok[p.idx]), msgKind, arg) + p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line, + p.col + p.tok[p.idx].col, msgKind, arg) proc rstMessage(p: TRstParser, msgKind: TMsgKind) = - GlobalError(tokInfo(p, p.tok[p.idx]), msgKind, p.tok[p.idx].symbol) + p.s.msgHandler(p.filename, p.line + p.tok[p.idx].line, + p.col + p.tok[p.idx].col, msgKind, + p.tok[p.idx].symbol) proc currInd(p: TRstParser): int = result = p.indentStack[high(p.indentStack)] @@ -371,7 +354,7 @@ proc addNodesAux(n: PRstNode, result: var string) = if n.kind == rnLeaf: add(result, n.text) else: - for i in countup(0, rsonsLen(n) - 1): addNodesAux(n.sons[i], result) + for i in countup(0, len(n) - 1): addNodesAux(n.sons[i], result) proc addNodes(n: PRstNode): string = result = "" @@ -400,7 +383,7 @@ proc rstnodeToRefnameAux(n: PRstNode, r: var string, b: var bool) = else: if (len(r) > 0): b = true else: - for i in countup(0, rsonsLen(n) - 1): rstnodeToRefnameAux(n.sons[i], r, b) + for i in countup(0, len(n) - 1): rstnodeToRefnameAux(n.sons[i], r, b) proc rstnodeToRefname(n: PRstNode): string = result = "" @@ -433,7 +416,7 @@ proc setRef(p: var TRstParser, key: string, value: PRstNode) = for i in countup(0, length - 1): if key == p.s.refs[i].key: if p.s.refs[i].value.addNodes != value.addNodes: - rstMessage(p, warnRedefinitionOfLabel, key) + rstMessage(p, mwRedefinitionOfLabel, key) p.s.refs[i].value = value return @@ -456,7 +439,7 @@ proc cmpNodes(a, b: PRstNode): int = proc sortIndex(a: PRstNode) = # we use shellsort here; fast and simple assert(a.kind == rnDefList) - var N = rsonsLen(a) + var N = len(a) var h = 1 while true: h = 3 * h + 1 @@ -478,14 +461,14 @@ proc eqRstNodes(a, b: PRstNode): bool = if a.kind == rnLeaf: result = a.text == b.text else: - if rsonsLen(a) != rsonsLen(b): return - for i in countup(0, rsonsLen(a) - 1): + if len(a) != len(b): return + for i in countup(0, len(a) - 1): if not eqRstNodes(a.sons[i], b.sons[i]): return result = true proc matchesHyperlink(h: PRstNode, filename: string): bool = if h.kind == rnInner: # this may happen in broken indexes! - assert(rsonsLen(h) == 1) + assert(len(h) == 1) result = matchesHyperlink(h.sons[0], filename) elif h.kind == rnHyperlink: var s = addNodes(h.sons[1]) @@ -498,14 +481,14 @@ proc clearIndex(index: PRstNode, filename: string) = var lastItem: int assert(index.kind == rnDefList) - for i in countup(0, rsonsLen(index) - 1): + for i in countup(0, len(index) - 1): assert(index.sons[i].sons[1].kind == rnDefBody) var val = index.sons[i].sons[1].sons[0] if val.kind == rnInner: val = val.sons[0] if val.kind == rnBulletList: - var items = rsonsLen(val) + var items = len(val) lastItem = - 1 # save the last valid item index - for j in countup(0, rsonsLen(val) - 1): + for j in countup(0, len(val) - 1): if val.sons[j] == nil: dec(items) elif matchesHyperlink(val.sons[j].sons[0], filename): @@ -520,7 +503,7 @@ proc clearIndex(index: PRstNode, filename: string) = elif matchesHyperlink(val, filename): index.sons[i] = nil var k = 0 - for i in countup(0, rsonsLen(index) - 1): + for i in countup(0, len(index) - 1): if index.sons[i] != nil: if k != i: index.sons[k] = index.sons[i] inc(k) @@ -531,28 +514,28 @@ proc setIndexPair(index, key, val: PRstNode) = assert(index.kind == rnDefList) assert(key.kind != rnDefName) a = newRstNode(rnDefName) - addSon(a, key) - for i in countup(0, rsonsLen(index) - 1): + add(a, key) + for i in countup(0, len(index) - 1): if eqRstNodes(index.sons[i].sons[0], a): assert(index.sons[i].sons[1].kind == rnDefBody) e = index.sons[i].sons[1].sons[0] if e.kind != rnBulletList: e = newRstNode(rnBulletList) b = newRstNode(rnBulletItem) - addSon(b, index.sons[i].sons[1].sons[0]) - addSon(e, b) + add(b, index.sons[i].sons[1].sons[0]) + add(e, b) index.sons[i].sons[1].sons[0] = e b = newRstNode(rnBulletItem) - addSon(b, val) - addSon(e, b) + add(b, val) + add(e, b) return # key already exists e = newRstNode(rnDefItem) assert(val.kind != rnDefBody) b = newRstNode(rnDefBody) - addSon(b, val) - addSon(e, a) - addSon(e, b) - addSon(index, e) + add(b, val) + add(e, a) + add(e, b) + add(index, e) proc newLeaf(p: var TRstParser): PRstNode = result = newRstNode(rnLeaf, p.tok[p.idx].symbol) @@ -562,15 +545,15 @@ proc getReferenceName(p: var TRstParser, endStr: string): PRstNode = while true: case p.tok[p.idx].kind of tkWord, tkOther, tkWhite: - addSon(res, newLeaf(p)) + add(res, newLeaf(p)) of tkPunct: if p.tok[p.idx].symbol == endStr: inc(p.idx) break else: - addSon(res, newLeaf(p)) + add(res, newLeaf(p)) else: - rstMessage(p, errXexpected, endStr) + rstMessage(p, meExpected, endStr) break inc(p.idx) result = res @@ -578,12 +561,12 @@ proc getReferenceName(p: var TRstParser, endStr: string): PRstNode = proc untilEol(p: var TRstParser): PRstNode = result = newRstNode(rnInner) while not (p.tok[p.idx].kind in {tkIndent, tkEof}): - addSon(result, newLeaf(p)) + add(result, newLeaf(p)) inc(p.idx) proc expect(p: var TRstParser, tok: string) = if p.tok[p.idx].symbol == tok: inc(p.idx) - else: rstMessage(p, errXexpected, tok) + else: rstMessage(p, meExpected, tok) proc isInlineMarkupEnd(p: TRstParser, markup: string): bool = result = p.tok[p.idx].symbol == markup @@ -676,13 +659,13 @@ proc match(p: TRstParser, start: int, expr: string): bool = proc fixupEmbeddedRef(n, a, b: PRstNode) = var sep = - 1 - for i in countdown(rsonsLen(n) - 2, 0): + for i in countdown(len(n) - 2, 0): if n.sons[i].text == "<": sep = i break var incr = if (sep > 0) and (n.sons[sep - 1].text[0] == ' '): 2 else: 1 - for i in countup(0, sep - incr): addSon(a, n.sons[i]) - for i in countup(sep + 1, rsonsLen(n) - 2): addSon(b, n.sons[i]) + for i in countup(0, sep - incr): add(a, n.sons[i]) + for i in countup(sep + 1, len(n) - 2): add(b, n.sons[i]) proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode = result = n @@ -692,19 +675,19 @@ proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode = var a = newRstNode(rnInner) var b = newRstNode(rnInner) fixupEmbeddedRef(n, a, b) - if rsonsLen(a) == 0: + if len(a) == 0: result = newRstNode(rnStandaloneHyperlink) - addSon(result, b) + add(result, b) else: result = newRstNode(rnHyperlink) - addSon(result, a) - addSon(result, b) + add(result, a) + add(result, b) setRef(p, rstnodeToRefname(a), b) elif n.kind == rnInterpretedText: n.kind = rnRef else: result = newRstNode(rnRef) - addSon(result, n) + add(result, n) elif match(p, p.idx, ":w:"): # a role: if p.tok[p.idx + 1].symbol == "idx": @@ -724,8 +707,8 @@ proc parsePostfix(p: var TRstParser, n: PRstNode): PRstNode = else: result = newRstNode(rnGeneralRole) n.kind = rnInner - addSon(result, n) - addSon(result, newRstNode(rnLeaf, p.tok[p.idx + 1].symbol)) + add(result, n) + add(result, newRstNode(rnLeaf, p.tok[p.idx + 1].symbol)) inc(p.idx, 3) proc matchVerbatim(p: TRstParser, start: int, expr: string): int = @@ -761,27 +744,27 @@ proc parseURL(p: var TRstParser, father: PRstNode) = if p.tok[p.idx+1].kind notin {tkWord, tkAdornment, tkOther, tkPunct}: break else: break - addSon(n, newLeaf(p)) + add(n, newLeaf(p)) inc(p.idx) - addSon(father, n) + add(father, n) else: var n = newLeaf(p) inc(p.idx) if p.tok[p.idx].symbol == "_": n = parsePostfix(p, n) - addSon(father, n) + add(father, n) proc parseBackslash(p: var TRstParser, father: PRstNode) = assert(p.tok[p.idx].kind == tkPunct) if p.tok[p.idx].symbol == "\\\\": - addSon(father, newRstNode(rnLeaf, "\\")) + add(father, newRstNode(rnLeaf, "\\")) inc(p.idx) elif p.tok[p.idx].symbol == "\\": # XXX: Unicode? inc(p.idx) - if p.tok[p.idx].kind != tkWhite: addSon(father, newLeaf(p)) + if p.tok[p.idx].kind != tkWhite: add(father, newLeaf(p)) inc(p.idx) else: - addSon(father, newLeaf(p)) + add(father, newLeaf(p)) inc(p.idx) when false: @@ -795,18 +778,18 @@ when false: if p.tok[p.idx+1].kind notin {tkWord, tkAdornment, tkOther, tkPunct}: break else: break - addSon(n, newLeaf(p)) + add(n, newLeaf(p)) inc(p.idx) - addSon(father, n) + add(father, n) elif not verbatim and roSupportSmilies in p.shared.options: let n = parseSmiley(p) if s != nil: - addSon(father, n) + add(father, n) else: var n = newLeaf(p) inc(p.idx) if p.tok[p.idx].symbol == "_": n = parsePostfix(p, n) - addSon(father, n) + add(father, n) proc parseUntil(p: var TRstParser, father: PRstNode, postfix: string, interpretBackslash: bool) = @@ -819,21 +802,21 @@ proc parseUntil(p: var TRstParser, father: PRstNode, postfix: string, elif interpretBackslash: parseBackslash(p, father) else: - addSon(father, newLeaf(p)) + add(father, newLeaf(p)) inc(p.idx) of tkAdornment, tkWord, tkOther: - addSon(father, newLeaf(p)) + add(father, newLeaf(p)) inc(p.idx) of tkIndent: - addSon(father, newRstNode(rnLeaf, " ")) + add(father, newRstNode(rnLeaf, " ")) inc(p.idx) if p.tok[p.idx].kind == tkIndent: - rstMessage(p, errXExpected, postfix) + rstMessage(p, meExpected, postfix) break of tkWhite: - addSon(father, newRstNode(rnLeaf, " ")) + add(father, newRstNode(rnLeaf, " ")) inc(p.idx) - else: rstMessage(p, errXExpected, postfix) + else: rstMessage(p, meExpected, postfix) proc parseInline(p: var TRstParser, father: PRstNode) = case p.tok[p.idx].kind @@ -842,54 +825,54 @@ proc parseInline(p: var TRstParser, father: PRstNode) = inc(p.idx) var n = newRstNode(rnTripleEmphasis) parseUntil(p, n, "***", true) - addSon(father, n) + add(father, n) elif isInlineMarkupStart(p, "**"): inc(p.idx) var n = newRstNode(rnStrongEmphasis) parseUntil(p, n, "**", true) - addSon(father, n) + add(father, n) elif isInlineMarkupStart(p, "*"): inc(p.idx) var n = newRstNode(rnEmphasis) parseUntil(p, n, "*", true) - addSon(father, n) + add(father, n) elif isInlineMarkupStart(p, "``"): inc(p.idx) var n = newRstNode(rnInlineLiteral) parseUntil(p, n, "``", false) - addSon(father, n) + add(father, n) elif isInlineMarkupStart(p, "`"): inc(p.idx) var n = newRstNode(rnInterpretedText) parseUntil(p, n, "`", true) n = parsePostfix(p, n) - addSon(father, n) + add(father, n) elif isInlineMarkupStart(p, "|"): inc(p.idx) var n = newRstNode(rnSubstitutionReferences) parseUntil(p, n, "|", false) - addSon(father, n) + add(father, n) else: if roSupportSmilies in p.s.options: let n = parseSmiley(p) if n != nil: - addSon(father, n) + add(father, n) return parseBackslash(p, father) of tkWord: if roSupportSmilies in p.s.options: let n = parseSmiley(p) if n != nil: - addSon(father, n) + add(father, n) return parseURL(p, father) of tkAdornment, tkOther, tkWhite: if roSupportSmilies in p.s.options: let n = parseSmiley(p) if n != nil: - addSon(father, n) + add(father, n) return - addSon(father, newLeaf(p)) + add(father, newLeaf(p)) inc(p.idx) else: nil @@ -944,8 +927,7 @@ const "title"] proc getDirKind(s: string): TDirKind = - var i: int - i = binaryStrSearch(DirIds, s) + let i = find(DirIds, s) if i >= 0: result = TDirKind(i) else: result = dkNone @@ -970,8 +952,8 @@ proc parseField(p: var TRstParser): PRstNode = pushInd(p, indent) parseSection(p, fieldbody) popInd(p) - addSon(result, fieldname) - addSon(result, fieldbody) + add(result, fieldname) + add(result, fieldbody) proc parseFields(p: var TRstParser): PRstNode = result = nil @@ -982,7 +964,7 @@ proc parseFields(p: var TRstParser): PRstNode = result = newRstNode(rnFieldList) if not atStart: inc(p.idx) while true: - addSon(result, parseField(p)) + add(result, parseField(p)) if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and (p.tok[p.idx + 1].symbol == ":"): inc(p.idx) @@ -996,7 +978,7 @@ proc getFieldValue(n: PRstNode, fieldname: string): string = #InternalError("getFieldValue (2): " & $n.sons[1].kind) # We don't like internal errors here anymore as that would break the forum! return - for i in countup(0, rsonsLen(n.sons[1]) - 1): + for i in countup(0, len(n.sons[1]) - 1): var f = n.sons[1].sons[i] if cmpIgnoreStyle(addNodes(f.sons[0]), fieldname) == 0: result = addNodes(f.sons[1]) @@ -1032,7 +1014,7 @@ proc parseLiteralBlock(p: var TRstParser): PRstNode = while not (p.tok[p.idx].kind in {tkIndent, tkEof}): add(n.text, p.tok[p.idx].symbol) inc(p.idx) - addSon(result, n) + add(result, n) proc getLevel(map: var TLevelMap, lvl: var int, c: Char): int = if map[c] == 0: @@ -1099,7 +1081,7 @@ proc whichSection(p: TRstParser): TRstNodeKind = result = rnEnumList elif match(p, p.idx, "+a+"): result = rnGridTable - rstMessage(p, errGridTableNotImplemented) + rstMessage(p, meGridTableNotImplemented) elif isDefList(p): result = rnDefList elif isOptionList(p): @@ -1123,7 +1105,7 @@ proc parseLineBlock(p: var TRstParser): PRstNode = while true: var item = newRstNode(rnLineBlockItem) parseSection(p, item) - addSon(result, item) + add(result, item) if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and (p.tok[p.idx + 1].symbol == "|") and (p.tok[p.idx + 2].kind == tkWhite): @@ -1143,9 +1125,9 @@ proc parseParagraph(p: var TRstParser, result: PRstNode) = inc(p.idx) case whichSection(p) of rnParagraph, rnLeaf, rnHeadline, rnOverline, rnDirective: - addSon(result, newRstNode(rnLeaf, " ")) + add(result, newRstNode(rnLeaf, " ")) of rnLineBlock: - addSonIfNotNil(result, parseLineBlock(p)) + addIfNotNil(result, parseLineBlock(p)) else: break else: break @@ -1153,9 +1135,9 @@ proc parseParagraph(p: var TRstParser, result: PRstNode) = if (p.tok[p.idx].symbol == "::") and (p.tok[p.idx + 1].kind == tkIndent) and (currInd(p) < p.tok[p.idx + 1].ival): - addSon(result, newRstNode(rnLeaf, ":")) + add(result, newRstNode(rnLeaf, ":")) inc(p.idx) # skip '::' - addSon(result, parseLiteralBlock(p)) + add(result, parseLiteralBlock(p)) break else: parseInline(p, result) @@ -1222,7 +1204,7 @@ proc parseSimpleTable(p: var TRstParser): PRstNode = getColumns(p, cols) setlen(row, len(cols)) if a != nil: - for j in 0..rsonsLen(a)-1: a.sons[j].kind = rnTableHeaderCell + for j in 0..len(a)-1: a.sons[j].kind = rnTableHeaderCell if p.tok[p.idx].kind == tkEof: break for j in countup(0, high(row)): row[j] = "" # the following while loop iterates over the lines a single cell may span: @@ -1248,9 +1230,9 @@ proc parseSimpleTable(p: var TRstParser): PRstNode = q.filename = p.filename getTokens(row[j], false, q.tok) b = newRstNode(rnTableDataCell) - addSon(b, parseDoc(q)) - addSon(a, b) - addSon(result, a) + add(b, parseDoc(q)) + add(a, b) + add(result, a) proc parseTransition(p: var TRstParser): PRstNode = result = newRstNode(rnTransition) @@ -1267,7 +1249,7 @@ proc parseOverline(p: var TRstParser): PRstNode = if p.tok[p.idx].kind == tkIndent: inc(p.idx) if p.tok[p.idx - 1].ival > currInd(p): - addSon(result, newRstNode(rnLeaf, " ")) + add(result, newRstNode(rnLeaf, " ")) else: break else: @@ -1288,7 +1270,7 @@ proc parseBulletList(p: var TRstParser): PRstNode = while true: var item = newRstNode(rnBulletItem) parseSection(p, item) - addSon(result, item) + add(result, item) if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and (p.tok[p.idx + 1].symbol == bullet) and (p.tok[p.idx + 2].kind == tkWhite): @@ -1309,7 +1291,7 @@ proc parseOptionList(p: var TRstParser): PRstNode = if (p.tok[p.idx].kind == tkWhite) and (len(p.tok[p.idx].symbol) > 1): inc(p.idx) break - addSon(a, newLeaf(p)) + add(a, newLeaf(p)) inc(p.idx) var j = tokenAfterNewline(p) if (j > 0) and (p.tok[j - 1].kind == tkIndent) and @@ -1320,9 +1302,9 @@ proc parseOptionList(p: var TRstParser): PRstNode = else: parseLine(p, b) if (p.tok[p.idx].kind == tkIndent): inc(p.idx) - addSon(c, a) - addSon(c, b) - addSon(result, c) + add(c, a) + add(c, b) + add(result, c) else: break @@ -1345,9 +1327,9 @@ proc parseDefinitionList(p: var TRstParser): PRstNode = var b = newRstNode(rnDefBody) parseSection(p, b) var c = newRstNode(rnDefItem) - addSon(c, a) - addSon(c, b) - addSon(result, c) + add(c, a) + add(c, b) + add(result, c) popInd(p) else: p.idx = j @@ -1360,7 +1342,7 @@ proc parseDefinitionList(p: var TRstParser): PRstNode = nil else: break - if rsonsLen(result) == 0: result = nil + if len(result) == 0: result = nil proc parseEnumList(p: var TRstParser): PRstNode = const @@ -1381,7 +1363,7 @@ proc parseEnumList(p: var TRstParser): PRstNode = while true: var item = newRstNode(rnEnumItem) parseSection(p, item) - addSon(result, item) + add(result, item) if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col) and match(p, p.idx + 1, wildcards[w]): inc(p.idx, wildpos[w] + 4) @@ -1394,7 +1376,7 @@ proc parseEnumList(p: var TRstParser): PRstNode = proc sonKind(father: PRstNode, i: int): TRstNodeKind = result = rnLeaf - if i < rsonsLen(father): result = father.sons[i].kind + if i < len(father): result = father.sons[i].kind proc parseSection(p: var TRstParser, result: PRstNode) = while true: @@ -1407,7 +1389,7 @@ proc parseSection(p: var TRstParser, result: PRstNode) = pushInd(p, p.tok[p.idx].ival) var a = newRstNode(rnBlockQuote) parseSection(p, a) - addSon(result, a) + add(result, a) popInd(p) else: leave = true @@ -1424,7 +1406,7 @@ proc parseSection(p: var TRstParser, result: PRstNode) = of rnLineblock: a = parseLineBlock(p) of rnDirective: a = parseDotDot(p) of rnEnumList: a = parseEnumList(p) - of rnLeaf: rstMessage(p, errNewSectionExpected) + of rnLeaf: rstMessage(p, meNewSectionExpected) of rnParagraph: nil of rnDefList: a = parseDefinitionList(p) of rnFieldList: @@ -1441,19 +1423,19 @@ proc parseSection(p: var TRstParser, result: PRstNode) = if a == nil and k != rnDirective: a = newRstNode(rnParagraph) parseParagraph(p, a) - addSonIfNotNil(result, a) + addIfNotNil(result, a) if sonKind(result, 0) == rnParagraph and sonKind(result, 1) != rnParagraph: result.sons[0].kind = rnInner proc parseSectionWrapper(p: var TRstParser): PRstNode = result = newRstNode(rnInner) parseSection(p, result) - while (result.kind == rnInner) and (rsonsLen(result) == 1): + while (result.kind == rnInner) and (len(result) == 1): result = result.sons[0] proc parseDoc(p: var TRstParser): PRstNode = result = parseSectionWrapper(p) - if p.tok[p.idx].kind != tkEof: rstMessage(p, errGeneralParseError) + if p.tok[p.idx].kind != tkEof: rstMessage(p, meGeneralParseError) type TDirFlag = enum @@ -1471,24 +1453,24 @@ proc parseDirective(p: var TRstParser, flags: TDirFlags): PRstNode = while True: case p.tok[p.idx].kind of tkWord, tkOther, tkPunct, tkAdornment: - addSon(args, newLeaf(p)) + add(args, newLeaf(p)) inc(p.idx) else: break elif argIsWord in flags: while p.tok[p.idx].kind == tkWhite: inc(p.idx) if p.tok[p.idx].kind == tkWord: - addSon(args, newLeaf(p)) + add(args, newLeaf(p)) inc(p.idx) else: args = nil else: parseLine(p, args) - addSon(result, args) + add(result, args) if hasOptions in flags: if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival >= 3) and (p.tok[p.idx + 1].symbol == ":"): options = parseFields(p) - addSon(result, options) + add(result, options) proc indFollows(p: TRstParser): bool = result = p.tok[p.idx].kind == tkIndent and p.tok[p.idx].ival > currInd(p) @@ -1500,9 +1482,9 @@ proc parseDirective(p: var TRstParser, flags: TDirFlags, pushInd(p, p.tok[p.idx].ival) var content = contentParser(p) popInd(p) - addSon(result, content) + add(result, content) else: - addSon(result, nil) + add(result, nil) proc parseDirBody(p: var TRstParser, contentParser: TSectionParser): PRstNode = if indFollows(p): @@ -1530,14 +1512,14 @@ proc dirInclude(p: var TRstParser): PRstNode = result = nil var n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil) var filename = strip(addNodes(n.sons[0])) - var path = findFile(filename) + var path = p.s.findFile(filename) if path == "": - rstMessage(p, errCannotOpenFile, filename) + rstMessage(p, meCannotOpenFile, filename) else: # XXX: error handling; recursive file inclusion! if getFieldValue(n, "literal") != "": result = newRstNode(rnLiteralBlock) - addSon(result, newRstNode(rnLeaf, readFile(path))) + add(result, newRstNode(rnLeaf, readFile(path))) else: var q: TRstParser initParser(q, p.s) @@ -1552,17 +1534,17 @@ proc dirCodeBlock(p: var TRstParser): PRstNode = result = parseDirective(p, {hasArg, hasOptions}, parseLiteralBlock) var filename = strip(getFieldValue(result, "file")) if filename != "": - var path = findFile(filename) - if path == "": rstMessage(p, errCannotOpenFile, filename) + var path = p.s.findFile(filename) + if path == "": rstMessage(p, meCannotOpenFile, filename) var n = newRstNode(rnLiteralBlock) - addSon(n, newRstNode(rnLeaf, readFile(path))) + add(n, newRstNode(rnLeaf, readFile(path))) result.sons[2] = n result.kind = rnCodeBlock proc dirContainer(p: var TRstParser): PRstNode = result = parseDirective(p, {hasArg}, parseSectionWrapper) assert(result.kind == rnDirective) - assert(rsonsLen(result) == 3) + assert(len(result) == 3) result.kind = rnContainer proc dirImage(p: var TRstParser): PRstNode = @@ -1590,16 +1572,16 @@ proc dirRawAux(p: var TRstParser, result: var PRstNode, kind: TRstNodeKind, contentParser: TSectionParser) = var filename = getFieldValue(result, "file") if filename.len > 0: - var path = findFile(filename) + var path = p.s.findFile(filename) if path.len == 0: - rstMessage(p, errCannotOpenFile, filename) + rstMessage(p, meCannotOpenFile, filename) else: var f = readFile(path) result = newRstNode(kind) - addSon(result, newRstNode(rnLeaf, f)) + add(result, newRstNode(rnLeaf, f)) else: result.kind = kind - addSon(result, parseDirBody(p, contentParser)) + add(result, parseDirBody(p, contentParser)) proc dirRaw(p: var TRstParser): PRstNode = # @@ -1617,7 +1599,7 @@ proc dirRaw(p: var TRstParser): PRstNode = elif cmpIgnoreCase(result.sons[0].sons[0].text, "latex") == 0: dirRawAux(p, result, rnRawLatex, parseLiteralBlock) else: - rstMessage(p, errInvalidDirectiveX, result.sons[0].text) + rstMessage(p, meInvalidDirective, result.sons[0].text) else: dirRawAux(p, result, rnRaw, parseSectionWrapper) @@ -1639,10 +1621,10 @@ proc parseDotDot(p: var TRstParser): PRstNode = if roSupportRawDirective in p.s.options: result = dirRaw(p) else: - rstMessage(p, errInvalidDirectiveX, d) + rstMessage(p, meInvalidDirective, d) of dkCodeblock: result = dirCodeBlock(p) of dkIndex: result = dirIndex(p) - else: rstMessage(p, errInvalidDirectiveX, d) + else: rstMessage(p, meInvalidDirective, d) popInd(p) elif match(p, p.idx, " _"): # hyperlink target: @@ -1665,7 +1647,7 @@ proc parseDotDot(p: var TRstParser): PRstNode = inc(p.idx) b = dirImage(p) else: - rstMessage(p, errInvalidDirectiveX, p.tok[p.idx].symbol) + rstMessage(p, meInvalidDirective, p.tok[p.idx].symbol) setSub(p, addNodes(a), b) elif match(p, p.idx, " ["): # footnotes, citations @@ -1689,27 +1671,28 @@ proc resolveSubs(p: var TRstParser, n: PRstNode): PRstNode = var key = addNodes(n) var e = getEnv(key) if e != "": result = newRstNode(rnLeaf, e) - else: rstMessage(p, warnUnknownSubstitutionX, key) + else: rstMessage(p, mwUnknownSubstitution, key) of rnRef: var y = findRef(p, rstnodeToRefname(n)) if y != nil: result = newRstNode(rnHyperlink) n.kind = rnInner - addSon(result, n) - addSon(result, y) + add(result, n) + add(result, y) of rnLeaf: nil of rnContents: p.hasToc = true else: - for i in countup(0, rsonsLen(n) - 1): n.sons[i] = resolveSubs(p, n.sons[i]) + for i in countup(0, len(n) - 1): n.sons[i] = resolveSubs(p, n.sons[i]) -proc rstParse(text, filename: string, - line, column: int, hasToc: var bool, - options: TRstParseOptions): PRstNode = +proc rstParse*(text, filename: string, + line, column: int, hasToc: var bool, + options: TRstParseOptions, + findFile: TFindFileHandler = nil, + msgHandler: TMsgHandler = nil): PRstNode = var p: TRstParser - if isNil(text): rawMessage(errCannotOpenFile, filename) - initParser(p, newSharedState(options)) + initParser(p, newSharedState(options, findFile, msgHandler)) p.filename = filename p.line = line p.col = column diff --git a/packages/docutils/rstast.nim b/packages/docutils/rstast.nim new file mode 100644 index 000000000..23233fd39 --- /dev/null +++ b/packages/docutils/rstast.nim @@ -0,0 +1,288 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2012 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements an AST for the `reStructuredText`:idx parser. + +import strutils + +type + TRstNodeKind* = enum ## the possible node kinds of an PRstNode + rnInner, # an inner node or a root + rnHeadline, # a headline + rnOverline, # an over- and underlined headline + rnTransition, # a transition (the ------------- <hr> thingie) + rnParagraph, # a paragraph + rnBulletList, # a bullet list + rnBulletItem, # a bullet item + rnEnumList, # an enumerated list + rnEnumItem, # an enumerated item + rnDefList, # a definition list + rnDefItem, # an item of a definition list consisting of ... + rnDefName, # ... a name part ... + rnDefBody, # ... and a body part ... + rnFieldList, # a field list + rnField, # a field item + rnFieldName, # consisting of a field name ... + rnFieldBody, # ... and a field body + rnOptionList, rnOptionListItem, rnOptionGroup, rnOption, rnOptionString, + rnOptionArgument, rnDescription, rnLiteralBlock, rnQuotedLiteralBlock, + rnLineBlock, # the | thingie + rnLineBlockItem, # sons of the | thing + rnBlockQuote, # text just indented + rnTable, rnGridTable, rnTableRow, rnTableHeaderCell, rnTableDataCell, + rnLabel, # used for footnotes and other things + rnFootnote, # a footnote + rnCitation, # similar to footnote + rnStandaloneHyperlink, rnHyperlink, rnRef, rnDirective, # a directive + rnDirArg, rnRaw, rnTitle, rnContents, rnImage, rnFigure, rnCodeBlock, + rnRawHtml, rnRawLatex, + rnContainer, # ``container`` directive + rnIndex, # index directve: + # .. index:: + # key + # * `file#id <file#id>`_ + # * `file#id <file#id>'_ + rnSubstitutionDef, # a definition of a substitution + rnGeneralRole, # Inline markup: + rnSub, rnSup, rnIdx, + rnEmphasis, # "*" + rnStrongEmphasis, # "**" + rnTripleEmphasis, # "***" + rnInterpretedText, # "`" + rnInlineLiteral, # "``" + rnSubstitutionReferences, # "|" + rnSmiley, # some smiley + rnLeaf # a leaf; the node's text field contains the + # leaf val + + + PRSTNode* = ref TRstNode ## an RST node + TRstNodeSeq* = seq[PRstNode] + TRSTNode* {.acyclic, final.} = object ## an RST node's description + kind*: TRstNodeKind ## the node's kind + text*: string ## valid for leafs in the AST; and the title of + ## the document or the section + level*: int ## valid for some node kinds + sons*: TRstNodeSeq ## the node's sons + +proc len*(n: PRstNode): int = + result = len(n.sons) + +proc newRstNode*(kind: TRstNodeKind): PRstNode = + new(result) + result.sons = @[] + result.kind = kind + +proc newRstNode*(kind: TRstNodeKind, s: string): PRstNode = + result = newRstNode(kind) + result.text = s + +proc lastSon*(n: PRstNode): PRstNode = + result = n.sons[len(n.sons)-1] + +proc add*(father, son: PRstNode) = + add(father.sons, son) + +proc addIfNotNil*(father, son: PRstNode) = + if son != nil: add(father, son) + + +type + TRenderContext {.pure.} = object + indent: int + verbatim: int + +proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) + +proc renderRstSons(d: var TRenderContext, n: PRstNode, result: var string) = + for i in countup(0, len(n) - 1): + renderRstToRst(d, n.sons[i], result) + +proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) = + # this is needed for the index generation; it may also be useful for + # debugging, but most code is already debugged... + const + lvlToChar: array[0..8, char] = ['!', '=', '-', '~', '`', '<', '*', '|', '+'] + if n == nil: return + var ind = repeatChar(d.indent) + case n.kind + of rnInner: + renderRstSons(d, n, result) + of rnHeadline: + result.add("\n") + result.add(ind) + + let oldLen = result.len + renderRstSons(d, n, result) + let HeadlineLen = result.len - oldLen + + result.add("\n") + result.add(ind) + result.add repeatChar(HeadlineLen, lvlToChar[n.level]) + of rnOverline: + result.add("\n") + result.add(ind) + + var headline = "" + renderRstSons(d, n, headline) + + let lvl = repeatChar(headline.Len - d.indent, lvlToChar[n.level]) + result.add(lvl) + result.add("\n") + result.add(headline) + + result.add("\n") + result.add(ind) + result.add(lvl) + of rnTransition: + result.add("\n\n") + result.add(ind) + result.add repeatChar(78-d.indent, '-') + result.add("\n\n") + of rnParagraph: + result.add("\n\n") + result.add(ind) + renderRstSons(d, n, result) + of rnBulletItem: + inc(d.indent, 2) + var tmp = "" + renderRstSons(d, n, tmp) + if tmp.len > 0: + result.add("\n") + result.add(ind) + result.add("* ") + result.add(tmp) + dec(d.indent, 2) + of rnEnumItem: + inc(d.indent, 4) + var tmp = "" + renderRstSons(d, n, tmp) + if tmp.len > 0: + result.add("\n") + result.add(ind) + result.add("(#) ") + result.add(tmp) + dec(d.indent, 4) + of rnOptionList, rnFieldList, rnDefList, rnDefItem, rnLineBlock, rnFieldName, + rnFieldBody, rnStandaloneHyperlink, rnBulletList, rnEnumList: + renderRstSons(d, n, result) + of rnDefName: + result.add("\n\n") + result.add(ind) + renderRstSons(d, n, result) + of rnDefBody: + inc(d.indent, 2) + if n.sons[0].kind != rnBulletList: + result.add("\n") + result.add(ind) + result.add(" ") + renderRstSons(d, n, result) + dec(d.indent, 2) + of rnField: + var tmp = "" + renderRstToRst(d, n.sons[0], tmp) + + var L = max(tmp.len + 3, 30) + inc(d.indent, L) + + result.add "\n" + result.add ind + result.add ':' + result.add tmp + result.add ':' + result.add repeatChar(L - tmp.len - 2) + renderRstToRst(d, n.sons[1], result) + + dec(d.indent, L) + of rnLineBlockItem: + result.add("\n") + result.add(ind) + result.add("| ") + renderRstSons(d, n, result) + of rnBlockQuote: + inc(d.indent, 2) + renderRstSons(d, n, result) + dec(d.indent, 2) + of rnRef: + result.add("`") + renderRstSons(d, n, result) + result.add("`_") + of rnHyperlink: + result.add('`') + renderRstToRst(d, n.sons[0], result) + result.add(" <") + renderRstToRst(d, n.sons[1], result) + result.add(">`_") + of rnGeneralRole: + result.add('`') + renderRstToRst(d, n.sons[0],result) + result.add("`:") + renderRstToRst(d, n.sons[1],result) + result.add(':') + of rnSub: + result.add('`') + renderRstSons(d, n, result) + result.add("`:sub:") + of rnSup: + result.add('`') + renderRstSons(d, n, result) + result.add("`:sup:") + of rnIdx: + result.add('`') + renderRstSons(d, n, result) + result.add("`:idx:") + of rnEmphasis: + result.add("*") + renderRstSons(d, n, result) + result.add("*") + of rnStrongEmphasis: + result.add("**") + renderRstSons(d, n, result) + result.add("**") + of rnTripleEmphasis: + result.add("***") + renderRstSons(d, n, result) + result.add("***") + of rnInterpretedText: + result.add('`') + renderRstSons(d, n, result) + result.add('`') + of rnInlineLiteral: + inc(d.verbatim) + result.add("``") + renderRstSons(d, n, result) + result.add("``") + dec(d.verbatim) + of rnSmiley: + result.add(n.text) + of rnLeaf: + if d.verbatim == 0 and n.text == "\\": + result.add("\\\\") # XXX: escape more special characters! + else: + result.add(n.text) + of rnIndex: + result.add("\n\n") + result.add(ind) + result.add(".. index::\n") + + inc(d.indent, 3) + if n.sons[2] != nil: renderRstSons(d, n.sons[2], result) + dec(d.indent, 3) + of rnContents: + result.add("\n\n") + result.add(ind) + result.add(".. contents::") + else: + result.add("Error: cannot render: " & $n.kind) + +proc renderRstToRst*(n: PRstNode, result: var string) = + ## renders `n` into its string representation and appends to `result`. + var d: TRenderContext + renderRstToRst(d, n, result) + diff --git a/packages/docutils/rstgen.nim b/packages/docutils/rstgen.nim new file mode 100644 index 000000000..93544124f --- /dev/null +++ b/packages/docutils/rstgen.nim @@ -0,0 +1,87 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2012 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements a generator of HTML/Latex from `reStructuredText`:idx. + +import strutils, strtabs, rstast + +type + TOutputTarget* = enum ## which document type to generate + outHtml, # output is HTML + outLatex # output is Latex + + +proc addXmlChar(dest: var string, c: Char) = + case c + of '&': add(dest, "&") + of '<': add(dest, "<") + of '>': add(dest, ">") + of '\"': add(dest, """) + else: add(dest, c) + +proc addRtfChar(dest: var string, c: Char) = + case c + of '{': add(dest, "\\{") + of '}': add(dest, "\\}") + of '\\': add(dest, "\\\\") + else: add(dest, c) + +proc addTexChar(dest: var string, c: Char) = + case c + of '_': add(dest, "\\_") + of '{': add(dest, "\\symbol{123}") + of '}': add(dest, "\\symbol{125}") + of '[': add(dest, "\\symbol{91}") + of ']': add(dest, "\\symbol{93}") + of '\\': add(dest, "\\symbol{92}") + of '$': add(dest, "\\$") + of '&': add(dest, "\\&") + of '#': add(dest, "\\#") + of '%': add(dest, "\\%") + of '~': add(dest, "\\symbol{126}") + of '@': add(dest, "\\symbol{64}") + of '^': add(dest, "\\symbol{94}") + of '`': add(dest, "\\symbol{96}") + else: add(dest, c) + +var splitter*: string = "<wbr />" + +proc escChar*(target: TOutputTarget, dest: var string, c: Char) {.inline.} = + case target + of outHtml: addXmlChar(dest, c) + of outLatex: addTexChar(dest, c) + +proc nextSplitPoint*(s: string, start: int): int = + result = start + while result < len(s) + 0: + case s[result] + of '_': return + of 'a'..'z': + if result + 1 < len(s) + 0: + if s[result + 1] in {'A'..'Z'}: return + else: nil + inc(result) + dec(result) # last valid index + +proc esc*(target: TOutputTarget, s: string, splitAfter = -1): string = + result = "" + if splitAfter >= 0: + var partLen = 0 + var j = 0 + while j < len(s): + var k = nextSplitPoint(s, j) + if (splitter != " ") or (partLen + k - j + 1 > splitAfter): + partLen = 0 + add(result, splitter) + for i in countup(j, k): escChar(target, result, s[i]) + inc(partLen, k - j + 1) + j = k + 1 + else: + for i in countup(0, len(s) - 1): escChar(target, result, s[i]) + \ No newline at end of file diff --git a/web/news.txt b/web/news.txt index 578e2203c..cff4bcbec 100755 --- a/web/news.txt +++ b/web/news.txt @@ -42,9 +42,10 @@ Library Additions - Added overload for ``system.items`` that can be used to iterate over the values of an enum. - Added ``system.TInteger`` and ``system.TNumber`` type classes matching - any of the corresponding type available in nimrod. + any of the corresponding types available in nimrod. - Added ``system.clamp`` to limit a value within an interval ``[a, b]``. - Added ``strutils.continuesWith``. +- Added ``system.getStackTrace``. - The GC supports (soft) realtime systems via ``GC_setMaxPause`` and ``GC_step`` procs. |