Skip to content

Commit

Permalink
Merge pull request #13 from nyjc-computing/variables
Browse files Browse the repository at this point in the history
06c Retrieving variables
  • Loading branch information
ngjunsiang committed Apr 15, 2022
2 parents c4b76f6 + 2f65c3b commit 1cbb022
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 36 deletions.
36 changes: 15 additions & 21 deletions builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,6 @@ class LogicError(Exception): pass



# Token types

KEYWORDS = [
'DECLARE', 'OUTPUT',
'WHILE', 'DO', 'ENDWHILE',
'CASE', 'OF', 'OTHERWISE', 'ENDCASE',
]

TYPES = ['INTEGER', 'STRING']

OPERATORS = [
'+', '-', '/', '*', '=',
'<', '<-', '<=', '>', '>=', '<>',
]

SYMBOLS = [':']



# Operators

def add(x, y):
Expand Down Expand Up @@ -59,11 +40,22 @@ def ne(x, y):
def eq(x, y):
return x == y

def get(frame, name):
return frame[name]['value']



# Token types

KEYWORDS = [
'DECLARE', 'OUTPUT',
'WHILE', 'DO', 'ENDWHILE',
'CASE', 'OF', 'OTHERWISE', 'ENDCASE',
]

# Classifier
TYPES = ['INTEGER', 'STRING']

operators = {
OPERATORS = {
'+': add,
'-': sub,
'*': mul,
Expand All @@ -75,3 +67,5 @@ def eq(x, y):
'<>': ne,
'=': eq,
}

SYMBOLS = [':']
21 changes: 12 additions & 9 deletions interpreter.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
from builtin import RuntimeError, LogicError
from builtin import RuntimeError, LogicError, get



def evaluate(expr):
def evaluate(expr, frame=None):
# Evaluating tokens
if 'type' in expr:
if expr['type'] == 'name':
return expr['word']
return expr['value']
# Evaluating exprs
left = evaluate(expr['left'])
right = evaluate(expr['right'])
oper = expr['oper']['value']
if oper is get:
left = frame # <-- expr['left'] is None
else:
left = evaluate(expr['left'])
right = evaluate(expr['right'])
return oper(left, right)

def execOutput(frame, stmt):
for expr in stmt['exprs']:
print(str(evaluate(expr)), end='')
print(str(evaluate(expr, frame)), end='')
print('') # Add \n

def execDeclare(frame, stmt):
name = evaluate(stmt['name'])
type_ = evaluate(stmt['type'])
name = evaluate(stmt['name'], frame)
type_ = evaluate(stmt['type'], frame)
frame[name] = {'type': type_, 'value': None}

def execAssign(frame, stmt):
name = evaluate(stmt['name'])
value = evaluate(stmt['expr'])
name = evaluate(stmt['name'], frame)
value = evaluate(stmt['expr'], frame)
if name not in frame:
raise LogicError(f'Undeclared name {repr(name)}')
# HACK: type-check values before storing
Expand Down
1 change: 1 addition & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
src = '''
DECLARE Index : INTEGER
Index <- 1
OUTPUT Index
'''


Expand Down
18 changes: 14 additions & 4 deletions parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from builtin import ParseError
from builtin import ParseError, get
from scanner import makeToken


Expand Down Expand Up @@ -28,6 +28,13 @@ def makeExpr(left, oper, right):

# Expr: {'left': ..., 'oper': ..., 'right': ...}

def identifier(tokens):
token = check(tokens)
if token['type'] == 'name':
return consume(tokens)
else:
raise ParseError(f"Expected variable name, got {repr(token['word'])}")

def value(tokens):
token = check(tokens)
# A single value
Expand All @@ -42,7 +49,10 @@ def value(tokens):
consume(tokens) # )
return expr
elif token['type'] == 'name':
return consume(tokens)
frame = None
name = identifier(tokens)
oper = {'type': 'symbol', 'word': '', 'value': get}
return makeExpr(frame, oper, name)
else:
raise ParseError(f"Unexpected token {repr(token['word'])}")

Expand Down Expand Up @@ -113,7 +123,7 @@ def outputStmt(tokens):
return stmt

def declareStmt(tokens):
name = value(tokens)
name = identifier(tokens)
expectElseError(tokens, ':')
typetoken = consume(tokens)
expectElseError(tokens, '\n')
Expand All @@ -125,7 +135,7 @@ def declareStmt(tokens):
return stmt

def assignStmt(tokens):
name = value(tokens)
name = identifier(tokens)
expectElseError(tokens, '<-')
expr = expression(tokens)
stmt = {
Expand Down
3 changes: 1 addition & 2 deletions scanner.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from builtin import ParseError
from builtin import KEYWORDS, TYPES, OPERATORS, SYMBOLS
from builtin import operators



Expand Down Expand Up @@ -83,7 +82,7 @@ def scan(src):
token = makeToken('string', text, text[1:-1])
elif char in '()[]:,.+-/*=<>':
text = symbol(code)
oper = operators.get(text, None)
oper = OPERATORS.get(text, None)
token = makeToken('symbol', text, oper)
else:
raise ParseError(f"Unrecognised character {repr(char)}.")
Expand Down

0 comments on commit 1cbb022

Please sign in to comment.