Skip to content

Commit

Permalink
added for and while loop in language
Browse files Browse the repository at this point in the history
  • Loading branch information
Aryangp committed Dec 27, 2023
1 parent eff8224 commit e91b681
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 5 deletions.
Binary file modified __pycache__/basic.cpython-311.pyc
Binary file not shown.
145 changes: 141 additions & 4 deletions basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@
"if",
"then",
"elif",
"else"
"else",
"for",
"to",
"step",
"while"
]

#----------------------errors----------------------#
Expand Down Expand Up @@ -315,7 +319,26 @@ def __init__(self,cases,else_case):
self.pos_start=self.cases[0][0].pos_start
self.pos_end=(self.else_case or self.cases[-1][0]).pos_end


class ForNode:
def __init__(self,var_name_tok,start_value_node,end_value_node,step_value_node,body_node,should_return_null):
self.var_name_tok=var_name_tok
self.start_value_node=start_value_node
self.end_value_node=end_value_node
self.step_value_node=step_value_node
self.body_node=body_node
self.should_return_null=should_return_null

self.pos_start=self.var_name_tok.pos_start
self.pos_end=self.body_node.pos_end

class WhileNode:
def __init__(self,condition_node,body_node,should_return_null=None):
self.condition_node=condition_node
self.body_node=body_node
self.should_return_null=should_return_null

self.pos_start=self.condition_node.pos_start
self.pos_end=self.body_node.pos_end

#----------------------parser result----------------------#

Expand Down Expand Up @@ -376,6 +399,7 @@ def factor(self):
res.register_advancement()
self.advance()# does not know what it does
return res.success(NumberNodes(tok))

elif tok.type == TT_LPAREN:
res.register_advancement()
self.advance()
Expand All @@ -390,7 +414,17 @@ def factor(self):
elif tok.matches(TT_KEYWORD,"if"):
if_expr=res.register(self.if_expr())
if res.error: return res
return res.success(if_expr)
return res.success(if_expr)

elif tok.matches(TT_KEYWORD,"for"):
for_expr=res.register(self.for_expr())
if res.error: return res
return res.success(for_expr)

elif tok.matches(TT_KEYWORD,"while"):
while_expr=res.register(self.while_expr())
if res.error: return res
return res.success(while_expr)

return res.failure(InvalidSyntaxError(tok.pos_start,tok.pos_end,"Expected int or float, Indentifier, '+','-','('"))

Expand Down Expand Up @@ -441,6 +475,75 @@ def if_expr(self):

return res.success(IfNode(cases,else_case))

def for_expr(self):
res=ParseResult()

if not self.current_tok.matches(TT_KEYWORD,"for"):
return res.failure(InvalidSyntaxError(self.current_tok.pos_start,self.current_tok.pos_end,"Expected 'for'"))
res.register_advancement()
self.advance()

if self.current_tok.type != TT_INDENTIFIER:
return res.failure(InvalidSyntaxError(self.current_tok.pos_start,self.current_tok.pos_end,"Expected identifier"))
var_name=self.current_tok
res.register_advancement()
self.advance()

if self.current_tok.type != TT_EQ:
return res.failure(InvalidSyntaxError(self.current_tok.pos_start,self.current_tok.pos_end,"Expected '='"))
res.register_advancement()
self.advance()

start_value=res.register(self.expr())
if res.error: return res

if not self.current_tok.matches(TT_KEYWORD,"to"):
return res.failure(InvalidSyntaxError(self.current_tok.pos_start,self.current_tok.pos_end,"Expected 'to'"))
res.register_advancement()
self.advance()

end_value=res.register(self.expr())
if res.error: return res

if self.current_tok.matches(TT_KEYWORD,"step"):
res.register_advancement()
self.advance()

step_value=res.register(self.expr())
if res.error: return res
else:
step_value=None

if not self.current_tok.matches(TT_KEYWORD,"then"):
return res.failure(InvalidSyntaxError(self.current_tok.pos_start,self.current_tok.pos_end,"Expected 'then'"))
res.register_advancement()
self.advance()

body=res.register(self.expr())
if res.error: return res

return res.success(ForNode(var_name,start_value,end_value,step_value,body,True))

def while_expr(self):
res=ParseResult()

if not self.current_tok.matches(TT_KEYWORD,"while"):
return res.failure(InvalidSyntaxError(self.current_tok.pos_start,self.current_tok.pos_end,"Expected 'while'"))
res.register_advancement()
self.advance()

condition=res.register(self.expr())
if res.error: return res

if not self.current_tok.matches(TT_KEYWORD,"then"):
return res.failure(InvalidSyntaxError(self.current_tok.pos_start,self.current_tok.pos_end,"Expected 'then'"))
res.register_advancement()
self.advance()

body=res.register(self.expr())
if res.error: return res

return res.success(WhileNode(condition,body,True))

def term(self):
return self.bin_op(self.factor,(TT_MUL,TT_DIV))
Expand Down Expand Up @@ -730,7 +833,41 @@ def visit_IfNode(self,node,context):
else_value=res.register(self.visit(node.else_case,context))
if res.error:return res
return res.success(else_value)
return res.success(None)
return res.success(None)

def visit_ForNode(self,node,context):
res=RTResult()

start_value=res.register(self.visit(node.start_value_node,context))
if res.error:return res
end_value=res.register(self.visit(node.end_value_node,context))
if res.error:return res
if node.step_value_node:
step_value=res.register(self.visit(node.step_value_node,context))
if res.error:return res
else:
step_value=Number(1)
i=start_value.value
if step_value.value >= 0:
condition=lambda:i<end_value.value
else:
condition=lambda:i>end_value.value
while condition():
context.symbol_table.set(node.var_name_tok.value,Number(i))
i+=step_value.value
res.register(self.visit(node.body_node,context))
if res.error:return res
return res.success(None)

def visit_WhileNode(self,node,context):
res=RTResult()
while True:
condition=res.register(self.visit(node.condition_node,context))
if res.error:return res
if not condition.is_true():break
res.register(self.visit(node.body_node,context))
if res.error:return res
return res.success(None)

#----------------------Runs----------------------#

Expand Down
6 changes: 5 additions & 1 deletion grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ factor : INT|FLOAT|IDENTIFIER
:if-expr
if-expr:KEYWORD:if expr KEYWORD:then expr
(KEYWORD:elif expr KEYWORD:then expr)*
(KEYWORD:else expr)?
(KEYWORD:else expr)?

for-expr :KEYWORD:for IDENTIFIER EO expr KEYWORD:to expr
(KEYWORD:step expr)? KEYWORD:then expr
while-expr:KEYWORD:while expr KEYWORD:then expr

0 comments on commit e91b681

Please sign in to comment.