Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class LSSParser {
- public static final Pattern LONG_COMMENT = Pattern.compile("(/\\*.*\\*/).*");
- public static final Pattern SHORT_COMMENT = Pattern.compile("(//[.&&^\\n]*\\n).*");
- public static LSSProgram compile (String s) {
- return build(compile(parse(tokenize(s))));
- }
- private static ArrayList<LSSToken> tokenize (String s) {
- int index = 0;
- ArrayList<LSSToken> tokens = new ArrayList<LSSToken>();
- while (s.length() > index) {
- String ss = s.substring(index);
- if (ss.matches("[ \f\t].*")) {
- index++;
- continue;
- }
- Matcher m = LONG_COMMENT.matcher(ss);
- if (m.matches()) {
- index += m.group(1).length();
- continue;
- }
- Matcher m = SHORT_COMMENT.matcher(ss);
- if (m.matches()) {
- index += m.group(1).length();
- continue;
- }
- LSSToken t = LSSToken.parse(ss);
- index += t.getText().length();
- tokens.add(t);
- }
- return tokens;
- }
- private static HashMap<String, Object> parse (ArrayList<LSSToken> tokens) {
- LSSParserState s = LSSParserState::PROGRAM_START;
- Iterator<LSSToken> it = tokens.iterator();
- HashMap<String, Object> map = new HashMap<String, Object>();
- while (it.hasNext()) s = s.parse(it, map);
- return map;
- }
- private static HashMap<String, Object> compile (HashMap<String, Object> map) {
- HashMap<String, Object> map2 = new HashMap<String, Object>();
- ArrayList<LSSPreMethod> premethods = (ArrayList<LSSPreMethod>) map.get("methods");
- LSSMethod[] postmethods = new LSSMethod[premethods.length];
- int size = 0;
- for (int i = 0; i < premethods.length; i++)
- size += (postmethods[i] = LSSMethod.compile(premethods.get(i), map, map2)).getLength();
- map2.put("methods", postmethods);
- map2.put("methods size", size);
- }
- }
- public interface LSSParserState {
- LSSParserState parse (Iterator<LSSToken> it, HashMap<String, Object> map);
- static LSSParserState PROGRAM_START (Iterator<LSSToken> it, HashMap<String, Object> map) {
- LSSToken next = it.next();
- if (next.getText().equals("@"))
- return LSSParserState::PROGRAM_ANNOTATION;
- else if (next.getText().equals("program"))
- return LSSParserState::PROGRAM_DECLARATION;
- else {
- LSSParser.error("invalid token: file started with " + next.getText());
- while (!next.getText().equals("@")
- && !next.getText().equals("program")
- && !next.getText().equals("enum")
- && !next.getText().equals("struct")) next = it.next();
- if (next.getText().equals("@"))
- return LSSParserState::PROGRAM_ANNOTATION;
- else if (next.getText().equals("program"))
- return LSSParserState::PROGRAM_DECLARATION;
- else if (next.getText().equals("enum"))
- return LSSParserState::ENUM_DECLARATION;
- else if (next.getText().equals("struct"))
- return LSSParserState::STRUCT_DECLARATION;
- }
- }
- static LSSParserState PROGRAM_ANNOTATION (Iterator<LSSToken> it, HashMap<String, Object> map) {
- String error = "";
- LSSToken next = it.next();
- nominal: {
- if (!(next instanceof LSSGenericToken)) {
- error = "invalid token: expected annotation name, got " + next.getText();
- break nominal;
- }
- String name = next.getText();
- next = it.next();
- if (!next.getText().equals("(")) {
- error = "invalid token: expected annotation params, got " + next.getText();
- break nominal;
- }
- ArrayList<LSSToken[]> params = new ArrayList<LSSToken[]>();
- next = it.next();
- while (!next.getText().equals(")")) {
- ArrayList<LSSToken> params = new ArrayList<LSSToken>();
- while (!next.getText().equals(",") && !next.getText().equals(")")) {
- params.add(next);
- next = it.next();
- }
- ((ArrayList<Map.Entry<String, LSSToken[][]>>) map.computeIfAbsent("program annotations", ArrayList<Map.Entry<String, LSSToken[][]>>::new))
- .add(Map.<String, LSSToken[][]>entry(name, params.toArray(new LSSToken[params.size()][])));
- }
- return LSSParserState::PROGRAM_START;
- }
- LSSParser.error(error);
- while (!next.getText().equals("@")
- && !next.getText().equals("program")
- && !next.getText().equals("enum")
- && !next.getText().equals("struct")) next = it.next();
- if (next.getText().equals("@"))
- return LSSParserState::PROGRAM_ANNOTATION;
- else if (next.getText().equals("program"))
- return LSSParserState::PROGRAM_DECLARATION;
- else if (next.getText().equals("enum"))
- return LSSParserState::ENUM_DECLARATION;
- else if (next.getText().equals("struct"))
- return LSSParserState::STRUCT_DECLARATION;
- }
- static LSSParserState PROGRAM_DECLARATION (Iterator<LSSToken> it, HashMap<String, Object> map) {
- String error = "";
- LSSToken next = it.next();
- nominal: {
- if (!(next instanceof LSSGenericToken)) {
- if (next.getText().equals("{")) {
- map.put("name", "unnamed");
- return PROGRAM_DATA;
- }
- error = "invalid token: expected program name, got " + next.getText();
- break nominal;
- }
- map.put("name", next.getText());
- if (!next.getText().equals("{")) {
- error = "invalid token: expected program opening bracket, got " + next.getText();
- break nominal;
- }
- return LSSParserState::PROGRAM_DATA;
- }
- LSSParser.error(error);
- while (it.hasNext()) it.next();
- return null;
- }
- static LSSParserState ENUM_DECLARATION (Iterator<LSSToken> it, HashMap<String, Object> map) {
- String error = "";
- LSSToken next = it.next();
- nominal: {
- if (!(next instanceof LSSGenericToken)) {
- error = "invalid token: expected enum name, got " + next.getText();
- break nominal;
- }
- map.put("enum name", next.getText());
- if (!next.getText().equals("{")) {
- error = "invalid token: expected enum opening bracket, got " + next.getText();
- break nominal;
- }
- return LSSParserState::ENUM_DATA;
- }
- LSSParser.error(error);
- while (it.hasNext()) it.next();
- return null;
- }
- static LSSParserState ENUM_DATA (Iterator<LSSToken> it, HashMap<String, Object> map) {
- String error = "";
- LSSToken next = it.next();
- nominal: {
- if (next.getText().equals("}")) {
- HashMap<String, HashMap<String, Integer>> enumeration = (HashMap<String, HashMap<String, Integer>>) map.computeIfAbsent("enums", HashMap<String, HashMap<String, Integer>>::new);
- if (enumeration.containsKey(map.get("enum name"))) {
- error = "enum name " + map.get("enum name") + " in use";
- break nominal;
- }
- enumeration.put((String) map.get("enum name"), (HashMap<String, Integer>) map.computeIfAbsent("enum", HashMap<String, Integer>::new));
- map.remove("enum name");
- map.remove("enum");
- return LSSParserState::PROGRAM_START;
- }
- if (!(next instanceof LSSGenericToken)) {
- error = "invalid token: expected enum constant, got " + next.getText();
- break nominal;
- }
- String name = next.getText();
- int assignment = null;
- if ((next = it.next()).getText().equals("=")) {
- if (!((next = it.next()) instanceof LSSNumericLiteralToken)) {
- error = "invalid token: expected numeric literal, got " + next.getText();
- break nominal;
- }
- assignment = ((LSSNumericLiteralToken) next).getValue();
- next = it.next();
- }
- if (!next.getText().equals(";")) {
- error = "invalid token: expected semicolon, got " + next.getText();
- break nominal;
- }
- HashMap<String, Integer> enumeration = (HashMap<String, Integer>) map.computeIfAbsent("enum", HashMap<String, Integer>::new);
- if (enumeration.containsKey(name)) {
- error = "enum constant " + name + " is already in use";
- break nominal;
- }
- enumeration.put(name, assignment);
- map.put(enumeration);
- return LSSParserState::ENUM_DATA;
- }
- LSSParser.error(error);
- while (!next.getText().equals(";") && !next.getText().equals("}")) next = it.next();
- if (next.getText().equals(";")) return LSSParserState::ENUM_DATA;
- else return LSSParserState::PROGRAM_START;
- }
- static LSSParserState STRUCT_DECLARATION (Iterator<LSSToken> it, HashMap<String, Object> map) {
- String error = "";
- LSSToken next = it.next();
- nominal: {
- if (!(next instanceof LSSGenericToken)) {
- error = "invalid token: expected struct name, got " + next.getText();
- break nominal;
- }
- map.put("struct name", next.getText());
- if (!next.getText().equals("{")) {
- error = "invalid token: expected struct opening bracket, got " + next.getText();
- break nominal;
- }
- return LSSParserState::STRUCT_DATA;
- }
- LSSParser.error(error);
- while (it.hasNext()) it.next();
- return null;
- }
- static LSSParserState STRUCT_DATA (Iterator<LSSToken> it, HashMap<String, Object> map) {
- String error = "";
- LSSToken next = it.next();
- nominal: {
- if (next.getText().equals("}")) {
- HashMap<String, HashMap<String, Integer>> structs = (HashMap<String, HashMap<String, Integer>>) map.computeIfAbsent("structs", HashMap<String, HashMap<String, Integer>>::new);
- if (enumeration.containsKey(map.get("struct name"))) {
- error = "struct name " + map.get("struct name") + " in use";
- break nominal;
- }
- enumeration.put((String) map.get("struct name"), (HashMap<String, LSSStructMember>) map.computeIfAbsent("struct", HashMap<String, LSSStructMember>::new));
- map.remove("struct name");
- map.remove("struct");
- return LSSParserState::PROGRAM_START;
- }
- if (!isPossibleTypeName(next)) {
- error = "invalid token: expected struct member type, got " + next.getText();
- break nominal;
- }
- LSSToken type = next;
- if (!(next instanceof LSSGenericToken)) {
- error = "invalid token: expected struct member name, got " + next.getText();
- break nominal;
- }
- String name = next.getText();
- LSSToken assignment = null;
- if ((next = it.next()).getText().equals("=")) {
- assignment = it.next();
- next = it.next();
- }
- if (!next.getText().equals(";")) {
- error = "invalid token: expected semicolon, got " + next.getText();
- break nominal;
- }
- HashMap<String, LSSStructMember> struct = (HashMap<String, LSSStructMember>) map.computeIfAbsent("struct", HashMap<String, LSSStructMember>::new);
- if (struct.containsKey(name)) {
- error = "struct member " + name + " is already in use";
- break nominal;
- }
- struct.put(name, new LSSStructMember(type, assignment));
- map.put(struct);
- return LSSParserState::STRUCT_DATA;
- }
- LSSParser.error(error);
- while (!next.getText().equals(";") && !next.getText().equals("}")) next = it.next();
- if (next.getText().equals(";")) return LSSParserState::ENUM_DATA;
- else return LSSParserState::PROGRAM_START;
- }
- static LSSParserState PROGRAM_DATA (Iterator<LSSToken> it, HashMap<String, Object> map) {
- String error = "";
- LSSToken next = it.next();
- nominal: {
- if ((Boolean) map.get("programmed")) {
- error = "multiple programs in the same file";
- break nominal;
- }
- map.put("programmed", Boolean.TRUE);
- if (next.getText().equals("}"))
- return LSSParserState::PROGRAM_START;
- else if (next.getText().equals("@"))
- return LSSParserState::PROGRAM_DATA_ANNOTATION;
- else {
- boolean f = false;
- if (next.getText().equals("final")) {
- f = true;
- next = it.next();
- }
- LSSToken type = next;
- if (!((next = it.next()) instanceof LSSGenericToken)) {
- error = "invalid token: expected program member name, got " + next.getText();
- break nominal;
- }
- String name = next.getText();
- if ((next = it.next()).getText().equals(";")) {
- HashMap<String, LSSField> fields = (HashMap<String, LSSField>) map.computeIfAbsent("fields", HashMap<String, LSSField>::new);
- if (fields.containsKey(name)) {
- error = "field name " + name + " already in use";
- break nominal;
- }
- fields.put(name, new LSSField(f, type, null));
- } else if ((next = it.next()).getText().equals("=")) {
- ArrayList<LSSToken> assignment = new ArrayList<LSSToken>();
- while (!(next = it.next()).getText().equals(";")) assignment.add(next);
- HashMap<String, LSSField> fields = (HashMap<String, LSSField>) map.computeIfAbsent("fields", HashMap<String, LSSField>::new);
- if (fields.containsKey(name)) {
- error = "field name " + name + " already in use";
- break nominal;
- }
- fields.put(name, new LSSField(f, type, assignment.toArray(new LSSToken[assignment.size()])));
- } else if ((next = it.next()).getText().equals("(")) {
- ArrayList<LSSToken> tokens = new ArrayList<LSSToken>();
- int scope = 0;
- while (scope >= 0) {
- if ((next = it.next()).getText().equals("}")) scope--;
- if (next.getText().equals("{")) scope++;
- tokens.add(next);
- }
- ArrayList<LSSMethod> methods = (ArrayList<LSSMethod>) map.computeIfAbsent("methods", ArrayList<LSSMethod>::new);
- fields.put(name, new LSSField(f, type, null));
- } else
- error = "invalid token: expected semicolon, field assignment or method parameters, got " + next.getText();
- }
- LSSParser.error(error);
- while (!next.getText().equals(";") && !next.getText().equals("}")) next = it.next();
- if (next.getText().equals(";")) return LSSParserState::ENUM_DATA;
- else return LSSParserState::PROGRAM_START;
- }
- }
- public interface LSSToken {
- String getText ();
- static LSSToken parse (String s) {
- for (String ss : LSSKeywordToken.KEYWORDS)
- if (s.matches(ss + "[ \f\t].*"))
- return LSSKeywordToken.of(ss);
- for (String ss : LSSPunctuatorToken.PUNCTUATORS)
- if (s.matches(ss + ".*"))
- return LSSPunctuatorToken.of(ss);
- if (s.matches("0x[0-9a-fA-F]+[bBwW]?.*"))
- return LSSNumericLiteralToken.ofHex(s);
- if (s.matches("0b[01]+[bBwW]?.*"))
- return LSSNumericLiteralToken.ofBinary(s);
- if (s.matches("0o?[0-7]+[bBwW]?.*"))
- return LSSNumericLiteralToken.ofOctal(s);
- if (s.matches("[0-9]+[bBwW]?.*"))
- return LSSNumericLiteralToken.ofDecimal(s);
- if (s.matches("'[.&&^\\n]'.*"))
- return LSSNumericLiteralToken.ofCharacter(s);
- if (s.matches("\"[.&&^\\n]*\".*"))
- return LSSStringLiteralToken.of(s);
- if (s.matches("\"\"\"[ \f\t]\\n.*\"\"\".*"))
- return LSSStringLiteralToken.ofTextBlock(s);
- }
- }
- public class LSSKeywordToken {
- public static final String[] KEYWORDS = new String[] {
- "assert",
- "break",
- "byte",
- "case",
- "continue",
- "default",
- "else",
- "enum",
- "for",
- "if",
- "jump",
- "program",
- "return",
- "spc",
- "struct",
- "switch",
- "void",
- "while",
- "word"
- };
- private final String text;
- private LSSKeywordToken (String s) {
- this.text = s;
- }
- public String getText () {
- return this.text;
- }
- public static LSSKeywordToken of (String s) {
- return new LSSKeywordToken(s);
- }
- }
- public class LSSPunctuatorToken {
- public static final String[] PUNCTUATORS = new String[] {
- "(",
- ")",
- "{",
- "}",
- "[",
- "]",
- ";",
- ",",
- ".",
- "@",
- "=",
- ">",
- "<",
- "!",
- "~",
- "?",
- ":",
- "+",
- "-",
- "*",
- "/",
- "&",
- "|",
- "^",
- "%"
- };
- private final String text;
- private LSSPunctuatorToken (String s) {
- this.text = s;
- }
- public String getText () {
- return this.text;
- }
- public static LSSPunctuatorToken of (String s) {
- return new LSSPunctuatorToken(s);
- }
- }
- public class LSSNumericLiteralToken {
- public static final Pattern HEX = Pattern.compile("(0x([0-9a-fA-F]+)[bBwW]).*");
- public static final Pattern BINARY = Pattern.compile("(0b([0-1]+)[bBwW]).*");
- public static final Pattern OCTAL = Pattern.compile("(0o?([0-7]+)[bBwW]).*");
- public static final Pattern DECIMAL = Pattern.compile("(([0-9]+)[bBwW]).*");
- public static final Pattern CHARACTER = Pattern.compile("'.'.*");
- private final String text;
- private final int value;
- private LSSNumericLiteralToken (String s, int value) {
- this.text = s;
- this.value = value;
- }
- public String getText () {
- return this.text;
- }
- public int getValue () {
- return this.value;
- }
- public static LSSNumericLiteralToken ofHex (String s) {
- Matcher m = HEX.matcher(s);
- String text = m.group(1);
- int value = Integer.parseInt(m.group(2), 16);
- return new LSSNumericLiteralToken(text, value);
- }
- public static LSSNumericLiteralToken ofBinary (String s) {
- Matcher m = BINARY.matcher(s);
- String text = m.group(1);
- int value = Integer.parseInt(m.group(2), 2);
- return new LSSNumericLiteralToken(text, value);
- }
- public static LSSNumericLiteralToken ofOctal (String s) {
- Matcher m = OCTAL.matcher(s);
- String text = m.group(1);
- int value = Integer.parseInt(m.group(2), 8);
- return new LSSNumericLiteralToken(text, value);
- }
- public static LSSNumericLiteralToken ofDecimal (String s) {
- Matcher m = DECIMAL.matcher(s);
- String text = m.group(1);
- int value = Integer.parseInt(m.group(2), 10);
- return new LSSNumericLiteralToken(text, value);
- }
- public static LSSNumericLiteralToken ofCharacter (String s) {
- Matcher m = CHARACTER.matcher(s);
- String text = m.group(1);
- int value = m.group(2).charAt(0);
- return new LSSNumericLiteralToken(text, value);
- }
- }
- public class LSSStringLiteralToken {
- public static final Pattern STRING = Pattern.compile("(\"([.&&^\\n]*)\").*");
- public static final Pattern STRING = Pattern.compile("(\"\"\"[ \f\t]\\n(.*)\"\"\").*");
- private final String text;
- private final String value;
- private LSSNumericLiteralToken (String s, String value) {
- this.text = s;
- this.value = value;
- }
- public String getText () {
- return this.text;
- }
- public int getValue () {
- return this.value;
- }
- public static LSSNumericLiteralToken of (String s) {
- Matcher m = STRING.matcher(s);
- String text = m.group(1);
- String value = m.group(2);
- return new LSSNumericLiteralToken(text, value);
- }
- public static LSSNumericLiteralToken ofBinary (String s) {
- Matcher m = TEXT_BLOCK.matcher(s);
- String text = m.group(1);
- String value = m.group(2);
- return new LSSNumericLiteralToken(text, value);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment