コード例 #1
0
 def process_special_form_or_expression(self, tokens):
     """
     Process command special form OR a parenthesized expression.
     Command token and all args will be in the token stream.
     """
     primitives = self.primitives
     procedures = self.procedures
     command_token = tokens.popleft()
     command = command_token.lower()
     second_token = None
     if len(tokens) > 0:
         second_token = tokens.peek()
     if isinstance(second_token, str) and second_token in ('-', '+', '*', '/', '=', '<>', '>=', '<='):
         tokens.appendleft(command_token)
         return self.evaluate(tokens)
     if command in primitives:
         proc = primitives[command]
     elif command in procedures:
         proc = procedures[command]
     else:
         tokens.appendleft(command_token)
         return self.evaluate(tokens)
     args = []
     while len(tokens) > 0:
         args.append(self.evaluate(tokens))
     max_arity = proc.max_arity
     if max_arity != -1 and len(args) > max_arity:
         raise errors.LogoError("There are too many arguments for `{}`.".format(command_token))
     if len(args) < proc.min_arity:
         raise errors.LogoError("Not enough arguments for `{}`.".format(command_token))
     if self.debug_primitives and command in primitives:
         print("PRIMITIVE:", command, "ARGS:", args)
     if self.debug_procs and command in procedures:
         print("PROCEDURE:", command, "ARGS:", args)
     return self.execute_procedure(proc, args)
コード例 #2
0
 def get_variable_value(self, varname):
     """
     Get the value of the named variable from the dynamic scope.
     """
     scopes = self.scope_stack
     for scope in reversed(scopes):
         if varname in scope:
             value = scope[varname]
             if value is None:
                 raise errors.LogoError("`{}` has no value.".format(varname))
             return value
     raise errors.LogoError("No scope has a variable named `{}`.".format(varname))
コード例 #3
0
 def evaluate_value(self, tokens, quoted=False):
     """
     Evaluate the next value from the token stream.
     """
     token = tokens.peek()
     if token is None:
         raise errors.LogoError("Expected a value but instead got EOF.")
     if is_list(token):
         lst_tokens = TokenStream.make_stream(tokens.popleft())
         return self.evaluate_list(lst_tokens)
     if is_special_form(token):
         spcl_frm_tokens = TokenStream.make_stream(tokens.popleft())
         return self.process_special_form_or_expression(spcl_frm_tokens)
     if is_paren_expr(token):
         expr_tokens = TokenStream.make_stream(tokens.popleft())
         return self.evaluate(expr_tokens)
     if isinstance(token, numbers.Number):
         num = tokens.popleft()
         return num
     if not quoted:
         if token.startswith('"'):
             return tokens.popleft()[1:]
         if token.startswith(':'):
             return self.get_variable_value(tokens.popleft()[1:])
         if token.startswith("-") and token != '-':
             temp_token = tokens.popleft()
             temp_token = temp_token[1:]
             tokens.appendleft(temp_token)
             return -1 * self.evaluate(tokens)
         return self.process_command(tokens)
     else:
         return tokens.popleft()
コード例 #4
0
 def execute_procedure(self, proc, args):
     """
     Execute a procedure with args, `args`.
     """
     if proc.primitive_func:
         return proc.primitive_func(self, *args)
     tokens = TokenStream.make_stream(proc.tokens)
     scope = {}
     scope_stack = self.scope_stack
     scope_stack.append(scope) 
     formal_params = list(itertools.chain(
         [(name, None) for name in proc.required_inputs], 
         proc.optional_inputs))
     rest_args = []
     rest_input = proc.rest_input
     for vardef, value in itertools.zip_longest(formal_params, args):
         if vardef is None:
             rest_args.append(value)
         else:
             varname, default_value = vardef
             if value is None:
                 if default_value != ':' and hasattr(default_value, 'startswith') and default_value.startswith(':'):
                     name = default_value[1:]
                     for a_scope in reversed(scope_stack):
                         if name in a_scope:
                             value = a_scope[name]
                             break
                     if value is None:
                         raise errors.LogoError("Default parameter `{}` could not find `:{}` in any scope.".format(varname, name)) 
                 else:
                     value = default_value
             if value is None:
                 raise errors.LogoError("Must have a value for formal parameter `{}` in procedure `{}`.".format(varname, proc.name))
             scope[varname] = value
     if rest_input:
         scope[rest_input] = rest_args
     result = None
     try:
         self.process_commands(tokens)
     except errors.StopSignal:
         result = None 
     except errors.OutputSignal as output:
         result = output.value
     scope_stack.pop()
     return result
