C interpriter
This commit is contained in:
parent
9fd2bfefec
commit
f124ba5585
@ -5,6 +5,6 @@ Collapsed=0
|
|||||||
|
|
||||||
[Window][Debug]
|
[Window][Debug]
|
||||||
Pos=12,41
|
Pos=12,41
|
||||||
Size=336,392
|
Size=778,630
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
|
14
python-c-interpriter/main.c
Normal file
14
python-c-interpriter/main.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "other.h"
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
int a = 5;
|
||||||
|
printf("%d", a);
|
||||||
|
foo();
|
||||||
|
int i = 10;
|
||||||
|
while (i != 0)
|
||||||
|
{
|
||||||
|
printf("%d", i);
|
||||||
|
i -= 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
159
python-c-interpriter/main.py
Normal file
159
python-c-interpriter/main.py
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
# ──────── Interpreter State ────────
|
||||||
|
|
||||||
|
class Frame:
|
||||||
|
def __init__(self, function_name, locals=None):
|
||||||
|
self.function_name = function_name
|
||||||
|
self.locals = locals or {}
|
||||||
|
|
||||||
|
class InterpreterState:
|
||||||
|
def __init__(self):
|
||||||
|
self.stack = [] # Call stack
|
||||||
|
self.functions = {} # name → AST
|
||||||
|
|
||||||
|
def push_frame(self, name):
|
||||||
|
self.stack.append(Frame(name))
|
||||||
|
|
||||||
|
def pop_frame(self):
|
||||||
|
return self.stack.pop()
|
||||||
|
|
||||||
|
def current_frame(self):
|
||||||
|
return self.stack[-1] if self.stack else None
|
||||||
|
|
||||||
|
def debug_bt(self):
|
||||||
|
print("\nBacktrace:")
|
||||||
|
for i, frame in enumerate(reversed(self.stack)):
|
||||||
|
print(f" #{i} {frame.function_name}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
def debug_vars(self):
|
||||||
|
frame = self.current_frame()
|
||||||
|
print("\nVariables:")
|
||||||
|
if frame:
|
||||||
|
for k, v in frame.locals.items():
|
||||||
|
print(f" {k} = {v}")
|
||||||
|
else:
|
||||||
|
print(" No active frame.")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# ──────── C Parser (toy) ────────
|
||||||
|
|
||||||
|
def parse_c_file(filename, included=None):
|
||||||
|
if included is None:
|
||||||
|
included = set()
|
||||||
|
|
||||||
|
abs_path = os.path.abspath(filename)
|
||||||
|
if abs_path in included:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
included.add(abs_path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(abs_path) as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Error: File '{filename}' not found.")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
ast = {}
|
||||||
|
current_fn = None
|
||||||
|
body = []
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("#include"):
|
||||||
|
match = re.match(r'#include\s+"(.+?)"', line)
|
||||||
|
if match:
|
||||||
|
included_ast = parse_c_file(os.path.join(os.path.dirname(abs_path), match.group(1)), included)
|
||||||
|
ast.update(included_ast)
|
||||||
|
elif line.startswith("void"):
|
||||||
|
fn_match = re.match(r'void\s+(\w+)\s*\(\s*\)\s*{', line)
|
||||||
|
if fn_match:
|
||||||
|
if current_fn:
|
||||||
|
ast[current_fn] = body
|
||||||
|
body = []
|
||||||
|
current_fn = fn_match.group(1)
|
||||||
|
elif line == "}":
|
||||||
|
if current_fn:
|
||||||
|
ast[current_fn] = body
|
||||||
|
current_fn = None
|
||||||
|
body = []
|
||||||
|
elif re.match(r'int\s+\w+\s*=\s*\d+;', line):
|
||||||
|
var_match = re.match(r'int\s+(\w+)\s*=\s*(\d+);', line)
|
||||||
|
body.append(('decl', var_match.group(1), int(var_match.group(2))))
|
||||||
|
elif re.match(r'printf\(".*",\s*\w+\);', line):
|
||||||
|
print_match = re.match(r'printf\(".*",\s*(\w+)\);', line)
|
||||||
|
body.append(('print', print_match.group(1)))
|
||||||
|
elif re.match(r'\w+\(\);', line):
|
||||||
|
call_match = re.match(r'(\w+)\(\);', line)
|
||||||
|
body.append(('call', call_match.group(1)))
|
||||||
|
return ast
|
||||||
|
|
||||||
|
# ──────── Interpreter Executor ────────
|
||||||
|
|
||||||
|
class Interpreter:
|
||||||
|
def __init__(self, state):
|
||||||
|
self.state = state
|
||||||
|
|
||||||
|
def run_function(self, name):
|
||||||
|
if name not in self.state.functions:
|
||||||
|
print(f"Function '{name}' not defined.")
|
||||||
|
return
|
||||||
|
self.state.push_frame(name)
|
||||||
|
body = self.state.functions[name]
|
||||||
|
for stmt in body:
|
||||||
|
self.exec_stmt(stmt)
|
||||||
|
self.state.pop_frame()
|
||||||
|
|
||||||
|
def exec_stmt(self, stmt):
|
||||||
|
frame = self.state.current_frame()
|
||||||
|
if stmt[0] == 'decl':
|
||||||
|
_, var, val = stmt
|
||||||
|
frame.locals[var] = val
|
||||||
|
elif stmt[0] == 'print':
|
||||||
|
var = stmt[1]
|
||||||
|
print(frame.locals.get(var, 'undefined'))
|
||||||
|
elif stmt[0] == 'call':
|
||||||
|
self.run_function(stmt[1])
|
||||||
|
|
||||||
|
# ──────── Debugger CLI ────────
|
||||||
|
|
||||||
|
def debugger_loop(state, interp):
|
||||||
|
print("Mini C Interpreter Debugger")
|
||||||
|
print("Commands: run, bt, vars, quit")
|
||||||
|
while True:
|
||||||
|
cmd = input("(debug) ").strip()
|
||||||
|
if cmd == "run":
|
||||||
|
interp.run_function("main")
|
||||||
|
elif cmd == "bt":
|
||||||
|
state.debug_bt()
|
||||||
|
elif cmd == "vars":
|
||||||
|
state.debug_vars()
|
||||||
|
elif cmd == "quit":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("Unknown command. Use: run, bt, vars, quit")
|
||||||
|
|
||||||
|
# ──────── Entry Point ────────
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python c_interpreter.py <file.c>")
|
||||||
|
return
|
||||||
|
|
||||||
|
filename = sys.argv[1]
|
||||||
|
ast = parse_c_file(filename)
|
||||||
|
if not ast:
|
||||||
|
print("No functions parsed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
state = InterpreterState()
|
||||||
|
state.functions = ast
|
||||||
|
interp = Interpreter(state)
|
||||||
|
debugger_loop(state, interp)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
4
python-c-interpriter/other.h
Normal file
4
python-c-interpriter/other.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
void foo() {
|
||||||
|
int x = 10;
|
||||||
|
printf("%d", x);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user