Package lepl :: Package _test :: Module magus
[hide private]
[frames] | no frames]

Source Code for Module lepl._test.magus

  1   
  2  # The contents of this file are subject to the Mozilla Public License 
  3  # (MPL) Version 1.1 (the "License"); you may not use this file except 
  4  # in compliance with the License. You may obtain a copy of the License 
  5  # at http://www.mozilla.org/MPL/ 
  6  # 
  7  # Software distributed under the License is distributed on an "AS IS" 
  8  # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 
  9  # the License for the specific language governing rights and 
 10  # limitations under the License. 
 11  # 
 12  # The Original Code is LEPL (http://www.acooke.org/lepl) 
 13  # The Initial Developer of the Original Code is Andrew Cooke. 
 14  # Portions created by the Initial Developer are Copyright (C) 2009-2010 
 15  # Andrew Cooke (andrew@acooke.org). All Rights Reserved. 
 16  # 
 17  # Alternatively, the contents of this file may be used under the terms 
 18  # of the LGPL license (the GNU Lesser General Public License, 
 19  # http://www.gnu.org/licenses/lgpl.html), in which case the provisions 
 20  # of the LGPL License are applicable instead of those above. 
 21  # 
 22  # If you wish to allow use of your version of this file only under the 
 23  # terms of the LGPL License and not to allow others to use your version 
 24  # of this file under the MPL, indicate your decision by deleting the 
 25  # provisions above and replace them with the notice and other provisions 
 26  # required by the LGPL License.  If you do not delete the provisions 
 27  # above, a recipient may use your version of this file under either the 
 28  # MPL or the LGPL License. 
 29   
 30  ''' 
 31  Tests for a bug reported for 3.2, 3.2.1 
 32  ''' 
 33   
 34  # pylint: disable-msg=W0614, W0401, C0103, R0201, R0914, R0915 
 35  # test 
 36  #@PydevCodeAnalysisIgnore 
 37   
 38   
 39  #from logging import basicConfig, DEBUG 
 40  from unittest import TestCase 
 41  from difflib import Differ 
 42   
 43  from lepl import * 
 44  from lepl.support.graph import ConstructorWalker 
 45  from lepl.matchers.matcher import Matcher, canonical_matcher_type,\ 
 46      MatcherTypeException, is_child 
 47  from lepl.matchers.memo import _LMemo, _RMemo, LMemo, RMemo 
 48  from lepl.matchers.transform import Transform, TransformationWrapper 
 49  from lepl.core.rewriters import NodeStats, Flatten, \ 
 50      ComposeTransforms, AutoMemoize, clone_matcher, RightMemoize, LeftMemoize 
 51   
 52   
53 -class MagusTest(TestCase):
54 ''' 55 Based on the original bug report. 56 ''' 57
58 - def test_magus(self):
59 ''' 60 This was failing. 61 ''' 62 #basicConfig(level=DEBUG) 63 64 name = Word(Letter()) > 'name' 65 66 expression = Delayed() 67 variable = Delayed() 68 69 function = (expression / '()') > 'function' 70 expression += (variable | function) > 'expression' 71 variable += (name | expression / '.' / name) 72 73 dotted_name = function & Eos() 74 75 parser = dotted_name.get_parse_string() 76 try: 77 parser("1func()") 78 assert False, 'expected left recursion' 79 except MemoException: 80 pass 81 dotted_name.config.auto_memoize().no_full_first_match() 82 parser = dotted_name.get_parse_string() 83 parser("1func()")
84 85 86 #class DelayedCloneTest(TestCase): 87 # ''' 88 # The original problem for 3.2 was related to clones losing children. 89 # ''' 90 # 91 # def test_clone(self): 92 # ''' 93 # Clone and check children. 94 # ''' 95 # a = Delayed() 96 # b = (a | 'c') 97 # a += b 98 # 99 # def simple_clone(node): 100 # ''' 101 # Clone the node. 102 # ''' 103 # walker = ConstructorWalker(node, Matcher) 104 # return walker(DelayedClone()) 105 # 106 # self.assert_children(b) 107 # bb = simple_clone(b) 108 # self.assert_children(bb) 109 # 110 # 111 # def assert_children(self, b): 112 # ''' 113 # Check children are non-None. 114 # ''' 115 ## print('>>>{0!s}<<<'.format(b)) 116 # assert is_child(b, Or) 117 # for child in b.matchers: 118 # assert child 119 120 121
122 -class CloneTest(TestCase):
123 ''' 124 Test various clone functions. 125 ''' 126
127 - def test_describe(self):
128 ''' 129 Use a description of the graph to check against changes. 130 ''' 131 #basicConfig(level=DEBUG) 132 133 name = Word(Letter()) > 'name' 134 135 expression = Delayed() 136 variable = Delayed() 137 138 function = (expression / '()') > 'function' 139 expression += (variable | function) > 'expression' 140 variable += (name | expression / '.' / name) 141 142 dotted_name = function & Eos() 143 base = dotted_name.tree() 144 # print(base) 145 desc0 = NodeStats(dotted_name) 146 print(desc0) 147 assert desc0.total == 18, desc0 148 self.assert_count(desc0, And, 5) 149 self.assert_count(desc0, Or, 2) 150 self.assert_count(desc0, Delayed, 2) 151 152 clone0 = clone_matcher(dotted_name) 153 # print(clone0.tree()) 154 diff = Differ() 155 diff_text = '\n'.join(diff.compare(base.split('\n'), clone0.tree().split('\n'))) 156 #print(diff_text) 157 descx = NodeStats(clone0) 158 print(descx) 159 assert descx == desc0 160 161 clone1 = Flatten()(dotted_name) 162 print(clone1.tree()) 163 desc1 = NodeStats(clone1) 164 print(desc1) 165 # flattened And (Or no longer flattened as Delayed intervenes) 166 assert desc1.total == 17, desc1 167 self.assert_count(desc1, And, 4) 168 self.assert_count(desc1, Or, 2) 169 self.assert_count(desc1, Delayed, 2) 170 self.assert_count(desc1, Transform, 7) 171 self.assert_count(desc1, TransformationWrapper, 7) 172 173 clone2 = ComposeTransforms()(clone1) 174 desc2 = NodeStats(clone2) 175 #print(desc2) 176 # compressed a transform 177 assert desc2.total == 17, desc2 178 self.assert_count(desc2, And, 4) 179 self.assert_count(desc2, Or, 2) 180 self.assert_count(desc2, Delayed, 2) 181 self.assert_count(desc2, Transform, 6) 182 self.assert_count(desc2, TransformationWrapper, 6) 183 184 clone3 = RightMemoize()(clone2) 185 desc3 = NodeStats(clone3) 186 #print(desc3) 187 assert desc3.total == 17, desc3 188 self.assert_count(desc3, _RMemo, 17) 189 self.assert_count(desc3, Delayed, 2) 190 191 clone4 = LeftMemoize()(clone2) 192 desc4 = NodeStats(clone4) 193 #print(desc4) 194 assert desc4.total == 17, desc4 195 self.assert_count(desc4, _LMemo, 20) 196 # left memo duplicates delayed 197 self.assert_count(desc4, Delayed, 3) 198 199 clone5 = AutoMemoize(left=LMemo, right=RMemo)(clone2) 200 desc5 = NodeStats(clone5) 201 #print(desc5) 202 assert desc5.total == 17, desc5 203 self.assert_count(desc5, _RMemo, 5) 204 self.assert_count(desc5, _LMemo, 15) 205 # left memo duplicates delayed 206 self.assert_count(desc5, Delayed, 3) 207 208 try: 209 clone3.config.clear() 210 clone3.parse_string('1join()') 211 assert False, 'Expected error' 212 except MemoException as error: 213 assert 'Left recursion was detected' in str(error), str(error) 214 215 clone4.config.clear() 216 clone4.parse_string('1join()') 217 clone5.config.clear() 218 clone5.parse_string('1join()')
219
220 - def assert_count(self, desc, type_, count):
221 ''' 222 Check the count for a given type. 223 ''' 224 try: 225 type_ = canonical_matcher_type(type_) 226 except MatcherTypeException: 227 pass 228 assert type_ in desc.types and len(desc.types[type_]) == count, \ 229 len(desc.types[type_]) if type_ in desc.types else type_
230