def check_bad_tree(self, tree, label):
     try:
         parser.sequence2st(tree)
     except parser.ParserError:
         pass
     else:
         self.fail("did not detect invalid tree for %r" % label)
 def test_illegal_encoding(self):
     tree = 339, (257, (0, ''))
     self.check_bad_tree(tree, 'missed encoding')
     tree = 339, (257, (0, '')), b'iso-8859-1'
     self.check_bad_tree(tree, 'non-string encoding')
     tree = 339, (257, (0, '')), '\udcff'
     with self.assertRaises(UnicodeEncodeError):
         parser.sequence2st(tree)
Example #3
0
 def roundtrip(self, f, s):
     st1 = f(s)
     t = st1.totuple()
     try:
         st2 = parser.sequence2st(t)
     except parser.ParserError, why:
         self.fail("could not roundtrip %r: %s" % (s, why))
def parse_formula(unit_name):
    for name in CONVERSION_FACTORS:
        exec(name + '=' + CONVERSION_FACTORS[name])

    # force any attempt to call a function to fail.
    unit_name = unit_name.replace('()', '')

    # these we have to hard code because the syntax tree can't be generated from them
    unit_name = unit_name.replace('\'', 'arcminute')
    unit_name = unit_name.replace('"', 'arcsecond')
    unit_name = unit_name.replace('°', 'degree')

    # turn the formula into a syntax tree and replace symbols with full names
    # can't be a simple string replace because 'h' could override 'ha'
    expr = parser.expr(unit_name)
    syntax_tree = expr.tolist()
    updated_tree, updated_unit_name = replace_tree_variable(syntax_tree)
    updated_expr = parser.sequence2st(updated_tree)
    code = updated_expr.compile()

    # execute our code. should be safe security wise because we removed the possibility of
    # function calls
    multiplication_factor = eval(code)
    multiplication_factor = str.format('{0:.14f}', multiplication_factor)

    return {
        'unit_name': updated_unit_name,
        'multiplication_factor': multiplication_factor,
    }
 def roundtrip(self, f, s):
     st1 = f(s)
     t = st1.totuple()
     try:
         st2 = parser.sequence2st(t)
     except parser.ParserError as why:
         self.fail('could not roundtrip %r: %s' % (s, why))
     self.assertEqual(t, st2.totuple(), 'could not re-generate syntax tree')
 def test_illegal_encoding(self):
     # Illegal encoding declaration
     tree = \
         (339,
          (257, (0, '')))
     self.check_bad_tree(tree, "missed encoding")
     tree = \
         (339,
          (257, (0, '')),
           b'iso-8859-1')
     self.check_bad_tree(tree, "non-string encoding")
     tree = \
         (339,
          (257, (0, '')),
           '\udcff')
     with self.assertRaises(UnicodeEncodeError):
         parser.sequence2st(tree)
Example #7
0
    def roundtrip(self, f, s):
        st1 = f(s)
        t = st1.totuple()
        try:
            st2 = parser.sequence2st(t)
        except parser.ParserError as why:
            self.fail("could not roundtrip %r: %s" % (s, why))

        self.assertEqual(t, st2.totuple(), "could not re-generate syntax tree")
    def roundtrip(self, f, s):
        st1 = f(s)
        t = st1.totuple()
        try:
            st2 = parser.sequence2st(t)
        except parser.ParserError:
            self.fail("could not roundtrip %r" % s)

        self.assertEquals(t, st2.totuple(),
                          "could not re-generate syntax tree")
