diff --git a/kibot/PcbDraw/populate.py b/kibot/PcbDraw/populate.py
index 14627d88..c1a7a154 100644
--- a/kibot/PcbDraw/populate.py
+++ b/kibot/PcbDraw/populate.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python3
# Author: Jan Mrázek
# License: MIT
@@ -21,7 +20,7 @@ try:
except ModuleNotFoundError:
InlineParser = mistune.InlineLexer
HTMLRenderer = mistune.Renderer
-import pybars # type: ignore
+from . import pybars # type: ignore
import yaml
from . import mdrenderer
diff --git a/kibot/PcbDraw/pybars/__init__.py b/kibot/PcbDraw/pybars/__init__.py
new file mode 100644
index 00000000..87500e16
--- /dev/null
+++ b/kibot/PcbDraw/pybars/__init__.py
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2012, Canonical Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, version 3 only.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+# GNU Lesser General Public License version 3 (see the file LICENSE).
+
+
+# same format as sys.version_info: "A tuple containing the five components of
+# the version number: major, minor, micro, releaselevel, and serial. All
+# values except releaselevel are integers; the release level is 'alpha',
+# 'beta', 'candidate', or 'final'. The version_info value corresponding to the
+# Python version 2.0 is (2, 0, 0, 'final', 0)." Additionally we use a
+# releaselevel of 'dev' for unreleased under-development code.
+#
+# If the releaselevel is 'alpha' then the major/minor/micro components are not
+# established at this point, and setup.py will use a version of next-$(revno).
+# If the releaselevel is 'final', then the tarball will be major.minor.micro.
+# Otherwise it is major.minor.micro~$(revno).
+
+from ._compiler import (
+ Compiler,
+ strlist,
+ Scope,
+ PybarsError
+ )
+
+__version__ = '0.9.7'
+__version_info__ = (0, 9, 7, 'final', 0)
+
+__all__ = [
+ 'Compiler',
+ 'log',
+ 'strlist',
+ 'Scope',
+ 'PybarsError'
+ ]
+
+
+def log(value):
+ return None
diff --git a/kibot/PcbDraw/pybars/_compiler.py b/kibot/PcbDraw/pybars/_compiler.py
new file mode 100644
index 00000000..103b0ebb
--- /dev/null
+++ b/kibot/PcbDraw/pybars/_compiler.py
@@ -0,0 +1,943 @@
+#
+# Copyright (c) 2015 Will Bond, Mjumbe Wawatu Ukweli, 2012 Canonical Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, version 3 only.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+# GNU Lesser General Public License version 3 (see the file LICENSE).
+
+"""The compiler for pybars."""
+
+import os
+import re
+import sys
+from types import ModuleType
+import linecache
+
+# The following code allows importing pybars from the current dir
+prev_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if sys.path[0] != prev_dir:
+ try:
+ sys.path.remove(prev_dir)
+ except ValueError:
+ pass
+ sys.path.insert(0, prev_dir)
+
+import pybars
+from pybars import _templates
+from .pymeta.grammar import OMeta
+
+__all__ = [
+ 'Compiler',
+ 'strlist',
+ 'Scope'
+ ]
+
+__metaclass__ = type
+
+
+# This allows the code to run on Python 2 and 3 by
+# creating a consistent reference for the appropriate
+# string class
+try:
+ str_class = unicode
+except NameError:
+ # Python 3 support
+ str_class = str
+
+# backward compatibility for basestring for python < 2.3
+try:
+ basestring
+except NameError:
+ basestring = str
+
+# Flag for testing
+debug = False
+
+
+# Note that unless we presume handlebars is only generating valid html, we have
+# to accept anything - so a broken template won't be all that visible - it will
+# just render literally (because the anything rule matches it).
+
+# this grammar generates a tokenised tree
+handlebars_grammar = r"""
+
+template ::= ( | )*:body => ['template'] + body
+text ::= | |
+newline_text ::= (~() ('\r'?'\n'):char) => ('newline', u'' + char)
+whitespace_text ::= (~() (' '|'\t'))+:text => ('whitespace', u''.join(text))
+other_text ::= (~() )+:text => ('literal', u''.join(text))
+other ::= :char => ('literal', u'' + char)
+templatecommand ::=
+ |
+ |
+ |
+ |
+ |
+start ::= '{' '{'
+finish ::= '}' '}'
+comment ::= '!' (~() )* => ('comment', )
+space ::= ' '|'\t'|'\r'|'\n'
+arguments ::= (+ (|||))*:arguments => arguments
+subexpression ::= '(' :p (+ (|||))*:arguments ')' => ('subexpr', p, arguments)
+expression_inner ::= :p :arguments => (p, arguments)
+expression ::= '{' :e '}' => ('expand', ) + e
+ | '&' :e => ('expand', ) + e
+escapedexpression ::= :e => ('escapedexpand', ) + e
+block_inner ::= :s :args
+ => (u''.join(s), args)
+partial_inner ::= :s :args
+ => (s, args)
+alt_inner ::= ('^' | 'e' 'l' 's' 'e')
+partial ::= '>' :i => ('partial',) + i
+path ::= ~('/') +:segments => ('path', segments)
+kwliteral ::= :s '=' (||):v => ('kwparam', s, v)
+literal ::= (||||):thing => ('literalparam', thing)
+string ::= '"' *:ls '"' => u'"' + u''.join(ls) + u'"'
+ | "'" *:ls "'" => u"'" + u''.join(ls) + u"'"
+integer ::= '-'?:sign +:ds => int((sign if sign else '') + ''.join(ds))
+boolean ::= |
+false ::= 'f' 'a' 'l' 's' 'e' => False
+true ::= 't' 'r' 'u' 'e' => True
+null ::= ('n' 'u' 'l' 'l') => None
+undefined ::= ('u' 'n' 'd' 'e' 'f' 'i' 'n' 'e' 'd') => None
+notdquote ::=
+ | '\n' => '\\n'
+ | '\r' => '\\r'
+ | '\\' => '\\\\'
+ | (~('"') )
+notsquote ::=
+ | '\n' => '\\n'
+ | '\r' => '\\r'
+ | '\\' => '\\\\'
+ | (~("'") )
+escapedquote ::= '\\' '"' => '\\"'
+ | "\\" "'" => "\\'"
+notclosebracket ::= (~(']') )
+safesymbol ::= ~ '['? (|'_'):start (|'_')+:symbol ']'? => start + u''.join(symbol)
+symbol ::= ~ '['? (|'-'|'@')+:symbol ']'? => u''.join(symbol)
+partialname ::= :s => s
+ | ~ ('['|'"')? (~(||']'|'"' ) )+:symbol (']'|'"')? => ('literalparam', '"' + u''.join(symbol) + '"')
+pathseg ::= '[' +:symbol ']' => u''.join(symbol)
+ | ('@' '.' '.' '/') => u'@@_parent'
+ |
+ | '/' => u''
+ | ('.' '.' '/') => u'@_parent'
+ | '.' => u''
+pathfinish :expected ::= '/' :found ?(found == expected)
+symbolfinish :expected ::= '/' :found ?(found == expected)
+blockrule ::= '#' :i
+ :t :alt_t => ('block',) + i + (t, alt_t)
+ | '^' :i
+ :t :alt_t => ('invertedblock',) + i + (t, alt_t)
+alttemplate ::= ( )?:alt_t => alt_t or []
+rawblockstart ::= :i => i
+rawblockfinish :expected ::=
+rawblock ::= :i (~() )*:r
+ => ('rawblock',) + i + (''.join(r),)
+"""
+
+# this grammar compiles the template to python
+compile_grammar = """
+compile ::= * => builder.finish()
+prolog ::= "template" => builder.start()
+rule ::=
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+block ::= [ "block" :symbol [*:arguments] [:t] [?:alt_t] ] => builder.add_block(symbol, arguments, t, alt_t)
+comment ::= [ "comment" ]
+literal ::= [ ( "literal" | "newline" | "whitespace" ) :value ] => builder.add_literal(value)
+expand ::= [ "expand" :value [*:arguments]] => builder.add_expand(value, arguments)
+escapedexpand ::= [ "escapedexpand" :value [*:arguments]] => builder.add_escaped_expand(value, arguments)
+invertedblock ::= [ "invertedblock" :symbol [*:arguments] [:t] [?:alt_t] ] => builder.add_invertedblock(symbol, arguments, t, alt_t)
+rawblock ::= [ "rawblock" :symbol [*:arguments] :raw ] => builder.add_rawblock(symbol, arguments, raw)
+partial ::= ["partial" :symbol [*:arguments]] => builder.add_partial(symbol, arguments)
+path ::= [ "path" [:segment]] => ("simple", segment)
+ | [ "path" [+:segments] ] => ("complex", u"resolve(context, u'" + u"', u'".join(segments) + u"')" )
+complexarg ::= [ "path" [+:segments] ] => u"resolve(context, u'" + u"', u'".join(segments) + u"')"
+ | [ "subexpr" ["path" :name] [*:arguments] ] => u'resolve_subexpr(helpers, "' + name + '", context' + (u', ' + u', '.join(arguments) if arguments else u'') + u')'
+ | [ "literalparam" :value ] => {str_class}(value)
+arg ::= [ "kwparam" :symbol :a ] => {str_class}(symbol) + '=' + a
+ |
+pathseg ::= "/" => ''
+ | "." => ''
+ | "" => ''
+ | "this" => ''
+pathseg ::= :symbol => u''.join(symbol)
+""" # noqa: E501
+compile_grammar = compile_grammar.format(str_class=str_class.__name__)
+
+
+class PybarsError(Exception):
+
+ pass
+
+
+class strlist(list):
+
+ """A quasi-list to let the template code avoid special casing."""
+
+ def __str__(self): # Python 3
+ return ''.join(self)
+
+ def __unicode__(self): # Python 2
+ return u''.join(self)
+
+ def grow(self, thing):
+ """Make the list longer, appending for unicode, extending otherwise."""
+ if type(thing) == str_class:
+ self.append(thing)
+
+ # This will only ever match in Python 2 since str_class is str in
+ # Python 3.
+ elif type(thing) == str:
+ self.append(unicode(thing)) # noqa: F821 undefined name 'unicode'
+
+ else:
+ # Recursively expand to a flat list; may deserve a C accelerator at
+ # some point.
+ for element in thing:
+ self.grow(element)
+
+
+_map = {
+ '&': '&',
+ '"': '"',
+ "'": ''',
+ '`': '`',
+ '<': '<',
+ '>': '>',
+ }
+
+
+def substitute(match, _map=_map):
+ return _map[match.group(0)]
+
+
+_escape_re = re.compile(r"&|\"|'|`|<|>")
+
+
+def escape(something, _escape_re=_escape_re, substitute=substitute):
+ return _escape_re.sub(substitute, something)
+
+
+def pick(context, name, default=None):
+ try:
+ return context[name]
+ except (KeyError, TypeError, AttributeError):
+ if isinstance(name, basestring):
+ try:
+ exists = hasattr(context, name)
+ except UnicodeEncodeError:
+ # Python 2 raises UnicodeEncodeError on non-ASCII strings
+ pass
+ else:
+ if exists:
+ return getattr(context, name)
+ if hasattr(context, 'get'):
+ return context.get(name)
+ return default
+
+
+sentinel = object()
+
+
+class Scope:
+
+ def __init__(self, context, parent, root, overrides=None, index=None, key=None, first=None, last=None):
+ self.context = context
+ self.parent = parent
+ self.root = root
+ # Must be dict of keys and values
+ self.overrides = overrides
+ self.index = index
+ self.key = key
+ self.first = first
+ self.last = last
+
+ def get(self, name, default=None):
+ if name == '@root':
+ return self.root
+ if name == '@_parent':
+ return self.parent
+ if name == '@index' and self.index is not None:
+ return self.index
+ if name == '@key' and self.key is not None:
+ return self.key
+ if name == '@first' and self.first is not None:
+ return self.first
+ if name == '@last' and self.last is not None:
+ return self.last
+ if name == 'this':
+ return self.context
+ if self.overrides and name in self.overrides:
+ return self.overrides[name]
+ return pick(self.context, name, default)
+ __getitem__ = get
+
+ def __len__(self):
+ return len(self.context)
+
+ # Added for Python 3
+ def __str__(self):
+ return str(self.context)
+
+ # Only called in Python 2
+ def __unicode__(self):
+ return unicode(self.context) # noqa: F821 undefined name 'unicode'
+
+
+def resolve(context, *segments):
+ carryover_data = False
+
+ # This makes sure that bare "this" paths don't return a Scope object
+ if segments == ('',) and isinstance(context, Scope):
+ return context.get('this')
+
+ for segment in segments:
+
+ # Handle @../index syntax by popping the extra @ along the segment path
+ if carryover_data:
+ carryover_data = False
+ segment = u'@%s' % segment
+ if len(segment) > 1 and segment[0:2] == '@@':
+ segment = segment[1:]
+ carryover_data = True
+
+ if context is None:
+ return None
+ if segment in (None, ""):
+ continue
+ if type(context) in (list, tuple):
+ if segment == 'length':
+ return len(context)
+ offset = int(segment)
+ context = context[offset]
+ elif isinstance(context, Scope):
+ context = context.get(segment)
+ else:
+ context = pick(context, segment)
+ return context
+
+
+def resolve_subexpr(helpers, name, context, *args, **kwargs):
+ if name not in helpers:
+ raise PybarsError(u"Could not find property %s" % (name,))
+ return helpers[name](context, *args, **kwargs)
+
+
+def prepare(value, should_escape):
+ """
+ Prepares a value to be added to the result
+
+ :param value:
+ The value to add to the result
+
+ :param should_escape:
+ If the string should be HTML-escaped
+
+ :return:
+ A unicode string or strlist
+ """
+
+ if value is None:
+ return u''
+ type_ = type(value)
+ if type_ is not strlist:
+ if type_ is not str_class:
+ if type_ is bool:
+ value = u'true' if value else u'false'
+ else:
+ value = str_class(value)
+ if should_escape:
+ value = escape(value)
+ return value
+
+
+def ensure_scope(context, root):
+ return context if isinstance(context, Scope) else Scope(context, context, root)
+
+
+def _each(this, options, context):
+ result = strlist()
+
+ # All sequences in python have a length
+ try:
+ last_index = len(context) - 1
+
+ # If there are no items, we want to trigger the else clause
+ if last_index < 0:
+ raise IndexError()
+
+ except (TypeError, IndexError):
+ return options['inverse'](this)
+
+ # We use the presence of a keys method to determine if the
+ # key attribute should be passed to the block handler
+ has_keys = hasattr(context, 'keys')
+
+ index = 0
+ for value in context:
+ kwargs = {
+ 'index': index,
+ 'first': index == 0,
+ 'last': index == last_index
+ }
+
+ if has_keys:
+ kwargs['key'] = value
+ value = context[value]
+
+ scope = Scope(value, this, options['root'], **kwargs)
+
+ # Necessary because of cases such as {{^each things}}test{{/each}}.
+ try:
+ result.grow(options['fn'](scope))
+ except TypeError:
+ pass
+ index += 1
+
+ return result
+
+
+def _if(this, options, context):
+ if hasattr(context, '__call__'):
+ context = context(this)
+ if context:
+ return options['fn'](this)
+ else:
+ return options['inverse'](this)
+
+
+def _log(this, context):
+ pybars.log(context)
+
+
+def _unless(this, options, context):
+ if not context:
+ return options['fn'](this)
+
+
+def _lookup(this, context, key):
+ try:
+ return context[key]
+ except (KeyError, IndexError, TypeError):
+ return
+
+
+def _blockHelperMissing(this, options, context):
+ if hasattr(context, '__call__'):
+ context = context(this)
+ if context != u"" and not context:
+ return options['inverse'](this)
+ if type(context) in (list, strlist, tuple):
+ return _each(this, options, context)
+ if context is True:
+ callwith = this
+ else:
+ callwith = context
+ return options['fn'](callwith)
+
+
+def _helperMissing(scope, name, *args):
+ if not args:
+ return None
+ raise PybarsError(u"Could not find property %s" % (name,))
+
+
+def _with(this, options, context):
+ return options['fn'](context)
+
+
+# scope for the compiled code to reuse globals
+_pybars_ = {
+ 'helpers': {
+ 'blockHelperMissing': _blockHelperMissing,
+ 'each': _each,
+ 'if': _if,
+ 'helperMissing': _helperMissing,
+ 'log': _log,
+ 'unless': _unless,
+ 'with': _with,
+ 'lookup': _lookup,
+ },
+}
+
+
+class FunctionContainer:
+
+ """
+ Used as a container for functions by the CodeBuidler
+ """
+
+ def __init__(self, name, code):
+ self.name = name
+ self.code = code
+
+ @property
+ def full_code(self):
+ headers = (
+ u'import pybars\n'
+ u'\n'
+ u'if pybars.__version__ != %s:\n'
+ u' raise pybars.PybarsError("This template was precompiled with pybars3 version %s, running version %%s" %% pybars.__version__)\n'
+ u'\n'
+ u'from pybars import strlist, Scope, PybarsError\n'
+ u'from pybars._compiler import _pybars_, escape, resolve, resolve_subexpr, prepare, ensure_scope\n'
+ u'\n'
+ u'from functools import partial\n'
+ u'\n'
+ u'\n'
+ ) % (repr(pybars.__version__), pybars.__version__)
+
+ return headers + self.code
+
+
+class CodeBuilder:
+
+ """Builds code for a template."""
+
+ def __init__(self):
+ self._reset()
+
+ def _reset(self):
+ self.stack = []
+ self.var_counter = 1
+ self.render_counter = 0
+
+ def start(self):
+ function_name = 'render' if self.render_counter == 0 else 'block_%s' % self.render_counter
+ self.render_counter += 1
+
+ self.stack.append((strlist(), {}, function_name))
+ self._result, self._locals, _ = self.stack[-1]
+ # Context may be a user hash or a Scope (which injects '@_parent' to
+ # implement .. lookups). The JS implementation uses a vector of scopes
+ # and then interprets a linear walk-up, which is why there is a
+ # disabled test showing arbitrary complex path manipulation: the scope
+ # approach used here will probably DTRT but may be slower: reevaluate
+ # when profiling.
+ if len(self.stack) == 1:
+ self._result.grow([
+ u"def render(context, helpers=None, partials=None, root=None):\n"
+ u" _helpers = dict(_pybars_['helpers'])\n"
+ u" if helpers is not None:\n"
+ u" _helpers.update(helpers)\n"
+ u" helpers = _helpers\n"
+ u" if partials is None:\n"
+ u" partials = {}\n"
+ u" called = root is None\n"
+ u" if called:\n"
+ u" root = context\n"
+ ])
+ else:
+ self._result.grow(u"def %s(context, helpers, partials, root):\n" % function_name)
+ self._result.grow(u" result = strlist()\n")
+ self._result.grow(u" context = ensure_scope(context, root)\n")
+
+ def finish(self):
+ lines, ns, function_name = self.stack.pop(-1)
+
+ # Ensure the result is a string and not a strlist
+ if len(self.stack) == 0:
+ self._result.grow(u" if called:\n")
+ self._result.grow(u" result = %s(result)\n" % str_class.__name__)
+ self._result.grow(u" return result\n")
+
+ source = str_class(u"".join(lines))
+
+ self._result = self.stack and self.stack[-1][0]
+ self._locals = self.stack and self.stack[-1][1]
+
+ code = ''
+ for key in ns:
+ if isinstance(ns[key], FunctionContainer):
+ code += ns[key].code + '\n'
+ else:
+ code += '%s = %s\n' % (key, repr(ns[key]))
+ code += source
+
+ result = FunctionContainer(function_name, code)
+ if debug and len(self.stack) == 0:
+ print('Compiled Python')
+ print('---------------')
+ print(result.full_code)
+
+ return result
+
+ def _wrap_nested(self, name):
+ return u"partial(%s, helpers=helpers, partials=partials, root=root)" % name
+
+ def add_block(self, symbol, arguments, nested, alt_nested):
+ name = nested.name
+ self._locals[name] = nested
+
+ if alt_nested:
+ alt_name = alt_nested.name
+ self._locals[alt_name] = alt_nested
+
+ call = self.arguments_to_call(arguments)
+ self._result.grow([
+ u" options = {'fn': %s}\n" % self._wrap_nested(name),
+ u" options['helpers'] = helpers\n"
+ u" options['partials'] = partials\n"
+ u" options['root'] = root\n"
+ ])
+ if alt_nested:
+ self._result.grow([
+ u" options['inverse'] = ",
+ self._wrap_nested(alt_name),
+ u"\n"
+ ])
+ else:
+ self._result.grow([
+ u" options['inverse'] = lambda this: None\n"
+ ])
+ self._result.grow([
+ u" value = helper = helpers.get(u'%s')\n" % symbol,
+ u" if value is None:\n"
+ u" value = resolve(context, u'%s')\n" % symbol,
+ u" if helper and hasattr(helper, '__call__'):\n"
+ u" value = helper(context, options%s\n" % call,
+ u" else:\n"
+ u" value = helpers['blockHelperMissing'](context, options, value)\n"
+ u" result.grow(value or '')\n"
+ ])
+
+ def add_literal(self, value):
+ self._result.grow(u" result.append(%s)\n" % repr(value))
+
+ def _lookup_arg(self, arg):
+ if not arg:
+ return u"context"
+ return arg
+
+ def arguments_to_call(self, arguments):
+ params = list(map(self._lookup_arg, arguments))
+ output = u', '.join(params) + u')'
+ if len(params) > 0:
+ output = u', ' + output
+ return output
+
+ def find_lookup(self, path, path_type, call):
+ if path_type == "simple": # simple names can reference helpers.
+ # TODO: compile this whole expression in the grammar; for now,
+ # fugly but only a compile time overhead.
+ # XXX: just rm.
+ realname = path.replace('.get("', '').replace('")', '')
+ self._result.grow([
+ u" value = helpers.get(u'%s')\n" % realname,
+ u" if value is None:\n"
+ u" value = resolve(context, u'%s')\n" % path,
+ ])
+ else:
+ realname = None
+ self._result.grow(u" value = %s\n" % path)
+ self._result.grow([
+ u" if hasattr(value, '__call__'):\n"
+ u" value = value(context%s\n" % call,
+ ])
+ if realname:
+ self._result.grow(
+ u" elif value is None:\n"
+ u" value = helpers['helperMissing'](context, u'%s'%s\n"
+ % (realname, call)
+ )
+
+ def add_escaped_expand(self, path_type_path, arguments):
+ (path_type, path) = path_type_path
+ call = self.arguments_to_call(arguments)
+ self.find_lookup(path, path_type, call)
+ self._result.grow([
+ u" result.grow(prepare(value, True))\n"
+ ])
+
+ def add_expand(self, path_type_path, arguments):
+ (path_type, path) = path_type_path
+ call = self.arguments_to_call(arguments)
+ self.find_lookup(path, path_type, call)
+ self._result.grow([
+ u" result.grow(prepare(value, False))\n"
+ ])
+
+ def _debug(self):
+ self._result.grow(u" import pdb;pdb.set_trace()\n")
+
+ def add_invertedblock(self, symbol, arguments, nested, alt_nested):
+ name = nested.name
+ self._locals[name] = nested
+
+ if alt_nested:
+ alt_name = alt_nested.name
+ self._locals[alt_name] = alt_nested
+
+ call = self.arguments_to_call(arguments)
+ self._result.grow([
+ u" options = {'inverse': %s}\n" % self._wrap_nested(name),
+ u" options['helpers'] = helpers\n"
+ u" options['partials'] = partials\n"
+ u" options['root'] = root\n"
+ ])
+ if alt_nested:
+ self._result.grow([
+ u" options['fn'] = ",
+ self._wrap_nested(alt_name),
+ u"\n"
+ ])
+ else:
+ self._result.grow([
+ u" options['fn'] = lambda this: None\n"
+ ])
+ self._result.grow([
+ u" value = helper = helpers.get(u'%s')\n" % symbol,
+ u" if value is None:\n"
+ u" value = resolve(context, u'%s')\n" % symbol,
+ u" if helper and hasattr(helper, '__call__'):\n"
+ u" value = helper(context, options%s\n" % call,
+ u" else:\n"
+ u" value = helpers['blockHelperMissing'](context, options, value)\n"
+ u" result.grow(value or '')\n"
+ ])
+
+ def add_rawblock(self, symbol, arguments, raw):
+ call = self.arguments_to_call(arguments)
+ self._result.grow([
+ u" options = {'fn': lambda this: %s}\n" % repr(raw),
+ u" options['helpers'] = helpers\n"
+ u" options['partials'] = partials\n"
+ u" options['root'] = root\n"
+ u" options['inverse'] = lambda this: None\n"
+ u" helper = helpers.get(u'%s')\n" % symbol,
+ u" if helper and hasattr(helper, '__call__'):\n"
+ u" value = helper(context, options%s\n" % call,
+ u" else:\n"
+ u" value = %s\n" % repr(raw),
+ u" result.grow(value or '')\n"
+ ])
+
+ def _invoke_template(self, fn_name, this_name):
+ self._result.grow([
+ u" result.grow(",
+ fn_name,
+ u"(",
+ this_name,
+ u", helpers=helpers, partials=partials, root=root))\n"
+ ])
+
+ def add_partial(self, symbol, arguments):
+ arg = ""
+
+ overrides = None
+ positional_args = 0
+ if arguments:
+ for argument in arguments:
+ kwmatch = re.match(r'(\w+)=(.+)$', argument)
+ if kwmatch:
+ if not overrides:
+ overrides = {}
+ overrides[kwmatch.group(1)] = kwmatch.group(2)
+ else:
+ if positional_args != 0:
+ raise PybarsError("An extra positional argument was passed to a partial")
+ positional_args += 1
+ arg = argument
+
+ overrides_literal = 'None'
+ if overrides:
+ overrides_literal = u'{'
+ for key in overrides:
+ overrides_literal += u'"%s": %s, ' % (key, overrides[key])
+ overrides_literal += u'}'
+ self._result.grow([u" overrides = %s\n" % overrides_literal])
+
+ self._result.grow([
+ u" partialName = %s\n" % symbol,
+ u" if partialName not in partials:\n",
+ u" raise PybarsError('The partial %s could not be found' % partialName)\n",
+ u" inner = partials[partialName]\n",
+ u" scope = Scope(%s, context, root, overrides=overrides)\n" % self._lookup_arg(arg)])
+ self._invoke_template("inner", "scope")
+
+
+class Compiler:
+
+ """A handlebars template compiler.
+
+ The compiler is not threadsafe: you need one per thread because of the
+ state in CodeBuilder.
+ """
+
+ _handlebars = OMeta.makeGrammar(handlebars_grammar, {}, 'handlebars')
+ _builder = CodeBuilder()
+ _compiler = OMeta.makeGrammar(compile_grammar, {'builder': _builder})
+
+ def __init__(self):
+ self._helpers = {}
+ self.template_counter = 1
+
+ def _extract_word(self, source, position):
+ """
+ Extracts the word that falls at or around a specific position
+
+ :param source:
+ The template source as a unicode string
+ :param position:
+ The position where the word falls
+
+ :return:
+ The word
+ """
+ boundry = re.search(r'{{|{|\s|$', source[:position][::-1])
+ start_offset = boundry.end() if boundry.group(0).startswith('{') else boundry.start()
+
+ boundry = re.search(r'}}|}|\s|$', source[position:])
+ end_offset = boundry.end() if boundry.group(0).startswith('}') else boundry.start()
+
+ return source[position - start_offset:position + end_offset]
+
+ def _generate_code(self, source):
+ """
+ Common compilation code shared between precompile() and compile()
+
+ :param source:
+ The template source as a unicode string
+
+ :return:
+ A tuple of (function, source_code)
+ """
+
+ if not isinstance(source, str_class):
+ raise PybarsError("Template source must be a unicode string")
+
+ source = self.whitespace_control(source)
+
+ tree, (position, _) = self._handlebars(source).apply('template')
+
+ if debug:
+ print('\nAST')
+ print('---')
+ print(tree)
+ print('')
+
+ if position < len(source):
+ line_num = source.count('\n') + 1
+ beginning_of_line = source.rfind('\n', 0, position)
+ if beginning_of_line == -1:
+ char_num = position
+ else:
+ char_num = position - beginning_of_line
+ word = self._extract_word(source, position)
+ raise PybarsError("Error at character %s of line %s near %s" % (char_num, line_num, word))
+
+ # Ensure the builder is in a clean state - kinda gross
+ self._compiler.globals['builder']._reset()
+
+ output = self._compiler(tree).apply('compile')[0]
+ return output
+
+ def whitespace_control(self, source):
+ """
+ Preprocess source to handle whitespace control and remove extra block
+ whitespaces.
+
+ :param source:
+ The template source as a unicode string
+ :return:
+ The processed template source as a unicode string
+ """
+ cleanup_sub = re.compile(
+ # Clean-up whitespace control marks and spaces between blocks tags
+ r'(?<={{)~|~(?=}})|(?<=}})[ \t]+(?={{)').sub
+
+ return re.sub(
+ # Whitespace control using "~" mark
+ r'~}}\s*|\s*{{~|'
+
+ # Whitespace around alone blocks tags that in a line
+ r'(?<=\n)([ \t]*{{(#[^{}]+|/[^{}]+|![^{}]+|else|else if [^{}]+)}}[ \t]*)+\r?\n|'
+
+ # Whitespace aroud alone blocks tag on the first line
+ r'^([ \t]*{{(#[^{}]+|![^{}]+)}}[ \t]*)+\r?\n|'
+
+ # Whitespace aroud alone blocks tag on the last line
+ r'\r?\n([ \t]*{{(/[^{}]+|![^{}]+)}}[ \t]*)+$',
+ lambda match: cleanup_sub('', match.group(0).strip()), source)
+
+ def precompile(self, source):
+ """
+ Generates python source code that can be saved to a file for caching
+
+ :param source:
+ The template to generate source for - should be a unicode string
+
+ :return:
+ Python code as a unicode string
+ """
+
+ return self._generate_code(source).full_code
+
+ def compile(self, source, path=None):
+ """Compile source to a ready to run template.
+
+ :param source:
+ The template to compile - should be a unicode string
+
+ :return:
+ A template function ready to execute
+ """
+
+ container = self._generate_code(source)
+
+ def make_module_name(name, suffix=None):
+ output = 'pybars._templates.%s' % name
+ if suffix:
+ output += '_%s' % suffix
+ return output
+
+ if not path:
+ path = '_template'
+ generate_name = True
+ else:
+ path = path.replace('\\', '/')
+ path = path.replace('/', '_')
+ mod_name = make_module_name(path)
+ generate_name = mod_name in sys.modules
+
+ if generate_name:
+ mod_name = make_module_name(path, self.template_counter)
+ while mod_name in sys.modules:
+ self.template_counter += 1
+ mod_name = make_module_name(path, self.template_counter)
+
+ mod = ModuleType(mod_name)
+ filename = '%s.py' % mod_name.replace('pybars.', '').replace('.', '/')
+ exec(compile(container.full_code, filename, 'exec', dont_inherit=True), mod.__dict__)
+ sys.modules[mod_name] = mod
+ linecache.getlines(filename, mod.__dict__)
+
+ return mod.__dict__[container.name]
+
+ def template(self, code):
+ def _render(context, helpers=None, partials=None, root=None):
+ ns = {
+ 'context': context,
+ 'helpers': helpers,
+ 'partials': partials,
+ 'root': root
+ }
+ exec(code + '\nresult = render(context, helpers=helpers, partials=partials, root=root)', ns)
+ return ns['result']
+ return _render
diff --git a/kibot/PcbDraw/pybars/_templates/__init__.py b/kibot/PcbDraw/pybars/_templates/__init__.py
new file mode 100644
index 00000000..05dd1cf3
--- /dev/null
+++ b/kibot/PcbDraw/pybars/_templates/__init__.py
@@ -0,0 +1 @@
+# This exists to create the pybars._templates module for in-memory templates
diff --git a/kibot/PcbDraw/pybars/pymeta/LICENSE b/kibot/PcbDraw/pybars/pymeta/LICENSE
new file mode 100644
index 00000000..43f52b27
--- /dev/null
+++ b/kibot/PcbDraw/pybars/pymeta/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2008-2010
+Allen Short
+Waldemar Kornewald
+
+Soli Deo Gloria.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/kibot/PcbDraw/pybars/pymeta/__init__.py b/kibot/PcbDraw/pybars/pymeta/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/kibot/PcbDraw/pybars/pymeta/boot.py b/kibot/PcbDraw/pybars/pymeta/boot.py
new file mode 100644
index 00000000..02b0fa9d
--- /dev/null
+++ b/kibot/PcbDraw/pybars/pymeta/boot.py
@@ -0,0 +1,732 @@
+# -*- test-case-name: pymeta.test.test_grammar -*-
+"""
+The definition of PyMeta's language is itself a PyMeta grammar, but something
+has to be able to read that. Most of the code in this module is generated from
+that grammar (in future versions, it will hopefully all be generated).
+"""
+import string
+from .runtime import OMetaBase, ParseError, EOFError, expected
+
+
+class BootOMetaGrammar(OMetaBase):
+ """
+ The bootstrap grammar, generated from L{pymeta.grammar.OMetaGrammar} via
+ L{pymeta.builder.PythonBuilder}.
+ """
+ globals = globals()
+
+ def __init__(self, input):
+ OMetaBase.__init__(self, input)
+ self._ruleNames = []
+
+
+ def parseGrammar(self, name, builder, *args):
+ """
+ Entry point for converting a grammar to code (of some variety).
+
+ @param name: The name for this grammar.
+
+ @param builder: A class that implements the grammar-building interface
+ (interface to be explicitly defined later)
+ """
+ self.builder = builder(name, self, *args)
+ res, err = self.apply("grammar")
+ try:
+ x = self.input.head()
+ except EOFError:
+ pass
+ else:
+ raise err
+ return res
+
+
+ def applicationArgs(self):
+ args = []
+ while True:
+ try:
+ (arg, endchar), err = self.pythonExpr(" >")
+ if not arg:
+ break
+ args.append(self.builder.expr(arg))
+ if endchar == '>':
+ break
+ except ParseError:
+ break
+ if args:
+ return args
+ else:
+ raise ParseError(self.input.position, expected("python expression"))
+
+
+ def ruleValueExpr(self):
+ (expr, endchar), err = self.pythonExpr(endChars="\r\n)]")
+ if str(endchar) in ")]":
+ self.input = self.input.prev()
+ return self.builder.expr(expr)
+
+
+ def semanticActionExpr(self):
+ return self.builder.action(self.pythonExpr(')')[0][0])
+
+
+ def semanticPredicateExpr(self):
+ expr = self.builder.expr(self.pythonExpr(')')[0][0])
+ return self.builder.pred(expr)
+
+
+ def eatWhitespace(self):
+ """
+ Consume input until a non-whitespace character is reached.
+ """
+ consumingComment = False
+ e = None
+ while True:
+ try:
+ c, e = self.input.head()
+ except EOFError:
+ break
+ t = self.input.tail()
+ if c.isspace() or consumingComment:
+ self.input = t
+ if c == '\n':
+ consumingComment = False
+ elif c == '#':
+ consumingComment = True
+ else:
+ break
+ return True, e
+ rule_spaces = eatWhitespace
+
+
+ def rule_number(self):
+ _locals = {'self': self}
+ self.locals['number'] = _locals
+ _G_apply_1, lastError = self._apply(self.rule_spaces, "spaces", [])
+ self.considerError(lastError)
+ def _G_or_2():
+ _G_exactly_1, lastError = self.exactly('-')
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_barenumber, "barenumber", [])
+ self.considerError(lastError)
+ _locals['x'] = _G_apply_2
+ _G_python_3, lastError = eval('self.builder.exactly(-x)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+ def _G_or_3():
+ _G_apply_1, lastError = self._apply(self.rule_barenumber, "barenumber", [])
+ self.considerError(lastError)
+ _locals['x'] = _G_apply_1
+ _G_python_2, lastError = eval('self.builder.exactly(x)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ _G_or_4, lastError = self._or([_G_or_2, _G_or_3])
+ self.considerError(lastError)
+ return (_G_or_4, self.currentError)
+
+
+ def rule_barenumber(self):
+ _locals = {'self': self}
+ self.locals['barenumber'] = _locals
+ def _G_or_1():
+ _G_exactly_1, lastError = self.exactly('0')
+ self.considerError(lastError)
+ def _G_or_2():
+ def _G_or_1():
+ _G_exactly_1, lastError = self.exactly('x')
+ self.considerError(lastError)
+ return (_G_exactly_1, self.currentError)
+ def _G_or_2():
+ _G_exactly_1, lastError = self.exactly('X')
+ self.considerError(lastError)
+ return (_G_exactly_1, self.currentError)
+ _G_or_3, lastError = self._or([_G_or_1, _G_or_2])
+ self.considerError(lastError)
+ def _G_many_4():
+ _G_apply_1, lastError = self._apply(self.rule_hexdigit, "hexdigit", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ _G_many_5, lastError = self.many(_G_many_4)
+ self.considerError(lastError)
+ _locals['hs'] = _G_many_5
+ _G_python_6, lastError = eval("int(''.join(hs), 16)", self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_6, self.currentError)
+ def _G_or_3():
+ def _G_many_1():
+ _G_apply_1, lastError = self._apply(self.rule_octaldigit, "octaldigit", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ _G_many_2, lastError = self.many(_G_many_1)
+ self.considerError(lastError)
+ _locals['ds'] = _G_many_2
+ _G_python_3, lastError = eval("int('0'+''.join(ds), 8)", self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+ _G_or_4, lastError = self._or([_G_or_2, _G_or_3])
+ self.considerError(lastError)
+ return (_G_or_4, self.currentError)
+ def _G_or_2():
+ def _G_many1_1():
+ _G_apply_1, lastError = self._apply(self.rule_digit, "digit", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ _G_many1_2, lastError = self.many(_G_many1_1, _G_many1_1())
+ self.considerError(lastError)
+ _locals['ds'] = _G_many1_2
+ _G_python_3, lastError = eval("int(''.join(ds))", self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+ _G_or_3, lastError = self._or([_G_or_1, _G_or_2])
+ self.considerError(lastError)
+ return (_G_or_3, self.currentError)
+
+
+ def rule_octaldigit(self):
+ _locals = {'self': self}
+ self.locals['octaldigit'] = _locals
+ _G_apply_1, lastError = self._apply(self.rule_anything, "anything", [])
+ self.considerError(lastError)
+ _locals['x'] = _G_apply_1
+ def _G_pred_2():
+ _G_python_1, lastError = eval('x in string.octdigits', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_1, self.currentError)
+ _G_pred_3, lastError = self.pred(_G_pred_2)
+ self.considerError(lastError)
+ _G_python_4, lastError = eval('x', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_4, self.currentError)
+
+
+ def rule_hexdigit(self):
+ _locals = {'self': self}
+ self.locals['hexdigit'] = _locals
+ _G_apply_1, lastError = self._apply(self.rule_anything, "anything", [])
+ self.considerError(lastError)
+ _locals['x'] = _G_apply_1
+ def _G_pred_2():
+ _G_python_1, lastError = eval('x in string.hexdigits', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_1, self.currentError)
+ _G_pred_3, lastError = self.pred(_G_pred_2)
+ self.considerError(lastError)
+ _G_python_4, lastError = eval('x', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_4, self.currentError)
+
+
+ def rule_escapedChar(self):
+ _locals = {'self': self}
+ self.locals['escapedChar'] = _locals
+ _G_exactly_1, lastError = self.exactly('\\')
+ self.considerError(lastError)
+ def _G_or_2():
+ _G_exactly_1, lastError = self.exactly('n')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('"\\n"', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_3():
+ _G_exactly_1, lastError = self.exactly('r')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('"\\r"', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_4():
+ _G_exactly_1, lastError = self.exactly('t')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('"\\t"', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_5():
+ _G_exactly_1, lastError = self.exactly('b')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('"\\b"', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_6():
+ _G_exactly_1, lastError = self.exactly('f')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('"\\f"', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_7():
+ _G_exactly_1, lastError = self.exactly('"')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('\'"\'', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_8():
+ _G_exactly_1, lastError = self.exactly("'")
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('"\'"', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_9():
+ _G_exactly_1, lastError = self.exactly('\\')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('"\\\\"', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ _G_or_10, lastError = self._or([_G_or_2, _G_or_3, _G_or_4, _G_or_5, _G_or_6, _G_or_7, _G_or_8, _G_or_9])
+ self.considerError(lastError)
+ return (_G_or_10, self.currentError)
+
+
+ def rule_character(self):
+ _locals = {'self': self}
+ self.locals['character'] = _locals
+ _G_python_1, lastError = eval('"\'"', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ def _G_or_3():
+ _G_apply_1, lastError = self._apply(self.rule_escapedChar, "escapedChar", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_4():
+ _G_apply_1, lastError = self._apply(self.rule_anything, "anything", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ _G_or_5, lastError = self._or([_G_or_3, _G_or_4])
+ self.considerError(lastError)
+ _locals['c'] = _G_or_5
+ _G_python_6, lastError = eval('"\'"', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_7, lastError = self._apply(self.rule_token, "token", [_G_python_6])
+ self.considerError(lastError)
+ _G_python_8, lastError = eval('self.builder.exactly(c)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_8, self.currentError)
+
+
+ def rule_string(self):
+ _locals = {'self': self}
+ self.locals['string'] = _locals
+ _G_python_1, lastError = eval('\'"\'', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ def _G_many_3():
+ def _G_or_1():
+ _G_apply_1, lastError = self._apply(self.rule_escapedChar, "escapedChar", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_2():
+ def _G_not_1():
+ _G_exactly_1, lastError = self.exactly('"')
+ self.considerError(lastError)
+ return (_G_exactly_1, self.currentError)
+ _G_not_2, lastError = self._not(_G_not_1)
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_anything, "anything", [])
+ self.considerError(lastError)
+ return (_G_apply_3, self.currentError)
+ _G_or_3, lastError = self._or([_G_or_1, _G_or_2])
+ self.considerError(lastError)
+ return (_G_or_3, self.currentError)
+ _G_many_4, lastError = self.many(_G_many_3)
+ self.considerError(lastError)
+ _locals['c'] = _G_many_4
+ _G_python_5, lastError = eval('\'"\'', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_6, lastError = self._apply(self.rule_token, "token", [_G_python_5])
+ self.considerError(lastError)
+ _G_python_7, lastError = eval("self.builder.exactly(''.join(c))", self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_7, self.currentError)
+
+
+ def rule_name(self):
+ _locals = {'self': self}
+ self.locals['name'] = _locals
+ _G_apply_1, lastError = self._apply(self.rule_letter, "letter", [])
+ self.considerError(lastError)
+ _locals['x'] = _G_apply_1
+ def _G_many_2():
+ _G_apply_1, lastError = self._apply(self.rule_letterOrDigit, "letterOrDigit", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ _G_many_3, lastError = self.many(_G_many_2)
+ self.considerError(lastError)
+ _locals['xs'] = _G_many_3
+ _G_python_4, lastError = eval('xs.insert(0, x)', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_python_5, lastError = eval("''.join(xs)", self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_5, self.currentError)
+
+
+ def rule_application(self):
+ _locals = {'self': self}
+ self.locals['application'] = _locals
+ _G_python_1, lastError = eval("'<'", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_spaces, "spaces", [])
+ self.considerError(lastError)
+ _G_apply_4, lastError = self._apply(self.rule_name, "name", [])
+ self.considerError(lastError)
+ _locals['name'] = _G_apply_4
+ def _G_or_5():
+ _G_exactly_1, lastError = self.exactly(' ')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('self.applicationArgs()', self.globals, _locals), None
+ self.considerError(lastError)
+ _locals['args'] = _G_python_2
+ _G_python_3, lastError = eval('self.builder.apply(name, self.name, *args)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+ def _G_or_6():
+ _G_python_1, lastError = eval("'>'", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_python_3, lastError = eval('self.builder.apply(name, self.name)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+ _G_or_7, lastError = self._or([_G_or_5, _G_or_6])
+ self.considerError(lastError)
+ return (_G_or_7, self.currentError)
+
+
+ def rule_expr1(self):
+ _locals = {'self': self}
+ self.locals['expr1'] = _locals
+ def _G_or_1():
+ _G_apply_1, lastError = self._apply(self.rule_application, "application", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_2():
+ _G_apply_1, lastError = self._apply(self.rule_ruleValue, "ruleValue", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_3():
+ _G_apply_1, lastError = self._apply(self.rule_semanticPredicate, "semanticPredicate", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_4():
+ _G_apply_1, lastError = self._apply(self.rule_semanticAction, "semanticAction", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_5():
+ _G_apply_1, lastError = self._apply(self.rule_number, "number", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_6():
+ _G_apply_1, lastError = self._apply(self.rule_character, "character", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_7():
+ _G_apply_1, lastError = self._apply(self.rule_string, "string", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ def _G_or_8():
+ _G_python_1, lastError = eval("'('", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_expr, "expr", [])
+ self.considerError(lastError)
+ _locals['e'] = _G_apply_3
+ _G_python_4, lastError = eval("')'", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_5, lastError = self._apply(self.rule_token, "token", [_G_python_4])
+ self.considerError(lastError)
+ _G_python_6, lastError = eval('e', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_6, self.currentError)
+ def _G_or_9():
+ _G_python_1, lastError = eval("'['", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_expr, "expr", [])
+ self.considerError(lastError)
+ _locals['e'] = _G_apply_3
+ _G_python_4, lastError = eval("']'", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_5, lastError = self._apply(self.rule_token, "token", [_G_python_4])
+ self.considerError(lastError)
+ _G_python_6, lastError = eval('self.builder.listpattern(e)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_6, self.currentError)
+ _G_or_10, lastError = self._or([_G_or_1, _G_or_2, _G_or_3, _G_or_4, _G_or_5, _G_or_6, _G_or_7, _G_or_8, _G_or_9])
+ self.considerError(lastError)
+ return (_G_or_10, self.currentError)
+
+
+ def rule_expr2(self):
+ _locals = {'self': self}
+ self.locals['expr2'] = _locals
+ def _G_or_1():
+ _G_python_1, lastError = eval("'~'", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ def _G_or_3():
+ _G_python_1, lastError = eval("'~'", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_expr2, "expr2", [])
+ self.considerError(lastError)
+ _locals['e'] = _G_apply_3
+ _G_python_4, lastError = eval('self.builder.lookahead(e)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_4, self.currentError)
+ def _G_or_4():
+ _G_apply_1, lastError = self._apply(self.rule_expr2, "expr2", [])
+ self.considerError(lastError)
+ _locals['e'] = _G_apply_1
+ _G_python_2, lastError = eval('self.builder._not(e)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ _G_or_5, lastError = self._or([_G_or_3, _G_or_4])
+ self.considerError(lastError)
+ return (_G_or_5, self.currentError)
+ def _G_or_2():
+ _G_apply_1, lastError = self._apply(self.rule_expr1, "expr1", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ _G_or_3, lastError = self._or([_G_or_1, _G_or_2])
+ self.considerError(lastError)
+ return (_G_or_3, self.currentError)
+
+
+ def rule_expr3(self):
+ _locals = {'self': self}
+ self.locals['expr3'] = _locals
+ def _G_or_1():
+ _G_apply_1, lastError = self._apply(self.rule_expr2, "expr2", [])
+ self.considerError(lastError)
+ _locals['e'] = _G_apply_1
+ def _G_or_2():
+ _G_exactly_1, lastError = self.exactly('*')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('self.builder.many(e)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_3():
+ _G_exactly_1, lastError = self.exactly('+')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('self.builder.many1(e)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_4():
+ _G_exactly_1, lastError = self.exactly('?')
+ self.considerError(lastError)
+ _G_python_2, lastError = eval('self.builder.optional(e)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_2, self.currentError)
+ def _G_or_5():
+ _G_python_1, lastError = eval('e', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_1, self.currentError)
+ _G_or_6, lastError = self._or([_G_or_2, _G_or_3, _G_or_4, _G_or_5])
+ self.considerError(lastError)
+ _locals['r'] = _G_or_6
+ def _G_or_7():
+ _G_exactly_1, lastError = self.exactly(':')
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_name, "name", [])
+ self.considerError(lastError)
+ _locals['n'] = _G_apply_2
+ _G_python_3, lastError = eval('self.builder.bind(r, n)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+ def _G_or_8():
+ _G_python_1, lastError = eval('r', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_1, self.currentError)
+ _G_or_9, lastError = self._or([_G_or_7, _G_or_8])
+ self.considerError(lastError)
+ return (_G_or_9, self.currentError)
+ def _G_or_2():
+ _G_python_1, lastError = eval("':'", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_name, "name", [])
+ self.considerError(lastError)
+ _locals['n'] = _G_apply_3
+ _G_python_4, lastError = eval('self.builder.bind(self.builder.apply("anything", self.name), n)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_4, self.currentError)
+ _G_or_3, lastError = self._or([_G_or_1, _G_or_2])
+ self.considerError(lastError)
+ return (_G_or_3, self.currentError)
+
+
+ def rule_expr4(self):
+ _locals = {'self': self}
+ self.locals['expr4'] = _locals
+ def _G_many_1():
+ _G_apply_1, lastError = self._apply(self.rule_expr3, "expr3", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ _G_many_2, lastError = self.many(_G_many_1)
+ self.considerError(lastError)
+ _locals['es'] = _G_many_2
+ _G_python_3, lastError = eval('self.builder.sequence(es)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+
+
+ def rule_expr(self):
+ _locals = {'self': self}
+ self.locals['expr'] = _locals
+ _G_apply_1, lastError = self._apply(self.rule_expr4, "expr4", [])
+ self.considerError(lastError)
+ _locals['e'] = _G_apply_1
+ def _G_many_2():
+ _G_python_1, lastError = eval("'|'", self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_expr4, "expr4", [])
+ self.considerError(lastError)
+ return (_G_apply_3, self.currentError)
+ _G_many_3, lastError = self.many(_G_many_2)
+ self.considerError(lastError)
+ _locals['es'] = _G_many_3
+ _G_python_4, lastError = eval('es.insert(0, e)', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_python_5, lastError = eval('self.builder._or(es)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_5, self.currentError)
+
+
+ def rule_ruleValue(self):
+ _locals = {'self': self}
+ self.locals['ruleValue'] = _locals
+ _G_python_1, lastError = eval('"=>"', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_python_3, lastError = eval('self.ruleValueExpr()', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+
+
+ def rule_semanticPredicate(self):
+ _locals = {'self': self}
+ self.locals['semanticPredicate'] = _locals
+ _G_python_1, lastError = eval('"?("', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_python_3, lastError = eval('self.semanticPredicateExpr()', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+
+
+ def rule_semanticAction(self):
+ _locals = {'self': self}
+ self.locals['semanticAction'] = _locals
+ _G_python_1, lastError = eval('"!("', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_python_3, lastError = eval('self.semanticActionExpr()', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+
+
+ def rule_rulePart(self):
+ _locals = {'self': self}
+ self.locals['rulePart'] = _locals
+ _G_apply_1, lastError = self._apply(self.rule_anything, "anything", [])
+ self.considerError(lastError)
+ _locals['requiredName'] = _G_apply_1
+ _G_apply_2, lastError = self._apply(self.rule_spaces, "spaces", [])
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_name, "name", [])
+ self.considerError(lastError)
+ _locals['n'] = _G_apply_3
+ def _G_pred_4():
+ _G_python_1, lastError = eval('n == requiredName', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_1, self.currentError)
+ _G_pred_5, lastError = self.pred(_G_pred_4)
+ self.considerError(lastError)
+ _G_python_6, lastError = eval('setattr(self, "name", n)', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_7, lastError = self._apply(self.rule_expr4, "expr4", [])
+ self.considerError(lastError)
+ _locals['args'] = _G_apply_7
+ def _G_or_8():
+ _G_python_1, lastError = eval('"::="', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_token, "token", [_G_python_1])
+ self.considerError(lastError)
+ _G_apply_3, lastError = self._apply(self.rule_expr, "expr", [])
+ self.considerError(lastError)
+ _locals['e'] = _G_apply_3
+ _G_python_4, lastError = eval('self.builder.sequence([args, e])', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_4, self.currentError)
+ def _G_or_9():
+ _G_python_1, lastError = eval('args', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_1, self.currentError)
+ _G_or_10, lastError = self._or([_G_or_8, _G_or_9])
+ self.considerError(lastError)
+ return (_G_or_10, self.currentError)
+
+
+ def rule_rule(self):
+ _locals = {'self': self}
+ self.locals['rule'] = _locals
+ _G_apply_1, lastError = self._apply(self.rule_spaces, "spaces", [])
+ self.considerError(lastError)
+ def _G_lookahead_2():
+ _G_apply_1, lastError = self._apply(self.rule_name, "name", [])
+ self.considerError(lastError)
+ _locals['n'] = _G_apply_1
+ return (_locals['n'], self.currentError)
+ _G_lookahead_3, lastError = self.lookahead(_G_lookahead_2)
+ self.considerError(lastError)
+ _G_python_4, lastError = eval('n', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_5, lastError = self._apply(self.rule_rulePart, "rulePart", [_G_python_4])
+ self.considerError(lastError)
+ _locals['r'] = _G_apply_5
+ def _G_or_6():
+ def _G_many1_1():
+ _G_python_1, lastError = eval('n', self.globals, _locals), None
+ self.considerError(lastError)
+ _G_apply_2, lastError = self._apply(self.rule_rulePart, "rulePart", [_G_python_1])
+ self.considerError(lastError)
+ return (_G_apply_2, self.currentError)
+ _G_many1_2, lastError = self.many(_G_many1_1, _G_many1_1())
+ self.considerError(lastError)
+ _locals['rs'] = _G_many1_2
+ _G_python_3, lastError = eval('self.builder.rule(n, self.builder._or([r] + rs))', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_3, self.currentError)
+ def _G_or_7():
+ _G_python_1, lastError = eval('self.builder.rule(n, r)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_1, self.currentError)
+ _G_or_8, lastError = self._or([_G_or_6, _G_or_7])
+ self.considerError(lastError)
+ return (_G_or_8, self.currentError)
+
+
+ def rule_grammar(self):
+ _locals = {'self': self}
+ self.locals['grammar'] = _locals
+ def _G_many_1():
+ _G_apply_1, lastError = self._apply(self.rule_rule, "rule", [])
+ self.considerError(lastError)
+ return (_G_apply_1, self.currentError)
+ _G_many_2, lastError = self.many(_G_many_1)
+ self.considerError(lastError)
+ _locals['rs'] = _G_many_2
+ _G_apply_3, lastError = self._apply(self.rule_spaces, "spaces", [])
+ self.considerError(lastError)
+ _G_python_4, lastError = eval('self.builder.makeGrammar(rs)', self.globals, _locals), None
+ self.considerError(lastError)
+ return (_G_python_4, self.currentError)
diff --git a/kibot/PcbDraw/pybars/pymeta/builder.py b/kibot/PcbDraw/pybars/pymeta/builder.py
new file mode 100644
index 00000000..865fe674
--- /dev/null
+++ b/kibot/PcbDraw/pybars/pymeta/builder.py
@@ -0,0 +1,326 @@
+# -*- test-case-name: pymeta.test.test_builder -*-
+import linecache, sys
+from types import ModuleType as module
+
+import itertools, linecache, sys
+
+class TreeBuilder(object):
+ """
+ Produce an abstract syntax tree of OMeta operations.
+ """
+
+ def __init__(self, name, grammar=None, *args):
+ self.name = name
+
+
+ def makeGrammar(self, rules):
+ return ["Grammar", self.name, rules]
+
+ def rule(self, name, expr):
+ return ["Rule", name, expr]
+
+ def apply(self, ruleName, codeName, *exprs):
+ return ["Apply", ruleName, codeName, exprs]
+
+ def exactly(self, expr):
+ return ["Exactly", expr]
+
+ def many(self, expr):
+ return ["Many", expr]
+
+ def many1(self, expr):
+ return ["Many1", expr]
+
+ def optional(self, expr):
+ return ["Optional", expr]
+
+ def _or(self, exprs):
+ return ["Or", exprs]
+
+ def _not(self, expr):
+ return ["Not", expr]
+
+ def lookahead(self, expr):
+ return ["Lookahead", expr]
+
+ def sequence(self, exprs):
+ return ["And", exprs]
+
+ def bind(self, expr, name):
+ return ["Bind", name, expr]
+
+ def pred(self, expr):
+ return ["Predicate", expr]
+
+ def action(self, expr):
+ return ["Action", expr]
+
+ def expr(self, expr):
+ return ["Python", expr]
+
+ def listpattern(self, exprs):
+ return ["List", exprs]
+
+
+
+class PythonWriter(object):
+ """
+ Converts an OMeta syntax tree into Python source.
+ """
+ def __init__(self, tree):
+ self.tree = tree
+ self.lines = []
+ self.gensymCounter = 0
+
+
+ def _generate(self, retrn=False):
+ result = self._generateNode(self.tree)
+ if retrn:
+ self.lines.append("return (%s, self.currentError)" % (result,))
+ elif result:
+ self.lines.append(result)
+ return self.lines
+
+
+ def output(self):
+ return '\n'.join(self._generate())
+
+
+ def _generateNode(self, node):
+ name = node[0]
+ args = node[1:]
+ return getattr(self, "generate_"+name)(*args)
+
+
+ def _gensym(self, name):
+ """
+ Produce a unique name for a variable in generated code.
+ """
+ self.gensymCounter += 1
+ return "_G_%s_%s" % (name, self.gensymCounter)
+
+
+ def _newThunkFor(self, name, expr):
+ """
+ Define a new function of no arguments.
+ @param name: The name of the rule generating this thunk.
+ @param expr: A list of lines of Python code.
+ """
+
+ subwriter = self.__class__(expr)
+ flines = subwriter._generate(retrn=True)
+ fname = self._gensym(name)
+ self._writeFunction(fname, (), flines)
+ return fname
+
+
+ def _expr(self, typ, e):
+ """
+ Generate the code needed to execute the expression, and return the
+ variable name bound to its value.
+ """
+ name = self._gensym(typ)
+ self.lines.append("%s, lastError = %s" % (name, e))
+ self.lines.append("self.considerError(lastError)")
+ return name
+
+
+ def _writeFunction(self, fname, arglist, flines):
+ """
+ Generate a function.
+ @param head: The initial line defining the function.
+ @param body: A list of lines for the function body.
+ """
+
+ self.lines.append("def %s(%s):" % (fname, ", ".join(arglist)))
+ for line in flines:
+ self.lines.append((" " * 4) + line)
+ return fname
+
+
+ def compilePythonExpr(self, expr):
+ """
+ Generate code for running embedded Python expressions.
+ """
+
+ return self._expr('python', 'eval(%r, self.globals, _locals), None' %(expr,))
+
+
+ def generate_Apply(self, ruleName, codeName, rawArgs):
+ """
+ Create a call to self.apply(ruleName, *args).
+ """
+ args = [self._generateNode(x) for x in rawArgs]
+ if ruleName == 'super':
+ return self._expr('apply', 'self.superApply("%s", %s)' % (codeName,
+ ', '.join(args)))
+ return self._expr('apply', 'self._apply(self.rule_%s, "%s", [%s])' % (ruleName,
+ ruleName,
+ ', '.join(args)))
+
+ def generate_Exactly(self, literal):
+ """
+ Create a call to self.exactly(expr).
+ """
+ return self._expr('exactly', 'self.exactly(%r)' % (literal,))
+
+
+ def generate_Many(self, expr):
+ """
+ Create a call to self.many(lambda: expr).
+ """
+ fname = self._newThunkFor("many", expr)
+ return self._expr('many', 'self.many(%s)' % (fname,))
+
+
+ def generate_Many1(self, expr):
+ """
+ Create a call to self.many(lambda: expr).
+ """
+ fname = self._newThunkFor("many1", expr)
+ return self._expr('many1', 'self.many(%s, %s())' % (fname, fname))
+
+
+ def generate_Optional(self, expr):
+ """
+ Try to parse an expr and continue if it fails.
+ """
+ realf = self._newThunkFor("optional", expr)
+ passf = self._gensym("optional")
+ self._writeFunction(passf, (), ["return (None, self.input.nullError())"])
+ return self._expr('or', 'self._or([%s])' % (', '.join([realf, passf])))
+
+
+ def generate_Or(self, exprs):
+ """
+ Create a call to
+ self._or([lambda: expr1, lambda: expr2, ... , lambda: exprN]).
+ """
+ if len(exprs) > 1:
+ fnames = [self._newThunkFor("or", expr) for expr in exprs]
+ return self._expr('or', 'self._or([%s])' % (', '.join(fnames)))
+ else:
+ return self._generateNode(exprs[0])
+
+
+ def generate_Not(self, expr):
+ """
+ Create a call to self._not(lambda: expr).
+ """
+ fname = self._newThunkFor("not", expr)
+ return self._expr("not", "self._not(%s)" % (fname,))
+
+
+ def generate_Lookahead(self, expr):
+ """
+ Create a call to self.lookahead(lambda: expr).
+ """
+ fname = self._newThunkFor("lookahead", expr)
+ return self._expr("lookahead", "self.lookahead(%s)" %(fname,))
+
+
+ def generate_And(self, exprs):
+ """
+ Generate code for each statement in order.
+ """
+ v = None
+ for ex in exprs:
+ v = self._generateNode(ex)
+ return v
+
+
+ def generate_Bind(self, name, expr):
+ """
+ Bind the value of 'expr' to a name in the _locals dict.
+ """
+ v = self._generateNode(expr)
+ ref = "_locals['%s']" % (name,)
+ self.lines.append("%s = %s" %(ref, v))
+ return ref
+
+
+ def generate_Predicate(self, expr):
+ """
+ Generate a call to self.pred(lambda: expr).
+ """
+
+ fname = self._newThunkFor("pred", expr)
+ return self._expr("pred", "self.pred(%s)" %(fname,))
+
+
+ def generate_Action(self, expr):
+ """
+ Generate this embedded Python expression on its own line.
+ """
+ return self.compilePythonExpr(expr)
+
+
+ def generate_Python(self, expr):
+ """
+ Generate this embedded Python expression on its own line.
+ """
+ return self.compilePythonExpr(expr)
+
+
+ def generate_List(self, expr):
+ """
+ Generate a call to self.listpattern(lambda: expr).
+ """
+ fname = self._newThunkFor("listpattern", expr)
+ return self._expr("listpattern", "self.listpattern(%s)" %(fname,))
+
+
+ def generate_Rule(self, name, expr):
+ rulelines = ["_locals = {'self': self}",
+ "self.locals[%r] = _locals" % (name,)]
+ subwriter = self.__class__(expr)
+ flines = subwriter._generate(retrn=True)
+ rulelines.extend(flines)
+ self._writeFunction("rule_" + name, ("self",), rulelines)
+
+
+ def generate_Grammar(self, name, rules):
+ self.lines.append("class %s(GrammarBase):" % (name,))
+ for rule in rules:
+ self._generateNode(rule)
+ self.lines.extend(['', ''])
+ self.lines[1:] = [line and (' ' * 4 + line) for line in self.lines[1:]]
+ del self.lines[-2:]
+
+
+
+def writePython(tree):
+ pw = PythonWriter(tree)
+ return pw.output()
+
+
+class GeneratedCodeLoader(object):
+ """
+ Object for use as a module's __loader__, to display generated
+ source.
+ """
+ def __init__(self, source):
+ self.source = source
+ def get_source(self, name):
+ return self.source
+
+
+
+def moduleFromGrammar(tree, className, superclass, globalsDict):
+ source = writePython(tree)
+ modname = "pymeta_grammar__" + className
+ filename = "/pymeta_generated_code/" + modname + ".py"
+ mod = module(modname)
+ mod.__dict__.update(globalsDict)
+ mod.__name__ = modname
+ mod.__dict__[superclass.__name__] = superclass
+ mod.__dict__["GrammarBase"] = superclass
+ mod.__loader__ = GeneratedCodeLoader(source)
+ code = compile(source, filename, "exec")
+ eval(code, mod.__dict__)
+ fullGlobals = dict(getattr(mod.__dict__[className], "globals", None) or {})
+ fullGlobals.update(globalsDict)
+ mod.__dict__[className].globals = fullGlobals
+ sys.modules[modname] = mod
+ linecache.getlines(filename, mod.__dict__)
+ return mod.__dict__[className]
diff --git a/kibot/PcbDraw/pybars/pymeta/grammar.py b/kibot/PcbDraw/pybars/pymeta/grammar.py
new file mode 100644
index 00000000..8db47dfc
--- /dev/null
+++ b/kibot/PcbDraw/pybars/pymeta/grammar.py
@@ -0,0 +1,321 @@
+# -*- test-case-name: pymeta.test.test_pymeta -*-
+"""
+Public interface to OMeta, as well as the grammars used to compile grammar
+definitions.
+"""
+import string
+from .builder import TreeBuilder, moduleFromGrammar
+from .boot import BootOMetaGrammar
+from .runtime import OMetaBase, ParseError, EOFError
+
+class OMeta(OMetaBase):
+ """
+ Base class for grammar definitions.
+ """
+ metagrammarClass = BootOMetaGrammar
+ def makeGrammar(cls, grammar, globals, name="Grammar"):
+ """
+ Define a new subclass with the rules in the given grammar.
+
+ @param grammar: A string containing a PyMeta grammar.
+ @param globals: A dict of names that should be accessible by this
+ grammar.
+ @param name: The name of the class to be generated.
+ """
+ g = cls.metagrammarClass(grammar)
+ tree = g.parseGrammar(name, TreeBuilder)
+ return moduleFromGrammar(tree, name, cls, globals)
+
+ makeGrammar = classmethod(makeGrammar)
+
+ometaGrammar = r"""
+number ::= ('-' :x => -x
+ |:x => x)
+barenumber ::= ('0' (('x'|'X') *:hs => int(''.join(hs), 16)
+ |*:ds => int('0'+''.join(ds), 8))
+ |+:ds => int(''.join(ds)))
+octaldigit ::= :x ?(x in string.octdigits) => x
+hexdigit ::= :x ?(x in string.hexdigits) => x
+
+escapedChar ::= '\\' ('n' => "\n"
+ |'r' => "\r"
+ |'t' => "\t"
+ |'b' => "\b"
+ |'f' => "\f"
+ |'"' => '"'
+ |'\'' => "'"
+ |'\\' => '\\')
+
+character ::= ( | ):c => c
+
+bareString ::= ( | ~('"') )*:c => ''.join(c)
+string ::= :s => self.builder.exactly(s)
+
+name ::= :x *:xs !(xs.insert(0, x)) => ''.join(xs)
+
+application ::= ( :name
+ (' ' !(self.applicationArgs(finalChar='>')):args
+ => self.builder.apply(name, self.name, *args)
+ |'>
+ => self.builder.apply(name, self.name)))
+
+expr1 ::= (
+ |
+ |
+ |
+ |( | ):lit => self.builder.exactly(lit)
+ |
+ | :e => e
+ | :e => self.builder.listpattern(e))
+
+expr2 ::= ( ( :e => self.builder.lookahead(e)
+ |:e => self.builder._not(e))
+ |)
+
+expr3 ::= ((:e ('*' => self.builder.many(e)
+ |'+' => self.builder.many1(e)
+ |'?' => self.builder.optional(e)
+ | => e)):r
+ (':' :n => self.builder.bind(r, n)
+ | => r)
+ | :n
+ => self.builder.bind(self.builder.apply("anything", self.name), n))
+
+expr4 ::= *:es => self.builder.sequence(es)
+
+expr ::= :e ( )*:es !(es.insert(0, e))
+ => self.builder._or(es)
+
+ruleValue ::= "> => self.ruleValueExpr(False)
+
+semanticPredicate ::= => self.semanticPredicateExpr()
+
+semanticAction ::= => self.semanticActionExpr()
+
+rulePart :requiredName ::= ( :n ?(n == requiredName)
+ !(setattr(self, "name", n))
+ :args
+ ( :e
+ => self.builder.sequence([args, e])
+ | => args))
+rule ::= ( ~~(:n) :r
+ (+:rs => self.builder.rule(n, self.builder._or([r] + rs))
+ | => self.builder.rule(n, r)))
+
+grammar ::= *:rs => self.builder.makeGrammar(rs)
+"""
+#don't be confused, emacs
+v2Grammar = r"""
+hspace ::= (' ' | '\t')
+vspace ::= ( | '\r' | '\n')
+emptyline ::= *
+indentation ::= * +
+noindentation ::= * ~~~
+
+number ::= ('-' :x => self.builder.exactly(-x)
+ |:x => self.builder.exactly(x))
+barenumber ::= '0' (('x'|'X') *:hs => int(''.join(hs), 16)
+ |*:ds => int('0'+''.join(ds), 8))
+ |+:ds => int(''.join(ds))
+octaldigit ::= :x ?(x in string.octdigits) => x
+hexdigit ::= :x ?(x in string.hexdigits) => x
+
+escapedChar ::= '\\' ('n' => "\n"
+ |'r' => "\r"
+ |'t' => "\t"
+ |'b' => "\b"
+ |'f' => "\f"
+ |'"' => '"'
+ |'\'' => "'"
+ |'\\' => "\\")
+
+character ::= ( | ):c => self.builder.exactly(c)
+
+string ::= ( | ~('"') )*:c => self.builder.exactly(''.join(c))
+
+name ::= :x *:xs !(xs.insert(0, x)) => ''.join(xs)
+
+application ::= ? :name
+ ('(' !(self.applicationArgs(finalChar=')')):args
+ => self.builder.apply(name, self.name, *args)
+ | => self.builder.apply(name, self.name))
+
+expr1 ::=
+ |
+ |
+ |
+ |
+ |
+ |
+ | :e => e
+ |