SforzandoCF

lss

Feb 18th, 2026 (edited)
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 21.47 KB | None | 0 0
  1. public class LSSParser {
  2.     public static final Pattern LONG_COMMENT = Pattern.compile("(/\\*.*\\*/).*");
  3.     public static final Pattern SHORT_COMMENT = Pattern.compile("(//[.&&^\\n]*\\n).*");
  4.    
  5.     public static LSSProgram compile (String s) {
  6.         return build(compile(parse(tokenize(s))));
  7.     }
  8.    
  9.     private static ArrayList<LSSToken> tokenize (String s) {
  10.         int index = 0;
  11.         ArrayList<LSSToken> tokens = new ArrayList<LSSToken>();
  12.         while (s.length() > index) {
  13.             String ss = s.substring(index);
  14.             if (ss.matches("[ \f\t].*")) {
  15.                 index++;
  16.                 continue;
  17.             }
  18.             Matcher m = LONG_COMMENT.matcher(ss);
  19.             if (m.matches()) {
  20.                 index += m.group(1).length();
  21.                 continue;
  22.             }
  23.             Matcher m = SHORT_COMMENT.matcher(ss);
  24.             if (m.matches()) {
  25.                 index += m.group(1).length();
  26.                 continue;
  27.             }
  28.             LSSToken t = LSSToken.parse(ss);
  29.             index += t.getText().length();
  30.             tokens.add(t);
  31.         }
  32.         return tokens;
  33.     }
  34.    
  35.     private static HashMap<String, Object> parse (ArrayList<LSSToken> tokens) {
  36.         LSSParserState s = LSSParserState::PROGRAM_START;
  37.         Iterator<LSSToken> it = tokens.iterator();
  38.         HashMap<String, Object> map = new HashMap<String, Object>();
  39.         while (it.hasNext()) s = s.parse(it, map);
  40.         return map;
  41.     }
  42.    
  43.     private static HashMap<String, Object> compile (HashMap<String, Object> map) {
  44.         HashMap<String, Object> map2 = new HashMap<String, Object>();
  45.         ArrayList<LSSPreMethod> premethods = (ArrayList<LSSPreMethod>) map.get("methods");
  46.         LSSMethod[] postmethods = new LSSMethod[premethods.length];
  47.         int size = 0;
  48.         for (int i = 0; i < premethods.length; i++)
  49.             size += (postmethods[i] = LSSMethod.compile(premethods.get(i), map, map2)).getLength();
  50.         map2.put("methods", postmethods);
  51.         map2.put("methods size", size);
  52.     }
  53. }
  54.  
  55. public interface LSSParserState {
  56.     LSSParserState parse (Iterator<LSSToken> it, HashMap<String, Object> map);
  57.    
  58.     static LSSParserState PROGRAM_START (Iterator<LSSToken> it, HashMap<String, Object> map) {
  59.         LSSToken next = it.next();
  60.         if (next.getText().equals("@"))
  61.             return LSSParserState::PROGRAM_ANNOTATION;
  62.         else if (next.getText().equals("program"))
  63.             return LSSParserState::PROGRAM_DECLARATION;
  64.         else {
  65.             LSSParser.error("invalid token: file started with " + next.getText());
  66.             while (!next.getText().equals("@")
  67.                    && !next.getText().equals("program")
  68.                    && !next.getText().equals("enum")
  69.                    && !next.getText().equals("struct")) next = it.next();
  70.             if (next.getText().equals("@"))
  71.                 return LSSParserState::PROGRAM_ANNOTATION;
  72.             else if (next.getText().equals("program"))
  73.                 return LSSParserState::PROGRAM_DECLARATION;
  74.             else if (next.getText().equals("enum"))
  75.                 return LSSParserState::ENUM_DECLARATION;
  76.             else if (next.getText().equals("struct"))
  77.                 return LSSParserState::STRUCT_DECLARATION;
  78.         }
  79.     }
  80.    
  81.     static LSSParserState PROGRAM_ANNOTATION (Iterator<LSSToken> it, HashMap<String, Object> map) {
  82.         String error = "";
  83.         LSSToken next = it.next();
  84.         nominal: {
  85.             if (!(next instanceof LSSGenericToken)) {
  86.                 error = "invalid token: expected annotation name, got " + next.getText();
  87.                 break nominal;
  88.             }
  89.             String name = next.getText();
  90.             next = it.next();
  91.             if (!next.getText().equals("(")) {
  92.                 error = "invalid token: expected annotation params, got " + next.getText();
  93.                 break nominal;
  94.             }
  95.             ArrayList<LSSToken[]> params = new ArrayList<LSSToken[]>();
  96.             next = it.next();
  97.             while (!next.getText().equals(")")) {
  98.                 ArrayList<LSSToken> params = new ArrayList<LSSToken>();
  99.                 while (!next.getText().equals(",") && !next.getText().equals(")")) {
  100.                     params.add(next);
  101.                     next = it.next();
  102.                 }
  103.                 ((ArrayList<Map.Entry<String, LSSToken[][]>>) map.computeIfAbsent("program annotations", ArrayList<Map.Entry<String, LSSToken[][]>>::new))
  104.                     .add(Map.<String, LSSToken[][]>entry(name, params.toArray(new LSSToken[params.size()][])));
  105.             }
  106.             return LSSParserState::PROGRAM_START;
  107.         }
  108.         LSSParser.error(error);
  109.         while (!next.getText().equals("@")
  110.                && !next.getText().equals("program")
  111.                && !next.getText().equals("enum")
  112.                && !next.getText().equals("struct")) next = it.next();
  113.         if (next.getText().equals("@"))
  114.             return LSSParserState::PROGRAM_ANNOTATION;
  115.         else if (next.getText().equals("program"))
  116.             return LSSParserState::PROGRAM_DECLARATION;
  117.         else if (next.getText().equals("enum"))
  118.             return LSSParserState::ENUM_DECLARATION;
  119.         else if (next.getText().equals("struct"))
  120.             return LSSParserState::STRUCT_DECLARATION;
  121.     }
  122.    
  123.     static LSSParserState PROGRAM_DECLARATION (Iterator<LSSToken> it, HashMap<String, Object> map) {
  124.         String error = "";
  125.         LSSToken next = it.next();
  126.         nominal: {
  127.             if (!(next instanceof LSSGenericToken)) {
  128.                 if (next.getText().equals("{")) {
  129.                     map.put("name", "unnamed");
  130.                     return PROGRAM_DATA;
  131.                 }
  132.                 error = "invalid token: expected program name, got " + next.getText();
  133.                 break nominal;
  134.             }
  135.             map.put("name", next.getText());
  136.             if (!next.getText().equals("{")) {
  137.                 error = "invalid token: expected program opening bracket, got " + next.getText();
  138.                 break nominal;
  139.             }
  140.             return LSSParserState::PROGRAM_DATA;
  141.         }
  142.         LSSParser.error(error);
  143.         while (it.hasNext()) it.next();
  144.         return null;
  145.     }
  146.    
  147.     static LSSParserState ENUM_DECLARATION (Iterator<LSSToken> it, HashMap<String, Object> map) {
  148.         String error = "";
  149.         LSSToken next = it.next();
  150.         nominal: {
  151.             if (!(next instanceof LSSGenericToken)) {
  152.                 error = "invalid token: expected enum name, got " + next.getText();
  153.                 break nominal;
  154.             }
  155.             map.put("enum name", next.getText());
  156.             if (!next.getText().equals("{")) {
  157.                 error = "invalid token: expected enum opening bracket, got " + next.getText();
  158.                 break nominal;
  159.             }
  160.             return LSSParserState::ENUM_DATA;
  161.         }
  162.         LSSParser.error(error);
  163.         while (it.hasNext()) it.next();
  164.         return null;
  165.     }
  166.    
  167.     static LSSParserState ENUM_DATA (Iterator<LSSToken> it, HashMap<String, Object> map) {
  168.         String error = "";
  169.         LSSToken next = it.next();
  170.         nominal: {
  171.             if (next.getText().equals("}")) {
  172.                 HashMap<String, HashMap<String, Integer>> enumeration = (HashMap<String, HashMap<String, Integer>>) map.computeIfAbsent("enums", HashMap<String, HashMap<String, Integer>>::new);
  173.                 if (enumeration.containsKey(map.get("enum name"))) {
  174.                     error = "enum name " + map.get("enum name") + " in use";
  175.                     break nominal;
  176.                 }
  177.                 enumeration.put((String) map.get("enum name"), (HashMap<String, Integer>) map.computeIfAbsent("enum", HashMap<String, Integer>::new));
  178.                 map.remove("enum name");
  179.                 map.remove("enum");
  180.                 return LSSParserState::PROGRAM_START;
  181.             }
  182.             if (!(next instanceof LSSGenericToken)) {
  183.                 error = "invalid token: expected enum constant, got " + next.getText();
  184.                 break nominal;
  185.             }
  186.             String name = next.getText();
  187.             int assignment = null;
  188.             if ((next = it.next()).getText().equals("=")) {
  189.                 if (!((next = it.next()) instanceof LSSNumericLiteralToken)) {
  190.                     error = "invalid token: expected numeric literal, got " + next.getText();
  191.                     break nominal;
  192.                 }
  193.                 assignment = ((LSSNumericLiteralToken) next).getValue();
  194.                 next = it.next();
  195.             }
  196.             if (!next.getText().equals(";")) {
  197.                 error = "invalid token: expected semicolon, got " + next.getText();
  198.                 break nominal;
  199.             }
  200.             HashMap<String, Integer> enumeration = (HashMap<String, Integer>) map.computeIfAbsent("enum", HashMap<String, Integer>::new);
  201.             if (enumeration.containsKey(name)) {
  202.                 error = "enum constant " + name + " is already in use";
  203.                 break nominal;
  204.             }
  205.             enumeration.put(name, assignment);
  206.             map.put(enumeration);
  207.             return LSSParserState::ENUM_DATA;
  208.         }
  209.         LSSParser.error(error);
  210.         while (!next.getText().equals(";") && !next.getText().equals("}")) next = it.next();
  211.         if (next.getText().equals(";")) return LSSParserState::ENUM_DATA;
  212.         else return LSSParserState::PROGRAM_START;
  213.     }
  214.    
  215.     static LSSParserState STRUCT_DECLARATION (Iterator<LSSToken> it, HashMap<String, Object> map) {
  216.         String error = "";
  217.         LSSToken next = it.next();
  218.         nominal: {
  219.             if (!(next instanceof LSSGenericToken)) {
  220.                 error = "invalid token: expected struct name, got " + next.getText();
  221.                 break nominal;
  222.             }
  223.             map.put("struct name", next.getText());
  224.             if (!next.getText().equals("{")) {
  225.                 error = "invalid token: expected struct opening bracket, got " + next.getText();
  226.                 break nominal;
  227.             }
  228.             return LSSParserState::STRUCT_DATA;
  229.         }
  230.         LSSParser.error(error);
  231.         while (it.hasNext()) it.next();
  232.         return null;
  233.     }
  234.    
  235.     static LSSParserState STRUCT_DATA (Iterator<LSSToken> it, HashMap<String, Object> map) {
  236.         String error = "";
  237.         LSSToken next = it.next();
  238.         nominal: {
  239.             if (next.getText().equals("}")) {
  240.                 HashMap<String, HashMap<String, Integer>> structs = (HashMap<String, HashMap<String, Integer>>) map.computeIfAbsent("structs", HashMap<String, HashMap<String, Integer>>::new);
  241.                 if (enumeration.containsKey(map.get("struct name"))) {
  242.                     error = "struct name " + map.get("struct name") + " in use";
  243.                     break nominal;
  244.                 }
  245.                 enumeration.put((String) map.get("struct name"), (HashMap<String, LSSStructMember>) map.computeIfAbsent("struct", HashMap<String, LSSStructMember>::new));
  246.                 map.remove("struct name");
  247.                 map.remove("struct");
  248.                 return LSSParserState::PROGRAM_START;
  249.             }
  250.             if (!isPossibleTypeName(next)) {
  251.                 error = "invalid token: expected struct member type, got " + next.getText();
  252.                 break nominal;
  253.             }
  254.             LSSToken type = next;
  255.             if (!(next instanceof LSSGenericToken)) {
  256.                 error = "invalid token: expected struct member name, got " + next.getText();
  257.                 break nominal;
  258.             }
  259.             String name = next.getText();
  260.             LSSToken assignment = null;
  261.             if ((next = it.next()).getText().equals("=")) {
  262.                 assignment = it.next();
  263.                 next = it.next();
  264.             }
  265.             if (!next.getText().equals(";")) {
  266.                 error = "invalid token: expected semicolon, got " + next.getText();
  267.                 break nominal;
  268.             }
  269.             HashMap<String, LSSStructMember> struct = (HashMap<String, LSSStructMember>) map.computeIfAbsent("struct", HashMap<String, LSSStructMember>::new);
  270.             if (struct.containsKey(name)) {
  271.                 error = "struct member " + name + " is already in use";
  272.                 break nominal;
  273.             }
  274.             struct.put(name, new LSSStructMember(type, assignment));
  275.             map.put(struct);
  276.             return LSSParserState::STRUCT_DATA;
  277.         }
  278.         LSSParser.error(error);
  279.         while (!next.getText().equals(";") && !next.getText().equals("}")) next = it.next();
  280.         if (next.getText().equals(";")) return LSSParserState::ENUM_DATA;
  281.         else return LSSParserState::PROGRAM_START;
  282.     }
  283.    
  284.     static LSSParserState PROGRAM_DATA (Iterator<LSSToken> it, HashMap<String, Object> map) {
  285.         String error = "";
  286.         LSSToken next = it.next();
  287.         nominal: {
  288.             if ((Boolean) map.get("programmed")) {
  289.                 error = "multiple programs in the same file";
  290.                 break nominal;
  291.             }
  292.             map.put("programmed", Boolean.TRUE);
  293.             if (next.getText().equals("}"))
  294.                 return LSSParserState::PROGRAM_START;
  295.             else if (next.getText().equals("@"))
  296.                 return LSSParserState::PROGRAM_DATA_ANNOTATION;
  297.             else {
  298.                 boolean f = false;
  299.                 if (next.getText().equals("final")) {
  300.                     f = true;
  301.                     next = it.next();
  302.                 }
  303.                 LSSToken type = next;
  304.                 if (!((next = it.next()) instanceof LSSGenericToken)) {
  305.                     error = "invalid token: expected program member name, got " + next.getText();
  306.                     break nominal;
  307.                 }
  308.                 String name = next.getText();
  309.                 if ((next = it.next()).getText().equals(";")) {
  310.                     HashMap<String, LSSField> fields = (HashMap<String, LSSField>) map.computeIfAbsent("fields", HashMap<String, LSSField>::new);
  311.                     if (fields.containsKey(name)) {
  312.                         error = "field name " + name + " already in use";
  313.                         break nominal;
  314.                     }
  315.                     fields.put(name, new LSSField(f, type, null));
  316.                 } else if ((next = it.next()).getText().equals("=")) {
  317.                     ArrayList<LSSToken> assignment = new ArrayList<LSSToken>();
  318.                     while (!(next = it.next()).getText().equals(";")) assignment.add(next);
  319.                     HashMap<String, LSSField> fields = (HashMap<String, LSSField>) map.computeIfAbsent("fields", HashMap<String, LSSField>::new);
  320.                     if (fields.containsKey(name)) {
  321.                         error = "field name " + name + " already in use";
  322.                         break nominal;
  323.                     }
  324.                     fields.put(name, new LSSField(f, type, assignment.toArray(new LSSToken[assignment.size()])));
  325.                 } else if ((next = it.next()).getText().equals("(")) {
  326.                     ArrayList<LSSToken> tokens = new ArrayList<LSSToken>();
  327.                     int scope = 0;
  328.                     while (scope >= 0) {
  329.                         if ((next = it.next()).getText().equals("}")) scope--;
  330.                         if (next.getText().equals("{")) scope++;
  331.                         tokens.add(next);
  332.                     }
  333.                     ArrayList<LSSMethod> methods = (ArrayList<LSSMethod>) map.computeIfAbsent("methods", ArrayList<LSSMethod>::new);
  334.                     fields.put(name, new LSSField(f, type, null));
  335.                 } else
  336.                     error = "invalid token: expected semicolon, field assignment or method parameters, got " + next.getText();
  337.         }
  338.         LSSParser.error(error);
  339.         while (!next.getText().equals(";") && !next.getText().equals("}")) next = it.next();
  340.         if (next.getText().equals(";")) return LSSParserState::ENUM_DATA;
  341.         else return LSSParserState::PROGRAM_START;
  342.     }
  343. }
  344.  
  345. public interface LSSToken {
  346.     String getText ();
  347.    
  348.     static LSSToken parse (String s) {
  349.         for (String ss : LSSKeywordToken.KEYWORDS)
  350.             if (s.matches(ss + "[ \f\t].*"))
  351.                 return LSSKeywordToken.of(ss);
  352.         for (String ss : LSSPunctuatorToken.PUNCTUATORS)
  353.             if (s.matches(ss + ".*"))
  354.                 return LSSPunctuatorToken.of(ss);
  355.         if (s.matches("0x[0-9a-fA-F]+[bBwW]?.*"))
  356.             return LSSNumericLiteralToken.ofHex(s);
  357.         if (s.matches("0b[01]+[bBwW]?.*"))
  358.             return LSSNumericLiteralToken.ofBinary(s);
  359.         if (s.matches("0o?[0-7]+[bBwW]?.*"))
  360.             return LSSNumericLiteralToken.ofOctal(s);
  361.         if (s.matches("[0-9]+[bBwW]?.*"))
  362.             return LSSNumericLiteralToken.ofDecimal(s);
  363.         if (s.matches("'[.&&^\\n]'.*"))
  364.             return LSSNumericLiteralToken.ofCharacter(s);
  365.         if (s.matches("\"[.&&^\\n]*\".*"))
  366.             return LSSStringLiteralToken.of(s);
  367.         if (s.matches("\"\"\"[ \f\t]\\n.*\"\"\".*"))
  368.             return LSSStringLiteralToken.ofTextBlock(s);
  369.     }
  370. }
  371.  
  372. public class LSSKeywordToken {
  373.     public static final String[] KEYWORDS = new String[] {
  374.         "assert",
  375.         "break",
  376.         "byte",
  377.         "case",
  378.         "continue",
  379.         "default",
  380.         "else",
  381.         "enum",
  382.         "for",
  383.         "if",
  384.         "jump",
  385.         "program",
  386.         "return",
  387.         "spc",
  388.         "struct",
  389.         "switch",
  390.         "void",
  391.         "while",
  392.         "word"
  393.     };
  394.    
  395.     private final String text;
  396.    
  397.     private LSSKeywordToken (String s) {
  398.         this.text = s;
  399.     }
  400.    
  401.     public String getText () {
  402.         return this.text;
  403.     }
  404.    
  405.     public static LSSKeywordToken of (String s) {
  406.         return new LSSKeywordToken(s);
  407.     }
  408. }
  409.  
  410. public class LSSPunctuatorToken {
  411.     public static final String[] PUNCTUATORS = new String[] {
  412.         "(",
  413.         ")",
  414.         "{",
  415.         "}",
  416.         "[",
  417.         "]",
  418.         ";",
  419.         ",",
  420.         ".",
  421.         "@",
  422.         "=",
  423.         ">",
  424.         "<",
  425.         "!",
  426.         "~",
  427.         "?",
  428.         ":",
  429.         "+",
  430.         "-",
  431.         "*",
  432.         "/",
  433.         "&",
  434.         "|",
  435.         "^",
  436.         "%"
  437.     };
  438.    
  439.     private final String text;
  440.    
  441.     private LSSPunctuatorToken (String s) {
  442.         this.text = s;
  443.     }
  444.    
  445.     public String getText () {
  446.         return this.text;
  447.     }
  448.    
  449.     public static LSSPunctuatorToken of (String s) {
  450.         return new LSSPunctuatorToken(s);
  451.     }
  452. }
  453.  
  454. public class LSSNumericLiteralToken {
  455.     public static final Pattern HEX = Pattern.compile("(0x([0-9a-fA-F]+)[bBwW]).*");
  456.     public static final Pattern BINARY = Pattern.compile("(0b([0-1]+)[bBwW]).*");
  457.     public static final Pattern OCTAL = Pattern.compile("(0o?([0-7]+)[bBwW]).*");
  458.     public static final Pattern DECIMAL = Pattern.compile("(([0-9]+)[bBwW]).*");
  459.     public static final Pattern CHARACTER = Pattern.compile("'.'.*");
  460.    
  461.     private final String text;
  462.     private final int value;
  463.    
  464.     private LSSNumericLiteralToken (String s, int value) {
  465.         this.text = s;
  466.         this.value = value;
  467.     }
  468.    
  469.     public String getText () {
  470.         return this.text;
  471.     }
  472.    
  473.     public int getValue () {
  474.         return this.value;
  475.     }
  476.    
  477.     public static LSSNumericLiteralToken ofHex (String s) {
  478.         Matcher m = HEX.matcher(s);
  479.         String text = m.group(1);
  480.         int value = Integer.parseInt(m.group(2), 16);
  481.         return new LSSNumericLiteralToken(text, value);
  482.     }
  483.    
  484.     public static LSSNumericLiteralToken ofBinary (String s) {
  485.         Matcher m = BINARY.matcher(s);
  486.         String text = m.group(1);
  487.         int value = Integer.parseInt(m.group(2), 2);
  488.         return new LSSNumericLiteralToken(text, value);
  489.     }
  490.    
  491.     public static LSSNumericLiteralToken ofOctal (String s) {
  492.         Matcher m = OCTAL.matcher(s);
  493.         String text = m.group(1);
  494.         int value = Integer.parseInt(m.group(2), 8);
  495.         return new LSSNumericLiteralToken(text, value);
  496.     }
  497.    
  498.     public static LSSNumericLiteralToken ofDecimal (String s) {
  499.         Matcher m = DECIMAL.matcher(s);
  500.         String text = m.group(1);
  501.         int value = Integer.parseInt(m.group(2), 10);
  502.         return new LSSNumericLiteralToken(text, value);
  503.     }
  504.    
  505.     public static LSSNumericLiteralToken ofCharacter (String s) {
  506.         Matcher m = CHARACTER.matcher(s);
  507.         String text = m.group(1);
  508.         int value = m.group(2).charAt(0);
  509.         return new LSSNumericLiteralToken(text, value);
  510.     }
  511. }
  512.  
  513. public class LSSStringLiteralToken {
  514.     public static final Pattern STRING = Pattern.compile("(\"([.&&^\\n]*)\").*");
  515.     public static final Pattern STRING = Pattern.compile("(\"\"\"[ \f\t]\\n(.*)\"\"\").*");
  516.    
  517.     private final String text;
  518.     private final String value;
  519.    
  520.     private LSSNumericLiteralToken (String s, String value) {
  521.         this.text = s;
  522.         this.value = value;
  523.     }
  524.    
  525.     public String getText () {
  526.         return this.text;
  527.     }
  528.    
  529.     public int getValue () {
  530.         return this.value;
  531.     }
  532.    
  533.     public static LSSNumericLiteralToken of (String s) {
  534.         Matcher m = STRING.matcher(s);
  535.         String text = m.group(1);
  536.         String value = m.group(2);
  537.         return new LSSNumericLiteralToken(text, value);
  538.     }
  539.    
  540.     public static LSSNumericLiteralToken ofBinary (String s) {
  541.         Matcher m = TEXT_BLOCK.matcher(s);
  542.         String text = m.group(1);
  543.         String value = m.group(2);
  544.         return new LSSNumericLiteralToken(text, value);
  545.     }
  546. }
Advertisement
Add Comment
Please, Sign In to add comment