⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grammar_analyse.cpp

📁 C-语言的编译器中的词法分析和语法分析VC++开发
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <iostream>
#include <string>
#include <fstream>
#include <stdio.h>
#include<conio.h>
#define MAXTOKENLEN 40//
#define MAXLINE 1000
#define MAXRESERVED 6
#define FALSE 0
#define TRUE 1
#define BUFLEN 256//

#define MAXCHILDREN 3
static int indentno = 0; 
#define INDENT indentno+=2
#define UNINDENT indentno-=2

using namespace std;

int   lineno=0; //
FILE* source; //
FILE* listing;//
int   linepos=0;//
static int bufsize=0;//
char file_in[100];
char file_out[100];
char lineBuf[MAXLINE];//
char tokenString[MAXTOKENLEN+1];

int Error = false;


typedef enum 
{   ENDFILE,ERROR,
    ELSE,IF,INT,RETURN,VOID,WHILE,//keyword
    ID, NUM,
    ADD,SUB,MUL,DIV,LT,LE,GT,GE,EQ,NEQ,ASSIGN,SEMICOLON,COMMA,LSP,RSP,LMP,RMP,LLP,RLP
}TokenType;

typedef enum
{ 
        START, INASSIGN, SINCOMMENT, FINCOMMENT, INCOMMENT, 
        INNUM, INID, INL, ING,INNE, DONE ,
        
}StateType;

static struct
{    char* str;
     TokenType tok;
}reservedWords[MAXRESERVED]=
{{"else",ELSE},{"if",IF},{"int",INT},{"return",RETURN},{"void",VOID},{"while",WHILE}}; 

TokenType reservedLookup(char *s)
{    for(int i=0;i<MAXRESERVED;i++)
        if(!strcmp(s,reservedWords[i].str))return reservedWords[i].tok; 
     return ID;
}

char getNextChar(void)
{   
    if(linepos >= bufsize)
    {
        lineno++;
       
        if(fgets(lineBuf,BUFLEN-1,source)){
                 cout<<endl<<"line"<<lineno<<": "<<lineBuf<<endl;
                 bufsize = strlen(lineBuf);
                 linepos=0;
                 return lineBuf[linepos++];
        }
        else return EOF;
    } 
    else return lineBuf[linepos++];
}

void ungetNextChar(void)
{    linepos --;    }

bool isdigit(char c)//判断是不是数字 
{
     if(c >= '0' && c <= '9') return true;
     return false;
}

bool isalpha(char c)//判断是不是字母 
{
     if(c >=65 && c <=90 || c >= 97 && c <= 122) return true;
     return false;
}
//
TokenType getToken(void)
{ 
   int tokenStringIndex = 0;
   TokenType currentToken;
   StateType state = START;
   int save ;
   while (state != DONE)
   { char c = getNextChar();
     save = true;
     switch (state)
     { case START:
         if (isdigit(c))
           state = INNUM;
         else if (isalpha(c))
           state = INID;
         else if (c == ' ' || c == '\t'||c=='\n')
           save = false;
         else if (c == '=')
           state = INASSIGN;
         else if (c == '<')
           state = INL;
         else if (c == '>')  
           state = ING;
         else if (c == '!')
           state = INNE;
         else if (c == '/')
         { 
           save  = false;
           state = SINCOMMENT;
         }
         else 
         {
           state = DONE;
           switch(c)
           {  case EOF : save = false; currentToken = ENDFILE; break;
              case '+' : currentToken = ADD; break;
              case '-' : currentToken = SUB; break;
              case '*' : currentToken = MUL; break;
              case ';' : currentToken = SEMICOLON; break;
              case ',' : currentToken = COMMA; break;
              case '(' : currentToken = LSP; break;
              case ')' : currentToken = RSP; break;
              case '[' : currentToken = LMP; break;
              case ']' : currentToken = RMP; break;
              case '{' : currentToken = LLP; break;
              case '}' : currentToken = RLP; break;
              default  : currentToken = ERROR;break;
           }
         }
         break;
       case SINCOMMENT:
         if (c == '*')
         {  save  = false;
            state = INCOMMENT;
         }
         else
         { 
            c = '/';
            save = true;
            state = DONE;
            currentToken = DIV; // 
            ungetNextChar();
         }
         break;  
       case INCOMMENT:
         if (c == EOF)
         { state = DONE;
           currentToken = ENDFILE;
         }
         else if (c == '*') { state = FINCOMMENT; save  = false; }
         else save  = false;
         break;
       case FINCOMMENT:
         if (c == '/')
         {
            state = START;
            save  = false;
         }
         else if(c == '*') { state= FINCOMMENT; save  = false; }
         else { state = INCOMMENT; save  = false; }
         break;
       case INASSIGN:
         state = DONE;
         if (c == '=')
           currentToken = EQ;
         else
         { 
           ungetNextChar();
           save = false;
           currentToken = ASSIGN;
         }
         break;
       case INL:
         state = DONE;
         if (c == '=')
           currentToken = LE;
         else
         {
           ungetNextChar();
           save = false;
           currentToken = LT;
         }
         break;
       case ING:
         state = DONE;
         if (c == '=')
           currentToken = GE;
         else
         { 
           ungetNextChar();
           save = false;
           currentToken = GT;
         }
         break;
       case INNE:
         state = DONE;
         if (c == '=')
           currentToken = NEQ;
         else
         { 
           ungetNextChar();
           save = false;
           currentToken = ERROR;
         }
         break;
       case INNUM:
         if (!isdigit(c))
         { 
           ungetNextChar();
           save = false;
           state = DONE;
           currentToken = NUM;
         }
         break;
       case INID:
         if (!isalpha(c))
         {
           ungetNextChar();
           save = false;
           state = DONE;
           currentToken = ID;
         }
         break;
       case DONE:
       default: 
         cout<<listing<<"Scanner Bug: state= "<<state<<endl;
         state = DONE;
         currentToken = ERROR;
         break;
     }
     if ((save) && (tokenStringIndex <= MAXTOKENLEN)){
       tokenString[tokenStringIndex++] = (char) c;
       }
     if (state == DONE)
     { tokenString[tokenStringIndex] = '\0';
       if (currentToken == ID)
         currentToken = reservedLookup(tokenString);
     }
   }
   return currentToken;
} 

void printToken(TokenType token, char * tokenString)
{
   switch(token)
   {   case ERROR      : cout<<lineno<<": ERROE!"<<endl;
                         fprintf(listing,"    %d: ERROE  %s\n",lineno,tokenString);break;
       case ENDFILE    : cout<<"END OF FILE!"<<endl; fprintf(listing,"%s\n",tokenString);break;
       case ELSE       : cout<<lineno<<": Keyword     "<<tokenString<<endl;
                         fprintf(listing,"    %d: Keyword     %s\n",lineno,tokenString);break;
       case IF         : cout<<lineno<<": Keyword     "<<tokenString<<endl;
                         fprintf(listing,"    %d: Keyword     %s\n",lineno,tokenString);break;
       case INT        : cout<<lineno<<": Keyword     "<<tokenString<<endl;
                         fprintf(listing,"    %d: Keyword     %s\n",lineno,tokenString);break;
       case RETURN     : cout<<lineno<<": Keyword     "<<tokenString<<endl;
                         fprintf(listing,"    %d: Keyword     %s\n",lineno,tokenString);break;
       case VOID       : cout<<lineno<<": Keyword     "<<tokenString<<endl;
                         fprintf(listing,"    %d: Keyword     %s\n",lineno,tokenString);break;
       case WHILE      : cout<<lineno<<": Keyword     "<<tokenString<<endl;
                         fprintf(listing,"    %d: Keyword     %s\n",lineno,tokenString);break;
       case ID         : cout<<lineno<<": Identifier  "<<tokenString<<endl;
                         fprintf(listing,"    %d: Identifier  %s\n",lineno,tokenString);break;
       case NUM        : cout<<lineno<<": Number      "<<tokenString<<endl;
                         fprintf(listing,"    %d: Number      %s\n",lineno,tokenString);break;
       case ADD        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case SUB        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case MUL        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case DIV        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case LT         : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case LE         : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case GT         : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case GE         : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case EQ         : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case NEQ        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case ASSIGN     : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case SEMICOLON  : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case COMMA      : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case LSP        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case RSP        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case LMP        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case RMP        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case LLP        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break;
       case RLP        : cout<<lineno<<": Sign        "<<tokenString<<endl;
                         fprintf(listing,"    %d: Sign        %s\n",lineno,tokenString);break; 
       default         : fprintf(listing,"\n");break;
   }
}



