improved handling of range and range type checks

This commit is contained in:
Irmen de Jong 2018-09-16 15:40:28 +02:00
parent 266f98a888
commit 3c7a233b43
14 changed files with 727 additions and 614 deletions

View File

@ -121,7 +121,7 @@ expression :
| left = expression bop = '&' right = expression
| left = expression bop = '^' right = expression
| left = expression bop = '|' right = expression
| rangefrom = expression 'to' rangeto = expression // can't create separate rule due to mutual left-recursion
| rangefrom = expression 'to' rangeto = expression ('step' rangestep = expression)? // can't create separate rule due to mutual left-recursion
| left = expression bop = 'and' right = expression
| left = expression bop = 'or' right = expression
| left = expression bop = 'xor' right = expression
@ -216,7 +216,7 @@ branchcondition: 'if_cs' | 'if_cc' | 'if_eq' | 'if_ne' | 'if_pl' | 'if_mi' | 'if
forloop :
'for' (register | identifier) 'in' range_expr=expression ('step' for_step=expression)? EOL? loop_statement_block EOL
'for' (register | identifier) 'in' expression EOL? loop_statement_block EOL
;
loop_statement_block :

View File

@ -6,6 +6,34 @@
sub start() -> () {
const str cs1 = "string1"
const str_p cs2 = "string2"
const str_s cs3 = "string3"
const str_ps cs4 = "string4"
str vs1 = "string1"
str_p vs2 = "string2"
str_s vs3 = "string3"
str_ps vs4 = "string4"
const byte[5] ba = [1,2,3,4,5]
const byte[5] ba2 = [1,2,3,4,50]
const word[5] wa = [1,2,3,4,5]
const word[5] wa2 = [1,2,3,4,500]
const byte[100] yy = 1 to 100
const byte[100] zz = 100 to 1 step -1
const byte[7] xx = 1 to 20 step 3
const byte[7] ww = 20 to 1 step -3
const byte[2,4] wwm = 23 to 1 step -3
const str derp2 = "a" to "z"
_vm_write_str(cs1)
_vm_write_str(cs2)
_vm_write_str(cs3)
_vm_write_str(cs4)
_vm_write_str(vs1)
_vm_write_str(vs2)
_vm_write_str(vs3)
_vm_write_str(vs4)
word tx = 0
word ty = 12 % 5
float time = 0.0

View File

@ -4,7 +4,9 @@ import prog8.functions.*
import prog8.parser.prog8Parser
import org.antlr.v4.runtime.ParserRuleContext
import org.antlr.v4.runtime.tree.TerminalNode
import prog8.compiler.Petscii
import java.nio.file.Paths
import kotlin.math.abs
import kotlin.math.floor
@ -180,8 +182,7 @@ interface IAstProcessor {
fun process(forLoop: ForLoop): IStatement {
forLoop.loopVar?.process(this)
forLoop.range = forLoop.range.process(this)
forLoop.step = forLoop.step?.process(this)
forLoop.iterable = forLoop.iterable.process(this)
forLoop.body = forLoop.body.asSequence().map {it.process(this)}.toMutableList()
return forLoop
}
@ -829,13 +830,17 @@ class LiteralValue(val type: DataType,
}
class RangeExpr(var from: IExpression, var to: IExpression, override val position: Position) : IExpression {
class RangeExpr(var from: IExpression,
var to: IExpression,
var step: IExpression?,
override val position: Position) : IExpression {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
this.parent = parent
from.linkParents(this)
to.linkParents(this)
step?.linkParents(this)
}
override fun constValue(namespace: INameScope): LiteralValue? = null
@ -854,6 +859,47 @@ class RangeExpr(var from: IExpression, var to: IExpression, override val positio
else -> DataType.BYTE
}
}
override fun toString(): String {
return "RangeExpr(from $from, to $to, step $step, pos=$position)"
}
fun size(): Int? {
val fromLv = (from as? LiteralValue)
val toLv = (to as? LiteralValue)
if(fromLv==null || toLv==null)
return null
return toKotlinRange().count()
}
fun toKotlinRange(): IntProgression {
val fromLv = from as LiteralValue
val toLv = to as LiteralValue
val fromVal: Int
val toVal: Int
if(fromLv.isString && toLv.isString) {
// string range -> int range over petscii values
fromVal = Petscii.encodePetscii(fromLv.strvalue!!, true)[0].toInt()
toVal = Petscii.encodePetscii(toLv.strvalue!!, true)[0].toInt()
} else {
// integer range
fromVal = (from as LiteralValue).asIntegerValue!!
toVal = (to as LiteralValue).asIntegerValue!!
}
val stepVal = (step as? LiteralValue)?.asIntegerValue ?: 1
return when {
fromVal <= toVal -> when {
stepVal <= 0 -> IntRange.EMPTY
stepVal == 1 -> fromVal..toVal
else -> fromVal..toVal step stepVal
}
else -> when {
stepVal >= 0 -> IntRange.EMPTY
stepVal == -1 -> fromVal downTo toVal
else -> fromVal downTo toVal step abs(stepVal)
}
}
}
}
@ -1448,8 +1494,12 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
}
litval.floatliteral()!=null -> LiteralValue(DataType.FLOAT, floatvalue = litval.floatliteral().toAst(), position = litval.toPosition())
litval.stringliteral()!=null -> LiteralValue(DataType.STR, strvalue = litval.stringliteral().text, position = litval.toPosition())
litval.arrayliteral()!=null -> LiteralValue(DataType.ARRAY, arrayvalue = litval.arrayliteral()?.toAst(), position = litval.toPosition())
// @todo byte/word array difference needed for literal array values?
litval.arrayliteral()!=null -> {
val array = litval.arrayliteral()?.toAst()
// byte/word array type difference is not determined here.
// the ConstantFolder takes care of that and converts the type if needed.
LiteralValue(DataType.ARRAY, arrayvalue = array, position = litval.toPosition())
}
else -> throw FatalAstException("invalid parsed literal")
}
}
@ -1473,8 +1523,9 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
val funcall = functioncall()?.toAst()
if(funcall!=null) return funcall
if (rangefrom!=null && rangeto!=null)
return RangeExpr(rangefrom.toAst(), rangeto.toAst(), toPosition())
if (rangefrom!=null && rangeto!=null) {
return RangeExpr(rangefrom.toAst(), rangeto.toAst(), rangestep?.toAst(), toPosition())
}
if(childCount==3 && children[0].text=="(" && children[2].text==")")
return expression(0).toAst() // expression within ( )
@ -1533,17 +1584,15 @@ private fun prog8Parser.BranchconditionContext.toAst() = BranchCondition.valueOf
private fun prog8Parser.ForloopContext.toAst(): ForLoop {
val loopregister = register()?.toAst()
val loopvar = identifier()?.toAst()
val range = range_expr.toAst()
val step = if(for_step==null) null else for_step.toAst()
val iterable = expression()!!.toAst()
val body = loop_statement_block().toAst()
return ForLoop(loopregister, loopvar, range, step, body, toPosition())
return ForLoop(loopregister, loopvar, iterable, body, toPosition())
}
class ForLoop(val loopRegister: Register?,
val loopVar: IdentifierReference?,
var range: IExpression,
var step: IExpression?,
var iterable: IExpression,
var body: MutableList<IStatement>,
override val position: Position) : IStatement {
override lateinit var parent: Node
@ -1551,8 +1600,7 @@ class ForLoop(val loopRegister: Register?,
override fun linkParents(parent: Node) {
this.parent=parent
loopVar?.linkParents(this)
range.linkParents(this)
step?.linkParents(this)
iterable.linkParents(this)
body.forEach { it.linkParents(this) }
}

View File

@ -11,12 +11,30 @@ import prog8.parser.ParsingFailedError
fun Module.checkValid(globalNamespace: INameScope, compilerOptions: CompilationOptions) {
val checker = AstChecker(globalNamespace, compilerOptions)
this.process(checker)
val checkResult = checker.result()
checkResult.forEach {
System.err.println(it)
printErrors(checker.result(), name)
}
fun printErrors(errors: List<Any>, moduleName: String) {
val reportedMessages = mutableSetOf<String>()
errors.forEach {
val msg = it.toString()
if(!reportedMessages.contains(msg)) {
System.err.println(msg)
reportedMessages.add(msg)
}
}
if(checkResult.isNotEmpty())
throw ParsingFailedError("There are ${checkResult.size} errors in module '$name'.")
if(reportedMessages.isNotEmpty())
throw ParsingFailedError("There are ${reportedMessages.size} errors in module '$moduleName'.")
}
fun printWarning(msg: String, position: Position, detailInfo: String?=null) {
print("$position Warning: $msg")
if(detailInfo==null)
print("\n")
else
println(": $detailInfo")
}
@ -169,7 +187,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
checkResult.add(ExpressionError("assignment source ${assignment.value} is no value or has no proper datatype", assignment.value.position))
}
else {
checkAssignmentCompatible(targetDatatype, sourceDatatype, assignment.position)
checkAssignmentCompatible(targetDatatype, sourceDatatype, assignment.value, assignment.position)
}
}
@ -198,17 +216,18 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
when(decl.type) {
VarDeclType.VAR, VarDeclType.CONST -> {
when(decl.value) {
null -> {
err("var/const declaration needs a compile-time constant initializer value")
return super.process(decl)
}
!is LiteralValue -> {
err("var/const declaration needs a compile-time constant initializer value, found: ${decl.value!!::class.simpleName}")
if (decl.value == null) {
err("var/const declaration needs a compile-time constant initializer value")
return super.process(decl)
}
when {
decl.value is RangeExpr -> checkValueTypeAndRange(decl.datatype, decl.arrayspec, decl.value as RangeExpr)
decl.value is LiteralValue -> checkValueTypeAndRange(decl.datatype, decl.arrayspec, decl.value as LiteralValue)
else -> {
err("var/const declaration needs a compile-time constant initializer value, or range, instead found: ${decl.value!!::class.simpleName}")
return super.process(decl)
}
}
checkValueTypeAndRange(decl.datatype, decl.arrayspec, decl.value as LiteralValue)
}
VarDeclType.MEMORY -> {
if(decl.value !is LiteralValue) {
@ -307,17 +326,34 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
super.process(range)
val from = range.from.constValue(namespace)
val to = range.to.constValue(namespace)
var step = 0
if(range.step!=null) {
val stepLv = range.step?.constValue(namespace) ?: LiteralValue(DataType.BYTE, 1, position = range.position)
if (stepLv.asIntegerValue == null || stepLv.asIntegerValue == 0) {
err("range step must be an integer != 0")
return range
}
step = stepLv.asIntegerValue
}
if(from!=null && to != null) {
when {
from.asIntegerValue!=null && to.asIntegerValue!=null -> {
if(from.asIntegerValue > to.asIntegerValue)
err("range from is larger than to value")
if(from.asIntegerValue == to.asIntegerValue)
printWarning("range contains just a single value", range.position)
else if(from.asIntegerValue < to.asIntegerValue && step<0)
err("ascending range requires step > 0")
else if(from.asIntegerValue > to.asIntegerValue && step>0)
err("descending range requires step < 0")
}
from.strvalue!=null && to.strvalue!=null -> {
if(from.strvalue.length!=1 || to.strvalue.length!=1)
err("range from and to must be a single character")
if(from.strvalue[0] > to.strvalue[0])
err("range from is larger than to value")
if(from.strvalue[0] == to.strvalue[0])
printWarning("range contains just a single character", range.position)
else if(from.strvalue[0] < to.strvalue[0] && step<0)
err("ascending range requires step > 0")
else if(from.strvalue[0] > to.strvalue[0] && step<0)
err("descending range requires step < 0")
}
else -> err("range expression must be over integers or over characters")
}
@ -385,6 +421,49 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
}
}
private fun checkValueTypeAndRange(targetDt: DataType, arrayspec: ArraySpec?, range: RangeExpr) : Boolean {
val from = range.from.constValue(namespace)
val to = range.to.constValue(namespace)
if(from==null || to==null) {
checkResult.add(SyntaxError("range from and to values must be constants", range.position))
return false
}
when(targetDt) {
DataType.BYTE, DataType.WORD, DataType.FLOAT -> {
checkResult.add(SyntaxError("can't assign a range to a scalar type", range.position))
return false
}
DataType.STR,
DataType.STR_P,
DataType.STR_S,
DataType.STR_PS -> {
// range check bytes (chars)
if(!from.isString || !to.isString) {
checkResult.add(ExpressionError("range for string must have single characters from and to values", range.position))
return false
}
val rangeSize=range.size()
if(rangeSize!=null && (rangeSize<1 || rangeSize>255)) {
checkResult.add(ExpressionError("size of range for string must be 1..255, instead of $rangeSize", range.position))
return false
}
return true
}
DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX -> {
// range and length check bytes
val expectedSize = arrayspec!!.size()
val rangeSize=range.size()
if(rangeSize!=null && rangeSize != expectedSize) {
checkResult.add(ExpressionError("range size doesn't match array/matrix size, expected $expectedSize found $rangeSize", range.position))
return false
}
return true
}
}
}
private fun checkValueTypeAndRange(targetDt: DataType, arrayspec: ArraySpec?, value: LiteralValue) : Boolean {
fun err(msg: String) : Boolean {
checkResult.add(ExpressionError(msg, value.position))
@ -441,9 +520,13 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
if(av.register!=Register.A && av.register!=Register.X && av.register!=Register.Y)
return err("register '$av' in byte array is not a single register")
} else {
TODO("check array value $av")
val avDt = av.resultingDatatype(namespace)
if(avDt!=DataType.BYTE)
return err("array must be all bytes")
}
}
} else if(value.type==DataType.ARRAY_W) {
return err("initialization value must be an array of bytes")
} else {
val number = value.bytevalue ?: return if (value.floatvalue!=null)
err("unsigned byte integer value expected instead of float; possible loss of precision")
@ -472,7 +555,9 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
if (number < 0 || number > 65535)
return err("value '$number' in array is out of range for unsigned word")
} else {
TODO("check array value $av")
val avDt = av.resultingDatatype(namespace)
if(avDt!=DataType.BYTE && avDt!=DataType.WORD)
return err("array must be all integers")
}
}
} else {
@ -513,7 +598,14 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
return true
}
private fun checkAssignmentCompatible(targetDatatype: DataType, sourceDatatype: DataType, position: Position) : Boolean {
private fun checkAssignmentCompatible(targetDatatype: DataType,
sourceDatatype: DataType,
sourceValue: IExpression,
position: Position) : Boolean {
if(sourceValue is RangeExpr)
return checkValueTypeAndRange(targetDatatype, null, sourceValue)
val result = when(targetDatatype) {
DataType.BYTE -> sourceDatatype==DataType.BYTE
DataType.WORD -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.WORD

View File

@ -1,7 +1,6 @@
package prog8.ast
import prog8.functions.BuiltinFunctionNames
import prog8.parser.ParsingFailedError
/**
* Checks the validity of all identifiers (no conflicts)
@ -12,12 +11,7 @@ import prog8.parser.ParsingFailedError
fun Module.checkIdentifiers(): MutableMap<String, IStatement> {
val checker = AstIdentifiersChecker()
this.process(checker)
val checkResult = checker.result()
checkResult.forEach {
System.err.println(it)
}
if(checkResult.isNotEmpty())
throw ParsingFailedError("There are ${checkResult.size} errors in module '$name'.")
printErrors(checker.result(), name)
return checker.symbols
}

View File

@ -1,7 +1,5 @@
package prog8.ast
import prog8.parser.ParsingFailedError
/**
* Checks for the occurrence of recursive subroutine calls
*/
@ -9,12 +7,7 @@ import prog8.parser.ParsingFailedError
fun Module.checkRecursion(namespace: INameScope) {
val checker = AstRecursionChecker(namespace)
this.process(checker)
val checkResult = checker.result()
checkResult.forEach {
System.err.println(it)
}
if(checkResult.isNotEmpty())
throw ParsingFailedError("There are ${checkResult.size} errors in module '$name'.")
printErrors(checker.result(), name)
}

View File

@ -1,7 +1,5 @@
package prog8.ast
import prog8.parser.ParsingFailedError
/**
* Checks that are specific for imported modules.
@ -11,12 +9,7 @@ fun Module.checkImportedValid() {
val checker = ImportedAstChecker()
this.linkParents()
this.process(checker)
val result = checker.result()
result.forEach {
System.err.println(it)
}
if(result.isNotEmpty())
throw ParsingFailedError("There are ${result.size} errors in imported module '$name'.")
printErrors(checker.result(), name)
}
@ -39,7 +32,7 @@ class ImportedAstChecker : IAstProcessor {
val stmt = sourceStmt.process(this)
if(stmt is Directive && stmt.parent is Module) {
if(moduleLevelDirectives.contains(stmt.directive)) {
println("${stmt.position} Warning: ignoring module directive because it was imported: ${stmt.directive}")
printWarning("ignoring module directive because it was imported", stmt.position, stmt.directive)
continue
}
}

View File

@ -291,6 +291,9 @@ class Compiler(private val options: CompilationOptions) {
else -> throw CompilerException("expression identifierref should be a vardef, not $target")
}
}
is RangeExpr -> {
TODO("TRANSLATE $expr") // todo
}
else -> {
val lv = expr.constValue(namespace) ?: throw CompilerException("constant expression required, not $expr")
when(lv.type) {
@ -475,7 +478,7 @@ class Compiler(private val options: CompilationOptions) {
private fun translate(loop: ForLoop) {
stackvmProg.line(loop.position)
println("@TODO: translate FOR LOOP") // @todo
println("@TODO: translate FOR LOOP") // @todo FOR LOOP
}
}
}

View File

@ -6,6 +6,8 @@ class Petscii {
// decoding: from Petscii/Screencodes (0-255) to unicode
// character tables used from https://github.com/dj51d/cbmcodecs
// todo: paste the actual unicode symbols after it in the comment for easy copy-pasting
private val decodingPetsciiLowercase = arrayOf(
'\ufffe', // 0x00 -> UNDEFINED
'\ufffe', // 0x01 -> UNDEFINED
@ -262,7 +264,7 @@ class Petscii {
'\u259d', // 0xFC -> QUADRANT UPPER RIGHT
'\u2518', // 0xFD -> BOX DRAWINGS LIGHT UP AND LEFT
'\u2598', // 0xFE -> QUADRANT UPPER LEFT
'\u2592' // 0xFF -> MEDIUM SHADE
'\u2592' // 0xFF -> MEDIUM SHADE
)
private val decodingPetsciiUppercase = arrayOf(
@ -780,7 +782,7 @@ class Petscii {
'\ufffe', // 0xFC -> UNDEFINED
'\ufffe', // 0xFD -> UNDEFINED
'\ufffe', // 0xFE -> UNDEFINED
'\ufffe' // 0xFF -> UNDEFINED
'\ufffe' // 0xFF -> UNDEFINED
)
private val decodingScreencodeUppercase = arrayOf(
@ -1039,7 +1041,7 @@ class Petscii {
'\ufffe', // 0xFC -> UNDEFINED
'\ufffe', // 0xFD -> UNDEFINED
'\ufffe', // 0xFE -> UNDEFINED
'\ufffe' // 0xFF -> UNDEFINED
'\ufffe' // 0xFF -> UNDEFINED
)
// encoding: from unicode to Petscii/Screencodes (0-255)

View File

@ -1,9 +1,6 @@
package prog8.compiler
import prog8.ast.DataType
import prog8.ast.LiteralValue
import prog8.ast.VarDecl
import prog8.ast.VarDeclType
import prog8.ast.*
class Zeropage(private val options: CompilationOptions) {
@ -53,7 +50,7 @@ class Zeropage(private val options: CompilationOptions) {
val size =
if(vardecl.arrayspec!=null) {
println("${vardecl.position} warning: allocating a large value (array) in zeropage")
printWarning("allocating a large value (array) in zeropage", vardecl.position)
val y = (vardecl.arrayspec.y as? LiteralValue)?.asIntegerValue
if(y==null) {
// 1 dimensional array
@ -76,7 +73,7 @@ class Zeropage(private val options: CompilationOptions) {
DataType.WORD -> 2
DataType.FLOAT -> {
if (options.floats) {
println("${vardecl.position} warning: allocating a large value (float) in zeropage")
printWarning("allocating a large value (float) in zeropage", vardecl.position)
5
} else throw CompilerException("floating point option not enabled")
}

View File

@ -4,7 +4,7 @@ import prog8.ast.*
import prog8.compiler.Petscii
class ConstantFolding(private val globalNamespace: INameScope) : IAstProcessor {
class ConstantFolding(private val namespace: INameScope) : IAstProcessor {
var optimizationsDone: Int = 0
var errors : MutableList<AstException> = mutableListOf()
@ -49,7 +49,7 @@ class ConstantFolding(private val globalNamespace: INameScope) : IAstProcessor {
}
}
DataType.MATRIX -> {
(decl.value as LiteralValue).let {
(decl.value as? LiteralValue)?.let {
val intvalue = it.asIntegerValue
if(intvalue!=null) {
// replace the single int value by a properly sized array to fill the matrix.
@ -64,7 +64,7 @@ class ConstantFolding(private val globalNamespace: INameScope) : IAstProcessor {
}
}
DataType.ARRAY, DataType.ARRAY_W -> {
(decl.value as LiteralValue).let {
(decl.value as? LiteralValue)?.let {
val intvalue = it.asIntegerValue
if(intvalue!=null) {
// replace the single int value by a properly sized array to fill the array with.
@ -94,7 +94,7 @@ class ConstantFolding(private val globalNamespace: INameScope) : IAstProcessor {
*/
override fun process(identifier: IdentifierReference): IExpression {
return try {
identifier.constValue(globalNamespace) ?: identifier
identifier.constValue(namespace) ?: identifier
} catch (ax: AstException) {
addError(ax)
identifier
@ -104,7 +104,7 @@ class ConstantFolding(private val globalNamespace: INameScope) : IAstProcessor {
override fun process(functionCall: FunctionCall): IExpression {
return try {
super.process(functionCall)
functionCall.constValue(globalNamespace) ?: functionCall
functionCall.constValue(namespace) ?: functionCall
} catch (ax: AstException) {
addError(ax)
functionCall
@ -174,8 +174,8 @@ class ConstantFolding(private val globalNamespace: INameScope) : IAstProcessor {
super.process(expr)
val evaluator = ConstExprEvaluator()
val leftconst = expr.left.constValue(globalNamespace)
val rightconst = expr.right.constValue(globalNamespace)
val leftconst = expr.left.constValue(namespace)
val rightconst = expr.right.constValue(namespace)
return when {
leftconst != null && rightconst != null -> {
optimizationsDone++
@ -190,60 +190,27 @@ class ConstantFolding(private val globalNamespace: INameScope) : IAstProcessor {
}
override fun process(range: RangeExpr): IExpression {
return try {
super.process(range)
val from = range.from.constValue(globalNamespace)
val to = range.to.constValue(globalNamespace)
if (from != null && to != null) {
when {
from.type==DataType.WORD || to.type==DataType.WORD -> {
// range on word value boundaries
val rangeValue = from.asIntegerValue!!.rangeTo(to.asIntegerValue!!)
if (rangeValue.last - rangeValue.first > 65535) {
throw ExpressionError("amount of values in range exceeds 65535", range.position)
}
return LiteralValue(DataType.ARRAY_W, arrayvalue = rangeValue.map {
val v = LiteralValue(DataType.WORD, wordvalue = it, position = range.position)
v.parent = range.parent
v
}.toTypedArray(), position = from.position)
}
from.type==DataType.BYTE && to.type==DataType.BYTE -> {
// range on byte value boundaries
val rangeValue = from.bytevalue!!.rangeTo(to.bytevalue!!)
if (rangeValue.last - rangeValue.first > 65535) {
throw ExpressionError("amount of values in range exceeds 65535", range.position)
}
return LiteralValue(DataType.ARRAY, arrayvalue = rangeValue.map {
val v = LiteralValue(DataType.BYTE, bytevalue = it.toShort(), position = range.position)
v.parent = range.parent
v
}.toTypedArray(), position = from.position)
}
from.strvalue != null && to.strvalue != null -> {
// char range
val rangevalue = from.strvalue[0].rangeTo(to.strvalue[0])
if (rangevalue.last - rangevalue.first > 65535) {
throw ExpressionError("amount of characters in range exceeds 65535", range.position)
}
val newval = LiteralValue(DataType.STR, strvalue = rangevalue.toList().joinToString(""), position = range.position)
newval.parent = range.parent
return newval
}
else -> AstException("range on weird datatype")
}
}
return range
} catch (ax: AstException) {
addError(ax)
range
}
range.from = range.from.process(this)
range.to = range.to.process(this)
range.step = range.step?.process(this)
return super.process(range)
}
override fun process(literalValue: LiteralValue): LiteralValue {
if(literalValue.arrayvalue!=null) {
val newArray = literalValue.arrayvalue.map { it.process(this) }.toTypedArray()
val newValue = LiteralValue(literalValue.type, arrayvalue = newArray, position = literalValue.position)
// determine if the values are all bytes or that we need a word array instead
var arrayDt = DataType.ARRAY
for (expr in newArray) {
val valueDt = expr.resultingDatatype(namespace)
if(valueDt==DataType.BYTE)
continue
else {
arrayDt = DataType.ARRAY_W
break
}
}
val newValue = LiteralValue(arrayDt, arrayvalue = newArray, position = literalValue.position)
return super.process(newValue)
}
return super.process(literalValue)

View File

@ -39,7 +39,7 @@ class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcesso
if(functionCall.target.nameInSource.size==1 && BuiltinFunctionNames.contains(functionCall.target.nameInSource[0])) {
val functionName = functionCall.target.nameInSource[0]
if (BuiltinFunctionsWithoutSideEffects.contains(functionName)) {
println("${functionCall.position} Warning: statement has no effect (function return value is discarded)")
printWarning("statement has no effect (function return value is discarded)", functionCall.position)
statementsToRemove.add(functionCall)
}
}
@ -62,11 +62,11 @@ class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcesso
if(constvalue!=null) {
return if(constvalue.asBooleanValue){
// always true -> keep only if-part
println("${ifStatement.position} Warning: condition is always true")
printWarning("condition is always true", ifStatement.position)
AnonymousStatementList(ifStatement.parent, ifStatement.statements, ifStatement.position)
} else {
// always false -> keep only else-part
println("${ifStatement.position} Warning: condition is always false")
printWarning("condition is always false", ifStatement.position)
AnonymousStatementList(ifStatement.parent, ifStatement.elsepart, ifStatement.position)
}
}

View File

@ -64,12 +64,12 @@ public class prog8Lexer extends Lexer {
"'float'", "'str'", "'str_p'", "'str_s'", "'str_ps'", "'['", "']'", "'+='",
"'-='", "'/='", "'*='", "'**='", "'&='", "'|='", "'^='", "'++'", "'--'",
"'('", "')'", "'+'", "'-'", "'**'", "'*'", "'/'", "'%'", "'<'", "'>'",
"'<='", "'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'and'",
"'or'", "'xor'", "'not'", "'return'", "'break'", "'continue'", "'.'",
"'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'",
"'.w'", "'true'", "'false'", "'%asm'", "'sub'", "'->'", "'{'", "'}'",
"'?'", "'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'", "'if_ne'", "'if_pl'",
"'if_mi'", "'if_vs'", "'if_vc'", "'for'", "'in'", "'step'"
"'<='", "'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'step'",
"'and'", "'or'", "'xor'", "'not'", "'return'", "'break'", "'continue'",
"'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'",
"'Pv'", "'.w'", "'true'", "'false'", "'%asm'", "'sub'", "'->'", "'{'",
"'}'", "'?'", "'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'", "'if_ne'",
"'if_pl'", "'if_mi'", "'if_vs'", "'if_vc'", "'for'", "'in'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, null, null, null, null, null, null,
@ -201,25 +201,25 @@ public class prog8Lexer extends Lexer {
"\37\3\37\3\37\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.\3.\3/\3/\3/\3\60"+
"\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\64\3\64\3\65\3\65"+
"\3\66\3\66\3\66\3\67\3\67\3\67\3\67\38\38\38\39\39\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=\3=\3>\3"+
">\3?\3?\3@\3@\3A\3A\3B\3B\3B\3C\3C\3C\3D\3D\3D\3E\3E\3E\3F\3F\3F\3G\3"+
"G\3G\3H\3H\3H\3I\3I\3I\3J\3J\3J\3J\3J\3K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3"+
"L\3M\3M\3M\3M\3N\3N\3N\3O\3O\3P\3P\3Q\3Q\3R\3R\3R\3S\3S\3S\3S\3S\3T\3"+
"\3\66\3\66\3\66\3\67\3\67\3\67\3\67\3\67\38\38\38\38\39\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>\3"+
">\3>\3>\3>\3>\3?\3?\3@\3@\3A\3A\3B\3B\3C\3C\3C\3D\3D\3D\3E\3E\3E\3F\3"+
"F\3F\3G\3G\3G\3H\3H\3H\3I\3I\3I\3J\3J\3J\3K\3K\3K\3K\3K\3L\3L\3L\3L\3"+
"L\3L\3M\3M\3M\3M\3M\3N\3N\3N\3N\3O\3O\3O\3P\3P\3Q\3Q\3R\3R\3S\3S\3S\3"+
"T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3U\3V\3V\3V\3V\3V\3V\3W\3W\3W\3W\3W\3W\3"+
"X\3X\3X\3X\3X\3X\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_\7_\u0266\n_\f_\16_\u0269"+
"\13_\3_\3_\3_\3_\3`\3`\7`\u0271\n`\f`\16`\u0274\13`\3`\3`\3a\3a\3a\3a"+
"\3b\6b\u027d\nb\rb\16b\u027e\3c\3c\7c\u0283\nc\fc\16c\u0286\13c\3d\3d"+
"\3d\6d\u028b\nd\rd\16d\u028c\5d\u028f\nd\3e\3e\6e\u0293\ne\re\16e\u0294"+
"\3f\3f\6f\u0299\nf\rf\16f\u029a\3g\3g\3g\5g\u02a0\ng\3g\5g\u02a3\ng\3"+
"h\6h\u02a6\nh\rh\16h\u02a7\3h\3h\6h\u02ac\nh\rh\16h\u02ad\5h\u02b0\nh"+
"\3i\3i\3i\3i\5i\u02b6\ni\3j\3j\3j\7j\u02bb\nj\fj\16j\u02be\13j\3j\3j\3"+
"j\3k\3k\3k\3k\6k\u02c7\nk\rk\16k\u02c8\3k\3k\3k\3k\3k\3\u02c8\2l\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\u0085D\u0087E\u0089F\u008bG\u008dH\u008f"+
"[\3\\\3\\\3\\\3\\\3\\\3\\\3]\3]\3]\3]\3^\3^\3^\3_\3_\7_\u0266\n_\f_\16"+
"_\u0269\13_\3_\3_\3_\3_\3`\3`\7`\u0271\n`\f`\16`\u0274\13`\3`\3`\3a\3"+
"a\3a\3a\3b\6b\u027d\nb\rb\16b\u027e\3c\3c\7c\u0283\nc\fc\16c\u0286\13"+
"c\3d\3d\3d\6d\u028b\nd\rd\16d\u028c\5d\u028f\nd\3e\3e\6e\u0293\ne\re\16"+
"e\u0294\3f\3f\6f\u0299\nf\rf\16f\u029a\3g\3g\3g\5g\u02a0\ng\3g\5g\u02a3"+
"\ng\3h\6h\u02a6\nh\rh\16h\u02a7\3h\3h\6h\u02ac\nh\rh\16h\u02ad\5h\u02b0"+
"\nh\3i\3i\3i\3i\5i\u02b6\ni\3j\3j\3j\7j\u02bb\nj\fj\16j\u02be\13j\3j\3"+
"j\3j\3k\3k\3k\3k\6k\u02c7\nk\rk\16k\u02c8\3k\3k\3k\3k\3k\3\u02c8\2l\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\67m8o9"+
"q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008f"+
"I\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3"+
"S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7"+
"]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9f\u00cb"+
@ -256,18 +256,18 @@ public class prog8Lexer extends Lexer {
"\u0195\3\2\2\2M\u0197\3\2\2\2O\u0199\3\2\2\2Q\u019b\3\2\2\2S\u019e\3\2"+
"\2\2U\u01a0\3\2\2\2W\u01a2\3\2\2\2Y\u01a4\3\2\2\2[\u01a6\3\2\2\2]\u01a8"+
"\3\2\2\2_\u01ab\3\2\2\2a\u01ae\3\2\2\2c\u01b1\3\2\2\2e\u01b4\3\2\2\2g"+
"\u01b6\3\2\2\2i\u01b8\3\2\2\2k\u01ba\3\2\2\2m\u01bd\3\2\2\2o\u01c1\3\2"+
"\2\2q\u01c4\3\2\2\2s\u01c8\3\2\2\2u\u01cc\3\2\2\2w\u01d3\3\2\2\2y\u01d9"+
"\3\2\2\2{\u01e2\3\2\2\2}\u01e4\3\2\2\2\177\u01e6\3\2\2\2\u0081\u01e8\3"+
"\2\2\2\u0083\u01ea\3\2\2\2\u0085\u01ed\3\2\2\2\u0087\u01f0\3\2\2\2\u0089"+
"\u01f3\3\2\2\2\u008b\u01f6\3\2\2\2\u008d\u01f9\3\2\2\2\u008f\u01fc\3\2"+
"\2\2\u0091\u01ff\3\2\2\2\u0093\u0202\3\2\2\2\u0095\u0207\3\2\2\2\u0097"+
"\u020d\3\2\2\2\u0099\u0212\3\2\2\2\u009b\u0216\3\2\2\2\u009d\u0219\3\2"+
"\2\2\u009f\u021b\3\2\2\2\u00a1\u021d\3\2\2\2\u00a3\u021f\3\2\2\2\u00a5"+
"\u0222\3\2\2\2\u00a7\u0227\3\2\2\2\u00a9\u022d\3\2\2\2\u00ab\u0233\3\2"+
"\2\2\u00ad\u0239\3\2\2\2\u00af\u023f\3\2\2\2\u00b1\u0245\3\2\2\2\u00b3"+
"\u024b\3\2\2\2\u00b5\u0251\3\2\2\2\u00b7\u0257\3\2\2\2\u00b9\u025b\3\2"+
"\2\2\u00bb\u025e\3\2\2\2\u00bd\u0263\3\2\2\2\u00bf\u026e\3\2\2\2\u00c1"+
"\u01b6\3\2\2\2i\u01b8\3\2\2\2k\u01ba\3\2\2\2m\u01bd\3\2\2\2o\u01c2\3\2"+
"\2\2q\u01c6\3\2\2\2s\u01c9\3\2\2\2u\u01cd\3\2\2\2w\u01d1\3\2\2\2y\u01d8"+
"\3\2\2\2{\u01de\3\2\2\2}\u01e7\3\2\2\2\177\u01e9\3\2\2\2\u0081\u01eb\3"+
"\2\2\2\u0083\u01ed\3\2\2\2\u0085\u01ef\3\2\2\2\u0087\u01f2\3\2\2\2\u0089"+
"\u01f5\3\2\2\2\u008b\u01f8\3\2\2\2\u008d\u01fb\3\2\2\2\u008f\u01fe\3\2"+
"\2\2\u0091\u0201\3\2\2\2\u0093\u0204\3\2\2\2\u0095\u0207\3\2\2\2\u0097"+
"\u020c\3\2\2\2\u0099\u0212\3\2\2\2\u009b\u0217\3\2\2\2\u009d\u021b\3\2"+
"\2\2\u009f\u021e\3\2\2\2\u00a1\u0220\3\2\2\2\u00a3\u0222\3\2\2\2\u00a5"+
"\u0224\3\2\2\2\u00a7\u0227\3\2\2\2\u00a9\u022c\3\2\2\2\u00ab\u0232\3\2"+
"\2\2\u00ad\u0238\3\2\2\2\u00af\u023e\3\2\2\2\u00b1\u0244\3\2\2\2\u00b3"+
"\u024a\3\2\2\2\u00b5\u0250\3\2\2\2\u00b7\u0256\3\2\2\2\u00b9\u025c\3\2"+
"\2\2\u00bb\u0260\3\2\2\2\u00bd\u0263\3\2\2\2\u00bf\u026e\3\2\2\2\u00c1"+
"\u0277\3\2\2\2\u00c3\u027c\3\2\2\2\u00c5\u0280\3\2\2\2\u00c7\u028e\3\2"+
"\2\2\u00c9\u0290\3\2\2\2\u00cb\u0296\3\2\2\2\u00cd\u029c\3\2\2\2\u00cf"+
"\u02a5\3\2\2\2\u00d1\u02b5\3\2\2\2\u00d3\u02b7\3\2\2\2\u00d5\u02c2\3\2"+
@ -330,51 +330,51 @@ public class prog8Lexer extends Lexer {
"\7?\2\2\u01af\u01b0\7?\2\2\u01b0b\3\2\2\2\u01b1\u01b2\7#\2\2\u01b2\u01b3"+
"\7?\2\2\u01b3d\3\2\2\2\u01b4\u01b5\7(\2\2\u01b5f\3\2\2\2\u01b6\u01b7\7"+
"`\2\2\u01b7h\3\2\2\2\u01b8\u01b9\7~\2\2\u01b9j\3\2\2\2\u01ba\u01bb\7v"+
"\2\2\u01bb\u01bc\7q\2\2\u01bcl\3\2\2\2\u01bd\u01be\7c\2\2\u01be\u01bf"+
"\7p\2\2\u01bf\u01c0\7f\2\2\u01c0n\3\2\2\2\u01c1\u01c2\7q\2\2\u01c2\u01c3"+
"\7t\2\2\u01c3p\3\2\2\2\u01c4\u01c5\7z\2\2\u01c5\u01c6\7q\2\2\u01c6\u01c7"+
"\7t\2\2\u01c7r\3\2\2\2\u01c8\u01c9\7p\2\2\u01c9\u01ca\7q\2\2\u01ca\u01cb"+
"\7v\2\2\u01cbt\3\2\2\2\u01cc\u01cd\7t\2\2\u01cd\u01ce\7g\2\2\u01ce\u01cf"+
"\7v\2\2\u01cf\u01d0\7w\2\2\u01d0\u01d1\7t\2\2\u01d1\u01d2\7p\2\2\u01d2"+
"v\3\2\2\2\u01d3\u01d4\7d\2\2\u01d4\u01d5\7t\2\2\u01d5\u01d6\7g\2\2\u01d6"+
"\u01d7\7c\2\2\u01d7\u01d8\7m\2\2\u01d8x\3\2\2\2\u01d9\u01da\7e\2\2\u01da"+
"\u01db\7q\2\2\u01db\u01dc\7p\2\2\u01dc\u01dd\7v\2\2\u01dd\u01de\7k\2\2"+
"\u01de\u01df\7p\2\2\u01df\u01e0\7w\2\2\u01e0\u01e1\7g\2\2\u01e1z\3\2\2"+
"\2\u01e2\u01e3\7\60\2\2\u01e3|\3\2\2\2\u01e4\u01e5\7C\2\2\u01e5~\3\2\2"+
"\2\u01e6\u01e7\7Z\2\2\u01e7\u0080\3\2\2\2\u01e8\u01e9\7[\2\2\u01e9\u0082"+
"\3\2\2\2\u01ea\u01eb\7C\2\2\u01eb\u01ec\7Z\2\2\u01ec\u0084\3\2\2\2\u01ed"+
"\u01ee\7C\2\2\u01ee\u01ef\7[\2\2\u01ef\u0086\3\2\2\2\u01f0\u01f1\7Z\2"+
"\2\u01f1\u01f2\7[\2\2\u01f2\u0088\3\2\2\2\u01f3\u01f4\7R\2\2\u01f4\u01f5"+
"\7e\2\2\u01f5\u008a\3\2\2\2\u01f6\u01f7\7R\2\2\u01f7\u01f8\7|\2\2\u01f8"+
"\u008c\3\2\2\2\u01f9\u01fa\7R\2\2\u01fa\u01fb\7p\2\2\u01fb\u008e\3\2\2"+
"\2\u01fc\u01fd\7R\2\2\u01fd\u01fe\7x\2\2\u01fe\u0090\3\2\2\2\u01ff\u0200"+
"\7\60\2\2\u0200\u0201\7y\2\2\u0201\u0092\3\2\2\2\u0202\u0203\7v\2\2\u0203"+
"\u0204\7t\2\2\u0204\u0205\7w\2\2\u0205\u0206\7g\2\2\u0206\u0094\3\2\2"+
"\2\u0207\u0208\7h\2\2\u0208\u0209\7c\2\2\u0209\u020a\7n\2\2\u020a\u020b"+
"\7u\2\2\u020b\u020c\7g\2\2\u020c\u0096\3\2\2\2\u020d\u020e\7\'\2\2\u020e"+
"\u020f\7c\2\2\u020f\u0210\7u\2\2\u0210\u0211\7o\2\2\u0211\u0098\3\2\2"+
"\2\u0212\u0213\7u\2\2\u0213\u0214\7w\2\2\u0214\u0215\7d\2\2\u0215\u009a"+
"\3\2\2\2\u0216\u0217\7/\2\2\u0217\u0218\7@\2\2\u0218\u009c\3\2\2\2\u0219"+
"\u021a\7}\2\2\u021a\u009e\3\2\2\2\u021b\u021c\7\177\2\2\u021c\u00a0\3"+
"\2\2\2\u021d\u021e\7A\2\2\u021e\u00a2\3\2\2\2\u021f\u0220\7k\2\2\u0220"+
"\u0221\7h\2\2\u0221\u00a4\3\2\2\2\u0222\u0223\7g\2\2\u0223\u0224\7n\2"+
"\2\u0224\u0225\7u\2\2\u0225\u0226\7g\2\2\u0226\u00a6\3\2\2\2\u0227\u0228"+
"\7k\2\2\u0228\u0229\7h\2\2\u0229\u022a\7a\2\2\u022a\u022b\7e\2\2\u022b"+
"\u022c\7u\2\2\u022c\u00a8\3\2\2\2\u022d\u022e\7k\2\2\u022e\u022f\7h\2"+
"\2\u022f\u0230\7a\2\2\u0230\u0231\7e\2\2\u0231\u0232\7e\2\2\u0232\u00aa"+
"\3\2\2\2\u0233\u0234\7k\2\2\u0234\u0235\7h\2\2\u0235\u0236\7a\2\2\u0236"+
"\u0237\7g\2\2\u0237\u0238\7s\2\2\u0238\u00ac\3\2\2\2\u0239\u023a\7k\2"+
"\2\u023a\u023b\7h\2\2\u023b\u023c\7a\2\2\u023c\u023d\7p\2\2\u023d\u023e"+
"\7g\2\2\u023e\u00ae\3\2\2\2\u023f\u0240\7k\2\2\u0240\u0241\7h\2\2\u0241"+
"\u0242\7a\2\2\u0242\u0243\7r\2\2\u0243\u0244\7n\2\2\u0244\u00b0\3\2\2"+
"\2\u0245\u0246\7k\2\2\u0246\u0247\7h\2\2\u0247\u0248\7a\2\2\u0248\u0249"+
"\7o\2\2\u0249\u024a\7k\2\2\u024a\u00b2\3\2\2\2\u024b\u024c\7k\2\2\u024c"+
"\u024d\7h\2\2\u024d\u024e\7a\2\2\u024e\u024f\7x\2\2\u024f\u0250\7u\2\2"+
"\u0250\u00b4\3\2\2\2\u0251\u0252\7k\2\2\u0252\u0253\7h\2\2\u0253\u0254"+
"\7a\2\2\u0254\u0255\7x\2\2\u0255\u0256\7e\2\2\u0256\u00b6\3\2\2\2\u0257"+
"\u0258\7h\2\2\u0258\u0259\7q\2\2\u0259\u025a\7t\2\2\u025a\u00b8\3\2\2"+
"\2\u025b\u025c\7k\2\2\u025c\u025d\7p\2\2\u025d\u00ba\3\2\2\2\u025e\u025f"+
"\7u\2\2\u025f\u0260\7v\2\2\u0260\u0261\7g\2\2\u0261\u0262\7r\2\2\u0262"+
"\2\2\u01bb\u01bc\7q\2\2\u01bcl\3\2\2\2\u01bd\u01be\7u\2\2\u01be\u01bf"+
"\7v\2\2\u01bf\u01c0\7g\2\2\u01c0\u01c1\7r\2\2\u01c1n\3\2\2\2\u01c2\u01c3"+
"\7c\2\2\u01c3\u01c4\7p\2\2\u01c4\u01c5\7f\2\2\u01c5p\3\2\2\2\u01c6\u01c7"+
"\7q\2\2\u01c7\u01c8\7t\2\2\u01c8r\3\2\2\2\u01c9\u01ca\7z\2\2\u01ca\u01cb"+
"\7q\2\2\u01cb\u01cc\7t\2\2\u01cct\3\2\2\2\u01cd\u01ce\7p\2\2\u01ce\u01cf"+
"\7q\2\2\u01cf\u01d0\7v\2\2\u01d0v\3\2\2\2\u01d1\u01d2\7t\2\2\u01d2\u01d3"+
"\7g\2\2\u01d3\u01d4\7v\2\2\u01d4\u01d5\7w\2\2\u01d5\u01d6\7t\2\2\u01d6"+
"\u01d7\7p\2\2\u01d7x\3\2\2\2\u01d8\u01d9\7d\2\2\u01d9\u01da\7t\2\2\u01da"+
"\u01db\7g\2\2\u01db\u01dc\7c\2\2\u01dc\u01dd\7m\2\2\u01ddz\3\2\2\2\u01de"+
"\u01df\7e\2\2\u01df\u01e0\7q\2\2\u01e0\u01e1\7p\2\2\u01e1\u01e2\7v\2\2"+
"\u01e2\u01e3\7k\2\2\u01e3\u01e4\7p\2\2\u01e4\u01e5\7w\2\2\u01e5\u01e6"+
"\7g\2\2\u01e6|\3\2\2\2\u01e7\u01e8\7\60\2\2\u01e8~\3\2\2\2\u01e9\u01ea"+
"\7C\2\2\u01ea\u0080\3\2\2\2\u01eb\u01ec\7Z\2\2\u01ec\u0082\3\2\2\2\u01ed"+
"\u01ee\7[\2\2\u01ee\u0084\3\2\2\2\u01ef\u01f0\7C\2\2\u01f0\u01f1\7Z\2"+
"\2\u01f1\u0086\3\2\2\2\u01f2\u01f3\7C\2\2\u01f3\u01f4\7[\2\2\u01f4\u0088"+
"\3\2\2\2\u01f5\u01f6\7Z\2\2\u01f6\u01f7\7[\2\2\u01f7\u008a\3\2\2\2\u01f8"+
"\u01f9\7R\2\2\u01f9\u01fa\7e\2\2\u01fa\u008c\3\2\2\2\u01fb\u01fc\7R\2"+
"\2\u01fc\u01fd\7|\2\2\u01fd\u008e\3\2\2\2\u01fe\u01ff\7R\2\2\u01ff\u0200"+
"\7p\2\2\u0200\u0090\3\2\2\2\u0201\u0202\7R\2\2\u0202\u0203\7x\2\2\u0203"+
"\u0092\3\2\2\2\u0204\u0205\7\60\2\2\u0205\u0206\7y\2\2\u0206\u0094\3\2"+
"\2\2\u0207\u0208\7v\2\2\u0208\u0209\7t\2\2\u0209\u020a\7w\2\2\u020a\u020b"+
"\7g\2\2\u020b\u0096\3\2\2\2\u020c\u020d\7h\2\2\u020d\u020e\7c\2\2\u020e"+
"\u020f\7n\2\2\u020f\u0210\7u\2\2\u0210\u0211\7g\2\2\u0211\u0098\3\2\2"+
"\2\u0212\u0213\7\'\2\2\u0213\u0214\7c\2\2\u0214\u0215\7u\2\2\u0215\u0216"+
"\7o\2\2\u0216\u009a\3\2\2\2\u0217\u0218\7u\2\2\u0218\u0219\7w\2\2\u0219"+
"\u021a\7d\2\2\u021a\u009c\3\2\2\2\u021b\u021c\7/\2\2\u021c\u021d\7@\2"+
"\2\u021d\u009e\3\2\2\2\u021e\u021f\7}\2\2\u021f\u00a0\3\2\2\2\u0220\u0221"+
"\7\177\2\2\u0221\u00a2\3\2\2\2\u0222\u0223\7A\2\2\u0223\u00a4\3\2\2\2"+
"\u0224\u0225\7k\2\2\u0225\u0226\7h\2\2\u0226\u00a6\3\2\2\2\u0227\u0228"+
"\7g\2\2\u0228\u0229\7n\2\2\u0229\u022a\7u\2\2\u022a\u022b\7g\2\2\u022b"+
"\u00a8\3\2\2\2\u022c\u022d\7k\2\2\u022d\u022e\7h\2\2\u022e\u022f\7a\2"+
"\2\u022f\u0230\7e\2\2\u0230\u0231\7u\2\2\u0231\u00aa\3\2\2\2\u0232\u0233"+
"\7k\2\2\u0233\u0234\7h\2\2\u0234\u0235\7a\2\2\u0235\u0236\7e\2\2\u0236"+
"\u0237\7e\2\2\u0237\u00ac\3\2\2\2\u0238\u0239\7k\2\2\u0239\u023a\7h\2"+
"\2\u023a\u023b\7a\2\2\u023b\u023c\7g\2\2\u023c\u023d\7s\2\2\u023d\u00ae"+
"\3\2\2\2\u023e\u023f\7k\2\2\u023f\u0240\7h\2\2\u0240\u0241\7a\2\2\u0241"+
"\u0242\7p\2\2\u0242\u0243\7g\2\2\u0243\u00b0\3\2\2\2\u0244\u0245\7k\2"+
"\2\u0245\u0246\7h\2\2\u0246\u0247\7a\2\2\u0247\u0248\7r\2\2\u0248\u0249"+
"\7n\2\2\u0249\u00b2\3\2\2\2\u024a\u024b\7k\2\2\u024b\u024c\7h\2\2\u024c"+
"\u024d\7a\2\2\u024d\u024e\7o\2\2\u024e\u024f\7k\2\2\u024f\u00b4\3\2\2"+
"\2\u0250\u0251\7k\2\2\u0251\u0252\7h\2\2\u0252\u0253\7a\2\2\u0253\u0254"+
"\7x\2\2\u0254\u0255\7u\2\2\u0255\u00b6\3\2\2\2\u0256\u0257\7k\2\2\u0257"+
"\u0258\7h\2\2\u0258\u0259\7a\2\2\u0259\u025a\7x\2\2\u025a\u025b\7e\2\2"+
"\u025b\u00b8\3\2\2\2\u025c\u025d\7h\2\2\u025d\u025e\7q\2\2\u025e\u025f"+
"\7t\2\2\u025f\u00ba\3\2\2\2\u0260\u0261\7k\2\2\u0261\u0262\7p\2\2\u0262"+
"\u00bc\3\2\2\2\u0263\u0267\t\2\2\2\u0264\u0266\t\3\2\2\u0265\u0264\3\2"+
"\2\2\u0266\u0269\3\2\2\2\u0267\u0265\3\2\2\2\u0267\u0268\3\2\2\2\u0268"+
"\u026a\3\2\2\2\u0269\u0267\3\2\2\2\u026a\u026b\5\u00bf`\2\u026b\u026c"+

File diff suppressed because it is too large Load Diff