summary refs log tree commit diff stats
path: root/rod/ptmplsyn.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/ptmplsyn.nim')
-rwxr-xr-xrod/ptmplsyn.nim185
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)