├── .gitignore ├── Constants ├── __init__.py ├── constants.py ├── keywords.py └── tokens.py ├── Context ├── __init__.py └── context.py ├── DOCS.md ├── Errors ├── __init__.py ├── base_error.py └── errors.py ├── Interpreter ├── __init__.py └── interpreter.py ├── LICENSE ├── Parser ├── __init__.py └── parser.py ├── README.md ├── SymbolTable ├── __init__.py └── symbol_table.py ├── Tests ├── __init__.py ├── test_variables.py └── tests_arithmetic.py ├── bugs.baji ├── example.baji ├── examples ├── HelloWorld.baji ├── fib.baji ├── fib2.baji ├── game_of_life.baji └── if_else.baji ├── grammar.md ├── lexer ├── __init__.py ├── lexer.py ├── position.py └── token.py ├── logo.gif ├── logo.svg ├── main.py ├── nodes ├── __init__.py ├── conditional.py ├── functions.py ├── loop.py ├── operation.py ├── value.py └── variable.py ├── results ├── __init__.py ├── parse_result.py └── runtime_result.py ├── shell.py ├── temp.baji ├── translate └── __init__.py └── values ├── __init__.py ├── function.py ├── list.py ├── number.py ├── string.py └── value.py /.gitignore: -------------------------------------------------------------------------------- 1 | temp.py 2 | __pycache__/ 3 | .vscode/ 4 | temp.txt 5 | dist/ 6 | build/ 7 | baji.spec -------------------------------------------------------------------------------- /Constants/__init__.py: -------------------------------------------------------------------------------- 1 | from Constants.constants import * 2 | from Constants.tokens import * 3 | from Constants.keywords import * -------------------------------------------------------------------------------- /Constants/constants.py: -------------------------------------------------------------------------------- 1 | # -----------CONSTANTS----------- 2 | DIGITS = "0123456789०१२३४५६७८९" 3 | MAR_DIGIRS="०१२३४५६७८९" 4 | MAR_LETTERS=("ऀँंःऄअआइईउऊऋऌऍऎएऐऑऒओऔकखगघङचछजझञटठडढणतथदधनऩपफबभमयरऱलळऴवशषस" 5 | +"हऺऻ़ऽािीुूृॄॅॆेैॉॊोौ्ॎॏॐ॒॑॓॔ॕॖॗक़ख़ग़ज़ड़ढ़फ़य़ॠॡॢॣ।॥" 6 | + "॰ॱॲॳॴॵॶॷॸॹॺॻॼॽॾॿ") 7 | 8 | LETTERS = ( 9 | MAR_LETTERS+MAR_DIGIRS 10 | + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 11 | ) 12 | LETTERS_DIGITS = LETTERS + DIGITS -------------------------------------------------------------------------------- /Constants/keywords.py: -------------------------------------------------------------------------------- 1 | KEYWORDS = [ 2 | "VAR", 3 | "चल", 4 | 5 | "AND", 6 | "आणि", 7 | 8 | "OR", 9 | "किंवा", 10 | 11 | "NOT", 12 | "नाही", 13 | 14 | "IF", 15 | 'जर', 16 | 17 | "ELIF", 18 | "किंवाजर", 19 | 20 | "ELSE", 21 | 'नाहीतर', 22 | 23 | "THEN", 24 | 'तर', 25 | 26 | "FOR", 27 | "वारंवार", 28 | 29 | 'TO', 30 | 'ते', 31 | 32 | 'STEP', 33 | 'पाऊल', 34 | 35 | 'WHILE', 36 | 'जोपर्यंत', 37 | 38 | "FUN", 39 | "कार्य", 40 | 41 | "END", 42 | "शेवट", 43 | 44 | "RETURN", 45 | "परत", 46 | 47 | "CONTINUE", 48 | "सुरू", 49 | 50 | "BREAK", 51 | "थांबवा", 52 | 53 | ] 54 | 55 | -------------------------------------------------------------------------------- /Constants/tokens.py: -------------------------------------------------------------------------------- 1 | # -----------TOKEN--------------- 2 | TT_INT = "INT" 3 | TT_FLOAT = "FLOAT" 4 | TT_STRING = "STRING" 5 | TT_IDENTIFIER = "IDENTIFIER" 6 | TT_KEYWORD = "KEYWORD" 7 | TT_PLUS = "PLUS" 8 | TT_MINUS = "MINUS" 9 | TT_MUL = "MUL" 10 | TT_DIV = "DIV" 11 | TT_POWER = "POWER" 12 | TT_MOD = "MOD" 13 | TT_EQ = "EQ" 14 | TT_LPAREN = "LPAREN" 15 | TT_RPAREN = "RPAREN" 16 | TT_LSQUARE = "LSQUARE" 17 | TT_RSQUARE = "RSQUARE" 18 | TT_EE = "EE" 19 | TT_NE = "NE" 20 | TT_LT = "LT" 21 | TT_GT = "GT" 22 | TT_LTE = "LTE" 23 | TT_GTE = "GTE" 24 | TT_COMMA = "COMMA" 25 | TT_ARROW = "ARROW" 26 | TT_NEWLINE = "NEWLINE" 27 | TT_EOF = "EOF" 28 | -------------------------------------------------------------------------------- /Context/__init__.py: -------------------------------------------------------------------------------- 1 | from Context.context import * -------------------------------------------------------------------------------- /Context/context.py: -------------------------------------------------------------------------------- 1 | # ------------Context----------------- 2 | class Context: 3 | def __init__(self, display_name, parent=None, parent_entry_pos=None): 4 | self.display_name = display_name 5 | self.parent = parent 6 | self.parent_entry_pos = parent_entry_pos 7 | self.symbol_table = None 8 | -------------------------------------------------------------------------------- /DOCS.md: -------------------------------------------------------------------------------- 1 | ## Docs 2 | ### **Print** 3 | ``` 4 | दाखवा("नमस्कार विश्व") 5 | ``` 6 | ### Variable 7 | 8 | ``` 9 | चल i = 10 10 | दाखवा(i) 11 | ``` 12 | 13 | ### **Conditionals** 14 | * IF 15 | ``` 16 | जर (१२== ३*४) तर 17 | दाखवा("जर(IF)") 18 | शेवट 19 | 20 | ``` 21 | * ELSE 22 | ``` 23 | जर (१२== ३*४) तर 24 | दाखवा("जर(IF)") 25 | नाहीतर 26 | दाखवा("नाहीतर(ELSE)") 27 | शेवट 28 | 29 | ``` 30 | * ELSE-IF 31 | ``` 32 | जर (१२!= ३*४) तर 33 | दाखवा("जर(IF)") 34 | किंवाजर १==१ तर 35 | दाखवा("नाहीतर(ELSE-IF)") 36 | शेवट 37 | 38 | ``` 39 | ### **LOOPS** 40 | * FOR 41 | ``` 42 | वारंवार i = 0 ते 10 तर 43 | दाखवा(i) 44 | दाखवा("\n") 45 | शेवट 46 | ``` 47 | 48 | * WHILE 49 | ``` 50 | जोपर्यंत i !=10 तर 51 | दाखवा(i) 52 | दाखवा("\n") 53 | i = i+1 54 | 55 | शेवट 56 | ``` 57 | 58 | 59 | ### Functions 60 | 61 | ``` 62 | कार्य नामस्कर(नाव) 63 | दाखवा("नामस्कर "+नाव) 64 | शेवट 65 | 66 | 67 | चल नाव = "Joey" 68 | नामस्कर(नाव) 69 | 70 | ``` -------------------------------------------------------------------------------- /Errors/__init__.py: -------------------------------------------------------------------------------- 1 | from Errors.errors import * 2 | -------------------------------------------------------------------------------- /Errors/base_error.py: -------------------------------------------------------------------------------- 1 | # -----------ERROR-------------- 2 | class Error: 3 | def __init__(self, error_name, pos_start, pos_end, details): 4 | self.pos_start = pos_start 5 | self.pos_end = pos_end 6 | self.error_name = error_name 7 | self.details = details 8 | 9 | def as_string(self): 10 | result = f"{self.error_name} : {self.details} \n" 11 | result += f"File {self.pos_start.fn}, line {self.pos_start.ln+1}" 12 | result += "\n\n" + self.string_with_arrows( 13 | self.pos_start.ftxt, self.pos_start, self.pos_end 14 | ) 15 | return result 16 | 17 | def string_with_arrows(self, text, pos_start, pos_end): 18 | result = "" 19 | 20 | # Calculate indices 21 | idx_start = max(text.rfind("\n", 0, pos_start.idx), 0) 22 | idx_end = text.find("\n", idx_start + 1) 23 | if idx_end < 0: 24 | idx_end = len(text) 25 | 26 | # Generate each line 27 | line_count = pos_end.ln - pos_start.ln + 1 28 | for i in range(line_count): 29 | # Calculate line columns 30 | line = text[idx_start:idx_end] 31 | col_start = pos_start.col if i == 0 else 0 32 | col_end = pos_end.col if i == line_count - 1 else len(line) - 1 33 | 34 | # Append to result 35 | result += line + "\n" 36 | result += " " * col_start + "^" * (col_end - col_start) 37 | 38 | # Re-calculate indices 39 | idx_start = idx_end 40 | idx_end = text.find("\n", idx_start + 1) 41 | if idx_end < 0: 42 | idx_end = len(text) 43 | 44 | return result.replace("\t", "") 45 | -------------------------------------------------------------------------------- /Errors/errors.py: -------------------------------------------------------------------------------- 1 | from Errors.base_error import Error 2 | 3 | 4 | class IllegalCharacterError(Error): 5 | def __init__(self, pos_start, pos_end, details): 6 | super().__init__( 7 | "चुकीचे अक्षर (Illegal Character)", pos_start, pos_end, details 8 | ) 9 | 10 | 11 | class InvalidSyntaxError(Error): 12 | def __init__(self, pos_start, pos_end, details): 13 | super().__init__("अवैध वाक्यरचना (InvalidSyntax)", pos_start, pos_end, details) 14 | 15 | 16 | class ExpectedCharError(Error): 17 | def __init__(self, pos_start, pos_end, details): 18 | super().__init__("अपेक्षित अक्षर (Expected Character)", pos_start, pos_end, details) 19 | 20 | 21 | class RTError(Error): 22 | def __init__(self, pos_start, pos_end, details, context): 23 | super().__init__("प्रोग्राम चालू असताना त्रुटी आली (Runtime Error)", pos_start, pos_end, details) 24 | self.context = context 25 | 26 | def as_string(self): 27 | result = self.generate_traceback() 28 | result += f"{self.error_name}: {self.details}" 29 | result += "\n\n" + self.string_with_arrows( 30 | self.pos_start.ftxt, self.pos_start, self.pos_end 31 | ) 32 | return result 33 | 34 | def generate_traceback(self): 35 | result = "" 36 | pos = self.pos_start 37 | ctx = self.context 38 | 39 | while ctx: 40 | result = ( 41 | f" File {pos.fn}, line {str(pos.ln + 1)}, in {ctx.display_name}\n" 42 | + result 43 | ) 44 | pos = ctx.parent_entry_pos 45 | ctx = ctx.parent 46 | 47 | return "त्रुटी मागोवा (Traceback (most recent call last)):\n" + result 48 | -------------------------------------------------------------------------------- /Interpreter/__init__.py: -------------------------------------------------------------------------------- 1 | from Interpreter.interpreter import * -------------------------------------------------------------------------------- /Interpreter/interpreter.py: -------------------------------------------------------------------------------- 1 | from Nodes.functions import FuncDefNode 2 | from Nodes import loop, value 3 | from Values import Number, Function, String, List 4 | from Errors import RTError 5 | from Constants import * 6 | from Results import ParseResult, RTResult 7 | 8 | 9 | # ------------Interpreter---------------- 10 | 11 | 12 | class Interpreter: 13 | def __init__(self): 14 | pass 15 | 16 | def visit(self, node, context): 17 | method_name = f"visit_{type(node).__name__}" 18 | method = getattr(self, method_name, self.no_visit_method) 19 | return method(node, context) 20 | 21 | def no_visit_method(self, node, context): 22 | raise Exception(f"No visit_{type(node).__name__} method defined") 23 | 24 | ################################### 25 | 26 | def visit_NumberNode(self, node, context): 27 | return RTResult().success( 28 | Number(node.token.value) 29 | .set_context(context) 30 | .set_pos(node.pos_start, node.pos_end) 31 | ) 32 | 33 | def visit_StringNode(self, node, context): 34 | return RTResult().success( 35 | String(node.token.value) 36 | .set_context(context) 37 | .set_pos(node.pos_start, node.pos_end) 38 | ) 39 | 40 | def visit_ListNode(self, node, context): 41 | res = RTResult() 42 | elements = [] 43 | 44 | for element_node in node.element_nodes: 45 | elements.append(res.register(self.visit(element_node, context))) 46 | if res.should_return(): 47 | return res 48 | 49 | return res.success( 50 | List(elements).set_context(context).set_pos(node.pos_start, node.pos_end) 51 | ) 52 | 53 | def visit_VarAccessNode(self, node, context): 54 | res = RTResult() 55 | var_name = node.var_name_token.value 56 | value = context.symbol_table.get(var_name) 57 | 58 | if value == None: 59 | return res.failure( 60 | RTError( 61 | node.pos_start, node.pos_end, f"{var_name} परिभाषित नाही (not defined)", context 62 | ) 63 | ) 64 | value = value.copy().set_pos(node.pos_start, node.pos_end).set_context(context) 65 | return res.success(value) 66 | 67 | def visit_VarAssignNode(self, node, context): 68 | res = RTResult() 69 | var_name = node.var_name_token.value 70 | 71 | if node.declare == False: 72 | value = context.symbol_table.get(var_name) 73 | if value == None: 74 | return res.failure( 75 | RTError( 76 | node.pos_start, 77 | node.pos_end, 78 | f"{var_name} नेमणूक करण्यापूर्वी संदर्भ(reference before assignment)", 79 | context, 80 | ) 81 | ) 82 | value = res.register(self.visit(node.value_node, context)) 83 | if res.should_return(): 84 | return res 85 | context.symbol_table.set(var_name, value) 86 | return res.success(value) 87 | 88 | def visit_BinOpNode(self, node, context): 89 | res = RTResult() 90 | left = res.register(self.visit(node.left_node, context)) 91 | if res.should_return(): 92 | return res 93 | right = res.register(self.visit(node.right_node, context)) 94 | if res.should_return(): 95 | return res 96 | 97 | if node.op_token.type == TT_PLUS: 98 | result, error = left.added_to(right) 99 | elif node.op_token.type == TT_MINUS: 100 | result, error = left.subbed_by(right) 101 | elif node.op_token.type == TT_MUL: 102 | result, error = left.multed_by(right) 103 | elif node.op_token.type == TT_DIV: 104 | result, error = left.dived_by(right) 105 | elif node.op_token.type == TT_MOD: 106 | result, error = left.moded_by(right) 107 | elif node.op_token.type == TT_POWER: 108 | result, error = left.power_by(right) 109 | elif node.op_token.type == TT_EE: 110 | result, error = left.get_comparison_eq(right) 111 | elif node.op_token.type == TT_NE: 112 | result, error = left.get_comparison_ne(right) 113 | elif node.op_token.type == TT_LT: 114 | result, error = left.get_comparison_lt(right) 115 | elif node.op_token.type == TT_GT: 116 | result, error = left.get_comparison_gt(right) 117 | elif node.op_token.type == TT_LTE: 118 | result, error = left.get_comparison_lte(right) 119 | elif node.op_token.type == TT_GTE: 120 | result, error = left.get_comparison_gte(right) 121 | elif node.op_token.matches(TT_KEYWORD, ("AND", "आणि")): 122 | result, error = left.anded_by(right) 123 | elif node.op_token.matches(TT_KEYWORD, ("OR", "किंवा")): 124 | result, error = left.ored_by(right) 125 | 126 | if error: 127 | return res.failure(error) 128 | else: 129 | return res.success(result.set_pos(node.pos_start, node.pos_end)) 130 | 131 | def visit_UnaryOpNode(self, node, context): 132 | res = RTResult() 133 | number = res.register(self.visit(node.node, context)) 134 | if res.should_return(): 135 | return res 136 | 137 | error = None 138 | 139 | if node.op_token.type == TT_MINUS: 140 | number, error = number.multed_by(Number(-1)) 141 | elif node.op_token.matches(TT_KEYWORD, ("NOT", "नाही")): 142 | number, error = number.notted() 143 | 144 | if error: 145 | return res.failure(error) 146 | else: 147 | return res.success(number.set_pos(node.pos_start, node.pos_end)) 148 | 149 | def visit_IfNode(self, node, context): 150 | res = RTResult() 151 | 152 | for condition, expr, should_return_null in node.cases: 153 | condition_value = res.register(self.visit(condition, context)) 154 | if res.should_return(): 155 | return res 156 | 157 | if condition_value.is_true(): 158 | expr_value = res.register(self.visit(expr, context)) 159 | if res.should_return(): 160 | return res 161 | return res.success(Number.null if should_return_null else expr_value) 162 | 163 | if node.else_case: 164 | expr, should_return_null = node.else_case 165 | else_value = res.register(self.visit(expr, context)) 166 | if res.should_return(): 167 | return res 168 | return res.success(Number.null if should_return_null else else_value) 169 | 170 | return res.success(Number.null) 171 | 172 | def visit_ForNode(self, node, context): 173 | res = RTResult() 174 | elements = [] 175 | 176 | start_value = res.register(self.visit(node.start_value_node, context)) 177 | if res.should_return(): 178 | return res 179 | 180 | end_value = res.register(self.visit(node.end_value_node, context)) 181 | if res.should_return(): 182 | return res 183 | 184 | if node.step_value_node: 185 | step_value = res.register(self.visit(node.step_value_node, context)) 186 | if res.should_return(): 187 | return res 188 | else: 189 | step_value = Number(1) 190 | 191 | i = start_value.value 192 | 193 | if step_value.value >= 0: 194 | condition = lambda: i < end_value.value 195 | else: 196 | condition = lambda: i > end_value.value 197 | 198 | while condition(): 199 | context.symbol_table.set(node.var_name_token.value, Number(i)) 200 | i += step_value.value 201 | 202 | value_ = res.register(self.visit(node.body_node, context)) 203 | 204 | if res.should_return() and res.loop_should_continue==False and res.loop_should_break==False: 205 | return res 206 | 207 | if res.loop_should_continue: 208 | continue 209 | if res.loop_should_break: 210 | break 211 | 212 | elements.append(value_) 213 | 214 | 215 | 216 | return res.success( 217 | Number.null 218 | if node.should_return_null 219 | else List(elements) 220 | .set_context(context) 221 | .set_pos(node.pos_start, node.pos_end) 222 | ) 223 | 224 | def visit_WhileNode(self, node, context): 225 | res = RTResult() 226 | 227 | while True: 228 | condition = res.register(self.visit(node.condition_node, context)) 229 | elements = [] 230 | if res.should_return(): 231 | return res 232 | 233 | if not condition.is_true(): 234 | break 235 | 236 | value_ = res.register(self.visit(node.body_node, context)) 237 | 238 | if res.should_return() and res.loop_should_continue==False and res.loop_should_break==False: 239 | return res 240 | 241 | if res.loop_should_continue: 242 | continue 243 | if res.loop_should_break: 244 | break 245 | 246 | elements.append(value_) 247 | 248 | 249 | 250 | return res.success( 251 | Number.null 252 | if node.should_return_null 253 | else List(elements) 254 | .set_context(context) 255 | .set_pos(node.pos_start, node.pos_end) 256 | ) 257 | 258 | def visit_FuncDefNode(self, node, context): 259 | res = RTResult() 260 | 261 | func_name = node.var_name_token.value if node.var_name_token else None 262 | body_node = node.body_node 263 | arg_names = [arg_name.value for arg_name in node.arg_name_tokens] 264 | func_value = ( 265 | Function(func_name, body_node, arg_names,node.should_auto_return) 266 | .set_context(context) 267 | .set_pos(node.pos_start, node.pos_end) 268 | ) 269 | 270 | if node.var_name_token: 271 | context.symbol_table.set(func_name, func_value) 272 | 273 | return res.success(func_value) 274 | 275 | def visit_CallNode(self, node, context): 276 | res = RTResult() 277 | args = [] 278 | func_name =node.node_to_call.var_name_token.value 279 | if not context.symbol_table.get(func_name): 280 | print("EERPR") 281 | return res.failure( 282 | RTError( 283 | node.pos_start, node.pos_end, f"अज्ञात कार्य बोलावले(call to unknown function)'{func_name}' ", context 284 | ) 285 | ) 286 | 287 | 288 | value_to_call = res.register(self.visit(node.node_to_call, context)) 289 | if res.should_return(): 290 | return res 291 | value_to_call = value_to_call.copy().set_pos(node.pos_start, node.pos_end) 292 | 293 | for arg_node in node.arg_nodes: 294 | args.append(res.register(self.visit(arg_node, context))) 295 | if res.should_return(): 296 | return res 297 | 298 | return_value = res.register(value_to_call.execute(args)) 299 | if res.should_return(): 300 | return res 301 | return_value = ( 302 | return_value.copy() 303 | .set_pos(node.pos_start, node.pos_end) 304 | .set_context(context) 305 | ) 306 | return res.success(return_value) 307 | def visit_ReturnNode(self, node, context): 308 | res = RTResult() 309 | 310 | if node.node_to_return: 311 | value = res.register(self.visit(node.node_to_return, context)) 312 | if res.should_return(): 313 | return res 314 | else: 315 | value = Number.null 316 | 317 | return res.success_return(value) 318 | 319 | def visit_ContinueNode(self, node, context): 320 | return RTResult().success_continue() 321 | 322 | def visit_BreakNode(self, node, context): 323 | return RTResult().success_break() 324 | 325 | def visit_IndexNode(self,node:value.IndexNode,context): 326 | res = RTResult() 327 | args = [] 328 | 329 | value_to_call = res.register(self.visit(node.index_node, context)) 330 | 331 | value_=res.register(self.visit(node.expr, context)) 332 | 333 | if res.should_return(): 334 | return res 335 | 336 | 337 | try: 338 | return_value = value_to_call.elements[value_.value] 339 | except Exception as e: 340 | return res.failure( 341 | RTError( 342 | node.pos_start, node.pos_end, f"{value_to_call} अनुक्रमणिका मर्यादित नाही(Index out of bound) ", context 343 | ) 344 | ) 345 | 346 | return res.success(return_value) 347 | 348 | def visit_IndexAssignNode(self,node:value.IndexAssignNode,context): 349 | res = RTResult() 350 | args = [] 351 | 352 | value_to_call = res.register(self.visit(node.index_node, context)) 353 | 354 | value_=res.register(self.visit(node.expr, context)) 355 | 356 | if res.should_return(): 357 | return res 358 | 359 | assgin_expr=res.register(self.visit(node.assgin_expr, context)) 360 | if res.should_return(): 361 | return res 362 | 363 | try: 364 | value_to_call.elements[value_.value]=assgin_expr 365 | except Exception as e: 366 | return res.failure( 367 | RTError( 368 | node.pos_start, node.pos_end, f"{value_to_call} अनुक्रमणिका मर्यादित नाही(Index out of bound)", context 369 | ) 370 | ) 371 | 372 | return res.success(assgin_expr) 373 | 374 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 joey00072 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Parser/__init__.py: -------------------------------------------------------------------------------- 1 | from Parser.parser import Parser -------------------------------------------------------------------------------- /Parser/parser.py: -------------------------------------------------------------------------------- 1 | from Errors import InvalidSyntaxError 2 | from Constants import * 3 | from Results import ParseResult 4 | from Nodes import * 5 | 6 | 7 | # ------------PARSER---------------- 8 | 9 | 10 | class Parser: 11 | def __init__(self, tokens): 12 | self.tokens = tokens 13 | self.token_idx = -1 14 | self.advance() 15 | 16 | def advance(self): 17 | self.token_idx += 1 18 | self.update_current_token() 19 | return self.current_token 20 | 21 | def reverse(self, amount=1): 22 | self.token_idx -= amount 23 | self.update_current_token() 24 | return self.current_token 25 | 26 | def update_current_token(self): 27 | if self.token_idx >= 0 and self.token_idx < len(self.tokens): 28 | self.current_token = self.tokens[self.token_idx] 29 | 30 | def peak(self): 31 | idx = self.token_idx + 1 32 | if idx < len(self.tokens): 33 | return self.tokens[idx] 34 | 35 | # -------------------# 36 | 37 | def parse(self): 38 | res = self.statements() 39 | if not res.error and self.current_token.type != TT_EOF: 40 | return res.failure( 41 | InvalidSyntaxError( 42 | self.current_token.pos_start, 43 | self.current_token.pos_end, 44 | "अपेक्षित(Expected) '+','-', '*' or '/'", 45 | ) 46 | ) 47 | return res 48 | 49 | def statements(self): 50 | res = ParseResult() 51 | statements = [] 52 | pos_start = self.current_token.pos_start.copy() 53 | 54 | while self.current_token.type == TT_NEWLINE: 55 | res.register_advancement() 56 | self.advance() 57 | 58 | statement = res.register(self.statement()) 59 | if res.error: 60 | return res 61 | statements.append(statement) 62 | 63 | more_statements = True 64 | 65 | while True: 66 | newline_count = -1 67 | while self.current_token.type == TT_NEWLINE: 68 | res.register_advancement() 69 | self.advance() 70 | newline_count += 1 71 | if newline_count == -1: 72 | more_statements = False 73 | 74 | if not more_statements: 75 | break 76 | statement = res.try_register(self.statement()) 77 | if not statement: 78 | self.reverse(res.to_reverse_count) 79 | more_statements = False 80 | continue 81 | statements.append(statement) 82 | 83 | return res.success( 84 | ListNode(statements, pos_start, self.current_token.pos_end.copy()) 85 | ) 86 | 87 | def statement(self): 88 | res = ParseResult() 89 | pos_start = self.current_token.pos_start.copy() 90 | 91 | if self.current_token.matches(TT_KEYWORD, ("RETURN", "परत")): 92 | res.register_advancement() 93 | self.advance() 94 | 95 | expr = res.try_register(self.expr()) 96 | if not expr: 97 | self.reverse(res.to_reverse_count) 98 | return res.success( 99 | ReturnNode(expr, pos_start, self.current_token.pos_start.copy()) 100 | ) 101 | 102 | if self.current_token.matches(TT_KEYWORD, ("CONTINUE", "सुरू")): 103 | res.register_advancement() 104 | self.advance() 105 | return res.success( 106 | ContinueNode(pos_start, self.current_token.pos_start.copy()) 107 | ) 108 | 109 | if self.current_token.matches(TT_KEYWORD, ("BREAK", "थांबवा")): 110 | res.register_advancement() 111 | self.advance() 112 | return res.success( 113 | BreakNode(pos_start, self.current_token.pos_start.copy()) 114 | ) 115 | 116 | expr = res.register(self.expr()) 117 | if res.error: 118 | return res.failure( 119 | InvalidSyntaxError( 120 | self.current_token.pos_start, 121 | self.current_token.pos_end, 122 | "अपेक्षित(Expected) 'परत', 'सुरू', 'थांबवा', 'चल', 'जर', 'वारंवार', 'जोपर्यंत', 'कार्य', 'संख्या', 'शब्द', '+', '-', '(', '['", 123 | ) 124 | ) 125 | return res.success(expr) 126 | 127 | def expr(self): 128 | res = ParseResult() 129 | if self.current_token.matches(TT_KEYWORD, ("VAR", "चल")): 130 | res.register_advancement() 131 | self.advance() 132 | if self.current_token.type != "IDENTIFIER": 133 | return res.failure( 134 | InvalidSyntaxError( 135 | self.current_token.pos_start, 136 | self.current_token.pos_end, 137 | "अपेक्षित चल शब्द (Expected Identifier)", 138 | ) 139 | ) 140 | var_name = self.current_token 141 | res.register_advancement() 142 | self.advance() 143 | 144 | if self.current_token.type != TT_EQ: 145 | return res.failure( 146 | InvalidSyntaxError( 147 | self.current_token.pos_start, 148 | self.current_token.pos_end, 149 | "अपेक्षित = (Expected =)", 150 | ) 151 | ) 152 | res.register_advancement() 153 | self.advance() 154 | expr = res.register(self.expr()) 155 | if res.error: 156 | return res 157 | return res.success(VarAssignNode(var_name, expr, True)) 158 | 159 | if self.current_token.type == "IDENTIFIER": 160 | var_name = self.current_token 161 | next_token = self.peak() 162 | if next_token != None and next_token.type == TT_EQ: 163 | res.register_advancement() 164 | self.advance() 165 | res.register_advancement() 166 | self.advance() 167 | expr = res.register(self.expr()) 168 | if res.error: 169 | return res 170 | return res.success(VarAssignNode(var_name, expr, False)) 171 | 172 | pass_keywords = ( 173 | (TT_KEYWORD, "AND"), 174 | (TT_KEYWORD, "आणि"), 175 | (TT_KEYWORD, "OR"), 176 | (TT_KEYWORD, "किंवा"), 177 | ) 178 | node = res.register(self.bin_op(self.comp_expr, pass_keywords)) 179 | 180 | if res.error: 181 | return res.failure( 182 | InvalidSyntaxError( 183 | self.current_token.pos_start, 184 | self.current_token.pos_end, 185 | "अपेक्षित(Expected) 'चल', 'संख्या', 'शब्द','जर', 'वारंवार', 'जोपर्यंत', 'कार्य', '+', '-','(' or '[' ", 186 | ) 187 | ) 188 | return res.success(node) 189 | 190 | def comp_expr(self): 191 | res = ParseResult() 192 | 193 | if self.current_token.matches(TT_KEYWORD, ("NOT", "नाही")): 194 | op_token = self.current_token 195 | res.register_advancement() 196 | self.advance() 197 | 198 | node = res.register(self.comp_expr()) 199 | if res.error: 200 | return res 201 | return res.success(UnaryOpNode(op_token, node)) 202 | 203 | node = res.register( 204 | self.bin_op(self.arith_expr, (TT_EE, TT_NE, TT_LT, TT_GT, TT_LTE, TT_GTE)) 205 | ) 206 | 207 | if res.error: 208 | return res.failure( 209 | InvalidSyntaxError( 210 | self.current_token.pos_start, 211 | self.current_token.pos_end, 212 | "अपेक्षित(Expected), 'संख्या', 'शब्द', '+', '-', '(','['", 213 | ) 214 | ) 215 | 216 | return res.success(node) 217 | 218 | def arith_expr(self): 219 | return self.bin_op(self.term, (TT_PLUS, TT_MINUS)) 220 | 221 | def term(self): 222 | return self.bin_op(self.factor, (TT_MUL, TT_DIV)) 223 | 224 | def factor(self): 225 | res = ParseResult() 226 | token = self.current_token 227 | if token.type in (TT_PLUS, TT_MINUS): 228 | res.register_advancement() 229 | self.advance() 230 | factor = res.register(self.factor()) 231 | if res.error: 232 | return res 233 | return res.success(UnaryOpNode(token, factor)) 234 | 235 | return self.mod() 236 | 237 | def mod(self): 238 | return self.bin_op(self.power, (TT_MOD,), self.factor) 239 | 240 | def power(self): 241 | return self.bin_op(self.call, (TT_POWER,), self.mod) 242 | 243 | 244 | def call(self): 245 | res = ParseResult() 246 | atom = res.register(self.atom()) 247 | if res.error: 248 | return res 249 | 250 | if self.current_token.type == TT_LPAREN: 251 | res.register_advancement() 252 | self.advance() 253 | arg_nodes = [] 254 | 255 | if self.current_token.type == TT_RPAREN: 256 | res.register_advancement() 257 | self.advance() 258 | else: 259 | arg_nodes.append(res.register(self.expr())) 260 | if res.error: 261 | return res.failure( 262 | InvalidSyntaxError( 263 | self.current_token.pos_start, 264 | self.current_token.pos_end, 265 | "अपेक्षित(Expected) ')', 'चल', 'जर', 'वारंवार', 'जोपर्यंत', 'कार्य', 'संख्या', 'शब्द', '+', '-', '(','[' or 'NOT'", 266 | ) 267 | ) 268 | 269 | while self.current_token.type == TT_COMMA: 270 | res.register_advancement() 271 | self.advance() 272 | 273 | arg_nodes.append(res.register(self.expr())) 274 | if res.error: 275 | return res 276 | 277 | if self.current_token.type != TT_RPAREN: 278 | return res.failure( 279 | InvalidSyntaxError( 280 | self.current_token.pos_start, 281 | self.current_token.pos_end, 282 | f"अपेक्षित(Expected) ',' or ')'", 283 | ) 284 | ) 285 | 286 | res.register_advancement() 287 | self.advance() 288 | return res.success(CallNode(atom, arg_nodes)) 289 | 290 | while self.current_token.type == TT_LSQUARE: 291 | res.register_advancement() 292 | self.advance() 293 | expr = res.register(self.expr()) 294 | if self.current_token.type != TT_RSQUARE: 295 | return res.failure( 296 | InvalidSyntaxError( 297 | self.current_token.pos_start, 298 | self.current_token.pos_end, 299 | f"अपेक्षित(Expected) ']'", 300 | ) 301 | ) 302 | res.register_advancement() 303 | self.advance() 304 | 305 | if self.current_token.type == TT_EQ: 306 | res.register_advancement() 307 | self.advance() 308 | assgin_expr = res.register(self.expr()) 309 | return res.success(IndexAssignNode(atom,expr,assgin_expr)) 310 | 311 | atom= IndexNode(atom, expr) 312 | 313 | 314 | 315 | 316 | 317 | return res.success(atom) 318 | 319 | def atom(self): 320 | res = ParseResult() 321 | token = self.current_token 322 | if self.current_token.type in (TT_INT, TT_FLOAT): 323 | res.register_advancement() 324 | self.advance() 325 | return res.success(NumberNode(token)) 326 | 327 | if self.current_token.type in (TT_STRING): 328 | res.register_advancement() 329 | self.advance() 330 | return res.success(StringNode(token)) 331 | 332 | if self.current_token.type in (TT_IDENTIFIER): 333 | res.register_advancement() 334 | self.advance() 335 | return res.success(VarAccessNode(token)) 336 | 337 | if token.type == TT_LSQUARE: 338 | list_expr = res.register(self.list_expr()) 339 | if res.error: 340 | return res 341 | return res.success(list_expr) 342 | 343 | if token.type == TT_LPAREN: 344 | res.register_advancement() 345 | self.advance() 346 | expr = res.register(self.expr()) 347 | if self.current_token.type == TT_RPAREN: 348 | res.register_advancement() 349 | self.advance() 350 | return res.success(expr) 351 | else: 352 | return res.failure( 353 | InvalidSyntaxError( 354 | self.current_token.pos_start, 355 | self.current_token.pos_end, 356 | "अपेक्षित(Expected) ')' ", 357 | ) 358 | ) 359 | 360 | if token.matches(TT_KEYWORD, ("IF", "जर")): 361 | if_expr = res.register(self.if_expr()) 362 | if res.error: 363 | return res 364 | return res.success(if_expr) 365 | if token.matches(TT_KEYWORD, ("FOR", "वारंवार")): 366 | for_expr = res.register(self.for_expr()) 367 | if res.error: 368 | return res 369 | return res.success(for_expr) 370 | 371 | if token.matches(TT_KEYWORD, ("WHILE", "जोपर्यंत")): 372 | while_expr = res.register(self.while_expr()) 373 | if res.error: 374 | return res 375 | return res.success(while_expr) 376 | 377 | if token.matches(TT_KEYWORD, ("FUN", "कार्य")): 378 | func_def = res.register(self.func_def()) 379 | if res.error: 380 | return res 381 | return res.success(func_def) 382 | 383 | return res.failure( 384 | InvalidSyntaxError( 385 | self.current_token.pos_start, 386 | self.current_token.pos_end, 387 | "अपेक्षित(Expected) int,float, identifier,'IF', 'FOR', 'WHILE', 'FUN', '+','-','[' or '('", 388 | ) 389 | ) 390 | 391 | def list_expr(self): 392 | res = ParseResult() 393 | element_nodes = [] 394 | pos_start = self.current_token.pos_start.copy() 395 | 396 | if self.current_token.type != TT_LSQUARE: 397 | return res.failure( 398 | InvalidSyntaxError( 399 | self.current_token.pos_start, 400 | self.current_token.pos_end, 401 | f"अपेक्षित(Expected) '['", 402 | ) 403 | ) 404 | 405 | res.register_advancement() 406 | self.advance() 407 | 408 | if self.current_token.type == TT_RSQUARE: 409 | res.register_advancement() 410 | self.advance() 411 | else: 412 | element_nodes.append(res.register(self.expr())) 413 | if res.error: 414 | return res.failure( 415 | InvalidSyntaxError( 416 | self.current_token.pos_start, 417 | self.current_token.pos_end, 418 | "अपेक्षित(Expected) ']', 'चल', 'जर', 'वारंवार', 'जोपर्यंत', 'कार्य', 'संख्या', 'शब्द', '+', '-', '(', '[' or 'नाही'", 419 | ) 420 | ) 421 | 422 | while self.current_token.type == TT_COMMA: 423 | res.register_advancement() 424 | self.advance() 425 | 426 | element_nodes.append(res.register(self.expr())) 427 | if res.error: 428 | return res 429 | 430 | if self.current_token.type != TT_RSQUARE: 431 | return res.failure( 432 | InvalidSyntaxError( 433 | self.current_token.pos_start, 434 | self.current_token.pos_end, 435 | f"अपेक्षित(Expected) ',' or ']'", 436 | ) 437 | ) 438 | 439 | res.register_advancement() 440 | self.advance() 441 | 442 | return res.success( 443 | ListNode(element_nodes, pos_start, self.current_token.pos_end.copy()) 444 | ) 445 | 446 | def if_expr(self): 447 | res = ParseResult() 448 | all_cases = res.register(self.if_expr_cases(("IF", "जर"))) 449 | if res.error: 450 | return res 451 | cases, else_case = all_cases 452 | return res.success(IfNode(cases, else_case)) 453 | 454 | def if_expr_b(self): 455 | return self.if_expr_cases(("ELIF", "किंवाजर")) 456 | 457 | def if_expr_c(self): 458 | res = ParseResult() 459 | else_case = None 460 | 461 | if self.current_token.matches(TT_KEYWORD, ("ELSE", "नाहीतर")): 462 | res.register_advancement() 463 | self.advance() 464 | 465 | if self.current_token.type == TT_NEWLINE: 466 | res.register_advancement() 467 | self.advance() 468 | 469 | statements = res.register(self.statements()) 470 | if res.error: 471 | return res 472 | else_case = (statements, True) 473 | 474 | if self.current_token.matches(TT_KEYWORD, ("END", "शेवट")): 475 | res.register_advancement() 476 | self.advance() 477 | else: 478 | return res.failure( 479 | InvalidSyntaxError( 480 | self.current_token.pos_start, 481 | self.current_token.pos_end, 482 | "अपेक्षित(Expected) 'शेवट'", 483 | ) 484 | ) 485 | else: 486 | expr = res.register(self.statement()) 487 | if res.error: 488 | return res 489 | else_case = (expr, False) 490 | 491 | return res.success(else_case) 492 | 493 | def if_expr_b_or_c(self): 494 | res = ParseResult() 495 | cases, else_case = [], None 496 | 497 | if self.current_token.matches(TT_KEYWORD, ("ELIF", "किंवाजर")): 498 | all_cases = res.register(self.if_expr_b()) 499 | if res.error: 500 | return res 501 | cases, else_case = all_cases 502 | else: 503 | else_case = res.register(self.if_expr_c()) 504 | if res.error: 505 | return res 506 | 507 | return res.success((cases, else_case)) 508 | 509 | def if_expr_cases(self, case_keyword): 510 | res = ParseResult() 511 | cases = [] 512 | else_case = None 513 | 514 | if not self.current_token.matches(TT_KEYWORD, case_keyword): 515 | return res.failure( 516 | InvalidSyntaxError( 517 | self.current_token.pos_start, 518 | self.current_token.pos_end, 519 | f"अपेक्षित(Expected) '{case_keyword}'", 520 | ) 521 | ) 522 | 523 | res.register_advancement() 524 | self.advance() 525 | 526 | condition = res.register(self.expr()) 527 | if res.error: 528 | return res 529 | 530 | if not self.current_token.matches(TT_KEYWORD, ("THEN", "तर")): 531 | return res.failure( 532 | InvalidSyntaxError( 533 | self.current_token.pos_start, 534 | self.current_token.pos_end, 535 | f"अपेक्षित(Expected) 'तर'", 536 | ) 537 | ) 538 | 539 | res.register_advancement() 540 | self.advance() 541 | 542 | if self.current_token.type == TT_NEWLINE: 543 | res.register_advancement() 544 | self.advance() 545 | 546 | statements = res.register(self.statements()) 547 | if res.error: 548 | return res 549 | cases.append((condition, statements, True)) 550 | 551 | if self.current_token.matches(TT_KEYWORD, ("END", "शेवट")): 552 | res.register_advancement() 553 | self.advance() 554 | else: 555 | all_cases = res.register(self.if_expr_b_or_c()) 556 | if res.error: 557 | return res 558 | new_cases, else_case = all_cases 559 | cases.extend(new_cases) 560 | else: 561 | expr = res.register(self.statement()) 562 | if res.error: 563 | return res 564 | cases.append((condition, expr, False)) 565 | 566 | all_cases = res.register(self.if_expr_b_or_c()) 567 | if res.error: 568 | return res 569 | new_cases, else_case = all_cases 570 | cases.extend(new_cases) 571 | 572 | return res.success((cases, else_case)) 573 | 574 | def for_expr(self): 575 | res = ParseResult() 576 | 577 | if not self.current_token.matches(TT_KEYWORD, ("FOR", "वारंवार")): 578 | return res.failure( 579 | InvalidSyntaxError( 580 | self.current_token.pos_start, 581 | self.current_token.pos_end, 582 | f"अपेक्षित(Expected) 'वारंवार'", 583 | ) 584 | ) 585 | 586 | res.register_advancement() 587 | self.advance() 588 | 589 | if self.current_token.type != TT_IDENTIFIER: 590 | return res.failure( 591 | InvalidSyntaxError( 592 | self.current_token.pos_start, 593 | self.current_token.pos_end, 594 | f"अपेक्षित(Expected) शब्द", 595 | ) 596 | ) 597 | 598 | var_name = self.current_token 599 | res.register_advancement() 600 | self.advance() 601 | 602 | if self.current_token.type != TT_EQ: 603 | return res.failure( 604 | InvalidSyntaxError( 605 | self.current_token.pos_start, 606 | self.current_token.pos_end, 607 | f"अपेक्षित(Expected) '='", 608 | ) 609 | ) 610 | 611 | res.register_advancement() 612 | self.advance() 613 | 614 | start_value = res.register(self.expr()) 615 | if res.error: 616 | return res 617 | 618 | if not self.current_token.matches(TT_KEYWORD, ("TO", "ते")): 619 | return res.failure( 620 | InvalidSyntaxError( 621 | self.current_token.pos_start, 622 | self.current_token.pos_end, 623 | f"अपेक्षित(Expected) 'ते'", 624 | ) 625 | ) 626 | 627 | res.register_advancement() 628 | self.advance() 629 | 630 | end_value = res.register(self.expr()) 631 | if res.error: 632 | return res 633 | 634 | if self.current_token.matches(TT_KEYWORD, ("STEP", "पाऊल")): 635 | res.register_advancement() 636 | self.advance() 637 | 638 | step_value = res.register(self.expr()) 639 | if res.error: 640 | return res 641 | else: 642 | step_value = None 643 | 644 | if not self.current_token.matches(TT_KEYWORD, ("THEN", "तर")): 645 | return res.failure( 646 | InvalidSyntaxError( 647 | self.current_token.pos_start, 648 | self.current_token.pos_end, 649 | f"अपेक्षित(Expected) 'तर'", 650 | ) 651 | ) 652 | 653 | res.register_advancement() 654 | self.advance() 655 | 656 | if self.current_token.type == TT_NEWLINE: 657 | res.register_advancement() 658 | self.advance() 659 | 660 | body = res.register(self.statements()) 661 | if res.error: 662 | return res 663 | 664 | if not self.current_token.matches(TT_KEYWORD, ("END", "शेवट")): 665 | return res.failure( 666 | InvalidSyntaxError( 667 | self.current_token.pos_start, 668 | self.current_token.pos_end, 669 | f"अपेक्षित(Expected) 'शेवट'", 670 | ) 671 | ) 672 | 673 | res.register_advancement() 674 | self.advance() 675 | 676 | return res.success( 677 | ForNode(var_name, start_value, end_value, step_value, body, True) 678 | ) 679 | 680 | body = res.register(self.statement()) 681 | if res.error: 682 | return res 683 | 684 | return res.success( 685 | ForNode(var_name, start_value, end_value, step_value, body, False) 686 | ) 687 | 688 | def while_expr(self): 689 | res = ParseResult() 690 | 691 | if not self.current_token.matches(TT_KEYWORD, ("WHILE", "जोपर्यंत")): 692 | return res.failure( 693 | InvalidSyntaxError( 694 | self.current_token.pos_start, 695 | self.current_token.pos_end, 696 | f"अपेक्षित(Expected) 'जोपर्यंत'", 697 | ) 698 | ) 699 | 700 | res.register_advancement() 701 | self.advance() 702 | 703 | condition = res.register(self.expr()) 704 | if res.error: 705 | return res 706 | 707 | if not self.current_token.matches(TT_KEYWORD, ("THEN", "तर")): 708 | return res.failure( 709 | InvalidSyntaxError( 710 | self.current_token.pos_start, 711 | self.current_token.pos_end, 712 | f"अपेक्षित(Expected) 'तर'", 713 | ) 714 | ) 715 | 716 | res.register_advancement() 717 | self.advance() 718 | 719 | if self.current_token.type == TT_NEWLINE: 720 | res.register_advancement() 721 | self.advance() 722 | 723 | body = res.register(self.statements()) 724 | if res.error: 725 | return res 726 | 727 | if not self.current_token.matches(TT_KEYWORD, ("END", "शेवट")): 728 | return res.failure( 729 | InvalidSyntaxError( 730 | self.current_token.pos_start, 731 | self.current_token.pos_end, 732 | f"अपेक्षित(Expected) 'शेवट'", 733 | ) 734 | ) 735 | 736 | res.register_advancement() 737 | self.advance() 738 | 739 | return res.success(WhileNode(condition, body, True)) 740 | 741 | body = res.register(self.statement()) 742 | if res.error: 743 | return res 744 | 745 | return res.success(WhileNode(condition, body, False)) 746 | 747 | def func_def(self): 748 | res = ParseResult() 749 | 750 | if not self.current_token.matches(TT_KEYWORD, ("FUN", "कार्य")): 751 | return res.failure( 752 | InvalidSyntaxError( 753 | self.current_token.pos_start, 754 | self.current_token.pos_end, 755 | f"अपेक्षित(Expected) 'FUN'", 756 | ) 757 | ) 758 | 759 | res.register_advancement() 760 | self.advance() 761 | 762 | if self.current_token.type == TT_IDENTIFIER: 763 | var_name_tok = self.current_token 764 | res.register_advancement() 765 | self.advance() 766 | if self.current_token.type != TT_LPAREN: 767 | return res.failure( 768 | InvalidSyntaxError( 769 | self.current_token.pos_start, 770 | self.current_token.pos_end, 771 | f"अपेक्षित(Expected) '('", 772 | ) 773 | ) 774 | else: 775 | var_name_tok = None 776 | if self.current_token.type != TT_LPAREN: 777 | return res.failure( 778 | InvalidSyntaxError( 779 | self.current_token.pos_start, 780 | self.current_token.pos_end, 781 | f"अपेक्षित(Expected) शब्द or '('", 782 | ) 783 | ) 784 | 785 | res.register_advancement() 786 | self.advance() 787 | arg_name_toks = [] 788 | 789 | if self.current_token.type == TT_IDENTIFIER: 790 | arg_name_toks.append(self.current_token) 791 | res.register_advancement() 792 | self.advance() 793 | 794 | while self.current_token.type == TT_COMMA: 795 | res.register_advancement() 796 | self.advance() 797 | 798 | if self.current_token.type != TT_IDENTIFIER: 799 | return res.failure( 800 | InvalidSyntaxError( 801 | self.current_token.pos_start, 802 | self.current_token.pos_end, 803 | f"अपेक्षित(Expected) शब्द", 804 | ) 805 | ) 806 | 807 | arg_name_toks.append(self.current_token) 808 | res.register_advancement() 809 | self.advance() 810 | 811 | if self.current_token.type != TT_RPAREN: 812 | return res.failure( 813 | InvalidSyntaxError( 814 | self.current_token.pos_start, 815 | self.current_token.pos_end, 816 | f"अपेक्षित(Expected) ',' or ')'", 817 | ) 818 | ) 819 | else: 820 | if self.current_token.type != TT_RPAREN: 821 | return res.failure( 822 | InvalidSyntaxError( 823 | self.current_token.pos_start, 824 | self.current_token.pos_end, 825 | f"अपेक्षित(Expected) शब्द or ')'", 826 | ) 827 | ) 828 | 829 | res.register_advancement() 830 | self.advance() 831 | 832 | if self.current_token.type == TT_ARROW: 833 | res.register_advancement() 834 | self.advance() 835 | 836 | body = res.register(self.expr()) 837 | if res.error: 838 | return res 839 | 840 | return res.success(FuncDefNode(var_name_tok, arg_name_toks, body, True)) 841 | 842 | if self.current_token.type != TT_NEWLINE: 843 | return res.failure( 844 | InvalidSyntaxError( 845 | self.current_token.pos_start, 846 | self.current_token.pos_end, 847 | f"अपेक्षित(Expected) '->' or '\\n'NEWLINE", 848 | ) 849 | ) 850 | 851 | res.register_advancement() 852 | self.advance() 853 | 854 | body = res.register(self.statements()) 855 | if res.error: 856 | return res 857 | 858 | if not self.current_token.matches(TT_KEYWORD,("END", "शेवट")): 859 | return res.failure( 860 | InvalidSyntaxError( 861 | self.current_token.pos_start, 862 | self.current_token.pos_end, 863 | f"अपेक्षित(Expected) 'शेवट'", 864 | ) 865 | ) 866 | 867 | res.register_advancement() 868 | self.advance() 869 | 870 | return res.success(FuncDefNode(var_name_tok, arg_name_toks, body, False)) 871 | 872 | ################ 873 | 874 | def bin_op(self, func_a, ops, func_b=None): 875 | if func_b == None: 876 | func_b = func_a 877 | res = ParseResult() 878 | left = res.register(func_a()) 879 | if res.error: 880 | return res 881 | 882 | while ( 883 | self.current_token.type in ops 884 | or (self.current_token.type, self.current_token.value) in ops 885 | ): 886 | op_token = self.current_token 887 | res.register_advancement() 888 | self.advance() 889 | right = res.register(func_b()) 890 | if res.error: 891 | return res 892 | left = BinOpNode(left, op_token, right) 893 | return res.success(left) 894 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **बाजी (Baji)- Marathi Programing Language** 2 |

