311 lines
8.2 KiB
Plaintext
311 lines
8.2 KiB
Plaintext
|
package slangc.parser;
|
||
|
|
||
|
/**
|
||
|
* Based on experience with previous scanners, I decided to split the language definition from the scanner sourceFile
|
||
|
* as much as practical. This makes it a lot easier to reuse scanner code in other projects later.
|
||
|
*
|
||
|
* @author Zak
|
||
|
*
|
||
|
*/
|
||
|
public class Language {
|
||
|
public static final String[] DEFAULT_LINE_COMMENT_PREFIXES = new String[] {"#!", "//"};
|
||
|
public static final String[][] DEFAULT_LONG_COMMENT_TERMINATORS = new String[][] {new String[] {"/*", "*/"}};
|
||
|
public static final String[][] DEFAULT_STRING_TERMINATORS = new String[][] {new String[] {"\"", "\""}};
|
||
|
public static final String[][] DEFAULT_CHAR_TERMINATORS = new String[][] {new String[] {"'", "'"}};
|
||
|
public static final String[][] DEFAULT_ESCAPES = new String[][] {
|
||
|
new String[] {"\\n", "\n"}, new String[] {"\\t", "\t"},
|
||
|
new String[] {"\\\"", "\""}, new String[] {"\\'", "'"},
|
||
|
new String[] {"\\\\", "\\"}
|
||
|
};
|
||
|
public static final String[] DEFAULT_STRING_FORBIDDEN_ESCAPES = new String[] {/*"\\", "\""*/};
|
||
|
public static final String[] DEFAULT_CHAR_FORBIDDEN_ESCAPES = new String[] {"\\"/*, "'"*/};
|
||
|
public static final String[] DEFAULT_HEX_PREFIXES = new String[] { "0x", "0X" };
|
||
|
public static final String[] DEFAULT_BIN_PREFIXES = new String[] { "0b", "0B" };
|
||
|
public static final String[] DEFAULT_OPERATORS = new String[] {
|
||
|
"{", "}", "(", ")", "[", "]",
|
||
|
"==",
|
||
|
"+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "++", "--", "=",
|
||
|
"&&", "||", "&", "|", "?", "::", ":", "->",
|
||
|
"<<=", ">>=", ">>>=",
|
||
|
"<<",
|
||
|
/*">>>", ">>",*/ /* These are handled as special cases of ">", to allow for ">>" in generic types */
|
||
|
"!=", "<=", ">=", "<", ">",
|
||
|
"+", "-", "*", "/", "%", "^",
|
||
|
"!",
|
||
|
"~",
|
||
|
// The "@" & "..." operators could possibly be disabled for some legacy code,
|
||
|
// but there's no practical need to be that strict
|
||
|
"@", "...", "##","#",
|
||
|
".", ",", ";"
|
||
|
};
|
||
|
public enum Key {
|
||
|
MODULE,
|
||
|
IMPORT,
|
||
|
PUBLIC,
|
||
|
PRIVATE,
|
||
|
PROTECTED,
|
||
|
ABSTRACT,
|
||
|
NATIVE,
|
||
|
SYNCHRONISED,
|
||
|
CLASS,
|
||
|
INTERFACE,
|
||
|
ENUM,
|
||
|
IMPLEMENTS,
|
||
|
EXTENDS,
|
||
|
THROWS,
|
||
|
VOID,
|
||
|
BIT,
|
||
|
BYTE,
|
||
|
SHORT,
|
||
|
COMPAT_CHAR,
|
||
|
INT,
|
||
|
LONG,
|
||
|
FLOAT,
|
||
|
DOUBLE,
|
||
|
IF,
|
||
|
ELSE,
|
||
|
DO,
|
||
|
WHILE,
|
||
|
FOR,
|
||
|
BREAK,
|
||
|
CONTINUE,
|
||
|
SWITCH,
|
||
|
CASE,
|
||
|
DEFAULT,
|
||
|
RETURN,
|
||
|
TRY,
|
||
|
CATCH,
|
||
|
FINALLY,
|
||
|
THROW,
|
||
|
ASSERT,
|
||
|
NEW,
|
||
|
TRUE,
|
||
|
FALSE,
|
||
|
NULL,
|
||
|
THIS,
|
||
|
SUPER,
|
||
|
INSTANCEOF,
|
||
|
TRANSIENT,
|
||
|
VOLATILE,
|
||
|
COMPAT_STRICTFP,
|
||
|
GOTO,
|
||
|
CONST,
|
||
|
WILDCARD,
|
||
|
NON_SEALED,
|
||
|
POINTER,
|
||
|
DUCK,
|
||
|
STATIC, FINAL
|
||
|
}
|
||
|
public static final String[] DEFAULT_KEYWORDS = new String[] {
|
||
|
"package", "module", "import",
|
||
|
"public", "private", "protected", "final", "abstract", "static", "native",
|
||
|
"synchronized", "synchronised",
|
||
|
"class", "interface",
|
||
|
"enum",// NOTE: The enum keyword will be disabled if necessary by the LegacyLanguage subclass
|
||
|
"implements", "extends", "throws",
|
||
|
"void",
|
||
|
"boolean", "byte", "short", "char", "int", "long", "float", "double",
|
||
|
"if", "else", "do", "while", "for", "break", "continue", "switch", "case", "default", "return",
|
||
|
"try", "catch", "finally", "throw", "assert",
|
||
|
"new",
|
||
|
"true", "false", "null",
|
||
|
"this", "super",
|
||
|
"instanceof",
|
||
|
"transient", "volatile", "strictfp",
|
||
|
"goto", "const", // These are reserved but not implemented
|
||
|
// This will be disabled by LegacyLanguage as necessary:
|
||
|
"_", // A special keyword as of v9
|
||
|
"non-sealed", // Added at some point???
|
||
|
// Not technically keywords: "var", // Added in v10
|
||
|
// Also not technically keywords: "record", "permits", "sealed", "yield"
|
||
|
// These will also be disabled for legacy code:
|
||
|
//"int8","int16","int32","int64","uint8","uint16","uint32","uint64",
|
||
|
"pointer",
|
||
|
"duck"
|
||
|
// maybe "cpuword" & "ucpuword"?
|
||
|
};
|
||
|
|
||
|
public Language() {
|
||
|
// TODO Auto-generated constructor stub
|
||
|
}
|
||
|
|
||
|
public String[][] getStringEscapes() {
|
||
|
return DEFAULT_ESCAPES;
|
||
|
}
|
||
|
|
||
|
public String[] getLineCommentPrefixes() {
|
||
|
return DEFAULT_LINE_COMMENT_PREFIXES;
|
||
|
}
|
||
|
|
||
|
public String[][] getLongCommentTerminators() {
|
||
|
return DEFAULT_LONG_COMMENT_TERMINATORS;
|
||
|
}
|
||
|
|
||
|
public String[][] getStringTerminators() {
|
||
|
return DEFAULT_STRING_TERMINATORS;
|
||
|
}
|
||
|
|
||
|
public String[] getStringForbiddenEscapes() {
|
||
|
return DEFAULT_STRING_FORBIDDEN_ESCAPES;
|
||
|
}
|
||
|
|
||
|
public String[][] getCharTerminators() {
|
||
|
return DEFAULT_CHAR_TERMINATORS;
|
||
|
}
|
||
|
|
||
|
public String[] getCharForbiddenEscapes() {
|
||
|
return DEFAULT_CHAR_FORBIDDEN_ESCAPES;
|
||
|
}
|
||
|
|
||
|
public String[][] getEscapes() {
|
||
|
// TODO: Better escape handling...
|
||
|
return DEFAULT_ESCAPES;
|
||
|
}
|
||
|
|
||
|
public String[] getHexPrefixes() {
|
||
|
return DEFAULT_HEX_PREFIXES;
|
||
|
}
|
||
|
|
||
|
public String[] getBinPrefixes() {
|
||
|
return DEFAULT_BIN_PREFIXES;
|
||
|
}
|
||
|
|
||
|
public String[] getOperators() {
|
||
|
return DEFAULT_OPERATORS;
|
||
|
}
|
||
|
|
||
|
public String[] getKeywords() {
|
||
|
return DEFAULT_KEYWORDS;
|
||
|
}
|
||
|
|
||
|
public boolean matches(Key key, String str) {
|
||
|
switch (key) {
|
||
|
case Key.MODULE:
|
||
|
return str.equals("module") || str.equals("package");
|
||
|
case Key.IMPORT:
|
||
|
return str.equals("import");
|
||
|
case Key.PUBLIC:
|
||
|
return str.equals("public");
|
||
|
case Key.PRIVATE:
|
||
|
return str.equals("private");
|
||
|
case Key.PROTECTED:
|
||
|
return str.equals("protected");
|
||
|
case Key.ABSTRACT:
|
||
|
return str.equals("abstract");
|
||
|
case Key.NATIVE:
|
||
|
return str.equals("native");
|
||
|
case Key.SYNCHRONISED:
|
||
|
return str.equals("synchronised") || str.equals("synchronized");
|
||
|
case Key.CLASS:
|
||
|
return str.equals("class");
|
||
|
case Key.INTERFACE:
|
||
|
return str.equals("interface");
|
||
|
case Key.ENUM:
|
||
|
return str.equals("enum");
|
||
|
case Key.IMPLEMENTS:
|
||
|
return str.equals("implements");
|
||
|
case Key.EXTENDS:
|
||
|
return str.equals("extends");
|
||
|
case Key.THROWS:
|
||
|
return str.equals("throws");
|
||
|
case Key.VOID:
|
||
|
return str.equals("void");
|
||
|
case Key.BIT:
|
||
|
return str.equals("boolean");
|
||
|
case Key.BYTE:
|
||
|
return str.equals("byte");
|
||
|
case Key.SHORT:
|
||
|
return str.equals("short");
|
||
|
case Key.COMPAT_CHAR:
|
||
|
return str.equals("char");
|
||
|
case Key.INT:
|
||
|
return str.equals("int");
|
||
|
case Key.LONG:
|
||
|
return str.equals("long");
|
||
|
case Key.FLOAT:
|
||
|
return str.equals("float");
|
||
|
case Key.DOUBLE:
|
||
|
return str.equals("double");
|
||
|
case Key.IF:
|
||
|
return str.equals("if");
|
||
|
case Key.ELSE:
|
||
|
return str.equals("else");
|
||
|
case Key.DO:
|
||
|
return str.equals("do");
|
||
|
case Key.WHILE:
|
||
|
return str.equals("while");
|
||
|
case Key.FOR:
|
||
|
return str.equals("for");
|
||
|
case Key.BREAK:
|
||
|
return str.equals("break");
|
||
|
case Key.CONTINUE:
|
||
|
return str.equals("continue");
|
||
|
case Key.SWITCH:
|
||
|
return str.equals("switch");
|
||
|
case Key.CASE:
|
||
|
return str.equals("case");
|
||
|
case Key.DEFAULT:
|
||
|
return str.equals("default");
|
||
|
case Key.RETURN:
|
||
|
return str.equals("return");
|
||
|
case Key.TRY:
|
||
|
return str.equals("try");
|
||
|
case Key.CATCH:
|
||
|
return str.equals("catch");
|
||
|
case Key.FINALLY:
|
||
|
return str.equals("finally");
|
||
|
case Key.THROW:
|
||
|
return str.equals("throw");
|
||
|
case Key.ASSERT:
|
||
|
return str.equals("assert");
|
||
|
case Key.NEW:
|
||
|
return str.equals("new");
|
||
|
case Key.TRUE:
|
||
|
return str.equals("true");
|
||
|
case Key.FALSE:
|
||
|
return str.equals("false");
|
||
|
case Key.NULL:
|
||
|
return str.equals("null");
|
||
|
case Key.THIS:
|
||
|
return str.equals("this");
|
||
|
case Key.SUPER:
|
||
|
return str.equals("super");
|
||
|
case Key.INSTANCEOF:
|
||
|
return str.equals("instanceof");
|
||
|
case Key.TRANSIENT:
|
||
|
return str.equals("transient");
|
||
|
case Key.VOLATILE:
|
||
|
return str.equals("volatile");
|
||
|
case Key.COMPAT_STRICTFP:
|
||
|
return str.equals("strictfp");
|
||
|
case Key.GOTO:
|
||
|
return str.equals("goto");
|
||
|
case Key.CONST:
|
||
|
return str.equals("const");
|
||
|
case Key.WILDCARD:
|
||
|
return str.equals("wildcard");
|
||
|
case Key.NON_SEALED:
|
||
|
return str.equals("non-sealed");
|
||
|
case Key.POINTER:
|
||
|
return str.equals("pointer");
|
||
|
case Key.DUCK:
|
||
|
return str.equals("duck");
|
||
|
case Key.STATIC:
|
||
|
return str.equals("static");
|
||
|
case Key.FINAL:
|
||
|
return str.equals("final");
|
||
|
|
||
|
default:
|
||
|
throw new Error("TODO: Keyword matching for " + key);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public boolean applySetting(String key, String value, boolean reset, boolean append) {
|
||
|
return false; // This should only return true if the setting is applied
|
||
|
}
|
||
|
|
||
|
public String getSettingInfo(String key) {
|
||
|
return "Setting info cannot be retrieved";
|
||
|
}
|
||
|
}
|