summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/c2nim/c2nim.nim2
-rwxr-xr-xcompiler/c2nim/cparse.nim2
-rwxr-xr-xcompiler/cgen.nim2
-rwxr-xr-xcompiler/cgmeth.nim2
-rwxr-xr-xcompiler/docgen.nim2
-rwxr-xr-xcompiler/ecmasgen.nim2
-rwxr-xr-xcompiler/evals.nim2
-rwxr-xr-xcompiler/filter_tmpl.nim (renamed from compiler/ptmplsyn.nim)2
-rwxr-xr-xcompiler/filters.nim3
-rwxr-xr-xcompiler/highlite.nim14
-rwxr-xr-xcompiler/lexer.nim (renamed from compiler/scanner.nim)0
-rwxr-xr-xcompiler/lookups.nim2
-rwxr-xr-xcompiler/main.nim2
-rwxr-xr-xcompiler/nimconf.nim2
-rwxr-xr-xcompiler/nimrod.nim2
-rwxr-xr-xcompiler/nimsets.nim4
-rwxr-xr-xcompiler/parser.nim (renamed from compiler/pnimsyn.nim)2
-rwxr-xr-xcompiler/pas2nim/pas2nim.nim2
-rwxr-xr-xcompiler/passes.nim4
-rwxr-xr-xcompiler/pbraces.nim1193
-rwxr-xr-xcompiler/pendx.nim13
-rwxr-xr-xcompiler/pragmas.nim2
-rwxr-xr-xcompiler/renderer.nim (renamed from compiler/rnimsyn.nim)4
-rwxr-xr-xcompiler/sem.nim6
-rwxr-xr-xcompiler/semdata.nim6
-rwxr-xr-xcompiler/semfold.nim2
-rwxr-xr-xcompiler/sigmatch.nim2
-rwxr-xr-xcompiler/suggest.nim5
-rwxr-xr-xcompiler/syntaxes.nim14
-rwxr-xr-xcompiler/transf.nim2
-rwxr-xr-xcompiler/trees.nim2
-rwxr-xr-xdoc/filelist.txt13
-rw-r--r--lib/pure/collections/hashtables.nim111
-rwxr-xr-xlib/pure/collections/lists.nim155
34 files changed, 326 insertions, 1257 deletions
diff --git a/compiler/c2nim/c2nim.nim b/compiler/c2nim/c2nim.nim
index f4e185445..beb4465fc 100755
--- a/compiler/c2nim/c2nim.nim
+++ b/compiler/c2nim/c2nim.nim
@@ -8,7 +8,7 @@
 #
 
 import 
-  strutils, os, times, parseopt, llstream, ast, rnimsyn, options, msgs,
+  strutils, os, times, parseopt, llstream, ast, renderer, options, msgs,
   clex, cparse
 
 const
diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim
index ce9caf7f5..d2b7caff6 100755
--- a/compiler/c2nim/cparse.nim
+++ b/compiler/c2nim/cparse.nim
@@ -14,7 +14,7 @@
 # XXX cleanup of declaration handling.
 
 import 
-  os, llstream, rnimsyn, clex, idents, strutils, pegs, ast, astalgo, msgs,
+  os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs,
   options, strtabs
 
 type 
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index a15c4c4ca..d76793c9a 100755
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -14,7 +14,7 @@ import
   ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp,
   options, 
   nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, 
-  times, ropes, math, passes, rodread, wordrecg, rnimsyn, treetab, cgmeth,
+  times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
   rodutils
 
 when options.hasTinyCBackend:
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index f9b12647f..12d58cdc1 100755
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -10,7 +10,7 @@
 ## This module implements code generation for multi methods.
 
 import 
-  options, ast, astalgo, msgs, idents, rnimsyn, types, magicsys
+  options, ast, astalgo, msgs, idents, renderer, types, magicsys
 
 proc genConv(n: PNode, d: PType, downcast: bool): PNode = 
   var 
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index ed5ca20ed..74316871d 100755
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -13,7 +13,7 @@
 
 import 
   ast, astalgo, strutils, nhashes, options, nversion, msgs, os, ropes, idents, 
-  wordrecg, math, syntaxes, rnimsyn, scanner, rst, times, highlite
+  wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite
 
 proc CommandDoc*(filename: string)
 proc CommandRst2Html*(filename: string)
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim
index 6898b01d1..a46c2b805 100755
--- a/compiler/ecmasgen.nim
+++ b/compiler/ecmasgen.nim
@@ -14,7 +14,7 @@
 import 
   ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp,
   options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
-  times, ropes, math, passes, ccgutils, wordrecg, rnimsyn, rodread, rodutils
+  times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils
 
 proc ecmasgenPass*(): TPass
 # implementation
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 7d0f9c801..d9c577367 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -15,7 +15,7 @@
 
 import 
   strutils, magicsys, lists, options, ast, astalgo, trees, treetab, nimsets, 
-  msgs, os, condsyms, idents, rnimsyn, types, passes, semfold
+  msgs, os, condsyms, idents, renderer, types, passes, semfold
 
 type 
   PStackFrame* = ref TStackFrame
diff --git a/compiler/ptmplsyn.nim b/compiler/filter_tmpl.nim
index 9699f1c58..0bb402874 100755
--- a/compiler/ptmplsyn.nim
+++ b/compiler/filter_tmpl.nim
@@ -11,7 +11,7 @@
 
 import 
   llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, 
-  rnimsyn, filters
+  renderer, filters
 
 proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode): PLLStream
   # #! template(subsChar='$', metaChar='#') | standard(version="0.7.2")
diff --git a/compiler/filters.nim b/compiler/filters.nim
index d1c61749d..43ac13c00 100755
--- a/compiler/filters.nim
+++ b/compiler/filters.nim
@@ -10,7 +10,8 @@
 # This module implements Nimrod's simple filters and helpers for filters.
 
 import
-  llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, rnimsyn
+  llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, 
+  renderer
 
 proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream
 proc filterStrip*(stdin: PLLStream, filename: string, call: PNode): PLLStream
diff --git a/compiler/highlite.nim b/compiler/highlite.nim
index c2fc95da8..c343074e7 100755
--- a/compiler/highlite.nim
+++ b/compiler/highlite.nim
@@ -12,7 +12,7 @@
 # The interface supports one language nested in another.
 
 import 
-  nhashes, options, msgs, strutils, platform, idents, lexbase, wordrecg, scanner
+  nhashes, options, msgs, strutils, platform, idents, lexbase, wordrecg, lexer
 
 type 
   TTokenClass* = enum 
@@ -154,7 +154,7 @@ proc nimNextToken(g: var TGeneralTokenizer) =
       while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): inc(pos)
     of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF': 
       var id = ""
-      while g.buf[pos] in scanner.SymChars + {'_'}: 
+      while g.buf[pos] in lexer.SymChars + {'_'}: 
         add(id, g.buf[pos])
         inc(pos)
       if (g.buf[pos] == '\"'): 
@@ -247,9 +247,9 @@ proc nimNextToken(g: var TGeneralTokenizer) =
     of '\0': 
       g.kind = gtEof
     else: 
-      if g.buf[pos] in scanner.OpChars: 
+      if g.buf[pos] in lexer.OpChars: 
         g.kind = gtOperator
-        while g.buf[pos] in scanner.OpChars: inc(pos)
+        while g.buf[pos] in lexer.OpChars: inc(pos)
       else: 
         inc(pos)
         g.kind = gtNone
@@ -462,10 +462,10 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openarray[string],
     of '\0': 
       g.kind = gtEof
     else: 
-      if g.buf[pos] in scanner.OpChars: 
+      if g.buf[pos] in lexer.OpChars: 
         g.kind = gtOperator
-        while g.buf[pos] in scanner.OpChars: inc(pos)
-      else: 
+        while g.buf[pos] in lexer.OpChars: inc(pos)
+      else:
         inc(pos)
         g.kind = gtNone
   g.length = pos - g.pos
diff --git a/compiler/scanner.nim b/compiler/lexer.nim
index f3d83480d..f3d83480d 100755
--- a/compiler/scanner.nim
+++ b/compiler/lexer.nim
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index f65fe24b7..80a6cd17e 100755
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -10,7 +10,7 @@
 # This module implements lookup helpers.
 
 import 
-  ast, astalgo, idents, semdata, types, msgs, options, rodread, rnimsyn
+  ast, astalgo, idents, semdata, types, msgs, options, rodread, renderer
 
 type 
   TOverloadIterMode* = enum 
diff --git a/compiler/main.nim b/compiler/main.nim
index bd429cad9..c43d35a96 100755
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -11,7 +11,7 @@
 # module handling
 
 import 
-  llstream, strutils, ast, astalgo, scanner, syntaxes, rnimsyn, options, msgs, 
+  llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs, 
   os, lists, condsyms, rodread, rodwrite, ropes, trees, 
   wordrecg, sem, semdata, idents, passes, docgen, extccomp,
   cgen, ecmasgen,
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
index 31558fe74..5d549c0f4 100755
--- a/compiler/nimconf.nim
+++ b/compiler/nimconf.nim
@@ -10,7 +10,7 @@
 # This module handles the reading of the config file.
 
 import 
