Scanner -- 詞彙掃描器
檔案:Scanner.h
#ifndef SCANNER_H
#define SCANNER_H
#include "Array.h"
typedef struct { // 掃描器的物件結構
char *text; // 輸入的程式 (text)
int textLen; // 目前掃描到的位置
int textIdx; // 程式的總長度
char token[MAX_LEN]; // 目前掃描到的詞彙
} Scanner;
Scanner* ScannerNew(char *pText);
void ScannerFree(Scanner *scanner);
char* ScannerScan(Scanner *scanner);
Array* tokenize(char *text);
char *tokenToType(char *token);
void printTokens(Array *tokens);
extern char STRING[];
extern char NUMBER[];
extern char ID[];
extern char KEYWORDS[];
extern char OP1[];
extern char OP2[];
extern char COND_OP[];
extern char ITEM[];
#endif
檔案:Scanner.c
#include <string.h>
#include "Scanner.h"
char STRING[] = "string";
char NUMBER[] = "number";
char ID[] = "id";
char KEYWORDS[] = "|if|for|while|return|";
char OP1[] = "|++|--|";
char OP2[] = "|+|-|*|/|";
char COND_OP[] = "|==|!=|<=|>=|<|>|";
char ITEM[]= "|id|number|string|";
char OP[] = "+-*/<=>!";
#define ch() (scanner->text[scanner->textIdx])
#define next() (scanner->textIdx++)
Scanner* ScannerNew(char *pText) {
Scanner *scanner = ObjNew(Scanner, 1);
scanner->text = pText;
scanner->textLen = strlen(pText);
scanner->textIdx = 0;
return scanner;
}
void ScannerFree(Scanner *scanner) {
ObjFree(scanner);
}
char *ScannerScan(Scanner *scanner) { // 掃描下一個詞彙
while (strMember(ch(), SPACE)) // 忽略空白
next();
if (scanner->textIdx >= scanner->textLen) // 檢查是否超過範圍
return NULL;
char c = ch(); // 取得下一個字元
int begin = scanner->textIdx; // 記住詞彙開始點
if (c == '\"') { // string = ".." // 如果是 ",代表字串開頭,
next(); // skip begin quote "
while (ch() != '\"') next(); // 一直讀到下一個 " 符號為止。
next(); // skip end quote "
} else if (strMember(c, OP)) { // OP , ex : ++, --, <=, >=, ... // 如果是OP(+-*/<=>!等符號)
while (strMember(ch(), OP)) next(); // 一直讀到不是OP為止
} else if (strMember(c, DIGIT)) { // number, ex : 312, 77568, ... // 如果是數字
while (strMember(ch(), DIGIT)) next(); // 一直讀到不是數字為止
} else if (strMember(c, ALPHA)) { // name, ex : int, sum, i, for, if, .... // 如果是英文字母
while (strMember(ch(), ALPHA) || strMember(ch(), DIGIT)) next(); // 一直讀到不是英文字母 (或數字)為止 (ex: x1y2z)
} else // some other symbol, such as #
next(); // 否則,傳回單一字元
strSubstr(scanner->token, scanner->text, begin, scanner->textIdx-begin); // 設定token為(begin…textIdx) 之間的子字串
return scanner->token; // 傳回token詞彙
}
Array* tokenize(char *text) { // 將程式轉換成一個一個的詞彙
Array *tokens = ArrayNew(10);
Scanner *scanner = ScannerNew(text);
char *token = NULL;
while ((token = ScannerScan(scanner))!= NULL) { // 不斷取出下一個詞彙,直到程式字串結束為止
ArrayAdd(tokens, newStr(token));
printf("token=%s\n", token);
}
ScannerFree(scanner);
return tokens;
}
char *tokenToType(char *token) { // 判斷並取得 token的型態
if (strPartOf(token, KEYWORDS)) // 如果是關鍵字 if, for, …
return token; // 型態即為該關鍵字
else if (token[0] == '\"') // 如果以符號 " 開頭,則
return STRING; // 型態為 STRING
else if (strMember(token[0], DIGIT)) // 如果是數字開頭,則
return NUMBER; // 型態為 NUMBER
else if (strMember(token[0], ALPHA)) // 如果是英文字母開頭,則
return ID; // 型態為 ID
else // 否則 (像是 +,-,*,/,>,<,….)
return token; // 型態即為該 token
}
void printTokens(Array *tokens) {
printf("tokens->count = %d\n", tokens->count);
int i;
for (i=0; i<tokens->count; i++) {
char *token = tokens->item[i];
printf("token=%s , type=%s\n", token, tokenToType(token));
}
}
page revision: 0, last edited: 13 Aug 2010 00:09
Post preview:
Close preview