From 60d9aabf8d79ca94a60c2e322ddde0021948f23e Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 31 Jan 2026 14:54:28 +0000 Subject: [PATCH] 15:54 --- core/__pycache__/obfuscator.cpython-311.pyc | Bin 22734 -> 29488 bytes core/__pycache__/parser.cpython-311.pyc | Bin 7073 -> 9693 bytes core/obfuscator.py | 345 +++++++++----------- core/parser.py | 130 ++++---- 4 files changed, 206 insertions(+), 269 deletions(-) diff --git a/core/__pycache__/obfuscator.cpython-311.pyc b/core/__pycache__/obfuscator.cpython-311.pyc index 64053a7b1b399c6f18b9399bb183401010383ca7..b54a4f09541d3cfeb16da2f1bae8a07a3bb45462 100644 GIT binary patch literal 29488 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 N$rk8Z(;QqH{};4 diff --git a/core/__pycache__/parser.cpython-311.pyc b/core/__pycache__/parser.cpython-311.pyc index 9b9da3ca1a76f404daa3dbab4da8bca0c76f3025..c444df74937e7529f695d45d91cfda77b4524e92 100644 GIT binary patch delta 4488 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 whAcg 2 or (depth > 0 and random.random() < 0.2): - return str(n) - - r = random.randint(1, 100000) - choice = random.choice(['add', 'sub', 'xor']) - - if choice == 'add': - return f"({self.to_expr(n - r, bit32_var, depth + 1)} + {self.to_expr(r, bit32_var, depth + 1)})" - elif choice == 'sub': - return f"({self.to_expr(n + r, bit32_var, depth + 1)} - {self.to_expr(r, bit32_var, depth + 1)})" - elif choice == 'xor': - return f"{bit32_var}.bxor({self.to_expr(n ^ r, bit32_var, depth + 1)}, {self.to_expr(r, bit32_var, depth + 1)})" - - return str(n) + def to_expr(self, n): + r = random.randint(1, 1000) + ch = random.choice(['add', 'sub', 'xor']) + if ch == 'add': return f"({n-r}+{r})" + if ch == 'sub': return f"({n+r}-{r})" + return f"bit32.bxor({n^r},{r})" def encrypt_string(self, s, key): - res = [] - last = key % 256 + res, last = [], key % 256 for i, c in enumerate(s): k = (key + i + last) % 256 last = ord(c) @@ -68,200 +51,168 @@ class LuauVMObfuscator: return code.strip() def generate_vm_source(self, bytecode): - raw_instructions = bytecode['instructions'] - indices = list(range(len(raw_instructions))) - random.shuffle(indices) - - pos_map = {orig: shuffled_idx for shuffled_idx, orig in enumerate(indices)} - - final_insts = [None] * len(raw_instructions) - for i, orig_idx in enumerate(indices): - inst = raw_instructions[orig_idx] - next_shuffled = pos_map[orig_idx + 1] if orig_idx + 1 < len(raw_instructions) else 0 - - packed = [ - inst[0] & 0xFF, (inst[0] >> 8) & 0xFF, - inst[1] & 0xFF, inst[2] & 0xFF, inst[3] & 0xFF, - next_shuffled & 0xFF, (next_shuffled >> 8) & 0xFF - ] - final_insts[i] = packed - + raw_ins = bytecode['instructions'] + indices = list(range(len(raw_ins))) + random.shuffle(indices); pos_map = {orig: i for i, orig in enumerate(indices)} + final_insts = [] + for orig_idx in indices: + inst = raw_ins[orig_idx] + next_sh = pos_map[orig_idx + 1] if orig_idx + 1 < len(raw_ins) else 0 + final_insts.append([inst[0]&0xFF,(inst[0]>>8)&0xFF,inst[1]&0xFF,inst[2]&0xFF,inst[3]&0xFF,next_sh&0xFF,(next_sh>>8)&0xFF]) inst_str = "".join(chr(i) for inst in final_insts for i in inst) inst_b64 = base64.b64encode(inst_str.encode('latin-1')).decode() - encrypted_consts = [] + consts = [] salt = random.randint(100000, 999999) for i, c in enumerate(bytecode['constants']): if c['type'] == 'string': - key = (i * 149 + salt) % 256 - enc_val = self.encrypt_string(c['value'], key) - encrypted_consts.append({"t": 1, "v": base64.b64encode(enc_val.encode('latin-1')).decode()}) - else: - encrypted_consts.append({"t": 2, "v": c['value']}) + k = (i * 149 + salt) % 256; enc = self.encrypt_string(c['value'], k) + consts.append({"t": 1, "v": base64.b64encode(enc.encode('latin-1')).decode()}) + elif c['type'] == 'number': consts.append({"t": 2, "v": c['value']}) + else: consts.append({"t": 3, "v": c['value']}) - consts_json = json.dumps(encrypted_consts) - start_idx = pos_map[0] + v = { + "BIT": "bit32", "ENV": self.get_var("env"), "DEC": self.get_var("dec"), + "INST": self.get_var("inst"), "CONSTS": self.get_var("consts"), "SALT": self.to_expr(salt), + "EXEC": self.get_var("exec"), "REGS": self.get_var("regs"), "CURR": self.get_var("curr"), + "PTR": self.get_var("ptr"), "OP": self.get_var("op"), "A": self.get_var("a"), + "B": self.get_var("b"), "C": self.get_var("c"), "UNP": "unpack or table.unpack", + "SPW": "task and task.spawn or spawn", "JSON": "game:GetService('HttpService')", + "CHARS": self.get_var("chars"), "LOOKUP": self.get_var("lookup"), "GETC": self.get_var("getc") + } - V_ENV = self.get_var("env") - V_BIT = self.get_var("bit") - V_B64 = self.get_var("b64") - V_DEC = self.get_var("dec") - V_INST = self.get_var("inst") - V_CONSTS = self.get_var("consts") - V_SALT = self.get_var("salt") - V_EXEC = self.get_var("exec") - V_REGS = self.get_var("regs") - V_CURR = self.get_var("curr") - V_RUN = self.get_var("run") - V_GETC = self.get_var("getc") - V_PTR = self.get_var("ptr") - V_OP = self.get_var("op") - V_A = self.get_var("a") - V_B = self.get_var("b") - V_C = self.get_var("c") - V_UNP = self.get_var("unp") - V_SPW = self.get_var("spw") - V_RAW = self.get_var("raw") - V_KEY = self.get_var("key") - V_RES = self.get_var("res") - V_LST = self.get_var("lst") - - vm_lua = f"""local {V_BIT}=bit32 -local {V_ENV}=setmetatable({{}},{{__index=getfenv()}}) -local {V_UNP}=unpack or table.unpack -local {V_SPW}=task and task.spawn or spawn -local {V_B64}='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -local {V_DEC}=function(data) - data=data:gsub('[^'..{V_B64}..'=]','') - local res,bits={{}},'' - for i=1,#data do - local c=data:sub(i,i) - if c=='=' then break end - local f={V_B64}:find(c)-1 - for j=5,0,-1 do bits=bits..({V_BIT}.extract(f,j,1)) end - end - for i=1,#bits-7,8 do - local b=0 - for j=1,8 do b=b+(bits:sub(i+j-1,i+j-1)=='1' and 2^(8-j) or 0) end - res[#res+1]=string.char(b) + vm_lua = f"""local {v['ENV']}=setmetatable({{}},{{__index=getfenv()}}) +local {v['CHARS']}='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +local {v['LOOKUP']}={{}} +for i=1,64 do {v['LOOKUP']}[{v['CHARS']}:sub(i,i)]=i-1 end +local function {v['DEC']}(data) + data=data:gsub('[^%a%d%+/]','') + local res={{}} + for i=1,#data,4 do + local a,b,c,d={v['LOOKUP']}[data:sub(i,i)],{v['LOOKUP']}[data:sub(i+1,i+1)],{v['LOOKUP']}[data:sub(i+2,i+2)],{v['LOOKUP']}[data:sub(i+3,i+3)] + local n={v['BIT']}.lshift(a or 0,18)+{v['BIT']}.lshift(b or 0,12)+{v['BIT']}.lshift(c or 0,6)+(d or 0) + res[#res+1]=string.char({v['BIT']}.extract(n,16,8)) + if c then res[#res+1]=string.char({v['BIT']}.extract(n,8,8)) end + if d then res[#res+1]=string.char({v['BIT']}.extract(n,0,8)) end end return table.concat(res) end -local {V_INST}={V_DEC}('{inst_b64}') -local {V_CONSTS}=game:GetService("HttpService"):JSONDecode([=[{consts_json}]=]) -local {V_SALT}={self.to_expr(salt, V_BIT)} -local function {V_EXEC}() - local {V_REGS}={{}} - local {V_CURR}={self.to_expr(start_idx, V_BIT)} - local {V_RUN}=true - local function {V_GETC}(idx) - if not idx then return nil end - local c={V_CONSTS}[idx+1] - if not c then return nil end - if c.t=={self.to_expr(1, V_BIT)} then - local {V_RAW}={V_DEC}(c.v) - local {V_KEY}=(idx*{self.to_expr(149, V_BIT)}+{V_SALT})%256 - local {V_RES}={{}} - local {V_LST}={V_KEY}%256 - for i=1,#{V_RAW} do - local k=({V_KEY}+i+{V_LST}-1)%256 - local b=string.byte({V_RAW},i) - local char={V_BIT}.bxor(b,k) - {V_RES}[i]=string.char(char) - {V_LST}=char +local {v['INST']}={v['DEC']}('{inst_b64}') +local {v['CONSTS']}={v['JSON']}:JSONDecode([=[{json.dumps(consts)}]=]) +local {v['EXEC']}=function() + local {v['REGS']}={{}} + local {v['CURR']}={self.to_expr(pos_map[0])} + local function {v['GETC']}(idx) + local c={v['CONSTS']}[idx+1] + if not c then return end + if c.t==1 then + local r,k={v['DEC']}(c.v),(idx*149+{v['SALT']})%256 + local res,lst={{}},k%256 + for i=1,#r do + local char={v['BIT']}.bxor(string.byte(r,i),(k+i+lst-1)%256) + res[i]=string.char(char) + lst=char end - return table.concat({V_RES}) - end + return table.concat(res) + elseif c.t==3 then return c.v=='true' and true or (c.v=='false' and false or nil) end return c.v end - while {V_RUN} do - local {V_PTR}={V_CURR}*7+1 - local op_l=string.byte({V_INST},{V_PTR}) or 0 - local op_h=string.byte({V_INST},{V_PTR}+1) or 0 - local {V_A}=string.byte({V_INST},{V_PTR}+2) or 0 - local {V_B}=string.byte({V_INST},{V_PTR}+3) or 0 - local {V_C}=string.byte({V_INST},{V_PTR}+4) or 0 - local n_l=string.byte({V_INST},{V_PTR}+5) or 0 - local n_h=string.byte({V_INST},{V_PTR}+6) or 0 - {V_CURR}=n_l+({V_BIT}.lshift(n_h,8)) - local op_raw=op_l+({V_BIT}.lshift(op_h,8)) - local {V_OP}={V_BIT}.bxor(op_raw,{self.to_expr(self.k2, V_BIT)})-{self.to_expr(self.k1, V_BIT)} - if {V_OP}=={self.opcodes.index('MOVE')} then - {V_REGS}[{V_A}]={V_REGS}[{V_B}] - elseif {V_OP}=={self.opcodes.index('LOADK')} then - {V_REGS}[{V_A}]={V_GETC}({V_B}) - elseif {V_OP}=={self.opcodes.index('GETGLOBAL')} then - local n={V_GETC}({V_B}) - if n then {V_REGS}[{V_A}]={V_ENV}[n] end - elseif {V_OP}=={self.opcodes.index('SETGLOBAL')} then - local n={V_GETC}({V_B}) - if n then {V_ENV}[n]={V_REGS}[{V_A}] end - elseif {V_OP}=={self.opcodes.index('CALL')} then - local f={V_REGS}[{V_A}] + while true do + local {v['PTR']}={v['CURR']}*7+1 + local b1,b2,b3,b4,b5,b6,b7=string.byte({v['INST']},{v['PTR']},{v['PTR']}+6) + if not b1 then break end + {v['CURR']}=b6+({v['BIT']}.lshift(b7,8)) + local {v['OP']}={v['BIT']}.bxor(b1+{v['BIT']}.lshift(b2,8),{self.to_expr(self.k2)})-{self.to_expr(self.k1)} + local {v['A']},{v['B']},{v['C']}=b3,b4,b5 + if {v['OP']}=={self.opcodes.index('MOVE')} then {v['REGS']}[{v['A']}]={v['REGS']}[{v['B']}] + elseif {v['OP']}=={self.opcodes.index('LOADK')} then {v['REGS']}[{v['A']}]={v['GETC']}({v['B']}) + elseif {v['OP']}=={self.opcodes.index('GETGLOBAL')} then {v['REGS']}[{v['A']}]={v['ENV']}[{v['GETC']}({v['B']})] + elseif {v['OP']}=={self.opcodes.index('SETGLOBAL')} then {v['ENV']}[{v['GETC']}({v['B']})]={v['REGS']}[{v['A']}] + elseif {v['OP']}=={self.opcodes.index('GETTABLE')} then + local b={v['REGS']}[{v['B']}] + if b then {v['REGS']}[{v['A']}]=b[{v['REGS']}[{v['C']}] or {v['GETC']}({v['C']})] end + elseif {v['OP']}=={self.opcodes.index('SETTABLE')} then + local a={v['REGS']}[{v['A']}] + if a then a[{v['REGS']}[{v['B']}] or {v['GETC']}({v['B']})]={v['REGS']}[{v['C']}] end + elseif {v['OP']}=={self.opcodes.index('ADD')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)+({v['REGS']}[{v['C']}] or 0) + elseif {v['OP']}=={self.opcodes.index('SUB')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)-({v['REGS']}[{v['C']}] or 0) + elseif {v['OP']}=={self.opcodes.index('MUL')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)*({v['REGS']}[{v['C']}] or 0) + elseif {v['OP']}=={self.opcodes.index('DIV')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)/({v['REGS']}[{v['C']}] or 1) + elseif {v['OP']}=={self.opcodes.index('UNM')} then {v['REGS']}[{v['A']}]=-({v['REGS']}[{v['B']}] or 0) + elseif {v['OP']}=={self.opcodes.index('NOT')} then {v['REGS']}[{v['A']}]=not {v['REGS']}[{v['B']}] + elseif {v['OP']}=={self.opcodes.index('LEN')} then {v['REGS']}[{v['A']}]=#{v['REGS']}[{v['B']}] or 0 + elseif {v['OP']}=={self.opcodes.index('CALL')} then + local f={v['REGS']}[{v['A']}] if f then local args={{}} - if {V_B}>1 then for i=1,{V_B}-1 do args[i]={V_REGS}[{V_A}+i] end end - local res={{f({V_UNP}(args))}} - if {V_C}>1 then for i=1,{V_C}-1 do {V_REGS}[{V_A}+i-1]=res[i] end end + if {v['B']}>1 then for i=1,{v['B']}-1 do args[i]={v['REGS']}[{v['A']}+i] end end + local res={{f(({v['UNP']})(args))}} + if {v['C']}>1 then for i=1,{v['C']}-1 do {v['REGS']}[{v['A']}+i-1]=res[i] end end end - elseif {V_OP}=={self.opcodes.index('RETURN')} then - {V_RUN}=false - end + elseif {v['OP']}=={self.opcodes.index('RETURN')} then break end end end -{V_SPW}({V_EXEC})""" +{v['SPW']}({v['EXEC']})""" return self.minify(vm_lua) def compile_to_bytecode(self, ast): - constants = [] - instructions = [] - locals_map = {} - next_reg = 0 - + constants, instructions, locals_map = [], [], {} + self.next_reg = 0 def add_const(val): - if isinstance(val, str): - s_q = chr(39); d_q = chr(34) - if (val.startswith(s_q) and val.endswith(s_q)) or (val.startswith(d_q) and val.endswith(d_q)): - val = val[1:-1] + if isinstance(val, str) and ((val.startswith("'") and val.endswith("'")) or (val.startswith('"') and val.endswith('"'))): val = val[1:-1] for i, c in enumerate(constants): if c['value'] == val: return i t = 'string' if isinstance(val, str) else 'number' + if val in ['true', 'false', 'nil']: t = 'keyword' constants.append({'type': t, 'value': val}) return len(constants) - 1 - - def load_expr_to_reg(expr, reg): - if expr['type'] == 'IDENT': - if expr['value'] in locals_map: - instructions.append([self.op_to_id["MOVE"], reg, locals_map[expr['value']], 0]) - else: - instructions.append([self.op_to_id["GETGLOBAL"], reg, add_const(expr['value']), 0]) - elif expr['type'] in ['STRING', 'NUMBER']: - val = expr['value'] - if expr['type'] == 'NUMBER': - try: val = float(val) - except: pass - instructions.append([self.op_to_id["LOADK"], reg, add_const(val), 0]) - + def emit(op, a=0, b=0, c=0): instructions.append([self.op_to_id[op], a, b, c]) + def gen_expr(expr, target): + if not expr: return + if expr['type'] == 'NUMBER': emit("LOADK", target, add_const(float(expr['value']))) + elif expr['type'] == 'STRING': emit("LOADK", target, add_const(expr['value'])) + elif expr['type'] == 'KEYWORD': emit("LOADK", target, add_const(expr['value'])) + elif expr['type'] == 'variable': + if expr['name'] in locals_map: emit("MOVE", target, locals_map[expr['name']]) + else: emit("GETGLOBAL", target, add_const(expr['name'])) + elif expr['type'] == 'index': + br = self.next_reg; self.next_reg += 1; gen_expr(expr['base'], br) + kr = self.next_reg; self.next_reg += 1; gen_expr(expr['key'], kr) + emit("GETTABLE", target, br, kr); self.next_reg -= 2 + elif expr['type'] == 'binary': + lr = self.next_reg; self.next_reg += 1; gen_expr(expr['left'], lr) + rr = self.next_reg; self.next_reg += 1; gen_expr(expr['right'], rr) + op_m = {'+': 'ADD', '-': 'SUB', '*': 'MUL', '/': 'DIV'} + emit(op_m.get(expr['op'], 'ADD'), target, lr, rr); self.next_reg -= 2 + elif expr['type'] == 'unary': + or_reg = self.next_reg; self.next_reg += 1; gen_expr(expr['operand'], or_reg) + op_m = {'-': 'UNM', '#': 'LEN', 'not': 'NOT'} + emit(op_m.get(expr['op'], 'UNM'), target, or_reg); self.next_reg -= 1 + elif expr['type'] == 'call': gen_call(expr, target) + def gen_call(node, target): + fr = self.next_reg; self.next_reg += 1 + if node['func']['type'] == 'variable': + if node['func']['name'] in locals_map: emit("MOVE", fr, locals_map[node['func']['name']]) + else: emit("GETGLOBAL", fr, add_const(node['func']['name'])) + else: gen_expr(node['func'], fr) + for i, arg in enumerate(node['args']): + ar = self.next_reg; self.next_reg += 1; gen_expr(arg, ar) + emit("CALL", fr, len(node['args']) + 1, 2) + emit("MOVE", target, fr) + self.next_reg = fr for node in ast: - if node['type'] == 'call': - func_reg = next_reg - if node['name'] in locals_map: - instructions.append([self.op_to_id["MOVE"], func_reg, locals_map[node['name']], 0]) - else: - instructions.append([self.op_to_id["GETGLOBAL"], func_reg, add_const(node['name']), 0]) - for i, arg_expr in enumerate(node['args']): - load_expr_to_reg(arg_expr, func_reg + 1 + i) - instructions.append([self.op_to_id["CALL"], func_reg, len(node['args']) + 1, 1]) - elif node['type'] == 'assign': - val_reg = next_reg - load_expr_to_reg(node['value'], val_reg) - if node.get('local'): - locals_map[node['name']] = val_reg - next_reg += 1 - else: - instructions.append([self.op_to_id["SETGLOBAL"], val_reg, add_const(node['name']), 0]) - - instructions.append([self.op_to_id["RETURN"], 0, 0, 0]) + if node['type'] == 'assign': + vr = self.next_reg; self.next_reg += 1; gen_expr(node['value'], vr) + if node.get('local'): locals_map[node['name']] = vr + elif 'target' in node: + t = node['target'] + if t['type'] == 'index': + br = self.next_reg; self.next_reg += 1; gen_expr(t['base'], br) + kr = self.next_reg; self.next_reg += 1; gen_expr(t['key'], kr) + emit("SETTABLE", br, kr, vr); self.next_reg -= 2 + else: emit("SETGLOBAL", vr, add_const(node['name'])) + elif node['type'] == 'call': gen_call(node, self.next_reg) + emit("RETURN") return {"instructions": instructions, "constants": constants} def obfuscate(self, code): diff --git a/core/parser.py b/core/parser.py index 3676e12..ee0fcda 100644 --- a/core/parser.py +++ b/core/parser.py @@ -5,102 +5,88 @@ class Lexer: self.code = code self.tokens = [] self.pos = 0 - - # Using chr() to build regex parts and avoid tool-induced corruption. - LB = chr(91) - RB = chr(93) - DQ = chr(34) - SQ = chr(39) - BS = chr(92) - - # List every operator individually to avoid character set issues. - OP_LIST = '==|~=|<=|>=|\.\.\.|\.\.|>>|<<|\+|\-|\*|/|%|\^|#|=|\<|\>|\(|\)|\{|\}|' + BS + LB + '|' + BS + RB + '|;|:|,|\.' - + LB, RB, DQ, SQ, BS = chr(91), chr(93), chr(34), chr(39), chr(92) + OP_LIST = r'==|~=|<=|>=|\.\.\.|\.\.|>>|<<|\+|\-|\*|/|%|\^|#|=|\<|\>|\(|\)|\{|\}|' + BS + LB + '|' + BS + RB + '|;|:|,|\.' self.rules = [ ('COMMENT', re.compile('--' + LB + LB + '.*?' + RB + RB + '|--.*', re.DOTALL)), - ('STRING', re.compile(DQ + '(?:' + BS + BS + '.|[^' + DQ + BS + BS + '])*' + DQ + '|' + SQ + '(?:' + BS + BS + '.|[^' + SQ + BS + BS + '])*' + SQ + '|' + LB + LB + '.*?' + RB + RB, re.DOTALL)), - ('NUMBER', re.compile(r'\d+\.?\d*')), + ('STRING', re.compile(DQ + r'(?:' + BS + BS + r'.|[^' + DQ + BS + BS + r'])*' + DQ + '|' + SQ + r'(?:' + BS + BS + r'.|[^' + SQ + BS + BS + r'])*' + SQ + '|' + LB + LB + '.*?' + RB + RB, re.DOTALL)), + ('NUMBER', re.compile(r'\b\d+\.?\d*(?:[eE][+-]?\d+)?\b|\b0x[0-9a-fA-F]+\b')), ('KEYWORD', re.compile(r'\b(and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b')), ('IDENT', re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*')), ('OP', re.compile(OP_LIST)), ('SPACE', re.compile(r'\s+')) ] - def tokenize(self): while self.pos < len(self.code): match = None for name, regex in self.rules: match = regex.match(self.code, self.pos) if match: - if name != 'SPACE' and name != 'COMMENT': - self.tokens.append((name, match.group(0))) - self.pos = match.end() - break - if not match: - self.pos += 1 + if name != 'SPACE' and name != 'COMMENT': self.tokens.append((name, match.group(0))) + self.pos = match.end(); break + if not match: self.pos += 1 return self.tokens class Parser: - def __init__(self, tokens): - self.tokens = tokens - self.pos = 0 - + def __init__(self, tokens): self.tokens = tokens; self.pos = 0 def peek(self, offset=0): - index = self.pos + offset - return self.tokens[index] if index < len(self.tokens) else (None, None) - - def consume(self, expected_type=None, expected_value=None): - token = self.peek() - if not token or not token[0]: return None - if expected_type and token[0] != expected_type: return None - if expected_value and token[1] != expected_value: return None - self.pos += 1 - return token - + idx = self.pos + offset + return self.tokens[idx] if idx < len(self.tokens) else (None, None) + def consume(self, t=None, v=None): + tk = self.peek() + if not tk or not tk[0]: return None + if t and tk[0] != t: return None + if v and tk[1] != v: return None + self.pos += 1; return tk def parse(self): nodes = [] while self.pos < len(self.tokens): node = self.parse_statement() - if node: - nodes.append(node) - else: - self.pos += 1 + if node: nodes.append(node) + else: self.pos += 1 return nodes - def parse_statement(self): - token = self.peek() - if not token or not token[0]: return None - - if token[1] == 'local': - self.consume() - ident = self.consume('IDENT') + tk = self.peek() + if not tk or not tk[0]: return None + if tk[1] == 'local': + self.consume(); ident = self.consume('IDENT') if ident: - if self.peek()[1] == '=': - self.consume() - val = self.parse_expression() - return {'type': 'assign', 'name': ident[1], 'value': val, 'local': True} + if self.peek()[1] == '=': self.consume(); return {'type': 'assign', 'name': ident[1], 'value': self.parse_expression(), 'local': True} return None - - if token[0] == 'IDENT': - ident = self.consume()[1] - next_token = self.peek() - if next_token[1] == '(': - self.consume() - args = [] - while self.peek()[1] and self.peek()[1] != ')': + start = self.pos; expr = self.parse_prefix_expression() + if expr: + if self.peek()[1] == '=': self.consume(); return {'type': 'assign', 'target': expr, 'value': self.parse_expression()} + elif expr['type'] == 'call': return expr + self.pos = start; return None + def parse_prefix_expression(self): + tk = self.peek() + if not tk or tk[0] != 'IDENT': return None + expr = {'type': 'variable', 'name': self.consume()[1]} + while True: + nt = self.peek() + if nt[1] == '.': + self.consume(); m = self.consume('IDENT'); expr = {'type': 'index', 'base': expr, 'key': {'type': 'STRING', 'value': '"'+m[1]+'"'}} + elif nt[1] == '[': self.consume(); key = self.parse_expression(); self.consume('OP', ']'); expr = {'type': 'index', 'base': expr, 'key': key} + elif nt[1] == '(': + self.consume(); args = [] + if self.peek()[1] != ')': args.append(self.parse_expression()) - if self.peek()[1] == ',': - self.consume() - self.consume('OP', ')') - return {'type': 'call', 'name': ident, 'args': args} - elif next_token[1] == '=': - self.consume() - val = self.parse_expression() - return {'type': 'assign', 'name': ident, 'value': val, 'local': False} - - return None - + while self.peek()[1] == ',': self.consume(); args.append(self.parse_expression()) + self.consume('OP', ')'); expr = {'type': 'call', 'func': expr, 'args': args} + else: break + return expr def parse_expression(self): - token = self.consume() - if not token: return None - return {'type': token[0], 'value': token[1]} + left = self.parse_primary_expression() + while self.peek()[1] in ['+', '-', '*', '/', '..', '==', '<', '>', '<=', '>=', '~=']: + op = self.consume()[1]; right = self.parse_primary_expression() + left = {'type': 'binary', 'op': op, 'left': left, 'right': right} + return left + def parse_primary_expression(self): + tk = self.peek() + if not tk: return None + if tk[1] in ['-', '#', 'not']: + op = self.consume()[1]; return {'type': 'unary', 'op': op, 'operand': self.parse_primary_expression()} + if tk[0] in ['STRING', 'NUMBER']: v = tk[1]; self.consume(); return {'type': tk[0], 'value': v} + if tk[1] in ['true', 'false', 'nil']: return {'type': 'KEYWORD', 'value': self.consume()[1]} + if tk[1] == '(': self.consume(); e = self.parse_expression(); self.consume('OP', ')'); return e + return self.parse_prefix_expression() \ No newline at end of file