1. 有人知道編譯原理實驗之詞法分析器用C++怎麼做嗎
#include "globals.h"
#include "util.h"
#include "scan.h"
#include "parse.h"
static TokenType token; /* holds current token */
/* function prototypes for recursive calls */
static TreeNode * stmt_sequence(void);
static TreeNode * statement(void);
static TreeNode * if_stmt(void);
static TreeNode * repeat_stmt(void);
static TreeNode * assign_stmt(void);
static TreeNode * read_stmt(void);
static TreeNode * write_stmt(void);
static TreeNode * exp(void);
static TreeNode * simple_exp(void);
static TreeNode * term(void);
static TreeNode * factor(void);
static void syntaxError(char * message)
{ fprintf(listing,"\n>>> ");
fprintf(listing,"Syntax error at line %d: %s",lineno,message);
Error = TRUE;
}
static void match(TokenType expected)
{ if (token == expected) token = getToken();
else {
syntaxError("unexpected token -> ");
printToken(token,tokenString);
fprintf(listing," ");
}
}
TreeNode * stmt_sequence(void)
{ TreeNode * t = statement();
TreeNode * p = t;
while ((token!=ENDFILE) && (token!=END) &&
(token!=ELSE) && (token!=UNTIL))
{ TreeNode * q;
match(SEMI);
q = statement();
if (q!=NULL) {
if (t==NULL) t = p = q;
else /* now p cannot be NULL either */
{ p->sibling = q;
p = q;
}
}
}
return t;
}
TreeNode * statement(void)
{ TreeNode * t = NULL;
switch (token) {
case IF : t = if_stmt(); break;
case REPEAT : t = repeat_stmt(); break;
case ID : t = assign_stmt(); break;
case READ : t = read_stmt(); break;
case WRITE : t = write_stmt(); break;
default : syntaxError("unexpected token -> ");
printToken(token,tokenString);
token = getToken();
break;
} /* end case */
return t;
}
TreeNode * if_stmt(void)
{ TreeNode * t = newStmtNode(IfK);
match(IF);
if (t!=NULL) t->child[0] = exp();
match(THEN);
if (t!=NULL) t->child[1] = stmt_sequence();
if (token==ELSE) {
match(ELSE);
if (t!=NULL) t->child[2] = stmt_sequence();
}
match(END);
return t;
}
TreeNode * repeat_stmt(void)
{ TreeNode * t = newStmtNode(RepeatK);
match(REPEAT);
if (t!=NULL) t->child[0] = stmt_sequence();
match(UNTIL);
if (t!=NULL) t->child[1] = exp();
return t;
}
TreeNode * assign_stmt(void)
{ TreeNode * t = newStmtNode(AssignK);
if ((t!=NULL) && (token==ID))
t->attr.name = String(tokenString);
match(ID);
match(ASSIGN);
if (t!=NULL) t->child[0] = exp();
return t;
}
TreeNode * read_stmt(void)
{ TreeNode * t = newStmtNode(ReadK);
match(READ);
if ((t!=NULL) && (token==ID))
t->attr.name = String(tokenString);
match(ID);
return t;
}
TreeNode * write_stmt(void)
{ TreeNode * t = newStmtNode(WriteK);
match(WRITE);
if (t!=NULL) t->child[0] = exp();
return t;
}
TreeNode * exp(void)
{ TreeNode * t = simple_exp();
if ((token==LT)||(token==EQ)) {
TreeNode * p = newExpNode(OpK);
if (p!=NULL) {
p->child[0] = t;
p->attr.op = token;
t = p;
}
match(token);
if (t!=NULL)
t->child[1] = simple_exp();
}
return t;
}
TreeNode * simple_exp(void)
{ TreeNode * t = term();
while ((token==PLUS)||(token==MINUS))
{ TreeNode * p = newExpNode(OpK);
if (p!=NULL) {
p->child[0] = t;
p->attr.op = token;
t = p;
match(token);
t->child[1] = term();
}
}
return t;
}
TreeNode * term(void)
{ TreeNode * t = factor();
while ((token==TIMES)||(token==OVER))
{ TreeNode * p = newExpNode(OpK);
if (p!=NULL) {
p->child[0] = t;
p->attr.op = token;
t = p;
match(token);
p->child[1] = factor();
}
}
return t;
}
TreeNode * factor(void)
{ TreeNode * t = NULL;
switch (token) {
case NUM :
t = newExpNode(ConstK);
if ((t!=NULL) && (token==NUM))
t->attr.val = atoi(tokenString);
match(NUM);
break;
case ID :
t = newExpNode(IdK);
if ((t!=NULL) && (token==ID))
t->attr.name = String(tokenString);
match(ID);
break;
case LPAREN :
match(LPAREN);
t = exp();
match(RPAREN);
break;
default:
syntaxError("unexpected token -> ");
printToken(token,tokenString);
token = getToken();
break;
}
return t;
}
/****************************************/
/* the primary function of the parser */
/****************************************/
/* Function parse returns the newly
* constructed syntax tree
*/
TreeNode * parse(void)
{ TreeNode * t;
token = getToken();
t = stmt_sequence();
if (token!=ENDFILE)
syntaxError("Code ends before file\n");
return t;
}
上面是一個語法分析器的主代碼部分它可以識別類似下面的代碼,但是由於篇幅有限,上面的代碼不是完整代碼,完整代碼太長,還有好幾個文件。
read x; { input an integer }
if 0 < x then { don't compute if x <= 0 }
fact := 1;
repeat
fact := fact * x;
x := x - 1
until x = 0;
write fact { output factorial of x }
end
2. C++:算術表達式求值
1/(1+1/(1+1/(x+y)));
x*(x*(x*(a*x+b)+c)+d)+e;
log(1+pow(fabs((a+b)/(a-b)),10));
sqrt(1+pi/2*cos(48));
1/tan((1-x*x)/(1+x*x));
//由於c語言中沒提供cot函數,所以就用tan的倒數表示了。
log10(a*a+a*b+b*b);
3. 編譯原理考試問題:已知表達式文法G(Exp)
簡單起見,用E代表Exp,用T代表Term,用F代表Factor。下面是所求屬性文法
(1)E→ E1 + T E.val:=E1.val+T.val /* 為了區別→兩側的E, →右側的E用E1表示 */
(2)E→
T E.val:=T.val
(3)T→ T1 * F T.val:=T1.val*F.val
(4)T→
F T.val:=F.val
(5)F→(E) F.val:=E.val
(6)F→num F.val:=num.val
4. 正則表達式
正則經常用於js 判斷手機號,郵箱等,通過簡單的辦法來實現強大的功能
符號解釋
字元 描述
\ 將下一個字元標記為一個特殊字元、或一個原義字元、或一個 向後引用、或一個八進制轉義符。例如,'n' 匹配字元 "n"。'\n' 匹配一個換行符。序列 '\\' 匹配 "\" 而 "\(" 則匹配 "("。
^ 匹配輸入字元串的開始位置。如果設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 之後的位置。
$ 匹配輸入字元串的結束位置。如果設置了RegExp 對象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 之前的位置。
* 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。
+ 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。
? 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價於 {0,1}。
{n} n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。
{n,} n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價於 'o+'。'o{0,}' 則等價於 'o*'。
{n,m} m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價於 'o?'。請注意在逗號和兩個數之間不能有空格。
? 當該字元緊跟在任何一個其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 後面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字元串,而默認的貪婪模式則盡可能多的匹配所搜索的字元串。例如,對於字元串 "oooo",'o+?' 將匹配單個 "o",而 'o+' 將匹配所有 'o'。
. 匹配除 "\n" 之外的任何單個字元。要匹配包括 '\n' 在內的任何字元,請使用象 '[.\n]' 的模式。
x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。
[xyz] 字元集合。匹配所包含的任意一個字元。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 負值字元集合。匹配未包含的任意字元。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字元范圍。匹配指定范圍內的任意字元。例如,'[a-z]' 可以匹配 'a' 到 'z' 范圍內的任意小寫字母字元。
[^a-z] 負值字元范圍。匹配任何不在指定范圍內的任意字元。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范圍內的任意字元。
\d 匹配一個數字字元。等價於 [0-9]。
\D 匹配一個非數字字元。等價於 [^0-9]。
\f 匹配一個換頁符。等價於 \x0c 和 \cL。
\n 匹配一個換行符。等價於 \x0a 和 \cJ。
\r 匹配一個回車符。等價於 \x0d 和 \cM。
\s 匹配任何空白字元,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。
\S 匹配任何非空白字元。等價於 [^ \f\n\r\t\v]。
\t 匹配一個製表符。等價於 \x09 和 \cI。
\v 匹配一個垂直製表符。等價於 \x0b 和 \cK。
\w 匹配包括下劃線的任何單詞字元。等價於'[A-Za-z0-9_]'。
\W 匹配任何非單詞字元。等價於 '[^A-Za-z0-9_]'。
具體怎麼使用還得多看例子,對照解釋
5. 這個用C語言寫的計算器的思路是什麼
對初學編程者來說,這個程序的原理確實難了點,因為它用到了編譯原理的知識.
即如果設一個四則運算表達式的形式為S,那麼它一定是一個以等號結尾的運算式,即S->exp=,->是推導符號.
運算式exp又可以繼續推導成
exp->exp+term|exp-term|term
exp表示加減運算,term表示乘除運算.這個推導式反映了乘除的優先順序比加減高.
即要先計算乘除式的結果,再來加減.
term可以推導如下:
term->term*factor|term/factor|factor
factor->num|(E)
factor是數字或者一個被括弧括住的運算式,表示最高優先順序.
數字本身是不帶運算的,是原子性的,肯定是最高優先順序.
括弧是被規定了優先計算.
這個程序的代碼就是按照上面的推導式,用遞歸方式來分析運算式的.
6. 計算器的實現(C語言)
這個計算器是賣不出去的,因為功能過於簡單o(∩_∩)o...
不支持多目運算,進制轉換只能將十進制整數轉換為其他進制整數,還有很多地方可以改進的,由於時間關系就沒一一寫出來了。
#include<stdio.h>
void add(void);
void sub(void);
void mul(void);
void div(void);
void sc(void);
void er(void);
int main()
{
int ch;
while(1)
{
printf("\n[Caculator]\n1.+ 2.- 3.* 4./ 5.Size Change 6.Exchange Rate 7.Quit\n");
do{
printf("Input Your Chooice:");
scanf("%d", &ch);
}while(!(ch > 0 && ch < 8));
if(ch == 7)
break;
switch(ch)
{
case 1:
add();
break;
case 2:
sub();
break;
case 3:
mul();
break;
case 4:
div();
break;
case 5:
sc();
break;
case 6:
er();
break;
default:
break;
}
}
return 0;
}
void add()
{
float a,b;
printf("[add]:Input a and b:");
scanf("%f%f",&a,&b);
printf("[add]Answer:%f\n",a+b);
}
void sub()
{
float a,b;
printf("[sub]:Input a and b:");
scanf("%f%f",&a,&b);
printf("[sub]Answer:%f\n",a-b);
}
void mul()
{
float a,b;
printf("[mul]:Input a and b:");
scanf("%f%f",&a,&b);
printf("[mul]Answer:%f\n",a*b);
}
void div()
{
float a,b;
printf("[div]:Input a and b:");
scanf("%f%f",&a,&b);
printf("[div]Answer:%f\n",a/b);
}
void sc()
{
int a,b,i;
char c[100];
printf("[Size Change]Input the number and change size:");
scanf("%d%d",&a,&b);
for(i = 0;a/b != 0; i++)
{
c[i] = a%b;
a /= b;
}
c[i] = a%b;
printf("[Size Change]:");
for(;i >= 0;i--)
{
printf("%d\n", c[i]);
}
}
void er()
{
float a,b;
printf("[Exchange Rate]:Input the money and rate:");
scanf("%f%f",&a,&b);
printf("[Exchange Rate]:%f\n", a*b);
}
7. 求一個用C++編過計算器的,就是那種加減乘除三角函數可以寫一排算的
//*************************************
//數學表達式解析類
//*************************************
//Expression_Parser.cpp
#include<stdio.h>
#include<string.h>
#include<math.h>
constdoublePI=3.141592654;
//將角度轉換成弧度
doubledegTorad(doubledeg)
{
return(2*PI*deg)/360;
}
//將中綴表達式轉換為後綴表達式(逆波蘭式)
voidtrans(chara[],charb[])
{
charstock[128]={0};
inttop=0;
intlen=0;
inti=0;
intj=0;
top=-1;
j=-1;
len=strlen(a);
for(i=0;i<len;i++)
{
switch(a[i])
{
case'(':
stock[++top]='(';
break;
case'+':
case'-':
while(top>=0&&stock[top]!='(')
{
b[++j]=stock[top--];
}
stock[++top]='';
stock[++top]=a[i];
break;
case'*':
case'/':
while(top>=0&&stock[top]!='('&&stock[top]!='+'&&stock[top]!='-')
{
b[++j]=stock[top--];
}
stock[++top]='';
stock[++top]=a[i];
break;
case's':
case'c':
case't':
while(top>=0&&stock[top]!='('&&stock[top]!='+'&&stock[top]!='-'&&stock[top]!='*'&&stock[top]!='/')
{
b[++j]=stock[top--];
}
stock[++top]='';
stock[++top]=a[i];
break;
case'v':
case'^':
while(top>=0&&stock[top]!='('&&stock[top]!='+'&&stock[top]!='-'&&stock[top]!='*'&&stock[top]!='/'&&stock[top]!='s'&&stock[top]!='c'&&stock[top]!='t')
{
b[++j]=stock[top--];
}
stock[++top]='';
stock[++top]=a[i];
break;
case'L':
while(top>=0&&stock[top]!='('&&stock[top]!='+'&&stock[top]!='-'&&stock[top]!='*'&&stock[top]!='/'&&stock[top]!='s'&&stock[top]!='c'&&stock[top]!='t'&&stock[top]!='v'&&stock[top]!='^')
{
b[++j]=stock[top--];
}
stock[++top]='';
stock[++top]=a[i];
break;
case')':
while(stock[top]!='(')
{
b[++j]=stock[top--];
}
top--;
break;
default:
b[++j]=a[i];
if(i==len-1||a[i+1]<'0'||a[i+1]>'9')
{
if(a[i+1]!='.')
{
b[++j]='';
}
}
break;
}
}
while(top>=0)
{
b[++j]=stock[top--];
}
b[++j]='