implemented extended quoting rules
This commit is contained in:
parent
0bcdab8395
commit
6c5693e633
11 changed files with 317 additions and 415 deletions
|
|
@ -215,7 +215,15 @@ String literals can also be delimited by three double quotes
|
||||||
Literals in this form may run for several lines, may contain ``"`` and do not
|
Literals in this form may run for several lines, may contain ``"`` and do not
|
||||||
interpret any escape sequences.
|
interpret any escape sequences.
|
||||||
For convenience, when the opening ``"""`` is immediately followed by a newline,
|
For convenience, when the opening ``"""`` is immediately followed by a newline,
|
||||||
the newline is not included in the string.
|
the newline is not included in the string. The ending of the string literal is
|
||||||
|
defined by the pattern ``"""[^"]``, so this:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
""""long string within quotes""""
|
||||||
|
|
||||||
|
Produces::
|
||||||
|
|
||||||
|
"long string within quotes"
|
||||||
|
|
||||||
|
|
||||||
Raw string literals
|
Raw string literals
|
||||||
|
|
@ -230,6 +238,19 @@ convenient for regular expressions or Windows paths:
|
||||||
|
|
||||||
var f = openFile(r"C:\texts\text.txt") # a raw string, so ``\t`` is no tab
|
var f = openFile(r"C:\texts\text.txt") # a raw string, so ``\t`` is no tab
|
||||||
|
|
||||||
|
To produce a single ``"`` within a raw string literal, it has to be doubled:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
|
||||||
|
r"a""b"
|
||||||
|
|
||||||
|
Produces::
|
||||||
|
|
||||||
|
a"b
|
||||||
|
|
||||||
|
``r""""`` is not possible with this notation, because the three leading
|
||||||
|
quotes introduce a triple quoted string literal.
|
||||||
|
|
||||||
|
|
||||||
Generalized raw string literals
|
Generalized raw string literals
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
@ -291,8 +312,8 @@ prefix), binary (prefix ``0b``), octal (prefix ``0o``) and hexadecimal
|
||||||
|
|
||||||
There exists a literal for each numerical type that is
|
There exists a literal for each numerical type that is
|
||||||
defined. The suffix starting with an apostrophe ('\'') is called a
|
defined. The suffix starting with an apostrophe ('\'') is called a
|
||||||
`type suffix`:idx:. Literals without a type prefix are of the type ``int``,
|
`type suffix`:idx:. Literals without a type suffix are of the type ``int``,
|
||||||
unless the literal contains a dot or an ``E`` in which case it is of
|
unless the literal contains a dot or ``E|e`` in which case it is of
|
||||||
type ``float``.
|
type ``float``.
|
||||||
|
|
||||||
The type suffixes are:
|
The type suffixes are:
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,16 @@ Configuration file
|
||||||
The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable
|
The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable
|
||||||
looks for it in the following directories (in this order):
|
looks for it in the following directories (in this order):
|
||||||
|
|
||||||
1. ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``$APPDATA/nimrod.cfg`` (Windows)
|
1. ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``%APPDATA%/nimrod.cfg`` (Windows)
|
||||||
2. ``$nimrod/config/nimrod.cfg`` (UNIX, Windows)
|
2. ``$nimrod/config/nimrod.cfg`` (UNIX, Windows)
|
||||||
3. ``/etc/nimrod.cfg`` (UNIX)
|
3. ``/etc/nimrod.cfg`` (UNIX)
|
||||||
|
|
||||||
The search stops as soon as a configuration file has been found. The reading
|
The search stops as soon as a configuration file has been found. The reading
|
||||||
of ``nimrod.cfg`` can be suppressed by the ``--skipCfg`` command line option.
|
of ``nimrod.cfg`` can be suppressed by the ``--skipCfg`` command line option.
|
||||||
|
|
||||||
|
**Note:** The *project file name* is the name of the ``.nim`` file that is
|
||||||
|
passed as a command line argument to the compiler.
|
||||||
|
|
||||||
Configuration settings can be overwritten in a project specific
|
Configuration settings can be overwritten in a project specific
|
||||||
configuration file that is read automatically. This specific file has to
|
configuration file that is read automatically. This specific file has to
|
||||||
be in the same directory as the project and be of the same name, except
|
be in the same directory as the project and be of the same name, except
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2010 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2008 Andreas Rumpf
|
# (c) Copyright 2010 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -57,13 +57,12 @@ proc getSourceLanguage(name: string): TSourceLanguage =
|
||||||
result = langNone
|
result = langNone
|
||||||
|
|
||||||
proc initGeneralTokenizer(g: var TGeneralTokenizer, buf: string) =
|
proc initGeneralTokenizer(g: var TGeneralTokenizer, buf: string) =
|
||||||
var pos: int
|
|
||||||
g.buf = cstring(buf)
|
g.buf = cstring(buf)
|
||||||
g.kind = low(TTokenClass)
|
g.kind = low(TTokenClass)
|
||||||
g.start = 0
|
g.start = 0
|
||||||
g.length = 0
|
g.length = 0
|
||||||
g.state = low(TTokenClass)
|
g.state = low(TTokenClass)
|
||||||
pos = 0 # skip initial whitespace:
|
var pos = 0 # skip initial whitespace:
|
||||||
while g.buf[pos] in {' ', '\x09'..'\x0D'}: inc(pos)
|
while g.buf[pos] in {' ', '\x09'..'\x0D'}: inc(pos)
|
||||||
g.pos = pos
|
g.pos = pos
|
||||||
|
|
||||||
|
|
@ -71,8 +70,7 @@ proc deinitGeneralTokenizer(g: var TGeneralTokenizer) =
|
||||||
nil
|
nil
|
||||||
|
|
||||||
proc nimGetKeyword(id: string): TTokenClass =
|
proc nimGetKeyword(id: string): TTokenClass =
|
||||||
var i: PIdent
|
var i = getIdent(id)
|
||||||
i = getIdent(id)
|
|
||||||
if (i.id >= ord(tokKeywordLow) - ord(tkSymbol)) and
|
if (i.id >= ord(tokKeywordLow) - ord(tkSymbol)) and
|
||||||
(i.id <= ord(tokKeywordHigh) - ord(tkSymbol)):
|
(i.id <= ord(tokKeywordHigh) - ord(tkSymbol)):
|
||||||
result = gtKeyword
|
result = gtKeyword
|
||||||
|
|
@ -80,8 +78,7 @@ proc nimGetKeyword(id: string): TTokenClass =
|
||||||
result = gtIdentifier
|
result = gtIdentifier
|
||||||
|
|
||||||
proc nimNumberPostfix(g: var TGeneralTokenizer, position: int): int =
|
proc nimNumberPostfix(g: var TGeneralTokenizer, position: int): int =
|
||||||
var pos: int
|
var pos = position
|
||||||
pos = position
|
|
||||||
if g.buf[pos] == '\'':
|
if g.buf[pos] == '\'':
|
||||||
inc(pos)
|
inc(pos)
|
||||||
case g.buf[pos]
|
case g.buf[pos]
|
||||||
|
|
@ -99,10 +96,8 @@ proc nimNumberPostfix(g: var TGeneralTokenizer, position: int): int =
|
||||||
result = pos
|
result = pos
|
||||||
|
|
||||||
proc nimNumber(g: var TGeneralTokenizer, position: int): int =
|
proc nimNumber(g: var TGeneralTokenizer, position: int): int =
|
||||||
const
|
const decChars = {'0'..'9', '_'}
|
||||||
decChars = {'0'..'9', '_'}
|
var pos = position
|
||||||
var pos: int
|
|
||||||
pos = position
|
|
||||||
g.kind = gtDecNumber
|
g.kind = gtDecNumber
|
||||||
while g.buf[pos] in decChars: inc(pos)
|
while g.buf[pos] in decChars: inc(pos)
|
||||||
if g.buf[pos] == '.':
|
if g.buf[pos] == '.':
|
||||||
|
|
@ -121,10 +116,7 @@ proc nimNextToken(g: var TGeneralTokenizer) =
|
||||||
hexChars = {'0'..'9', 'A'..'F', 'a'..'f', '_'}
|
hexChars = {'0'..'9', 'A'..'F', 'a'..'f', '_'}
|
||||||
octChars = {'0'..'7', '_'}
|
octChars = {'0'..'7', '_'}
|
||||||
binChars = {'0'..'1', '_'}
|
binChars = {'0'..'1', '_'}
|
||||||
var
|
var pos = g.pos
|
||||||
pos: int
|
|
||||||
id: string
|
|
||||||
pos = g.pos
|
|
||||||
g.start = g.pos
|
g.start = g.pos
|
||||||
if g.state == gtStringLit:
|
if g.state == gtStringLit:
|
||||||
g.kind = gtStringLit
|
g.kind = gtStringLit
|
||||||
|
|
@ -161,7 +153,7 @@ proc nimNextToken(g: var TGeneralTokenizer) =
|
||||||
g.kind = gtComment
|
g.kind = gtComment
|
||||||
while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): inc(pos)
|
while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): inc(pos)
|
||||||
of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF':
|
of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF':
|
||||||
id = ""
|
var id = ""
|
||||||
while g.buf[pos] in scanner.SymChars + {'_'}:
|
while g.buf[pos] in scanner.SymChars + {'_'}:
|
||||||
add(id, g.buf[pos])
|
add(id, g.buf[pos])
|
||||||
inc(pos)
|
inc(pos)
|
||||||
|
|
@ -175,14 +167,17 @@ proc nimNextToken(g: var TGeneralTokenizer) =
|
||||||
break
|
break
|
||||||
of '\"':
|
of '\"':
|
||||||
inc(pos)
|
inc(pos)
|
||||||
if (g.buf[pos] == '\"') and (g.buf[pos + 1] == '\"'):
|
if g.buf[pos] == '\"' and g.buf[pos+1] == '\"' and
|
||||||
|
g.buf[pos+2] != '\"':
|
||||||
inc(pos, 2)
|
inc(pos, 2)
|
||||||
break
|
break
|
||||||
else: inc(pos)
|
else: inc(pos)
|
||||||
else:
|
else:
|
||||||
g.kind = gtRawData
|
g.kind = gtRawData
|
||||||
inc(pos)
|
inc(pos)
|
||||||
while not (g.buf[pos] in {'\0', '\"', '\x0A', '\x0D'}): inc(pos)
|
while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}):
|
||||||
|
if g.buf[pos] == '"' and g.buf[pos+1] != '"': break
|
||||||
|
inc(pos)
|
||||||
if g.buf[pos] == '\"': inc(pos)
|
if g.buf[pos] == '\"': inc(pos)
|
||||||
else:
|
else:
|
||||||
g.kind = nimGetKeyword(id)
|
g.kind = nimGetKeyword(id)
|
||||||
|
|
@ -228,7 +223,8 @@ proc nimNextToken(g: var TGeneralTokenizer) =
|
||||||
break
|
break
|
||||||
of '\"':
|
of '\"':
|
||||||
inc(pos)
|
inc(pos)
|
||||||
if (g.buf[pos] == '\"') and (g.buf[pos + 1] == '\"'):
|
if g.buf[pos] == '\"' and g.buf[pos+1] == '\"' and
|
||||||
|
g.buf[pos+2] != '\"':
|
||||||
inc(pos, 2)
|
inc(pos, 2)
|
||||||
break
|
break
|
||||||
else: inc(pos)
|
else: inc(pos)
|
||||||
|
|
@ -263,10 +259,8 @@ proc nimNextToken(g: var TGeneralTokenizer) =
|
||||||
g.pos = pos
|
g.pos = pos
|
||||||
|
|
||||||
proc generalNumber(g: var TGeneralTokenizer, position: int): int =
|
proc generalNumber(g: var TGeneralTokenizer, position: int): int =
|
||||||
const
|
const decChars = {'0'..'9'}
|
||||||
decChars = {'0'..'9'}
|
var pos = position
|
||||||
var pos: int
|
|
||||||
pos = position
|
|
||||||
g.kind = gtDecNumber
|
g.kind = gtDecNumber
|
||||||
while g.buf[pos] in decChars: inc(pos)
|
while g.buf[pos] in decChars: inc(pos)
|
||||||
if g.buf[pos] == '.':
|
if g.buf[pos] == '.':
|
||||||
|
|
@ -284,12 +278,9 @@ proc generalStrLit(g: var TGeneralTokenizer, position: int): int =
|
||||||
const
|
const
|
||||||
decChars = {'0'..'9'}
|
decChars = {'0'..'9'}
|
||||||
hexChars = {'0'..'9', 'A'..'F', 'a'..'f'}
|
hexChars = {'0'..'9', 'A'..'F', 'a'..'f'}
|
||||||
var
|
var pos = position
|
||||||
pos: int
|
|
||||||
c: Char
|
|
||||||
pos = position
|
|
||||||
g.kind = gtStringLit
|
g.kind = gtStringLit
|
||||||
c = g.buf[pos]
|
var c = g.buf[pos]
|
||||||
inc(pos) # skip " or '
|
inc(pos) # skip " or '
|
||||||
while true:
|
while true:
|
||||||
case g.buf[pos]
|
case g.buf[pos]
|
||||||
|
|
@ -316,12 +307,11 @@ proc generalStrLit(g: var TGeneralTokenizer, position: int): int =
|
||||||
result = pos
|
result = pos
|
||||||
|
|
||||||
proc isKeyword(x: openarray[string], y: string): int =
|
proc isKeyword(x: openarray[string], y: string): int =
|
||||||
var a, b, mid, c: int
|
var a = 0
|
||||||
a = 0
|
var b = len(x) - 1
|
||||||
b = len(x) - 1
|
|
||||||
while a <= b:
|
while a <= b:
|
||||||
mid = (a + b) div 2
|
var mid = (a + b) div 2
|
||||||
c = cmp(x[mid], y)
|
var c = cmp(x[mid], y)
|
||||||
if c < 0:
|
if c < 0:
|
||||||
a = mid + 1
|
a = mid + 1
|
||||||
elif c > 0:
|
elif c > 0:
|
||||||
|
|
@ -331,12 +321,11 @@ proc isKeyword(x: openarray[string], y: string): int =
|
||||||
result = - 1
|
result = - 1
|
||||||
|
|
||||||
proc isKeywordIgnoreCase(x: openarray[string], y: string): int =
|
proc isKeywordIgnoreCase(x: openarray[string], y: string): int =
|
||||||
var a, b, mid, c: int
|
var a = 0
|
||||||
a = 0
|
var b = len(x) - 1
|
||||||
b = len(x) - 1
|
|
||||||
while a <= b:
|
while a <= b:
|
||||||
mid = (a + b) div 2
|
var mid = (a + b) div 2
|
||||||
c = cmpIgnoreCase(x[mid], y)
|
var c = cmpIgnoreCase(x[mid], y)
|
||||||
if c < 0:
|
if c < 0:
|
||||||
a = mid + 1
|
a = mid + 1
|
||||||
elif c > 0:
|
elif c > 0:
|
||||||
|
|
@ -357,10 +346,7 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openarray[string],
|
||||||
octChars = {'0'..'7'}
|
octChars = {'0'..'7'}
|
||||||
binChars = {'0'..'1'}
|
binChars = {'0'..'1'}
|
||||||
symChars = {'A'..'Z', 'a'..'z', '0'..'9', '_', '\x80'..'\xFF'}
|
symChars = {'A'..'Z', 'a'..'z', '0'..'9', '_', '\x80'..'\xFF'}
|
||||||
var
|
var pos = g.pos
|
||||||
pos, nested: int
|
|
||||||
id: string
|
|
||||||
pos = g.pos
|
|
||||||
g.start = g.pos
|
g.start = g.pos
|
||||||
if g.state == gtStringLit:
|
if g.state == gtStringLit:
|
||||||
g.kind = gtStringLit
|
g.kind = gtStringLit
|
||||||
|
|
@ -400,7 +386,7 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openarray[string],
|
||||||
while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): inc(pos)
|
while not (g.buf[pos] in {'\0', '\x0A', '\x0D'}): inc(pos)
|
||||||
elif g.buf[pos] == '*':
|
elif g.buf[pos] == '*':
|
||||||
g.kind = gtLongComment
|
g.kind = gtLongComment
|
||||||
nested = 0
|
var nested = 0
|
||||||
inc(pos)
|
inc(pos)
|
||||||
while true:
|
while true:
|
||||||
case g.buf[pos]
|
case g.buf[pos]
|
||||||
|
|
@ -426,7 +412,7 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openarray[string],
|
||||||
else:
|
else:
|
||||||
g.kind = gtOperator
|
g.kind = gtOperator
|
||||||
of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF':
|
of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF':
|
||||||
id = ""
|
var id = ""
|
||||||
while g.buf[pos] in SymChars:
|
while g.buf[pos] in SymChars:
|
||||||
add(id, g.buf[pos])
|
add(id, g.buf[pos])
|
||||||
inc(pos)
|
inc(pos)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2008 Andreas Rumpf
|
# (c) Copyright 2010 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -83,7 +83,8 @@ proc FillBuffer(L: var TBaseLexer) =
|
||||||
toCopy = L.BufLen - L.sentinel - 1
|
toCopy = L.BufLen - L.sentinel - 1
|
||||||
assert(toCopy >= 0)
|
assert(toCopy >= 0)
|
||||||
if toCopy > 0:
|
if toCopy > 0:
|
||||||
MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) # "moveMem" handles overlapping regions
|
MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize)
|
||||||
|
# "moveMem" handles overlapping regions
|
||||||
charsRead = LLStreamRead(L.stream, addr(L.buf[toCopy]),
|
charsRead = LLStreamRead(L.stream, addr(L.buf[toCopy]),
|
||||||
(L.sentinel + 1) * chrSize) div chrSize
|
(L.sentinel + 1) * chrSize) div chrSize
|
||||||
s = toCopy + charsRead
|
s = toCopy + charsRead
|
||||||
|
|
@ -142,7 +143,7 @@ proc skip_UTF_8_BOM(L: var TBaseLexer) =
|
||||||
inc(L.bufpos, 3)
|
inc(L.bufpos, 3)
|
||||||
inc(L.lineStart, 3)
|
inc(L.lineStart, 3)
|
||||||
|
|
||||||
proc openBaseLexer(L: var TBaseLexer, inputstream: PLLStream, bufLen: int = 8192) =
|
proc openBaseLexer(L: var TBaseLexer, inputstream: PLLStream, bufLen = 8192) =
|
||||||
assert(bufLen > 0)
|
assert(bufLen > 0)
|
||||||
L.bufpos = 0
|
L.bufpos = 0
|
||||||
L.bufLen = bufLen
|
L.bufLen = bufLen
|
||||||
|
|
@ -158,9 +159,8 @@ proc getColNumber(L: TBaseLexer, pos: int): int =
|
||||||
result = abs(pos - L.lineStart)
|
result = abs(pos - L.lineStart)
|
||||||
|
|
||||||
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
|
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
|
||||||
var i: int
|
|
||||||
result = ""
|
result = ""
|
||||||
i = L.lineStart
|
var i = L.lineStart
|
||||||
while not (L.buf[i] in {CR, LF, EndOfFile}):
|
while not (L.buf[i] in {CR, LF, EndOfFile}):
|
||||||
add(result, L.buf[i])
|
add(result, L.buf[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
|
||||||
|
|
@ -113,9 +113,8 @@ proc parLineInfo(p: TParser): TLineInfo =
|
||||||
result = getLineInfo(p.lex^)
|
result = getLineInfo(p.lex^)
|
||||||
|
|
||||||
proc indAndComment(p: var TParser, n: PNode) =
|
proc indAndComment(p: var TParser, n: PNode) =
|
||||||
var info: TLineInfo
|
|
||||||
if p.tok.tokType == tkInd:
|
if p.tok.tokType == tkInd:
|
||||||
info = parLineInfo(p)
|
var info = parLineInfo(p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
if p.tok.tokType == tkComment: skipComment(p, n)
|
if p.tok.tokType == tkComment: skipComment(p, n)
|
||||||
else: liMessage(info, errInvalidIndentation)
|
else: liMessage(info, errInvalidIndentation)
|
||||||
|
|
|
||||||
393
rod/rnimsyn.nim
393
rod/rnimsyn.nim
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2010 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -51,8 +51,8 @@ const
|
||||||
LineCommentColumn = 30
|
LineCommentColumn = 30
|
||||||
|
|
||||||
proc InitSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) =
|
proc InitSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) =
|
||||||
g.comStack = @ []
|
g.comStack = @[]
|
||||||
g.tokens = @ []
|
g.tokens = @[]
|
||||||
g.indent = 0
|
g.indent = 0
|
||||||
g.lineLen = 0
|
g.lineLen = 0
|
||||||
g.pos = 0
|
g.pos = 0
|
||||||
|
|
@ -62,8 +62,7 @@ proc InitSrcGen(g: var TSrcGen, renderFlags: TRenderFlags) =
|
||||||
g.pendingNL = - 1
|
g.pendingNL = - 1
|
||||||
|
|
||||||
proc addTok(g: var TSrcGen, kind: TTokType, s: string) =
|
proc addTok(g: var TSrcGen, kind: TTokType, s: string) =
|
||||||
var length: int
|
var length = len(g.tokens)
|
||||||
length = len(g.tokens)
|
|
||||||
setlen(g.tokens, length + 1)
|
setlen(g.tokens, length + 1)
|
||||||
g.tokens[length].kind = kind
|
g.tokens[length].kind = kind
|
||||||
g.tokens[length].length = int16(len(s))
|
g.tokens[length].length = int16(len(s))
|
||||||
|
|
@ -128,15 +127,11 @@ proc makeNimString(s: string): string =
|
||||||
add(result, '\"')
|
add(result, '\"')
|
||||||
|
|
||||||
proc putComment(g: var TSrcGen, s: string) =
|
proc putComment(g: var TSrcGen, s: string) =
|
||||||
var
|
var i = 0
|
||||||
i, j, ind, comIndent: int
|
var comIndent = 1
|
||||||
isCode: bool
|
var isCode = (len(s) >= 2) and (s[0 + 1] != ' ')
|
||||||
com: string
|
var ind = g.lineLen
|
||||||
i = 0
|
var com = ""
|
||||||
comIndent = 1
|
|
||||||
isCode = (len(s) >= 2) and (s[0 + 1] != ' ')
|
|
||||||
ind = g.lineLen
|
|
||||||
com = ""
|
|
||||||
while true:
|
while true:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '\0':
|
of '\0':
|
||||||
|
|
@ -167,7 +162,7 @@ proc putComment(g: var TSrcGen, s: string) =
|
||||||
# we may break the comment into a multi-line comment if the line
|
# we may break the comment into a multi-line comment if the line
|
||||||
# gets too long:
|
# gets too long:
|
||||||
# compute length of the following word:
|
# compute length of the following word:
|
||||||
j = i
|
var j = i
|
||||||
while s[j] > ' ': inc(j)
|
while s[j] > ' ': inc(j)
|
||||||
if not isCode and (g.lineLen + (j - i) > MaxLineLen):
|
if not isCode and (g.lineLen + (j - i) > MaxLineLen):
|
||||||
put(g, tkComment, com)
|
put(g, tkComment, com)
|
||||||
|
|
@ -181,10 +176,9 @@ proc putComment(g: var TSrcGen, s: string) =
|
||||||
optNL(g)
|
optNL(g)
|
||||||
|
|
||||||
proc maxLineLength(s: string): int =
|
proc maxLineLength(s: string): int =
|
||||||
var i, linelen: int
|
|
||||||
result = 0
|
result = 0
|
||||||
i = 0
|
var i = 0
|
||||||
lineLen = 0
|
var lineLen = 0
|
||||||
while true:
|
while true:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '\0':
|
of '\0':
|
||||||
|
|
@ -203,12 +197,9 @@ proc maxLineLength(s: string): int =
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
proc putRawStr(g: var TSrcGen, kind: TTokType, s: string) =
|
proc putRawStr(g: var TSrcGen, kind: TTokType, s: string) =
|
||||||
var
|
var i = 0
|
||||||
i, hi: int
|
var hi = len(s) + 0 - 1
|
||||||
str: string
|
var str = ""
|
||||||
i = 0
|
|
||||||
hi = len(s) + 0 - 1
|
|
||||||
str = ""
|
|
||||||
while i <= hi:
|
while i <= hi:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '\x0D':
|
of '\x0D':
|
||||||
|
|
@ -237,8 +228,7 @@ proc containsNL(s: string): bool =
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc pushCom(g: var TSrcGen, n: PNode) =
|
proc pushCom(g: var TSrcGen, n: PNode) =
|
||||||
var length: int
|
var length = len(g.comStack)
|
||||||
length = len(g.comStack)
|
|
||||||
setlen(g.comStack, length + 1)
|
setlen(g.comStack, length + 1)
|
||||||
g.comStack[length] = n
|
g.comStack[length] = n
|
||||||
|
|
||||||
|
|
@ -258,15 +248,15 @@ proc shouldRenderComment(g: var TSrcGen, n: PNode): bool =
|
||||||
(renderDocComments in g.flags) and startsWith(n.comment, "##")
|
(renderDocComments in g.flags) and startsWith(n.comment, "##")
|
||||||
|
|
||||||
proc gcom(g: var TSrcGen, n: PNode) =
|
proc gcom(g: var TSrcGen, n: PNode) =
|
||||||
var ml: int
|
|
||||||
assert(n != nil)
|
assert(n != nil)
|
||||||
if shouldRenderComment(g, n):
|
if shouldRenderComment(g, n):
|
||||||
if (g.pendingNL < 0) and (len(g.buf) > 0) and (g.buf[len(g.buf)] != ' '):
|
if (g.pendingNL < 0) and (len(g.buf) > 0) and (g.buf[len(g.buf)] != ' '):
|
||||||
put(g, tkSpaces, Space) # Before long comments we cannot make sure that a newline is generated,
|
put(g, tkSpaces, Space)
|
||||||
|
# Before long comments we cannot make sure that a newline is generated,
|
||||||
# because this might be wrong. But it is no problem in practice.
|
# because this might be wrong. But it is no problem in practice.
|
||||||
if (g.pendingNL < 0) and (len(g.buf) > 0) and
|
if (g.pendingNL < 0) and (len(g.buf) > 0) and
|
||||||
(g.lineLen < LineCommentColumn):
|
(g.lineLen < LineCommentColumn):
|
||||||
ml = maxLineLength(n.comment)
|
var ml = maxLineLength(n.comment)
|
||||||
if ml + LineCommentColumn <= maxLineLen:
|
if ml + LineCommentColumn <= maxLineLen:
|
||||||
put(g, tkSpaces, repeatChar(LineCommentColumn - g.lineLen))
|
put(g, tkSpaces, repeatChar(LineCommentColumn - g.lineLen))
|
||||||
putComment(g, n.comment) #assert(g.comStack[high(g.comStack)] = n);
|
putComment(g, n.comment) #assert(g.comStack[high(g.comStack)] = n);
|
||||||
|
|
@ -285,30 +275,18 @@ proc litAux(n: PNode, x: biggestInt, size: int): string =
|
||||||
proc atom(n: PNode): string =
|
proc atom(n: PNode): string =
|
||||||
var f: float32
|
var f: float32
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkEmpty:
|
of nkEmpty: result = ""
|
||||||
result = ""
|
of nkIdent: result = n.ident.s
|
||||||
of nkIdent:
|
of nkSym: result = n.sym.name.s
|
||||||
result = n.ident.s
|
of nkStrLit: result = makeNimString(n.strVal)
|
||||||
of nkSym:
|
of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"") & '\"'
|
||||||
result = n.sym.name.s
|
of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\""
|
||||||
of nkStrLit:
|
of nkCharLit: result = '\'' & toNimChar(chr(int(n.intVal))) & '\''
|
||||||
result = makeNimString(n.strVal)
|
of nkIntLit: result = litAux(n, n.intVal, 4)
|
||||||
of nkRStrLit:
|
of nkInt8Lit: result = litAux(n, n.intVal, 1) & "\'i8"
|
||||||
result = "r\"" & n.strVal & '\"'
|
of nkInt16Lit: result = litAux(n, n.intVal, 2) & "\'i16"
|
||||||
of nkTripleStrLit:
|
of nkInt32Lit: result = litAux(n, n.intVal, 4) & "\'i32"
|
||||||
result = "\"\"\"" & n.strVal & "\"\"\""
|
of nkInt64Lit: result = litAux(n, n.intVal, 8) & "\'i64"
|
||||||
of nkCharLit:
|
|
||||||
result = '\'' & toNimChar(chr(int(n.intVal))) & '\''
|
|
||||||
of nkIntLit:
|
|
||||||
result = litAux(n, n.intVal, 4)
|
|
||||||
of nkInt8Lit:
|
|
||||||
result = litAux(n, n.intVal, 1) & "\'i8"
|
|
||||||
of nkInt16Lit:
|
|
||||||
result = litAux(n, n.intVal, 2) & "\'i16"
|
|
||||||
of nkInt32Lit:
|
|
||||||
result = litAux(n, n.intVal, 4) & "\'i32"
|
|
||||||
of nkInt64Lit:
|
|
||||||
result = litAux(n, n.intVal, 8) & "\'i64"
|
|
||||||
of nkFloatLit:
|
of nkFloatLit:
|
||||||
if n.flags * {nfBase2, nfBase8, nfBase16} == {}: result = $(n.floatVal)
|
if n.flags * {nfBase2, nfBase8, nfBase16} == {}: result = $(n.floatVal)
|
||||||
else: result = litAux(n, (cast[PInt64](addr(n.floatVal)))^ , 8)
|
else: result = litAux(n, (cast[PInt64](addr(n.floatVal)))^ , 8)
|
||||||
|
|
@ -323,8 +301,7 @@ proc atom(n: PNode): string =
|
||||||
result = $(n.floatVal) & "\'f64"
|
result = $(n.floatVal) & "\'f64"
|
||||||
else:
|
else:
|
||||||
result = litAux(n, (cast[PInt64](addr(n.floatVal)))^ , 8) & "\'f64"
|
result = litAux(n, (cast[PInt64](addr(n.floatVal)))^ , 8) & "\'f64"
|
||||||
of nkNilLit:
|
of nkNilLit: result = "nil"
|
||||||
result = "nil"
|
|
||||||
of nkType:
|
of nkType:
|
||||||
if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s
|
if (n.typ != nil) and (n.typ.sym != nil): result = n.typ.sym.name.s
|
||||||
else: result = "[type node]"
|
else: result = "[type node]"
|
||||||
|
|
@ -346,142 +323,87 @@ proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int =
|
||||||
|
|
||||||
proc lsub(n: PNode): int =
|
proc lsub(n: PNode): int =
|
||||||
# computes the length of a tree
|
# computes the length of a tree
|
||||||
var L: int
|
if n == nil: return 0
|
||||||
if n == nil:
|
if n.comment != nil: return maxLineLen + 1
|
||||||
return 0
|
|
||||||
if n.comment != nil:
|
|
||||||
return maxLineLen + 1
|
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkTripleStrLit:
|
of nkTripleStrLit:
|
||||||
if containsNL(n.strVal): result = maxLineLen + 1
|
if containsNL(n.strVal): result = maxLineLen + 1
|
||||||
else: result = len(atom(n))
|
else: result = len(atom(n))
|
||||||
of nkEmpty..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
of nkEmpty..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
||||||
result = len(atom(n))
|
result = len(atom(n))
|
||||||
of nkCall, nkBracketExpr, nkConv:
|
of nkCall, nkBracketExpr, nkConv: result = lsub(n.sons[0]) + lcomma(n, 1) + 2
|
||||||
result = lsub(n.sons[0]) + lcomma(n, 1) + 2
|
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv:
|
of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
|
||||||
result = lsub(n.sons[1])
|
of nkAddr: result = lsub(n.sons[0]) + len("addr()")
|
||||||
of nkCast:
|
of nkHiddenAddr, nkHiddenDeref: result = lsub(n.sons[0])
|
||||||
result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
|
of nkCommand: result = lsub(n.sons[0]) + lcomma(n, 1) + 1
|
||||||
of nkAddr:
|
of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(n) + 3
|
||||||
result = lsub(n.sons[0]) + len("addr()")
|
of nkPar, nkCurly, nkBracket: result = lcomma(n) + 2
|
||||||
of nkHiddenAddr, nkHiddenDeref:
|
of nkSymChoice: result = lsons(n) + len("()") + sonsLen(n) - 1
|
||||||
result = lsub(n.sons[0])
|
of nkTupleTy: result = lcomma(n) + len("tuple[]")
|
||||||
of nkCommand:
|
of nkDotExpr: result = lsons(n) + 1
|
||||||
result = lsub(n.sons[0]) + lcomma(n, 1) + 1
|
of nkBind: result = lsons(n) + len("bind_")
|
||||||
of nkExprEqExpr, nkAsgn, nkFastAsgn:
|
of nkCheckedFieldExpr: result = lsub(n.sons[0])
|
||||||
result = lsons(n) + 3
|
of nkLambda: result = lsons(n) + len("lambda__=_")
|
||||||
of nkPar, nkCurly, nkBracket:
|
|
||||||
result = lcomma(n) + 2
|
|
||||||
of nkSymChoice:
|
|
||||||
result = lsons(n) + len("()") + sonsLen(n) - 1
|
|
||||||
of nkTupleTy:
|
|
||||||
result = lcomma(n) + len("tuple[]")
|
|
||||||
of nkDotExpr:
|
|
||||||
result = lsons(n) + 1
|
|
||||||
of nkBind:
|
|
||||||
result = lsons(n) + len("bind_")
|
|
||||||
of nkCheckedFieldExpr:
|
|
||||||
result = lsub(n.sons[0])
|
|
||||||
of nkLambda:
|
|
||||||
result = lsons(n) + len("lambda__=_")
|
|
||||||
of nkConstDef, nkIdentDefs:
|
of nkConstDef, nkIdentDefs:
|
||||||
result = lcomma(n, 0, - 3)
|
result = lcomma(n, 0, - 3)
|
||||||
L = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
if n.sons[L - 2] != nil: result = result + lsub(n.sons[L - 2]) + 2
|
if n.sons[L - 2] != nil: result = result + lsub(n.sons[L - 2]) + 2
|
||||||
if n.sons[L - 1] != nil: result = result + lsub(n.sons[L - 1]) + 3
|
if n.sons[L - 1] != nil: result = result + lsub(n.sons[L - 1]) + 3
|
||||||
of nkVarTuple:
|
of nkVarTuple: result = lcomma(n, 0, - 3) + len("() = ") + lsub(lastSon(n))
|
||||||
result = lcomma(n, 0, - 3) + len("() = ") + lsub(lastSon(n))
|
of nkChckRangeF: result = len("chckRangeF") + 2 + lcomma(n)
|
||||||
of nkChckRangeF:
|
of nkChckRange64: result = len("chckRange64") + 2 + lcomma(n)
|
||||||
result = len("chckRangeF") + 2 + lcomma(n)
|
of nkChckRange: result = len("chckRange") + 2 + lcomma(n)
|
||||||
of nkChckRange64:
|
|
||||||
result = len("chckRange64") + 2 + lcomma(n)
|
|
||||||
of nkChckRange:
|
|
||||||
result = len("chckRange") + 2 + lcomma(n)
|
|
||||||
of nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString,
|
of nkObjDownConv, nkObjUpConv, nkStringToCString, nkCStringToString,
|
||||||
nkPassAsOpenArray:
|
nkPassAsOpenArray:
|
||||||
result = 2
|
result = 2
|
||||||
if sonsLen(n) >= 1: result = result + lsub(n.sons[0])
|
if sonsLen(n) >= 1: result = result + lsub(n.sons[0])
|
||||||
result = result + lcomma(n, 1)
|
result = result + lcomma(n, 1)
|
||||||
of nkExprColonExpr:
|
of nkExprColonExpr: result = lsons(n) + 2
|
||||||
result = lsons(n) + 2
|
of nkInfix: result = lsons(n) + 2
|
||||||
of nkInfix:
|
of nkPrefix: result = lsons(n) + 1
|
||||||
result = lsons(n) + 2
|
of nkPostfix: result = lsons(n)
|
||||||
of nkPrefix:
|
of nkCallStrLit: result = lsons(n)
|
||||||
result = lsons(n) + 1
|
of nkPragmaExpr: result = lsub(n.sons[0]) + lcomma(n, 1)
|
||||||
of nkPostfix:
|
of nkRange: result = lsons(n) + 2
|
||||||
result = lsons(n)
|
of nkDerefExpr: result = lsub(n.sons[0]) + 2
|
||||||
of nkCallStrLit:
|
of nkAccQuoted: result = lsub(n.sons[0]) + 2
|
||||||
result = lsons(n)
|
|
||||||
of nkPragmaExpr:
|
|
||||||
result = lsub(n.sons[0]) + lcomma(n, 1)
|
|
||||||
of nkRange:
|
|
||||||
result = lsons(n) + 2
|
|
||||||
of nkDerefExpr:
|
|
||||||
result = lsub(n.sons[0]) + 2
|
|
||||||
of nkAccQuoted:
|
|
||||||
result = lsub(n.sons[0]) + 2
|
|
||||||
of nkIfExpr:
|
of nkIfExpr:
|
||||||
result = lsub(n.sons[0].sons[0]) + lsub(n.sons[0].sons[1]) + lsons(n, 1) +
|
result = lsub(n.sons[0].sons[0]) + lsub(n.sons[0].sons[1]) + lsons(n, 1) +
|
||||||
len("if_:_")
|
len("if_:_")
|
||||||
of nkElifExpr:
|
of nkElifExpr: result = lsons(n) + len("_elif_:_")
|
||||||
result = lsons(n) + len("_elif_:_")
|
of nkElseExpr: result = lsub(n.sons[0]) + len("_else:_") # type descriptions
|
||||||
of nkElseExpr:
|
of nkTypeOfExpr: result = lsub(n.sons[0]) + len("type_")
|
||||||
result = lsub(n.sons[0]) + len("_else:_") # type descriptions
|
of nkRefTy: result = lsub(n.sons[0]) + len("ref_")
|
||||||
of nkTypeOfExpr:
|
of nkPtrTy: result = lsub(n.sons[0]) + len("ptr_")
|
||||||
result = lsub(n.sons[0]) + len("type_")
|
of nkVarTy: result = lsub(n.sons[0]) + len("var_")
|
||||||
of nkRefTy:
|
of nkDistinctTy: result = lsub(n.sons[0]) + len("Distinct_")
|
||||||
result = lsub(n.sons[0]) + len("ref_")
|
of nkTypeDef: result = lsons(n) + 3
|
||||||
of nkPtrTy:
|
of nkOfInherit: result = lsub(n.sons[0]) + len("of_")
|
||||||
result = lsub(n.sons[0]) + len("ptr_")
|
of nkProcTy: result = lsons(n) + len("proc_")
|
||||||
of nkVarTy:
|
of nkEnumTy: result = lsub(n.sons[0]) + lcomma(n, 1) + len("enum_")
|
||||||
result = lsub(n.sons[0]) + len("var_")
|
of nkEnumFieldDef: result = lsons(n) + 3
|
||||||
of nkDistinctTy:
|
|
||||||
result = lsub(n.sons[0]) + len("Distinct_")
|
|
||||||
of nkTypeDef:
|
|
||||||
result = lsons(n) + 3
|
|
||||||
of nkOfInherit:
|
|
||||||
result = lsub(n.sons[0]) + len("of_")
|
|
||||||
of nkProcTy:
|
|
||||||
result = lsons(n) + len("proc_")
|
|
||||||
of nkEnumTy:
|
|
||||||
result = lsub(n.sons[0]) + lcomma(n, 1) + len("enum_")
|
|
||||||
of nkEnumFieldDef:
|
|
||||||
result = lsons(n) + 3
|
|
||||||
of nkVarSection:
|
of nkVarSection:
|
||||||
if sonsLen(n) > 1: result = maxLineLen + 1
|
if sonsLen(n) > 1: result = maxLineLen + 1
|
||||||
else: result = lsons(n) + len("var_")
|
else: result = lsons(n) + len("var_")
|
||||||
of nkReturnStmt:
|
of nkReturnStmt: result = lsub(n.sons[0]) + len("return_")
|
||||||
result = lsub(n.sons[0]) + len("return_")
|
of nkRaiseStmt: result = lsub(n.sons[0]) + len("raise_")
|
||||||
of nkRaiseStmt:
|
of nkYieldStmt: result = lsub(n.sons[0]) + len("yield_")
|
||||||
result = lsub(n.sons[0]) + len("raise_")
|
of nkDiscardStmt: result = lsub(n.sons[0]) + len("discard_")
|
||||||
of nkYieldStmt:
|
of nkBreakStmt: result = lsub(n.sons[0]) + len("break_")
|
||||||
result = lsub(n.sons[0]) + len("yield_")
|
of nkContinueStmt: result = lsub(n.sons[0]) + len("continue_")
|
||||||
of nkDiscardStmt:
|
of nkPragma: result = lcomma(n) + 4
|
||||||
result = lsub(n.sons[0]) + len("discard_")
|
of nkCommentStmt: result = len(n.comment)
|
||||||
of nkBreakStmt:
|
of nkOfBranch: result = lcomma(n, 0, - 2) + lsub(lastSon(n)) + len("of_:_")
|
||||||
result = lsub(n.sons[0]) + len("break_")
|
of nkElifBranch: result = lsons(n) + len("elif_:_")
|
||||||
of nkContinueStmt:
|
of nkElse: result = lsub(n.sons[0]) + len("else:_")
|
||||||
result = lsub(n.sons[0]) + len("continue_")
|
of nkFinally: result = lsub(n.sons[0]) + len("finally:_")
|
||||||
of nkPragma:
|
of nkGenericParams: result = lcomma(n) + 2
|
||||||
result = lcomma(n) + 4
|
|
||||||
of nkCommentStmt:
|
|
||||||
result = len(n.comment)
|
|
||||||
of nkOfBranch:
|
|
||||||
result = lcomma(n, 0, - 2) + lsub(lastSon(n)) + len("of_:_")
|
|
||||||
of nkElifBranch:
|
|
||||||
result = lsons(n) + len("elif_:_")
|
|
||||||
of nkElse:
|
|
||||||
result = lsub(n.sons[0]) + len("else:_")
|
|
||||||
of nkFinally:
|
|
||||||
result = lsub(n.sons[0]) + len("finally:_")
|
|
||||||
of nkGenericParams:
|
|
||||||
result = lcomma(n) + 2
|
|
||||||
of nkFormalParams:
|
of nkFormalParams:
|
||||||
result = lcomma(n, 1) + 2
|
result = lcomma(n, 1) + 2
|
||||||
if n.sons[0] != nil: result = result + lsub(n.sons[0]) + 2
|
if n.sons[0] != nil: result = result + lsub(n.sons[0]) + 2
|
||||||
of nkExceptBranch:
|
of nkExceptBranch:
|
||||||
result = lcomma(n, 0, - 2) + lsub(lastSon(n)) + len("except_:_")
|
result = lcomma(n, 0, -2) + lsub(lastSon(n)) + len("except_:_")
|
||||||
else: result = maxLineLen + 1
|
else: result = maxLineLen + 1
|
||||||
|
|
||||||
proc fits(g: TSrcGen, x: int): bool =
|
proc fits(g: TSrcGen, x: int): bool =
|
||||||
|
|
@ -509,15 +431,12 @@ proc gsub(g: var TSrcGen, n: PNode) =
|
||||||
proc hasCom(n: PNode): bool =
|
proc hasCom(n: PNode): bool =
|
||||||
result = false
|
result = false
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
if n.comment != nil:
|
if n.comment != nil: return true
|
||||||
return true
|
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkEmpty..nkNilLit:
|
of nkEmpty..nkNilLit: nil
|
||||||
nil
|
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if hasCom(n.sons[i]):
|
if hasCom(n.sons[i]): return true
|
||||||
return true
|
|
||||||
|
|
||||||
proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
|
proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
|
||||||
put(g, kind, s)
|
put(g, kind, s)
|
||||||
|
|
@ -525,12 +444,9 @@ proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
|
||||||
|
|
||||||
proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
|
proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
|
||||||
theEnd: int = - 1) =
|
theEnd: int = - 1) =
|
||||||
var
|
|
||||||
sublen: int
|
|
||||||
c: bool
|
|
||||||
for i in countup(start, sonsLen(n) + theEnd):
|
for i in countup(start, sonsLen(n) + theEnd):
|
||||||
c = i < sonsLen(n) + theEnd
|
var c = i < sonsLen(n) + theEnd
|
||||||
sublen = lsub(n.sons[i]) + ord(c)
|
var sublen = lsub(n.sons[i]) + ord(c)
|
||||||
if not fits(g, sublen) and (ind + sublen < maxLineLen): optNL(g, ind)
|
if not fits(g, sublen) and (ind + sublen < maxLineLen): optNL(g, ind)
|
||||||
gsub(g, n.sons[i])
|
gsub(g, n.sons[i])
|
||||||
if c:
|
if c:
|
||||||
|
|
@ -550,19 +466,17 @@ proc gcomma(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
|
||||||
gcommaAux(g, n, ind, start, theEnd)
|
gcommaAux(g, n, ind, start, theEnd)
|
||||||
|
|
||||||
proc gcomma(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) =
|
proc gcomma(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) =
|
||||||
var ind: int
|
var ind = g.lineLen
|
||||||
ind = g.lineLen
|
|
||||||
if ind > maxLineLen div 2: ind = g.indent + longIndentWid
|
if ind > maxLineLen div 2: ind = g.indent + longIndentWid
|
||||||
gcommaAux(g, n, ind, start, theEnd)
|
gcommaAux(g, n, ind, start, theEnd)
|
||||||
|
|
||||||
proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
|
proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
|
||||||
theEnd: int = - 1) =
|
theEnd: int = - 1) =
|
||||||
for i in countup(start, sonsLen(n) + theEnd):
|
for i in countup(start, sonsLen(n) + theEnd): gsub(g, n.sons[i], c)
|
||||||
gsub(g, n.sons[i], c)
|
|
||||||
|
|
||||||
proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType, k: string) =
|
proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType,
|
||||||
if sonsLen(n) == 0:
|
k: string) =
|
||||||
return # empty var sections are possible
|
if sonsLen(n) == 0: return # empty var sections are possible
|
||||||
putWithSpace(g, kind, k)
|
putWithSpace(g, kind, k)
|
||||||
gcoms(g)
|
gcoms(g)
|
||||||
indentNL(g)
|
indentNL(g)
|
||||||
|
|
@ -600,7 +514,6 @@ proc gstmts(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
proc gif(g: var TSrcGen, n: PNode) =
|
proc gif(g: var TSrcGen, n: PNode) =
|
||||||
var
|
var
|
||||||
c: TContext
|
c: TContext
|
||||||
length: int
|
|
||||||
gsub(g, n.sons[0].sons[0])
|
gsub(g, n.sons[0].sons[0])
|
||||||
initContext(c)
|
initContext(c)
|
||||||
putWithSpace(g, tkColon, ":")
|
putWithSpace(g, tkColon, ":")
|
||||||
|
|
@ -608,7 +521,7 @@ proc gif(g: var TSrcGen, n: PNode) =
|
||||||
incl(c.flags, rfLongMode)
|
incl(c.flags, rfLongMode)
|
||||||
gcoms(g) # a good place for comments
|
gcoms(g) # a good place for comments
|
||||||
gstmts(g, n.sons[0].sons[1], c)
|
gstmts(g, n.sons[0].sons[1], c)
|
||||||
length = sonsLen(n)
|
var length = sonsLen(n)
|
||||||
for i in countup(1, length - 1):
|
for i in countup(1, length - 1):
|
||||||
optNL(g)
|
optNL(g)
|
||||||
gsub(g, n.sons[i], c)
|
gsub(g, n.sons[i], c)
|
||||||
|
|
@ -636,10 +549,8 @@ proc gtry(g: var TSrcGen, n: PNode) =
|
||||||
gsons(g, n, c, 1)
|
gsons(g, n, c, 1)
|
||||||
|
|
||||||
proc gfor(g: var TSrcGen, n: PNode) =
|
proc gfor(g: var TSrcGen, n: PNode) =
|
||||||
var
|
var c: TContext
|
||||||
c: TContext
|
var length = sonsLen(n)
|
||||||
length: int
|
|
||||||
length = sonsLen(n)
|
|
||||||
putWithSpace(g, tkFor, "for")
|
putWithSpace(g, tkFor, "for")
|
||||||
initContext(c)
|
initContext(c)
|
||||||
if longMode(n) or
|
if longMode(n) or
|
||||||
|
|
@ -665,18 +576,16 @@ proc gmacro(g: var TSrcGen, n: PNode) =
|
||||||
gsons(g, n, c, 1)
|
gsons(g, n, c, 1)
|
||||||
|
|
||||||
proc gcase(g: var TSrcGen, n: PNode) =
|
proc gcase(g: var TSrcGen, n: PNode) =
|
||||||
var
|
var c: TContext
|
||||||
c: TContext
|
|
||||||
length, last: int
|
|
||||||
initContext(c)
|
initContext(c)
|
||||||
length = sonsLen(n)
|
var length = sonsLen(n)
|
||||||
if n.sons[length - 1].kind == nkElse: last = - 2
|
var last = if n.sons[length-1].kind == nkElse: -2 else: -1
|
||||||
else: last = - 1
|
|
||||||
if longMode(n, 0, last): incl(c.flags, rfLongMode)
|
if longMode(n, 0, last): incl(c.flags, rfLongMode)
|
||||||
putWithSpace(g, tkCase, "case")
|
putWithSpace(g, tkCase, "case")
|
||||||
gsub(g, n.sons[0])
|
gsub(g, n.sons[0])
|
||||||
gcoms(g)
|
gcoms(g)
|
||||||
optNL(g)
|
optNL(g)
|
||||||
|
last = 0
|
||||||
gsons(g, n, c, 1, last)
|
gsons(g, n, c, 1, last)
|
||||||
if last == - 2:
|
if last == - 2:
|
||||||
initContext(c)
|
initContext(c)
|
||||||
|
|
@ -722,10 +631,8 @@ proc gasm(g: var TSrcGen, n: PNode) =
|
||||||
gsub(g, n.sons[1])
|
gsub(g, n.sons[1])
|
||||||
|
|
||||||
proc gident(g: var TSrcGen, n: PNode) =
|
proc gident(g: var TSrcGen, n: PNode) =
|
||||||
var
|
var t: TTokType
|
||||||
s: string
|
var s = atom(n)
|
||||||
t: TTokType
|
|
||||||
s = atom(n)
|
|
||||||
if (s[0] in scanner.SymChars):
|
if (s[0] in scanner.SymChars):
|
||||||
if (n.kind == nkIdent):
|
if (n.kind == nkIdent):
|
||||||
if (n.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or
|
if (n.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or
|
||||||
|
|
@ -747,36 +654,21 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
if n.comment != nil: pushCom(g, n)
|
if n.comment != nil: pushCom(g, n)
|
||||||
case n.kind # atoms:
|
case n.kind # atoms:
|
||||||
of nkTripleStrLit:
|
of nkTripleStrLit: putRawStr(g, tkTripleStrLit, n.strVal)
|
||||||
putRawStr(g, tkTripleStrLit, n.strVal)
|
of nkEmpty, nkType: put(g, tkInvalid, atom(n))
|
||||||
of nkEmpty, nkType:
|
of nkSym, nkIdent: gident(g, n)
|
||||||
put(g, tkInvalid, atom(n))
|
of nkIntLit: put(g, tkIntLit, atom(n))
|
||||||
of nkSym, nkIdent:
|
of nkInt8Lit: put(g, tkInt8Lit, atom(n))
|
||||||
gident(g, n)
|
of nkInt16Lit: put(g, tkInt16Lit, atom(n))
|
||||||
of nkIntLit:
|
of nkInt32Lit: put(g, tkInt32Lit, atom(n))
|
||||||
put(g, tkIntLit, atom(n))
|
of nkInt64Lit: put(g, tkInt64Lit, atom(n))
|
||||||
of nkInt8Lit:
|
of nkFloatLit: put(g, tkFloatLit, atom(n))
|
||||||
put(g, tkInt8Lit, atom(n))
|
of nkFloat32Lit: put(g, tkFloat32Lit, atom(n))
|
||||||
of nkInt16Lit:
|
of nkFloat64Lit: put(g, tkFloat64Lit, atom(n))
|
||||||
put(g, tkInt16Lit, atom(n))
|
of nkStrLit: put(g, tkStrLit, atom(n))
|
||||||
of nkInt32Lit:
|
of nkRStrLit: put(g, tkRStrLit, atom(n))
|
||||||
put(g, tkInt32Lit, atom(n))
|
of nkCharLit: put(g, tkCharLit, atom(n))
|
||||||
of nkInt64Lit:
|
of nkNilLit: put(g, tkNil, atom(n)) # complex expressions
|
||||||
put(g, tkInt64Lit, atom(n))
|
|
||||||
of nkFloatLit:
|
|
||||||
put(g, tkFloatLit, atom(n))
|
|
||||||
of nkFloat32Lit:
|
|
||||||
put(g, tkFloat32Lit, atom(n))
|
|
||||||
of nkFloat64Lit:
|
|
||||||
put(g, tkFloat64Lit, atom(n))
|
|
||||||
of nkStrLit:
|
|
||||||
put(g, tkStrLit, atom(n))
|
|
||||||
of nkRStrLit:
|
|
||||||
put(g, tkRStrLit, atom(n))
|
|
||||||
of nkCharLit:
|
|
||||||
put(g, tkCharLit, atom(n))
|
|
||||||
of nkNilLit:
|
|
||||||
put(g, tkNil, atom(n)) # complex expressions
|
|
||||||
of nkCall, nkConv, nkDotCall:
|
of nkCall, nkConv, nkDotCall:
|
||||||
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
||||||
put(g, tkParLe, "(")
|
put(g, tkParLe, "(")
|
||||||
|
|
@ -785,11 +677,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
of nkCallStrLit:
|
of nkCallStrLit:
|
||||||
gsub(g, n.sons[0])
|
gsub(g, n.sons[0])
|
||||||
if n.sons[1].kind == nkRStrLit:
|
if n.sons[1].kind == nkRStrLit:
|
||||||
put(g, tkRStrLit, '\"' & n.sons[1].strVal & '\"')
|
put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"')
|
||||||
else:
|
else:
|
||||||
gsub(g, n.sons[0])
|
gsub(g, n.sons[0])
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv:
|
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[0])
|
||||||
gsub(g, n.sons[0])
|
|
||||||
of nkCast:
|
of nkCast:
|
||||||
put(g, tkCast, "cast")
|
put(g, tkCast, "cast")
|
||||||
put(g, tkBracketLe, "[")
|
put(g, tkBracketLe, "[")
|
||||||
|
|
@ -878,7 +769,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
gsub(g, n.sons[codePos])
|
gsub(g, n.sons[codePos])
|
||||||
of nkConstDef, nkIdentDefs:
|
of nkConstDef, nkIdentDefs:
|
||||||
gcomma(g, n, 0, - 3)
|
gcomma(g, n, 0, - 3)
|
||||||
L = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
if n.sons[L - 2] != nil:
|
if n.sons[L - 2] != nil:
|
||||||
putWithSpace(g, tkColon, ":")
|
putWithSpace(g, tkColon, ":")
|
||||||
gsub(g, n.sons[L - 2])
|
gsub(g, n.sons[L - 2])
|
||||||
|
|
@ -919,8 +810,8 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
gsub(g, n.sons[1])
|
gsub(g, n.sons[1])
|
||||||
of nkDerefExpr:
|
of nkDerefExpr:
|
||||||
gsub(g, n.sons[0])
|
gsub(g, n.sons[0])
|
||||||
putWithSpace(g, tkHat, "^") # unfortunately this requires a space, because ^. would be
|
putWithSpace(g, tkHat, "^")
|
||||||
# only one operator
|
# unfortunately this requires a space, because ^. would be only one operator
|
||||||
of nkAccQuoted:
|
of nkAccQuoted:
|
||||||
put(g, tkAccent, "`")
|
put(g, tkAccent, "`")
|
||||||
gsub(g, n.sons[0])
|
gsub(g, n.sons[0])
|
||||||
|
|
@ -996,28 +887,20 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
put(g, tkSpaces, Space)
|
put(g, tkSpaces, Space)
|
||||||
putWithSpace(g, tkEquals, "=")
|
putWithSpace(g, tkEquals, "=")
|
||||||
gsub(g, n.sons[1])
|
gsub(g, n.sons[1])
|
||||||
of nkStmtList, nkStmtListExpr:
|
of nkStmtList, nkStmtListExpr: gstmts(g, n, emptyContext)
|
||||||
gstmts(g, n, emptyContext)
|
|
||||||
of nkIfStmt:
|
of nkIfStmt:
|
||||||
putWithSpace(g, tkIf, "if")
|
putWithSpace(g, tkIf, "if")
|
||||||
gif(g, n)
|
gif(g, n)
|
||||||
of nkWhenStmt, nkRecWhen:
|
of nkWhenStmt, nkRecWhen:
|
||||||
putWithSpace(g, tkWhen, "when")
|
putWithSpace(g, tkWhen, "when")
|
||||||
gif(g, n)
|
gif(g, n)
|
||||||
of nkWhileStmt:
|
of nkWhileStmt: gwhile(g, n)
|
||||||
gwhile(g, n)
|
of nkCaseStmt, nkRecCase: gcase(g, n)
|
||||||
of nkCaseStmt, nkRecCase:
|
of nkMacroStmt: gmacro(g, n)
|
||||||
gcase(g, n)
|
of nkTryStmt: gtry(g, n)
|
||||||
of nkMacroStmt:
|
of nkForStmt: gfor(g, n)
|
||||||
gmacro(g, n)
|
of nkBlockStmt, nkBlockExpr: gblock(g, n)
|
||||||
of nkTryStmt:
|
of nkAsmStmt: gasm(g, n)
|
||||||
gtry(g, n)
|
|
||||||
of nkForStmt:
|
|
||||||
gfor(g, n)
|
|
||||||
of nkBlockStmt, nkBlockExpr:
|
|
||||||
gblock(g, n)
|
|
||||||
of nkAsmStmt:
|
|
||||||
gasm(g, n)
|
|
||||||
of nkProcDef:
|
of nkProcDef:
|
||||||
putWithSpace(g, tkProc, "proc")
|
putWithSpace(g, tkProc, "proc")
|
||||||
gproc(g, n)
|
gproc(g, n)
|
||||||
|
|
@ -1170,8 +1053,7 @@ proc renderModule(n: PNode, filename: string, renderFlags: TRenderFlags = {}) =
|
||||||
if n.sons[i] != nil:
|
if n.sons[i] != nil:
|
||||||
case n.sons[i].kind
|
case n.sons[i].kind
|
||||||
of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
|
of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
|
||||||
else:
|
else: nil
|
||||||
nil
|
|
||||||
gcoms(g)
|
gcoms(g)
|
||||||
if open(f, filename, fmWrite):
|
if open(f, filename, fmWrite):
|
||||||
write(f, g.buf)
|
write(f, g.buf)
|
||||||
|
|
@ -1182,10 +1064,9 @@ proc initTokRender(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) =
|
||||||
gsub(r, n)
|
gsub(r, n)
|
||||||
|
|
||||||
proc getNextTok(r: var TSrcGen, kind: var TTokType, literal: var string) =
|
proc getNextTok(r: var TSrcGen, kind: var TTokType, literal: var string) =
|
||||||
var length: int
|
|
||||||
if r.idx < len(r.tokens):
|
if r.idx < len(r.tokens):
|
||||||
kind = r.tokens[r.idx].kind
|
kind = r.tokens[r.idx].kind
|
||||||
length = r.tokens[r.idx].length
|
var length = r.tokens[r.idx].length
|
||||||
literal = copy(r.buf, r.pos + 0, r.pos + 0 + length - 1)
|
literal = copy(r.buf, r.pos + 0, r.pos + 0 + length - 1)
|
||||||
inc(r.pos, length)
|
inc(r.pos, length)
|
||||||
inc(r.idx)
|
inc(r.idx)
|
||||||
|
|
|
||||||
151
rod/scanner.nim
151
rod/scanner.nim
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2010 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -52,15 +52,18 @@ type
|
||||||
tkImplies, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator, tkLambda,
|
tkImplies, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator, tkLambda,
|
||||||
tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr,
|
tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr,
|
||||||
tkOut, tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkTemplate,
|
tkOut, tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkTemplate,
|
||||||
tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor, tkYield, #[[[end]]]
|
tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
|
||||||
|
tkYield, #[[[end]]]
|
||||||
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit,
|
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit,
|
||||||
tkFloat32Lit, tkFloat64Lit, tkStrLit, tkRStrLit, tkTripleStrLit,
|
tkFloat32Lit, tkFloat64Lit, tkStrLit, tkRStrLit, tkTripleStrLit,
|
||||||
tkCallRStrLit, tkCallTripleStrLit, tkCharLit, tkParLe, tkParRi, tkBracketLe,
|
tkCallRStrLit, tkCallTripleStrLit, tkCharLit, tkParLe, tkParRi, tkBracketLe,
|
||||||
tkBracketRi, tkCurlyLe, tkCurlyRi, tkBracketDotLe, tkBracketDotRi, # [. and .]
|
tkBracketRi, tkCurlyLe, tkCurlyRi,
|
||||||
|
tkBracketDotLe, tkBracketDotRi, # [. and .]
|
||||||
tkCurlyDotLe, tkCurlyDotRi, # {. and .}
|
tkCurlyDotLe, tkCurlyDotRi, # {. and .}
|
||||||
tkParDotLe, tkParDotRi, # (. and .)
|
tkParDotLe, tkParDotRi, # (. and .)
|
||||||
tkComma, tkSemiColon, tkColon, tkEquals, tkDot, tkDotDot, tkHat, tkOpr,
|
tkComma, tkSemiColon, tkColon, tkEquals, tkDot, tkDotDot, tkHat, tkOpr,
|
||||||
tkComment, tkAccent, tkInd, tkSad, tkDed, # pseudo token types used by the source renderers:
|
tkComment, tkAccent, tkInd, tkSad,
|
||||||
|
tkDed, # pseudo token types used by the source renderers:
|
||||||
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr
|
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr
|
||||||
TTokTypes* = set[TTokType]
|
TTokTypes* = set[TTokType]
|
||||||
|
|
||||||
|
|
@ -70,7 +73,8 @@ const
|
||||||
tokOperators*: TTokTypes = {tkOpr, tkSymbol, tkBracketLe, tkBracketRi, tkIn,
|
tokOperators*: TTokTypes = {tkOpr, tkSymbol, tkBracketLe, tkBracketRi, tkIn,
|
||||||
tkIs, tkIsNot, tkEquals, tkDot, tkHat, tkNot, tkAnd, tkOr, tkXor, tkShl,
|
tkIs, tkIsNot, tkEquals, tkDot, tkHat, tkNot, tkAnd, tkOr, tkXor, tkShl,
|
||||||
tkShr, tkDiv, tkMod, tkNotIn}
|
tkShr, tkDiv, tkMod, tkNotIn}
|
||||||
TokTypeToStr*: array[TTokType, string] = ["tkInvalid", "[EOF]", "tkSymbol", #[[[cog
|
TokTypeToStr*: array[TTokType, string] = ["tkInvalid", "[EOF]",
|
||||||
|
"tkSymbol", #[[[cog
|
||||||
#cog.out(strings)
|
#cog.out(strings)
|
||||||
#]]]
|
#]]]
|
||||||
"addr", "and", "as", "asm", "bind", "block", "break", "case", "cast",
|
"addr", "and", "as", "asm", "bind", "block", "break", "case", "cast",
|
||||||
|
|
@ -79,7 +83,8 @@ const
|
||||||
"implies", "import", "in", "include", "is", "isnot", "iterator", "lambda",
|
"implies", "import", "in", "include", "is", "isnot", "iterator", "lambda",
|
||||||
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or",
|
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or",
|
||||||
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template",
|
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template",
|
||||||
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor", "yield", #[[[end]]]
|
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
|
||||||
|
"yield", #[[[end]]]
|
||||||
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
|
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
|
||||||
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkStrLit", "tkRStrLit",
|
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkStrLit", "tkRStrLit",
|
||||||
"tkTripleStrLit", "tkCallRStrLit", "tkCallTripleStrLit", "tkCharLit", "(",
|
"tkTripleStrLit", "tkCallRStrLit", "tkCallTripleStrLit", "tkCharLit", "(",
|
||||||
|
|
@ -213,17 +218,13 @@ proc lexMessage(L: TLexer, msg: TMsgKind, arg: string = "") =
|
||||||
msgs.liMessage(getLineInfo(L), msg, arg)
|
msgs.liMessage(getLineInfo(L), msg, arg)
|
||||||
|
|
||||||
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg: string = "") =
|
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg: string = "") =
|
||||||
var info: TLineInfo
|
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
|
||||||
info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
|
|
||||||
msgs.liMessage(info, msg, arg)
|
msgs.liMessage(info, msg, arg)
|
||||||
|
|
||||||
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
|
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
|
||||||
# matches ([chars]_)*
|
# matches ([chars]_)*
|
||||||
var
|
var pos = L.bufpos # use registers for pos, buf
|
||||||
pos: int
|
var buf = L.buf
|
||||||
buf: cstring
|
|
||||||
pos = L.bufpos # use registers for pos, buf
|
|
||||||
buf = L.buf
|
|
||||||
while true:
|
while true:
|
||||||
if buf[pos] in chars:
|
if buf[pos] in chars:
|
||||||
add(tok.literal, buf[pos])
|
add(tok.literal, buf[pos])
|
||||||
|
|
@ -256,7 +257,8 @@ proc GetNumber(L: var TLexer): TToken =
|
||||||
matchUnderscoreChars(L, result, {'A'..'Z', 'a'..'z', '0'..'9'})
|
matchUnderscoreChars(L, result, {'A'..'Z', 'a'..'z', '0'..'9'})
|
||||||
if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}):
|
if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}):
|
||||||
add(result.literal, '.')
|
add(result.literal, '.')
|
||||||
inc(L.bufpos) #matchUnderscoreChars(L, result, ['A'..'Z', 'a'..'z', '0'..'9'])
|
inc(L.bufpos)
|
||||||
|
#matchUnderscoreChars(L, result, ['A'..'Z', 'a'..'z', '0'..'9'])
|
||||||
matchUnderscoreChars(L, result, {'0'..'9'})
|
matchUnderscoreChars(L, result, {'0'..'9'})
|
||||||
if L.buf[L.bufpos] in {'e', 'E'}:
|
if L.buf[L.bufpos] in {'e', 'E'}:
|
||||||
add(result.literal, 'e')
|
add(result.literal, 'e')
|
||||||
|
|
@ -355,19 +357,15 @@ proc GetNumber(L: var TLexer): TToken =
|
||||||
else: break
|
else: break
|
||||||
else: InternalError(getLineInfo(L), "getNumber")
|
else: InternalError(getLineInfo(L), "getNumber")
|
||||||
case result.tokType
|
case result.tokType
|
||||||
of tkIntLit, tkInt64Lit:
|
of tkIntLit, tkInt64Lit: result.iNumber = xi
|
||||||
result.iNumber = xi
|
of tkInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi))))
|
||||||
of tkInt8Lit:
|
of tkInt16Lit: result.iNumber = biggestInt(toU16(int(xi)))
|
||||||
result.iNumber = biggestInt(int8(toU8(int(xi))))
|
of tkInt32Lit: result.iNumber = biggestInt(toU32(xi))
|
||||||
of tkInt16Lit:
|
|
||||||
result.iNumber = biggestInt(toU16(int(xi)))
|
|
||||||
of tkInt32Lit:
|
|
||||||
result.iNumber = biggestInt(toU32(xi))
|
|
||||||
of tkFloat32Lit:
|
of tkFloat32Lit:
|
||||||
result.fNumber = (cast[PFloat32](addr(xi)))^ # note: this code is endian neutral!
|
result.fNumber = (cast[PFloat32](addr(xi)))^
|
||||||
|
# note: this code is endian neutral!
|
||||||
# XXX: Test this on big endian machine!
|
# XXX: Test this on big endian machine!
|
||||||
of tkFloat64Lit:
|
of tkFloat64Lit: result.fNumber = (cast[PFloat64](addr(xi)))^
|
||||||
result.fNumber = (cast[PFloat64](addr(xi)))^
|
|
||||||
else: InternalError(getLineInfo(L), "getNumber")
|
else: InternalError(getLineInfo(L), "getNumber")
|
||||||
elif isFloatLiteral(result.literal) or (result.tokType == tkFloat32Lit) or
|
elif isFloatLiteral(result.literal) or (result.tokType == tkFloat32Lit) or
|
||||||
(result.tokType == tkFloat64Lit):
|
(result.tokType == tkFloat64Lit):
|
||||||
|
|
@ -380,12 +378,9 @@ proc GetNumber(L: var TLexer): TToken =
|
||||||
result.tokType = tkInt64Lit
|
result.tokType = tkInt64Lit
|
||||||
elif result.tokType != tkInt64Lit:
|
elif result.tokType != tkInt64Lit:
|
||||||
lexMessage(L, errInvalidNumber, result.literal)
|
lexMessage(L, errInvalidNumber, result.literal)
|
||||||
except EInvalidValue:
|
except EInvalidValue: lexMessage(L, errInvalidNumber, result.literal)
|
||||||
lexMessage(L, errInvalidNumber, result.literal)
|
except EOverflow: lexMessage(L, errNumberOutOfRange, result.literal)
|
||||||
except EOverflow:
|
except EOutOfRange: lexMessage(L, errNumberOutOfRange, result.literal)
|
||||||
lexMessage(L, errNumberOutOfRange, result.literal)
|
|
||||||
except EOutOfRange:
|
|
||||||
lexMessage(L, errNumberOutOfRange, result.literal)
|
|
||||||
L.bufpos = endpos
|
L.bufpos = endpos
|
||||||
|
|
||||||
proc handleHexChar(L: var TLexer, xi: var int) =
|
proc handleHexChar(L: var TLexer, xi: var int) =
|
||||||
|
|
@ -472,14 +467,10 @@ proc HandleCRLF(L: var TLexer, pos: int): int =
|
||||||
else: result = pos
|
else: result = pos
|
||||||
|
|
||||||
proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||||
var
|
var pos = L.bufPos + 1 # skip "
|
||||||
line, line2, pos: int
|
var buf = L.buf # put `buf` in a register
|
||||||
c: Char
|
var line = L.linenumber # save linenumber for better error message
|
||||||
buf: cstring
|
if buf[pos] == '\"' and buf[pos+1] == '\"':
|
||||||
pos = L.bufPos + 1 # skip "
|
|
||||||
buf = L.buf # put `buf` in a register
|
|
||||||
line = L.linenumber # save linenumber for better error message
|
|
||||||
if (buf[pos] == '\"') and (buf[pos + 1] == '\"'):
|
|
||||||
tok.tokType = tkTripleStrLit # long string literal:
|
tok.tokType = tkTripleStrLit # long string literal:
|
||||||
inc(pos, 2) # skip ""
|
inc(pos, 2) # skip ""
|
||||||
# skip leading newline:
|
# skip leading newline:
|
||||||
|
|
@ -488,7 +479,10 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||||
while true:
|
while true:
|
||||||
case buf[pos]
|
case buf[pos]
|
||||||
of '\"':
|
of '\"':
|
||||||
if (buf[pos + 1] == '\"') and (buf[pos + 2] == '\"'): break
|
if buf[pos+1] == '\"' and buf[pos+2] == '\"' and
|
||||||
|
buf[pos+3] != '\"':
|
||||||
|
L.bufpos = pos + 3 # skip the three """
|
||||||
|
break
|
||||||
add(tok.literal, '\"')
|
add(tok.literal, '\"')
|
||||||
Inc(pos)
|
Inc(pos)
|
||||||
of CR, LF:
|
of CR, LF:
|
||||||
|
|
@ -496,7 +490,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
tok.literal = tok.literal & tnl
|
tok.literal = tok.literal & tnl
|
||||||
of lexbase.EndOfFile:
|
of lexbase.EndOfFile:
|
||||||
line2 = L.linenumber
|
var line2 = L.linenumber
|
||||||
L.LineNumber = line
|
L.LineNumber = line
|
||||||
lexMessagePos(L, errClosingTripleQuoteExpected, L.lineStart)
|
lexMessagePos(L, errClosingTripleQuoteExpected, L.lineStart)
|
||||||
L.LineNumber = line2
|
L.LineNumber = line2
|
||||||
|
|
@ -504,20 +498,23 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||||
else:
|
else:
|
||||||
add(tok.literal, buf[pos])
|
add(tok.literal, buf[pos])
|
||||||
Inc(pos)
|
Inc(pos)
|
||||||
L.bufpos = pos + 3 # skip the three """
|
|
||||||
else:
|
else:
|
||||||
# ordinary string literal
|
# ordinary string literal
|
||||||
if rawMode: tok.tokType = tkRStrLit
|
if rawMode: tok.tokType = tkRStrLit
|
||||||
else: tok.tokType = tkStrLit
|
else: tok.tokType = tkStrLit
|
||||||
while true:
|
while true:
|
||||||
c = buf[pos]
|
var c = buf[pos]
|
||||||
if c == '\"':
|
if c == '\"':
|
||||||
|
if rawMode and buf[pos+1] == '\"':
|
||||||
|
inc(pos, 2)
|
||||||
|
add(tok.literal, '"')
|
||||||
|
else:
|
||||||
inc(pos) # skip '"'
|
inc(pos) # skip '"'
|
||||||
break
|
break
|
||||||
if c in {CR, LF, lexbase.EndOfFile}:
|
elif c in {CR, LF, lexbase.EndOfFile}:
|
||||||
lexMessage(L, errClosingQuoteExpected)
|
lexMessage(L, errClosingQuoteExpected)
|
||||||
break
|
break
|
||||||
if (c == '\\') and not rawMode:
|
elif (c == '\\') and not rawMode:
|
||||||
L.bufPos = pos
|
L.bufPos = pos
|
||||||
getEscapedChar(L, tok)
|
getEscapedChar(L, tok)
|
||||||
pos = L.bufPos
|
pos = L.bufPos
|
||||||
|
|
@ -527,29 +524,23 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
proc getCharacter(L: var TLexer, tok: var TToken) =
|
proc getCharacter(L: var TLexer, tok: var TToken) =
|
||||||
var c: Char
|
|
||||||
Inc(L.bufpos) # skip '
|
Inc(L.bufpos) # skip '
|
||||||
c = L.buf[L.bufpos]
|
var c = L.buf[L.bufpos]
|
||||||
case c
|
case c
|
||||||
of '\0'..Pred(' '), '\'': lexMessage(L, errInvalidCharacterConstant)
|
of '\0'..Pred(' '), '\'': lexMessage(L, errInvalidCharacterConstant)
|
||||||
of '\\': getEscapedChar(L, tok)
|
of '\\': getEscapedChar(L, tok)
|
||||||
else:
|
else:
|
||||||
tok.literal = c & ""
|
tok.literal = $c
|
||||||
Inc(L.bufpos)
|
Inc(L.bufpos)
|
||||||
if L.buf[L.bufpos] != '\'': lexMessage(L, errMissingFinalQuote)
|
if L.buf[L.bufpos] != '\'': lexMessage(L, errMissingFinalQuote)
|
||||||
inc(L.bufpos) # skip '
|
inc(L.bufpos) # skip '
|
||||||
|
|
||||||
proc getSymbol(L: var TLexer, tok: var TToken) =
|
proc getSymbol(L: var TLexer, tok: var TToken) =
|
||||||
var
|
var h: THash = 0
|
||||||
pos: int
|
var pos = L.bufpos
|
||||||
c: Char
|
var buf = L.buf
|
||||||
buf: cstring
|
|
||||||
h: THash # hashing algorithm inlined
|
|
||||||
h = 0
|
|
||||||
pos = L.bufpos
|
|
||||||
buf = L.buf
|
|
||||||
while true:
|
while true:
|
||||||
c = buf[pos]
|
var c = buf[pos]
|
||||||
case c
|
case c
|
||||||
of 'a'..'z', '0'..'9', '\x80'..'\xFF':
|
of 'a'..'z', '0'..'9', '\x80'..'\xFF':
|
||||||
h = h +% Ord(c)
|
h = h +% Ord(c)
|
||||||
|
|
@ -560,8 +551,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
|
||||||
h = h +% Ord(c)
|
h = h +% Ord(c)
|
||||||
h = h +% h shl 10
|
h = h +% h shl 10
|
||||||
h = h xor (h shr 6)
|
h = h xor (h shr 6)
|
||||||
of '_':
|
of '_': nil
|
||||||
nil
|
|
||||||
else: break
|
else: break
|
||||||
Inc(pos)
|
Inc(pos)
|
||||||
h = h +% h shl 3
|
h = h +% h shl 3
|
||||||
|
|
@ -580,16 +570,11 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
|
||||||
else: tok.tokType = tkCallTripleStrLit
|
else: tok.tokType = tkCallTripleStrLit
|
||||||
|
|
||||||
proc getOperator(L: var TLexer, tok: var TToken) =
|
proc getOperator(L: var TLexer, tok: var TToken) =
|
||||||
var
|
var pos = L.bufpos
|
||||||
pos: int
|
var buf = L.buf
|
||||||
c: Char
|
var h: THash = 0
|
||||||
buf: cstring
|
|
||||||
h: THash # hashing algorithm inlined
|
|
||||||
pos = L.bufpos
|
|
||||||
buf = L.buf
|
|
||||||
h = 0
|
|
||||||
while true:
|
while true:
|
||||||
c = buf[pos]
|
var c = buf[pos]
|
||||||
if c in OpChars:
|
if c in OpChars:
|
||||||
h = h +% Ord(c)
|
h = h +% Ord(c)
|
||||||
h = h +% h shl 10
|
h = h +% h shl 10
|
||||||
|
|
@ -606,9 +591,8 @@ proc getOperator(L: var TLexer, tok: var TToken) =
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
proc handleIndentation(L: var TLexer, tok: var TToken, indent: int) =
|
proc handleIndentation(L: var TLexer, tok: var TToken, indent: int) =
|
||||||
var i: int
|
|
||||||
tok.indent = indent
|
tok.indent = indent
|
||||||
i = high(L.indentStack)
|
var i = high(L.indentStack)
|
||||||
if indent > L.indentStack[i]:
|
if indent > L.indentStack[i]:
|
||||||
tok.tokType = tkInd
|
tok.tokType = tkInd
|
||||||
elif indent == L.indentStack[i]:
|
elif indent == L.indentStack[i]:
|
||||||
|
|
@ -625,22 +609,19 @@ proc handleIndentation(L: var TLexer, tok: var TToken, indent: int) =
|
||||||
lexMessage(L, errInvalidIndentation)
|
lexMessage(L, errInvalidIndentation)
|
||||||
|
|
||||||
proc scanComment(L: var TLexer, tok: var TToken) =
|
proc scanComment(L: var TLexer, tok: var TToken) =
|
||||||
var
|
var pos = L.bufpos
|
||||||
buf: cstring
|
var buf = L.buf
|
||||||
pos, col: int
|
# a comment ends if the next line does not start with the # on the same
|
||||||
indent: int
|
|
||||||
pos = L.bufpos
|
|
||||||
buf = L.buf # a comment ends if the next line does not start with the # on the same
|
|
||||||
# column after only whitespace
|
# column after only whitespace
|
||||||
tok.tokType = tkComment
|
tok.tokType = tkComment
|
||||||
col = getColNumber(L, pos)
|
var col = getColNumber(L, pos)
|
||||||
while true:
|
while true:
|
||||||
while not (buf[pos] in {CR, LF, lexbase.EndOfFile}):
|
while not (buf[pos] in {CR, LF, lexbase.EndOfFile}):
|
||||||
add(tok.literal, buf[pos])
|
add(tok.literal, buf[pos])
|
||||||
inc(pos)
|
inc(pos)
|
||||||
pos = handleCRLF(L, pos)
|
pos = handleCRLF(L, pos)
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
indent = 0
|
var indent = 0
|
||||||
while buf[pos] == ' ':
|
while buf[pos] == ' ':
|
||||||
inc(pos)
|
inc(pos)
|
||||||
inc(indent)
|
inc(indent)
|
||||||
|
|
@ -654,11 +635,8 @@ proc scanComment(L: var TLexer, tok: var TToken) =
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
proc skip(L: var TLexer, tok: var TToken) =
|
proc skip(L: var TLexer, tok: var TToken) =
|
||||||
var
|
var pos = L.bufpos
|
||||||
buf: cstring
|
var buf = L.buf
|
||||||
indent, pos: int
|
|
||||||
pos = L.bufpos
|
|
||||||
buf = L.buf
|
|
||||||
while true:
|
while true:
|
||||||
case buf[pos]
|
case buf[pos]
|
||||||
of ' ':
|
of ' ':
|
||||||
|
|
@ -669,7 +647,7 @@ proc skip(L: var TLexer, tok: var TToken) =
|
||||||
of CR, LF:
|
of CR, LF:
|
||||||
pos = HandleCRLF(L, pos)
|
pos = HandleCRLF(L, pos)
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
indent = 0
|
var indent = 0
|
||||||
while buf[pos] == ' ':
|
while buf[pos] == ' ':
|
||||||
Inc(pos)
|
Inc(pos)
|
||||||
Inc(indent)
|
Inc(indent)
|
||||||
|
|
@ -681,7 +659,6 @@ proc skip(L: var TLexer, tok: var TToken) =
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
proc rawGetTok(L: var TLexer, tok: var TToken) =
|
proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
var c: Char
|
|
||||||
fillToken(tok)
|
fillToken(tok)
|
||||||
if L.dedent > 0:
|
if L.dedent > 0:
|
||||||
dec(L.dedent)
|
dec(L.dedent)
|
||||||
|
|
@ -691,10 +668,10 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
else:
|
else:
|
||||||
tok.tokType = tkDed
|
tok.tokType = tkDed
|
||||||
return
|
return
|
||||||
skip(L, tok) # skip
|
skip(L, tok)
|
||||||
# got an documentation comment or tkIndent, return that:
|
# got an documentation comment or tkIndent, return that:
|
||||||
if tok.toktype != tkInvalid: return
|
if tok.toktype != tkInvalid: return
|
||||||
c = L.buf[L.bufpos]
|
var c = L.buf[L.bufpos]
|
||||||
if c in SymStartChars - {'r', 'R', 'l'}:
|
if c in SymStartChars - {'r', 'R', 'l'}:
|
||||||
getSymbol(L, tok)
|
getSymbol(L, tok)
|
||||||
elif c in {'0'..'9'}:
|
elif c in {'0'..'9'}:
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ proc callC() = callA()
|
||||||
try:
|
try:
|
||||||
callC()
|
callC()
|
||||||
except EAssertionFailed:
|
except EAssertionFailed:
|
||||||
write(stdout, "assertion failure!\n")
|
write(stdout, "assertion failure!")
|
||||||
except:
|
except:
|
||||||
write(stdout, "unknown exception!\n")
|
write(stdout, "unknown exception!")
|
||||||
finally:
|
finally:
|
||||||
system.write(stdout, "this shall be always written\n")
|
system.write(stdout, "this shall be always written")
|
||||||
|
|
||||||
assert(false)
|
assert(false) #OUT assertion failure!this shall be always written
|
||||||
|
|
|
||||||
20
tests/tinvalidnewseq.nim
Executable file
20
tests/tinvalidnewseq.nim
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import regexprs, strutils
|
||||||
|
|
||||||
|
type
|
||||||
|
TURL = tuple[protocol, subdomain, domain, port: string, path: seq[string]]
|
||||||
|
|
||||||
|
proc parseURL(url: string): TURL =
|
||||||
|
#([a-zA-Z]+://)?(\w+?\.)?(\w+)(\.\w+)(:[0-9]+)?(/.+)?
|
||||||
|
var pattern: string = r"([a-zA-Z]+://)?(\w+?\.)?(\w+)(\.\w+)(:[0-9]+)?(/.+)?"
|
||||||
|
var m: array[0..6, string] #Array with the matches
|
||||||
|
newSeq(m, 7) #ERROR
|
||||||
|
discard regexprs.match(url, pattern, m)
|
||||||
|
|
||||||
|
result = (protocol: m[1], subdomain: m[2], domain: m[3] & m[4],
|
||||||
|
port: m[5], path: m[6].split('/'))
|
||||||
|
|
||||||
|
var r: TUrl
|
||||||
|
|
||||||
|
r = parseUrl(r"http://google.com/search?var=bleahdhsad")
|
||||||
|
echo(r.domain)
|
||||||
|
|
||||||
14
tests/tstrlits.nim
Executable file
14
tests/tstrlits.nim
Executable file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Test the new different string literals
|
||||||
|
|
||||||
|
const
|
||||||
|
tripleEmpty = """"long string"""""""" # "long string """""
|
||||||
|
|
||||||
|
rawQuote = r"a"""
|
||||||
|
|
||||||
|
raw = r"abc""def"
|
||||||
|
|
||||||
|
stdout.write(rawQuote)
|
||||||
|
stdout.write(tripleEmpty)
|
||||||
|
stdout.write(raw)
|
||||||
|
#OUT a""long string"""""abc"def
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue