C言語アルゴリズム-字句解析 |
2 字句解析 (2)
C言語専用の字句解析関数get_token_cを作成する。
関数get_tokenでは記号は1文字ずつ取り出される。上の実行例のようにコメント文をはさむ/*と*/もバラバラに取り出されている。/*、*/として取り出せた方が関数strcmpで比較できて便利である。また、比較演算子も同様である。このように、記号が連続した演算子等を次に示す。
++, --, ==, !=, >=, <=, &&, ||, >>, <<, ->, /*, */
ここでは、関数get_tokenを利用してC言語専用の字句解析関数get_token_cを作成する。処理の手順を簡単に説明すると次のようになる。
上の記号の1文字目が現れたら再度get_tokenし、その記号に対応する2文字目かどうかを判定する。
該当する連続記号であれば、1番目と2番目の記号を連結して変数tokenに格納する。該当する連続記号でなければ2番目を関数unget_tokenで戻し、1番目を変数tokenに格納する。
[gt_c.c]
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "gettoken.h" char *c_get_token(void) { char token_1[STR_MAX]; char flag = 0; /* 連続記号用フラグ */ if(*get_token() == '\0') /* 1番目のトークン取得 */ return(token); strcpy(token_1, token); /* token_1に保存 */ if(*get_token() == '\0'){ /* 2番目のトークン取得 */ strcpy(token, token_1); return(token); } switch(*token_1){ case '+': /* ++, &&, ||, == */ case '&': case '|': case '=': if(*token_1 == *token) /* 1番目と2番目が同じ */ flag = 1; break; case '<': /* <=, >=, <<, >> */ case '>': if(*token_1 == *token || *token == '=') /* 同じか=である */ flag = 1; break; case '-': if(*token_1 == *token || *token == '>') /* 同じか>である */ flag = 1; break; case '!': /* != */ if(*token == '=') /* 2番目が=である */ flag = 1; break; case '/': /* / * */ if(*token == '*') /* 2番目が*である */ flag = 1; break; case '*': /* * / */ if(*token == '/') /* 2番目が/である */ flag = 1; break; } if(flag){ strcat(token_1, token); /* トークンの連結 */ strcpy(token, token_1); /* tokenに格納 */ }else{ unget_token(token); /* 2番目を戻す */ strcpy(token, token_1); /* 1番目をtokenに格納 */ } return(token); } void main(void) { FILE *bf; char file[80]; /* ファイル名 */ printf("ファイル名 : "); /* プロンプト表示 */ gets(file); /* ファイル名入力 */ if((bf = fopen(file, "r")) == NULL){ /* ファイルオープン */ printf("ファイルがオープンできない\n"); exit(1); /* 強制終了 */ } while(fgets(gt_line, STR_MAX, bf) != NULL){ /* 1行読み込み */ while(1){ c_get_token(); if(token[0] == '\0') /* 1行分終了 */ break; if(*token == '\n') printf("(\\n)"); /* 改行コード */ else printf("(%s) ", token); /* 表示 */ } printf("\n"); } fclose(bf); /* ファイルクローズ */ } |
ここでは、文字の判定にswitch文を使用している。これは、例えば20〜23行目の部分をif文にすると次のように非常に長くなるためである。
if(*token_1 == '+' || *token_1 == '&' || *token_1 == '|' || *token_1 == '=')
12行目で、1番目のトークンを取り出し、14行目で変数token_1に格納する。
15行目で、2番目のトークンを取り出している。
19〜48行で、該当する連続記号であれば、変数flagを1にする。
該当する連続記号であれば50,51行が実行され、該当しなければ53,54行が実行される。例えば、!=の処理は、次のようになる。
このように、関数get_tokenをベースに各種の言語に合わせた字句解析ルーチンを作成することができる。
Copyright © 2001 Hiroshi Masuda |