div and mult by a power of 2 are now optimized into shifts. Added bit shift operators << and >>

This commit is contained in:
Irmen de Jong 2019-01-06 08:17:18 +01:00
parent e9704bdca1
commit 04bbdf5991
16 changed files with 1360 additions and 1023 deletions

View File

@ -112,7 +112,7 @@ assignment : assign_targets '=' expression ;
assign_targets : assign_target (',' assign_target)* ;
augassignment :
assign_target operator=('+=' | '-=' | '/=' | '//=' | '*=' | '**=' | '&=' | '|=' | '^=' | '%=' ) expression
assign_target operator=('+=' | '-=' | '/=' | '//=' | '*=' | '**=' | '&=' | '|=' | '^=' | '%=' | '<<=' | '>>=' ) expression
;
assign_target:
@ -130,6 +130,7 @@ expression :
| left = expression bop = '**' right = expression
| left = expression bop = ('*' | '/' | '//' | '%' ) right = expression
| left = expression bop = ('+' | '-' ) right = expression
| left = expression bop = ('<<' | '>>' ) right = expression
| left = expression bop = ('<' | '>' | '<=' | '>=') right = expression
| left = expression bop = ('==' | '!=') right = expression
| left = expression bop = '&' right = expression

View File

@ -43,22 +43,8 @@
word wcosc = cos8(az) as word
word wsinc = sin8(az) as word
word wcosa_sinb = wcosa*wsinb
lsr(wcosa_sinb)
lsr(wcosa_sinb)
lsr(wcosa_sinb)
lsr(wcosa_sinb)
lsr(wcosa_sinb)
lsr(wcosa_sinb)
lsr(wcosa_sinb) ; / 128
word wsina_sinb = wsina*wsinb
lsr(wsina_sinb)
lsr(wsina_sinb)
lsr(wsina_sinb)
lsr(wsina_sinb)
lsr(wsina_sinb)
lsr(wsina_sinb)
lsr(wsina_sinb) ; / 128
word wcosa_sinb = wcosa*wsinb // 128
word wsina_sinb = wsina*wsinb // 128
word Axx = (wcosa*wcosb as float / 128.0) as word
word Axy = ((wcosa_sinb*wsinc - wsina*wcosc) as float / 128.0) as word
@ -74,32 +60,11 @@
word xc = xcoor[i] as word
word yc = ycoor[i] as word
word zc = zcoor[i] as word
word zz = Axx*xc + Axy*yc + Axz*zc
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz) ; /128
word zz = (Axx*xc + Axy*yc + Axz*zc) // 128 ; @todo bugs when not using 'zz' temporary var!?
rotatedx[i] = zz
zz=Ayx*xc + Ayy*yc + Ayz*zc
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz) ; /128
zz=(Ayx*xc + Ayy*yc + Ayz*zc) // 128
rotatedy[i] = zz
zz = Azx*xc + Azy*yc + Azz*zc
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz)
lsr(zz) ; /128
zz = (Azx*xc + Azy*yc + Azz*zc) // 128
rotatedz[i] = zz
}
}

View File

@ -3,6 +3,74 @@
~ main {
byte[3] stuff=[1,2,3]
ubyte ub
word w
uword uw
sub start() {
A //= 1 ; @todo wrong error about float
A = A//1 ; @todo wrong error about float
Y = A//1 ; @todo wrong error about float
A=A*2
A=255
A=A*4
A=255
A=A*8
A=255
A=A*16
A=255
A=A*32
A=255
A=A*64
A=255
A=A*128
A=255
A=A*3
A=255
; A *= 0
; A *= 1
; A *= 2
; A *= 3
; A *= 4
; A *= 5
; A *= 6
; A *= 7
; A *= 8
; A *= 9
; A *= 10
; A *= 11
; A *= 16
; A *= 32
; A *= 64
; A *= 128
; A *= 255
;A *= 256
;A *= 257
; Y = A
; Y = A*0
; Y = A*1
; Y = A*2
; Y = A*3
; Y = A*4
; Y = A*5
; Y = A*6
; Y = A*7
; Y = A*8
; Y = A*9
; Y = A*10
; Y = A*11
; Y = A*16
; Y = A*32
; Y = A*64
; Y = A*128
; Y = A*255
;Y = A*256
;Y = A*257
}
}

View File

