/* basic_proj1_part1.c */ /* prettify BASIC program by identifying lexemes */ /* for each line, ensure line numbers exist */ /* reorder line numbers */ #include char nextChar; /* next character read from input */ int charClass; /* character classes: */ #define LETTER 0 /* [a-zA-Z] */ #define DIGIT 1 /* [0-9] */ #define EQUALS_SIGN 2 #define GREATER_THAN_SIGN 3 #define LESS_THAN_SIGN 4 #define PLUS_SIGN 5 #define DOUBLE_QUOTE 6 #define DOLLAR_SIGN 7 #define NEWLINE 8 #define UNKNOWN 9 /* also EOF from stdio.h */ /* tokens: */ #define INTEGER_LITERAL 1 /* including line number */ #define EQUALS_OPERATOR 2 #define GREATER_THAN_OPERATOR 3 #define LESS_THAN_OPERATOR 4 #define PLUS_OPERATOR 5 #define LET 6 #define PRINT 7 #define INPUT 8 #define REMARK 9 #define IF 10 #define THEN 11 #define GOTO 12 #define GOSUB 13 #define RETURN 14 #define IDENTIFIER 15 #define QUOTED_STRING 16 #define END 17 #define EOLN 18 #define UNKNOWN_TOKEN 19 #define MAXLENGTH 80 char lexeme[MAXLENGTH]; int lexemeLength; #define MAXLINES 100 /* getChar() function */ void getChar() { /* get next character from stdin */ nextChar = getc(stdin); /* determine the character class */ if (nextChar == EOF) charClass = EOF; else if (nextChar == '\n') charClass = NEWLINE; else if (nextChar == '=') charClass = EQUALS_SIGN; else if (nextChar == '>') charClass = GREATER_THAN_SIGN; else if (nextChar == '<') charClass = LESS_THAN_SIGN; else if (nextChar == '+') charClass = PLUS_SIGN; else if (nextChar == '"') charClass = DOUBLE_QUOTE; else if (nextChar == '$') charClass = DOLLAR_SIGN; else if (isalpha(nextChar)) charClass = LETTER; else if (isdigit(nextChar)) charClass = DIGIT; else charClass = UNKNOWN; } /* addChar() function */ void addChar() { if (lexemeLength < MAXLENGTH) { lexeme[lexemeLength++] = nextChar; lexeme[lexemeLength] = '\0'; } else fprintf(stderr, "ERROR: Lexeme is too long\n"); } /* lookup() function */ int lookup(char *lexeme) { if ( strcmp( lexeme, "IF" ) == 0 ) return IF; else if ( strcmp( lexeme, "THEN" ) == 0 ) return THEN; else if ( strcmp( lexeme, "LET" ) == 0 ) return LET; else if ( strcmp( lexeme, "PRINT" ) == 0 ) return PRINT; else if ( strcmp( lexeme, "INPUT" ) == 0 ) return INPUT; else if ( strcmp( lexeme, "REM" ) == 0 ) return REMARK; else if ( strcmp( lexeme, "GOTO" ) == 0 ) return GOTO; else if ( strcmp( lexeme, "GOSUB" ) == 0 ) return GOSUB; else if ( strcmp( lexeme, "RETURN" ) == 0 ) return RETURN; else if ( strcmp( lexeme, "END" ) == 0 ) return END; else return IDENTIFIER; } int lex() { int token; lexemeLength = 0; static int first = 1; if (first) { getChar(); first = 0; } /* skip whitespace */ while (nextChar != '\n' && isspace(nextChar)) getChar(); switch (charClass) { case NEWLINE: addChar(); getChar(); return EOLN; case LETTER: addChar(); getChar(); while ( (token = lookup(lexeme)) == IDENTIFIER && (charClass == LETTER || charClass == DIGIT) ) { addChar(); getChar(); } if ( token == IDENTIFIER && charClass == DOLLAR_SIGN ) { addChar(); getChar(); } if ( token == REMARK ) { while ( charClass != NEWLINE && charClass != EOF ) { addChar(); getChar(); } } return token; case DIGIT: addChar(); getChar(); while (charClass == DIGIT) { addChar(); getChar(); } return INTEGER_LITERAL; case EQUALS_SIGN: addChar(); getChar(); return EQUALS_OPERATOR; case GREATER_THAN_SIGN: addChar(); getChar(); return GREATER_THAN_OPERATOR; case LESS_THAN_SIGN: addChar(); getChar(); return LESS_THAN_OPERATOR; case PLUS_SIGN: addChar(); getChar(); return PLUS_OPERATOR; case DOUBLE_QUOTE: addChar(); getChar(); while ( charClass != DOUBLE_QUOTE && charClass != NEWLINE && charClass != EOF ) { addChar(); getChar(); } nextChar = '"'; addChar(); getChar(); return QUOTED_STRING; case EOF: return EOF; case UNKNOWN: default: /* including DOLLAR_SIGN */ addChar(); getChar(); return UNKNOWN_TOKEN; } } struct basicLine { int lineNumber; char line[MAXLENGTH]; }; main() { int x; struct basicLine lines[MAXLINES]; int nextLinesIndex = 0; int firstToken = 1; int lineNumber = -1; int lastLineNumber = -1; char line[MAXLENGTH]; line[0] = '\0'; do { x = lex(); if (x != EOF && firstToken) { firstToken = 0; if (x == INTEGER_LITERAL) { lineNumber = atoi(lexeme); } else { fprintf(stderr, "*** NO LINE NUMBER\n"); } } if (x == EOLN || x == EOF) { if (lineNumber != -1 && lineNumber < lastLineNumber) { int y, z = 0; fprintf(stderr, "*** WARNING: LINE %d IS NOT IN THE PROPER ORDER\n", lineNumber); while (lines[z].lineNumber < lineNumber) z++; for ( y = nextLinesIndex ; y >= z ; y-- ) { lines[y].lineNumber = lines[y-1].lineNumber; strcpy(lines[y].line, lines[y-1].line); } nextLinesIndex++; lines[z].lineNumber = lineNumber; strcpy(lines[z].line, line); } else { lines[nextLinesIndex].lineNumber = lineNumber; strcpy(lines[nextLinesIndex++].line, line); lastLineNumber = lineNumber; } lineNumber = -1; line[0] = '\0'; firstToken = 1; } else sprintf(line + strlen(line), "%s ", lexeme); } while (x != EOF); for (x = 0 ; x < nextLinesIndex ; x++) { printf("%s\n", lines[x].line); } }