I'm trying to create a function that returns True is the string passed in is '1'(valid) or '1*'(valid) or in the form of '(' + valid + '|' + valid + ')' (valid). What I mean by the last part is for example:
(1|1) <- since its in the form of '(' + valid + '|' + valid + ')' and '1' is valid.
((1|1)|1) <- since its in the form of '(' + valid + '|' + valid + ')' and (1|1) is valid and so is '1'
((1|(1|1))|1) <- since its in the form of '(' + valid + '|' + valid + ')' and (1|(1|1)) is valid and so is '1'
My plan:
My code based on my plan:
def check(s):
    if s == '1':
        return True
    elif s == '1'+'*':
        return True
    else:
        if s.startswith('(') and s.endswith(')'):
            #TO-DO
            pass
    return False 
Some examples:
check('((1|1)|1)')
True
check('((1|1*)|1)')
True
check('(1|1)')
True
check('1')
True
check('1*')
True
check('((1|(1|1))|1)')
True
check('((1|(1|1))|((1|(1|1))|1))')
True
check('*1')
False
check('2')
False
check('((1|(1|1));1)')
False
I spent 3 days on this and still couldn't figure out how to do the recursive step so I'm hoping someone can help me with this. I can't figure out how to find the '*' symbol that is not within another set of brackets. I think if I'am able to find that '*' symbol than I can do the rest myself.
I'm sure that we can do this using the re module but let's just pretend we can't use that.
For parsing small grammars like this, I would suggest you to simplify them manually to a point where you can apply a non-backtracking recursive descent parser. The grammar you gave is:
valid ::= "1*" | "1" | "(" valid "|" valid ")"
so it is already non-left-recursive and ready to go, you just have to prefer 1* over 1. I suggest your parser functions to have type string -> (bool, string), where the bool indicates whether the parsing was successful and the second component is the unparsed rest of the string. Instead of the bool, you can also return an internal representation (AST) of the parsed string.
As an example, here is a parser for the valid production:
def valid(s):
    if s.startswith('1*'):
        return True, s[2:]
    if s.startswith('1'):
        return True, s[1:]
    if s.startswith('('):
        success, rest = valid(s[1:])
        if not success or not rest.startswith('|'): return False, s
        success, rest = valid(rest[1:])
        if not success or not rest.startswith(')'): return False, s
        return True, rest[1:]
    return False, s
def check(s):
    return valid(s) == (True, '')
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With