0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

コンパイラ作りながら学ぶ第4章 字句解析

Last updated at Posted at 2021-08-10

この記事に出てくるプログラムは,コンパイラ作りながら学ぶ https://www.ohmsha.co.jp/book/9784274221163/ で紹介されているC言語プログラムや疑似コードをPythonで書き換えたものです.

4.1 文字読み込み

コンパイラはまず,原始プログラムを読み込まなければならない.このときに次のような機能を持つ関数nextCharを作る.
(1) 読み込んだ原始プログラムの中で最後に返した文字の位置を覚えていて
(2) 呼ばれたら,その次の文字を返す.返す文字がなかったらファイルから次の行を読み込みその最初の文字を返す.

import linecache
line_number = 1 #行番号
lineIndex = -1
end = len(open('sample.c').readlines()) #ファイルの行数

def nextChar():
    global line_number
    global lineIndex

    line = linecache.getline('sample.c', int(line_number))
    if lineIndex == -1:
        if line_number<=end:
            lineIndex = 0
        else:
            print("end of file")
            exit(1)
    ch = line[lineIndex]
    lineIndex+=1
    if ch == '\n':
        lineIndex = -1
        line_number+=1
        return ' '
    return ch

linecache.getline()で特定の行を文字列として取得する.line_numberが行番号を指定する変数.'\n'を読み込んだ場合lineIndexを-1,lineIndex+=1として,次に関数が呼ばれた際には次の行を読み込む.

4.2 字句読み取り

 以下のプログラムは,名前を読み込むためのものです.ここでいう「名前」とは,単語の一文字目が英字,その後に英字または数字のゼロ回以上の繰り返しから成る文字列のことを意味します.state1関数で,一文字目の英字を読み込みます.一文字目が英字でない場合,エラーとなります.次に,state2関数によって,英字or数字の繰り返しから生成される文字列を読み込みます.単語が読み込み終わり,次の単語へと移る際にはstate3関数で,lineindex-=1をします.最終的に変数ansに読み込んだ名前が返される仕組みになっています.

def error():
    return "Not Name"

def state3():
    global lineIndex
    lineIndex-=1

def state1(s):
    ch = nextChar()
    while ch == ' ':
        ch = nextChar() #単語間の空白文字を読み飛ばす
    if ch.isalpha():
        s+=ch
        return state2(s)
    else:
        return error()

def state2(s):
    ch = nextChar()
    if ch.isalpha() or ch.isdigit():
        s+=ch
        return state2(s)
    else:
        state3()
        return s

if __name__ == '__main__':
    while True:
        ans = state1("")
        print(ans)
def error():
    return "Error"

def state5():
    global lineIndex
    lineIndex-=1

def state4(s): #区切り記号
    ch = nextChar()
    state5()
    return s

def state3(s): #数字
    ch = nextChar()
    if ch.isdigit():
        s+=ch
        return state3(s)
    else:
        state5()
        return s

def state2(s): #名前
    ch = nextChar()
    if ch.isalpha() or ch.isdigit():
        s+=ch
        return state2(s)
    else:
        state5()
        return s

def state1(s):
    ch = nextChar()
    while ch == ' ':
        ch = nextChar() #単語間の空白文字を読み飛ばす
    s+=ch
    if ch.isalpha(): #名前のとき
        return state2(s)
    elif ch.isdigit(): #数字のとき
        return state3(s)
    elif ch == ',' or ch == ';': #区切り記号
        return state4(s)
    else:
        return error()
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?