Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Author: Rudy Bermudez
- Filename: parser.py
- Assignment: HW3
- Description: Controls Parsing Tasks
- """
- import mytoken
- from error import Error
- from mypl_ast import *
- class Parser(object):
- def __init__(self, lexer):
- """ Initializes the Parser Class
- :param lexer: Instance of `Lexer`
- """
- self.lexer = lexer
- self.current_token = None
- def parse(self):
- """ Starts the reverse descent parser
- Succeeds if program is syntactically well-formed
- """
- stmt_list_node = StmtList()
- self.__advance()
- self.__stmts(stmt_list_node)
- self.__expect(mytoken.EOS, 'expecting end of file')
- return stmt_list_node
- def __advance(self):
- """ Calls for the next token from the `lexer` and stores it to `self.current_token` """
- self.current_token = self.lexer.next_token()
- def __expect(self, tokentype, error_msg):
- """ Checks to see if the current token is what is syntactically expected
- :param tokentype: the expected token type of type `Token`
- :param error_msg: the error message to be delivered to the console
- """
- if self.current_token.tokentype == tokentype:
- self.__advance()
- else:
- self.__error(error_msg)
- def __error(self, error_msg):
- """ Raises an Error
- :param error_msg: the error message to be delivered to the console
- """
- s = error_msg + ' found "' + self.current_token.lexeme + '"'
- l = self.current_token.line
- c = self.current_token.column
- raise Error(s, l, c)
- def __stmts(self, stmt_list_node):
- if not (self.current_token.tokentype == mytoken.EOS
- or self.current_token.tokentype == mytoken.END
- or self.current_token.tokentype == mytoken.ELSE
- or self.current_token.tokentype == mytoken.ELSEIF
- ):
- self.__stmt(stmt_list_node)
- self.__stmts(stmt_list_node)
- def __stmt(self, stmt_list_node):
- if self.current_token.tokentype == mytoken.PRINT or self.current_token.tokentype == mytoken.PRINTLN:
- self.__output(stmt_list_node)
- elif self.current_token.tokentype == mytoken.ID:
- self.__assign(stmt_list_node)
- elif self.current_token.tokentype == mytoken.IF:
- self.__cond(stmt_list_node)
- elif self.current_token.tokentype == mytoken.WHILE:
- self.__loop(stmt_list_node)
- # Done
- def __output(self, stmt_list_node):
- print_node = PrintStmt()
- if self.current_token.tokentype == mytoken.PRINT:
- print_node.is_println = False
- self.__advance()
- self.__expect(mytoken.LPAREN, 'expecting "("')
- print_node.expr = self.__expr()
- self.__expect(mytoken.RPAREN, 'expecting ")"')
- self.__expect(mytoken.SEMICOLON, 'expecting ";"')
- stmt_list_node.stmts.append(print_node)
- elif self.current_token.tokentype == mytoken.PRINTLN:
- print_node.is_println = True
- self.__advance()
- self.__expect(mytoken.LPAREN, 'expecting "("')
- print_node.expr = self.__expr()
- self.__expect(mytoken.RPAREN, 'expecting ")"')
- self.__expect(mytoken.SEMICOLON, 'expecting ";"')
- stmt_list_node.stmts.append(print_node)
- def __input(self):
- # Should this function return?
- read_node = ReadExpr()
- if self.current_token.tokentype == mytoken.READINT:
- read_node.is_read_int = True
- self.__advance()
- self.__expect(mytoken.LPAREN, 'expecting "("')
- read_node.msg = self.current_token
- self.__expect(mytoken.STRING, 'expecting "STRING"')
- self.__expect(mytoken.RPAREN, 'expecting ")"')
- self.__value()
- return read_node
- elif self.current_token.tokentype == mytoken.READSTR:
- self.__advance()
- read_node.is_read_int = False
- self.__expect(mytoken.LPAREN, 'expecting "("')
- read_node.msg = self.current_token
- self.__expect(mytoken.STRING, 'expecting "STRING"')
- self.__expect(mytoken.RPAREN, 'expecting ")"')
- self.__value()
- return read_node
- # Done
- def __assign(self, stmt_list_node):
- assign_node = AssignStmt()
- assign_node.lhs = self.current_token
- self.__advance()
- assign_node.index_expr = self.__listindex()
- self.__expect(mytoken.ASSIGN, 'expecting "="')
- assign_node.rhs = self.__expr()
- self.__expect(mytoken.SEMICOLON, 'expecting ";"')
- stmt_list_node.stmts.append(assign_node)
- # Done
- def __listindex(self):
- index_expr = IndexExpr()
- if self.current_token.tokentype == mytoken.LBRACKET:
- self.__advance()
- index_expr.identifier = self.current_token
- index_expr.expr = self.__expr()
- self.__expect(mytoken.RBRACKET, 'expecting "]"')
- return index_expr
- def __expr(self):
- expr_list = ListExpr()
- # TODO: Rudy - Do I pass in expr_list to value() and exprt()?
- self.__value(expr_list)
- self.__exprt(expr_list)
- return expr_list
- def __value(self, expr_list):
- # Should this method return or append?
- if self.current_token.tokentype == mytoken.ID:
- simple_expr_node = SimpleExpr()
- simple_expr_node.term = self.current_token
- self.__advance()
- self.__listindex() # What do I do with this list index?
- expr_list.expressions.append(simple_expr_node)
- elif (self.current_token.tokentype == mytoken.STRING
- or self.current_token.tokentype == mytoken.INT
- or self.current_token.tokentype == mytoken.BOOL
- ):
- simple_expr_node = SimpleExpr()
- simple_expr_node.term = self.current_token
- self.__advance()
- expr_list.expressions.append(simple_expr_node)
- elif self.current_token.tokentype == mytoken.LBRACKET:
- # TODO: Rudy - What do I do in this case?
- self.__advance()
- self.__exprlist()
- self.__expect(mytoken.RBRACKET, 'expecting "]"')
- else:
- expr_list.expressions.append(self.__input())
- def __exprt(self, expr_list):
- if (self.current_token.tokentype == mytoken.PLUS
- or self.current_token.tokentype == mytoken.MINUS
- or self.current_token.tokentype == mytoken.DIVIDE
- or self.current_token.tokentype == mytoken.MULTIPLY
- or self.current_token.tokentype == mytoken.MODULUS
- ):
- self.__math_rel()
- self.__expr()
- def __exprlist(self):
- # TODO: Do I have to do a nested check of <expr> and <value> ?
- self.__expr()
- self.__exprtail()
- def __exprtail(self):
- if self.current_token.tokentype == mytoken.COMMA:
- self.__advance()
- self.__expr()
- self.__exprtail()
- def __math_rel(self):
- self.__advance()
- def __cond(self):
- self.__advance()
- self.__bexpr()
- self.__expect(mytoken.THEN, 'expecting "THEN"')
- self.__stmts()
- self.__condt()
- self.__expect(mytoken.END, 'expecting "END"')
- def __condt(self):
- if self.current_token.tokentype == mytoken.ELSEIF:
- self.__advance()
- self.__bexpr()
- self.__expect(mytoken.THEN, 'expecting "THEN"')
- self.__stmts()
- self.__condt()
- elif self.current_token.tokentype == mytoken.ELSE:
- self.__advance()
- self.__stmts()
- def __bexpr(self):
- if self.current_token.tokentype == mytoken.NOT:
- self.__advance()
- self.__expr()
- self.__bexprt()
- else:
- self.__expr()
- self.__bexprt()
- def __bexprt(self):
- if (self.current_token.tokentype == mytoken.EQUAL
- or self.current_token.tokentype == mytoken.LESS_THAN
- or self.current_token.tokentype == mytoken.GREATER_THAN
- or self.current_token.tokentype == mytoken.LESS_THAN_EQUAL
- or self.current_token.tokentype == mytoken.GREATER_THAN_EQUAL
- or self.current_token.tokentype == mytoken.NOT_EQUAL
- ):
- self.__bool_rel()
- self.__expr()
- self.__bconnect()
- def __bconnect(self):
- if self.current_token.tokentype == mytoken.AND:
- self.__advance()
- self.__bexpr()
- elif self.current_token.tokentype == mytoken.OR:
- self.__advance()
- self.__bexpr()
- def __bool_rel(self):
- self.__advance()
- def __loop(self):
- self.__advance()
- self.__bexpr()
- self.__expect(mytoken.DO, 'expecting "DO"')
- self.__stmts()
- self.__expect(mytoken.END, 'expecting "END"')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement