I'm writing a syntax controller for empirical formulas. It seems to be working fairly well, but there is one error that I can not seem to fix.
Here is the code:
import string
from linkedQFile import LinkedQ
ATOMER = ["H","He","Li","Be","B","C","N","O","F","Ne","Na","Mg","Al","Si","P","S","Cl","Ar"]
class Formelfel(Exception):
    pass
def readFormel():
    if q.peek() == None:
        print("Formel saknas. ")
    readMol()
    print("Formeln är syntaktiskt korrekt")
    #newline check?
def readMol():
    if q.peek() == None:
        return
    readGroup()
    readMol()
    return
def readGroup():
    if q.peek() == "(":
        print(q.get(), end="")
        if q.peek() in string.ascii_lowercase or q.peek() in string.ascii_uppercase:
            readMol()
        else:
            raise Formelfel
    if q.peek() == ")":
        print(q.get(), end="")
        readNum()
        return
    readAtom()
    try: 
        readNum()
    except Formelfel:
        pass
    return
def readAtom():
    X = readLetter()
    try:
        x = readletter() 
    except Formelfel:
        x = ""
    atom = X+x
    if atom in ATOMER:
        return
    rest=""
    while not q.isEmpty():
        rest += print(q.get(), end="")
    raise Formelfel("Okänd atom vid radslutet "+rest)
def readNum():
    try:
        if q.peek() != None:
            print(q.peek())
            while not q.peek() in string.ascii_uppercase and not q.peek() in string.ascii_lowercase and not q.peek() == "(" and not q.peek()==")": # If q.peek() is a number
                if q.peek() == None:
                    return
                int(q.get())    
        return
    except:
        raise Formelfel
def readLetter():
    if q.peek() in string.ascii_uppercase:
        x =q.get()
        print(x,end="")
        return x
    raise Formelfel
def readletter():
    if q.peek() == None:
        raise Formelfel
    if q.peek() in string.ascii_lowercase:
        x =q.get()
        print(x,end= "")
        return x
    raise Formelfel
formel= "Si(C3(COOH)2)4(H2O)7"
q = LinkedQ()
for symbol in formel:
    q.put(symbol)
readFormel()
I get the following output and error:
Si(
(C3
(CO
OO
OH
H)
)2
)4
(H2
O)
)7
Traceback (most recent call last):
  File "formelkoll.py", line 59, in readNum
    while not q.peek() in string.ascii_uppercase and not q.peek() in string.ascii_lowercase and not q.peek() == "(" and not q.peek()==")": # If q.peek() is a number
TypeError: 'in <string>' requires string as left operand, not NoneType
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "formelkoll.py", line 88, in <module>
    readFormel()
  File "formelkoll.py", line 12, in readFormel
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 19, in readMol
    readGroup()
  File "formelkoll.py", line 27, in readGroup
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 19, in readMol
    readGroup()
  File "formelkoll.py", line 27, in readGroup
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 19, in readMol
    readGroup()
  File "formelkoll.py", line 27, in readGroup
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 20, in readMol
    readMol()
  File "formelkoll.py", line 19, in readMol
    readGroup()
  File "formelkoll.py", line 32, in readGroup
    readNum()
  File "formelkoll.py", line 65, in readNum
    raise Formelfel
__main__.Formelfel
I don't understand why this error occurs, as I have an if statement:
if q.peek() != None:
before the row where the error occurs. In other words, why is None allowed to slip through this if statement?
 
    