Skip to content

Instantly share code, notes, and snippets.

@wong2
Created March 4, 2012 07:53
Show Gist options
  • Save wong2/1971162 to your computer and use it in GitHub Desktop.
Save wong2/1971162 to your computer and use it in GitHub Desktop.
编译原理作业
#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