-  llstream, nversion, commands, os, strutils, msgs, platform, condsyms, scanner, 
+  llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer, 
   options, idents, wordrecg
 
 # ---------------- configuration file parser -----------------------------
diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim
index a1751da7f..05c7a2af1 100755
--- a/compiler/nimrod.nim
+++ b/compiler/nimrod.nim
@@ -11,7 +11,7 @@ when defined(gcc) and defined(windows):
   {.link: "icons/nimrod.res".}
 
 import 
-  times, commands, scanner, condsyms, options, msgs, nversion, nimconf, ropes, 
+  times, commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, 
   extccomp, strutils, os, platform, main, parseopt
 
 when hasTinyCBackend:
diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim
index 337aedda9..218cd8b62 100755
--- a/compiler/nimsets.nim
+++ b/compiler/nimsets.nim
@@ -10,7 +10,7 @@
 # this unit handles Nimrod sets; it implements symbolic sets
 
 import 
-  ast, astalgo, trees, nversion, msgs, platform, bitsets, types, rnimsyn
+  ast, astalgo, trees, nversion, msgs, platform, bitsets, types, renderer
 
 proc toBitSet*(s: PNode, b: var TBitSet)
   # this function is used for case statement checking:
@@ -172,4 +172,4 @@ proc SetHasRange(s: PNode): bool =
 
 proc emptyRange(a, b: PNode): bool = 
   result = not leValue(a, b)  # a > b iff not (a <= b)
-  
\ No newline at end of file
+  
diff --git a/compiler/pnimsyn.nim b/compiler/parser.nim
index 80adc7824..871f486fc 100755
--- a/compiler/pnimsyn.nim
+++ b/compiler/parser.nim
@@ -15,7 +15,7 @@
 # from the grammar and how comments belong to the AST.
 
 import
-  llstream, scanner, idents, strutils, ast, msgs
+  llstream, lexer, idents, strutils, ast, msgs
 
 type 
   TParser*{.final.} = object  # a TParser object represents a module that
diff --git a/compiler/pas2nim/pas2nim.nim b/compiler/pas2nim/pas2nim.nim
index 5c7b68857..7f66e8e47 100755
--- a/compiler/pas2nim/pas2nim.nim
+++ b/compiler/pas2nim/pas2nim.nim
@@ -8,7 +8,7 @@
 #
 
 import 
-  strutils, os, parseopt, llstream, ast, rnimsyn, options, msgs,
+  strutils, os, parseopt, llstream, ast, renderer, options, msgs,
   paslex, pasparse
 
 const
diff --git a/compiler/passes.nim b/compiler/passes.nim
index b380cd66f..34e2b03a5 100755
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -12,8 +12,8 @@
 
 import 
   strutils, lists, options, ast, astalgo, llstream, msgs, platform, os, 
-  condsyms, idents, rnimsyn, types, extccomp, math, magicsys, nversion, nimsets, 
-  syntaxes, times, rodread
+  condsyms, idents, renderer, types, extccomp, math, magicsys, nversion, 
+  nimsets, syntaxes, times, rodread
 
 type 
   TPassContext* = object of TObject # the pass's context
diff --git a/compiler/pbraces.nim b/compiler/pbraces.nim
index 45d38e342..18d654d6c 100755
--- a/compiler/pbraces.nim
+++ b/compiler/pbraces.nim
@@ -8,1194 +8,11 @@
 #
 
 import 
-  llstream, scanner, idents, strutils, ast, msgs, pnimsyn
+  llstream, lexer, parser, idents, strutils, ast, msgs
 
