8
8
class Lexer (object ):
9
9
START_IDENTIFIER = set (string .ascii_letters + '_' )
10
10
VALID_IDENTIFIER = set (string .ascii_letters + string .digits + '_' )
11
- START_NUMBER = set (string .digits + '-' )
12
11
VALID_NUMBER = set (string .digits )
13
12
WHITESPACE = set (" \t \n \r " )
14
13
SIMPLE_TOKENS = {
@@ -63,13 +62,22 @@ def tokenize(self, expression):
63
62
yield self ._match_or_else ('&' , 'and' , 'expref' )
64
63
elif self ._current == '`' :
65
64
yield self ._consume_literal ()
66
- elif self ._current in self .START_NUMBER :
65
+ elif self ._current in self .VALID_NUMBER :
67
66
start = self ._position
68
- buff = self ._current
69
- while self ._next () in self .VALID_NUMBER :
70
- buff += self ._current
67
+ buff = self ._consume_number ()
71
68
yield {'type' : 'number' , 'value' : int (buff ),
72
69
'start' : start , 'end' : start + len (buff )}
70
+ elif self ._current == '-' :
71
+ # Negative number.
72
+ start = self ._position
73
+ buff = self ._consume_number ()
74
+ if len (buff ) > 1 :
75
+ yield {'type' : 'number' , 'value' : int (buff ),
76
+ 'start' : start , 'end' : start + len (buff )}
77
+ else :
78
+ raise LexerError (lexer_position = start ,
79
+ lexer_value = buff ,
80
+ message = "Unknown token '%s'" % buff )
73
81
elif self ._current == '"' :
74
82
yield self ._consume_quoted_identifier ()
75
83
elif self ._current == '<' :
@@ -87,6 +95,13 @@ def tokenize(self, expression):
87
95
yield {'type' : 'eof' , 'value' : '' ,
88
96
'start' : self ._length , 'end' : self ._length }
89
97
98
+ def _consume_number (self ):
99
+ start = self ._position
100
+ buff = self ._current
101
+ while self ._next () in self .VALID_NUMBER :
102
+ buff += self ._current
103
+ return buff
104
+
90
105
def _initialize_for_expression (self , expression ):
91
106
if not expression :
92
107
raise EmptyExpressionError ()
0 commit comments