cs編譯原理
『壹』 要是想在碩士期間轉專業申請CS碩士留學的話,可行嗎要怎麼准備
是可行的。最重要的是課程方面的背景要補充,高數線代概率論都是要學的,另外還要修一些CS的專業課,如計算機組成原理、操作系統、離散數學、數據結構、計算機網路等等。學完這些就基本入門了。高階課比如編譯原理、演算法、計算機圖形學、面向對象程序設計、軟體工程、人工智慧等等多多益善。
『貳』 我想轉專業去CS,課程上要怎麼准備
課程方面的背景要補充,高數線代概率論都是要學的,另外還要修一些CS的專業課,如計算機組成原理、操作系統、離散數學、數據結構、計算機網路等等。學完這些就基本入門了。高階課比如編譯原理、演算法、計算機圖形學、面向對象程序設計、軟體工程、人工智慧等等多多益善。如果學校的選課制度不太靈活,可以選擇網課平台如coursera、mooc等等。
『叄』 轉專業去CS,課程上怎麼准備
高數線代概率論都是要學的,另外還要修一些CS的專業課,如計算機組成原理、操作系統、離散數學、數據結構、計算機網路等等。學完這些就基本入門了。高階課比如編譯原理、演算法、計算機圖形學、面向對象程序設計、軟體工程、人工智慧等等多多益善。如果學校的選課制度不太靈活,可以選擇網課平台如coursera、mooc等等。
『肆』 編譯原理語法分析編程
#include <iostream>
#include <string>
#include <fstream>
#include <queue>
#include <string.h>
#include <stdio.h>
using namespace std;
enum Datatype { RESERVE_WORD=1,IDENTIFIER=2,DIGIT=3,OPERATOR=4,SEPRATOR=5 };
struct OutputStruct
{
public:
Datatype type;
string value;
};
string operate[]={"sin","cos","pow"};
string KeyWord[]={"main","int","if","char","cout"};
const int MAX_SIZE=255;
char BUFF[MAX_SIZE]; //buffer to contain a char line.
ifstream inFile;
ofstream outFileStream;
queue<OutputStruct> tt;
bool IsKeyWord(string& cs)
{
for(int i=0;i<5;++i)
if(cs==KeyWord[i])
return true; //Exist
return false;
}
void ReadLineAndAnalyze()
{
int strSize=0;
int i;
int errFlag=0;
char ch;
string outStructStr,str;
struct OutputStruct outStruct;
{
i=0;
inFile.getline(BUFF,MAX_SIZE,'\n');
strSize=inFile.gcount();
cout<<BUFF;
do{
str="";
do{
ch=BUFF[i];
i++;
}while(ch==' '||ch==' '||ch=='\n');
switch(ch)
{
case '+':
case '-':
case '*':
case '/':
outStruct.type=OPERATOR;
outStruct.value=ch;
break;
case '=':
case '>':
case '<':
outStructStr=ch;
if(BUFF[i]=='=')
{
outStruct.type=OPERATOR;
outStructStr+=BUFF[i];
outStruct.value=outStructStr;
i++;
}
else
{
outStruct.type=OPERATOR;
outStruct.value=ch;
};
break;
case ',':
case ';':
case '{':
case '}':
case '(':
case ')':
case '[':
case ']':
case '\"':
outStruct.type=SEPRATOR;
outStruct.value=ch;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
outStructStr+=ch;
while(BUFF[i]>='0'&&BUFF[i]<='9'||BUFF[i]=='.')
{
outStructStr+=BUFF[i];
i++;
}//while
outStruct.type=DIGIT;
outStruct.value=outStructStr;
break;
default:
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')
{
outStructStr+=ch;
while(BUFF[i]>='a'&&BUFF[i]<='z'||BUFF[i]>='A'&&BUFF[i]<='Z')
{
outStructStr+=BUFF[i];
i++;
}//while
if(IsKeyWord(outStructStr))
{
outStruct.type=RESERVE_WORD;
outStruct.value=outStructStr;
}
else
{
outStruct.type=IDENTIFIER;
outStruct.value=outStructStr;
}
break;
}
else
errFlag=1;
}//switch;
if(!errFlag)
tt.push(outStruct);
errFlag=0;
outStructStr="";
}while(i<strSize-1);
}//while(i<MAX_SIZE&&!inFile.eof());//do_while
return;
}
float F();
float T();
float E();
float S();
float F()
{
float ret;
if((tt.front().type==IDENTIFIER)||(tt.front().type==DIGIT))
{
ret=atof(tt.front().value.c_str());
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
tt.pop();
return ret;
}
if(tt.front().value=="(")
{
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
tt.pop();
ret=E();
if(tt.front().value==")")
{
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
tt.pop();
return ret;
}
else
{
cout<<"\b ----ERROR! "<<tt.front().value<<" 缺少右括弧"<<endl;
cout<<"Press \"enter\" to modify the data file!";
getchar();
system("notepad data.txt");
exit(0);
}
}
else
{
cout<<"\b ----ERROR! "<<tt.front().value<<" 缺少因子"<<endl;
cout<<"Press \"enter\" to modify the data file!";
getchar();
system("notepad data.txt");
exit(0);
}
}
float T()
{
float i,j;
i=F();
if(tt.front().value=="*")
{
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
tt.pop();
j=T();
return i*j;
}
else if(tt.front().value=="/")
{
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
tt.pop();
j=T();
if(abs(j)<0.0000001)
{
cout<<"\b ----ERROR! 除數為零!"<<endl;
cout<<"Press \"enter\" to modify the data file!";
getchar();
system("notepad data.txt");
exit(0);
}
return i/j;
}
return i;
}
float E()
{
float i,j;
i=T();
if(tt.front().value=="+")
{
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
tt.pop();
j=E();
i=i+j;
}
else if(tt.front().value=="-")
{
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
tt.pop();
j=E();
i=i-j;
}
if(tt.front().value==";"||tt.front().type==OPERATOR||tt.front().value==")")
return i;
else
{
cout<<"\b ----ERROR! "<<tt.front().value<<" 缺少運算符"<<endl;
cout<<"Press \"enter\" to modify the data file!";
getchar();
system("notepad data.txt");
exit (0);
}
}
float S()
{
float i;
i=E();
if(tt.front().value==";")
{
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
tt.pop();
return i;
}
cout<<"\b ----ERROR! "<<tt.front().value<<" 缺少左括弧"<<endl;
cout<<"Press \"enter\" to modify the data file!";
getchar();
system("notepad data.txt");
exit(0);
}
void GrammaAnalize()
{
float i;
if(tt.empty())
{
cout<<"END"<<endl;exit(0);
}
i=S();
cout<<"\b="<<i<<endl;
}
int main()
{
inFile.open("data.txt");
if(!inFile)
{
cout<<"打開源文件失敗!";
return 1;
}
while(!inFile.eof())
{
ReadLineAndAnalyze();
GrammaAnalize();
}
inFile.close();
return 0;
}
『伍』 CS專業大學生怎樣平衡績點和編程能力
只能說但願個人都能找到適合自己的學習方法吧。
編程和學習也並不矛盾,尤其是專業課。比如計算機組成原理,實現一個流水線的mips指令集的cpu,編譯原理,寫編譯器,網路課可以嘗試NAT打洞嘛,操作系統課抄一個 unix V6 那樣的系統出來~ 圖形學可以做軟體渲染器。邊學邊嘗試,在學校基本都需要幾個月才能完成。
『陸』 如果不發明一種新語言,那學編譯原理有什麼用
編譯原理是計算機科學與技術中一個非常成熟的分支,非常完美地將原理與技術結合了起來,對於理解計算機的本質非常有幫助
編譯原理的很多設計思想可以在你設計的程序中運用
比如你想寫個程序對於某個文本作詞法分析和語法分析的處理,那麼編譯原理的知識完全可以幫助你來完成它
又或者你也可能寫個能自動生成菜單或者界面的程序,你需要自定義一個非常簡單的腳本語言並解析它,編譯原理也可以幫助你做到這一點
總之,編譯原理應用的領域十分廣泛,不要以為學編譯原理就僅僅是用來做編譯器的
另外,編譯原理包含了很多巧妙的設計構思,作為一名CS的學生,當然是很有必要來學習它的
『柒』 編譯原理詞法分析器
#include<iostream.h>
#include<fstream.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<conio.h>
#include<process.h> /*頭文件*/
void init();
char *DchangeB(char *buf);
int search(char *buf,int type,int command);
void intdeal(char *buffer);
void chardeal(char *buffer);
void errordeal(char error,int lineno);
void scanner();
void init()
{ char *key[]={"","auto","break","case","char","const","continue","default","do","double",
"else","enum","extern","float","for","goto","if","int","long","register",
"return","short","signed","sizeof","static","struct","switch","typedef",
"union","unsigned","void","volatile","while"}; /*C語言所有關鍵字/
char *limit[]={" ","(",")","[","]","->",".","!","++","--","&","~",
"*","/","%","+","-","<<",">>","<","<=",">",">=","==","!=","&&","||",
"=","+=","-=","*=","/=",",",";","{","}","#","_","'"};/*運算、限界符*/
fstream outfile;
int i,j;
char *c;
outfile.open("key.txt",ios::out);
for(i=0;i<32;i++)
outfile<<key[i]<<endl;
outfile.close();
outfile.open("Limit.txt",ios::out);
for(j=0;j<38;j++)
outfile<<limit[j]<<endl;
c="";
outfile<<c;
outfile.close();
outfile.open("bsf.txt",ios::out);
outfile.close();
outfile.open("cs.txt",ios::out);
outfile.close();
outfile.open("output.txt",ios::out);
outfile.close();
}
char *DchangeB(char *buf)
{
int temp[20];
char *binary;
int value=0,i=0,j;
for(i=0;buf[i]!='\0';i++)
value=value*10+(buf[i]-48); /*將字元轉化為十進制數*/
if(value==0)
{
binary=new char[2];
binary[0]='0';
binary[1]='\0';
return(binary);
}
i=0;
while(value!=0)
{
temp[i++]=value%2;
value/=2;
}
temp[i]='\0';
binary=new char[i+1];
for(j=0;j<=i-1;j++)
binary[j]=(char)(temp[i-j-1]+48);
binary[i]='\0';
return(binary); /*十進制轉化為二進制*/
}
int search(char *buf,int type,int command)
{ int number=0;
fstream outfile;
char ch;
char temp[30];
int i=0;
switch(type)
{
case 1: outfile.open("key.txt",ios::in);break;
case 2: outfile.open("bsf.txt",ios::in);break;
case 3: outfile.open("cs.txt",ios::in);break;
case 4: outfile.open("limit.txt",ios::in);break;
}
outfile.get(ch);
while(ch!=EOF){
while(ch!='\n')
{
temp[i++]=ch;
outfile.get(ch);
}
temp[i]='\0';
i=0;
number++;
if(strcmp(temp,buf)==0)
{
outfile.close();
return number; /*若找到,返回在相應表中的序號*/
}
else
outfile.get(ch);
} //結束外層while循環
if(command==1)
{
outfile.close( );
return 0; /*找不到,當只需查表,返回0,否則還需造表*/
}
switch(type)
{
case 1: outfile.open("key.txt",ios::in);break;
case 2: outfile.open("bsf.txt",ios::in);break;
case 3: outfile.open("cs.txt",ios::in);break;
case 4: outfile.open("limit.txt",ios::in);break;
}
outfile<<buf;
outfile.close();
return number+1;
}
void intdeal(char *buffer){
fstream outfile;
int result;
result=search(buffer,1,1); /*先查關鍵字表*/
outfile.open("output.txt",ios::app);
if(result!=0)
outfile<<buffer<<result<<endl; /*若找到,寫入輸出文件*/
else
{
result=search(buffer,2,2); /*若找不到,則非關鍵字,查標識符表,還找不到則造入標識符表*/
outfile<<buffer<<result<<endl;
} /*寫入輸出文件*/
outfile.close();
}
void chardeal(char *buffer)
{ fstream outfile;
int result;
result=search(buffer,1,1); /*先查關鍵字表*/
outfile.open("output.txt",ios::app);
if(result!=0)
outfile<<buffer<<result<<endl; /*若找到,寫入輸出文件*/
else
{
result=search(buffer,2,2); /*若找不到,則非關鍵字,查標識符表,還找不到則造入標識符表*/
outfile<<buffer<<result<<endl;
} /*寫入輸出文件*/
outfile.close();
}
void errordeal(char error,int lineno)
{ cout<<"\nerror: "<<error<<" ,line"<<lineno;
}
void scanner()
{ fstream infile,outfile;
char filename[20];
char ch;
int err=0;
int i=0,line=1;
int count,result,errorno=0;
char array[30];
char *word;
printf("\n please input the file scanner name:");
scanf("%s",filename);
err=1;
infile.open(filename,ios::nocreate|ios::in);
while(! infile)
{
cout<<"cannot open file"<<endl;
printf("please input the file name again:\n");
scanf("%s",filename);
infile.open(filename,ios::nocreate|ios::in);
err++;
if(err==3)
{cout<<"SORROY YOU CAN'T VUEW THE PRGARME\n";
cout<<"TANKE YOU VIEW"<<endl;
exit(0);}
}
infile.get(ch);
while(ch!=EOF)
{ /*按字元依次掃描源程序,直至結束*/
i=0;
if(((ch>='A')&&(ch<='Z'))||((ch>='a')&&(ch<='z'))||(ch=='_'))
{ /*以字母開頭*/
while(((ch>='A')&&(ch<='Z'))||((ch>='a')&&(ch<='z'))||(ch=='_')||((ch>='0')&&(ch<='9')))
{
array[i++]=ch;
infile.get(ch);
}
word=new char[i+1];
memcpy(word,array,i);
word[i]='\0';
intdeal(word);
if(ch!=EOF)
infile.seekg(-1,ios::cur);
}
else if(ch>='0'&&ch<='9')
{ /*以數字開頭*/
while(ch>='0'&&ch<='9')
{
array[i++]=ch;
infile.get(ch);
}
word=new char[i+1];
memcpy(word,array,i);
word[i]='\0';
intdeal(word);
if(ch!=EOF)
infile.seekg(-1,ios::cur);
}
else if((ch==' ')||(ch=='\t'))
; /*消除空格符和水平製表符*/
else if(ch=='\n')
line++; /*消除回車並記錄行數*/
else if(ch=='/')
{ /*消除注釋*/
infile.get(ch);
if(ch=='=')
{ /*判斷是否為『/=』符號*/
outfile.open("output.txt",ios::noreplace|ios::app);
outfile<<"/=\t\t\t4\t\t\t32\n";
outfile.close();
}
else if(ch!='*')
{ /*若為除號,寫入輸出文件*/
outfile.open("output.txt",ios::noreplace|ios::app);
outfile<<"/\t\t\t4\t\t\t13\n";
outfile.close();
outfile.seekg(-1,ios::cur);
}
else if(ch=='*')
{ /*若為注釋的開始,消除包含在裡面的所有字元*/
count=0;
infile.get(ch);
while(count!=2)
{ /*當掃描到『*』且緊接著下一個字元為『/』才是注釋的結束*/
count=0;
while(ch!='*')
infile.get(ch);
count++;
infile.get(ch);
if(ch=='/')
count++;
else
infile.get(ch);
}
}
}
else if(ch=='"')
{ /*消除包含在雙引號中的字元串常量*/
outfile.open("output.txt",ios::noreplace|ios::app);
outfile<<ch<<"\t\t\t4\t\t\t37\n";
outfile.close();
while(ch!='"')
infile.get(ch);
infile<<ch<<"\t\t\t4\t\t\t37\n";
infile.close();
}
else
{ /*首字元為其它字元,即運算限界符或非法字元*/
array[0]=ch;
infile.get(ch); /*再讀入下一個字元,判斷是否為雙字元運算、限界符*/
if(ch!=EOF)
{ /*若該字元非文件結束符*/
array[1]=ch;
word=new char[3];
memcpy(word,array,2);
word[2]='\0';
result=search(word,4,1); /*先檢索是否為雙字元運算、限界符*/
if(result==0)
{ /*若不是*/
word=new char[2];
memcpy(word,array,1);
word[1]='\0';
result=search(word,4,1); /*檢索是否為單字元運算、限界符*/
if(result==0)
{ /*若還不是,則為非法字元*/
errordeal(array[0],line);
errorno++;
infile.seekg(-1,ios::cur);
}
else
{ /*若為單字元運算、限界符,寫入輸出文件並將掃描文件指針回退一個字元*/
outfile.open("output.txt",ios::noreplace|ios::app);
outfile<<word<<"\t\t\t4\t\t\t"<<result<<"\t"<<endl;
outfile.close();
infile.seekg(-1,ios::cur);
}
}
else
{ /*若為雙字元運算、限界符,寫入輸出文件*/
outfile.open("output.txt",ios::noreplace|ios::app);
outfile<<word<<"\t\t\t4\t\t\t"<<result<<endl;;
outfile.close( );
}
}
else
{ /*若讀入的下一個字元為文件結束符*/
word=new char[2];
memcpy(word,array,1);
word[1]='\0';
result=search(word,4,1); /*只考慮是否為單字元運算、限界符*/
if(result==0) /*若不是,轉出錯處理*/
errordeal(array[0],line);
else
{ /*若是,寫輸出文件*/
outfile.open("output.txt",ios::noreplace|ios::app);
outfile<<word<<"\t\t\t4\t\t\t"<<result<<"\t"<<endl;
outfile.close();
}
}
}
infile.get(ch);
}
infile.close();
cout<<"\nThere are "<<errorno<<" error(s).\n"; /*報告錯誤字元個數*/
}
void main()
{ char yn;
do{
init(); /*初始化*/
scanner();/*掃描源程序*/
printf("Are You continue(y/n)\n"); //判斷是否繼續?
yn=getch();
}while(yn=='y'||yn=='Y');
}
『捌』 編譯原理試題·
Lex和Yacc應用方法(一).初識Lex
草木瓜 20070301
Lex(Lexical Analyzar 詞法分析生成器),Yacc(Yet Another Compiler Compiler
編譯器代碼生成器)是Unix下十分重要的詞法分析,語法分析的工具。經常用於語言分
析,公式編譯等廣泛領域。遺憾的是網上中文資料介紹不是過於簡單,就是跳躍太大,
入門參考意義並不大。本文通過循序漸進的例子,從0開始了解掌握Lex和Yacc的用法。
一.Lex(Lexical Analyzar) 初步示例
先看簡單的例子(註:本文所有實例皆在RetHat linux下完成):
一個簡單的Lex文件 exfirst.l 內容:
%{
#include "stdio.h"
%}
%%
[\n] ;
[0-9]+ printf("Int : %s\n",yytext);
[0-9]*\.[0-9]+ printf("Float : %s\n",yytext);
[a-zA-Z][a-zA-Z0-9]* printf("Var : %s\n",yytext);
[\+\-\*\/\%] printf("Op : %s\n",yytext);
. printf("Unknown : %c\n",yytext[0]);
%%
在命令行下執行命令flex解析,會自動生成lex.yy.c文件:
[root@localhost liweitest]flex exfirst.l
進行編譯生成parser可執行程序:
[root@localhost liweitest]cc -o parser lex.yy.c -ll
[注意:如果不加-ll鏈結選項,cc編譯時會出現以下錯誤,後面會進一步說明。]
/usr/lib/gcc-lib/i386-redhat-linux/3.2.2/../../../crt1.o(.text+0x18): In function `_start':
../sysdeps/i386/elf/start.S:77: undefined reference to `main'
/tmp/cciACkbX.o(.text+0x37b): In function `yylex':
: undefined reference to `yywrap'
/tmp/cciACkbX.o(.text+0xabd): In function `input':
: undefined reference to `yywrap'
collect2: ld returned 1 exit status
創建待解析的文件 file.txt:
title
i=1+3.9;
a3=909/6
bcd=4%9-333
通過已生成的可執行程序,進行文件解析。
[root@localhost liweitest]# ./parser < file.txt
Var : title
Var : i
Unknown : =
Int : 1
Op : +
Float : 3.9
Unknown : ;
Var : a3
Unknown : =
Int : 909
Op : /
Int : 6
Var : bcd
Unknown : =
Int : 4
Op : %
Int : 9
Op : -
Int : 333
到此Lex用法會有個直觀的了解:
1.定義Lex描述文件
2.通過lex,flex工具解析成lex.yy.c文件
3.使用cc編譯lex.yy.c生成可執行程序
再來看一個比較完整的Lex描述文件 exsec.l :
%{
#include "stdio.h"
int linenum;
%}
%%
title showtitle();
[\n] linenum++;
[0-9]+ printf("Int : %s\n",yytext);
[0-9]*\.[0-9]+ printf("Float : %s\n",yytext);
[a-zA-Z][a-zA-Z0-9]* printf("Var : %s\n",yytext);
[\+\-\*\/\%] printf("Op : %s\n",yytext);
. printf("Unknown : %c\n",yytext[0]);
%%
showtitle()
{
printf("----- Lex Example -----\n");
}
int main()
{
linenum=0;
yylex(); /* 進行分析 */
printf("\nLine Count: %d\n",linenum);
return 0;
}
int yywrap()
{
return 1;
}
進行解析編譯:
[root@localhost liweitest]flex exsec.l
[root@localhost liweitest]cc -o parser lex.yy.c
[root@localhost liweitest]./parser < file.txt
----- Lex Example -----
Var : i
Unknown : =
Int : 1
Op : +
Float : 3.9
Unknown : ;
Var : a3
Unknown : =
Int : 909
Op : /
Int : 6
Var : bcd
Unknown : =
Int : 4
Op : %
Int : 9
Op : -
Int : 333
Line Count: 4
這里就沒有加-ll選項,但是可以編譯通過。下面開始著重整理下Lex描述文件.l。
二.Lex(Lexical Analyzar) 描述文件的結構介紹
Lex工具是一種詞法分析程序生成器,它可以根據詞法規則說明書的要求來生成單詞識
別程序,由該程序識別出輸入文本中的各個單詞。一般可以分為<定義部分><規則部
分><用戶子程序部分>。其中規則部分是必須的,定義和用戶子程序部分是任選的。
(1)定義部分
定義部分起始於 %{ 符號,終止於 %} 符號,其間可以是包括include語句、聲明語句
在內的C語句。這部分跟普通C程序開頭沒什麼區別。
%{
#include "stdio.h"
int linenum;
%}
(2) 規則部分
規則部分起始於"%%"符號,終止於"%%"符號,其間則是詞法規則。詞法規則由模式和
動作兩部分組成。模式部分可以由任意的正則表達式組成,動作部分是由C語言語句組
成,這些語句用來對所匹配的模式進行相應處理。需要注意的是,lex將識別出來的單
詞存放在yytext[]字元數據中,因此該數組的內容就代表了所識別出來的單詞的內容。
類似yytext這些預定義的變數函數會隨著後面內容展開一一介紹。動作部分如果有多
行執行語句,也可以用{}括起來。
%%
title showtitle();
[\n] linenum++;
[0-9]+ printf("Int : %s\n",yytext);
[0-9]*\.[0-9]+ printf("Float : %s\n",yytext);
[a-zA-Z][a-zA-Z0-9]* printf("Var : %s\n",yytext);
[\+\-\*\/\%] printf("Op : %s\n",yytext);
. printf("Unknown : %c\n",yytext[0]);
%%
A.規則部分的正則表達式
規則部分是Lex描述文件中最為復雜的一部分,下面列出一些模式部分的正則表達式字
符含義:
A-Z, 0-9, a-z 構成模式部分的字元和數字。
- 指定范圍。例如:a-z 指從 a 到 z 之間的所有字元。
\ 轉義元字元。用來覆蓋字元在此表達式中定義的特殊意義,
只取字元的本身。
[] 表示一個字元集合。匹配括弧內的任意字元。如果第一個字
符是^那麼它表示否定模式。例如: [abC] 匹配 a, b, 和C
的任何一個。
^ 表示否定。
* 匹配0個或者多個上述模式。
+ 匹配1個或者多個上述模式。
? 匹配0個或1個上述模式。
$ 作為模式的最後一個字元時匹配一行的結尾。
{ } 表示一個模式可能出現的次數。 例如: A{1,3} 表示 A 可
能出現1次或3次。[a-z]{5} 表示長度為5的,由a-z組成的
字元。此外,還可以表示預定義的變數。
. 匹配任意字元,除了 \n。
( ) 將一系列常規表達式分組。如:{Letter}({Letter}|{Digit})*
| 表達式間的邏輯或。
"一些符號" 字元的字面含義。元字元具有。如:"*" 相當於 [\*]。
/ 向前匹配。如果在匹配的模式中的"/"後跟有後續表達式,
只匹配模版中"/"前面的部分。如:模式為 ABC/D 輸入 ABCD,
時ABC會匹配ABC/D,而D會匹配相應的模式。輸入ABCE的話,
ABCE就不會去匹配ABC/D。
B.規則部分的優先順序
規則部分具有優先順序的概念,先舉個簡單的例子:
%{
#include "stdio.h"
%}
%%
[\n] ;
A {printf("ONE\n");};
AA {printf("TWO\n");};
AAAA {printf("THREE\n");};
%%
此時,如果輸入內容:
[root@localhost liweitest]# cat file1.txt
AAAAAAA
[root@localhost liweitest]# ./parser < file1.txt
THREE
TWO
ONE
Lex分析詞法時,是逐個字元進行讀取,自上而下進行規則匹配的,讀取到第一個A字元
時,遍歷後發現三個規則皆匹配成功,Lex會繼續分析下去,讀至第五個字元時,發現
"AAAA"只有一個規則可用,即按行為進行處理,以此類推。可見Lex會選擇最長的字元
匹配規則。
如果將規則
AAAA {printf("THREE\n");};
改為
AAAAA {printf("THREE\n");};
./parser < file1.txt 輸出結果為:
THREE
TWO
再來一個特殊的例子:
%%
title showtitle();
[a-zA-Z][a-zA-Z0-9]* printf("Var : %s\n",yytext);
%%
並輸入title,Lex解析完後發現,仍然存在兩個規則,這時Lex只會選擇第一個規則,下面
的則被忽略的。這里就體現了Lex的順序優先順序。把這個例子稍微改一下:
%%
[a-zA-Z][a-zA-Z0-9]* printf("Var : %s\n",yytext);
title showtitle();
%%
Lex編譯時會提示:warning, rule cannot be matched.這時處理title字元時,匹配
到第一個規則後,第二個規則就無效了。
再把剛才第一個例子修改下,加深下印象!
%{
#include "stdio.h"
%}
%%
[\n] ;
A {printf("ONE\n");};
AA {printf("TWO\n");};
AAAA {printf("THREE\n");};
AAAA {printf("Cannot be executed!");};
./parser < file1.txt 顯示效果是一樣的,最後一項規則肯定是會忽略掉的。
C.規則部分的使用變數
且看下面示例:
%{
#include "stdio.h"
int linenum;
%}
int [0-9]+
float [0-9]*\.[0-9]+
%%
{int} printf("Int : %s\n",yytext);
{float} printf("Float : %s\n",yytext);
. printf("Unknown : %c\n",yytext[0]);
%%
在%}和%%之間,加入了一些類似變數的東西,注意是沒有;的,這表示int,float分
別代指特定的含義,在兩個%%之間,可以通過{int}{float}進行直接引用,簡化模
式定義。
(3) 用戶子程序部分
最後一個%%後面的內容是用戶子程序部分,可以包含用C語言編寫的子程序,而這些子
程序可以用在前面的動作中,這樣就可以達到簡化編程的目的。這里需要注意的是,
當編譯時不帶-ll選項時,是必須加入main函數和yywrap(yywrap將下後面說明)。如:
...
%%
showtitle()
{
printf("----- Lex Example -----\n");
}
int main()
{
linenum=0;
yylex(); /* 進行Lex分析 */
printf("\nLine Count: %d\n",linenum);
return 0;
}
int yywrap()
{
return 1;
}
三.Lex(Lexical Analyzar) 一些的內部變數和函數
內部預定義變數:
yytext char * 當前匹配的字元串
yyleng int 當前匹配的字元串長度
yyin FILE * lex當前的解析文件,默認為標准輸出
yyout FILE * lex解析後的輸出文件,默認為標准輸入
yylineno int 當前的行數信息
內部預定義宏:
ECHO #define ECHO fwrite(yytext, yyleng, 1, yyout) 也是未匹配字元的
默認動作
內部預定義的函數:
int yylex(void) 調用Lex進行詞法分析
int yywrap(void) 在文件(或輸入)的末尾調用。如果函數的返回值是1,就停止解
析。 因此它可以用來解析多個文件。代碼可以寫在第三段,這
樣可以解析多個文件。 方法是使用 yyin 文件指針指向不同的
文件,直到所有的文件都被解析。最後,yywrap() 可以返回1
來表示解析的結束。
lex和flex都是解析Lex文件的工具,用法相近,flex意為fast lexical analyzer generator。
可以看成lex的升級版本。
相關更多內容就需要參考flex的man手冊了,十分詳盡。
四.關於Lex的一些綜述
Lex其實就是詞法分析器,通過配置文件*.l,依據正則表達式逐字元去順序解析文件,
並動態更新內存的數據解析狀態。不過Lex只有狀態和狀態轉換能力。因為它沒有堆棧,
它不適合用於剖析外殼結構。而yacc增加了一個堆棧,並且能夠輕易處理像括弧這樣的
結構。Lex善長於模式匹配,如果有更多的運算要求就需要yacc了。
『玖』 關於編譯原理的問題
1.當然是機器語言了,如果是匯編指令,那還得編譯一次!能運行的程序都是機器語言,只有機器語言才能控制CPU,NET或Java這些中間語言,程序在運行時會被CLR或JVM快速編譯成機器語言,因此這些程序速度上有損失。
高級語言源代碼(文本)-通過編譯器(compiler)-程序(二進制機器語言)
匯編代碼(文本)-通過匯編器(assembler)-程序(二進制語言)
看到這里,你可能會想那匯編語言到底有什麼用呢,編譯器完全能代替匯編啊?
(1).編譯器是通過高級語言(c,c++)轉到機器語言的。轉換過的機器語言受限與高級語言,效率和功能上都有限制。比如c不等過分操作內存。但通過匯編器轉化過來的機器語言,效率高,且用匯編語言,直接和CPU對話!
(2).匯編可以反匯編(逆向編譯),而這里高級語言沒有發言權,就是:
程序(二進制機器語言)-通過反匯編器(compiler)-可轉化為匯編代碼(文本)
但永遠不能轉化為高級語言的源代碼,。
以上兩點匯編存在的重要性。
2。當然是說移植源代碼。windows用x86機器語言,蘋果用powerPC機器語言,windows程序當然不能運行在蘋果機上,因為程序其實就是一串機器語言!但windows上有c的編譯器(vc++),蘋果機上也有c編譯器(gcc),因此同一個c的源代碼,當然就可以通過不同平台的同一種編譯器實現平台移植。
3.當然是NASM,我看的所有書都首先說NASM,他是開源的,就像Linux一樣,很受歡迎,還有MASN是微軟的,borland的也有匯編器,不過都不常見了。
4.這跟CPU有關,一般32位x86兼容的cpu有許多寄存器,多數是32位的,也有16位的。比如CS,ES,DS這些segment寄存器一直是16位的。
5.優勢太多了,這和32位和16位存在的優勢一樣,16位電腦最大內存1MB,寄存器都是16位的。32位,最大內存可以有4GB,整整是16位的4096倍啊!16位多渺小啊,同理64位基本上也可以蔑視32位,64內存最大內存用TB來衡量,寄存器多數是64位!地址匯流排也是64位。64對32位沒有什麼優勢劣勢可言,64位完全就是32位的下一代。
『拾』 在碩士期間轉專業申請CS碩士留學的話,可行嗎要怎麼准備
可行,最重要的是課程方面的背景要補充,高數線代概率論都是要學的,另外還要修一些CS的專業課,如計算機組成原理、操作系統、離散數學、數據結構、計算機網路等等。學完這些就基本入門了。高階課比如編譯原理、演算法、計算機圖形學、面向對象程序設計、軟體工程、人工智慧等等多多益善。