トークンクラスの分離に大成功!
ついにトークンクラスの分離に成功した!
ていうか、「self.」多すぎ。
予約語などの定義もトークンファイルに入れた。これがベストかはわからないけど、メインプログラムがスッキリするのでいいかな、と。
分離した「tkn.py」ファイルを下に示す。
#!/usr/bin/python
# coding: utf-8
import sys
class tkn:
def __init__(self, infile):
self.infile = infile
self.token = ''
self.char = ''
self.digit = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
self.letter = ['A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_',
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z']
self.spechar = [':', ',', ';', '.','=', '+', '-', '<', '>', '(', ')']
self.keyword = ['program','const','var','int','integer','bool','boolean',
'begin','end','true','false']
def next_char(self):
self.char = self.infile.read(1)
if not self.char: #EOFなら(file.read()は、EOFを検出すると空を返す)
self.char = 'end_of_file'
return self.char
else:
sys.stdout.write(self.char)
return self.char
def next(self):
self.token = ''
while self.token == '':
if self.char == '{': #トークンが{の場合
while self.char != '}': # }まで読み飛ばす(コメント処理)
if self.char == 'end_of_file': #コメントの途中でEOFになったら
e.error(1) #エラーを出す
else:
self.next_char()
self.next_char()
elif self.char == '}': #トークンの頭に}は来ないので
e.error(2) #エラーを出す
elif self.char == '#': # #が来たら改行まで読み飛ばす(一行コメント処理)
while self.char != '\n':
if self.char == 'end_of_file':
e.error(1)
else:
self.next_char()
elif self.char in self.spechar: #「記号」の処理
self.token = self.char
self.next_char()
elif self.char in self.letter: #文字列の処理
self.token = self.char
self.next_char()
while self.char in (self.letter + self.digit):
self.token = self.token + self.char
self.next_char()
elif self.char in self.digit: #数列の処理
self.token = self.char
self.next_char()
while self.char in self.digit:
self.token = self.token + self.char
self.next_char()
elif self.char in [' ', '\n', '\t', '\r']: #スペース,改行,タブ,リターンは
self.next_char() #読み飛ばす
elif self.char == 'end_of_file': #EOFの処理
self.token = 'end_of_file'
else:
e.error(3)
#print(self.token)
return self.token
メインプログラム側は下の状態です。
#!/usr/bin/python
# coding: utf-8
def ids():
temp = token.token
if token.token in token.keyword:
e.error(4)
if token.next() not in [',', ':']:
e.error(5)
while token.token == ',':
if token.next() in token.keyword:
e.error(4)
temp = temp + ',' + token.token
token.next()
return temp
def var_stmts():
if token.token in token.keyword:
e.error(4)
ids()
if token.token != ':':
e.error(6)
if token.next() not in ['int', 'integer', 'bool', 'boolean']:
e.error(7)
if token.next() != ';':
e.error(8)
if token.next() != 'begin':
if token.token in token.keyword:
e.error(9)
if token.token not in token.keyword:
var_stmts()
def const_stmts():
if token.token in token.keyword:
e.error(10)
if token.next() != '=':
e.error(11)
x = token.next()
if x in token.keyword:
if not x.isdigit():
if x != '+':
if x != '-':
if x != 'true':
if x != 'false':
e.error(12)
if x in ['+','-']:
token.next()
if not token.token.isdigit:
e.error(13)
x = x + token.token
if token.next() != ';':
e.error(8)
if token.next() in token.keyword:
if token.token != 'var':
if token.token != 'begin':
e.error(14)
if token.token not in token.keyword:
const_stmts()
def begin_end_stmt():
if token.token != 'begin':
e.error(15)
if token.next() != 'end':
e.error(16)
if token.next() != '.':
e.error(17)
token.next()
def consts():
if token.token != 'const':
e.error(18)
if token.next() in token.keyword:
e.error(10)
const_stmts()
def vars():
if token.token != 'var':
e.error(19)
if token.next() in token.keyword:
e.error(4)
var_stmts()
def prog_stmt():
if token.token != 'program':
e.error(20)
token.next()
if token.token in token.keyword:
e.error(21)
if token.next() != ';':
e.error(8)
token.next()
def prog():
if token.token != 'program':
e.error(20)
prog_stmt()
if token.token == 'const':
consts()
if token.token == 'var':
vars()
if token.token != 'begin':
e.error(15)
begin_end_stmt()
if token.token != 'end_of_file':
e.error(22)
print(u'正常終了')
def parser():
token.next_char()
if token.next() != 'program':
e.error(20)
prog()
from err import *
from tkn import *
infile = open('test.p', 'r')
e = err()
token = tkn(infile)
parser()
infile.close()
で、実行結果が↓
~/PasAvr$ python parser02.py
program test;
const
yes = true;
no = false;
small = 0;
big = 123456;
var
id1 : integer;
id2 : boolean;
hen : integer;
x, y, z : int;
begin
end.
正常終了
~/PasAvr$
ちゃんと動いた!