プログラミングと工作と

PythonとかPascalとかAVRマイコンとか、コンパイラつくったり電子工作なんかを楽しんでいるおっさんの記録

とりあえず、トークン関数の完成だ!

仕上げとして、ソースファイル中のコメント処理を入れてみた。
Pascalは、{と}の間にある文字をコメントとして処理する。なので、その間の文字と{}自身を読み飛ばすようにした。

また、一行コメントも便利なので処理に追加した。
Pascalの進化系Delphiは、c++同様「//」の後の文字を改行までコメントとみなす。Pascalコンパイラを名乗る以上これに準拠しようとも思ったのですが、今勉強中のPythonに敬意を払い「#」から改行までをコメントとした。
スクリプトもちょっとだけ簡単になるし、Python先生も「複雑より簡単の方がいい」とおっしゃっていますし。

あと、error()関数をちょっとだけパワーアップした。
エラー番号を受け取って、エラー内容を表示するという簡単なものだが、無言よりはいいだろう。

書きなおしたのが↓

#!/usr/bin/python
# coding: utf-8

def error(err):
     if err == 1:
         e = u' 突然ファイルの終端になっています'
     elif err == 2:
         e = u' }はトークンの始まりには出来ません'
     elif err == 3:
         e = u' 誤った記号が使用されています'

     infile.close()
     print('Error' + str(err) + e)
     input()

 


def next_char():
    global char    
    char = infile.read(1)
    if not char:   #EOFなら(file.read()は、EOFを検出すると空を返す)
        char = 'end_of_file'
        return char
    else:
        return char

def next_token():
    global char, token
    token = ''
    while token == '':
        if char == '{':                    #トークンが{の場合
            while char != '}':             # }まで読み飛ばす(コメント処理)
                if char == 'end_of_file':  #コメントの途中でEOFになったら
                    error(1)               #エラーを出す
                else:
                    next_char()
            next_char()
        elif char == '}':  #トークンの頭に}は来ないので
            error(2)       #エラーを出す
        elif char == '#':  # #が来たら改行まで読み飛ばす(一行コメント処理)
            while char != '\n':
                if char == 'end_of_file':
                    error(1)
                else:
                    next_char()
        elif char in spechar:  #「記号」の処理
            token = char
            next_char()
        elif char in letter:   #文字列の処理
            token = char
            next_char()
            while char in (letter + digit):
                token = token + char
                next_char()
        elif char in digit:  #数列の処理
            token = char
            next_char()
            while char in digit:
                token = token + char
                next_char()
        elif char in [' ', '\n', '\t', '\r']:  #スペース,改行,タブ,リターンは
            next_char()                        #読み飛ばす
        elif char == 'end_of_file': #EOFの処理
            token = 'end_of_file'
        else:
            error(3)
    return token


digit = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
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']
spechar = [':', ',', ';', '.','=', '+', '-', '<', '>', '(', ')']

token = ''
        
infile = open('test.p', 'r')
char = next_char()
while 1:
    next_token()
    if token == 'end_of_file':
        print('EndOfFile')
        break
    print(token)
infile.close()


●以下のテストファイルを読ませた。

program Pa;
{コメントのテスト
 改行してもOKかな?}
var
    id1 : integer;
    id2 : boolean;
    hen : integer;
begin #Python風のコメント
end.

●実行した結果が↓

~/PasAvr$ python gettoken3.py
program
Pa
;
var
id1
:
integer
;
id2
:
boolean
;
hen
:
integer
;
begin
end
.
EndOfFile
~/PasAvr$

ちゃんとコメントを読み飛ばしています。
トークンの取得関数はここでひとまず完成として、次回から先に進みましょう。