Advertisement
Femn0X

Yep I made this :)

Mar 5th, 2025
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.12 KB | Source Code | 0 0
  1. import re
  2.  
  3. class Token:
  4.     def __init__(self, type, value):
  5.         self.type = type
  6.         self.value = value
  7.  
  8.     def __repr__(self):
  9.         return f"Token({self.type}, {self.value})"
  10.  
  11. class Parser:
  12.     def __init__(self, tokens):
  13.         self.tokens = tokens
  14.         self.current_token = None
  15.         self.token_index = -1
  16.         self.advance()
  17.  
  18.     def advance(self):
  19.         self.token_index += 1
  20.         if self.token_index < len(self.tokens):
  21.             self.current_token = self.tokens[self.token_index]
  22.         else:
  23.             self.current_token = None
  24.  
  25.     def eat(self, token_type):
  26.         if self.current_token and self.current_token.type == token_type:
  27.             self.advance()
  28.         else:
  29.             raise Exception(f"Expected {token_type}, but got {self.current_token}")
  30.  
  31.     def parse_main(self):
  32.         self.eat('PUBLIC')
  33.         self.eat('CLASS')
  34.         class_name = self.current_token.value
  35.         self.eat('MAIN')
  36.         self.eat('LPAREN')
  37.         self.eat('AT')
  38.         self.eat('SELF')
  39.         self.eat('RPAREN')
  40.         self.eat('LBRACE')
  41.         main_body = self.parse_main_body()
  42.         self.eat('RBRACE')
  43.         return {"type": "main_definition", "name": class_name, "body": main_body}
  44.  
  45.     def parse_main_body(self):
  46.         body = []
  47.         while self.current_token and self.current_token.type != 'RBRACE':
  48.             if self.current_token.type == 'PUBLIC':
  49.                 body.append(self.parse_class_definition())
  50.             elif self.current_token.type == 'DEF':
  51.                 body.append(self.parse_method_definition())
  52.             elif self.current_token.type == 'PRINT':
  53.                 body.append(self.parse_print_statement())
  54.             elif self.current_token.type == 'LET':
  55.                 body.append(self.parse_const())
  56.             else:
  57.                 body.append(self.parse_pass())
  58.         return body
  59.  
  60.     def parse_pass(self):
  61.         self.eat('PASS')
  62.         self.eat('COLON')
  63.         return {"type": "pass"}
  64.  
  65.     def parse_const(self):
  66.         self.eat('LET')
  67.         self.eat('CONST')
  68.         identifier = self.current_token.value
  69.         self.eat('IDENTIFIER')
  70.         self.eat('EQUAL')
  71.         value = None
  72.         if self.current_token.type == 'STRING_LITERAL':
  73.             value = self.current_token.value
  74.             self.eat('STRING_LITERAL')
  75.         elif self.current_token.type == 'NUMBER':
  76.             value = self.current_token.value
  77.             self.eat('NUMBER')
  78.         self.eat('SEMICOLON')
  79.         return {"type": "const", "identifier": identifier, "value": value}
  80.  
  81.     def parse_class_definition(self):
  82.         self.eat('PUBLIC')
  83.         self.eat('CLASS')
  84.         class_name = self.current_token.value
  85.         self.eat('IDENTIFIER')
  86.         self.eat('LPAREN')
  87.         self.eat('AT')
  88.         self.eat('INNER_SELF')
  89.         self.eat('RPAREN')
  90.         self.eat('LBRACE')
  91.         class_body = self.parse_class_body()
  92.         self.eat('RBRACE')
  93.         self.eat('SEMICOLON')
  94.         return {"type": "class_definition", "name": class_name, "body": class_body}
  95.  
  96.     def parse_class_body(self):
  97.         body = []
  98.         while self.current_token and self.current_token.type != 'RBRACE':
  99.             if self.current_token.type == 'DEF':
  100.                 body.append(self.parse_method_definition())
  101.             else:
  102.                 body.append(self.parse_pass())
  103.         return body
  104.  
  105.     def parse_method_definition(self):
  106.         self.eat('DEF')
  107.         method_name = self.current_token.value
  108.         self.eat('IDENTIFIER')
  109.         self.eat('LPAREN')
  110.         self.eat('AT')
  111.         self.eat('SELF')
  112.         self.parse_method_head()
  113.         self.eat('RPAREN')
  114.         self.eat('LBRACE')
  115.         method_body = self.parse_method_body()
  116.         self.eat('RBRACE')
  117.         self.eat('SEMICOLON')
  118.         return {"type": "method_definition", "name": method_name, "body": method_body}
  119.  
  120.     def parse_extend_method(self):
  121.         self.eat('COMMA')
  122.         self.eat('IDENTIFIER')
  123.         if self.current_token and self.current_token.type == 'COMMA':
  124.             self.parse_extend_method()
  125.  
  126.     def parse_method_head(self):
  127.         if self.current_token and self.current_token.type == 'COMMA':
  128.             self.parse_extend_method()
  129.  
  130.     def parse_method_body(self):
  131.         body = []
  132.         while self.current_token and self.current_token.type != 'RBRACE':
  133.             if self.current_token.type == 'PUBLIC':
  134.                 raise Exception("Cannot nest classes in methods")
  135.             elif self.current_token.type == 'DEF':
  136.                 body.append(self.parse_method_definition())
  137.             elif self.current_token.type == 'PRINT':
  138.                 body.append(self.parse_print_statement())
  139.             elif self.current_token.type == 'LET':
  140.                 body.append(self.parse_const())
  141.             else:
  142.                 body.append(self.parse_pass())
  143.         return body
  144.  
  145.     def parse_print_statement(self):
  146.         self.eat('PRINT')
  147.         self.eat('LPAREN')
  148.         string_literal =self.parse_printable()
  149.         self.eat('RPAREN')
  150.         self.eat('SEMICOLON')
  151.         return {"type": "print_statement", "value": string_literal}
  152.     def parse_printable(self):
  153.         if self.current_token and self.current_token.type=='STRING_LITERAL':
  154.             return self.current_token.value
  155.         if self.current_token and self.current_token.type=='NUMBER':
  156.             self.eat('NUMBER')
  157.             while self.current_token and self.current_token.type=='NUMBER':
  158.                 self.eat('NUMBER')
  159.             return self.current_token.value
  160.     def parse(self):
  161.         return self.parse_main()
  162.  
  163. class Lexer:
  164.     def __init__(self, text):
  165.         self.text = self.remove_comments(text)
  166.         self.pos = 0
  167.         self.current_char = self.text[self.pos] if len(self.text) > 0 else None
  168.  
  169.     def remove_comments(self, text):
  170.         text = re.sub(r'//.*', '', text)
  171.         text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL)
  172.         return text
  173.  
  174.     def advance(self):
  175.         self.pos += 1
  176.         if self.pos < len(self.text):
  177.             self.current_char = self.text[self.pos]
  178.         else:
  179.             self.current_char = None
  180.  
  181.     def skip_whitespace(self):
  182.         while self.current_char is not None and self.current_char.isspace():
  183.             self.advance()
  184.  
  185.     def identifier(self):
  186.         result = ''
  187.         while self.current_char is not None and (self.current_char.isalnum() or self.current_char == '_'):
  188.             result += self.current_char
  189.             self.advance()
  190.         return result
  191.  
  192.     def string_literal(self):
  193.         result = '"'
  194.         self.advance()
  195.         while self.current_char is not None and self.current_char != '"':
  196.             result += self.current_char
  197.             self.advance()
  198.         if self.current_char == '"':
  199.             result += '"'
  200.             self.advance()
  201.             return result
  202.         else:
  203.             raise Exception("Unterminated string literal")
  204.  
  205.     def get_next_token(self):
  206.         while self.current_char is not None:
  207.             if self.current_char.isspace():
  208.                 self.skip_whitespace()
  209.                 continue
  210.  
  211.             if self.current_char.isalpha() or self.current_char == '_':
  212.                 identifier = self.identifier()
  213.                 if identifier == 'public':
  214.                     return Token('PUBLIC', 'public')
  215.                 elif identifier == 'class':
  216.                     return Token('CLASS', 'class')
  217.                 elif identifier == 'main':
  218.                     return Token('MAIN', 'main')
  219.                 elif identifier == 'self':
  220.                     return Token('SELF', 'self')
  221.                 elif identifier == 'inner_self':
  222.                     return Token('INNER_SELF', 'inner_self')
  223.                 elif identifier == 'def':
  224.                     return Token('DEF', 'def')
  225.                 elif identifier == 'print':
  226.                     return Token('PRINT', 'print')
  227.                 elif identifier == 'pass':
  228.                     return Token('PASS', 'pass')
  229.                 elif identifier == 'let':
  230.                     return Token('LET', 'let')
  231.                 elif identifier == 'const':
  232.                     return Token('CONST', 'const')
  233.                 else:
  234.                     return Token('IDENTIFIER', identifier)
  235.             if self.current_char == '(':
  236.                 self.advance()
  237.                 return Token('LPAREN', '(')
  238.             if self.current_char == ')':
  239.                 self.advance()
  240.                 return Token('RPAREN', ')')
  241.             if self.current_char == '{':
  242.                 self.advance()
  243.                 return Token('LBRACE', '{')
  244.             if self.current_char == '}':
  245.                 self.advance()
  246.                 return Token('RBRACE', '}')
  247.             if self.current_char == ':':
  248.                 self.advance()
  249.                 return Token('COLON', ':')
  250.             if self.current_char == ';':
  251.                 self.advance()
  252.                 return Token('SEMICOLON', ';')
  253.             if self.current_char == '"':
  254.                 return Token('STRING_LITERAL', self.string_literal())
  255.             if self.current_char == '=':
  256.                 self.advance()
  257.                 return Token('EQUAL', '=')
  258.             if self.current_char=="@":
  259.                 self.advance()
  260.                 return Token('AT',"@")
  261.             if self.current_char.isdigit():
  262.                 number = self.current_char
  263.                 self.advance()
  264.                 return Token('NUMBER', number)
  265.             raise Exception(f"Invalid character: {self.current_char}")
  266.         return None
  267.  
  268.     def tokenize(self):
  269.         tokens = []
  270.         token = self.get_next_token()
  271.         while token:
  272.             tokens.append(token)
  273.             token = self.get_next_token()
  274.         return tokens
  275.  
  276. def run(code):
  277.     lexer = Lexer(code)
  278.     tokens = lexer.tokenize()
  279.     parser = Parser(tokens)
  280.     try:
  281.         ast = parser.parse()
  282.         for item in ast['body']:
  283.             if item['type'] == 'print_statement':
  284.                 print(item['value'][1:-1])
  285.     except Exception as e:
  286.         print(e)
  287.  
  288. run('public class main(@self){print(78);}')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement