I'm solving such issue:
I need to implement a feature for a string to find errors in the usage of brackets.
If string is balanced, then I should return
{}
Success
If not, I need to mention the position of problematic bracket.
{[}
3
So for that reason I decided to create a class Bracket
class Bracket:
def __init__(self, bracket_type, position):
self.bracket_type = bracket_type
self.position = position
def Match(self, c):
if self.bracket_type == '[' and c == ']':
return True
if self.bracket_type == '{' and c == '}':
return True
if self.bracket_type == '(' and c == ')':
return True
return False
Next, I'm using stack, whether sting is balanced or not. I created a loop, going through every symbol, and if symbol is a bracket I want to assign it to my special class in order to match for closing one further.
if __name__ == "__main__":
text = sys.stdin.read()
brackets_stack = []
Balanced = True
for i, symbol in enumerate(str(text)):
if symbol in ['(', '[', '{']:
j = i
brackets_stack.append(symbol)
new_bracket = Bracket(brackets_stack[j], j)
elif new_bracket.Match(symbol) == True:
brackets_stack.pop(i)
elif len(brackets_stack) == 0:
print("Success")
But it works good only with cases like this
{}
Success
For other tests, like
[()]
It shows that array is not empty yet, as his tenth is equal to 1. I think the problem lies in variable new_bracket. After removing "(" from array my program doesn't compare "{" for matching.
I don't know why.
Can somebody help me?
Your code has a few problems. First, there are a few things that I want to address:
Your code will throw an error if the symbols string does not start with an opening bracket. This is because you initialize new_bracket inside of the first if statement. This would cause problems since if the first character is NOT an opening bracket, it will try to call new_bracket in the elif statement, and since it has not been initiated, it will raise an UnboundLocalError. This can be fixed with an elif symbol in [')', ']', '}']: return False. Since starting with a close bracket obviously means its unbalanced, this makes sense and prevents the program from calling new_bracket without it being initialized.
Your use of the j variable is useless since you never use it outside of the scope of that if statement. You could have just used i.
Your use of list.pop(i) may cause errors if i is out of range of brackets_stack. You don't need the index since you want the symbol at the end of the stack, which is automatically what list.pop() does.
elif len(brackets_stack) == 0: should not be inside of the for loop. This should be outside of the loop since you only want to say success after all the text has been processed.
new_bracket = Bracket(brackets_stack[j], j) is wrong in many ways. The first is that you don't want to make a new symbol with brackets_stack[j], you want it to be made with either text[j] or better yet, symbol. Another is that this will only be changed whenever a new open bracket is seen. However, if you find the match to that bracket, since you never change this variable, it will stay as the previous bracket. You should re-declare what the symbol of your new_bracket should be. The name itself is then misleading and is changed below.
With all this in mind, below is a revised version of what you want to do, encapsulated in a function. There are some stuff you need to add to your class as well.
class Bracket:
def __init__(self, bracket_type, position):
self.bracket_type = bracket_type
self.position = position
def Match(self, c):
if self.bracket_type: //handles empty bracket_type
if self.bracket_type == '[' and c == ']':
return True
if self.bracket_type == '{' and c == '}':
return True
if self.bracket_type == '(' and c == ')':
return True
return False
//update function to use the same object instead of initializing a new one each time (better space complexity)
def update(self, new_type, new_position):
self.bracket_type = new_type
self.position = new_position
// pass in text to check if text has balanced brackets or not
def isBalanced(text):
brackets_stack = []
current_bracket = Bracket('',0) //initialize an empty bracket
for i, symbol in enumerate(str(text)):
print(brackets_stack)
if symbol in ['(', '[', '{']:
brackets_stack.append(symbol)
current_bracket.update(symbol, i) //call update function
elif symbol in [')', ']', '}']:
return False
elif new_bracket.Match(symbol):
brackets_stack.pop()
else: //since it assumes symmetrical balanced brackets, this can return False immediately
return False
//same as saying return len(list) == 0
return not(len(brackets_stack))
This code assumes that text ONLY contains brackets. I do not know if this is a reasonable assumption and you should keep this in mind for whatever application you are using it for. Also, like MTset commented on your post, it also assumes simply, symmetrical, balanced brackets. [{]} will return False, although it is technically balanced.
Related
So we're working on stacks in my data structures class. Our task is to adapt the following sample code and improve it. The function uses stacks to determine whether a string is a mirror. Meaning something like "abcmcba". Our task is to rewrite this sample to return a more specific reason why it isn't a mirror instead of just true or false. Like if there's a mismatch of characters, an invalid char was used, or if one side is longer than the other. I got it done but I wasn't satisfied with my solution even though it met the criteria so I took another look at the sample and I think I may have found a problem that I would like your help to confirm
from Stack_array import Stack
MIRROR = "m"
CHARS = "abc"
def is_mirror(string):
mirror = True
stack = Stack()
n = len(string)
i = 0
#pushes all values in string to a stack
while i < n and string[i] != MIRROR:
if string[i] in CHARS:
stack.push(string[i])
i += 1
else:
mirror = False
# skip over the mirror character
i += 1
#Compares left and right sides by popping stacks.
while mirror and i < n and not stack.is_empty():
c = stack.pop()
if string[i] != c:
mirror = False
else:
i += 1
# check final conditions. Will check if one side is longer than the other.
if not (i == n and stack.is_empty()):
mirror = False
return mirror
The final if statement is where I see a possible error. If i is not equal to the length of the string and the stack isn't empty that means one side is longer than the other. the problem? In the while loop above it if we find that mirror is false prior to reaching the end of the string we'll stop incrementing i and stop popping values from the stack. Meaning that if I'm correct "if not (i == n and stack.is_empty()):" will ALWAYS trigger even if both sides in fact have equal length. In the example above this works out fine since it's false either way. But if we want more specific results like one side being longer than the other then the if statement will evaluate true and mirror will be overidden.
As an example
from Stack_array import Stack
MIRROR = "m"
CHARS = "abc"
def is_mirror(string):
mirror = True
stack = Stack()
n = len(string)
i = 0
#pushes all values in string to a stack
while i < n and string[i] != MIRROR:
if string[i] in CHARS:
stack.push(string[i])
i += 1
else:
mirror = "Invalid char"
# skip over the mirror character
i += 1
#Compares left and right sides by popping stacks.
while mirror and i < n and not stack.is_empty():
c = stack.pop()
if string[i] != c:
mirror = "Side character mismatch"
else:
i += 1
# check final conditions. Will check if one side is longer than the other.
if not (i == n and stack.is_empty()):
mirror = "Side length mismatch"
return mirror
And we feed it the string "abmcb
If we have a side character mismatch then i<n and the stack won't be empty. So then the side length mismatch result will override the character mismatch result even though the side lengths are in fact equal
This means that we'd need to fix this and ensure that the final check only runs if everything else is clear and we haven't hit any other errors so far. The specs for this adaption also say that the check only happens if everything else so far is clear. Is my hunch right?
Simply adapting the code to add special conditions doesn't work. I believe this is because of an error made by the professor involving an if statement and incrementation of variable i
Some of the issues:
In the first loop, when mirror is given a value, the loop continues and the loop condition will never change. Instead, the loop (and function) should exit.
In the second loop the loop condition includes mirror, but if all is well so far, mirror will be False, so the second loop will not execute. This should not be a condition of the loop.
Not a problem, but:
When mirror is given a value, the loop still continues. It would make more sense to exit the loop (and function) when a mismatch has been detected.
It is not good practice to have a function that can return different data types: sometimes False (boolean), sometimes a string. I would always return a string. If not problem is found, it could be "ok" or the empty string.
Shouldn't there be a check that "m" really occurs in the string and if not this is given its own reason?
Here is a correction:
MIRROR = "m"
CHARS = "abc"
def is_mirror(string):
stack = Stack()
n = len(string)
i = 0
while i < n and string[i] != MIRROR:
if string[i] in CHARS:
stack.push(string[i])
i += 1
else: # return when something is wrong
return "Invalid char"
if i == n: # A separate reason
return "Center character ('m') not found"
i += 1
# `mirror` is not a loop condition
while i < n and not stack.is_empty():
c = stack.pop()
if string[i] != c: # return
return "Side character mismatch"
i += 1
if not (i == n and stack.is_empty()):
return "Side length mismatch"
return "ok" # Don't return a boolean
It should be said that using a stack for this problem is overkill. Secondly, in Python a for...in loop is preferred over a while with a body that increments an index variable.
I have to write a function that receives a string and returns that string with the characters between "*" in uppercase, for example given that string: “I want *this text* to be uppercase”, it returns : “I want THIS TEXT to be uppercase”.
Here is the code that I have written:
l = []
def func(s):
inside = False
for i in s:
if i == "*" and not inside:
inside = True
while inside:
if i == "*":
inside = False
else:
i.upper()
l.append(i)
print(s)
When I run the program it prints out the text without any change.
What am I doing wrong?
By splitting the string at the character * then the uppercase entry is the odd one, then joining together. It is supposed that there are always an even number of * so it should be considered a kind of reserved character.
s = "I want *this text* to be uppercase and *this* as well"
print(' '.join((j.upper() if i%2!=0 else j for i, j in enumerate(s.split('*')))))
Output
I want THIS TEXT to be uppercase and THIS as well
First, this function isn't doing anything to s, so print(s) will print whatever was input, unchanged.
Second, the while inside loop needs to be outside of that if statement - right now, it's only accessed when i is an asterisk. Decrease that whole block's indent by one, and change while inside to if inside - that way, that code is executed for all values of i when inside is true.
Next, you need a way to signal when a second asterisk is reached, or a third, and so on. How about instead of assigning inside to True if i is an asterisk and inside is False, you swap the value of inside every time an asterisk is reached?
if i == '*':
inside = not inside
This negates any need to mess with changing inside in the second part of your code - it puts all the determining "am I inside/am I outside" logic in one place.
Next, you've declared a list l outside the scope of the function, and it looks like you want to add the edited characters to it so the answer you want is in that list in the end. But you want your answer in a string, not a list, and it's usually bad practice to declare a list in global scope and then edit it during a function call (if you call the function more than once, the list will get messy!). Declare an empty string l = '' at the beginning of the function, and then instead of appending characters to it, you can add them using the += operator.
You also need to make sure you're adding the uppercase version, l += i.upper() or the regular version, l += i, depending on whether or not inside is true. You can put all the code after the if i == '*' line in an else statement to catch all cases that i isn't an asterisk.
Putting it all together, your function can look something like this:
def func(s):
l = '' # the string that will be returned (the result of the function)
inside = False
for i in s:
if i == "*": # flip value of inside whenever you see an asterisk
inside = not inside
else: # otherwise, add i to the result
if inside:
l += i.upper() # uppercase if between two asterisks
else:
l += i # unchanged if not
return l # and return the modified string
Then, to test the function:
my_string = "I want *this text* to be uppercase"
my_string_modified = func(my_string)
print(my_string)
print(my_string_modified)
Output:
I want *this text* to be uppercase
I want THIS TEXT to be uppercase
There are definitely more "advanced" ways to do this, as pointed out in other answers on this post, but I hope this answer has helped to clarify what's going wrong in your code, how to fix it, and what some good practices are when you write this kind of thing. Writing code this way is, in my opinion, a really good way to understand how algorithmic processes can be designed and implemented.
I think you've tried to make this more complicated than it is. You need to find the index of both asterisks. From that you can get three slices of the original string and apply upper() to the slice between the asterisks. Note that this code will fail if there are fewer than two asterisks in the string.
def dotricks(s):
i = s.index('*')
j = s.index('*', i+i)
return s[0:i] + s[i+1:j].upper() + s[j+1:]
print(dotricks('I want *this text* to be uppercase'))
You are not changing the string in your code. In this edit below, I've assigned the letters of the string to a new variable. And used continue to skip over the "*". Also, at the end your append will give you a list of letters which you need to use .join() to concatentate.
Try this edit to your code, tested and working:
l = []
def func(s):
inside = False
temp = ""
for i in s:
if i == "*" and not inside:
inside = True
continue
if inside:
if i == "*":
inside = False
continue
else:
temp = i.upper()
else:
temp = i
l.append(temp)
new_string = "".join(l)
print(new_string)
return new_string
func("I want *this text* to be uppercase")
There are several issues here:
You don't return anything inside your function
Your while loop is pointless as i is not incremented inside of it
You need to assign i to i.upper()
You need to convey the input to a list
The corrected code would be as follows:
l = []
def func(s):
inside = False
for i in s:
if i == "*" and not inside:
inside = True
while inside:
if i == "*":
inside = False
else:
i.upper()
if i != "*":
l.append(i)
return l
I would leverage the power of the re module:
import re
st = "I want *this text* to be uppercase and *this one*"
v = re.findall("\*(.*?)\*", st)
for s in v:
st = st.replace(f'*{s}*', s.upper())
print(st)
Output:
>>> I want THIS TEXT to be uppercase and THIS ONE
Anyway, re-editing your code:
def func(s):
l = []
inside = False
for i in s:
if i == "*":
inside = not inside # switch inside on/off when * is found
if inside:
i = i.upper() # upper the character if inside == True
l.append(i)
return l
If you look at your original code, part of the problem is in the following logic:
if i == "*" and not inside:
inside = True # inside is set to True when * is found....
while inside:
if i == "*":
inside = False # and immediately set to False again!
So far I have done this. I am stuck on recursion. I have no idea how to move forward, joining and reversing etc.
def callrecursion(s):
a=s.index('(')
z=len(s) - string[::-1].index(')') -1
newStr=s[a+1:z]
# Something is missing here i cant figure it out
print(newStr)
return newStr
def reverseParentheses(s):
if '(' in s:
return reverseParentheses(callrecursion(s))
print('wabba labba dub dub')
else:
return s
string='a(bcdefghijkl(mno)p)q'
reverseParentheses(string)
EXPECTED OUTPUT : "apmnolkjihgfedcbq"
def reverseParentheses(s):
if '(' in s:
posopen=s.find('(')
s=s[:posopen]+reverseParentheses(s[posopen+1:])
posclose=s.find(')',posopen+1)
s=s[:posopen]+s[posopen:posclose][::-1]+s[posclose+1:]
return s
string='a(bcdefghijkl(mno)p)q'
print(string)
print(reverseParentheses(string))
print('apmnolkjihgfedcbq') # your test
string='a(bc)(ef)g'
print(string)
print(reverseParentheses(string))
The idea is to go 'inward' as long as possible (where 'inward' does not even mean 'nesting', it goes as long as there are any opening parentheses), so the innermost pairs are flipped first, and then the rest as the recursion returns. This way 'parallel' parentheses seem to work too, while simple pairing of "first opening parentheses" with "last closing ones" do not handle them well. Or at least that is what I think.
Btw: recursion is just a convoluted replacement for rfind here:
def reverseParentheses(s):
while '(' in s:
posopen=s.rfind('(')
posclose=s.find(')',posopen+1)
s=s[:posopen]+s[posopen+1:posclose][::-1]+s[posclose+1:]
return s;
(... TBH: now I tried, and the recursive magic dies on empty parentheses () placed in the string, while this one works)
I've come up with tho following logic (assuming the parentheses are properly nested).
The base case is the absence of parentheses in s, so it is returned unchanged.
Otherwise we locate indices of leftmost and rightmost opening and closing parentheses
(taking care of possible string reversal, so ')' might appear opening and '(' -- as closing).
Having obtained beg and end the remaining job is quite simple: one has to pass the reversed substring contained between beg and end to the subsequent recursive call.
def reverseParentheses(s):
if s.find('(') == -1:
return s
if s.find('(') < s.find(')'):
beg, end = s.find('('), s.rfind(')')
else:
beg, end = s.find(')'), s.rfind('(')
return s[:beg] + reverseParentheses(s[beg + 1:end][::-1]) + s[end + 1:]
Assuming that number of opening and closing brackets always match, this might be the one of the simplest method to reverse words in parenthesis:
def reverse_parentheses(st: str) -> str:
while True:
split1 = st.split('(')
split2 = split1[-1].split(')')[0]
st = st.replace(f'({split2})', f'{split2[::-1]}')
if '(' not in st and ')' not in st:
return st
# s = "(abcd)"
# s = "(ed(et)el)"
# s = "(ed(et(oc))el)"
# s = "(u(love)i)"
s= "((ng)ipm(ca))"
reversed = reverse_parentheses(s)
print(reversed)
You have a few issues in your code, and much of the logic missing. This adapts your code and produces the desired output:
def callrecursion(s):
a=s.index('(')
# 's' not 'string'
z=len(s) - s[::-1].index(')') -1
newStr=s[a+1:z][::-1]
# Need to consider swapped parentheses
newStr=newStr.replace('(', "$") # Placeholder for other swap
newStr=newStr.replace(')', "(")
newStr=newStr.replace('$', ")")
#Need to recombine initial and trailing portions of original string
newStr = s[:a] + newStr + s[z+1:]
return newStr
def reverseParentheses(s):
if '(' in s:
return reverseParentheses(callrecursion(s))
print('wabba labba dub dub')
else:
return s
string='a(bcdefghijkl(mno)p)q'
print(reverseParentheses(string))
>>>apmnolkjihgfedcbq
While the existing O(n^2) solutions were sufficient here, this problem is solvable in O(n) time, and the solution is pretty fun.
The idea is to build a k-ary tree to represent our string, and traverse it with DFS. Each 'level' of the tree represents one layer of nested parentheses. There is one node for each set of parentheses, and one node for each letter, so there are only O(n) nodes in the tree.
For example, the tree-nodes at the top level are either:
A letter that is not contained in parentheses
A tree-node representing a pair of parentheses at the outermost layer of our string, which may have child tree-nodes
To get the effect of reversals, we can traverse the tree in a depth-first way recursively. Besides knowing our current node, we just need to know if we're in 'reverse mode': a boolean to tell us whether to visit our node's children from left to right, or right to left.
Every time we go down a level in our tree, whether we're in 'reverse mode' or not is flipped.
Python code:
class TreeNode:
def __init__(self, parent=None):
self.parent = parent
self.children = []
def reverseParentheses(s: str) -> str:
root_node = TreeNode()
curr_node = root_node
# Build the tree
for let in s:
# Go down a level-- new child
if let == '(':
new_child = TreeNode(parent=curr_node)
curr_node.children.append(new_child)
curr_node = new_child
# Go back to our parent
elif let == ')':
curr_node = curr_node.parent
else:
curr_node.children.append(let)
answer = []
def dfs(node, is_reversed: bool):
nonlocal answer
num_children = len(node.children)
if is_reversed:
range_start, range_end, range_step = num_children-1, -1, -1
else:
range_start, range_end, range_step = 0, num_children, 1
for i in range(range_start, range_end, range_step):
if isinstance(node.children[i], str):
answer.append(node.children[i])
else:
dfs(node.children[i], not is_reversed)
dfs(root_node, False)
return ''.join(answer)
Here is the correct version for your callrecursion function:
def callrecursion(text):
print(text)
a = text.find('(') + 1
z = text.rfind(')') + 1
newStr = text[:a - 1] + text[a:z-1][::-1].replace('(', ']').replace(')', '[').replace(']', ')').replace('[', '(') + text[z:]
return newStr
You probably have to take into account if the parethesis is the first/last character.
The goal is to implement a simplification operation: remove the parentheses around the very first element in an expression tree and in each of its sub-expression trees, where the expression is given as a string input enclosed in various parentheses. This must work for an arbitrary number of parentheses, so for example:
(12)3((45)6) -> 123(456), remove the parentheses around 12 then around 45
((12)3)4(((5)67)8) -> 1234(5678), remove the parentheses around 12, then 123, then 5, then 567. Do not remove the parentheses around 5678 since that is the second element.
How do I do this?
EDIT: So far what I have is this:
def simplify(expression):
"""
call itself recursively until no consecutive parentheses exist
"""
result = []
consec_parens = 0
inside_nested = False
for char in expression:
if char == ')' and inside_nested:
inside_nested = False
consec_parens = 0
continue
if char == '(':
consec_parens += 1
else:
consec_parens = 0
if consec_parens == 2:
inside_nested = True
else:
result.append(char)
result = ''.join(result)
if result == expression:
return result
return simplify(result)
It works for all cases where the number of nested parentheses is at least two, but it doesn't work for the head, i.e. for (AB)C, it does not remove the parentheses around AB. However, for ((AB)C) it removes the parentheses around AB resulting in (ABC).
This can be viewed as a finite state machine (with three states) which you instantiate once per level, where each ( symbol creates a new level. Alternatively, it is a deterministic pushdown automaton with two trivial states (an in-progress state and a done state, neither of which we model explicitly) and three stack symbols, each representing the state of the machine for the current level:
Before - The state we are in immediately after entering a level. Encountering any characters except ) transitions to some other state.
Inside - The state we are in while inside parentheses that need to be removed. Entered by encoutering a ( while in Before.
Done - The state we are in when the current level has been processed. This means that either we already removed a set of parentheses or we did not need to, since the first element wasn't enclosed in them.
Additionally, encountering a ( pushes a new symbol onto the stack, which models entering a new level, and a ) pops the one symbol from it, which models leaving from a level. All input characters get appended onto the result except when the Before → Inside and Inside → Done transitions occur.
The following code is a simple translation of the above into Python:
from enum import Enum
class State(Enum):
Before = 0
Inside = 1
Done = 2
def simplify(expression):
levels = [State.Before]
result = []
for c in expression:
if c == '(':
if levels[-1] == State.Before:
levels[-1] = State.Inside
else:
result.append(c)
levels.append(State.Before)
elif c == ')':
levels.pop()
if levels[-1] == State.Inside:
levels[-1] = State.Done
else:
result.append(c)
else:
if levels[-1] == State.Before:
levels[-1] = State.Done
result.append(c)
return ''.join(result)
Testing the above out, we get:
>>> simplify('(12)3((45)6)')
'123(456)'
>>> simplify('((12)3)4(((5)67)8)')
'1234(5678)'
>>> simplify('(AB)C')
'ABC'
>>> simplify('((AB)C)')
'ABC'
I am having an issue parsing a string and adding parenthesis to it in Python. One of my issues is that the string may be input in a fully parenthesized manner (ie (01U(1U0))) or it may be none at all (ie 01U1U0). The grammar that I cannot seem to split it on is:
A -> e* | (eUe)
e -> any combination of chars from the grammar
The e* has higher precedence and than the U.
Hopefully this makes sense. Anyone have any ideas how I can parse through and check parenthesis?
What is probably the simplest way to write a parser from a LL grammar is to have one function per non-terminal symbol. This function should eat the characters from the input string corresponding to one reduction of the rules. Below is the parser corresponding to the grammar
A -> e+ | '(' A 'U' A ')'
e -> '0' | '1'
This is not exactly the grammar you wanted, but it was more relevent from the examples you gave. The grammar is LL(1), you just need to read one character to know how to proceed. The following parser defines two functions A() and e() for those two non-terminal symbols :
class MySyntaxError(Exception):
def __init__(self, text, index):
self.text = text
self.index = index
def __str__(self):
return "Syntax error at index " + repr(self.index) + ": " + self.text
def parse(input):
global index
index = 0
def eat_char(set):
global index
if index < len(input) and input[index] in set:
index += 1
else:
raise MySyntaxError("expected char in " + repr(set), index)
def e():
eat_char(['0', '1'])
def A():
global index
if index == len(input): # Successfully parsed
return
elif input[index] in ['0', '1']:
while (input[index] in ['0', '1']):
e()
elif input[index] is '(':
eat_char(['('])
A()
eat_char(['U'])
A()
eat_char([')'])
else:
raise MySyntaxError("expected char '0', '1' or '('", index)
A()
if index != len(input): # Parsing didn't reach the end of the string
raise MySyntaxError("parsing ended before the end of the input", index)
def test(string):
try:
parse(string)
print "The string " + string + " have been successfully parsed"
except MySyntaxError as e:
print "The string " + string + " can't be parsed:"
print e
test("(01U(1U0))")
test("(01U(1U0)") # Missing parenthesis, syntax error
test("(01U(1U0)))") # Too many parenthesis, syntax error
test("01U(1U0)") # No parenthesis, syntax error
Note taht using e* instead of e+ makes empty reducing to A which complicates the parser.
The push-down automata is hidden in the parser. o build the automaton from the grammar is not so simple. Here, the PDA have only one state. We can describe the automaton this way:
from state [1]
read a '0' or a '1' and loop into state [1]
read a '(', push the parenthesis and loop into state [1]
read a 'U', when there is an open parenthesis on the top of stack, push the 'U' and loop into state [1]
read a ')', when there is a 'U' on the top of the stack, pop the 'U', pop the opend parenthesis following, and loop into state[1]
There is a straightforward way to write this automaton in Python. Usually, you need a goto to write an automaton. Each state binds to a label, and going from one state to another is done with a goto. Unfortunately, there is no goto in Python. Howeve, since you have only one state, it isn't necessary and a loop will do:
def parse(input):
index = 0
stack = [];
def top():
if len(stack) > 0:
return stack[len(stack)-1]
else:
return None
while index < len(input):
if input[index] in ['0', '1']:
pass
elif input[index] is '(':
stack.append('(')
elif input[index] is 'U' and top() == '(':
stack.append('U')
elif input[index] is ')' and top() == 'U':
stack.pop()
stack.pop()
else:
raise MySyntaxError("Unexpected char '" + input[index] + "'", index)
index += 1
if len(stack):
raise MySyntaxError("unterminated input", index)
This is a PDA with an explicit stack. The previous parser used the program stack instead of an implicit stack, and remembered the number of parenthesis read in the number of recursive calls. This second parser is usefull when you want to check the validity of a string. But it is unhandy when you want to produce a representation of the input, like an Abstract Syntax Tree: they are usually built from grammar and thus easier to produce from the first parser. The first one is also easier to read as you don't have to compute the automaton to understand it.