| Conditions | 29 |
| Total Lines | 120 |
| Lines | 0 |
| Ratio | 0 % |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like _lex() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # Sadly, re isn't available in rpython. |
||
| 206 | def _lex(tokens): |
||
| 207 | """Given a Python list of unicodes that look roughly like tokens, lex |
||
| 208 | them. Returns a Trifle exception if they aren't valid tokens. |
||
| 209 | |||
| 210 | """ |
||
| 211 | lexed_tokens = [] |
||
| 212 | |||
| 213 | for token in tokens: |
||
| 214 | found_match = False |
||
| 215 | |||
| 216 | for lexeme_name, regexp in LEXEMES: |
||
| 217 | match = rsre_core.match(regexp, token) |
||
| 218 | if match: |
||
| 219 | found_match = True |
||
| 220 | |||
| 221 | if lexeme_name == OPEN_PAREN: |
||
| 222 | lexed_tokens.append(OpenParen()) |
||
| 223 | elif lexeme_name == CLOSE_PAREN: |
||
| 224 | lexed_tokens.append(CloseParen()) |
||
| 225 | |||
| 226 | elif lexeme_name == OPEN_CURLY_PAREN: |
||
| 227 | lexed_tokens.append(OpenCurlyParen()) |
||
| 228 | elif lexeme_name == CLOSE_CURLY_PAREN: |
||
| 229 | lexed_tokens.append(CloseCurlyParen()) |
||
| 230 | |||
| 231 | elif lexeme_name == BOOLEAN: |
||
| 232 | if token == u'#true': |
||
| 233 | lexed_tokens.append(TRUE) |
||
| 234 | else: |
||
| 235 | lexed_tokens.append(FALSE) |
||
| 236 | elif lexeme_name == NULL_TYPE: |
||
| 237 | lexed_tokens.append(NULL) |
||
| 238 | |||
| 239 | elif lexeme_name == INTEGER: |
||
| 240 | integer_string = remove_char(token, "_") |
||
| 241 | |||
| 242 | # TODO: validate that the integer string is only numbers |
||
| 243 | lexed_tokens.append(Integer.fromstr(integer_string)) |
||
| 244 | |||
| 245 | elif lexeme_name == FLOAT: |
||
| 246 | float_string = remove_char(token, "_") |
||
| 247 | try: |
||
| 248 | lexed_tokens.append(Float(float(float_string))) |
||
| 249 | except ValueError: |
||
| 250 | return TrifleExceptionInstance( |
||
| 251 | lex_failed, u"Invalid float: '%s'" % token) |
||
| 252 | |||
| 253 | elif lexeme_name == FRACTION: |
||
| 254 | fraction_string = remove_char(token, "_") |
||
| 255 | fraction_parts = fraction_string.split('/') |
||
| 256 | numerator = fraction_parts[0] |
||
| 257 | denominator = fraction_parts[1] |
||
| 258 | |||
| 259 | # TODO: validate that the fraction string is only numbers |
||
| 260 | numerator = RBigInt.fromstr(numerator) |
||
| 261 | denominator = RBigInt.fromstr(denominator) |
||
| 262 | |||
| 263 | if denominator.eq(RBigInt.fromint(0)): |
||
| 264 | return TrifleExceptionInstance( |
||
| 265 | division_by_zero, |
||
| 266 | u"Can't have fraction denominator of zero: '%s'" % token) |
||
| 267 | |||
| 268 | fraction = Fraction(numerator, denominator) |
||
| 269 | |||
| 270 | if fraction.denominator.eq(RBigInt.fromint(1)): |
||
| 271 | lexed_tokens.append(Integer(fraction.numerator)) |
||
| 272 | else: |
||
| 273 | lexed_tokens.append(fraction) |
||
| 274 | |||
| 275 | elif lexeme_name == SYMBOL: |
||
| 276 | lexed_tokens.append(Symbol(token)) |
||
| 277 | elif lexeme_name == KEYWORD: |
||
| 278 | # todoc |
||
| 279 | lexed_tokens.append(Keyword(token[1:])) |
||
| 280 | elif lexeme_name == BYTESTRING: |
||
| 281 | string_end = match.match_end - 2 |
||
| 282 | |||
| 283 | # This is always true, but RPython doesn't support |
||
| 284 | # negative indexes on slices and can't prove the |
||
| 285 | # slice is non-negative. |
||
| 286 | if string_end >= 0: |
||
| 287 | contents = token[8:string_end] |
||
| 288 | else: |
||
| 289 | # Unreachable. |
||
| 290 | contents = u"" |
||
| 291 | |||
| 292 | lexed_tokens.append(Bytestring(unescape_bytestring_chars(contents))) |
||
| 293 | |||
| 294 | elif lexeme_name == STRING: |
||
| 295 | string_end = match.match_end - 1 |
||
| 296 | |||
| 297 | # This is always true, but RPython doesn't support |
||
| 298 | # negative indexes on slices and can't prove the |
||
| 299 | # slice is non-negative. |
||
| 300 | if string_end >= 0: |
||
| 301 | |||
| 302 | string_contents = token[1:string_end] |
||
| 303 | |||
| 304 | lexed_tokens.append(String(unescape_chars(string_contents, u'"'))) |
||
| 305 | elif lexeme_name == CHARACTER: |
||
| 306 | |||
| 307 | # TODO: use unescape_chars |
||
| 308 | if token == u"'\\n'": |
||
| 309 | lexed_tokens.append(Character(u'\n')) |
||
| 310 | elif token == u"'\\\\'": |
||
| 311 | lexed_tokens.append(Character(u'\\')) |
||
| 312 | elif token == u"'\\''": |
||
| 313 | lexed_tokens.append(Character(u"'")) |
||
| 314 | else: |
||
| 315 | lexed_tokens.append(Character(token[1])) |
||
| 316 | else: |
||
| 317 | assert False, u"Unrecognised token '%s'" % token |
||
| 318 | |||
| 319 | break |
||
| 320 | |||
| 321 | if not found_match: |
||
| 322 | return TrifleExceptionInstance( |
||
| 323 | lex_failed, u"Could not lex token: '%s'" % token) |
||
| 324 | |||
| 325 | return List(lexed_tokens) |
||
| 326 | |||
| 335 |