现在的位置: 首页 > 综合 > 正文

一个简单的C语言词法分析与语法分析器【原】

2012年11月01日 ⁄ 综合 ⁄ 共 4970字 ⁄ 字号 评论关闭

 


 

词法分析
可识别内容:
标识符:id
数字:num
关键字:int,char,if,else,while,do,for
标号:, , . ,  ;
算术运算符号:=,+,-,*,/,&,!,|,&&,||
关系运算符:<,<=,>=,>,==,!=
注释://

内码定义:
单个符号,如{,+,*,> 等,均使用其ascii码做内码,占双或多个字节的符号(包括保留字,标号,数字,运算符等)为其取名如下:
Enum { END=0,INT,CHAR,IF,ELSE,WHILE=5,
DO,FOR,ARGAND,ARGOR,NUM=10,
ID,LESSEQUAL,EQUAL,GREATEQUAL,NOTEQUAL=15 };
其中NUM代表数字,ID代表标识符.

测试程序1-1的词法分析结果如下:

内码表
123 {
11 X
61 =
10 12
43 +
43 +
11 b
47 /
10 13
45 -
10 5
42 *
10 4
42 *
10 9 
59 ;
11 Y
61 =
10 4
42 *
10 1024
59 ;
3 if
40 (
11 X
14 >=
11 Y
41 )
123 {
3 if 40 (
11 i
13 ==
11 i
41 )
123 {
11 X
61 =
11 Y
125 }
125 }
59 ;
59 ;
59 ;
59 ;
 5 while
40 (
11 X
60 <
11 Y
41 )
123 {
11 X
61 =
11 X
43 +
10 1
59 ;
125 }
125 }
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

语法分析
C语言子集,可支持
语句块,语句,条件语句,While循环语句,赋值语句,基本算术表达式等。例如:
{
  // Comment Supported : This is only a Test ^_^

X = 12 + b / 13 - 5 * 4 * 9; // A AssignmentStatement
Y = 4 * 1024;
if( X >= Y){
if( i == i){   // This is nested if Statement
X=Y; 
}
}
;;;;      // This is Null Statement
while( X < Y){   // This is while Statement
X = X +1;
}

测试程序1-1 

 

 

 

支持错误检测,如将上面例子中X = 12 + b / 13 - 5 * 4 * 9;
故意修改为:X = 12 ++ b / 13 - 5 * 4 * 9; 则会出现如下错误提示,指示了出错行数和行内偏移位置:

规则如下:
  <StatementBlock> ::= '{'<StatementSequence>'}'
  <StatementSequence> ::= {<NullStatement>|<CommonStatement>|<VariantStatement>}

  <NullStatement> ::= ';'
  <CommonStatement> ::= <AssignmentStatement>
  <VariantStatement> ::= <ConditionStatement>| <LoopWhileStatement>

  <AssignmentStatement> ::= ID=<Expression>
  <ConditionStatement> ::= if(<Condition> <StatementBlock>
  <LoopWhileStatement> ::= while(<Condition> <StatementBlock>

  <Condition> ::= <Expression><RelationOperator><Expression>
  <Expression> ::= <Item>{+<Item>|-<Item>}
  <Item> ::= <Factor>{*<Factor>|/<Factor>}
  <Factor> ::= ID|NUM|(<Expression>)
  <RelationOperator> ::= <|<=|>=|>|==|!=
 
//非终结符的英文定义
void StatementBlock();  //语句块
void StatementSequence(); //语句串

// XxxxxStatement() 为三类语句
void NullStatement();  //空语句--仅仅含有一个;号
void CommonStatement();  //语句
void VariantStatement(); //变种语句--包括 if(){},while{},他们都不以;结尾

// 下面的属于CommonStatement
void AssignmentStatement(); //赋值语句

// 下面两种属于VariantStatement
void ConditionStatement(); //条件语句
void LoopWhileStatement(); //while循环语句

void Condition();   //条件
void Expression();   //表达式
void Item();    //项
void Factor();    //因子
void RelationOperator();  //关系运算符 

不能支持的主要方面:函数调用的识别,逗号表达式,for循环,switch语句。

 


 

词法分析:

 

// LexAly.cpp :C子集词法分析程序
/**//*
  
支持内容:
标识符:id
关键字: int,char,if,else,while,do,for
标号: ,, .,  ;
算术运算符号: =,+,-,&,!,|,&&,||

全局字符串:
instr 记录待解析的字符串
string 存贮当前被解析到的ID

接口:
gettoken();



Sample:
输入:
instr = 
for(i=0;i<10;i++){
    j=i+10;
    printf("%d",j);
}
输出:
for
(
i
……
}


注意:
要记得处理程序中未显示出来的符号,如空白(' '),回车(' '),值表符(' ')
*/


#include 
"stdafx.h"
#include 
<ctype.h>
#include 
<stdlib.h>
#include 
<string.h>
#include 
"Constant.h"

extern 
void grammar_check();


// 注意:这里累计数目(最大值)不能大于32 (10 0000B)TOKEN
//enum {END=0,INT=1,CHAR,IF,ELSE,WHILE,DO,FOR,ARGAND,ARGOR,NUM,ID} ;

char index[][20= ...{
    
...{"END OF File"},    /**//* 0 END*/
    
...{"int"},    /**//* 1 INT*/
    
...{"char"},    /**//* 2 CHAR*/
    
...{"if"},    /**//* 3 IF*/
    
...{"else"},    /**//* 4 ELSE*/
    
...{"while"},    /**//* 5 WHILE*/
    
...{"do"},    /**//* 6 DO*/
    
...{"for"},    /**//* 7 FOR*/
    
...{"&&"},    /**//* 8 ARGAND*/
    
...{"||"},    /**//* 9 ARGOR*/
    
...{""},    /**//* 10 NUM */
    
...{""},    /**//* 11 ID */
    
...{"<="},    /**//* 12 LESSEQUAL */
    
...{"=="},    /**//* 13 EQUAL */
    
...{">="},    /**//* 14 GREATEQUAL */
    
...{"!="},    /**//* 15 NOTEQUAL */
    
...{""}    /**//* 16 ID */
}
;

char input[10000= ...{0};

char * instr = input;
char * const start_of_instr=input;

//string 包含gettoken最新得到的id等串
//gym包含 gettoken得到的内容的代号
//current_line 包含当前行号
char string[MAX_INDENT];
int  sym;
int current_line = 1;
int start_pos_of_current_line;

char *strstart;    //用于辅助识别num,id

int gettoken();
int _gettoken();

void error(char *cur);
char* getlinestring(int line,char *in_buf);
int nextline();
int getline();
int getcurrentpos();


int nextline() ...{    return ++current_line; }
int getline() ...{    return current_line; }
int getcurrentpos() ...return (int)instr; }

char* getlinestring(int line,char *in_buf)
...{
    
char * t = input;
    
int i = 1;

    
while(*!= 0 &&  i < line )...{
        
if*t=='
' ) i++;
        t
++;
    }


    
int len = 0;
    
while ( *!= '
' )...{
        in_buf[len] 
= *t;
        len
++;
        t
++;
    }

    in_buf[len] 
= 0;
    
return in_buf;
        
}


void error(char *cur)
...{
    printf(
"Spell Error found at line %d 
",getline());
    exit(
0);
    
}



//语法分析
int main_grammar(char *filename)
...{
    
int i;

    FILE 
*f;
    
if(!(f=fopen(filename,"r")))...{
        printf(
"Fail to open source file %s!
",filename);
        exit(
0);
    }

    
int k=0;
    
char c;
    
while((c=fgetc(f))!=EOF)
    
...{
        input[k]
=c;
        k
++;
    }

    input[k] 
= 0;
    
    
//打印出程序
    printf("%s
",start_of_instr);

    
//开始语法检查
    grammar_check();

    printf(
"Success!
");
    
return 0;
}


// 词法分析
int main_spell(char *filename)
...{
    
int i;

    FILE 
*f;
    
if(!(f=fopen(filename,"r")))...{
        printf(
"Fail to open source file %s!
",filename);
        exit(
0);
    }


    

    
int k=0;
    
char c;
    
while((c=fgetc(f))!=EOF)
    
...{
        input[k]
=c;
        k
++;
    }


    input[k] 
= 0;

    printf(
"%s
",start_of_instr);


    
while((i=gettoken())!=

抱歉!评论已关闭.