def multiplier(): if token.table == TABLE_ID: return NodeAST(NodeAST.ID, token_line, token.index) if token.table == TABLE_NUMBER: return NodeAST(NodeAST.NUMBER, token_line, token.index) if token.value == token.TRUE or token.value == token.FALSE: return NodeAST(NodeAST.BOOL, token_line, token.index) if token.value == token.NOT: next_token() m = multiplier() if not m: return None return NodeAST( NodeAST.EXPR, token_line, NodeAST(NodeAST.OP, token_line, TABLE_KEYWORD, token.NOT), m, None) if token.value == token.LPAR: next_token() e = expr() if e and token.value == token.RPAR: return e return None
def read_stmt(): args = [] next_token() if token.value == token.LPAR: next_token() if token.table != TABLE_ID: print('Error [line ' + str(token_line) + ']: expected variable after \'(\'') return None args.append(NodeAST(NodeAST.ID, token_line, token.index)) next_token() while token.value == token.COMMA: next_token() if token.table != TABLE_ID: print('Error [line ' + str(token_line) + ']: expected variable after \'(\'') return None args.append(NodeAST(NodeAST.ID, token_line, token.index)) next_token() if token.value == token.RPAR: next_token() return NodeAST(NodeAST.READ, token_line, *args) print('Error [line ' + str(token_line) + ']: expected \'(\' after \'read\'') return None
def if_stmt(): next_token() cond = expr() if cond: if token.value == token.THEN: next_token() lhs = stmt() if lhs: if token.value == token.ELSE: next_token() rhs = stmt() if rhs: return NodeAST(NodeAST.IF, token_line, cond, lhs, rhs) print('Error [line ' + str(token_line) + ']: expected statement after \'else\'') return None return NodeAST(NodeAST.IF, token_line, cond, lhs, None) print('Error [line ' + str(token_line) + ']: expected statement after \'then\'') return None print('Error [line ' + str(token_line) + ']: expected \'then\' in \'if\' statement') return None print('Error [line ' + str(token_line) + ']: expected expression after \'if\'') return None
def ass_stmt(): lhs = NodeAST(NodeAST.ID, token_line, token.index) next_token() if token.value == token.ASS: next_token() rhs = expr() if rhs: return NodeAST(NodeAST.ASS, token_line, lhs, rhs) print('Error [line ' + str(token_line) + ']: expected expression after \'ass\'') return None print('Error [line ' + str(token_line) + ']: expected \'ass\'') return None
def write_stmt(): next_token() args = [] if token.value == token.LPAR: next_token() args.append(expr()) if not args[-1]: print('Error [line ' + str(token_line) + ']: expected expression after \'(\'') return None while token.value == token.COMMA: next_token() args.append(expr()) if not args[-1]: print('Error [line ' + str(token_line) + ']: expected expression') return None if token.table == TABLE_ID: print('Error [line ' + str(token_line) + ']: expected \',\'') return None elif token.value == token.RPAR: next_token() return NodeAST(NodeAST.WRITE, token_line, *args) else: print('Error [line ' + str(token_line) + ']: expected \')') return None print('Error [line ' + str(token_line) + ']: expected \'(\'') return None
def for_stmt(): next_token() begin = ass_stmt() if begin: if token.value == token.TO: next_token() end = expr() if end: if token.value == token.DO: next_token() stmts = stmt() if stmts: return NodeAST(NodeAST.FOR, token_line, begin, end, stmts) print('Error [line ' + str(token_line) + ']: expected statement after \'do\'') return None print('Error [line ' + str(token_line) + ']: expected \'do\' in \'for\' statement') return None print('Error [line ' + str(token_line) + ']: expected expression after \'to\'') return None print('Error [line ' + str(token_line) + ']: expected \'to\' in \'for\' statement') return None print('Error [line ' + str(token_line) + ']: expected statement after \'for\'') return None
def parse(): global errors if token.value != token.PROGRAM: print('Error [line ' + str(token_line) + ']: expected \'program\'') return None next_token() if token.value != token.VAR: print('Error [line ' + str(token_line) + ']: expected \'var\'') return None next_token() decls = [] decls.append(declaration()) while decls[-1]: if token.value == token.BEGIN: break decls.append(declaration()) if not decls: print('Error [line ' + str(token_line) + ']: expected declarations') return None next_token() stmts = [] result = stmt() while True: if not result: if token.value == token.END or not token.value: break errors = True while token.value != token.SEMICOLON: next_token() if not token.value: break next_token() if token.value == token.END or not token.value: break result = stmt() stmts.append(result) if token.value != token.SEMICOLON: print('Error [line ' + str(token_line) + ']: ' + 'expected \';\' after statement') return None next_token() result = stmt() if token.value != token.END: print('Error [line ' + str(token_line) + ']: ' + 'expected \'end\'') return None next_token() if token.value != token.DOT: print('Error [line ' + str(token_line) + ']: ' + 'expected \'.\' after \'end\'') return None return NodeAST(NodeAST.PROGRAM, token_line, decls, stmts)
def operand(): lhs = summand() if lhs: op = sumop() if op: next_token() rhs = operand() if rhs: return NodeAST(NodeAST.EXPR, token_line, op, lhs, rhs) return None return lhs return None
def summand(): lhs = multiplier() if lhs: next_token() op = mulop() if op: next_token() rhs = summand() if rhs: return NodeAST(NodeAST.EXPR, token_line, op, lhs, rhs) return None return lhs return None
def while_stmt(): next_token() cond = expr() if cond: if token.value == token.DO: next_token() stmts = stmt() if stmts: return NodeAST(NodeAST.WHILE, token_line, cond, stmts) print('Error [line ' + str(token_line) + ']: expected statement after \'do\'') return None print('Error [line ' + str(token_line) + ']: expected \'do\' in \'while\' statement') return None print('Error [line ' + str(token_line) + ']: expected expression after \'while\'') return None
def stmt(): args = [] node = None if token.table == TABLE_ID: node = ass_stmt() elif token.value == token.IF: node = if_stmt() elif token.value == token.WRITE: node = write_stmt() elif token.value == token.READ: node = read_stmt() elif token.value == token.FOR: node = for_stmt() elif token.value == token.WHILE: node = while_stmt() if node: if token.value == token.COLON: args.append(node) while token.value == token.COLON: next_token() if token.table == TABLE_ID: node = ass_stmt() elif token.value == token.IF: node = if_stmt() elif token.value == token.WRITE: node = write_stmt() elif token.value == token.READ: node = read_stmt() elif token.value == token.FOR: node = for_stmt() elif token.value == token.WHILE: node = while_stmt() if not node: return None args.append(node) return NodeAST(NodeAST.STMT_SEQ, token_line, *args) return node return None
def relop(): if (token.value == token.NOTEQUAL) or (token.value == token.EQUAL) or \ (token.value == token.LESS) or (token.value == token.GREAT) or \ (token.value == token.LESSEQUAL) or (token.value == token.GREATEQUAL): return NodeAST(NodeAST.OP, token_line, TABLE_SEPARATOR, token.value) return None
def sumop(): if token.value == token.PLUS or token.value == token.MINUS: return NodeAST(NodeAST.OP, token_line, TABLE_SEPARATOR, token.value) if token.value == token.OR: return NodeAST(NodeAST.OP, token_line, TABLE_KEYWORD, token.value) return None
def mulop(): if token.value == token.MUL or token.value == token.DIV: return NodeAST(NodeAST.OP, token_line, TABLE_SEPARATOR, token.value) if token.value == token.AND: return NodeAST(NodeAST.OP, token_line, TABLE_KEYWORD, token.value) return None