Advertisement
Guest User

Untitled

a guest
Jul 18th, 2019
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.71 KB | None | 0 0
  1. #!/usr/bin/python3
  2. #AST gist.
  3.  
  4. from time import sleep
  5.  
  6. def strip_parens(input_string):
  7. '''
  8. this function is causing problems-- I initially naively assumed
  9. that there would only be an outermost layer of parentheses
  10. when we strip off the outermost layer, sometimes there are ')('
  11. pairs inside.
  12. '''
  13. """
  14. If the string begins and ends with parens, remove them
  15. If they aren't there at all, just return the string
  16. """
  17. if input_string[0] == '(' and input_string[-1] == ')':
  18. return input_string[1:-1]
  19. else:
  20. return input_string
  21.  
  22. def find_paren_index_pairs(input_string):
  23. '''
  24. This actually works for arbitrary strings. I think this is
  25. #closer to how I should actually be writing the AST parser.
  26. '''
  27. """
  28. Takes a string and returns the open/close pairs of parentheses.
  29. ...Assumes a well formed string.
  30. """
  31. pairs = []
  32. open_state = 0
  33. seen_parens = 0
  34. for input_index, char in enumerate(input_string):
  35. if char == '(':
  36. seen_parens += 1
  37. pairs.insert(0, [input_index, None])
  38. elif char == ')':
  39. for pair_index, pair in enumerate(pairs):
  40. if pair[1] is None:
  41. pairs[pair_index][1] = input_index
  42. break
  43. return pairs
  44.  
  45. def split_along_parens(input_string):
  46. """
  47. splits a string into three strings:
  48. the text found before the first '('.
  49. the text inside and up to the last ')'.
  50. the text after the last '('
  51.  
  52. 'first (list 1 (+ 2 3) 9)' --> 'first', '(list 1 (+ 2 3) 9)', ''
  53.  
  54. Breaks right now if there are multiple pairs of parentheses on the same
  55. level of the tree.
  56. """
  57. l_index, r_index = input_string.find('('), input_string.rfind(')') + 1
  58. #check for parens inside that range:
  59. inner_range = input_string[l_index + 1:r_index - 1]
  60. if '(' in inner_range and ')' in inner_range:
  61. print("INNER RANGE: {}".format(inner_range))
  62. inner_l_index, inner_r_index = input_string.find('('), input_string.rfind(')')
  63. '''
  64. I thought I could fix the problem by checking whether the pair was crossed
  65. i.e. there exists a ')' before the first '(' in the middle of the checked
  66. string.
  67. '''
  68. if inner_l_index > inner_r_index:
  69. r_index = inner_r_index + 1
  70. left, middle, right = (input_string[:l_index],
  71. input_string[l_index:r_index],
  72. input_string[r_index:])
  73. return left, middle, right
  74.  
  75. def parser(input_string, debug=False):
  76. """
  77. Takes a string as input, returns a nested array of strings and ints.
  78.  
  79. input: "(first (list 1 (+ 2 3) 9))"
  80. output: ['first', ['list', 1, ['+', 2, 3], 9]]
  81.  
  82. ... assumes a well formed string with matched pairs of parentheses
  83. and spaces as separators between elements.
  84. """
  85. if input_string == '':
  86. return ''
  87. #input_string = input_string.strip()
  88. input_string = strip_parens(input_string).strip()
  89. if '(' in input_string and ')' in input_string:
  90. left, middle, right = split_along_parens(input_string)
  91. left_output, middle_output, right_output = (parser(left),
  92. parser(middle),
  93. parser(right))
  94. l_is_list, r_is_list = (type(left_output) not in (str, int),
  95. type(right_output) not in (str, int))
  96. if l_is_list and not r_is_list:
  97. output = (*left_output, middle_output, right_output)
  98. elif not l_is_list and r_is_list:
  99. output = (left_output, middle_output, *right_output)
  100. elif l_is_list and r_is_list:
  101. output = (*left_output, middle_output, *right_output)
  102. else:
  103. output = (left_output, middle_output, right_output)
  104. output = [string for string in output if string != '']
  105. return output
  106. elif ' ' in input_string:
  107. output = input_string.split(' ')
  108. output = [int(string) if string.isdigit()
  109. else string
  110. for string in output]
  111. return output
  112. else:
  113. if input_string.isdigit():
  114. return int(input_string)
  115. else:
  116. return input_string
  117.  
  118. def interpreter(input_string):
  119.  
  120.  
  121. def main():
  122. tests = ("(1 1 1)",
  123. "(1 (1 1))",
  124. "(first (list 1 (+ 2 3) 9))",
  125. "(0 1 ((a b c) d) e f)",
  126. "(0 1 ((a b c) (1 2 3) d) e f)") #breaks on this case
  127.  
  128. for test in tests:
  129. print("input: {}".format(test))
  130. output = parser(test)
  131. print("output : {}".format(output))
  132.  
  133. plus_tests = ("(+ 1 1)",
  134. "(+ (+ 1 1) 4)",
  135. "(+ (+ 2 2) (+ 2 2))")
  136.  
  137. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement