summary refs log tree commit diff stats
path: root/nim/ptmplsyn.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/ptmplsyn.pas')
-rwxr-xr-xnim/ptmplsyn.pas210
1 files changed, 81 insertions, 129 deletions
diff --git a/nim/ptmplsyn.pas b/nim/ptmplsyn.pas
index 2368b22c7..717da6ee0 100755
--- a/nim/ptmplsyn.pas
+++ b/nim/ptmplsyn.pas
@@ -1,28 +1,31 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
 //
 unit ptmplsyn;
 
-// This module implements the parser of the Nimrod Template files.
+// This module implements Nimrod's standard template filter.
 
 {$include config.inc}
 
 interface
 
 uses
-  nsystem, llstream, nos, charsets, wordrecg, strutils,
-  ast, astalgo, msgs, options, pnimsyn;
+  nsystem, llstream, nos, charsets, wordrecg, idents, strutils,
+  ast, astalgo, msgs, options, rnimsyn, filters;
 
-function ParseTmplFile(const filename: string): PNode;
+function filterTmpl(input: PLLStream; const filename: string;
+                    call: PNode): PLLStream;
+// #! template(subsChar='$', metaChar='#') | standard(version="0.7.2")
 
+implementation
 
 type
-  TParseState = (psDirective, psMultiDir, psTempl);
+  TParseState = (psDirective, psTempl);
   TTmplParser = record
     inp: PLLStream;
     state: TParseState;
@@ -30,19 +33,11 @@ type
     indent, par: int;
     x: string; // the current input line
     outp: PLLStream; // the ouput will be parsed by pnimsyn
-    subsChar: Char;
+    subsChar, NimDirective: Char;
+    emit, conc, toStr: string;
   end;
 
-function ParseTmpl(var p: TTmplParser): PNode;
-
-procedure openTmplParser(var p: TTmplParser; const filename: string;
-                         inputStream: PLLStream);
-procedure closeTmplParser(var p: TTmplParser);
-
-implementation
-
 const
