You are on page 1of 7

編譯器期末專案報告

資工四 49385002 陳俊志

一、介紹
  本程式是一個簡單的 C 語言 parser,運行在 Linux 作業系統下。程式使用了 flex 與 bison
此二個工具產生程式碼。執行時,使用者輸入一個.c 檔案,程式會在螢幕上輸出此檔案的語
法錯誤。

二、完成的功能
  程式能辨認以下幾種語法結構:
1. 註解
2. 一部分變數宣告功能
3. if-else 敘述
4. 迴圈方面的敘述
5. 一般的算術運算和邏輯運算  

三、執行結果
  測試以下三個檔案:
1. test1.c(有錯誤)
{
//This is a test file.
int nd2, ad3, bd4, bd5, qwes4;

nd2 = 20563;
ad3 = 1;
bd4 = 0;
0 = bd5;

while( ad3 )
bd4 = bd5 + 1;

for ( qwes4 = 0; qwes4 <= 5; qwes4 = qwes4 + 1 )


nd2 = nd2 * 2;

return nd2 + nd2 * 6;

2. test2.c(無錯誤)
{
/*This is a test file.*/
double abcdef, ghijk;

abcdef = 0.006;

if ( abcdef == 0.006 )
ghijk = 0.0;

資工四 49385002 陳俊志
3. test3.c(有錯誤)
{
int a, b, c;

a = 1;
b = 2;
c = 0;

while ( a != b ) {
c=c/5
a = a + 1;

return c

執行的結果如下圖:

test1.c

test2.c

test3.c

四、未完成的功能
1. 一般 C 程式蠻常出現的 preprocessor directive、指標、陣列和函數呼叫
2. symbol table 建立
3. syntax tree 建立

五、附錄
A. lexer.l
%{

資工四 49385002 陳俊志
#include "parser.tab.h"
#include <cstdlib>
#include <cstring>
int lineNum = 1;
%}

%option stack
%x comment ocomment

%%
"/*" BEGIN( comment );
<comment>[^*\n]*
<comment>[^*\n]*\n ++lineNum;
<comment>"*"+[^*/\n]*
<comment>"*"+[^*/\n]*\n ++lineNum;
<comment>"*"+"/" BEGIN( INITIAL );

"//" BEGIN( ocomment );


<ocomment>[^\n]*
<ocomment>\n { ++lineNum;
BEGIN( INITIAL ); }

[ \t]+ /*skip blanks and tabs*/


"int" return INT;
"double" return DOUBLE;
"if" return IF;
"else" return ELSE;
"do" return DO;
"while" return WHILE;
"for" return FOR;
"return" return RETURN;
\"[^\n"]+\" { char *tempStr = new char[ strlen( yytext ) + 1 ];
strcpy( tempStr, yytext );
yylval.sVal = tempStr;
return STRING; }
[A-Za-z_]([A-Za-z_]|[0-9])* { char *tempID = new char[ strlen( yytext ) + 1 ];
strcpy( tempID, yytext );
yylval.sVal = tempID;
return ID; }
([+-]?[0-9]+)|([+-]?[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?) { yylval.val = atof( yytext );
return NUMBER; }
">=" return GE_OP;
"<=" return LE_OP;
"==" return EQ_OP;
"!=" return NE_OP;
"&&" return AND_OP;
"||" return OR_OP;
"+" return '+';
"-" return '-';
"!" return '!';

資工四 49385002 陳俊志
"*" return '*';
"/" return '/';
"=" return '=';
">" return '>';
"<" return '<';
";" return ';';
"," return ',';
"(" return '(';
")" return ')';
"{" return '{';
"}" return '}';
\n ++lineNum;
. /*ignore bad characters*/

%%

B. parser.y
%{
#include <iostream>
#include <cstdio>
#include <string>

using namespace std;

int numOfErrs = 0;
extern FILE *yyin;
extern int yylex();
void yyerror( char * );
extern int lineNum;
%}

%token INT DOUBLE


%token IF ELSE DO WHILE FOR RETURN
%token GE_OP LE_OP EQ_OP NE_OP AND_OP OR_OP

%union {
double val;
char *sVal;
}

%token <val> NUMBER


%token <sVal> STRING ID

%%
program: block
;

block: '{' decls stmts '}'


;

資工四 49385002 陳俊志
decls: /*empty*/
| decls decl
;

decl: type ids ';'


| error ';' { yyerrok; }
;

ids: ids ',' ID


| ID
;

type: INT
| DOUBLE
;

stmts: /*empty*/
| stmts stmt
;

stmt: loc '=' bool ';'


| ifstmt
| loopstmt
| RETURN bool ';'
| RETURN ';'
| block
| error ';' { yyerrok; }
;

ifstmt: IF '(' bool ')' stmt


| IF '(' bool ')' stmt ELSE stmt
;

loopstmt: WHILE '(' bool ')' stmt


| DO stmt WHILE '(' bool ')' ';'
| FOR '(' optassign ';' ';' optassign ')' stmt
| FOR '(' optassign ';' bool ';' optassign ')' stmt
;

optassign: /*empty*/
| loc '=' bool
;

loc: ID
;

bool: bool OR_OP join


| join
;

資工四 49385002 陳俊志
join: join AND_OP equality
| equality
;

equality: equality EQ_OP rel


| equality NE_OP rel
| rel
;

rel: expr '<' expr


| expr LE_OP expr
| expr GE_OP expr
| expr '>' expr
| expr
;

expr: expr '+' term


| expr '-' term
| term
;

term: term '*' unary


| term '/' unary
| unary
;

unary: '!' unary


| '-' unary
| factor
;

factor: '(' bool ')'


| loc
| NUMBER
| STRING
;

%%
void yyerror( char *eMsg )
{
cout << "Error occurred at line " << lineNum << ": " << eMsg << endl;

++numOfErrs;
}

int main()
{
string testFile;

cout << "Enter a test file: ";

資工四 49385002 陳俊志
getline( cin, testFile );

FILE *tf = fopen( testFile.c_str(), "r" );


if ( tf != NULL ) {

yyin = tf;
int result = yyparse();
if ( result == 0 )
cout << "Parsing succeeded. " << numOfErrs << " error(s)." << endl;
else
cout << "Parsing failed. " << numOfErrs << " error(s)." << endl;

return 0;
}
else {
cout << "The file can't be opened." << endl;

return 0;
}

資工四 49385002 陳俊志

You might also like