Example #9
0
def tweak_field(moose_wildcard, field, assignment_string):
    """Tweak a specified field of all objects that match the
    moose_wildcard using assignment string. All identifiers in
    assignment string must be fields of the target object.

    Example:

    tweak_field('/mycell/##[Class=Compartment]', 'Rm', '1.5 / (3.1416 * diameter * length')

    will assign Rm to every compartment in mycell such that the
    specific membrane resistance is 1.5 Ohm-m2.
    """
    if not isinstance(moose_wildcard, str):
        raise TypeError('moose_wildcard must be a string.')
    id_list = moose.getWildcardList(moose_wildcard, True)
    expression = parser.expr(assignment_string)
    expr_list = expression.tolist()

    # This is a hack: I just tried out some possible syntax trees and
    # hand coded the replacement such that any identifier is replaced
    # by moose_obj.identifier
    def replace_fields_with_value(x):
        if len(x) > 1:
            if x[0] == symbol.power and x[1][0] == symbol.atom and x[1][1][
                    0] == token.NAME:
                field = x[1][1][1]
                x[1] = [symbol.atom, [token.NAME, 'moose_obj']]
                x.append(
                    [symbol.trailer, [token.DOT, '.'], [token.NAME, field]])
            for item in x:
                if isinstance(item, list):
                    replace_fields_with_value(item)
        return x

    tmp = replace_fields_with_value(expr_list)
    new_expr = parser.sequence2st(tmp)
    code = new_expr.compile()
    for moose_id in id_list:
        moose_obj = eval('moose.%s(moose_id)' %
                         (moose.Neutral(moose_id).className))
        value = eval(code)
        moose.setField(moose_id, field, str(value))
Example #10
0
def _esoteric_source(src):
    if str_check(src):
        return parser.suite(src).compile()
    if is_ast_node(src):
        if isinstance(src, ast.ClassDef):
            node = ast.Module([src])
        elif (isinstance(src, ast.Module) and
              isinstance(src.body[0], ast.ClassDef)):
            node = src
        else:
            raise TypeError(f'build_class() using an ast node as the '
                                f'class body it must be a ast.Class node '
                                f'or an ast.Module node whose .body[0] is '
                                f'a Class')
        return compile(node, '<ast.Class>', 'exec')
    if isinstance(src, (tuple, list)):
        src = parser.sequence2st(src)
    if isinstance(src, parser.STType):
        if not parser.issuite(src):
            raise TypeError(f'build_class() the parser syntax tree objects '
                            f'must be a "suite"')
        return parser.compilest(src)
Example #11
0
def tweak_field(moose_wildcard, field, assignment_string):
    """Tweak a specified field of all objects that match the
    moose_wildcard using assignment string. All identifiers in
    assignment string must be fields of the target object.

    Example:

    tweak_field('/mycell/##[Class=Compartment]', 'Rm', '1.5 / (3.1416 * diameter * length')

    will assign Rm to every compartment in mycell such that the
    specific membrane resistance is 1.5 Ohm-m2.
    """
    if not isinstance(moose_wildcard, str):
        raise TypeError("moose_wildcard must be a string.")
    id_list = _moose.getWildcardList(moose_wildcard, True)
    expression = parser.expr(assignment_string)
    expr_list = expression.tolist()
    # This is a hack: I just tried out some possible syntax trees and
    # hand coded the replacement such that any identifier is replaced
    # by moose_obj.identifier
    def replace_fields_with_value(x):
        if len(x) > 1:
            if x[0] == symbol.power and x[1][0] == symbol.atom and x[1][1][0] == token.NAME:
                field = x[1][1][1]
                x[1] = [symbol.atom, [token.NAME, "moose_obj"]]
                x.append([symbol.trailer, [token.DOT, "."], [token.NAME, field]])
            for item in x:
                if isinstance(item, list):
                    replace_fields_with_value(item)
        return x

    tmp = replace_fields_with_value(expr_list)
    new_expr = parser.sequence2st(tmp)
    code = new_expr.compile()
    for moose_id in id_list:
        moose_obj = eval("_moose.%s(moose_id)" % (_moose.Neutral(moose_id).className))
        value = eval(code)
        _moose.setField(moose_id, field, str(value))
def dump_and_modify(node):
    name = symbol.sym_name.get(node[0])
    if name is None:
        name = token.tok_name.get(node[0])
    print(name, '', end='')
    for i in range(1, len(node)):
        item = node[i]
        if type(item) is type([]):
            dump_and_modify(item)
        else:
            print(repr(item))
            if name == 'NUMBER':
                node[i] = repr(int(item) + 1)