-  NimDirective = '#';
   PatternChars = ['a'..'z', 'A'..'Z', '0'..'9', #128..#255, '.', '_'];
 
 procedure newLine(var p: TTmplParser);
@@ -59,73 +54,45 @@ var
 begin
   j := strStart;
   while p.x[j] = ' ' do inc(j);
-  if p.state = psMultiDir then begin
-    newLine(p);
-    if p.x[j] = '*' then begin
-      inc(j);
-      if p.x[j] = NimDirective then p.state := psTempl;
-      // ignore the rest of the line
-    end
-    else
-      LLStreamWrite(p.outp, p.x); // simply add the whole line
-  end
-  else if p.x[j] = NimDirective then begin
+  if (p.x[strStart] = p.NimDirective) and (p.x[strStart+1] = '!') then
+    newLine(p)
+  else if (p.x[j] = p.NimDirective) then begin
     newLine(p);
     inc(j);
     while p.x[j] = ' ' do inc(j);
     d := j;
-    if p.x[j] = '*' then begin
+    keyw := '';
+    while p.x[j] in PatternChars do begin
+      addChar(keyw, p.x[j]);
       inc(j);
-      p.state := psMultiDir;
-      LLStreamWrite(p.outp, repeatChar(p.indent));
-      LLStreamWrite(p.outp, '#*');
-      LLStreamWrite(p.outp, ncopy(p.x, j)); // simply add the whole line
-    end
-    else begin
-      keyw := '';
-      while p.x[j] in PatternChars do begin
-        addChar(keyw, p.x[j]);
-        inc(j);
-      end;
-      case whichKeyword(keyw) of
-        wEnd: begin
-          if p.indent >= 2 then
-            dec(p.indent, 2)
-          else begin
-            p.info.col := int16(j);
-            liMessage(p.info, errXNotAllowedHere, 'end');
-          end;
-          LLStreamWrite(p.outp, repeatChar(p.indent));
-          LLStreamWrite(p.outp, '#end');
-        end;
-        wSubsChar: begin
-          LLStreamWrite(p.outp, repeatChar(p.indent));
-          LLStreamWrite(p.outp, '#subschar');
-          while p.x[j] = ' ' do inc(j);
-          if p.x[j] in ['+', '-', '*', '/', '<', '>', '!', '?', '^', '.',
-                 '|', '=', '%', '&', '$', '@', '~'] then p.subsChar := p.x[j]
-          else begin
-            p.info.col := int16(j);
-            liMessage(p.info, errXNotAllowedHere, p.x[j]+'');
-          end
-        end;
-        wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator,
-        wConverter, wMacro, wTemplate: begin
-          LLStreamWrite(p.outp, repeatChar(p.indent));
-          LLStreamWrite(p.outp, ncopy(p.x, d));
-          inc(p.indent, 2);
-        end;
-        wElif, wOf, wElse, wExcept, wFinally: begin
-          LLStreamWrite(p.outp, repeatChar(p.indent-2));
-          LLStreamWrite(p.outp, ncopy(p.x, d));
-        end
+    end;
+    case whichKeyword(keyw) of
+      wEnd: begin
+        if p.indent >= 2 then
+          dec(p.indent, 2)
         else begin
-          LLStreamWrite(p.outp, repeatChar(p.indent));
-          LLStreamWrite(p.outp, ncopy(p.x, d));
-        end
+          p.info.col := int16(j);
+          liMessage(p.info, errXNotAllowedHere, 'end');
+        end;
+        LLStreamWrite(p.outp, repeatChar(p.indent));
+        LLStreamWrite(p.outp, '#end');
+      end;
+      wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator,
+      wConverter, wMacro, wTemplate, wMethod: begin
+        LLStreamWrite(p.outp, repeatChar(p.indent));
+        LLStreamWrite(p.outp, ncopy(p.x, d));
+        inc(p.indent, 2);
       end;
-      p.state := psDirective;
-    end
+      wElif, wOf, wElse, wExcept, wFinally: begin
+        LLStreamWrite(p.outp, repeatChar(p.indent-2));
+        LLStreamWrite(p.outp, ncopy(p.x, d));
+      end
+      else begin
+        LLStreamWrite(p.outp, repeatChar(p.indent));
+        LLStreamWrite(p.outp, ncopy(p.x, d));
+      end
+    end;
+    p.state := psDirective
   end
   else begin
     // data line
@@ -133,17 +100,18 @@ begin
     case p.state of
       psTempl: begin
         // next line of string literal:
-        LLStreamWrite(p.outp, ' &'+nl);
+        LLStreamWrite(p.outp, p.conc);
+        LLStreamWrite(p.outp, nl);
         LLStreamWrite(p.outp, repeatChar(p.indent + 2));
         LLStreamWrite(p.outp, '"'+'');
       end;
       psDirective: begin
         newLine(p);
         LLStreamWrite(p.outp, repeatChar(p.indent));
-        LLStreamWrite(p.outp, 'add(result, "');
+        LLStreamWrite(p.outp, p.emit);
+        LLStreamWrite(p.outp, '("');
         inc(p.par);
-      end;
-      else InternalError(p.info, 'parser in invalid state');
+      end
     end;
     p.state := psTempl;
     while true do begin
@@ -162,7 +130,10 @@ begin
           case p.x[j] of
             '{': begin
               p.info.col := int16(j);
-              LLStreamWrite(p.outp, '" & $(');
+              LLStreamWrite(p.outp, '"');
+              LLStreamWrite(p.outp, p.conc);
+              LLStreamWrite(p.outp, p.toStr);
+              LLStreamWrite(p.outp, '(');
               inc(j);
               curly := 0;
               while true do begin
@@ -171,13 +142,13 @@ begin
                   '{': begin
                     inc(j);
                     inc(curly);
-                    LLStreamWrite(p.outp, '{'+'');
+                    LLStreamWrite(p.outp, '{');
                   end;
                   '}': begin
                     inc(j);
                     if curly = 0 then break;
                     if curly > 0 then dec(curly);
-                    LLStreamWrite(p.outp, '}'+'');
+                    LLStreamWrite(p.outp, '}');
                   end;
                   else begin
                     LLStreamWrite(p.outp, p.x[j]);
@@ -185,15 +156,22 @@ begin
                   end
                 end
               end;
-              LLStreamWrite(p.outp, ') & "')
+              LLStreamWrite(p.outp, ')');
+              LLStreamWrite(p.outp, p.conc);
+              LLStreamWrite(p.outp, '"');
             end;
-            'A'..'Z', 'a'..'z', '_': begin
-              LLStreamWrite(p.outp, '" & $');
+            'a'..'z', 'A'..'Z', #128..#255: begin
+              LLStreamWrite(p.outp, '"');
+              LLStreamWrite(p.outp, p.conc);
+              LLStreamWrite(p.outp, p.toStr);
+              LLStreamWrite(p.outp, '(');
               while p.x[j] in PatternChars do begin
                 LLStreamWrite(p.outp, p.x[j]);
                 inc(j)
               end;
-              LLStreamWrite(p.outp, ' & "')
+              LLStreamWrite(p.outp, ')');
+              LLStreamWrite(p.outp, p.conc);
+              LLStreamWrite(p.outp, '"')
             end;
             else if p.x[j] = p.subsChar then begin
               LLStreamWrite(p.outp, p.subsChar);
@@ -203,7 +181,7 @@ begin
               p.info.col := int16(j);
               liMessage(p.info, errInvalidExpression, '$'+'');
             end
-          end;
+          end
         end
         else begin
           LLStreamWrite(p.outp, p.x[j]);
@@ -215,56 +193,30 @@ begin
   end
 end;
 
-function ParseTmpl(var p: TTmplParser): PNode;
+function filterTmpl(input: PLLStream; const filename: string;
+                    call: PNode): PLLStream;
 var
-  q: TParser;
+  p: TTmplParser; 
 begin
+{@ignore}
+  FillChar(p, sizeof(p), 0);
+{@emit}
+  p.info := newLineInfo(filename, 0, 0);
+  p.outp := LLStreamOpen('');
+  p.inp := input;
+  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) do begin
     p.x := LLStreamReadLine(p.inp) {@ignore} + #0 {@emit};
     p.info.line := p.info.line + int16(1);
     parseLine(p);
   end;
   newLine(p);
