class IncludeDirective(BaseDirective): possible_keywords = ["#include"] exp = strparse.compile("#include {start:1.1}{name:1}{end:1.1}") ORDER_SCRIPT_RELATIVE = 1 ORDER_INCLUDES_RELATIVE = 2 def __init__(self, name, order_type): self.name = name self.order_type = order_type def __str__(self): start, end = self.clause() return "include {start}{name}{end}".format(start=start, name=self.name, end=end) def clause(self): if self.order_type == IncludeDirective.ORDER_SCRIPT_RELATIVE: return '<', '>' return '"', '"' @classmethod def parse(cls, raw_lines, current_line): raw_line = raw_lines[current_line] exp_result = IncludeDirective.exp.parse(raw_line.content) if exp_result is None: raise SyntaxError("Error in {line}".format(line=str(raw_line))) start, name, end = exp_result['start'], exp_result['name'], exp_result[ 'end'] if start == '<' and end == '>': order_type = IncludeDirective.ORDER_INCLUDES_RELATIVE elif start == '"' and end == '"': order_type = IncludeDirective.ORDER_SCRIPT_RELATIVE else: raise SyntaxError("Error in {line}".format(line=str(raw_line))) return IncludeDirective(name, order_type), current_line + 1
class PragmaDirective(BaseDirective): possible_keywords = ['#pragma'] exp = strparse.compile('#pragma {setting:1}') def __init__(self, setting): self.setting = setting def __str__(self): return "#pragma {setting}".format(setting=self.setting) @classmethod def parse(cls, raw_lines, current_line): raw_line = raw_lines[current_line] exp_result = PragmaDirective.exp.parse(raw_line.content) if exp_result is None: raise SyntaxError("Error in {line}".format(line=str(raw_line))) return PragmaDirective(exp_result['setting']), current_line + 1
class FunctionDeclaration(BaseDirective): exp = strparse.compile('Func {func_name}({args})') def __init__(self, func_name, args, func_block): self.func_name = func_name self.args = args self.func_block = func_block def __str__(self): return 'Func {name}({args})\n{block}\nEndFunc'.format( name=self.func_name, args=', '.join(self.args), block=str(self.func_block)) def __repr__(self): return '{}(func_name={}, args={}, func_block={})'.format( FunctionDeclaration.__name__, repr(self.func_name), repr(self.args), repr(self.func_name)) @classmethod def try_parse(cls, raw_lines, current_line): content = raw_lines[current_line].content if not content.startswith('Func '): return NO_MATCH exp_result = FunctionDeclaration.exp.parse(content) func_name = exp_result['func_name'].strip() expressions.validate_symbol_name(func_name) args = exp_result['args'].strip() args = map(str.strip, args.split(',')) for arg in args: expressions.validate_variable_name(arg) func_block, end_line = blocks.parse_lines( raw_lines, current_line + 1, end_condition=lambda line: line == 'EndFunc') return FunctionDeclaration(func_name, args, func_block), end_line + 1
class DirectiveFlag(BaseDirective): possible_keywords = ['#'] exp = strparse.compile('#{flag_name}') starts_with = True def __init__(self, flag_name): self.flag_name = flag_name def __str__(self): return "#{flag_name}".format(flag_name=self.flag_name) @classmethod def parse(cls, lines, current_line): line = lines[current_line] exp_result = DirectiveFlag.exp.parse(line.content) if exp_result is None: raise SyntaxError flag_name = exp_result['flag_name'] return DirectiveFlag(flag_name), current_line + 1
class OnAutoItStartRegisterDirective(BaseDirective): possible_keywords = ['#OnAutoItStartRegister'] exp = strparse.compile('#OnAutoItStartRegister "{function_name:1}"') def __init__(self, function_name): self.function_name = function_name def __str__(self): return '#OnAutoItStartRegister "{function_name}"'.format( function_name=self.function_name) @classmethod def parse(cls, raw_lines, current_line): raw_line = raw_lines[current_line] exp_result = OnAutoItStartRegisterDirective.exp.parse(raw_line.content) if exp_result is None: raise SyntaxError("Error in {line}".format(line=str(raw_line))) function_name = exp_result['function_name'] return OnAutoItStartRegisterDirective(function_name), current_line + 1
class IfStatement(BaseDirective): if_exp = strparse.compile('If {exp} Then') elseif_exp = strparse.compile('ElseIf {exp} Then') def __init__(self, condition_blocks, else_block): self.condition_blocks = condition_blocks self.else_block = else_block def __str__(self): x = str(self.condition_blocks[0].exp) s = 'If {exp} Then\n'.format(exp=str(self.condition_blocks[0].exp)) s += str(self.condition_blocks[0].block) + '\n' for else_if in self.condition_blocks[1:]: s += 'ElseIf {exp} Then\n'.format(exp=str(else_if.exp)) s += str(else_if.block) + '\n' if self.else_block is not None: s += 'Else\n' + str(self.else_block) + '\n' s += 'EndIf' return s @classmethod def try_parse(cls, raw_lines, current_line): line = raw_lines[current_line].content if not line.startswith('If '): return NO_MATCH exp_result = IfStatement.if_exp.parse(line) if exp_result is None: raise SyntaxError("Cannot parse If line: {}".format(line)) if_expression = exp_result['exp'] condition_blocks = [] if_expression_node, _ = expressions.parse_expression(if_expression) block, current_line = blocks.parse_lines( raw_lines, current_line + 1, end_condition=cls.__end_condition) condition_blocks.append( ConditionBlock(exp=if_expression_node, block=block)) else_if_blocks, current_line = cls.__parse_else_if_blocks( raw_lines, current_line) condition_blocks += else_if_blocks if raw_lines[current_line].content == 'Else': else_block, current_line = blocks.parse_lines( raw_lines, current_line + 1, end_condition=lambda x: x == 'EndIf') else: else_block = None return IfStatement(condition_blocks=condition_blocks, else_block=else_block), current_line + 1 @classmethod def __parse_else_if_blocks(cls, raw_lines, current_line): condition_blocks = [] while current_line < len(raw_lines) and \ raw_lines[current_line].content.startswith('ElseIf '): else_if_expression = IfStatement.elseif_exp.parse( raw_lines[current_line].content) if else_if_expression is None: raise SyntaxError("Could not parse ElseIf Expression: " + str(raw_lines[current_line])) else_if_expression_node, _ = expressions.parse_expression( else_if_expression['exp']) else_if_block, current_line = blocks.parse_lines( raw_lines, current_line + 1, end_condition=cls.__end_condition) condition_blocks.append( ConditionBlock(exp=else_if_expression_node, block=else_if_block)) return condition_blocks, current_line @classmethod def __end_condition(cls, line_content): if line_content == 'Else': return True if line_content == 'EndIf': return True if line_content.startswith('ElseIf '): return True return False