diff options
Diffstat (limited to 'rod/ptmplsyn.nim')
-rwxr-xr-x | rod/ptmplsyn.nim | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/rod/ptmplsyn.nim b/rod/ptmplsyn.nim new file mode 100755 index 000000000..ad3a73b70 --- /dev/null +++ b/rod/ptmplsyn.nim @@ -0,0 +1,185 @@ +# +# +# The Nimrod Compiler +# (c) Copyright 2009 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# This module implements Nimrod's standard template filter. + +import + llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, + rnimsyn, filters + +proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode): PLLStream + # #! template(subsChar='$', metaChar='#') | standard(version="0.7.2") +# implementation + +type + TParseState = enum + psDirective, psTempl + TTmplParser{.final.} = object + inp*: PLLStream + state*: TParseState + info*: TLineInfo + indent*, par*: int + x*: string # the current input line + outp*: PLLStream # the ouput will be parsed by pnimsyn + subsChar*, NimDirective*: Char + emit*, conc*, toStr*: string + + +const + PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '.', '_'} + +proc newLine(p: var TTmplParser) = + LLStreamWrite(p.outp, repeatChar(p.par, ')')) + p.par = 0 + if p.info.line > int16(1): LLStreamWrite(p.outp, "\n") + +proc parseLine(p: var TTmplParser) = + var + d, j, curly: int + keyw: string + j = 0 + while p.x[j] == ' ': inc(j) + if (p.x[0] == p.NimDirective) and (p.x[0 + 1] == '!'): + newLine(p) + elif (p.x[j] == p.NimDirective): + newLine(p) + inc(j) + while p.x[j] == ' ': inc(j) + d = j + keyw = "" + while p.x[j] in PatternChars: + add(keyw, p.x[j]) + inc(j) + case whichKeyword(keyw) + of wEnd: + if p.indent >= 2: + dec(p.indent, 2) + else: + p.info.col = int16(j) + liMessage(p.info, errXNotAllowedHere, "end") + LLStreamWrite(p.outp, repeatChar(p.indent)) + LLStreamWrite(p.outp, "#end") + of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator, + wConverter, wMacro, wTemplate, wMethod: + LLStreamWrite(p.outp, repeatChar(p.indent)) + LLStreamWrite(p.outp, copy(p.x, d)) + inc(p.indent, 2) + of wElif, wOf, wElse, wExcept, wFinally: + LLStreamWrite(p.outp, repeatChar(p.indent - 2)) + LLStreamWrite(p.outp, copy(p.x, d)) + else: + LLStreamWrite(p.outp, repeatChar(p.indent)) + LLStreamWrite(p.outp, copy(p.x, d)) + p.state = psDirective + else: + # data line + j = 0 + case p.state + of psTempl: + # next line of string literal: + LLStreamWrite(p.outp, p.conc) + LLStreamWrite(p.outp, "\n") + LLStreamWrite(p.outp, repeatChar(p.indent + 2)) + LLStreamWrite(p.outp, "\"") + of psDirective: + newLine(p) + LLStreamWrite(p.outp, repeatChar(p.indent)) + LLStreamWrite(p.outp, p.emit) + LLStreamWrite(p.outp, "(\"") + inc(p.par) + p.state = psTempl + while true: + case p.x[j] + of '\0': + break + of '\x01'..'\x1F', '\x80'..'\xFF': + LLStreamWrite(p.outp, "\\x") + LLStreamWrite(p.outp, toHex(ord(p.x[j]), 2)) + inc(j) + of '\\': + LLStreamWrite(p.outp, "\\\\") + inc(j) + of '\'': + LLStreamWrite(p.outp, "\\\'") + inc(j) + of '\"': + LLStreamWrite(p.outp, "\\\"") + inc(j) + else: + if p.x[j] == p.subsChar: + # parse Nimrod expression: + inc(j) + case p.x[j] + of '{': + p.info.col = int16(j) + LLStreamWrite(p.outp, '\"') + LLStreamWrite(p.outp, p.conc) + LLStreamWrite(p.outp, p.toStr) + LLStreamWrite(p.outp, '(') + inc(j) + curly = 0 + while true: + case p.x[j] + of '\0': + liMessage(p.info, errXExpected, "}") + of '{': + inc(j) + inc(curly) + LLStreamWrite(p.outp, '{') + of '}': + inc(j) + if curly == 0: break + if curly > 0: dec(curly) + LLStreamWrite(p.outp, '}') + else: + LLStreamWrite(p.outp, p.x[j]) + inc(j) + LLStreamWrite(p.outp, ')') + LLStreamWrite(p.outp, p.conc) + LLStreamWrite(p.outp, '\"') + of 'a'..'z', 'A'..'Z', '\x80'..'\xFF': + LLStreamWrite(p.outp, '\"') + LLStreamWrite(p.outp, p.conc) + LLStreamWrite(p.outp, p.toStr) + LLStreamWrite(p.outp, '(') + while p.x[j] in PatternChars: + LLStreamWrite(p.outp, p.x[j]) + inc(j) + LLStreamWrite(p.outp, ')') + LLStreamWrite(p.outp, p.conc) + LLStreamWrite(p.outp, '\"') + else: + if p.x[j] == p.subsChar: + LLStreamWrite(p.outp, p.subsChar) + inc(j) + else: + p.info.col = int16(j) + liMessage(p.info, errInvalidExpression, "$") + else: + LLStreamWrite(p.outp, p.x[j]) + inc(j) + LLStreamWrite(p.outp, "\\n\"") + +proc filterTmpl(stdin: PLLStream, filename: string, call: PNode): PLLStream = + var p: TTmplParser + p.info = newLineInfo(filename, 0, 0) + p.outp = LLStreamOpen("") + p.inp = stdin + p.subsChar = charArg(call, "subschar", 1, '$') + p.nimDirective = charArg(call, "metachar", 2, '#') + p.emit = strArg(call, "emit", 3, "result.add") + p.conc = strArg(call, "conc", 4, " & ") + p.toStr = strArg(call, "tostring", 5, "$") + while not LLStreamAtEnd(p.inp): + p.x = LLStreamReadLine(p.inp) + p.info.line = p.info.line + int16(1) + parseLine(p) + newLine(p) + result = p.outp + LLStreamClose(p.inp) |