diff options
Diffstat (limited to 'nim/ptmplsyn.pas')
-rwxr-xr-x | nim/ptmplsyn.pas | 210 |
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. |