-  if gVerbosity >= 2 then begin
-    rawMessage(hintCodeBegin);
-    messageOut(p.outp.s);
-    rawMessage(hintCodeEnd);
-  end;
-  openParser(q, toFilename(p.info), p.outp);
-  result := ParseModule(q);
-  closeParser(q);
-end;
-
-procedure openTmplParser(var p: TTmplParser; const filename: string;
-                         inputStream: PLLStream);
-begin
-{@ignore}
-  FillChar(p, sizeof(p), 0);
-{@emit}
-  p.info := newLineInfo(filename, 0, 0);
-  p.outp := LLStreamOpen('');
-  p.inp := inputStream;
-  p.subsChar := '$';
-end;
-
-procedure CloseTmplParser(var p: TTmplParser);
-begin
+  result := p.outp;
   LLStreamClose(p.inp);
 end;
 
-function ParseTmplFile(const filename: string): PNode;
-var
-  p: TTmplParser;
-  f: TBinaryFile;
-begin
-  if not OpenFile(f, filename) then begin
-    rawMessage(errCannotOpenFile, filename);
-    result := nil;
-    exit
-  end;
-  OpenTmplParser(p, filename, LLStreamOpen(f));
-  result := ParseTmpl(p);
-  CloseTmplParser(p);
-end;
-
 end.