Kalaam logo

3 | 4 | बाजी (baji) high-level,dynamically typed, interpreted first Marathi programing language. 5 | 6 | ## Quick Start 7 | ### Hello World 8 | ``` 9 | दाखवा("नमस्कार विश्व") 10 | ``` 11 | ### Fibonacci Series 12 | ``` 13 | कार्य फिबोनॅकी(क) 14 | जर क<2 तर 15 | परत 1 16 | नाहीतर 17 | परत फिबोनॅकी(क-1) + फिबोनॅकी(क-2) 18 | शेवट 19 | शेवट 20 | 21 | 22 | 23 | वारंवार क=0 ते 24 तर 24 | दाखवा(क) 25 | दाखवा(" ") 26 | दाखवा(फिबोनॅकी(क)) 27 | दाखवा("\n") 28 | शेवट 29 | 30 | 31 | दाखवा("\n") 32 | ``` 33 | Save file with `.baji` extension. 34 |
35 | RUN 36 | ``` 37 | baji example.baji 38 | ``` 39 | ## Docs 40 | refer [DOCS.md](./DOCS.md) 41 | 42 | ## Installation 43 | 1. Download binary from Here 44 | * [RELEASE](https://github.com/joey00072/Marathi-Programing-Language/releases/tag/1.0.1) 45 | 46 | * Windows baji.zip 47 | 48 | * Linux baji.tar 49 | 50 | * Mac Comming Soon... 51 | 2. 52 | **Winodows**
53 | Unzip baji.zip move `baji.exe` to suitable folder path 54 | ``` 55 | C:/baji/baji.exe -> recommanded 56 | ``` 57 | Then set environment variables [guide](https://support.microsoft.com/en-us/topic/how-to-manage-environment-variables-in-windows-xp-5bf6725b-655e-151c-0b55-9a8c9c7f747d) 58 | 59 | 3. **Linux/Mac** 60 | Download baji.tar 61 | then run this command 62 | ``` 63 | tar -xvf baji.tar && sudo mv .baji /bin/ && echo 'export PATH="$PATH:/bin/.baji/"' >> ~/.bashrc && source ~/.bashrc 64 | ``` 65 | note : you need password to run this command also 66 | change bashrc to zshrc if you are using zsh shell 67 | 4. Run File 68 | ``` 69 | baji example.baji 70 | ``` 71 | 72 | ## Build 73 | **Run With Python** 74 | ``` 75 | python3 shell.py example.baji 76 | ``` 77 | Build executable 78 | 79 | Use [pyinstaller](https://github.com/pyinstaller/pyinstaller) to genrate executable 80 | 81 | ``` 82 | python3 -m pyinstller shell.py -n baji 83 | ``` 84 |

85 | 86 | 87 | ## Todo List 88 | 89 | - [x] Refactor 90 | - [ ] print function with multiple args 91 | - [ ] Class Object 92 | - [ ] Replace block Structure with {} 93 | - [ ] Web/Js Version 94 | - [ ] syntax highlighting 95 | 96 | ## Reporting Bugs 97 | Create issue on github or 98 | you can also content me on 00shxf@gmail.com 99 | 100 | 101 | ## Contributions 102 | Any contribution is welcome, drop me a line or file a pull request.
103 | 104 | ## Licenses 105 | Refer [LICENSE](./LICENSE) 106 | 107 | [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R8KQTZ5) 108 | -------------------------------------------------------------------------------- /SymbolTable/__init__.py: -------------------------------------------------------------------------------- 1 | from Values import * 2 | from SymbolTable.symbol_table import SymbolTable 3 | 4 | 5 | 6 | 7 | #Global Symbols 8 | global_symbol_table = SymbolTable() 9 | 10 | # global_symbol_table.set('null',Number(0)) 11 | # global_symbol_table.set('true',Number(1)) 12 | # global_symbol_table.set('false',Number(0)) 13 | global_symbol_table.set("NULL", Number.null) 14 | global_symbol_table.set("FALSE", Number.false) 15 | global_symbol_table.set("TRUE", Number.true) 16 | global_symbol_table.set("MATH_PI", Number(3.141592653589793)) 17 | -------------------------------------------------------------------------------- /SymbolTable/symbol_table.py: -------------------------------------------------------------------------------- 1 | class SymbolTable: 2 | def __init__(self, parent=None): 3 | self.symbols = {} 4 | self.parent = parent 5 | 6 | def get(self, name): 7 | value = self.symbols.get(name, None) 8 | if value == None and self.parent: 9 | return self.parent.get(name) 10 | return value 11 | 12 | def set(self, name, value): 13 | self.symbols[name] = value 14 | 15 | def remove(self, name): 16 | del self.symbols[name] 17 | -------------------------------------------------------------------------------- /Tests/__init__.py: -------------------------------------------------------------------------------- 1 | from Tests.test_variables import * 2 | from Tests.tests_arithmetic import * -------------------------------------------------------------------------------- /Tests/test_variables.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import main 3 | 4 | 5 | class TestVariable(unittest.TestCase): 6 | def test_sum_var(self): 7 | text = "2+(var a=2)" 8 | result, error = main.run("", text) 9 | self.assertEqual(str(result), "४") 10 | 11 | text = "var b=2" 12 | result, error = main.run("", text) 13 | 14 | text = "b+a" 15 | result, error = main.run("", text) 16 | self.assertEqual(str(result), "४") 17 | 18 | def test_sub_var(self): 19 | text = "8-(var a=4)" 20 | result, error = main.run("", text) 21 | self.assertEqual(str(result), "४") 22 | 23 | text = "var b=8" 24 | result, error = main.run("", text) 25 | 26 | text = "b-a" 27 | result, error = main.run("", text) 28 | self.assertEqual(str(result), "४") 29 | 30 | def test_mul_var(self): 31 | text = "2*(var a=2)" 32 | result, error = main.run("", text) 33 | self.assertEqual(str(result), "४") 34 | 35 | text = "var b=2" 36 | result, error = main.run("", text) 37 | 38 | text = "b*a" 39 | result, error = main.run("", text) 40 | self.assertEqual(str(result), "४") 41 | 42 | def test_div_var(self): 43 | text = "8/(var a=2)" 44 | result, error = main.run("", text) 45 | self.assertEqual(str(result), "४") 46 | 47 | text = "var b=8" 48 | result, error = main.run("", text) 49 | 50 | text = "b/a" 51 | result, error = main.run("", text) 52 | self.assertEqual(str(result), "४") 53 | 54 | def test_div_var_float(self): 55 | text = "22/(var a=7)" 56 | result, error = main.run("", text) 57 | self.assertEqual(str(result), "३.१४२८५७१४२८५७१४३") 58 | 59 | text = "var b=22" 60 | result, error = main.run("", text) 61 | 62 | text = "b/a" 63 | result, error = main.run("", text) 64 | self.assertEqual(str(result), "३.१४२८५७१४२८५७१४३") 65 | 66 | 67 | class TestVariableMAR(unittest.TestCase): 68 | def test_sum_var(self): 69 | text = "२+(चल क=२)" 70 | result, error = main.run("", text) 71 | self.assertEqual(str(result), "४") 72 | 73 | text = "चल जग=२" 74 | result, error = main.run("", text) 75 | 76 | text = "जग+क" 77 | result, error = main.run("", text) 78 | self.assertEqual(str(result), "४") 79 | 80 | def test_sub_var(self): 81 | text = "8-(चल क=4)" 82 | result, error = main.run("", text) 83 | self.assertEqual(str(result), "४") 84 | 85 | text = "चल जग=8" 86 | result, error = main.run("", text) 87 | 88 | text = "जग-क" 89 | result, error = main.run("", text) 90 | self.assertEqual(str(result), "४") 91 | 92 | def test_mul_var(self): 93 | text = "२*(चल क=२)" 94 | result, error = main.run("", text) 95 | self.assertEqual(str(result), "४") 96 | 97 | text = "चल जग=२" 98 | result, error = main.run("", text) 99 | 100 | text = "जग*क" 101 | result, error = main.run("", text) 102 | self.assertEqual(str(result), "४") 103 | 104 | def test_div_var(self): 105 | text = "८/(चल क=२)" 106 | result, error = main.run("", text) 107 | self.assertEqual(str(result), "४") 108 | 109 | text = "चल जग=८" 110 | result, error = main.run("", text) 111 | 112 | text = "जग/क" 113 | result, error = main.run("", text) 114 | self.assertEqual(str(result), "४") 115 | 116 | def test_div_var_float(self): 117 | text = "२२/(चल क=७)" 118 | result, error = main.run("", text) 119 | self.assertEqual(str(result), "३.१४२८५७१४२८५७१४३") 120 | 121 | text = "चल जग=२२" 122 | result, error = main.run("", text) 123 | 124 | text = "जग/क" 125 | result, error = main.run("", text) 126 | self.assertEqual(str(result), "३.१४२८५७१४२८५७१४३") 127 | -------------------------------------------------------------------------------- /Tests/tests_arithmetic.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import main 3 | 4 | class TestArithmetic(unittest.TestCase): 5 | 6 | def test_sum(self): 7 | text = '2+2' 8 | result , error = main.run('',text) 9 | self.assertEqual(str(result), "४") 10 | 11 | def test_sub(self): 12 | text = '8-4' 13 | result , error = main.run('',text) 14 | self.assertEqual(str(result), "४") 15 | 16 | def test_mul(self): 17 | text = '2*2' 18 | result , error = main.run('',text) 19 | self.assertEqual(str(result), "४") 20 | 21 | def test_div(self): 22 | text = '8/2' 23 | result , error = main.run('',text) 24 | self.assertEqual(str(result), "४") 25 | 26 | def test_div_float(self): 27 | text = '22/7' 28 | result , error = main.run('',text) 29 | self.assertEqual(str(result), "३.१४२८५७१४२८५७१४३") 30 | 31 | 32 | 33 | 34 | 35 | 36 | if __name__ == '__main__': 37 | unittest.main() -------------------------------------------------------------------------------- /bugs.baji: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joey00072/Baji-Marathi-Programing-Language/43db51c563e351388459044a28f09aec7a74cda3/bugs.baji -------------------------------------------------------------------------------- /example.baji: -------------------------------------------------------------------------------- 1 | वारंवार i = 1 ते 101 तर 2 | IF (i%3==0 AND i%5==0 )THEN 3 | PRINT("FIZZBUZZ\n") 4 | ELIF i%3==0 THEN 5 | PRINT("FIZZ\n") 6 | ELIF i%5==0 THEN 7 | PRINT("BUZZ\n") 8 | ELSE 9 | PRINT(i) 10 | PRINT("\n") 11 | END 12 | शेवट -------------------------------------------------------------------------------- /examples/HelloWorld.baji: -------------------------------------------------------------------------------- 1 | दाखवा("नमस्कार विश्व") -------------------------------------------------------------------------------- /examples/fib.baji: -------------------------------------------------------------------------------- 1 | दाखवा("Recurrsive \n") 2 | 3 | 4 | कार्य फिबोनॅकी(क) 5 | जर क<2 तर 6 | परत 1 7 | नाहीतर 8 | परत फिबोनॅकी(क-1) + फिबोनॅकी(क-2) 9 | शेवट 10 | शेवट 11 | 12 | 13 | 14 | वारंवार क=0 ते 24 तर 15 | दाखवा(क) 16 | दाखवा(" ") 17 | दाखवा(फिबोनॅकी(क)) 18 | दाखवा("\n") 19 | शेवट 20 | 21 | 22 | दाखवा("\n") -------------------------------------------------------------------------------- /examples/fib2.baji: -------------------------------------------------------------------------------- 1 | 2 | दाखवा("Dynamic Programing \n") 3 | 4 | कार्य get_2d_array(length) 5 | चल यादी =[] 6 | वारंवार i = 0 ते length तर 7 | वाढवा(यादी,[RAND_INT(0,0)]) 8 | शेवट 9 | परत यादी 10 | शेवट 11 | 12 | 13 | चल यादी = get_2d_array(100) 14 | 15 | 16 | कार्य फिबोनॅकी(n) 17 | जर n<2 तर 18 | परत 1 19 | किंवाजर यादी[n]!=0 तर 20 | परत यादी[n] 21 | नाहीतर 22 | यादी[n]=फिबोनॅकी(n-1) + फिबोनॅकी(n-2) 23 | परत यादी[n] 24 | शेवट 25 | शेवट 26 | 27 | वारंवार i=0 ते 100 तर 28 | दाखवा(i) 29 | दाखवा(" ") 30 | दाखवा(फिबोनॅकी(i)) 31 | दाखवा("\n") 32 | शेवट -------------------------------------------------------------------------------- /examples/game_of_life.baji: -------------------------------------------------------------------------------- 1 | # Game Of Lजरe 2 | 3 | कार्य बोर्ड_घ्या(तत,दद) 4 | चल बोर्ड =[] 5 | वारंवार i = 0 ते तत तर 6 | चल कतक = [] 7 | वारंवार j=0 ते दद तर 8 | वाढवा(कतक,[०]) 9 | शेवट 10 | बोर्ड = बोर्ड+कतक 11 | शेवट 12 | परत बोर्ड 13 | शेवट 14 | 15 | चल आकार = 10 16 | चल बोर्ड = बोर्ड_घ्या(आकार,2*आकार) 17 | 18 | 19 | बोर्ड[1+2][0+2]=1 20 | बोर्ड[0+2][2+2]=1 21 | बोर्ड[1+2][2+2]=1 22 | बोर्ड[2+2][2+2]=1 23 | बोर्ड[2+2][1+2]=1 24 | 25 | कार्य दाखवा_बोर्ड() 26 | वारंवार i=0 ते लांबी(बोर्ड) तर 27 | वारंवार j=0 ते लांबी(बोर्ड[0]) तर 28 | दाखवा(".") 29 | जर बोर्ड[i][j]==1 तर 30 | दाखवा("#") 31 | नाहीतर 32 | दाखवा(".") 33 | शेवट 34 | शेवट 35 | दाखवा("\n") 36 | शेवट 37 | शेवट 38 | 39 | 40 | कार्य ददद(पप,कर) 41 | चल करर =0 42 | करर = (पप+कर+आकार)%आकार 43 | परत करर 44 | शेवट 45 | 46 | 47 | 48 | 49 | कार्य is_alive(ox,oy) 50 | चल cnt =0 51 | चल x =0 52 | चल y =0 53 | वारंवार i=-1 ते 2 तर 54 | वारंवार j=-1 ते 2 तर 55 | जर (i==0 AND j==0) != 1 तर 56 | x = ददद(ox,i) 57 | y = ददद(oy,j) 58 | जर बोर्ड[y][x]==1 तर 59 | cnt= cnt+1 60 | शेवट 61 | शेवट 62 | शेवट 63 | शेवट 64 | चल RT = 0 65 | जर cnt<2 OR cnt>3 तर 66 | RT= 0 67 | किंवाजर बोर्ड[oy][ox]==1 AND cnt<4 तर 68 | RT= 1 69 | किंवाजर cnt==3 तर 70 | RT= 1 71 | शेवट 72 | परत RT 73 | शेवट 74 | 75 | कार्य next_gen() 76 | चल गद = बोर्ड_घ्या(आकार,2*आकार) 77 | वारंवार y=0 ते आकार तर 78 | वारंवार x=0 ते आकार तर 79 | गद[y][x]=is_alive(x,y) 80 | शेवट 81 | शेवट 82 | परत गद 83 | शेवट 84 | 85 | 86 | 87 | WHILE 5==5 तर 88 | पुसा() 89 | दाखवा_बोर्ड() 90 | बोर्ड = next_gen() 91 | शेवट 92 | 93 | -------------------------------------------------------------------------------- /examples/if_else.baji: -------------------------------------------------------------------------------- 1 | 2 | IF 1==1 THEN 3 | PRINT("IF") 4 | END 5 | 6 | IF 1==1 THEN 7 | PRINT("IF") 8 | END 9 | 10 | IF 1==1 THEN 11 | PRINT("IF") 12 | END 13 | 14 | IF 1==1 THEN 15 | PRINT("IF") 16 | END -------------------------------------------------------------------------------- /grammar.md: -------------------------------------------------------------------------------- 1 | ## GRAMMAR 2 | --- 3 | statements : NEWLINE* statement (NEWLINE+ statement)* NEWLINE* 4 | --- 5 | statement : KEYWORD:RETURN expr? 6 | : KEYWORD:CONTINUE 7 | : KEYWORD:BREAK 8 | : expr 9 | --- 10 | 11 | expr : KEYWORD var|चल IDENTIFIER EQ expr 12 | : comp-expr ((KEYWORD:AND|KEYWORD:OR) comp-expr)* 13 | 14 | --- 15 | 16 | comp-expr : NOT comp-expr 17 | : arith-expr ((EE|LT|GT|LTE|GTE) arith-expr)* 18 | 19 | --- 20 | 21 | arith-expr : term ((PLUS|MINUS) term)* 22 | 23 | --- 24 | 25 | term : factor((MUL|DIV) factor)* 26 | 27 | --- 28 | 29 | factor : (PLUS|MINUS) factor 30 | : mod 31 | --- 32 | mod : power((MUL|DIV) factor)* 33 | --- 34 | 35 | power : call(POWER mod)* 36 | --- 37 | call : atom (LPAREN (expr (COMMA expr)*)? RPAREN)? 38 | : atom (LSQUARE (expr) LSQUARE)? EQ expr 39 | : atom (LSQUARE (expr) LSQUARE)? 40 | 41 | --- 42 | 43 | atom : INT | FLOAT | STRING | IDENTIFIER 44 | : LPARAN expr RPARAN 45 | : list-expr 46 | : if-expr 47 | : for-expr 48 | : while-expr 49 | : func-def 50 | --- 51 | list-expr : LSQUARE (expr (COMMA expr)*)? RSQUARE 52 | --- 53 | if-expr : KEYWORD:IF expr KEYWORD:THEN 54 | (statement if-expr-b|if-expr-c?) 55 | | (NEWLINE statements KEYWORD:END|if-expr-b|if-expr-c) 56 | --- 57 | if-expr-b : KEYWORD:ELIF expr KEYWORD:THEN 58 | (statement if-expr-b|if-expr-c?) 59 | | (NEWLINE statements KEYWORD:END|if-expr-b|if-expr-c) 60 | --- 61 | if-expr-c : KEYWORD:ELSE 62 | statement 63 | | (NEWLINE statements KEYWORD:END) 64 | 65 | --- 66 | for-expr : KEYWORD:FOR IDENTIFIER EQ expr KEYWORD:TO 67 | statement 68 | | (NEWLINE statements KEYWORD:END)expr 69 | 70 | --- 71 | while-expr : KEYWORD:WHILE expr KEYWORD:THEN 72 | statement 73 | | (NEWLINE statements KEYWORD:END) 74 | --- 75 | func-def : KEYWORD:FUN IDENTIFIER? 76 | LPAREN (IDENTIFIER (COMMA IDENTIFIER)*)? RPAREN 77 | (ARROW expr) 78 | | (NEWLINE statements KEYWORD:END) 79 | 80 | -------------------------------------------------------------------------------- /lexer/__init__.py: -------------------------------------------------------------------------------- 1 | from Lexer.lexer import * 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lexer/lexer.py: -------------------------------------------------------------------------------- 1 | from typing import Counter 2 | from Translate import Translate 3 | from Errors import Error, IllegalCharacterError, ExpectedCharError 4 | from Lexer.position import Position 5 | from Lexer.token import Token 6 | from Constants import * 7 | 8 | 9 | # -----------LEXER--------------- 10 | 11 | 12 | class Lexer: 13 | def __init__(self, fn, text): 14 | self.fn = fn 15 | self.text = text 16 | self.pos = Position(-1, 0, -1, fn, text) 17 | self.current_char = None 18 | self.advance() 19 | self.translate = Translate() 20 | 21 | def advance(self): 22 | self.pos.advance(self.current_char) 23 | self.current_char = ( 24 | self.text[self.pos.idx] if self.pos.idx < len(self.text) else None 25 | ) 26 | 27 | def peak(self, idx=1): 28 | if self.pos.idx + idx < len(self.text): 29 | return self.text[self.pos.idx + idx] 30 | return None 31 | 32 | def primitive_token(self): 33 | if self.current_char == "+": 34 | return TT_PLUS, None 35 | 36 | if self.current_char == "-": 37 | return self.make_minus_or_arrow() 38 | 39 | if self.current_char == "*": 40 | return self.make_mul_or_power() 41 | 42 | if self.current_char == "/": 43 | return TT_DIV, None 44 | 45 | if self.current_char == "%": 46 | return TT_MOD, None 47 | 48 | if self.current_char == ",": 49 | return TT_COMMA, None 50 | 51 | if self.current_char == "(": 52 | return TT_LPAREN, None 53 | 54 | if self.current_char == ")": 55 | return TT_RPAREN, None 56 | 57 | if self.current_char == "[": 58 | return TT_LSQUARE, None 59 | 60 | if self.current_char == "]": 61 | return TT_RSQUARE , None 62 | 63 | if self.current_char == "=": 64 | return self.make_equals() 65 | if self.current_char == "<": 66 | return self.make_less_than() 67 | 68 | if self.current_char == ">": 69 | return self.make_greater_than() 70 | 71 | if self.current_char == "!": 72 | token, error = self.make_not_equals() 73 | if error: 74 | return None, error 75 | return token, None 76 | 77 | if self.current_char in ";\n": 78 | return TT_NEWLINE,None 79 | 80 | 81 | 82 | 83 | return None, None 84 | 85 | def get_token(self): 86 | token, error = self.primitive_token() 87 | 88 | if error: 89 | return error 90 | if token: 91 | self.advance() 92 | return Token(token, pos_start=self.pos) 93 | 94 | if self.current_char == '"': 95 | return self.make_string() 96 | 97 | if self.current_char in DIGITS: 98 | return self.make_number() 99 | 100 | if self.current_char in LETTERS: 101 | return self.make_identifier() 102 | 103 | 104 | 105 | 106 | position_start = self.pos.copy() 107 | 108 | return IllegalCharacterError( 109 | position_start, self.pos, "'" + self.current_char + "'" 110 | ) 111 | 112 | def make_tokens(self): 113 | tokens = [] 114 | while self.current_char != None: 115 | if self.current_char in " \t": 116 | self.advance() 117 | continue 118 | if self.current_char == "#": 119 | self.skip_comment() 120 | current_token = self.get_token() 121 | if isinstance(current_token, Error): 122 | return [], current_token 123 | tokens.append(current_token) 124 | 125 | tokens.append(Token(TT_EOF, pos_start=self.pos)) 126 | return tokens, None 127 | 128 | def make_number(self): 129 | num_str = "" 130 | dot = False 131 | pos_start = self.pos 132 | 133 | while self.current_char != None and self.current_char in DIGITS + ".": 134 | if self.current_char == ".": 135 | if dot == True: 136 | break 137 | dot = True 138 | num_str += "." 139 | else: 140 | num_str += self.translate.digit_to_eng(self.current_char) 141 | self.advance() 142 | 143 | if dot: 144 | return Token( 145 | TT_FLOAT, float(num_str), pos_start=pos_start, pos_end=self.pos 146 | ) 147 | else: 148 | return Token(TT_INT, int(num_str), pos_start=pos_start, pos_end=self.pos) 149 | 150 | def make_string(self): 151 | string = '' 152 | pos_start = self.pos.copy() 153 | escape_character = False 154 | self.advance() 155 | 156 | escape_characters = { 157 | 'n': '\n', 158 | 't': '\t' 159 | } 160 | 161 | while self.current_char != None and (self.current_char != '"' or escape_character): 162 | if escape_character: 163 | string += escape_characters.get(self.current_char, self.current_char) 164 | else: 165 | if self.current_char == '\\': 166 | escape_character = True 167 | if self.peak()=="n": 168 | self.advance() 169 | string+="\n" 170 | else: 171 | string += self.current_char 172 | self.advance() 173 | escape_character = False 174 | 175 | self.advance() 176 | return Token(TT_STRING, string, pos_start, self.pos) 177 | 178 | 179 | def make_identifier(self): 180 | id_str = "" 181 | pos_start = self.pos 182 | 183 | while self.current_char != None and self.current_char in LETTERS_DIGITS + "_": 184 | id_str += self.translate.digit_to_eng(self.current_char) 185 | self.advance() 186 | 187 | token_type = TT_KEYWORD if id_str in KEYWORDS else TT_IDENTIFIER 188 | return Token(token_type, id_str, pos_start, self.pos) 189 | 190 | def make_not_equals(self): 191 | pos_start = self.pos.copy() 192 | self.advance() 193 | 194 | if self.current_char == "=": 195 | return TT_NE, None 196 | 197 | return None, ExpectedCharError(pos_start, self.pos, "'=' (after '!')") 198 | 199 | def make_equals(self): 200 | tok_type = TT_EQ 201 | nxt = self.peak() 202 | if nxt == "=": 203 | self.advance() 204 | tok_type = TT_EE 205 | return tok_type, None 206 | 207 | def make_less_than(self): 208 | tok_type = TT_LT 209 | nxt = self.peak() 210 | 211 | if nxt == "=": 212 | self.advance() 213 | tok_type = TT_LTE 214 | 215 | return tok_type, None 216 | 217 | def make_greater_than(self): 218 | tok_type = TT_GT 219 | nxt = self.peak() 220 | 221 | if nxt == "=": 222 | self.advance() 223 | tok_type = TT_GTE 224 | 225 | return tok_type, None 226 | 227 | def make_mul_or_power(self): 228 | tok_type = TT_MUL 229 | nxt = self.peak() 230 | 231 | if nxt == "*": 232 | self.advance() 233 | tok_type = TT_POWER 234 | 235 | return tok_type, None 236 | 237 | def make_minus_or_arrow(self): 238 | tok_type = TT_MINUS 239 | nxt = self.peak() 240 | 241 | if nxt == ">": 242 | self.advance() 243 | tok_type = TT_ARROW 244 | 245 | return tok_type, None 246 | 247 | def skip_comment(self): 248 | while self.current_char != '\n': 249 | self.advance() 250 | self.advance() 251 | -------------------------------------------------------------------------------- /lexer/position.py: -------------------------------------------------------------------------------- 1 | # ----------Position-------------- 2 | 3 | 4 | class Position: 5 | def __init__(self, idx, ln, col, fn, ftxt): 6 | self.idx = idx 7 | self.ln = ln 8 | self.col = col 9 | self.fn = fn 10 | self.ftxt = ftxt 11 | 12 | def advance(self, current_char=None): 13 | self.idx += 1 14 | self.col += 1 15 | 16 | if current_char == "\n": 17 | self.ln += 1 18 | self.col = 0 19 | return self 20 | 21 | def copy(self): 22 | return Position(self.idx, self.ln, self.col, self.fn, self.ftxt) -------------------------------------------------------------------------------- /lexer/token.py: -------------------------------------------------------------------------------- 1 | class Token: 2 | def __init__(self, type_, value=None, pos_start=None, pos_end=None): 3 | self.type = type_ 4 | self.value = value 5 | if pos_start: 6 | self.pos_start = pos_start.copy() 7 | self.pos_end = pos_start.copy() 8 | self.pos_end.advance() 9 | 10 | if pos_end: 11 | self.pos_end = pos_end.copy() 12 | 13 | def matches(self, type_, value): 14 | if isinstance(value,tuple): 15 | match=False 16 | for val in value: 17 | match = match or (self.type == type_ and self.value == val) 18 | return match 19 | return self.type == type_ and self.value == value 20 | 21 | def __repr__(self): 22 | return f"{self.type}:{self.value}" if self.value else f"{self.type}" 23 | -------------------------------------------------------------------------------- /logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joey00072/Baji-Marathi-Programing-Language/43db51c563e351388459044a28f09aec7a74cda3/logo.gif -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from Lexer import Lexer 2 | from Parser import Parser 3 | from Interpreter import Interpreter 4 | from Context import Context 5 | from SymbolTable import global_symbol_table 6 | 7 | import sys 8 | 9 | 10 | #------------EXECUTE-------------- 11 | 12 | # ------------RUN----------------- 13 | 14 | context =None 15 | def run(fn, text, debug=False): 16 | global context 17 | lexer = Lexer(fn, text) 18 | # Genarate Tokens 19 | tokens, error = lexer.make_tokens() 20 | if error: 21 | return None, error 22 | 23 | # Generate AST 24 | parser = Parser(tokens) 25 | ast = parser.parse() 26 | 27 | if debug: 28 | print("---symbols--\n") 29 | print(global_symbol_table.symbols, "\n") 30 | print("---tokens--\n") 31 | print(tokens, "\n") 32 | print("--AST--\n") 33 | print(ast.node, "\n") 34 | print("--output--\n") 35 | 36 | if ast.error: 37 | return None, ast.error 38 | 39 | # Run program 40 | interpreter = Interpreter() 41 | context = Context("") 42 | context.symbol_table = global_symbol_table 43 | result = interpreter.visit(ast.node, context) 44 | 45 | return result.value, result.error 46 | 47 | 48 | def run_from_file(file_name): 49 | splits = file_name.strip().split(".") 50 | 51 | if len(splits)<2: 52 | print("Invalid argument") 53 | 54 | name = "".join(splits[:-1]) 55 | 56 | extension = splits[-1].lower() 57 | 58 | if extension!='baji': 59 | print("File extension should .baji") 60 | print(f"Found -> {extension}") 61 | exit() 62 | 63 | try: 64 | with open(file_name , 'r',encoding='utf-8') as f: 65 | script = f.read() 66 | except BaseException as e: 67 | print("Failed to load Script") 68 | print(str(e)) 69 | 70 | _,error = run(f"<{name}>", script, debug=False) 71 | 72 | if error: 73 | print(error.as_string()) 74 | 75 | 76 | if __name__=="__main__": 77 | args = sys.argv 78 | 79 | if len(args)>1: 80 | run_from_file(args[1]) 81 | else: 82 | print("Provide file name") 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /nodes/__init__.py: -------------------------------------------------------------------------------- 1 | # ------------NODES---------------- 2 | 3 | from Nodes.operation import * 4 | from Nodes.value import * 5 | from Nodes.variable import * 6 | from Nodes.conditional import * 7 | from Nodes.loop import * 8 | from Nodes.functions import * -------------------------------------------------------------------------------- /nodes/conditional.py: -------------------------------------------------------------------------------- 1 | class IfNode: 2 | def __init__(self, cases, else_case): 3 | self.cases = cases 4 | self.else_case = else_case 5 | 6 | self.pos_start = self.cases[0][0].pos_start 7 | self.pos_end = (self.else_case or self.cases[len(self.cases) - 1])[0].pos_end 8 | 9 | def __repr__(self): 10 | return f"(IF {self.cases}, THEN )" 11 | -------------------------------------------------------------------------------- /nodes/functions.py: -------------------------------------------------------------------------------- 1 | class FuncDefNode: 2 | def __init__(self, var_name_token, arg_name_tokens, body_node, should_auto_return): 3 | self.var_name_token = var_name_token 4 | self.arg_name_tokens = arg_name_tokens 5 | self.body_node = body_node 6 | 7 | if self.var_name_token: 8 | self.pos_start = self.var_name_token.pos_start 9 | elif len(self.arg_name_tokens) > 0: 10 | self.pos_start = self.arg_name_tokens[0].pos_start 11 | else: 12 | self.pos_start = self.body_node.pos_start 13 | 14 | self.pos_end = self.body_node.pos_end 15 | 16 | self.should_auto_return = should_auto_return 17 | 18 | def __repr__(self): 19 | return f"( function {self.var_name_token}->args({self.arg_name_tokens}) ({self.body_node}) ) " 20 | 21 | 22 | class CallNode: 23 | def __init__(self, node_to_call, arg_nodes): 24 | self.node_to_call = node_to_call 25 | self.arg_nodes = arg_nodes 26 | 27 | self.pos_start = self.node_to_call.pos_start 28 | 29 | if len(self.arg_nodes) > 0: 30 | self.pos_end = self.arg_nodes[len(self.arg_nodes) - 1].pos_end 31 | else: 32 | self.pos_end = self.node_to_call.pos_end 33 | 34 | def __repr__(self): 35 | return f"( function call {self.node_to_call}->args({self.arg_nodes}) ) " 36 | 37 | 38 | class ReturnNode: 39 | def __init__(self, node_to_return, pos_start, pos_end): 40 | self.node_to_return = node_to_return 41 | 42 | self.pos_start = pos_start 43 | self.pos_end = pos_end 44 | 45 | def __repr__(self) -> str: 46 | return f"( return ->({self.node_to_return}) ) " 47 | -------------------------------------------------------------------------------- /nodes/loop.py: -------------------------------------------------------------------------------- 1 | class ForNode: 2 | def __init__( 3 | self, 4 | var_name_token, 5 | start_value_node, 6 | end_value_node, 7 | step_value_node, 8 | body_node, 9 | should_return_null, 10 | ): 11 | self.var_name_token = var_name_token 12 | self.start_value_node = start_value_node 13 | self.end_value_node = end_value_node 14 | self.step_value_node = step_value_node 15 | self.body_node = body_node 16 | 17 | self.pos_start = self.var_name_token.pos_start 18 | self.pos_end = self.body_node.pos_end 19 | self.should_return_null = should_return_null 20 | 21 | def __repr__(self): 22 | return f"(For Loop[{self.start_value_node},{self.end_value_node},{self.step_value_node}] :{self.body_node})" 23 | 24 | 25 | class WhileNode: 26 | def __init__(self, condition_node, body_node, should_return_null): 27 | self.condition_node = condition_node 28 | self.body_node = body_node 29 | 30 | self.pos_start = self.condition_node.pos_start 31 | self.pos_end = self.body_node.pos_end 32 | self.should_return_null = should_return_null 33 | 34 | def __repr__(self): 35 | return f"(WHILE {self.body_node})" 36 | 37 | 38 | class ContinueNode: 39 | def __init__(self, pos_start, pos_end): 40 | self.pos_start = pos_start 41 | self.pos_end = pos_end 42 | def __repr__(self) -> str: 43 | return f"(continue)" 44 | 45 | 46 | class BreakNode: 47 | def __init__(self, pos_start, pos_end): 48 | self.pos_start = pos_start 49 | self.pos_end = pos_end 50 | def __repr__(self) -> str: 51 | return f"(break)" 52 | -------------------------------------------------------------------------------- /nodes/operation.py: -------------------------------------------------------------------------------- 1 | 2 | class BinOpNode: 3 | def __init__(self, left_node, op_token, right_node): 4 | self.left_node = left_node 5 | self.op_token = op_token 6 | self.right_node = right_node 7 | 8 | self.pos_start = self.left_node.pos_start 9 | self.pos_end = self.right_node.pos_end 10 | 11 | def __repr__(self): 12 | return f'( {self.left_node} {self.op_token} {self.right_node} )' 13 | 14 | class UnaryOpNode: 15 | def __init__(self, op_token, node): 16 | self.op_token = op_token 17 | self.node = node 18 | 19 | self.pos_start = self.op_token.pos_start 20 | self.pos_end = node.pos_end 21 | 22 | def __repr__(self): 23 | return f'({self.op_token}, {self.node})' -------------------------------------------------------------------------------- /nodes/value.py: -------------------------------------------------------------------------------- 1 | class NumberNode: 2 | def __init__(self, token): 3 | self.token = token 4 | self.pos_start = self.token.pos_start 5 | self.pos_end = self.token.pos_end 6 | 7 | def __repr__(self): 8 | return f"{self.token}" 9 | 10 | class StringNode: 11 | def __init__(self, token): 12 | self.token = token 13 | self.pos_start = self.token.pos_start 14 | self.pos_end = self.token.pos_end 15 | 16 | def __repr__(self): 17 | return f"{self.token}" 18 | 19 | 20 | class ListNode: 21 | def __init__(self, element_nodes,pos_start,pos_end): 22 | self.element_nodes = element_nodes 23 | self.pos_start = pos_start 24 | self.pos_end = pos_end 25 | 26 | def __repr__(self): 27 | return f"{self.element_nodes}" 28 | 29 | 30 | class IndexNode: 31 | def __init__(self, index_node, expr): 32 | self.index_node = index_node 33 | self.expr = expr 34 | 35 | self.pos_start = self.index_node.pos_start 36 | 37 | self.pos_end = self.index_node.pos_end 38 | 39 | def __repr__(self): 40 | return f"( Index {self.index_node}->expr({self.expr}) ) " 41 | 42 | 43 | class IndexAssignNode: 44 | def __init__(self, index_node, expr,assgin_expr): 45 | self.index_node = index_node 46 | self.expr = expr 47 | 48 | self.pos_start = self.index_node.pos_start 49 | 50 | self.pos_end = self.index_node.pos_end 51 | self.assgin_expr = assgin_expr 52 | 53 | def __repr__(self): 54 | return f"( Index assign {self.index_node}->expr({self.expr}) := expr({self.assgin_expr}) ) " -------------------------------------------------------------------------------- /nodes/variable.py: -------------------------------------------------------------------------------- 1 | class VarAccessNode: 2 | def __init__(self, var_name_token): 3 | self.var_name_token = var_name_token 4 | self.pos_start = self.var_name_token.pos_start 5 | self.pos_end = self.var_name_token.pos_end 6 | 7 | 8 | def __repr__(self): 9 | return f"(variable : ({self.var_name_token}))" 10 | 11 | class VarAssignNode: 12 | def __init__(self, var_name_token,value_node,declare=True): 13 | self.var_name_token = var_name_token 14 | self.value_node = value_node 15 | self.declare = declare 16 | 17 | self.pos_start = self.var_name_token.pos_start 18 | self.pos_end = self.var_name_token.pos_end 19 | 20 | def __repr__(self): 21 | return f"(var assign = ({self.var_name_token}))" -------------------------------------------------------------------------------- /results/__init__.py: -------------------------------------------------------------------------------- 1 | from Results.parse_result import ParseResult 2 | from Results.runtime_result import RTResult 3 | -------------------------------------------------------------------------------- /results/parse_result.py: -------------------------------------------------------------------------------- 1 | # ---------PARSE_RESULT------------ 2 | class ParseResult: 3 | def __init__(self): 4 | self.error = None 5 | self.node = None 6 | self.advance_count = 0 7 | self.to_reverse_count = 0 8 | 9 | def register_advancement(self): 10 | self.advance_count += 1 11 | 12 | def register(self, res): 13 | self.advance_count += res.advance_count 14 | if res.error: 15 | self.error = res.error 16 | return res.node 17 | 18 | def try_register(self, res): 19 | if res.error: 20 | self.to_reverse_count = res.advance_count 21 | return None 22 | return self.register(res) 23 | 24 | def success(self, node): 25 | self.node = node 26 | return self 27 | 28 | def failure(self, error): 29 | if not self.error or self.advance_count == 0: 30 | self.error = error 31 | return self 32 | -------------------------------------------------------------------------------- /results/runtime_result.py: -------------------------------------------------------------------------------- 1 | # ------------Runtime Result--------------- 2 | class RTResult: 3 | def __init__(self): 4 | self.reset() 5 | 6 | def reset(self): 7 | self.value = None 8 | self.error = None 9 | self.func_return_value = None 10 | self.loop_should_continue = False 11 | self.loop_should_break = False 12 | 13 | def register(self, res): 14 | self.error = res.error 15 | self.func_return_value = res.func_return_value 16 | self.loop_should_continue = res.loop_should_continue 17 | self.loop_should_break = res.loop_should_break 18 | return res.value 19 | 20 | def success(self, value): 21 | self.reset() 22 | self.value = value 23 | return self 24 | 25 | def success_return(self, value): 26 | self.reset() 27 | self.func_return_value = value 28 | return self 29 | 30 | def success_continue(self): 31 | self.reset() 32 | self.loop_should_continue = True 33 | return self 34 | 35 | def success_break(self): 36 | self.reset() 37 | self.loop_should_break = True 38 | return self 39 | 40 | def failure(self, error): 41 | self.reset() 42 | self.error = error 43 | return self 44 | 45 | def should_return(self): 46 | return ( 47 | self.error 48 | or self.func_return_value 49 | or self.loop_should_continue 50 | or self.loop_should_break 51 | ) 52 | -------------------------------------------------------------------------------- /shell.py: -------------------------------------------------------------------------------- 1 | import main 2 | import sys 3 | 4 | Debug=False 5 | 6 | try: 7 | if len(sys.argv)>1: 8 | main.run_from_file(sys.argv[1]) 9 | else: 10 | while True: 11 | text = input("बाजी >") 12 | text = text.strip() 13 | if len(text)==0: 14 | continue 15 | 16 | result, error = main.run("<मुख्य>", text, debug=Debug) 17 | if error: 18 | print(error.as_string()) 19 | elif result: 20 | if len(result)==1: 21 | print(result[0]) 22 | else: 23 | print(result) 24 | except KeyboardInterrupt as e: 25 | print("\n--------------------") 26 | print("कीबोर्डद्वारे प्रोग्राम थांबविला") 27 | print("^^^^^^^^^^^^^^^^^^^^") 28 | except BaseException as e: 29 | print("\n--------------------") 30 | print("प्रोग्राम चालू असताना त्रुटी आली") 31 | print("^^^^^^^^^^^^^^^^^^^^") 32 | -------------------------------------------------------------------------------- /temp.baji: -------------------------------------------------------------------------------- 1 | FUN get_2d_array(length) 2 | VAR arr =[] 3 | FOR i = 0 TO length THEN 4 | EXTEND(arr,[RAND_INT(0,0)]) 5 | END 6 | RETURN arr 7 | END 8 | 9 | VAR arr = get_2d_array(100) 10 | 11 | 12 | FUN fib(n) 13 | IF n<2 THEN 14 | RETURN 1 15 | ELIF arr[n]!=0 THEN 16 | RETURN arr[n] 17 | ELSE 18 | arr[n]=fib(n-1) + fib(n-2) 19 | RETURN arr[n] 20 | END 21 | END 22 | 23 | FOR i=0 TO 10 THEN 24 | PRINT(fib(i)) 25 | PRINT("\n") 26 | END -------------------------------------------------------------------------------- /translate/__init__.py: -------------------------------------------------------------------------------- 1 | class Translate: 2 | def __init__(self): 3 | self.DIGITS_M_TO_E = { 4 | "०": "0", 5 | "१": "1", 6 | "२": "2", 7 | "३": "3", 8 | "४": "4", 9 | "५": "5", 10 | "६": "6", 11 | "७": "7", 12 | "८": "8", 13 | "९": "9", 14 | } 15 | 16 | self.DIGITS_E_TO_M = { 17 | "0": "०", 18 | "1": "१", 19 | "2": "२", 20 | "3": "३", 21 | "4": "४", 22 | "5": "५", 23 | "6": "६", 24 | "7": "७", 25 | "8": "८", 26 | "9": "९", 27 | } 28 | 29 | def digit_to_eng(self, num_char): 30 | if num_char in self.DIGITS_M_TO_E: 31 | return self.DIGITS_M_TO_E[num_char] 32 | return num_char 33 | 34 | def digit_to_mar(self, num_char): 35 | if num_char in self.DIGITS_E_TO_M: 36 | return self.DIGITS_E_TO_M[num_char] 37 | return num_char 38 | 39 | def number_to_mar(self, num): 40 | num = str(num) 41 | result = "" 42 | for char in num: 43 | if char == ".": 44 | result += "." 45 | else: 46 | result += self.digit_to_mar(char) 47 | return result 48 | -------------------------------------------------------------------------------- /values/__init__.py: -------------------------------------------------------------------------------- 1 | from Values.number import * 2 | from Values.function import * 3 | from Values.string import * 4 | from Values.list import * -------------------------------------------------------------------------------- /values/function.py: -------------------------------------------------------------------------------- 1 | from Nodes import value 2 | from Values.value import Value 3 | from Values.string import String 4 | from Values.number import Number 5 | from Values.list import List 6 | from Errors import RTError 7 | import Interpreter as IPTR 8 | from Context.context import Context 9 | import SymbolTable as S_Table 10 | from Results.runtime_result import RTResult 11 | from Values import * 12 | import os 13 | import time 14 | import random 15 | 16 | 17 | class BaseFunction(Value): 18 | def __init__(self, name): 19 | super().__init__() 20 | self.name = name or "" 21 | 22 | def generate_new_context(self): 23 | new_context = Context(self.name, self.context, self.pos_start) 24 | new_context.symbol_table = S_Table.symbol_table.SymbolTable( 25 | new_context.parent.symbol_table 26 | ) 27 | return new_context 28 | 29 | def check_args(self, arg_names, args): 30 | res = RTResult() 31 | 32 | if len(args) > len(arg_names): 33 | return res.failure( 34 | RTError( 35 | self.pos_start, 36 | self.pos_end, 37 | f"{len(args) - len(arg_names)} too many args passed into {self}", 38 | self.context, 39 | ) 40 | ) 41 | 42 | if len(args) < len(arg_names): 43 | return res.failure( 44 | RTError( 45 | self.pos_start, 46 | self.pos_end, 47 | f"{len(arg_names) - len(args)} too few args passed into {self}", 48 | self.context, 49 | ) 50 | ) 51 | 52 | return res.success(None) 53 | 54 | def populate_args(self, arg_names, args, exec_ctx): 55 | for i in range(len(args)): 56 | arg_name = arg_names[i] 57 | arg_value = args[i] 58 | arg_value.set_context(exec_ctx) 59 | exec_ctx.symbol_table.set(arg_name, arg_value) 60 | 61 | def check_and_populate_args(self, arg_names, args, exec_ctx): 62 | res = RTResult() 63 | res.register(self.check_args(arg_names, args)) 64 | if res.should_return(): 65 | return res 66 | self.populate_args(arg_names, args, exec_ctx) 67 | return res.success(None) 68 | 69 | 70 | class Function(BaseFunction): 71 | def __init__(self, name, body_node, arg_names, should_auto_return): 72 | super().__init__(name) 73 | self.body_node = body_node 74 | self.arg_names = arg_names 75 | self.should_auto_return = should_auto_return 76 | 77 | def execute(self, args): 78 | res = RTResult() 79 | interpreter = IPTR.Interpreter() 80 | exec_ctx = self.generate_new_context() 81 | 82 | res.register(self.check_and_populate_args(self.arg_names, args, exec_ctx)) 83 | if res.should_return(): 84 | return res 85 | 86 | value = res.register(interpreter.visit(self.body_node, exec_ctx)) 87 | if res.should_return() and res.func_return_value == None: 88 | return res 89 | 90 | ret_value = (value if self.should_auto_return else None) or res.func_return_value or Number.null 91 | return res.success(ret_value) 92 | 93 | def copy(self): 94 | copy = Function( 95 | self.name, self.body_node, self.arg_names, self.should_auto_return 96 | ) 97 | copy.set_context(self.context) 98 | copy.set_pos(self.pos_start, self.pos_end) 99 | return copy 100 | 101 | def __repr__(self): 102 | return f"" 103 | 104 | 105 | class BuiltInFunction(BaseFunction): 106 | def __init__(self, name): 107 | super().__init__(name) 108 | 109 | def execute(self, args): 110 | res = RTResult() 111 | exec_ctx = self.generate_new_context() 112 | 113 | method_name = f"execute_{self.name}" 114 | method = getattr(self, method_name, self.no_visit_method) 115 | 116 | res.register(self.check_and_populate_args(method.arg_names, args, exec_ctx)) 117 | if res.should_return(): 118 | return res 119 | 120 | return_value = res.register(method(exec_ctx)) 121 | if res.should_return(): 122 | return res 123 | return res.success(return_value) 124 | 125 | def no_visit_method(self, node, context): 126 | raise Exception(f"No execute_{self.name} method defined") 127 | 128 | def copy(self): 129 | copy = BuiltInFunction(self.name) 130 | copy.set_context(self.context) 131 | copy.set_pos(self.pos_start, self.pos_end) 132 | return copy 133 | 134 | def __repr__(self): 135 | return f"" 136 | 137 | ##################################### 138 | 139 | def execute_print(self, exec_ctx): 140 | print(str(exec_ctx.symbol_table.get("value")),end="") 141 | return RTResult().success(Number.null) 142 | 143 | execute_print.arg_names = ["value"] 144 | 145 | 146 | def execute_print_ret(self, exec_ctx): 147 | return RTResult().success(String(str(exec_ctx.symbol_table.get("value")))) 148 | 149 | execute_print_ret.arg_names = ["value"] 150 | 151 | def execute_input(self, exec_ctx): 152 | text = input() 153 | return RTResult().success(String(text)) 154 | 155 | execute_input.arg_names = [] 156 | 157 | def execute_input_int(self, exec_ctx): 158 | while True: 159 | text = input() 160 | try: 161 | number = int(text) 162 | break 163 | except ValueError: 164 | print(f"'{text}' must be an integer. Try again!") 165 | return RTResult().success(Number(number)) 166 | 167 | execute_input_int.arg_names = [] 168 | 169 | def execute_clear(self, exec_ctx): 170 | os.system("cls" if os.name == "nt" else "clear") 171 | return RTResult().success(Number.null) 172 | 173 | execute_clear.arg_names = [] 174 | 175 | def execute_is_number(self, exec_ctx): 176 | is_number = isinstance(exec_ctx.symbol_table.get("value"), Number) 177 | return RTResult().success(Number.true if is_number else Number.false) 178 | 179 | execute_is_number.arg_names = ["value"] 180 | 181 | def execute_is_string(self, exec_ctx): 182 | is_number = isinstance(exec_ctx.symbol_table.get("value"), String) 183 | return RTResult().success(Number.true if is_number else Number.false) 184 | 185 | execute_is_string.arg_names = ["value"] 186 | 187 | def execute_is_list(self, exec_ctx): 188 | is_number = isinstance(exec_ctx.symbol_table.get("value"), List) 189 | return RTResult().success(Number.true if is_number else Number.false) 190 | 191 | execute_is_list.arg_names = ["value"] 192 | 193 | def execute_is_function(self, exec_ctx): 194 | is_number = isinstance(exec_ctx.symbol_table.get("value"), BaseFunction) 195 | return RTResult().success(Number.true if is_number else Number.false) 196 | 197 | execute_is_function.arg_names = ["value"] 198 | 199 | def execute_append(self, exec_ctx): 200 | list_ = exec_ctx.symbol_table.get("list") 201 | value = exec_ctx.symbol_table.get("value") 202 | 203 | if not isinstance(list_, List): 204 | return RTResult().failure( 205 | RTError( 206 | self.pos_start, 207 | self.pos_end, 208 | "First argument must be list", 209 | exec_ctx, 210 | ) 211 | ) 212 | 213 | list_.elements.append(value) 214 | return RTResult().success(Number.null) 215 | 216 | execute_append.arg_names = ["list", "value"] 217 | 218 | def execute_pop(self, exec_ctx): 219 | list_ = exec_ctx.symbol_table.get("list") 220 | index = exec_ctx.symbol_table.get("index") 221 | 222 | if not isinstance(list_, List): 223 | return RTResult().failure( 224 | RTError( 225 | self.pos_start, 226 | self.pos_end, 227 | "First argument must be list", 228 | exec_ctx, 229 | ) 230 | ) 231 | 232 | if not isinstance(index, Number): 233 | return RTResult().failure( 234 | RTError( 235 | self.pos_start, 236 | self.pos_end, 237 | "Second argument must be number", 238 | exec_ctx, 239 | ) 240 | ) 241 | 242 | try: 243 | element = list_.elements.pop(index.value) 244 | except: 245 | return RTResult().failure( 246 | RTError( 247 | self.pos_start, 248 | self.pos_end, 249 | "Element at this index could not be removed from list because index is out of bounds", 250 | exec_ctx, 251 | ) 252 | ) 253 | return RTResult().success(element) 254 | 255 | execute_pop.arg_names = ["list", "index"] 256 | 257 | def execute_extend(self, exec_ctx): 258 | listA = exec_ctx.symbol_table.get("listA") 259 | listB = exec_ctx.symbol_table.get("listB") 260 | 261 | if not isinstance(listA, List): 262 | return RTResult().failure( 263 | RTError( 264 | self.pos_start, 265 | self.pos_end, 266 | "First argument must be list", 267 | exec_ctx, 268 | ) 269 | ) 270 | 271 | if not isinstance(listB, List): 272 | return RTResult().failure( 273 | RTError( 274 | self.pos_start, 275 | self.pos_end, 276 | "Second argument must be list", 277 | exec_ctx, 278 | ) 279 | ) 280 | 281 | listA.elements.extend(listB.elements) 282 | return RTResult().success(Number.null) 283 | 284 | execute_extend.arg_names = ["listA", "listB"] 285 | 286 | 287 | def execute_len(self, exec_ctx): 288 | list_ = exec_ctx.symbol_table.get("list") 289 | 290 | if not isinstance(list_, List): 291 | return RTResult().failure( 292 | RTError( 293 | self.pos_start, 294 | self.pos_end, 295 | "Argument must be list", 296 | exec_ctx, 297 | ) 298 | ) 299 | 300 | return RTResult().success(Number(len(list_.elements))) 301 | 302 | execute_len.arg_names = ["list"] 303 | 304 | def execute_sleep(self, exec_ctx): 305 | value_ = exec_ctx.symbol_table.get("time") 306 | 307 | if not isinstance(value_, Number): 308 | return RTResult().failure( 309 | RTError( 310 | self.pos_start, 311 | self.pos_end, 312 | "Argument must be Number", 313 | exec_ctx, 314 | ) 315 | ) 316 | 317 | time.sleep(value_.value) 318 | return RTResult().success(Number.null) 319 | 320 | execute_sleep.arg_names = ["time"] 321 | 322 | def execute_rand(self, exec_ctx): 323 | MIN = exec_ctx.symbol_table.get("MIN") 324 | MAX = exec_ctx.symbol_table.get("MAX") 325 | RAND = random.randint(MIN.value,MAX.value) 326 | 327 | return RTResult().success(Number(RAND)) 328 | 329 | execute_rand.arg_names = ["MIN", "MAX"] 330 | 331 | 332 | BuiltInFunction.print = BuiltInFunction("print") 333 | BuiltInFunction.print_ret = BuiltInFunction("print_ret") 334 | BuiltInFunction.input = BuiltInFunction("input") 335 | BuiltInFunction.input_int = BuiltInFunction("input_int") 336 | BuiltInFunction.clear = BuiltInFunction("clear") 337 | BuiltInFunction.is_number = BuiltInFunction("is_number") 338 | BuiltInFunction.is_string = BuiltInFunction("is_string") 339 | BuiltInFunction.is_list = BuiltInFunction("is_list") 340 | BuiltInFunction.is_function = BuiltInFunction("is_function") 341 | BuiltInFunction.append = BuiltInFunction("append") 342 | BuiltInFunction.pop = BuiltInFunction("pop") 343 | BuiltInFunction.extend = BuiltInFunction("extend") 344 | BuiltInFunction.len = BuiltInFunction("len") 345 | BuiltInFunction.sleep = BuiltInFunction("sleep") 346 | BuiltInFunction.rand = BuiltInFunction("rand") 347 | 348 | 349 | S_Table.global_symbol_table.set("PRINT", BuiltInFunction.print) 350 | S_Table.global_symbol_table.set("दाखवा", BuiltInFunction.print) 351 | 352 | S_Table.global_symbol_table.set("PRINT_RET", BuiltInFunction.print_ret) 353 | S_Table.global_symbol_table.set("दाखवा_आणि_परत", BuiltInFunction.print_ret) 354 | 355 | S_Table.global_symbol_table.set("INPUT", BuiltInFunction.input) 356 | S_Table.global_symbol_table.set("इनपुट", BuiltInFunction.input) 357 | 358 | S_Table.global_symbol_table.set("INPUT_INT", BuiltInFunction.input_int) 359 | S_Table.global_symbol_table.set("इनपुट_संख्या", BuiltInFunction.input_int) 360 | 361 | S_Table.global_symbol_table.set("CLEAR", BuiltInFunction.clear) 362 | S_Table.global_symbol_table.set("पुसा", BuiltInFunction.clear) 363 | 364 | S_Table.global_symbol_table.set("IS_NUM", BuiltInFunction.is_number) 365 | S_Table.global_symbol_table.set("संख्या_आहे", BuiltInFunction.is_number) 366 | 367 | S_Table.global_symbol_table.set("IS_STR", BuiltInFunction.is_string) 368 | S_Table.global_symbol_table.set("शब्दांचीदोरी_आहे", BuiltInFunction.is_string) 369 | 370 | S_Table.global_symbol_table.set("IS_LIST", BuiltInFunction.is_list) 371 | S_Table.global_symbol_table.set("यादी_आहे", BuiltInFunction.is_list) 372 | 373 | S_Table.global_symbol_table.set("IS_FUN", BuiltInFunction.is_function) 374 | S_Table.global_symbol_table.set("कार्य_आहे", BuiltInFunction.is_function) 375 | 376 | S_Table.global_symbol_table.set("APPEND", BuiltInFunction.append) 377 | S_Table.global_symbol_table.set("जोडा", BuiltInFunction.append) 378 | 379 | S_Table.global_symbol_table.set("POP", BuiltInFunction.pop) 380 | S_Table.global_symbol_table.set("काढा", BuiltInFunction.pop) 381 | 382 | S_Table.global_symbol_table.set("EXTEND", BuiltInFunction.extend) 383 | S_Table.global_symbol_table.set("वाढवा", BuiltInFunction.extend) 384 | 385 | 386 | S_Table.global_symbol_table.set("LEN", BuiltInFunction.len) 387 | S_Table.global_symbol_table.set("लांबी", BuiltInFunction.len) 388 | 389 | 390 | S_Table.global_symbol_table.set("SLEEP", BuiltInFunction.sleep) 391 | S_Table.global_symbol_table.set("झोप", BuiltInFunction.sleep) 392 | 393 | 394 | S_Table.global_symbol_table.set("RAND_INT", BuiltInFunction.rand) 395 | 396 | -------------------------------------------------------------------------------- /values/list.py: -------------------------------------------------------------------------------- 1 | from typing import NewType 2 | from Values.value import Value 3 | from Errors import RTError, errors 4 | from Translate import Translate 5 | from Values.number import Number 6 | 7 | class List(Value): 8 | def __init__(self, elements): 9 | super().__init__() 10 | self.elements = elements 11 | 12 | def added_to(self, other): 13 | new_list = self.copy() 14 | new_list.elements.append(other) 15 | return new_list, None 16 | 17 | def subbed_by(self, other): 18 | if isinstance(other, Number): 19 | new_list = self.copy() 20 | try: 21 | new_list.elements.pop(other.value) 22 | return new_list, None 23 | except: 24 | return None, RTError( 25 | other.pos_start, other.pos_end, 26 | 'Element at this index could not be removed from list because index is out of bounds', 27 | self.context 28 | ) 29 | else: 30 | return None, Value.illegal_operation(self, other) 31 | 32 | def multed_by(self, other): 33 | if isinstance(other, List): 34 | new_list = self.copy() 35 | new_list.elements.extend(other.elements) 36 | return new_list, None 37 | else: 38 | return None, Value.illegal_operation(self, other) 39 | 40 | def dived_by(self, other): 41 | if isinstance(other, Number): 42 | try: 43 | return self.elements[other.value], None 44 | except: 45 | return None, RTError( 46 | other.pos_start, other.pos_end, 47 | 'Element at this index could not be retrieved from list because index is out of bounds', 48 | self.context 49 | ) 50 | else: 51 | return None, Value.illegal_operation(self, other) 52 | def copy(self): 53 | copy = List(self.elements) 54 | copy.set_pos(self.pos_start, self.pos_end) 55 | copy.set_context(self.context) 56 | return copy 57 | 58 | 59 | def __len__(self): 60 | return len(self.elements) 61 | 62 | def __getitem__(self,index): 63 | return self.elements[index] 64 | 65 | def __repr__(self): 66 | return f'[{", ".join([str(x) for x in self.elements])}]' 67 | 68 | 69 | -------------------------------------------------------------------------------- /values/number.py: -------------------------------------------------------------------------------- 1 | from Values.value import Value 2 | from Errors import RTError 3 | from Translate import Translate 4 | #------------Values----------------- 5 | class Number(Value): 6 | def __init__(self, value): 7 | super().__init__() 8 | self.value = value 9 | self.translate = Translate() 10 | 11 | def set_pos(self, pos_start=None, pos_end=None): 12 | self.pos_start = pos_start 13 | self.pos_end = pos_end 14 | return self 15 | 16 | def set_context(self, context=None): 17 | self.context = context 18 | return self 19 | 20 | def added_to(self, other): 21 | if isinstance(other, Number): 22 | return Number(self.value + other.value).set_context(self.context), None 23 | else: 24 | return None, Value.illegal_operation(self, other) 25 | 26 | def subbed_by(self, other): 27 | if isinstance(other, Number): 28 | return Number(self.value - other.value).set_context(self.context), None 29 | else: 30 | return None, Value.illegal_operation(self, other) 31 | 32 | def multed_by(self, other): 33 | if isinstance(other, Number): 34 | return Number(self.value * other.value).set_context(self.context), None 35 | else: 36 | return None, Value.illegal_operation(self, other) 37 | 38 | def dived_by(self, other): 39 | if isinstance(other, Number): 40 | if other.value == 0: 41 | return None, RTError( 42 | other.pos_start, other.pos_end, 43 | 'Division by zero', 44 | self.context 45 | ) 46 | div = self.value / other.value 47 | #👇convert float->int if if int==float 48 | div = int(div) if int(div)==div else div 49 | return Number(div).set_context(self.context), None 50 | else: 51 | return None, Value.illegal_operation(self, other) 52 | def moded_by(self, other): 53 | if isinstance(other, Number): 54 | if other.value == 0: 55 | return None, RTError( 56 | other.pos_start, other.pos_end, 57 | 'Mod by zero', 58 | self.context 59 | ) 60 | div = self.value % other.value 61 | #👇convert float->int if if int==float 62 | div = int(div) if int(div)==div else div 63 | return Number(div).set_context(self.context), None 64 | else: 65 | return None, Value.illegal_operation(self, other) 66 | 67 | def power_by(self,other): 68 | if isinstance(other,Number): 69 | return Number(self.value ** other.value).set_context(self.context), None 70 | else: 71 | return None, Value.illegal_operation(self, other) 72 | 73 | def get_comparison_eq(self, other): 74 | if isinstance(other, Number): 75 | return Number(int(self.value == other.value)).set_context(self.context), None 76 | else: 77 | return None, Value.illegal_operation(self, other) 78 | 79 | def get_comparison_ne(self, other): 80 | if isinstance(other, Number): 81 | return Number(int(self.value != other.value)).set_context(self.context), None 82 | else: 83 | return None, Value.illegal_operation(self, other) 84 | 85 | def get_comparison_lt(self, other): 86 | if isinstance(other, Number): 87 | return Number(int(self.value < other.value)).set_context(self.context), None 88 | else: 89 | return None, Value.illegal_operation(self, other) 90 | 91 | def get_comparison_gt(self, other): 92 | if isinstance(other, Number): 93 | return Number(int(self.value > other.value)).set_context(self.context), None 94 | else: 95 | return None, Value.illegal_operation(self, other) 96 | 97 | def get_comparison_lte(self, other): 98 | if isinstance(other, Number): 99 | return Number(int(self.value <= other.value)).set_context(self.context), None 100 | else: 101 | return None, Value.illegal_operation(self, other) 102 | 103 | def get_comparison_gte(self, other): 104 | if isinstance(other, Number): 105 | return Number(int(self.value >= other.value)).set_context(self.context), None 106 | else: 107 | return None, Value.illegal_operation(self, other) 108 | 109 | def anded_by(self, other): 110 | if isinstance(other, Number): 111 | return Number(int(self.value and other.value)).set_context(self.context), None 112 | else: 113 | return None, Value.illegal_operation(self, other) 114 | 115 | def ored_by(self, other): 116 | if isinstance(other, Number): 117 | return Number(int(self.value or other.value)).set_context(self.context), None 118 | else: 119 | return None, Value.illegal_operation(self, other) 120 | 121 | def notted(self): 122 | return Number(1 if self.value == 0 else 0).set_context(self.context), None 123 | 124 | def copy(self): 125 | copy = Number(self.value) 126 | copy.set_pos(self.pos_start, self.pos_end) 127 | copy.set_context(self.context) 128 | return copy 129 | def is_true(self): 130 | return self.value != 0 131 | 132 | def __repr__(self): 133 | return str(self.translate.number_to_mar(self.value)) 134 | 135 | Number.null = Number(0) 136 | Number.false = Number(0) 137 | Number.true = Number(1) -------------------------------------------------------------------------------- /values/string.py: -------------------------------------------------------------------------------- 1 | from Values.value import Value 2 | from Errors import RTError 3 | from Translate import Translate 4 | from Values.number import Number 5 | 6 | 7 | class String(Value): 8 | def __init__(self, value): 9 | super().__init__() 10 | self.value = value 11 | 12 | def added_to(self, other): 13 | if isinstance(other, String): 14 | return String(self.value + other.value).set_context(self.context), None 15 | else: 16 | return None, Value.illegal_operation(self, other) 17 | 18 | def multed_by(self, other): 19 | if isinstance(other, Number): 20 | return String(self.value * other.value).set_context(self.context), None 21 | else: 22 | return None, Value.illegal_operation(self, other) 23 | 24 | def is_true(self): 25 | return len(self.value) > 0 26 | 27 | def copy(self): 28 | copy = String(self.value) 29 | copy.set_pos(self.pos_start, self.pos_end) 30 | copy.set_context(self.context) 31 | return copy 32 | 33 | def __str__(self): 34 | return self.value 35 | 36 | def __repr__(self): 37 | return f'"{self.value}"' 38 | -------------------------------------------------------------------------------- /values/value.py: -------------------------------------------------------------------------------- 1 | from Errors import RTError 2 | class Value: 3 | def __init__(self): 4 | self.set_pos() 5 | self.set_context() 6 | 7 | def set_pos(self, pos_start=None, pos_end=None): 8 | self.pos_start = pos_start 9 | self.pos_end = pos_end 10 | return self 11 | 12 | def set_context(self, context=None): 13 | self.context = context 14 | return self 15 | 16 | def added_to(self, other): 17 | return None, self.illegal_operation(other) 18 | 19 | def subbed_by(self, other): 20 | return None, self.illegal_operation(other) 21 | 22 | def multed_by(self, other): 23 | return None, self.illegal_operation(other) 24 | 25 | def dived_by(self, other): 26 | return None, self.illegal_operation(other) 27 | 28 | def powed_by(self, other): 29 | return None, self.illegal_operation(other) 30 | 31 | def get_comparison_eq(self, other): 32 | return None, self.illegal_operation(other) 33 | 34 | def get_comparison_ne(self, other): 35 | return None, self.illegal_operation(other) 36 | 37 | def get_comparison_lt(self, other): 38 | return None, self.illegal_operation(other) 39 | 40 | def get_comparison_gt(self, other): 41 | return None, self.illegal_operation(other) 42 | 43 | def get_comparison_lte(self, other): 44 | return None, self.illegal_operation(other) 45 | 46 | def get_comparison_gte(self, other): 47 | return None, self.illegal_operation(other) 48 | 49 | def anded_by(self, other): 50 | return None, self.illegal_operation(other) 51 | 52 | def ored_by(self, other): 53 | return None, self.illegal_operation(other) 54 | 55 | def notted(self): 56 | return None, self.illegal_operation(other) 57 | 58 | def execute(self, args): 59 | return RTResult().failure(self.illegal_operation()) 60 | 61 | def copy(self): 62 | raise Exception('No copy method defined') 63 | 64 | def is_true(self): 65 | return False 66 | 67 | def illegal_operation(self, other=None): 68 | if not other: other = self 69 | return RTError( 70 | self.pos_start, other.pos_end, 71 | 'Illegal operation', 72 | self.context 73 | ) --------------------------------------------------------------------------------