Changeset 2
- Timestamp:
- 11/08/04 18:32:32 (4 years ago)
- Files:
-
- trunk/airspeed.py (modified) (6 diffs)
- trunk/airspeed_test.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/airspeed.py
r1 r2 3 3 import re 4 4 5 class SyntaxError(Exception): 6 pass 7 5 class SyntaxError(Exception): pass 8 6 9 7 class Tokeniser: 10 8 PLAIN, IF, PLACEHOLDER, END = range(4) 11 9 12 REST = '(.*)$'13 10 UP_TO_NEXT_TEMPLATE_BIT = re.compile('^(.*?)((?:#|\$).*)', re.MULTILINE + re.DOTALL) 14 11 REST = '(.*)$' 15 12 NAME_OR_CALL = '[a-z0-9_]+(?:\(\))?' 16 13 EXPRESSION = '(' + NAME_OR_CALL + '(?:\.' + NAME_OR_CALL + ')*)' 17 PLACEHOLDER_PATTERN = re.compile('^\$(!?)({?)' + EXPRESSION + '(}?)' + REST, re.IGNORECASE )18 BEGIN_IF_PATTERN = re.compile('^#if[ \t]*\([ \t]*\$' + EXPRESSION + '[ \t]*\)' + REST, re.IGNORECASE )19 END_PATTERN = re.compile('^#end' + REST, re.IGNORECASE )20 14 PLACEHOLDER_PATTERN = re.compile('^\$(!?)({?)' + EXPRESSION + '(}?)' + REST, re.IGNORECASE + re.DOTALL + re.MULTILINE) 15 BEGIN_IF_PATTERN = re.compile('^#if[ \t]*\([ \t]*\$' + EXPRESSION + '[ \t]*\)' + REST, re.IGNORECASE + re.DOTALL + re.MULTILINE) 16 END_PATTERN = re.compile('^#end' + REST, re.IGNORECASE + re.DOTALL + re.MULTILINE) 17 21 18 def tokenise(self, text): 22 19 while True: … … 43 40 continue 44 41 raise SyntaxError("invalid token: %s" % text[:40]) 45 42 46 43 def get_placeholder(self, match): 47 44 silent, open_brace, var_name, close_brace, rest = match.groups() … … 57 54 58 55 class Parser: 59 56 60 57 def __init__(self): 61 58 self.data = {} 62 59 63 60 def merge(self, content): 64 61 output = [] 65 62 filter_output_at_nesting_level = [False] 66 for token_type, token_value in Tokeniser().tokenise(str(content)): 63 tokens = Tokeniser().tokenise(str(content)) 64 for token_type, token_value in tokens: 67 65 filter_at_this_level = filter_output_at_nesting_level[-1] 68 66 if token_type == Tokeniser.PLAIN: … … 90 88 continue 91 89 raise SyntaxError("invalid token: %s" % text[:40]) 92 90 93 91 if len(filter_output_at_nesting_level) > 1: 94 92 raise SyntaxError("Unclosed block") 95 93 return ''.join(output) 96 94 97 95 98 96 def find(self, expression): … … 111 109 if o in (None, self.data): return None 112 110 return o 113 114 111 112 115 113 def __setitem__(self, name, value): 116 114 self.data[name] = value … … 121 119 def __init__(self, content): 122 120 self.content = content 123 121 124 122 def __str__(self): 125 123 return self.content 126 127 124 128 129 125 trunk/airspeed_test.py
r1 r2 39 39 parser["name"] = "World" 40 40 self.assertEquals("Hello World.", parser.merge(template)) 41 41 42 42 def test_unmatched_braces_raises_exception(self): 43 43 parser = airspeed.Parser() … … 51 51 parser["name"] = "World" 52 52 self.assertEquals("Hello World}.", parser.merge(template)) 53 53 54 54 def test_can_return_value_from_an_attribute_of_a_context_object(self): 55 55 parser = airspeed.Parser() … … 69 69 parser["name"] = o 70 70 self.assertEquals("Hello Chris", parser.merge(template)) 71 71 72 72 def test_can_return_value_from_a_method_of_a_context_object(self): 73 73 parser = airspeed.Parser() … … 83 83 parser["name"] = "Steve" 84 84 self.assertEquals("Hello your name is Steve Good to see you", parser.merge(template)) 85 85 86 86 def test_when_if_statement_resolves_to_false_the_content_is_skipped(self): 87 87 parser = airspeed.Parser() … … 108 108 parser["show_greeting"] = True 109 109 parser["is_birthday"] = True 110 self.assertEquals(" Hello Steve.\nHappy Birthday\n.\nOff out later?", parser.merge(template))111 112 110 self.assertEquals("hello Steve.\nHappy Birthday\n.\nOff out later?", parser.merge(template)) 111 112 113 113 if __name__ == '__main__': 114 reload(airspeed) 114 115 try: main() 115 116 except SystemExit: pass
