summary refs log tree commit diff stats
path: root/nim/pasparse.pas
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-04-12 01:13:42 +0200
committerAraq <rumpf_a@web.de>2011-04-12 01:13:42 +0200
commitcd292568d775d55d9abb51e962882ecda12c03a9 (patch)
tree85451f0e1f17dc0463350915f12bdd0a82a73455 /nim/pasparse.pas
parent46c41e43690cba9bc1caff6a994bb6915df8a1b7 (diff)
downloadNim-cd292568d775d55d9abb51e962882ecda12c03a9.tar.gz
big repo cleanup
Diffstat (limited to 'nim/pasparse.pas')
-rwxr-xr-xnim/pasparse.pas1998
1 files changed, 0 insertions, 1998 deletions
diff --git a/nim/pasparse.pas b/nim/pasparse.pas
deleted file mode 100755
index dbfbf0437..000000000
--- a/nim/pasparse.pas
+++ /dev/null
@@ -1,1998 +0,0 @@
-//
-//
-//           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
-//
-//    See the file "copying.txt", included in this
-//    distribution, for details about the copyright.
-//
-
-unit pasparse;
-
-// This module implements the parser of the Pascal variant Nimrod is written in.
-// It transfers a Pascal module into a Nimrod AST. Then the renderer can be
-// used to generate the Nimrod version of the compiler.
-
-{$include config.inc}
-
-interface
-
-uses
-  nsystem, nos, llstream, charsets, scanner, paslex, idents, wordrecg, strutils,
-  ast, astalgo, msgs, options;
-
-type
-  TPasSection = (seImplementation, seInterface);
-  TPasContext = (conExpr, conStmt, conTypeDesc);
-  TPasParser = record
-    section: TPasSection;
-    inParamList: boolean;
-    context: TPasContext;    // needed for the @emit command
-    lastVarSection: PNode;
-    lex: TPasLex;
-    tok: TPasTok;
-    repl: TIdTable;       // replacements
-  end;
-
-  TReplaceTuple = array [0..1] of string;
-
-const
-  ImportBlackList: array [1..3] of string = (
-    'nsystem', 'sysutils', 'charsets'
-  );
-  stdReplacements: array [1..19] of TReplaceTuple = (
-    ('include',      'incl'),
-    ('exclude',      'excl'),
-    ('pchar',        'cstring'),
-    ('assignfile',   'open'),
-    ('integer',      'int'),
-    ('longword',     'int32'),
-    ('cardinal',     'int'),
-    ('boolean',      'bool'),
-    ('shortint',     'int8'),
-    ('smallint',     'int16'),
-    ('longint',      'int32'),
-    ('byte',         'int8'),
-    ('word',         'int16'),
-    ('single',       'float32'),
-    ('double',       'float64'),
-    ('real',         'float'),
-    ('length',       'len'),
-    ('len',          'length'),
-    ('setlength',    'setlen')
-  );
-  nimReplacements: array [1..35] of TReplaceTuple = (
-    ('nimread',      'read'),
-    ('nimwrite',     'write'),
-    ('nimclosefile', 'close'),
-    ('closefile',    'close'),
-    ('openfile',     'open'),
-    ('nsystem', 'system'),
-    ('ntime', 'times'),
-    ('nos', 'os'),
-    ('nmath', 'math'),
-
-    ('ncopy', 'copy'),
-    ('addChar', 'add'),
-    ('halt', 'quit'),
-    ('nobject', 'TObject'),
-    ('eof', 'EndOfFile'),
-
-    ('input', 'stdin'),
-    ('output', 'stdout'),
-    ('addu', '`+%`'),
-    ('subu', '`-%`'),
-    ('mulu', '`*%`'),
-    ('divu', '`/%`'),
-    ('modu', '`%%`'),
-    ('ltu', '`<%`'),
-    ('leu', '`<=%`'),
-    ('shlu', '`shl`'),
-    ('shru', '`shr`'),
-    ('assigned',     'not isNil'),
-
-    ('eintoverflow', 'EOverflow'),
-    ('format', '`%`'),
-    ('snil', 'nil'),
-    ('tostringf', '$'+''),
-    ('ttextfile', 'tfile'),
-    ('tbinaryfile', 'tfile'),
-    ('strstart', '0'+''),
-    ('nl', '"\n"'),
-    ('tostring', '$'+'')
-    {,
-    ('NL', '"\n"'),
-    ('tabulator', '''\t'''),
-    ('esc', '''\e'''),
-    ('cr', '''\r'''),
-    ('lf', '''\l'''),
-    ('ff', '''\f'''),
-    ('bel', '''\a'''),
-    ('backspace', '''\b'''),
-    ('vt', '''\v''') }
-  );
-
-function ParseUnit(var p: TPasParser): PNode;
-
-procedure openPasParser(var p: TPasParser; const filename: string;
-                        inputStream: PLLStream);
-procedure closePasParser(var p: TPasParser);
-
-procedure exSymbol(var n: PNode);
-procedure fixRecordDef(var n: PNode);
-// XXX: move these two to an auxiliary module
-
-implementation
-
-procedure OpenPasParser(var p: TPasParser; const filename: string;
-                        inputStream: PLLStream);
-var
-  i: int;
-begin
-{@ignore}
-  FillChar(p, sizeof(p), 0);
-{@emit}
-  OpenLexer(p.lex, filename, inputStream);
-  initIdTable(p.repl);
-  for i := low(stdReplacements) to high(stdReplacements) do
-    IdTablePut(p.repl, getIdent(stdReplacements[i][0]),
-                       getIdent(stdReplacements[i][1]));
-  if gCmd = cmdBoot then
-    for i := low(nimReplacements) to high(nimReplacements) do
-      IdTablePut(p.repl, getIdent(nimReplacements[i][0]),
-                         getIdent(nimReplacements[i][1]));
-end;
-
-procedure ClosePasParser(var p: TPasParser);
-begin
-  CloseLexer(p.lex);
-end;
-
-// ---------------- parser helpers --------------------------------------------
-
-procedure getTok(var p: TPasParser);
-begin
-  getPasTok(p.lex, p.tok)
-end;
-
-procedure parMessage(const p: TPasParser; const msg: TMsgKind;
-                     const arg: string = '');
-begin
-  lexMessage(p.lex, msg, arg);
-end;
-
-function parLineInfo(const p: TPasParser): TLineInfo;
-begin
-  result := getLineInfo(p.lex)
-end;
-
-procedure skipCom(var p: TPasParser; n: PNode);
-begin
-  while p.tok.xkind = pxComment do begin
-    if (n <> nil) then begin
-      if n.comment = snil then n.comment := p.tok.literal
-      else n.comment := n.comment +{&} nl +{&} p.tok.literal;
-    end
-    else
-      parMessage(p, warnCommentXIgnored, p.tok.literal);
-    getTok(p);
-  end
-end;
-
-procedure ExpectIdent(const p: TPasParser);
-begin
-  if p.tok.xkind <> pxSymbol then
-    lexMessage(p.lex, errIdentifierExpected, pasTokToStr(p.tok));
-end;
-
-procedure Eat(var p: TPasParser; xkind: TPasTokKind);
-begin
-  if p.tok.xkind = xkind then getTok(p)
-  else lexMessage(p.lex, errTokenExpected, PasTokKindToStr[xkind])
-end;
-
-procedure Opt(var p: TPasParser; xkind: TPasTokKind);
-begin
-  if p.tok.xkind = xkind then getTok(p)
-end;
-// ----------------------------------------------------------------------------
-
-function newNodeP(kind: TNodeKind; const p: TPasParser): PNode;
-begin
-  result := newNodeI(kind, getLineInfo(p.lex));
-end;
-
-function newIntNodeP(kind: TNodeKind; const intVal: BiggestInt;
-                     const p: TPasParser): PNode;
-begin
-  result := newNodeP(kind, p);
-  result.intVal := intVal;
-end;
-
-function newFloatNodeP(kind: TNodeKind; const floatVal: BiggestFloat;
-                       const p: TPasParser): PNode;
-begin
-  result := newNodeP(kind, p);
-  result.floatVal := floatVal;
-end;
-
-function newStrNodeP(kind: TNodeKind; const strVal: string;
-                     const p: TPasParser): PNode;
-begin
-  result := newNodeP(kind, p);
-  result.strVal := strVal;
-end;
-
-function newIdentNodeP(ident: PIdent; const p: TPasParser): PNode;
-begin
-  result := newNodeP(nkIdent, p);
-  result.ident := ident;
-end;
-
-function createIdentNodeP(ident: PIdent; const p: TPasParser): PNode;
-var
-  x: PIdent;
-begin
-  result := newNodeP(nkIdent, p);
-  x := PIdent(IdTableGet(p.repl, ident));
-  if x <> nil then result.ident := x
-  else result.ident := ident;
-end;
-
-// ------------------- Expression parsing ------------------------------------
-
-function parseExpr(var p: TPasParser): PNode; forward;
-function parseStmt(var p: TPasParser): PNode; forward;
-function parseTypeDesc(var p: TPasParser;
-                       definition: PNode=nil): PNode; forward;
-
-function parseEmit(var p: TPasParser; definition: PNode): PNode;
-var
-  a: PNode;
-begin
-  getTok(p); // skip 'emit'
-  result := nil;
-  if p.tok.xkind <> pxCurlyDirRi then
-    case p.context of
-      conExpr: result := parseExpr(p);
-      conStmt: begin
-        result := parseStmt(p);
-        if p.tok.xkind <> pxCurlyDirRi then begin
-          a := result;
-          result := newNodeP(nkStmtList, p);
-          addSon(result, a);
-          while p.tok.xkind <> pxCurlyDirRi do begin
-            addSon(result, parseStmt(p));
-          end
-        end
-      end;
-      conTypeDesc: result := parseTypeDesc(p, definition);
-    end;
-  eat(p, pxCurlyDirRi);
-end;
-
-function parseCommand(var p: TPasParser; definition: PNode=nil): PNode;
-var
-  a: PNode;
-begin
-  result := nil;
-  getTok(p);
-  if p.tok.ident.id = getIdent('discard').id then begin
-    result := newNodeP(nkDiscardStmt, p);
-    getTok(p); eat(p, pxCurlyDirRi);
-    addSon(result, parseExpr(p));
-  end
-  else if p.tok.ident.id = getIdent('set').id then begin
-    getTok(p); eat(p, pxCurlyDirRi);
-    result := parseExpr(p);
-    result.kind := nkCurly;
-    assert(sonsNotNil(result));
-  end
-  else if p.tok.ident.id = getIdent('cast').id then begin
-    getTok(p); eat(p, pxCurlyDirRi);
-    a := parseExpr(p);
-    if (a.kind = nkCall) and (sonsLen(a) = 2) then begin
-      result := newNodeP(nkCast, p);
-      addSon(result, a.sons[0]);
-      addSon(result, a.sons[1]);
-    end
-    else begin
-      parMessage(p, errInvalidDirectiveX, pasTokToStr(p.tok));
-      result := a
-    end
-  end
-  else if p.tok.ident.id = getIdent('emit').id then begin
-    result := parseEmit(p, definition);
-  end
-  else if p.tok.ident.id = getIdent('ignore').id then begin
-    getTok(p); eat(p, pxCurlyDirRi);
-    while true do begin
-      case p.tok.xkind of
-        pxEof: parMessage(p, errTokenExpected, '{@emit}');
-        pxCommand: begin
-          getTok(p);
-          if p.tok.ident.id = getIdent('emit').id then begin
-            result := parseEmit(p, definition);
-            break
-          end
-          else begin
-            while (p.tok.xkind <> pxCurlyDirRi) and (p.tok.xkind <> pxEof) do
-              getTok(p);
-            eat(p, pxCurlyDirRi);
-          end;
-        end;
-        else getTok(p) // skip token
-      end
-    end
-  end
-  else if p.tok.ident.id = getIdent('ptr').id then begin
-    result := newNodeP(nkPtrTy, p);
-    getTok(p); eat(p, pxCurlyDirRi);
-  end
-  else if p.tok.ident.id = getIdent('tuple').id then begin
-    result := newNodeP(nkTupleTy, p);
-    getTok(p); eat(p, pxCurlyDirRi);
-  end
-  else if p.tok.ident.id = getIdent('acyclic').id then begin
-    result := newIdentNodeP(p.tok.ident, p);
-    getTok(p); eat(p, pxCurlyDirRi);
-  end
-  else begin
-    parMessage(p, errInvalidDirectiveX, pasTokToStr(p.tok));
-    while true do begin
-      getTok(p);
-      if (p.tok.xkind = pxCurlyDirRi) or (p.tok.xkind = pxEof) then break;
-    end;
-    eat(p, pxCurlyDirRi);
-    result := nil
-  end;
-end;
-
-function getPrecedence(const kind: TPasTokKind): int;
-begin
-  case kind of
-    pxDiv, pxMod, pxStar, pxSlash, pxShl, pxShr, pxAnd: result := 5; // highest
-    pxPlus, pxMinus, pxOr, pxXor: result := 4;
-    pxIn, pxEquals, pxLe, pxLt, pxGe, pxGt, pxNeq, pxIs: result := 3;
-    else result := -1;
-  end;
-end;
-
-function rangeExpr(var p: TPasParser): PNode;
-var
-  a: PNode;
-begin
-  a := parseExpr(p);
-  if p.tok.xkind = pxDotDot then begin
-    result := newNodeP(nkRange, p);
-    addSon(result, a);
-    getTok(p); skipCom(p, result);
-    addSon(result, parseExpr(p))
-  end
-  else result := a
-end;
-
-function bracketExprList(var p: TPasParser; first: PNode): PNode;
-var
-  a: PNode;
-begin
-  result := newNodeP(nkBracketExpr, p);
-  addSon(result, first);
-  getTok(p);
-  skipCom(p, result);
-  while true do begin
-    if p.tok.xkind = pxBracketRi then begin
-      getTok(p); break
-    end;
-    if p.tok.xkind = pxEof then begin
-      parMessage(p, errTokenExpected, PasTokKindToStr[pxBracketRi]); break
-    end;
-    a := rangeExpr(p);
-    skipCom(p, a);
-    if p.tok.xkind = pxComma then begin
-      getTok(p);
-      skipCom(p, a)
-    end;
-    addSon(result, a);
-  end;
-end;
-
-function exprColonEqExpr(var p: TPasParser; kind: TNodeKind;
-                         tok: TPasTokKind): PNode;
-var
-  a: PNode;
-begin
-  a := parseExpr(p);
-  if p.tok.xkind = tok then begin
-    result := newNodeP(kind, p);
-    getTok(p);
-    skipCom(p, result);
-    addSon(result, a);
-    addSon(result, parseExpr(p));
-  end
-  else
-    result := a
-end;
-
-procedure exprListAux(var p: TPasParser; elemKind: TNodeKind;
-                      endTok, sepTok: TPasTokKind; result: PNode);
-var
-  a: PNode;
-begin
-  getTok(p);
-  skipCom(p, result);
-  while true do begin
-    if p.tok.xkind = endTok then begin
-      getTok(p); break
-    end;
-    if p.tok.xkind = pxEof then begin
-      parMessage(p, errTokenExpected, PasTokKindToStr[endtok]); break
-    end;
-    a := exprColonEqExpr(p, elemKind, sepTok);
-    skipCom(p, a);
-    if (p.tok.xkind = pxComma) or (p.tok.xkind = pxSemicolon) then begin
-      getTok(p);
-      skipCom(p, a)
-    end;
-    addSon(result, a);
-  end;
-end;
-
-function qualifiedIdent(var p: TPasParser): PNode;
-var
-  a: PNode;
-begin
-  if p.tok.xkind = pxSymbol then
-    result := createIdentNodeP(p.tok.ident, p)
-  else begin
-    parMessage(p, errIdentifierExpected, pasTokToStr(p.tok));
-    result := nil;
-    exit
-  end;
-  getTok(p);
-  skipCom(p, result);
-  if p.tok.xkind = pxDot then begin
-    getTok(p);
-    skipCom(p, result);
-    if p.tok.xkind = pxSymbol then begin
-      a := result;
-      result := newNodeI(nkDotExpr, a.info);
-      addSon(result, a);
-      addSon(result, createIdentNodeP(p.tok.ident, p));
-      getTok(p);
-    end
-    else parMessage(p, errIdentifierExpected, pasTokToStr(p.tok))
-  end;
-end;
-
-procedure qualifiedIdentListAux(var p: TPasParser; endTok: TPasTokKind;
-                                result: PNode);
-var
-  a: PNode;
-begin
-  getTok(p);
-  skipCom(p, result);
-  while true do begin
-    if p.tok.xkind = endTok then begin
-      getTok(p); break
-    end;
-    if p.tok.xkind = pxEof then begin
-      parMessage(p, errTokenExpected, PasTokKindToStr[endtok]); break
-    end;
-    a := qualifiedIdent(p);
-    skipCom(p, a);
-    if p.tok.xkind = pxComma then begin
-      getTok(p); skipCom(p, a)
-    end;
-    addSon(result, a);
-  end
-end;
-
-function exprColonEqExprList(var p: TPasParser; kind, elemKind: TNodeKind;
-                             endTok, sepTok: TPasTokKind): PNode;
-begin
-  result := newNodeP(kind, p);
-  exprListAux(p, elemKind, endTok, sepTok, result);
-end;
-
-procedure setBaseFlags(n: PNode; base: TNumericalBase);
-begin
-  case base of
-    base10: begin end;
-    base2: include(n.flags, nfBase2);
-    base8: include(n.flags, nfBase8);
-    base16: include(n.flags, nfBase16);
-  end
-end;
-
-function identOrLiteral(var p: TPasParser): PNode;
-var
-  a: PNode;
-begin
-  case p.tok.xkind of
-    pxSymbol: begin
-      result := createIdentNodeP(p.tok.ident, p);
-      getTok(p)
-    end;
-    // literals
-    pxIntLit: begin
-      result := newIntNodeP(nkIntLit, p.tok.iNumber, p);
-      setBaseFlags(result, p.tok.base);
-      getTok(p);
-    end;
-    pxInt64Lit: begin
-      result := newIntNodeP(nkInt64Lit, p.tok.iNumber, p);
-      setBaseFlags(result, p.tok.base);
-      getTok(p);
-    end;
-    pxFloatLit: begin
-      result := newFloatNodeP(nkFloatLit, p.tok.fNumber, p);
-      setBaseFlags(result, p.tok.base);
-      getTok(p);
-    end;
-    pxStrLit: begin
-      if length(p.tok.literal) <> 1 then
-        result := newStrNodeP(nkStrLit, p.tok.literal, p)
-      else
-        result := newIntNodeP(nkCharLit, ord(p.tok.literal[strStart]), p);
-      getTok(p);
-    end;
-    pxNil: begin
-      result := newNodeP(nkNilLit, p);
-      getTok(p);
-    end;
-
-    pxParLe: begin // () constructor
-      result := exprColonEqExprList(p, nkPar, nkExprColonExpr, pxParRi,
-                                    pxColon);
-      //if hasSonWith(result, nkExprColonExpr) then
-      //  replaceSons(result, nkExprColonExpr, nkExprEqExpr)
-      if (sonsLen(result) > 1) and not hasSonWith(result, nkExprColonExpr) then
-        result.kind := nkBracket; // is an array constructor
-    end;
-    pxBracketLe: begin // [] constructor
-      result := newNodeP(nkBracket, p);
-      getTok(p);
-      skipCom(p, result);
-      while (p.tok.xkind <> pxBracketRi) and (p.tok.xkind <> pxEof) do begin
-        a := rangeExpr(p);
-        if a.kind = nkRange then
-          result.kind := nkCurly; // it is definitely a set literal
-        opt(p, pxComma);
-        skipCom(p, a);
-        assert(a <> nil);
-        addSon(result, a);
-      end;
-      eat(p, pxBracketRi);
-    end;
-    pxCommand: result := parseCommand(p);
-    else begin
-      parMessage(p, errExprExpected, pasTokToStr(p.tok));
-      getTok(p); // we must consume a token here to prevend endless loops!
-      result := nil
-    end
-  end;
-  if result <> nil then
-    skipCom(p, result);
-end;
-
-function primary(var p: TPasParser): PNode;
-var
-  a: PNode;
-begin
-  // prefix operator?
-  if (p.tok.xkind = pxNot) or (p.tok.xkind = pxMinus)
-  or (p.tok.xkind = pxPlus) then begin
-    result := newNodeP(nkPrefix, p);
-    a := newIdentNodeP(getIdent(pasTokToStr(p.tok)), p);
-    addSon(result, a);
-    getTok(p);
-    skipCom(p, a);
-    addSon(result, primary(p));
-    exit
-  end
-  else if p.tok.xkind = pxAt then begin
-    result := newNodeP(nkAddr, p);
-    a := newIdentNodeP(getIdent(pasTokToStr(p.tok)), p);
-    getTok(p);
-    if p.tok.xkind = pxBracketLe then begin
-      result := newNodeP(nkPrefix, p);
-      addSon(result, a);
-      addSon(result, identOrLiteral(p));
-    end
-    else
-      addSon(result, primary(p));
-    exit
-  end;
-  result := identOrLiteral(p);
-  while true do begin
-    case p.tok.xkind of
-      pxParLe: begin
-        a := result;
-        result := newNodeP(nkCall, p);
-        addSon(result, a);
-        exprListAux(p, nkExprEqExpr, pxParRi, pxEquals, result);
-      end;
-      pxDot: begin
-        a := result;
-        result := newNodeP(nkDotExpr, p);
-        addSon(result, a);
-        getTok(p); // skip '.'
-        skipCom(p, result);
-        if p.tok.xkind = pxSymbol then begin
-          addSon(result, createIdentNodeP(p.tok.ident, p));
-          getTok(p);
-        end
-        else
-          parMessage(p, errIdentifierExpected, pasTokToStr(p.tok));
-      end;
-      pxHat: begin
-        a := result;
-        result := newNodeP(nkDerefExpr, p);
-        addSon(result, a);
-        getTok(p);
-      end;
-      pxBracketLe: result := bracketExprList(p, result);
-      else break
-    end
-  end
-end;
-
-function lowestExprAux(var p: TPasParser; out v: PNode;
-                       limit: int): TPasTokKind;
-var
-  op, nextop: TPasTokKind;
-  opPred: int;
-  v2, node, opNode: PNode;
-begin
-  v := primary(p);
-  // expand while operators have priorities higher than 'limit'
-  op := p.tok.xkind;
-  opPred := getPrecedence(op);
-  while (opPred > limit) do begin
-    node := newNodeP(nkInfix, p);
-    opNode := newIdentNodeP(getIdent(pasTokToStr(p.tok)), p);
-    // skip operator:
-    getTok(p);
-    case op of
-      pxPlus: begin
-        case p.tok.xkind of
-          pxPer: begin getTok(p); eat(p, pxCurlyDirRi);
-                       opNode.ident := getIdent('+%') end;
-          pxAmp: begin getTok(p); eat(p, pxCurlyDirRi);
-                       opNode.ident := getIdent('&'+'') end;
-          else begin end
-        end
-      end;
-      pxMinus: begin
-        if p.tok.xkind = pxPer then begin
-          getTok(p); eat(p, pxCurlyDirRi);
-          opNode.ident := getIdent('-%')
-        end;
-      end;
-      pxEquals: opNode.ident := getIdent('==');
-      pxNeq:    opNode.ident := getIdent('!=');
-      else begin end
-    end;
-
-    skipCom(p, opNode);
-
-    // read sub-expression with higher priority
-    nextop := lowestExprAux(p, v2, opPred);
-    addSon(node, opNode);
-    addSon(node, v);
-    addSon(node, v2);
-    v := node;
-    op := nextop;
-    opPred := getPrecedence(nextop);
-  end;
-  result := op;  // return first untreated operator
-end;
-
-function fixExpr(n: PNode): PNode;
-var
-  i: int;
-begin
-  result := n;
-  if n = nil then exit;
-  case n.kind of
-    nkInfix: begin
-      if n.sons[1].kind = nkBracket then // binary expression with [] is a set
-        n.sons[1].kind := nkCurly;
-      if n.sons[2].kind = nkBracket then // binary expression with [] is a set
-        n.sons[2].kind := nkCurly;
-      if (n.sons[0].kind = nkIdent) then begin
-        if (n.sons[0].ident.id = getIdent('+'+'').id) then begin
-          if (n.sons[1].kind = nkCharLit)
-              and (n.sons[2].kind = nkStrLit) and (n.sons[2].strVal = '') then
-          begin
-              result := newStrNode(nkStrLit, chr(int(n.sons[1].intVal))+'');
-              result.info := n.info;
-              exit; // do not process sons as they don't exist anymore
-          end
-          else if (n.sons[1].kind in [nkCharLit, nkStrLit])
-               or (n.sons[2].kind in [nkCharLit, nkStrLit]) then begin
-            n.sons[0].ident := getIdent('&'+''); // fix operator
-          end
-        end
-      end
-    end
-    else begin end
-  end;
-  if not (n.kind in [nkEmpty..nkNilLit]) then
-    for i := 0 to sonsLen(n)-1 do
-      result.sons[i] := fixExpr(n.sons[i])
-end;
-
-function parseExpr(var p: TPasParser): PNode;
-var
-  oldcontext: TPasContext;
-begin
-  oldcontext := p.context;
-  p.context := conExpr;
-  if p.tok.xkind = pxCommand then begin
-    result := parseCommand(p)
-  end
-  else begin
-  {@discard} lowestExprAux(p, result, -1);
-    result := fixExpr(result)
-  end;
-  //if result = nil then
-  //  internalError(parLineInfo(p), 'parseExpr() returned nil');
-  p.context := oldcontext;
-end;
-
-// ---------------------- statement parser ------------------------------------
-function parseExprStmt(var p: TPasParser): PNode;
-var
-  a, b: PNode;
-  info: TLineInfo;
-begin
-  info := parLineInfo(p);
-  a := parseExpr(p);
-  if p.tok.xkind = pxAsgn then begin
-    getTok(p);
-    skipCom(p, a);
-    b := parseExpr(p);
-    result := newNodeI(nkAsgn, info);
-    addSon(result, a);
-    addSon(result, b);
-  end
-  else
-    result := a
-end;
-
-function inImportBlackList(ident: PIdent): bool;
-var
-  i: int;
-begin
-  for i := low(ImportBlackList) to high(ImportBlackList) do
-    if ident.id = getIdent(ImportBlackList[i]).id then begin
-      result := true; exit
-    end;
-  result := false
-end;
-
-function parseUsesStmt(var p: TPasParser): PNode;
-var
-  a: PNode;
-begin
-  result := newNodeP(nkImportStmt, p);
-  getTok(p); // skip `import`
-  skipCom(p, result);
-  while true do begin
-    case p.tok.xkind of
-      pxEof: break;
-      pxSymbol:   a := newIdentNodeP(p.tok.ident, p);
-      else begin
-        parMessage(p, errIdentifierExpected, pasTokToStr(p.tok));
-        break
-      end;
-    end;
-    getTok(p); // skip identifier, string
-    skipCom(p, a);
-    if (gCmd <> cmdBoot) or not inImportBlackList(a.ident) then
-      addSon(result, createIdentNodeP(a.ident, p));
-    if p.tok.xkind = pxComma then begin
-      getTok(p);
-      skipCom(p, a)
-    end
-    else break
-  end;
-  if sonsLen(result) = 0 then result := nil;
-end;
-
-function parseIncludeDir(var p: TPasParser): PNode;
-var
-  filename: string;
-begin
-  result := newNodeP(nkIncludeStmt, p);
-  getTok(p); // skip `include`
-  filename := '';
-  while true do begin
-    case p.tok.xkind of
-      pxSymbol, pxDot, pxDotDot, pxSlash: begin
-        filename := filename +{&} pasTokToStr(p.tok);
-        getTok(p);
-      end;
-      pxStrLit: begin
-        filename := p.tok.literal;
-        getTok(p);
-        break
-      end;
-      pxCurlyDirRi: break;
-      else begin
-        parMessage(p, errIdentifierExpected, pasTokToStr(p.tok));
-        break
-      end;
-    end;
-  end;
-  addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, 'nim'), p));
-  if filename = 'config.inc' then result := nil;
-end;
-
-function definedExprAux(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkCall, p);
-  addSon(result, newIdentNodeP(getIdent('defined'), p));
-  ExpectIdent(p);
-  addSon(result, createIdentNodeP(p.tok.ident, p));
-  getTok(p);
-end;
-
-function isHandledDirective(const p: TPasParser): bool;
-begin
-  result := false;
-  if p.tok.xkind in [pxCurlyDirLe, pxStarDirLe] then
-    case whichKeyword(p.tok.ident) of
-      wElse, wEndif: result := false
-      else result := true
-    end
-end;
-
-function parseStmtList(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkStmtList, p);
-  while true do begin
-    case p.tok.xkind of
-      pxEof: break;
-      pxCurlyDirLe, pxStarDirLe: begin
-        if not isHandledDirective(p) then break;
-      end
-      else begin end
-    end;
-    addSon(result, parseStmt(p))
-  end;
-  if sonsLen(result) = 1 then result := result.sons[0];
-end;
-
-procedure parseIfDirAux(var p: TPasParser; result: PNode);
-var
-  s: PNode;
-  endMarker: TPasTokKind;
-begin
-  addSon(result.sons[0], parseStmtList(p));
-  if p.tok.xkind in [pxCurlyDirLe, pxStarDirLe] then begin
-    endMarker := succ(p.tok.xkind);
-    if whichKeyword(p.tok.ident) = wElse then begin
-      s := newNodeP(nkElse, p);
-      while (p.tok.xkind <> pxEof) and (p.tok.xkind <> endMarker) do getTok(p);
-      eat(p, endMarker);
-      addSon(s, parseStmtList(p));
-      addSon(result, s);
-    end;
-    if p.tok.xkind in [pxCurlyDirLe, pxStarDirLe] then begin
-      endMarker := succ(p.tok.xkind);
-      if whichKeyword(p.tok.ident) = wEndif then begin
-        while (p.tok.xkind <> pxEof) and (p.tok.xkind <> endMarker) do getTok(p);
-        eat(p, endMarker);
-      end
-      else parMessage(p, errXExpected, '{$endif}');
-    end
-  end
-  else
-    parMessage(p, errXExpected, '{$endif}');
-end;
-
-function parseIfdefDir(var p: TPasParser; endMarker: TPasTokKind): PNode;
-begin
-  result := newNodeP(nkWhenStmt, p);
-  addSon(result, newNodeP(nkElifBranch, p));
-  getTok(p);
-  addSon(result.sons[0], definedExprAux(p));
-  eat(p, endMarker);
-  parseIfDirAux(p, result);
-end;
-
-function parseIfndefDir(var p: TPasParser; endMarker: TPasTokKind): PNode;
-var
-  e: PNode;
-begin
-  result := newNodeP(nkWhenStmt, p);
-  addSon(result, newNodeP(nkElifBranch, p));
-  getTok(p);
-  e := newNodeP(nkCall, p);
-  addSon(e, newIdentNodeP(getIdent('not'), p));
-  addSon(e, definedExprAux(p));
-  eat(p, endMarker);
-  addSon(result.sons[0], e);
-  parseIfDirAux(p, result);
-end;
-
-function parseIfDir(var p: TPasParser; endMarker: TPasTokKind): PNode;
-begin
-  result := newNodeP(nkWhenStmt, p);
-  addSon(result, newNodeP(nkElifBranch, p));
-  getTok(p);
-  addSon(result.sons[0], parseExpr(p));
-  eat(p, endMarker);
-  parseIfDirAux(p, result);
-end;
-
-function parseDirective(var p: TPasParser): PNode;
-var
-  endMarker: TPasTokKind;
-begin
-  result := nil;
-  if not (p.tok.xkind in [pxCurlyDirLe, pxStarDirLe]) then exit;
-  endMarker := succ(p.tok.xkind);
-  if p.tok.ident <> nil then
-    case whichKeyword(p.tok.ident) of
-      wInclude: begin
-        result := parseIncludeDir(p);
-        eat(p, endMarker);
-      end;
-      wIf: result := parseIfDir(p, endMarker);
-      wIfdef: result := parseIfdefDir(p, endMarker);
-      wIfndef: result := parseIfndefDir(p, endMarker);
-      else begin
-        // skip unknown compiler directive
-        while (p.tok.xkind <> pxEof) and (p.tok.xkind <> endMarker) do
-          getTok(p);
-        eat(p, endMarker);
-      end
-    end
-  else eat(p, endMarker);
-end;
-
-function parseRaise(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkRaiseStmt, p);
-  getTok(p);
-  skipCom(p, result);
-  if p.tok.xkind <> pxSemicolon then addSon(result, parseExpr(p))
-  else addSon(result, nil);
-end;
-
-function parseIf(var p: TPasParser): PNode;
-var
-  branch: PNode;
-begin
-  result := newNodeP(nkIfStmt, p);
-  while true do begin
-    getTok(p); // skip ``if``
-    branch := newNodeP(nkElifBranch, p);
-    skipCom(p, branch);
-    addSon(branch, parseExpr(p));
-    eat(p, pxThen);
-    skipCom(p, branch);
-    addSon(branch, parseStmt(p));
-    skipCom(p, branch);
-    addSon(result, branch);
-    if p.tok.xkind = pxElse then begin
-      getTok(p);
-      if p.tok.xkind <> pxIf then begin
-        // ordinary else part:
-        branch := newNodeP(nkElse, p);
-        skipCom(p, result); // BUGFIX
-        addSon(branch, parseStmt(p));
-        addSon(result, branch);
-        break
-      end
-      // else: next iteration
-    end
-    else break
-  end
-end;
-
-function parseWhile(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkWhileStmt, p);
-  getTok(p);
-  skipCom(p, result);
-  addSon(result, parseExpr(p));
-  eat(p, pxDo);
-  skipCom(p, result);
-  addSon(result, parseStmt(p));
-end;
-
-function parseRepeat(var p: TPasParser): PNode;
-var
-  a, b, c, s: PNode;
-begin
-  result := newNodeP(nkWhileStmt, p);
-  getTok(p);
-  skipCom(p, result);
-  addSon(result, newIdentNodeP(getIdent('true'), p));
-  s := newNodeP(nkStmtList, p);
-  while (p.tok.xkind <> pxEof) and (p.tok.xkind <> pxUntil) do begin
-    addSon(s, parseStmt(p))
-  end;
-  eat(p, pxUntil);
-  a := newNodeP(nkIfStmt, p);
-  skipCom(p, a);
-  b := newNodeP(nkElifBranch, p);
-  c := newNodeP(nkBreakStmt, p);
-  addSon(c, nil);
-  addSon(b, parseExpr(p));
-  skipCom(p, a);
-  addSon(b, c);
-  addSon(a, b);
-
-  if (b.sons[0].kind = nkIdent) and (b.sons[0].ident.id = getIdent('false').id)
-  then begin end // do not add an ``if false: break`` statement
-  else addSon(s, a);
-  addSon(result, s);
-end;
-
-function parseCase(var p: TPasParser): PNode;
-var
-  b: PNode;
-begin
-  result := newNodeP(nkCaseStmt, p);
-  getTok(p);
-  addSon(result, parseExpr(p));
-  eat(p, pxOf);
-  skipCom(p, result);
-  while (p.tok.xkind <> pxEnd) and (p.tok.xkind <> pxEof) do begin
-    if p.tok.xkind = pxElse then begin
-      b := newNodeP(nkElse, p);
-      getTok(p);
-    end
-    else begin
-      b := newNodeP(nkOfBranch, p);
-      while (p.tok.xkind <> pxEof) and (p.tok.xkind <> pxColon) do begin
-        addSon(b, rangeExpr(p));
-        opt(p, pxComma);
-        skipcom(p, b);
-      end;
-      eat(p, pxColon);
-    end;
-    skipCom(p, b);
-    addSon(b, parseStmt(p));
-    addSon(result, b);
-    if b.kind = nkElse then break;
-  end;
-  eat(p, pxEnd);
-end;
-
-function parseTry(var p: TPasParser): PNode;
-var
-  b, e: PNode;
-begin
-  result := newNodeP(nkTryStmt, p);
-  getTok(p);
-  skipCom(p, result);
-  b := newNodeP(nkStmtList, p);
-  while not (p.tok.xkind in [pxFinally, pxExcept, pxEof, pxEnd]) do
-    addSon(b, parseStmt(p));
-  addSon(result, b);
-  if p.tok.xkind = pxExcept then begin
-    getTok(p);
-    while p.tok.ident.id = getIdent('on').id do begin
-      b := newNodeP(nkExceptBranch, p);
-      getTok(p);
-      e := qualifiedIdent(p);
-      if p.tok.xkind = pxColon then begin
-        getTok(p);
-        e := qualifiedIdent(p);
-      end;
-      addSon(b, e);
-      eat(p, pxDo);
-      addSon(b, parseStmt(p));
-      addSon(result, b);
-      if p.tok.xkind = pxCommand then {@discard} parseCommand(p);
-    end;
-    if p.tok.xkind = pxElse then begin
-      b := newNodeP(nkExceptBranch, p);
-      getTok(p);
-      addSon(b, parseStmt(p));
-      addSon(result, b);
-    end
-  end;
-  if p.tok.xkind = pxFinally then begin
-    b := newNodeP(nkFinally, p);
-    getTok(p);
-    e := newNodeP(nkStmtList, p);
-    while (p.tok.xkind <> pxEof) and (p.tok.xkind <> pxEnd) do begin
-      addSon(e, parseStmt(p))
-    end;
-    if sonsLen(e) = 0 then
-      addSon(e, newNodeP(nkNilLit, p));
-    addSon(result, e);
-  end;
-  eat(p, pxEnd);
-end;
-
-function parseFor(var p: TPasParser): PNode;
-var
-  a, b, c: PNode;
-begin
-  result := newNodeP(nkForStmt, p);
-  getTok(p);
-  skipCom(p, result);
-  expectIdent(p);
-  addSon(result, createIdentNodeP(p.tok.ident, p));
-  getTok(p);
-  eat(p, pxAsgn);
-  a := parseExpr(p);
-  b := nil;
-  c := newNodeP(nkCall, p);
-  if p.tok.xkind = pxTo then begin
-    addSon(c, newIdentNodeP(getIdent('countup'), p));
-    getTok(p);
-    b := parseExpr(p);
-  end
-  else if p.tok.xkind = pxDownto then begin
-    addSon(c, newIdentNodeP(getIdent('countdown'), p));
-    getTok(p);
-    b := parseExpr(p);
-  end
-  else
-    parMessage(p, errTokenExpected, PasTokKindToStr[pxTo]);
-  addSon(c, a);
-  addSon(c, b);
-
-  eat(p, pxDo);
-  skipCom(p, result);
-  addSon(result, c);
-  addSon(result, parseStmt(p))
-end;
-
-function parseParam(var p: TPasParser): PNode;
-var
-  a, v: PNode;
-begin
-  result := newNodeP(nkIdentDefs, p);
-  v := nil;
-  case p.tok.xkind of
-    pxConst: getTok(p);
-    pxVar:   begin getTok(p); v := newNodeP(nkVarTy, p); end;
-    pxOut:   begin getTok(p); v := newNodeP(nkVarTy, p); end;
-    else begin end
-  end;
-  while true do begin
-    case p.tok.xkind of
-      pxSymbol: a := createIdentNodeP(p.tok.ident, p);
-      pxColon, pxEof, pxParRi, pxEquals: break;
-      else begin
-        parMessage(p, errIdentifierExpected, pasTokToStr(p.tok));
-        exit;
-      end;
-    end;
-    getTok(p); // skip identifier
-    skipCom(p, a);
-    if p.tok.xkind = pxComma then begin
-      getTok(p); skipCom(p, a)
-    end;
-    addSon(result, a);
-  end;
-  if p.tok.xkind = pxColon then begin
-    getTok(p); skipCom(p, result);
-    if v <> nil then addSon(v, parseTypeDesc(p))
-    else v := parseTypeDesc(p);
-    addSon(result, v);
-  end
-  else begin
-    addSon(result, nil);
-    if p.tok.xkind <> pxEquals then
-      parMessage(p, errColonOrEqualsExpected, pasTokToStr(p.tok))
-  end;
-  if p.tok.xkind = pxEquals then begin
-    getTok(p); skipCom(p, result);
-    addSon(result, parseExpr(p));
-  end
-  else
-    addSon(result, nil);
-end;
-
-function parseParamList(var p: TPasParser): PNode;
-var
-  a: PNode;
-begin
-  result := newNodeP(nkFormalParams, p);
-  addSon(result, nil); // return type
-  if p.tok.xkind = pxParLe then begin
-    p.inParamList := true;
-    getTok(p);
-    skipCom(p, result);
-    while true do begin
-      case p.tok.xkind of
-        pxSymbol, pxConst, pxVar, pxOut: a := parseParam(p);
-        pxParRi: begin getTok(p); break end;
-        else begin parMessage(p, errTokenExpected, ')'+''); break; end;
-      end;
-      skipCom(p, a);
-      if p.tok.xkind = pxSemicolon then begin
-        getTok(p); skipCom(p, a)
-      end;
-      addSon(result, a)
-    end;
-    p.inParamList := false
-  end;
-  if p.tok.xkind = pxColon then begin
-    getTok(p);
-    skipCom(p, result);
-    result.sons[0] := parseTypeDesc(p)
-  end
-end;
-
-function parseCallingConvention(var p: TPasParser): PNode;
-begin
-  result := nil;
-  if p.tok.xkind = pxSymbol then begin
-    case whichKeyword(p.tok.ident) of
-      wStdcall, wCDecl, wSafeCall, wSysCall, wInline, wFastCall: begin
-        result := newNodeP(nkPragma, p);
-        addSon(result, newIdentNodeP(p.tok.ident, p));
-        getTok(p);
-        opt(p, pxSemicolon);
-      end;
-      wRegister: begin
-        result := newNodeP(nkPragma, p);
-        addSon(result, newIdentNodeP(getIdent('fastcall'), p));
-        getTok(p);
-        opt(p, pxSemicolon);
-      end
-      else begin end
-    end
-  end
-end;
-
-function parseRoutineSpecifiers(var p: TPasParser; out noBody: boolean): PNode;
-var
-  e: PNode;
-begin
-  result := parseCallingConvention(p);
-  noBody := false;
-  while p.tok.xkind = pxSymbol do begin
-    case whichKeyword(p.tok.ident) of
-      wAssembler, wOverload, wFar: begin
-        getTok(p); opt(p, pxSemicolon);
-      end;
-      wForward: begin
-        noBody := true;
-        getTok(p); opt(p, pxSemicolon);
-      end;
-      wImportc: begin
-        // This is a fake for platform module. There is no ``importc``
-        // directive in Pascal.
-        if result = nil then result := newNodeP(nkPragma, p);
-        addSon(result, newIdentNodeP(getIdent('importc'), p));
-        noBody := true;
-        getTok(p); opt(p, pxSemicolon);
-      end;
-      wNoConv: begin
-        // This is a fake for platform module. There is no ``noconv``
-        // directive in Pascal.
-        if result = nil then result := newNodeP(nkPragma, p);
-        addSon(result, newIdentNodeP(getIdent('noconv'), p));
-        noBody := true;
-        getTok(p); opt(p, pxSemicolon);
-      end;
-      wProcVar: begin
-        // This is a fake for the Nimrod compiler. There is no ``procvar``
-        // directive in Pascal.
-        if result = nil then result := newNodeP(nkPragma, p);
-        addSon(result, newIdentNodeP(getIdent('procvar'), p));
-        getTok(p); opt(p, pxSemicolon);
-      end;
-      wVarargs: begin
-        if result = nil then result := newNodeP(nkPragma, p);
-        addSon(result, newIdentNodeP(getIdent('varargs'), p));
-        getTok(p); opt(p, pxSemicolon);
-      end;
-      wExternal: begin
-        if result = nil then result := newNodeP(nkPragma, p);
-        getTok(p);
-        noBody := true;
-        e := newNodeP(nkExprColonExpr, p);
-        addSon(e, newIdentNodeP(getIdent('dynlib'), p));
-        addSon(e, parseExpr(p));
-        addSon(result, e);
-        opt(p, pxSemicolon);
-        if (p.tok.xkind = pxSymbol)
-        and (p.tok.ident.id = getIdent('name').id) then begin
-          e := newNodeP(nkExprColonExpr, p);
-          getTok(p);
-          addSon(e, newIdentNodeP(getIdent('importc'), p));
-          addSon(e, parseExpr(p));
-          addSon(result, e);
-        end
-        else
-          addSon(result, newIdentNodeP(getIdent('importc'), p));
-        opt(p, pxSemicolon);
-      end
-      else begin
-        e := parseCallingConvention(p);
-        if e = nil then break;
-        if result = nil then result := newNodeP(nkPragma, p);
-        addSon(result, e.sons[0]);
-      end;
-    end
-  end
-end;
-
-function parseRoutineType(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkProcTy, p);
-  getTok(p); skipCom(p, result);
-  addSon(result, parseParamList(p));
-  opt(p, pxSemicolon);
-  addSon(result, parseCallingConvention(p));
-  skipCom(p, result);
-end;
-
-function parseEnum(var p: TPasParser): PNode;
-var
-  a, b: PNode;
-begin
-  result := newNodeP(nkEnumTy, p);
-  getTok(p);
-  skipCom(p, result);
-  addSon(result, nil); // it does not inherit from any enumeration
-
-  while true do begin
-    case p.tok.xkind of
-      pxEof, pxParRi: break;
-      pxSymbol: a := newIdentNodeP(p.tok.ident, p);
-      else begin
-        parMessage(p, errIdentifierExpected, pasTokToStr(p.tok));
-        break
-      end;
-    end;
-    getTok(p); // skip identifier
-    skipCom(p, a);
-    if (p.tok.xkind = pxEquals) or (p.tok.xkind = pxAsgn) then begin
-      getTok(p);
-      skipCom(p, a);
-      b := a;
-      a := newNodeP(nkEnumFieldDef, p);
-      addSon(a, b);
-      addSon(a, parseExpr(p));
-    end;
-    if p.tok.xkind = pxComma then begin
-      getTok(p); skipCom(p, a)
-    end;
-    addSon(result, a);
-  end;
-  eat(p, pxParRi)
-end;
-
-function identVis(var p: TPasParser): PNode; // identifier with visability
-var
-  a: PNode;
-begin
-  a := createIdentNodeP(p.tok.ident, p);
-  if p.section = seInterface then begin
-    result := newNodeP(nkPostfix, p);
-    addSon(result, newIdentNodeP(getIdent('*'+''), p));
-    addSon(result, a);
-  end
-  else
-    result := a;
-  getTok(p)
-end;
-
-type
-  TSymbolParser = function (var p: TPasParser): PNode;
-
-function rawIdent(var p: TPasParser): PNode;
-begin
-  result := createIdentNodeP(p.tok.ident, p);
-  getTok(p);
-end;
-
-function parseIdentColonEquals(var p: TPasParser;
-                               identParser: TSymbolParser): PNode;
-var
-  a: PNode;
-begin
-  result := newNodeP(nkIdentDefs, p);
-  while true do begin
-    case p.tok.xkind of
-      pxSymbol: a := identParser(p);
-      pxColon, pxEof, pxParRi, pxEquals: break;
-      else begin
-        parMessage(p, errIdentifierExpected, pasTokToStr(p.tok));
-        exit;
-      end;
-    end;
-    skipCom(p, a);
-    if p.tok.xkind = pxComma then begin
-      getTok(p);
-      skipCom(p, a)
-    end;
-    addSon(result, a);
-  end;
-  if p.tok.xkind = pxColon then begin
-    getTok(p); skipCom(p, result);
-    addSon(result, parseTypeDesc(p));
-  end
-  else begin
-    addSon(result, nil);
-    if p.tok.xkind <> pxEquals then
-      parMessage(p, errColonOrEqualsExpected, pasTokToStr(p.tok))
-  end;
-  if p.tok.xkind = pxEquals then begin
-    getTok(p); skipCom(p, result);
-    addSon(result, parseExpr(p));
-  end
-  else
-    addSon(result, nil);
-  if p.tok.xkind = pxSemicolon then begin
-    getTok(p); skipCom(p, result);
-  end
-end;
-
-function parseRecordCase(var p: TPasParser): PNode;
-var
-  a, b, c: PNode;
-begin
-  result := newNodeP(nkRecCase, p);
-  getTok(p);
-  a := newNodeP(nkIdentDefs, p);
-  addSon(a, rawIdent(p));
-  eat(p, pxColon);
-  addSon(a, parseTypeDesc(p));
-  addSon(a, nil);
-  addSon(result, a);
-  eat(p, pxOf);
-  skipCom(p, result);
-
-  while true do begin
-    case p.tok.xkind of
-      pxEof, pxEnd: break;
-      pxElse: begin
-        b := newNodeP(nkElse, p);
-        getTok(p);
-      end;
-      else begin
-        b := newNodeP(nkOfBranch, p);
-        while (p.tok.xkind <> pxEof) and (p.tok.xkind <> pxColon) do begin
-          addSon(b, rangeExpr(p));
-          opt(p, pxComma);
-          skipcom(p, b);
-        end;
-        eat(p, pxColon);
-      end
-    end;
-    skipCom(p, b);
-    c := newNodeP(nkRecList, p);
-    eat(p, pxParLe);
-    while (p.tok.xkind <> pxParRi) and (p.tok.xkind <> pxEof) do begin
-      addSon(c, parseIdentColonEquals(p, rawIdent));
-      opt(p, pxSemicolon);
-      skipCom(p, lastSon(c));
-    end;
-    eat(p, pxParRi);
-    opt(p, pxSemicolon);
-    if sonsLen(c) > 0 then skipCom(p, lastSon(c))
-    else addSon(c, newNodeP(nkNilLit, p));
-    addSon(b, c);
-    addSon(result, b);
-    if b.kind = nkElse then break;
-  end
-end;
-
-function parseRecordPart(var p: TPasParser): PNode;
-begin
-  result := nil;
-  while (p.tok.xkind <> pxEof) and (p.tok.xkind <> pxEnd) do begin
-    if result = nil then result := newNodeP(nkRecList, p);
-    case p.tok.xkind of
-      pxSymbol: begin
-        addSon(result, parseIdentColonEquals(p, rawIdent));
-        opt(p, pxSemicolon);
-        skipCom(p, lastSon(result));
-      end;
-      pxCase: begin
-        addSon(result, parseRecordCase(p));
-      end;
-      pxComment: skipCom(p, lastSon(result));
-      else begin
-        parMessage(p, errIdentifierExpected, pasTokToStr(p.tok));
-        break
-      end
-    end
-  end
-end;
-
-procedure exSymbol(var n: PNode);
-var
-  a: PNode;
-begin
-  case n.kind of
-    nkPostfix: begin end; // already an export marker
-    nkPragmaExpr: exSymbol(n.sons[0]);
-    nkIdent, nkAccQuoted: begin
-      a := newNodeI(nkPostFix, n.info);
-      addSon(a, newIdentNode(getIdent('*'+''), n.info));
-      addSon(a, n);
-      n := a
-    end;
-    else internalError(n.info, 'exSymbol(): ' + nodekindtostr[n.kind]);
-  end
-end;
-
-procedure fixRecordDef(var n: PNode);
-var
-  i, len: int;
-begin
-  if n = nil then exit;
-  case n.kind of
-    nkRecCase: begin
-      fixRecordDef(n.sons[0]);
-      for i := 1 to sonsLen(n)-1 do begin
-        len := sonsLen(n.sons[i]);
-        fixRecordDef(n.sons[i].sons[len-1])
-      end
-    end;
-    nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch,
-    nkObjectTy: begin
-      for i := 0 to sonsLen(n)-1 do fixRecordDef(n.sons[i])
-    end;
-    nkIdentDefs: begin
-      for i := 0 to sonsLen(n)-3 do exSymbol(n.sons[i])
-    end;
-    nkNilLit: begin end;
-    //nkIdent: exSymbol(n);
-    else internalError(n.info, 'fixRecordDef(): ' + nodekindtostr[n.kind]);
-  end
-end;
-
-procedure addPragmaToIdent(var ident: PNode; pragma: PNode);
-var
-  e, pragmasNode: PNode;
-begin
-  if ident.kind <> nkPragmaExpr then begin
-    pragmasNode := newNodeI(nkPragma, ident.info);
-    e := newNodeI(nkPragmaExpr, ident.info);
-    addSon(e, ident);
-    addSon(e, pragmasNode);
-    ident := e;
-  end
-  else begin
-    pragmasNode := ident.sons[1];
-    if pragmasNode.kind <> nkPragma then
-      InternalError(ident.info, 'addPragmaToIdent');
-  end;
-  addSon(pragmasNode, pragma);
-end;
-
-procedure parseRecordBody(var p: TPasParser; result, definition: PNode);
-var
-  a: PNode;
-begin
-  skipCom(p, result);
-  a := parseRecordPart(p);
-  if result.kind <> nkTupleTy then fixRecordDef(a);
-  addSon(result, a);
-  eat(p, pxEnd);
-  case p.tok.xkind of
-    pxSymbol: begin
-      if (p.tok.ident.id = getIdent('acyclic').id) then begin
-        if definition <> nil then
-          addPragmaToIdent(definition.sons[0], newIdentNodeP(p.tok.ident, p))
-        else
-          InternalError(result.info, 'anonymous record is not supported');
-        getTok(p);
-      end
-      else
-        InternalError(result.info, 'parseRecordBody');
-    end;
-    pxCommand: begin
-      if definition <> nil then
-        addPragmaToIdent(definition.sons[0], parseCommand(p))
-      else
-        InternalError(result.info, 'anonymous record is not supported');
-    end;
-    else begin end
-  end;
-  opt(p, pxSemicolon);
-  skipCom(p, result);
-end;
-
-function parseRecordOrObject(var p: TPasParser; kind: TNodeKind;
-                             definition: PNode): PNode;
-var
-  a: PNode;
-begin
-  result := newNodeP(kind, p);
-  getTok(p);
-  addSon(result, nil);
-  if p.tok.xkind = pxParLe then begin
-    a := newNodeP(nkOfInherit, p);
-    getTok(p);
-    addSon(a, parseTypeDesc(p));
-    addSon(result, a);
-    eat(p, pxParRi);
-  end
-  else addSon(result, nil);
-  parseRecordBody(p, result, definition);
-end;
-
-function parseTypeDesc(var p: TPasParser; definition: PNode=nil): PNode;
-var
-  oldcontext: TPasContext;
-  a, r: PNode;
-  i: int;
-begin
-  oldcontext := p.context;
-  p.context := conTypeDesc;
-  if p.tok.xkind = pxPacked then getTok(p);
-  case p.tok.xkind of
-    pxCommand: result := parseCommand(p, definition);
-    pxProcedure, pxFunction: result := parseRoutineType(p);
-    pxRecord: begin
-      getTok(p);
-      if p.tok.xkind = pxCommand then begin
-        result := parseCommand(p);
-        if result.kind <> nkTupleTy then
-          InternalError(result.info, 'parseTypeDesc');
-        parseRecordBody(p, result, definition);
-        a := lastSon(result);
-        // embed nkRecList directly into nkTupleTy
-        for i := 0 to sonsLen(a)-1 do
-          if i = 0 then result.sons[sonsLen(result)-1] := a.sons[0]
-          else addSon(result, a.sons[i]);
-      end
-      else begin
-        result := newNodeP(nkObjectTy, p);
-        addSon(result, nil);
-        addSon(result, nil);
-        parseRecordBody(p, result, definition);
-        if definition <> nil then
-          addPragmaToIdent(definition.sons[0],
-                           newIdentNodeP(getIdent('final'), p))
-        else
-          InternalError(result.info, 'anonymous record is not supported');
-      end;
-    end;
-    pxObject: result := parseRecordOrObject(p, nkObjectTy, definition);
-    pxParLe: result := parseEnum(p);
-    pxArray: begin
-      result := newNodeP(nkBracketExpr, p);
-      getTok(p);
-      if p.tok.xkind = pxBracketLe then begin
-        addSon(result, newIdentNodeP(getIdent('array'), p));
-        getTok(p);
-        addSon(result, rangeExpr(p));
-        eat(p, pxBracketRi);
-      end
-      else begin
-        if p.inParamList then
-          addSon(result, newIdentNodeP(getIdent('openarray'), p))
-        else
-          addSon(result, newIdentNodeP(getIdent('seq'), p));
-      end;
-      eat(p, pxOf);
-      addSon(result, parseTypeDesc(p));
-    end;
-    pxSet: begin
-      result := newNodeP(nkBracketExpr, p);
-      getTok(p);
-      eat(p, pxOf);
-      addSon(result, newIdentNodeP(getIdent('set'), p));
-      addSon(result, parseTypeDesc(p));
-    end;
-    pxHat: begin
-      getTok(p);
-      if p.tok.xkind = pxCommand then
-        result := parseCommand(p)
-      else if gCmd = cmdBoot then
-        result := newNodeP(nkRefTy, p)
-      else
-        result := newNodeP(nkPtrTy, p);
-      addSon(result, parseTypeDesc(p))
-    end;
-    pxType: begin
-      getTok(p);
-      result := parseTypeDesc(p);
-    end;
-    else begin
-      a := primary(p);
-      if p.tok.xkind = pxDotDot then begin
-        result := newNodeP(nkBracketExpr, p);
-        r := newNodeP(nkRange, p);
-        addSon(result, newIdentNodeP(getIdent('range'), p));
-        getTok(p);
-        addSon(r, a);
-        addSon(r, parseExpr(p));
-        addSon(result, r);
-      end
-      else
-        result := a
-    end
-  end;
-  p.context := oldcontext;
-end;
-
-function parseTypeDef(var p: TPasParser): PNode;
-var
-  a: PNode;
-begin
-  result := newNodeP(nkTypeDef, p);
-  addSon(result, identVis(p));
-  addSon(result, nil); // generic params
-  if p.tok.xkind = pxEquals then begin
-    getTok(p); skipCom(p, result);
-    a := parseTypeDesc(p, result);
-    addSon(result, a);
-  end
-  else
-    addSon(result, nil);
-  if p.tok.xkind = pxSemicolon then begin
-    getTok(p); skipCom(p, result);
-  end;
-end;
-
-function parseTypeSection(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkTypeSection, p);
-  getTok(p);
-  skipCom(p, result);
-  while p.tok.xkind = pxSymbol do begin
-    addSon(result, parseTypeDef(p))
-  end
-end;
-
-function parseConstant(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkConstDef, p);
-  addSon(result, identVis(p));
-  if p.tok.xkind = pxColon then begin
-    getTok(p); skipCom(p, result);
-    addSon(result, parseTypeDesc(p));
-  end
-  else begin
-    addSon(result, nil);
-    if p.tok.xkind <> pxEquals then
-      parMessage(p, errColonOrEqualsExpected, pasTokToStr(p.tok));
-  end;
-  if p.tok.xkind = pxEquals then begin
-    getTok(p); skipCom(p, result);
-    addSon(result, parseExpr(p));
-  end
-  else
-    addSon(result, nil);
-  if p.tok.xkind = pxSemicolon then begin
-    getTok(p); skipCom(p, result);
-  end;
-end;
-
-function parseConstSection(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkConstSection, p);
-  getTok(p);
-  skipCom(p, result);
-  while p.tok.xkind = pxSymbol do begin
-    addSon(result, parseConstant(p))
-  end
-end;
-
-function parseVar(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkVarSection, p);
-  getTok(p);
-  skipCom(p, result);
-  while p.tok.xkind = pxSymbol do begin
-    addSon(result, parseIdentColonEquals(p, identVis));
-  end;
-  p.lastVarSection := result
-end;
-
-function parseRoutine(var p: TPasParser): PNode;
-var
-  a, stmts: PNode;
-  noBody: boolean;
-  i: int;
-begin
-  result := newNodeP(nkProcDef, p);
-  getTok(p);
-  skipCom(p, result);
-  expectIdent(p);
-  addSon(result, identVis(p));
-  addSon(result, nil); // generic parameters
-  addSon(result, parseParamList(p));
-  opt(p, pxSemicolon);
-  addSon(result, parseRoutineSpecifiers(p, noBody));
-  if (p.section = seInterface) or noBody then
-    addSon(result, nil)
-  else begin
-    stmts := newNodeP(nkStmtList, p);
-    while true do begin
-      case p.tok.xkind of
-        pxVar:   addSon(stmts, parseVar(p));
-        pxConst: addSon(stmts, parseConstSection(p));
-        pxType:  addSon(stmts, parseTypeSection(p));
-        pxComment: skipCom(p, result);
-        pxBegin: break;
-        else begin
-          parMessage(p, errTokenExpected, 'begin');
-          break
-        end
-      end
-    end;
-    a := parseStmt(p);
-    for i := 0 to sonsLen(a)-1 do addSon(stmts, a.sons[i]);
-    addSon(result, stmts);
-  end
-end;
-
-function fixExit(var p: TPasParser; n: PNode): boolean;
-var
-  len: int;
-  a: PNode;
-begin
-  result := false;
-  if (p.tok.ident.id = getIdent('exit').id) then begin
-    len := sonsLen(n);
-    if (len <= 0) then exit;
-    a := n.sons[len-1];
-    if (a.kind = nkAsgn)
-    and (a.sons[0].kind = nkIdent)
-    and (a.sons[0].ident.id = getIdent('result').id) then begin
-      delSon(a, 0);
-      a.kind := nkReturnStmt;
-      result := true;
-      getTok(p); opt(p, pxSemicolon);
-      skipCom(p, a);
-    end
-  end
-end;
-
-procedure fixVarSection(var p: TPasParser; counter: PNode);
-var
-  i, j: int;
-  v: PNode;
-begin
-  if p.lastVarSection = nil then exit;
-  assert(counter.kind = nkIdent);
-  for i := 0 to sonsLen(p.lastVarSection)-1 do begin
-    v := p.lastVarSection.sons[i];
-    for j := 0 to sonsLen(v)-3 do begin
-      if v.sons[j].ident.id = counter.ident.id then begin
-        delSon(v, j);
-        if sonsLen(v) <= 2 then // : type = int remains --> delete it
-          delSon(p.lastVarSection, i);
-        exit
-      end
-    end
-  end
-end;
-
-procedure parseBegin(var p: TPasParser; result: PNode);
-begin
-  getTok(p);
-  while true do begin
-    case p.tok.xkind of
-      pxComment: addSon(result, parseStmt(p));
-      pxSymbol: begin
-        if not fixExit(p, result) then addSon(result, parseStmt(p))
-      end;
-      pxEnd: begin getTok(p); break end;
-      pxSemicolon: begin getTok(p); end;
-      pxEof: parMessage(p, errExprExpected);
-      else addSonIfNotNil(result, parseStmt(p));
-    end
-  end;
-  if sonsLen(result) = 0 then
-    addSon(result, newNodeP(nkNilLit, p));
-end;
-
-function parseStmt(var p: TPasParser): PNode;
-var
-  oldcontext: TPasContext;
-begin
-  oldcontext := p.context;
-  p.context := conStmt;
-  result := nil;
-  case p.tok.xkind of
-    pxBegin:    begin
-      result := newNodeP(nkStmtList, p);
-      parseBegin(p, result);
-    end;
-    pxCommand:  result := parseCommand(p);
-    pxCurlyDirLe, pxStarDirLe: begin
-      if isHandledDirective(p) then
-        result := parseDirective(p);
-    end;
-    pxIf:       result := parseIf(p);
-    pxWhile:    result := parseWhile(p);
-    pxRepeat:   result := parseRepeat(p);
-    pxCase:     result := parseCase(p);
-    pxTry:      result := parseTry(p);
-    pxProcedure, pxFunction:  result := parseRoutine(p);
-    pxType:     result := parseTypeSection(p);
-    pxConst:    result := parseConstSection(p);
-    pxVar:      result := parseVar(p);
-    pxFor:      begin
-      result := parseFor(p);
-      fixVarSection(p, result.sons[0]);
-    end;
-    pxRaise:    result := parseRaise(p);
-    pxUses:     result := parseUsesStmt(p);
-    pxProgram, pxUnit, pxLibrary: begin
-      // skip the pointless header
-      while not (p.tok.xkind in [pxSemicolon, pxEof]) do getTok(p);
-      getTok(p);
-    end;
-    pxInitialization: begin
-      getTok(p); // just skip the token
-    end;
-    pxImplementation: begin
-      p.section := seImplementation;
-      result := newNodeP(nkCommentStmt, p);
-      result.comment := '# implementation';
-      getTok(p);
-    end;
-    pxInterface: begin
-      p.section := seInterface;
-      getTok(p);
-    end;
-    pxComment: begin
-      result := newNodeP(nkCommentStmt, p);
-      skipCom(p, result);
-    end;
-    pxSemicolon: getTok(p);
-    pxSymbol: begin
-      if p.tok.ident.id = getIdent('break').id then begin
-        result := newNodeP(nkBreakStmt, p);
-        getTok(p); skipCom(p, result);
-        addSon(result, nil);
-      end
-      else if p.tok.ident.id = getIdent('continue').id then begin
-        result := newNodeP(nkContinueStmt, p);
-        getTok(p); skipCom(p, result);
-        addSon(result, nil);
-      end
-      else if p.tok.ident.id = getIdent('exit').id then begin
-        result := newNodeP(nkReturnStmt, p);
-        getTok(p); skipCom(p, result);
-        addSon(result, nil);
-      end
-      else result := parseExprStmt(p)
-    end;
-    pxDot: getTok(p); // BUGFIX for ``end.`` in main program
-    else result := parseExprStmt(p)
-  end;
-  opt(p, pxSemicolon);
-  if result <> nil then skipCom(p, result);
-  p.context := oldcontext;
-end;
-
-function parseUnit(var p: TPasParser): PNode;
-begin
-  result := newNodeP(nkStmtList, p);
-  getTok(p); // read first token
-  while true do begin
-    case p.tok.xkind of
-      pxEof, pxEnd: break;
-      pxBegin: parseBegin(p, result);
-      pxCurlyDirLe, pxStarDirLe: begin
-        if isHandledDirective(p) then
-          addSon(result, parseDirective(p))
-        else
-          parMessage(p, errXNotAllowedHere, p.tok.ident.s)
-      end
-      else addSon(result, parseStmt(p))
-    end;
-  end;
-  opt(p, pxEnd);
-  opt(p, pxDot);
-  if p.tok.xkind <> pxEof then
-    addSon(result, parseStmt(p)); // comments after final 'end.'
-end;
-
-end.