Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack-based arithmetics #19

Merged
merged 1 commit into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions src/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,27 @@ def execute_block(self, block, bindings: Bindings):
return True

def instruction_add(self, args, bindings):
value, (_, target) = args
((_, target),) = args
current = self.stack.pop()
old = bindings.resolve(target)
current = self.resolve_value(value, bindings)
bindings.assign(target, old + current)

def instruction_subtract(self, args, bindings):
value, (_, target) = args
((_, target),) = args
current = self.stack.pop()
old = bindings.resolve(target)
current = self.resolve_value(value, bindings)
bindings.assign(target, old - current)

def instruction_multiply(self, args, bindings):
value, (_, target) = args
((_, target),) = args
current = self.stack.pop()
old = bindings.resolve(target)
current = self.resolve_value(value, bindings)
bindings.assign(target, old * current)

def instruction_divide(self, args, bindings):
value, (_, target) = args
((_, target),) = args
current = self.stack.pop()
old = bindings.resolve(target)
current = self.resolve_value(value, bindings)
bindings.assign(target, old // current)

def instruction_and(self, args, bindings):
Expand Down Expand Up @@ -139,9 +139,7 @@ def instruction_load(self):

for pos in reversed(temp_positions):
if pos < 0 or pos >= len(self.heap):
raise InvalidMemoryAddressException(
f"Invalid memory access at position: {pos}"
)
raise InvalidMemoryAddressException(f"Invalid memory access at position: {pos}")

value = self.heap[pos]
self.stack.append(value)
Expand Down
17 changes: 7 additions & 10 deletions src/grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@
program = ws_0n subroutine (sp_0n br ws_0n subroutine)* ws_0n
subroutine = identifier ws_1n block
block = begin ws_1n (instruction (sp_0n br ws_0n instruction)*)? ws_1n end
instruction = assignment / conditional / loop / stack_op
/ arithmetic_op / boolean_op / io_op / stop / identifier
/ halt / store / load
instruction = assignment / conditional / loop / stack / op / io / stop
/ identifier / halt / store / load

assignment = let sp_1n identifier
conditional = if sp_1n value ws_1n block (ws_1n elif sp_1n value ws_1n block)* (ws_1n else ws_1n block)?
loop = while sp_1n value ws_1n block
stack_op = (push sp_1n value) / (pop sp_1n identifier)
arithmetic_op = (add / subtract / multiply / divide) sp_1n value sp_1n identifier
boolean_op = (and / or / xor / negate / not) sp_1n identifier
io_op = print sp_1n value
stack = (push sp_1n value) / (pop sp_1n identifier)
op = (add / subtract / multiply / divide / and / or / xor / negate / not) sp_1n identifier
io = print sp_1n value
halt = exit sp_1n value

value = identifier / literal
Expand All @@ -37,9 +35,8 @@
sp_1n = ~r"[ \t]+"

reserved = begin / end / stop / if / elif / else / while / push
/ pop / let / add / subtract / multiply
/ divide / and / or / xor / not / print / exit / store
/ load
/ pop / let / add / subtract / multiply / divide / and
/ or / xor / not / print / exit / store / load
begin = ~r"begin"i / ~r"do"i
exit = ~r"exit"i
end = ~r"end"i
Expand Down
14 changes: 7 additions & 7 deletions src/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
import argparse
import pprint

import grammar as grammar
import visitor as visitor
from preprocessor import PipelinePreprocessor, CommentsPreprocessor
import grammar
import visitor
import preprocessor


class ImperivmParser:
def __init__(
self,
grammar=grammar.imperivm,
visitor=visitor.ImperivmVisitor(),
preprocessor=None,
preprocessor=preprocessor.PipelinePreprocessor(
[preprocessor.CommentsPreprocessor()]
),
):
self.grammar = grammar
self.visitor = visitor
self.preprocessor = preprocessor or PipelinePreprocessor(
[CommentsPreprocessor()]
)
self.preprocessor = preprocessor

def parse(self, program):
program = self.preprocessor.process(program)
Expand Down
8 changes: 5 additions & 3 deletions src/preprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@

class Preprocessor(ABC):
@abstractmethod
def process(self, program: str) -> str:
def process(self, program: str):
pass


class CommentsPreprocessor(Preprocessor):
@override
def process(self, program: str):
cleaned_program = map(lambda line: re.sub(r"#.*$", "", line), program.splitlines())
cleaned_program = map(
lambda line: re.sub(r"#.*$", "", line), program.splitlines()
)
return "\n".join(cleaned_program)


Expand All @@ -24,4 +26,4 @@ def __init__(self, preprocessor_actions: List[Preprocessor]):
def process(self, program: str):
for action in self.preprocessor_actions:
program = action.process(program)
return program
return program
16 changes: 5 additions & 11 deletions src/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ def visit_assignment(self, _, visited_children):
return instruction.text, target

def visit_conditional(self, _, visited_children):
operation, _, condition, _, block, elif_operations, else_operations = (
visited_children
)
operation, _, condition, _, block, elif_operations, else_operations = visited_children

elif_tree = []
if type(elif_operations) is list:
Expand All @@ -59,20 +57,16 @@ def visit_loop(self, _, visited_children):
operation, _, condition, _, block = visited_children
return operation.text, condition, block

def visit_stack_op(self, _, visited_children):
def visit_stack(self, _, visited_children):
[child] = visited_children
operation, _, target = child
return operation.text, target

def visit_arithmetic_op(self, _, visited_children):
[operation], _, value, _, target = visited_children
return operation.text, value, target

def visit_boolean_op(self, _, visited_children):
def visit_op(self, _, visited_children):
[operation], _, target = visited_children
return operation.text, target

def visit_io_op(self, _, visited_children):
def visit_io(self, _, visited_children):
operation, _, target = visited_children
return operation.text, target

Expand Down Expand Up @@ -103,5 +97,5 @@ def visit_identifier(self, node, _):
return "id", node.text

def generic_visit(self, node, visited_children):
"""The generic visit method."""
"""the generic visit method"""
return visited_children or node
3 changes: 2 additions & 1 deletion tests/add.imp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ main
begin
push -5
let x
add 5 x
push 5
add x
exit x
exit 1
end
3 changes: 2 additions & 1 deletion tests/divide.imp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ main
begin
push 0
let x
divide 14884 x
push 14884
divide x
exit x
exit 1
end
3 changes: 2 additions & 1 deletion tests/multiply.imp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ main
begin
push 84781
let x
multiply 0 x
push 0
multiply x
exit x
exit 1
end
3 changes: 2 additions & 1 deletion tests/negate.imp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ main begin
let x
negate x

add 2 x
push 2
add x

if x do
exit 1
Expand Down
3 changes: 2 additions & 1 deletion tests/or.imp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ main begin
push 2
or x

subtract 3 x
push 3
subtract x

if x do
exit 1
Expand Down
3 changes: 2 additions & 1 deletion tests/subtract.imp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ main
begin
push 5
let x
subtract 5 x
push 5
subtract x
exit x
exit 1
end
3 changes: 2 additions & 1 deletion tests/xor.imp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ main begin
push 3
xor x

subtract 2 x
push 2
subtract x

if x do
exit 1
Expand Down
Loading