📄 grammar_analyse.cpp
字号:
#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 + -