Compare commits

...
15 Commits
45 changed files with 1414 additions and 1285 deletions

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
**/.idea/
.idea/workspace.xml
/build/
/dist/
/output/
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="/usr/share/java/gradle" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/compiler" />
<option value="$PROJECT_DIR$/parser" />
</set>
</option>
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/docs/docs.iml" filepath="$PROJECT_DIR$/docs/docs.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+27 -3
View File
@@ -18,11 +18,18 @@ dependencies {
runtime 'org.antlr:antlr4-runtime:4.7.2'
runtime project(':parser')
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:$kotlinVersion"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:$kotlinVersion"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.2'
testImplementation 'org.hamcrest:hamcrest-junit:2.0.0.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.2'
}
compileKotlin {
kotlinOptions {
jvmTarget = "1.8"
}
}
sourceSets {
main {
@@ -55,8 +62,8 @@ task p8vmScript(type: CreateStartScripts) {
}
applicationDistribution.into("bin") {
from(p8vmScript)
fileMode = 0755
from(p8vmScript)
fileMode = 0755
}
task fatJar(type: Jar) {
@@ -71,3 +78,20 @@ task fatJar(type: Jar) {
with jar
}
// build.finalizedBy(fatJar)
// Java target version
sourceCompatibility = 1.8
test {
// Enable JUnit 5 (Gradle 4.6+).
useJUnitPlatform()
// Always run tests, even when nothing changed.
dependsOn 'cleanTest'
// Show test results.
testLogging {
events "passed", "skipped", "failed"
}
}
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="library" name="antlr-runtime-4.7.2" level="project" />
<orderEntry type="library" name="testlibs" level="project" />
<orderEntry type="module" module-name="parser" />
</component>
</module>
+1 -1
View File
@@ -1 +1 @@
1.6
1.7
+47 -34
View File
@@ -156,7 +156,7 @@ interface IAstProcessor {
fun process(decl: VarDecl): IStatement {
decl.value = decl.value?.process(this)
decl.arrayspec?.process(this)
decl.arraysize?.process(this)
return decl
}
@@ -628,30 +628,30 @@ class Break(override val position: Position) : IStatement {
}
class ArraySpec(var x: IExpression, override val position: Position) : Node {
class ArrayIndex(var index: IExpression, override val position: Position) : Node {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
this.parent = parent
x.linkParents(this)
index.linkParents(this)
}
companion object {
fun forArray(v: LiteralValue, heap: HeapValues): ArraySpec {
fun forArray(v: LiteralValue, heap: HeapValues): ArrayIndex {
val arraySize = v.arrayvalue?.size ?: heap.get(v.heapId!!).arraysize
return ArraySpec(LiteralValue.optimalNumeric(arraySize, v.position), v.position)
return ArrayIndex(LiteralValue.optimalNumeric(arraySize, v.position), v.position)
}
}
fun process(processor: IAstProcessor) {
x = x.process(processor)
index = index.process(processor)
}
override fun toString(): String {
return("ArraySpec($x, pos=$position)")
return("ArrayIndex($index, pos=$position)")
}
fun size() = (x as? LiteralValue)?.asIntegerValue
fun size() = (index as? LiteralValue)?.asIntegerValue
}
@@ -664,7 +664,8 @@ enum class VarDeclType {
class VarDecl(val type: VarDeclType,
private val declaredDatatype: DataType,
val zeropage: Boolean,
val arrayspec: ArraySpec?,
var arraysize: ArrayIndex?,
val isUnsizedArray: Boolean,
val name: String,
var value: IExpression?,
override val position: Position) : IStatement {
@@ -672,7 +673,7 @@ class VarDecl(val type: VarDeclType,
val datatypeErrors = mutableListOf<SyntaxError>() // don't crash at init time, report them in the AstChecker
val datatype =
if (arrayspec == null) declaredDatatype
if (arraysize == null && !isUnsizedArray) declaredDatatype
else when (declaredDatatype) {
DataType.UBYTE -> DataType.ARRAY_UB
DataType.BYTE -> DataType.ARRAY_B
@@ -687,7 +688,7 @@ class VarDecl(val type: VarDeclType,
override fun linkParents(parent: Node) {
this.parent = parent
arrayspec?.linkParents(this)
arraysize?.linkParents(this)
value?.linkParents(this)
}
@@ -708,7 +709,7 @@ class VarDecl(val type: VarDeclType,
DataType.FLOAT -> LiteralValue(DataType.FLOAT, floatvalue=0.0, position=position)
else -> throw FatalAstException("can only set a default value for a numeric type")
}
val decl = VarDecl(type, declaredDatatype, zeropage, arrayspec, name, constValue, position)
val decl = VarDecl(type, declaredDatatype, zeropage, arraysize, isUnsizedArray, name, constValue, position)
if(parent!=null)
decl.linkParents(parent)
return decl
@@ -805,6 +806,9 @@ data class AssignTarget(val register: Register?,
return (if(withTypePrefix) "1address::" else "") +address.asIntegerValue.toString()
return if(withTypePrefix) "???::???" else "???"
}
fun isMemoryMapped(namespace: INameScope): Boolean =
memoryAddress!=null || (identifier?.targetVarDecl(namespace)?.type==VarDeclType.MEMORY)
}
@@ -951,7 +955,7 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
}
class ArrayIndexedExpression(val identifier: IdentifierReference,
var arrayspec: ArraySpec,
var arrayspec: ArrayIndex,
override val position: Position) : IExpression {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
@@ -983,7 +987,7 @@ class ArrayIndexedExpression(val identifier: IdentifierReference,
}
override fun toString(): String {
return "ArrayIndexed(ident=$identifier, arrayspec=$arrayspec; pos=$position)"
return "ArrayIndexed(ident=$identifier, arraysize=$arrayspec; pos=$position)"
}
}
@@ -1186,8 +1190,8 @@ class LiteralValue(val type: DataType,
else "str:$initialstrvalue"
}
in ArrayDatatypes -> {
if(heapId!=null) "arrayspec:#$heapId"
else "arrayspec:$arrayvalue"
if(heapId!=null) "array:#$heapId"
else "array:$arrayvalue"
}
else -> throw FatalAstException("weird datatype")
}
@@ -1410,13 +1414,15 @@ class RegisterExpr(val register: Register, override val position: Position) : IE
data class IdentifierReference(val nameInSource: List<String>, override val position: Position) : IExpression {
override lateinit var parent: Node
// TODO make a shortcut for idref.targetStatement(namespace) as VarDecl
fun targetStatement(namespace: INameScope) =
if(nameInSource.size==1 && nameInSource[0] in BuiltinFunctions)
BuiltinFunctionStatementPlaceholder(nameInSource[0], position)
else
namespace.lookup(nameInSource, this)
fun targetVarDecl(namespace: INameScope): VarDecl? = targetStatement(namespace) as? VarDecl
fun targetSubroutine(namespace: INameScope): Subroutine? = targetStatement(namespace) as? Subroutine
override fun linkParents(parent: Node) {
this.parent = parent
}
@@ -1853,40 +1859,47 @@ private fun prog8Parser.StatementContext.toAst() : IStatement {
return VarDecl(VarDeclType.VAR,
it.datatype().toAst(),
it.ZEROPAGE()!=null,
it.arrayspec()?.toAst(),
it.arrayindex()?.toAst(),
it.ARRAYSIG()!=null,
it.identifier().text,
null,
it.toPosition())
}
varinitializer()?.let {
val vd = it.vardecl()
return VarDecl(VarDeclType.VAR,
it.vardecl().datatype().toAst(),
it.vardecl().ZEROPAGE()!=null,
it.vardecl().arrayspec()?.toAst(),
it.vardecl().identifier().text,
vd.datatype().toAst(),
vd.ZEROPAGE()!=null,
vd.arrayindex()?.toAst(),
vd.ARRAYSIG()!=null,
vd.identifier().text,
it.expression().toAst(),
it.toPosition())
}
constdecl()?.let {
val cvarinit = it.varinitializer()
val vd = cvarinit.vardecl()
return VarDecl(VarDeclType.CONST,
cvarinit.vardecl().datatype().toAst(),
cvarinit.vardecl().ZEROPAGE()!=null,
cvarinit.vardecl().arrayspec()?.toAst(),
cvarinit.vardecl().identifier().text,
vd.datatype().toAst(),
vd.ZEROPAGE()!=null,
vd.arrayindex()?.toAst(),
vd.ARRAYSIG()!=null,
vd.identifier().text,
cvarinit.expression().toAst(),
cvarinit.toPosition())
}
memoryvardecl()?.let {
val mvarinit = it.varinitializer()
val vd = mvarinit.vardecl()
return VarDecl(VarDeclType.MEMORY,
mvarinit.vardecl().datatype().toAst(),
mvarinit.vardecl().ZEROPAGE()!=null,
mvarinit.vardecl().arrayspec()?.toAst(),
mvarinit.vardecl().identifier().text,
vd.datatype().toAst(),
vd.ZEROPAGE()!=null,
vd.arrayindex()?.toAst(),
vd.ARRAYSIG()!=null,
vd.identifier().text,
mvarinit.expression().toAst(),
mvarinit.toPosition())
}
@@ -2082,8 +2095,8 @@ private fun prog8Parser.DatatypeContext.toAst() = DataType.valueOf(text.toUpperC
private fun prog8Parser.RegisterorpairContext.toAst() = RegisterOrPair.valueOf(text.toUpperCase())
private fun prog8Parser.ArrayspecContext.toAst() : ArraySpec =
ArraySpec(expression().toAst(), toPosition())
private fun prog8Parser.ArrayindexContext.toAst() : ArrayIndex =
ArrayIndex(expression().toAst(), toPosition())
private fun prog8Parser.DirectiveContext.toAst() : Directive =
@@ -2176,7 +2189,7 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
}
litval.arrayliteral()!=null -> {
val array = litval.arrayliteral()?.toAst()
// the actual type of the arrayspec can not yet be determined here (missing namespace & heap)
// the actual type of the arraysize can not yet be determined here (missing namespace & heap)
// the ConstantFolder takes care of that and converts the type if needed.
LiteralValue(DataType.ARRAY_UB, arrayvalue = array, position = litval.toPosition())
}
@@ -2226,7 +2239,7 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
private fun prog8Parser.ArrayindexedContext.toAst(): ArrayIndexedExpression {
return ArrayIndexedExpression(scoped_identifier().toAst(),
arrayspec().toAst(),
arrayindex().toAst(),
toPosition())
}
+56 -26
View File
@@ -7,6 +7,7 @@ import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE
import prog8.functions.BuiltinFunctions
import prog8.optimizing.same
import prog8.parser.ParsingFailedError
import java.io.File
/**
* General checks on the Ast
@@ -150,7 +151,7 @@ private class AstChecker(private val namespace: INameScope,
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
} else {
// loop variable
val loopvar = forLoop.loopVar!!.targetStatement(namespace) as? VarDecl
val loopvar = forLoop.loopVar!!.targetVarDecl(namespace)
if(loopvar==null || loopvar.type==VarDeclType.CONST) {
checkResult.add(SyntaxError("for loop requires a variable to loop with", forLoop.position))
@@ -430,10 +431,10 @@ private class AstChecker(private val namespace: INameScope,
if(constVal!=null) {
val arrayspec = if(target.identifier!=null) {
val targetVar = namespace.lookup(target.identifier.nameInSource, assignment) as? VarDecl
targetVar?.arrayspec
targetVar?.arraysize
} else null
checkValueTypeAndRange(targetDatatype,
arrayspec ?: ArraySpec(LiteralValue.optimalInteger(-1, assignment.position), assignment.position),
arrayspec ?: ArrayIndex(LiteralValue.optimalInteger(-1, assignment.position), assignment.position),
constVal, heap)
} else {
val sourceDatatype: DataType? = assignment.value.resultingDatatype(namespace, heap)
@@ -456,7 +457,7 @@ private class AstChecker(private val namespace: INameScope,
}
override fun process(addressOf: AddressOf): IExpression {
val variable=addressOf.identifier.targetStatement(namespace) as? VarDecl
val variable=addressOf.identifier.targetVarDecl(namespace)
if(variable==null)
checkResult.add(ExpressionError("pointer-of operand must be the name of a heap variable", addressOf.position))
else {
@@ -477,7 +478,7 @@ private class AstChecker(private val namespace: INameScope,
}
// the initializer value can't refer to the variable itself (recursive definition)
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arrayspec?.x?.referencesIdentifier(decl.name) == true) {
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.index?.referencesIdentifier(decl.name) == true) {
err("recursive var declaration")
}
@@ -492,6 +493,22 @@ private class AstChecker(private val namespace: INameScope,
checkResult.add(SyntaxError("floating point used, but that is not enabled via options", decl.position))
}
// ARRAY without size specifier MUST have an iterable initializer value
if(decl.isUnsizedArray) {
if(decl.type==VarDeclType.MEMORY)
checkResult.add(SyntaxError("memory mapped array must have a size specification", decl.position))
if(decl.value==null) {
checkResult.add(SyntaxError("array variable is missing a size specification or an initialization value", decl.position))
return decl
}
if(decl.value is LiteralValue && !(decl.value as LiteralValue).isArray) {
checkResult.add(SyntaxError("unsized array declaration cannot use a single literal initialization value", decl.position))
return decl
}
if(decl.value is RangeExpr)
throw FatalAstException("range expressions in vardecls should have been converted into array values during constFolding $decl")
}
when(decl.type) {
VarDeclType.VAR, VarDeclType.CONST -> {
if (decl.value == null) {
@@ -513,13 +530,16 @@ private class AstChecker(private val namespace: INameScope,
return super.process(decl)
}
when {
decl.value is RangeExpr -> checkValueTypeAndRange(decl.datatype, decl.arrayspec, decl.value as RangeExpr)
decl.value is RangeExpr -> {
if(!decl.isUnsizedArray)
checkValueTypeAndRange(decl.datatype, decl.arraysize!!, decl.value as RangeExpr)
}
decl.value is LiteralValue -> {
val arraySpec = decl.arrayspec ?: (
val arraySpec = decl.arraysize ?: (
if((decl.value as LiteralValue).isArray)
ArraySpec.forArray(decl.value as LiteralValue, heap)
ArrayIndex.forArray(decl.value as LiteralValue, heap)
else
ArraySpec(LiteralValue.optimalInteger(-2, decl.position), decl.position)
ArrayIndex(LiteralValue.optimalInteger(-2, decl.position), decl.position)
)
checkValueTypeAndRange(decl.datatype, arraySpec, decl.value as LiteralValue, heap)
}
@@ -530,8 +550,8 @@ private class AstChecker(private val namespace: INameScope,
}
}
VarDeclType.MEMORY -> {
if(decl.arrayspec!=null) {
val arraySize = decl.arrayspec.size() ?: 1
if(decl.arraysize!=null) {
val arraySize = decl.arraysize!!.size() ?: 1
when(decl.datatype) {
DataType.ARRAY_B, DataType.ARRAY_UB ->
if(arraySize > 256)
@@ -613,6 +633,7 @@ private class AstChecker(private val namespace: INameScope,
if(directive.parent !is INameScope || directive.parent is Module) err("this directive may only occur in a block")
if(directive.args.size!=2 || directive.args[0].str==null || directive.args[1].str==null)
err("invalid asminclude directive, expected arguments: \"filename\", \"scopelabel\"")
checkFileExists(directive, directive.args[0].str!!)
}
"%asmbinary" -> {
if(directive.parent !is INameScope || directive.parent is Module) err("this directive may only occur in a block")
@@ -622,6 +643,7 @@ private class AstChecker(private val namespace: INameScope,
if(directive.args.size>=2 && directive.args[1].int==null) err(errormsg)
if(directive.args.size==3 && directive.args[2].int==null) err(errormsg)
if(directive.args.size>3) err(errormsg)
checkFileExists(directive, directive.args[0].str!!)
}
"%option" -> {
if(directive.parent !is Block && directive.parent !is Module) err("this directive may only occur in a block or at module level")
@@ -635,15 +657,23 @@ private class AstChecker(private val namespace: INameScope,
return super.process(directive)
}
private fun checkFileExists(directive: Directive, filename: String) {
var definingModule = directive.parent
while (definingModule !is Module)
definingModule = definingModule.parent
if (!(filename.startsWith("library:") || definingModule.importedFrom.resolveSibling(filename).toFile().isFile || File(filename).isFile))
checkResult.add(NameError("included file not found: $filename", directive.position))
}
override fun process(literalValue: LiteralValue): LiteralValue {
if(!compilerOptions.floats && literalValue.type==DataType.FLOAT) {
checkResult.add(SyntaxError("floating point used, but that is not enabled via options", literalValue.position))
}
val arrayspec =
if(literalValue.isArray)
ArraySpec.forArray(literalValue, heap)
ArrayIndex.forArray(literalValue, heap)
else
ArraySpec(LiteralValue.optimalInteger(-3, literalValue.position), literalValue.position)
ArrayIndex(LiteralValue.optimalInteger(-3, literalValue.position), literalValue.position)
checkValueTypeAndRange(literalValue.type, arrayspec, literalValue, heap)
val lv = super.process(literalValue)
@@ -880,17 +910,17 @@ private class AstChecker(private val namespace: INameScope,
if(target is VarDecl) {
if(target.datatype !in IterableDatatypes)
checkResult.add(SyntaxError("indexing requires an iterable variable", arrayIndexedExpression.position))
val arraysize = target.arrayspec?.size()
val arraysize = target.arraysize?.size()
if(arraysize!=null) {
// check out of bounds
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
val index = (arrayIndexedExpression.arrayspec.index as? LiteralValue)?.asIntegerValue
if(index!=null && (index<0 || index>=arraysize))
checkResult.add(ExpressionError("array index out of bounds", arrayIndexedExpression.arrayspec.position))
} else if(target.datatype in StringDatatypes) {
// check string lengths
val heapId = (target.value as LiteralValue).heapId!!
val stringLen = heap.get(heapId).str!!.length
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
val index = (arrayIndexedExpression.arrayspec.index as? LiteralValue)?.asIntegerValue
if(index!=null && (index<0 || index>=stringLen))
checkResult.add(ExpressionError("index out of bounds", arrayIndexedExpression.arrayspec.position))
}
@@ -898,7 +928,7 @@ private class AstChecker(private val namespace: INameScope,
checkResult.add(SyntaxError("indexing requires a variable to act upon", arrayIndexedExpression.position))
// check index value 0..255
val dtx = arrayIndexedExpression.arrayspec.x.resultingDatatype(namespace, heap)
val dtx = arrayIndexedExpression.arrayspec.index.resultingDatatype(namespace, heap)
if(dtx!=DataType.UBYTE && dtx!=DataType.BYTE)
checkResult.add(SyntaxError("array indexing is limited to byte size 0..255", arrayIndexedExpression.position))
@@ -913,7 +943,7 @@ private class AstChecker(private val namespace: INameScope,
return null
}
private fun checkValueTypeAndRange(targetDt: DataType, arrayspec: ArraySpec?, range: RangeExpr) : Boolean {
private fun checkValueTypeAndRange(targetDt: DataType, arrayspec: ArrayIndex, range: RangeExpr) : Boolean {
val from = range.from.constValue(namespace, heap)
val to = range.to.constValue(namespace, heap)
if(from==null || to==null) {
@@ -941,7 +971,7 @@ private class AstChecker(private val namespace: INameScope,
}
in ArrayDatatypes -> {
// range and length check bytes
val expectedSize = arrayspec!!.size()
val expectedSize = arrayspec.size()
val rangeSize=range.size(heap)
if(rangeSize!=null && rangeSize != expectedSize) {
checkResult.add(ExpressionError("range size doesn't match array size, expected $expectedSize found $rangeSize", range.position))
@@ -953,7 +983,7 @@ private class AstChecker(private val namespace: INameScope,
}
}
private fun checkValueTypeAndRange(targetDt: DataType, arrayspec: ArraySpec, value: LiteralValue, heap: HeapValues) : Boolean {
private fun checkValueTypeAndRange(targetDt: DataType, arrayspec: ArrayIndex, value: LiteralValue, heap: HeapValues) : Boolean {
fun err(msg: String) : Boolean {
checkResult.add(ExpressionError(msg, value.position))
return false
@@ -1009,7 +1039,7 @@ private class AstChecker(private val namespace: INameScope,
return err("string length must be 0-255")
}
DataType.ARRAY_UB, DataType.ARRAY_B -> {
// value may be either a single byte, or a byte arrayspec (of all constant values)
// value may be either a single byte, or a byte arraysize (of all constant values), or a range
if(value.type==targetDt) {
if(!checkArrayValues(value, targetDt))
return false
@@ -1018,7 +1048,7 @@ private class AstChecker(private val namespace: INameScope,
if(arraySpecSize!=null && arraySpecSize>0) {
if(arraySpecSize<1 || arraySpecSize>256)
return err("byte array length must be 1-256")
val constX = arrayspec.x.constValue(namespace, heap)
val constX = arrayspec.index.constValue(namespace, heap)
if(constX?.asIntegerValue==null)
return err("array size specifier must be constant integer value")
val expectedSize = constX.asIntegerValue
@@ -1031,7 +1061,7 @@ private class AstChecker(private val namespace: INameScope,
return err("invalid byte array initialization value ${value.type}, expected $targetDt")
}
DataType.ARRAY_UW, DataType.ARRAY_W -> {
// value may be either a single word, or a word arrayspec
// value may be either a single word, or a word arraysize, or a range
if(value.type==targetDt) {
if(!checkArrayValues(value, targetDt))
return false
@@ -1040,7 +1070,7 @@ private class AstChecker(private val namespace: INameScope,
if(arraySpecSize!=null && arraySpecSize>0) {
if(arraySpecSize<1 || arraySpecSize>128)
return err("word array length must be 1-128")
val constX = arrayspec.x.constValue(namespace, heap)
val constX = arrayspec.index.constValue(namespace, heap)
if(constX?.asIntegerValue==null)
return err("array size specifier must be constant integer value")
val expectedSize = constX.asIntegerValue
@@ -1053,7 +1083,7 @@ private class AstChecker(private val namespace: INameScope,
return err("invalid word array initialization value ${value.type}, expected $targetDt")
}
DataType.ARRAY_F -> {
// value may be either a single float, or a float arrayspec
// value may be either a single float, or a float arraysize
if(value.type==targetDt) {
if(!checkArrayValues(value, targetDt))
return false
@@ -1062,7 +1092,7 @@ private class AstChecker(private val namespace: INameScope,
if(arraySpecSize!=null && arraySpecSize>0) {
if(arraySpecSize < 1 || arraySpecSize>51)
return err("float array length must be 1-51")
val constX = arrayspec.x.constValue(namespace, heap)
val constX = arrayspec.index.constValue(namespace, heap)
if(constX?.asIntegerValue==null)
return err("array size specifier must be constant integer value")
val expectedSize = constX.asIntegerValue
@@ -126,7 +126,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
subroutine.parameters
.filter { it.name !in allDefinedNames }
.forEach {
val vardecl = VarDecl(VarDeclType.VAR, it.type, false, null, it.name, null, subroutine.position)
val vardecl = VarDecl(VarDeclType.VAR, it.type, false, null, false, it.name, null, subroutine.position)
vardecl.linkParents(subroutine)
subroutine.statements.add(0, vardecl)
}
@@ -164,7 +164,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(forLoop.loopVar.nameInSource, forLoop.body.statements.first())
if(existing==null) {
// create the local scoped for loop variable itself
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, true, null, varName, null, forLoop.loopVar.position)
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, true, null, false, varName, null, forLoop.loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
@@ -176,7 +176,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(listOf(ForLoop.iteratorLoopcounterVarname), forLoop.body.statements.first())
if(existing==null) {
// create loop iteration counter variable (without value, to avoid an assignment)
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, true, null, ForLoop.iteratorLoopcounterVarname, null, forLoop.loopVar.position)
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, true, null, false, ForLoop.iteratorLoopcounterVarname, null, forLoop.loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
@@ -224,7 +224,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
if(literalValue.heapId!=null && literalValue.parent !is VarDecl) {
// a literal value that's not declared as a variable, which refers to something on the heap.
// we need to introduce an auto-generated variable for this to be able to refer to the value!
val variable = VarDecl(VarDeclType.VAR, literalValue.type, false, null, "$autoHeapValuePrefix${literalValue.heapId}", literalValue, literalValue.position)
val variable = VarDecl(VarDeclType.VAR, literalValue.type, false, null, false, "$autoHeapValuePrefix${literalValue.heapId}", literalValue, literalValue.position)
anonymousVariablesFromHeap[variable.name] = Pair(literalValue, variable)
}
return super.process(literalValue)
@@ -232,7 +232,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
override fun process(addressOf: AddressOf): IExpression {
// register the scoped name of the referenced identifier
val variable= addressOf.identifier.targetStatement(namespace) as? VarDecl ?: return addressOf
val variable= addressOf.identifier.targetVarDecl(namespace) ?: return addressOf
addressOf.scopedname = variable.scopedname
return super.process(addressOf)
}
+16 -5
View File
@@ -155,12 +155,23 @@ private class StatementReorderer(private val namespace: INameScope, private val
return scope
}
override fun process(decl: VarDecl): IStatement {
if(decl.arraysize==null) {
val array = decl.value as? LiteralValue
if(array!=null && array.isArray) {
val size = heap.get(array.heapId!!).arraysize
decl.arraysize = ArrayIndex(LiteralValue.optimalInteger(size, decl.position), decl.position)
}
}
return super.process(decl)
}
private fun sortConstantAssignments(statements: MutableList<IStatement>) {
// sort assignments by datatype and value, so multiple initializations with the same value can be optimized (to load the value just once)
val result = mutableListOf<IStatement>()
val stmtIter = statements.iterator()
for(stmt in stmtIter) {
if(stmt is Assignment) {
if(stmt is Assignment && !stmt.targets.any { it.isMemoryMapped(namespace) }) {
val constval = stmt.value.constValue(namespace, heap)
if(constval!=null) {
val (sorted, trailing) = sortConstantAssignmentSequence(stmt, stmtIter)
@@ -254,7 +265,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
}
override fun process(functionCall: FunctionCall): IExpression {
val targetStatement = functionCall.target.targetStatement(namespace) as? Subroutine
val targetStatement = functionCall.target.targetSubroutine(namespace)
if(targetStatement!=null) {
var node: Node = functionCall
while(node !is IStatement)
@@ -265,7 +276,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
}
override fun process(functionCallStatement: FunctionCallStatement): IStatement {
val targetStatement = functionCallStatement.target.targetStatement(namespace) as? Subroutine
val targetStatement = functionCallStatement.target.targetSubroutine(namespace)
if(targetStatement!=null)
addAddressOfExprIfNeeded(targetStatement, functionCallStatement.arglist, functionCallStatement)
return functionCallStatement
@@ -280,7 +291,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
val idref = argparam.second as? IdentifierReference
val strvalue = argparam.second as? LiteralValue
if(idref!=null) {
val variable = idref.targetStatement(namespace) as? VarDecl
val variable = idref.targetVarDecl(namespace)
if(variable!=null && (variable.datatype in StringDatatypes || variable.datatype in ArrayDatatypes)) {
val pointerExpr = AddressOf(idref, idref.position)
pointerExpr.scopedname = parent.makeScopedName(idref.nameInSource.single())
@@ -298,7 +309,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
pointerExpr.linkParents(arglist[argparam.first.index].parent)
arglist[argparam.first.index] = pointerExpr
// add a vardecl so that the autovar can be resolved in later lookups
val variable = VarDecl(VarDeclType.VAR, strvalue.type, false, null, autoVarName, strvalue, strvalue.position)
val variable = VarDecl(VarDeclType.VAR, strvalue.type, false, null, false, autoVarName, strvalue, strvalue.position)
addVarDecl(strvalue.definingScope(), variable)
}
}
+24 -21
View File
@@ -13,7 +13,6 @@ import prog8.stackvm.Syscall
import java.io.File
import java.nio.file.Path
import java.util.*
import javax.lang.model.type.ArrayType
import kotlin.math.abs
@@ -818,8 +817,8 @@ internal class Compiler(private val rootModule: Module,
"any", "all" -> {
// 1 array argument, type determines the exact syscall to use
val arg=args.single() as IdentifierReference
val target=arg.targetStatement(namespace) as VarDecl
val length=Value(DataType.UBYTE, target.arrayspec!!.size()!!)
val target=arg.targetVarDecl(namespace)!!
val length=Value(DataType.UBYTE, target.arraysize!!.size()!!)
prog.instr(Opcode.PUSH_BYTE, length)
when (arg.resultingDatatype(namespace, heap)) {
DataType.ARRAY_B, DataType.ARRAY_UB -> createSyscall("${funcname}_b")
@@ -831,8 +830,8 @@ internal class Compiler(private val rootModule: Module,
"avg" -> {
// 1 array argument, type determines the exact syscall to use
val arg=args.single() as IdentifierReference
val target=arg.targetStatement(namespace) as VarDecl
val length=Value(DataType.UBYTE, target.arrayspec!!.size()!!)
val target=arg.targetVarDecl(namespace)!!
val length=Value(DataType.UBYTE, target.arraysize!!.size()!!)
val arrayDt=arg.resultingDatatype(namespace, heap)
prog.instr(Opcode.PUSH_BYTE, length)
when (arrayDt) {
@@ -862,8 +861,8 @@ internal class Compiler(private val rootModule: Module,
"min", "max", "sum" -> {
// 1 array argument, type determines the exact syscall to use
val arg=args.single() as IdentifierReference
val target=arg.targetStatement(namespace) as VarDecl
val length=Value(DataType.UBYTE, target.arrayspec!!.size()!!)
val target=arg.targetVarDecl(namespace)!!
val length=Value(DataType.UBYTE, target.arraysize!!.size()!!)
prog.instr(Opcode.PUSH_BYTE, length)
when (arg.resultingDatatype(namespace, heap)) {
DataType.ARRAY_UB -> createSyscall("${funcname}_ub")
@@ -1383,8 +1382,8 @@ internal class Compiler(private val rootModule: Module,
}
private fun translate(arrayindexed: ArrayIndexedExpression, write: Boolean) {
val variable = arrayindexed.identifier.targetStatement(namespace) as VarDecl
translate(arrayindexed.arrayspec.x)
val variable = arrayindexed.identifier.targetVarDecl(namespace)!!
translate(arrayindexed.arrayspec.index)
if (write)
prog.instr(opcodeWriteindexedvar(variable.datatype), callLabel = variable.scopedname)
else
@@ -1434,15 +1433,15 @@ internal class Compiler(private val rootModule: Module,
"--" -> prog.instr(Opcode.DEC_VAR_UB, callLabel = stmt.target.register!!.name)
}
stmt.target.identifier != null -> {
val targetStatement = stmt.target.identifier!!.targetStatement(namespace) as VarDecl
val targetStatement = stmt.target.identifier!!.targetVarDecl(namespace)!!
when(stmt.operator) {
"++" -> prog.instr(opcodeIncvar(targetStatement.datatype), callLabel = targetStatement.scopedname)
"--" -> prog.instr(opcodeDecvar(targetStatement.datatype), callLabel = targetStatement.scopedname)
}
}
stmt.target.arrayindexed != null -> {
val variable = stmt.target.arrayindexed!!.identifier.targetStatement(namespace) as VarDecl
translate(stmt.target.arrayindexed!!.arrayspec.x)
val variable = stmt.target.arrayindexed!!.identifier.targetVarDecl(namespace)!!
translate(stmt.target.arrayindexed!!.arrayspec.index)
when(stmt.operator) {
"++" -> prog.instr(opcodeIncArrayindexedVar(variable.datatype), callLabel = variable.scopedname)
"--" -> prog.instr(opcodeDecArrayindexedVar(variable.datatype), callLabel = variable.scopedname)
@@ -1501,7 +1500,7 @@ internal class Compiler(private val rootModule: Module,
DataType.STR, DataType.STR_S -> pushHeapVarAddress(stmt.value, true)
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.ARRAY_W, DataType.ARRAY_UW, DataType.ARRAY_F -> {
if (stmt.value is IdentifierReference) {
val vardecl = (stmt.value as IdentifierReference).targetStatement(namespace) as VarDecl
val vardecl = (stmt.value as IdentifierReference).targetVarDecl(namespace)!!
prog.removeLastInstruction()
prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname)
}
@@ -1538,7 +1537,7 @@ internal class Compiler(private val rootModule: Module,
when (value) {
is LiteralValue -> throw CompilerException("can only push address of string or array (value on the heap)")
is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl
val vardecl = value.targetVarDecl(namespace)!!
if(removeLastOpcode) prog.removeLastInstruction()
prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname)
}
@@ -1550,7 +1549,7 @@ internal class Compiler(private val rootModule: Module,
when (value) {
is LiteralValue -> throw CompilerException("can only push address of float that is a variable on the heap")
is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl
val vardecl = value.targetVarDecl(namespace)!!
prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname)
}
else -> throw CompilerException("can only take address of a the float as constant literal or variable")
@@ -1629,7 +1628,7 @@ internal class Compiler(private val rootModule: Module,
loopVarName = reg.name
loopVarDt = DataType.UBYTE
} else {
val loopvar = (loop.loopVar!!.targetStatement(namespace) as VarDecl)
val loopvar = loop.loopVar!!.targetVarDecl(namespace)!!
loopVarName = loopvar.scopedname
loopVarDt = loopvar.datatype
}
@@ -1678,7 +1677,7 @@ internal class Compiler(private val rootModule: Module,
when {
loop.iterable is IdentifierReference -> {
val idRef = loop.iterable as IdentifierReference
val vardecl = (idRef.targetStatement(namespace) as VarDecl)
val vardecl = idRef.targetVarDecl(namespace)!!
val iterableValue = vardecl.value as LiteralValue
if(!iterableValue.isIterable(namespace, heap))
throw CompilerException("loop over something that isn't iterable ${loop.iterable}")
@@ -1753,7 +1752,7 @@ internal class Compiler(private val rootModule: Module,
AssignTarget(loop.loopRegister, null, null, null, loop.position)
else
AssignTarget(null, loop.loopVar!!.copy(), null, null, loop.position)
val arrayspec = ArraySpec(IdentifierReference(listOf(ForLoop.iteratorLoopcounterVarname), loop.position), loop.position)
val arrayspec = ArrayIndex(IdentifierReference(listOf(ForLoop.iteratorLoopcounterVarname), loop.position), loop.position)
val assignLv = Assignment(
listOf(assignTarget), null,
ArrayIndexedExpression((loop.iterable as IdentifierReference).copy(), arrayspec, loop.position),
@@ -1942,7 +1941,7 @@ internal class Compiler(private val rootModule: Module,
lvTarget.linkParents(body)
val targetStatement: VarDecl? =
if(lvTarget.identifier!=null) {
lvTarget.identifier.targetStatement(namespace) as VarDecl
lvTarget.identifier.targetVarDecl(namespace)
} else {
null
}
@@ -2138,7 +2137,7 @@ internal class Compiler(private val rootModule: Module,
}
private fun translate(addrof: AddressOf) {
val target = addrof.identifier.targetStatement(namespace) as VarDecl
val target = addrof.identifier.targetVarDecl(namespace)!!
if(target.datatype in ArrayDatatypes || target.datatype in StringDatatypes|| target.datatype==DataType.FLOAT) {
pushHeapVarAddress(addrof.identifier, false)
}
@@ -2170,7 +2169,11 @@ internal class Compiler(private val rootModule: Module,
}
private fun translateAsmBinary(args: List<DirectiveArg>) {
TODO("asmbinary not implemented yet $args")
val offset = if(args.size>=2) Value(DataType.UWORD, args[1].int!!) else null
val length = if(args.size==3) Value(DataType.UWORD, args[2].int!!) else null
val filename = args[0].str!!
// reading the actual data is not performed by the compiler but is delegated to the assembler
prog.instr(Opcode.INCLUDE_FILE, offset, length, filename)
}
}
@@ -23,6 +23,9 @@ open class Instruction(val opcode: Opcode,
else
"inline_assembly"
}
opcode==Opcode.INCLUDE_FILE -> {
"include_file \"$callLabel\" $arg $arg2"
}
opcode==Opcode.SYSCALL -> {
val syscall = Syscall.values().find { it.callNr==arg!!.numericValue() }
"syscall $syscall"
@@ -69,7 +69,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
optimizeMultipleSequentialLineInstrs()
optimizeCallReturnIntoJump()
optimizeConditionalBranches()
// todo: add more optimizations to stackvm code
// todo: add more optimizations to intermediate code!
optimizeRemoveNops() // must be done as the last step
optimizeMultipleSequentialLineInstrs() // once more
@@ -262,7 +262,8 @@ enum class Opcode {
BREAKPOINT, // breakpoint
TERMINATE, // end the program
LINE, // track source file line number
INLINE_ASSEMBLY // container to hold inline raw assembly code
INLINE_ASSEMBLY, // container to hold inline raw assembly code
INCLUDE_FILE // directive to include a file at this position in the memory of the program
}
val opcodesWithVarArgument = setOf(
@@ -288,7 +288,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
out(" .byte " + chunk.joinToString())
}
DataType.ARRAY_UB -> {
// unsigned integer byte arrayspec
// unsigned integer byte arraysize
val data = makeArrayFillDataUnsigned(v.second)
if (data.size <= 16)
out("${v.first}\t.byte ${data.joinToString()}")
@@ -299,7 +299,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
DataType.ARRAY_B -> {
// signed integer byte arrayspec
// signed integer byte arraysize
val data = makeArrayFillDataSigned(v.second)
if (data.size <= 16)
out("${v.first}\t.char ${data.joinToString()}")
@@ -310,7 +310,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
DataType.ARRAY_UW -> {
// unsigned word arrayspec
// unsigned word arraysize
val data = makeArrayFillDataUnsigned(v.second)
if (data.size <= 16)
out("${v.first}\t.word ${data.joinToString()}")
@@ -321,7 +321,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
DataType.ARRAY_W -> {
// signed word arrayspec
// signed word arraysize
val data = makeArrayFillDataSigned(v.second)
if (data.size <= 16)
out("${v.first}\t.sint ${data.joinToString()}")
@@ -332,7 +332,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
}
DataType.ARRAY_F -> {
// float arrayspec
// float arraysize
val array = heap.get(v.second.heapId).doubleArray!!
val floatFills = array.map { makeFloatFill(Mflpt5.fromNumber(it)) }
out(v.first)
@@ -370,7 +370,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
else -> throw AssemblyError("weird type in array")
}
}
else -> throw AssemblyError("invalid arrayspec type")
else -> throw AssemblyError("invalid arraysize type")
}
}
@@ -385,7 +385,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"-$"+abs(it.integer).toString(16).padStart(2, '0')
}
}
else throw AssemblyError("invalid arrayspec type")
else throw AssemblyError("invalid arraysize type")
}
private fun instr2asm(ins: List<Instruction>): Int {
@@ -472,6 +472,11 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.DISCARD_WORD -> " inx"
Opcode.DISCARD_FLOAT -> " inx | inx | inx"
Opcode.INLINE_ASSEMBLY -> "@inline@" + (ins.callLabel2 ?: "") // All of the inline assembly is stored in the calllabel2 property. the '@inline@' is a special marker to process it.
Opcode.INCLUDE_FILE -> {
val offset = if(ins.arg==null) "" else ", ${ins.arg.integerValue()}"
val length = if(ins.arg2==null) "" else ", ${ins.arg2.integerValue()}"
" .binary \"${ins.callLabel}\" $offset $length"
}
Opcode.SYSCALL -> {
if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr })
throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}")
@@ -118,7 +118,7 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
if(arglist.type==DataType.ARRAY_UB || arglist.type==DataType.ARRAY_UW || arglist.type==DataType.ARRAY_F) {
val dt = arglist.arrayvalue!!.map {it.resultingDatatype(namespace, heap)}
if(dt.any { it!=DataType.UBYTE && it!=DataType.UWORD && it!=DataType.FLOAT}) {
throw FatalAstException("fuction $function only accepts arrayspec of numeric values")
throw FatalAstException("fuction $function only accepts arraysize of numeric values")
}
if(dt.any { it==DataType.FLOAT }) return DataType.FLOAT
if(dt.any { it==DataType.UWORD }) return DataType.UWORD
@@ -299,7 +299,6 @@ private fun builtinAvg(args: List<IExpression>, position: Position, namespace:IN
if(args.size!=1)
throw SyntaxError("avg requires array argument", position)
val iterable = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
val result = if(iterable.arrayvalue!=null) {
val constants = iterable.arrayvalue.map { it.constValue(namespace, heap)?.asNumericValue }
if (null in constants)
@@ -307,13 +306,17 @@ private fun builtinAvg(args: List<IExpression>, position: Position, namespace:IN
(constants.map { it!!.toDouble() }).average()
}
else {
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("avg requires array argument", position)
if(array.all {it.integer!=null}) {
array.map { it.integer!! }.average()
val integerarray = heap.get(iterable.heapId!!).array
if(integerarray!=null) {
if (integerarray.all { it.integer != null }) {
integerarray.map { it.integer!! }.average()
} else {
throw ExpressionError("cannot avg() over array that does not only contain constant numerical values", position)
}
} else {
throw ExpressionError("cannot avg() over array that does not only contain constant integer values", position)
val doublearray = heap.get(iterable.heapId).doubleArray
doublearray?.average() ?: throw SyntaxError("avg requires array argument", position)
}
// TODO what about avg() on floating point array variable!
}
return numericLiteral(result, args[0].position)
}
@@ -338,8 +341,12 @@ private fun builtinLen(args: List<IExpression>, position: Position, namespace:IN
throw SyntaxError("len requires one argument", position)
var argument = args[0].constValue(namespace, heap)
if(argument==null) {
val directMemVar = ((args[0] as? DirectMemoryRead)?.addressExpression as? IdentifierReference)?.targetVarDecl(namespace)
val arraySize = directMemVar?.arraysize?.size()
if(arraySize != null)
return LiteralValue.optimalInteger(arraySize, position)
if(args[0] !is IdentifierReference)
throw SyntaxError("len over weird argument ${args[0]}", position)
throw SyntaxError("len argument should be an identifier, but is ${args[0]}", position)
val target = (args[0] as IdentifierReference).targetStatement(namespace)
val argValue = (target as? VarDecl)?.value
argument = argValue?.constValue(namespace, heap)
@@ -25,7 +25,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
override fun process(decl: VarDecl): IStatement {
// the initializer value can't refer to the variable itself (recursive definition)
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arrayspec?.x?.referencesIdentifier(decl.name) == true) {
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.index?.referencesIdentifier(decl.name) == true) {
errors.add(ExpressionError("recursive var declaration", decl.position))
return decl
}
@@ -45,11 +45,34 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
}
}
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> {
val rangeExpr = decl.value as? RangeExpr
if(rangeExpr!=null) {
// convert the initializer range expression to an actual array (will be put on heap later)
val declArraySize = decl.arraysize?.size()
if(declArraySize!=null && declArraySize!=rangeExpr.size(heap))
errors.add(ExpressionError("range expression size doesn't match declared array size", decl.value?.position!!))
val constRange = rangeExpr.toConstantIntegerRange(heap)
if(constRange!=null) {
val eltType = rangeExpr.resultingDatatype(namespace, heap)!!
if(eltType in ByteDatatypes) {
decl.value = LiteralValue(decl.datatype,
arrayvalue = constRange.map { LiteralValue(eltType, bytevalue=it.toShort(), position = decl.value!!.position ) }
.toTypedArray(), position=decl.value!!.position)
} else {
decl.value = LiteralValue(decl.datatype,
arrayvalue = constRange.map { LiteralValue(eltType, wordvalue= it, position = decl.value!!.position ) }
.toTypedArray(), position=decl.value!!.position)
}
decl.value!!.linkParents(decl)
}
}
if(litval?.type==DataType.FLOAT)
errors.add(ExpressionError("arrayspec requires only integers here", litval.position))
val size = decl.arrayspec!!.size()
if ((litval==null || !litval.isArray) && size != null) {
// arrayspec initializer is empty or a single int, and we know the size; create the arrayspec.
errors.add(ExpressionError("arraysize requires only integers here", litval.position))
if(decl.arraysize==null)
return decl
val size = decl.arraysize!!.size()
if ((litval==null || !litval.isArray) && size != null && rangeExpr==null) {
// arraysize initializer is empty or a single int, and we know the size; create the arraysize.
val fillvalue = if (litval == null) 0 else litval.asIntegerValue ?: 0
when(decl.datatype){
DataType.ARRAY_UB -> {
@@ -75,9 +98,11 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
}
}
DataType.ARRAY_F -> {
val size = decl.arrayspec!!.size()
if(decl.arraysize==null)
return decl
val size = decl.arraysize!!.size()
if ((litval==null || !litval.isArray) && size != null) {
// arrayspec initializer is empty or a single int, and we know the size; create the arrayspec.
// arraysize initializer is empty or a single int, and we know the size; create the arraysize.
val fillvalue = if (litval == null) 0.0 else litval.asNumericValue?.toDouble() ?: 0.0
if(fillvalue< FLOAT_MAX_NEGATIVE || fillvalue> FLOAT_MAX_POSITIVE)
errors.add(ExpressionError("float value overflow", litval?.position ?: decl.position))
@@ -116,7 +141,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval.position)
}
}
else -> throw AstException("invalid array vardecl type")
else -> throw FatalAstException("invalid array vardecl type ${decl.datatype}")
}
}
@@ -156,7 +181,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
}
private fun typeCastConstArguments(functionCall: IFunctionCall) {
val subroutine = functionCall.target.targetStatement(namespace) as? Subroutine
val subroutine = functionCall.target.targetSubroutine(namespace)
if(subroutine!=null) {
// if types differ, try to typecast constant arguments to the function call to the desired data type of the parameter
for(arg in functionCall.arglist.withIndex().zip(subroutine.parameters)) {
@@ -173,6 +198,21 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
}
}
override fun process(memread: DirectMemoryRead): IExpression {
// @( &thing ) --> thing
val addrOf = memread.addressExpression as? AddressOf
if(addrOf!=null)
return super.process(addrOf.identifier)
return super.process(memread)
}
override fun process(memwrite: DirectMemoryWrite): IExpression {
// @( &thing ) --> thing
val addrOf = memwrite.addressExpression as? AddressOf
if(addrOf!=null)
return super.process(addrOf.identifier)
return super.process(memwrite)
}
/**
* Try to process a unary prefix expression.
@@ -493,7 +533,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
val rangeTo = iterableRange.to as? LiteralValue
if(rangeFrom==null || rangeTo==null) return resultStmt
val loopvar = resultStmt.loopVar!!.targetStatement(namespace) as? VarDecl
val loopvar = resultStmt.loopVar!!.targetVarDecl(namespace)
if(loopvar!=null) {
val stepLiteral = iterableRange.step as? LiteralValue
when(loopvar.datatype) {
@@ -600,7 +640,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
DataType.ARRAY_UW,
DataType.ARRAY_W -> heap.addIntegerArray(arrayDt, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray())
DataType.ARRAY_F -> heap.addDoublesArray(doubleArray)
else -> throw CompilerException("invalid arrayspec type")
else -> throw CompilerException("invalid arraysize type")
}
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)
}
@@ -673,5 +713,3 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
return assignment
}
}
@@ -18,6 +18,22 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
return super.process(assignment)
}
override fun process(memread: DirectMemoryRead): IExpression {
// @( &thing ) --> thing
val addrOf = memread.addressExpression as? AddressOf
if(addrOf!=null)
return super.process(addrOf.identifier)
return super.process(memread)
}
override fun process(memwrite: DirectMemoryWrite): IExpression {
// @( &thing ) --> thing
val addrOf = memwrite.addressExpression as? AddressOf
if(addrOf!=null)
return super.process(addrOf.identifier)
return super.process(memwrite)
}
override fun process(expr: PrefixExpression): IExpression {
if (expr.operator == "+") {
// +X --> X
@@ -101,12 +101,12 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
if(target.memoryAddress!=null)
return false
if(target.arrayindexed!=null) {
val targetStmt = target.arrayindexed.identifier.targetStatement(namespace) as? VarDecl
val targetStmt = target.arrayindexed.identifier.targetVarDecl(namespace)
if(targetStmt!=null)
return targetStmt.type!=VarDeclType.MEMORY
}
if(target.identifier!=null) {
val targetStmt = target.identifier.targetStatement(namespace) as? VarDecl
val targetStmt = target.identifier.targetVarDecl(namespace)
if(targetStmt!=null)
return targetStmt.type!=VarDeclType.MEMORY
}
@@ -156,7 +156,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
// if it calls a subroutine,
// and the first instruction in the subroutine is a jump, call that jump target instead
// if the first instruction in the subroutine is a return statement, replace with a nop instruction
val subroutine = functionCallStatement.target.targetStatement(namespace) as? Subroutine
val subroutine = functionCallStatement.target.targetSubroutine(namespace)
if(subroutine!=null) {
val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull()
if(first is Jump && first.identifier!=null) {
@@ -176,7 +176,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
// if it calls a subroutine,
// and the first instruction in the subroutine is a jump, call that jump target instead
// if the first instruction in the subroutine is a return statement with constant value, replace with the constant value
val subroutine = functionCall.target.targetStatement(namespace) as? Subroutine
val subroutine = functionCall.target.targetSubroutine(namespace)
if(subroutine!=null) {
val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull()
if(first is Jump && first.identifier!=null) {
@@ -341,7 +341,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
}
override fun process(jump: Jump): IStatement {
val subroutine = jump.identifier?.targetStatement(namespace) as? Subroutine
val subroutine = jump.identifier?.targetSubroutine(namespace)
if(subroutine!=null) {
// if the first instruction in the subroutine is another jump, shortcut this one
val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull()
@@ -380,7 +380,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
if (same(target, bexpr.left)) {
// remove assignments that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc
// A = A <operator> B
val vardeclDt = (target.identifier?.targetStatement(namespace) as? VarDecl)?.type
val vardeclDt = (target.identifier?.targetVarDecl(namespace))?.type
when (bexpr.operator) {
"+" -> {
@@ -522,8 +522,8 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
}
if(target1.arrayindexed!=null && target2.arrayindexed!=null) {
if(target1.arrayindexed.identifier.nameInSource == target2.arrayindexed.identifier.nameInSource) {
val x1 = target1.arrayindexed.arrayspec.x.constValue(namespace, heap)
val x2 = target2.arrayindexed.arrayspec.x.constValue(namespace, heap)
val x1 = target1.arrayindexed.arrayspec.index.constValue(namespace, heap)
val x2 = target2.arrayindexed.arrayspec.index.constValue(namespace, heap)
return x1!=null && x2!=null && x1==x2
}
}
@@ -548,7 +548,7 @@ fun same(left: IExpression, right: IExpression): Boolean {
&& same(right.right, left.right))
is ArrayIndexedExpression -> {
return (right is ArrayIndexedExpression && right.identifier.nameInSource == left.identifier.nameInSource
&& same(right.arrayspec.x, left.arrayspec.x))
&& same(right.arrayspec.index, left.arrayspec.index))
}
is LiteralValue -> return (right is LiteralValue && right==left)
}
+7
View File
@@ -170,6 +170,13 @@ class Program (val name: String,
}
}
}
Opcode.INCLUDE_FILE -> {
val argparts = args!!.split(' ')
val filename = argparts[0]
val offset = if(argparts.size>=2 && argparts[1]!="null") getArgValue(argparts[1], heap) else null
val length = if(argparts.size>=3 && argparts[2]!="null") getArgValue(argparts[2], heap) else null
Instruction(opcode, offset, length, filename)
}
else -> {
Instruction(opcode, getArgValue(args, heap))
}
+13 -12
View File
@@ -1622,7 +1622,7 @@ class StackVm(private var traceOutputFile: String?) {
// assume the variable is a pointer (address) and get the ubyte value from that memory location
Value(DataType.UBYTE, mem.getUByte(variable.integerValue()))
} else {
// get indexed byte element from the arrayspec
// get indexed byte element from the arraysize
val array = heap.get(variable.heapId)
when (array.type) {
DataType.ARRAY_UB -> Value(DataType.UBYTE, array.array!![index].integer!!)
@@ -1645,7 +1645,7 @@ class StackVm(private var traceOutputFile: String?) {
when(variable.second) {
DataType.ARRAY_UW -> Value(DataType.UWORD, mem.getUWord(address))
DataType.ARRAY_W -> Value(DataType.WORD, mem.getSWord(address))
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
else -> throw VmExecutionException("not a proper arraysize var with word elements")
}
} else {
// normal variable
@@ -1654,7 +1654,7 @@ class StackVm(private var traceOutputFile: String?) {
// assume the variable is a pointer (address) and get the word value from that memory location
Value(DataType.UWORD, mem.getUWord(variable.integerValue()))
} else {
// get indexed word element from the arrayspec
// get indexed word element from the arraysize
val array = heap.get(variable.heapId)
when(array.type){
DataType.ARRAY_UW -> {
@@ -1671,7 +1671,7 @@ class StackVm(private var traceOutputFile: String?) {
}
}
DataType.ARRAY_W -> Value(DataType.WORD, array.array!![index].integer!!)
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
else -> throw VmExecutionException("not a proper arraysize var with word elements")
}
}
}
@@ -1688,17 +1688,17 @@ class StackVm(private var traceOutputFile: String?) {
if(variable.second==DataType.ARRAY_F)
Value(DataType.FLOAT, mem.getFloat(address))
else
throw VmExecutionException("not a proper arrayspec var with float elements")
throw VmExecutionException("not a proper arraysize var with float elements")
} else {
val variable = getVar(ins.callLabel!!)
if (variable.type == DataType.UWORD) {
// assume the variable is a pointer (address) and get the float value from that memory location
Value(DataType.UWORD, mem.getFloat(variable.integerValue()))
} else {
// get indexed float element from the arrayspec
// get indexed float element from the arraysize
val array = heap.get(variable.heapId)
if (array.type != DataType.ARRAY_F)
throw VmExecutionException("not a proper arrayspec var with float elements")
throw VmExecutionException("not a proper arraysize var with float elements")
Value(DataType.FLOAT, array.doubleArray!![index])
}
}
@@ -1733,7 +1733,7 @@ class StackVm(private var traceOutputFile: String?) {
else
mem.setSByte(variable.integerValue(), value.integerValue().toShort())
} else {
// set indexed byte element in the arrayspec
// set indexed byte element in the arraysize
val array = heap.get(variable.heapId)
when (array.type) {
DataType.ARRAY_UB -> array.array!![index] = IntegerOrAddressOf(value.integerValue(), null)
@@ -1781,12 +1781,12 @@ class StackVm(private var traceOutputFile: String?) {
else
mem.setSWord(variable.integerValue()+index*2, value.integerValue())
} else {
// set indexed word element in the arrayspec
// set indexed word element in the arraysize
val array = heap.get(variable.heapId)
when (array.type) {
DataType.ARRAY_UW -> array.array!![index] = IntegerOrAddressOf(value.integerValue(), null)
DataType.ARRAY_W -> array.array!![index] = IntegerOrAddressOf(value.integerValue(), null)
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
else -> throw VmExecutionException("not a proper arraysize var with word elements")
}
}
}
@@ -1810,10 +1810,10 @@ class StackVm(private var traceOutputFile: String?) {
// assume the variable is a pointer (address) and write the float value to that memory location
mem.setFloat(variable.integerValue()+index*5, value.numericValue().toDouble())
} else {
// set indexed float element in the arrayspec
// set indexed float element in the arraysize
val array = heap.get(variable.heapId)
if (array.type != DataType.ARRAY_F)
throw VmExecutionException("not a proper arrayspec var with float elements")
throw VmExecutionException("not a proper arraysize var with float elements")
array.doubleArray!![index] = value.numericValue().toDouble()
}
}
@@ -1836,6 +1836,7 @@ class StackVm(private var traceOutputFile: String?) {
Opcode.RSAVEX -> registerSaveX = variables.getValue("X")
Opcode.RRESTOREX -> variables["X"] = registerSaveX
Opcode.INLINE_ASSEMBLY -> throw VmExecutionException("stackVm doesn't support executing inline assembly code $ins")
Opcode.INCLUDE_FILE -> throw VmExecutionException("stackVm doesn't support including a file $ins")
Opcode.PUSH_ADDR_HEAPVAR -> {
val heapId = variables.getValue(ins.callLabel!!).heapId
if(heapId<0)
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
# this script uses the Gradle build to compile the code,
# and then adds the contents of several jar files into one output jar.
./gradlew jar
mkdir -p compiler_jar/extracted
mkdir -p compiler_jar/source
cp compiler/build/libs/compiler.jar parser/build/libs/parser.jar parser/antlr/lib/antlr-runtime-4.7.2.jar compiler_jar/source/
KOTLINLIBS=$(kotlinc -verbose -script 2>&1 | grep home | cut -d ' ' -f 6-)/lib
cp ${KOTLINLIBS}/kotlin-stdlib-jdk8.jar ${KOTLINLIBS}/kotlin-stdlib.jar compiler_jar/source/
pushd compiler_jar/extracted
for i in ../source/*.jar; do jar xf $i; done
cd ..
jar cfe ../prog8compiler.jar prog8.CompilerMainKt -C extracted .
popd
rm -r compiler_jar
ls -l prog8compiler.jar
+3 -3
View File
@@ -237,9 +237,9 @@ Arrays
^^^^^^
Array types are also supported. They can be made of bytes, words or floats::
byte[4] array = [1, 2, 3, 4] ; initialize the array
byte[99] array = 255 ; initialize array with all 255's [255, 255, 255, 255, ...]
byte[100] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199]
byte[] array = [1, 2, 3, 4] ; initialize the array, size taken from value
byte[99] array = 255 ; initialize array with 99 times 255 [255, 255, 255, 255, ...]
byte[] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199]
value = array[3] ; the fourth value in the array (index is 0-based)
char = string[4] ; the fifth character (=byte) in the string
+19 -10
View File
@@ -123,6 +123,7 @@ Directives
This directive can only be used inside a block.
The assembler will include the file as binary bytes at this point, prog8 will not process this at all.
The optional offset and length can be used to select a particular piece of the file.
The file is located relative to the current working directory!
.. data:: %asminclude "<filename>", "scopelabel"
@@ -133,6 +134,8 @@ Directives
The scopelabel argument will be used as a prefix to access the labels from the included source code,
otherwise you would risk symbol redefinitions or duplications.
If you know what you are doing you can leave it as an empty string to not have a scope prefix.
The compiler first looks for the file relative to the same directory as the module containing this statement is in,
if the file can't be found there it is searched relative to the current directory.
.. data:: %breakpoint
@@ -227,7 +230,7 @@ Various examples::
float wallet = 55.25
str name = "my name is Irmen"
uword address = &counter
byte[5] values = [11, 22, 33, 44, 55]
byte[] values = [11, 22, 33, 44, 55]
byte[5] values = 255 ; initialize with five 255 bytes
word @zp zpword = 9999 ; prioritize this when selecting vars for zeropage storage
@@ -251,18 +254,24 @@ type identifier type storage size example var declara
``uword`` unsigned word 2 bytes = 16 bits ``uword myvar = $8fee``
``float`` floating-point 5 bytes = 40 bits ``float myvar = 1.2345``
stored in 5-byte cbm MFLPT format
``byte[x]`` signed byte array x bytes ``byte[4] myvar = [1, 2, 3, 4]``
``ubyte[x]`` unsigned byte array x bytes ``ubyte[4] myvar = [1, 2, 3, 4]``
``word[x]`` signed word array 2*x bytes ``word[4] myvar = [1, 2, 3, 4]``
``uword[x]`` unsigned word array 2*x bytes ``uword[4] myvar = [1, 2, 3, 4]``
``float[x]`` floating-point array 5*x bytes ``float[4] myvar = [1.1, 2.2, 3.3, 4.4]``
``byte[x]`` signed byte array x bytes ``byte[4] myvar``
``ubyte[x]`` unsigned byte array x bytes ``ubyte[4] myvar``
``word[x]`` signed word array 2*x bytes ``word[4] myvar``
``uword[x]`` unsigned word array 2*x bytes ``uword[4] myvar``
``float[x]`` floating-point array 5*x bytes ``float[4] myvar``
``byte[]`` signed byte array depends on value ``byte[] myvar = [1, 2, 3, 4]``
``ubyte[]`` unsigned byte array depends on value ``ubyte[] myvar = [1, 2, 3, 4]``
``word[]`` signed word array depends on value ``word[] myvar = [1, 2, 3, 4]``
``uword[]`` unsigned word array depends on value ``uword[] myvar = [1, 2, 3, 4]``
``float[]`` floating-point array depends on value ``float[] myvar = [1.1, 2.2, 3.3, 4.4]``
``str`` string (petscii) varies ``str myvar = "hello."``
implicitly terminated by a 0-byte
``str_s`` string (screencodes) varies ``str_s myvar = "hello."``
implicitly terminated by a 0-byte
=============== ======================= ================= =========================================
**arrays:** you can split an array initializer list over several lines if you want.
**arrays:** you can split an array initializer list over several lines if you want. When an initialization
value is given, the array size in the declaration can be omitted.
**hexadecimal numbers:** you can use a dollar prefix to write hexadecimal numbers: ``$20ac``
@@ -336,7 +345,7 @@ which represents a range of numbers or characters,
from the starting value to (and including) the ending value.
If used in the place of a literal value, it expands into the actual array of values::
byte[100] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199]
byte[] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199]
Array indexing
@@ -394,7 +403,7 @@ range creation: ``to``
X = 10
A to X ; range of 5, 6, 7, 8, 9, 10
byte[4] array = 10 to 13 ; sets the array to [1, 2, 3, 4]
byte[] array = 10 to 13 ; sets the array to [1, 2, 3, 4]
for i in 0 to 127 {
; i loops 0, 1, 2, ... 127
@@ -507,7 +516,7 @@ For example, this is a for loop using the existing byte variable ``i`` to loop o
And this is a loop over the values of the array ``fibonacci_numbers`` where the loop variable is declared in the loop itself::
word[20] fibonacci_numbers = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
word[] fibonacci_numbers = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
for word fibnr in fibonacci_numbers {
; do something
+1 -3
View File
@@ -60,7 +60,7 @@ of values together (and use it multiple times). Something like::
struct Point {
ubyte color
word[3] vec = [0,0,0]
word[] vec = [0,0,0]
}
Point p1
@@ -74,6 +74,4 @@ of values together (and use it multiple times). Something like::
Misc
^^^^
- implement %asmbinary
- make the array size optional in the var decl if an initialization array is given
- are there any other missing instructions in the code generator?
+2 -2
View File
@@ -56,7 +56,7 @@ sub start() {
; details about the boulderdash music can be found here:
; https://www.elmerproductions.com/sp/peterb/sounds.html#Theme%20tune
uword[128] notes = [
uword[] notes = [
$1622, $1d26, $2229, $252e, $1424, $1f27, $2029, $2730,
$122a, $122c, $1e2e, $1231, $202c, $3337, $212d, $3135,
$1622, $162e, $161d, $1624, $1420, $1430, $1424, $1420,
@@ -76,7 +76,7 @@ sub start() {
]
uword[59] music_freq_table = [
uword[] music_freq_table = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
732, 778, 826, 876, 928, 978, 1042, 1100, 1170, 1238, 1312, 1390, 1464, 1556,
1652, 1752, 1856, 1956, 2084, 2200, 2340, 2476, 2624, 2780, 2928, 3112, 3304,
+3 -3
View File
@@ -8,9 +8,9 @@
const uword height = 25
; vertices
float[8] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ]
float[8] ycoor = [ -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0 ]
float[8] zcoor = [ -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ]
float[] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ]
float[] ycoor = [ -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0 ]
float[] zcoor = [ -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ]
; storage for rotated coordinates
float[len(xcoor)] rotatedx=0.0
+5 -5
View File
@@ -6,7 +6,7 @@
; it must start on an address aligned to 64 bytes.
%option force_output ; make sure the data in this block appears in the resulting program
ubyte[128] sprites = [
ubyte[] sprites = [
%00000000,%00000000,%00000000,
%00000000,%00111100,%00000000,
%00000000,%11111111,%00000000,
@@ -64,9 +64,9 @@
const uword height = 200
; vertices
byte[8] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
byte[8] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
byte[8] zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ]
byte[] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
byte[] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
byte[] zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ]
; storage for rotated coordinates
word[len(xcoor)] rotatedx
@@ -146,7 +146,7 @@
}
}
ubyte[8] spritecolors = [1,1,7,15,12,11,9,9]
ubyte[] spritecolors = [1,1,7,15,12,11,9,9]
for ubyte i in 0 to 7 {
word zc = rotatedz[i]
+4 -4
View File
@@ -20,12 +20,12 @@
const uword height = 200
; vertices
float[8] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ]
float[8] ycoor = [ -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0 ]
float[8] zcoor = [ -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ]
float[] xcoor = [ -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0 ]
float[] ycoor = [ -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0 ]
float[] zcoor = [ -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ]
; edges (msb=from vertex, lsb=to vertex)
uword[12] edges = [$0001, $0103, $0302, $0200, $0405, $0507, $0706, $0604, $0004, $0105, $0206, $0307]
uword[] edges = [$0001, $0103, $0302, $0200, $0405, $0507, $0706, $0604, $0004, $0105, $0206, $0307]
; storage for rotated coordinates
float[len(xcoor)] rotatedx
+4 -4
View File
@@ -7,9 +7,9 @@
const uword height = 25
; vertices
byte[8] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
byte[8] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
byte[8] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
byte[] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
byte[] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
byte[] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
; storage for rotated coordinates
word[len(xcoor)] rotatedx
@@ -68,7 +68,7 @@
}
}
ubyte[6] vertexcolors = [1,7,7,12,11,6]
ubyte[] vertexcolors = [1,7,7,12,11,6]
sub draw_edges() {
+1 -1
View File
@@ -18,7 +18,7 @@
~ irq {
const ubyte barheight = 4
ubyte[13] colors = [6,2,4,5,15,7,1,13,3,12,8,11,9]
ubyte[] colors = [6,2,4,5,15,7,1,13,3,12,8,11,9]
ubyte color = 0
ubyte ypos = 0
+21 -21
View File
@@ -8,27 +8,27 @@
; it must start on an address aligned to 64 bytes.
%option force_output ; make sure the data in this block appears in the resulting program
ubyte[63] balloonsprite = [ %00000000,%01111111,%00000000,
%00000001,%11111111,%11000000,
%00000011,%11111111,%11100000,
%00000011,%11100011,%11100000,
%00000111,%11011100,%11110000,
%00000111,%11011101,%11110000,
%00000111,%11011100,%11110000,
%00000011,%11100011,%11100000,
%00000011,%11111111,%11100000,
%00000011,%11111111,%11100000,
%00000010,%11111111,%10100000,
%00000001,%01111111,%01000000,
%00000001,%00111110,%01000000,
%00000000,%10011100,%10000000,
%00000000,%10011100,%10000000,
%00000000,%01001001,%00000000,
%00000000,%01001001,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00011100,%00000000 ]
ubyte[] balloonsprite = [ %00000000,%01111111,%00000000,
%00000001,%11111111,%11000000,
%00000011,%11111111,%11100000,
%00000011,%11100011,%11100000,
%00000111,%11011100,%11110000,
%00000111,%11011101,%11110000,
%00000111,%11011100,%11110000,
%00000011,%11100011,%11100000,
%00000011,%11111111,%11100000,
%00000011,%11111111,%11100000,
%00000010,%11111111,%10100000,
%00000001,%01111111,%01000000,
%00000001,%00111110,%01000000,
%00000000,%10011100,%10000000,
%00000000,%10011100,%10000000,
%00000000,%01001001,%00000000,
%00000000,%01001001,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00011100,%00000000 ]
}
~ main {
+32 -46
View File
@@ -205,7 +205,7 @@ waitkey:
if linepos and blocklogic.isLineFull(linepos)
blocklogic.collapse(linepos)
lines += num_lines
uword[4] scores = [10, 25, 50, 100] ; can never clear more than 4 lines
uword[] scores = [10, 25, 50, 100] ; can never clear more than 4 lines
score += scores[num_lines-1]
speedlevel = 1+lsb(lines/10)
drawScore()
@@ -320,7 +320,7 @@ waitkey:
c64scr.setcc(boardOffsetX+boardWidth, i, 84, 11)
}
ubyte[5] colors = [6,8,7,5,4]
ubyte[] colors = [6,8,7,5,4]
for i in len(colors)-1 to 0 step -1 {
for ubyte x in 5 to 0 step -1 {
c64scr.setcc(6+x-i, 11+2*i, 102, colors[i])
@@ -387,54 +387,40 @@ waitkey:
ubyte[16] rotated
; the 7 tetrominos
ubyte[16] blockI = [0,0,0,0, ; cyan ; note: special rotation (around matrix center)
3,3,3,3,
0,0,0,0,
0,0,0,0]
ubyte[16] blockJ = [6,0,0,0, ; blue
6,6,6,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockL = [0,0,8,0, ; orange
8,8,8,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockO = [0,7,7,0, ; yellow ; note: no rotation (square)
0,7,7,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockS = [0,5,5,0, ; green
5,5,0,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockT = [0,4,0,0, ; purple
4,4,4,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockZ = [2,2,0,0, ; red
0,2,2,0,
0,0,0,0,
0,0,0,0]
ubyte[] blockI = [0,0,0,0, ; cyan ; note: special rotation (around matrix center)
3,3,3,3,
0,0,0,0,
0,0,0,0]
ubyte[] blockJ = [6,0,0,0, ; blue
6,6,6,0,
0,0,0,0,
0,0,0,0]
ubyte[] blockL = [0,0,8,0, ; orange
8,8,8,0,
0,0,0,0,
0,0,0,0]
ubyte[] blockO = [0,7,7,0, ; yellow ; note: no rotation (square)
0,7,7,0,
0,0,0,0,
0,0,0,0]
ubyte[] blockS = [0,5,5,0, ; green
5,5,0,0,
0,0,0,0,
0,0,0,0]
ubyte[] blockT = [0,4,0,0, ; purple
4,4,4,0,
0,0,0,0,
0,0,0,0]
ubyte[] blockZ = [2,2,0,0, ; red
0,2,2,0,
0,0,0,0,
0,0,0,0]
; @todo use the '&' operator to create an array of pointers and use that, like so:
; uword[7] blocks = [&blockI, &blockJ, &blockL, &blockO, &blockS, &blockT, &blockZ]
uword[] blocks = [&blockI, &blockJ, &blockL, &blockO, &blockS, &blockT, &blockZ]
sub newCurrentBlock(ubyte block) {
currentBlockNum = block
if block==0
memcopy(blockI, currentBlock, len(currentBlock))
else if block==1
memcopy(blockJ, currentBlock, len(currentBlock))
else if block==2
memcopy(blockL, currentBlock, len(currentBlock))
else if block==3
memcopy(blockO, currentBlock, len(currentBlock))
else if block==4
memcopy(blockS, currentBlock, len(currentBlock))
else if block==5
memcopy(blockT, currentBlock, len(currentBlock))
else if block==6
memcopy(blockZ, currentBlock, len(currentBlock))
memcopy(blocks[block], currentBlock, len(currentBlock))
}
sub rotateCW() {
+15 -76
View File
@@ -1,89 +1,28 @@
%zeropage basicsafe
%option enable_floats
%import c64flt
~ main {
float[] fa = [1.1,2.2,3.3]
ubyte[] uba = [10,2,3,4]
byte[] ba = [-10,2,3,4]
uword[] uwa = [100,20,30,40]
word[] wa = [-100,20,30,40]
sub start() {
ubyte[3] array1
ubyte[3] array2
ubyte[3] array3
str string1="hello"
str string2="bye"
uword pointer = &array1
uword pointer2
uword pointer3
byte bt
pointer2 = &array2
pointer3 = &string1
uword[4] pointers = [&array1, &array2, &string1, &string2]
ptrsubasm("moet werken")
pointersub("moet werken")
myprintasm(string1)
myprintasm(string2)
myprintasm("moet werken3")
myprintasm("moet werken3")
myprintasm("moet werken4")
c64scr.print("this print must work\n")
c64.CHROUT('\n')
ptrsubasm(&array1)
ptrsubasm(&array2)
ptrsubasm(&string1)
ptrsubasm(&string2)
pointersub(&array1)
pointersub(&array2)
pointersub(&string1)
pointersub(&string2)
c64scr.print_uwhex(1, pointers[0])
c64.CHROUT(',')
c64scr.print_uwhex(1, pointers[1])
c64.CHROUT(',')
c64scr.print_uwhex(1, pointers[2])
c64.CHROUT(',')
c64scr.print_uwhex(1, pointers[3])
}
sub pointersub(uword arg) {
c64scr.print_uwhex(1, arg)
float a
a=avg([1,2,3,4])
c64flt.print_f(a)
c64.CHROUT('\n')
a=avg([100,200,300,400])
c64flt.print_f(a)
c64.CHROUT('\n')
a=avg([1.1,2.2,3.3,4.4])
c64flt.print_f(a)
c64.CHROUT('\n')
}
asmsub ptrsubasm(uword arg @ AY) -> clobbers() -> () {
%asm {{
sec
jsr c64scr.print_uwhex
lda #13
jmp c64.CHROUT
}}
}
asmsub myprintasm(str arg @ AY) -> clobbers() -> () {
%asm {{
sec
jsr c64scr.print_uwhex
lda #13
jmp c64.CHROUT
}}
}
}
~ test {
sub testsub() {
uword[4] pointers = [&main.start.array1, &main.start.array2, &main.start.string1, &main.start.string2] ; @todo make it possible to initialize array with pointers
}
}
+21 -21
View File
@@ -8,27 +8,27 @@
; it must start on an address aligned to 64 bytes.
%option force_output ; make sure the data in this block appears in the resulting program
ubyte[63] balloonsprite = [ %00000000,%01111111,%00000000,
%00000001,%11111111,%11000000,
%00000011,%11111111,%11100000,
%00000011,%11100011,%11100000,
%00000111,%11011100,%11110000,
%00000111,%11011101,%11110000,
%00000111,%11011100,%11110000,
%00000011,%11100011,%11100000,
%00000011,%11111111,%11100000,
%00000011,%11111111,%11100000,
%00000010,%11111111,%10100000,
%00000001,%01111111,%01000000,
%00000001,%00111110,%01000000,
%00000000,%10011100,%10000000,
%00000000,%10011100,%10000000,
%00000000,%01001001,%00000000,
%00000000,%01001001,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00011100,%00000000 ]
ubyte[] balloonsprite = [ %00000000,%01111111,%00000000,
%00000001,%11111111,%11000000,
%00000011,%11111111,%11100000,
%00000011,%11100011,%11100000,
%00000111,%11011100,%11110000,
%00000111,%11011101,%11110000,
%00000111,%11011100,%11110000,
%00000011,%11100011,%11100000,
%00000011,%11111111,%11100000,
%00000011,%11111111,%11100000,
%00000010,%11111111,%10100000,
%00000001,%01111111,%01000000,
%00000001,%00111110,%01000000,
%00000000,%10011100,%10000000,
%00000000,%10011100,%10000000,
%00000000,%01001001,%00000000,
%00000000,%01001001,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00011100,%00000000 ]
}
~ main {
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
# compile using regular Kotlin sdk command line tool
echo "Compiling the parser..."
java -jar ./parser/antlr/lib/antlr-4.7.2-complete.jar -o ./parser/src/prog8/parser -Xexact-output-dir -no-listener -no-visitor ./parser/antlr/prog8.g4
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env sh
PROG8CLASSPATH=./out/production/compiler_main:./out/production/parser_main
PROG8CLASSPATH=./compiler/build/classes/kotlin/main:./compiler/build/resources/main:./parser/build/classes/java/main
KOTLINPATH=${HOME}/.IntelliJIdea2019.1/config/plugins/Kotlin
LIBJARS=${KOTLINPATH}/lib/kotlin-stdlib.jar:${KOTLINPATH}/lib/kotlin-reflect.jar:./parser/antlr/lib/antlr-runtime-4.7.2.jar
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env sh
PROG8CLASSPATH=./out/production/compiler_main
PROG8CLASSPATH=./compiler/build/classes/kotlin/main:./compiler/build/resources/main
KOTLINPATH=${HOME}/.IntelliJIdea2019.1/config/plugins/Kotlin
LIBJARS=${KOTLINPATH}/lib/kotlin-stdlib.jar:${KOTLINPATH}/lib/kotlin-reflect.jar
+7 -3
View File
@@ -59,6 +59,10 @@ ZEROPAGE :
'@zp'
;
ARRAYSIG :
'[]'
;
module : (modulestatement | EOL)* EOF ;
@@ -104,7 +108,7 @@ directive :
directivearg : stringliteral | identifier | integerliteral ;
vardecl: datatype ZEROPAGE? arrayspec? identifier ;
vardecl: datatype ZEROPAGE? (arrayindex | ARRAYSIG) ? identifier ;
varinitializer : vardecl '=' expression ;
@@ -114,7 +118,7 @@ memoryvardecl: ADDRESS_OF varinitializer;
datatype: 'ubyte' | 'byte' | 'uword' | 'word' | 'float' | 'str' | 'str_s' ;
arrayspec: '[' expression ']' ;
arrayindex: '[' expression ']' ;
assignment : assign_targets '=' expression ;
@@ -164,7 +168,7 @@ expression :
typecast : 'as' datatype;
arrayindexed : scoped_identifier arrayspec ;
arrayindexed : scoped_identifier arrayindex ;
directmemory : '@' '(' expression ')';
-12
View File
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="antlr-4.7.2-complete" level="project" />
</component>
</module>
+279 -277
View File
@@ -1,4 +1,4 @@
// Generated from ./parser/antlr/prog8.g4 by ANTLR 4.7.2
// Generated from prog8.g4 by ANTLR 4.7.2
package prog8.parser;
@@ -36,7 +36,7 @@ public class prog8Lexer extends Lexer {
T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107,
T__107=108, LINECOMMENT=109, COMMENT=110, WS=111, EOL=112, NAME=113, DEC_INTEGER=114,
HEX_INTEGER=115, BIN_INTEGER=116, ADDRESS_OF=117, FLOAT_NUMBER=118, STRING=119,
INLINEASMBLOCK=120, SINGLECHAR=121, ZEROPAGE=122;
INLINEASMBLOCK=120, SINGLECHAR=121, ZEROPAGE=122, ARRAYSIG=123;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
@@ -63,7 +63,7 @@ public class prog8Lexer extends Lexer {
"T__105", "T__106", "T__107", "LINECOMMENT", "COMMENT", "WS", "EOL",
"NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "ADDRESS_OF", "FLOAT_NUMBER",
"FNUMBER", "STRING_ESCAPE_SEQ", "STRING", "INLINEASMBLOCK", "SINGLECHAR",
"ZEROPAGE"
"ZEROPAGE", "ARRAYSIG"
};
}
public static final String[] ruleNames = makeRuleNames();
@@ -84,7 +84,8 @@ public class prog8Lexer extends Lexer {
"'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'", null, null, null,
null, null, null, null, null, "'&'", null, null, null, null, "'@zp'"
null, null, null, null, null, "'&'", null, null, null, null, "'@zp'",
"'[]'"
};
}
private static final String[] _LITERAL_NAMES = makeLiteralNames();
@@ -101,7 +102,7 @@ public class prog8Lexer extends Lexer {
null, null, null, null, null, null, null, null, null, null, null, null,
null, "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER",
"BIN_INTEGER", "ADDRESS_OF", "FLOAT_NUMBER", "STRING", "INLINEASMBLOCK",
"SINGLECHAR", "ZEROPAGE"
"SINGLECHAR", "ZEROPAGE", "ARRAYSIG"
};
}
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
@@ -211,7 +212,7 @@ public class prog8Lexer extends Lexer {
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2|\u0359\b\1\4\2\t"+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2}\u035e\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
@@ -224,277 +225,278 @@ public class prog8Lexer extends Lexer {
"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
"`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k\t"+
"k\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv\4"+
"w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3"+
"\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6"+
"\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3"+
"\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n"+
"\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13"+
"\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3"+
"\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3"+
"\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3"+
"\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3"+
"\24\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3"+
"\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3"+
"\33\3\34\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\37\3\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.\3.\3.\3/\3/\3"+
"/\3\60\3\60\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\63\3\64\3\64\3\64\3\65"+
"\3\65\3\65\3\66\3\66\3\67\3\67\38\38\38\39\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@\3A\3A\3B\3B\3B\3B"+
"\3B\3B\3B\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3D\3E\3E\3F\3F\3G"+
"\3G\3H\3H\3I\3I\3I\3J\3J\3J\3K\3K\3K\3L\3L\3L\3M\3M\3M\3N\3N\3N\3O\3O"+
"\3O\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3R\3S\3S\3S\3S\3S\3T\3T\3T"+
"\3T\3U\3U\3U\3V\3V\3W\3W\3X\3X\3X\3X\3X\3X\3X\3Y\3Y\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`\3a\3a\3a\3a\3a\3a\3"+
"b\3b\3b\3b\3b\3b\3c\3c\3c\3c\3c\3c\3d\3d\3d\3d\3d\3d\3d\3e\3e\3e\3e\3"+
"e\3e\3f\3f\3f\3f\3f\3f\3f\3g\3g\3g\3g\3g\3g\3h\3h\3h\3h\3h\3h\3i\3i\3"+
"i\3i\3j\3j\3j\3k\3k\3k\3k\3k\3k\3l\3l\3l\3l\3l\3l\3l\3m\3m\3m\3m\3m\3"+
"m\3n\3n\7n\u02e2\nn\fn\16n\u02e5\13n\3n\3n\3n\3n\3o\3o\7o\u02ed\no\fo"+
"\16o\u02f0\13o\3o\3o\3p\3p\3p\3p\3q\6q\u02f9\nq\rq\16q\u02fa\3r\3r\7r"+
"\u02ff\nr\fr\16r\u0302\13r\3s\3s\3s\6s\u0307\ns\rs\16s\u0308\5s\u030b"+
"\ns\3t\3t\6t\u030f\nt\rt\16t\u0310\3u\3u\6u\u0315\nu\ru\16u\u0316\3v\3"+
"v\3w\3w\3w\5w\u031e\nw\3w\5w\u0321\nw\3x\6x\u0324\nx\rx\16x\u0325\3x\3"+
"x\6x\u032a\nx\rx\16x\u032b\5x\u032e\nx\3y\3y\3y\3y\5y\u0334\ny\3z\3z\3"+
"z\7z\u0339\nz\fz\16z\u033c\13z\3z\3z\3z\3{\3{\3{\3{\6{\u0345\n{\r{\16"+
"{\u0346\3{\3{\3{\3{\3{\3|\3|\3|\5|\u0351\n|\3|\3|\3|\3}\3}\3}\3}\3\u0346"+
"\2~\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\67"+
"m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008d"+
"H\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1"+
"R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5"+
"\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9"+
"f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9n\u00dbo\u00dd"+
"p\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9v\u00ebw\u00edx\u00ef\2\u00f1"+
"\2\u00f3y\u00f5z\u00f7{\u00f9|\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"+
"\u0368\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\2"+
"G\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\2"+
"m\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\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9"+
"\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2"+
"\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb"+
"\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2"+
"\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd"+
"\3\2\2\2\2\u00df\3\2\2\2\2\u00e1\3\2\2\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2"+
"\2\2\u00e7\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2\2\2\u00f3"+
"\3\2\2\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9\3\2\2\2\3\u00fb\3\2\2"+
"\2\5\u00fd\3\2\2\2\7\u00ff\3\2\2\2\t\u0104\3\2\2\2\13\u010c\3\2\2\2\r"+
"\u0116\3\2\2\2\17\u0120\3\2\2\2\21\u012c\3\2\2\2\23\u0135\3\2\2\2\25\u013d"+
"\3\2\2\2\27\u0149\3\2\2\2\31\u0155\3\2\2\2\33\u0160\3\2\2\2\35\u0168\3"+
"\2\2\2\37\u016a\3\2\2\2!\u016c\3\2\2\2#\u0172\3\2\2\2%\u0178\3\2\2\2\'"+
"\u017d\3\2\2\2)\u0183\3\2\2\2+\u0188\3\2\2\2-\u018e\3\2\2\2/\u0192\3\2"+
"\2\2\61\u0198\3\2\2\2\63\u019a\3\2\2\2\65\u019c\3\2\2\2\67\u019f\3\2\2"+
"\29\u01a2\3\2\2\2;\u01a5\3\2\2\2=\u01a8\3\2\2\2?\u01ac\3\2\2\2A\u01af"+
"\3\2\2\2C\u01b2\3\2\2\2E\u01b5\3\2\2\2G\u01b8\3\2\2\2I\u01bc\3\2\2\2K"+
"\u01c0\3\2\2\2M\u01c3\3\2\2\2O\u01c6\3\2\2\2Q\u01c8\3\2\2\2S\u01ca\3\2"+
"\2\2U\u01cd\3\2\2\2W\u01cf\3\2\2\2Y\u01d1\3\2\2\2[\u01d3\3\2\2\2]\u01d6"+
"\3\2\2\2_\u01d9\3\2\2\2a\u01db\3\2\2\2c\u01dd\3\2\2\2e\u01e0\3\2\2\2g"+
"\u01e3\3\2\2\2i\u01e6\3\2\2\2k\u01e9\3\2\2\2m\u01eb\3\2\2\2o\u01ed\3\2"+
"\2\2q\u01f0\3\2\2\2s\u01f5\3\2\2\2u\u01f9\3\2\2\2w\u01fc\3\2\2\2y\u0200"+
"\3\2\2\2{\u0204\3\2\2\2}\u0206\3\2\2\2\177\u0208\3\2\2\2\u0081\u020b\3"+
"\2\2\2\u0083\u020d\3\2\2\2\u0085\u0214\3\2\2\2\u0087\u021a\3\2\2\2\u0089"+
"\u0223\3\2\2\2\u008b\u0225\3\2\2\2\u008d\u0227\3\2\2\2\u008f\u0229\3\2"+
"\2\2\u0091\u022b\3\2\2\2\u0093\u022e\3\2\2\2\u0095\u0231\3\2\2\2\u0097"+
"\u0234\3\2\2\2\u0099\u0237\3\2\2\2\u009b\u023a\3\2\2\2\u009d\u023d\3\2"+
"\2\2\u009f\u0240\3\2\2\2\u00a1\u0243\3\2\2\2\u00a3\u0248\3\2\2\2\u00a5"+
"\u024e\3\2\2\2\u00a7\u0253\3\2\2\2\u00a9\u0257\3\2\2\2\u00ab\u025a\3\2"+
"\2\2\u00ad\u025c\3\2\2\2\u00af\u025e\3\2\2\2\u00b1\u0265\3\2\2\2\u00b3"+
"\u026e\3\2\2\2\u00b5\u0274\3\2\2\2\u00b7\u0277\3\2\2\2\u00b9\u027c\3\2"+
"\2\2\u00bb\u0282\3\2\2\2\u00bd\u0288\3\2\2\2\u00bf\u028e\3\2\2\2\u00c1"+
"\u0293\3\2\2\2\u00c3\u0299\3\2\2\2\u00c5\u029f\3\2\2\2\u00c7\u02a5\3\2"+
"\2\2\u00c9\u02ac\3\2\2\2\u00cb\u02b2\3\2\2\2\u00cd\u02b9\3\2\2\2\u00cf"+
"\u02bf\3\2\2\2\u00d1\u02c5\3\2\2\2\u00d3\u02c9\3\2\2\2\u00d5\u02cc\3\2"+
"\2\2\u00d7\u02d2\3\2\2\2\u00d9\u02d9\3\2\2\2\u00db\u02df\3\2\2\2\u00dd"+
"\u02ea\3\2\2\2\u00df\u02f3\3\2\2\2\u00e1\u02f8\3\2\2\2\u00e3\u02fc\3\2"+
"\2\2\u00e5\u030a\3\2\2\2\u00e7\u030c\3\2\2\2\u00e9\u0312\3\2\2\2\u00eb"+
"\u0318\3\2\2\2\u00ed\u031a\3\2\2\2\u00ef\u0323\3\2\2\2\u00f1\u0333\3\2"+
"\2\2\u00f3\u0335\3\2\2\2\u00f5\u0340\3\2\2\2\u00f7\u034d\3\2\2\2\u00f9"+
"\u0355\3\2\2\2\u00fb\u00fc\7\u0080\2\2\u00fc\4\3\2\2\2\u00fd\u00fe\7<"+
"\2\2\u00fe\6\3\2\2\2\u00ff\u0100\7i\2\2\u0100\u0101\7q\2\2\u0101\u0102"+
"\7v\2\2\u0102\u0103\7q\2\2\u0103\b\3\2\2\2\u0104\u0105\7\'\2\2\u0105\u0106"+
"\7q\2\2\u0106\u0107\7w\2\2\u0107\u0108\7v\2\2\u0108\u0109\7r\2\2\u0109"+
"\u010a\7w\2\2\u010a\u010b\7v\2\2\u010b\n\3\2\2\2\u010c\u010d\7\'\2\2\u010d"+
"\u010e\7n\2\2\u010e\u010f\7c\2\2\u010f\u0110\7w\2\2\u0110\u0111\7p\2\2"+
"\u0111\u0112\7e\2\2\u0112\u0113\7j\2\2\u0113\u0114\7g\2\2\u0114\u0115"+
"\7t\2\2\u0115\f\3\2\2\2\u0116\u0117\7\'\2\2\u0117\u0118\7|\2\2\u0118\u0119"+
"\7g\2\2\u0119\u011a\7t\2\2\u011a\u011b\7q\2\2\u011b\u011c\7r\2\2\u011c"+
"\u011d\7c\2\2\u011d\u011e\7i\2\2\u011e\u011f\7g\2\2\u011f\16\3\2\2\2\u0120"+
"\u0121\7\'\2\2\u0121\u0122\7|\2\2\u0122\u0123\7r\2\2\u0123\u0124\7t\2"+
"\2\u0124\u0125\7g\2\2\u0125\u0126\7u\2\2\u0126\u0127\7g\2\2\u0127\u0128"+
"\7t\2\2\u0128\u0129\7x\2\2\u0129\u012a\7g\2\2\u012a\u012b\7f\2\2\u012b"+
"\20\3\2\2\2\u012c\u012d\7\'\2\2\u012d\u012e\7c\2\2\u012e\u012f\7f\2\2"+
"\u012f\u0130\7f\2\2\u0130\u0131\7t\2\2\u0131\u0132\7g\2\2\u0132\u0133"+
"\7u\2\2\u0133\u0134\7u\2\2\u0134\22\3\2\2\2\u0135\u0136\7\'\2\2\u0136"+
"\u0137\7k\2\2\u0137\u0138\7o\2\2\u0138\u0139\7r\2\2\u0139\u013a\7q\2\2"+
"\u013a\u013b\7t\2\2\u013b\u013c\7v\2\2\u013c\24\3\2\2\2\u013d\u013e\7"+
"\'\2\2\u013e\u013f\7d\2\2\u013f\u0140\7t\2\2\u0140\u0141\7g\2\2\u0141"+
"\u0142\7c\2\2\u0142\u0143\7m\2\2\u0143\u0144\7r\2\2\u0144\u0145\7q\2\2"+
"\u0145\u0146\7k\2\2\u0146\u0147\7p\2\2\u0147\u0148\7v\2\2\u0148\26\3\2"+
"\2\2\u0149\u014a\7\'\2\2\u014a\u014b\7c\2\2\u014b\u014c\7u\2\2\u014c\u014d"+
"\7o\2\2\u014d\u014e\7k\2\2\u014e\u014f\7p\2\2\u014f\u0150\7e\2\2\u0150"+
"\u0151\7n\2\2\u0151\u0152\7w\2\2\u0152\u0153\7f\2\2\u0153\u0154\7g\2\2"+
"\u0154\30\3\2\2\2\u0155\u0156\7\'\2\2\u0156\u0157\7c\2\2\u0157\u0158\7"+
"u\2\2\u0158\u0159\7o\2\2\u0159\u015a\7d\2\2\u015a\u015b\7k\2\2\u015b\u015c"+
"\7p\2\2\u015c\u015d\7c\2\2\u015d\u015e\7t\2\2\u015e\u015f\7{\2\2\u015f"+
"\32\3\2\2\2\u0160\u0161\7\'\2\2\u0161\u0162\7q\2\2\u0162\u0163\7r\2\2"+
"\u0163\u0164\7v\2\2\u0164\u0165\7k\2\2\u0165\u0166\7q\2\2\u0166\u0167"+
"\7p\2\2\u0167\34\3\2\2\2\u0168\u0169\7.\2\2\u0169\36\3\2\2\2\u016a\u016b"+
"\7?\2\2\u016b \3\2\2\2\u016c\u016d\7e\2\2\u016d\u016e\7q\2\2\u016e\u016f"+
"\7p\2\2\u016f\u0170\7u\2\2\u0170\u0171\7v\2\2\u0171\"\3\2\2\2\u0172\u0173"+
"\7w\2\2\u0173\u0174\7d\2\2\u0174\u0175\7{\2\2\u0175\u0176\7v\2\2\u0176"+
"\u0177\7g\2\2\u0177$\3\2\2\2\u0178\u0179\7d\2\2\u0179\u017a\7{\2\2\u017a"+
"\u017b\7v\2\2\u017b\u017c\7g\2\2\u017c&\3\2\2\2\u017d\u017e\7w\2\2\u017e"+
"\u017f\7y\2\2\u017f\u0180\7q\2\2\u0180\u0181\7t\2\2\u0181\u0182\7f\2\2"+
"\u0182(\3\2\2\2\u0183\u0184\7y\2\2\u0184\u0185\7q\2\2\u0185\u0186\7t\2"+
"\2\u0186\u0187\7f\2\2\u0187*\3\2\2\2\u0188\u0189\7h\2\2\u0189\u018a\7"+
"n\2\2\u018a\u018b\7q\2\2\u018b\u018c\7c\2\2\u018c\u018d\7v\2\2\u018d,"+
"\3\2\2\2\u018e\u018f\7u\2\2\u018f\u0190\7v\2\2\u0190\u0191\7t\2\2\u0191"+
".\3\2\2\2\u0192\u0193\7u\2\2\u0193\u0194\7v\2\2\u0194\u0195\7t\2\2\u0195"+
"\u0196\7a\2\2\u0196\u0197\7u\2\2\u0197\60\3\2\2\2\u0198\u0199\7]\2\2\u0199"+
"\62\3\2\2\2\u019a\u019b\7_\2\2\u019b\64\3\2\2\2\u019c\u019d\7-\2\2\u019d"+
"\u019e\7?\2\2\u019e\66\3\2\2\2\u019f\u01a0\7/\2\2\u01a0\u01a1\7?\2\2\u01a1"+
"8\3\2\2\2\u01a2\u01a3\7\61\2\2\u01a3\u01a4\7?\2\2\u01a4:\3\2\2\2\u01a5"+
"\u01a6\7,\2\2\u01a6\u01a7\7?\2\2\u01a7<\3\2\2\2\u01a8\u01a9\7,\2\2\u01a9"+
"\u01aa\7,\2\2\u01aa\u01ab\7?\2\2\u01ab>\3\2\2\2\u01ac\u01ad\7(\2\2\u01ad"+
"\u01ae\7?\2\2\u01ae@\3\2\2\2\u01af\u01b0\7~\2\2\u01b0\u01b1\7?\2\2\u01b1"+
"B\3\2\2\2\u01b2\u01b3\7`\2\2\u01b3\u01b4\7?\2\2\u01b4D\3\2\2\2\u01b5\u01b6"+
"\7\'\2\2\u01b6\u01b7\7?\2\2\u01b7F\3\2\2\2\u01b8\u01b9\7>\2\2\u01b9\u01ba"+
"\7>\2\2\u01ba\u01bb\7?\2\2\u01bbH\3\2\2\2\u01bc\u01bd\7@\2\2\u01bd\u01be"+
"\7@\2\2\u01be\u01bf\7?\2\2\u01bfJ\3\2\2\2\u01c0\u01c1\7-\2\2\u01c1\u01c2"+
"\7-\2\2\u01c2L\3\2\2\2\u01c3\u01c4\7/\2\2\u01c4\u01c5\7/\2\2\u01c5N\3"+
"\2\2\2\u01c6\u01c7\7-\2\2\u01c7P\3\2\2\2\u01c8\u01c9\7/\2\2\u01c9R\3\2"+
"\2\2\u01ca\u01cb\7,\2\2\u01cb\u01cc\7,\2\2\u01ccT\3\2\2\2\u01cd\u01ce"+
"\7,\2\2\u01ceV\3\2\2\2\u01cf\u01d0\7\61\2\2\u01d0X\3\2\2\2\u01d1\u01d2"+
"\7\'\2\2\u01d2Z\3\2\2\2\u01d3\u01d4\7>\2\2\u01d4\u01d5\7>\2\2\u01d5\\"+
"\3\2\2\2\u01d6\u01d7\7@\2\2\u01d7\u01d8\7@\2\2\u01d8^\3\2\2\2\u01d9\u01da"+
"\7>\2\2\u01da`\3\2\2\2\u01db\u01dc\7@\2\2\u01dcb\3\2\2\2\u01dd\u01de\7"+
">\2\2\u01de\u01df\7?\2\2\u01dfd\3\2\2\2\u01e0\u01e1\7@\2\2\u01e1\u01e2"+
"\7?\2\2\u01e2f\3\2\2\2\u01e3\u01e4\7?\2\2\u01e4\u01e5\7?\2\2\u01e5h\3"+
"\2\2\2\u01e6\u01e7\7#\2\2\u01e7\u01e8\7?\2\2\u01e8j\3\2\2\2\u01e9\u01ea"+
"\7`\2\2\u01eal\3\2\2\2\u01eb\u01ec\7~\2\2\u01ecn\3\2\2\2\u01ed\u01ee\7"+
"v\2\2\u01ee\u01ef\7q\2\2\u01efp\3\2\2\2\u01f0\u01f1\7u\2\2\u01f1\u01f2"+
"\7v\2\2\u01f2\u01f3\7g\2\2\u01f3\u01f4\7r\2\2\u01f4r\3\2\2\2\u01f5\u01f6"+
"\7c\2\2\u01f6\u01f7\7p\2\2\u01f7\u01f8\7f\2\2\u01f8t\3\2\2\2\u01f9\u01fa"+
"\7q\2\2\u01fa\u01fb\7t\2\2\u01fbv\3\2\2\2\u01fc\u01fd\7z\2\2\u01fd\u01fe"+
"\7q\2\2\u01fe\u01ff\7t\2\2\u01ffx\3\2\2\2\u0200\u0201\7p\2\2\u0201\u0202"+
"\7q\2\2\u0202\u0203\7v\2\2\u0203z\3\2\2\2\u0204\u0205\7*\2\2\u0205|\3"+
"\2\2\2\u0206\u0207\7+\2\2\u0207~\3\2\2\2\u0208\u0209\7c\2\2\u0209\u020a"+
"\7u\2\2\u020a\u0080\3\2\2\2\u020b\u020c\7B\2\2\u020c\u0082\3\2\2\2\u020d"+
"\u020e\7t\2\2\u020e\u020f\7g\2\2\u020f\u0210\7v\2\2\u0210\u0211\7w\2\2"+
"\u0211\u0212\7t\2\2\u0212\u0213\7p\2\2\u0213\u0084\3\2\2\2\u0214\u0215"+
"\7d\2\2\u0215\u0216\7t\2\2\u0216\u0217\7g\2\2\u0217\u0218\7c\2\2\u0218"+
"\u0219\7m\2\2\u0219\u0086\3\2\2\2\u021a\u021b\7e\2\2\u021b\u021c\7q\2"+
"\2\u021c\u021d\7p\2\2\u021d\u021e\7v\2\2\u021e\u021f\7k\2\2\u021f\u0220"+
"\7p\2\2\u0220\u0221\7w\2\2\u0221\u0222\7g\2\2\u0222\u0088\3\2\2\2\u0223"+
"\u0224\7\60\2\2\u0224\u008a\3\2\2\2\u0225\u0226\7C\2\2\u0226\u008c\3\2"+
"\2\2\u0227\u0228\7Z\2\2\u0228\u008e\3\2\2\2\u0229\u022a\7[\2\2\u022a\u0090"+
"\3\2\2\2\u022b\u022c\7C\2\2\u022c\u022d\7Z\2\2\u022d\u0092\3\2\2\2\u022e"+
"\u022f\7C\2\2\u022f\u0230\7[\2\2\u0230\u0094\3\2\2\2\u0231\u0232\7Z\2"+
"\2\u0232\u0233\7[\2\2\u0233\u0096\3\2\2\2\u0234\u0235\7R\2\2\u0235\u0236"+
"\7e\2\2\u0236\u0098\3\2\2\2\u0237\u0238\7R\2\2\u0238\u0239\7|\2\2\u0239"+
"\u009a\3\2\2\2\u023a\u023b\7R\2\2\u023b\u023c\7p\2\2\u023c\u009c\3\2\2"+
"\2\u023d\u023e\7R\2\2\u023e\u023f\7x\2\2\u023f\u009e\3\2\2\2\u0240\u0241"+
"\7\60\2\2\u0241\u0242\7y\2\2\u0242\u00a0\3\2\2\2\u0243\u0244\7v\2\2\u0244"+
"\u0245\7t\2\2\u0245\u0246\7w\2\2\u0246\u0247\7g\2\2\u0247\u00a2\3\2\2"+
"\2\u0248\u0249\7h\2\2\u0249\u024a\7c\2\2\u024a\u024b\7n\2\2\u024b\u024c"+
"\7u\2\2\u024c\u024d\7g\2\2\u024d\u00a4\3\2\2\2\u024e\u024f\7\'\2\2\u024f"+
"\u0250\7c\2\2\u0250\u0251\7u\2\2\u0251\u0252\7o\2\2\u0252\u00a6\3\2\2"+
"\2\u0253\u0254\7u\2\2\u0254\u0255\7w\2\2\u0255\u0256\7d\2\2\u0256\u00a8"+
"\3\2\2\2\u0257\u0258\7/\2\2\u0258\u0259\7@\2\2\u0259\u00aa\3\2\2\2\u025a"+
"\u025b\7}\2\2\u025b\u00ac\3\2\2\2\u025c\u025d\7\177\2\2\u025d\u00ae\3"+
"\2\2\2\u025e\u025f\7c\2\2\u025f\u0260\7u\2\2\u0260\u0261\7o\2\2\u0261"+
"\u0262\7u\2\2\u0262\u0263\7w\2\2\u0263\u0264\7d\2\2\u0264\u00b0\3\2\2"+
"\2\u0265\u0266\7e\2\2\u0266\u0267\7n\2\2\u0267\u0268\7q\2\2\u0268\u0269"+
"\7d\2\2\u0269\u026a\7d\2\2\u026a\u026b\7g\2\2\u026b\u026c\7t\2\2\u026c"+
"\u026d\7u\2\2\u026d\u00b2\3\2\2\2\u026e\u026f\7u\2\2\u026f\u0270\7v\2"+
"\2\u0270\u0271\7c\2\2\u0271\u0272\7e\2\2\u0272\u0273\7m\2\2\u0273\u00b4"+
"\3\2\2\2\u0274\u0275\7k\2\2\u0275\u0276\7h\2\2\u0276\u00b6\3\2\2\2\u0277"+
"\u0278\7g\2\2\u0278\u0279\7n\2\2\u0279\u027a\7u\2\2\u027a\u027b\7g\2\2"+
"\u027b\u00b8\3\2\2\2\u027c\u027d\7k\2\2\u027d\u027e\7h\2\2\u027e\u027f"+
"\7a\2\2\u027f\u0280\7e\2\2\u0280\u0281\7u\2\2\u0281\u00ba\3\2\2\2\u0282"+
"\u0283\7k\2\2\u0283\u0284\7h\2\2\u0284\u0285\7a\2\2\u0285\u0286\7e\2\2"+
"\u0286\u0287\7e\2\2\u0287\u00bc\3\2\2\2\u0288\u0289\7k\2\2\u0289\u028a"+
"\7h\2\2\u028a\u028b\7a\2\2\u028b\u028c\7g\2\2\u028c\u028d\7s\2\2\u028d"+
"\u00be\3\2\2\2\u028e\u028f\7k\2\2\u028f\u0290\7h\2\2\u0290\u0291\7a\2"+
"\2\u0291\u0292\7|\2\2\u0292\u00c0\3\2\2\2\u0293\u0294\7k\2\2\u0294\u0295"+
"\7h\2\2\u0295\u0296\7a\2\2\u0296\u0297\7p\2\2\u0297\u0298\7g\2\2\u0298"+
"\u00c2\3\2\2\2\u0299\u029a\7k\2\2\u029a\u029b\7h\2\2\u029b\u029c\7a\2"+
"\2\u029c\u029d\7p\2\2\u029d\u029e\7|\2\2\u029e\u00c4\3\2\2\2\u029f\u02a0"+
"\7k\2\2\u02a0\u02a1\7h\2\2\u02a1\u02a2\7a\2\2\u02a2\u02a3\7r\2\2\u02a3"+
"\u02a4\7n\2\2\u02a4\u00c6\3\2\2\2\u02a5\u02a6\7k\2\2\u02a6\u02a7\7h\2"+
"\2\u02a7\u02a8\7a\2\2\u02a8\u02a9\7r\2\2\u02a9\u02aa\7q\2\2\u02aa\u02ab"+
"\7u\2\2\u02ab\u00c8\3\2\2\2\u02ac\u02ad\7k\2\2\u02ad\u02ae\7h\2\2\u02ae"+
"\u02af\7a\2\2\u02af\u02b0\7o\2\2\u02b0\u02b1\7k\2\2\u02b1\u00ca\3\2\2"+
"\2\u02b2\u02b3\7k\2\2\u02b3\u02b4\7h\2\2\u02b4\u02b5\7a\2\2\u02b5\u02b6"+
"\7p\2\2\u02b6\u02b7\7g\2\2\u02b7\u02b8\7i\2\2\u02b8\u00cc\3\2\2\2\u02b9"+
"\u02ba\7k\2\2\u02ba\u02bb\7h\2\2\u02bb\u02bc\7a\2\2\u02bc\u02bd\7x\2\2"+
"\u02bd\u02be\7u\2\2\u02be\u00ce\3\2\2\2\u02bf\u02c0\7k\2\2\u02c0\u02c1"+
"\7h\2\2\u02c1\u02c2\7a\2\2\u02c2\u02c3\7x\2\2\u02c3\u02c4\7e\2\2\u02c4"+
"\u00d0\3\2\2\2\u02c5\u02c6\7h\2\2\u02c6\u02c7\7q\2\2\u02c7\u02c8\7t\2"+
"\2\u02c8\u00d2\3\2\2\2\u02c9\u02ca\7k\2\2\u02ca\u02cb\7p\2\2\u02cb\u00d4"+
"\3\2\2\2\u02cc\u02cd\7y\2\2\u02cd\u02ce\7j\2\2\u02ce\u02cf\7k\2\2\u02cf"+
"\u02d0\7n\2\2\u02d0\u02d1\7g\2\2\u02d1\u00d6\3\2\2\2\u02d2\u02d3\7t\2"+
"\2\u02d3\u02d4\7g\2\2\u02d4\u02d5\7r\2\2\u02d5\u02d6\7g\2\2\u02d6\u02d7"+
"\7c\2\2\u02d7\u02d8\7v\2\2\u02d8\u00d8\3\2\2\2\u02d9\u02da\7w\2\2\u02da"+
"\u02db\7p\2\2\u02db\u02dc\7v\2\2\u02dc\u02dd\7k\2\2\u02dd\u02de\7n\2\2"+
"\u02de\u00da\3\2\2\2\u02df\u02e3\t\2\2\2\u02e0\u02e2\t\3\2\2\u02e1\u02e0"+
"\3\2\2\2\u02e2\u02e5\3\2\2\2\u02e3\u02e1\3\2\2\2\u02e3\u02e4\3\2\2\2\u02e4"+
"\u02e6\3\2\2\2\u02e5\u02e3\3\2\2\2\u02e6\u02e7\5\u00ddo\2\u02e7\u02e8"+
"\3\2\2\2\u02e8\u02e9\bn\2\2\u02e9\u00dc\3\2\2\2\u02ea\u02ee\7=\2\2\u02eb"+
"\u02ed\n\2\2\2\u02ec\u02eb\3\2\2\2\u02ed\u02f0\3\2\2\2\u02ee\u02ec\3\2"+
"\2\2\u02ee\u02ef\3\2\2\2\u02ef\u02f1\3\2\2\2\u02f0\u02ee\3\2\2\2\u02f1"+
"\u02f2\bo\2\2\u02f2\u00de\3\2\2\2\u02f3\u02f4\t\3\2\2\u02f4\u02f5\3\2"+
"\2\2\u02f5\u02f6\bp\3\2\u02f6\u00e0\3\2\2\2\u02f7\u02f9\t\2\2\2\u02f8"+
"\u02f7\3\2\2\2\u02f9\u02fa\3\2\2\2\u02fa\u02f8\3\2\2\2\u02fa\u02fb\3\2"+
"\2\2\u02fb\u00e2\3\2\2\2\u02fc\u0300\t\4\2\2\u02fd\u02ff\t\5\2\2\u02fe"+
"\u02fd\3\2\2\2\u02ff\u0302\3\2\2\2\u0300\u02fe\3\2\2\2\u0300\u0301\3\2"+
"\2\2\u0301\u00e4\3\2\2\2\u0302\u0300\3\2\2\2\u0303\u030b\4\62;\2\u0304"+
"\u0306\4\63;\2\u0305\u0307\4\62;\2\u0306\u0305\3\2\2\2\u0307\u0308\3\2"+
"\2\2\u0308\u0306\3\2\2\2\u0308\u0309\3\2\2\2\u0309\u030b\3\2\2\2\u030a"+
"\u0303\3\2\2\2\u030a\u0304\3\2\2\2\u030b\u00e6\3\2\2\2\u030c\u030e\7&"+
"\2\2\u030d\u030f\t\6\2\2\u030e\u030d\3\2\2\2\u030f\u0310\3\2\2\2\u0310"+
"\u030e\3\2\2\2\u0310\u0311\3\2\2\2\u0311\u00e8\3\2\2\2\u0312\u0314\7\'"+
"\2\2\u0313\u0315\4\62\63\2\u0314\u0313\3\2\2\2\u0315\u0316\3\2\2\2\u0316"+
"\u0314\3\2\2\2\u0316\u0317\3\2\2\2\u0317\u00ea\3\2\2\2\u0318\u0319\7("+
"\2\2\u0319\u00ec\3\2\2\2\u031a\u0320\5\u00efx\2\u031b\u031d\t\7\2\2\u031c"+
"\u031e\t\b\2\2\u031d\u031c\3\2\2\2\u031d\u031e\3\2\2\2\u031e\u031f\3\2"+
"\2\2\u031f\u0321\5\u00efx\2\u0320\u031b\3\2\2\2\u0320\u0321\3\2\2\2\u0321"+
"\u00ee\3\2\2\2\u0322\u0324\4\62;\2\u0323\u0322\3\2\2\2\u0324\u0325\3\2"+
"\2\2\u0325\u0323\3\2\2\2\u0325\u0326\3\2\2\2\u0326\u032d\3\2\2\2\u0327"+
"\u0329\7\60\2\2\u0328\u032a\4\62;\2\u0329\u0328\3\2\2\2\u032a\u032b\3"+
"\2\2\2\u032b\u0329\3\2\2\2\u032b\u032c\3\2\2\2\u032c\u032e\3\2\2\2\u032d"+
"\u0327\3\2\2\2\u032d\u032e\3\2\2\2\u032e\u00f0\3\2\2\2\u032f\u0330\7^"+
"\2\2\u0330\u0334\13\2\2\2\u0331\u0332\7^\2\2\u0332\u0334\5\u00e1q\2\u0333"+
"\u032f\3\2\2\2\u0333\u0331\3\2\2\2\u0334\u00f2\3\2\2\2\u0335\u033a\7$"+
"\2\2\u0336\u0339\5\u00f1y\2\u0337\u0339\n\t\2\2\u0338\u0336\3\2\2\2\u0338"+
"\u0337\3\2\2\2\u0339\u033c\3\2\2\2\u033a\u0338\3\2\2\2\u033a\u033b\3\2"+
"\2\2\u033b\u033d\3\2\2\2\u033c\u033a\3\2\2\2\u033d\u033e\7$\2\2\u033e"+
"\u033f\bz\4\2\u033f\u00f4\3\2\2\2\u0340\u0341\7}\2\2\u0341\u0342\7}\2"+
"\2\u0342\u0344\3\2\2\2\u0343\u0345\13\2\2\2\u0344\u0343\3\2\2\2\u0345"+
"\u0346\3\2\2\2\u0346\u0347\3\2\2\2\u0346\u0344\3\2\2\2\u0347\u0348\3\2"+
"\2\2\u0348\u0349\7\177\2\2\u0349\u034a\7\177\2\2\u034a\u034b\3\2\2\2\u034b"+
"\u034c\b{\5\2\u034c\u00f6\3\2\2\2\u034d\u0350\7)\2\2\u034e\u0351\5\u00f1"+
"y\2\u034f\u0351\n\t\2\2\u0350\u034e\3\2\2\2\u0350\u034f\3\2\2\2\u0351"+
"\u0352\3\2\2\2\u0352\u0353\7)\2\2\u0353\u0354\b|\6\2\u0354\u00f8\3\2\2"+
"\2\u0355\u0356\7B\2\2\u0356\u0357\7|\2\2\u0357\u0358\7r\2\2\u0358\u00fa"+
"\3\2\2\2\26\2\u02e3\u02ee\u02fa\u0300\u0308\u030a\u030e\u0310\u0316\u031d"+
"\u0320\u0325\u032b\u032d\u0333\u0338\u033a\u0346\u0350\7\2\3\2\b\2\2\3"+
"z\2\3{\3\3|\4";
"w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\3\2\3\2\3\3\3\3\3\4\3\4"+
"\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3"+
"\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b"+
"\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3"+
"\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13"+
"\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3"+
"\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3"+
"\16\3\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3"+
"\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3"+
"\24\3\24\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3"+
"\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3"+
"\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\37\3\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.\3.\3.\3/"+
"\3/\3/\3\60\3\60\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\63\3\64\3\64\3\64"+
"\3\65\3\65\3\65\3\66\3\66\3\67\3\67\38\38\38\39\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@\3A\3A\3B\3B\3"+
"B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3D\3E\3E\3F\3"+
"F\3G\3G\3H\3H\3I\3I\3I\3J\3J\3J\3K\3K\3K\3L\3L\3L\3M\3M\3M\3N\3N\3N\3"+
"O\3O\3O\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3R\3S\3S\3S\3S\3S\3T\3"+
"T\3T\3T\3U\3U\3U\3V\3V\3W\3W\3X\3X\3X\3X\3X\3X\3X\3Y\3Y\3Y\3Y\3Y\3Y\3"+
"Y\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`\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\7n\u02e4\nn\fn\16n\u02e7\13n\3n\3n\3n\3n\3o\3o\7o\u02ef\n"+
"o\fo\16o\u02f2\13o\3o\3o\3p\3p\3p\3p\3q\6q\u02fb\nq\rq\16q\u02fc\3r\3"+
"r\7r\u0301\nr\fr\16r\u0304\13r\3s\3s\3s\6s\u0309\ns\rs\16s\u030a\5s\u030d"+
"\ns\3t\3t\6t\u0311\nt\rt\16t\u0312\3u\3u\6u\u0317\nu\ru\16u\u0318\3v\3"+
"v\3w\3w\3w\5w\u0320\nw\3w\5w\u0323\nw\3x\6x\u0326\nx\rx\16x\u0327\3x\3"+
"x\6x\u032c\nx\rx\16x\u032d\5x\u0330\nx\3y\3y\3y\3y\5y\u0336\ny\3z\3z\3"+
"z\7z\u033b\nz\fz\16z\u033e\13z\3z\3z\3z\3{\3{\3{\3{\6{\u0347\n{\r{\16"+
"{\u0348\3{\3{\3{\3{\3{\3|\3|\3|\5|\u0353\n|\3|\3|\3|\3}\3}\3}\3}\3~\3"+
"~\3~\3\u0348\2\177\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\63"+
"e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089"+
"F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009d"+
"P\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1"+
"Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5"+
"d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9"+
"n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5t\u00e7u\u00e9v\u00ebw\u00ed"+
"x\u00ef\2\u00f1\2\u00f3y\u00f5z\u00f7{\u00f9|\u00fb}\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\u036d\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\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7"+
"\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2"+
"\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9"+
"\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2"+
"\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9\3\2\2\2\2\u00db"+
"\3\2\2\2\2\u00dd\3\2\2\2\2\u00df\3\2\2\2\2\u00e1\3\2\2\2\2\u00e3\3\2\2"+
"\2\2\u00e5\3\2\2\2\2\u00e7\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed"+
"\3\2\2\2\2\u00f3\3\2\2\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9\3\2\2"+
"\2\2\u00fb\3\2\2\2\3\u00fd\3\2\2\2\5\u00ff\3\2\2\2\7\u0101\3\2\2\2\t\u0106"+
"\3\2\2\2\13\u010e\3\2\2\2\r\u0118\3\2\2\2\17\u0122\3\2\2\2\21\u012e\3"+
"\2\2\2\23\u0137\3\2\2\2\25\u013f\3\2\2\2\27\u014b\3\2\2\2\31\u0157\3\2"+
"\2\2\33\u0162\3\2\2\2\35\u016a\3\2\2\2\37\u016c\3\2\2\2!\u016e\3\2\2\2"+
"#\u0174\3\2\2\2%\u017a\3\2\2\2\'\u017f\3\2\2\2)\u0185\3\2\2\2+\u018a\3"+
"\2\2\2-\u0190\3\2\2\2/\u0194\3\2\2\2\61\u019a\3\2\2\2\63\u019c\3\2\2\2"+
"\65\u019e\3\2\2\2\67\u01a1\3\2\2\29\u01a4\3\2\2\2;\u01a7\3\2\2\2=\u01aa"+
"\3\2\2\2?\u01ae\3\2\2\2A\u01b1\3\2\2\2C\u01b4\3\2\2\2E\u01b7\3\2\2\2G"+
"\u01ba\3\2\2\2I\u01be\3\2\2\2K\u01c2\3\2\2\2M\u01c5\3\2\2\2O\u01c8\3\2"+
"\2\2Q\u01ca\3\2\2\2S\u01cc\3\2\2\2U\u01cf\3\2\2\2W\u01d1\3\2\2\2Y\u01d3"+
"\3\2\2\2[\u01d5\3\2\2\2]\u01d8\3\2\2\2_\u01db\3\2\2\2a\u01dd\3\2\2\2c"+
"\u01df\3\2\2\2e\u01e2\3\2\2\2g\u01e5\3\2\2\2i\u01e8\3\2\2\2k\u01eb\3\2"+
"\2\2m\u01ed\3\2\2\2o\u01ef\3\2\2\2q\u01f2\3\2\2\2s\u01f7\3\2\2\2u\u01fb"+
"\3\2\2\2w\u01fe\3\2\2\2y\u0202\3\2\2\2{\u0206\3\2\2\2}\u0208\3\2\2\2\177"+
"\u020a\3\2\2\2\u0081\u020d\3\2\2\2\u0083\u020f\3\2\2\2\u0085\u0216\3\2"+
"\2\2\u0087\u021c\3\2\2\2\u0089\u0225\3\2\2\2\u008b\u0227\3\2\2\2\u008d"+
"\u0229\3\2\2\2\u008f\u022b\3\2\2\2\u0091\u022d\3\2\2\2\u0093\u0230\3\2"+
"\2\2\u0095\u0233\3\2\2\2\u0097\u0236\3\2\2\2\u0099\u0239\3\2\2\2\u009b"+
"\u023c\3\2\2\2\u009d\u023f\3\2\2\2\u009f\u0242\3\2\2\2\u00a1\u0245\3\2"+
"\2\2\u00a3\u024a\3\2\2\2\u00a5\u0250\3\2\2\2\u00a7\u0255\3\2\2\2\u00a9"+
"\u0259\3\2\2\2\u00ab\u025c\3\2\2\2\u00ad\u025e\3\2\2\2\u00af\u0260\3\2"+
"\2\2\u00b1\u0267\3\2\2\2\u00b3\u0270\3\2\2\2\u00b5\u0276\3\2\2\2\u00b7"+
"\u0279\3\2\2\2\u00b9\u027e\3\2\2\2\u00bb\u0284\3\2\2\2\u00bd\u028a\3\2"+
"\2\2\u00bf\u0290\3\2\2\2\u00c1\u0295\3\2\2\2\u00c3\u029b\3\2\2\2\u00c5"+
"\u02a1\3\2\2\2\u00c7\u02a7\3\2\2\2\u00c9\u02ae\3\2\2\2\u00cb\u02b4\3\2"+
"\2\2\u00cd\u02bb\3\2\2\2\u00cf\u02c1\3\2\2\2\u00d1\u02c7\3\2\2\2\u00d3"+
"\u02cb\3\2\2\2\u00d5\u02ce\3\2\2\2\u00d7\u02d4\3\2\2\2\u00d9\u02db\3\2"+
"\2\2\u00db\u02e1\3\2\2\2\u00dd\u02ec\3\2\2\2\u00df\u02f5\3\2\2\2\u00e1"+
"\u02fa\3\2\2\2\u00e3\u02fe\3\2\2\2\u00e5\u030c\3\2\2\2\u00e7\u030e\3\2"+
"\2\2\u00e9\u0314\3\2\2\2\u00eb\u031a\3\2\2\2\u00ed\u031c\3\2\2\2\u00ef"+
"\u0325\3\2\2\2\u00f1\u0335\3\2\2\2\u00f3\u0337\3\2\2\2\u00f5\u0342\3\2"+
"\2\2\u00f7\u034f\3\2\2\2\u00f9\u0357\3\2\2\2\u00fb\u035b\3\2\2\2\u00fd"+
"\u00fe\7\u0080\2\2\u00fe\4\3\2\2\2\u00ff\u0100\7<\2\2\u0100\6\3\2\2\2"+
"\u0101\u0102\7i\2\2\u0102\u0103\7q\2\2\u0103\u0104\7v\2\2\u0104\u0105"+
"\7q\2\2\u0105\b\3\2\2\2\u0106\u0107\7\'\2\2\u0107\u0108\7q\2\2\u0108\u0109"+
"\7w\2\2\u0109\u010a\7v\2\2\u010a\u010b\7r\2\2\u010b\u010c\7w\2\2\u010c"+
"\u010d\7v\2\2\u010d\n\3\2\2\2\u010e\u010f\7\'\2\2\u010f\u0110\7n\2\2\u0110"+
"\u0111\7c\2\2\u0111\u0112\7w\2\2\u0112\u0113\7p\2\2\u0113\u0114\7e\2\2"+
"\u0114\u0115\7j\2\2\u0115\u0116\7g\2\2\u0116\u0117\7t\2\2\u0117\f\3\2"+
"\2\2\u0118\u0119\7\'\2\2\u0119\u011a\7|\2\2\u011a\u011b\7g\2\2\u011b\u011c"+
"\7t\2\2\u011c\u011d\7q\2\2\u011d\u011e\7r\2\2\u011e\u011f\7c\2\2\u011f"+
"\u0120\7i\2\2\u0120\u0121\7g\2\2\u0121\16\3\2\2\2\u0122\u0123\7\'\2\2"+
"\u0123\u0124\7|\2\2\u0124\u0125\7r\2\2\u0125\u0126\7t\2\2\u0126\u0127"+
"\7g\2\2\u0127\u0128\7u\2\2\u0128\u0129\7g\2\2\u0129\u012a\7t\2\2\u012a"+
"\u012b\7x\2\2\u012b\u012c\7g\2\2\u012c\u012d\7f\2\2\u012d\20\3\2\2\2\u012e"+
"\u012f\7\'\2\2\u012f\u0130\7c\2\2\u0130\u0131\7f\2\2\u0131\u0132\7f\2"+
"\2\u0132\u0133\7t\2\2\u0133\u0134\7g\2\2\u0134\u0135\7u\2\2\u0135\u0136"+
"\7u\2\2\u0136\22\3\2\2\2\u0137\u0138\7\'\2\2\u0138\u0139\7k\2\2\u0139"+
"\u013a\7o\2\2\u013a\u013b\7r\2\2\u013b\u013c\7q\2\2\u013c\u013d\7t\2\2"+
"\u013d\u013e\7v\2\2\u013e\24\3\2\2\2\u013f\u0140\7\'\2\2\u0140\u0141\7"+
"d\2\2\u0141\u0142\7t\2\2\u0142\u0143\7g\2\2\u0143\u0144\7c\2\2\u0144\u0145"+
"\7m\2\2\u0145\u0146\7r\2\2\u0146\u0147\7q\2\2\u0147\u0148\7k\2\2\u0148"+
"\u0149\7p\2\2\u0149\u014a\7v\2\2\u014a\26\3\2\2\2\u014b\u014c\7\'\2\2"+
"\u014c\u014d\7c\2\2\u014d\u014e\7u\2\2\u014e\u014f\7o\2\2\u014f\u0150"+
"\7k\2\2\u0150\u0151\7p\2\2\u0151\u0152\7e\2\2\u0152\u0153\7n\2\2\u0153"+
"\u0154\7w\2\2\u0154\u0155\7f\2\2\u0155\u0156\7g\2\2\u0156\30\3\2\2\2\u0157"+
"\u0158\7\'\2\2\u0158\u0159\7c\2\2\u0159\u015a\7u\2\2\u015a\u015b\7o\2"+
"\2\u015b\u015c\7d\2\2\u015c\u015d\7k\2\2\u015d\u015e\7p\2\2\u015e\u015f"+
"\7c\2\2\u015f\u0160\7t\2\2\u0160\u0161\7{\2\2\u0161\32\3\2\2\2\u0162\u0163"+
"\7\'\2\2\u0163\u0164\7q\2\2\u0164\u0165\7r\2\2\u0165\u0166\7v\2\2\u0166"+
"\u0167\7k\2\2\u0167\u0168\7q\2\2\u0168\u0169\7p\2\2\u0169\34\3\2\2\2\u016a"+
"\u016b\7.\2\2\u016b\36\3\2\2\2\u016c\u016d\7?\2\2\u016d \3\2\2\2\u016e"+
"\u016f\7e\2\2\u016f\u0170\7q\2\2\u0170\u0171\7p\2\2\u0171\u0172\7u\2\2"+
"\u0172\u0173\7v\2\2\u0173\"\3\2\2\2\u0174\u0175\7w\2\2\u0175\u0176\7d"+
"\2\2\u0176\u0177\7{\2\2\u0177\u0178\7v\2\2\u0178\u0179\7g\2\2\u0179$\3"+
"\2\2\2\u017a\u017b\7d\2\2\u017b\u017c\7{\2\2\u017c\u017d\7v\2\2\u017d"+
"\u017e\7g\2\2\u017e&\3\2\2\2\u017f\u0180\7w\2\2\u0180\u0181\7y\2\2\u0181"+
"\u0182\7q\2\2\u0182\u0183\7t\2\2\u0183\u0184\7f\2\2\u0184(\3\2\2\2\u0185"+
"\u0186\7y\2\2\u0186\u0187\7q\2\2\u0187\u0188\7t\2\2\u0188\u0189\7f\2\2"+
"\u0189*\3\2\2\2\u018a\u018b\7h\2\2\u018b\u018c\7n\2\2\u018c\u018d\7q\2"+
"\2\u018d\u018e\7c\2\2\u018e\u018f\7v\2\2\u018f,\3\2\2\2\u0190\u0191\7"+
"u\2\2\u0191\u0192\7v\2\2\u0192\u0193\7t\2\2\u0193.\3\2\2\2\u0194\u0195"+
"\7u\2\2\u0195\u0196\7v\2\2\u0196\u0197\7t\2\2\u0197\u0198\7a\2\2\u0198"+
"\u0199\7u\2\2\u0199\60\3\2\2\2\u019a\u019b\7]\2\2\u019b\62\3\2\2\2\u019c"+
"\u019d\7_\2\2\u019d\64\3\2\2\2\u019e\u019f\7-\2\2\u019f\u01a0\7?\2\2\u01a0"+
"\66\3\2\2\2\u01a1\u01a2\7/\2\2\u01a2\u01a3\7?\2\2\u01a38\3\2\2\2\u01a4"+
"\u01a5\7\61\2\2\u01a5\u01a6\7?\2\2\u01a6:\3\2\2\2\u01a7\u01a8\7,\2\2\u01a8"+
"\u01a9\7?\2\2\u01a9<\3\2\2\2\u01aa\u01ab\7,\2\2\u01ab\u01ac\7,\2\2\u01ac"+
"\u01ad\7?\2\2\u01ad>\3\2\2\2\u01ae\u01af\7(\2\2\u01af\u01b0\7?\2\2\u01b0"+
"@\3\2\2\2\u01b1\u01b2\7~\2\2\u01b2\u01b3\7?\2\2\u01b3B\3\2\2\2\u01b4\u01b5"+
"\7`\2\2\u01b5\u01b6\7?\2\2\u01b6D\3\2\2\2\u01b7\u01b8\7\'\2\2\u01b8\u01b9"+
"\7?\2\2\u01b9F\3\2\2\2\u01ba\u01bb\7>\2\2\u01bb\u01bc\7>\2\2\u01bc\u01bd"+
"\7?\2\2\u01bdH\3\2\2\2\u01be\u01bf\7@\2\2\u01bf\u01c0\7@\2\2\u01c0\u01c1"+
"\7?\2\2\u01c1J\3\2\2\2\u01c2\u01c3\7-\2\2\u01c3\u01c4\7-\2\2\u01c4L\3"+
"\2\2\2\u01c5\u01c6\7/\2\2\u01c6\u01c7\7/\2\2\u01c7N\3\2\2\2\u01c8\u01c9"+
"\7-\2\2\u01c9P\3\2\2\2\u01ca\u01cb\7/\2\2\u01cbR\3\2\2\2\u01cc\u01cd\7"+
",\2\2\u01cd\u01ce\7,\2\2\u01ceT\3\2\2\2\u01cf\u01d0\7,\2\2\u01d0V\3\2"+
"\2\2\u01d1\u01d2\7\61\2\2\u01d2X\3\2\2\2\u01d3\u01d4\7\'\2\2\u01d4Z\3"+
"\2\2\2\u01d5\u01d6\7>\2\2\u01d6\u01d7\7>\2\2\u01d7\\\3\2\2\2\u01d8\u01d9"+
"\7@\2\2\u01d9\u01da\7@\2\2\u01da^\3\2\2\2\u01db\u01dc\7>\2\2\u01dc`\3"+
"\2\2\2\u01dd\u01de\7@\2\2\u01deb\3\2\2\2\u01df\u01e0\7>\2\2\u01e0\u01e1"+
"\7?\2\2\u01e1d\3\2\2\2\u01e2\u01e3\7@\2\2\u01e3\u01e4\7?\2\2\u01e4f\3"+
"\2\2\2\u01e5\u01e6\7?\2\2\u01e6\u01e7\7?\2\2\u01e7h\3\2\2\2\u01e8\u01e9"+
"\7#\2\2\u01e9\u01ea\7?\2\2\u01eaj\3\2\2\2\u01eb\u01ec\7`\2\2\u01ecl\3"+
"\2\2\2\u01ed\u01ee\7~\2\2\u01een\3\2\2\2\u01ef\u01f0\7v\2\2\u01f0\u01f1"+
"\7q\2\2\u01f1p\3\2\2\2\u01f2\u01f3\7u\2\2\u01f3\u01f4\7v\2\2\u01f4\u01f5"+
"\7g\2\2\u01f5\u01f6\7r\2\2\u01f6r\3\2\2\2\u01f7\u01f8\7c\2\2\u01f8\u01f9"+
"\7p\2\2\u01f9\u01fa\7f\2\2\u01fat\3\2\2\2\u01fb\u01fc\7q\2\2\u01fc\u01fd"+
"\7t\2\2\u01fdv\3\2\2\2\u01fe\u01ff\7z\2\2\u01ff\u0200\7q\2\2\u0200\u0201"+
"\7t\2\2\u0201x\3\2\2\2\u0202\u0203\7p\2\2\u0203\u0204\7q\2\2\u0204\u0205"+
"\7v\2\2\u0205z\3\2\2\2\u0206\u0207\7*\2\2\u0207|\3\2\2\2\u0208\u0209\7"+
"+\2\2\u0209~\3\2\2\2\u020a\u020b\7c\2\2\u020b\u020c\7u\2\2\u020c\u0080"+
"\3\2\2\2\u020d\u020e\7B\2\2\u020e\u0082\3\2\2\2\u020f\u0210\7t\2\2\u0210"+
"\u0211\7g\2\2\u0211\u0212\7v\2\2\u0212\u0213\7w\2\2\u0213\u0214\7t\2\2"+
"\u0214\u0215\7p\2\2\u0215\u0084\3\2\2\2\u0216\u0217\7d\2\2\u0217\u0218"+
"\7t\2\2\u0218\u0219\7g\2\2\u0219\u021a\7c\2\2\u021a\u021b\7m\2\2\u021b"+
"\u0086\3\2\2\2\u021c\u021d\7e\2\2\u021d\u021e\7q\2\2\u021e\u021f\7p\2"+
"\2\u021f\u0220\7v\2\2\u0220\u0221\7k\2\2\u0221\u0222\7p\2\2\u0222\u0223"+
"\7w\2\2\u0223\u0224\7g\2\2\u0224\u0088\3\2\2\2\u0225\u0226\7\60\2\2\u0226"+
"\u008a\3\2\2\2\u0227\u0228\7C\2\2\u0228\u008c\3\2\2\2\u0229\u022a\7Z\2"+
"\2\u022a\u008e\3\2\2\2\u022b\u022c\7[\2\2\u022c\u0090\3\2\2\2\u022d\u022e"+
"\7C\2\2\u022e\u022f\7Z\2\2\u022f\u0092\3\2\2\2\u0230\u0231\7C\2\2\u0231"+
"\u0232\7[\2\2\u0232\u0094\3\2\2\2\u0233\u0234\7Z\2\2\u0234\u0235\7[\2"+
"\2\u0235\u0096\3\2\2\2\u0236\u0237\7R\2\2\u0237\u0238\7e\2\2\u0238\u0098"+
"\3\2\2\2\u0239\u023a\7R\2\2\u023a\u023b\7|\2\2\u023b\u009a\3\2\2\2\u023c"+
"\u023d\7R\2\2\u023d\u023e\7p\2\2\u023e\u009c\3\2\2\2\u023f\u0240\7R\2"+
"\2\u0240\u0241\7x\2\2\u0241\u009e\3\2\2\2\u0242\u0243\7\60\2\2\u0243\u0244"+
"\7y\2\2\u0244\u00a0\3\2\2\2\u0245\u0246\7v\2\2\u0246\u0247\7t\2\2\u0247"+
"\u0248\7w\2\2\u0248\u0249\7g\2\2\u0249\u00a2\3\2\2\2\u024a\u024b\7h\2"+
"\2\u024b\u024c\7c\2\2\u024c\u024d\7n\2\2\u024d\u024e\7u\2\2\u024e\u024f"+
"\7g\2\2\u024f\u00a4\3\2\2\2\u0250\u0251\7\'\2\2\u0251\u0252\7c\2\2\u0252"+
"\u0253\7u\2\2\u0253\u0254\7o\2\2\u0254\u00a6\3\2\2\2\u0255\u0256\7u\2"+
"\2\u0256\u0257\7w\2\2\u0257\u0258\7d\2\2\u0258\u00a8\3\2\2\2\u0259\u025a"+
"\7/\2\2\u025a\u025b\7@\2\2\u025b\u00aa\3\2\2\2\u025c\u025d\7}\2\2\u025d"+
"\u00ac\3\2\2\2\u025e\u025f\7\177\2\2\u025f\u00ae\3\2\2\2\u0260\u0261\7"+
"c\2\2\u0261\u0262\7u\2\2\u0262\u0263\7o\2\2\u0263\u0264\7u\2\2\u0264\u0265"+
"\7w\2\2\u0265\u0266\7d\2\2\u0266\u00b0\3\2\2\2\u0267\u0268\7e\2\2\u0268"+
"\u0269\7n\2\2\u0269\u026a\7q\2\2\u026a\u026b\7d\2\2\u026b\u026c\7d\2\2"+
"\u026c\u026d\7g\2\2\u026d\u026e\7t\2\2\u026e\u026f\7u\2\2\u026f\u00b2"+
"\3\2\2\2\u0270\u0271\7u\2\2\u0271\u0272\7v\2\2\u0272\u0273\7c\2\2\u0273"+
"\u0274\7e\2\2\u0274\u0275\7m\2\2\u0275\u00b4\3\2\2\2\u0276\u0277\7k\2"+
"\2\u0277\u0278\7h\2\2\u0278\u00b6\3\2\2\2\u0279\u027a\7g\2\2\u027a\u027b"+
"\7n\2\2\u027b\u027c\7u\2\2\u027c\u027d\7g\2\2\u027d\u00b8\3\2\2\2\u027e"+
"\u027f\7k\2\2\u027f\u0280\7h\2\2\u0280\u0281\7a\2\2\u0281\u0282\7e\2\2"+
"\u0282\u0283\7u\2\2\u0283\u00ba\3\2\2\2\u0284\u0285\7k\2\2\u0285\u0286"+
"\7h\2\2\u0286\u0287\7a\2\2\u0287\u0288\7e\2\2\u0288\u0289\7e\2\2\u0289"+
"\u00bc\3\2\2\2\u028a\u028b\7k\2\2\u028b\u028c\7h\2\2\u028c\u028d\7a\2"+
"\2\u028d\u028e\7g\2\2\u028e\u028f\7s\2\2\u028f\u00be\3\2\2\2\u0290\u0291"+
"\7k\2\2\u0291\u0292\7h\2\2\u0292\u0293\7a\2\2\u0293\u0294\7|\2\2\u0294"+
"\u00c0\3\2\2\2\u0295\u0296\7k\2\2\u0296\u0297\7h\2\2\u0297\u0298\7a\2"+
"\2\u0298\u0299\7p\2\2\u0299\u029a\7g\2\2\u029a\u00c2\3\2\2\2\u029b\u029c"+
"\7k\2\2\u029c\u029d\7h\2\2\u029d\u029e\7a\2\2\u029e\u029f\7p\2\2\u029f"+
"\u02a0\7|\2\2\u02a0\u00c4\3\2\2\2\u02a1\u02a2\7k\2\2\u02a2\u02a3\7h\2"+
"\2\u02a3\u02a4\7a\2\2\u02a4\u02a5\7r\2\2\u02a5\u02a6\7n\2\2\u02a6\u00c6"+
"\3\2\2\2\u02a7\u02a8\7k\2\2\u02a8\u02a9\7h\2\2\u02a9\u02aa\7a\2\2\u02aa"+
"\u02ab\7r\2\2\u02ab\u02ac\7q\2\2\u02ac\u02ad\7u\2\2\u02ad\u00c8\3\2\2"+
"\2\u02ae\u02af\7k\2\2\u02af\u02b0\7h\2\2\u02b0\u02b1\7a\2\2\u02b1\u02b2"+
"\7o\2\2\u02b2\u02b3\7k\2\2\u02b3\u00ca\3\2\2\2\u02b4\u02b5\7k\2\2\u02b5"+
"\u02b6\7h\2\2\u02b6\u02b7\7a\2\2\u02b7\u02b8\7p\2\2\u02b8\u02b9\7g\2\2"+
"\u02b9\u02ba\7i\2\2\u02ba\u00cc\3\2\2\2\u02bb\u02bc\7k\2\2\u02bc\u02bd"+
"\7h\2\2\u02bd\u02be\7a\2\2\u02be\u02bf\7x\2\2\u02bf\u02c0\7u\2\2\u02c0"+
"\u00ce\3\2\2\2\u02c1\u02c2\7k\2\2\u02c2\u02c3\7h\2\2\u02c3\u02c4\7a\2"+
"\2\u02c4\u02c5\7x\2\2\u02c5\u02c6\7e\2\2\u02c6\u00d0\3\2\2\2\u02c7\u02c8"+
"\7h\2\2\u02c8\u02c9\7q\2\2\u02c9\u02ca\7t\2\2\u02ca\u00d2\3\2\2\2\u02cb"+
"\u02cc\7k\2\2\u02cc\u02cd\7p\2\2\u02cd\u00d4\3\2\2\2\u02ce\u02cf\7y\2"+
"\2\u02cf\u02d0\7j\2\2\u02d0\u02d1\7k\2\2\u02d1\u02d2\7n\2\2\u02d2\u02d3"+
"\7g\2\2\u02d3\u00d6\3\2\2\2\u02d4\u02d5\7t\2\2\u02d5\u02d6\7g\2\2\u02d6"+
"\u02d7\7r\2\2\u02d7\u02d8\7g\2\2\u02d8\u02d9\7c\2\2\u02d9\u02da\7v\2\2"+
"\u02da\u00d8\3\2\2\2\u02db\u02dc\7w\2\2\u02dc\u02dd\7p\2\2\u02dd\u02de"+
"\7v\2\2\u02de\u02df\7k\2\2\u02df\u02e0\7n\2\2\u02e0\u00da\3\2\2\2\u02e1"+
"\u02e5\t\2\2\2\u02e2\u02e4\t\3\2\2\u02e3\u02e2\3\2\2\2\u02e4\u02e7\3\2"+
"\2\2\u02e5\u02e3\3\2\2\2\u02e5\u02e6\3\2\2\2\u02e6\u02e8\3\2\2\2\u02e7"+
"\u02e5\3\2\2\2\u02e8\u02e9\5\u00ddo\2\u02e9\u02ea\3\2\2\2\u02ea\u02eb"+
"\bn\2\2\u02eb\u00dc\3\2\2\2\u02ec\u02f0\7=\2\2\u02ed\u02ef\n\2\2\2\u02ee"+
"\u02ed\3\2\2\2\u02ef\u02f2\3\2\2\2\u02f0\u02ee\3\2\2\2\u02f0\u02f1\3\2"+
"\2\2\u02f1\u02f3\3\2\2\2\u02f2\u02f0\3\2\2\2\u02f3\u02f4\bo\2\2\u02f4"+
"\u00de\3\2\2\2\u02f5\u02f6\t\3\2\2\u02f6\u02f7\3\2\2\2\u02f7\u02f8\bp"+
"\3\2\u02f8\u00e0\3\2\2\2\u02f9\u02fb\t\2\2\2\u02fa\u02f9\3\2\2\2\u02fb"+
"\u02fc\3\2\2\2\u02fc\u02fa\3\2\2\2\u02fc\u02fd\3\2\2\2\u02fd\u00e2\3\2"+
"\2\2\u02fe\u0302\t\4\2\2\u02ff\u0301\t\5\2\2\u0300\u02ff\3\2\2\2\u0301"+
"\u0304\3\2\2\2\u0302\u0300\3\2\2\2\u0302\u0303\3\2\2\2\u0303\u00e4\3\2"+
"\2\2\u0304\u0302\3\2\2\2\u0305\u030d\4\62;\2\u0306\u0308\4\63;\2\u0307"+
"\u0309\4\62;\2\u0308\u0307\3\2\2\2\u0309\u030a\3\2\2\2\u030a\u0308\3\2"+
"\2\2\u030a\u030b\3\2\2\2\u030b\u030d\3\2\2\2\u030c\u0305\3\2\2\2\u030c"+
"\u0306\3\2\2\2\u030d\u00e6\3\2\2\2\u030e\u0310\7&\2\2\u030f\u0311\t\6"+
"\2\2\u0310\u030f\3\2\2\2\u0311\u0312\3\2\2\2\u0312\u0310\3\2\2\2\u0312"+
"\u0313\3\2\2\2\u0313\u00e8\3\2\2\2\u0314\u0316\7\'\2\2\u0315\u0317\4\62"+
"\63\2\u0316\u0315\3\2\2\2\u0317\u0318\3\2\2\2\u0318\u0316\3\2\2\2\u0318"+
"\u0319\3\2\2\2\u0319\u00ea\3\2\2\2\u031a\u031b\7(\2\2\u031b\u00ec\3\2"+
"\2\2\u031c\u0322\5\u00efx\2\u031d\u031f\t\7\2\2\u031e\u0320\t\b\2\2\u031f"+
"\u031e\3\2\2\2\u031f\u0320\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u0323\5\u00ef"+
"x\2\u0322\u031d\3\2\2\2\u0322\u0323\3\2\2\2\u0323\u00ee\3\2\2\2\u0324"+
"\u0326\4\62;\2\u0325\u0324\3\2\2\2\u0326\u0327\3\2\2\2\u0327\u0325\3\2"+
"\2\2\u0327\u0328\3\2\2\2\u0328\u032f\3\2\2\2\u0329\u032b\7\60\2\2\u032a"+
"\u032c\4\62;\2\u032b\u032a\3\2\2\2\u032c\u032d\3\2\2\2\u032d\u032b\3\2"+
"\2\2\u032d\u032e\3\2\2\2\u032e\u0330\3\2\2\2\u032f\u0329\3\2\2\2\u032f"+
"\u0330\3\2\2\2\u0330\u00f0\3\2\2\2\u0331\u0332\7^\2\2\u0332\u0336\13\2"+
"\2\2\u0333\u0334\7^\2\2\u0334\u0336\5\u00e1q\2\u0335\u0331\3\2\2\2\u0335"+
"\u0333\3\2\2\2\u0336\u00f2\3\2\2\2\u0337\u033c\7$\2\2\u0338\u033b\5\u00f1"+
"y\2\u0339\u033b\n\t\2\2\u033a\u0338\3\2\2\2\u033a\u0339\3\2\2\2\u033b"+
"\u033e\3\2\2\2\u033c\u033a\3\2\2\2\u033c\u033d\3\2\2\2\u033d\u033f\3\2"+
"\2\2\u033e\u033c\3\2\2\2\u033f\u0340\7$\2\2\u0340\u0341\bz\4\2\u0341\u00f4"+
"\3\2\2\2\u0342\u0343\7}\2\2\u0343\u0344\7}\2\2\u0344\u0346\3\2\2\2\u0345"+
"\u0347\13\2\2\2\u0346\u0345\3\2\2\2\u0347\u0348\3\2\2\2\u0348\u0349\3"+
"\2\2\2\u0348\u0346\3\2\2\2\u0349\u034a\3\2\2\2\u034a\u034b\7\177\2\2\u034b"+
"\u034c\7\177\2\2\u034c\u034d\3\2\2\2\u034d\u034e\b{\5\2\u034e\u00f6\3"+
"\2\2\2\u034f\u0352\7)\2\2\u0350\u0353\5\u00f1y\2\u0351\u0353\n\t\2\2\u0352"+
"\u0350\3\2\2\2\u0352\u0351\3\2\2\2\u0353\u0354\3\2\2\2\u0354\u0355\7)"+
"\2\2\u0355\u0356\b|\6\2\u0356\u00f8\3\2\2\2\u0357\u0358\7B\2\2\u0358\u0359"+
"\7|\2\2\u0359\u035a\7r\2\2\u035a\u00fa\3\2\2\2\u035b\u035c\7]\2\2\u035c"+
"\u035d\7_\2\2\u035d\u00fc\3\2\2\2\26\2\u02e5\u02f0\u02fc\u0302\u030a\u030c"+
"\u0310\u0312\u0318\u031f\u0322\u0327\u032d\u032f\u0335\u033a\u033c\u0348"+
"\u0352\7\2\3\2\b\2\2\3z\2\3{\3\3|\4";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
File diff suppressed because it is too large. Load diff
-16
View File
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="prog8" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/docs/build" />
<excludeFolder url="file://$MODULE_DIR$/gradle" />
<excludeFolder url="file://$MODULE_DIR$/out" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>