|
最近在学编译原理,用的编译原理与实践这本书,为了能更好的学习,所以把书中tiny compiler的词法分析器给分出来了,编成一个独立的程序,在改的时候出现了一个问题,就是如果把scan.c中一些函数用到的变量
int lineno=0;
FILE *source,*listing,*fp;
放在scan.h中,就编译不了,出现变量未定义的错误,而放在
scan.c中就可以编译通过。
一直不能理解这是为什么,难道在预处理时,不是把scan.h与scan.c合在一起的吗?
- /****************************************************/
- /* File: scan.h */
- /* The scanner interface for the TINY compiler */
- /* Compiler Construction: Principles and Practice */
- /* Kenneth C. Louden */
- /****************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- /* MAXTOKENLEN is the maximum size of a token */
- #define MAXTOKENLEN 40
- #define FALSE 0
- #define TRUE 1
- #define MAXRESERVED 8
- typedef enum
- /* book-keeping tokens */
- {ENDFILE,ERROR,
- /* reserved words */
- IF,THEN,ELSE,END,REPEAT,UNTIL,READ,WRITE,
- /* multicharacter tokens */
- ID,NUM,
- /* special symbols */
- ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI
- } TokenType;
- /* states in scanner DFA */
- typedef enum
- { START,INASSIGN,INCOMMENT,INNUM,INID,DONE }
- StateType;
- /* lexeme of identifier or reserved word */
- char tokenString[MAXTOKENLEN+1];
- /* BUFLEN = length of the input buffer for
- source code lines */
- #define BUFLEN 256
- static char lineBuf[BUFLEN]; /* holds the current line */
- static int linepos = 0; /* current position in LineBuf */
- static int bufsize = 0; /* current size of buffer string */
- static int EOF_flag = FALSE; /* corrects ungetNextChar behavior on EOF
- /* functions */
- TokenType getToken(void);
- static int getNextChar(void);
- static void ungetNextChar(void);
- static TokenType reservedLookup (char * s);
- void printToken( TokenType token, const char* tokenString ,FILE *listing);
复制代码
- /****************************************************/
- /* File: scan.c */
- /* The scanner implementation for the TINY compiler */
- /* Compiler Construction: Principles and Practice */
- /* Kenneth C. Louden */
- /****************************************************/
- #include "scan.h"
- FILE *source,*listing,*fp;
- int lineno=0;
- /* getNextChar fetches the next non-blank character
- from lineBuf, reading in a new line if lineBuf is
- exhausted */
- static int getNextChar(void)
- { if (!(linepos < bufsize))
- { lineno++;
- if (fgets(lineBuf,BUFLEN-1,source))
- {
- bufsize = strlen(lineBuf);
- linepos = 0;
- return lineBuf[linepos++];
- }
- else
- { EOF_flag = TRUE;
- return EOF;
- }
- }
- else return lineBuf[linepos++];
- }
- /* ungetNextChar backtracks one character
- in lineBuf */
- static void ungetNextChar(void)
- { if (!EOF_flag) linepos-- ;}
- /* lookup table of reserved words */
- static struct
- { char* str;
- TokenType tok;
- } reservedWords[MAXRESERVED]
- = {{"if",IF},{"then",THEN},{"else",ELSE},{"end",END},
- {"repeat",REPEAT},{"until",UNTIL},{"read",READ},
- {"write",WRITE}};
- /* lookup an identifier to see if it is a reserved word */
- /* uses linear search */
- static TokenType reservedLookup (char * s)
- { int i;
- for (i=0;i<MAXRESERVED;i++)
- if (!strcmp(s,reservedWords[i].str))
- return reservedWords[i].tok;
- return ID;
- }
- /*print tokens and save them in a file */
- void printToken( TokenType token, const char* tokenString ,FILE *listing)
- { switch (token)
- { case IF:
- case THEN:
- case ELSE:
- case END:
- case REPEAT:
- case UNTIL:
- case READ:
- case WRITE:
- fprintf(listing,
- "reserved word: %s\n",tokenString);
- break;
- case ASSIGN: fprintf(listing,":=\n"); break;
- case LT: fprintf(listing,"<\n"); break;
- case EQ: fprintf(listing,"=\n"); break;
- case LPAREN: fprintf(listing,"(\n"); break;
- case RPAREN: fprintf(listing,")\n"); break;
- case SEMI: fprintf(listing,";\n"); break;
- case PLUS: fprintf(listing,"+\n"); break;
- case MINUS: fprintf(listing,"-\n"); break;
- case TIMES: fprintf(listing,"*\n"); break;
- case OVER: fprintf(listing,"/\n"); break;
- case ENDFILE: fprintf(listing,"EOF\n"); break;
- case NUM:
- fprintf(listing,
- "NUM, val= %s\n",tokenString);
- break;
- case ID:
- fprintf(listing,
- "ID, name= %s\n",tokenString);
- break;
- case ERROR:
- fprintf(listing,
- "ERROR: %s\n",tokenString);
- break;
- default: /* should never happen */
- fprintf(listing,"Unknown token: %d\n",token);
- }
- }
- /****************************************/
- /* the primary function of the scanner */
- /****************************************/
- /* function getToken returns the
- * next token in source file
- */
- TokenType getToken(void)
- { /* index for storing into tokenString */
- int tokenStringIndex = 0;
- /* holds current token to be returned */
- TokenType currentToken;
- /* current state - always begins at START */
- StateType state = START;
- /* flag to indicate save to tokenString */
- int save;
- while (state != DONE)
- { int c = getNextChar();
- save = TRUE;
- switch (state)
- { case START:
- if (isdigit(c))
- state = INNUM;
- else if (isalpha(c))
- state = INID;
- else if (c == ':')
- state = INASSIGN;
- else if ((c == ' ') || (c == '\t') || (c == '\n'))
- save = FALSE;
- else if (c == '{')
- { save = FALSE;
- state = INCOMMENT;
- }
- else
- { state = DONE;
- switch (c)
- { case EOF:
- save = FALSE;
- currentToken = ENDFILE;
- break;
- case '=':
- currentToken = EQ;
- break;
- case '<':
- currentToken = LT;
- break;
- case '+':
- currentToken = PLUS;
- break;
- case '-':
- currentToken = MINUS;
- break;
- case '*':
- currentToken = TIMES;
- break;
- case '/':
- currentToken = OVER;
- break;
- case '(':
- currentToken = LPAREN;
- break;
- case ')':
- currentToken = RPAREN;
- break;
- case ';':
- currentToken = SEMI;
- break;
- default:
- currentToken = ERROR;
- break;
- }
- }
- break;
- case INCOMMENT:
- save = FALSE;
- if (c == EOF)
- { state = DONE;
- currentToken = ENDFILE;
- }
- else if (c == '}') state = START;
- break;
- case INASSIGN:
- state = DONE;
- if (c == '=')
- currentToken = ASSIGN;
- else
- { /* backup in the input */
- ungetNextChar();
- save = FALSE;
- currentToken = ERROR;
- }
- break;
- case INNUM:
- if (!isdigit(c))
- { /* backup in the input */
- ungetNextChar();
- save = FALSE;
- state = DONE;
- currentToken = NUM;
- }
- break;
- case INID:
- if (!isalpha(c))
- { /* backup in the input */
- ungetNextChar();
- save = FALSE;
- state = DONE;
- currentToken = ID;
- }
- break;
- case DONE:
- default: /* should never happen */
- fprintf(listing,"Scanner Bug: state= %d\n",state);
- 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);
- }
- }
- fprintf(listing,"\t%d: ",lineno);
- printToken(currentToken,tokenString,listing);
- printToken(currentToken,tokenString,fp);
- return currentToken;
- } /* end getToken */
- main( int argc, char * argv[] )
- {
- char pgm[120]; /* source code file name */
- if (argc != 2)
- { fprintf(stderr,"usage: %s <filename>\n",argv[0]);
- exit(1);
- }
- strcpy(pgm,argv[1]) ;
- if (strchr (pgm, '.') == NULL)
- strcat(pgm,".tny");
- source = fopen(pgm,"r");
- if (source==NULL)
- { fprintf(stderr,"File %s not found\n",pgm);
- exit(1);
- }
- listing = stdout; /* send listing to screen */
- fprintf(listing,"\nTINY COMPILATION: %s\n",pgm);
- if((fp=fopen("string.txt","wt"))==NULL)
- {
- printf("Cannot open file strike any key exit!");
- getch();
- exit(1);
- }
- fprintf(fp,"\nTINY COMPILATION: %s\n",pgm);
- while (getToken()!=ENDFILE);
- }
复制代码 |
|