added '@' alternative string/char encoding

This commit is contained in:
Irmen de Jong 2020-03-11 00:32:50 +01:00
parent 98a638a2f3
commit ef6c731bb3
19 changed files with 852 additions and 787 deletions

View File

@ -55,8 +55,12 @@ private fun compileMain(args: Array<String>) {
with(CompilationTarget) {
name = "c64"
machine = C64MachineDefinition
encodeString = { str -> Petscii.encodePetscii(str, true) }
decodeString = { bytes -> Petscii.decodePetscii(bytes, true) }
encodeString = { str, altEncoding ->
if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
}
decodeString = { bytes, altEncoding ->
if(altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
}
asmGenerator = ::AsmGen
}
}

View File

@ -380,8 +380,13 @@ private fun prog8Parser.DirectiveContext.toAst() : Directive =
Directive(directivename.text, directivearg().map { it.toAst() }, toPosition())
private fun prog8Parser.DirectiveargContext.toAst() : DirectiveArg =
DirectiveArg(stringliteral()?.text, identifier()?.text, integerliteral()?.toAst()?.number?.toInt(), toPosition())
private fun prog8Parser.DirectiveargContext.toAst() : DirectiveArg {
val str = stringliteral()
if(str?.ALT_STRING_ENCODING() != null)
throw AstException("${toPosition()} can't use alternate string encodings for directive arguments")
return DirectiveArg(stringliteral()?.text, identifier()?.text, integerliteral()?.toAst()?.number?.toInt(), toPosition())
}
private fun prog8Parser.IntegerliteralContext.toAst(): NumericLiteral {
@ -456,11 +461,13 @@ private fun prog8Parser.ExpressionContext.toAst() : Expression {
else -> throw FatalAstException("invalid datatype for numeric literal")
}
litval.floatliteral()!=null -> NumericLiteralValue(DataType.FLOAT, litval.floatliteral().toAst(), litval.toPosition())
litval.stringliteral()!=null -> StringLiteralValue(unescape(litval.stringliteral().text, litval.toPosition()), litval.toPosition())
litval.stringliteral()!=null -> litval.stringliteral().toAst()
litval.charliteral()!=null -> {
try {
val cc=litval.charliteral()
NumericLiteralValue(DataType.UBYTE, CompilationTarget.encodeString(
unescape(litval.charliteral().text, litval.toPosition()))[0], litval.toPosition())
unescape(litval.charliteral().SINGLECHAR().text, litval.toPosition()),
litval.charliteral().ALT_STRING_ENCODING()!=null)[0], litval.toPosition())
} catch (ce: CharConversionException) {
throw SyntaxError(ce.message ?: ce.toString(), litval.toPosition())
}
@ -519,6 +526,10 @@ private fun prog8Parser.ExpressionContext.toAst() : Expression {
}
private fun prog8Parser.StringliteralContext.toAst(): StringLiteralValue =
StringLiteralValue(unescape(this.STRING().text, toPosition()), ALT_STRING_ENCODING()!=null, toPosition())
private fun prog8Parser.ArrayindexedContext.toAst(): ArrayIndexedExpression {
return ArrayIndexedExpression(scoped_identifier().toAst(),
arrayindex().toAst(),

View File

@ -430,6 +430,7 @@ class StructLiteralValue(var values: List<Expression>,
private var heapIdSequence = 0 // unique ids for strings and arrays "on the heap"
class StringLiteralValue(val value: String,
val altEncoding: Boolean, // such as: screencodes instead of Petscii for the C64
override val position: Position) : Expression() {
override lateinit var parent: Node
@ -445,11 +446,11 @@ class StringLiteralValue(val value: String,
override fun toString(): String = "'${escape(value)}'"
override fun inferType(program: Program): InferredTypes.InferredType = InferredTypes.knownFor(DataType.STR)
operator fun compareTo(other: StringLiteralValue): Int = value.compareTo(other.value)
override fun hashCode(): Int = value.hashCode()
override fun hashCode(): Int = Objects.hash(value, altEncoding)
override fun equals(other: Any?): Boolean {
if(other==null || other !is StringLiteralValue)
return false
return value==other.value
return value==other.value && altEncoding == other.altEncoding
}
}
@ -552,9 +553,9 @@ class RangeExpr(var from: Expression,
val fromString = from as? StringLiteralValue
val toString = to as? StringLiteralValue
if(fromString!=null && toString!=null ) {
// string range -> int range over petscii values
fromVal = CompilationTarget.encodeString(fromString.value)[0].toInt()
toVal = CompilationTarget.encodeString(toString.value)[0].toInt()
// string range -> int range over character values
fromVal = CompilationTarget.encodeString(fromString.value, fromString.altEncoding)[0].toInt()
toVal = CompilationTarget.encodeString(toString.value, fromString.altEncoding)[0].toInt()
} else {
val fromLv = from as? NumericLiteralValue
val toLv = to as? NumericLiteralValue

View File

@ -326,12 +326,12 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
if(constvalue!=null) {
if (expr.operator == "*") {
// repeat a string a number of times
return StringLiteralValue(string.value.repeat(constvalue.number.toInt()), expr.position)
return StringLiteralValue(string.value.repeat(constvalue.number.toInt()), string.altEncoding, expr.position)
}
}
if(expr.operator == "+" && operand is StringLiteralValue) {
// concatenate two strings
return StringLiteralValue("${string.value}${operand.value}", expr.position)
return StringLiteralValue("${string.value}${operand.value}", string.altEncoding, expr.position)
}
return expr
}

View File

@ -9,8 +9,8 @@ internal interface CompilationTarget {
companion object {
lateinit var name: String
lateinit var machine: IMachineDefinition
lateinit var encodeString: (str: String) -> List<Short>
lateinit var decodeString: (bytes: List<Short>) -> String
lateinit var encodeString: (str: String, altEncoding: Boolean) -> List<Short>
lateinit var decodeString: (bytes: List<Short>, altEncoding: Boolean) -> String
lateinit var asmGenerator: (Program, Zeropage, CompilationOptions, Path) -> IAssemblyGenerator
}
}

View File

@ -206,8 +206,8 @@ internal class AsmGen(private val program: Program,
return "$b0, $b1, $b2, $b3, $b4"
}
private fun petscii(str: String): List<Short> {
val bytes = Petscii.encodePetscii(str, true)
private fun encode(str: String, altEncoding: Boolean): List<Short> {
val bytes = if(altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
return bytes.plus(0)
}
@ -246,8 +246,8 @@ internal class AsmGen(private val program: Program,
DataType.FLOAT -> out("${decl.name}\t.byte 0,0,0,0,0 ; float")
DataType.STRUCT -> {} // is flattened
DataType.STR -> {
val string = (decl.value as StringLiteralValue).value
outputStringvar(decl, petscii(string))
val str = decl.value as StringLiteralValue
outputStringvar(decl, encode(str.value, str.altEncoding))
}
DataType.ARRAY_UB -> {
val data = makeArrayFillDataUnsigned(decl)
@ -331,7 +331,10 @@ internal class AsmGen(private val program: Program,
// special treatment for string types: merge strings that are identical
val encodedstringVars = normalVars
.filter {it.datatype == DataType.STR }
.map { it to petscii((it.value as StringLiteralValue).value) }
.map {
val str = it.value as StringLiteralValue
it to encode(str.value, str.altEncoding)
}
.groupBy({it.second}, {it.first})
for((encoded, variables) in encodedstringVars) {
variables.dropLast(1).forEach { out(it.name) }

View File

@ -180,7 +180,7 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
val vardecl = stringVar.targetVarDecl(program.namespace)!!
val string = vardecl.value!! as StringLiteralValue
if(string.value.length==1) {
val firstCharEncoded = CompilationTarget.encodeString(string.value)[0]
val firstCharEncoded = CompilationTarget.encodeString(string.value, string.altEncoding)[0]
functionCallStatement.args.clear()
functionCallStatement.args.add(NumericLiteralValue.optimalInteger(firstCharEncoded.toInt(), functionCallStatement.position))
functionCallStatement.target = IdentifierReference(listOf("c64", "CHROUT"), functionCallStatement.target.position)
@ -188,7 +188,7 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
optimizationsDone++
return functionCallStatement
} else if(string.value.length==2) {
val firstTwoCharsEncoded = CompilationTarget.encodeString(string.value.take(2))
val firstTwoCharsEncoded = CompilationTarget.encodeString(string.value.take(2), string.altEncoding)
val scope = AnonymousScope(mutableListOf(), functionCallStatement.position)
scope.statements.add(FunctionCallStatement(IdentifierReference(listOf("c64", "CHROUT"), functionCallStatement.target.position),
mutableListOf(NumericLiteralValue.optimalInteger(firstTwoCharsEncoded[0].toInt(), functionCallStatement.position)),

View File

@ -570,10 +570,10 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
}
class RuntimeValueString(val str: String, val heapId: Int?): RuntimeValueBase(DataType.STR) {
class RuntimeValueString(val str: String, val altEncoding: Boolean, val heapId: Int?): RuntimeValueBase(DataType.STR) {
companion object {
fun fromLv(string: StringLiteralValue): RuntimeValueString {
return RuntimeValueString(string.value, string.heapId)
return RuntimeValueString(string.value, string.altEncoding, string.heapId)
}
}

View File

@ -575,7 +575,7 @@ class AstVm(val program: Program, compilationTarget: String) {
DataType.UWORD -> mem.setUWord(address, (value as RuntimeValueNumeric).wordval!!)
DataType.WORD -> mem.setSWord(address, (value as RuntimeValueNumeric).wordval!!)
DataType.FLOAT -> mem.setFloat(address, (value as RuntimeValueNumeric).floatval!!)
DataType.STR -> mem.setString(address, (value as RuntimeValueString).str)
DataType.STR -> mem.setString(address, (value as RuntimeValueString).str, value.altEncoding)
else -> throw VmExecutionException("weird memaddress type $decl")
}
} else
@ -626,7 +626,7 @@ class AstVm(val program: Program, compilationTarget: String) {
val ident = contextStmt.definingScope().lookup(targetArrayIndexed.identifier.nameInSource, contextStmt) as? VarDecl
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
val identScope = ident.definingScope()
runtimeVariables.set(identScope, ident.name, RuntimeValueString(newstr, array.heapId))
runtimeVariables.set(identScope, ident.name, RuntimeValueString(newstr, false, array.heapId))
}
}
else {

View File

@ -124,7 +124,7 @@ fun evaluate(expr: Expression, ctx: EvalContext): RuntimeValueBase {
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, ctx.mem.getUWord(address))
DataType.WORD -> RuntimeValueNumeric(DataType.WORD, ctx.mem.getSWord(address))
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, ctx.mem.getFloat(address))
DataType.STR -> RuntimeValueString(ctx.mem.getString(address), null)
DataType.STR -> RuntimeValueString(ctx.mem.getString(address, false), false, null)
else -> throw VmExecutionException("unexpected datatype $variable")
}
}

View File

@ -93,14 +93,14 @@ class Memory(private val readObserver: (address: Int, value: Short) -> Short,
getUByte(address + 3), getUByte(address + 4)).toDouble()
}
fun setString(address: Int, str: String) {
val encoded = CompilationTarget.encodeString(str)
fun setString(address: Int, str: String, altEncoding: Boolean) {
val encoded = CompilationTarget.encodeString(str, altEncoding)
var addr = address
for (c in encoded) setUByte(addr++, c)
setUByte(addr, 0)
}
fun getString(strAddress: Int): String {
fun getString(strAddress: Int, altEncoding: Boolean): String {
val encoded = mutableListOf<Short>()
var addr = strAddress
while(true) {
@ -108,7 +108,7 @@ class Memory(private val readObserver: (address: Int, value: Short) -> Short,
if(byte==0.toShort()) break
encoded.add(byte)
}
return CompilationTarget.decodeString(encoded)
return CompilationTarget.decodeString(encoded, altEncoding)
}
fun clear() {

View File

@ -83,8 +83,11 @@ class TestParserNumericLiteralValue {
@Test
fun testEqualsRef() {
assertEquals(StringLiteralValue("hello", dummyPos), StringLiteralValue("hello", dummyPos))
assertNotEquals(StringLiteralValue("hello", dummyPos), StringLiteralValue("bye", dummyPos))
assertEquals(StringLiteralValue("hello", false, dummyPos), StringLiteralValue("hello", false, dummyPos))
assertNotEquals(StringLiteralValue("hello", false, dummyPos), StringLiteralValue("bye", false, dummyPos))
assertEquals(StringLiteralValue("hello", true, dummyPos), StringLiteralValue("hello", true, dummyPos))
assertNotEquals(StringLiteralValue("hello", true, dummyPos), StringLiteralValue("bye", true, dummyPos))
assertNotEquals(StringLiteralValue("hello", true, dummyPos), StringLiteralValue("hello", false, dummyPos))
val lvOne = NumericLiteralValue(DataType.UBYTE, 1, dummyPos)
val lvTwo = NumericLiteralValue(DataType.UBYTE, 2, dummyPos)

View File

@ -369,8 +369,8 @@ class TestPetscii {
assertTrue(ten <= ten)
assertFalse(ten < ten)
val abc = StringLiteralValue("abc", Position("", 0, 0, 0))
val abd = StringLiteralValue("abd", Position("", 0, 0, 0))
val abc = StringLiteralValue("abc", false, Position("", 0, 0, 0))
val abd = StringLiteralValue("abd", false, Position("", 0, 0, 0))
assertEquals(abc, abc)
assertTrue(abc!=abd)
assertFalse(abc!=abc)

View File

@ -188,9 +188,11 @@ Values will usually be part of an expression or assignment statement::
12345 ; integer number
$aa43 ; hex integer number
%100101 ; binary integer number (% is also remainder operator so be careful)
"Hi, I am a string" ; text string
'a' ; petscii value (byte) for the letter a
-33.456e52 ; floating point number
"Hi, I am a string" ; text string, encoded with compiler target default encoding
'a' ; byte value (ubyte) for the letter a
@"Alternate" ; text string, encoded with alternate encoding
@'a' ; byte value of the letter a, using alternate encoding
byte counter = 42 ; variable of size 8 bits, with initial value 42
@ -271,8 +273,12 @@ Strings
Strings are a sequence of characters enclosed in ``"`` quotes. The length is limited to 255 characters.
They're stored and treated much the same as a byte array,
but they have some special properties because they are considered to be *text*.
Strings in your source code files will be encoded (translated from ASCII/UTF-8) into the byte-encoding
that is used on the target platform. For the C-64, this is CBM PETSCII.
Strings in your source code files will be encoded (translated from ASCII/UTF-8) into bytes via the
default encoding that is used on the target platform. For the C-64, this is CBM PETSCII.
Alternate-encoding strings (prefixed with ``@``) will be encoded via the alternate encoding for the
platform (if defined). For the C-64, that is SCREEN CODES (also known as POKE codes).
This @-prefix can also be used for character byte values.
You can concatenate two string literals using '+' (not very useful though) or repeat
a string literal a given number of times using '*'::

View File

@ -230,6 +230,7 @@ Various examples::
byte age = 2018 - 1974
float wallet = 55.25
str name = "my name is Irmen"
str name = @"my name is Irmen" ; string with alternative byte encoding
uword address = &counter
byte[] values = [11, 22, 33, 44, 55]
byte[5] values ; array of 5 bytes, initially set to zero
@ -248,7 +249,7 @@ Prog8 supports the following data types:
type identifier type storage size example var declaration and literal value
=============== ======================= ================= =========================================
``byte`` signed byte 1 byte = 8 bits ``byte myvar = -22``
``ubyte`` unsigned byte 1 byte = 8 bits ``ubyte myvar = $8f``
``ubyte`` unsigned byte 1 byte = 8 bits ``ubyte myvar = $8f``, ``ubyte c = 'a'``, ``ubyte c2 = @'a'``
-- boolean 1 byte = 8 bits ``byte myvar = true`` or ``byte myvar == false``
The true and false are actually just aliases
for the byte values 1 and 0.

View File

@ -9,19 +9,29 @@ main {
c64.VMCSB |= 2 ; switch to lowercase charset
str s1 = "HELLO hello 1234 @[/]\n" ; regular strings have default encoding (petscii on c64)
str s2 = @"HELLO hello 1234 @[/]\n" ; TODO @-strings for alternate encoding (screencode on c64)
str s1 = "HELLO hello 1234 @[/]" ; regular strings have default encoding (petscii on c64)
str s2 = @"HELLO hello 1234 @[/]" ; alternative encoding (screencodes on c64)
c64scr.print("\n\n\n\nString output via print:\n")
c64scr.print("petscii-str: ")
c64scr.print(s1)
c64scr.print("\nscrcode-str: ")
c64scr.print(s2)
c64scr.print("\nThe top two screen lines are set via screencodes.\n")
c64scr.print("\n\nThe top two screen lines are set via screencodes.\n")
ubyte i
for i in 0 to len(s1)-1
@($0400+i) = s1[i]
for i in 0 to len(s2)-1
@($0400+40+i) = s2[i]
ubyte c1 = 'z'
ubyte c2 = @'z'
c64scr.print("\npetscii z=")
c64scr.print_ub(c1)
c64scr.print("\nscreencode z=")
c64scr.print_ub(c2)
}
}

View File

@ -25,6 +25,7 @@ DEC_INTEGER : ('0'..'9') | (('1'..'9')('0'..'9')+);
HEX_INTEGER : '$' (('a'..'f') | ('A'..'F') | ('0'..'9'))+ ;
BIN_INTEGER : '%' ('0' | '1')+ ;
ADDRESS_OF: '&';
ALT_STRING_ENCODING: '@';
FLOAT_NUMBER : FNUMBER (('E'|'e') ('+' | '-')? FNUMBER)? ; // sign comes later from unary expression
fragment FNUMBER : ('0' .. '9') + ('.' ('0' .. '9') +)? ;
@ -219,9 +220,9 @@ arrayliteral : '[' EOL? expression (',' EOL? expression)* EOL? ']' ; // y
structliteral : '{' EOL? expression (',' EOL? expression)* EOL? '}' ; // you can split the values over several lines
stringliteral : STRING ;
stringliteral : ALT_STRING_ENCODING? STRING ;
charliteral : SINGLECHAR ;
charliteral : ALT_STRING_ENCODING? SINGLECHAR ;
floatliteral : FLOAT_NUMBER ;

View File

@ -34,10 +34,10 @@ public class prog8Lexer extends Lexer {
T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94,
T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101,
T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107,
T__107=108, T__108=109, T__109=110, LINECOMMENT=111, COMMENT=112, WS=113,
EOL=114, VOID=115, NAME=116, DEC_INTEGER=117, HEX_INTEGER=118, BIN_INTEGER=119,
ADDRESS_OF=120, FLOAT_NUMBER=121, STRING=122, INLINEASMBLOCK=123, SINGLECHAR=124,
ZEROPAGE=125, ARRAYSIG=126;
T__107=108, T__108=109, LINECOMMENT=110, COMMENT=111, WS=112, EOL=113,
VOID=114, NAME=115, DEC_INTEGER=116, HEX_INTEGER=117, BIN_INTEGER=118,
ADDRESS_OF=119, ALT_STRING_ENCODING=120, FLOAT_NUMBER=121, STRING=122,
INLINEASMBLOCK=123, SINGLECHAR=124, ZEROPAGE=125, ARRAYSIG=126;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
@ -61,10 +61,10 @@ public class prog8Lexer extends Lexer {
"T__81", "T__82", "T__83", "T__84", "T__85", "T__86", "T__87", "T__88",
"T__89", "T__90", "T__91", "T__92", "T__93", "T__94", "T__95", "T__96",
"T__97", "T__98", "T__99", "T__100", "T__101", "T__102", "T__103", "T__104",
"T__105", "T__106", "T__107", "T__108", "T__109", "LINECOMMENT", "COMMENT",
"WS", "EOL", "VOID", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER",
"ADDRESS_OF", "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ", "STRING",
"INLINEASMBLOCK", "SINGLECHAR", "ZEROPAGE", "ARRAYSIG"
"T__105", "T__106", "T__107", "T__108", "LINECOMMENT", "COMMENT", "WS",
"EOL", "VOID", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "ADDRESS_OF",
"ALT_STRING_ENCODING", "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ",
"STRING", "INLINEASMBLOCK", "SINGLECHAR", "ZEROPAGE", "ARRAYSIG"
};
}
public static final String[] ruleNames = makeRuleNames();
@ -79,13 +79,13 @@ public class prog8Lexer extends Lexer {
"'>>='", "'++'", "'--'", "'+'", "'-'", "'~'", "'**'", "'*'", "'/'", "'%'",
"'<<'", "'>>'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='", "'^'",
"'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'", "'('", "')'",
"'as'", "'@'", "'return'", "'break'", "'continue'", "'.'", "'A'", "'X'",
"'Y'", "'AX'", "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'",
"'true'", "'false'", "'%asm'", "'sub'", "'->'", "'asmsub'", "'romsub'",
"'stack'", "'clobbers'", "'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'",
"'if_z'", "'if_ne'", "'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", "'if_neg'",
"'if_vs'", "'if_vc'", "'for'", "'in'", "'while'", "'repeat'", "'until'",
"'when'", null, null, null, null, "'void'", null, null, null, null, "'&'",
"'as'", "'return'", "'break'", "'continue'", "'.'", "'A'", "'X'", "'Y'",
"'AX'", "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'",
"'false'", "'%asm'", "'sub'", "'->'", "'asmsub'", "'romsub'", "'stack'",
"'clobbers'", "'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'", "'if_z'",
"'if_ne'", "'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'",
"'if_vc'", "'for'", "'in'", "'while'", "'repeat'", "'until'", "'when'",
null, null, null, null, "'void'", null, null, null, null, "'&'", "'@'",
null, null, null, null, "'@zp'", "'[]'"
};
}
@ -101,8 +101,8 @@ public class prog8Lexer extends Lexer {
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, "LINECOMMENT", "COMMENT", "WS", "EOL", "VOID", "NAME",
"DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "ADDRESS_OF", "FLOAT_NUMBER",
null, null, "LINECOMMENT", "COMMENT", "WS", "EOL", "VOID", "NAME", "DEC_INTEGER",
"HEX_INTEGER", "BIN_INTEGER", "ADDRESS_OF", "ALT_STRING_ENCODING", "FLOAT_NUMBER",
"STRING", "INLINEASMBLOCK", "SINGLECHAR", "ZEROPAGE", "ARRAYSIG"
};
}
@ -243,50 +243,50 @@ public class prog8Lexer extends Lexer {
")\3*\3*\3+\3+\3,\3,\3,\3-\3-\3.\3.\3/\3/\3\60\3\60\3\60\3\61\3\61\3\61"+
"\3\62\3\62\3\63\3\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\67"+
"\3\67\3\67\38\38\39\39\3:\3:\3:\3;\3;\3;\3;\3;\3<\3<\3<\3<\3=\3=\3=\3"+
">\3>\3>\3>\3?\3?\3?\3?\3@\3@\3A\3A\3B\3B\3B\3C\3C\3D\3D\3D\3D\3D\3D\3"+
"D\3E\3E\3E\3E\3E\3E\3F\3F\3F\3F\3F\3F\3F\3F\3F\3G\3G\3H\3H\3I\3I\3J\3"+
"J\3K\3K\3K\3L\3L\3L\3M\3M\3M\3N\3N\3N\3O\3O\3O\3P\3P\3P\3Q\3Q\3Q\3R\3"+
"R\3R\3S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3V\3V\3V\3V\3W\3"+
"W\3W\3X\3X\3X\3X\3X\3X\3X\3Y\3Y\3Y\3Y\3Y\3Y\3Y\3Z\3Z\3Z\3Z\3Z\3Z\3[\3"+
"[\3[\3[\3[\3[\3[\3[\3[\3\\\3\\\3\\\3]\3]\3]\3]\3]\3^\3^\3^\3^\3^\3^\3"+
"_\3_\3_\3_\3_\3_\3`\3`\3`\3`\3`\3`\3a\3a\3a\3a\3a\3b\3b\3b\3b\3b\3b\3"+
"c\3c\3c\3c\3c\3c\3d\3d\3d\3d\3d\3d\3e\3e\3e\3e\3e\3e\3e\3f\3f\3f\3f\3"+
"f\3f\3g\3g\3g\3g\3g\3g\3g\3h\3h\3h\3h\3h\3h\3i\3i\3i\3i\3i\3i\3j\3j\3"+
"j\3j\3k\3k\3k\3l\3l\3l\3l\3l\3l\3m\3m\3m\3m\3m\3m\3m\3n\3n\3n\3n\3n\3"+
"n\3o\3o\3o\3o\3o\3p\3p\7p\u02f7\np\fp\16p\u02fa\13p\3p\3p\3p\3p\3q\3q"+
"\7q\u0302\nq\fq\16q\u0305\13q\3q\3q\3r\3r\3r\3r\3s\6s\u030e\ns\rs\16s"+
"\u030f\3t\3t\3t\3t\3t\3u\3u\7u\u0319\nu\fu\16u\u031c\13u\3v\3v\3v\6v\u0321"+
"\nv\rv\16v\u0322\5v\u0325\nv\3w\3w\6w\u0329\nw\rw\16w\u032a\3x\3x\6x\u032f"+
"\nx\rx\16x\u0330\3y\3y\3z\3z\3z\5z\u0338\nz\3z\5z\u033b\nz\3{\6{\u033e"+
"\n{\r{\16{\u033f\3{\3{\6{\u0344\n{\r{\16{\u0345\5{\u0348\n{\3|\3|\3|\3"+
"|\5|\u034e\n|\3}\3}\3}\7}\u0353\n}\f}\16}\u0356\13}\3}\3}\3}\3~\3~\3~"+
"\3~\6~\u035f\n~\r~\16~\u0360\3~\3~\3~\3~\3~\3\177\3\177\3\177\5\177\u036b"+
"\n\177\3\177\3\177\3\177\3\u0080\3\u0080\3\u0080\3\u0080\3\u0081\3\u0081"+
"\3\u0081\3\u0360\2\u0082\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f"+
"\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63"+
"\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62"+
"c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087"+
"E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009b"+
"O\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00af"+
"Y\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3"+
"c\u00c5d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7"+
"m\u00d9n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9v\u00eb"+
"w\u00edx\u00efy\u00f1z\u00f3{\u00f5\2\u00f7\2\u00f9|\u00fb}\u00fd~\u00ff"+
"\177\u0101\u0080\3\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2C\\aac|\6\2\62;"+
"C\\aac|\5\2\62;CHch\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2\u0385\2\3\3\2"+
"\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17"+
"\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2"+
"\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3"+
"\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3"+
"\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2"+
"=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3"+
"\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2"+
"\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2"+
"c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3"+
"\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2"+
"\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3"+
"\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2"+
"\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097"+
">\3>\3>\3>\3?\3?\3?\3?\3@\3@\3A\3A\3B\3B\3B\3C\3C\3C\3C\3C\3C\3C\3D\3"+
"D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F\3G\3G\3H\3H\3I\3I\3J\3"+
"J\3J\3K\3K\3K\3L\3L\3L\3M\3M\3M\3N\3N\3N\3O\3O\3O\3P\3P\3P\3Q\3Q\3Q\3"+
"R\3R\3R\3R\3R\3S\3S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3U\3U\3U\3U\3V\3V\3V\3"+
"W\3W\3W\3W\3W\3W\3W\3X\3X\3X\3X\3X\3X\3X\3Y\3Y\3Y\3Y\3Y\3Y\3Z\3Z\3Z\3"+
"Z\3Z\3Z\3Z\3Z\3Z\3[\3[\3[\3\\\3\\\3\\\3\\\3\\\3]\3]\3]\3]\3]\3]\3^\3^"+
"\3^\3^\3^\3^\3_\3_\3_\3_\3_\3_\3`\3`\3`\3`\3`\3a\3a\3a\3a\3a\3a\3b\3b"+
"\3b\3b\3b\3b\3c\3c\3c\3c\3c\3c\3d\3d\3d\3d\3d\3d\3d\3e\3e\3e\3e\3e\3e"+
"\3f\3f\3f\3f\3f\3f\3f\3g\3g\3g\3g\3g\3g\3h\3h\3h\3h\3h\3h\3i\3i\3i\3i"+
"\3j\3j\3j\3k\3k\3k\3k\3k\3k\3l\3l\3l\3l\3l\3l\3l\3m\3m\3m\3m\3m\3m\3n"+
"\3n\3n\3n\3n\3o\3o\7o\u02f5\no\fo\16o\u02f8\13o\3o\3o\3o\3o\3p\3p\7p\u0300"+
"\np\fp\16p\u0303\13p\3p\3p\3q\3q\3q\3q\3r\6r\u030c\nr\rr\16r\u030d\3s"+
"\3s\3s\3s\3s\3t\3t\7t\u0317\nt\ft\16t\u031a\13t\3u\3u\3u\6u\u031f\nu\r"+
"u\16u\u0320\5u\u0323\nu\3v\3v\6v\u0327\nv\rv\16v\u0328\3w\3w\6w\u032d"+
"\nw\rw\16w\u032e\3x\3x\3y\3y\3z\3z\3z\5z\u0338\nz\3z\5z\u033b\nz\3{\6"+
"{\u033e\n{\r{\16{\u033f\3{\3{\6{\u0344\n{\r{\16{\u0345\5{\u0348\n{\3|"+
"\3|\3|\3|\5|\u034e\n|\3}\3}\3}\7}\u0353\n}\f}\16}\u0356\13}\3}\3}\3}\3"+
"~\3~\3~\3~\6~\u035f\n~\r~\16~\u0360\3~\3~\3~\3~\3~\3\177\3\177\3\177\5"+
"\177\u036b\n\177\3\177\3\177\3\177\3\u0080\3\u0080\3\u0080\3\u0080\3\u0081"+
"\3\u0081\3\u0081\3\u0360\2\u0082\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23"+
"\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31"+
"\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60"+
"_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085"+
"D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099"+
"N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00ad"+
"X\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1"+
"b\u00c3c\u00c5d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5"+
"l\u00d7m\u00d9n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9"+
"v\u00ebw\u00edx\u00efy\u00f1z\u00f3{\u00f5\2\u00f7\2\u00f9|\u00fb}\u00fd"+
"~\u00ff\177\u0101\u0080\3\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2C\\aac|\6"+
"\2\62;C\\aac|\5\2\62;CHch\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2\u0385\2"+
"\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2"+
"\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2"+
"\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2"+
"\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2"+
"\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2"+
"\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2"+
"\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U"+
"\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2"+
"\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2"+
"\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{"+
"\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085"+
"\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2"+
"\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097"+
"\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2"+
"\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9"+
"\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2"+
@ -313,22 +313,22 @@ public class prog8Lexer extends Lexer {
"\2\2k\u01f0\3\2\2\2m\u01f3\3\2\2\2o\u01f6\3\2\2\2q\u01f8\3\2\2\2s\u01fa"+
"\3\2\2\2u\u01fd\3\2\2\2w\u0202\3\2\2\2y\u0206\3\2\2\2{\u0209\3\2\2\2}"+
"\u020d\3\2\2\2\177\u0211\3\2\2\2\u0081\u0213\3\2\2\2\u0083\u0215\3\2\2"+
"\2\u0085\u0218\3\2\2\2\u0087\u021a\3\2\2\2\u0089\u0221\3\2\2\2\u008b\u0227"+
"\2\u0085\u0218\3\2\2\2\u0087\u021f\3\2\2\2\u0089\u0225\3\2\2\2\u008b\u022e"+
"\3\2\2\2\u008d\u0230\3\2\2\2\u008f\u0232\3\2\2\2\u0091\u0234\3\2\2\2\u0093"+
"\u0236\3\2\2\2\u0095\u0238\3\2\2\2\u0097\u023b\3\2\2\2\u0099\u023e\3\2"+
"\2\2\u009b\u0241\3\2\2\2\u009d\u0244\3\2\2\2\u009f\u0247\3\2\2\2\u00a1"+
"\u024a\3\2\2\2\u00a3\u024d\3\2\2\2\u00a5\u0250\3\2\2\2\u00a7\u0255\3\2"+
"\2\2\u00a9\u025b\3\2\2\2\u00ab\u0260\3\2\2\2\u00ad\u0264\3\2\2\2\u00af"+
"\u0267\3\2\2\2\u00b1\u026e\3\2\2\2\u00b3\u0275\3\2\2\2\u00b5\u027b\3\2"+
"\2\2\u00b7\u0284\3\2\2\2\u00b9\u0287\3\2\2\2\u00bb\u028c\3\2\2\2\u00bd"+
"\u0292\3\2\2\2\u00bf\u0298\3\2\2\2\u00c1\u029e\3\2\2\2\u00c3\u02a3\3\2"+
"\2\2\u00c5\u02a9\3\2\2\2\u00c7\u02af\3\2\2\2\u00c9\u02b5\3\2\2\2\u00cb"+
"\u02bc\3\2\2\2\u00cd\u02c2\3\2\2\2\u00cf\u02c9\3\2\2\2\u00d1\u02cf\3\2"+
"\2\2\u00d3\u02d5\3\2\2\2\u00d5\u02d9\3\2\2\2\u00d7\u02dc\3\2\2\2\u00d9"+
"\u02e2\3\2\2\2\u00db\u02e9\3\2\2\2\u00dd\u02ef\3\2\2\2\u00df\u02f4\3\2"+
"\2\2\u00e1\u02ff\3\2\2\2\u00e3\u0308\3\2\2\2\u00e5\u030d\3\2\2\2\u00e7"+
"\u0311\3\2\2\2\u00e9\u0316\3\2\2\2\u00eb\u0324\3\2\2\2\u00ed\u0326\3\2"+
"\2\2\u00ef\u032c\3\2\2\2\u00f1\u0332\3\2\2\2\u00f3\u0334\3\2\2\2\u00f5"+
"\u0236\3\2\2\2\u0095\u0239\3\2\2\2\u0097\u023c\3\2\2\2\u0099\u023f\3\2"+
"\2\2\u009b\u0242\3\2\2\2\u009d\u0245\3\2\2\2\u009f\u0248\3\2\2\2\u00a1"+
"\u024b\3\2\2\2\u00a3\u024e\3\2\2\2\u00a5\u0253\3\2\2\2\u00a7\u0259\3\2"+
"\2\2\u00a9\u025e\3\2\2\2\u00ab\u0262\3\2\2\2\u00ad\u0265\3\2\2\2\u00af"+
"\u026c\3\2\2\2\u00b1\u0273\3\2\2\2\u00b3\u0279\3\2\2\2\u00b5\u0282\3\2"+
"\2\2\u00b7\u0285\3\2\2\2\u00b9\u028a\3\2\2\2\u00bb\u0290\3\2\2\2\u00bd"+
"\u0296\3\2\2\2\u00bf\u029c\3\2\2\2\u00c1\u02a1\3\2\2\2\u00c3\u02a7\3\2"+
"\2\2\u00c5\u02ad\3\2\2\2\u00c7\u02b3\3\2\2\2\u00c9\u02ba\3\2\2\2\u00cb"+
"\u02c0\3\2\2\2\u00cd\u02c7\3\2\2\2\u00cf\u02cd\3\2\2\2\u00d1\u02d3\3\2"+
"\2\2\u00d3\u02d7\3\2\2\2\u00d5\u02da\3\2\2\2\u00d7\u02e0\3\2\2\2\u00d9"+
"\u02e7\3\2\2\2\u00db\u02ed\3\2\2\2\u00dd\u02f2\3\2\2\2\u00df\u02fd\3\2"+
"\2\2\u00e1\u0306\3\2\2\2\u00e3\u030b\3\2\2\2\u00e5\u030f\3\2\2\2\u00e7"+
"\u0314\3\2\2\2\u00e9\u0322\3\2\2\2\u00eb\u0324\3\2\2\2\u00ed\u032a\3\2"+
"\2\2\u00ef\u0330\3\2\2\2\u00f1\u0332\3\2\2\2\u00f3\u0334\3\2\2\2\u00f5"+
"\u033d\3\2\2\2\u00f7\u034d\3\2\2\2\u00f9\u034f\3\2\2\2\u00fb\u035a\3\2"+
"\2\2\u00fd\u0367\3\2\2\2\u00ff\u036f\3\2\2\2\u0101\u0373\3\2\2\2\u0103"+
"\u0104\7<\2\2\u0104\4\3\2\2\2\u0105\u0106\7i\2\2\u0106\u0107\7q\2\2\u0107"+
@ -402,87 +402,87 @@ public class prog8Lexer extends Lexer {
"\7t\2\2\u020c|\3\2\2\2\u020d\u020e\7p\2\2\u020e\u020f\7q\2\2\u020f\u0210"+
"\7v\2\2\u0210~\3\2\2\2\u0211\u0212\7*\2\2\u0212\u0080\3\2\2\2\u0213\u0214"+
"\7+\2\2\u0214\u0082\3\2\2\2\u0215\u0216\7c\2\2\u0216\u0217\7u\2\2\u0217"+
"\u0084\3\2\2\2\u0218\u0219\7B\2\2\u0219\u0086\3\2\2\2\u021a\u021b\7t\2"+
"\2\u021b\u021c\7g\2\2\u021c\u021d\7v\2\2\u021d\u021e\7w\2\2\u021e\u021f"+
"\7t\2\2\u021f\u0220\7p\2\2\u0220\u0088\3\2\2\2\u0221\u0222\7d\2\2\u0222"+
"\u0223\7t\2\2\u0223\u0224\7g\2\2\u0224\u0225\7c\2\2\u0225\u0226\7m\2\2"+
"\u0226\u008a\3\2\2\2\u0227\u0228\7e\2\2\u0228\u0229\7q\2\2\u0229\u022a"+
"\7p\2\2\u022a\u022b\7v\2\2\u022b\u022c\7k\2\2\u022c\u022d\7p\2\2\u022d"+
"\u022e\7w\2\2\u022e\u022f\7g\2\2\u022f\u008c\3\2\2\2\u0230\u0231\7\60"+
"\2\2\u0231\u008e\3\2\2\2\u0232\u0233\7C\2\2\u0233\u0090\3\2\2\2\u0234"+
"\u0235\7Z\2\2\u0235\u0092\3\2\2\2\u0236\u0237\7[\2\2\u0237\u0094\3\2\2"+
"\2\u0238\u0239\7C\2\2\u0239\u023a\7Z\2\2\u023a\u0096\3\2\2\2\u023b\u023c"+
"\7C\2\2\u023c\u023d\7[\2\2\u023d\u0098\3\2\2\2\u023e\u023f\7Z\2\2\u023f"+
"\u0240\7[\2\2\u0240\u009a\3\2\2\2\u0241\u0242\7R\2\2\u0242\u0243\7e\2"+
"\2\u0243\u009c\3\2\2\2\u0244\u0245\7R\2\2\u0245\u0246\7|\2\2\u0246\u009e"+
"\3\2\2\2\u0247\u0248\7R\2\2\u0248\u0249\7p\2\2\u0249\u00a0\3\2\2\2\u024a"+
"\u024b\7R\2\2\u024b\u024c\7x\2\2\u024c\u00a2\3\2\2\2\u024d\u024e\7\60"+
"\2\2\u024e\u024f\7y\2\2\u024f\u00a4\3\2\2\2\u0250\u0251\7v\2\2\u0251\u0252"+
"\7t\2\2\u0252\u0253\7w\2\2\u0253\u0254\7g\2\2\u0254\u00a6\3\2\2\2\u0255"+
"\u0256\7h\2\2\u0256\u0257\7c\2\2\u0257\u0258\7n\2\2\u0258\u0259\7u\2\2"+
"\u0259\u025a\7g\2\2\u025a\u00a8\3\2\2\2\u025b\u025c\7\'\2\2\u025c\u025d"+
"\7c\2\2\u025d\u025e\7u\2\2\u025e\u025f\7o\2\2\u025f\u00aa\3\2\2\2\u0260"+
"\u0261\7u\2\2\u0261\u0262\7w\2\2\u0262\u0263\7d\2\2\u0263\u00ac\3\2\2"+
"\2\u0264\u0265\7/\2\2\u0265\u0266\7@\2\2\u0266\u00ae\3\2\2\2\u0267\u0268"+
"\7c\2\2\u0268\u0269\7u\2\2\u0269\u026a\7o\2\2\u026a\u026b\7u\2\2\u026b"+
"\u026c\7w\2\2\u026c\u026d\7d\2\2\u026d\u00b0\3\2\2\2\u026e\u026f\7t\2"+
"\2\u026f\u0270\7q\2\2\u0270\u0271\7o\2\2\u0271\u0272\7u\2\2\u0272\u0273"+
"\7w\2\2\u0273\u0274\7d\2\2\u0274\u00b2\3\2\2\2\u0275\u0276\7u\2\2\u0276"+
"\u0277\7v\2\2\u0277\u0278\7c\2\2\u0278\u0279\7e\2\2\u0279\u027a\7m\2\2"+
"\u027a\u00b4\3\2\2\2\u027b\u027c\7e\2\2\u027c\u027d\7n\2\2\u027d\u027e"+
"\7q\2\2\u027e\u027f\7d\2\2\u027f\u0280\7d\2\2\u0280\u0281\7g\2\2\u0281"+
"\u0282\7t\2\2\u0282\u0283\7u\2\2\u0283\u00b6\3\2\2\2\u0284\u0285\7k\2"+
"\2\u0285\u0286\7h\2\2\u0286\u00b8\3\2\2\2\u0287\u0288\7g\2\2\u0288\u0289"+
"\7n\2\2\u0289\u028a\7u\2\2\u028a\u028b\7g\2\2\u028b\u00ba\3\2\2\2\u028c"+
"\u028d\7k\2\2\u028d\u028e\7h\2\2\u028e\u028f\7a\2\2\u028f\u0290\7e\2\2"+
"\u0290\u0291\7u\2\2\u0291\u00bc\3\2\2\2\u0292\u0293\7k\2\2\u0293\u0294"+
"\7h\2\2\u0294\u0295\7a\2\2\u0295\u0296\7e\2\2\u0296\u0297\7e\2\2\u0297"+
"\u00be\3\2\2\2\u0298\u0299\7k\2\2\u0299\u029a\7h\2\2\u029a\u029b\7a\2"+
"\2\u029b\u029c\7g\2\2\u029c\u029d\7s\2\2\u029d\u00c0\3\2\2\2\u029e\u029f"+
"\7k\2\2\u029f\u02a0\7h\2\2\u02a0\u02a1\7a\2\2\u02a1\u02a2\7|\2\2\u02a2"+
"\u00c2\3\2\2\2\u02a3\u02a4\7k\2\2\u02a4\u02a5\7h\2\2\u02a5\u02a6\7a\2"+
"\2\u02a6\u02a7\7p\2\2\u02a7\u02a8\7g\2\2\u02a8\u00c4\3\2\2\2\u02a9\u02aa"+
"\7k\2\2\u02aa\u02ab\7h\2\2\u02ab\u02ac\7a\2\2\u02ac\u02ad\7p\2\2\u02ad"+
"\u02ae\7|\2\2\u02ae\u00c6\3\2\2\2\u02af\u02b0\7k\2\2\u02b0\u02b1\7h\2"+
"\2\u02b1\u02b2\7a\2\2\u02b2\u02b3\7r\2\2\u02b3\u02b4\7n\2\2\u02b4\u00c8"+
"\3\2\2\2\u02b5\u02b6\7k\2\2\u02b6\u02b7\7h\2\2\u02b7\u02b8\7a\2\2\u02b8"+
"\u02b9\7r\2\2\u02b9\u02ba\7q\2\2\u02ba\u02bb\7u\2\2\u02bb\u00ca\3\2\2"+
"\2\u02bc\u02bd\7k\2\2\u02bd\u02be\7h\2\2\u02be\u02bf\7a\2\2\u02bf\u02c0"+
"\7o\2\2\u02c0\u02c1\7k\2\2\u02c1\u00cc\3\2\2\2\u02c2\u02c3\7k\2\2\u02c3"+
"\u02c4\7h\2\2\u02c4\u02c5\7a\2\2\u02c5\u02c6\7p\2\2\u02c6\u02c7\7g\2\2"+
"\u02c7\u02c8\7i\2\2\u02c8\u00ce\3\2\2\2\u02c9\u02ca\7k\2\2\u02ca\u02cb"+
"\7h\2\2\u02cb\u02cc\7a\2\2\u02cc\u02cd\7x\2\2\u02cd\u02ce\7u\2\2\u02ce"+
"\u00d0\3\2\2\2\u02cf\u02d0\7k\2\2\u02d0\u02d1\7h\2\2\u02d1\u02d2\7a\2"+
"\2\u02d2\u02d3\7x\2\2\u02d3\u02d4\7e\2\2\u02d4\u00d2\3\2\2\2\u02d5\u02d6"+
"\7h\2\2\u02d6\u02d7\7q\2\2\u02d7\u02d8\7t\2\2\u02d8\u00d4\3\2\2\2\u02d9"+
"\u02da\7k\2\2\u02da\u02db\7p\2\2\u02db\u00d6\3\2\2\2\u02dc\u02dd\7y\2"+
"\2\u02dd\u02de\7j\2\2\u02de\u02df\7k\2\2\u02df\u02e0\7n\2\2\u02e0\u02e1"+
"\7g\2\2\u02e1\u00d8\3\2\2\2\u02e2\u02e3\7t\2\2\u02e3\u02e4\7g\2\2\u02e4"+
"\u02e5\7r\2\2\u02e5\u02e6\7g\2\2\u02e6\u02e7\7c\2\2\u02e7\u02e8\7v\2\2"+
"\u02e8\u00da\3\2\2\2\u02e9\u02ea\7w\2\2\u02ea\u02eb\7p\2\2\u02eb\u02ec"+
"\7v\2\2\u02ec\u02ed\7k\2\2\u02ed\u02ee\7n\2\2\u02ee\u00dc\3\2\2\2\u02ef"+
"\u02f0\7y\2\2\u02f0\u02f1\7j\2\2\u02f1\u02f2\7g\2\2\u02f2\u02f3\7p\2\2"+
"\u02f3\u00de\3\2\2\2\u02f4\u02f8\t\2\2\2\u02f5\u02f7\t\3\2\2\u02f6\u02f5"+
"\3\2\2\2\u02f7\u02fa\3\2\2\2\u02f8\u02f6\3\2\2\2\u02f8\u02f9\3\2\2\2\u02f9"+
"\u02fb\3\2\2\2\u02fa\u02f8\3\2\2\2\u02fb\u02fc\5\u00e1q\2\u02fc\u02fd"+
"\3\2\2\2\u02fd\u02fe\bp\2\2\u02fe\u00e0\3\2\2\2\u02ff\u0303\7=\2\2\u0300"+
"\u0302\n\2\2\2\u0301\u0300\3\2\2\2\u0302\u0305\3\2\2\2\u0303\u0301\3\2"+
"\2\2\u0303\u0304\3\2\2\2\u0304\u0306\3\2\2\2\u0305\u0303\3\2\2\2\u0306"+
"\u0307\bq\2\2\u0307\u00e2\3\2\2\2\u0308\u0309\t\3\2\2\u0309\u030a\3\2"+
"\2\2\u030a\u030b\br\3\2\u030b\u00e4\3\2\2\2\u030c\u030e\t\2\2\2\u030d"+
"\u030c\3\2\2\2\u030e\u030f\3\2\2\2\u030f\u030d\3\2\2\2\u030f\u0310\3\2"+
"\2\2\u0310\u00e6\3\2\2\2\u0311\u0312\7x\2\2\u0312\u0313\7q\2\2\u0313\u0314"+
"\7k\2\2\u0314\u0315\7f\2\2\u0315\u00e8\3\2\2\2\u0316\u031a\t\4\2\2\u0317"+
"\u0319\t\5\2\2\u0318\u0317\3\2\2\2\u0319\u031c\3\2\2\2\u031a\u0318\3\2"+
"\2\2\u031a\u031b\3\2\2\2\u031b\u00ea\3\2\2\2\u031c\u031a\3\2\2\2\u031d"+
"\u0325\4\62;\2\u031e\u0320\4\63;\2\u031f\u0321\4\62;\2\u0320\u031f\3\2"+
"\2\2\u0321\u0322\3\2\2\2\u0322\u0320\3\2\2\2\u0322\u0323\3\2\2\2\u0323"+
"\u0325\3\2\2\2\u0324\u031d\3\2\2\2\u0324\u031e\3\2\2\2\u0325\u00ec\3\2"+
"\2\2\u0326\u0328\7&\2\2\u0327\u0329\t\6\2\2\u0328\u0327\3\2\2\2\u0329"+
"\u032a\3\2\2\2\u032a\u0328\3\2\2\2\u032a\u032b\3\2\2\2\u032b\u00ee\3\2"+
"\2\2\u032c\u032e\7\'\2\2\u032d\u032f\4\62\63\2\u032e\u032d\3\2\2\2\u032f"+
"\u0330\3\2\2\2\u0330\u032e\3\2\2\2\u0330\u0331\3\2\2\2\u0331\u00f0\3\2"+
"\2\2\u0332\u0333\7(\2\2\u0333\u00f2\3\2\2\2\u0334\u033a\5\u00f5{\2\u0335"+
"\u0084\3\2\2\2\u0218\u0219\7t\2\2\u0219\u021a\7g\2\2\u021a\u021b\7v\2"+
"\2\u021b\u021c\7w\2\2\u021c\u021d\7t\2\2\u021d\u021e\7p\2\2\u021e\u0086"+
"\3\2\2\2\u021f\u0220\7d\2\2\u0220\u0221\7t\2\2\u0221\u0222\7g\2\2\u0222"+
"\u0223\7c\2\2\u0223\u0224\7m\2\2\u0224\u0088\3\2\2\2\u0225\u0226\7e\2"+
"\2\u0226\u0227\7q\2\2\u0227\u0228\7p\2\2\u0228\u0229\7v\2\2\u0229\u022a"+
"\7k\2\2\u022a\u022b\7p\2\2\u022b\u022c\7w\2\2\u022c\u022d\7g\2\2\u022d"+
"\u008a\3\2\2\2\u022e\u022f\7\60\2\2\u022f\u008c\3\2\2\2\u0230\u0231\7"+
"C\2\2\u0231\u008e\3\2\2\2\u0232\u0233\7Z\2\2\u0233\u0090\3\2\2\2\u0234"+
"\u0235\7[\2\2\u0235\u0092\3\2\2\2\u0236\u0237\7C\2\2\u0237\u0238\7Z\2"+
"\2\u0238\u0094\3\2\2\2\u0239\u023a\7C\2\2\u023a\u023b\7[\2\2\u023b\u0096"+
"\3\2\2\2\u023c\u023d\7Z\2\2\u023d\u023e\7[\2\2\u023e\u0098\3\2\2\2\u023f"+
"\u0240\7R\2\2\u0240\u0241\7e\2\2\u0241\u009a\3\2\2\2\u0242\u0243\7R\2"+
"\2\u0243\u0244\7|\2\2\u0244\u009c\3\2\2\2\u0245\u0246\7R\2\2\u0246\u0247"+
"\7p\2\2\u0247\u009e\3\2\2\2\u0248\u0249\7R\2\2\u0249\u024a\7x\2\2\u024a"+
"\u00a0\3\2\2\2\u024b\u024c\7\60\2\2\u024c\u024d\7y\2\2\u024d\u00a2\3\2"+
"\2\2\u024e\u024f\7v\2\2\u024f\u0250\7t\2\2\u0250\u0251\7w\2\2\u0251\u0252"+
"\7g\2\2\u0252\u00a4\3\2\2\2\u0253\u0254\7h\2\2\u0254\u0255\7c\2\2\u0255"+
"\u0256\7n\2\2\u0256\u0257\7u\2\2\u0257\u0258\7g\2\2\u0258\u00a6\3\2\2"+
"\2\u0259\u025a\7\'\2\2\u025a\u025b\7c\2\2\u025b\u025c\7u\2\2\u025c\u025d"+
"\7o\2\2\u025d\u00a8\3\2\2\2\u025e\u025f\7u\2\2\u025f\u0260\7w\2\2\u0260"+
"\u0261\7d\2\2\u0261\u00aa\3\2\2\2\u0262\u0263\7/\2\2\u0263\u0264\7@\2"+
"\2\u0264\u00ac\3\2\2\2\u0265\u0266\7c\2\2\u0266\u0267\7u\2\2\u0267\u0268"+
"\7o\2\2\u0268\u0269\7u\2\2\u0269\u026a\7w\2\2\u026a\u026b\7d\2\2\u026b"+
"\u00ae\3\2\2\2\u026c\u026d\7t\2\2\u026d\u026e\7q\2\2\u026e\u026f\7o\2"+
"\2\u026f\u0270\7u\2\2\u0270\u0271\7w\2\2\u0271\u0272\7d\2\2\u0272\u00b0"+
"\3\2\2\2\u0273\u0274\7u\2\2\u0274\u0275\7v\2\2\u0275\u0276\7c\2\2\u0276"+
"\u0277\7e\2\2\u0277\u0278\7m\2\2\u0278\u00b2\3\2\2\2\u0279\u027a\7e\2"+
"\2\u027a\u027b\7n\2\2\u027b\u027c\7q\2\2\u027c\u027d\7d\2\2\u027d\u027e"+
"\7d\2\2\u027e\u027f\7g\2\2\u027f\u0280\7t\2\2\u0280\u0281\7u\2\2\u0281"+
"\u00b4\3\2\2\2\u0282\u0283\7k\2\2\u0283\u0284\7h\2\2\u0284\u00b6\3\2\2"+
"\2\u0285\u0286\7g\2\2\u0286\u0287\7n\2\2\u0287\u0288\7u\2\2\u0288\u0289"+
"\7g\2\2\u0289\u00b8\3\2\2\2\u028a\u028b\7k\2\2\u028b\u028c\7h\2\2\u028c"+
"\u028d\7a\2\2\u028d\u028e\7e\2\2\u028e\u028f\7u\2\2\u028f\u00ba\3\2\2"+
"\2\u0290\u0291\7k\2\2\u0291\u0292\7h\2\2\u0292\u0293\7a\2\2\u0293\u0294"+
"\7e\2\2\u0294\u0295\7e\2\2\u0295\u00bc\3\2\2\2\u0296\u0297\7k\2\2\u0297"+
"\u0298\7h\2\2\u0298\u0299\7a\2\2\u0299\u029a\7g\2\2\u029a\u029b\7s\2\2"+
"\u029b\u00be\3\2\2\2\u029c\u029d\7k\2\2\u029d\u029e\7h\2\2\u029e\u029f"+
"\7a\2\2\u029f\u02a0\7|\2\2\u02a0\u00c0\3\2\2\2\u02a1\u02a2\7k\2\2\u02a2"+
"\u02a3\7h\2\2\u02a3\u02a4\7a\2\2\u02a4\u02a5\7p\2\2\u02a5\u02a6\7g\2\2"+
"\u02a6\u00c2\3\2\2\2\u02a7\u02a8\7k\2\2\u02a8\u02a9\7h\2\2\u02a9\u02aa"+
"\7a\2\2\u02aa\u02ab\7p\2\2\u02ab\u02ac\7|\2\2\u02ac\u00c4\3\2\2\2\u02ad"+
"\u02ae\7k\2\2\u02ae\u02af\7h\2\2\u02af\u02b0\7a\2\2\u02b0\u02b1\7r\2\2"+
"\u02b1\u02b2\7n\2\2\u02b2\u00c6\3\2\2\2\u02b3\u02b4\7k\2\2\u02b4\u02b5"+
"\7h\2\2\u02b5\u02b6\7a\2\2\u02b6\u02b7\7r\2\2\u02b7\u02b8\7q\2\2\u02b8"+
"\u02b9\7u\2\2\u02b9\u00c8\3\2\2\2\u02ba\u02bb\7k\2\2\u02bb\u02bc\7h\2"+
"\2\u02bc\u02bd\7a\2\2\u02bd\u02be\7o\2\2\u02be\u02bf\7k\2\2\u02bf\u00ca"+
"\3\2\2\2\u02c0\u02c1\7k\2\2\u02c1\u02c2\7h\2\2\u02c2\u02c3\7a\2\2\u02c3"+
"\u02c4\7p\2\2\u02c4\u02c5\7g\2\2\u02c5\u02c6\7i\2\2\u02c6\u00cc\3\2\2"+
"\2\u02c7\u02c8\7k\2\2\u02c8\u02c9\7h\2\2\u02c9\u02ca\7a\2\2\u02ca\u02cb"+
"\7x\2\2\u02cb\u02cc\7u\2\2\u02cc\u00ce\3\2\2\2\u02cd\u02ce\7k\2\2\u02ce"+
"\u02cf\7h\2\2\u02cf\u02d0\7a\2\2\u02d0\u02d1\7x\2\2\u02d1\u02d2\7e\2\2"+
"\u02d2\u00d0\3\2\2\2\u02d3\u02d4\7h\2\2\u02d4\u02d5\7q\2\2\u02d5\u02d6"+
"\7t\2\2\u02d6\u00d2\3\2\2\2\u02d7\u02d8\7k\2\2\u02d8\u02d9\7p\2\2\u02d9"+
"\u00d4\3\2\2\2\u02da\u02db\7y\2\2\u02db\u02dc\7j\2\2\u02dc\u02dd\7k\2"+
"\2\u02dd\u02de\7n\2\2\u02de\u02df\7g\2\2\u02df\u00d6\3\2\2\2\u02e0\u02e1"+
"\7t\2\2\u02e1\u02e2\7g\2\2\u02e2\u02e3\7r\2\2\u02e3\u02e4\7g\2\2\u02e4"+
"\u02e5\7c\2\2\u02e5\u02e6\7v\2\2\u02e6\u00d8\3\2\2\2\u02e7\u02e8\7w\2"+
"\2\u02e8\u02e9\7p\2\2\u02e9\u02ea\7v\2\2\u02ea\u02eb\7k\2\2\u02eb\u02ec"+
"\7n\2\2\u02ec\u00da\3\2\2\2\u02ed\u02ee\7y\2\2\u02ee\u02ef\7j\2\2\u02ef"+
"\u02f0\7g\2\2\u02f0\u02f1\7p\2\2\u02f1\u00dc\3\2\2\2\u02f2\u02f6\t\2\2"+
"\2\u02f3\u02f5\t\3\2\2\u02f4\u02f3\3\2\2\2\u02f5\u02f8\3\2\2\2\u02f6\u02f4"+
"\3\2\2\2\u02f6\u02f7\3\2\2\2\u02f7\u02f9\3\2\2\2\u02f8\u02f6\3\2\2\2\u02f9"+
"\u02fa\5\u00dfp\2\u02fa\u02fb\3\2\2\2\u02fb\u02fc\bo\2\2\u02fc\u00de\3"+
"\2\2\2\u02fd\u0301\7=\2\2\u02fe\u0300\n\2\2\2\u02ff\u02fe\3\2\2\2\u0300"+
"\u0303\3\2\2\2\u0301\u02ff\3\2\2\2\u0301\u0302\3\2\2\2\u0302\u0304\3\2"+
"\2\2\u0303\u0301\3\2\2\2\u0304\u0305\bp\2\2\u0305\u00e0\3\2\2\2\u0306"+
"\u0307\t\3\2\2\u0307\u0308\3\2\2\2\u0308\u0309\bq\3\2\u0309\u00e2\3\2"+
"\2\2\u030a\u030c\t\2\2\2\u030b\u030a\3\2\2\2\u030c\u030d\3\2\2\2\u030d"+
"\u030b\3\2\2\2\u030d\u030e\3\2\2\2\u030e\u00e4\3\2\2\2\u030f\u0310\7x"+
"\2\2\u0310\u0311\7q\2\2\u0311\u0312\7k\2\2\u0312\u0313\7f\2\2\u0313\u00e6"+
"\3\2\2\2\u0314\u0318\t\4\2\2\u0315\u0317\t\5\2\2\u0316\u0315\3\2\2\2\u0317"+
"\u031a\3\2\2\2\u0318\u0316\3\2\2\2\u0318\u0319\3\2\2\2\u0319\u00e8\3\2"+
"\2\2\u031a\u0318\3\2\2\2\u031b\u0323\4\62;\2\u031c\u031e\4\63;\2\u031d"+
"\u031f\4\62;\2\u031e\u031d\3\2\2\2\u031f\u0320\3\2\2\2\u0320\u031e\3\2"+
"\2\2\u0320\u0321\3\2\2\2\u0321\u0323\3\2\2\2\u0322\u031b\3\2\2\2\u0322"+
"\u031c\3\2\2\2\u0323\u00ea\3\2\2\2\u0324\u0326\7&\2\2\u0325\u0327\t\6"+
"\2\2\u0326\u0325\3\2\2\2\u0327\u0328\3\2\2\2\u0328\u0326\3\2\2\2\u0328"+
"\u0329\3\2\2\2\u0329\u00ec\3\2\2\2\u032a\u032c\7\'\2\2\u032b\u032d\4\62"+
"\63\2\u032c\u032b\3\2\2\2\u032d\u032e\3\2\2\2\u032e\u032c\3\2\2\2\u032e"+
"\u032f\3\2\2\2\u032f\u00ee\3\2\2\2\u0330\u0331\7(\2\2\u0331\u00f0\3\2"+
"\2\2\u0332\u0333\7B\2\2\u0333\u00f2\3\2\2\2\u0334\u033a\5\u00f5{\2\u0335"+
"\u0337\t\7\2\2\u0336\u0338\t\b\2\2\u0337\u0336\3\2\2\2\u0337\u0338\3\2"+
"\2\2\u0338\u0339\3\2\2\2\u0339\u033b\5\u00f5{\2\u033a\u0335\3\2\2\2\u033a"+
"\u033b\3\2\2\2\u033b\u00f4\3\2\2\2\u033c\u033e\4\62;\2\u033d\u033c\3\2"+
@ -491,7 +491,7 @@ public class prog8Lexer extends Lexer {
"\2\2\2\u0344\u0345\3\2\2\2\u0345\u0343\3\2\2\2\u0345\u0346\3\2\2\2\u0346"+
"\u0348\3\2\2\2\u0347\u0341\3\2\2\2\u0347\u0348\3\2\2\2\u0348\u00f6\3\2"+
"\2\2\u0349\u034a\7^\2\2\u034a\u034e\13\2\2\2\u034b\u034c\7^\2\2\u034c"+
"\u034e\5\u00e5s\2\u034d\u0349\3\2\2\2\u034d\u034b\3\2\2\2\u034e\u00f8"+
"\u034e\5\u00e3r\2\u034d\u0349\3\2\2\2\u034d\u034b\3\2\2\2\u034e\u00f8"+
"\3\2\2\2\u034f\u0354\7$\2\2\u0350\u0353\5\u00f7|\2\u0351\u0353\n\t\2\2"+
"\u0352\u0350\3\2\2\2\u0352\u0351\3\2\2\2\u0353\u0356\3\2\2\2\u0354\u0352"+
"\3\2\2\2\u0354\u0355\3\2\2\2\u0355\u0357\3\2\2\2\u0356\u0354\3\2\2\2\u0357"+
@ -504,7 +504,7 @@ public class prog8Lexer extends Lexer {
"\3\2\2\2\u036b\u036c\3\2\2\2\u036c\u036d\7)\2\2\u036d\u036e\b\177\6\2"+
"\u036e\u00fe\3\2\2\2\u036f\u0370\7B\2\2\u0370\u0371\7|\2\2\u0371\u0372"+
"\7r\2\2\u0372\u0100\3\2\2\2\u0373\u0374\7]\2\2\u0374\u0375\7_\2\2\u0375"+
"\u0102\3\2\2\2\26\2\u02f8\u0303\u030f\u031a\u0322\u0324\u0328\u032a\u0330"+
"\u0102\3\2\2\2\26\2\u02f6\u0301\u030d\u0318\u0320\u0322\u0326\u0328\u032e"+
"\u0337\u033a\u033f\u0345\u0347\u034d\u0352\u0354\u0360\u036a\7\2\3\2\b"+
"\2\2\3}\2\3~\3\3\177\4";
public static final ATN _ATN =

File diff suppressed because it is too large Load Diff