コード例 #5
0
 def process_command(self, tokens):
     """
     Process a command.
     """
     if self.halt:
         raise errors.HaltSignal("Received HALT")
     primitives = self.primitives
     procedures = self.procedures
     while len(tokens) > 0:
         token = tokens.popleft()  
         token = transform_qmark(token)
         is_cmd = is_command(token)
         is_spcl_frm = is_special_form(token)
         if not is_cmd and not is_spcl_frm:
             raise errors.LogoError("Expected a command.  Instead, got `{}`.".format(token))
         if is_spcl_frm:
             stream = TokenStream.make_stream(token)
             return self.process_special_form_or_expression(stream)
         else:
             command = token.lower()
             if command == 'to': 
                 procedure.process_to(self, tokens)
             elif command in primitives:
                 proc = primitives[command]
                 args = self.evaluate_args_for_command(proc.default_arity, tokens)
                 for n, arg in enumerate(args):
                     if arg is None:
                         raise errors.LogoError("Primitive `{}` received a null value for argument {}.".format(command.upper(), n+1))
                 if self.debug_primitives:
                     print("PRIMITIVE:", command, "ARGS:", args)
                 return self.execute_procedure(proc, args)
             elif command in procedures:
                 proc = procedures[command]
                 args = self.evaluate_args_for_command(proc.default_arity, tokens)
                 for n, arg in enumerate(args):
                     if arg is None:
                         raise errors.LogoError("Procedure `{}` received a null value for argument {}.".format(command.upper(), n+1))
                 if self.debug_procs:
                     print("PROCEDURE:", command, "ARGS:", args)
                 return self.execute_procedure(proc, args)
             else:
                 raise errors.LogoError("I don't know how to `{}`.".format(token))
コード例 #6
0
 def receive_input(self, data):
     """
     Handles input received from GUI.
     """
     try:
         grammar = self.grammar
         tokens = parse_tokens(grammar, data, debug=self.debug_tokens)
         result = self.process_commands(tokens)
         if result is not None:
             raise errors.LogoError("You don't say what to do with `{}`.".format(result))
     except errors.HaltSignal:
         self.halt = False
コード例 #7
0
 def load_script(self, filename):
     """
     Attempt to load a Logo script and insert its 
     contents into the curent token stream.
     """
     script_folders = self.script_folders
     for folder in script_folders:
         pth = os.path.join(folder, filename)
         if os.path.exists(pth):
             with open(pth, "r") as f:
                 data = f.read()
             return self.process_instructionlist(data)
     raise errors.LogoError("Could not locate script `{}`.".format(filename))
コード例 #8
0
def main(args):
    """
    Parse Logo
    """
    grammar = make_token_grammar()
    interpreter = LogoInterpreter.create_interpreter()
    interpreter.turtle_backend_args = dict(input_handler=interpreter.receive_input)
    if args.turtle == 'tk':
        interpreter.turtle_backend_args['maximize'] = args.maximize
        interpreter.init_turtle_graphics()
    interpreter.debug_tokens = args.debug_tokens
    interpreter.grammar = grammar
    interpreter.debug_primitives = args.debug_primitives
    interpreter.debug_procs = args.debug_procs
    script_folders = args.script_folder
    if script_folders is None:
        script_folders = []
    interpreter.script_folders = script_folders
    if args.turtle == 'svg':
        interpreter.turtle_backend = svgturtle.SVGTurtleEnv.create_turtle_env()
        svg_args = dict(
            output_file=args.outfile,
            html_folder=args.html,
        )
        html_args = {}
        d = vars(args)
        for k in ('html_title', 'animation_duration', 'animation_type'):
            v = d.get(k)
            if v is not None:
                html_args[k] = v
        if args.html_width:
            html_args['html_width'] = args.html_width
        if args.html_scale:
            html_args['html_scale'] = args.html_scale
        if args.animation_duration:
            html_args['animation_duration'] = args.animation_duration
        if args.animation_type:
            animation_type = args.animation_type
            if animation_type == 'onebyone':
                animation_type = 'oneByOne'
            html_args['animation_type'] = animation_type
        if args.animation_start:
            animation_start = args.animation_start
            html_args['animation_start'] = animation_start
        svg_args['html_args'] = html_args
        interpreter.turtle_backend_args = svg_args
    if args.file is not None:
        script = args.file.read()
        tokens = parse_tokens(grammar, script, debug=args.debug_tokens)
        if args.tokenize_only:
            return
        try:
            result = interpreter.process_commands(tokens)
        except Exception as ex:
            print("Processed tokens: {}".format(tokens.processed), file=sys.stderr)
            raise ex
        if result is not None:
            raise errors.LogoError("You don't say what to do with `{}`.".format(result))
    if interpreter.is_turtle_active():
        interpreter.turtle_backend.wait_complete()
    if args.debug_interpreter:
        print("")
        import pprint
        pprint.pprint(interpreter)