Created
March 4, 2012 07:53
-
-
Save wong2/1971162 to your computer and use it in GitHub Desktop.
编译原理作业
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <ctype.h> | |
#include <stdlib.h> | |
#define NUM_OF_KEYWORDS 7 | |
#define BUFFER_SIZE 1000 | |
#define TOKEN_VALUE_SIZE 20 | |
typedef struct Token{ | |
int id; | |
char value[TOKEN_VALUE_SIZE]; | |
} Token; | |
enum lexemes {ID = 10, NUM, PLUS = 13, MINUS, MUL, DIVIDE, LE, NE, LT, COLON = 21, COLONE, COMMA, LPARENTHESIS = 27, RPARENTHESIS = 28, WRONG = 100}; | |
char buffer[BUFFER_SIZE]; | |
char *keywords[NUM_OF_KEYWORDS] = {"begin", "end", "if", "then", "else", "while", "do"}; | |
int p = 0; | |
int line = 0; | |
int lastIsNumOrID = 2; | |
void ungetch(int n) | |
{ | |
while(n--) | |
p--; | |
} | |
int isKeyword(char *s) | |
{ | |
int i; | |
for(i=0; i<NUM_OF_KEYWORDS; i++) | |
if(strcmp(s, keywords[i]) == 0) | |
return i+1; | |
return 0; | |
} | |
/* ??double? */ | |
double str2db(char *s) | |
{ | |
int sign, signn, n, power, i = 0; | |
double result = 0.0; | |
sign = isdigit(s[0]) ? 1 : (44-s[i++]); | |
while(isdigit(n=s[i++])) | |
result = 10.0 * result + (n-'0'); | |
if(s[i] == '.') | |
i++; | |
for(power=1; isdigit(n=s[i]); i++){ | |
result = 10.0 * result + (n-'0'); | |
power *= 10; | |
} | |
result /= power; | |
if(s[i] == 'e'){ | |
signn = isdigit(s[++i]) ? 1 : (44-s[i++]); | |
result *= pow(10, signn * atoi(s+i)); | |
} | |
return sign * result; | |
} | |
Token scanner() | |
{ | |
Token token; | |
char c; | |
int id, i = 0; | |
while(isspace(c=buffer[p++])){ | |
if(c == '\n') | |
line++; | |
} | |
if(isalpha(c)){ | |
token.value[i++] = c; | |
while(isalnum(c = buffer[p++]) && c != '\0'){ | |
token.value[i++] = c; | |
} | |
ungetch(1); | |
token.value[i] = '\0'; | |
token.id = (id = isKeyword(token.value)) ? id : ID; | |
lastIsNumOrID = 1; | |
return token; | |
} | |
else if((lastIsNumOrID == 0 && (c == '+' || c == '-') && (isdigit(buffer[p]))) || isdigit(c)){ | |
token.value[i++] = c; | |
while(isdigit(c=buffer[p++]) && c != '\0') | |
token.value[i++] = c; | |
if(c == '.'){ | |
token.value[i++] = c; | |
while(isdigit(c=buffer[p++])) | |
token.value[i++] = c; | |
} | |
if(c == 'e'){ | |
token.value[i++] = c; | |
if((c=buffer[p++]) == '+' || c == '-') | |
token.value[i++] = c; | |
else | |
ungetch(1); | |
while(isdigit(c=buffer[p++])) | |
token.value[i++] = c; | |
} | |
ungetch(1); | |
token.value[i] = '\0'; | |
token.id = NUM; | |
lastIsNumOrID = 1; | |
return token; | |
} | |
else{ | |
token.value[i++] = c; | |
switch(c){ | |
case '+': | |
token.id = PLUS; | |
break; | |
case '-': | |
token.id = MINUS; | |
break; | |
case '*': | |
token.id = MUL; | |
break; | |
case '/': | |
token.id = DIVIDE; | |
break; | |
case '<': | |
if((c = buffer[p++]) == '='){ | |
token.id = LE; | |
token.value[i++] = c; | |
} | |
else if(c == '>'){ | |
token.id = NE; | |
token.value[i++] = c; | |
} | |
else{ | |
ungetch(1); | |
token.id = LT; | |
} | |
break; | |
case ':': | |
if((c = buffer[p++]) == '='){ | |
token.id = COLONE; | |
token.value[i++] = c; | |
} | |
else{ | |
token.id = COLON; | |
ungetch(1); | |
} | |
break; | |
case ';': | |
token.id = COMMA; | |
break; | |
case '(': | |
token.id = LPARENTHESIS; | |
break; | |
case ')': | |
token.id = RPARENTHESIS; | |
break; | |
default: | |
token.id = WRONG; | |
token.value[i++] = line + '0'; | |
} | |
token.value[i] = '\0'; | |
lastIsNumOrID = 0; | |
return token; | |
} | |
} | |
int main() | |
{ | |
char c, fileName[25]; | |
Token token; | |
FILE *fp; | |
/* ????ж? */ | |
do{ | |
printf("\nPress i to input codes, or press r to read codes from a file: "); | |
}while((c = getchar()) != 'i' && c != 'r'); | |
/* ???buffer */ | |
if(c == 'i'){ | |
printf("\nPlease input the codes: (end with #)\n"); | |
while((c=getchar()) != '#'){ | |
buffer[p++] = c; | |
} | |
} | |
/* ?ж??buffer */ | |
else{ | |
printf("\nPlease input the file's path: "); | |
scanf("%s", fileName); | |
if((fp = fopen(fileName, "r")) == NULL){ | |
printf("Can't open the file!"); | |
return 1; | |
} | |
while((c=fgetc(fp)) != EOF){ | |
buffer[p++] = c; | |
} | |
} | |
/* ?? */ | |
while(isspace(buffer[--p])); | |
buffer[p+1] = '\0'; | |
getchar(); | |
p = 0; | |
/* scanner()??? */ | |
while(buffer[p] != '\0'){ | |
token = scanner(); | |
if(token.id == NUM){ | |
printf("Token is < %d, %e >\n", token.id, str2db(token.value)); | |
} | |
else if(token.id == WRONG) | |
printf("Error Found on line %c\n", token.value[1]); | |
else | |
printf("Token is < %d, %s >\n", token.id, token.value); | |
} | |
/*(+123.456+-456.789e-120)*m2+(a++456)*/ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment