def call_statement(l, loc): l.expect_noblock('call statment') if l.keyword('expression'): expression = True target = l.require(l.simple_expression) else: expression = False target = l.require(l.name) # Optional pass, to let someone write: # call expression foo pass (bar, baz) l.keyword('pass') arguments = parse_arguments(l) rv = [ast.Call(loc, target, expression, arguments)] if l.keyword('from'): name = l.require(l.name) rv.append(ast.Label(loc, name, [], None)) else: rv.append(ast.Pass(loc)) l.expect_eol() l.advance() return rv
def label_statement(l, loc): name = l.require(l.name) parameters = parse_parameters(l) l.require(':') l.expect_eol() # Optional block here. It's empty if no block is associated with # this statement. block = parse_block(l.subblock_lexer()) l.advance() return ast.Label(loc, name, block, parameters)
def menu_statement(l, loc): l.expect_block('menu statement') label = l.name() l.require(':') l.expect_eol() menu = parse_menu(l, loc) l.advance() rv = [] if label: rv.append(ast.Label(loc, label, [], None)) rv.extend(menu) return rv
def parse_statement(l): """ This parses a Ren'Py statement. l is expected to be a Ren'Py lexer that has been advanced to a logical line. This function will advance l beyond the last logical line making up the current statement, and will return an AST object representing this statement, or a list of AST objects representing this statement. """ # Store the current location. loc = l.get_location() ### If statement if l.keyword('if'): entries = [] condition = l.require(l.python_expression) l.require(':') l.expect_eol() l.expect_block('if statement') block = parse_block(l.subblock_lexer()) entries.append((condition, block)) l.advance() while l.keyword('elif'): condition = l.require(l.python_expression) l.require(':') l.expect_eol() l.expect_block('elif clause') block = parse_block(l.subblock_lexer()) entries.append((condition, block)) l.advance() if l.keyword('else'): l.require(':') l.expect_eol() l.expect_block('else clause') block = parse_block(l.subblock_lexer()) entries.append(('True', block)) l.advance() return ast.If(loc, entries) if l.keyword('elif'): l.error('elif clause must be associated with an if statement.') if l.keyword('else'): l.error('else clause must be associated with an if statement.') ### While statement if l.keyword('while'): condition = l.require(l.python_expression) l.require(':') l.expect_eol() l.expect_block('while statement') block = parse_block(l.subblock_lexer()) l.advance() return ast.While(loc, condition, block) ### Pass statement if l.keyword('pass'): l.expect_noblock('pass statement') l.expect_eol() l.advance() return ast.Pass(loc) ### Menu statement. if l.keyword('menu'): l.expect_block('menu statement') label = l.name() l.require(':') l.expect_eol() menu = parse_menu(l, loc) l.advance() rv = [] if label: rv.append(ast.Label(loc, label, [], None)) rv.extend(menu) return rv ### Return statement. if l.keyword('return'): l.expect_noblock('return statement') rest = l.rest() if not rest: rest = None l.expect_eol() l.advance() return ast.Return(loc, rest) ### Jump statement if l.keyword('jump'): l.expect_noblock('jump statement') if l.keyword('expression'): expression = True target = l.require(l.simple_expression) else: expression = False target = l.require(l.name) l.expect_eol() l.advance() return ast.Jump(loc, target, expression) ### Call/From statement. if l.keyword('call'): l.expect_noblock('call statment') if l.keyword('expression'): expression = True target = l.require(l.simple_expression) else: expression = False target = l.require(l.name) # Optional pass, to let someone write: # call expression foo pass (bar, baz) l.keyword('pass') arguments = parse_arguments(l) rv = [ast.Call(loc, target, expression, arguments)] if l.keyword('from'): name = l.require(l.name) rv.append(ast.Label(loc, name, [], None)) else: rv.append(ast.Pass(loc)) l.expect_eol() l.advance() return rv ### Scene statement. if l.keyword('scene'): if l.keyword('onlayer'): layer = l.require(l.name) else: layer = "master" # Empty. if l.eol(): l.advance() return ast.Scene(loc, None, layer) imspec = parse_image_specifier(l) stmt = ast.Scene(loc, imspec, imspec[4]) rv = parse_with(l, stmt) if l.match(':'): stmt.atl = renpy.atl.parse_atl(l.subblock_lexer()) else: l.expect_noblock('scene statement') l.expect_eol() l.advance() return rv ### Show statement. if l.keyword('show'): imspec = parse_image_specifier(l) stmt = ast.Show(loc, imspec) rv = parse_with(l, stmt) if l.match(':'): stmt.atl = renpy.atl.parse_atl(l.subblock_lexer()) else: l.expect_noblock('show statement') l.expect_eol() l.advance() return rv ### Hide statement. if l.keyword('hide'): imspec = parse_image_specifier(l) rv = parse_with(l, ast.Hide(loc, imspec)) l.expect_eol() l.expect_noblock('hide statement') l.advance() return rv ### With statement. if l.keyword('with'): expr = l.require(l.simple_expression) l.expect_eol() l.expect_noblock('with statement') l.advance() return ast.With(loc, expr) ### Image statement. if l.keyword('image'): name = parse_image_name(l) if l.match(':'): l.expect_eol() expr = None atl = renpy.atl.parse_atl(l.subblock_lexer()) else: l.require('=') expr = l.rest() atl = None l.expect_noblock('image statement') rv = ast.Image(loc, name, expr, atl) if not l.init: rv = ast.Init(loc, [rv], 990) l.advance() return rv ### Define statement. if l.keyword('define'): priority = l.integer() if priority: priority = int(priority) else: priority = 0 name = l.require(l.name) l.require('=') expr = l.rest() l.expect_noblock('define statement') rv = ast.Define(loc, name, expr) if not l.init: rv = ast.Init(loc, [rv], priority) l.advance() return rv ### Transform statement. if l.keyword('transform'): priority = l.integer() if priority: priority = int(priority) else: priority = 0 name = l.require(l.name) parameters = parse_parameters(l) if parameters and (parameters.extrakw or parameters.extrapos): l.error( 'transform statement does not take a variable number of parameters' ) l.require(':') l.expect_eol() atl = renpy.atl.parse_atl(l.subblock_lexer()) rv = ast.Transform(loc, name, atl, parameters) if not l.init: rv = ast.Init(loc, [rv], priority) l.advance() return rv ### One-line python statement. if l.match(r'\$'): python_code = l.rest() l.expect_noblock('one-line python statement') l.advance() return ast.Python(loc, python_code) ### Python block. if l.keyword('python'): hide = False early = False if l.keyword('early'): early = True if l.keyword('hide'): hide = True l.require(':') l.expect_block('python block') python_code = l.python_block() l.advance() if early: return ast.EarlyPython(loc, python_code, hide) else: return ast.Python(loc, python_code, hide) ### Label Statement if l.keyword('label'): name = l.require(l.name) parameters = parse_parameters(l) l.require(':') l.expect_eol() # Optional block here. It's empty if no block is associated with # this statement. block = parse_block(l.subblock_lexer()) l.advance() return ast.Label(loc, name, block, parameters) ### Init Statement if l.keyword('init'): p = l.integer() if p: priority = int(p) else: priority = 0 if l.keyword('python'): hide = False if l.keyword('hide'): hide = True l.require(':') l.expect_block('python block') python_code = l.python_block() l.advance() block = [ast.Python(loc, python_code, hide)] else: l.require(':') l.expect_eol() l.expect_block('init statement') block = parse_block(l.subblock_lexer(True)) l.advance() return ast.Init(loc, block, priority) # Try parsing as a user-statement. If that doesn't work, revert and # try as a say. state = l.checkpoint() word = l.word() if (word, ) in renpy.statements.registry: text = l.text l.expect_noblock(word + ' statement') l.advance() renpy.exports.push_error_handler(l.error) try: rv = ast.UserStatement(loc, text) finally: renpy.exports.pop_error_handler() return rv l.revert(state) # Try parsing as the default statement. if () in renpy.statements.registry: text = l.text l.expect_noblock('default statement') l.advance() renpy.exports.push_error_handler(l.error) try: rv = ast.UserStatement(loc, text) finally: renpy.exports.pop_error_handler() return rv # The one and two arguement say statements are ambiguous in terms # of lookahead. So we first try parsing as a one-argument, then a # two-argument. # We're using the checkpoint from above. what = l.string() if l.keyword('with'): with_ = l.require(l.simple_expression) else: with_ = None if what is not None and l.eol(): # We have a one-argument say statement. l.expect_noblock('say statement') l.advance() return ast.Say(loc, None, what, with_) l.revert(state) # Try for a two-argument say statement. who = l.simple_expression() what = l.string() if l.keyword('with'): with_ = l.require(l.simple_expression) else: with_ = None if who and what is not None: l.expect_eol() l.expect_noblock('say statement') l.advance() return ast.Say(loc, who, what, with_) l.error('expected statement.')