-proc ParseAll*(p: var TParser): PNode
-proc parseTopLevelStmt*(p: var TParser): PNode
-  # implements an iterator. Returns the next top-level statement or nil if end
-  # of stream.
-# implementation
-# ------------------- Expression parsing ------------------------------------
-
-proc parseExpr(p: var TParser): PNode
-proc parseStmt(p: var TParser): PNode
-proc parseTypeDesc(p: var TParser): PNode
-proc parseParamList(p: var TParser): PNode
-proc optExpr(p: var TParser): PNode = 
-  # [expr]
-  if (p.tok.tokType != tkComma) and (p.tok.tokType != tkBracketRi) and
-      (p.tok.tokType != tkDotDot): 
-    result = parseExpr(p)
-  else: 
-    result = nil
-  
-proc dotdotExpr(p: var TParser, first: PNode = nil): PNode = 
-  result = newNodeP(nkRange, p)
-  addSon(result, first)
-  getTok(p)
-  optInd(p, result)
-  addSon(result, optExpr(p))
-
-proc indexExpr(p: var TParser): PNode = 
-  # indexExpr ::= '..' [expr] | expr ['=' expr | '..' expr]
-  var a, b: PNode
-  if p.tok.tokType == tkDotDot: 
-    result = dotdotExpr(p)
-  else: 
-    a = parseExpr(p)
-    case p.tok.tokType
-    of tkEquals: 
-      result = newNodeP(nkExprEqExpr, p)
-      addSon(result, a)
-      getTok(p)
-      if p.tok.tokType == tkDotDot: 
-        addSon(result, dotdotExpr(p))
-      else: 
-        b = parseExpr(p)
-        if p.tok.tokType == tkDotDot: b = dotdotExpr(p, b)
-        addSon(result, b)
-    of tkDotDot: 
-      result = dotdotExpr(p, a)
-    else: result = a
-  
-proc indexExprList(p: var TParser, first: PNode): PNode = 
-  var a: PNode
-  result = newNodeP(nkBracketExpr, p)
-  addSon(result, first)
-  getTok(p)
-  optInd(p, result)
-  while (p.tok.tokType != tkBracketRi) and (p.tok.tokType != tkEof) and
-      (p.tok.tokType != tkSad): 
-    a = indexExpr(p)
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-  optPar(p)
-  eat(p, tkBracketRi)
-
-proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode = 
-  var a: PNode
-  a = parseExpr(p)
-  if p.tok.tokType == tok: 
-    result = newNodeP(kind, p)
-    getTok(p)                 #optInd(p, result);
-    addSon(result, a)
-    addSon(result, parseExpr(p))
-  else: 
-    result = a
-  
-proc exprListAux(p: var TParser, elemKind: TNodeKind, endTok, sepTok: TTokType, 
-                 result: PNode) = 
-  var a: PNode
-  getTok(p)
-  optInd(p, result)
-  while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof): 
-    a = exprColonEqExpr(p, elemKind, sepTok)
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-  eat(p, endTok)
-
-proc qualifiedIdent(p: var TParser): PNode = 
-  var a: PNode
-  result = parseSymbol(p)
-  if p.tok.tokType == tkDot: 
-    getTok(p)
-    optInd(p, result)
-    a = result
-    result = newNodeI(nkDotExpr, a.info)
-    addSon(result, a)
-    addSon(result, parseSymbol(p))
-
-proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) = 
-  var a: PNode
-  getTok(p)
-  optInd(p, result)
-  while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof): 
-    a = qualifiedIdent(p)
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-  eat(p, endTok)
-
-proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind, 
-                            endTok, sepTok: TTokType, result: PNode) = 
-  var a: PNode
-  getTok(p)
-  optInd(p, result)
-  while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof) and
-      (p.tok.tokType != tkSad): 
-    a = exprColonEqExpr(p, elemKind, sepTok)
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-  optPar(p)
-  eat(p, endTok)
-
-proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind, 
-                         endTok, sepTok: TTokType): PNode = 
-  result = newNodeP(kind, p)
-  exprColonEqExprListAux(p, elemKind, endTok, sepTok, result)
-
-proc parseCast(p: var TParser): PNode = 
-  result = newNodeP(nkCast, p)
-  getTok(p)
-  eat(p, tkBracketLe)
-  optInd(p, result)
-  addSon(result, parseTypeDesc(p))
-  optPar(p)
-  eat(p, tkBracketRi)
-  eat(p, tkParLe)
-  optInd(p, result)
-  addSon(result, parseExpr(p))
-  optPar(p)
-  eat(p, tkParRi)
-
-proc parseAddr(p: var TParser): PNode = 
-  result = newNodeP(nkAddr, p)
-  getTok(p)
-  eat(p, tkParLe)
-  optInd(p, result)
-  addSon(result, parseExpr(p))
-  optPar(p)
-  eat(p, tkParRi)
-  
-proc parseGStrLit(p: var TParser, a: PNode): PNode = 
-  case p.tok.tokType
-  of tkGStrLit: 
-    result = newNodeP(nkCallStrLit, p)
-    addSon(result, a)
-    addSon(result, newStrNodeP(nkRStrLit, p.tok.literal, p))
-    getTok(p)
-  of tkGTripleStrLit: 
-    result = newNodeP(nkCallStrLit, p)
-    addSon(result, a)
-    addSon(result, newStrNodeP(nkTripleStrLit, p.tok.literal, p))
-    getTok(p)
-  else:
-    result = a
-
-proc identOrLiteral(p: var TParser): PNode = 
-  case p.tok.tokType
-  of tkSymbol: 
-    result = newIdentNodeP(p.tok.ident, p)
-    getTok(p)
-    result = parseGStrLit(p, result)
-  of tkAccent: 
-    result = accExpr(p)       # literals
-  of tkIntLit: 
-    result = newIntNodeP(nkIntLit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of tkInt8Lit: 
-    result = newIntNodeP(nkInt8Lit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of tkInt16Lit: 
-    result = newIntNodeP(nkInt16Lit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of tkInt32Lit: 
-    result = newIntNodeP(nkInt32Lit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of tkInt64Lit: 
-    result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of tkFloatLit: 
-    result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of tkFloat32Lit: 
-    result = newFloatNodeP(nkFloat32Lit, p.tok.fNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of tkFloat64Lit: 
-    result = newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p)
-    setBaseFlags(result, p.tok.base)
-    getTok(p)
-  of tkStrLit: 
-    result = newStrNodeP(nkStrLit, p.tok.literal, p)
-    getTok(p)
-  of tkRStrLit: 
-    result = newStrNodeP(nkRStrLit, p.tok.literal, p)
-    getTok(p)
-  of tkTripleStrLit: 
-    result = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
-    getTok(p)
-  of tkCharLit: 
-    result = newIntNodeP(nkCharLit, ord(p.tok.literal[0]), p)
-    getTok(p)
-  of tkNil: 
-    result = newNodeP(nkNilLit, p)
-    getTok(p)
-  of tkParLe: 
-    # () constructor
-    result = exprColonEqExprList(p, nkPar, nkExprColonExpr, tkParRi, tkColon)
-  of tkCurlyLe: 
-    # {} constructor
-    result = exprColonEqExprList(p, nkCurly, nkRange, tkCurlyRi, tkDotDot)
-  of tkBracketLe: 
-    # [] constructor
-    result = exprColonEqExprList(p, nkBracket, nkExprColonExpr, tkBracketRi, 
-                                 tkColon)
-  of tkCast: 
-    result = parseCast(p)
-  of tkAddr: 
-    result = parseAddr(p)
-  else: 
-    parMessage(p, errExprExpected, tokToStr(p.tok))
-    getTok(p)                 # we must consume a token here to prevend endless loops!
-    result = nil
-
-proc primary(p: var TParser): PNode = 
-  var a: PNode
-  # prefix operator?
-  if (p.tok.tokType == tkNot) or (p.tok.tokType == tkOpr): 
-    result = newNodeP(nkPrefix, p)
-    a = newIdentNodeP(p.tok.ident, p)
-    addSon(result, a)
-    getTok(p)
-    optInd(p, a)
-    addSon(result, primary(p))
-    return 
-  elif p.tok.tokType == tkBind: 
-    result = newNodeP(nkBind, p)
-    getTok(p)
-    optInd(p, result)
-    addSon(result, primary(p))
-    return 
-  result = identOrLiteral(p)
-  while true: 
-    case p.tok.tokType
-    of tkParLe: 
-      a = result
-      result = newNodeP(nkCall, p)
-      addSon(result, a)
-      exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
-    of tkDot: 
-      a = result
-      result = newNodeP(nkDotExpr, p)
-      addSon(result, a)
-      getTok(p)               # skip '.'
-      optInd(p, result)
-      addSon(result, parseSymbol(p))
-      result = parseGStrLit(p, result)
-    of tkHat: 
-      a = result
-      result = newNodeP(nkDerefExpr, p)
-      addSon(result, a)
-      getTok(p)
-    of tkBracketLe: 
-      result = indexExprList(p, result)
-    else: break 
-  
-proc lowestExprAux(p: var TParser, v: var PNode, limit: int): PToken = 
-  var 
-    op, nextop: PToken
-    opPred: int
-    v2, node, opNode: PNode
-  v = primary(p)              # expand while operators have priorities higher than 'limit'
-  op = p.tok
-  opPred = getPrecedence(p.tok)
-  while (opPred > limit): 
-    node = newNodeP(nkInfix, p)
-    opNode = newIdentNodeP(op.ident, p) # skip operator:
-    getTok(p)
-    optInd(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)
-  result = op                 # return first untreated operator
-  
-proc lowestExpr(p: var TParser): PNode = 
-  discard lowestExprAux(p, result, - 1)
-
-proc parseIfExpr(p: var TParser): PNode = 
-  # if (expr) expr else expr
-  var branch: PNode
-  result = newNodeP(nkIfExpr, p)
-  while true: 
-    getTok(p)                 # skip `if`, `elif`
-    branch = newNodeP(nkElifExpr, p)
-    eat(p, tkParLe)
-    addSon(branch, parseExpr(p))
-    eat(p, tkParRi)
-    addSon(branch, parseExpr(p))
-    addSon(result, branch)
-    if p.tok.tokType != tkElif: break 
-  branch = newNodeP(nkElseExpr, p)
-  eat(p, tkElse)
-  addSon(branch, parseExpr(p))
-  addSon(result, branch)
-
-proc parsePragma(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkPragma, p)
-  getTok(p)
-  optInd(p, result)
-  while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
-      (p.tok.tokType != tkEof) and (p.tok.tokType != tkSad): 
-    a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
-    addSon(result, a)
-    if p.tok.tokType == tkComma: 
-      getTok(p)
-      optInd(p, a)
-  optPar(p)
-  if (p.tok.tokType == tkCurlyDotRi) or (p.tok.tokType == tkCurlyRi): getTok(p)
-  else: parMessage(p, errTokenExpected, ".}")
-  
-proc identVis(p: var TParser): PNode = 
-  # identifier with visability
-  var a: PNode
-  a = parseSymbol(p)
-  if p.tok.tokType == tkOpr: 
-    result = newNodeP(nkPostfix, p)
-    addSon(result, newIdentNodeP(p.tok.ident, p))
-    addSon(result, a)
-    getTok(p)
-  else: 
-    result = a
-  
-proc identWithPragma(p: var TParser): PNode = 
-  var a: PNode
-  a = identVis(p)
-  if p.tok.tokType == tkCurlyDotLe: 
-    result = newNodeP(nkPragmaExpr, p)
-    addSon(result, a)
-    addSon(result, parsePragma(p))
-  else: 
-    result = a
-  
-type 
-  TDeclaredIdentFlag = enum 
-    withPragma,               # identifier may have pragma
-    withBothOptional          # both ':' and '=' parts are optional
-  TDeclaredIdentFlags = set[TDeclaredIdentFlag]
-
-proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode = 
-  var a: PNode
-  result = newNodeP(nkIdentDefs, p)
-  while true: 
-    case p.tok.tokType
-    of tkSymbol, tkAccent: 
-      if withPragma in flags: a = identWithPragma(p)
-      else: a = parseSymbol(p)
-      if a == nil: return 
-    else: break 
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-  if p.tok.tokType == tkColon: 
-    getTok(p)
-    optInd(p, result)
-    addSon(result, parseTypeDesc(p))
-  else: 
-    addSon(result, nil)
-    if (p.tok.tokType != tkEquals) and not (withBothOptional in flags): 
-      parMessage(p, errColonOrEqualsExpected, tokToStr(p.tok))
-  if p.tok.tokType == tkEquals: 
-    getTok(p)
-    optInd(p, result)
-    addSon(result, parseExpr(p))
-  else: 
-    addSon(result, nil)
-  
-proc parseTuple(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkTupleTy, p)
-  getTok(p)
-  eat(p, tkBracketLe)
-  optInd(p, result)
-  while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent): 
-    a = parseIdentColonEquals(p, {})
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-  optPar(p)
-  eat(p, tkBracketRi)
-
-proc parseParamList(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkFormalParams, p)
-  addSon(result, nil)         # return type
-  if p.tok.tokType == tkParLe: 
-    getTok(p)
-    optInd(p, result)
-    while true: 
-      case p.tok.tokType
-      of tkSymbol, tkAccent: a = parseIdentColonEquals(p, {})
-      of tkParRi: break 
-      else: 
-        parMessage(p, errTokenExpected, ")")
-        break 
-      addSon(result, a)
-      if p.tok.tokType != tkComma: break 
-      getTok(p)
-      optInd(p, a)
-    optPar(p)
-    eat(p, tkParRi)
-  if p.tok.tokType == tkColon: 
-    getTok(p)
-    optInd(p, result)
-    result.sons[0] = parseTypeDesc(p)
-
-proc parseProcExpr(p: var TParser, isExpr: bool): PNode = 
-  # either a proc type or a anonymous proc
-  var 
-    pragmas, params: PNode
-    info: TLineInfo
-  info = parLineInfo(p)
-  getTok(p)
-  params = parseParamList(p)
-  if p.tok.tokType == tkCurlyDotLe: pragmas = parsePragma(p)
-  else: pragmas = nil
-  if (p.tok.tokType == tkCurlyLe) and isExpr: 
-    result = newNodeI(nkLambda, info)
-    addSon(result, nil)       # no name part
-    addSon(result, nil)       # no generic parameters
-    addSon(result, params)
-    addSon(result, pragmas)   #getTok(p); skipComment(p, result);
-    addSon(result, parseStmt(p))
-  else: 
-    result = newNodeI(nkProcTy, info)
-    addSon(result, params)
-    addSon(result, pragmas)
-
-proc parseTypeDescKAux(p: var TParser, kind: TNodeKind): PNode = 
-  result = newNodeP(kind, p)
-  getTok(p)
-  optInd(p, result)
-  addSon(result, parseTypeDesc(p))
-
-proc parseExpr(p: var TParser): PNode = 
-  #
-  #expr ::= lowestExpr
-  #     | 'if' expr ':' expr ('elif' expr ':' expr)* 'else' ':' expr
-  #     | 'var' expr
-  #     | 'ref' expr
-  #     | 'ptr' expr
-  #     | 'type' expr
-  #     | 'tuple' tupleDesc
-  #     | 'proc' paramList [pragma] ['=' stmt] 
-  #
-  case p.tok.toktype
-  of tkVar: result = parseTypeDescKAux(p, nkVarTy)
-  of tkRef: result = parseTypeDescKAux(p, nkRefTy)
-  of tkPtr: result = parseTypeDescKAux(p, nkPtrTy)
-  of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr)
-  of tkTuple: result = parseTuple(p)
-  of tkProc: result = parseProcExpr(p, true)
-  of tkIf: result = parseIfExpr(p)
-  else: result = lowestExpr(p)
-  
-proc parseTypeDesc(p: var TParser): PNode = 
-  if p.tok.toktype == tkProc: result = parseProcExpr(p, false)
-  else: result = parseExpr(p)
-  
-proc isExprStart(p: TParser): bool = 
-  case p.tok.tokType
-  of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkProc, tkBind, 
-     tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr, 
-     tkTuple, tkType: 
-    result = true
-  else: result = false
-  
-proc parseExprStmt(p: var TParser): PNode = 
-  var a, b, e: PNode
-  a = lowestExpr(p)
-  if p.tok.tokType == tkEquals: 
-    getTok(p)
-    optInd(p, result)
-    b = parseExpr(p)
-    result = newNodeI(nkAsgn, a.info)
-    addSon(result, a)
-    addSon(result, b)
-  else: 
-    result = newNodeP(nkCommand, p)
-    result.info = a.info
-    addSon(result, a)
-    while true: 
-      if not isExprStart(p): break 
-      e = parseExpr(p)
-      addSon(result, e)
-      if p.tok.tokType != tkComma: break 
-      getTok(p)
-      optInd(p, a)
-    if sonsLen(result) <= 1: result = a
-    else: a = result
-    if p.tok.tokType == tkCurlyLe: 
-      # macro statement
-      result = newNodeP(nkMacroStmt, p)
-      result.info = a.info
-      addSon(result, a)
-      getTok(p)
-      skipComment(p, result)
-      if (p.tok.tokType == tkInd) or
-          not (p.tok.TokType in {tkOf, tkElif, tkElse, tkExcept}): 
-        addSon(result, parseStmt(p))
-      while true: 
-        if p.tok.tokType == tkSad: getTok(p)
-        case p.tok.tokType
-        of tkOf: 
-          b = newNodeP(nkOfBranch, p)
-          exprListAux(p, nkRange, tkCurlyLe, tkDotDot, b)
-        of tkElif: 
-          b = newNodeP(nkElifBranch, p)
-          getTok(p)
-          optInd(p, b)
-          addSon(b, parseExpr(p))
-          eat(p, tkCurlyLe)
-        of tkExcept: 
-          b = newNodeP(nkExceptBranch, p)
-          qualifiedIdentListAux(p, tkCurlyLe, b)
-          skipComment(p, b)
-        of tkElse: 
-          b = newNodeP(nkElse, p)
-          getTok(p)
-          eat(p, tkCurlyLe)
-        else: break 
-        addSon(b, parseStmt(p))
-        eat(p, tkCurlyRi)
-        addSon(result, b)
-        if b.kind == nkElse: break 
-      eat(p, tkCurlyRi)
-
-proc parseImportOrIncludeStmt(p: var TParser, kind: TNodeKind): PNode = 
-  var a: PNode
-  result = newNodeP(kind, p)
-  getTok(p)                   # skip `import` or `include`
-  optInd(p, result)
-  while true: 
-    case p.tok.tokType
-    of tkEof, tkSad, tkDed: 
-      break 
-    of tkSymbol, tkAccent: 
-      a = parseSymbol(p)
-    of tkRStrLit: 
-      a = newStrNodeP(nkRStrLit, p.tok.literal, p)
-      getTok(p)
-    of tkStrLit: 
-      a = newStrNodeP(nkStrLit, p.tok.literal, p)
-      getTok(p)
-    of tkTripleStrLit: 
-      a = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
-      getTok(p)
-    else: 
-      parMessage(p, errIdentifierExpected, tokToStr(p.tok))
-      break 
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-
-proc parseFromStmt(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkFromStmt, p)
-  getTok(p)                   # skip `from`
-  optInd(p, result)
-  case p.tok.tokType
-  of tkSymbol, tkAccent: 
-    a = parseSymbol(p)
-  of tkRStrLit: 
-    a = newStrNodeP(nkRStrLit, p.tok.literal, p)
-    getTok(p)
-  of tkStrLit: 
-    a = newStrNodeP(nkStrLit, p.tok.literal, p)
-    getTok(p)
-  of tkTripleStrLit: 
-    a = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
-    getTok(p)
-  else: 
-    parMessage(p, errIdentifierExpected, tokToStr(p.tok))
-    return 
-  addSon(result, a)           #optInd(p, a);
-  eat(p, tkImport)
-  optInd(p, result)
-  while true: 
-    case p.tok.tokType        #optInd(p, a);
-    of tkEof, tkSad, tkDed: 
-      break 
-    of tkSymbol, tkAccent: 
-      a = parseSymbol(p)
-    else: 
-      parMessage(p, errIdentifierExpected, tokToStr(p.tok))
-      break 
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-
-proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode = 
-  result = newNodeP(kind, p)
-  getTok(p)
-  optInd(p, result)
-  case p.tok.tokType
-  of tkEof, tkSad, tkDed: addSon(result, nil)
-  else: addSon(result, parseExpr(p))
-  
-proc parseYieldOrDiscard(p: var TParser, kind: TNodeKind): PNode = 
-  result = newNodeP(kind, p)
-  getTok(p)
-  optInd(p, result)
-  addSon(result, parseExpr(p))
-
-proc parseBreakOrContinue(p: var TParser, kind: TNodeKind): PNode = 
-  result = newNodeP(kind, p)
-  getTok(p)
-  optInd(p, result)
-  case p.tok.tokType
-  of tkEof, tkSad, tkDed: addSon(result, nil)
-  else: addSon(result, parseSymbol(p))
-  
-proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode = 
-  var branch: PNode
-  result = newNodeP(kind, p)
-  while true: 
-    getTok(p)                 # skip `if`, `when`, `elif`
-    branch = newNodeP(nkElifBranch, p)
-    optInd(p, branch)
-    eat(p, tkParLe)
-    addSon(branch, parseExpr(p))
-    eat(p, tkParRi)
-    skipComment(p, branch)
-    addSon(branch, parseStmt(p))
-    skipComment(p, branch)
-    addSon(result, branch)
-    if p.tok.tokType != tkElif: break 
-  if p.tok.tokType == tkElse: 
-    branch = newNodeP(nkElse, p)
-    eat(p, tkElse)
-    skipComment(p, branch)
-    addSon(branch, parseStmt(p))
-    addSon(result, branch)
-
-proc parseWhile(p: var TParser): PNode = 
-  result = newNodeP(nkWhileStmt, p)
-  getTok(p)
-  optInd(p, result)
-  eat(p, tkParLe)
-  addSon(result, parseExpr(p))
-  eat(p, tkParRi)
-  skipComment(p, result)
-  addSon(result, parseStmt(p))
-
-proc parseCase(p: var TParser): PNode = 
-  var 
-    b: PNode
-    inElif: bool
-  result = newNodeP(nkCaseStmt, p)
-  getTok(p)
-  eat(p, tkParLe)
-  addSon(result, parseExpr(p))
-  eat(p, tkParRi)
-  skipComment(p, result)
-  inElif = false
-  while true: 
-    if p.tok.tokType == tkSad: getTok(p)
-    case p.tok.tokType
-    of tkOf: 
-      if inElif: break 
-      b = newNodeP(nkOfBranch, p)
-      exprListAux(p, nkRange, tkColon, tkDotDot, b)
-    of tkElif: 
-      inElif = true
-      b = newNodeP(nkElifBranch, p)
-      getTok(p)
-      optInd(p, b)
-      addSon(b, parseExpr(p))
-      eat(p, tkColon)
-    of tkElse: 
-      b = newNodeP(nkElse, p)
-      getTok(p)
-      eat(p, tkColon)
-    else: break 
-    skipComment(p, b)
-    addSon(b, parseStmt(p))
-    addSon(result, b)
-    if b.kind == nkElse: break 
-  
-proc parseTry(p: var TParser): PNode = 
-  var b: PNode
-  result = newNodeP(nkTryStmt, p)
-  getTok(p)
-  eat(p, tkColon)
-  skipComment(p, result)
-  addSon(result, parseStmt(p))
-  b = nil
-  while true: 
-    if p.tok.tokType == tkSad: getTok(p)
-    case p.tok.tokType
-    of tkExcept: 
-      b = newNodeP(nkExceptBranch, p)
-      qualifiedIdentListAux(p, tkColon, b)
-    of tkFinally: 
-      b = newNodeP(nkFinally, p)
-      getTok(p)
-      eat(p, tkColon)
-    else: break 
-    skipComment(p, b)
-    addSon(b, parseStmt(p))
-    addSon(result, b)
-    if b.kind == nkFinally: break 
-  if b == nil: parMessage(p, errTokenExpected, "except")
-  
-proc parseFor(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkForStmt, p)
-  getTok(p)
-  optInd(p, result)
-  a = parseSymbol(p)
-  addSon(result, a)
-  while p.tok.tokType == tkComma: 
-    getTok(p)
-    optInd(p, a)
-    a = parseSymbol(p)
-    addSon(result, a)
-  eat(p, tkIn)
-  addSon(result, exprColonEqExpr(p, nkRange, tkDotDot))
-  eat(p, tkColon)
-  skipComment(p, result)
-  addSon(result, parseStmt(p))
-
-proc parseBlock(p: var TParser): PNode = 
-  result = newNodeP(nkBlockStmt, p)
-  getTok(p)
-  optInd(p, result)
-  case p.tok.tokType
-  of tkEof, tkSad, tkDed, tkColon: addSon(result, nil)
-  else: addSon(result, parseSymbol(p))
-  eat(p, tkColon)
-  skipComment(p, result)
-  addSon(result, parseStmt(p))
-
-proc parseAsm(p: var TParser): PNode = 
-  result = newNodeP(nkAsmStmt, p)
-  getTok(p)
-  optInd(p, result)
-  if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
-  else: addSon(result, nil)
-  case p.tok.tokType
-  of tkStrLit: addSon(result, newStrNodeP(nkStrLit, p.tok.literal, p))
-  of tkRStrLit: addSon(result, newStrNodeP(nkRStrLit, p.tok.literal, p))
-  of tkTripleStrLit: addSon(result, 
-                            newStrNodeP(nkTripleStrLit, p.tok.literal, p))
-  else: 
-    parMessage(p, errStringLiteralExpected)
-    addSon(result, nil)
-    return 
-  getTok(p)
-
-proc parseGenericParamList(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkGenericParams, p)
-  getTok(p)
-  optInd(p, result)
-  while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent): 
-    a = parseIdentColonEquals(p, {withBothOptional})
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-  optPar(p)
-  eat(p, tkBracketRi)
-
-proc parseRoutine(p: var TParser, kind: TNodeKind): PNode = 
-  result = newNodeP(kind, p)
-  getTok(p)
-  optInd(p, result)
-  addSon(result, identVis(p))
-  if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
-  else: addSon(result, nil)
-  addSon(result, parseParamList(p))
-  if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
-  else: addSon(result, nil)
-  if p.tok.tokType == tkEquals: 
-    getTok(p)
-    skipComment(p, result)
-    addSon(result, parseStmt(p))
-  else: 
-    addSon(result, nil)
-  indAndComment(p, result)    # XXX: document this in the grammar!
-  
-proc newCommentStmt(p: var TParser): PNode = 
-  result = newNodeP(nkCommentStmt, p)
-  result.info.line = result.info.line - int16(1)
-
-type 
-  TDefParser = proc (p: var TParser): PNode
-
-proc parseSection(p: var TParser, kind: TNodeKind, defparser: TDefParser): PNode = 
-  var a: PNode
-  result = newNodeP(kind, p)
-  getTok(p)
-  skipComment(p, result)
-  case p.tok.tokType
-  of tkInd: 
-    pushInd(p.lex[] , p.tok.indent)
-    getTok(p)
-    skipComment(p, result)
-    while true: 
-      case p.tok.tokType
-      of tkSad: 
-        getTok(p)
-      of tkSymbol, tkAccent: 
-        a = defparser(p)
-        skipComment(p, a)
-        addSon(result, a)
-      of tkDed: 
-        getTok(p)
-        break 
-      of tkEof: 
-        break                 # BUGFIX
-      of tkComment: 
-        a = newCommentStmt(p)
-        skipComment(p, a)
-        addSon(result, a)
-      else: 
-        parMessage(p, errIdentifierExpected, tokToStr(p.tok))
-        break 
-    popInd(p.lex[] )
-  of tkSymbol, tkAccent, tkParLe: 
-    # tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
-    addSon(result, defparser(p))
-  else: parMessage(p, errIdentifierExpected, tokToStr(p.tok))
-  
-proc parseConstant(p: var TParser): PNode = 
-  result = newNodeP(nkConstDef, p)
-  addSon(result, identWithPragma(p))
-  if p.tok.tokType == tkColon: 
-    getTok(p)
-    optInd(p, result)
-    addSon(result, parseTypeDesc(p))
-  else: 
-    addSon(result, nil)
-  eat(p, tkEquals)
-  optInd(p, result)
-  addSon(result, parseExpr(p))
-  indAndComment(p, result)    # XXX: special extension!
-  
-proc parseConstSection(p: var TParser): PNode = 
-  result = newNodeP(nkConstSection, p)
-  getTok(p)
-  skipComment(p, result)
-  if p.tok.tokType == tkCurlyLe: 
-    getTok(p)
-    skipComment(p, result)
-    while (p.tok.tokType != tkCurlyRi) and (p.tok.tokType != tkEof): 
-      addSon(result, parseConstant(p))
-    eat(p, tkCurlyRi)
-  else: 
-    addSon(result, parseConstant(p))
-  
-proc parseEnum(p: var TParser): PNode = 
-  var a, b: PNode
-  result = newNodeP(nkEnumTy, p)
-  a = nil
-  getTok(p)
-  optInd(p, result)
-  if p.tok.tokType == tkOf: 
-    a = newNodeP(nkOfInherit, p)
-    getTok(p)
-    optInd(p, a)
-    addSon(a, parseTypeDesc(p))
-    addSon(result, a)
-  else: 
-    addSon(result, nil)
-  while true: 
-    case p.tok.tokType
-    of tkEof, tkSad, tkDed: break 
-    else: a = parseSymbol(p)
-    optInd(p, a)
-    if p.tok.tokType == tkEquals: 
-      getTok(p)
-      optInd(p, a)
-      b = a
-      a = newNodeP(nkEnumFieldDef, p)
-      addSon(a, b)
-      addSon(a, parseExpr(p))
-      skipComment(p, a)
-    if p.tok.tokType == tkComma: 
-      getTok(p)
-      optInd(p, a)
-    addSon(result, a)
-
-proc parseObjectPart(p: var TParser): PNode
-proc parseObjectWhen(p: var TParser): PNode = 
-  var branch: PNode
-  result = newNodeP(nkRecWhen, p)
-  while true: 
-    getTok(p)                 # skip `when`, `elif`
-    branch = newNodeP(nkElifBranch, p)
-    optInd(p, branch)
-    addSon(branch, parseExpr(p))
-    eat(p, tkColon)
-    skipComment(p, branch)
-    addSon(branch, parseObjectPart(p))
-    skipComment(p, branch)
-    addSon(result, branch)
-    if p.tok.tokType != tkElif: break 
-  if p.tok.tokType == tkElse: 
-    branch = newNodeP(nkElse, p)
-    eat(p, tkElse)
-    eat(p, tkColon)
-    skipComment(p, branch)
-    addSon(branch, parseObjectPart(p))
-    addSon(result, branch)
-
-proc parseObjectCase(p: var TParser): PNode = 
-  var a, b: PNode
-  result = newNodeP(nkRecCase, p)
-  getTok(p)
-  a = newNodeP(nkIdentDefs, p)
-  addSon(a, identWithPragma(p))
-  eat(p, tkColon)
-  addSon(a, parseTypeDesc(p))
-  addSon(a, nil)
-  addSon(result, a)
-  skipComment(p, result)
-  while true: 
-    if p.tok.tokType == tkSad: getTok(p)
-    case p.tok.tokType
-    of tkOf: 
-      b = newNodeP(nkOfBranch, p)
-      exprListAux(p, nkRange, tkColon, tkDotDot, b)
-    of tkElse: 
-      b = newNodeP(nkElse, p)
-      getTok(p)
-      eat(p, tkColon)
-    else: break 
-    skipComment(p, b)
-    addSon(b, parseObjectPart(p))
-    addSon(result, b)
-    if b.kind == nkElse: break 
-  
-proc parseObjectPart(p: var TParser): PNode = 
-  case p.tok.tokType
-  of tkInd: 
-    result = newNodeP(nkRecList, p)
-    pushInd(p.lex[] , p.tok.indent)
-    getTok(p)
-    skipComment(p, result)
-    while true: 
-      case p.tok.tokType
-      of tkSad: 
-        getTok(p)
-      of tkCase, tkWhen, tkSymbol, tkAccent, tkNil: 
-        addSon(result, parseObjectPart(p))
-      of tkDed: 
-        getTok(p)
-        break 
-      of tkEof: 
-        break 
-      else: 
-        parMessage(p, errIdentifierExpected, tokToStr(p.tok))
-        break 
-    popInd(p.lex[] )
-  of tkWhen: 
-    result = parseObjectWhen(p)
-  of tkCase: 
-    result = parseObjectCase(p)
-  of tkSymbol, tkAccent: 
-    result = parseIdentColonEquals(p, {withPragma})
-    skipComment(p, result)
-  of tkNil: 
-    result = newNodeP(nkNilLit, p)
-    getTok(p)
-  else: result = nil
-  
-proc parseObject(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkObjectTy, p)
-  getTok(p)
-  if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
-  else: addSon(result, nil)
-  if p.tok.tokType == tkOf: 
-    a = newNodeP(nkOfInherit, p)
-    getTok(p)
-    addSon(a, parseTypeDesc(p))
-    addSon(result, a)
-  else: 
-    addSon(result, nil)
-  skipComment(p, result)
-  addSon(result, parseObjectPart(p))
-
-proc parseDistinct(p: var TParser): PNode = 
-  result = newNodeP(nkDistinctTy, p)
-  getTok(p)
-  optInd(p, result)
-  addSon(result, parseTypeDesc(p))
-
-proc parseTypeDef(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkTypeDef, p)
-  addSon(result, identWithPragma(p))
-  if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
-  else: addSon(result, nil)
-  if p.tok.tokType == tkEquals: 
-    getTok(p)
-    optInd(p, result)
-    case p.tok.tokType
-    of tkObject: a = parseObject(p)
-    of tkEnum: a = parseEnum(p)
-    of tkDistinct: a = parseDistinct(p)
-    else: a = parseTypeDesc(p)
-    addSon(result, a)
-  else: 
-    addSon(result, nil)
-  indAndComment(p, result)    # special extension!
-  
-proc parseVarTuple(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkVarTuple, p)
-  getTok(p)                   # skip '('
-  optInd(p, result)
-  while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent): 
-    a = identWithPragma(p)
-    addSon(result, a)
-    if p.tok.tokType != tkComma: break 
-    getTok(p)
-    optInd(p, a)
-  addSon(result, nil)         # no type desc
-  optPar(p)
-  eat(p, tkParRi)
-  eat(p, tkEquals)
-  optInd(p, result)
-  addSon(result, parseExpr(p))
-
-proc parseVariable(p: var TParser): PNode = 
-  if p.tok.tokType == tkParLe: result = parseVarTuple(p)
-  else: result = parseIdentColonEquals(p, {withPragma})
-  indAndComment(p, result)    # special extension!
-  
-proc simpleStmt(p: var TParser): PNode = 
-  case p.tok.tokType
-  of tkReturn: result = parseReturnOrRaise(p, nkReturnStmt)
-  of tkRaise: result = parseReturnOrRaise(p, nkRaiseStmt)
-  of tkYield: result = parseYieldOrDiscard(p, nkYieldStmt)
-  of tkDiscard: result = parseYieldOrDiscard(p, nkDiscardStmt)
-  of tkBreak: result = parseBreakOrContinue(p, nkBreakStmt)
-  of tkContinue: result = parseBreakOrContinue(p, nkContinueStmt)
-  of tkCurlyDotLe: result = parsePragma(p)
-  of tkImport: result = parseImportOrIncludeStmt(p, nkImportStmt)
-  of tkFrom: result = parseFromStmt(p)
-  of tkInclude: result = parseImportOrIncludeStmt(p, nkIncludeStmt)
-  of tkComment: result = newCommentStmt(p)
-  else: 
-    if isExprStart(p): result = parseExprStmt(p)
-    else: result = nil
-  if result != nil: skipComment(p, result)
-  
-proc parseType(p: var TParser): PNode = 
-  result = newNodeP(nkTypeSection, p)
-  while true: 
-    case p.tok.tokType
-    of tkComment: 
-      skipComment(p, result)
-    of tkType: 
-      # type alias:
-    of tkEnum: 
-      nil
-    of tkObject: 
-      nil
-    of tkTuple: 
-      nil
-    else: break 
-  
-proc complexOrSimpleStmt(p: var TParser): PNode = 
-  case p.tok.tokType
-  of tkIf: 
-    result = parseIfOrWhen(p, nkIfStmt)
-  of tkWhile: 
-    result = parseWhile(p)
-  of tkCase: 
-    result = parseCase(p)
-  of tkTry: 
-    result = parseTry(p)
-  of tkFor: 
-    result = parseFor(p)
-  of tkBlock: 
-    result = parseBlock(p)
-  of tkAsm: 
-    result = parseAsm(p)
-  of tkProc: 
-    result = parseRoutine(p, nkProcDef)
-  of tkMethod: 
-    result = parseRoutine(p, nkMethodDef)
-  of tkIterator: 
-    result = parseRoutine(p, nkIteratorDef)
-  of tkMacro: 
-    result = parseRoutine(p, nkMacroDef)
-  of tkTemplate: 
-    result = parseRoutine(p, nkTemplateDef)
-  of tkConverter: 
-    result = parseRoutine(p, nkConverterDef)
-  of tkType, tkEnum, tkObject, tkTuple: 
-    result = nil              #result := parseTypeAlias(p, nkTypeSection, parseTypeDef);
-  of tkConst: 
-    result = parseConstSection(p)
-  of tkWhen: 
-    result = parseIfOrWhen(p, nkWhenStmt)
-  of tkVar: 
-    result = parseSection(p, nkVarSection, parseVariable)
-  else: result = simpleStmt(p)
-  
-proc parseStmt(p: var TParser): PNode = 
-  var a: PNode
-  if p.tok.tokType == tkCurlyLe: 
-    result = newNodeP(nkStmtList, p)
-    getTok(p)
-    while true: 
-      case p.tok.tokType
-      of tkSad, tkInd, tkDed: getTok(p)
-      of tkEof, tkCurlyRi: break 
-      else: 
-        a = complexOrSimpleStmt(p)
-        if a == nil: break 
-        addSon(result, a)
-    eat(p, tkCurlyRi)
-  else: 
-    # the case statement is only needed for better error messages:
-    case p.tok.tokType
-    of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkIterator, 
-       tkMacro, tkType, tkConst, tkWhen, tkVar: 
-      parMessage(p, errComplexStmtRequiresInd)
-      result = nil
-    else: 
-      result = simpleStmt(p)
-      if result == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
-      if p.tok.tokType in {tkInd, tkDed, tkSad}: getTok(p)
-  
-proc parseAll(p: var TParser): PNode = 
-  var a: PNode
-  result = newNodeP(nkStmtList, p)
-  while true: 
-    case p.tok.tokType
-    of tkDed, tkInd, tkSad: getTok(p)
-    of tkEof: break 
-    else: 
-      a = complexOrSimpleStmt(p)
-      if a == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
-      addSon(result, a)
+proc ParseAll*(p: var TParser): PNode = 
+  result = nil
 