@ -44,7 +44,7 @@
c64.SPRPTR7 = sprite_address_ptr
c64.SPENA = 255 ; enable all sprites
c64utils.set_rasterirq(240) ; enable animation
c64utils.set_rasterirq(260) ; enable animation
}
}
@ -64,8 +64,8 @@ sub irq() {
ubyte i=14
nextsprite: ; @todo should be a for loop from 14 to 0 step -2 but this causes a value out of range error at the moment
word x = (sin8(angle*2-i*8) as word)+190 ; @todo will/should be using shifts for faster multiplication and division
byte y = cos8(angle*3-i*8) // 2 ; @todo will/should be using shifts for faster multiplication and division
word x = (sin8(angle*2-i*8) as word)+190
byte y = cos8(angle*3-i*8) // 2
@(SP0X+i) = lsb(x)
@(SP0Y+i) = y+150 as ubyte

View File

@ -254,7 +254,7 @@ interface IAstProcessor {
}
fun process(arrayIndexedExpression: ArrayIndexedExpression): IExpression {
arrayIndexedExpression.identifier?.process(this)
arrayIndexedExpression.identifier.process(this)
arrayIndexedExpression.arrayspec.process(this)
return arrayIndexedExpression
}
@ -792,7 +792,7 @@ data class AssignTarget(val register: Register?,
if(identifier!=null)
return identifier.nameInSource.last()
if(arrayindexed!=null)
return arrayindexed.identifier!!.nameInSource.last()
return arrayindexed.identifier.nameInSource.last()
val address = memoryAddress?.addressExpression
if(address is LiteralValue)
return address.asIntegerValue.toString()
@ -869,6 +869,7 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
"<", ">",
"<=", ">=",
"==", "!=" -> DataType.UBYTE
"<<", ">>" -> leftDt
"/" -> DataType.FLOAT // use integer division '//' if you don't want floats
else -> throw FatalAstException("resulting datatype check for invalid operator $operator")
}
@ -938,23 +939,23 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
}
}
class ArrayIndexedExpression(val identifier: IdentifierReference?,
class ArrayIndexedExpression(val identifier: IdentifierReference,
var arrayspec: ArraySpec,
override val position: Position) : IExpression {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
this.parent = parent
identifier?.linkParents(this)
identifier.linkParents(this)
arrayspec.linkParents(this)
}
override fun isIterable(namespace: INameScope, heap: HeapValues) = false
override fun constValue(namespace: INameScope, heap: HeapValues): LiteralValue? = null
override fun process(processor: IAstProcessor): IExpression = processor.process(this)
override fun referencesIdentifier(name: String) = identifier?.referencesIdentifier(name) ?: false
override fun referencesIdentifier(name: String) = identifier.referencesIdentifier(name)
override fun resultingDatatype(namespace: INameScope, heap: HeapValues): DataType? {
val target = identifier?.targetStatement(namespace)
val target = identifier.targetStatement(namespace)
if (target is VarDecl) {
return when (target.datatype) {
in NumericDatatypes -> null
@ -1089,7 +1090,10 @@ class LiteralValue(val type: DataType,
}
fun optimalInteger(value: Number, position: Position): LiteralValue {
return when (value) {
val intval = value.toInt()
if(intval.toDouble() != value.toDouble())
throw FatalAstException("value is not an integer: $value")
return when (intval) {
in 0..255 -> LiteralValue(DataType.UBYTE, bytevalue=value.toShort(), position = position)
in -128..127 -> LiteralValue(DataType.BYTE, bytevalue=value.toShort(), position = position)
in 0..65535 -> LiteralValue(DataType.UWORD, wordvalue = value.toInt(), position = position)
@ -1589,6 +1593,17 @@ class AnonymousScope(override var statements: MutableList<IStatement>,
}
class NopStatement(override val position:Position): IStatement {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
this.parent = parent
}
override fun process(processor: IAstProcessor) = this
}
// the subroutine class covers both the normal user-defined subroutines,
// and also the predefined/ROM/register-based subroutines.
// (multiple return types can only occur for the latter type)

View File

@ -424,7 +424,7 @@ class AstChecker(private val namespace: INameScope,
}
if(assignment.aug_op!=null) {
// check augmented assignment:
// check augmented assignment (and convert it into a normal assignment!)
// A /= 3 -> check as if it was A = A / 3
val newTarget: IExpression =
when {
@ -847,7 +847,7 @@ class AstChecker(private val namespace: INameScope,
}
override fun process(arrayIndexedExpression: ArrayIndexedExpression): IExpression {
val target = arrayIndexedExpression.identifier!!.targetStatement(namespace)
val target = arrayIndexedExpression.identifier.targetStatement(namespace)
if(target is VarDecl) {
if(target.datatype !in IterableDatatypes)
checkResult.add(SyntaxError("indexing requires an iterable variable", arrayIndexedExpression.position))

View File

@ -218,6 +218,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
is VarDecl, is Subroutine -> {} // skip this, already processed these.
is NopStatement -> {}
is InlineAssembly -> translate(stmt)
else -> TODO("translate statement $stmt to stackvm")
}
@ -600,7 +601,10 @@ private class StatementTranslator(private val prog: IntermediateProgram,
translate(expr.right)
if(rightDt!=commonDt)
convertType(rightDt, commonDt)
translateBinaryOperator(expr.operator, commonDt)
if(expr.operator=="<<" || expr.operator==">>")
translateBitshiftedOperator(expr.operator, leftDt, expr.right.constValue(namespace, heap))
else
translateBinaryOperator(expr.operator, commonDt)
}
is FunctionCall -> {
val target = expr.target.targetStatement(namespace)
@ -1218,6 +1222,36 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.instr(opcode)
}
private fun translateBitshiftedOperator(operator: String, leftDt: DataType, amount: LiteralValue?) {
if(amount?.asIntegerValue == null)
throw FatalAstException("bitshift operators should only have constant integer value as right operand")
var shifts=amount.asIntegerValue
if(shifts<0)
throw FatalAstException("bitshift value should be >= 0")
prog.removeLastInstruction() // the amount of shifts is not used as a stack value
if(shifts==0)
return
while(shifts>0) {
if(operator==">>") {
when (leftDt) {
DataType.UBYTE -> prog.instr(Opcode.SHIFTEDR_UBYTE)
DataType.BYTE -> prog.instr(Opcode.SHIFTEDR_SBYTE)
DataType.UWORD -> prog.instr(Opcode.SHIFTEDR_UWORD)
DataType.WORD -> prog.instr(Opcode.SHIFTEDR_SWORD)
else -> throw CompilerException("wrong datatype")
}
} else if(operator=="<<") {
when (leftDt) {
DataType.UBYTE, DataType.BYTE -> prog.instr(Opcode.SHIFTEDL_BYTE)
DataType.UWORD, DataType.WORD -> prog.instr(Opcode.SHIFTEDL_WORD)
else -> throw CompilerException("wrong datatype")
}
}
shifts--
}
}
private fun translatePrefixOperator(operator: String, operandDt: DataType?) {
if(operandDt==null)
throw CompilerException("operand datatype not known")
@ -1251,7 +1285,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
private fun translate(arrayindexed: ArrayIndexedExpression, write: Boolean) {
val variable = arrayindexed.identifier?.targetStatement(namespace) as VarDecl
val variable = arrayindexed.identifier.targetStatement(namespace) as VarDecl
translate(arrayindexed.arrayspec.x)
if (write)
prog.instr(opcodeWriteindexedvar(variable.datatype), callLabel = variable.scopedname)
@ -1309,7 +1343,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
stmt.target.arrayindexed != null -> {
val variable = stmt.target.arrayindexed!!.identifier?.targetStatement(namespace) as VarDecl
val variable = stmt.target.arrayindexed!!.identifier.targetStatement(namespace) as VarDecl
translate(stmt.target.arrayindexed!!.arrayspec.x)
when(stmt.operator) {
"++" -> prog.instr(opcodeIncArrayindexedVar(variable.datatype), callLabel = variable.scopedname)

View File

@ -75,6 +75,12 @@ enum class Opcode {
ABS_F,
// bit shifts and bitwise arithmetic
SHIFTEDL_BYTE, // shifts stack value
SHIFTEDL_WORD, // shifts stack value
SHIFTEDR_UBYTE, // shifts stack value
SHIFTEDR_SBYTE, // shifts stack value
SHIFTEDR_UWORD, // shifts stack value
SHIFTEDR_SWORD, // shifts stack value
SHL_BYTE,
SHL_WORD,
SHL_MEM_BYTE,

View File

@ -860,6 +860,13 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.LESSEQ_W -> " jsr prog8_lib.lesseq_w"
Opcode.LESSEQ_F -> " jsr c64flt.lesseq_f"
Opcode.SHIFTEDL_BYTE -> " asl ${(ESTACK_LO+1).toHex()},x"
Opcode.SHIFTEDL_WORD -> " asl ${(ESTACK_LO+1).toHex()},x | rol ${(ESTACK_HI+1).toHex()},x"
Opcode.SHIFTEDR_SBYTE -> " lda ${(ESTACK_LO+1).toHex()},x | asl a | ror ${(ESTACK_LO+1).toHex()},x"
Opcode.SHIFTEDR_UBYTE -> " lsr ${(ESTACK_LO+1).toHex()},x"
Opcode.SHIFTEDR_SWORD -> " lda ${(ESTACK_HI+1).toHex()},x | asl a | ror ${(ESTACK_HI+1).toHex()},x | ror ${(ESTACK_LO+1).toHex()},x"
Opcode.SHIFTEDR_UWORD -> " lsr ${(ESTACK_HI+1).toHex()},x | ror ${(ESTACK_LO+1).toHex()},x"
else -> null
}
}

View File

@ -31,10 +31,30 @@ class ConstExprEvaluator {
">=" -> LiteralValue.fromBoolean(left >= right, left.position)
"==" -> LiteralValue.fromBoolean(left == right, left.position)
"!=" -> LiteralValue.fromBoolean(left != right, left.position)
"<<" -> shiftedleft(left, right)
">>" -> shiftedright(left, right)
else -> throw FatalAstException("const evaluation for invalid operator $operator")
}
}
private fun shiftedright(left: LiteralValue, amount: LiteralValue): IExpression {
if(left.asIntegerValue==null || amount.asIntegerValue==null)
throw ExpressionError("cannot compute $left >> $amount", left.position)
val result =
if(left.type==DataType.UBYTE || left.type==DataType.UWORD)
left.asIntegerValue.ushr(amount.asIntegerValue)
else
left.asIntegerValue.shr(amount.asIntegerValue)
return LiteralValue.fromNumber(result, left.type, left.position)
}
private fun shiftedleft(left: LiteralValue, amount: LiteralValue): IExpression {
if(left.asIntegerValue==null || amount.asIntegerValue==null)
throw ExpressionError("cannot compute $left << $amount", left.position)
val result = left.asIntegerValue.shl(amount.asIntegerValue)
return LiteralValue.fromNumber(result, left.type, left.position)
}
private fun logicalxor(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left locical-bitxor $right"
return when {

View File

@ -3,6 +3,7 @@ package prog8.optimizing
import prog8.ast.*
import prog8.compiler.HeapValues
import kotlin.math.abs
import kotlin.math.log2
/*
todo simplify expression terms:
@ -15,6 +16,22 @@ import kotlin.math.abs
X % 2 -> X and 1 (if X is byte/word)
todo often used multiplications to factors that are more efficiently calculated (via shifts)
X*3 -> X*2+X
X*5 -> X*4+X
X*6 -> X*2+X*2+X*2
X*7 -> X*4+X*2+X
X*9 -> X*8 + X
X*10 -> X*8 + X*2
X*11 -> X*8 + X*2 +X
X*12 -> X*8 + X*4
X*13 -> X*8 + X*4 +X
X*14 -> X*8 + X*4 + X*2
X*15 -> X*8 + X*4 + X*2 + X
(and negatives)
todo expression optimization: common (sub) expression elimination (turn common expressions into single subroutine call + introduce variable to hold it)
*/
@ -23,9 +40,8 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
var optimizationsDone: Int = 0
override fun process(assignment: Assignment): IStatement {
if(assignment.aug_op!=null) {
if(assignment.aug_op!=null)
throw AstException("augmented assignments should have been converted to normal assignments before this optimizer")
}
return super.process(assignment)
}
@ -46,7 +62,7 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
}
}
// simplify logical expressions when a term is constant and determines the outcome
// simplify when a term is constant and determines the outcome
when(expr.operator) {
"or" -> {
if((leftVal!=null && leftVal.asBooleanValue) || (rightVal!=null && rightVal.asBooleanValue)) {
@ -352,10 +368,13 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
if(leftVal==null && rightVal==null)
return expr
// cannot shuffle assiciativity with division!
if(rightVal!=null) {
// right value is a constant, see if we can optimize
val rightConst: LiteralValue = rightVal
when(rightConst.asNumericValue?.toDouble()) {
val cv = rightConst.asNumericValue?.toDouble()
when(cv) {
-1.0 -> {
// '/' -> -left, '//' -> -ceil(left)
optimizationsDone++
@ -374,6 +393,22 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
"//" -> return FunctionCall(IdentifierReference(listOf("floor"), expr.position), mutableListOf(expr.left), expr.position)
}
}
2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 2048.0, 4096.0, 8192.0, 16384.0, 32768.0, 65536.0 -> {
if(expr.left.resultingDatatype(namespace, heap) in IntegerDatatypes) {
// divided by a power of two => shift right
optimizationsDone++
val numshifts = log2(cv)
return BinaryExpression(expr.left, ">>", LiteralValue.optimalInteger(numshifts, expr.position), expr.position)
}
}
-2.0, -4.0, -8.0, -16.0, -32.0, -64.0, -128.0, -256.0, -512.0, -1024.0, -2048.0, -4096.0, -8192.0, -16384.0, -32768.0, -65536.0 -> {
if(expr.left.resultingDatatype(namespace, heap) in IntegerDatatypes) {
// divided by a negative power of two => negate, then shift right
optimizationsDone++
val numshifts = log2(-cv)
return BinaryExpression(PrefixExpression("-", expr.left, expr.position), ">>", LiteralValue.optimalInteger(numshifts, expr.position), expr.position)
}
}
}
if (expr.left.resultingDatatype(namespace, heap) == DataType.UBYTE) {
@ -413,7 +448,8 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
// right value is a constant, see if we can optimize
val leftValue: IExpression = expr.left
val rightConst: LiteralValue = rightVal
when(rightConst.asNumericValue?.toDouble()) {
val cv = rightConst.asNumericValue?.toDouble()
when(cv) {
-1.0 -> {
// -left
optimizationsDone++
@ -429,6 +465,22 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
optimizationsDone++
return expr.left
}
2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 2048.0, 4096.0, 8192.0, 16384.0, 32768.0, 65536.0 -> {
if(leftValue.resultingDatatype(namespace, heap) in IntegerDatatypes) {
// times a power of two => shift left
optimizationsDone++
val numshifts = log2(cv)
return BinaryExpression(expr.left, "<<", LiteralValue.optimalInteger(numshifts, expr.position), expr.position)
}
}
-2.0, -4.0, -8.0, -16.0, -32.0, -64.0, -128.0, -256.0, -512.0, -1024.0, -2048.0, -4096.0, -8192.0, -16384.0, -32768.0, -65536.0 -> {
if(leftValue.resultingDatatype(namespace, heap) in IntegerDatatypes) {
// times a negative power of two => negate, then shift left
optimizationsDone++
val numshifts = log2(-cv)
return BinaryExpression(PrefixExpression("-", expr.left, expr.position), "<<", LiteralValue.optimalInteger(numshifts, expr.position), expr.position)
}
}
}
}
// no need to check for left val constant (because of associativity)

View File

@ -6,18 +6,18 @@ import prog8.functions.BuiltinFunctions
/*
todo remove empty blocks? already done?
todo remove empty subs? already done?
todo remove unused blocks
todo remove unused variables
todo remove unused subroutines
todo remove unused strings and arrays from the heap
todo remove if statements with empty statement blocks
todo remove if/while/repeat/for statements with empty statement blocks
todo replace if statements with only else block
todo regular subroutines that have 1 or 2 (u)byte or 1 (u)word parameters -> change to asmsub to accept these in A/Y registers instead of on stack
todo statement optimization: create augmented assignment from assignment that only refers to its lvalue (A=A+10, A=4*A, ...)
todo statement optimization: X+=1, X-=1 --> X++/X-- (to 3? 4? incs/decs in a row after that use arithmetic)
todo remove statements that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc
todo optimize addition with self into shift 1 (A+=A -> A<<=1)
todo assignment optimization: optimize some simple multiplications and divisions into shifts (A*=2 -> lsl(A), X=X/2 -> lsr(X) )
todo statement optimization: X+=1, X-=1 --> X++/X-- (to 3? 4? incs/decs in a row, after that use arithmetic)
todo optimize integer addition with self into shift 1 (A+=A -> A<<=1)
todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to)
todo merge sequence of assignments into one to avoid repeated value loads (as long as the value is a constant and the target not a MEMORY type!)
todo report more always true/always false conditions
@ -121,7 +121,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
// always false -> ditch whole statement
printWarning("condition is always false", whileLoop.position)
optimizationsDone++
AnonymousScope(mutableListOf(), whileLoop.position)
NopStatement(whileLoop.position)
}
}
return whileLoop
@ -163,4 +163,125 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
}
return jump
}
override fun process(assignment: Assignment): IStatement {
if(assignment.aug_op!=null)
throw AstException("augmented assignments should have been converted to normal assignments before this optimizer")
// 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
if(assignment.targets.size==1) {
val target=assignment.targets[0]
if(same(target, assignment.value)) {
optimizationsDone++
return NopStatement(assignment.position)
}
val targetDt = target.determineDatatype(namespace, heap, assignment)
val bexpr=assignment.value as? BinaryExpression
if(bexpr!=null && same(target, bexpr.left)) {
val cv = bexpr.right.constValue(namespace, heap)?.asNumericValue?.toDouble()
if(cv!=null) {
when (bexpr.operator) {
"+" -> if (cv==0.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"-" -> if (cv==0.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"*" -> if (cv==1.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"%" -> if (cv==1.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"/" -> if (cv==1.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"//" -> if (cv==1.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"**" -> if (cv==1.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"|" -> if (cv==0.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"^" -> if (cv==0.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
"<<" -> {
if(cv==0.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
if(((targetDt==DataType.UWORD || targetDt==DataType.WORD) && cv >15.0) ||
((targetDt==DataType.UBYTE || targetDt==DataType.BYTE) && cv > 7.0)) {
assignment.value = LiteralValue.optimalInteger(0, assignment.value.position)
assignment.value.linkParents(assignment)
optimizationsDone++
}
else {
// replace by in-place lsl(...) call
val scope = AnonymousScope(mutableListOf(), assignment.position)
var numshifts = cv.toInt()
while(numshifts>0) {
scope.statements.add(FunctionCallStatement(IdentifierReference(listOf("lsl"), assignment.position), mutableListOf(bexpr.left), assignment.position))
numshifts--
}
optimizationsDone++
return scope
}
}
">>" -> {
if(cv==0.0) {
optimizationsDone++
return NopStatement(assignment.position)
}
if(((targetDt==DataType.UWORD || targetDt==DataType.WORD) && cv >15.0) ||
((targetDt==DataType.UBYTE || targetDt==DataType.BYTE) && cv > 7.0)) {
assignment.value = LiteralValue.optimalInteger(0, assignment.value.position)
assignment.value.linkParents(assignment)
optimizationsDone++
}
else {
// replace by in-place lsr(...) call
val scope = AnonymousScope(mutableListOf(), assignment.position)
var numshifts = cv.toInt()
while(numshifts>0) {
scope.statements.add(FunctionCallStatement(IdentifierReference(listOf("lsr"), assignment.position), mutableListOf(bexpr.left), assignment.position))
numshifts--
}
optimizationsDone++
return scope
}
}
}
}
}
}
return super.process(assignment)
}
private fun same(target: AssignTarget, value: IExpression): Boolean {
return when {
target.memoryAddress!=null -> false
target.register!=null -> value is RegisterExpr && value.register==target.register
target.identifier!=null -> value is IdentifierReference && value.nameInSource==target.identifier.nameInSource
target.arrayindexed!=null -> value is ArrayIndexedExpression &&
value.identifier.nameInSource==target.arrayindexed.identifier.nameInSource &&
value.arrayspec.size()!=null &&
target.arrayindexed.arrayspec.size()!=null &&
value.arrayspec.size()==target.arrayindexed.arrayspec.size()
else -> false
}
}
}

View File

@ -32,9 +32,10 @@ public class prog8Lexer extends Lexer {
T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94,
T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101,
T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107,
T__107=108, T__108=109, T__109=110, LINECOMMENT=111, COMMENT=112, WS=113,
EOL=114, NAME=115, DEC_INTEGER=116, HEX_INTEGER=117, BIN_INTEGER=118,
FLOAT_NUMBER=119, STRING=120, INLINEASMBLOCK=121, SINGLECHAR=122;
T__107=108, T__108=109, T__109=110, T__110=111, T__111=112, T__112=113,
T__113=114, LINECOMMENT=115, COMMENT=116, WS=117, EOL=118, NAME=119, DEC_INTEGER=120,
HEX_INTEGER=121, BIN_INTEGER=122, FLOAT_NUMBER=123, STRING=124, INLINEASMBLOCK=125,
SINGLECHAR=126;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
@ -58,9 +59,10 @@ public class prog8Lexer extends Lexer {
"T__81", "T__82", "T__83", "T__84", "T__85", "T__86", "T__87", "T__88",
"T__89", "T__90", "T__91", "T__92", "T__93", "T__94", "T__95", "T__96",
"T__97", "T__98", "T__99", "T__100", "T__101", "T__102", "T__103", "T__104",
"T__105", "T__106", "T__107", "T__108", "T__109", "LINECOMMENT", "COMMENT",
"WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER",
"FNUMBER", "STRING_ESCAPE_SEQ", "STRING", "INLINEASMBLOCK", "SINGLECHAR"
"T__105", "T__106", "T__107", "T__108", "T__109", "T__110", "T__111",
"T__112", "T__113", "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER",
"HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ",
"STRING", "INLINEASMBLOCK", "SINGLECHAR"
};
}
public static final String[] ruleNames = makeRuleNames();
@ -72,16 +74,16 @@ public class prog8Lexer extends Lexer {
"'%asmbinary'", "'%option'", "','", "'='", "'const'", "'memory'", "'ubyte'",
"'byte'", "'uword'", "'word'", "'float'", "'str'", "'str_p'", "'str_s'",
"'str_ps'", "'['", "']'", "'+='", "'-='", "'/='", "'//='", "'*='", "'**='",
"'&='", "'|='", "'^='", "'%='", "'++'", "'--'", "'+'", "'-'", "'**'",
"'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='",
"'&'", "'^'", "'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'",
"'('", "')'", "'as'", "'@'", "'return'", "'break'", "'continue'", "'.'",
"'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'",
"'Pv'", "'.w'", "'true'", "'false'", "'%asm'", "'sub'", "'->'", "'{'",
"'}'", "'asmsub'", "'clobbers'", "'stack'", "'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'"
"'&='", "'|='", "'^='", "'%='", "'<<='", "'>>='", "'++'", "'--'", "'+'",
"'-'", "'**'", "'*'", "'/'", "'//'", "'%'", "'<<'", "'>>'", "'<'", "'>'",
"'<='", "'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'step'",
"'and'", "'or'", "'xor'", "'not'", "'('", "')'", "'as'", "'@'", "'return'",
"'break'", "'continue'", "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'",
"'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'", "'false'",
"'%asm'", "'sub'", "'->'", "'{'", "'}'", "'asmsub'", "'clobbers'", "'stack'",
"'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'"
};
}
private static final String[] _LITERAL_NAMES = makeLiteralNames();
@ -96,9 +98,9 @@ public class prog8Lexer extends Lexer {
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER",
"HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "STRING", "INLINEASMBLOCK",
"SINGLECHAR"
null, null, null, null, null, null, null, "LINECOMMENT", "COMMENT", "WS",
"EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER",
"STRING", "INLINEASMBLOCK", "SINGLECHAR"
};
}
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
@ -162,13 +164,13 @@ public class prog8Lexer extends Lexer {
@Override
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
switch (ruleIndex) {
case 121:
case 125:
STRING_action((RuleContext)_localctx, actionIndex);
break;
case 122:
case 126:
INLINEASMBLOCK_action((RuleContext)_localctx, actionIndex);
break;
case 123:
case 127:
SINGLECHAR_action((RuleContext)_localctx, actionIndex);
break;
}
@ -208,293 +210,303 @@ public class prog8Lexer extends Lexer {
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2|\u0362\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"+
"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+
",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+
"\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\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\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+
"\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\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3"+
"\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\27\3"+
"\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3"+
"\31\3\32\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3"+
"\34\3\34\3\35\3\35\3\36\3\36\3\36\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/\3\60\3\60\3\61"+
"\3\61\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\66\3\67\3\67\38\38\39\39\3:\3:\3:\3;\3;\3;\3;\3;\3<\3<\3<\3<\3=\3="+
"\3=\3>\3>\3>\3>\3?\3?\3?\3?\3@\3@\3A\3A\3B\3B\3B\3C\3C\3D\3D\3D\3D\3D"+
"\3D\3D\3E\3E\3E\3E\3E\3E\3F\3F\3F\3F\3F\3F\3F\3F\3F\3G\3G\3H\3H\3I\3I"+
"\3J\3J\3K\3K\3K\3L\3L\3L\3M\3M\3M\3N\3N\3N\3O\3O\3O\3P\3P\3P\3Q\3Q\3Q"+
"\3R\3R\3R\3S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3V\3V\3V\3V"+
"\3W\3W\3W\3X\3X\3Y\3Y\3Z\3Z\3Z\3Z\3Z\3Z\3Z\3[\3[\3[\3[\3[\3[\3[\3[\3["+
"\3\\\3\\\3\\\3\\\3\\\3\\\3]\3]\3]\3^\3^\3^\3^\3^\3_\3_\3_\3_\3_\3_\3`"+
"\3`\3`\3`\3`\3`\3a\3a\3a\3a\3a\3a\3b\3b\3b\3b\3b\3c\3c\3c\3c\3c\3c\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\3h\3i\3i\3i\3i\3i\3i\3j\3j\3j\3j\3j\3j\3k\3k\3k"+
"\3k\3l\3l\3l\3m\3m\3m\3m\3m\3m\3n\3n\3n\3n\3n\3n\3n\3o\3o\3o\3o\3o\3o"+
"\3p\3p\7p\u02f1\np\fp\16p\u02f4\13p\3p\3p\3p\3p\3q\3q\7q\u02fc\nq\fq\16"+
"q\u02ff\13q\3q\3q\3r\3r\3r\3r\3s\6s\u0308\ns\rs\16s\u0309\3t\3t\7t\u030e"+
"\nt\ft\16t\u0311\13t\3u\3u\3u\6u\u0316\nu\ru\16u\u0317\5u\u031a\nu\3v"+
"\3v\6v\u031e\nv\rv\16v\u031f\3w\3w\6w\u0324\nw\rw\16w\u0325\3x\3x\3x\5"+
"x\u032b\nx\3x\5x\u032e\nx\3y\6y\u0331\ny\ry\16y\u0332\3y\3y\6y\u0337\n"+
"y\ry\16y\u0338\5y\u033b\ny\3z\3z\3z\3z\5z\u0341\nz\3{\3{\3{\7{\u0346\n"+
"{\f{\16{\u0349\13{\3{\3{\3{\3|\3|\3|\3|\6|\u0352\n|\r|\16|\u0353\3|\3"+
"|\3|\3|\3|\3}\3}\3}\5}\u035e\n}\3}\3}\3}\3\u0353\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\67m8o9q:s;u<w=y>{?}@\177"+
"A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093"+
"K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7"+
"U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb"+
"_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9f\u00cbg\u00cdh\u00cf"+
"i\u00d1j\u00d3k\u00d5l\u00d7m\u00d9n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3"+
"s\u00e5t\u00e7u\u00e9v\u00ebw\u00edx\u00efy\u00f1\2\u00f3\2\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\u0371\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\2"+
"e\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\u00ef\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%\u0179\3\2\2\2\'\u017f\3\2\2\2)\u0184\3\2\2\2+\u018a"+
"\3\2\2\2-\u018f\3\2\2\2/\u0195\3\2\2\2\61\u0199\3\2\2\2\63\u019f\3\2\2"+
"\2\65\u01a5\3\2\2\2\67\u01ac\3\2\2\29\u01ae\3\2\2\2;\u01b0\3\2\2\2=\u01b3"+
"\3\2\2\2?\u01b6\3\2\2\2A\u01b9\3\2\2\2C\u01bd\3\2\2\2E\u01c0\3\2\2\2G"+
"\u01c4\3\2\2\2I\u01c7\3\2\2\2K\u01ca\3\2\2\2M\u01cd\3\2\2\2O\u01d0\3\2"+
"\2\2Q\u01d3\3\2\2\2S\u01d6\3\2\2\2U\u01d8\3\2\2\2W\u01da\3\2\2\2Y\u01dd"+
"\3\2\2\2[\u01df\3\2\2\2]\u01e1\3\2\2\2_\u01e4\3\2\2\2a\u01e6\3\2\2\2c"+
"\u01e8\3\2\2\2e\u01ea\3\2\2\2g\u01ed\3\2\2\2i\u01f0\3\2\2\2k\u01f3\3\2"+
"\2\2m\u01f6\3\2\2\2o\u01f8\3\2\2\2q\u01fa\3\2\2\2s\u01fc\3\2\2\2u\u01ff"+
"\3\2\2\2w\u0204\3\2\2\2y\u0208\3\2\2\2{\u020b\3\2\2\2}\u020f\3\2\2\2\177"+
"\u0213\3\2\2\2\u0081\u0215\3\2\2\2\u0083\u0217\3\2\2\2\u0085\u021a\3\2"+
"\2\2\u0087\u021c\3\2\2\2\u0089\u0223\3\2\2\2\u008b\u0229\3\2\2\2\u008d"+
"\u0232\3\2\2\2\u008f\u0234\3\2\2\2\u0091\u0236\3\2\2\2\u0093\u0238\3\2"+
"\2\2\u0095\u023a\3\2\2\2\u0097\u023d\3\2\2\2\u0099\u0240\3\2\2\2\u009b"+
"\u0243\3\2\2\2\u009d\u0246\3\2\2\2\u009f\u0249\3\2\2\2\u00a1\u024c\3\2"+
"\2\2\u00a3\u024f\3\2\2\2\u00a5\u0252\3\2\2\2\u00a7\u0257\3\2\2\2\u00a9"+
"\u025d\3\2\2\2\u00ab\u0262\3\2\2\2\u00ad\u0266\3\2\2\2\u00af\u0269\3\2"+
"\2\2\u00b1\u026b\3\2\2\2\u00b3\u026d\3\2\2\2\u00b5\u0274\3\2\2\2\u00b7"+
"\u027d\3\2\2\2\u00b9\u0283\3\2\2\2\u00bb\u0286\3\2\2\2\u00bd\u028b\3\2"+
"\2\2\u00bf\u0291\3\2\2\2\u00c1\u0297\3\2\2\2\u00c3\u029d\3\2\2\2\u00c5"+
"\u02a2\3\2\2\2\u00c7\u02a8\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\u02c8\3\2\2\2\u00d3"+
"\u02ce\3\2\2\2\u00d5\u02d4\3\2\2\2\u00d7\u02d8\3\2\2\2\u00d9\u02db\3\2"+
"\2\2\u00db\u02e1\3\2\2\2\u00dd\u02e8\3\2\2\2\u00df\u02ee\3\2\2\2\u00e1"+
"\u02f9\3\2\2\2\u00e3\u0302\3\2\2\2\u00e5\u0307\3\2\2\2\u00e7\u030b\3\2"+
"\2\2\u00e9\u0319\3\2\2\2\u00eb\u031b\3\2\2\2\u00ed\u0321\3\2\2\2\u00ef"+
"\u0327\3\2\2\2\u00f1\u0330\3\2\2\2\u00f3\u0340\3\2\2\2\u00f5\u0342\3\2"+
"\2\2\u00f7\u034d\3\2\2\2\u00f9\u035a\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\7u\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\7o\2\2\u0173\u0174\7g"+
"\2\2\u0174\u0175\7o\2\2\u0175\u0176\7q\2\2\u0176\u0177\7t\2\2\u0177\u0178"+
"\7{\2\2\u0178$\3\2\2\2\u0179\u017a\7w\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"+
"\7d\2\2\u0180\u0181\7{\2\2\u0181\u0182\7v\2\2\u0182\u0183\7g\2\2\u0183"+
"(\3\2\2\2\u0184\u0185\7w\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\7y\2\2\u018b"+
"\u018c\7q\2\2\u018c\u018d\7t\2\2\u018d\u018e\7f\2\2\u018e,\3\2\2\2\u018f"+
"\u0190\7h\2\2\u0190\u0191\7n\2\2\u0191\u0192\7q\2\2\u0192\u0193\7c\2\2"+
"\u0193\u0194\7v\2\2\u0194.\3\2\2\2\u0195\u0196\7u\2\2\u0196\u0197\7v\2"+
"\2\u0197\u0198\7t\2\2\u0198\60\3\2\2\2\u0199\u019a\7u\2\2\u019a\u019b"+
"\7v\2\2\u019b\u019c\7t\2\2\u019c\u019d\7a\2\2\u019d\u019e\7r\2\2\u019e"+
"\62\3\2\2\2\u019f\u01a0\7u\2\2\u01a0\u01a1\7v\2\2\u01a1\u01a2\7t\2\2\u01a2"+
"\u01a3\7a\2\2\u01a3\u01a4\7u\2\2\u01a4\64\3\2\2\2\u01a5\u01a6\7u\2\2\u01a6"+
"\u01a7\7v\2\2\u01a7\u01a8\7t\2\2\u01a8\u01a9\7a\2\2\u01a9\u01aa\7r\2\2"+
"\u01aa\u01ab\7u\2\2\u01ab\66\3\2\2\2\u01ac\u01ad\7]\2\2\u01ad8\3\2\2\2"+
"\u01ae\u01af\7_\2\2\u01af:\3\2\2\2\u01b0\u01b1\7-\2\2\u01b1\u01b2\7?\2"+
"\2\u01b2<\3\2\2\2\u01b3\u01b4\7/\2\2\u01b4\u01b5\7?\2\2\u01b5>\3\2\2\2"+
"\u01b6\u01b7\7\61\2\2\u01b7\u01b8\7?\2\2\u01b8@\3\2\2\2\u01b9\u01ba\7"+
"\61\2\2\u01ba\u01bb\7\61\2\2\u01bb\u01bc\7?\2\2\u01bcB\3\2\2\2\u01bd\u01be"+
"\7,\2\2\u01be\u01bf\7?\2\2\u01bfD\3\2\2\2\u01c0\u01c1\7,\2\2\u01c1\u01c2"+
"\7,\2\2\u01c2\u01c3\7?\2\2\u01c3F\3\2\2\2\u01c4\u01c5\7(\2\2\u01c5\u01c6"+
"\7?\2\2\u01c6H\3\2\2\2\u01c7\u01c8\7~\2\2\u01c8\u01c9\7?\2\2\u01c9J\3"+
"\2\2\2\u01ca\u01cb\7`\2\2\u01cb\u01cc\7?\2\2\u01ccL\3\2\2\2\u01cd\u01ce"+
"\7\'\2\2\u01ce\u01cf\7?\2\2\u01cfN\3\2\2\2\u01d0\u01d1\7-\2\2\u01d1\u01d2"+
"\7-\2\2\u01d2P\3\2\2\2\u01d3\u01d4\7/\2\2\u01d4\u01d5\7/\2\2\u01d5R\3"+
"\2\2\2\u01d6\u01d7\7-\2\2\u01d7T\3\2\2\2\u01d8\u01d9\7/\2\2\u01d9V\3\2"+
"\2\2\u01da\u01db\7,\2\2\u01db\u01dc\7,\2\2\u01dcX\3\2\2\2\u01dd\u01de"+
"\7,\2\2\u01deZ\3\2\2\2\u01df\u01e0\7\61\2\2\u01e0\\\3\2\2\2\u01e1\u01e2"+
"\7\61\2\2\u01e2\u01e3\7\61\2\2\u01e3^\3\2\2\2\u01e4\u01e5\7\'\2\2\u01e5"+
"`\3\2\2\2\u01e6\u01e7\7>\2\2\u01e7b\3\2\2\2\u01e8\u01e9\7@\2\2\u01e9d"+
"\3\2\2\2\u01ea\u01eb\7>\2\2\u01eb\u01ec\7?\2\2\u01ecf\3\2\2\2\u01ed\u01ee"+
"\7@\2\2\u01ee\u01ef\7?\2\2\u01efh\3\2\2\2\u01f0\u01f1\7?\2\2\u01f1\u01f2"+
"\7?\2\2\u01f2j\3\2\2\2\u01f3\u01f4\7#\2\2\u01f4\u01f5\7?\2\2\u01f5l\3"+
"\2\2\2\u01f6\u01f7\7(\2\2\u01f7n\3\2\2\2\u01f8\u01f9\7`\2\2\u01f9p\3\2"+
"\2\2\u01fa\u01fb\7~\2\2\u01fbr\3\2\2\2\u01fc\u01fd\7v\2\2\u01fd\u01fe"+
"\7q\2\2\u01fet\3\2\2\2\u01ff\u0200\7u\2\2\u0200\u0201\7v\2\2\u0201\u0202"+
"\7g\2\2\u0202\u0203\7r\2\2\u0203v\3\2\2\2\u0204\u0205\7c\2\2\u0205\u0206"+
"\7p\2\2\u0206\u0207\7f\2\2\u0207x\3\2\2\2\u0208\u0209\7q\2\2\u0209\u020a"+
"\7t\2\2\u020az\3\2\2\2\u020b\u020c\7z\2\2\u020c\u020d\7q\2\2\u020d\u020e"+
"\7t\2\2\u020e|\3\2\2\2\u020f\u0210\7p\2\2\u0210\u0211\7q\2\2\u0211\u0212"+
"\7v\2\2\u0212~\3\2\2\2\u0213\u0214\7*\2\2\u0214\u0080\3\2\2\2\u0215\u0216"+
"\7+\2\2\u0216\u0082\3\2\2\2\u0217\u0218\7c\2\2\u0218\u0219\7u\2\2\u0219"+
"\u0084\3\2\2\2\u021a\u021b\7B\2\2\u021b\u0086\3\2\2\2\u021c\u021d\7t\2"+
"\2\u021d\u021e\7g\2\2\u021e\u021f\7v\2\2\u021f\u0220\7w\2\2\u0220\u0221"+
"\7t\2\2\u0221\u0222\7p\2\2\u0222\u0088\3\2\2\2\u0223\u0224\7d\2\2\u0224"+
"\u0225\7t\2\2\u0225\u0226\7g\2\2\u0226\u0227\7c\2\2\u0227\u0228\7m\2\2"+
"\u0228\u008a\3\2\2\2\u0229\u022a\7e\2\2\u022a\u022b\7q\2\2\u022b\u022c"+
"\7p\2\2\u022c\u022d\7v\2\2\u022d\u022e\7k\2\2\u022e\u022f\7p\2\2\u022f"+
"\u0230\7w\2\2\u0230\u0231\7g\2\2\u0231\u008c\3\2\2\2\u0232\u0233\7\60"+
"\2\2\u0233\u008e\3\2\2\2\u0234\u0235\7C\2\2\u0235\u0090\3\2\2\2\u0236"+
"\u0237\7Z\2\2\u0237\u0092\3\2\2\2\u0238\u0239\7[\2\2\u0239\u0094\3\2\2"+
"\2\u023a\u023b\7C\2\2\u023b\u023c\7Z\2\2\u023c\u0096\3\2\2\2\u023d\u023e"+
"\7C\2\2\u023e\u023f\7[\2\2\u023f\u0098\3\2\2\2\u0240\u0241\7Z\2\2\u0241"+
"\u0242\7[\2\2\u0242\u009a\3\2\2\2\u0243\u0244\7R\2\2\u0244\u0245\7e\2"+
"\2\u0245\u009c\3\2\2\2\u0246\u0247\7R\2\2\u0247\u0248\7|\2\2\u0248\u009e"+
"\3\2\2\2\u0249\u024a\7R\2\2\u024a\u024b\7p\2\2\u024b\u00a0\3\2\2\2\u024c"+
"\u024d\7R\2\2\u024d\u024e\7x\2\2\u024e\u00a2\3\2\2\2\u024f\u0250\7\60"+
"\2\2\u0250\u0251\7y\2\2\u0251\u00a4\3\2\2\2\u0252\u0253\7v\2\2\u0253\u0254"+
"\7t\2\2\u0254\u0255\7w\2\2\u0255\u0256\7g\2\2\u0256\u00a6\3\2\2\2\u0257"+
"\u0258\7h\2\2\u0258\u0259\7c\2\2\u0259\u025a\7n\2\2\u025a\u025b\7u\2\2"+
"\u025b\u025c\7g\2\2\u025c\u00a8\3\2\2\2\u025d\u025e\7\'\2\2\u025e\u025f"+
"\7c\2\2\u025f\u0260\7u\2\2\u0260\u0261\7o\2\2\u0261\u00aa\3\2\2\2\u0262"+
"\u0263\7u\2\2\u0263\u0264\7w\2\2\u0264\u0265\7d\2\2\u0265\u00ac\3\2\2"+
"\2\u0266\u0267\7/\2\2\u0267\u0268\7@\2\2\u0268\u00ae\3\2\2\2\u0269\u026a"+
"\7}\2\2\u026a\u00b0\3\2\2\2\u026b\u026c\7\177\2\2\u026c\u00b2\3\2\2\2"+
"\u026d\u026e\7c\2\2\u026e\u026f\7u\2\2\u026f\u0270\7o\2\2\u0270\u0271"+
"\7u\2\2\u0271\u0272\7w\2\2\u0272\u0273\7d\2\2\u0273\u00b4\3\2\2\2\u0274"+
"\u0275\7e\2\2\u0275\u0276\7n\2\2\u0276\u0277\7q\2\2\u0277\u0278\7d\2\2"+
"\u0278\u0279\7d\2\2\u0279\u027a\7g\2\2\u027a\u027b\7t\2\2\u027b\u027c"+
"\7u\2\2\u027c\u00b6\3\2\2\2\u027d\u027e\7u\2\2\u027e\u027f\7v\2\2\u027f"+
"\u0280\7c\2\2\u0280\u0281\7e\2\2\u0281\u0282\7m\2\2\u0282\u00b8\3\2\2"+
"\2\u0283\u0284\7k\2\2\u0284\u0285\7h\2\2\u0285\u00ba\3\2\2\2\u0286\u0287"+
"\7g\2\2\u0287\u0288\7n\2\2\u0288\u0289\7u\2\2\u0289\u028a\7g\2\2\u028a"+
"\u00bc\3\2\2\2\u028b\u028c\7k\2\2\u028c\u028d\7h\2\2\u028d\u028e\7a\2"+
"\2\u028e\u028f\7e\2\2\u028f\u0290\7u\2\2\u0290\u00be\3\2\2\2\u0291\u0292"+
"\7k\2\2\u0292\u0293\7h\2\2\u0293\u0294\7a\2\2\u0294\u0295\7e\2\2\u0295"+
"\u0296\7e\2\2\u0296\u00c0\3\2\2\2\u0297\u0298\7k\2\2\u0298\u0299\7h\2"+
"\2\u0299\u029a\7a\2\2\u029a\u029b\7g\2\2\u029b\u029c\7s\2\2\u029c\u00c2"+
"\3\2\2\2\u029d\u029e\7k\2\2\u029e\u029f\7h\2\2\u029f\u02a0\7a\2\2\u02a0"+
"\u02a1\7|\2\2\u02a1\u00c4\3\2\2\2\u02a2\u02a3\7k\2\2\u02a3\u02a4\7h\2"+
"\2\u02a4\u02a5\7a\2\2\u02a5\u02a6\7p\2\2\u02a6\u02a7\7g\2\2\u02a7\u00c6"+
"\3\2\2\2\u02a8\u02a9\7k\2\2\u02a9\u02aa\7h\2\2\u02aa\u02ab\7a\2\2\u02ab"+
"\u02ac\7p\2\2\u02ac\u02ad\7|\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\7r\2\2\u02b2\u02b3"+
"\7n\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\7r\2\2\u02b8\u02b9\7q\2\2\u02b9\u02ba\7u\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\7o\2\2\u02bf\u02c0\7k\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\7p\2\2"+
"\u02c5\u02c6\7g\2\2\u02c6\u02c7\7i\2\2\u02c7\u00d0\3\2\2\2\u02c8\u02c9"+
"\7k\2\2\u02c9\u02ca\7h\2\2\u02ca\u02cb\7a\2\2\u02cb\u02cc\7x\2\2\u02cc"+
"\u02cd\7u\2\2\u02cd\u00d2\3\2\2\2\u02ce\u02cf\7k\2\2\u02cf\u02d0\7h\2"+
"\2\u02d0\u02d1\7a\2\2\u02d1\u02d2\7x\2\2\u02d2\u02d3\7e\2\2\u02d3\u00d4"+
"\3\2\2\2\u02d4\u02d5\7h\2\2\u02d5\u02d6\7q\2\2\u02d6\u02d7\7t\2\2\u02d7"+
"\u00d6\3\2\2\2\u02d8\u02d9\7k\2\2\u02d9\u02da\7p\2\2\u02da\u00d8\3\2\2"+
"\2\u02db\u02dc\7y\2\2\u02dc\u02dd\7j\2\2\u02dd\u02de\7k\2\2\u02de\u02df"+
"\7n\2\2\u02df\u02e0\7g\2\2\u02e0\u00da\3\2\2\2\u02e1\u02e2\7t\2\2\u02e2"+
"\u02e3\7g\2\2\u02e3\u02e4\7r\2\2\u02e4\u02e5\7g\2\2\u02e5\u02e6\7c\2\2"+
"\u02e6\u02e7\7v\2\2\u02e7\u00dc\3\2\2\2\u02e8\u02e9\7w\2\2\u02e9\u02ea"+
"\7p\2\2\u02ea\u02eb\7v\2\2\u02eb\u02ec\7k\2\2\u02ec\u02ed\7n\2\2\u02ed"+
"\u00de\3\2\2\2\u02ee\u02f2\t\2\2\2\u02ef\u02f1\t\3\2\2\u02f0\u02ef\3\2"+
"\2\2\u02f1\u02f4\3\2\2\2\u02f2\u02f0\3\2\2\2\u02f2\u02f3\3\2\2\2\u02f3"+
"\u02f5\3\2\2\2\u02f4\u02f2\3\2\2\2\u02f5\u02f6\5\u00e1q\2\u02f6\u02f7"+
"\3\2\2\2\u02f7\u02f8\bp\2\2\u02f8\u00e0\3\2\2\2\u02f9\u02fd\7=\2\2\u02fa"+
"\u02fc\n\2\2\2\u02fb\u02fa\3\2\2\2\u02fc\u02ff\3\2\2\2\u02fd\u02fb\3\2"+
"\2\2\u02fd\u02fe\3\2\2\2\u02fe\u0300\3\2\2\2\u02ff\u02fd\3\2\2\2\u0300"+
"\u0301\bq\2\2\u0301\u00e2\3\2\2\2\u0302\u0303\t\3\2\2\u0303\u0304\3\2"+
"\2\2\u0304\u0305\br\3\2\u0305\u00e4\3\2\2\2\u0306\u0308\t\2\2\2\u0307"+
"\u0306\3\2\2\2\u0308\u0309\3\2\2\2\u0309\u0307\3\2\2\2\u0309\u030a\3\2"+
"\2\2\u030a\u00e6\3\2\2\2\u030b\u030f\t\4\2\2\u030c\u030e\t\5\2\2\u030d"+
"\u030c\3\2\2\2\u030e\u0311\3\2\2\2\u030f\u030d\3\2\2\2\u030f\u0310\3\2"+
"\2\2\u0310\u00e8\3\2\2\2\u0311\u030f\3\2\2\2\u0312\u031a\4\62;\2\u0313"+
"\u0315\4\63;\2\u0314\u0316\4\62;\2\u0315\u0314\3\2\2\2\u0316\u0317\3\2"+
"\2\2\u0317\u0315\3\2\2\2\u0317\u0318\3\2\2\2\u0318\u031a\3\2\2\2\u0319"+
"\u0312\3\2\2\2\u0319\u0313\3\2\2\2\u031a\u00ea\3\2\2\2\u031b\u031d\7&"+
"\2\2\u031c\u031e\t\6\2\2\u031d\u031c\3\2\2\2\u031e\u031f\3\2\2\2\u031f"+
"\u031d\3\2\2\2\u031f\u0320\3\2\2\2\u0320\u00ec\3\2\2\2\u0321\u0323\7\'"+
"\2\2\u0322\u0324\4\62\63\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\u00ee\3\2\2\2\u0327\u032d\5\u00f1"+
"y\2\u0328\u032a\t\7\2\2\u0329\u032b\t\b\2\2\u032a\u0329\3\2\2\2\u032a"+
"\u032b\3\2\2\2\u032b\u032c\3\2\2\2\u032c\u032e\5\u00f1y\2\u032d\u0328"+
"\3\2\2\2\u032d\u032e\3\2\2\2\u032e\u00f0\3\2\2\2\u032f\u0331\4\62;\2\u0330"+
"\u032f\3\2\2\2\u0331\u0332\3\2\2\2\u0332\u0330\3\2\2\2\u0332\u0333\3\2"+
"\2\2\u0333\u033a\3\2\2\2\u0334\u0336\7\60\2\2\u0335\u0337\4\62;\2\u0336"+
"\u0335\3\2\2\2\u0337\u0338\3\2\2\2\u0338\u0336\3\2\2\2\u0338\u0339\3\2"+
"\2\2\u0339\u033b\3\2\2\2\u033a\u0334\3\2\2\2\u033a\u033b\3\2\2\2\u033b"+
"\u00f2\3\2\2\2\u033c\u033d\7^\2\2\u033d\u0341\13\2\2\2\u033e\u033f\7^"+
"\2\2\u033f\u0341\5\u00e5s\2\u0340\u033c\3\2\2\2\u0340\u033e\3\2\2\2\u0341"+
"\u00f4\3\2\2\2\u0342\u0347\7$\2\2\u0343\u0346\5\u00f3z\2\u0344\u0346\n"+
"\t\2\2\u0345\u0343\3\2\2\2\u0345\u0344\3\2\2\2\u0346\u0349\3\2\2\2\u0347"+
"\u0345\3\2\2\2\u0347\u0348\3\2\2\2\u0348\u034a\3\2\2\2\u0349\u0347\3\2"+
"\2\2\u034a\u034b\7$\2\2\u034b\u034c\b{\4\2\u034c\u00f6\3\2\2\2\u034d\u034e"+
"\7}\2\2\u034e\u034f\7}\2\2\u034f\u0351\3\2\2\2\u0350\u0352\13\2\2\2\u0351"+
"\u0350\3\2\2\2\u0352\u0353\3\2\2\2\u0353\u0354\3\2\2\2\u0353\u0351\3\2"+
"\2\2\u0354\u0355\3\2\2\2\u0355\u0356\7\177\2\2\u0356\u0357\7\177\2\2\u0357"+
"\u0358\3\2\2\2\u0358\u0359\b|\5\2\u0359\u00f8\3\2\2\2\u035a\u035d\7)\2"+
"\2\u035b\u035e\5\u00f3z\2\u035c\u035e\n\t\2\2\u035d\u035b\3\2\2\2\u035d"+
"\u035c\3\2\2\2\u035e\u035f\3\2\2\2\u035f\u0360\7)\2\2\u0360\u0361\b}\6"+
"\2\u0361\u00fa\3\2\2\2\26\2\u02f2\u02fd\u0309\u030f\u0317\u0319\u031d"+
"\u031f\u0325\u032a\u032d\u0332\u0338\u033a\u0340\u0345\u0347\u0353\u035d"+
"\7\2\3\2\b\2\2\3{\2\3|\3\3}\4";
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\u0080\u0378\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\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t"+
" \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t"+
"+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+
"\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\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\4"+
"I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\t"+
"T\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"+
"\tk\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv"+
"\4w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\4\177\t\177\4\u0080\t"+
"\u0080\4\u0081\t\u0081\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"+
"\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3"+
"\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3"+
"\27\3\30\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3"+
"\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\35\3\35\3"+
"\36\3\36\3\36\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.\3.\3/\3/\3\60\3\60\3\61\3\61\3\61\3"+
"\62\3\62\3\63\3\63\3\63\3\64\3\64\3\64\3\65\3\65\3\66\3\66\3\67\3\67\3"+
"\67\38\38\38\39\39\39\3:\3:\3:\3;\3;\3<\3<\3=\3=\3>\3>\3>\3?\3?\3?\3?"+
"\3?\3@\3@\3@\3@\3A\3A\3A\3B\3B\3B\3B\3C\3C\3C\3C\3D\3D\3E\3E\3F\3F\3F"+
"\3G\3G\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3K\3K\3L\3L\3M\3M\3N\3N\3O\3O\3O\3P\3P\3P\3Q\3Q\3Q\3R\3R\3R\3S\3S"+
"\3S\3T\3T\3T\3U\3U\3U\3V\3V\3V\3W\3W\3W\3W\3W\3X\3X\3X\3X\3X\3X\3Y\3Y"+
"\3Y\3Y\3Y\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`\3a\3a\3a\3b\3b\3b\3b\3b\3c\3"+
"c\3c\3c\3c\3c\3d\3d\3d\3d\3d\3d\3e\3e\3e\3e\3e\3e\3f\3f\3f\3f\3f\3g\3"+
"g\3g\3g\3g\3g\3h\3h\3h\3h\3h\3h\3i\3i\3i\3i\3i\3i\3j\3j\3j\3j\3j\3j\3"+
"j\3k\3k\3k\3k\3k\3k\3l\3l\3l\3l\3l\3l\3l\3m\3m\3m\3m\3m\3m\3n\3n\3n\3"+
"n\3n\3n\3o\3o\3o\3o\3p\3p\3p\3q\3q\3q\3q\3q\3q\3r\3r\3r\3r\3r\3r\3r\3"+
"s\3s\3s\3s\3s\3s\3t\3t\7t\u0307\nt\ft\16t\u030a\13t\3t\3t\3t\3t\3u\3u"+
"\7u\u0312\nu\fu\16u\u0315\13u\3u\3u\3v\3v\3v\3v\3w\6w\u031e\nw\rw\16w"+
"\u031f\3x\3x\7x\u0324\nx\fx\16x\u0327\13x\3y\3y\3y\6y\u032c\ny\ry\16y"+
"\u032d\5y\u0330\ny\3z\3z\6z\u0334\nz\rz\16z\u0335\3{\3{\6{\u033a\n{\r"+
"{\16{\u033b\3|\3|\3|\5|\u0341\n|\3|\5|\u0344\n|\3}\6}\u0347\n}\r}\16}"+
"\u0348\3}\3}\6}\u034d\n}\r}\16}\u034e\5}\u0351\n}\3~\3~\3~\3~\5~\u0357"+
"\n~\3\177\3\177\3\177\7\177\u035c\n\177\f\177\16\177\u035f\13\177\3\177"+
"\3\177\3\177\3\u0080\3\u0080\3\u0080\3\u0080\6\u0080\u0368\n\u0080\r\u0080"+
"\16\u0080\u0369\3\u0080\3\u0080\3\u0080\3\u0080\3\u0080\3\u0081\3\u0081"+
"\3\u0081\5\u0081\u0374\n\u0081\3\u0081\3\u0081\3\u0081\3\u0369\2\u0082"+
"\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20"+
"\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37"+
"= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o"+
"9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH"+
"\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\u00efy\u00f1"+
"z\u00f3{\u00f5|\u00f7}\u00f9\2\u00fb\2\u00fd~\u00ff\177\u0101\u0080\3"+
"\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2C\\aac|\6\2\62;C\\aac|\5\2\62;CHc"+
"h\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2\u0387\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\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_\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\2"+
"s\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\u00ef\3\2\2\2\2\u00f1\3\2\2\2\2\u00f3\3\2\2"+
"\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00fd\3\2\2\2\2\u00ff\3\2\2\2\2\u0101"+
"\3\2\2\2\3\u0103\3\2\2\2\5\u0105\3\2\2\2\7\u0107\3\2\2\2\t\u010c\3\2\2"+
"\2\13\u0114\3\2\2\2\r\u011e\3\2\2\2\17\u0128\3\2\2\2\21\u0134\3\2\2\2"+
"\23\u013d\3\2\2\2\25\u0145\3\2\2\2\27\u0151\3\2\2\2\31\u015d\3\2\2\2\33"+
"\u0168\3\2\2\2\35\u0170\3\2\2\2\37\u0172\3\2\2\2!\u0174\3\2\2\2#\u017a"+
"\3\2\2\2%\u0181\3\2\2\2\'\u0187\3\2\2\2)\u018c\3\2\2\2+\u0192\3\2\2\2"+
"-\u0197\3\2\2\2/\u019d\3\2\2\2\61\u01a1\3\2\2\2\63\u01a7\3\2\2\2\65\u01ad"+
"\3\2\2\2\67\u01b4\3\2\2\29\u01b6\3\2\2\2;\u01b8\3\2\2\2=\u01bb\3\2\2\2"+
"?\u01be\3\2\2\2A\u01c1\3\2\2\2C\u01c5\3\2\2\2E\u01c8\3\2\2\2G\u01cc\3"+
"\2\2\2I\u01cf\3\2\2\2K\u01d2\3\2\2\2M\u01d5\3\2\2\2O\u01d8\3\2\2\2Q\u01dc"+
"\3\2\2\2S\u01e0\3\2\2\2U\u01e3\3\2\2\2W\u01e6\3\2\2\2Y\u01e8\3\2\2\2["+
"\u01ea\3\2\2\2]\u01ed\3\2\2\2_\u01ef\3\2\2\2a\u01f1\3\2\2\2c\u01f4\3\2"+
"\2\2e\u01f6\3\2\2\2g\u01f9\3\2\2\2i\u01fc\3\2\2\2k\u01fe\3\2\2\2m\u0200"+
"\3\2\2\2o\u0203\3\2\2\2q\u0206\3\2\2\2s\u0209\3\2\2\2u\u020c\3\2\2\2w"+
"\u020e\3\2\2\2y\u0210\3\2\2\2{\u0212\3\2\2\2}\u0215\3\2\2\2\177\u021a"+
"\3\2\2\2\u0081\u021e\3\2\2\2\u0083\u0221\3\2\2\2\u0085\u0225\3\2\2\2\u0087"+
"\u0229\3\2\2\2\u0089\u022b\3\2\2\2\u008b\u022d\3\2\2\2\u008d\u0230\3\2"+
"\2\2\u008f\u0232\3\2\2\2\u0091\u0239\3\2\2\2\u0093\u023f\3\2\2\2\u0095"+
"\u0248\3\2\2\2\u0097\u024a\3\2\2\2\u0099\u024c\3\2\2\2\u009b\u024e\3\2"+
"\2\2\u009d\u0250\3\2\2\2\u009f\u0253\3\2\2\2\u00a1\u0256\3\2\2\2\u00a3"+
"\u0259\3\2\2\2\u00a5\u025c\3\2\2\2\u00a7\u025f\3\2\2\2\u00a9\u0262\3\2"+
"\2\2\u00ab\u0265\3\2\2\2\u00ad\u0268\3\2\2\2\u00af\u026d\3\2\2\2\u00b1"+
"\u0273\3\2\2\2\u00b3\u0278\3\2\2\2\u00b5\u027c\3\2\2\2\u00b7\u027f\3\2"+
"\2\2\u00b9\u0281\3\2\2\2\u00bb\u0283\3\2\2\2\u00bd\u028a\3\2\2\2\u00bf"+
"\u0293\3\2\2\2\u00c1\u0299\3\2\2\2\u00c3\u029c\3\2\2\2\u00c5\u02a1\3\2"+
"\2\2\u00c7\u02a7\3\2\2\2\u00c9\u02ad\3\2\2\2\u00cb\u02b3\3\2\2\2\u00cd"+
"\u02b8\3\2\2\2\u00cf\u02be\3\2\2\2\u00d1\u02c4\3\2\2\2\u00d3\u02ca\3\2"+
"\2\2\u00d5\u02d1\3\2\2\2\u00d7\u02d7\3\2\2\2\u00d9\u02de\3\2\2\2\u00db"+
"\u02e4\3\2\2\2\u00dd\u02ea\3\2\2\2\u00df\u02ee\3\2\2\2\u00e1\u02f1\3\2"+
"\2\2\u00e3\u02f7\3\2\2\2\u00e5\u02fe\3\2\2\2\u00e7\u0304\3\2\2\2\u00e9"+
"\u030f\3\2\2\2\u00eb\u0318\3\2\2\2\u00ed\u031d\3\2\2\2\u00ef\u0321\3\2"+
"\2\2\u00f1\u032f\3\2\2\2\u00f3\u0331\3\2\2\2\u00f5\u0337\3\2\2\2\u00f7"+
"\u033d\3\2\2\2\u00f9\u0346\3\2\2\2\u00fb\u0356\3\2\2\2\u00fd\u0358\3\2"+
"\2\2\u00ff\u0363\3\2\2\2\u0101\u0370\3\2\2\2\u0103\u0104\7\u0080\2\2\u0104"+
"\4\3\2\2\2\u0105\u0106\7<\2\2\u0106\6\3\2\2\2\u0107\u0108\7i\2\2\u0108"+
"\u0109\7q\2\2\u0109\u010a\7v\2\2\u010a\u010b\7q\2\2\u010b\b\3\2\2\2\u010c"+
"\u010d\7\'\2\2\u010d\u010e\7q\2\2\u010e\u010f\7w\2\2\u010f\u0110\7v\2"+
"\2\u0110\u0111\7r\2\2\u0111\u0112\7w\2\2\u0112\u0113\7v\2\2\u0113\n\3"+
"\2\2\2\u0114\u0115\7\'\2\2\u0115\u0116\7n\2\2\u0116\u0117\7c\2\2\u0117"+
"\u0118\7w\2\2\u0118\u0119\7p\2\2\u0119\u011a\7e\2\2\u011a\u011b\7j\2\2"+
"\u011b\u011c\7g\2\2\u011c\u011d\7t\2\2\u011d\f\3\2\2\2\u011e\u011f\7\'"+
"\2\2\u011f\u0120\7|\2\2\u0120\u0121\7g\2\2\u0121\u0122\7t\2\2\u0122\u0123"+
"\7q\2\2\u0123\u0124\7r\2\2\u0124\u0125\7c\2\2\u0125\u0126\7i\2\2\u0126"+
"\u0127\7g\2\2\u0127\16\3\2\2\2\u0128\u0129\7\'\2\2\u0129\u012a\7|\2\2"+
"\u012a\u012b\7r\2\2\u012b\u012c\7t\2\2\u012c\u012d\7g\2\2\u012d\u012e"+
"\7u\2\2\u012e\u012f\7g\2\2\u012f\u0130\7t\2\2\u0130\u0131\7x\2\2\u0131"+
"\u0132\7g\2\2\u0132\u0133\7f\2\2\u0133\20\3\2\2\2\u0134\u0135\7\'\2\2"+
"\u0135\u0136\7c\2\2\u0136\u0137\7f\2\2\u0137\u0138\7f\2\2\u0138\u0139"+
"\7t\2\2\u0139\u013a\7g\2\2\u013a\u013b\7u\2\2\u013b\u013c\7u\2\2\u013c"+
"\22\3\2\2\2\u013d\u013e\7\'\2\2\u013e\u013f\7k\2\2\u013f\u0140\7o\2\2"+
"\u0140\u0141\7r\2\2\u0141\u0142\7q\2\2\u0142\u0143\7t\2\2\u0143\u0144"+
"\7v\2\2\u0144\24\3\2\2\2\u0145\u0146\7\'\2\2\u0146\u0147\7d\2\2\u0147"+
"\u0148\7t\2\2\u0148\u0149\7g\2\2\u0149\u014a\7c\2\2\u014a\u014b\7m\2\2"+
"\u014b\u014c\7r\2\2\u014c\u014d\7q\2\2\u014d\u014e\7k\2\2\u014e\u014f"+
"\7p\2\2\u014f\u0150\7v\2\2\u0150\26\3\2\2\2\u0151\u0152\7\'\2\2\u0152"+
"\u0153\7c\2\2\u0153\u0154\7u\2\2\u0154\u0155\7o\2\2\u0155\u0156\7k\2\2"+
"\u0156\u0157\7p\2\2\u0157\u0158\7e\2\2\u0158\u0159\7n\2\2\u0159\u015a"+
"\7w\2\2\u015a\u015b\7f\2\2\u015b\u015c\7g\2\2\u015c\30\3\2\2\2\u015d\u015e"+
"\7\'\2\2\u015e\u015f\7c\2\2\u015f\u0160\7u\2\2\u0160\u0161\7o\2\2\u0161"+
"\u0162\7d\2\2\u0162\u0163\7k\2\2\u0163\u0164\7p\2\2\u0164\u0165\7c\2\2"+
"\u0165\u0166\7t\2\2\u0166\u0167\7{\2\2\u0167\32\3\2\2\2\u0168\u0169\7"+
"\'\2\2\u0169\u016a\7q\2\2\u016a\u016b\7r\2\2\u016b\u016c\7v\2\2\u016c"+
"\u016d\7k\2\2\u016d\u016e\7q\2\2\u016e\u016f\7p\2\2\u016f\34\3\2\2\2\u0170"+
"\u0171\7.\2\2\u0171\36\3\2\2\2\u0172\u0173\7?\2\2\u0173 \3\2\2\2\u0174"+
"\u0175\7e\2\2\u0175\u0176\7q\2\2\u0176\u0177\7p\2\2\u0177\u0178\7u\2\2"+
"\u0178\u0179\7v\2\2\u0179\"\3\2\2\2\u017a\u017b\7o\2\2\u017b\u017c\7g"+
"\2\2\u017c\u017d\7o\2\2\u017d\u017e\7q\2\2\u017e\u017f\7t\2\2\u017f\u0180"+
"\7{\2\2\u0180$\3\2\2\2\u0181\u0182\7w\2\2\u0182\u0183\7d\2\2\u0183\u0184"+
"\7{\2\2\u0184\u0185\7v\2\2\u0185\u0186\7g\2\2\u0186&\3\2\2\2\u0187\u0188"+
"\7d\2\2\u0188\u0189\7{\2\2\u0189\u018a\7v\2\2\u018a\u018b\7g\2\2\u018b"+
"(\3\2\2\2\u018c\u018d\7w\2\2\u018d\u018e\7y\2\2\u018e\u018f\7q\2\2\u018f"+
"\u0190\7t\2\2\u0190\u0191\7f\2\2\u0191*\3\2\2\2\u0192\u0193\7y\2\2\u0193"+
"\u0194\7q\2\2\u0194\u0195\7t\2\2\u0195\u0196\7f\2\2\u0196,\3\2\2\2\u0197"+
"\u0198\7h\2\2\u0198\u0199\7n\2\2\u0199\u019a\7q\2\2\u019a\u019b\7c\2\2"+
"\u019b\u019c\7v\2\2\u019c.\3\2\2\2\u019d\u019e\7u\2\2\u019e\u019f\7v\2"+
"\2\u019f\u01a0\7t\2\2\u01a0\60\3\2\2\2\u01a1\u01a2\7u\2\2\u01a2\u01a3"+
"\7v\2\2\u01a3\u01a4\7t\2\2\u01a4\u01a5\7a\2\2\u01a5\u01a6\7r\2\2\u01a6"+
"\62\3\2\2\2\u01a7\u01a8\7u\2\2\u01a8\u01a9\7v\2\2\u01a9\u01aa\7t\2\2\u01aa"+
"\u01ab\7a\2\2\u01ab\u01ac\7u\2\2\u01ac\64\3\2\2\2\u01ad\u01ae\7u\2\2\u01ae"+
"\u01af\7v\2\2\u01af\u01b0\7t\2\2\u01b0\u01b1\7a\2\2\u01b1\u01b2\7r\2\2"+
"\u01b2\u01b3\7u\2\2\u01b3\66\3\2\2\2\u01b4\u01b5\7]\2\2\u01b58\3\2\2\2"+
"\u01b6\u01b7\7_\2\2\u01b7:\3\2\2\2\u01b8\u01b9\7-\2\2\u01b9\u01ba\7?\2"+
"\2\u01ba<\3\2\2\2\u01bb\u01bc\7/\2\2\u01bc\u01bd\7?\2\2\u01bd>\3\2\2\2"+
"\u01be\u01bf\7\61\2\2\u01bf\u01c0\7?\2\2\u01c0@\3\2\2\2\u01c1\u01c2\7"+
"\61\2\2\u01c2\u01c3\7\61\2\2\u01c3\u01c4\7?\2\2\u01c4B\3\2\2\2\u01c5\u01c6"+
"\7,\2\2\u01c6\u01c7\7?\2\2\u01c7D\3\2\2\2\u01c8\u01c9\7,\2\2\u01c9\u01ca"+
"\7,\2\2\u01ca\u01cb\7?\2\2\u01cbF\3\2\2\2\u01cc\u01cd\7(\2\2\u01cd\u01ce"+
"\7?\2\2\u01ceH\3\2\2\2\u01cf\u01d0\7~\2\2\u01d0\u01d1\7?\2\2\u01d1J\3"+
"\2\2\2\u01d2\u01d3\7`\2\2\u01d3\u01d4\7?\2\2\u01d4L\3\2\2\2\u01d5\u01d6"+
"\7\'\2\2\u01d6\u01d7\7?\2\2\u01d7N\3\2\2\2\u01d8\u01d9\7>\2\2\u01d9\u01da"+
"\7>\2\2\u01da\u01db\7?\2\2\u01dbP\3\2\2\2\u01dc\u01dd\7@\2\2\u01dd\u01de"+
"\7@\2\2\u01de\u01df\7?\2\2\u01dfR\3\2\2\2\u01e0\u01e1\7-\2\2\u01e1\u01e2"+
"\7-\2\2\u01e2T\3\2\2\2\u01e3\u01e4\7/\2\2\u01e4\u01e5\7/\2\2\u01e5V\3"+
"\2\2\2\u01e6\u01e7\7-\2\2\u01e7X\3\2\2\2\u01e8\u01e9\7/\2\2\u01e9Z\3\2"+
"\2\2\u01ea\u01eb\7,\2\2\u01eb\u01ec\7,\2\2\u01ec\\\3\2\2\2\u01ed\u01ee"+
"\7,\2\2\u01ee^\3\2\2\2\u01ef\u01f0\7\61\2\2\u01f0`\3\2\2\2\u01f1\u01f2"+
"\7\61\2\2\u01f2\u01f3\7\61\2\2\u01f3b\3\2\2\2\u01f4\u01f5\7\'\2\2\u01f5"+
"d\3\2\2\2\u01f6\u01f7\7>\2\2\u01f7\u01f8\7>\2\2\u01f8f\3\2\2\2\u01f9\u01fa"+
"\7@\2\2\u01fa\u01fb\7@\2\2\u01fbh\3\2\2\2\u01fc\u01fd\7>\2\2\u01fdj\3"+
"\2\2\2\u01fe\u01ff\7@\2\2\u01ffl\3\2\2\2\u0200\u0201\7>\2\2\u0201\u0202"+
"\7?\2\2\u0202n\3\2\2\2\u0203\u0204\7@\2\2\u0204\u0205\7?\2\2\u0205p\3"+
"\2\2\2\u0206\u0207\7?\2\2\u0207\u0208\7?\2\2\u0208r\3\2\2\2\u0209\u020a"+
"\7#\2\2\u020a\u020b\7?\2\2\u020bt\3\2\2\2\u020c\u020d\7(\2\2\u020dv\3"+
"\2\2\2\u020e\u020f\7`\2\2\u020fx\3\2\2\2\u0210\u0211\7~\2\2\u0211z\3\2"+
"\2\2\u0212\u0213\7v\2\2\u0213\u0214\7q\2\2\u0214|\3\2\2\2\u0215\u0216"+
"\7u\2\2\u0216\u0217\7v\2\2\u0217\u0218\7g\2\2\u0218\u0219\7r\2\2\u0219"+
"~\3\2\2\2\u021a\u021b\7c\2\2\u021b\u021c\7p\2\2\u021c\u021d\7f\2\2\u021d"+
"\u0080\3\2\2\2\u021e\u021f\7q\2\2\u021f\u0220\7t\2\2\u0220\u0082\3\2\2"+
"\2\u0221\u0222\7z\2\2\u0222\u0223\7q\2\2\u0223\u0224\7t\2\2\u0224\u0084"+
"\3\2\2\2\u0225\u0226\7p\2\2\u0226\u0227\7q\2\2\u0227\u0228\7v\2\2\u0228"+
"\u0086\3\2\2\2\u0229\u022a\7*\2\2\u022a\u0088\3\2\2\2\u022b\u022c\7+\2"+
"\2\u022c\u008a\3\2\2\2\u022d\u022e\7c\2\2\u022e\u022f\7u\2\2\u022f\u008c"+
"\3\2\2\2\u0230\u0231\7B\2\2\u0231\u008e\3\2\2\2\u0232\u0233\7t\2\2\u0233"+
"\u0234\7g\2\2\u0234\u0235\7v\2\2\u0235\u0236\7w\2\2\u0236\u0237\7t\2\2"+
"\u0237\u0238\7p\2\2\u0238\u0090\3\2\2\2\u0239\u023a\7d\2\2\u023a\u023b"+
"\7t\2\2\u023b\u023c\7g\2\2\u023c\u023d\7c\2\2\u023d\u023e\7m\2\2\u023e"+
"\u0092\3\2\2\2\u023f\u0240\7e\2\2\u0240\u0241\7q\2\2\u0241\u0242\7p\2"+
"\2\u0242\u0243\7v\2\2\u0243\u0244\7k\2\2\u0244\u0245\7p\2\2\u0245\u0246"+
"\7w\2\2\u0246\u0247\7g\2\2\u0247\u0094\3\2\2\2\u0248\u0249\7\60\2\2\u0249"+
"\u0096\3\2\2\2\u024a\u024b\7C\2\2\u024b\u0098\3\2\2\2\u024c\u024d\7Z\2"+
"\2\u024d\u009a\3\2\2\2\u024e\u024f\7[\2\2\u024f\u009c\3\2\2\2\u0250\u0251"+
"\7C\2\2\u0251\u0252\7Z\2\2\u0252\u009e\3\2\2\2\u0253\u0254\7C\2\2\u0254"+
"\u0255\7[\2\2\u0255\u00a0\3\2\2\2\u0256\u0257\7Z\2\2\u0257\u0258\7[\2"+
"\2\u0258\u00a2\3\2\2\2\u0259\u025a\7R\2\2\u025a\u025b\7e\2\2\u025b\u00a4"+
"\3\2\2\2\u025c\u025d\7R\2\2\u025d\u025e\7|\2\2\u025e\u00a6\3\2\2\2\u025f"+
"\u0260\7R\2\2\u0260\u0261\7p\2\2\u0261\u00a8\3\2\2\2\u0262\u0263\7R\2"+
"\2\u0263\u0264\7x\2\2\u0264\u00aa\3\2\2\2\u0265\u0266\7\60\2\2\u0266\u0267"+
"\7y\2\2\u0267\u00ac\3\2\2\2\u0268\u0269\7v\2\2\u0269\u026a\7t\2\2\u026a"+
"\u026b\7w\2\2\u026b\u026c\7g\2\2\u026c\u00ae\3\2\2\2\u026d\u026e\7h\2"+
"\2\u026e\u026f\7c\2\2\u026f\u0270\7n\2\2\u0270\u0271\7u\2\2\u0271\u0272"+
"\7g\2\2\u0272\u00b0\3\2\2\2\u0273\u0274\7\'\2\2\u0274\u0275\7c\2\2\u0275"+
"\u0276\7u\2\2\u0276\u0277\7o\2\2\u0277\u00b2\3\2\2\2\u0278\u0279\7u\2"+
"\2\u0279\u027a\7w\2\2\u027a\u027b\7d\2\2\u027b\u00b4\3\2\2\2\u027c\u027d"+
"\7/\2\2\u027d\u027e\7@\2\2\u027e\u00b6\3\2\2\2\u027f\u0280\7}\2\2\u0280"+
"\u00b8\3\2\2\2\u0281\u0282\7\177\2\2\u0282\u00ba\3\2\2\2\u0283\u0284\7"+
"c\2\2\u0284\u0285\7u\2\2\u0285\u0286\7o\2\2\u0286\u0287\7u\2\2\u0287\u0288"+
"\7w\2\2\u0288\u0289\7d\2\2\u0289\u00bc\3\2\2\2\u028a\u028b\7e\2\2\u028b"+
"\u028c\7n\2\2\u028c\u028d\7q\2\2\u028d\u028e\7d\2\2\u028e\u028f\7d\2\2"+
"\u028f\u0290\7g\2\2\u0290\u0291\7t\2\2\u0291\u0292\7u\2\2\u0292\u00be"+
"\3\2\2\2\u0293\u0294\7u\2\2\u0294\u0295\7v\2\2\u0295\u0296\7c\2\2\u0296"+
"\u0297\7e\2\2\u0297\u0298\7m\2\2\u0298\u00c0\3\2\2\2\u0299\u029a\7k\2"+
"\2\u029a\u029b\7h\2\2\u029b\u00c2\3\2\2\2\u029c\u029d\7g\2\2\u029d\u029e"+
"\7n\2\2\u029e\u029f\7u\2\2\u029f\u02a0\7g\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\7e\2\2"+
"\u02a5\u02a6\7u\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\7e\2\2\u02ab\u02ac\7e\2\2\u02ac"+
"\u00c8\3\2\2\2\u02ad\u02ae\7k\2\2\u02ae\u02af\7h\2\2\u02af\u02b0\7a\2"+
"\2\u02b0\u02b1\7g\2\2\u02b1\u02b2\7s\2\2\u02b2\u00ca\3\2\2\2\u02b3\u02b4"+
"\7k\2\2\u02b4\u02b5\7h\2\2\u02b5\u02b6\7a\2\2\u02b6\u02b7\7|\2\2\u02b7"+
"\u00cc\3\2\2\2\u02b8\u02b9\7k\2\2\u02b9\u02ba\7h\2\2\u02ba\u02bb\7a\2"+
"\2\u02bb\u02bc\7p\2\2\u02bc\u02bd\7g\2\2\u02bd\u00ce\3\2\2\2\u02be\u02bf"+
"\7k\2\2\u02bf\u02c0\7h\2\2\u02c0\u02c1\7a\2\2\u02c1\u02c2\7p\2\2\u02c2"+
"\u02c3\7|\2\2\u02c3\u00d0\3\2\2\2\u02c4\u02c5\7k\2\2\u02c5\u02c6\7h\2"+
"\2\u02c6\u02c7\7a\2\2\u02c7\u02c8\7r\2\2\u02c8\u02c9\7n\2\2\u02c9\u00d2"+
"\3\2\2\2\u02ca\u02cb\7k\2\2\u02cb\u02cc\7h\2\2\u02cc\u02cd\7a\2\2\u02cd"+
"\u02ce\7r\2\2\u02ce\u02cf\7q\2\2\u02cf\u02d0\7u\2\2\u02d0\u00d4\3\2\2"+
"\2\u02d1\u02d2\7k\2\2\u02d2\u02d3\7h\2\2\u02d3\u02d4\7a\2\2\u02d4\u02d5"+
"\7o\2\2\u02d5\u02d6\7k\2\2\u02d6\u00d6\3\2\2\2\u02d7\u02d8\7k\2\2\u02d8"+
"\u02d9\7h\2\2\u02d9\u02da\7a\2\2\u02da\u02db\7p\2\2\u02db\u02dc\7g\2\2"+
"\u02dc\u02dd\7i\2\2\u02dd\u00d8\3\2\2\2\u02de\u02df\7k\2\2\u02df\u02e0"+
"\7h\2\2\u02e0\u02e1\7a\2\2\u02e1\u02e2\7x\2\2\u02e2\u02e3\7u\2\2\u02e3"+
"\u00da\3\2\2\2\u02e4\u02e5\7k\2\2\u02e5\u02e6\7h\2\2\u02e6\u02e7\7a\2"+
"\2\u02e7\u02e8\7x\2\2\u02e8\u02e9\7e\2\2\u02e9\u00dc\3\2\2\2\u02ea\u02eb"+
"\7h\2\2\u02eb\u02ec\7q\2\2\u02ec\u02ed\7t\2\2\u02ed\u00de\3\2\2\2\u02ee"+
"\u02ef\7k\2\2\u02ef\u02f0\7p\2\2\u02f0\u00e0\3\2\2\2\u02f1\u02f2\7y\2"+
"\2\u02f2\u02f3\7j\2\2\u02f3\u02f4\7k\2\2\u02f4\u02f5\7n\2\2\u02f5\u02f6"+
"\7g\2\2\u02f6\u00e2\3\2\2\2\u02f7\u02f8\7t\2\2\u02f8\u02f9\7g\2\2\u02f9"+
"\u02fa\7r\2\2\u02fa\u02fb\7g\2\2\u02fb\u02fc\7c\2\2\u02fc\u02fd\7v\2\2"+
"\u02fd\u00e4\3\2\2\2\u02fe\u02ff\7w\2\2\u02ff\u0300\7p\2\2\u0300\u0301"+
"\7v\2\2\u0301\u0302\7k\2\2\u0302\u0303\7n\2\2\u0303\u00e6\3\2\2\2\u0304"+
"\u0308\t\2\2\2\u0305\u0307\t\3\2\2\u0306\u0305\3\2\2\2\u0307\u030a\3\2"+
"\2\2\u0308\u0306\3\2\2\2\u0308\u0309\3\2\2\2\u0309\u030b\3\2\2\2\u030a"+
"\u0308\3\2\2\2\u030b\u030c\5\u00e9u\2\u030c\u030d\3\2\2\2\u030d\u030e"+
"\bt\2\2\u030e\u00e8\3\2\2\2\u030f\u0313\7=\2\2\u0310\u0312\n\2\2\2\u0311"+
"\u0310\3\2\2\2\u0312\u0315\3\2\2\2\u0313\u0311\3\2\2\2\u0313\u0314\3\2"+
"\2\2\u0314\u0316\3\2\2\2\u0315\u0313\3\2\2\2\u0316\u0317\bu\2\2\u0317"+
"\u00ea\3\2\2\2\u0318\u0319\t\3\2\2\u0319\u031a\3\2\2\2\u031a\u031b\bv"+
"\3\2\u031b\u00ec\3\2\2\2\u031c\u031e\t\2\2\2\u031d\u031c\3\2\2\2\u031e"+
"\u031f\3\2\2\2\u031f\u031d\3\2\2\2\u031f\u0320\3\2\2\2\u0320\u00ee\3\2"+
"\2\2\u0321\u0325\t\4\2\2\u0322\u0324\t\5\2\2\u0323\u0322\3\2\2\2\u0324"+
"\u0327\3\2\2\2\u0325\u0323\3\2\2\2\u0325\u0326\3\2\2\2\u0326\u00f0\3\2"+
"\2\2\u0327\u0325\3\2\2\2\u0328\u0330\4\62;\2\u0329\u032b\4\63;\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\u0328\3\2\2\2\u032f"+
"\u0329\3\2\2\2\u0330\u00f2\3\2\2\2\u0331\u0333\7&\2\2\u0332\u0334\t\6"+
"\2\2\u0333\u0332\3\2\2\2\u0334\u0335\3\2\2\2\u0335\u0333\3\2\2\2\u0335"+
"\u0336\3\2\2\2\u0336\u00f4\3\2\2\2\u0337\u0339\7\'\2\2\u0338\u033a\4\62"+
"\63\2\u0339\u0338\3\2\2\2\u033a\u033b\3\2\2\2\u033b\u0339\3\2\2\2\u033b"+
"\u033c\3\2\2\2\u033c\u00f6\3\2\2\2\u033d\u0343\5\u00f9}\2\u033e\u0340"+
"\t\7\2\2\u033f\u0341\t\b\2\2\u0340\u033f\3\2\2\2\u0340\u0341\3\2\2\2\u0341"+
"\u0342\3\2\2\2\u0342\u0344\5\u00f9}\2\u0343\u033e\3\2\2\2\u0343\u0344"+
"\3\2\2\2\u0344\u00f8\3\2\2\2\u0345\u0347\4\62;\2\u0346\u0345\3\2\2\2\u0347"+
"\u0348\3\2\2\2\u0348\u0346\3\2\2\2\u0348\u0349\3\2\2\2\u0349\u0350\3\2"+
"\2\2\u034a\u034c\7\60\2\2\u034b\u034d\4\62;\2\u034c\u034b\3\2\2\2\u034d"+
"\u034e\3\2\2\2\u034e\u034c\3\2\2\2\u034e\u034f\3\2\2\2\u034f\u0351\3\2"+
"\2\2\u0350\u034a\3\2\2\2\u0350\u0351\3\2\2\2\u0351\u00fa\3\2\2\2\u0352"+
"\u0353\7^\2\2\u0353\u0357\13\2\2\2\u0354\u0355\7^\2\2\u0355\u0357\5\u00ed"+
"w\2\u0356\u0352\3\2\2\2\u0356\u0354\3\2\2\2\u0357\u00fc\3\2\2\2\u0358"+
"\u035d\7$\2\2\u0359\u035c\5\u00fb~\2\u035a\u035c\n\t\2\2\u035b\u0359\3"+
"\2\2\2\u035b\u035a\3\2\2\2\u035c\u035f\3\2\2\2\u035d\u035b\3\2\2\2\u035d"+
"\u035e\3\2\2\2\u035e\u0360\3\2\2\2\u035f\u035d\3\2\2\2\u0360\u0361\7$"+
"\2\2\u0361\u0362\b\177\4\2\u0362\u00fe\3\2\2\2\u0363\u0364\7}\2\2\u0364"+
"\u0365\7}\2\2\u0365\u0367\3\2\2\2\u0366\u0368\13\2\2\2\u0367\u0366\3\2"+
"\2\2\u0368\u0369\3\2\2\2\u0369\u036a\3\2\2\2\u0369\u0367\3\2\2\2\u036a"+
"\u036b\3\2\2\2\u036b\u036c\7\177\2\2\u036c\u036d\7\177\2\2\u036d\u036e"+
"\3\2\2\2\u036e\u036f\b\u0080\5\2\u036f\u0100\3\2\2\2\u0370\u0373\7)\2"+
"\2\u0371\u0374\5\u00fb~\2\u0372\u0374\n\t\2\2\u0373\u0371\3\2\2\2\u0373"+
"\u0372\3\2\2\2\u0374\u0375\3\2\2\2\u0375\u0376\7)\2\2\u0376\u0377\b\u0081"+
"\6\2\u0377\u0102\3\2\2\2\26\2\u0308\u0313\u031f\u0325\u032d\u032f\u0333"+
"\u0335\u033b\u0340\u0343\u0348\u034e\u0350\u0356\u035b\u035d\u0369\u0373"+
"\7\2\3\2\b\2\2\3\177\2\3\u0080\3\3\u0081\4";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

File diff suppressed because it is too large Load Diff

View File

@ -585,6 +585,12 @@ class StackVm(private var traceOutputFile: String?) {
checkDt(v, DataType.WORD)
evalstack.push(v.shr())
}
Opcode.SHIFTEDL_BYTE -> TODO()
Opcode.SHIFTEDL_WORD -> TODO()
Opcode.SHIFTEDR_UBYTE -> TODO()
Opcode.SHIFTEDR_SBYTE -> TODO()
Opcode.SHIFTEDR_UWORD -> TODO()
Opcode.SHIFTEDR_SWORD -> TODO()
Opcode.ROL_BYTE -> {
val v = evalstack.pop()
checkDt(v, DataType.UBYTE)

View File

@ -369,14 +369,15 @@ arithmetic: ``+`` ``-`` ``*`` ``/`` ``//`` ``**`` ``%``
Remainder is only supported on integer operands (not floats).
bitwise arithmetic: ``&`` ``|`` ``^`` ``~``
bitwise arithmetic: ``&`` ``|`` ``^`` ``~`` ``<<`` ``>>``
``&`` is bitwise and, ``|`` is bitwise or, ``^`` is bitwise xor, ``~`` is bitwise invert (this one is an unary operator)
``<<`` is bitwise left shift and ``>>`` is bitwise right shift (both will not change the datatype of the value)
assignment: ``=``
Sets the target on the LHS (left hand side) of the operator to the value of the expression on the RHS (right hand side).
Note that an assignment sometimes is not possible or supported.
augmented assignment: ``+=`` ``-=`` ``*=`` ``/=`` ``**=`` ``&=`` ``|=`` ``^=``
augmented assignment: ``+=`` ``-=`` ``*=`` ``/=`` ``**=`` ``&=`` ``|=`` ``^=`` ``<<=`` ``>>=``
Syntactic sugar; ``A += X`` is equivalent to ``A = A + X``
postfix increment and decrement: ``++`` ``--``