/************************************************************************************************/
typedef enum { StmtK,ExpK } NodeKind;
typedef enum { AssignK,CompK,IfK,RepeatK,ReturnK } StmtKind;
typedef enum { OpK,ConstK,IdK } ExpKind;
typedef enum { Void } ExpType;


/*************TREE**********************/
typedef struct treeNode
{  struct treeNode * child[MAXCHILDREN];
   struct treeNode * sibling;
   int lineno;
   NodeKind nodekind;
   union { StmtKind stmt; ExpKind exp;}kind;
   union { char * op;
           int val;
           char * name;}attr;
   ExpType type;
}TreeNode;

TreeNode * newStmtNode(StmtKind kind)
{  TreeNode * t = (TreeNode *)malloc(sizeof(TreeNode));
   int i;
   if(t==NULL) fprintf(listing,"Out of memory error at line %d\n",lineno);
   else
   {  for(i=0;i<MAXCHILDREN;i++) t->child[i] = NULL;
      t->sibling = NULL;
      t->nodekind = StmtK;
      t->kind.stmt = kind;
      t->lineno = lineno;
   }
   return t;
}

TreeNode * newExpNode(ExpKind kind)
{  TreeNode * t = (TreeNode *)malloc(sizeof(TreeNode));
   int i;
   if(t==NULL) fprintf(listing,"Out of memory error at line %d\n",lineno);
   else
   {  for(i=0;i<MAXCHILDREN;i++) t->child[i] = NULL;
      t->sibling = NULL;
      t->nodekind = ExpK;
      t->kind.exp = kind;
      t->lineno = lineno;
      t->type = Void;
   }
   return t;
}

char * copyString(char *s)
{  int n;
   char * t;
   if(s==NULL) return NULL;
   n = strlen(s)+1;
   t = (char *)malloc(n);
   if(t==NULL) fprintf(listing,"Out of memory error at line %d\n",lineno);
   else strcpy(t,s);
   return t;
}

void printSpace(void)
{  int i;
   for(i=0;i<indentno;i++) fprintf(listing," ");
}

void printTree(TreeNode * tree)
{  int i;
   INDENT;
   while(tree!=NULL)
   {  printSpace();
      if(tree->nodekind==StmtK)
      {  switch(tree->kind.stmt)
         {  case IfK     : fprintf(listing,"If\n");break;
            case RepeatK : fprintf(listing,"Iteration\n");break;
            case AssignK : fprintf(listing,"Assign\n");break;
            case ReturnK : fprintf(listing,"Return\n");break;
            case CompK   : fprintf(listing,"Compound\n");break;
            default      : fprintf(listing,"Unknown StmtNode\n");break;
         }
      }
      else if(tree->nodekind==ExpK)
      {  switch(tree->kind.exp)
         {  case OpK     : fprintf(listing,"Op: %s\n",tree->attr.op);break;
            case ConstK  : fprintf(listing,"Const: %d\n",tree->attr.val);break;
            case IdK     : fprintf(listing,"Id: %s\n",tree->attr.name);break;
            default      : fprintf(listing,"Unknown ExpNode\n");break;
         }
      }
      else fprintf(listing,"Unknown node kind\n");
      for(i=0;i<MAXCHILDREN;i++) printTree(tree->child[i]);
      tree = tree->sibling;
   }
   UNINDENT;
}
/*************************************************/
static TokenType token;
TreeNode * declaration_list(void);
TreeNode * declaration(void);
TreeNode * var_declaration(void);
TreeNode * params(void);
TreeNode * param(void);
TreeNode * compound_stmt(void);
TreeNode * local_declarations(void);
TreeNode * statement_list(void);
TreeNode * statement(void);
TreeNode * selection_stmt(void);
TreeNode * iteration_stmt(void);
TreeNode * return_stmt(void);
TreeNode * assign_stmt(void);
TreeNode * expression(void);
TreeNode * additive_expression(void);
TreeNode * term(void);
TreeNode * factor(void);
TreeNode * args(void);




void syntaxError(char * message)
{  fprintf(listing,"\n>>> ");
   fprintf(listing,"Syntax error at line %d: %s",lineno,message);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -