mirror of
https://github.com/Alvin-Zilverstand/femcode.git
synced 2026-03-06 13:23:39 +01:00
feat: Implement for loops, break, and continue statements
This commit is contained in:
21
examples/loops_advanced.fem
Normal file
21
examples/loops_advanced.fem
Normal file
@@ -0,0 +1,21 @@
|
||||
my_list is ["apple", "banana", "cherry"]
|
||||
Tomgirl item is my_list Femboycore
|
||||
UwU Boy item
|
||||
Periodt
|
||||
|
||||
my_string is "Femboy"
|
||||
Tomgirl char is my_string Femboycore
|
||||
UwU Boy char
|
||||
Periodt
|
||||
|
||||
counter is 0
|
||||
Otokonoko counter < 10 Femboycore
|
||||
counter is counter + 1
|
||||
Femboy Feminine counter == 5 Femboycore
|
||||
Break
|
||||
Periodt
|
||||
Femboy Feminine counter == 2 Femboycore
|
||||
Continue
|
||||
Periodt
|
||||
UwU Boy counter
|
||||
Periodt
|
||||
@@ -104,7 +104,36 @@ class Interpreter:
|
||||
|
||||
def visit_WhileStatement(self, node):
|
||||
while self.visit(node.condition):
|
||||
try:
|
||||
self.visit(node.body)
|
||||
except BreakLoop:
|
||||
break
|
||||
except ContinueLoop:
|
||||
continue
|
||||
|
||||
def visit_ForStatement(self, node):
|
||||
iterable = self.visit(node.iterable)
|
||||
if not isinstance(iterable, (list, str)):
|
||||
raise TypeError(f"'for' loop can only iterate over lists or strings, got {type(iterable).__name__}")
|
||||
|
||||
for item in iterable:
|
||||
self.scope_stack.append({})
|
||||
self.current_scope[node.var_name] = item
|
||||
try:
|
||||
self.visit(node.body)
|
||||
except BreakLoop:
|
||||
self.scope_stack.pop()
|
||||
break
|
||||
except ContinueLoop:
|
||||
self.scope_stack.pop()
|
||||
continue
|
||||
self.scope_stack.pop()
|
||||
|
||||
def visit_BreakStatement(self, node):
|
||||
raise BreakLoop()
|
||||
|
||||
def visit_ContinueStatement(self, node):
|
||||
raise ContinueLoop()
|
||||
|
||||
def visit_List(self, node):
|
||||
elements = [self.visit(element) for element in node.elements]
|
||||
@@ -187,3 +216,15 @@ class Interpreter:
|
||||
class ReturnValue(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
class BreakLoop(Exception):
|
||||
pass
|
||||
|
||||
class ContinueLoop(Exception):
|
||||
pass
|
||||
|
||||
class BreakLoop(Exception):
|
||||
pass
|
||||
|
||||
class ContinueLoop(Exception):
|
||||
pass
|
||||
15
src/lexer.py
15
src/lexer.py
@@ -149,6 +149,21 @@ class Lexer:
|
||||
if re.match(r'\bCringe\b', self.text[self.pos:]):
|
||||
self.pos += len('Cringe')
|
||||
return Token('CRINGE', False)
|
||||
if re.match(r'\bGhosted\b', self.text[self.pos:]):
|
||||
self.pos += len('Ghosted')
|
||||
return Token('NULL', None)
|
||||
if re.match(r'\bTomgirl\b', self.text[self.pos:]):
|
||||
self.pos += len('Tomgirl')
|
||||
return Token('FOR', 'Tomgirl')
|
||||
if re.match(r'\bSlay\b', self.text[self.pos:]):
|
||||
self.pos += len('Slay')
|
||||
return Token('PASS', 'Slay')
|
||||
if re.match(r'\bBreak\b', self.text[self.pos:]):
|
||||
self.pos += len('Break')
|
||||
return Token('BREAK', 'Break')
|
||||
if re.match(r'\bContinue\b', self.text[self.pos:]):
|
||||
self.pos += len('Continue')
|
||||
return Token('CONTINUE', 'Continue')
|
||||
if re.match(r'\band\b', self.text[self.pos:]):
|
||||
self.pos += len('and')
|
||||
return Token('AND', 'and')
|
||||
|
||||
@@ -81,6 +81,18 @@ class BreakStatement(AST):
|
||||
class ContinueStatement(AST):
|
||||
pass
|
||||
|
||||
class ForStatement(AST):
|
||||
def __init__(self, var_name, iterable, body):
|
||||
self.var_name = var_name
|
||||
self.iterable = iterable
|
||||
self.body = body
|
||||
|
||||
class BreakStatement(AST):
|
||||
pass
|
||||
|
||||
class ContinueStatement(AST):
|
||||
pass
|
||||
|
||||
class FunctionDefinition(AST):
|
||||
def __init__(self, name, parameters, body):
|
||||
self.name = name
|
||||
|
||||
Reference in New Issue
Block a user