1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-02-17 10:30:43 +00:00

Implemented support for string and character escape codes \n \r \\ \" \'. Closes #241

This commit is contained in:
jespergravgaard 2019-08-18 16:43:15 +02:00
parent f08812ab91
commit 577e0f6011
25 changed files with 2377 additions and 313 deletions

View File

@ -34,15 +34,27 @@ public class AsmFormat {
} else if(value instanceof ConstantChar) {
ConstantChar constantChar = (ConstantChar) value;
if(!ConstantString.Encoding.SCREENCODE_MIXED.equals(constantChar.getEncoding())) {
// Current KickAsm does not support encoded literal chars
// Manually convert literal chars in non-standard encodings
CharToPetsciiConverter.setCurrentEncoding(constantChar.getEncoding().name);
byte converted = CharToPetsciiConverter.convertOrChar(constantChar.getChar(), true);
return getAsmNumber(new Long(converted));
} else {
return "'" + constantChar.getValue() + "'";
String escapedChar = ConstantChar.asciiToCharEscape(((ConstantChar) value).getChar());
if(escapedChar.length()>1) {
// Currently KickAss does not support escaped characters - so instead we must output the number value instead
CharToPetsciiConverter.setCurrentEncoding(constantChar.getEncoding().name);
byte converted = CharToPetsciiConverter.convertOrChar(constantChar.getChar(), true);
return getAsmNumber(new Long(converted));
} else {
return "'" + escapedChar + "'";
}
}
} else if(value instanceof ConstantString) {
return "\"" + ((ConstantString) value).getValue() + "\"";
String stringValue = ((ConstantString) value).getValue();
String escapedString = ConstantString.asciiToStringEscape(stringValue);
boolean hasEscape = !stringValue.equals(escapedString);
return (hasEscape?"@":"")+"\"" + escapedString + "\"";
} else if(value instanceof ConstantUnary) {
ConstantUnary unary = (ConstantUnary) value;
Operator operator = unary.getOperator();

View File

@ -1,5 +1,7 @@
package dk.camelot64.kickc.model.values;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
@ -45,12 +47,63 @@ public class ConstantChar implements ConstantLiteral<Character> {
@Override
public String toString(Program program) {
String enc = (encoding.equals(ConstantString.Encoding.SCREENCODE_MIXED))?"":encoding.suffix;
String enc = (encoding.equals(ConstantString.Encoding.SCREENCODE_MIXED)) ? "" : encoding.suffix;
if(program == null) {
return "'" + value + "'"+enc;
return "'" + value + "'" + enc;
} else {
return "(" + SymbolType.BYTE.getTypeName() + ") " + "'" + value + "'"+enc;
return "(" + SymbolType.BYTE.getTypeName() + ") " + "'" + value + "'" + enc;
}
}
/**
* Parses a potentially escaped char
*
* @param charString Either just a single char - or an escaped char using \-notation
* @return The ASCII char
*/
public static char charEscapeToAscii(String charString) {
if(charString.length() == 1) {
return charString.charAt(0);
} else if(charString.length() == 2) {
switch(charString.charAt(1)) {
case 'n':
return '\n';
case 'r':
return '\r';
case 'f':
return '\f';
case '"':
return '\"';
case '\'':
return '\'';
default:
throw new CompileError("Illegal char escape sequence \\" + charString.charAt(1));
}
} else {
throw new InternalError("Illegal char '" + charString + "'");
}
}
/**
* Converts a char to an escape sequence if needed. If not needed the char itself is returned.
* @param aChar The char
* @return The char itself - or the appropriate escape sequence
*/
public static String asciiToCharEscape(char aChar) {
switch(aChar) {
case '\n':
return "\\n";
case '\r':
return "\\r";
case '\f':
return "\\f";
case '\'':
return "\\'";
default:
return Character.toString(aChar);
}
}
}

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc.model.values;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
@ -11,13 +12,13 @@ import java.util.Objects;
*/
public class ConstantString implements ConstantLiteral<String> {
/** String encoding. */
public static enum Encoding {
PETSCII_MIXED("petscii_mixed", "pm"),
PETSCII_UPPER("petscii_upper", "pu"),
SCREENCODE_MIXED("screencode_mixed", "sm"),
SCREENCODE_UPPER("screencode_upper", "su")
;
SCREENCODE_UPPER("screencode_upper", "su");
public final String name;
public final String suffix;
@ -73,12 +74,12 @@ public class ConstantString implements ConstantLiteral<String> {
@Override
public String toString(Program program) {
String suffix = (encoding.equals(Encoding.SCREENCODE_MIXED))?"":encoding.suffix;
suffix += zeroTerminated?"":"z";
String suffix = (encoding.equals(Encoding.SCREENCODE_MIXED)) ? "" : encoding.suffix;
suffix += zeroTerminated ? "" : "z";
if(program == null) {
return "\"" + value + "\""+suffix;
return "\"" + value + "\"" + suffix;
} else {
return "(" + SymbolType.STRING.getTypeName() + ") "+"\"" + value + "\""+suffix;
return "(" + SymbolType.STRING.getTypeName() + ") " + "\"" + value + "\"" + suffix;
}
}
@ -96,4 +97,82 @@ public class ConstantString implements ConstantLiteral<String> {
public int hashCode() {
return Objects.hash(value, encoding, zeroTerminated);
}
/**
* Find any string escape sequences and convert them to the ASCII-equivalent character
*
* @param stringValue The string to convert
* @return The string where any escape sequence has been converted to ASCII
* @throws CompileError If the string value has a syntax error (unfinished or illegal escape sequences)
*/
public static String stringEscapeToAscii(String stringValue) {
StringBuilder stringResult = new StringBuilder();
char[] stringChars = stringValue.toCharArray();
int i = 0;
while(i < stringChars.length) {
// State: Normal - examine whether an escape is starting
char stringChar = stringChars[i];
if(stringChar == '\\') {
// Escape started - handle it!
i++;
if(i >= stringChars.length) throw new CompileError("Unfinished string escape sequence at end of string");
char escapeChar = stringChars[i];
switch(escapeChar) {
case 'n':
stringChar = '\n';
break;
case 'r':
stringChar = '\r';
break;
case 'f':
stringChar = '\f';
break;
case '"':
stringChar = '"';
break;
case '\'':
stringChar = '\'';
break;
default:
throw new CompileError("Illegal string escape sequence \\" + escapeChar);
}
}
// Output the char
stringResult.append(stringChar);
i++;
}
return stringResult.toString();
}
/**
* Find any ASCII character that must be escaped to represent the string in source code - and convert them to the escaped string.
*
* @param stringValue The string to convert
* @return The string where any character that must be escaped is converted to the escape sequence
*/
public static String asciiToStringEscape(String stringValue) {
StringBuilder stringResult = new StringBuilder();
char[] stringChars = stringValue.toCharArray();
for(char stringChar : stringChars) {
switch(stringChar) {
case '\n':
stringResult.append("\\n");
break;
case '\r':
stringResult.append("\\r");
break;
case '\f':
stringResult.append("\\f");
break;
case '"':
stringResult.append("\\\"");
break;
default:
stringResult.append(stringChar);
}
}
return stringResult.toString();
}
}

View File

@ -285,7 +285,7 @@ MNEMONIC:
KICKASM: '{{' .*? '}}';
SIMPLETYPE: 'byte' | 'word' | 'dword' | 'bool' | 'char' | 'short' | 'int' | 'long' | 'void' ;
STRING : '"' ('\\"' | ~'"')* '"' [z]?([ps][mu]?)?[z]?;
CHAR : '\'' ('\\\'' | ~'\'' ) '\'';
CHAR : '\'' ('\\'['"rfn] | ~'\'' ) '\'';
BOOLEAN : 'true' | 'false';
NUMBER : NUMFLOAT | NUMINT ;
NUMFLOAT : BINFLOAT | DECFLOAT | HEXFLOAT;

View File

@ -219,291 +219,291 @@ public class KickCLexer extends Lexer {
"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\u00dd\2\u00df\2\u00e1\2\u00e3"+
"p\u00e5\2\u00e7\2\u00e9q\u00ebr\u00eds\u00eft\3\2\22\3\2$$\3\2||\4\2r"+
"ruu\4\2ooww\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DDdd\3\2\62\63\3\2\62;\5\2"+
"\62;CHch\5\2C\\aac|\6\2\62;C\\aac|\4\2--//\6\2\13\f\17\17\"\"\u00a2\u00a2"+
"\4\2\f\f\17\17\2\u04fc\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\2"+
"Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3"+
"\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2"+
"\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2"+
"w\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\u00e3\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\3\u00f1\3\2\2\2\5\u00f8\3\2\2\2\7\u00fa\3\2\2\2\t\u0102\3\2\2"+
"\2\13\u0104\3\2\2\2\r\u0106\3\2\2\2\17\u0108\3\2\2\2\21\u010a\3\2\2\2"+
"\23\u010c\3\2\2\2\25\u010e\3\2\2\2\27\u0116\3\2\2\2\31\u011e\3\2\2\2\33"+
"\u0127\3\2\2\2\35\u012a\3\2\2\2\37\u012e\3\2\2\2!\u0135\3\2\2\2#\u013d"+
"\3\2\2\2%\u0142\3\2\2\2\'\u014b\3\2\2\2)\u0154\3\2\2\2+\u015d\3\2\2\2"+
"-\u0167\3\2\2\2/\u016d\3\2\2\2\61\u0174\3\2\2\2\63\u017b\3\2\2\2\65\u0181"+
"\3\2\2\2\67\u018a\3\2\2\29\u0191\3\2\2\2;\u019a\3\2\2\2=\u01a4\3\2\2\2"+
"?\u01a7\3\2\2\2A\u01ac\3\2\2\2C\u01b2\3\2\2\2E\u01b5\3\2\2\2G\u01b9\3"+
"\2\2\2I\u01c0\3\2\2\2K\u01c7\3\2\2\2M\u01cd\3\2\2\2O\u01d6\3\2\2\2Q\u01da"+
"\3\2\2\2S\u01e3\3\2\2\2U\u01e8\3\2\2\2W\u01ea\3\2\2\2Y\u01ed\3\2\2\2["+
"\u01f4\3\2\2\2]\u01fd\3\2\2\2_\u01ff\3\2\2\2a\u0201\3\2\2\2c\u0203\3\2"+
"\2\2e\u020a\3\2\2\2g\u020f\3\2\2\2i\u0211\3\2\2\2k\u0214\3\2\2\2m\u021b"+
"\3\2\2\2o\u0222\3\2\2\2q\u0225\3\2\2\2s\u0228\3\2\2\2u\u022a\3\2\2\2w"+
"\u022c\3\2\2\2y\u022e\3\2\2\2{\u0230\3\2\2\2}\u0232\3\2\2\2\177\u0235"+
"\3\2\2\2\u0081\u0238\3\2\2\2\u0083\u023a\3\2\2\2\u0085\u023c\3\2\2\2\u0087"+
"\u023e\3\2\2\2\u0089\u0240\3\2\2\2\u008b\u0243\3\2\2\2\u008d\u0246\3\2"+
"\2\2\u008f\u0249\3\2\2\2\u0091\u024c\3\2\2\2\u0093\u024e\3\2\2\2\u0095"+
"\u0250\3\2\2\2\u0097\u0253\3\2\2\2\u0099\u0256\3\2\2\2\u009b\u0258\3\2"+
"\2\2\u009d\u025b\3\2\2\2\u009f\u025e\3\2\2\2\u00a1\u0261\3\2\2\2\u00a3"+
"\u0264\3\2\2\2\u00a5\u0267\3\2\2\2\u00a7\u026b\3\2\2\2\u00a9\u026f\3\2"+
"\2\2\u00ab\u0272\3\2\2\2\u00ad\u0275\3\2\2\2\u00af\u0278\3\2\2\2\u00b1"+
"\u0280\3\2\2\2\u00b3\u0289\3\2\2\2\u00b5\u028e\3\2\2\2\u00b7\u0297\3\2"+
"\2\2\u00b9\u029d\3\2\2\2\u00bb\u02a4\3\2\2\2\u00bd\u02aa\3\2\2\2\u00bf"+
"\u038a\3\2\2\2\u00c1\u038c\3\2\2\2\u00c3\u03bd\3\2\2\2\u00c5\u03bf\3\2"+
"\2\2\u00c7\u03d5\3\2\2\2\u00c9\u03e6\3\2\2\2\u00cb\u03ea\3\2\2\2\u00cd"+
"\u03ef\3\2\2\2\u00cf\u03f6\3\2\2\2\u00d1\u0407\3\2\2\2\u00d3\u0415\3\2"+
"\2\2\u00d5\u0426\3\2\2\2\u00d7\u043a\3\2\2\2\u00d9\u043d\3\2\2\2\u00db"+
"\u0446\3\2\2\2\u00dd\u044d\3\2\2\2\u00df\u044f\3\2\2\2\u00e1\u0451\3\2"+
"\2\2\u00e3\u0453\3\2\2\2\u00e5\u045a\3\2\2\2\u00e7\u045c\3\2\2\2\u00e9"+
"\u045e\3\2\2\2\u00eb\u046b\3\2\2\2\u00ed\u0471\3\2\2\2\u00ef\u047c\3\2"+
"\2\2\u00f1\u00f2\7k\2\2\u00f2\u00f3\7o\2\2\u00f3\u00f4\7r\2\2\u00f4\u00f5"+
"\7q\2\2\u00f5\u00f6\7t\2\2\u00f6\u00f7\7v\2\2\u00f7\4\3\2\2\2\u00f8\u00f9"+
"\7=\2\2\u00f9\6\3\2\2\2\u00fa\u00fb\7v\2\2\u00fb\u00fc\7{\2\2\u00fc\u00fd"+
"\7r\2\2\u00fd\u00fe\7g\2\2\u00fe\u00ff\7f\2\2\u00ff\u0100\7g\2\2\u0100"+
"\u0101\7h\2\2\u0101\b\3\2\2\2\u0102\u0103\7.\2\2\u0103\n\3\2\2\2\u0104"+
"\u0105\7?\2\2\u0105\f\3\2\2\2\u0106\u0107\7*\2\2\u0107\16\3\2\2\2\u0108"+
"\u0109\7+\2\2\u0109\20\3\2\2\2\u010a\u010b\7}\2\2\u010b\22\3\2\2\2\u010c"+
"\u010d\7\177\2\2\u010d\24\3\2\2\2\u010e\u010f\7%\2\2\u010f\u0110\7r\2"+
"\2\u0110\u0111\7t\2\2\u0111\u0112\7c\2\2\u0112\u0113\7i\2\2\u0113\u0114"+
"\7o\2\2\u0114\u0115\7c\2\2\u0115\26\3\2\2\2\u0116\u0117\7t\2\2\u0117\u0118"+
"\7g\2\2\u0118\u0119\7u\2\2\u0119\u011a\7g\2\2\u011a\u011b\7t\2\2\u011b"+
"\u011c\7x\2\2\u011c\u011d\7g\2\2\u011d\30\3\2\2\2\u011e\u011f\7%\2\2\u011f"+
"\u0120\7t\2\2\u0120\u0121\7g\2\2\u0121\u0122\7u\2\2\u0122\u0123\7g\2\2"+
"\u0123\u0124\7t\2\2\u0124\u0125\7x\2\2\u0125\u0126\7g\2\2\u0126\32\3\2"+
"\2\2\u0127\u0128\7r\2\2\u0128\u0129\7e\2\2\u0129\34\3\2\2\2\u012a\u012b"+
"\7%\2\2\u012b\u012c\7r\2\2\u012c\u012d\7e\2\2\u012d\36\3\2\2\2\u012e\u012f"+
"\7v\2\2\u012f\u0130\7c\2\2\u0130\u0131\7t\2\2\u0131\u0132\7i\2\2\u0132"+
"\u0133\7g\2\2\u0133\u0134\7v\2\2\u0134 \3\2\2\2\u0135\u0136\7%\2\2\u0136"+
"\u0137\7v\2\2\u0137\u0138\7c\2\2\u0138\u0139\7t\2\2\u0139\u013a\7i\2\2"+
"\u013a\u013b\7g\2\2\u013b\u013c\7v\2\2\u013c\"\3\2\2\2\u013d\u013e\7n"+
"\2\2\u013e\u013f\7k\2\2\u013f\u0140\7p\2\2\u0140\u0141\7m\2\2\u0141$\3"+
"\2\2\2\u0142\u0143\7e\2\2\u0143\u0144\7q\2\2\u0144\u0145\7f\2\2\u0145"+
"\u0146\7g\2\2\u0146\u0147\7a\2\2\u0147\u0148\7u\2\2\u0148\u0149\7g\2\2"+
"\u0149\u014a\7i\2\2\u014a&\3\2\2\2\u014b\u014c\7f\2\2\u014c\u014d\7c\2"+
"\2\u014d\u014e\7v\2\2\u014e\u014f\7c\2\2\u014f\u0150\7a\2\2\u0150\u0151"+
"\7u\2\2\u0151\u0152\7g\2\2\u0152\u0153\7i\2\2\u0153(\3\2\2\2\u0154\u0155"+
"\7g\2\2\u0155\u0156\7p\2\2\u0156\u0157\7e\2\2\u0157\u0158\7q\2\2\u0158"+
"\u0159\7f\2\2\u0159\u015a\7k\2\2\u015a\u015b\7p\2\2\u015b\u015c\7i\2\2"+
"\u015c*\3\2\2\2\u015d\u015e\7%\2\2\u015e\u015f\7g\2\2\u015f\u0160\7p\2"+
"\2\u0160\u0161\7e\2\2\u0161\u0162\7q\2\2\u0162\u0163\7f\2\2\u0163\u0164"+
"\7k\2\2\u0164\u0165\7p\2\2\u0165\u0166\7i\2\2\u0166,\3\2\2\2\u0167\u0168"+
"\7e\2\2\u0168\u0169\7q\2\2\u0169\u016a\7p\2\2\u016a\u016b\7u\2\2\u016b"+
"\u016c\7v\2\2\u016c.\3\2\2\2\u016d\u016e\7g\2\2\u016e\u016f\7z\2\2\u016f"+
"\u0170\7v\2\2\u0170\u0171\7g\2\2\u0171\u0172\7t\2\2\u0172\u0173\7p\2\2"+
"\u0173\60\3\2\2\2\u0174\u0175\7g\2\2\u0175\u0176\7z\2\2\u0176\u0177\7"+
"r\2\2\u0177\u0178\7q\2\2\u0178\u0179\7t\2\2\u0179\u017a\7v\2\2\u017a\62"+
"\3\2\2\2\u017b\u017c\7c\2\2\u017c\u017d\7n\2\2\u017d\u017e\7k\2\2\u017e"+
"\u017f\7i\2\2\u017f\u0180\7p\2\2\u0180\64\3\2\2\2\u0181\u0182\7t\2\2\u0182"+
"\u0183\7g\2\2\u0183\u0184\7i\2\2\u0184\u0185\7k\2\2\u0185\u0186\7u\2\2"+
"\u0186\u0187\7v\2\2\u0187\u0188\7g\2\2\u0188\u0189\7t\2\2\u0189\66\3\2"+
"\2\2\u018a\u018b\7k\2\2\u018b\u018c\7p\2\2\u018c\u018d\7n\2\2\u018d\u018e"+
"\7k\2\2\u018e\u018f\7p\2\2\u018f\u0190\7g\2\2\u01908\3\2\2\2\u0191\u0192"+
"\7x\2\2\u0192\u0193\7q\2\2\u0193\u0194\7n\2\2\u0194\u0195\7c\2\2\u0195"+
"\u0196\7v\2\2\u0196\u0197\7k\2\2\u0197\u0198\7n\2\2\u0198\u0199\7g\2\2"+
"\u0199:\3\2\2\2\u019a\u019b\7k\2\2\u019b\u019c\7p\2\2\u019c\u019d\7v\2"+
"\2\u019d\u019e\7g\2\2\u019e\u019f\7t\2\2\u019f\u01a0\7t\2\2\u01a0\u01a1"+
"\7w\2\2\u01a1\u01a2\7r\2\2\u01a2\u01a3\7v\2\2\u01a3<\3\2\2\2\u01a4\u01a5"+
"\7k\2\2\u01a5\u01a6\7h\2\2\u01a6>\3\2\2\2\u01a7\u01a8\7g\2\2\u01a8\u01a9"+
"\7n\2\2\u01a9\u01aa\7u\2\2\u01aa\u01ab\7g\2\2\u01ab@\3\2\2\2\u01ac\u01ad"+
"\7y\2\2\u01ad\u01ae\7j\2\2\u01ae\u01af\7k\2\2\u01af\u01b0\7n\2\2\u01b0"+
"\u01b1\7g\2\2\u01b1B\3\2\2\2\u01b2\u01b3\7f\2\2\u01b3\u01b4\7q\2\2\u01b4"+
"D\3\2\2\2\u01b5\u01b6\7h\2\2\u01b6\u01b7\7q\2\2\u01b7\u01b8\7t\2\2\u01b8"+
"F\3\2\2\2\u01b9\u01ba\7u\2\2\u01ba\u01bb\7y\2\2\u01bb\u01bc\7k\2\2\u01bc"+
"\u01bd\7v\2\2\u01bd\u01be\7e\2\2\u01be\u01bf\7j\2\2\u01bfH\3\2\2\2\u01c0"+
"\u01c1\7t\2\2\u01c1\u01c2\7g\2\2\u01c2\u01c3\7v\2\2\u01c3\u01c4\7w\2\2"+
"\u01c4\u01c5\7t\2\2\u01c5\u01c6\7p\2\2\u01c6J\3\2\2\2\u01c7\u01c8\7d\2"+
"\2\u01c8\u01c9\7t\2\2\u01c9\u01ca\7g\2\2\u01ca\u01cb\7c\2\2\u01cb\u01cc"+
"\7m\2\2\u01ccL\3\2\2\2\u01cd\u01ce\7e\2\2\u01ce\u01cf\7q\2\2\u01cf\u01d0"+
"\7p\2\2\u01d0\u01d1\7v\2\2\u01d1\u01d2\7k\2\2\u01d2\u01d3\7p\2\2\u01d3"+
"\u01d4\7w\2\2\u01d4\u01d5\7g\2\2\u01d5N\3\2\2\2\u01d6\u01d7\7c\2\2\u01d7"+
"\u01d8\7u\2\2\u01d8\u01d9\7o\2\2\u01d9P\3\2\2\2\u01da\u01db\7f\2\2\u01db"+
"\u01dc\7g\2\2\u01dc\u01dd\7h\2\2\u01dd\u01de\7c\2\2\u01de\u01df\7w\2\2"+
"\u01df\u01e0\7n\2\2\u01e0\u01e1\7v\2\2\u01e1\u01e2\7<\2\2\u01e2R\3\2\2"+
"\2\u01e3\u01e4\7e\2\2\u01e4\u01e5\7c\2\2\u01e5\u01e6\7u\2\2\u01e6\u01e7"+
"\7g\2\2\u01e7T\3\2\2\2\u01e8\u01e9\7<\2\2\u01e9V\3\2\2\2\u01ea\u01eb\7"+
"\60\2\2\u01eb\u01ec\7\60\2\2\u01ecX\3\2\2\2\u01ed\u01ee\7u\2\2\u01ee\u01ef"+
"\7k\2\2\u01ef\u01f0\7i\2\2\u01f0\u01f1\7p\2\2\u01f1\u01f2\7g\2\2\u01f2"+
"\u01f3\7f\2\2\u01f3Z\3\2\2\2\u01f4\u01f5\7w\2\2\u01f5\u01f6\7p\2\2\u01f6"+
"\u01f7\7u\2\2\u01f7\u01f8\7k\2\2\u01f8\u01f9\7i\2\2\u01f9\u01fa\7p\2\2"+
"\u01fa\u01fb\7g\2\2\u01fb\u01fc\7f\2\2\u01fc\\\3\2\2\2\u01fd\u01fe\7,"+
"\2\2\u01fe^\3\2\2\2\u01ff\u0200\7]\2\2\u0200`\3\2\2\2\u0201\u0202\7_\2"+
"\2\u0202b\3\2\2\2\u0203\u0204\7u\2\2\u0204\u0205\7v\2\2\u0205\u0206\7"+
"t\2\2\u0206\u0207\7w\2\2\u0207\u0208\7e\2\2\u0208\u0209\7v\2\2\u0209d"+
"\3\2\2\2\u020a\u020b\7g\2\2\u020b\u020c\7p\2\2\u020c\u020d\7w\2\2\u020d"+
"\u020e\7o\2\2\u020ef\3\2\2\2\u020f\u0210\7\60\2\2\u0210h\3\2\2\2\u0211"+
"\u0212\7/\2\2\u0212\u0213\7@\2\2\u0213j\3\2\2\2\u0214\u0215\7u\2\2\u0215"+
"\u0216\7k\2\2\u0216\u0217\7|\2\2\u0217\u0218\7g\2\2\u0218\u0219\7q\2\2"+
"\u0219\u021a\7h\2\2\u021al\3\2\2\2\u021b\u021c\7v\2\2\u021c\u021d\7{\2"+
"\2\u021d\u021e\7r\2\2\u021e\u021f\7g\2\2\u021f\u0220\7k\2\2\u0220\u0221"+
"\7f\2\2\u0221n\3\2\2\2\u0222\u0223\7/\2\2\u0223\u0224\7/\2\2\u0224p\3"+
"\2\2\2\u0225\u0226\7-\2\2\u0226\u0227\7-\2\2\u0227r\3\2\2\2\u0228\u0229"+
"\7-\2\2\u0229t\3\2\2\2\u022a\u022b\7/\2\2\u022bv\3\2\2\2\u022c\u022d\7"+
"#\2\2\u022dx\3\2\2\2\u022e\u022f\7(\2\2\u022fz\3\2\2\2\u0230\u0231\7\u0080"+
"\2\2\u0231|\3\2\2\2\u0232\u0233\7@\2\2\u0233\u0234\7@\2\2\u0234~\3\2\2"+
"\2\u0235\u0236\7>\2\2\u0236\u0237\7>\2\2\u0237\u0080\3\2\2\2\u0238\u0239"+
"\7\61\2\2\u0239\u0082\3\2\2\2\u023a\u023b\7\'\2\2\u023b\u0084\3\2\2\2"+
"\u023c\u023d\7>\2\2\u023d\u0086\3\2\2\2\u023e\u023f\7@\2\2\u023f\u0088"+
"\3\2\2\2\u0240\u0241\7?\2\2\u0241\u0242\7?\2\2\u0242\u008a\3\2\2\2\u0243"+
"\u0244\7#\2\2\u0244\u0245\7?\2\2\u0245\u008c\3\2\2\2\u0246\u0247\7>\2"+
"\2\u0247\u0248\7?\2\2\u0248\u008e\3\2\2\2\u0249\u024a\7@\2\2\u024a\u024b"+
"\7?\2\2\u024b\u0090\3\2\2\2\u024c\u024d\7`\2\2\u024d\u0092\3\2\2\2\u024e"+
"\u024f\7~\2\2\u024f\u0094\3\2\2\2\u0250\u0251\7(\2\2\u0251\u0252\7(\2"+
"\2\u0252\u0096\3\2\2\2\u0253\u0254\7~\2\2\u0254\u0255\7~\2\2\u0255\u0098"+
"\3\2\2\2\u0256\u0257\7A\2\2\u0257\u009a\3\2\2\2\u0258\u0259\7-\2\2\u0259"+
"\u025a\7?\2\2\u025a\u009c\3\2\2\2\u025b\u025c\7/\2\2\u025c\u025d\7?\2"+
"\2\u025d\u009e\3\2\2\2\u025e\u025f\7,\2\2\u025f\u0260\7?\2\2\u0260\u00a0"+
"\3\2\2\2\u0261\u0262\7\61\2\2\u0262\u0263\7?\2\2\u0263\u00a2\3\2\2\2\u0264"+
"\u0265\7\'\2\2\u0265\u0266\7?\2\2\u0266\u00a4\3\2\2\2\u0267\u0268\7>\2"+
"\2\u0268\u0269\7>\2\2\u0269\u026a\7?\2\2\u026a\u00a6\3\2\2\2\u026b\u026c"+
"\7@\2\2\u026c\u026d\7@\2\2\u026d\u026e\7?\2\2\u026e\u00a8\3\2\2\2\u026f"+
"\u0270\7(\2\2\u0270\u0271\7?\2\2\u0271\u00aa\3\2\2\2\u0272\u0273\7~\2"+
"\2\u0273\u0274\7?\2\2\u0274\u00ac\3\2\2\2\u0275\u0276\7`\2\2\u0276\u0277"+
"\7?\2\2\u0277\u00ae\3\2\2\2\u0278\u0279\7m\2\2\u0279\u027a\7k\2\2\u027a"+
"\u027b\7e\2\2\u027b\u027c\7m\2\2\u027c\u027d\7c\2\2\u027d\u027e\7u\2\2"+
"\u027e\u027f\7o\2\2\u027f\u00b0\3\2\2\2\u0280\u0281\7t\2\2\u0281\u0282"+
"\7g\2\2\u0282\u0283\7u\2\2\u0283\u0284\7q\2\2\u0284\u0285\7w\2\2\u0285"+
"\u0286\7t\2\2\u0286\u0287\7e\2\2\u0287\u0288\7g\2\2\u0288\u00b2\3\2\2"+
"\2\u0289\u028a\7w\2\2\u028a\u028b\7u\2\2\u028b\u028c\7g\2\2\u028c\u028d"+
"\7u\2\2\u028d\u00b4\3\2\2\2\u028e\u028f\7e\2\2\u028f\u0290\7n\2\2\u0290"+
"\u0291\7q\2\2\u0291\u0292\7d\2\2\u0292\u0293\7d\2\2\u0293\u0294\7g\2\2"+
"\u0294\u0295\7t\2\2\u0295\u0296\7u\2\2\u0296\u00b6\3\2\2\2\u0297\u0298"+
"\7d\2\2\u0298\u0299\7{\2\2\u0299\u029a\7v\2\2\u029a\u029b\7g\2\2\u029b"+
"\u029c\7u\2\2\u029c\u00b8\3\2\2\2\u029d\u029e\7e\2\2\u029e\u029f\7{\2"+
"\2\u029f\u02a0\7e\2\2\u02a0\u02a1\7n\2\2\u02a1\u02a2\7g\2\2\u02a2\u02a3"+
"\7u\2\2\u02a3\u00ba\3\2\2\2\u02a4\u02a5\7\60\2\2\u02a5\u02a6\7d\2\2\u02a6"+
"\u02a7\7{\2\2\u02a7\u02a8\7v\2\2\u02a8\u02a9\7g\2\2\u02a9\u00bc\3\2\2"+
"\2\u02aa\u02ab\7%\2\2\u02ab\u00be\3\2\2\2\u02ac\u02ad\7d\2\2\u02ad\u02ae"+
"\7t\2\2\u02ae\u038b\7m\2\2\u02af\u02b0\7q\2\2\u02b0\u02b1\7t\2\2\u02b1"+
"\u038b\7c\2\2\u02b2\u02b3\7m\2\2\u02b3\u02b4\7k\2\2\u02b4\u038b\7n\2\2"+
"\u02b5\u02b6\7u\2\2\u02b6\u02b7\7n\2\2\u02b7\u038b\7q\2\2\u02b8\u02b9"+
"\7p\2\2\u02b9\u02ba\7q\2\2\u02ba\u038b\7r\2\2\u02bb\u02bc\7c\2\2\u02bc"+
"\u02bd\7u\2\2\u02bd\u038b\7n\2\2\u02be\u02bf\7r\2\2\u02bf\u02c0\7j\2\2"+
"\u02c0\u038b\7r\2\2\u02c1\u02c2\7c\2\2\u02c2\u02c3\7p\2\2\u02c3\u038b"+
"\7e\2\2\u02c4\u02c5\7d\2\2\u02c5\u02c6\7r\2\2\u02c6\u038b\7n\2\2\u02c7"+
"\u02c8\7e\2\2\u02c8\u02c9\7n\2\2\u02c9\u038b\7e\2\2\u02ca\u02cb\7l\2\2"+
"\u02cb\u02cc\7u\2\2\u02cc\u038b\7t\2\2\u02cd\u02ce\7c\2\2\u02ce\u02cf"+
"\7p\2\2\u02cf\u038b\7f\2\2\u02d0\u02d1\7t\2\2\u02d1\u02d2\7n\2\2\u02d2"+
"\u038b\7c\2\2\u02d3\u02d4\7d\2\2\u02d4\u02d5\7k\2\2\u02d5\u038b\7v\2\2"+
"\u02d6\u02d7\7t\2\2\u02d7\u02d8\7q\2\2\u02d8\u038b\7n\2\2\u02d9\u02da"+
"\7r\2\2\u02da\u02db\7n\2\2\u02db\u038b\7c\2\2\u02dc\u02dd\7r\2\2\u02dd"+
"\u02de\7n\2\2\u02de\u038b\7r\2\2\u02df\u02e0\7d\2\2\u02e0\u02e1\7o\2\2"+
"\u02e1\u038b\7k\2\2\u02e2\u02e3\7u\2\2\u02e3\u02e4\7g\2\2\u02e4\u038b"+
"\7e\2\2\u02e5\u02e6\7t\2\2\u02e6\u02e7\7v\2\2\u02e7\u038b\7k\2\2\u02e8"+
"\u02e9\7g\2\2\u02e9\u02ea\7q\2\2\u02ea\u038b\7t\2\2\u02eb\u02ec\7u\2\2"+
"\u02ec\u02ed\7t\2\2\u02ed\u038b\7g\2\2\u02ee\u02ef\7n\2\2\u02ef\u02f0"+
"\7u\2\2\u02f0\u038b\7t\2\2\u02f1\u02f2\7r\2\2\u02f2\u02f3\7j\2\2\u02f3"+
"\u038b\7c\2\2\u02f4\u02f5\7c\2\2\u02f5\u02f6\7n\2\2\u02f6\u038b\7t\2\2"+
"\u02f7\u02f8\7l\2\2\u02f8\u02f9\7o\2\2\u02f9\u038b\7r\2\2\u02fa\u02fb"+
"\7d\2\2\u02fb\u02fc\7x\2\2\u02fc\u038b\7e\2\2\u02fd\u02fe\7e\2\2\u02fe"+
"\u02ff\7n\2\2\u02ff\u038b\7k\2\2\u0300\u0301\7t\2\2\u0301\u0302\7v\2\2"+
"\u0302\u038b\7u\2\2\u0303\u0304\7c\2\2\u0304\u0305\7f\2\2\u0305\u038b"+
"\7e\2\2\u0306\u0307\7t\2\2\u0307\u0308\7t\2\2\u0308\u038b\7c\2\2\u0309"+
"\u030a\7d\2\2\u030a\u030b\7x\2\2\u030b\u038b\7u\2\2\u030c\u030d\7u\2\2"+
"\u030d\u030e\7g\2\2\u030e\u038b\7k\2\2\u030f\u0310\7u\2\2\u0310\u0311"+
"\7c\2\2\u0311\u038b\7z\2\2\u0312\u0313\7u\2\2\u0313\u0314\7v\2\2\u0314"+
"\u038b\7{\2\2\u0315\u0316\7u\2\2\u0316\u0317\7v\2\2\u0317\u038b\7c\2\2"+
"\u0318\u0319\7u\2\2\u0319\u031a\7v\2\2\u031a\u038b\7z\2\2\u031b\u031c"+
"\7f\2\2\u031c\u031d\7g\2\2\u031d\u038b\7{\2\2\u031e\u031f\7v\2\2\u031f"+
"\u0320\7z\2\2\u0320\u038b\7c\2\2\u0321\u0322\7z\2\2\u0322\u0323\7c\2\2"+
"\u0323\u038b\7c\2\2\u0324\u0325\7d\2\2\u0325\u0326\7e\2\2\u0326\u038b"+
"\7e\2\2\u0327\u0328\7c\2\2\u0328\u0329\7j\2\2\u0329\u038b\7z\2\2\u032a"+
"\u032b\7v\2\2\u032b\u032c\7{\2\2\u032c\u038b\7c\2\2\u032d\u032e\7v\2\2"+
"\u032e\u032f\7z\2\2\u032f\u038b\7u\2\2\u0330\u0331\7v\2\2\u0331\u0332"+
"\7c\2\2\u0332\u038b\7u\2\2\u0333\u0334\7u\2\2\u0334\u0335\7j\2\2\u0335"+
"\u038b\7{\2\2\u0336\u0337\7u\2\2\u0337\u0338\7j\2\2\u0338\u038b\7z\2\2"+
"\u0339\u033a\7n\2\2\u033a\u033b\7f\2\2\u033b\u038b\7{\2\2\u033c\u033d"+
"\7n\2\2\u033d\u033e\7f\2\2\u033e\u038b\7c\2\2\u033f\u0340\7n\2\2\u0340"+
"\u0341\7f\2\2\u0341\u038b\7z\2\2\u0342\u0343\7n\2\2\u0343\u0344\7c\2\2"+
"\u0344\u038b\7z\2\2\u0345\u0346\7v\2\2\u0346\u0347\7c\2\2\u0347\u038b"+
"\7{\2\2\u0348\u0349\7v\2\2\u0349\u034a\7c\2\2\u034a\u038b\7z\2\2\u034b"+
"\u034c\7d\2\2\u034c\u034d\7e\2\2\u034d\u038b\7u\2\2\u034e\u034f\7e\2\2"+
"\u034f\u0350\7n\2\2\u0350\u038b\7x\2\2\u0351\u0352\7v\2\2\u0352\u0353"+
"\7u\2\2\u0353\u038b\7z\2\2\u0354\u0355\7n\2\2\u0355\u0356\7c\2\2\u0356"+
"\u038b\7u\2\2\u0357\u0358\7e\2\2\u0358\u0359\7r\2\2\u0359\u038b\7{\2\2"+
"\u035a\u035b\7e\2\2\u035b\u035c\7o\2\2\u035c\u038b\7r\2\2\u035d\u035e"+
"\7e\2\2\u035e\u035f\7r\2\2\u035f\u038b\7z\2\2\u0360\u0361\7f\2\2\u0361"+
"\u0362\7e\2\2\u0362\u038b\7r\2\2\u0363\u0364\7f\2\2\u0364\u0365\7g\2\2"+
"\u0365\u038b\7e\2\2\u0366\u0367\7k\2\2\u0367\u0368\7p\2\2\u0368\u038b"+
"\7e\2\2\u0369\u036a\7c\2\2\u036a\u036b\7z\2\2\u036b\u038b\7u\2\2\u036c"+
"\u036d\7d\2\2\u036d\u036e\7p\2\2\u036e\u038b\7g\2\2\u036f\u0370\7e\2\2"+
"\u0370\u0371\7n\2\2\u0371\u038b\7f\2\2\u0372\u0373\7u\2\2\u0373\u0374"+
"\7d\2\2\u0374\u038b\7e\2\2\u0375\u0376\7k\2\2\u0376\u0377\7u\2\2\u0377"+
"\u038b\7e\2\2\u0378\u0379\7k\2\2\u0379\u037a\7p\2\2\u037a\u038b\7z\2\2"+
"\u037b\u037c\7d\2\2\u037c\u037d\7g\2\2\u037d\u038b\7s\2\2\u037e\u037f"+
"\7u\2\2\u037f\u0380\7g\2\2\u0380\u038b\7f\2\2\u0381\u0382\7f\2\2\u0382"+
"\u0383\7g\2\2\u0383\u038b\7z\2\2\u0384\u0385\7k\2\2\u0385\u0386\7p\2\2"+
"\u0386\u038b\7{\2\2\u0387\u0388\7t\2\2\u0388\u0389\7q\2\2\u0389\u038b"+
"\7t\2\2\u038a\u02ac\3\2\2\2\u038a\u02af\3\2\2\2\u038a\u02b2\3\2\2\2\u038a"+
"\u02b5\3\2\2\2\u038a\u02b8\3\2\2\2\u038a\u02bb\3\2\2\2\u038a\u02be\3\2"+
"\2\2\u038a\u02c1\3\2\2\2\u038a\u02c4\3\2\2\2\u038a\u02c7\3\2\2\2\u038a"+
"\u02ca\3\2\2\2\u038a\u02cd\3\2\2\2\u038a\u02d0\3\2\2\2\u038a\u02d3\3\2"+
"\2\2\u038a\u02d6\3\2\2\2\u038a\u02d9\3\2\2\2\u038a\u02dc\3\2\2\2\u038a"+
"\u02df\3\2\2\2\u038a\u02e2\3\2\2\2\u038a\u02e5\3\2\2\2\u038a\u02e8\3\2"+
"\2\2\u038a\u02eb\3\2\2\2\u038a\u02ee\3\2\2\2\u038a\u02f1\3\2\2\2\u038a"+
"\u02f4\3\2\2\2\u038a\u02f7\3\2\2\2\u038a\u02fa\3\2\2\2\u038a\u02fd\3\2"+
"\2\2\u038a\u0300\3\2\2\2\u038a\u0303\3\2\2\2\u038a\u0306\3\2\2\2\u038a"+
"\u0309\3\2\2\2\u038a\u030c\3\2\2\2\u038a\u030f\3\2\2\2\u038a\u0312\3\2"+
"\2\2\u038a\u0315\3\2\2\2\u038a\u0318\3\2\2\2\u038a\u031b\3\2\2\2\u038a"+
"\u031e\3\2\2\2\u038a\u0321\3\2\2\2\u038a\u0324\3\2\2\2\u038a\u0327\3\2"+
"\2\2\u038a\u032a\3\2\2\2\u038a\u032d\3\2\2\2\u038a\u0330\3\2\2\2\u038a"+
"\u0333\3\2\2\2\u038a\u0336\3\2\2\2\u038a\u0339\3\2\2\2\u038a\u033c\3\2"+
"\2\2\u038a\u033f\3\2\2\2\u038a\u0342\3\2\2\2\u038a\u0345\3\2\2\2\u038a"+
"\u0348\3\2\2\2\u038a\u034b\3\2\2\2\u038a\u034e\3\2\2\2\u038a\u0351\3\2"+
"\2\2\u038a\u0354\3\2\2\2\u038a\u0357\3\2\2\2\u038a\u035a\3\2\2\2\u038a"+
"\u035d\3\2\2\2\u038a\u0360\3\2\2\2\u038a\u0363\3\2\2\2\u038a\u0366\3\2"+
"\2\2\u038a\u0369\3\2\2\2\u038a\u036c\3\2\2\2\u038a\u036f\3\2\2\2\u038a"+
"\u0372\3\2\2\2\u038a\u0375\3\2\2\2\u038a\u0378\3\2\2\2\u038a\u037b\3\2"+
"\2\2\u038a\u037e\3\2\2\2\u038a\u0381\3\2\2\2\u038a\u0384\3\2\2\2\u038a"+
"\u0387\3\2\2\2\u038b\u00c0\3\2\2\2\u038c\u038d\7}\2\2\u038d\u038e\7}\2"+
"\2\u038e\u0392\3\2\2\2\u038f\u0391\13\2\2\2\u0390\u038f\3\2\2\2\u0391"+
"\u0394\3\2\2\2\u0392\u0393\3\2\2\2\u0392\u0390\3\2\2\2\u0393\u0395\3\2"+
"\2\2\u0394\u0392\3\2\2\2\u0395\u0396\7\177\2\2\u0396\u0397\7\177\2\2\u0397"+
"\u00c2\3\2\2\2\u0398\u0399\7d\2\2\u0399\u039a\7{\2\2\u039a\u039b\7v\2"+
"\2\u039b\u03be\7g\2\2\u039c\u039d\7y\2\2\u039d\u039e\7q\2\2\u039e\u039f"+
"\7t\2\2\u039f\u03be\7f\2\2\u03a0\u03a1\7f\2\2\u03a1\u03a2\7y\2\2\u03a2"+
"\u03a3\7q\2\2\u03a3\u03a4\7t\2\2\u03a4\u03be\7f\2\2\u03a5\u03a6\7d\2\2"+
"\u03a6\u03a7\7q\2\2\u03a7\u03a8\7q\2\2\u03a8\u03be\7n\2\2\u03a9\u03aa"+
"\7e\2\2\u03aa\u03ab\7j\2\2\u03ab\u03ac\7c\2\2\u03ac\u03be\7t\2\2\u03ad"+
"\u03ae\7u\2\2\u03ae\u03af\7j\2\2\u03af\u03b0\7q\2\2\u03b0\u03b1\7t\2\2"+
"\u03b1\u03be\7v\2\2\u03b2\u03b3\7k\2\2\u03b3\u03b4\7p\2\2\u03b4\u03be"+
"\7v\2\2\u03b5\u03b6\7n\2\2\u03b6\u03b7\7q\2\2\u03b7\u03b8\7p\2\2\u03b8"+
"\u03be\7i\2\2\u03b9\u03ba\7x\2\2\u03ba\u03bb\7q\2\2\u03bb\u03bc\7k\2\2"+
"\u03bc\u03be\7f\2\2\u03bd\u0398\3\2\2\2\u03bd\u039c\3\2\2\2\u03bd\u03a0"+
"\3\2\2\2\u03bd\u03a5\3\2\2\2\u03bd\u03a9\3\2\2\2\u03bd\u03ad\3\2\2\2\u03bd"+
"\u03b2\3\2\2\2\u03bd\u03b5\3\2\2\2\u03bd\u03b9\3\2\2\2\u03be\u00c4\3\2"+
"\2\2\u03bf\u03c5\7$\2\2\u03c0\u03c1\7^\2\2\u03c1\u03c4\7$\2\2\u03c2\u03c4"+
"\n\2\2\2\u03c3\u03c0\3\2\2\2\u03c3\u03c2\3\2\2\2\u03c4\u03c7\3\2\2\2\u03c5"+
"\u03c3\3\2\2\2\u03c5\u03c6\3\2\2\2\u03c6\u03c8\3\2\2\2\u03c7\u03c5\3\2"+
"\2\2\u03c8\u03ca\7$\2\2\u03c9\u03cb\t\3\2\2\u03ca\u03c9\3\2\2\2\u03ca"+
"\u03cb\3\2\2\2\u03cb\u03d0\3\2\2\2\u03cc\u03ce\t\4\2\2\u03cd\u03cf\t\5"+
"\2\2\u03ce\u03cd\3\2\2\2\u03ce\u03cf\3\2\2\2\u03cf\u03d1\3\2\2\2\u03d0"+
"\u03cc\3\2\2\2\u03d0\u03d1\3\2\2\2\u03d1\u03d3\3\2\2\2\u03d2\u03d4\t\3"+
"\2\2\u03d3\u03d2\3\2\2\2\u03d3\u03d4\3\2\2\2\u03d4\u00c6\3\2\2\2\u03d5"+
"\u03d9\7)\2\2\u03d6\u03d7\7^\2\2\u03d7\u03da\7)\2\2\u03d8\u03da\n\6\2"+
"\2\u03d9\u03d6\3\2\2\2\u03d9\u03d8\3\2\2\2\u03da\u03db\3\2\2\2\u03db\u03dc"+
"\7)\2\2\u03dc\u00c8\3\2\2\2\u03dd\u03de\7v\2\2\u03de\u03df\7t\2\2\u03df"+
"\u03e0\7w\2\2\u03e0\u03e7\7g\2\2\u03e1\u03e2\7h\2\2\u03e2\u03e3\7c\2\2"+
"\u03e3\u03e4\7n\2\2\u03e4\u03e5\7u\2\2\u03e5\u03e7\7g\2\2\u03e6\u03dd"+
"\3\2\2\2\u03e6\u03e1\3\2\2\2\u03e7\u00ca\3\2\2\2\u03e8\u03eb\5\u00cdg"+
"\2\u03e9\u03eb\5\u00d5k\2\u03ea\u03e8\3\2\2\2\u03ea\u03e9\3\2\2\2\u03eb"+
"p\u00e5\2\u00e7\2\u00e9q\u00ebr\u00eds\u00eft\3\2\23\3\2$$\3\2||\4\2r"+
"ruu\4\2ooww\7\2$$))hhpptt\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DDdd\3\2\62\63"+
"\3\2\62;\5\2\62;CHch\5\2C\\aac|\6\2\62;C\\aac|\4\2--//\6\2\13\f\17\17"+
"\"\"\u00a2\u00a2\4\2\f\f\17\17\2\u04fc\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2"+
"\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2"+
"\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3"+
"\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3"+
"\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65"+
"\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3"+
"\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2"+
"\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2"+
"[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3"+
"\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2"+
"\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2"+
"\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089"+
"\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2"+
"\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b"+
"\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2"+
"\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad"+
"\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2"+
"\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf"+
"\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2"+
"\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1"+
"\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9\3\2\2"+
"\2\2\u00db\3\2\2\2\2\u00e3\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\3\u00f1\3\2\2\2\5\u00f8\3\2\2\2\7\u00fa\3\2\2"+
"\2\t\u0102\3\2\2\2\13\u0104\3\2\2\2\r\u0106\3\2\2\2\17\u0108\3\2\2\2\21"+
"\u010a\3\2\2\2\23\u010c\3\2\2\2\25\u010e\3\2\2\2\27\u0116\3\2\2\2\31\u011e"+
"\3\2\2\2\33\u0127\3\2\2\2\35\u012a\3\2\2\2\37\u012e\3\2\2\2!\u0135\3\2"+
"\2\2#\u013d\3\2\2\2%\u0142\3\2\2\2\'\u014b\3\2\2\2)\u0154\3\2\2\2+\u015d"+
"\3\2\2\2-\u0167\3\2\2\2/\u016d\3\2\2\2\61\u0174\3\2\2\2\63\u017b\3\2\2"+
"\2\65\u0181\3\2\2\2\67\u018a\3\2\2\29\u0191\3\2\2\2;\u019a\3\2\2\2=\u01a4"+
"\3\2\2\2?\u01a7\3\2\2\2A\u01ac\3\2\2\2C\u01b2\3\2\2\2E\u01b5\3\2\2\2G"+
"\u01b9\3\2\2\2I\u01c0\3\2\2\2K\u01c7\3\2\2\2M\u01cd\3\2\2\2O\u01d6\3\2"+
"\2\2Q\u01da\3\2\2\2S\u01e3\3\2\2\2U\u01e8\3\2\2\2W\u01ea\3\2\2\2Y\u01ed"+
"\3\2\2\2[\u01f4\3\2\2\2]\u01fd\3\2\2\2_\u01ff\3\2\2\2a\u0201\3\2\2\2c"+
"\u0203\3\2\2\2e\u020a\3\2\2\2g\u020f\3\2\2\2i\u0211\3\2\2\2k\u0214\3\2"+
"\2\2m\u021b\3\2\2\2o\u0222\3\2\2\2q\u0225\3\2\2\2s\u0228\3\2\2\2u\u022a"+
"\3\2\2\2w\u022c\3\2\2\2y\u022e\3\2\2\2{\u0230\3\2\2\2}\u0232\3\2\2\2\177"+
"\u0235\3\2\2\2\u0081\u0238\3\2\2\2\u0083\u023a\3\2\2\2\u0085\u023c\3\2"+
"\2\2\u0087\u023e\3\2\2\2\u0089\u0240\3\2\2\2\u008b\u0243\3\2\2\2\u008d"+
"\u0246\3\2\2\2\u008f\u0249\3\2\2\2\u0091\u024c\3\2\2\2\u0093\u024e\3\2"+
"\2\2\u0095\u0250\3\2\2\2\u0097\u0253\3\2\2\2\u0099\u0256\3\2\2\2\u009b"+
"\u0258\3\2\2\2\u009d\u025b\3\2\2\2\u009f\u025e\3\2\2\2\u00a1\u0261\3\2"+
"\2\2\u00a3\u0264\3\2\2\2\u00a5\u0267\3\2\2\2\u00a7\u026b\3\2\2\2\u00a9"+
"\u026f\3\2\2\2\u00ab\u0272\3\2\2\2\u00ad\u0275\3\2\2\2\u00af\u0278\3\2"+
"\2\2\u00b1\u0280\3\2\2\2\u00b3\u0289\3\2\2\2\u00b5\u028e\3\2\2\2\u00b7"+
"\u0297\3\2\2\2\u00b9\u029d\3\2\2\2\u00bb\u02a4\3\2\2\2\u00bd\u02aa\3\2"+
"\2\2\u00bf\u038a\3\2\2\2\u00c1\u038c\3\2\2\2\u00c3\u03bd\3\2\2\2\u00c5"+
"\u03bf\3\2\2\2\u00c7\u03d5\3\2\2\2\u00c9\u03e6\3\2\2\2\u00cb\u03ea\3\2"+
"\2\2\u00cd\u03ef\3\2\2\2\u00cf\u03f6\3\2\2\2\u00d1\u0407\3\2\2\2\u00d3"+
"\u0415\3\2\2\2\u00d5\u0426\3\2\2\2\u00d7\u043a\3\2\2\2\u00d9\u043d\3\2"+
"\2\2\u00db\u0446\3\2\2\2\u00dd\u044d\3\2\2\2\u00df\u044f\3\2\2\2\u00e1"+
"\u0451\3\2\2\2\u00e3\u0453\3\2\2\2\u00e5\u045a\3\2\2\2\u00e7\u045c\3\2"+
"\2\2\u00e9\u045e\3\2\2\2\u00eb\u046b\3\2\2\2\u00ed\u0471\3\2\2\2\u00ef"+
"\u047c\3\2\2\2\u00f1\u00f2\7k\2\2\u00f2\u00f3\7o\2\2\u00f3\u00f4\7r\2"+
"\2\u00f4\u00f5\7q\2\2\u00f5\u00f6\7t\2\2\u00f6\u00f7\7v\2\2\u00f7\4\3"+
"\2\2\2\u00f8\u00f9\7=\2\2\u00f9\6\3\2\2\2\u00fa\u00fb\7v\2\2\u00fb\u00fc"+
"\7{\2\2\u00fc\u00fd\7r\2\2\u00fd\u00fe\7g\2\2\u00fe\u00ff\7f\2\2\u00ff"+
"\u0100\7g\2\2\u0100\u0101\7h\2\2\u0101\b\3\2\2\2\u0102\u0103\7.\2\2\u0103"+
"\n\3\2\2\2\u0104\u0105\7?\2\2\u0105\f\3\2\2\2\u0106\u0107\7*\2\2\u0107"+
"\16\3\2\2\2\u0108\u0109\7+\2\2\u0109\20\3\2\2\2\u010a\u010b\7}\2\2\u010b"+
"\22\3\2\2\2\u010c\u010d\7\177\2\2\u010d\24\3\2\2\2\u010e\u010f\7%\2\2"+
"\u010f\u0110\7r\2\2\u0110\u0111\7t\2\2\u0111\u0112\7c\2\2\u0112\u0113"+
"\7i\2\2\u0113\u0114\7o\2\2\u0114\u0115\7c\2\2\u0115\26\3\2\2\2\u0116\u0117"+
"\7t\2\2\u0117\u0118\7g\2\2\u0118\u0119\7u\2\2\u0119\u011a\7g\2\2\u011a"+
"\u011b\7t\2\2\u011b\u011c\7x\2\2\u011c\u011d\7g\2\2\u011d\30\3\2\2\2\u011e"+
"\u011f\7%\2\2\u011f\u0120\7t\2\2\u0120\u0121\7g\2\2\u0121\u0122\7u\2\2"+
"\u0122\u0123\7g\2\2\u0123\u0124\7t\2\2\u0124\u0125\7x\2\2\u0125\u0126"+
"\7g\2\2\u0126\32\3\2\2\2\u0127\u0128\7r\2\2\u0128\u0129\7e\2\2\u0129\34"+
"\3\2\2\2\u012a\u012b\7%\2\2\u012b\u012c\7r\2\2\u012c\u012d\7e\2\2\u012d"+
"\36\3\2\2\2\u012e\u012f\7v\2\2\u012f\u0130\7c\2\2\u0130\u0131\7t\2\2\u0131"+
"\u0132\7i\2\2\u0132\u0133\7g\2\2\u0133\u0134\7v\2\2\u0134 \3\2\2\2\u0135"+
"\u0136\7%\2\2\u0136\u0137\7v\2\2\u0137\u0138\7c\2\2\u0138\u0139\7t\2\2"+
"\u0139\u013a\7i\2\2\u013a\u013b\7g\2\2\u013b\u013c\7v\2\2\u013c\"\3\2"+
"\2\2\u013d\u013e\7n\2\2\u013e\u013f\7k\2\2\u013f\u0140\7p\2\2\u0140\u0141"+
"\7m\2\2\u0141$\3\2\2\2\u0142\u0143\7e\2\2\u0143\u0144\7q\2\2\u0144\u0145"+
"\7f\2\2\u0145\u0146\7g\2\2\u0146\u0147\7a\2\2\u0147\u0148\7u\2\2\u0148"+
"\u0149\7g\2\2\u0149\u014a\7i\2\2\u014a&\3\2\2\2\u014b\u014c\7f\2\2\u014c"+
"\u014d\7c\2\2\u014d\u014e\7v\2\2\u014e\u014f\7c\2\2\u014f\u0150\7a\2\2"+
"\u0150\u0151\7u\2\2\u0151\u0152\7g\2\2\u0152\u0153\7i\2\2\u0153(\3\2\2"+
"\2\u0154\u0155\7g\2\2\u0155\u0156\7p\2\2\u0156\u0157\7e\2\2\u0157\u0158"+
"\7q\2\2\u0158\u0159\7f\2\2\u0159\u015a\7k\2\2\u015a\u015b\7p\2\2\u015b"+
"\u015c\7i\2\2\u015c*\3\2\2\2\u015d\u015e\7%\2\2\u015e\u015f\7g\2\2\u015f"+
"\u0160\7p\2\2\u0160\u0161\7e\2\2\u0161\u0162\7q\2\2\u0162\u0163\7f\2\2"+
"\u0163\u0164\7k\2\2\u0164\u0165\7p\2\2\u0165\u0166\7i\2\2\u0166,\3\2\2"+
"\2\u0167\u0168\7e\2\2\u0168\u0169\7q\2\2\u0169\u016a\7p\2\2\u016a\u016b"+
"\7u\2\2\u016b\u016c\7v\2\2\u016c.\3\2\2\2\u016d\u016e\7g\2\2\u016e\u016f"+
"\7z\2\2\u016f\u0170\7v\2\2\u0170\u0171\7g\2\2\u0171\u0172\7t\2\2\u0172"+
"\u0173\7p\2\2\u0173\60\3\2\2\2\u0174\u0175\7g\2\2\u0175\u0176\7z\2\2\u0176"+
"\u0177\7r\2\2\u0177\u0178\7q\2\2\u0178\u0179\7t\2\2\u0179\u017a\7v\2\2"+
"\u017a\62\3\2\2\2\u017b\u017c\7c\2\2\u017c\u017d\7n\2\2\u017d\u017e\7"+
"k\2\2\u017e\u017f\7i\2\2\u017f\u0180\7p\2\2\u0180\64\3\2\2\2\u0181\u0182"+
"\7t\2\2\u0182\u0183\7g\2\2\u0183\u0184\7i\2\2\u0184\u0185\7k\2\2\u0185"+
"\u0186\7u\2\2\u0186\u0187\7v\2\2\u0187\u0188\7g\2\2\u0188\u0189\7t\2\2"+
"\u0189\66\3\2\2\2\u018a\u018b\7k\2\2\u018b\u018c\7p\2\2\u018c\u018d\7"+
"n\2\2\u018d\u018e\7k\2\2\u018e\u018f\7p\2\2\u018f\u0190\7g\2\2\u01908"+
"\3\2\2\2\u0191\u0192\7x\2\2\u0192\u0193\7q\2\2\u0193\u0194\7n\2\2\u0194"+
"\u0195\7c\2\2\u0195\u0196\7v\2\2\u0196\u0197\7k\2\2\u0197\u0198\7n\2\2"+
"\u0198\u0199\7g\2\2\u0199:\3\2\2\2\u019a\u019b\7k\2\2\u019b\u019c\7p\2"+
"\2\u019c\u019d\7v\2\2\u019d\u019e\7g\2\2\u019e\u019f\7t\2\2\u019f\u01a0"+
"\7t\2\2\u01a0\u01a1\7w\2\2\u01a1\u01a2\7r\2\2\u01a2\u01a3\7v\2\2\u01a3"+
"<\3\2\2\2\u01a4\u01a5\7k\2\2\u01a5\u01a6\7h\2\2\u01a6>\3\2\2\2\u01a7\u01a8"+
"\7g\2\2\u01a8\u01a9\7n\2\2\u01a9\u01aa\7u\2\2\u01aa\u01ab\7g\2\2\u01ab"+
"@\3\2\2\2\u01ac\u01ad\7y\2\2\u01ad\u01ae\7j\2\2\u01ae\u01af\7k\2\2\u01af"+
"\u01b0\7n\2\2\u01b0\u01b1\7g\2\2\u01b1B\3\2\2\2\u01b2\u01b3\7f\2\2\u01b3"+
"\u01b4\7q\2\2\u01b4D\3\2\2\2\u01b5\u01b6\7h\2\2\u01b6\u01b7\7q\2\2\u01b7"+
"\u01b8\7t\2\2\u01b8F\3\2\2\2\u01b9\u01ba\7u\2\2\u01ba\u01bb\7y\2\2\u01bb"+
"\u01bc\7k\2\2\u01bc\u01bd\7v\2\2\u01bd\u01be\7e\2\2\u01be\u01bf\7j\2\2"+
"\u01bfH\3\2\2\2\u01c0\u01c1\7t\2\2\u01c1\u01c2\7g\2\2\u01c2\u01c3\7v\2"+
"\2\u01c3\u01c4\7w\2\2\u01c4\u01c5\7t\2\2\u01c5\u01c6\7p\2\2\u01c6J\3\2"+
"\2\2\u01c7\u01c8\7d\2\2\u01c8\u01c9\7t\2\2\u01c9\u01ca\7g\2\2\u01ca\u01cb"+
"\7c\2\2\u01cb\u01cc\7m\2\2\u01ccL\3\2\2\2\u01cd\u01ce\7e\2\2\u01ce\u01cf"+
"\7q\2\2\u01cf\u01d0\7p\2\2\u01d0\u01d1\7v\2\2\u01d1\u01d2\7k\2\2\u01d2"+
"\u01d3\7p\2\2\u01d3\u01d4\7w\2\2\u01d4\u01d5\7g\2\2\u01d5N\3\2\2\2\u01d6"+
"\u01d7\7c\2\2\u01d7\u01d8\7u\2\2\u01d8\u01d9\7o\2\2\u01d9P\3\2\2\2\u01da"+
"\u01db\7f\2\2\u01db\u01dc\7g\2\2\u01dc\u01dd\7h\2\2\u01dd\u01de\7c\2\2"+
"\u01de\u01df\7w\2\2\u01df\u01e0\7n\2\2\u01e0\u01e1\7v\2\2\u01e1\u01e2"+
"\7<\2\2\u01e2R\3\2\2\2\u01e3\u01e4\7e\2\2\u01e4\u01e5\7c\2\2\u01e5\u01e6"+
"\7u\2\2\u01e6\u01e7\7g\2\2\u01e7T\3\2\2\2\u01e8\u01e9\7<\2\2\u01e9V\3"+
"\2\2\2\u01ea\u01eb\7\60\2\2\u01eb\u01ec\7\60\2\2\u01ecX\3\2\2\2\u01ed"+
"\u01ee\7u\2\2\u01ee\u01ef\7k\2\2\u01ef\u01f0\7i\2\2\u01f0\u01f1\7p\2\2"+
"\u01f1\u01f2\7g\2\2\u01f2\u01f3\7f\2\2\u01f3Z\3\2\2\2\u01f4\u01f5\7w\2"+
"\2\u01f5\u01f6\7p\2\2\u01f6\u01f7\7u\2\2\u01f7\u01f8\7k\2\2\u01f8\u01f9"+
"\7i\2\2\u01f9\u01fa\7p\2\2\u01fa\u01fb\7g\2\2\u01fb\u01fc\7f\2\2\u01fc"+
"\\\3\2\2\2\u01fd\u01fe\7,\2\2\u01fe^\3\2\2\2\u01ff\u0200\7]\2\2\u0200"+
"`\3\2\2\2\u0201\u0202\7_\2\2\u0202b\3\2\2\2\u0203\u0204\7u\2\2\u0204\u0205"+
"\7v\2\2\u0205\u0206\7t\2\2\u0206\u0207\7w\2\2\u0207\u0208\7e\2\2\u0208"+
"\u0209\7v\2\2\u0209d\3\2\2\2\u020a\u020b\7g\2\2\u020b\u020c\7p\2\2\u020c"+
"\u020d\7w\2\2\u020d\u020e\7o\2\2\u020ef\3\2\2\2\u020f\u0210\7\60\2\2\u0210"+
"h\3\2\2\2\u0211\u0212\7/\2\2\u0212\u0213\7@\2\2\u0213j\3\2\2\2\u0214\u0215"+
"\7u\2\2\u0215\u0216\7k\2\2\u0216\u0217\7|\2\2\u0217\u0218\7g\2\2\u0218"+
"\u0219\7q\2\2\u0219\u021a\7h\2\2\u021al\3\2\2\2\u021b\u021c\7v\2\2\u021c"+
"\u021d\7{\2\2\u021d\u021e\7r\2\2\u021e\u021f\7g\2\2\u021f\u0220\7k\2\2"+
"\u0220\u0221\7f\2\2\u0221n\3\2\2\2\u0222\u0223\7/\2\2\u0223\u0224\7/\2"+
"\2\u0224p\3\2\2\2\u0225\u0226\7-\2\2\u0226\u0227\7-\2\2\u0227r\3\2\2\2"+
"\u0228\u0229\7-\2\2\u0229t\3\2\2\2\u022a\u022b\7/\2\2\u022bv\3\2\2\2\u022c"+
"\u022d\7#\2\2\u022dx\3\2\2\2\u022e\u022f\7(\2\2\u022fz\3\2\2\2\u0230\u0231"+
"\7\u0080\2\2\u0231|\3\2\2\2\u0232\u0233\7@\2\2\u0233\u0234\7@\2\2\u0234"+
"~\3\2\2\2\u0235\u0236\7>\2\2\u0236\u0237\7>\2\2\u0237\u0080\3\2\2\2\u0238"+
"\u0239\7\61\2\2\u0239\u0082\3\2\2\2\u023a\u023b\7\'\2\2\u023b\u0084\3"+
"\2\2\2\u023c\u023d\7>\2\2\u023d\u0086\3\2\2\2\u023e\u023f\7@\2\2\u023f"+
"\u0088\3\2\2\2\u0240\u0241\7?\2\2\u0241\u0242\7?\2\2\u0242\u008a\3\2\2"+
"\2\u0243\u0244\7#\2\2\u0244\u0245\7?\2\2\u0245\u008c\3\2\2\2\u0246\u0247"+
"\7>\2\2\u0247\u0248\7?\2\2\u0248\u008e\3\2\2\2\u0249\u024a\7@\2\2\u024a"+
"\u024b\7?\2\2\u024b\u0090\3\2\2\2\u024c\u024d\7`\2\2\u024d\u0092\3\2\2"+
"\2\u024e\u024f\7~\2\2\u024f\u0094\3\2\2\2\u0250\u0251\7(\2\2\u0251\u0252"+
"\7(\2\2\u0252\u0096\3\2\2\2\u0253\u0254\7~\2\2\u0254\u0255\7~\2\2\u0255"+
"\u0098\3\2\2\2\u0256\u0257\7A\2\2\u0257\u009a\3\2\2\2\u0258\u0259\7-\2"+
"\2\u0259\u025a\7?\2\2\u025a\u009c\3\2\2\2\u025b\u025c\7/\2\2\u025c\u025d"+
"\7?\2\2\u025d\u009e\3\2\2\2\u025e\u025f\7,\2\2\u025f\u0260\7?\2\2\u0260"+
"\u00a0\3\2\2\2\u0261\u0262\7\61\2\2\u0262\u0263\7?\2\2\u0263\u00a2\3\2"+
"\2\2\u0264\u0265\7\'\2\2\u0265\u0266\7?\2\2\u0266\u00a4\3\2\2\2\u0267"+
"\u0268\7>\2\2\u0268\u0269\7>\2\2\u0269\u026a\7?\2\2\u026a\u00a6\3\2\2"+
"\2\u026b\u026c\7@\2\2\u026c\u026d\7@\2\2\u026d\u026e\7?\2\2\u026e\u00a8"+
"\3\2\2\2\u026f\u0270\7(\2\2\u0270\u0271\7?\2\2\u0271\u00aa\3\2\2\2\u0272"+
"\u0273\7~\2\2\u0273\u0274\7?\2\2\u0274\u00ac\3\2\2\2\u0275\u0276\7`\2"+
"\2\u0276\u0277\7?\2\2\u0277\u00ae\3\2\2\2\u0278\u0279\7m\2\2\u0279\u027a"+
"\7k\2\2\u027a\u027b\7e\2\2\u027b\u027c\7m\2\2\u027c\u027d\7c\2\2\u027d"+
"\u027e\7u\2\2\u027e\u027f\7o\2\2\u027f\u00b0\3\2\2\2\u0280\u0281\7t\2"+
"\2\u0281\u0282\7g\2\2\u0282\u0283\7u\2\2\u0283\u0284\7q\2\2\u0284\u0285"+
"\7w\2\2\u0285\u0286\7t\2\2\u0286\u0287\7e\2\2\u0287\u0288\7g\2\2\u0288"+
"\u00b2\3\2\2\2\u0289\u028a\7w\2\2\u028a\u028b\7u\2\2\u028b\u028c\7g\2"+
"\2\u028c\u028d\7u\2\2\u028d\u00b4\3\2\2\2\u028e\u028f\7e\2\2\u028f\u0290"+
"\7n\2\2\u0290\u0291\7q\2\2\u0291\u0292\7d\2\2\u0292\u0293\7d\2\2\u0293"+
"\u0294\7g\2\2\u0294\u0295\7t\2\2\u0295\u0296\7u\2\2\u0296\u00b6\3\2\2"+
"\2\u0297\u0298\7d\2\2\u0298\u0299\7{\2\2\u0299\u029a\7v\2\2\u029a\u029b"+
"\7g\2\2\u029b\u029c\7u\2\2\u029c\u00b8\3\2\2\2\u029d\u029e\7e\2\2\u029e"+
"\u029f\7{\2\2\u029f\u02a0\7e\2\2\u02a0\u02a1\7n\2\2\u02a1\u02a2\7g\2\2"+
"\u02a2\u02a3\7u\2\2\u02a3\u00ba\3\2\2\2\u02a4\u02a5\7\60\2\2\u02a5\u02a6"+
"\7d\2\2\u02a6\u02a7\7{\2\2\u02a7\u02a8\7v\2\2\u02a8\u02a9\7g\2\2\u02a9"+
"\u00bc\3\2\2\2\u02aa\u02ab\7%\2\2\u02ab\u00be\3\2\2\2\u02ac\u02ad\7d\2"+
"\2\u02ad\u02ae\7t\2\2\u02ae\u038b\7m\2\2\u02af\u02b0\7q\2\2\u02b0\u02b1"+
"\7t\2\2\u02b1\u038b\7c\2\2\u02b2\u02b3\7m\2\2\u02b3\u02b4\7k\2\2\u02b4"+
"\u038b\7n\2\2\u02b5\u02b6\7u\2\2\u02b6\u02b7\7n\2\2\u02b7\u038b\7q\2\2"+
"\u02b8\u02b9\7p\2\2\u02b9\u02ba\7q\2\2\u02ba\u038b\7r\2\2\u02bb\u02bc"+
"\7c\2\2\u02bc\u02bd\7u\2\2\u02bd\u038b\7n\2\2\u02be\u02bf\7r\2\2\u02bf"+
"\u02c0\7j\2\2\u02c0\u038b\7r\2\2\u02c1\u02c2\7c\2\2\u02c2\u02c3\7p\2\2"+
"\u02c3\u038b\7e\2\2\u02c4\u02c5\7d\2\2\u02c5\u02c6\7r\2\2\u02c6\u038b"+
"\7n\2\2\u02c7\u02c8\7e\2\2\u02c8\u02c9\7n\2\2\u02c9\u038b\7e\2\2\u02ca"+
"\u02cb\7l\2\2\u02cb\u02cc\7u\2\2\u02cc\u038b\7t\2\2\u02cd\u02ce\7c\2\2"+
"\u02ce\u02cf\7p\2\2\u02cf\u038b\7f\2\2\u02d0\u02d1\7t\2\2\u02d1\u02d2"+
"\7n\2\2\u02d2\u038b\7c\2\2\u02d3\u02d4\7d\2\2\u02d4\u02d5\7k\2\2\u02d5"+
"\u038b\7v\2\2\u02d6\u02d7\7t\2\2\u02d7\u02d8\7q\2\2\u02d8\u038b\7n\2\2"+
"\u02d9\u02da\7r\2\2\u02da\u02db\7n\2\2\u02db\u038b\7c\2\2\u02dc\u02dd"+
"\7r\2\2\u02dd\u02de\7n\2\2\u02de\u038b\7r\2\2\u02df\u02e0\7d\2\2\u02e0"+
"\u02e1\7o\2\2\u02e1\u038b\7k\2\2\u02e2\u02e3\7u\2\2\u02e3\u02e4\7g\2\2"+
"\u02e4\u038b\7e\2\2\u02e5\u02e6\7t\2\2\u02e6\u02e7\7v\2\2\u02e7\u038b"+
"\7k\2\2\u02e8\u02e9\7g\2\2\u02e9\u02ea\7q\2\2\u02ea\u038b\7t\2\2\u02eb"+
"\u02ec\7u\2\2\u02ec\u02ed\7t\2\2\u02ed\u038b\7g\2\2\u02ee\u02ef\7n\2\2"+
"\u02ef\u02f0\7u\2\2\u02f0\u038b\7t\2\2\u02f1\u02f2\7r\2\2\u02f2\u02f3"+
"\7j\2\2\u02f3\u038b\7c\2\2\u02f4\u02f5\7c\2\2\u02f5\u02f6\7n\2\2\u02f6"+
"\u038b\7t\2\2\u02f7\u02f8\7l\2\2\u02f8\u02f9\7o\2\2\u02f9\u038b\7r\2\2"+
"\u02fa\u02fb\7d\2\2\u02fb\u02fc\7x\2\2\u02fc\u038b\7e\2\2\u02fd\u02fe"+
"\7e\2\2\u02fe\u02ff\7n\2\2\u02ff\u038b\7k\2\2\u0300\u0301\7t\2\2\u0301"+
"\u0302\7v\2\2\u0302\u038b\7u\2\2\u0303\u0304\7c\2\2\u0304\u0305\7f\2\2"+
"\u0305\u038b\7e\2\2\u0306\u0307\7t\2\2\u0307\u0308\7t\2\2\u0308\u038b"+
"\7c\2\2\u0309\u030a\7d\2\2\u030a\u030b\7x\2\2\u030b\u038b\7u\2\2\u030c"+
"\u030d\7u\2\2\u030d\u030e\7g\2\2\u030e\u038b\7k\2\2\u030f\u0310\7u\2\2"+
"\u0310\u0311\7c\2\2\u0311\u038b\7z\2\2\u0312\u0313\7u\2\2\u0313\u0314"+
"\7v\2\2\u0314\u038b\7{\2\2\u0315\u0316\7u\2\2\u0316\u0317\7v\2\2\u0317"+
"\u038b\7c\2\2\u0318\u0319\7u\2\2\u0319\u031a\7v\2\2\u031a\u038b\7z\2\2"+
"\u031b\u031c\7f\2\2\u031c\u031d\7g\2\2\u031d\u038b\7{\2\2\u031e\u031f"+
"\7v\2\2\u031f\u0320\7z\2\2\u0320\u038b\7c\2\2\u0321\u0322\7z\2\2\u0322"+
"\u0323\7c\2\2\u0323\u038b\7c\2\2\u0324\u0325\7d\2\2\u0325\u0326\7e\2\2"+
"\u0326\u038b\7e\2\2\u0327\u0328\7c\2\2\u0328\u0329\7j\2\2\u0329\u038b"+
"\7z\2\2\u032a\u032b\7v\2\2\u032b\u032c\7{\2\2\u032c\u038b\7c\2\2\u032d"+
"\u032e\7v\2\2\u032e\u032f\7z\2\2\u032f\u038b\7u\2\2\u0330\u0331\7v\2\2"+
"\u0331\u0332\7c\2\2\u0332\u038b\7u\2\2\u0333\u0334\7u\2\2\u0334\u0335"+
"\7j\2\2\u0335\u038b\7{\2\2\u0336\u0337\7u\2\2\u0337\u0338\7j\2\2\u0338"+
"\u038b\7z\2\2\u0339\u033a\7n\2\2\u033a\u033b\7f\2\2\u033b\u038b\7{\2\2"+
"\u033c\u033d\7n\2\2\u033d\u033e\7f\2\2\u033e\u038b\7c\2\2\u033f\u0340"+
"\7n\2\2\u0340\u0341\7f\2\2\u0341\u038b\7z\2\2\u0342\u0343\7n\2\2\u0343"+
"\u0344\7c\2\2\u0344\u038b\7z\2\2\u0345\u0346\7v\2\2\u0346\u0347\7c\2\2"+
"\u0347\u038b\7{\2\2\u0348\u0349\7v\2\2\u0349\u034a\7c\2\2\u034a\u038b"+
"\7z\2\2\u034b\u034c\7d\2\2\u034c\u034d\7e\2\2\u034d\u038b\7u\2\2\u034e"+
"\u034f\7e\2\2\u034f\u0350\7n\2\2\u0350\u038b\7x\2\2\u0351\u0352\7v\2\2"+
"\u0352\u0353\7u\2\2\u0353\u038b\7z\2\2\u0354\u0355\7n\2\2\u0355\u0356"+
"\7c\2\2\u0356\u038b\7u\2\2\u0357\u0358\7e\2\2\u0358\u0359\7r\2\2\u0359"+
"\u038b\7{\2\2\u035a\u035b\7e\2\2\u035b\u035c\7o\2\2\u035c\u038b\7r\2\2"+
"\u035d\u035e\7e\2\2\u035e\u035f\7r\2\2\u035f\u038b\7z\2\2\u0360\u0361"+
"\7f\2\2\u0361\u0362\7e\2\2\u0362\u038b\7r\2\2\u0363\u0364\7f\2\2\u0364"+
"\u0365\7g\2\2\u0365\u038b\7e\2\2\u0366\u0367\7k\2\2\u0367\u0368\7p\2\2"+
"\u0368\u038b\7e\2\2\u0369\u036a\7c\2\2\u036a\u036b\7z\2\2\u036b\u038b"+
"\7u\2\2\u036c\u036d\7d\2\2\u036d\u036e\7p\2\2\u036e\u038b\7g\2\2\u036f"+
"\u0370\7e\2\2\u0370\u0371\7n\2\2\u0371\u038b\7f\2\2\u0372\u0373\7u\2\2"+
"\u0373\u0374\7d\2\2\u0374\u038b\7e\2\2\u0375\u0376\7k\2\2\u0376\u0377"+
"\7u\2\2\u0377\u038b\7e\2\2\u0378\u0379\7k\2\2\u0379\u037a\7p\2\2\u037a"+
"\u038b\7z\2\2\u037b\u037c\7d\2\2\u037c\u037d\7g\2\2\u037d\u038b\7s\2\2"+
"\u037e\u037f\7u\2\2\u037f\u0380\7g\2\2\u0380\u038b\7f\2\2\u0381\u0382"+
"\7f\2\2\u0382\u0383\7g\2\2\u0383\u038b\7z\2\2\u0384\u0385\7k\2\2\u0385"+
"\u0386\7p\2\2\u0386\u038b\7{\2\2\u0387\u0388\7t\2\2\u0388\u0389\7q\2\2"+
"\u0389\u038b\7t\2\2\u038a\u02ac\3\2\2\2\u038a\u02af\3\2\2\2\u038a\u02b2"+
"\3\2\2\2\u038a\u02b5\3\2\2\2\u038a\u02b8\3\2\2\2\u038a\u02bb\3\2\2\2\u038a"+
"\u02be\3\2\2\2\u038a\u02c1\3\2\2\2\u038a\u02c4\3\2\2\2\u038a\u02c7\3\2"+
"\2\2\u038a\u02ca\3\2\2\2\u038a\u02cd\3\2\2\2\u038a\u02d0\3\2\2\2\u038a"+
"\u02d3\3\2\2\2\u038a\u02d6\3\2\2\2\u038a\u02d9\3\2\2\2\u038a\u02dc\3\2"+
"\2\2\u038a\u02df\3\2\2\2\u038a\u02e2\3\2\2\2\u038a\u02e5\3\2\2\2\u038a"+
"\u02e8\3\2\2\2\u038a\u02eb\3\2\2\2\u038a\u02ee\3\2\2\2\u038a\u02f1\3\2"+
"\2\2\u038a\u02f4\3\2\2\2\u038a\u02f7\3\2\2\2\u038a\u02fa\3\2\2\2\u038a"+
"\u02fd\3\2\2\2\u038a\u0300\3\2\2\2\u038a\u0303\3\2\2\2\u038a\u0306\3\2"+
"\2\2\u038a\u0309\3\2\2\2\u038a\u030c\3\2\2\2\u038a\u030f\3\2\2\2\u038a"+
"\u0312\3\2\2\2\u038a\u0315\3\2\2\2\u038a\u0318\3\2\2\2\u038a\u031b\3\2"+
"\2\2\u038a\u031e\3\2\2\2\u038a\u0321\3\2\2\2\u038a\u0324\3\2\2\2\u038a"+
"\u0327\3\2\2\2\u038a\u032a\3\2\2\2\u038a\u032d\3\2\2\2\u038a\u0330\3\2"+
"\2\2\u038a\u0333\3\2\2\2\u038a\u0336\3\2\2\2\u038a\u0339\3\2\2\2\u038a"+
"\u033c\3\2\2\2\u038a\u033f\3\2\2\2\u038a\u0342\3\2\2\2\u038a\u0345\3\2"+
"\2\2\u038a\u0348\3\2\2\2\u038a\u034b\3\2\2\2\u038a\u034e\3\2\2\2\u038a"+
"\u0351\3\2\2\2\u038a\u0354\3\2\2\2\u038a\u0357\3\2\2\2\u038a\u035a\3\2"+
"\2\2\u038a\u035d\3\2\2\2\u038a\u0360\3\2\2\2\u038a\u0363\3\2\2\2\u038a"+
"\u0366\3\2\2\2\u038a\u0369\3\2\2\2\u038a\u036c\3\2\2\2\u038a\u036f\3\2"+
"\2\2\u038a\u0372\3\2\2\2\u038a\u0375\3\2\2\2\u038a\u0378\3\2\2\2\u038a"+
"\u037b\3\2\2\2\u038a\u037e\3\2\2\2\u038a\u0381\3\2\2\2\u038a\u0384\3\2"+
"\2\2\u038a\u0387\3\2\2\2\u038b\u00c0\3\2\2\2\u038c\u038d\7}\2\2\u038d"+
"\u038e\7}\2\2\u038e\u0392\3\2\2\2\u038f\u0391\13\2\2\2\u0390\u038f\3\2"+
"\2\2\u0391\u0394\3\2\2\2\u0392\u0393\3\2\2\2\u0392\u0390\3\2\2\2\u0393"+
"\u0395\3\2\2\2\u0394\u0392\3\2\2\2\u0395\u0396\7\177\2\2\u0396\u0397\7"+
"\177\2\2\u0397\u00c2\3\2\2\2\u0398\u0399\7d\2\2\u0399\u039a\7{\2\2\u039a"+
"\u039b\7v\2\2\u039b\u03be\7g\2\2\u039c\u039d\7y\2\2\u039d\u039e\7q\2\2"+
"\u039e\u039f\7t\2\2\u039f\u03be\7f\2\2\u03a0\u03a1\7f\2\2\u03a1\u03a2"+
"\7y\2\2\u03a2\u03a3\7q\2\2\u03a3\u03a4\7t\2\2\u03a4\u03be\7f\2\2\u03a5"+
"\u03a6\7d\2\2\u03a6\u03a7\7q\2\2\u03a7\u03a8\7q\2\2\u03a8\u03be\7n\2\2"+
"\u03a9\u03aa\7e\2\2\u03aa\u03ab\7j\2\2\u03ab\u03ac\7c\2\2\u03ac\u03be"+
"\7t\2\2\u03ad\u03ae\7u\2\2\u03ae\u03af\7j\2\2\u03af\u03b0\7q\2\2\u03b0"+
"\u03b1\7t\2\2\u03b1\u03be\7v\2\2\u03b2\u03b3\7k\2\2\u03b3\u03b4\7p\2\2"+
"\u03b4\u03be\7v\2\2\u03b5\u03b6\7n\2\2\u03b6\u03b7\7q\2\2\u03b7\u03b8"+
"\7p\2\2\u03b8\u03be\7i\2\2\u03b9\u03ba\7x\2\2\u03ba\u03bb\7q\2\2\u03bb"+
"\u03bc\7k\2\2\u03bc\u03be\7f\2\2\u03bd\u0398\3\2\2\2\u03bd\u039c\3\2\2"+
"\2\u03bd\u03a0\3\2\2\2\u03bd\u03a5\3\2\2\2\u03bd\u03a9\3\2\2\2\u03bd\u03ad"+
"\3\2\2\2\u03bd\u03b2\3\2\2\2\u03bd\u03b5\3\2\2\2\u03bd\u03b9\3\2\2\2\u03be"+
"\u00c4\3\2\2\2\u03bf\u03c5\7$\2\2\u03c0\u03c1\7^\2\2\u03c1\u03c4\7$\2"+
"\2\u03c2\u03c4\n\2\2\2\u03c3\u03c0\3\2\2\2\u03c3\u03c2\3\2\2\2\u03c4\u03c7"+
"\3\2\2\2\u03c5\u03c3\3\2\2\2\u03c5\u03c6\3\2\2\2\u03c6\u03c8\3\2\2\2\u03c7"+
"\u03c5\3\2\2\2\u03c8\u03ca\7$\2\2\u03c9\u03cb\t\3\2\2\u03ca\u03c9\3\2"+
"\2\2\u03ca\u03cb\3\2\2\2\u03cb\u03d0\3\2\2\2\u03cc\u03ce\t\4\2\2\u03cd"+
"\u03cf\t\5\2\2\u03ce\u03cd\3\2\2\2\u03ce\u03cf\3\2\2\2\u03cf\u03d1\3\2"+
"\2\2\u03d0\u03cc\3\2\2\2\u03d0\u03d1\3\2\2\2\u03d1\u03d3\3\2\2\2\u03d2"+
"\u03d4\t\3\2\2\u03d3\u03d2\3\2\2\2\u03d3\u03d4\3\2\2\2\u03d4\u00c6\3\2"+
"\2\2\u03d5\u03d9\7)\2\2\u03d6\u03d7\7^\2\2\u03d7\u03da\t\6\2\2\u03d8\u03da"+
"\n\7\2\2\u03d9\u03d6\3\2\2\2\u03d9\u03d8\3\2\2\2\u03da\u03db\3\2\2\2\u03db"+
"\u03dc\7)\2\2\u03dc\u00c8\3\2\2\2\u03dd\u03de\7v\2\2\u03de\u03df\7t\2"+
"\2\u03df\u03e0\7w\2\2\u03e0\u03e7\7g\2\2\u03e1\u03e2\7h\2\2\u03e2\u03e3"+
"\7c\2\2\u03e3\u03e4\7n\2\2\u03e4\u03e5\7u\2\2\u03e5\u03e7\7g\2\2\u03e6"+
"\u03dd\3\2\2\2\u03e6\u03e1\3\2\2\2\u03e7\u00ca\3\2\2\2\u03e8\u03eb\5\u00cd"+
"g\2\u03e9\u03eb\5\u00d5k\2\u03ea\u03e8\3\2\2\2\u03ea\u03e9\3\2\2\2\u03eb"+
"\u00cc\3\2\2\2\u03ec\u03f0\5\u00cfh\2\u03ed\u03f0\5\u00d1i\2\u03ee\u03f0"+
"\5\u00d3j\2\u03ef\u03ec\3\2\2\2\u03ef\u03ed\3\2\2\2\u03ef\u03ee\3\2\2"+
"\2\u03f0\u00ce\3\2\2\2\u03f1\u03f7\7\'\2\2\u03f2\u03f3\7\62\2\2\u03f3"+
@ -525,10 +525,10 @@ public class KickCLexer extends Lexer {
"\u00e1q\2\u041f\u041e\3\2\2\2\u0420\u0421\3\2\2\2\u0421\u041f\3\2\2\2"+
"\u0421\u0422\3\2\2\2\u0422\u00d4\3\2\2\2\u0423\u0427\5\u00d9m\2\u0424"+
"\u0427\5\u00dbn\2\u0425\u0427\5\u00d7l\2\u0426\u0423\3\2\2\2\u0426\u0424"+
"\3\2\2\2\u0426\u0425\3\2\2\2\u0427\u042b\3\2\2\2\u0428\u0429\t\7\2\2\u0429"+
"\u042c\t\b\2\2\u042a\u042c\7n\2\2\u042b\u0428\3\2\2\2\u042b\u042a\3\2"+
"\3\2\2\2\u0426\u0425\3\2\2\2\u0427\u042b\3\2\2\2\u0428\u0429\t\b\2\2\u0429"+
"\u042c\t\t\2\2\u042a\u042c\7n\2\2\u042b\u0428\3\2\2\2\u042b\u042a\3\2"+
"\2\2\u042b\u042c\3\2\2\2\u042c\u00d6\3\2\2\2\u042d\u042e\7\62\2\2\u042e"+
"\u0430\t\t\2\2\u042f\u0431\5\u00ddo\2\u0430\u042f\3\2\2\2\u0431\u0432"+
"\u0430\t\n\2\2\u042f\u0431\5\u00ddo\2\u0430\u042f\3\2\2\2\u0431\u0432"+
"\3\2\2\2\u0432\u0430\3\2\2\2\u0432\u0433\3\2\2\2\u0433\u043b\3\2\2\2\u0434"+
"\u0436\7\'\2\2\u0435\u0437\5\u00ddo\2\u0436\u0435\3\2\2\2\u0437\u0438"+
"\3\2\2\2\u0438\u0436\3\2\2\2\u0438\u0439\3\2\2\2\u0439\u043b\3\2\2\2\u043a"+
@ -538,20 +538,20 @@ public class KickCLexer extends Lexer {
"\2\2\u0443\u0447\7z\2\2\u0444\u0445\7\62\2\2\u0445\u0447\7Z\2\2\u0446"+
"\u0441\3\2\2\2\u0446\u0442\3\2\2\2\u0446\u0444\3\2\2\2\u0447\u0449\3\2"+
"\2\2\u0448\u044a\5\u00e1q\2\u0449\u0448\3\2\2\2\u044a\u044b\3\2\2\2\u044b"+
"\u0449\3\2\2\2\u044b\u044c\3\2\2\2\u044c\u00dc\3\2\2\2\u044d\u044e\t\n"+
"\2\2\u044e\u00de\3\2\2\2\u044f\u0450\t\13\2\2\u0450\u00e0\3\2\2\2\u0451"+
"\u0452\t\f\2\2\u0452\u00e2\3\2\2\2\u0453\u0457\5\u00e5s\2\u0454\u0456"+
"\u0449\3\2\2\2\u044b\u044c\3\2\2\2\u044c\u00dc\3\2\2\2\u044d\u044e\t\13"+
"\2\2\u044e\u00de\3\2\2\2\u044f\u0450\t\f\2\2\u0450\u00e0\3\2\2\2\u0451"+
"\u0452\t\r\2\2\u0452\u00e2\3\2\2\2\u0453\u0457\5\u00e5s\2\u0454\u0456"+
"\5\u00e7t\2\u0455\u0454\3\2\2\2\u0456\u0459\3\2\2\2\u0457\u0455\3\2\2"+
"\2\u0457\u0458\3\2\2\2\u0458\u00e4\3\2\2\2\u0459\u0457\3\2\2\2\u045a\u045b"+
"\t\r\2\2\u045b\u00e6\3\2\2\2\u045c\u045d\t\16\2\2\u045d\u00e8\3\2\2\2"+
"\t\16\2\2\u045b\u00e6\3\2\2\2\u045c\u045d\t\17\2\2\u045d\u00e8\3\2\2\2"+
"\u045e\u0462\7#\2\2\u045f\u0461\5\u00e7t\2\u0460\u045f\3\2\2\2\u0461\u0464"+
"\3\2\2\2\u0462\u0460\3\2\2\2\u0462\u0463\3\2\2\2\u0463\u0466\3\2\2\2\u0464"+
"\u0462\3\2\2\2\u0465\u0467\t\17\2\2\u0466\u0465\3\2\2\2\u0467\u0468\3"+
"\u0462\3\2\2\2\u0465\u0467\t\20\2\2\u0466\u0465\3\2\2\2\u0467\u0468\3"+
"\2\2\2\u0468\u0466\3\2\2\2\u0468\u0469\3\2\2\2\u0469\u00ea\3\2\2\2\u046a"+
"\u046c\t\20\2\2\u046b\u046a\3\2\2\2\u046c\u046d\3\2\2\2\u046d\u046b\3"+
"\u046c\t\21\2\2\u046b\u046a\3\2\2\2\u046c\u046d\3\2\2\2\u046d\u046b\3"+
"\2\2\2\u046d\u046e\3\2\2\2\u046e\u046f\3\2\2\2\u046f\u0470\bv\2\2\u0470"+
"\u00ec\3\2\2\2\u0471\u0472\7\61\2\2\u0472\u0473\7\61\2\2\u0473\u0477\3"+
"\2\2\2\u0474\u0476\n\21\2\2\u0475\u0474\3\2\2\2\u0476\u0479\3\2\2\2\u0477"+
"\2\2\2\u0474\u0476\n\22\2\2\u0475\u0474\3\2\2\2\u0476\u0479\3\2\2\2\u0477"+
"\u0475\3\2\2\2\u0477\u0478\3\2\2\2\u0478\u047a\3\2\2\2\u0479\u0477\3\2"+
"\2\2\u047a\u047b\bw\3\2\u047b\u00ee\3\2\2\2\u047c\u047d\7\61\2\2\u047d"+
"\u047e\7,\2\2\u047e\u0482\3\2\2\2\u047f\u0481\13\2\2\2\u0480\u047f\3\2"+

View File

@ -4,7 +4,6 @@ import dk.camelot64.kickc.Compiler;
import dk.camelot64.kickc.NumberParser;
import dk.camelot64.kickc.asm.AsmClobber;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.operators.*;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.*;
@ -1700,11 +1699,11 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
}
/** The current string encoding used if no explicit encoding is specified. */
ConstantString.Encoding currentEncoding = ConstantString.Encoding.SCREENCODE_MIXED;
private ConstantString.Encoding currentEncoding = ConstantString.Encoding.SCREENCODE_MIXED;
@Override
public RValue visitExprString(KickCParser.ExprStringContext ctx) {
String stringValue = "";
StringBuilder stringValue = new StringBuilder();
String subText;
String lastSuffix = "";
ConstantString.Encoding encoding = null;
@ -1719,10 +1718,15 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
encoding = suffixEncoding;
}
lastSuffix = suffix;
stringValue += subText.substring(1, subText.lastIndexOf('"'));
stringValue.append(subText, 1, subText.lastIndexOf('"'));
}
boolean zeroTerminated = !lastSuffix.contains("z");
return new ConstantString(stringValue, encoding, zeroTerminated);
try {
return new ConstantString(ConstantString.stringEscapeToAscii(stringValue.toString()), encoding, zeroTerminated);
} catch(CompileError e) {
// Rethrow - adding statement context!
throw new CompileError(e.getMessage(), new StatementSource(ctx));
}
}
/**
@ -1757,7 +1761,15 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
@Override
public Object visitExprChar(KickCParser.ExprCharContext ctx) {
return new ConstantChar(ctx.getText().charAt(1), currentEncoding);
try {
String charText = ctx.getText();
charText = charText.substring(1, charText.length() - 1);
char constChar = ConstantChar.charEscapeToAscii(charText);
return new ConstantChar(constChar, currentEncoding);
} catch (CompileError e) {
// Rethrow adding source location
throw new CompileError(e.getMessage(), new StatementSource(ctx));
}
}
@Override

View File

@ -13,6 +13,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
@ -193,6 +194,10 @@ public class Pass1ProcedureInline extends Pass1Base {
StatementCall inlinedCall = new StatementCall(procCall.getlValue(), procCall.getProcedureName(), new ArrayList<>(procCall.getParameters()), procCall.getSource(), Comment.NO_COMMENTS);
inlinedCall.setProcedure(procCall.getProcedure());
inlinedStatement = inlinedCall;
} else if(procStatement instanceof StatementAsm) {
StatementAsm procAsm = (StatementAsm) procStatement;
StatementAsm inlinedAsm = new StatementAsm(procAsm.getAsmBody(), new LinkedHashMap<>(procAsm.getReferenced()), procAsm.getDeclaredClobber(), procAsm.getSource(), Comment.NO_COMMENTS);
inlinedStatement = inlinedAsm;
} else if(procStatement instanceof StatementConditionalJump) {
StatementConditionalJump procConditional = (StatementConditionalJump) procStatement;
LabelRef procDestinationRef = procConditional.getDestination();

View File

@ -36,6 +36,31 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testStringEscapesErr1() throws IOException, URISyntaxException {
assertError("string-escapes-err-1", "Illegal string escape sequence");
}
@Test
public void testStringEscapesErr0() throws IOException, URISyntaxException {
assertError("string-escapes-err-0", "Unfinished string escape sequence at end of string");
}
@Test
public void testStringEscapes2() throws IOException, URISyntaxException {
compileAndCompare("string-escapes-2");
}
@Test
public void testStringEscapes1() throws IOException, URISyntaxException {
compileAndCompare("string-escapes-1");
}
@Test
public void testStringEscapes0() throws IOException, URISyntaxException {
compileAndCompare("string-escapes-0");
}
//@Test
//public void testLoopheadProblem() throws IOException, URISyntaxException {
// compileAndCompare("loophead-problem");

View File

@ -0,0 +1,10 @@
// Test using some simple supported string escapes \r \f \n \' \"
char[] MESSAGE = "\r\f\n\"\'";
char* SCREEN = 0x0400;
void main() {
byte i=0;
while(MESSAGE[i])
SCREEN[i] = MESSAGE[i++];
}

View File

@ -0,0 +1,23 @@
// Test using some simple supported string escape \n in both string and char
char[] MESSAGE = "hello\nworld";
char* SCREEN = 0x0400;
void main() {
byte* line = 0x0400;
byte* cursor = line;
byte* msg = MESSAGE;
while(*msg) {
switch(*msg) {
case '\n':
line += 0x28;
cursor = line;
break;
default:
*cursor++ = *msg;
}
msg++;
}
}

View File

@ -0,0 +1,21 @@
// Test using some simple supported string escape characters in PETSCII
#pragma encoding(petscii_mixed)
char[] MESSAGE = "hello\nworld";
const char* memA = 0xff;
void main() {
byte i=0;
while(MESSAGE[i])
chrout(MESSAGE[i++]);
}
void chrout(char c) {
*memA = c;
asm {
lda memA
jsr $ffd2
}
}

View File

@ -0,0 +1,11 @@
// Test errors using string escape sequences
// Unfinished escape at end of string
char[] MESSAGE = "qwe\";
char* SCREEN = 0x0400;
void main() {
byte i=0;
while(MESSAGE[i])
SCREEN[i] = MESSAGE[i++];
}

View File

@ -0,0 +1,11 @@
// Test errors using string escape sequences
// Unsupported escape sequence
char[] MESSAGE = "qwe\qasd";
char* SCREEN = 0x0400;
void main() {
byte i=0;
while(MESSAGE[i])
SCREEN[i] = MESSAGE[i++];
}

View File

@ -0,0 +1,20 @@
// Test using some simple supported string escapes \r \f \n \' \"
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
main: {
ldy #0
b1:
lda #0
cmp MESSAGE,y
bne b2
rts
b2:
lda MESSAGE,y
sta SCREEN,y
iny
jmp b1
}
MESSAGE: .text @"\r\f\n\"'"
.byte 0

View File

@ -0,0 +1,23 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
[6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[7] return
to:@return
main::@2: scope:[main] from main::@1
[8] *((const byte*) SCREEN#0 + (byte) main::i#2) ← *((const byte[]) MESSAGE#0 + (byte) main::i#2)
[9] (byte) main::i#1 ← ++ (byte) main::i#2
to:main::@1

View File

@ -0,0 +1,370 @@
Warning! Adding boolean cast to non-boolean condition *((byte[]) MESSAGE + (byte) main::i)
Identified constant variable (byte*) SCREEN
Culled Empty Block (label) main::@4
Culled Empty Block (label) main::@3
Culled Empty Block (label) main::@5
Culled Empty Block (label) main::@6
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte[]) MESSAGE#0 ← (const string) $0
(byte*) SCREEN#0 ← ((byte*)) (number) $400
to:@1
main: scope:[main] from @1
(byte) main::i#0 ← (number) 0
to:main::@1
main::@1: scope:[main] from main main::@2
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 )
(bool~) main::$0 ← (number) 0 != *((byte[]) MESSAGE#0 + (byte) main::i#2)
if((bool~) main::$0) goto main::@2
to:main::@return
main::@2: scope:[main] from main::@1
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
*((byte*) SCREEN#0 + (byte) main::i#3) ← *((byte[]) MESSAGE#0 + (byte) main::i#3)
(byte) main::i#1 ← ++ (byte) main::i#3
to:main::@1
main::@return: scope:[main] from main::@1
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(const string) $0 = (string) "
"'"
(label) @1
(label) @2
(label) @begin
(label) @end
(byte[]) MESSAGE
(byte[]) MESSAGE#0
(byte*) SCREEN
(byte*) SCREEN#0
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@2
(label) main::@return
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte) main::i#3
Adding number conversion cast (unumber) 0 in (byte) main::i#0 ← (number) 0
Adding number conversion cast (unumber) 0 in (bool~) main::$0 ← (number) 0 != *((byte[]) MESSAGE#0 + (byte) main::i#2)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
Inlining cast (byte) main::i#0 ← (unumber)(number) 0
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) main::i#2 = (byte) main::i#3
Successful SSA optimization Pass2AliasElimination
Simple Condition (bool~) main::$0 [5] if((byte) 0!=*((byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte[]) MESSAGE#0 = $0
Constant (const byte*) SCREEN#0 = (byte*) 1024
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Inlining constant with var siblings (const byte) main::i#0
Constant inlined $0 = (const byte[]) MESSAGE#0
Constant inlined main::i#0 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Created 1 initial phi equivalence classes
Coalesced [11] main::i#4 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
[6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[7] return
to:@return
main::@2: scope:[main] from main::@1
[8] *((const byte*) SCREEN#0 + (byte) main::i#2) ← *((const byte[]) MESSAGE#0 + (byte) main::i#2)
[9] (byte) main::i#1 ← ++ (byte) main::i#2
to:main::@1
VARIABLE REGISTER WEIGHTS
(byte[]) MESSAGE
(byte*) SCREEN
(void()) main()
(byte) main::i
(byte) main::i#1 22.0
(byte) main::i#2 18.333333333333332
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
INITIAL ASM
Target platform is c64basic
// File Comments
// Test using some simple supported string escapes \r \f \n \' \"
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label i = 2
// [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z i
jmp b1
// main::@1
b1:
// [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 -- vbuc1_neq_pbuc2_derefidx_vbuz1_then_la1
lda #0
ldy.z i
cmp MESSAGE,y
bne b2
jmp breturn
// main::@return
breturn:
// [7] return
rts
// main::@2
b2:
// [8] *((const byte*) SCREEN#0 + (byte) main::i#2) ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz1
ldy.z i
lda MESSAGE,y
sta SCREEN,y
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
b1_from_b2:
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
jmp b1
}
// File Data
MESSAGE: .text @"\r\f\n\"'"
.byte 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Statement [8] *((const byte*) SCREEN#0 + (byte) main::i#2) ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [8] *((const byte*) SCREEN#0 + (byte) main::i#2) ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 40.33: zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Uplift Scope []
Uplifting [main] best 333 combination reg byte y [ main::i#2 main::i#1 ]
Uplifting [] best 333 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test using some simple supported string escapes \r \f \n \' \"
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
// [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuyy=vbuc1
ldy #0
jmp b1
// main::@1
b1:
// [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 -- vbuc1_neq_pbuc2_derefidx_vbuyy_then_la1
lda #0
cmp MESSAGE,y
bne b2
jmp breturn
// main::@return
breturn:
// [7] return
rts
// main::@2
b2:
// [8] *((const byte*) SCREEN#0 + (byte) main::i#2) ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuyy
lda MESSAGE,y
sta SCREEN,y
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuyy=_inc_vbuyy
iny
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
b1_from_b2:
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
jmp b1
}
// File Data
MESSAGE: .text @"\r\f\n\"'"
.byte 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction breturn:
Removing instruction b1_from_b2:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(byte[]) MESSAGE
(const byte[]) MESSAGE#0 MESSAGE = (string) "
"'"
(byte*) SCREEN
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte y 22.0
(byte) main::i#2 reg byte y 18.333333333333332
reg byte y [ main::i#2 main::i#1 ]
FINAL ASSEMBLER
Score: 261
// File Comments
// Test using some simple supported string escapes \r \f \n \' \"
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
// [5] phi from main to main::@1 [phi:main->main::@1]
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuyy=vbuc1
ldy #0
// main::@1
b1:
// while(MESSAGE[i])
// [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 -- vbuc1_neq_pbuc2_derefidx_vbuyy_then_la1
lda #0
cmp MESSAGE,y
bne b2
// main::@return
// }
// [7] return
rts
// main::@2
b2:
// SCREEN[i] = MESSAGE[i++]
// [8] *((const byte*) SCREEN#0 + (byte) main::i#2) ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuyy
lda MESSAGE,y
sta SCREEN,y
// SCREEN[i] = MESSAGE[i++];
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuyy=_inc_vbuyy
iny
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
jmp b1
}
// File Data
MESSAGE: .text @"\r\f\n\"'"
.byte 0

View File

@ -0,0 +1,17 @@
(label) @1
(label) @begin
(label) @end
(byte[]) MESSAGE
(const byte[]) MESSAGE#0 MESSAGE = (string) "
"'"
(byte*) SCREEN
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte y 22.0
(byte) main::i#2 reg byte y 18.333333333333332
reg byte y [ main::i#2 main::i#1 ]

View File

@ -0,0 +1,59 @@
// Test using some simple supported string escape \n in both string and char
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
.label cursor = 6
.label msg = 2
.label line = 4
lda #<$400
sta.z cursor
lda #>$400
sta.z cursor+1
lda #<$400
sta.z line
lda #>$400
sta.z line+1
lda #<MESSAGE
sta.z msg
lda #>MESSAGE
sta.z msg+1
b1:
ldy #0
lda (msg),y
cmp #0
bne b2
rts
b2:
lda #-$33
ldy #0
cmp (msg),y
beq b3
lda (msg),y
sta (cursor),y
inc.z cursor
bne !+
inc.z cursor+1
!:
b5:
inc.z msg
bne !+
inc.z msg+1
!:
jmp b1
b3:
lda #$28
clc
adc.z line
sta.z cursor
lda #0
adc.z line+1
sta.z cursor+1
lda.z cursor
sta.z line
lda.z cursor+1
sta.z line+1
jmp b5
}
MESSAGE: .text @"hello\nworld"
.byte 0

View File

@ -0,0 +1,38 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@5
[5] (byte*) main::cursor#3 ← phi( main/(byte*) 1024 main::@5/(byte*) main::cursor#6 )
[5] (byte*) main::line#2 ← phi( main/(byte*) 1024 main::@5/(byte*) main::line#5 )
[5] (byte*) main::msg#2 ← phi( main/(const byte[]) MESSAGE#0 main::@5/(byte*) main::msg#1 )
[6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[7] return
to:@return
main::@2: scope:[main] from main::@1
[8] if(*((byte*) main::msg#2)==(byte) '
') goto main::@3
to:main::@4
main::@4: scope:[main] from main::@2
[9] *((byte*) main::cursor#3) ← *((byte*) main::msg#2)
[10] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3
to:main::@5
main::@5: scope:[main] from main::@3 main::@4
[11] (byte*) main::cursor#6 ← phi( main::@3/(byte*) main::cursor#1 main::@4/(byte*) main::cursor#2 )
[11] (byte*) main::line#5 ← phi( main::@3/(byte*~) main::line#8 main::@4/(byte*) main::line#2 )
[12] (byte*) main::msg#1 ← ++ (byte*) main::msg#2
to:main::@1
main::@3: scope:[main] from main::@2
[13] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28
[14] (byte*~) main::line#8 ← (byte*) main::cursor#1
to:main::@5

View File

@ -0,0 +1,663 @@
Warning! Adding boolean cast to non-boolean condition *((byte*) main::msg)
Identified constant variable (byte*) SCREEN
Culled Empty Block (label) main::@9
Culled Empty Block (label) main::@3
Culled Empty Block (label) main::@10
Culled Empty Block (label) main::@11
Culled Empty Block (label) main::@12
Culled Empty Block (label) main::@7
Culled Empty Block (label) main::@8
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte[]) MESSAGE#0 ← (const string) $0
to:@1
main: scope:[main] from @1
(byte*) main::line#0 ← ((byte*)) (number) $400
(byte*) main::cursor#0 ← (byte*) main::line#0
(byte*) main::msg#0 ← (byte[]) MESSAGE#0
to:main::@1
main::@1: scope:[main] from main main::@6
(byte*) main::cursor#5 ← phi( main/(byte*) main::cursor#0 main::@6/(byte*) main::cursor#6 )
(byte*) main::line#4 ← phi( main/(byte*) main::line#0 main::@6/(byte*) main::line#5 )
(byte*) main::msg#2 ← phi( main/(byte*) main::msg#0 main::@6/(byte*) main::msg#1 )
(bool~) main::$0 ← (number) 0 != *((byte*) main::msg#2)
if((bool~) main::$0) goto main::@2
to:main::@return
main::@2: scope:[main] from main::@1
(byte*) main::cursor#4 ← phi( main::@1/(byte*) main::cursor#5 )
(byte*) main::line#3 ← phi( main::@1/(byte*) main::line#4 )
(byte*) main::msg#3 ← phi( main::@1/(byte*) main::msg#2 )
if(*((byte*) main::msg#3)==(byte) '
') goto main::@4
to:main::@5
main::@4: scope:[main] from main::@2
(byte*) main::msg#6 ← phi( main::@2/(byte*) main::msg#3 )
(byte*) main::line#2 ← phi( main::@2/(byte*) main::line#3 )
(byte*) main::line#1 ← (byte*) main::line#2 + (number) $28
(byte*) main::cursor#1 ← (byte*) main::line#1
to:main::@6
main::@5: scope:[main] from main::@2
(byte*) main::line#6 ← phi( main::@2/(byte*) main::line#3 )
(byte*) main::cursor#3 ← phi( main::@2/(byte*) main::cursor#4 )
(byte*) main::msg#4 ← phi( main::@2/(byte*) main::msg#3 )
*((byte*) main::cursor#3) ← *((byte*) main::msg#4)
(byte*) main::cursor#2 ← ++ (byte*) main::cursor#3
to:main::@6
main::@6: scope:[main] from main::@4 main::@5
(byte*) main::cursor#6 ← phi( main::@4/(byte*) main::cursor#1 main::@5/(byte*) main::cursor#2 )
(byte*) main::line#5 ← phi( main::@4/(byte*) main::line#1 main::@5/(byte*) main::line#6 )
(byte*) main::msg#5 ← phi( main::@4/(byte*) main::msg#6 main::@5/(byte*) main::msg#4 )
(byte*) main::msg#1 ← ++ (byte*) main::msg#5
to:main::@1
main::@return: scope:[main] from main::@1
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(const string) $0 = (string) "hello
world"
(label) @1
(label) @2
(label) @begin
(label) @end
(byte[]) MESSAGE
(byte[]) MESSAGE#0
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@2
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@return
(byte*) main::cursor
(byte*) main::cursor#0
(byte*) main::cursor#1
(byte*) main::cursor#2
(byte*) main::cursor#3
(byte*) main::cursor#4
(byte*) main::cursor#5
(byte*) main::cursor#6
(byte*) main::line
(byte*) main::line#0
(byte*) main::line#1
(byte*) main::line#2
(byte*) main::line#3
(byte*) main::line#4
(byte*) main::line#5
(byte*) main::line#6
(byte*) main::msg
(byte*) main::msg#0
(byte*) main::msg#1
(byte*) main::msg#2
(byte*) main::msg#3
(byte*) main::msg#4
(byte*) main::msg#5
(byte*) main::msg#6
Adding number conversion cast (unumber) 0 in (bool~) main::$0 ← (number) 0 != *((byte*) main::msg#2)
Adding number conversion cast (unumber) $28 in (byte*) main::line#1 ← (byte*) main::line#2 + (number) $28
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) main::line#0 ← (byte*)(number) $400
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast $28
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) $28
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte*) main::cursor#0 = (byte*) main::line#0
Alias (byte*) main::msg#2 = (byte*) main::msg#3 (byte*) main::msg#6 (byte*) main::msg#4
Alias (byte*) main::line#2 = (byte*) main::line#3 (byte*) main::line#4 (byte*) main::line#6
Alias (byte*) main::cursor#3 = (byte*) main::cursor#4 (byte*) main::cursor#5
Alias (byte*) main::cursor#1 = (byte*) main::line#1
Successful SSA optimization Pass2AliasElimination
Alias (byte*) main::msg#2 = (byte*) main::msg#5
Successful SSA optimization Pass2AliasElimination
Simple Condition (bool~) main::$0 [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte[]) MESSAGE#0 = $0
Constant (const byte*) main::cursor#0 = (byte*) 1024
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte*) main::msg#0 = MESSAGE#0
Successful SSA optimization Pass2ConstantIdentification
Inlining constant with var siblings (const byte*) main::cursor#0
Inlining constant with var siblings (const byte*) main::msg#0
Constant inlined $0 = (const byte[]) MESSAGE#0
Constant inlined main::cursor#0 = (byte*) 1024
Constant inlined main::msg#0 = (const byte[]) MESSAGE#0
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Created 5 initial phi equivalence classes
Coalesced [12] main::line#9 ← main::line#2
Coalesced [13] main::cursor#9 ← main::cursor#2
Coalesced [16] main::msg#7 ← main::msg#1
Coalesced (already) [17] main::line#7 ← main::line#5
Coalesced [18] main::cursor#7 ← main::cursor#6
Not coalescing [20] main::line#8 ← main::cursor#1
Coalesced [21] main::cursor#8 ← main::cursor#1
Coalesced down to 3 phi equivalence classes
Culled Empty Block (label) @2
Renumbering block main::@4 to main::@3
Renumbering block main::@5 to main::@4
Renumbering block main::@6 to main::@5
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@5
[5] (byte*) main::cursor#3 ← phi( main/(byte*) 1024 main::@5/(byte*) main::cursor#6 )
[5] (byte*) main::line#2 ← phi( main/(byte*) 1024 main::@5/(byte*) main::line#5 )
[5] (byte*) main::msg#2 ← phi( main/(const byte[]) MESSAGE#0 main::@5/(byte*) main::msg#1 )
[6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[7] return
to:@return
main::@2: scope:[main] from main::@1
[8] if(*((byte*) main::msg#2)==(byte) '
') goto main::@3
to:main::@4
main::@4: scope:[main] from main::@2
[9] *((byte*) main::cursor#3) ← *((byte*) main::msg#2)
[10] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3
to:main::@5
main::@5: scope:[main] from main::@3 main::@4
[11] (byte*) main::cursor#6 ← phi( main::@3/(byte*) main::cursor#1 main::@4/(byte*) main::cursor#2 )
[11] (byte*) main::line#5 ← phi( main::@3/(byte*~) main::line#8 main::@4/(byte*) main::line#2 )
[12] (byte*) main::msg#1 ← ++ (byte*) main::msg#2
to:main::@1
main::@3: scope:[main] from main::@2
[13] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28
[14] (byte*~) main::line#8 ← (byte*) main::cursor#1
to:main::@5
VARIABLE REGISTER WEIGHTS
(byte[]) MESSAGE
(void()) main()
(byte*) main::cursor
(byte*) main::cursor#1 16.5
(byte*) main::cursor#2 22.0
(byte*) main::cursor#3 8.25
(byte*) main::cursor#6 16.5
(byte*) main::line
(byte*) main::line#2 6.6000000000000005
(byte*) main::line#5 16.5
(byte*~) main::line#8 22.0
(byte*) main::msg
(byte*) main::msg#1 22.0
(byte*) main::msg#2 6.875
Initial phi equivalence classes
[ main::msg#2 main::msg#1 ]
[ main::line#2 main::line#5 main::line#8 ]
[ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
Complete equivalence classes
[ main::msg#2 main::msg#1 ]
[ main::line#2 main::line#5 main::line#8 ]
[ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
Allocated zp ZP_WORD:2 [ main::msg#2 main::msg#1 ]
Allocated zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ]
Allocated zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
INITIAL ASM
Target platform is c64basic
// File Comments
// Test using some simple supported string escape \n in both string and char
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label cursor = 6
.label msg = 2
.label line = 4
// [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
// [5] phi (byte*) main::cursor#3 = (byte*) 1024 [phi:main->main::@1#0] -- pbuz1=pbuc1
lda #<$400
sta.z cursor
lda #>$400
sta.z cursor+1
// [5] phi (byte*) main::line#2 = (byte*) 1024 [phi:main->main::@1#1] -- pbuz1=pbuc1
lda #<$400
sta.z line
lda #>$400
sta.z line+1
// [5] phi (byte*) main::msg#2 = (const byte[]) MESSAGE#0 [phi:main->main::@1#2] -- pbuz1=pbuc1
lda #<MESSAGE
sta.z msg
lda #>MESSAGE
sta.z msg+1
jmp b1
// main::@1
b1:
// [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2 -- vbuc1_neq__deref_pbuz1_then_la1
ldy #0
lda (msg),y
cmp #0
bne b2
jmp breturn
// main::@return
breturn:
// [7] return
rts
// main::@2
b2:
// [8] if(*((byte*) main::msg#2)==(byte) ' ') goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
lda #-$33
ldy #0
cmp (msg),y
beq b3
jmp b4
// main::@4
b4:
// [9] *((byte*) main::cursor#3) ← *((byte*) main::msg#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (msg),y
ldy #0
sta (cursor),y
// [10] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3 -- pbuz1=_inc_pbuz1
inc.z cursor
bne !+
inc.z cursor+1
!:
// [11] phi from main::@3 main::@4 to main::@5 [phi:main::@3/main::@4->main::@5]
b5_from_b3:
b5_from_b4:
// [11] phi (byte*) main::cursor#6 = (byte*) main::cursor#1 [phi:main::@3/main::@4->main::@5#0] -- register_copy
// [11] phi (byte*) main::line#5 = (byte*~) main::line#8 [phi:main::@3/main::@4->main::@5#1] -- register_copy
jmp b5
// main::@5
b5:
// [12] (byte*) main::msg#1 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1
inc.z msg
bne !+
inc.z msg+1
!:
// [5] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
b1_from_b5:
// [5] phi (byte*) main::cursor#3 = (byte*) main::cursor#6 [phi:main::@5->main::@1#0] -- register_copy
// [5] phi (byte*) main::line#2 = (byte*) main::line#5 [phi:main::@5->main::@1#1] -- register_copy
// [5] phi (byte*) main::msg#2 = (byte*) main::msg#1 [phi:main::@5->main::@1#2] -- register_copy
jmp b1
// main::@3
b3:
// [13] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28 -- pbuz1=pbuz2_plus_vbuc1
lda #$28
clc
adc.z line
sta.z cursor
lda #0
adc.z line+1
sta.z cursor+1
// [14] (byte*~) main::line#8 ← (byte*) main::cursor#1 -- pbuz1=pbuz2
lda.z cursor
sta.z line
lda.z cursor+1
sta.z line+1
jmp b5_from_b3
}
// File Data
MESSAGE: .text @"hello\nworld"
.byte 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2 [ main::msg#2 main::line#2 main::cursor#3 ] ( main:2 [ main::msg#2 main::line#2 main::cursor#3 ] ) always clobbers reg byte a reg byte y
Statement [8] if(*((byte*) main::msg#2)==(byte) '
') goto main::@3 [ main::msg#2 main::line#2 main::cursor#3 ] ( main:2 [ main::msg#2 main::line#2 main::cursor#3 ] ) always clobbers reg byte a reg byte y
Statement [9] *((byte*) main::cursor#3) ← *((byte*) main::msg#2) [ main::msg#2 main::line#2 main::cursor#3 ] ( main:2 [ main::msg#2 main::line#2 main::cursor#3 ] ) always clobbers reg byte a reg byte y
Statement [13] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28 [ main::msg#2 main::cursor#1 ] ( main:2 [ main::msg#2 main::cursor#1 ] ) always clobbers reg byte a
Statement [14] (byte*~) main::line#8 ← (byte*) main::cursor#1 [ main::msg#2 main::line#8 main::cursor#1 ] ( main:2 [ main::msg#2 main::line#8 main::cursor#1 ] ) always clobbers reg byte a
Potential registers zp ZP_WORD:2 [ main::msg#2 main::msg#1 ] : zp ZP_WORD:2 ,
Potential registers zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ] : zp ZP_WORD:4 ,
Potential registers zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ] : zp ZP_WORD:6 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 63.25: zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ] 45.1: zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ] 28.88: zp ZP_WORD:2 [ main::msg#2 main::msg#1 ]
Uplift Scope []
Uplifting [main] best 1443 combination zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ] zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ] zp ZP_WORD:2 [ main::msg#2 main::msg#1 ]
Uplifting [] best 1443 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test using some simple supported string escape \n in both string and char
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label cursor = 6
.label msg = 2
.label line = 4
// [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
// [5] phi (byte*) main::cursor#3 = (byte*) 1024 [phi:main->main::@1#0] -- pbuz1=pbuc1
lda #<$400
sta.z cursor
lda #>$400
sta.z cursor+1
// [5] phi (byte*) main::line#2 = (byte*) 1024 [phi:main->main::@1#1] -- pbuz1=pbuc1
lda #<$400
sta.z line
lda #>$400
sta.z line+1
// [5] phi (byte*) main::msg#2 = (const byte[]) MESSAGE#0 [phi:main->main::@1#2] -- pbuz1=pbuc1
lda #<MESSAGE
sta.z msg
lda #>MESSAGE
sta.z msg+1
jmp b1
// main::@1
b1:
// [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2 -- vbuc1_neq__deref_pbuz1_then_la1
ldy #0
lda (msg),y
cmp #0
bne b2
jmp breturn
// main::@return
breturn:
// [7] return
rts
// main::@2
b2:
// [8] if(*((byte*) main::msg#2)==(byte) ' ') goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
lda #-$33
ldy #0
cmp (msg),y
beq b3
jmp b4
// main::@4
b4:
// [9] *((byte*) main::cursor#3) ← *((byte*) main::msg#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (msg),y
ldy #0
sta (cursor),y
// [10] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3 -- pbuz1=_inc_pbuz1
inc.z cursor
bne !+
inc.z cursor+1
!:
// [11] phi from main::@3 main::@4 to main::@5 [phi:main::@3/main::@4->main::@5]
b5_from_b3:
b5_from_b4:
// [11] phi (byte*) main::cursor#6 = (byte*) main::cursor#1 [phi:main::@3/main::@4->main::@5#0] -- register_copy
// [11] phi (byte*) main::line#5 = (byte*~) main::line#8 [phi:main::@3/main::@4->main::@5#1] -- register_copy
jmp b5
// main::@5
b5:
// [12] (byte*) main::msg#1 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1
inc.z msg
bne !+
inc.z msg+1
!:
// [5] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
b1_from_b5:
// [5] phi (byte*) main::cursor#3 = (byte*) main::cursor#6 [phi:main::@5->main::@1#0] -- register_copy
// [5] phi (byte*) main::line#2 = (byte*) main::line#5 [phi:main::@5->main::@1#1] -- register_copy
// [5] phi (byte*) main::msg#2 = (byte*) main::msg#1 [phi:main::@5->main::@1#2] -- register_copy
jmp b1
// main::@3
b3:
// [13] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28 -- pbuz1=pbuz2_plus_vbuc1
lda #$28
clc
adc.z line
sta.z cursor
lda #0
adc.z line+1
sta.z cursor+1
// [14] (byte*~) main::line#8 ← (byte*) main::cursor#1 -- pbuz1=pbuz2
lda.z cursor
sta.z line
lda.z cursor+1
sta.z line+1
jmp b5_from_b3
}
// File Data
MESSAGE: .text @"hello\nworld"
.byte 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Removing instruction jmp b4
Removing instruction jmp b5
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction ldy #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label b5_from_b3 with b5
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Removing instruction b5_from_b3:
Removing instruction b5_from_b4:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction breturn:
Removing instruction b4:
Removing instruction b1_from_b5:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction ldy #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(byte[]) MESSAGE
(const byte[]) MESSAGE#0 MESSAGE = (string) "hello
world"
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@return
(byte*) main::cursor
(byte*) main::cursor#1 cursor zp ZP_WORD:6 16.5
(byte*) main::cursor#2 cursor zp ZP_WORD:6 22.0
(byte*) main::cursor#3 cursor zp ZP_WORD:6 8.25
(byte*) main::cursor#6 cursor zp ZP_WORD:6 16.5
(byte*) main::line
(byte*) main::line#2 line zp ZP_WORD:4 6.6000000000000005
(byte*) main::line#5 line zp ZP_WORD:4 16.5
(byte*~) main::line#8 line zp ZP_WORD:4 22.0
(byte*) main::msg
(byte*) main::msg#1 msg zp ZP_WORD:2 22.0
(byte*) main::msg#2 msg zp ZP_WORD:2 6.875
zp ZP_WORD:2 [ main::msg#2 main::msg#1 ]
zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ]
zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]
FINAL ASSEMBLER
Score: 1271
// File Comments
// Test using some simple supported string escape \n in both string and char
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label cursor = 6
.label msg = 2
.label line = 4
// [5] phi from main to main::@1 [phi:main->main::@1]
// [5] phi (byte*) main::cursor#3 = (byte*) 1024 [phi:main->main::@1#0] -- pbuz1=pbuc1
lda #<$400
sta.z cursor
lda #>$400
sta.z cursor+1
// [5] phi (byte*) main::line#2 = (byte*) 1024 [phi:main->main::@1#1] -- pbuz1=pbuc1
lda #<$400
sta.z line
lda #>$400
sta.z line+1
// [5] phi (byte*) main::msg#2 = (const byte[]) MESSAGE#0 [phi:main->main::@1#2] -- pbuz1=pbuc1
lda #<MESSAGE
sta.z msg
lda #>MESSAGE
sta.z msg+1
// main::@1
b1:
// while(*msg)
// [6] if((byte) 0!=*((byte*) main::msg#2)) goto main::@2 -- vbuc1_neq__deref_pbuz1_then_la1
ldy #0
lda (msg),y
cmp #0
bne b2
// main::@return
// }
// [7] return
rts
// main::@2
b2:
// case '\n':
// line += 0x28;
// cursor = line;
// break;
// [8] if(*((byte*) main::msg#2)==(byte) ' ') goto main::@3 -- _deref_pbuz1_eq_vbuc1_then_la1
lda #-$33
ldy #0
cmp (msg),y
beq b3
// main::@4
// *cursor++ = *msg
// [9] *((byte*) main::cursor#3) ← *((byte*) main::msg#2) -- _deref_pbuz1=_deref_pbuz2
lda (msg),y
sta (cursor),y
// *cursor++ = *msg;
// [10] (byte*) main::cursor#2 ← ++ (byte*) main::cursor#3 -- pbuz1=_inc_pbuz1
inc.z cursor
bne !+
inc.z cursor+1
!:
// [11] phi from main::@3 main::@4 to main::@5 [phi:main::@3/main::@4->main::@5]
// [11] phi (byte*) main::cursor#6 = (byte*) main::cursor#1 [phi:main::@3/main::@4->main::@5#0] -- register_copy
// [11] phi (byte*) main::line#5 = (byte*~) main::line#8 [phi:main::@3/main::@4->main::@5#1] -- register_copy
// main::@5
b5:
// msg++;
// [12] (byte*) main::msg#1 ← ++ (byte*) main::msg#2 -- pbuz1=_inc_pbuz1
inc.z msg
bne !+
inc.z msg+1
!:
// [5] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
// [5] phi (byte*) main::cursor#3 = (byte*) main::cursor#6 [phi:main::@5->main::@1#0] -- register_copy
// [5] phi (byte*) main::line#2 = (byte*) main::line#5 [phi:main::@5->main::@1#1] -- register_copy
// [5] phi (byte*) main::msg#2 = (byte*) main::msg#1 [phi:main::@5->main::@1#2] -- register_copy
jmp b1
// main::@3
b3:
// line += 0x28
// [13] (byte*) main::cursor#1 ← (byte*) main::line#2 + (byte) $28 -- pbuz1=pbuz2_plus_vbuc1
lda #$28
clc
adc.z line
sta.z cursor
lda #0
adc.z line+1
sta.z cursor+1
// [14] (byte*~) main::line#8 ← (byte*) main::cursor#1 -- pbuz1=pbuz2
lda.z cursor
sta.z line
lda.z cursor+1
sta.z line+1
jmp b5
}
// File Data
MESSAGE: .text @"hello\nworld"
.byte 0

View File

@ -0,0 +1,29 @@
(label) @1
(label) @begin
(label) @end
(byte[]) MESSAGE
(const byte[]) MESSAGE#0 MESSAGE = (string) "hello
world"
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@return
(byte*) main::cursor
(byte*) main::cursor#1 cursor zp ZP_WORD:6 16.5
(byte*) main::cursor#2 cursor zp ZP_WORD:6 22.0
(byte*) main::cursor#3 cursor zp ZP_WORD:6 8.25
(byte*) main::cursor#6 cursor zp ZP_WORD:6 16.5
(byte*) main::line
(byte*) main::line#2 line zp ZP_WORD:4 6.6000000000000005
(byte*) main::line#5 line zp ZP_WORD:4 16.5
(byte*~) main::line#8 line zp ZP_WORD:4 22.0
(byte*) main::msg
(byte*) main::msg#1 msg zp ZP_WORD:2 22.0
(byte*) main::msg#2 msg zp ZP_WORD:2 6.875
zp ZP_WORD:2 [ main::msg#2 main::msg#1 ]
zp ZP_WORD:4 [ main::line#2 main::line#5 main::line#8 ]
zp ZP_WORD:6 [ main::cursor#3 main::cursor#6 main::cursor#1 main::cursor#2 ]

View File

@ -0,0 +1,31 @@
// Test using some simple supported string escape characters in PETSCII
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label memA = $ff
main: {
.label i = 2
lda #0
sta.z i
b1:
lda #0
ldy.z i
cmp MESSAGE,y
bne b2
rts
b2:
ldy.z i
lda MESSAGE,y
jsr chrout
inc.z i
jmp b1
}
// chrout(byte register(A) c)
chrout: {
sta memA
jsr $ffd2
rts
}
.encoding "petscii_mixed"
MESSAGE: .text @"hello\nworld"
.byte 0

View File

@ -0,0 +1,33 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@3
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 )
[6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[7] return
to:@return
main::@2: scope:[main] from main::@1
[8] (byte) chrout::c#0 ← *((const byte[]) MESSAGE#0 + (byte) main::i#2)
[9] call chrout
to:main::@3
main::@3: scope:[main] from main::@2
[10] (byte) main::i#1 ← ++ (byte) main::i#2
to:main::@1
chrout: scope:[chrout] from main::@2
[11] *((const byte*) memA#0) ← (byte) chrout::c#0
asm { ldamemA jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
[13] return
to:@return

View File

@ -0,0 +1,496 @@
Warning! Adding boolean cast to non-boolean condition *((byte[]) MESSAGE + (byte) main::i)
Culled Empty Block (label) main::@4
Culled Empty Block (label) main::@3
Culled Empty Block (label) main::@5
Culled Empty Block (label) main::@6
Culled Empty Block (label) @1
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte[]) MESSAGE#0 ← (const string) $0
(byte*) memA#0 ← ((byte*)) (number) $ff
to:@2
main: scope:[main] from @2
(byte) main::i#0 ← (number) 0
to:main::@1
main::@1: scope:[main] from main main::@7
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@7/(byte) main::i#1 )
(bool~) main::$1 ← (number) 0 != *((byte[]) MESSAGE#0 + (byte) main::i#2)
if((bool~) main::$1) goto main::@2
to:main::@return
main::@2: scope:[main] from main::@1
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
(byte) chrout::c#0 ← *((byte[]) MESSAGE#0 + (byte) main::i#3)
call chrout
to:main::@7
main::@7: scope:[main] from main::@2
(byte) main::i#4 ← phi( main::@2/(byte) main::i#3 )
(byte) main::i#1 ← ++ (byte) main::i#4
to:main::@1
main::@return: scope:[main] from main::@1
return
to:@return
chrout: scope:[chrout] from main::@2
(byte) chrout::c#1 ← phi( main::@2/(byte) chrout::c#0 )
*((byte*) memA#0) ← (byte) chrout::c#1
asm { ldamemA jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
return
to:@return
@2: scope:[] from @begin
call main
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(const string) $0 = (string) "hello
world"pm
(label) @2
(label) @3
(label) @begin
(label) @end
(byte[]) MESSAGE
(byte[]) MESSAGE#0
(void()) chrout((byte) chrout::c)
(label) chrout::@return
(byte) chrout::c
(byte) chrout::c#0
(byte) chrout::c#1
(void()) main()
(bool~) main::$1
(label) main::@1
(label) main::@2
(label) main::@7
(label) main::@return
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte) main::i#3
(byte) main::i#4
(byte*) memA
(byte*) memA#0
Adding number conversion cast (unumber) 0 in (byte) main::i#0 ← (number) 0
Adding number conversion cast (unumber) 0 in (bool~) main::$1 ← (number) 0 != *((byte[]) MESSAGE#0 + (byte) main::i#2)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) memA#0 ← (byte*)(number) $ff
Inlining cast (byte) main::i#0 ← (unumber)(number) 0
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 255
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) main::i#2 = (byte) main::i#3 (byte) main::i#4
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte) chrout::c#1 (byte) chrout::c#0
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) main::$1 [5] if((byte) 0!=*((byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte[]) MESSAGE#0 = $0
Constant (const byte*) memA#0 = (byte*) 255
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Inlining constant with var siblings (const byte) main::i#0
Constant inlined $0 = (const byte[]) MESSAGE#0
Constant inlined main::i#0 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Calls in [main] to chrout:10
Created 1 initial phi equivalence classes
Coalesced [12] main::i#5 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @3
Renumbering block @2 to @1
Renumbering block main::@7 to main::@3
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@3
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 )
[6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[7] return
to:@return
main::@2: scope:[main] from main::@1
[8] (byte) chrout::c#0 ← *((const byte[]) MESSAGE#0 + (byte) main::i#2)
[9] call chrout
to:main::@3
main::@3: scope:[main] from main::@2
[10] (byte) main::i#1 ← ++ (byte) main::i#2
to:main::@1
chrout: scope:[chrout] from main::@2
[11] *((const byte*) memA#0) ← (byte) chrout::c#0
asm { ldamemA jsr$ffd2 }
to:chrout::@return
chrout::@return: scope:[chrout] from chrout
[13] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte[]) MESSAGE
(void()) chrout((byte) chrout::c)
(byte) chrout::c
(byte) chrout::c#0 13.0
(void()) main()
(byte) main::i
(byte) main::i#1 22.0
(byte) main::i#2 11.0
(byte*) memA
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Added variable chrout::c#0 to zero page equivalence class [ chrout::c#0 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ chrout::c#0 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:3 [ chrout::c#0 ]
INITIAL ASM
Target platform is c64basic
// File Comments
// Test using some simple supported string escape characters in PETSCII
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label memA = $ff
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label i = 2
// [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z i
jmp b1
// main::@1
b1:
// [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 -- vbuc1_neq_pbuc2_derefidx_vbuz1_then_la1
lda #0
ldy.z i
cmp MESSAGE,y
bne b2
jmp breturn
// main::@return
breturn:
// [7] return
rts
// main::@2
b2:
// [8] (byte) chrout::c#0 ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) -- vbuz1=pbuc1_derefidx_vbuz2
ldy.z i
lda MESSAGE,y
sta.z chrout.c
// [9] call chrout
jsr chrout
jmp b3
// main::@3
b3:
// [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
}
// chrout
// chrout(byte zeropage(3) c)
chrout: {
.label c = 3
// [11] *((const byte*) memA#0) ← (byte) chrout::c#0 -- _deref_pbuc1=vbuz1
lda.z c
sta memA
// asm { ldamemA jsr$ffd2 }
lda memA
jsr $ffd2
jmp breturn
// chrout::@return
breturn:
// [13] return
rts
}
// File Data
.encoding "petscii_mixed"
MESSAGE: .text @"hello\nworld"
.byte 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Statement asm { ldamemA jsr$ffd2 } always clobbers reg byte a reg byte x reg byte y
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Statement [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a reg byte y
Statement [8] (byte) chrout::c#0 ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) [ main::i#2 chrout::c#0 ] ( main:2 [ main::i#2 chrout::c#0 ] ) always clobbers reg byte y
Statement asm { ldamemA jsr$ffd2 } always clobbers reg byte a reg byte x reg byte y
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 ,
Potential registers zp ZP_BYTE:3 [ chrout::c#0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 33: zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Uplift Scope [chrout] 13: zp ZP_BYTE:3 [ chrout::c#0 ]
Uplift Scope []
Uplifting [main] best 549 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Uplifting [chrout] best 516 combination reg byte a [ chrout::c#0 ]
Uplifting [] best 516 combination
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Uplifting [main] best 516 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test using some simple supported string escape characters in PETSCII
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label memA = $ff
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label i = 2
// [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z i
jmp b1
// main::@1
b1:
// [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 -- vbuc1_neq_pbuc2_derefidx_vbuz1_then_la1
lda #0
ldy.z i
cmp MESSAGE,y
bne b2
jmp breturn
// main::@return
breturn:
// [7] return
rts
// main::@2
b2:
// [8] (byte) chrout::c#0 ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) -- vbuaa=pbuc1_derefidx_vbuz1
ldy.z i
lda MESSAGE,y
// [9] call chrout
jsr chrout
jmp b3
// main::@3
b3:
// [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
}
// chrout
// chrout(byte register(A) c)
chrout: {
// [11] *((const byte*) memA#0) ← (byte) chrout::c#0 -- _deref_pbuc1=vbuaa
sta memA
// asm { ldamemA jsr$ffd2 }
lda memA
jsr $ffd2
jmp breturn
// chrout::@return
breturn:
// [13] return
rts
}
// File Data
.encoding "petscii_mixed"
MESSAGE: .text @"hello\nworld"
.byte 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Removing instruction jmp b3
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda memA
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction breturn:
Removing instruction b3:
Removing instruction b1_from_b3:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(byte[]) MESSAGE
(const byte[]) MESSAGE#0 MESSAGE = (string) "hello
world"pm
(void()) chrout((byte) chrout::c)
(label) chrout::@return
(byte) chrout::c
(byte) chrout::c#0 reg byte a 13.0
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(byte) main::i
(byte) main::i#1 i zp ZP_BYTE:2 22.0
(byte) main::i#2 i zp ZP_BYTE:2 11.0
(byte*) memA
(const byte*) memA#0 memA = (byte*) 255
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
reg byte a [ chrout::c#0 ]
FINAL ASSEMBLER
Score: 407
// File Comments
// Test using some simple supported string escape characters in PETSCII
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label memA = $ff
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label i = 2
// [5] phi from main to main::@1 [phi:main->main::@1]
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z i
// main::@1
b1:
// while(MESSAGE[i])
// [6] if((byte) 0!=*((const byte[]) MESSAGE#0 + (byte) main::i#2)) goto main::@2 -- vbuc1_neq_pbuc2_derefidx_vbuz1_then_la1
lda #0
ldy.z i
cmp MESSAGE,y
bne b2
// main::@return
// }
// [7] return
rts
// main::@2
b2:
// chrout(MESSAGE[i++])
// [8] (byte) chrout::c#0 ← *((const byte[]) MESSAGE#0 + (byte) main::i#2) -- vbuaa=pbuc1_derefidx_vbuz1
ldy.z i
lda MESSAGE,y
// [9] call chrout
jsr chrout
// main::@3
// chrout(MESSAGE[i++]);
// [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
}
// chrout
// chrout(byte register(A) c)
chrout: {
// *memA = c
// [11] *((const byte*) memA#0) ← (byte) chrout::c#0 -- _deref_pbuc1=vbuaa
sta memA
// asm
// asm { ldamemA jsr$ffd2 }
jsr $ffd2
// chrout::@return
// }
// [13] return
rts
}
// File Data
.encoding "petscii_mixed"
MESSAGE: .text @"hello\nworld"
.byte 0

View File

@ -0,0 +1,23 @@
(label) @1
(label) @begin
(label) @end
(byte[]) MESSAGE
(const byte[]) MESSAGE#0 MESSAGE = (string) "hello
world"pm
(void()) chrout((byte) chrout::c)
(label) chrout::@return
(byte) chrout::c
(byte) chrout::c#0 reg byte a 13.0
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(byte) main::i
(byte) main::i#1 i zp ZP_BYTE:2 22.0
(byte) main::i#2 i zp ZP_BYTE:2 11.0
(byte*) memA
(const byte*) memA#0 memA = (byte*) 255
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
reg byte a [ chrout::c#0 ]