-proc parseTopLevelStmt(p: var TParser): PNode = 
+proc parseTopLevelStmt*(p: var TParser): PNode = 
   result = nil
-  while true: 
-    case p.tok.tokType
-    of tkDed, tkInd, tkSad: getTok(p)
-    of tkEof: break 
-    else: 
-      result = complexOrSimpleStmt(p)
-      if result == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
-      break 
+
diff --git a/compiler/pendx.nim b/compiler/pendx.nim
index debe0d852..72c80126d 100755
--- a/compiler/pendx.nim
+++ b/compiler/pendx.nim
@@ -8,16 +8,11 @@
 #
 
 import 
-  llstream, scanner, idents, strutils, ast, msgs, pnimsyn
+  llstream, lexer, parser, idents, strutils, ast, msgs
 
-proc ParseAll*(p: var TParser): PNode
-proc parseTopLevelStmt*(p: var TParser): PNode
-  # implements an iterator. Returns the next top-level statement or nil if end
-  # of stream.
-# implementation
-
-proc ParseAll(p: var TParser): PNode = 
+proc ParseAll*(p: var TParser): PNode = 
   result = nil
 
-proc parseTopLevelStmt(p: var TParser): PNode = 
+proc parseTopLevelStmt*(p: var TParser): PNode = 
   result = nil
