今天写一个词法分析器,在 vs 下 debug 后生成运行好好的,转到 Ubuntu 用 gcc 编译一下子傻眼了,回 win 下面用 gcc 编译也是一样的结果
这是 vs 的结果(正常): http://chuantu.biz/t6/82/1507355708x3738353725.png
这是 gcc 的结果(无限循环): http://chuantu.biz/t6/82/1507355765x2890174166.png
初学者,实在搞不懂为什么
这是代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
int charClass;
#define MAX_LEN 3000
char lexeme[MAX_LEN];
char nextChar;
char next2Char;
int lexLen;
int token;
int nextToken;
FILE* inFile;
#define LETTER 0
#define DIGIT 1
#define SLASH 2
#define ASTERISK 3
#define DQUOTE 4
#define UNKNOWN 999
enum {ABSTRACT =258, CASE, CATCH, CLASS, DEF,
DO, ELSE, EXTENDS, fALSE, FINAL,
FINALLY, FOR, FORSOME, IF, IMPLICIT,
IMPORT, LAZY, MACRO, MATCH, NEW,
nULL, OBJECT, OVERRIDE, PACKAGE, PRIVATE,
PROTECTED, RETURN, SEALED, SUPER, THIS,
THROW, TRAIT, TRY, tRUE, TYPE,
VAL, VAR, WHILE, WITH, YIELD,
UNDERLINE, COLON, EQU, EQUG, LDE, LCO, LPER, GCO, HASHTAG, AITE,
OPERATOR, ID, INTERGER, ERROR, SYMBOL, COMMENT, STRING};
char* keywords[]={"abstract", "case", "catch", "class", "def",
"do", "else", "extends", "false", "final",
"finally", "for", "forSome", "if", "implicit",
"import", "lazy", "macro", "match", "new",
"null", "object", "override", "package", "private",
"protected", "return", "sealed", "super", "this",
"throw", "trait", "try", "true", "type",
"val", "var", "while", "with", "yield",
"_", ":", "=", "=>", "<-", "<:", "<%", ">:", "#", "@", 0};
void addChar()
{
if(lexLen <= MAX_LEN -2)
{
lexeme[lexLen++] = nextChar;
lexeme[lexLen] = 0;
}
else
printf("ERROR:lexeme is too long. \n" );
}
void getChar()
{
static int firstRun = 1;
if(firstRun)
{
nextChar = getc(inFile);
next2Char = getc(inFile);
firstRun = 0;
}
else
{
nextChar = next2Char;
next2Char = getc(inFile);
}
if(nextChar == EOF)
{
charClass = EOF;
}
else
{
if (nextChar == '\"')
charClass = DQUOTE;
else if(nextChar == '/')
charClass = SLASH;
else if(nextChar == '*')
charClass = ASTERISK;
else if(isalpha(nextChar))
charClass = LETTER;
else if(isdigit(nextChar))
charClass = DIGIT;
else
charClass = UNKNOWN;
}
}
void getNonBlank()
{
while (isspace(nextChar)) {
getChar();
}
}
int checkSymbol(char ch,char nextCh)
{
switch (ch) {
case '(':case ')':case '{':case '}':case '<':case '>':case'&':case '[': case ']':case '.':case '\\':case '_':case '=':case ':':case ';':
addChar();
nextToken = SYMBOL;
break;
case '+':case '-':case '*':case '/':
addChar();
nextToken = OPERATOR;
break;
case EOF:
addChar();
nextToken = EOF;
default:
printf("ERROR:unknown character '%c'. \n",ch );
nextToken = ERROR;
}
return nextToken;
}
void checkKeywords(char* pword)
{
int i = 0;
while(keywords[i]!= 0)
{
char* pkeyword=keywords[i];
if(strcmp(pword,pkeyword) == 0)
{
nextToken = 258 + i;
return;
}
i++;
}
}
int lexer()
{
lexLen =0;
getNonBlank();
switch (charClass) {
case DQUOTE:
addChar();
getChar();
while(charClass != DQUOTE)
{
addChar();
getChar();
}
addChar();
getChar();
nextToken = STRING;
break;
case SLASH:
addChar();
getChar();
if(charClass == ASTERISK)
{
addChar();
getChar();
loop:
while(charClass != ASTERISK)
{
addChar();
getChar();
}
addChar();
getChar();
if(charClass == SLASH)
{
addChar();
getChar();
nextToken = COMMENT;
break;
}
else goto loop;
}
else if(charClass == SLASH)
{
addChar();
getChar();
while(nextChar != '\n')
{
addChar();
getChar();
}
nextToken = COMMENT;
break;
}
else
{
nextToken = OPERATOR;
break;
}
case ASTERISK:
nextToken = OPERATOR;
break;
case LETTER:
addChar();
getChar();
while(charClass == LETTER || charClass == DIGIT)
{
addChar();
getChar();
}
nextToken = ID;
checkKeywords(lexeme);
break;
case DIGIT:
addChar();
getChar();
while(charClass == DIGIT)
{
addChar();
getChar();
}
nextToken = INTERGER;
break;
case UNKNOWN:
checkSymbol(nextChar,next2Char);
getChar();
break;
case EOF:
nextToken = EOF;
lexeme[0] = 'E';
lexeme[1] = 'O';
lexeme[2] = 'F';
lexeme[3] = 0;
break;
}
printf("<%6d, %s >\n",nextToken,lexeme);
return nextToken;
memset(lexeme,0,sizeof(lexeme));
}
int main(int argc,char* argv[])
{
argv++;argc--;
inFile = fopen(argv[0],"r");
if(inFile == NULL)
{
printf("ERROR:cannot open file.\n" );
exit(0);
}
getChar();
while(nextToken != EOF)
lexer();
return 0;
}
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.