我试图做一个计算C程序的一些东西的程序,我遇到的问题是,我试图计算行数:
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)
它不计算我的行,这里是输入和输出的一个例子:
for
if
else
switch
exit
Number of if´s: 1
Number of for´s: 1
Number of While´s: 0
Number of else´s: 1
Number of switche´s: 1
Number of lines: 1
但是每当我按Enter键编写一行新代码时,它都不会被计算,如果我按Enter键而不写任何内容,则会出现此错误:
Traceback(最近一次调用最后一次):文件 “C:/Users/User/PycharmProjects/practicas/firma_digital.py”,第80行, 在 如果tok.type不是None:AttributeError:'NoneType'对象没有属性'type'
这是我的所有代码:
import ply.lex as lex
import ply.yacc as yacc
FinishProgram=0
Enters=0
Fors=0
Whiles=0
ifs=0
elses=0
Switches=0
reserved = {
'if' : 'IF',
'for' : 'FOR',
'while': 'WHILE',
'else': 'ELSE',
'switch': 'SWITCH'
}
tokens = [
'ID',
'COLON',
'SEMICOLON',
]+ list(reserved.values()) #Palabras reservadas
t_COLON= r','
t_SEMICOLON=r';'
def t_ID(t):
r'[a-zA-Z_][a-zA-Z0-9_]*'
t.type = reserved.get(t.value, 'ID')
return t
t_ignore=r' '
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)
def t_error(t):
print("This thing failed")
t.lexer.skip(1)
lexer=lex.lex()
#def p_gram_sets(p):
# '''
# gram : SETS SEMICOLON
# | empty
#'''
#if p[1]:
# print(p[1])
# print("SETS")
def p_empty(p):
'''
empty :
'''
p[0]=None
def p_error(p):
print("Syntax error in input!")
parser=yacc.yacc()
while FinishProgram==0:
s=input('')
lexer.input(s)
tok = lexer.token()
if tok.type is not None:
if tok.type=='IF':
ifs+=1
elif tok.type=='FOR':
Fors+=1
elif tok.type=='WHILE':
Whiles+=1
elif tok.type=='ELSE':
elses+=1
elif tok.type=='SWITCH':
Switches+=1
#parser.parse(s)
if "exit" in s:
print("Number of if´s: "+ str(ifs) + "\n"+"Number of for´s: "+str(Fors)+"\n"+"Number of While´s: "+str(Whiles)+"\n"+"Number of else´s: "+str(elses)+"\n"+"Number of switche´s: "+str(Switches)+"\n"+"Number of lines: "+str(tok.lineno))
FinishProgram=1
答案 0 :(得分:1)
并不是说ply不计算换行符。它从未见过它们,因为您使用input()
重复调用它。
从Python文档(强调添加):
输入([提示])
如果存在prompt参数,则将其写入标准输出而不带尾随换行符。然后该函数从输入中读取一行,将其转换为字符串(剥离尾随换行符),然后返回该行。
lex.lex
的正常用法是
此外,您正在打印
... + str(tok.lineno)
而不是
... + str(lexer.lineno)
在最后一个令牌被标记后,lex.lex
返回None
,因此当您的循环终止时,您可以期望tok
为Null
,因此它是错误的尝试提取它的lineno
属性。 (但是,在您的情况下,只有在您尝试标记的行为空时才会发生这种情况,因为您只使用每行上的第一个标记。)您希望记录在词法分析器对象中的行数,这是您更新的计数你的行动。
如果你想处理整个文件(这是解析器的常见情况,而不是逐行计算器),你需要读取文件的全部内容(或者stdin,视情况而定) )。对于非交互式使用,通常使用文件对象的read
函数来执行此操作。如果您想测试词法分析器,那么您将使用lex
函数实现Python迭代协议的事实,因此它将在for
语句中工作。所以你的主循环就像:
import sys
lexer.input(sys.stdin.read())
for tok in lexer:
# Update counts
并且您将通过在行的开头键入文件结尾字符来终止输入(Linux上的control-D或Windows上的control-Z)。
就个人而言,我会使用defaultdict
:
from collections import defaultdict
counts = defaultdict(int)
for tok in lexer:
counts[tok.type] += 1
for type, count in counts.items():
print ("Number of %s's: %d\n" % (type, count))
# Or: print('\n'.join("Number of %s's: %d\n" % (type, count) for type, count in counts.items())
print ("Number of lines: %d\n" % lexer.lineno)