ast = parser.expr('1 + 3')
list = ast.tolist()
dump_and_modify(list)

ast = parser.sequence2st(list)
print(eval(parser.compilest(ast)))
'''
eval_input testlist test or_test and_test not_test comparison expr xor_expr and_expr shift_expr arith_expr term factor power atom NUMBER '1'
PLUS '+'
term factor power atom NUMBER '3'
NEWLINE ''
ENDMARKER ''
6
[Finished in 0.2s]
'''
Example #13
0
    def ParseAndCompileUserFunctionString(self, inString):

        # shift user functions into numpy namespace at run time, not import time
        numpySafeTokenList = []
        for key in list(self.functionDictionary.keys()):
            numpySafeTokenList += self.functionDictionary[key]
        for key in list(self.constantsDictionary.keys()):
            numpySafeTokenList += self.constantsDictionary[key]

        # no blank lines of text, StringIO() allows using file methods on text
        stringToConvert = ''
        rawData = io.StringIO(inString).readlines()

        for line in rawData:
            stripped = line.strip()
            if len(stripped) > 0:  # no empty strings
                if stripped[0] != '#':  # no comment-only lines
                    stringToConvert += stripped + '\n'

        # convert brackets to parentheses
        stringToConvert = stringToConvert.replace('[', '(').replace(']', ')')

        if stringToConvert == '':
            raise Exception(
                'You must enter some function text for the software to use.')

        if -1 != stringToConvert.find('='):
            raise Exception(
                'Please do not use an equals sign "=" in your text.')

        st = parser.expr(stringToConvert)
        tup = st.totuple()
        tokens = self.GetTokensFromTupleParsingHelper(tup)

        if '^' in tokens:
            raise Exception(
                'The caret symbol "^" is not recognized by the parser, please substitute double asterisks "**" for "^".'
            )

        if 'ln' in tokens:
            raise Exception(
                "The parser uses log() for the natural log function, not ln(). Please use log() in your text."
            )

        if 'abs' in tokens:
            raise Exception(
                "The parser uses fabs() for the absolute value, not abs(). Please use fabs() in your text."
            )

        if 'EXP' in tokens:
            raise Exception(
                "The parser uses lower case exp(), not upper case EXP(). Please use lower case exp() in your text."
            )

        if 'LOG' in tokens:
            raise Exception(
                "The parser uses lower case log(), not upper case LOG(). Please use lower case log() in your text."
            )

        # test for required reserved tokens
        tokenNames = list(set(tokens) - set(numpySafeTokenList))
        if 'X' not in tokenNames:
            raise Exception(
                'You must use a separate upper case "X" in your function to enter a valid function of X.'
            )
        if 'Y' not in tokenNames:
            raise Exception(
                'You must use a separate upper case "Y" in your function to enter a valid function of Y.'
            )

        self._coefficientDesignators = sorted(
            list(set(tokenNames) - set(['X', 'Y'])))

        if len(self._coefficientDesignators) == 0:
            raise Exception(
                'I could not find any equation parameter or coefficient names, please check the function text'
            )

        # now compile code object using safe tokens with integer conversion
        self.safe_dict = locals()
        for f in numpySafeTokenList:
            self.safe_dict[f] = eval('numpy.' + f)

        # convert integer use such as (3/2) into floats such as (3.0/2.0)
        st = parser.expr(stringToConvert)
        stList = parser.st2list(st)
        stList = self.RecursivelyConvertIntStringsToFloatStrings(stList)
        st = parser.sequence2st(stList)

        # later evals re-use this compiled code for improved performance in EvaluateCachedData() methods
        self.userFunctionCodeObject = parser.compilest(st)
 def test_ParserError_message(self):
     try:
         parser.sequence2st((257, (269, (257, (0, '')))))
     except parser.ParserError as why:
         self.assertIn("simple_stmt", str(why))  # Expected
         self.assertIn("file_input", str(why))  # Got
