我最近正在學(xué)編譯原理,我有c語言實(shí)現(xiàn)的詞法分析程序,不知可不可以,識(shí)別的是TEST語言的單詞。
十余年品牌的成都網(wǎng)站建設(shè)公司,1000多家企業(yè)網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn).價(jià)格合理,可準(zhǔn)確把握網(wǎng)頁設(shè)計(jì)訴求.提供定制網(wǎng)站建設(shè)、商城網(wǎng)站開發(fā)、成都微信小程序、響應(yīng)式網(wǎng)站開發(fā)等服務(wù),我們?cè)O(shè)計(jì)的作品屢獲殊榮,是您值得信賴的專業(yè)網(wǎng)絡(luò)公司。
#includestdio.h
#includectype.h
#includestring.h
#define keywordSum 8
char * keyword[keywordSum] = {"do", "else", "for", "if", "int", "read", "while", "write"};
char singleword[50] = "+-*(){};,:";
char doubleword[10] = "=!|";
char Scanin[300], Scanout[300];
FILE * fin, * fout;
int binaryFind(int low, int high, char * c1, char ** c2) {
int mid;
if(low high) return -1;
mid = (low+high)/2;
if(strcmp(c1, c2[mid]) == 0) return mid;
else if(strcmp(c1, c2[mid]) 0) return binaryFind(mid+1, high, c1, c2);
else return binaryFind(low, mid-1, c1, c2);
}
int TESTscan() {
char ch, token[40];
int es = 0, j, n;
printf("請(qǐng)輸入源文件名(包括路徑):");
scanf("%s", Scanin);
printf("請(qǐng)輸入詞法分析輸出文件名(包括路徑):");
scanf("%s", Scanout);
if((fin=fopen(Scanin, "r")) == NULL) {
printf("\n打開詞法分析輸入文件出錯(cuò)!\n");
return 1;
}
if((fout=fopen(Scanout, "w")) == NULL) {
printf("\n創(chuàng)建詞法分析輸出文件出錯(cuò)!\n");
return 2;
}
// printf("%c", getc(fin));
ch = getc(fin);
while(ch != EOF) {
while(ch==' ' || ch=='\n' || ch=='\t') {
ch = getc(fin);
}
if(isalpha(ch)) { //標(biāo)識(shí)符
token[0] = ch;
j = 1;
ch = getc(fin);
while(isalnum(ch)) { //判斷當(dāng)前字符是否是字母或數(shù)字
token[j++] = ch;
ch = getc(fin);
}
token[j] = '\0';
// printf("%s", token);
n = binaryFind(0, keywordSum-1, token, keyword);
if(n 0 ) {
fprintf(fout, "%s\t%s\n", "ID", token);
} else {
fprintf(fout, "%s\t%s\n", token, token);
}
} else if(isdigit(ch)) { //數(shù)字
token[0] = ch;
j = 1;
ch = getc(fin);
while(isdigit(ch)) {
token[j++] = ch;
ch = getc(fin);
}
token[j] = '\0';
fprintf(fout, "%s\t%s\n", "NUM", token);
} else if(strchr(singleword, ch) 0) { //singleword
token[0] = ch;
token[1] = '\0';
ch = getc(fin);
fprintf(fout, "%s\t%s\n", token, token);
} else if(strchr(doubleword, ch) 0) { //doubleword
token[0] = ch;
ch = getc(fin);
if(ch=='=' (token[0]==''||token[0]=='' || token[0] == '!')) {
token[1] = ch;
token[2] = '\0';
ch = getc(fin);
} else if((ch=='')||(ch=='|')||(ch=='=') ch==token[0]) {
token[1] = ch;
token[2] = '\0';
ch = getc(fin);
} else {
token[1] = '\0';
}
fprintf(fout, "%s\t%s\n", token, token);
} else if(ch == '/') { //注釋
ch = getc(fin);
if(ch == '*') {
char ch1;
ch1 = getc(fin);
do {
ch = ch1;
ch1 = getc(fin);
} while((ch!='*'||ch1!='/') ch1!=EOF);
ch = getc(fin);
} else {
token[0] = '/';
token[1] = '\0';
fprintf(fout, "%s\t%s\n", token, token);
}
} else {
token[0] = ch;
token[1] = '\0';
ch = getc(fin);
es = 3;
fprintf(fout, "%s\t%s\n", "ERROR", token);
}
}
fclose(fin);
fclose(fout);
return es;
}
void main() {
int es = 0;
es = TESTscan();
if(es 0) {
printf("詞法分析有錯(cuò), 編譯停止!\n");
} else {
printf("詞法分析成功!\n");
}
}
這個(gè)我做了一個(gè)類似的,識(shí)別字符串的,發(fā)給你,你在這個(gè)基礎(chǔ)上改一下吧,哥最近在忙軟考不然幫你做做。
程序識(shí)別的字符串輸入的格式:
1、輸入如下正確的常量說明串:
const count=10,sum=81.5,char1=‘f’,max=169,str1=“h*54 2..4S!AAsj”, char2=‘@’,str2=“aa!+h”;
輸出:
count(integer,10)
sum(float,81.5)
char1(char, ‘f’)
max(integer,169)
str1(string,“h*54 2..4S!AAsj”)
char2(char, ‘@’)
str2(string,“aa!+h”)
int_num=2; char_num=2; string_num=2; float_num=1.
程序如下:
#includeiostream
using namespace std;
int char_num=0,string_num=0,int_num=0,float_num=0; // 字符值類型,0=字符,1=字符串,2=整數(shù),3=浮點(diǎn)數(shù)
class zifu //建立字符類,存儲(chǔ)一個(gè)字符串的信息
{
public:
int i;
char name[20];
char data[20];
int dataname;
void display(){
i=0;
while(name[i]!='\0')
{
coutname[i];
i++;
}
cout"=";
i=0;
while(data[i]!='\0'){
coutdata[i];
}
coutendl;
coutdatanameendl;
}
};
void input(char a[]) //輸入函數(shù)
{
char stand[6]="const";
int i=0,judge=0;
gets(a);
for(i=0;i5;i++)
{
if(a[i]==stand[i])
judge++;
}
if(judge!=5 || a[5]!=' ')
{
cout"It is not a constant declaration statement! ";
cout"Please input a string again!"endl;
input(a);
}
}
void sort(zifu aclass[],char b[],int integer,int tag) //識(shí)別函數(shù),tag 類標(biāo)記 ,integer 當(dāng)前查找的位置
{
int i=0;
while(b[++integer]!='=')
{
if(b[integer]!=' ')
aclass[tag].name[i]=b[integer];
i++; //獲取字符串名
}
aclass[tag].name[i]='\0';
i=0;
++integer;
while(b[integer]!=',' b[integer]!=';') //獲取字符串值、值類型
{
if(b[integer]='0' b[integer]='9')// 字符值類型,0=字符,1=字符串,2=整數(shù),3=浮點(diǎn)數(shù)
aclass[tag].dataname=2;
else if(b[integer]=='.') //浮點(diǎn)數(shù)判斷。。。真麻煩
{ aclass[tag].dataname=3;
while(b[integer]!=',' b[integer]!=';'){
aclass[tag].data[i]=b[integer];
integer++;i++;}}
else if(b[integer]='a' b[integer]='z')
aclass[tag].dataname=0;
else if(b[integer]='A' b[integer]='Z')
aclass[tag].dataname=1;
else if(b[integer]=='\'' || b[integer]=='\'')
aclass[tag].dataname=0;
else if(b[integer]=='"' || b[integer]=='"')
aclass[tag].dataname=1;
if(b[integer]!=',' b[integer]!=';')
{
aclass[tag].data[i]=b[integer];
i++;
++integer;
}
}
aclass[tag].data[i]='\0';
++tag;
if(b[integer]!=';')
sort(aclass,b,integer,tag);
}
void display(zifu a) //輸出函數(shù)
{
int n=0;
int q=0;
while (a.name[n]!='\0')
{couta.name[n];
n++;}
cout"(";
switch (a.dataname)
{case 0:
cout"char";
char_num++;
break;
case 1:
cout"string";
string_num++;
break;
case 2:
cout"integer";
int_num++;
break;
case 3:
cout"float";
float_num++;
break;
default:
cout"type error";}
cout',';
while (a.data[q]!='\0')
{couta.data[q];
q++;}
cout")"endl;
}
void main()
{
zifu teger[10];
char c[100];
int tag0=0,integer0=5;
int m=0;
while(1){
cout"please input:"endl;
input(c);
// cout"0=字符,1=字符串,2=整數(shù),3=浮點(diǎn)數(shù)"endl;
sort(teger,c,integer0,tag0);
// cout"字符串?dāng)?shù)量="tag0endl;
for(m=0;mtag0;m++)
{display(teger[m]);}
coutendl"int_num="int_num"; ""char_num="char_num"; ";
cout"string_num="string_num"; ""float_num="float_numendlendl;
}
}
首先看下我們要分析的代碼段如下:
輸出結(jié)果如下:
輸出結(jié)果(a).PNG
輸出結(jié)果(b).PNG
輸出結(jié)果(c).PNG
括號(hào)里是一個(gè)二元式:(單詞類別編碼,單詞位置編號(hào))
代碼如下:
?
1234567891011121314
package Yue.LexicalAnalyzer;?import java.io.*;?/*?* 主程序?*/public class Main {??public static void main(String[] args) throws IOException {????Lexer lexer = new Lexer();????lexer.printToken();????lexer.printSymbolsTable();??}}
?
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
package Yue.LexicalAnalyzer;?import java.io.*;import java.util.*;?/*?* 詞法分析并輸出?*/public class Lexer {??/*記錄行號(hào)*/??public static int line = 1;??/*存放最新讀入的字符*/??char character = ' ';???/*保留字*/??HashtableString, KeyWord keywords = new HashtableString, KeyWord();??/*token序列*/??private ArrayListToken tokens = new ArrayListToken();??/*符號(hào)表*/??private ArrayListSymbol symtable = new ArrayListSymbol();???/*讀取文件變量*/??BufferedReader reader = null;??/*保存當(dāng)前是否讀取到了文件的結(jié)尾*/??private Boolean isEnd = false;???/* 是否讀取到文件的結(jié)尾 */??public Boolean getReaderState() {????return this.isEnd;??}???/*打印tokens序列*/??public void printToken() throws IOException {????FileWriter writer = new FileWriter("E:\\lex.txt");????System.out.println("詞法分析結(jié)果如下:");????System.out.print("杜悅-2015220201031\r\n\n");????writer.write("杜悅-2015220201031\r\n\r\n");????while (getReaderState() == false) {??????Token tok = scan();??????String str = "line " + tok.line + "\t(" + tok.tag + "," + tok.pos + ")\t\t"??????????+ tok.name + ": " + tok.toString() + "\r\n";??????writer.write(str);??????System.out.print(str);????}????writer.flush();???}???/*打印符號(hào)表*/??public void printSymbolsTable() throws IOException {????FileWriter writer = new FileWriter("E:\\symtab1.txt");????System.out.print("\r\n\r\n符號(hào)表\r\n");????System.out.print("編號(hào)\t行號(hào)\t名稱\r\n");????writer.write("符號(hào)表\r\n");????writer.write("編號(hào) " + "\t行號(hào) " + "\t名稱 \r\n");????IteratorSymbol e = symtable.iterator();????while (e.hasNext()) {??????Symbol symbol = e.next();??????String desc = symbol.pos + "\t" + symbol.line + "\t" + symbol.toString();??????System.out.print(desc + "\r\n");??????writer.write(desc + "\r\n");????}?????writer.flush();??}???/*打印錯(cuò)誤*/??public void printError(Token tok) throws IOException{????FileWriter writer = new FileWriter("E:\\error.txt");????System.out.print("\r\n\r\n錯(cuò)誤詞法如下:\r\n");????writer.write("錯(cuò)誤詞法如下:\r\n");????String str = "line " + tok.line + "\t(" + tok.tag + "," + tok.pos + ")\t\t"????????+ tok.name + ": " + tok.toString() + "\r\n";????writer.write(str);??}???/*添加保留字*/??void reserve(KeyWord w) {????keywords.put(w.lexme, w);??}???public Lexer() {????/*初始化讀取文件變量*/????try {??????reader = new BufferedReader(new FileReader("E:\\輸入.txt"));????} catch (IOException e) {??????System.out.print(e);????}?????/*添加保留字*/????this.reserve(KeyWord.begin);????this.reserve(KeyWord.end);????this.reserve(KeyWord.integer);????this.reserve(KeyWord.function);????this.reserve(KeyWord.read);????this.reserve(KeyWord.write);????this.reserve(KeyWord.aIf);????this.reserve(KeyWord.aThen);????this.reserve(KeyWord.aElse);??}???/*按字符讀*/??public void readch() throws IOException {????character = (char) reader.read();????if ((int) character == 0xffff) {??????this.isEnd = true;????}??}???/*判斷是否匹配*/??public Boolean readch(char ch) throws IOException {????readch();????if (this.character != ch) {??????return false;????}?????this.character = ' ';????return true;??}???/*數(shù)字的識(shí)別*/??public Boolean isDigit() throws IOException {????if (Character.isDigit(character)) {??????int value = 0;??????while (Character.isDigit(character)) {????????value = 10 * value + Character.digit(character, 10);????????readch();??????}???????Num n = new Num(value);??????n.line = line;??????tokens.add(n);??????return true;????} else??????return false;??}???/*保留字、標(biāo)識(shí)符的識(shí)別*/??public Boolean isLetter() throws IOException {????if (Character.isLetter(character)) {??????StringBuffer sb = new StringBuffer();???????/*首先得到整個(gè)的一個(gè)分割*/??????while (Character.isLetterOrDigit(character)) {????????sb.append(character);????????readch();??????}???????/*判斷是保留字還是標(biāo)識(shí)符*/??????String s = sb.toString();??????KeyWord w = keywords.get(s);???????/*如果是保留字的話,w不應(yīng)該是空的*/??????if (w != null) {????????w.line = line;????????tokens.add(w);??????} else {????????/*否則就是標(biāo)識(shí)符,此處多出記錄標(biāo)識(shí)符編號(hào)的語句*/????????Symbol sy = new Symbol(s);????????Symbol mark = sy;????? //用于標(biāo)記已存在標(biāo)識(shí)符????????Boolean isRepeat = false;????????sy.line = line;????????for (Symbol i : symtable) {??????????if (sy.toString().equals(i.toString())) {????????????mark = i;????????????isRepeat = true;??????????}????????}????????if (!isRepeat) {??????????sy.pos = symtable.size() + 1;??????????symtable.add(sy);????????} else if (isRepeat) {??????????sy.pos = mark.pos;????????}????????tokens.add(sy);??????}??????return true;????} else??????return false;??}???/*符號(hào)的識(shí)別*/??public Boolean isSign() throws IOException {????switch (character) {??????case '#':????????readch();????????AllEnd.allEnd.line = line;????????tokens.add(AllEnd.allEnd);????????return true;??????case '\r':????????if (readch('\n')) {??????????readch();??????????LineEnd.lineEnd.line = line;??????????tokens.add(LineEnd.lineEnd);??????????line++;??????????return true;????????}??????case '(':????????readch();????????Delimiter.lpar.line = line;????????tokens.add(Delimiter.lpar);????????return true;??????case ')':????????readch();????????Delimiter.rpar.line = line;????????tokens.add(Delimiter.rpar);????????return true;??????case ';':????????readch();????????Delimiter.sem.line = line;????????tokens.add(Delimiter.sem);????????return true;??????case '+':????????readch();????????CalcWord.add.line = line;????????tokens.add(CalcWord.add);????????return true;??????case '-':????????readch();????????CalcWord.sub.line = line;????????tokens.add(CalcWord.sub);????????return true;??????case '*':????????readch();????????CalcWord.mul.line = line;????????tokens.add(CalcWord.mul);????????return true;??????case '/':????????readch();????????CalcWord.div.line = line;????????tokens.add(CalcWord.div);????????return true;??????case ':':????????if (readch('=')) {??????????readch();??????????CalcWord.assign.line = line;??????????tokens.add(CalcWord.assign);??????????return true;????????}????????break;??????case '':????????if (readch('=')) {??????????readch();??????????CalcWord.ge.line = line;??????????tokens.add(CalcWord.ge);??????????return true;????????}????????break;??????case '':????????if (readch('=')) {??????????readch();??????????CalcWord.le.line = line;??????????tokens.add(CalcWord.le);??????????return true;????????}????????break;??????case '!':????????if (readch('=')) {??????????readch();??????????CalcWord.ne.line = line;??????????tokens.add(CalcWord.ne);??????????return true;????????}????????break;????}????return false;??}????/*下面開始分割關(guān)鍵字,標(biāo)識(shí)符等信息*/??public Token scan() throws IOException {????Token tok;????while (character == ' ')??????readch();????if (isDigit() || isSign() || isLetter()) {??????tok = tokens.get(tokens.size() - 1);????} else {??????tok = new Token(character);??????printError(tok);????}????return tok;??}}