mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
improved handling of range and range type checks
This commit is contained in:
parent
266f98a888
commit
3c7a233b43
@ -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 :
|
||||
|
@ -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
|
||||
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user