Example #15
0
    def ParseAndCompileUserFunctionString(self, inString):

        # shift user functions into numpy namespace at run time, do not import time
        numpySafeTokenList = []
        for key in list(self.functionDictionary.keys()):
            numpySafeTokenList += self.functionDictionary[key]
        for key in list(self.constantsDictionary.keys()):
            numpySafeTokenList += self.constantsDictionary[key]

        # to shift user functions such as "power" into the numpy namespace "numpy.power" for evaluation
        for token in numpySafeTokenList:
            exec(token + " = numpy." + token)

        # no blank lines of text, StringIO() allows using file methods on text
        stringToConvert = ""
        rawData = StringIO.StringIO(inString).readlines()

        for line in rawData:
            stripped = line.strip()
            if len(stripped) > 0:  # no empty strings
                if stripped[0] != "#":  # no comment-only lines
                    stringToConvert += stripped + "\n"

        # convert brackets to parentheses
        stringToConvert = stringToConvert.replace("[", "(").replace("]", ")")

        if stringToConvert == "":
            raise Exception("You must enter some function text for the software to use.")

        if -1 != stringToConvert.find("="):
            raise Exception('Please do not use an equals sign "=" in your text.')

        st = parser.expr(stringToConvert)
        tup = st.totuple()
        tokens = self.GetTokensFromTupleParsingHelper(tup)

        if "^" in tokens:
            raise Exception(
                'The caret symbol "^" is not recognized by the parser, please substitute double asterisks "**" for "^".'
            )

        if "ln" in tokens:
            raise Exception(
                "The parser uses log() for the natural log function, not ln(). Please use log() in your text."
            )

        if "abs" in tokens:
            raise Exception("The parser uses fabs() for the absolute value, not abs(). Please use fabs() in your text.")

        if "EXP" in tokens:
            raise Exception(
                "The parser uses lower case exp(), not upper case EXP(). Please use lower case exp() in your text."
            )

        if "LOG" in tokens:
            raise Exception(
                "The parser uses lower case log(), not upper case LOG(). Please use lower case log() in your text."
            )

        # test for required reserved tokens
        tokenNames = list(set(tokens) - set(numpySafeTokenList))
        if "X" not in tokenNames:
            raise Exception('You must use a separate upper case "X" in your function to enter a valid function of X.')
        if "Y" not in tokenNames:
            raise Exception('You must use a separate upper case "Y" in your function to enter a valid function of Y.')

        self._coefficientDesignators = sorted(list(set(tokenNames) - set(["X", "Y"])))

        if len(self._coefficientDesignators) == 0:
            raise Exception(
                "I could not find any equation parameter or coefficient names, please check the function text"
            )

        # now compile code object using safe tokens
        self.safe_dict = dict([(k, locals().get(k, None)) for k in numpySafeTokenList])

        # now compile code object using safe tokens with integer conversion
        self.safe_dict = dict([(k, locals().get(k, None)) for k in numpySafeTokenList])

        # convert integer use such as (3/2) into floats such as (3.0/2.0)
        st = parser.expr(stringToConvert)
        stList = parser.st2list(st)
        stList = self.RecursivelyConvertIntStringsToFloatStrings(stList)
        st = parser.sequence2st(stList)

        # later evals re-use this compiled code for improved performance in EvaluateCachedData() methods
        self.userFunctionCodeObject = parser.compilest(st)
		name = token.tok_name.get(node[0])
	print(name, '', end = '')
	for i in range(1, len(node)):
		item = node[i]
		if type(item) is type([]):
			dump_and_modify(item)
		else:
			print(repr(item))
			if name == 'NUMBER':
				node[i] = repr(int(item) + 1)

ast = parser.expr('1 + 3')
list = ast.tolist()
dump_and_modify(list)

ast = parser.sequence2st(list)
print(eval(parser.compilest(ast)))

'''
eval_input testlist test or_test and_test not_test comparison expr xor_expr and_expr shift_expr arith_expr term factor power atom NUMBER '1'
PLUS '+'
term factor power atom NUMBER '3'
NEWLINE ''
ENDMARKER ''
6
[Finished in 0.2s]
'''



Example #17
0
import parser
Example #18
0
import parser
Example #19
0
 def get_st(self):
     return sequence2st(self.tree)