code_junkie

Reversing a regular expression in python

Nov 13th, 2011
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.95 KB | None | 0 0
  1. import re
  2. import string
  3.  
  4. def traverse(tree):
  5. retval = ''
  6. for node in tree:
  7. if node[0] == 'any':
  8. retval += 'x'
  9. elif node[0] == 'at':
  10. pass
  11. elif node[0] in ['min_repeat', 'max_repeat']:
  12. retval += traverse(node[1][2]) * node[1][0]
  13. elif node[0] == 'in':
  14. if node[1][0][0] == 'negate':
  15. letters = list(string.ascii_letters)
  16. for part in node[1][1:]:
  17. if part[0] == 'literal':
  18. letters.remove(chr(part[1]))
  19. else:
  20. for letter in range(part[1][0], part[1][1]+1):
  21. letters.remove(chr(letter))
  22. retval += letters[0]
  23. else:
  24. if node[1][0][0] == 'range':
  25. retval += chr(node[1][0][1][0])
  26. else:
  27. retval += chr(node[1][0][1])
  28. elif node[0] == 'not_literal':
  29. if node[1] == 120:
  30. retval += 'y'
  31. else:
  32. retval += 'x'
  33. elif node[0] == 'branch':
  34. retval += traverse(node[1][1][0])
  35. elif node[0] == 'subpattern':
  36. retval += traverse(node[1][1])
  37. elif node[0] == 'literal':
  38. retval += chr(node[1])
  39. return retval
  40.  
  41. print traverse(re.sre_parse.parse(regex).data)
  42.  
  43. In [1]: import re
  44.  
  45. In [2]: a = re.sre_parse.parse("[abc]+[def]*d?z")
  46.  
  47. In [3]: a
  48. Out[3]: [('max_repeat', (1, 65535, [('in', [('literal', 97), ('literal', 98), ('literal', 99)])])), ('max_repeat', (0, 65535, [('in', [('literal', 100), ('literal', 101), ('literal', 102)])])), ('max_repeat', (0, 1, [('in', [('category', 'category_digit')])])), ('literal', 122)]
  49.  
  50. In [4]: eval(str(a))
  51. Out[4]:
  52. [('max_repeat',
  53. (1, 65535, [('in', [('literal', 97), ('literal', 98), ('literal', 99)])])),
  54. ('max_repeat',
  55. (0,
  56. 65535,
  57. [('in', [('literal', 100), ('literal', 101), ('literal', 102)])])),
  58. ('max_repeat', (0, 1, [('in', [('category', 'category_digit')])])),
  59. ('literal', 122)]
  60.  
  61. In [5]: a.dump()
  62. max_repeat 1 65535
  63. in
  64. literal 97
  65. literal 98
  66. literal 99
  67. max_repeat 0 65535
  68. in
  69. literal 100
  70. literal 101
  71. literal 102
  72. max_repeat 0 1
  73. in
  74. category category_digit
  75. literal 122
  76.  
  77. import re
  78. class REParser(object):
  79. """Parses an RE an gives the least greedy value that would match it"""
  80.  
  81. def parse(self, parseInput):
  82. re.compile(parseInput) #try to parse to see if it is a valid RE
  83. retval = ""
  84. stack = list(parseInput)
  85. lastelement = ""
  86. while stack:
  87. element = stack.pop(0) #Read from front
  88. if element == "\":
  89. element = stack.pop(0)
  90. element = element.replace("d", "0").replace("D", "a").replace("w", "a").replace("W", " ")
  91. elif element in ["?", "*"]:
  92. lastelement = ""
  93. element = ""
  94. elif element == ".":
  95. element = "a"
  96. elif element == "+":
  97. element = ""
  98. elif element == "{":
  99. arg = self._consumeTo(stack, "}")
  100. arg = arg[:-1] #dump the }
  101. arg = arg.split(",")[0] #dump the possible ,
  102. lastelement = lastelement * int(arg)
  103. element = ""
  104. elif element == "[":
  105. element = self._consumeTo(stack, "]")[0] # just use the first char in set
  106. if element == "]": #this is the odd case of []<something>]
  107. self._consumeTo(stack, "]") # throw rest away and use ] as first element
  108. elif element == "|":
  109. break # you get to an | an you have all you need to match
  110. elif element == "(":
  111. arg = self._consumeTo(stack, ")")
  112. element = self.parse( arg[:-1] )
  113.  
  114. retval += lastelement
  115. lastelement = element
  116. retval += lastelement #Complete the string with the last char
  117.  
  118. return retval
  119.  
  120. def _consumeTo(self, stackToConsume, endElement ):
  121. retval = ""
  122. while not retval.endswith(endElement):
  123. retval += stackToConsume.pop(0)
  124. return retval
Add Comment
Please, Sign In to add comment