+  
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index d7bda4099..c94b8b68b 100755
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -10,7 +10,7 @@
 # This module implements semantic checking for pragmas
 
 import 
-  os, platform, condsyms, ast, astalgo, idents, semdata, msgs, rnimsyn, 
+  os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer, 
   wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees,
   rodread
 
diff --git a/compiler/rnimsyn.nim b/compiler/renderer.nim
index 4436467fa..5ba24bbfa 100755
--- a/compiler/rnimsyn.nim
+++ b/compiler/renderer.nim
@@ -10,7 +10,7 @@
 # This module implements the renderer of the standard Nimrod representation.
 
 import 
-  scanner, options, idents, strutils, ast, msgs, lists
+  lexer, options, idents, strutils, ast, msgs, lists
 
 type 
   TRenderFlag* = enum 
@@ -637,7 +637,7 @@ proc gasm(g: var TSrcGen, n: PNode) =
 proc gident(g: var TSrcGen, n: PNode) = 
   var t: TTokType
   var s = atom(n)
-  if (s[0] in scanner.SymChars): 
+  if (s[0] in lexer.SymChars): 
     if (n.kind == nkIdent): 
       if (n.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or
           (n.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)): 
diff --git a/compiler/sem.nim b/compiler/sem.nim
index bb948ffc9..5f717f006 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -10,9 +10,9 @@
 # This module implements the semantic checking pass.
 
 import
