def test_load_from_dict(): src = {'rules': {'exp': ['exp1', 'exp2'], 'exp1': [False], 'exp2': [True]}} grammar = load(src) assert type(grammar) is Grammar assert grammar.root == 'exp' assert set(grammar.rules.keys()) == {'exp', 'exp1', 'exp2'}
def test_load_with_overridden_root(): src = ''' root: exp1 rules: exp: - exp1 - exp2 exp1: [ false ] expr2: [ true ] ''' assert load(src).root == 'exp1'
def test_load_from_string(): src = ''' rules: exp: - exp1 - exp2 exp1: [ false ] exp2: [ true ] ''' grammar = load(src) assert type(grammar) is Grammar assert grammar.root == 'exp' assert grammar.yaml == { 'exp': ['exp1', 'exp2'], 'exp1': [False], 'exp2': [True] }
def test_load_from_object_raises_TypeError(): with pytest.raises(TypeError): load(object())
def test_load_from_file(): assert load('tests/predicate.yml').root == 'predicate'
from sexpr import extend, inject, load, Sexpr grammar = load('tests/predicate.yml') def test_pure(): sexp = ['tautology', True] sexp = inject(sexp, lambda e: not e) sexp = extend(sexp, lambda e: ['not', e]) assert sexp == ['not', ['tautology', False]] sexp = inject(['and', ['lit', True], ['lit', False]], lambda left, right: ['or', left, right]) assert sexp == ['and', ['or', ['lit', True], ['lit', False]]] def test_inplace(): sexp = grammar.sexpr(['tautology', True]) sexp.inject(lambda e: not e) sexp.extend(lambda e: ['not', e]) assert sexp.tag == 'not' assert sexp.body == [['tautology', False]] assert sexp.sexpr == ['not', ['tautology', False]] q = sexp p = sexp.copy() sexp = Sexpr(['not', ['or', p, q]], grammar) sexp.inject(lambda exp: (['not', exp[1]], ['not', exp[2]])) sexp.extend(lambda exp: ['and', *exp[1:]])
import unittest import sexpr grammar = sexpr.load('tests/predicate.yml') class CompositionTest(unittest.TestCase): def test_cannot_match_terminal(self): e = ['name', 'foo'] self.assertFalse(grammar.matches(e)) def test_can_match_nonterminal(self): e = ['identifier', 'foo'] self.assertTrue(grammar.matches(e)) def test_cannot_match_nonexistent_symbol(self): e = ['foo', 'bar'] self.assertFalse(grammar.matches(e)) def test_matches_valid_regexpr(self): e = ['identifier', 'foo'] self.assertTrue(grammar.matches(e)) def test_cannot_match_invalid_regexpr(self): e = ['identifier', '&^51*='] self.assertFalse(grammar.matches(e))
import unittest import sexpr grammar = sexpr.load(''' rules: expr: - expr1 - expr2 expr1: - [ literal1 ] expr2: - [ literal2 ] literal1: [ true, false ] literal2: - true - false ''') class OtherTest(unittest.TestCase): '''Test alternative representations.''' def test_literal1(self): s = ['expr1', True] self.assertTrue(grammar.matches(s)) def test_literal2(self): s = ['expr2', True] self.assertTrue(grammar.matches(s))
convienience, as compiling a list of arguments for target function separetely is often handy. """ import ast import os import uuid from types import FunctionType, LambdaType from typing import Dict, List, Optional, Set, Union import sexpr from . import nodes cd = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) grammar = sexpr.load(os.path.join(cd, 'predicate.yml')) rules = grammar.yaml def read_argnames(sexp: List) -> Set[str]: """ Builds expression's argument list. Traversal is performeed in a DFS manner. """ names = set() if isinstance(sexp, list) and sexp and sexp[0] in grammar.top_tags: if sexp[0] == 'identifier': return set([sexp[1]]) else: for child in sexp[1:]:
from sexpr import Grammar, Sexpr, load, register def setup_function(): Grammar.registered_tags = {} grammar = load(''' root: exp1 rules: exp: - exp1 - exp2 exp1: [ false ] exp2: [ exp3 ] exp3: [ exp4 ] exp4: [ True, False ] ''') class Exp1(Sexpr): pass class Exp2(Sexpr): pass
import sexpr grammar = sexpr.load(''' rules: expr: - exactly_one - exactly_two - one_or_more - zero_or_more - optional - literal one_or_more: - [ expr+ ] zero_or_more: - [ expr* ] exactly_two: - [ expr, expr ] exactly_one: - [ expr ] optional: - [ 'expr?' ] literal: - [ lit ] lit: - true - false ''') def expr():