This commit is contained in:
Irmen de Jong 2018-08-16 23:10:28 +02:00
parent 4dc594a046
commit 26a7a3c8d0
20 changed files with 629 additions and 316 deletions

View File

@ -52,7 +52,7 @@ Directives
- type ``none`` : no launcher logic is added at all
.. data:: %zp <style>
.. data:: %zeropage <style>
Level: module.
Global setting, select ZeroPage handling style. Defaults to ``compatible``.

View File

@ -72,7 +72,7 @@ labeldef : identifier ':' ;
unconditionaljump : 'goto' (integerliteral | identifier | scoped_identifier) ;
directive :
directivename=('%output' | '%launcher' | '%zp' | '%address' | '%import' |
directivename=('%output' | '%launcher' | '%zeropage' | '%address' | '%import' |
'%breakpoint' | '%asminclude' | '%asmbinary' | '%option')
(directivearg? | directivearg (',' directivearg)*)
;
@ -120,11 +120,11 @@ expression :
| left = expression bop = '&' right = expression
| left = expression bop = '^' right = expression
| left = expression bop = '|' right = expression
| rangefrom = expression 'to' rangeto = expression // create separate rule once for-loops are here?
| left = expression bop = 'and' right = expression
| left = expression bop = 'or' right = expression
| left = expression bop = 'xor' right = expression
| prefix = 'not' expression
| rangefrom = expression 'to' rangeto = expression // create separate rule once for-loops are here?
| literalvalue
| register
| identifier

View File

@ -1,4 +1,4 @@
%zp full
%zeropage full
%address 33
%option enable_floats
%option enable_floats

View File

@ -1,4 +1,4 @@
%zp full
%zeropage full
%address 33
~ extra3 {

View File

@ -1,4 +1,12 @@
%output prg
%launcher basic
~ main $c003 {
A = X>2
X = Y>Y
word[1000] ascending = 10 to 1009
word[100] ascending2 = "a" to "z"
str ascending3 = "a" to "z"
@ -62,7 +70,7 @@
main.foo(1,2,3)
mega:
X=1
X += 1
cool:
Y=2

View File

@ -27,19 +27,26 @@ fun main(args: Array<String>) {
// determine special compiler options
val options = moduleAst.statements.filter { it is Directive && it.directive=="%option" }.flatMap { (it as Directive).args }.toSet()
val optionEnableFloats = options.contains(DirectiveArg(null, "enable_floats", null))
val outputType = (moduleAst.statements.singleOrNull { it is Directive && it.directive=="%output"}
as? Directive)?.args?.single()?.name?.toUpperCase()
val launcherType = (moduleAst.statements.singleOrNull { it is Directive && it.directive=="%launcher"}
as? Directive)?.args?.single()?.name?.toUpperCase()
val zpType = (moduleAst.statements.singleOrNull { it is Directive && it.directive=="%zeropage"}
as? Directive)?.args?.single()?.name?.toUpperCase()
val compilerOptions = CompilationOptions(OutputType.PRG,
Launcher.BASIC,
Zeropage.COMPATIBLE,
optionEnableFloats)
val intermediate = moduleAst.compileToIntermediate(compilerOptions, globalNamespaceAfterOptimize)
val compilerOptions = CompilationOptions(
if(outputType==null) OutputType.PRG else OutputType.valueOf(outputType),
if(launcherType==null) LauncherType.BASIC else LauncherType.valueOf(launcherType),
if(zpType==null) ZeropageType.COMPATIBLE else ZeropageType.valueOf(zpType),
options.contains(DirectiveArg(null, "enable_floats", null))
)
val compiler = Compiler(compilerOptions, globalNamespaceAfterOptimize)
val intermediate = compiler.compile(moduleAst)
intermediate.optimize()
// val assembler = intermediate.compileToAssembly()
// assembler.assemble(compilerOptions, "input", "output")
// val monitorfile = assembler.genereateBreakpointList()
// val monitorfile = assembler.generateBreakpointList()
// start the vice emulator
// val program = "foo"

View File

@ -698,7 +698,7 @@ fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) : Module
}
/************** Helper extesion methods (private) ************/
/************** Helper extension methods (private) ************/
private fun ParserRuleContext.toPosition(withPosition: Boolean) : Position? {
val file = Paths.get(this.start.inputStream.sourceName).fileName.toString()

View File

@ -19,6 +19,12 @@ fun Module.checkValid(globalNamespace: INameScope) {
}
/**
* todo check subroutine parameters against signature
* todo check subroutine return values against target assignment values
*
*/
class AstChecker(private val globalNamespace: INameScope) : IAstProcessor {
private val checkResult: MutableList<SyntaxError> = mutableListOf()
private val blockNames: HashMap<String, Position?> = hashMapOf()
@ -27,6 +33,17 @@ class AstChecker(private val globalNamespace: INameScope) : IAstProcessor {
return checkResult
}
override fun process(module: Module) {
super.process(module)
val directives = module.statements.filter { it is Directive }.groupBy { (it as Directive).directive }
directives.filter { it.value.size > 1 }.forEach{
when(it.key) {
"%output", "%launcher", "%zeropage", "%address" ->
it.value.mapTo(checkResult) { SyntaxError("directive can just occur once", it.position) }
}
}
}
override fun process(jump: Jump): IStatement {
super.process(jump)
if(jump.address!=null && (jump.address < 0 || jump.address > 65535))
@ -231,7 +248,7 @@ class AstChecker(private val globalNamespace: INameScope) : IAstProcessor {
if(directive.args.size!=1 || directive.args[0].name != "basic" && directive.args[0].name != "none")
err("invalid launcher directive type, expected basic or none")
}
"%zp" -> {
"%zeropage" -> {
if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 ||
directive.args[0].name != "compatible" &&

View File

@ -9,6 +9,7 @@ import il65.parser.ParsingFailedError
fun Module.checkImportedValid() {
val checker = ImportedAstChecker()
this.linkParents()
this.process(checker)
val result = checker.result()
result.forEach {
@ -33,9 +34,10 @@ class ImportedAstChecker : IAstProcessor {
super.process(module)
val newStatements : MutableList<IStatement> = mutableListOf()
val moduleLevelDirectives = listOf("%output", "%launcher", "%zp", "%address")
val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%address")
for (sourceStmt in module.statements) {
val stmt = sourceStmt.process(this)
if(stmt.parent == null) throw AstException("should have linked parents")
if(stmt is Directive && stmt.parent is Module) {
if(moduleLevelDirectives.contains(stmt.directive)) {
println("${stmt.position} Warning: ignoring module directive because it was imported: ${stmt.directive}")

View File

@ -5,14 +5,11 @@ import il65.ast.Module
import kotlin.system.exitProcess
fun Module.compileToIntermediate(options: CompilationOptions, namespace: INameScope): IntermediateForm {
val compiler = Compiler(options, namespace)
return compiler.compile(this)
}
class Compiler(val options: CompilationOptions, val namespace: INameScope) {
init {
val zeropage = Zeropage(options)
}
fun compile(module: Module) : IntermediateForm {
println("......@TODO compile Ast into Intermediate result......") // todo
return IntermediateForm(module.name)
@ -37,12 +34,12 @@ enum class OutputType {
PRG
}
enum class Launcher {
enum class LauncherType {
BASIC,
NONE
}
enum class Zeropage {
enum class ZeropageType {
COMPATIBLE,
FULL,
FULL_RESTORE
@ -50,8 +47,8 @@ enum class Zeropage {
data class CompilationOptions(val output: OutputType,
val launcher: Launcher,
val zeropage: Zeropage,
val launcher: LauncherType,
val zeropage: ZeropageType,
val floats: Boolean)

View File

@ -0,0 +1,107 @@
package il65.compiler
import il65.ast.DataType
import il65.ast.LiteralValue
import il65.ast.VarDecl
import il65.ast.VarDeclType
class Zeropage(private val options: CompilationOptions) {
companion object {
const val SCRATCH_B1 = 0x02
const val SCRATCH_B2 = 0x03
const val SCRATCH_W1 = 0xfb // $fb/$fc
const val SCRATCH_W2 = 0xfd // $fd/$fe
}
private val allocations = mutableMapOf<Int, Pair<String, DataType>>()
val free = mutableListOf<Int>()
init {
if(options.zeropage==ZeropageType.FULL || options.zeropage==ZeropageType.FULL_RESTORE) {
free.addAll(0x04 .. 0xfa)
free.add(0xff)
free.removeAll(listOf(0xa0, 0xa1, 0xa2, 0x91, 0xc0, 0xc5, 0xcb, 0xf5, 0xf6)) // these are updated by IRQ
} else {
// these are valid for the C-64 (when no RS232 I/O is performed):
// ($02, $03, $fb-$fc, $fd-$fe are reserved as scratch addresses for various routines)
free.addAll(listOf(0x04, 0x05, 0x06, 0x2a, 0x52, 0xf7, 0xf8, 0xf9, 0xfa))
}
assert(!free.contains(Zeropage.SCRATCH_B1))
assert(!free.contains(Zeropage.SCRATCH_B2))
assert(!free.contains(Zeropage.SCRATCH_W1))
assert(!free.contains(Zeropage.SCRATCH_W2))
}
fun available() = free.size
fun allocate(vardecl: VarDecl) : Int {
assert(vardecl.name.isEmpty() || !allocations.values.any { it.first==vardecl.name } ) {"same name can't be allocated twice"}
assert(vardecl.type==VarDeclType.VAR) {"can only allocate VAR type"}
val size =
if(vardecl.arrayspec!=null) {
println("${vardecl.position} warning: allocating a large value in zeropage")
val y = (vardecl.arrayspec.y as? LiteralValue)?.intvalue
if(y==null) {
// 1 dimensional array
when(vardecl.datatype) {
DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).intvalue!!
DataType.WORD -> (vardecl.arrayspec.x as LiteralValue).intvalue!! * 2
DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).intvalue!! * 5
else -> throw UnsupportedOperationException("array can only be of byte, word, float")
}
} else {
// 2 dimensional matrix (only bytes for now)
when(vardecl.datatype) {
DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).intvalue!! * y
else -> throw UnsupportedOperationException("matrix can only be of byte")
}
}
} else {
when (vardecl.datatype) {
DataType.BYTE -> 1
DataType.WORD -> 2
DataType.FLOAT -> {
if (options.floats) {
println("${vardecl.position} warning: allocating a large value in zeropage")
5
} else throw UnsupportedOperationException("floating point option not enabled")
}
else -> throw UnsupportedOperationException("cannot put datatype ${vardecl.datatype} in zeropage")
}
}
if(free.size > 0) {
if(size==1) {
for(candidate in free.min()!! .. free.max()!!+1) {
if(loneByte(candidate))
return makeAllocation(candidate, 1, vardecl.datatype, vardecl.name)
}
return makeAllocation(free[0], 1, vardecl.datatype, vardecl.name)
}
for(candidate in free.min()!! .. free.max()!!+1) {
if (sequentialFree(candidate, size))
return makeAllocation(candidate, size, vardecl.datatype, vardecl.name)
}
}
throw UnsupportedOperationException("ERROR: no free space in ZP to allocate $size sequential bytes")
}
private fun makeAllocation(location: Int, size: Int, datatype: DataType, name: String?): Int {
free.removeAll(location until location+size)
allocations[location] = Pair(name ?: "<unnamed>", datatype)
return location
}
private fun loneByte(location: Int): Boolean {
return free.contains(location) && !free.contains(location-1) && !free.contains(location+1)
}
private fun sequentialFree(location: Int, size: Int): Boolean {
return free.containsAll((location until location+size).toList())
}
}

View File

@ -31,6 +31,26 @@ fun Module.optimizeExpressions(globalNamespace: INameScope) {
}
/*
todo eliminate useless terms:
*0 -> constant 0
X*1, X/1, X//1 -> just X
X*-1 -> unary prefix -X
X**0 -> 1
X**1 -> X
X**-1 -> 1.0/X
X << 0 -> X
X | 0 -> X
x & 0 -> 0
X ^ 0 -> X
todo expression optimization: reduce expression nesting / flattening of parenthesis
todo expression optimization: simplify logical expression when a term makes it always true or false (1 or 0)
todo expression optimization: optimize some simple multiplications into shifts (A*8 -> A<<3, A/4 -> A>>2)
to
*/
class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcessor {
var optimizationsDone: Int = 0
var errors : MutableList<AstException> = mutableListOf()

View File

@ -17,6 +17,17 @@ fun Module.optimizeStatements(globalNamespace: INameScope) {
this.linkParents() // re-link in final configuration
}
/*
todo remove unused blocks and unused subroutines
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-- ,
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 into shifts (A*=8 -> A<<=3)
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 (as long as the value is a constant and the target not a MEMORY type!)
todo report more always true/always false conditions
*/
class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcessor {
var optimizationsDone: Int = 0

File diff suppressed because one or more lines are too long

View File

@ -101,7 +101,7 @@ INLINEASMBLOCK=98
'goto'=3
'%output'=4
'%launcher'=5
'%zp'=6
'%zeropage'=6
'%address'=7
'%import'=8
'%breakpoint'=9
@ -155,11 +155,11 @@ INLINEASMBLOCK=98
'&'=57
'^'=58
'|'=59
'and'=60
'or'=61
'xor'=62
'not'=63
'to'=64
'to'=60
'and'=61
'or'=62
'xor'=63
'not'=64
'return'=65
'.'=66
'A'=67

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
// Generated from /home/irmen/Projects/IL65/il65/antlr/il65.g4 by ANTLR 4.7
// Generated from il65.g4 by ANTLR 4.7.1
package il65.parser;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
@ -11,7 +11,7 @@ import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class il65Lexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
static { RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
@ -56,17 +56,17 @@ public class il65Lexer extends Lexer {
};
private static final String[] _LITERAL_NAMES = {
null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zp'", "'%address'",
"'%import'", "'%breakpoint'", "'%asminclude'", "'%asmbinary'", "'%option'",
"','", "'='", "'const'", "'memory'", "'byte'", "'word'", "'float'", "'str'",
"'str_p'", "'str_s'", "'str_ps'", "'['", "']'", "'+='", "'-='", "'/='",
"'*='", "'**='", "'<<='", "'>>='", "'<<@='", "'>>@='", "'&='", "'|='",
"'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'", "'*'", "'/'",
"'<<'", "'>>'", "'<<@'", "'>>@'", "'<'", "'>'", "'<='", "'>='", "'=='",
"'!='", "'&'", "'^'", "'|'", "'and'", "'or'", "'xor'", "'not'", "'to'",
"'return'", "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'Pc'",
"'Pi'", "'Pz'", "'Pn'", "'Pv'", "'true'", "'false'", "'%asm'", "'sub'",
"'->'", "'{'", "'}'", "'?'", "'if'", "'else'"
null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zeropage'",
"'%address'", "'%import'", "'%breakpoint'", "'%asminclude'", "'%asmbinary'",
"'%option'", "','", "'='", "'const'", "'memory'", "'byte'", "'word'",
"'float'", "'str'", "'str_p'", "'str_s'", "'str_ps'", "'['", "']'", "'+='",
"'-='", "'/='", "'*='", "'**='", "'<<='", "'>>='", "'<<@='", "'>>@='",
"'&='", "'|='", "'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'",
"'*'", "'/'", "'<<'", "'>>'", "'<<@'", "'>>@'", "'<'", "'>'", "'<='",
"'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'and'", "'or'",
"'xor'", "'not'", "'return'", "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'",
"'XY'", "'Pc'", "'Pi'", "'Pz'", "'Pn'", "'Pv'", "'true'", "'false'", "'%asm'",
"'sub'", "'->'", "'{'", "'}'", "'?'", "'if'", "'else'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, null, null, null, null, null, null,
@ -172,7 +172,7 @@ public class il65Lexer extends Lexer {
}
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2d\u0290\b\1\4\2\t"+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2d\u0296\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"+
@ -185,210 +185,212 @@ public class il65Lexer 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\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\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\n\3\n\3\n\3\n\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\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3"+
"\16\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3"+
"\21\3\21\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\26\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\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.\3/\3/\3\60\3\60\3\60\3\61\3\61\3\61\3"+
"\62\3\62\3\62\3\62\3\63\3\63\3\63\3\63\3\64\3\64\3\65\3\65\3\66\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\3B\3B\3B\3C\3C\3D"+
"\3D\3E\3E\3F\3F\3G\3G\3G\3H\3H\3H\3I\3I\3I\3J\3J\3J\3K\3K\3K\3L\3L\3L"+
"\3M\3M\3M\3N\3N\3N\3O\3O\3O\3O\3O\3P\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3R"+
"\3R\3R\3R\3S\3S\3S\3T\3T\3U\3U\3V\3V\3W\3W\3W\3X\3X\3X\3X\3X\3Y\3Y\7Y"+
"\u0227\nY\fY\16Y\u022a\13Y\3Y\3Y\3Y\3Y\3Z\3Z\7Z\u0232\nZ\fZ\16Z\u0235"+
"\13Z\3Z\3Z\3[\3[\3[\3[\3\\\6\\\u023e\n\\\r\\\16\\\u023f\3]\3]\7]\u0244"+
"\n]\f]\16]\u0247\13]\3^\3^\3^\6^\u024c\n^\r^\16^\u024d\5^\u0250\n^\3_"+
"\3_\6_\u0254\n_\r_\16_\u0255\3`\3`\6`\u025a\n`\r`\16`\u025b\3a\3a\3a\5"+
"a\u0261\na\3a\5a\u0264\na\3b\6b\u0267\nb\rb\16b\u0268\3b\3b\6b\u026d\n"+
"b\rb\16b\u026e\5b\u0271\nb\3c\3c\3c\3c\5c\u0277\nc\3d\3d\3d\7d\u027c\n"+
"d\fd\16d\u027f\13d\3d\3d\3d\3e\3e\3e\3e\6e\u0288\ne\re\16e\u0289\3e\3"+
"e\3e\3e\3e\3\u0289\2f\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\u00c3\2\u00c5"+
"\2\u00c7c\u00c9d\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\u029e\2\3\3\2"+
"\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17"+
"\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2"+
"\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3"+
"\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3"+
"\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2"+
"=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3"+
"\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2"+
"\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2"+
"c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3"+
"\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2"+
"\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3"+
"\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2"+
"\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097"+
"\3\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\u00c7\3\2\2"+
"\2\2\u00c9\3\2\2\2\3\u00cb\3\2\2\2\5\u00cd\3\2\2\2\7\u00cf\3\2\2\2\t\u00d4"+
"\3\2\2\2\13\u00dc\3\2\2\2\r\u00e6\3\2\2\2\17\u00ea\3\2\2\2\21\u00f3\3"+
"\2\2\2\23\u00fb\3\2\2\2\25\u0107\3\2\2\2\27\u0113\3\2\2\2\31\u011e\3\2"+
"\2\2\33\u0126\3\2\2\2\35\u0128\3\2\2\2\37\u012a\3\2\2\2!\u0130\3\2\2\2"+
"#\u0137\3\2\2\2%\u013c\3\2\2\2\'\u0141\3\2\2\2)\u0147\3\2\2\2+\u014b\3"+
"\2\2\2-\u0151\3\2\2\2/\u0157\3\2\2\2\61\u015e\3\2\2\2\63\u0160\3\2\2\2"+
"\65\u0162\3\2\2\2\67\u0165\3\2\2\29\u0168\3\2\2\2;\u016b\3\2\2\2=\u016e"+
"\3\2\2\2?\u0172\3\2\2\2A\u0176\3\2\2\2C\u017a\3\2\2\2E\u017f\3\2\2\2G"+
"\u0184\3\2\2\2I\u0187\3\2\2\2K\u018a\3\2\2\2M\u018d\3\2\2\2O\u0190\3\2"+
"\2\2Q\u0193\3\2\2\2S\u0195\3\2\2\2U\u0197\3\2\2\2W\u0199\3\2\2\2Y\u019b"+
"\3\2\2\2[\u019e\3\2\2\2]\u01a0\3\2\2\2_\u01a2\3\2\2\2a\u01a5\3\2\2\2c"+
"\u01a8\3\2\2\2e\u01ac\3\2\2\2g\u01b0\3\2\2\2i\u01b2\3\2\2\2k\u01b4\3\2"+
"\2\2m\u01b7\3\2\2\2o\u01ba\3\2\2\2q\u01bd\3\2\2\2s\u01c0\3\2\2\2u\u01c2"+
"\3\2\2\2w\u01c4\3\2\2\2y\u01c6\3\2\2\2{\u01ca\3\2\2\2}\u01cd\3\2\2\2\177"+
"\u01d1\3\2\2\2\u0081\u01d5\3\2\2\2\u0083\u01d8\3\2\2\2\u0085\u01df\3\2"+
"\2\2\u0087\u01e1\3\2\2\2\u0089\u01e3\3\2\2\2\u008b\u01e5\3\2\2\2\u008d"+
"\u01e7\3\2\2\2\u008f\u01ea\3\2\2\2\u0091\u01ed\3\2\2\2\u0093\u01f0\3\2"+
"\2\2\u0095\u01f3\3\2\2\2\u0097\u01f6\3\2\2\2\u0099\u01f9\3\2\2\2\u009b"+
"\u01fc\3\2\2\2\u009d\u01ff\3\2\2\2\u009f\u0204\3\2\2\2\u00a1\u020a\3\2"+
"\2\2\u00a3\u020f\3\2\2\2\u00a5\u0213\3\2\2\2\u00a7\u0216\3\2\2\2\u00a9"+
"\u0218\3\2\2\2\u00ab\u021a\3\2\2\2\u00ad\u021c\3\2\2\2\u00af\u021f\3\2"+
"\2\2\u00b1\u0224\3\2\2\2\u00b3\u022f\3\2\2\2\u00b5\u0238\3\2\2\2\u00b7"+
"\u023d\3\2\2\2\u00b9\u0241\3\2\2\2\u00bb\u024f\3\2\2\2\u00bd\u0251\3\2"+
"\2\2\u00bf\u0257\3\2\2\2\u00c1\u025d\3\2\2\2\u00c3\u0266\3\2\2\2\u00c5"+
"\u0276\3\2\2\2\u00c7\u0278\3\2\2\2\u00c9\u0283\3\2\2\2\u00cb\u00cc\7\u0080"+
"\2\2\u00cc\4\3\2\2\2\u00cd\u00ce\7<\2\2\u00ce\6\3\2\2\2\u00cf\u00d0\7"+
"i\2\2\u00d0\u00d1\7q\2\2\u00d1\u00d2\7v\2\2\u00d2\u00d3\7q\2\2\u00d3\b"+
"\3\2\2\2\u00d4\u00d5\7\'\2\2\u00d5\u00d6\7q\2\2\u00d6\u00d7\7w\2\2\u00d7"+
"\u00d8\7v\2\2\u00d8\u00d9\7r\2\2\u00d9\u00da\7w\2\2\u00da\u00db\7v\2\2"+
"\u00db\n\3\2\2\2\u00dc\u00dd\7\'\2\2\u00dd\u00de\7n\2\2\u00de\u00df\7"+
"c\2\2\u00df\u00e0\7w\2\2\u00e0\u00e1\7p\2\2\u00e1\u00e2\7e\2\2\u00e2\u00e3"+
"\7j\2\2\u00e3\u00e4\7g\2\2\u00e4\u00e5\7t\2\2\u00e5\f\3\2\2\2\u00e6\u00e7"+
"\7\'\2\2\u00e7\u00e8\7|\2\2\u00e8\u00e9\7r\2\2\u00e9\16\3\2\2\2\u00ea"+
"\u00eb\7\'\2\2\u00eb\u00ec\7c\2\2\u00ec\u00ed\7f\2\2\u00ed\u00ee\7f\2"+
"\2\u00ee\u00ef\7t\2\2\u00ef\u00f0\7g\2\2\u00f0\u00f1\7u\2\2\u00f1\u00f2"+
"\7u\2\2\u00f2\20\3\2\2\2\u00f3\u00f4\7\'\2\2\u00f4\u00f5\7k\2\2\u00f5"+
"\u00f6\7o\2\2\u00f6\u00f7\7r\2\2\u00f7\u00f8\7q\2\2\u00f8\u00f9\7t\2\2"+
"\u00f9\u00fa\7v\2\2\u00fa\22\3\2\2\2\u00fb\u00fc\7\'\2\2\u00fc\u00fd\7"+
"d\2\2\u00fd\u00fe\7t\2\2\u00fe\u00ff\7g\2\2\u00ff\u0100\7c\2\2\u0100\u0101"+
"\7m\2\2\u0101\u0102\7r\2\2\u0102\u0103\7q\2\2\u0103\u0104\7k\2\2\u0104"+
"\u0105\7p\2\2\u0105\u0106\7v\2\2\u0106\24\3\2\2\2\u0107\u0108\7\'\2\2"+
"\u0108\u0109\7c\2\2\u0109\u010a\7u\2\2\u010a\u010b\7o\2\2\u010b\u010c"+
"\7k\2\2\u010c\u010d\7p\2\2\u010d\u010e\7e\2\2\u010e\u010f\7n\2\2\u010f"+
"\u0110\7w\2\2\u0110\u0111\7f\2\2\u0111\u0112\7g\2\2\u0112\26\3\2\2\2\u0113"+
"\u0114\7\'\2\2\u0114\u0115\7c\2\2\u0115\u0116\7u\2\2\u0116\u0117\7o\2"+
"\2\u0117\u0118\7d\2\2\u0118\u0119\7k\2\2\u0119\u011a\7p\2\2\u011a\u011b"+
"\7c\2\2\u011b\u011c\7t\2\2\u011c\u011d\7{\2\2\u011d\30\3\2\2\2\u011e\u011f"+
"\7\'\2\2\u011f\u0120\7q\2\2\u0120\u0121\7r\2\2\u0121\u0122\7v\2\2\u0122"+
"\u0123\7k\2\2\u0123\u0124\7q\2\2\u0124\u0125\7p\2\2\u0125\32\3\2\2\2\u0126"+
"\u0127\7.\2\2\u0127\34\3\2\2\2\u0128\u0129\7?\2\2\u0129\36\3\2\2\2\u012a"+
"\u012b\7e\2\2\u012b\u012c\7q\2\2\u012c\u012d\7p\2\2\u012d\u012e\7u\2\2"+
"\u012e\u012f\7v\2\2\u012f \3\2\2\2\u0130\u0131\7o\2\2\u0131\u0132\7g\2"+
"\2\u0132\u0133\7o\2\2\u0133\u0134\7q\2\2\u0134\u0135\7t\2\2\u0135\u0136"+
"\7{\2\2\u0136\"\3\2\2\2\u0137\u0138\7d\2\2\u0138\u0139\7{\2\2\u0139\u013a"+
"\7v\2\2\u013a\u013b\7g\2\2\u013b$\3\2\2\2\u013c\u013d\7y\2\2\u013d\u013e"+
"\7q\2\2\u013e\u013f\7t\2\2\u013f\u0140\7f\2\2\u0140&\3\2\2\2\u0141\u0142"+
"\7h\2\2\u0142\u0143\7n\2\2\u0143\u0144\7q\2\2\u0144\u0145\7c\2\2\u0145"+
"\u0146\7v\2\2\u0146(\3\2\2\2\u0147\u0148\7u\2\2\u0148\u0149\7v\2\2\u0149"+
"\u014a\7t\2\2\u014a*\3\2\2\2\u014b\u014c\7u\2\2\u014c\u014d\7v\2\2\u014d"+
"\u014e\7t\2\2\u014e\u014f\7a\2\2\u014f\u0150\7r\2\2\u0150,\3\2\2\2\u0151"+
"\u0152\7u\2\2\u0152\u0153\7v\2\2\u0153\u0154\7t\2\2\u0154\u0155\7a\2\2"+
"\u0155\u0156\7u\2\2\u0156.\3\2\2\2\u0157\u0158\7u\2\2\u0158\u0159\7v\2"+
"\2\u0159\u015a\7t\2\2\u015a\u015b\7a\2\2\u015b\u015c\7r\2\2\u015c\u015d"+
"\7u\2\2\u015d\60\3\2\2\2\u015e\u015f\7]\2\2\u015f\62\3\2\2\2\u0160\u0161"+
"\7_\2\2\u0161\64\3\2\2\2\u0162\u0163\7-\2\2\u0163\u0164\7?\2\2\u0164\66"+
"\3\2\2\2\u0165\u0166\7/\2\2\u0166\u0167\7?\2\2\u01678\3\2\2\2\u0168\u0169"+
"\7\61\2\2\u0169\u016a\7?\2\2\u016a:\3\2\2\2\u016b\u016c\7,\2\2\u016c\u016d"+
"\7?\2\2\u016d<\3\2\2\2\u016e\u016f\7,\2\2\u016f\u0170\7,\2\2\u0170\u0171"+
"\7?\2\2\u0171>\3\2\2\2\u0172\u0173\7>\2\2\u0173\u0174\7>\2\2\u0174\u0175"+
"\7?\2\2\u0175@\3\2\2\2\u0176\u0177\7@\2\2\u0177\u0178\7@\2\2\u0178\u0179"+
"\7?\2\2\u0179B\3\2\2\2\u017a\u017b\7>\2\2\u017b\u017c\7>\2\2\u017c\u017d"+
"\7B\2\2\u017d\u017e\7?\2\2\u017eD\3\2\2\2\u017f\u0180\7@\2\2\u0180\u0181"+
"\7@\2\2\u0181\u0182\7B\2\2\u0182\u0183\7?\2\2\u0183F\3\2\2\2\u0184\u0185"+
"\7(\2\2\u0185\u0186\7?\2\2\u0186H\3\2\2\2\u0187\u0188\7~\2\2\u0188\u0189"+
"\7?\2\2\u0189J\3\2\2\2\u018a\u018b\7`\2\2\u018b\u018c\7?\2\2\u018cL\3"+
"\2\2\2\u018d\u018e\7-\2\2\u018e\u018f\7-\2\2\u018fN\3\2\2\2\u0190\u0191"+
"\7/\2\2\u0191\u0192\7/\2\2\u0192P\3\2\2\2\u0193\u0194\7*\2\2\u0194R\3"+
"\2\2\2\u0195\u0196\7+\2\2\u0196T\3\2\2\2\u0197\u0198\7-\2\2\u0198V\3\2"+
"\2\2\u0199\u019a\7/\2\2\u019aX\3\2\2\2\u019b\u019c\7,\2\2\u019c\u019d"+
"\7,\2\2\u019dZ\3\2\2\2\u019e\u019f\7,\2\2\u019f\\\3\2\2\2\u01a0\u01a1"+
"\7\61\2\2\u01a1^\3\2\2\2\u01a2\u01a3\7>\2\2\u01a3\u01a4\7>\2\2\u01a4`"+
"\3\2\2\2\u01a5\u01a6\7@\2\2\u01a6\u01a7\7@\2\2\u01a7b\3\2\2\2\u01a8\u01a9"+
"\7>\2\2\u01a9\u01aa\7>\2\2\u01aa\u01ab\7B\2\2\u01abd\3\2\2\2\u01ac\u01ad"+
"\7@\2\2\u01ad\u01ae\7@\2\2\u01ae\u01af\7B\2\2\u01aff\3\2\2\2\u01b0\u01b1"+
"\7>\2\2\u01b1h\3\2\2\2\u01b2\u01b3\7@\2\2\u01b3j\3\2\2\2\u01b4\u01b5\7"+
">\2\2\u01b5\u01b6\7?\2\2\u01b6l\3\2\2\2\u01b7\u01b8\7@\2\2\u01b8\u01b9"+
"\7?\2\2\u01b9n\3\2\2\2\u01ba\u01bb\7?\2\2\u01bb\u01bc\7?\2\2\u01bcp\3"+
"\2\2\2\u01bd\u01be\7#\2\2\u01be\u01bf\7?\2\2\u01bfr\3\2\2\2\u01c0\u01c1"+
"\7(\2\2\u01c1t\3\2\2\2\u01c2\u01c3\7`\2\2\u01c3v\3\2\2\2\u01c4\u01c5\7"+
"~\2\2\u01c5x\3\2\2\2\u01c6\u01c7\7c\2\2\u01c7\u01c8\7p\2\2\u01c8\u01c9"+
"\7f\2\2\u01c9z\3\2\2\2\u01ca\u01cb\7q\2\2\u01cb\u01cc\7t\2\2\u01cc|\3"+
"\2\2\2\u01cd\u01ce\7z\2\2\u01ce\u01cf\7q\2\2\u01cf\u01d0\7t\2\2\u01d0"+
"~\3\2\2\2\u01d1\u01d2\7p\2\2\u01d2\u01d3\7q\2\2\u01d3\u01d4\7v\2\2\u01d4"+
"\u0080\3\2\2\2\u01d5\u01d6\7v\2\2\u01d6\u01d7\7q\2\2\u01d7\u0082\3\2\2"+
"\2\u01d8\u01d9\7t\2\2\u01d9\u01da\7g\2\2\u01da\u01db\7v\2\2\u01db\u01dc"+
"\7w\2\2\u01dc\u01dd\7t\2\2\u01dd\u01de\7p\2\2\u01de\u0084\3\2\2\2\u01df"+
"\u01e0\7\60\2\2\u01e0\u0086\3\2\2\2\u01e1\u01e2\7C\2\2\u01e2\u0088\3\2"+
"\2\2\u01e3\u01e4\7Z\2\2\u01e4\u008a\3\2\2\2\u01e5\u01e6\7[\2\2\u01e6\u008c"+
"\3\2\2\2\u01e7\u01e8\7C\2\2\u01e8\u01e9\7Z\2\2\u01e9\u008e\3\2\2\2\u01ea"+
"\u01eb\7C\2\2\u01eb\u01ec\7[\2\2\u01ec\u0090\3\2\2\2\u01ed\u01ee\7Z\2"+
"\2\u01ee\u01ef\7[\2\2\u01ef\u0092\3\2\2\2\u01f0\u01f1\7R\2\2\u01f1\u01f2"+
"\7e\2\2\u01f2\u0094\3\2\2\2\u01f3\u01f4\7R\2\2\u01f4\u01f5\7k\2\2\u01f5"+
"\u0096\3\2\2\2\u01f6\u01f7\7R\2\2\u01f7\u01f8\7|\2\2\u01f8\u0098\3\2\2"+
"\2\u01f9\u01fa\7R\2\2\u01fa\u01fb\7p\2\2\u01fb\u009a\3\2\2\2\u01fc\u01fd"+
"\7R\2\2\u01fd\u01fe\7x\2\2\u01fe\u009c\3\2\2\2\u01ff\u0200\7v\2\2\u0200"+
"\u0201\7t\2\2\u0201\u0202\7w\2\2\u0202\u0203\7g\2\2\u0203\u009e\3\2\2"+
"\2\u0204\u0205\7h\2\2\u0205\u0206\7c\2\2\u0206\u0207\7n\2\2\u0207\u0208"+
"\7u\2\2\u0208\u0209\7g\2\2\u0209\u00a0\3\2\2\2\u020a\u020b\7\'\2\2\u020b"+
"\u020c\7c\2\2\u020c\u020d\7u\2\2\u020d\u020e\7o\2\2\u020e\u00a2\3\2\2"+
"\2\u020f\u0210\7u\2\2\u0210\u0211\7w\2\2\u0211\u0212\7d\2\2\u0212\u00a4"+
"\3\2\2\2\u0213\u0214\7/\2\2\u0214\u0215\7@\2\2\u0215\u00a6\3\2\2\2\u0216"+
"\u0217\7}\2\2\u0217\u00a8\3\2\2\2\u0218\u0219\7\177\2\2\u0219\u00aa\3"+
"\2\2\2\u021a\u021b\7A\2\2\u021b\u00ac\3\2\2\2\u021c\u021d\7k\2\2\u021d"+
"\u021e\7h\2\2\u021e\u00ae\3\2\2\2\u021f\u0220\7g\2\2\u0220\u0221\7n\2"+
"\2\u0221\u0222\7u\2\2\u0222\u0223\7g\2\2\u0223\u00b0\3\2\2\2\u0224\u0228"+
"\t\2\2\2\u0225\u0227\t\3\2\2\u0226\u0225\3\2\2\2\u0227\u022a\3\2\2\2\u0228"+
"\u0226\3\2\2\2\u0228\u0229\3\2\2\2\u0229\u022b\3\2\2\2\u022a\u0228\3\2"+
"\2\2\u022b\u022c\5\u00b3Z\2\u022c\u022d\3\2\2\2\u022d\u022e\bY\2\2\u022e"+
"\u00b2\3\2\2\2\u022f\u0233\7=\2\2\u0230\u0232\n\2\2\2\u0231\u0230\3\2"+
"\2\2\u0232\u0235\3\2\2\2\u0233\u0231\3\2\2\2\u0233\u0234\3\2\2\2\u0234"+
"\u0236\3\2\2\2\u0235\u0233\3\2\2\2\u0236\u0237\bZ\2\2\u0237\u00b4\3\2"+
"\2\2\u0238\u0239\t\3\2\2\u0239\u023a\3\2\2\2\u023a\u023b\b[\3\2\u023b"+
"\u00b6\3\2\2\2\u023c\u023e\t\2\2\2\u023d\u023c\3\2\2\2\u023e\u023f\3\2"+
"\2\2\u023f\u023d\3\2\2\2\u023f\u0240\3\2\2\2\u0240\u00b8\3\2\2\2\u0241"+
"\u0245\t\4\2\2\u0242\u0244\t\5\2\2\u0243\u0242\3\2\2\2\u0244\u0247\3\2"+
"\2\2\u0245\u0243\3\2\2\2\u0245\u0246\3\2\2\2\u0246\u00ba\3\2\2\2\u0247"+
"\u0245\3\2\2\2\u0248\u0250\4\62;\2\u0249\u024b\4\63;\2\u024a\u024c\4\62"+
";\2\u024b\u024a\3\2\2\2\u024c\u024d\3\2\2\2\u024d\u024b\3\2\2\2\u024d"+
"\u024e\3\2\2\2\u024e\u0250\3\2\2\2\u024f\u0248\3\2\2\2\u024f\u0249\3\2"+
"\2\2\u0250\u00bc\3\2\2\2\u0251\u0253\7&\2\2\u0252\u0254\t\6\2\2\u0253"+
"\u0252\3\2\2\2\u0254\u0255\3\2\2\2\u0255\u0253\3\2\2\2\u0255\u0256\3\2"+
"\2\2\u0256\u00be\3\2\2\2\u0257\u0259\7\'\2\2\u0258\u025a\4\62\63\2\u0259"+
"\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\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\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\r\3\r\3\r\3\r\3"+
"\r\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21"+
"\3\21\3\21\3\21\3\21\3\21\3\21\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\26\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\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.\3/\3/\3\60\3\60\3"+
"\60\3\61\3\61\3\61\3\62\3\62\3\62\3\62\3\63\3\63\3\63\3\63\3\64\3\64\3"+
"\65\3\65\3\66\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@\3A\3A\3A\3A\3B\3B\3B\3"+
"B\3B\3B\3B\3C\3C\3D\3D\3E\3E\3F\3F\3G\3G\3G\3H\3H\3H\3I\3I\3I\3J\3J\3"+
"J\3K\3K\3K\3L\3L\3L\3M\3M\3M\3N\3N\3N\3O\3O\3O\3O\3O\3P\3P\3P\3P\3P\3"+
"P\3Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3S\3S\3S\3T\3T\3U\3U\3V\3V\3W\3W\3W\3X\3"+
"X\3X\3X\3X\3Y\3Y\7Y\u022d\nY\fY\16Y\u0230\13Y\3Y\3Y\3Y\3Y\3Z\3Z\7Z\u0238"+
"\nZ\fZ\16Z\u023b\13Z\3Z\3Z\3[\3[\3[\3[\3\\\6\\\u0244\n\\\r\\\16\\\u0245"+
"\3]\3]\7]\u024a\n]\f]\16]\u024d\13]\3^\3^\3^\6^\u0252\n^\r^\16^\u0253"+
"\5^\u0256\n^\3_\3_\6_\u025a\n_\r_\16_\u025b\3`\3`\6`\u0260\n`\r`\16`\u0261"+
"\3a\3a\3a\5a\u0267\na\3a\5a\u026a\na\3b\6b\u026d\nb\rb\16b\u026e\3b\3"+
"b\6b\u0273\nb\rb\16b\u0274\5b\u0277\nb\3c\3c\3c\3c\5c\u027d\nc\3d\3d\3"+
"d\7d\u0282\nd\fd\16d\u0285\13d\3d\3d\3d\3e\3e\3e\3e\6e\u028e\ne\re\16"+
"e\u028f\3e\3e\3e\3e\3e\3\u028f\2f\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23"+
"\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31"+
"\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60"+
"_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085"+
"D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099"+
"N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00ad"+
"X\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1"+
"b\u00c3\2\u00c5\2\u00c7c\u00c9d\3\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2"+
"C\\aac|\6\2\62;C\\aac|\5\2\62;CHch\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2"+
"\u02a4\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\u00c7\3\2\2\2\2\u00c9\3\2\2\2\3\u00cb\3\2\2\2\5\u00cd\3\2\2\2\7\u00cf"+
"\3\2\2\2\t\u00d4\3\2\2\2\13\u00dc\3\2\2\2\r\u00e6\3\2\2\2\17\u00f0\3\2"+
"\2\2\21\u00f9\3\2\2\2\23\u0101\3\2\2\2\25\u010d\3\2\2\2\27\u0119\3\2\2"+
"\2\31\u0124\3\2\2\2\33\u012c\3\2\2\2\35\u012e\3\2\2\2\37\u0130\3\2\2\2"+
"!\u0136\3\2\2\2#\u013d\3\2\2\2%\u0142\3\2\2\2\'\u0147\3\2\2\2)\u014d\3"+
"\2\2\2+\u0151\3\2\2\2-\u0157\3\2\2\2/\u015d\3\2\2\2\61\u0164\3\2\2\2\63"+
"\u0166\3\2\2\2\65\u0168\3\2\2\2\67\u016b\3\2\2\29\u016e\3\2\2\2;\u0171"+
"\3\2\2\2=\u0174\3\2\2\2?\u0178\3\2\2\2A\u017c\3\2\2\2C\u0180\3\2\2\2E"+
"\u0185\3\2\2\2G\u018a\3\2\2\2I\u018d\3\2\2\2K\u0190\3\2\2\2M\u0193\3\2"+
"\2\2O\u0196\3\2\2\2Q\u0199\3\2\2\2S\u019b\3\2\2\2U\u019d\3\2\2\2W\u019f"+
"\3\2\2\2Y\u01a1\3\2\2\2[\u01a4\3\2\2\2]\u01a6\3\2\2\2_\u01a8\3\2\2\2a"+
"\u01ab\3\2\2\2c\u01ae\3\2\2\2e\u01b2\3\2\2\2g\u01b6\3\2\2\2i\u01b8\3\2"+
"\2\2k\u01ba\3\2\2\2m\u01bd\3\2\2\2o\u01c0\3\2\2\2q\u01c3\3\2\2\2s\u01c6"+
"\3\2\2\2u\u01c8\3\2\2\2w\u01ca\3\2\2\2y\u01cc\3\2\2\2{\u01cf\3\2\2\2}"+
"\u01d3\3\2\2\2\177\u01d6\3\2\2\2\u0081\u01da\3\2\2\2\u0083\u01de\3\2\2"+
"\2\u0085\u01e5\3\2\2\2\u0087\u01e7\3\2\2\2\u0089\u01e9\3\2\2\2\u008b\u01eb"+
"\3\2\2\2\u008d\u01ed\3\2\2\2\u008f\u01f0\3\2\2\2\u0091\u01f3\3\2\2\2\u0093"+
"\u01f6\3\2\2\2\u0095\u01f9\3\2\2\2\u0097\u01fc\3\2\2\2\u0099\u01ff\3\2"+
"\2\2\u009b\u0202\3\2\2\2\u009d\u0205\3\2\2\2\u009f\u020a\3\2\2\2\u00a1"+
"\u0210\3\2\2\2\u00a3\u0215\3\2\2\2\u00a5\u0219\3\2\2\2\u00a7\u021c\3\2"+
"\2\2\u00a9\u021e\3\2\2\2\u00ab\u0220\3\2\2\2\u00ad\u0222\3\2\2\2\u00af"+
"\u0225\3\2\2\2\u00b1\u022a\3\2\2\2\u00b3\u0235\3\2\2\2\u00b5\u023e\3\2"+
"\2\2\u00b7\u0243\3\2\2\2\u00b9\u0247\3\2\2\2\u00bb\u0255\3\2\2\2\u00bd"+
"\u0257\3\2\2\2\u00bf\u025d\3\2\2\2\u00c1\u0263\3\2\2\2\u00c3\u026c\3\2"+
"\2\2\u00c5\u027c\3\2\2\2\u00c7\u027e\3\2\2\2\u00c9\u0289\3\2\2\2\u00cb"+
"\u00cc\7\u0080\2\2\u00cc\4\3\2\2\2\u00cd\u00ce\7<\2\2\u00ce\6\3\2\2\2"+
"\u00cf\u00d0\7i\2\2\u00d0\u00d1\7q\2\2\u00d1\u00d2\7v\2\2\u00d2\u00d3"+
"\7q\2\2\u00d3\b\3\2\2\2\u00d4\u00d5\7\'\2\2\u00d5\u00d6\7q\2\2\u00d6\u00d7"+
"\7w\2\2\u00d7\u00d8\7v\2\2\u00d8\u00d9\7r\2\2\u00d9\u00da\7w\2\2\u00da"+
"\u00db\7v\2\2\u00db\n\3\2\2\2\u00dc\u00dd\7\'\2\2\u00dd\u00de\7n\2\2\u00de"+
"\u00df\7c\2\2\u00df\u00e0\7w\2\2\u00e0\u00e1\7p\2\2\u00e1\u00e2\7e\2\2"+
"\u00e2\u00e3\7j\2\2\u00e3\u00e4\7g\2\2\u00e4\u00e5\7t\2\2\u00e5\f\3\2"+
"\2\2\u00e6\u00e7\7\'\2\2\u00e7\u00e8\7|\2\2\u00e8\u00e9\7g\2\2\u00e9\u00ea"+
"\7t\2\2\u00ea\u00eb\7q\2\2\u00eb\u00ec\7r\2\2\u00ec\u00ed\7c\2\2\u00ed"+
"\u00ee\7i\2\2\u00ee\u00ef\7g\2\2\u00ef\16\3\2\2\2\u00f0\u00f1\7\'\2\2"+
"\u00f1\u00f2\7c\2\2\u00f2\u00f3\7f\2\2\u00f3\u00f4\7f\2\2\u00f4\u00f5"+
"\7t\2\2\u00f5\u00f6\7g\2\2\u00f6\u00f7\7u\2\2\u00f7\u00f8\7u\2\2\u00f8"+
"\20\3\2\2\2\u00f9\u00fa\7\'\2\2\u00fa\u00fb\7k\2\2\u00fb\u00fc\7o\2\2"+
"\u00fc\u00fd\7r\2\2\u00fd\u00fe\7q\2\2\u00fe\u00ff\7t\2\2\u00ff\u0100"+
"\7v\2\2\u0100\22\3\2\2\2\u0101\u0102\7\'\2\2\u0102\u0103\7d\2\2\u0103"+
"\u0104\7t\2\2\u0104\u0105\7g\2\2\u0105\u0106\7c\2\2\u0106\u0107\7m\2\2"+
"\u0107\u0108\7r\2\2\u0108\u0109\7q\2\2\u0109\u010a\7k\2\2\u010a\u010b"+
"\7p\2\2\u010b\u010c\7v\2\2\u010c\24\3\2\2\2\u010d\u010e\7\'\2\2\u010e"+
"\u010f\7c\2\2\u010f\u0110\7u\2\2\u0110\u0111\7o\2\2\u0111\u0112\7k\2\2"+
"\u0112\u0113\7p\2\2\u0113\u0114\7e\2\2\u0114\u0115\7n\2\2\u0115\u0116"+
"\7w\2\2\u0116\u0117\7f\2\2\u0117\u0118\7g\2\2\u0118\26\3\2\2\2\u0119\u011a"+
"\7\'\2\2\u011a\u011b\7c\2\2\u011b\u011c\7u\2\2\u011c\u011d\7o\2\2\u011d"+
"\u011e\7d\2\2\u011e\u011f\7k\2\2\u011f\u0120\7p\2\2\u0120\u0121\7c\2\2"+
"\u0121\u0122\7t\2\2\u0122\u0123\7{\2\2\u0123\30\3\2\2\2\u0124\u0125\7"+
"\'\2\2\u0125\u0126\7q\2\2\u0126\u0127\7r\2\2\u0127\u0128\7v\2\2\u0128"+
"\u0129\7k\2\2\u0129\u012a\7q\2\2\u012a\u012b\7p\2\2\u012b\32\3\2\2\2\u012c"+
"\u012d\7.\2\2\u012d\34\3\2\2\2\u012e\u012f\7?\2\2\u012f\36\3\2\2\2\u0130"+
"\u0131\7e\2\2\u0131\u0132\7q\2\2\u0132\u0133\7p\2\2\u0133\u0134\7u\2\2"+
"\u0134\u0135\7v\2\2\u0135 \3\2\2\2\u0136\u0137\7o\2\2\u0137\u0138\7g\2"+
"\2\u0138\u0139\7o\2\2\u0139\u013a\7q\2\2\u013a\u013b\7t\2\2\u013b\u013c"+
"\7{\2\2\u013c\"\3\2\2\2\u013d\u013e\7d\2\2\u013e\u013f\7{\2\2\u013f\u0140"+
"\7v\2\2\u0140\u0141\7g\2\2\u0141$\3\2\2\2\u0142\u0143\7y\2\2\u0143\u0144"+
"\7q\2\2\u0144\u0145\7t\2\2\u0145\u0146\7f\2\2\u0146&\3\2\2\2\u0147\u0148"+
"\7h\2\2\u0148\u0149\7n\2\2\u0149\u014a\7q\2\2\u014a\u014b\7c\2\2\u014b"+
"\u014c\7v\2\2\u014c(\3\2\2\2\u014d\u014e\7u\2\2\u014e\u014f\7v\2\2\u014f"+
"\u0150\7t\2\2\u0150*\3\2\2\2\u0151\u0152\7u\2\2\u0152\u0153\7v\2\2\u0153"+
"\u0154\7t\2\2\u0154\u0155\7a\2\2\u0155\u0156\7r\2\2\u0156,\3\2\2\2\u0157"+
"\u0158\7u\2\2\u0158\u0159\7v\2\2\u0159\u015a\7t\2\2\u015a\u015b\7a\2\2"+
"\u015b\u015c\7u\2\2\u015c.\3\2\2\2\u015d\u015e\7u\2\2\u015e\u015f\7v\2"+
"\2\u015f\u0160\7t\2\2\u0160\u0161\7a\2\2\u0161\u0162\7r\2\2\u0162\u0163"+
"\7u\2\2\u0163\60\3\2\2\2\u0164\u0165\7]\2\2\u0165\62\3\2\2\2\u0166\u0167"+
"\7_\2\2\u0167\64\3\2\2\2\u0168\u0169\7-\2\2\u0169\u016a\7?\2\2\u016a\66"+
"\3\2\2\2\u016b\u016c\7/\2\2\u016c\u016d\7?\2\2\u016d8\3\2\2\2\u016e\u016f"+
"\7\61\2\2\u016f\u0170\7?\2\2\u0170:\3\2\2\2\u0171\u0172\7,\2\2\u0172\u0173"+
"\7?\2\2\u0173<\3\2\2\2\u0174\u0175\7,\2\2\u0175\u0176\7,\2\2\u0176\u0177"+
"\7?\2\2\u0177>\3\2\2\2\u0178\u0179\7>\2\2\u0179\u017a\7>\2\2\u017a\u017b"+
"\7?\2\2\u017b@\3\2\2\2\u017c\u017d\7@\2\2\u017d\u017e\7@\2\2\u017e\u017f"+
"\7?\2\2\u017fB\3\2\2\2\u0180\u0181\7>\2\2\u0181\u0182\7>\2\2\u0182\u0183"+
"\7B\2\2\u0183\u0184\7?\2\2\u0184D\3\2\2\2\u0185\u0186\7@\2\2\u0186\u0187"+
"\7@\2\2\u0187\u0188\7B\2\2\u0188\u0189\7?\2\2\u0189F\3\2\2\2\u018a\u018b"+
"\7(\2\2\u018b\u018c\7?\2\2\u018cH\3\2\2\2\u018d\u018e\7~\2\2\u018e\u018f"+
"\7?\2\2\u018fJ\3\2\2\2\u0190\u0191\7`\2\2\u0191\u0192\7?\2\2\u0192L\3"+
"\2\2\2\u0193\u0194\7-\2\2\u0194\u0195\7-\2\2\u0195N\3\2\2\2\u0196\u0197"+
"\7/\2\2\u0197\u0198\7/\2\2\u0198P\3\2\2\2\u0199\u019a\7*\2\2\u019aR\3"+
"\2\2\2\u019b\u019c\7+\2\2\u019cT\3\2\2\2\u019d\u019e\7-\2\2\u019eV\3\2"+
"\2\2\u019f\u01a0\7/\2\2\u01a0X\3\2\2\2\u01a1\u01a2\7,\2\2\u01a2\u01a3"+
"\7,\2\2\u01a3Z\3\2\2\2\u01a4\u01a5\7,\2\2\u01a5\\\3\2\2\2\u01a6\u01a7"+
"\7\61\2\2\u01a7^\3\2\2\2\u01a8\u01a9\7>\2\2\u01a9\u01aa\7>\2\2\u01aa`"+
"\3\2\2\2\u01ab\u01ac\7@\2\2\u01ac\u01ad\7@\2\2\u01adb\3\2\2\2\u01ae\u01af"+
"\7>\2\2\u01af\u01b0\7>\2\2\u01b0\u01b1\7B\2\2\u01b1d\3\2\2\2\u01b2\u01b3"+
"\7@\2\2\u01b3\u01b4\7@\2\2\u01b4\u01b5\7B\2\2\u01b5f\3\2\2\2\u01b6\u01b7"+
"\7>\2\2\u01b7h\3\2\2\2\u01b8\u01b9\7@\2\2\u01b9j\3\2\2\2\u01ba\u01bb\7"+
">\2\2\u01bb\u01bc\7?\2\2\u01bcl\3\2\2\2\u01bd\u01be\7@\2\2\u01be\u01bf"+
"\7?\2\2\u01bfn\3\2\2\2\u01c0\u01c1\7?\2\2\u01c1\u01c2\7?\2\2\u01c2p\3"+
"\2\2\2\u01c3\u01c4\7#\2\2\u01c4\u01c5\7?\2\2\u01c5r\3\2\2\2\u01c6\u01c7"+
"\7(\2\2\u01c7t\3\2\2\2\u01c8\u01c9\7`\2\2\u01c9v\3\2\2\2\u01ca\u01cb\7"+
"~\2\2\u01cbx\3\2\2\2\u01cc\u01cd\7v\2\2\u01cd\u01ce\7q\2\2\u01cez\3\2"+
"\2\2\u01cf\u01d0\7c\2\2\u01d0\u01d1\7p\2\2\u01d1\u01d2\7f\2\2\u01d2|\3"+
"\2\2\2\u01d3\u01d4\7q\2\2\u01d4\u01d5\7t\2\2\u01d5~\3\2\2\2\u01d6\u01d7"+
"\7z\2\2\u01d7\u01d8\7q\2\2\u01d8\u01d9\7t\2\2\u01d9\u0080\3\2\2\2\u01da"+
"\u01db\7p\2\2\u01db\u01dc\7q\2\2\u01dc\u01dd\7v\2\2\u01dd\u0082\3\2\2"+
"\2\u01de\u01df\7t\2\2\u01df\u01e0\7g\2\2\u01e0\u01e1\7v\2\2\u01e1\u01e2"+
"\7w\2\2\u01e2\u01e3\7t\2\2\u01e3\u01e4\7p\2\2\u01e4\u0084\3\2\2\2\u01e5"+
"\u01e6\7\60\2\2\u01e6\u0086\3\2\2\2\u01e7\u01e8\7C\2\2\u01e8\u0088\3\2"+
"\2\2\u01e9\u01ea\7Z\2\2\u01ea\u008a\3\2\2\2\u01eb\u01ec\7[\2\2\u01ec\u008c"+
"\3\2\2\2\u01ed\u01ee\7C\2\2\u01ee\u01ef\7Z\2\2\u01ef\u008e\3\2\2\2\u01f0"+
"\u01f1\7C\2\2\u01f1\u01f2\7[\2\2\u01f2\u0090\3\2\2\2\u01f3\u01f4\7Z\2"+
"\2\u01f4\u01f5\7[\2\2\u01f5\u0092\3\2\2\2\u01f6\u01f7\7R\2\2\u01f7\u01f8"+
"\7e\2\2\u01f8\u0094\3\2\2\2\u01f9\u01fa\7R\2\2\u01fa\u01fb\7k\2\2\u01fb"+
"\u0096\3\2\2\2\u01fc\u01fd\7R\2\2\u01fd\u01fe\7|\2\2\u01fe\u0098\3\2\2"+
"\2\u01ff\u0200\7R\2\2\u0200\u0201\7p\2\2\u0201\u009a\3\2\2\2\u0202\u0203"+
"\7R\2\2\u0203\u0204\7x\2\2\u0204\u009c\3\2\2\2\u0205\u0206\7v\2\2\u0206"+
"\u0207\7t\2\2\u0207\u0208\7w\2\2\u0208\u0209\7g\2\2\u0209\u009e\3\2\2"+
"\2\u020a\u020b\7h\2\2\u020b\u020c\7c\2\2\u020c\u020d\7n\2\2\u020d\u020e"+
"\7u\2\2\u020e\u020f\7g\2\2\u020f\u00a0\3\2\2\2\u0210\u0211\7\'\2\2\u0211"+
"\u0212\7c\2\2\u0212\u0213\7u\2\2\u0213\u0214\7o\2\2\u0214\u00a2\3\2\2"+
"\2\u0215\u0216\7u\2\2\u0216\u0217\7w\2\2\u0217\u0218\7d\2\2\u0218\u00a4"+
"\3\2\2\2\u0219\u021a\7/\2\2\u021a\u021b\7@\2\2\u021b\u00a6\3\2\2\2\u021c"+
"\u021d\7}\2\2\u021d\u00a8\3\2\2\2\u021e\u021f\7\177\2\2\u021f\u00aa\3"+
"\2\2\2\u0220\u0221\7A\2\2\u0221\u00ac\3\2\2\2\u0222\u0223\7k\2\2\u0223"+
"\u0224\7h\2\2\u0224\u00ae\3\2\2\2\u0225\u0226\7g\2\2\u0226\u0227\7n\2"+
"\2\u0227\u0228\7u\2\2\u0228\u0229\7g\2\2\u0229\u00b0\3\2\2\2\u022a\u022e"+
"\t\2\2\2\u022b\u022d\t\3\2\2\u022c\u022b\3\2\2\2\u022d\u0230\3\2\2\2\u022e"+
"\u022c\3\2\2\2\u022e\u022f\3\2\2\2\u022f\u0231\3\2\2\2\u0230\u022e\3\2"+
"\2\2\u0231\u0232\5\u00b3Z\2\u0232\u0233\3\2\2\2\u0233\u0234\bY\2\2\u0234"+
"\u00b2\3\2\2\2\u0235\u0239\7=\2\2\u0236\u0238\n\2\2\2\u0237\u0236\3\2"+
"\2\2\u0238\u023b\3\2\2\2\u0239\u0237\3\2\2\2\u0239\u023a\3\2\2\2\u023a"+
"\u023c\3\2\2\2\u023b\u0239\3\2\2\2\u023c\u023d\bZ\2\2\u023d\u00b4\3\2"+
"\2\2\u023e\u023f\t\3\2\2\u023f\u0240\3\2\2\2\u0240\u0241\b[\3\2\u0241"+
"\u00b6\3\2\2\2\u0242\u0244\t\2\2\2\u0243\u0242\3\2\2\2\u0244\u0245\3\2"+
"\2\2\u0245\u0243\3\2\2\2\u0245\u0246\3\2\2\2\u0246\u00b8\3\2\2\2\u0247"+
"\u024b\t\4\2\2\u0248\u024a\t\5\2\2\u0249\u0248\3\2\2\2\u024a\u024d\3\2"+
"\2\2\u024b\u0249\3\2\2\2\u024b\u024c\3\2\2\2\u024c\u00ba\3\2\2\2\u024d"+
"\u024b\3\2\2\2\u024e\u0256\4\62;\2\u024f\u0251\4\63;\2\u0250\u0252\4\62"+
";\2\u0251\u0250\3\2\2\2\u0252\u0253\3\2\2\2\u0253\u0251\3\2\2\2\u0253"+
"\u0254\3\2\2\2\u0254\u0256\3\2\2\2\u0255\u024e\3\2\2\2\u0255\u024f\3\2"+
"\2\2\u0256\u00bc\3\2\2\2\u0257\u0259\7&\2\2\u0258\u025a\t\6\2\2\u0259"+
"\u0258\3\2\2\2\u025a\u025b\3\2\2\2\u025b\u0259\3\2\2\2\u025b\u025c\3\2"+
"\2\2\u025c\u00c0\3\2\2\2\u025d\u0263\5\u00c3b\2\u025e\u0260\t\7\2\2\u025f"+
"\u0261\t\b\2\2\u0260\u025f\3\2\2\2\u0260\u0261\3\2\2\2\u0261\u0262\3\2"+
"\2\2\u0262\u0264\5\u00c3b\2\u0263\u025e\3\2\2\2\u0263\u0264\3\2\2\2\u0264"+
"\u00c2\3\2\2\2\u0265\u0267\4\62;\2\u0266\u0265\3\2\2\2\u0267\u0268\3\2"+
"\2\2\u0268\u0266\3\2\2\2\u0268\u0269\3\2\2\2\u0269\u0270\3\2\2\2\u026a"+
"\u026c\7\60\2\2\u026b\u026d\4\62;\2\u026c\u026b\3\2\2\2\u026d\u026e\3"+
"\2\2\2\u026e\u026c\3\2\2\2\u026e\u026f\3\2\2\2\u026f\u0271\3\2\2\2\u0270"+
"\u026a\3\2\2\2\u0270\u0271\3\2\2\2\u0271\u00c4\3\2\2\2\u0272\u0273\7^"+
"\2\2\u0273\u0277\13\2\2\2\u0274\u0275\7^\2\2\u0275\u0277\5\u00b7\\\2\u0276"+
"\u0272\3\2\2\2\u0276\u0274\3\2\2\2\u0277\u00c6\3\2\2\2\u0278\u027d\7$"+
"\2\2\u0279\u027c\5\u00c5c\2\u027a\u027c\n\t\2\2\u027b\u0279\3\2\2\2\u027b"+
"\u027a\3\2\2\2\u027c\u027f\3\2\2\2\u027d\u027b\3\2\2\2\u027d\u027e\3\2"+
"\2\2\u027e\u0280\3\2\2\2\u027f\u027d\3\2\2\2\u0280\u0281\7$\2\2\u0281"+
"\u0282\bd\4\2\u0282\u00c8\3\2\2\2\u0283\u0284\7}\2\2\u0284\u0285\7}\2"+
"\2\u0285\u0287\3\2\2\2\u0286\u0288\13\2\2\2\u0287\u0286\3\2\2\2\u0288"+
"\u0289\3\2\2\2\u0289\u028a\3\2\2\2\u0289\u0287\3\2\2\2\u028a\u028b\3\2"+
"\2\2\u028b\u028c\7\177\2\2\u028c\u028d\7\177\2\2\u028d\u028e\3\2\2\2\u028e"+
"\u028f\be\5\2\u028f\u00ca\3\2\2\2\25\2\u0228\u0233\u023f\u0245\u024d\u024f"+
"\u0253\u0255\u025b\u0260\u0263\u0268\u026e\u0270\u0276\u027b\u027d\u0289"+
"\2\2\u025c\u00be\3\2\2\2\u025d\u025f\7\'\2\2\u025e\u0260\4\62\63\2\u025f"+
"\u025e\3\2\2\2\u0260\u0261\3\2\2\2\u0261\u025f\3\2\2\2\u0261\u0262\3\2"+
"\2\2\u0262\u00c0\3\2\2\2\u0263\u0269\5\u00c3b\2\u0264\u0266\t\7\2\2\u0265"+
"\u0267\t\b\2\2\u0266\u0265\3\2\2\2\u0266\u0267\3\2\2\2\u0267\u0268\3\2"+
"\2\2\u0268\u026a\5\u00c3b\2\u0269\u0264\3\2\2\2\u0269\u026a\3\2\2\2\u026a"+
"\u00c2\3\2\2\2\u026b\u026d\4\62;\2\u026c\u026b\3\2\2\2\u026d\u026e\3\2"+
"\2\2\u026e\u026c\3\2\2\2\u026e\u026f\3\2\2\2\u026f\u0276\3\2\2\2\u0270"+
"\u0272\7\60\2\2\u0271\u0273\4\62;\2\u0272\u0271\3\2\2\2\u0273\u0274\3"+
"\2\2\2\u0274\u0272\3\2\2\2\u0274\u0275\3\2\2\2\u0275\u0277\3\2\2\2\u0276"+
"\u0270\3\2\2\2\u0276\u0277\3\2\2\2\u0277\u00c4\3\2\2\2\u0278\u0279\7^"+
"\2\2\u0279\u027d\13\2\2\2\u027a\u027b\7^\2\2\u027b\u027d\5\u00b7\\\2\u027c"+
"\u0278\3\2\2\2\u027c\u027a\3\2\2\2\u027d\u00c6\3\2\2\2\u027e\u0283\7$"+
"\2\2\u027f\u0282\5\u00c5c\2\u0280\u0282\n\t\2\2\u0281\u027f\3\2\2\2\u0281"+
"\u0280\3\2\2\2\u0282\u0285\3\2\2\2\u0283\u0281\3\2\2\2\u0283\u0284\3\2"+
"\2\2\u0284\u0286\3\2\2\2\u0285\u0283\3\2\2\2\u0286\u0287\7$\2\2\u0287"+
"\u0288\bd\4\2\u0288\u00c8\3\2\2\2\u0289\u028a\7}\2\2\u028a\u028b\7}\2"+
"\2\u028b\u028d\3\2\2\2\u028c\u028e\13\2\2\2\u028d\u028c\3\2\2\2\u028e"+
"\u028f\3\2\2\2\u028f\u0290\3\2\2\2\u028f\u028d\3\2\2\2\u0290\u0291\3\2"+
"\2\2\u0291\u0292\7\177\2\2\u0292\u0293\7\177\2\2\u0293\u0294\3\2\2\2\u0294"+
"\u0295\be\5\2\u0295\u00ca\3\2\2\2\25\2\u022e\u0239\u0245\u024b\u0253\u0255"+
"\u0259\u025b\u0261\u0266\u0269\u026e\u0274\u0276\u027c\u0281\u0283\u028f"+
"\6\2\3\2\b\2\2\3d\2\3e\3";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());

View File

@ -101,7 +101,7 @@ INLINEASMBLOCK=98
'goto'=3
'%output'=4
'%launcher'=5
'%zp'=6
'%zeropage'=6
'%address'=7
'%import'=8
'%breakpoint'=9
@ -155,11 +155,11 @@ INLINEASMBLOCK=98
'&'=57
'^'=58
'|'=59
'and'=60
'or'=61
'xor'=62
'not'=63
'to'=64
'to'=60
'and'=61
'or'=62
'xor'=63
'not'=64
'return'=65
'.'=66
'A'=67

View File

@ -1,4 +1,4 @@
// Generated from /home/irmen/Projects/IL65/il65/antlr/il65.g4 by ANTLR 4.7
// Generated from il65.g4 by ANTLR 4.7.1
package il65.parser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
@ -11,7 +11,7 @@ import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class il65Parser extends Parser {
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
static { RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
@ -56,17 +56,17 @@ public class il65Parser extends Parser {
};
private static final String[] _LITERAL_NAMES = {
null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zp'", "'%address'",
"'%import'", "'%breakpoint'", "'%asminclude'", "'%asmbinary'", "'%option'",
"','", "'='", "'const'", "'memory'", "'byte'", "'word'", "'float'", "'str'",
"'str_p'", "'str_s'", "'str_ps'", "'['", "']'", "'+='", "'-='", "'/='",
"'*='", "'**='", "'<<='", "'>>='", "'<<@='", "'>>@='", "'&='", "'|='",
"'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'", "'*'", "'/'",
"'<<'", "'>>'", "'<<@'", "'>>@'", "'<'", "'>'", "'<='", "'>='", "'=='",
"'!='", "'&'", "'^'", "'|'", "'and'", "'or'", "'xor'", "'not'", "'to'",
"'return'", "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'Pc'",
"'Pi'", "'Pz'", "'Pn'", "'Pv'", "'true'", "'false'", "'%asm'", "'sub'",
"'->'", "'{'", "'}'", "'?'", "'if'", "'else'"
null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zeropage'",
"'%address'", "'%import'", "'%breakpoint'", "'%asminclude'", "'%asmbinary'",
"'%option'", "','", "'='", "'const'", "'memory'", "'byte'", "'word'",
"'float'", "'str'", "'str_p'", "'str_s'", "'str_ps'", "'['", "']'", "'+='",
"'-='", "'/='", "'*='", "'**='", "'<<='", "'>>='", "'<<@='", "'>>@='",
"'&='", "'|='", "'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'",
"'*'", "'/'", "'<<'", "'>>'", "'<<@'", "'>>@'", "'<'", "'>'", "'<='",
"'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'and'", "'or'",
"'xor'", "'not'", "'return'", "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'",
"'XY'", "'Pc'", "'Pi'", "'Pz'", "'Pn'", "'Pv'", "'true'", "'false'", "'%asm'",
"'sub'", "'->'", "'{'", "'}'", "'?'", "'if'", "'else'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, null, null, null, null, null, null,
@ -1274,9 +1274,9 @@ public class il65Parser extends Parser {
case 4:
{
setState(204);
((ExpressionContext)_localctx).prefix = match(T__62);
((ExpressionContext)_localctx).prefix = match(T__63);
setState(205);
expression(6);
expression(5);
}
break;
case 5:
@ -1490,15 +1490,15 @@ public class il65Parser extends Parser {
case 10:
{
_localctx = new ExpressionContext(_parentctx, _parentState);
_localctx.left = _prevctx;
_localctx.left = _prevctx;
_localctx.rangefrom = _prevctx;
_localctx.rangefrom = _prevctx;
pushNewRecursionContext(_localctx, _startState, RULE_expression);
setState(239);
if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
setState(240);
((ExpressionContext)_localctx).bop = match(T__59);
match(T__59);
setState(241);
((ExpressionContext)_localctx).right = expression(10);
((ExpressionContext)_localctx).rangeto = expression(10);
}
break;
case 11:
@ -1532,15 +1532,15 @@ public class il65Parser extends Parser {
case 13:
{
_localctx = new ExpressionContext(_parentctx, _parentState);
_localctx.rangefrom = _prevctx;
_localctx.rangefrom = _prevctx;
_localctx.left = _prevctx;
_localctx.left = _prevctx;
pushNewRecursionContext(_localctx, _startState, RULE_expression);
setState(248);
if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)");
if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
setState(249);
match(T__63);
((ExpressionContext)_localctx).bop = match(T__62);
setState(250);
((ExpressionContext)_localctx).rangeto = expression(6);
((ExpressionContext)_localctx).right = expression(7);
}
break;
case 14:
@ -1617,7 +1617,7 @@ public class il65Parser extends Parser {
setState(264);
_errHandler.sync(this);
_la = _input.LA(1);
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__23) | (1L << T__39) | (1L << T__41) | (1L << T__42) | (1L << T__62))) != 0) || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & ((1L << (T__66 - 67)) | (1L << (T__67 - 67)) | (1L << (T__68 - 67)) | (1L << (T__69 - 67)) | (1L << (T__70 - 67)) | (1L << (T__71 - 67)) | (1L << (T__72 - 67)) | (1L << (T__73 - 67)) | (1L << (T__74 - 67)) | (1L << (T__75 - 67)) | (1L << (T__76 - 67)) | (1L << (T__77 - 67)) | (1L << (T__78 - 67)) | (1L << (NAME - 67)) | (1L << (DEC_INTEGER - 67)) | (1L << (HEX_INTEGER - 67)) | (1L << (BIN_INTEGER - 67)) | (1L << (FLOAT_NUMBER - 67)) | (1L << (STRING - 67)))) != 0)) {
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__23) | (1L << T__39) | (1L << T__41) | (1L << T__42))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (T__63 - 64)) | (1L << (T__66 - 64)) | (1L << (T__67 - 64)) | (1L << (T__68 - 64)) | (1L << (T__69 - 64)) | (1L << (T__70 - 64)) | (1L << (T__71 - 64)) | (1L << (T__72 - 64)) | (1L << (T__73 - 64)) | (1L << (T__74 - 64)) | (1L << (T__75 - 64)) | (1L << (T__76 - 64)) | (1L << (T__77 - 64)) | (1L << (T__78 - 64)) | (1L << (NAME - 64)) | (1L << (DEC_INTEGER - 64)) | (1L << (HEX_INTEGER - 64)) | (1L << (BIN_INTEGER - 64)) | (1L << (FLOAT_NUMBER - 64)) | (1L << (STRING - 64)))) != 0)) {
{
setState(263);
expression_list();
@ -1683,7 +1683,7 @@ public class il65Parser extends Parser {
setState(274);
_errHandler.sync(this);
_la = _input.LA(1);
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__23) | (1L << T__39) | (1L << T__41) | (1L << T__42) | (1L << T__62))) != 0) || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & ((1L << (T__66 - 67)) | (1L << (T__67 - 67)) | (1L << (T__68 - 67)) | (1L << (T__69 - 67)) | (1L << (T__70 - 67)) | (1L << (T__71 - 67)) | (1L << (T__72 - 67)) | (1L << (T__73 - 67)) | (1L << (T__74 - 67)) | (1L << (T__75 - 67)) | (1L << (T__76 - 67)) | (1L << (T__77 - 67)) | (1L << (T__78 - 67)) | (1L << (NAME - 67)) | (1L << (DEC_INTEGER - 67)) | (1L << (HEX_INTEGER - 67)) | (1L << (BIN_INTEGER - 67)) | (1L << (FLOAT_NUMBER - 67)) | (1L << (STRING - 67)))) != 0)) {
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__23) | (1L << T__39) | (1L << T__41) | (1L << T__42))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (T__63 - 64)) | (1L << (T__66 - 64)) | (1L << (T__67 - 64)) | (1L << (T__68 - 64)) | (1L << (T__69 - 64)) | (1L << (T__70 - 64)) | (1L << (T__71 - 64)) | (1L << (T__72 - 64)) | (1L << (T__73 - 64)) | (1L << (T__74 - 64)) | (1L << (T__75 - 64)) | (1L << (T__76 - 64)) | (1L << (T__77 - 64)) | (1L << (T__78 - 64)) | (1L << (NAME - 64)) | (1L << (DEC_INTEGER - 64)) | (1L << (HEX_INTEGER - 64)) | (1L << (BIN_INTEGER - 64)) | (1L << (FLOAT_NUMBER - 64)) | (1L << (STRING - 64)))) != 0)) {
{
setState(273);
expression_list();
@ -2934,7 +2934,7 @@ public class il65Parser extends Parser {
case 11:
return precpred(_ctx, 7);
case 12:
return precpred(_ctx, 5);
return precpred(_ctx, 6);
case 13:
return precpred(_ctx, 21);
}
@ -3018,7 +3018,7 @@ public class il65Parser extends Parser {
"\u00c3\u00c4\5\"\22\2\u00c4\u00c5\t\5\2\2\u00c5%\3\2\2\2\u00c6\u00c7\b"+
"\24\1\2\u00c7\u00c8\7*\2\2\u00c8\u00c9\5&\24\2\u00c9\u00ca\7+\2\2\u00ca"+
"\u00d5\3\2\2\2\u00cb\u00d5\5(\25\2\u00cc\u00cd\t\6\2\2\u00cd\u00d5\5&"+
"\24\25\u00ce\u00cf\7A\2\2\u00cf\u00d5\5&\24\b\u00d0\u00d5\5@!\2\u00d1"+
"\24\25\u00ce\u00cf\7B\2\2\u00cf\u00d5\5&\24\7\u00d0\u00d5\5@!\2\u00d1"+
"\u00d5\5\64\33\2\u00d2\u00d5\5\60\31\2\u00d3\u00d5\5\62\32\2\u00d4\u00c6"+
"\3\2\2\2\u00d4\u00cb\3\2\2\2\u00d4\u00cc\3\2\2\2\u00d4\u00ce\3\2\2\2\u00d4"+
"\u00d0\3\2\2\2\u00d4\u00d1\3\2\2\2\u00d4\u00d2\3\2\2\2\u00d4\u00d3\3\2"+
@ -3032,8 +3032,8 @@ public class il65Parser extends Parser {
"\2\2\u00ed\u0100\5&\24\16\u00ee\u00ef\f\f\2\2\u00ef\u00f0\7=\2\2\u00f0"+
"\u0100\5&\24\r\u00f1\u00f2\f\13\2\2\u00f2\u00f3\7>\2\2\u00f3\u0100\5&"+
"\24\f\u00f4\u00f5\f\n\2\2\u00f5\u00f6\7?\2\2\u00f6\u0100\5&\24\13\u00f7"+
"\u00f8\f\t\2\2\u00f8\u00f9\7@\2\2\u00f9\u0100\5&\24\n\u00fa\u00fb\f\7"+
"\2\2\u00fb\u00fc\7B\2\2\u00fc\u0100\5&\24\b\u00fd\u00fe\f\27\2\2\u00fe"+
"\u00f8\f\t\2\2\u00f8\u00f9\7@\2\2\u00f9\u0100\5&\24\n\u00fa\u00fb\f\b"+
"\2\2\u00fb\u00fc\7A\2\2\u00fc\u0100\5&\24\t\u00fd\u00fe\f\27\2\2\u00fe"+
"\u0100\5\34\17\2\u00ff\u00d6\3\2\2\2\u00ff\u00d9\3\2\2\2\u00ff\u00dc\3"+
"\2\2\2\u00ff\u00df\3\2\2\2\u00ff\u00e2\3\2\2\2\u00ff\u00e5\3\2\2\2\u00ff"+
"\u00e8\3\2\2\2\u00ff\u00eb\3\2\2\2\u00ff\u00ee\3\2\2\2\u00ff\u00f1\3\2"+

View File

@ -1,21 +1,108 @@
package il65tests
package demo
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import org.hamcrest.CoreMatchers.`is` as Is
import il65.ast.DataType
import il65.ast.VarDecl
import il65.ast.VarDeclType
import il65.compiler.*
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import kotlin.test.assertFailsWith
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class TestSource {
class TestZeropage {
@Test
fun f() {
assertThat(2, Is(equalTo(2)))
fun testNames() {
val zp = Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.COMPATIBLE, false))
assertFailsWith<AssertionError> {
zp.allocate(VarDecl(VarDeclType.MEMORY, DataType.BYTE, null, "", null))
}
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "varname", null))
assertFailsWith<AssertionError> {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "varname", null))
}
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "varname2", null))
}
@Test
fun f2() {
assertThat(2, Is(equalTo(3)))
fun testZpFloatEnable() {
val zp = Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, false))
assertFailsWith<UnsupportedOperationException> {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null))
}
val zp2 = Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, true))
zp2.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null))
}
@Test
fun testCompatibleAllocation() {
val zp = Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.COMPATIBLE, true))
assert(zp.available() == 9)
assertFailsWith<UnsupportedOperationException> {
// in regular zp there aren't 5 sequential bytes free
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null))
}
for (i in 0 until zp.available()) {
val loc = zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null))
assert(loc > 0)
}
assert(zp.available() == 0)
assertFailsWith<UnsupportedOperationException> {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null))
}
assertFailsWith<UnsupportedOperationException> {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null))
}
}
@Test
fun testFullAllocation() {
val zp = Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, true))
assert(zp.available() == 239)
val loc = zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null))
assert(loc > 3)
assert(!zp.free.contains(loc))
val num = zp.available() / 5
val rest = zp.available() % 5
for(i in 0..num-4) {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null))
}
assert(zp.available() == 19)
assertFailsWith<UnsupportedOperationException> {
// can't allocate because no more sequential bytes, only fragmented
zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null))
}
for(i in 0..13) {
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null))
}
zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null))
zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null))
assert(zp.available() == 1)
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null))
assertFailsWith<UnsupportedOperationException> {
// no more space
zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null))
}
}
@Test
fun testEfficientAllocation() {
// free = [0x04, 0x05, 0x06, 0x2a, 0x52, 0xf7, 0xf8, 0xf9, 0xfa]
val zp = Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.COMPATIBLE, true))
assert(zp.available()==9)
assert(0x2a == zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null)))
assert(0x52 == zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null)))
assert(0x04 == zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null)))
assert(0xf7 == zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null)))
assert(0x06 == zp.allocate(VarDecl(VarDeclType.VAR, DataType.BYTE, null, "", null)))
assert(0xf9 == zp.allocate(VarDecl(VarDeclType.VAR, DataType.WORD, null, "", null)))
assert(zp.available()==0)
}
}