-  strutils, nhashes, lists, options, scanner, ast, astalgo, trees, treetab, 
-  wordrecg, ropes, msgs, os, condsyms, idents, rnimsyn, types, platform, math, 
-  magicsys, pnimsyn, nversion, nimsets, semdata, evals, semfold, importer, 
+  strutils, nhashes, lists, options, lexer, ast, astalgo, trees, treetab, 
+  wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math, 
+  magicsys, parser, nversion, nimsets, semdata, evals, semfold, importer, 
   procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest
 
 proc semPass*(): TPass
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index e052a0baf..240a783d4 100755
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -10,9 +10,9 @@
 # This module contains the data structures for the semantic checking phase.
 
 import 
-  strutils, lists, options, scanner, ast, astalgo, trees, treetab, wordrecg, 
-  ropes, msgs, platform, os, condsyms, idents, rnimsyn, types, extccomp, math, 
-  magicsys, nversion, nimsets, pnimsyn, times, passes, rodread
+  strutils, lists, options, lexer, ast, astalgo, trees, treetab, wordrecg, 
+  ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math, 
+  magicsys, nversion, nimsets, parser, times, passes, rodread
 
 type 
   TOptionEntry* = object of lists.TListEntry # entries to put on a
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index bae2a19bc..041655ef6 100755
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -12,7 +12,7 @@
 
 import 
   strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times, 
