【发布时间】:2015-04-20 01:40:29
【问题描述】:
这将是一个很长的问题,希望大家耐心等待。
我正在编写一个程序来检查分子式的语法是否正确。
我有一个 BNF 语法:
<formel>::= <mol> \n
<mol> ::= <group> | <group><mol>
<group> ::= <atom> |<atom><num> | (<mol>) <num>
<atom> ::= <LETTER> | <LETTER><letter>
<LETTER>::= A | B | C | ... | Z
<letter>::= a | b | c | ... | z
<num> ::= 2 | 3 | 4 | ...
这是我的代码:
from linkedQFile import LinkedQ
import string
import sys
ATOMER = ["H","He","Li","Be","B","C","N","O","F","Ne","Na","Mg","Al","Si","P","S","Cl","Ar"]
class FormelError(Exception):
pass
class Gruppfel(Exception):
pass
q = LinkedQ()
formel= "(Cl)2)3"
for symbol in formel:
q.put(symbol)
def readNum():
"""Reads digits larger than 1. Raises exception if condition is not fulfilled."""
try:
if int(q.peek()) >= 2:
print(q.peek())
q.get()
return
else:
q.get()
print("Too small digit at the end of row: "+getRest())
sys.exit()
except (ValueError,TypeError):
raise FormelError("Not a number.")
def readletter():
"""Reads lowercase letters and returns them."""
if q.peek() in string.ascii_lowercase:
print(q.peek())
return q.get()
else:
raise FormelError("Expected lowercase letter.")
def readLetter():
"""Reads capital letters and returns them."""
if q.peek() in string.ascii_uppercase:
print(q.peek())
return q.get()
else:
raise FormelError("Expected capital letter.")
def readAtom():
"""Reads atoms on the form X and Xx. Raises Exception if the format for an atom is not fulfilled or if the atom does not exist."""
X = ""
try:
X += readLetter()
except FormelError:
print("Missing capital letter at end of row: "+getRest())
sys.exit()
return
try:
x = readletter()
atom = X+x
except (FormelError, TypeError):
atom = X
if atom in ATOMER:
return
else:
raise FormelError("Unknown atom.")
def readGroup():
if q.peek() in string.ascii_uppercase or q.peek() in string.ascii_lowercase:
try:
readAtom()
except:
print("Unknown atom at end of row: "+getRest())
sys.exit()
try:
while True:
readNum()
except FormelError:
pass
return
if q.peek() == "(":
print(q.peek())
q.get()
try:
readMol()
except FormelError:
pass
if q.peek() == ")":
print(q.peek())
q.get()
else:
print("Missing right parenthesis at end of row: "+ getRest())
sys.exit()
return
digitfound = False
try:
while True:
readNum()
digitfound = True
except:
if digitfound:
return
print("Missing digit at end of row: "+getRest())
sys.exit()
return
raise FormelError("Incorrect start of group")
def readMol():
try:
readGroup()
except FormelError:
print("Incorrect start of group at end of row: "+getRest())
raise FormelError
if q.peek() == None:
return
if not q.peek() == ")":
try:
readMol()
except FormelError:
pass
def readFormel():
try:
readMol()
except:
return
print("Correct formula")
def getRest():
rest = ""
while not q.isEmpty():
rest += q.get()
return rest
readFormel()
现在代码应该接受一些给定的公式,并为一些给定的不正确公式提供错误代码。让我们看看这些给定的公式:
正确: Si(C3(COOH)2)4(H2O)7
不正确: H2O)Fe
(Cl)2)3
程序接受正确的公式,但不幸的是也接受不正确的公式。原因在于:
中的if语句if not q.peek() == ")":
try:
readMol()
except FormelError:
pass
使右侧的括号不平衡(右侧有一个或多个括号过多)滑过代码,而不是被检测为“组”的不正确开头。我该如何解决这个问题,同时仍然让 Si(C3(COOH)2)4(H2O)7 被接受为语法正确?
感谢您的耐心等待:)
【问题讨论】:
-
如果您认为我的回答有用,请点赞。
标签: python parsing syntax formula bnf