📄 lex.cpp
字号:
/*
* file: lex.cpp
* func: The lexical parser program file.
*/
#include <iostream>
#include <exception>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include "lex.h"
using std::string;
using std::exception;
using std::cout;
Lex::Lex(const string &fname):pfname(fname)
{
lineno=1;
nerror=0;
ungetflag=False;
/// 打开待分析的源文件.
pf.open(fname.c_str());
if(!pf)
{
cout<<"打开文法文件 "<< fname <<" 错误.\n";
exit(1);
}
}
Void
Lex::showErr(errortype who)
{
++nerror;
switch(who)
{
case UNKNOWN:
cout<<'('<<lineno<<')'<<"未知错误.\n";break;
case UNTERMINATED_COMMENT:
cout<<'('<<lineno<<')'<<"注释缺少(*/)结束符.\n";break;
case UNTERMINATED_STRING:
cout<<'('<<lineno<<')'<<"字符串尾缺少(\").\n";break;
case OUT_OF_RANGE:
cout<<'('<<lineno<<')'<<"标识符的长度大于"<<MAXTOKENLEN-1<<".\n";break;
case MUST_KEYWORD:
cout<<'('<<lineno<<')'<<"缺少关键字.\n";break;
case LITERAL_ERROR:
cout<<'('<<lineno<<')'<<"字符常量错误.\n";break;
case ESCAPE_ERROR:
cout<<'('<<lineno<<')'<<"错误的转义字符"<<errorstring<<".\n";break;
case LACK_QUOTE:
cout<<'('<<lineno<<')'<<"缺少引号.\n";break;
case PERCENT_ERROR:
cout<<'('<<lineno<<')'<<"\"%\"后的符号无效.\n";break;
case UNKNOWN_LITERAL:
cout<<'('<<lineno<<')'<<"不能识别的符号\""<<errorstring<<"\".\n";break;
default:
assert(0);
break;
}
}
/// 返回字符串中的最后一个符号(双引号,回车号,文件结束符).
sint32
Lex::eatup_string()
{
//1 char * cc="lvjin\"";
//2 char * cc="lvjin\\";
//3 char * cc="lvjin\
// jinhua";
//4 char * cc="lvjin
//5 char *xx="lvjinhua""aaaa"\
// "ddd";
//5 char *xx="lvjinhua""aaaa"
// "ddd";
register sint32 c;
register Bool instring=True;
while(instring)
{
instring=True;
c=pf.get();
while(c!='\\' && c!='\"' && c!='\n' && ENDOFFILE!=c)
c=pf.get();
if('\\'==c)
{
c=pf.get();
if('\n'==c) // 续行.
++lineno;
else if(ENDOFFILE==c)
{
instring=False;
}
//
// 如果不是第3种情况.即跳过'\x'后的一个字符,
// 第3种情况是C语言的续行操作,行号加1.
}
else if('\"'==c)
instring=False;
else if('\n'==c)
{
showErr(UNTERMINATED_STRING);
++lineno;
instring=False;
}
else if(ENDOFFILE==c)
{
instring=False;
}
#ifdef _DEBUG
else
{
assert(0);
}
#endif //_DEBUG
}// while(instring)
return c;
}
/*
* 去除Bison中的 "/* * /'及'//'注释.
* 返回注释后的下一个字符.
*/
sint32
Lex::eatup_white_comment()
{
register sint32 c;
for(;;)
{
c=pf.get();
switch(c)
{
case '/':
{
c=pf.get();
if('*'==c)
{//处理C语言的 '/* */' 注释内容.
register Bool incomment=True;
while(incomment)
{
while('*'!=(c=pf.get()) && '\n'!=c
&& ENDOFFILE!=c)
/* empty */;
if('*'==c && '/'==pf.peek())
{
pf.get();
incomment=False;
}
else if('\n'==c)
++lineno;
else if('*'==c && ('/'!=pf.peek()))
/* empty */;
else
{
showErr(UNTERMINATED_COMMENT);
return ENDOFFILE;
}
}// while(incomment)
}
else if('/'==c)
{// 处理C++的 '//' 注释内容.
do{
c=pf.get();
}while('\n'!=c && ENDOFFILE!=c);// && '\\' !=c);
if('\n'==c)
{
++lineno;
return pf.get();
}
else
return c;
}
else
{// 并非注释的开始.
pf.unget();
return '/';
}
break;
}
case '\n':
++lineno; // 行号加1.
//c=pf.get(); // 读入下一个字符.
break;
case ' ':
case '\t':
case '\f':
do{
c=pf.get();
}while(' '==c || '\t' ==c || '\f'==c);
pf.unget();
break;
default:
return c;
}
}// for(;;)
//return c;
showErr(UNKNOWN);
}
string
Lex::read_Identifier() // istream pf
{
char str[MAXTOKENLEN]={'\0'};
register uint32 size=0;
register uchar8 c=pf.get();
if(isalpha(c) || '_'==c || '.'==c)
{
do{
str[size++]=c;
c=pf.get();
if(size >= MAXTOKENLEN)
{
showErr(OUT_OF_RANGE);
while( isalnum(c) || c=='_' || '.'==c)
c=pf.get();
break;
}
}while(isalnum(c) || '_'==c || '.'==c);
pf.unget();
if(size<MAXTOKENLEN)
str[size]='\0';
else
str[MAXTOKENLEN-1]='\0';
return string(str,str+size) ;
}
else
{
assert(0);
pf.unget();
return string("");
}
}
sint32
Lex::lex()
{
if (ungetflag)
{
ungetflag=False;
strval=unstrval;
numval=unnumval;
return untoken;
}
register sint32 c;
again:
strval.clear();
c=eatup_white_comment();
if(isalpha(c) || '_'==c || '.'==c)
{ // 标识包含以字母,下划线与点开头的以字母 数字 下划线 点组成的
// 长度小于 MAXTOKENLEN 的序列。
pf.putback(c);
strval=read_Identifier();
numval = -1;
assert(strval.size()>0);
return ID;
}
else if(isdigit(c))
{
uchar8 digitstr[MAXDIGITLEN];
uint32 size=0;
do{
digitstr[size++]=c;
c=pf.get();
if(size>=MAXDIGITLEN)
{
showErr(OUT_OF_RANGE);
while(isdigit(c))
c=pf.get();
break;
}
}while(isdigit(c));
pf.unget();
digitstr[size]='\0';
strval.assign(digitstr,digitstr+size);
numval=atoi((char*)digitstr);
return NUM;
}
else
switch(c)
{
case '%':
c=pf.get();
if('%'==c){
strval="%%";
return MARK;
}
else if('{'==c){
strval="%{";
return LCURL;
}
else if('}'==c){
strval="%}";
return RCURL;
}
else if(isalpha(c)||'_'==c)
{
pf.unget();
strval=read_Identifier();
if("token"==strval) return TOKEN;
else if("left"==strval) return LEFT;
else if("right"==strval) return RIGHT;
else if("nonassoc"==strval) return NONASSOC;
else if("prec"==strval) return PREC;
else if("type"==strval) return TYPE;
else if("start"==strval) return START;
else if("union"==strval) return UNION;
#ifdef EXTEND
else if("except"==strval) return EXCEPT;
else if("pure_parser"==strval)return PURE_PARSER;
#endif /* EXTEND */
else
{
showErr(MUST_KEYWORD);
assert(strval.size()>0);
pf.unget();
goto again;
}
}
else
{
showErr(PERCENT_ERROR);
pf.unget();
goto again;
}
break;
/* 处理单字符 */
case '\'':
{
register sint32 code=0;
c=pf.get();
if('\\'==c)
{
c=pf.get();
if(c>='0' && c<='7')
{
while(c>='0' && c<='7')
{
code=code*8+(c-'0');
if(code >=256 || code <0)
showErr(LITERAL_ERROR);
c=pf.get();
}
pf.unget();
}
else if('\"'==c) code='\"';
else if('\\'==c) code='\\';
else if('\''==c) code='\'';
else if('n'==c) code='\n';
else if('t'==c) code='\t';
else if('r'==c) code='\r';
else if('f'==c) code='\f';
else if('a'==c) code='\007';
else if('b'==c) code='\b';
else if('v'==c) code=013;
else if ('x'==c || 'X'==c)
{
c = pf.get();
while ((c <= '9' && c >= '0')
|| (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z'))
{
code *= 16;
if (c <= '9' && c >= '0')
code += c - '0';
else if (c >= 'a' && c <= 'z')
code += c - 'a' + 10;
else if (c >= 'A' && c <= 'Z')
code += c - 'A' + 10;
if (code >= 256 || code<0)/* JF this said if(c>=128) */
showErr(LITERAL_ERROR);
c=pf.get();
}
pf.unget();
}
else
{
errorstring='\'';
errorstring+=(uchar8)c;
errorstring+='\'';
showErr(ESCAPE_ERROR);
}
}
else
{// 如果单引号中无转义,如形如:'y'
if('\''==c )
{
errorstring=" \'\'\'";
showErr(ESCAPE_ERROR);
}
code=c;
}
c=pf.get();
if('\'' != c)
{
showErr(LACK_QUOTE);
}
// 将各转换字符转换为可输出的字符串形式,如 '\n' 转换为 '\\n'
strval='\'';
if ('\''==code)
strval+="\\'";
else if('\"'==code)
strval+="\\\"";
else if('\\'==code)
strval+="\\\\";
else if(code >=040 && code !=0177)
strval+=(uchar8)code;
else if('\n'==code)
strval+="\\n";
else if('\t'==code)
strval+="\\t";
else if('\f'==code)
strval+="\\f";
else if('\v'==code)
strval+="\\v";
else if('\b'==code)
strval+="\\b";
else
{
strval+=(uchar8)(code/0100 + '0');
strval+=(uchar8)((code/010 & 07)+'0');
strval+=(uchar8)((code & 07) + '0');
}
strval+='\'';
numval=code;
//////////
return ASC;
}// case '\'':
case ':': case '|': case ';':
case '{': case '}': case '<':
case '>':
strval=(char)c;
return c;
break;
#ifdef _DEBUG
case '\n':
++lineno;
case ' ': case '\t': case '\f':
//cout<<lineno;
//assert(0);
goto again;
break;
#endif
case ENDOFFILE:
return END;
default:
errorstring=(char)c;
showErr(UNKNOWN_LITERAL);
goto again;
break;
}
assert(0);
goto again;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -