from ..interface import Contract, ContractNotRespected, RValue, describe_value
from ..syntax import (W, oneOf, FollowedBy, NotAny)
[docs]class BindVariable(Contract):
def __init__(self, variable, allowed_types, where=None):
assert isinstance(variable, str) and len(variable) == 1
assert allowed_types, '%r' % allowed_types
Contract.__init__(self, where)
self.variable = variable
self.allowed_types = allowed_types
[docs] def check_contract(self, context, value, silent):
if self.variable in context:
expected = context[self.variable]
if not (expected == value):
# TODO: add where it was bound
error = (
'Expected value for %r was: %s\n'
' instead I received: %s' %
(self.variable, describe_value(expected),
describe_value(value)))
raise ContractNotRespected(contract=self, error=error,
value=value, context=context)
else:
# bound variable
if not isinstance(value, self.allowed_types):
error = ('Variable %r can only bind to %r, not %r.' %
(self.variable, self.allowed_types,
value.__class__.__name__))
raise ContractNotRespected(self, error, value, context)
context[self.variable] = value
def __str__(self):
return self.variable
def __repr__(self):
# XXX: invalid if tuple
return 'BindVariable(%r,%s)' % (self.variable,
self.allowed_types.__name__)
[docs] @staticmethod
def parse_action(allowed_types):
def parse(s, loc, tokens):
where = W(s, loc)
variable = tokens[0]
assert len(variable) == 1, \
('Wrong syntax, matched %r as variable in %r.'
% (variable, s))
# print ('Matched %r as variable in %r.' % (variable, s))
return BindVariable(variable, allowed_types, where=where)
return parse
[docs]class VariableRef(RValue):
def __init__(self, variable, where=None):
assert isinstance(variable, str)
self.where = where
self.variable = variable
[docs] def eval(self, context): # @ReservedAssignment
var = self.variable
if not var in context:
raise ValueError('Unknown variable %r.' % var)
return context[var]
def __repr__(self):
return "VariableRef(%r)" % self.variable
def __str__(self):
return "%s" % self.variable
[docs] @staticmethod
def parse_action(s, loc, tokens):
where = W(s, loc)
return VariableRef(tokens[0], where=where)
alphabetu = 'A B C D E F G H I J K L M N O P Q R S T U W V X Y Z '
alphabetl = 'a b c d e f g h i j k l m n o p q r s t u w v x y z '
# Special case: allow an expression like AxBxC
nofollow = 'a b c d e f g h i j k l m n o p q r s t u w v y z'
# also do not commit if part of word (SEn, a_2)
nofollow += ' A B C D E F G H I J K L M N O P Q R S T U W V X Y Z '
nofollow += ' 0 1 2 3 4 5 6 7 8 9 _'
# but recall 'axis_angle'
int_variables = (oneOf(alphabetu.split())
+ FollowedBy(NotAny(oneOf(nofollow.split()))))
misc_variables = (oneOf(alphabetl.split())
+ FollowedBy(NotAny(oneOf(nofollow.split() + ['x']))))
int_variables_ref = int_variables.copy().setParseAction(
VariableRef.parse_action)
misc_variables_ref = misc_variables.copy().setParseAction(
VariableRef.parse_action)
#int_variables = oneOf(alphabetu.split()) + FollowedBy(White() ^ 'x')
# These must be followed by whitespace; punctuation
#misc_variables = oneOf(alphabet.lower()) + FollowedBy(White())
nofollow = 'a b c d e f g h i j k l m n o p q r s t u w v y z '
nofollow += ' * - + / '
nofollow += ' A B C D E F G H I J K L M N O P Q R S T U W V X Y Z '
nofollow += ' 0 1 2 3 4 5 6 7 8 9 _'
int_variables2 = (oneOf(alphabetu.split())
+ FollowedBy(NotAny(oneOf(nofollow.split()))))
misc_variables2 = (oneOf(alphabetl.split())
+ FollowedBy(NotAny(oneOf(nofollow.split() + ['x']))))
int_variables_contract = int_variables2.setParseAction(
BindVariable.parse_action(int))
misc_variables_contract = misc_variables2.setParseAction(
BindVariable.parse_action(object))