-  nversion, platform, math, msgs, os, condsyms, idents, rnimsyn, types,
+  nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
   commands
 
 proc getConstExpr*(m: PSym, n: PNode): PNode
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 1e61ddfe0..d5b8f3204 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -11,7 +11,7 @@
 # the call to overloaded procs, generic procs and operators.
 
 import 
-  ast, astalgo, semdata, types, msgs, rnimsyn, lookups, semtypinst, 
+  ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst, 
   magicsys
 
 type 
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index 6f4babe63..b16c4eba7 100755
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -9,7 +9,8 @@
 
 ## This file implements features required for IDE support.
 
-import scanner, idents, ast, astalgo, semdata, msgs, types, sigmatch, options
+import 
+  lexer, idents, ast, astalgo, semdata, msgs, types, sigmatch, options
 
 const
   sep = '\t'
@@ -38,7 +39,7 @@ proc SymToStr(s: PSym, isLocal: bool, section: string): string =
   result.add($ToColumn(s.info))
 
 proc filterSym(s: PSym): bool {.inline.} = 
-  result = s.name.s[0] in scanner.SymChars
+  result = s.name.s[0] in lexer.SymChars
 
 proc suggestField(s: PSym) = 
   if filterSym(s):
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index adb17efee..b098e4817 100755
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -10,8 +10,8 @@
 ## Implements the dispatcher for the different parsers.
 
 import 
-  strutils, llstream, ast, astalgo, idents, scanner, options, msgs, pnimsyn, 
-  pbraces, ptmplsyn, filters, rnimsyn
+  strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser, 
+  pbraces, filters, filter_tmpl, renderer
 
 type 
   TFilterKind* = enum 
@@ -54,7 +54,7 @@ proc ParseFile(filename: string): PNode =
 proc parseAll(p: var TParsers): PNode = 
   case p.skin
   of skinStandard: 
-    result = pnimsyn.parseAll(p.parser)
+    result = parser.parseAll(p.parser)
   of skinBraces: 
     result = pbraces.parseAll(p.parser)
   of skinEndX: 
@@ -65,7 +65,7 @@ proc parseAll(p: var TParsers): PNode =
 proc parseTopLevelStmt(p: var TParsers): PNode = 
   case p.skin
   of skinStandard: 
-    result = pnimsyn.parseTopLevelStmt(p.parser)
+    result = parser.parseTopLevelStmt(p.parser)
   of skinBraces: 
     result = pbraces.parseTopLevelStmt(p.parser)
   of skinEndX: 
@@ -99,7 +99,7 @@ proc parsePipe(filename: string, inputStream: PLLStream): PNode =
       while line[i] in WhiteSpace: inc(i)
       var q: TParser
       OpenParser(q, filename, LLStreamOpen(copy(line, i)))
-      result = pnimsyn.parseAll(q)
+      result = parser.parseAll(q)
       CloseParser(q)
     LLStreamClose(s)
 
@@ -167,7 +167,7 @@ proc openParsers(p: var TParsers, filename: string, inputstream: PLLStream) =
   else: s = inputStream
   case p.skin
   of skinStandard, skinBraces, skinEndX: 
-    pnimsyn.openParser(p.parser, filename, s)
+    parser.openParser(p.parser, filename, s)
   
 proc closeParsers(p: var TParsers) = 
-  pnimsyn.closeParser(p.parser)
+  parser.closeParser(p.parser)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index db5146bb5..cdc89538c 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -18,7 +18,7 @@
 
 import 
   strutils, lists, options, ast, astalgo, trees, treetab, evals, msgs, os, 
-  idents, rnimsyn, types, passes, semfold, magicsys, cgmeth
+  idents, renderer, types, passes, semfold, magicsys, cgmeth
 
 const 
   genPrefix* = ":tmp"         # prefix for generated names
diff --git a/compiler/trees.nim b/compiler/trees.nim
index 69b77b8ab..54f688103 100755
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -10,7 +10,7 @@
 # tree helper routines
 
 import 
-  ast, astalgo, scanner, msgs, strutils
+  ast, astalgo, lexer, msgs, strutils
 
 proc getMagic*(op: PNode): TMagic
 
diff --git a/doc/filelist.txt b/doc/filelist.txt
index 7bcd424db..ce9923453 100755
--- a/doc/filelist.txt
+++ b/doc/filelist.txt
@@ -9,16 +9,11 @@ nimrod          main module: parses the command line and calls
 main            implements the top-level command dispatching
 nimconf         implements the config file reader
 syntaxes        dispatcher for the different parsers and filters
-ptmplsyn        standard template filter (``#! stdtempl``)
+filter_tmpl     standard template filter (``#! stdtempl``)
 lexbase         buffer handling of the lexical analyser
-scanner         lexical analyser
-pnimsyn         Nimrod's parser
-rnimsyn         Nimrod code renderer (AST back to its textual form)
-
-paslex          lexer for Pascal
-pasparse        parser for Pascal; Pascal's advanced OO features are not
-                supported
-
+lexer           lexical analyser
+parser          Nimrod's parser
+renderer        Nimrod code renderer (AST back to its textual form)
 options         contains global and local compiler options
 ast             type definitions of the abstract syntax tree (AST) and
                 node constructors
diff --git a/lib/pure/collections/hashtables.nim b/lib/pure/collections/hashtables.nim
index 133db66e1..6730163c2 100644
--- a/lib/pure/collections/hashtables.nim
+++ b/lib/pure/collections/hashtables.nim
@@ -18,8 +18,8 @@ type
   TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
   TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
   THashTable[A, B] = object of TObject
-    counter: int
     data: TKeyValuePairSeq[A, B]
+    counter: int
 
   PHashTable*[A, B] = ref THashTable[A, B] ## use this type to declare tables
 
@@ -32,12 +32,12 @@ iterator pairs*[A, B](t: PHashTable[A, B]): tuple[key: A, val: B] =
   for h in 0..high(t.data):
     if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
 
-iterator keys*[A, B](t: PHashTable[A, B]): tuple[key: A, val: B] =
+iterator keys*[A, B](t: PHashTable[A, B]): A =
   ## iterates over any key in the table `t`.
   for h in 0..high(t.data):
     if t.data[h].slot == seFilled: yield t.data[h].key
 
-iterator values*[A, B](t: PHashTable[A, B]): tuple[key: A, val: B] =
+iterator values*[A, B](t: PHashTable[A, B]): B =
   ## iterates over any value in the table `t`.
   for h in 0..high(t.data):
     if t.data[h].slot == seFilled: yield t.data[h].val
@@ -103,6 +103,7 @@ proc del*[A, B](t: PHashTable[A, B], key: A) =
   var index = RawGet(t, key)
   if index >= 0:
     t.data[index].slot = seDeleted
+    dec(t.counter)
 
 proc newHashTable*[A, B](initialSize = 64): PHashTable[A, B] =
   ## creates a new string table that is empty. `initialSize` needs to be
@@ -125,6 +126,110 @@ proc `$`*[A, B](t: PHashTable[A, B]): string =
       result.add($val)
     result.add("}")
 
+
+# ------------------------------ count tables -------------------------------
+
+const
+  deletedCount = -1
+
+type
+  TCountTable*[A] {.final.} = object
+    data: seq[tuple[key: A, val: int]]
+    counter: int
+
+proc len*[A](t: TCountTable[A]): int =
+  ## returns the number of keys in `t`.
+  result = t.counter
+
+iterator pairs*[A](t: TCountTable[A]): tuple[key: A, val: int] =
+  ## iterates over any (key, value) pair in the table `t`.
+  for h in 0..high(t.data):
+    if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val)
+
+iterator keys*[A](t: TCountTable[A]): A =
+  ## iterates over any key in the table `t`.
+  for h in 0..high(t.data):
+    if t.data[h].slot == seFilled: yield t.data[h].key
+
+iterator values*[A](t: TCountTable[A]): int =
+  ## iterates over any value in the table `t`.
+  for h in 0..high(t.data):
+    if t.data[h].slot == seFilled: yield t.data[h].val
+
+proc RawGet[A](t: TCountTable[A], key: A): int =
+  var h: THash = hash(key) and high(t.data) # start with real hash value
+  while t.data[h].slot != seEmpty:
+    if t.data[h].key == key and t.data[h].slot == seFilled:
+      return h
+    h = nextTry(h, high(t.data))
+  result = -1
+
+proc `[]`*[A](t: TCountTable[A], key: A): B =
+  ## retrieves the value at ``t[key]``. If `key` is not in `t`,
+  ## default empty value for the type `B` is returned
+  ## and no exception is raised. One can check with ``hasKey`` whether the key
+  ## exists.
+  var index = RawGet(t, key)
+  if index >= 0: result = t.data[index].val
+
+proc hasKey*[A](t: TCountTable[A], key: A): bool =
+  ## returns true iff `key` is in the table `t`.
+  result = rawGet(t, key) >= 0
+
+proc RawInsert[A](t: TCountTable[A], data: var TKeyValuePairSeq[A, B],
+                     key: A, val: int) =
+  var h: THash = hash(key) and high(data)
+  while data[h].slot == seFilled:
+    h = nextTry(h, high(data))
+  data[h].key = key
+  data[h].val = val
+  data[h].slot = seFilled
+
+proc Enlarge[A](t: TCountTable[A]) =
+  var n: TKeyValuePairSeq[A, B]
+  newSeq(n, len(t.data) * growthFactor)
+  for i in countup(0, high(t.data)):
+    if t.data[i].slot == seFilled: RawInsert(t, n, t.data[i].key, t.data[i].val)
+  swap(t.data, n)
+
+proc `[]=`*[A](t: TCountTable[A], key: A, val: int) =
+  ## puts a (key, value)-pair into `t`.
+  var index = RawGet(t, key)
+  if index >= 0:
+    t.data[index].val = val
+  else:
+    if mustRehash(len(t.data), t.counter): Enlarge(t)
+    RawInsert(t, t.data, key, val)
+    inc(t.counter)
+
+proc del*[A](t: TCountTable[A], key: A) =
+  ## deletes `key` from hash table `t`.
+  var index = RawGet(t, key)
+  if index >= 0:
+    t.data[index].slot = seDeleted
+
+proc newHashTable*[A, B](initialSize = 64): PHashTable[A, B] =
+  ## creates a new string table that is empty. `initialSize` needs to be
+  ## a power of two.
+  assert isPowerOfTwo(initialSize)
+  new(result)
+  result.counter = 0
+  newSeq(result.data, initialSize)
+
+proc `$`*[A](t: TCountTable[A]): string =
+  ## The `$` operator for string tables.
+  if t.len == 0:
+    result = "{:}"
+  else:
+    result = "{"
+    for key, val in pairs(t):
+      if result.len > 1: result.add(", ")
+      result.add($key)
+      result.add(": ")
+      result.add($val)
+    result.add("}")
+
+
 when isMainModule:
   var table = newHashTable[string, float]()
   table["test"] = 1.2345
diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim
new file mode 100755
index 000000000..cae6d4620
--- /dev/null
+++ b/lib/pure/collections/lists.nim
@@ -0,0 +1,155 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2011 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Implementation of singly and doubly linked lists. Because it makes no sense
+## to do so, the 'next' and 'prev' pointers are not hidden from you and can
+## be manipulated directly for efficiency.
+
+type
+  TDoublyLinkedNode[T] {.pure, final.} = object
+    next*, prev*: ref TDoublyLinkedNode[T]
+    value*: T
+  PDoublyLinkedNode*[T] = ref TDoublyLinkedNode[T]
+
+  TSinglyLinkedNode[T] {.pure, final.} = object
+    next*: ref TSinglyLinkedNode[T]
+    value*: T
+  PSinglyLinkedNode*[T] = ref TSinglyLinkedNode[T]
+
+proc newDoublyLinkedNode*[T](value: T): PDoublyLinkedNode[T] =
+  ## creates a new doubly linked node with the given `value`.
+  new(result)
+  result.value = value
+
+proc newSinglyLinkedNode*[T](value: T): PSinglyLinkedNode[T] =
+  ## creates a new singly linked node with the given `value`.
+  new(result)
+  result.value = value
+
+iterator items*[T](n: PDoublyLinkedNode[T]): T = 
+  ## yields every value of `x`.
+  var it = n
+  while it != nil:
+    yield it.value
+    it = it.next
+
+iterator items*[T](n: PSinglyLinkedNode[T]): T = 
+  ## yields every value of `x`.
+  var it = n
+  while it != nil:
+    yield it.value
+    it = it.next
+
+iterator nodes*[T](n: PSinglyLinkedNode[T]): PSinglyLinkedNode[T] = 
+  ## iterates over every node of `x`. Removing the current node from the
+  ## list during traversal is supported.
+  var it = n
+  while it != nil:
+    var nxt = it.next
+    yield it
+    it = nxt
+
+iterator nodes*[T](n: PDoublyLinkedNode[T]): PDoublyLinkedNode[T] = 
+  ## iterates over every node of `x`. Removing the current node from the
+  ## list during traversal is supported.
+  var it = n
+  while it != nil:
+    var nxt = it.next
+    yield it
+    it = nxt
+
+proc `$`*[list: PSinglyLinkedNode|PDoublyLinkedNode](n: list): string = 
+  ## turns a list into its string representation.
+  result = "["
+  for x in nodes(n):
+    if result.len > 1: result.add(", ")
+    result.add($x.value)
+  result.add("]")
+
+proc find*[list: PSinglyLinkedNode|PDoublyLinkedNode, T](
+           n: list, value: T): list = 
+  ## searches in the list for a value. Returns nil if the value does not
+  ## exist.
+  for x in nodes(n):
+    if x.value == value: return x
+
+proc contains*[list: PSinglyLinkedNode|PDoublyLinkedNode, T](
+           n: list, value: T): list = 
+  ## searches in the list for a value. Returns false if the value does not
+  ## exist, true otherwise.
+  for x in nodes(n):
+    if x.value == value: return true
+
+proc prepend*[T](head: var PSinglyLinkedNode[T], 
+                 toAdd: PSinglyLinkedNode[T]) {.inline.} = 
+  ## prepends a node to `head`. Efficiency: O(1).
+  toAdd.next = head
+  head = toAdd
+
+proc prepend*[T](head: var PSinglyLinkedNode[T], x: T) {.inline.} = 
+  ## creates a new node with the value `x` and prepends that node to `head`.
+  ## Efficiency: O(1).
+  preprend(head, newSinglyLinkedNode(x))
+
+proc append*[T](head: var PSinglyLinkedNode[T], 
+                toAdd: PSinglyLinkedNode[T]) = 
+  ## appends a node to `head`. Efficiency: O(n).
+  if head == nil:
+    head = toAdd
+  else:
+    var it = head
+    while it.next != nil: it = it.next
+    it.next = toAdd
+
+proc append*[T](head: var PSinglyLinkedNode[T], x: T) {.inline.} = 
+  ## creates a new node with the value `x` and appends that node to `head`.
+  ## Efficiency: O(n).
+  append(head, newSinglyLinkedNode(x))
+
+
+proc prepend*[T](head: var PDoublyLinkedNode[T], 
+                 toAdd: PDoublyLinkedNode[T]) {.inline.} = 
+  ## prepends a node to `head`. Efficiency: O(1).
+  if head == nil:
+    head = toAdd
+    # head.prev stores the last node:
+    head.prev = toAdd
+  else:
+    toAdd.next = head
+    toAdd.prev = head.prev # copy pointer to last element
+    head.prev = toAdd
+    head = toAdd
+
+proc prepend*[T](head: var PDoublyLinkedNode[T], x: T) {.inline.} = 
+  ## creates a new node with the value `x` and prepends that node to `head`.
+  ## Efficiency: O(1).
+  preprend(head, newDoublyLinkedNode(x))
+
+proc append*[T](head: var PDoublyLinkedNode[T], 
+                toAdd: PDoublyLinkedNode[T]) {.inline.} = 
+  ## appends a node to `head`. Efficiency: O(1).
+  if head == nil:
+    head = toAdd
+    # head.prev stores the last node:
+    head.prev = toAdd
+  else:
+    var last = head.prev
+    assert last.next == nil
+    last.next = toAdd
+    toAdd.prev = last
+    head.prev = toAdd # new last element
+
+proc append*[T](head: var PDoublyLinkedNode[T], x: T) {.inline.} = 
+  ## creates a new node with the value `x` and appends that node to `head`.
+  ## Efficiency: O(1).
+  append(head, newDoublyLinkedNode(x))
+
+
+
+