📄 parser.cpp
字号:
if(!unsigned_suffix && (ch == 'u' || ch == 'U'))
{
token += static_cast<char>(ch);
ch = getChar();
}
}
}
if(minus)
token.value = - token.value;
if(ch != -1)
putBack(static_cast<char>(ch));
return true;
}
/*
* 僆儁儗乕僞(摿庩暥帤偺慻崌偣偐傜側傞僩乕僋儞)偺愗弌偟
*/
bool Parser::getOperator(Token & token, int ch)
{
const char * work;
/* ch偑僆儁儗乕僞暥帤偱偁傞偐偳偆偐妋偐傔傞 */
for(work = Operator;*work != '\x0' && *work != ch;work++);
if(*work == '\x0')
return false;
/* 屻懕偡傞暥帤傕僆儁儗乕僞暥帤偱偁傞偐偳偆偐妋偐傔傞 */
do {
token += static_cast<char>(ch);
ch = getChar();
for(work = Operator;*work != '\x0' && *work != ch;work++);
} while(*work != '\x0');
putBack(ch);
token.type = Token::OPERATOR;
return true;
}
/*
* 暥帤楍儕僥儔儖 (僟僽儖僋僅乕僩偱妵傜傟偨暥帤)
* 丒僔儞僌儖僋僅乕僩傕嫋偡傛偆偵偟偨
*
* VisualStudio6.0偱僐儞僷僀儖偟偨応崌丄夵峴偑LF偺僼傽僀儖偵懳偟偰tellg屻偵
* get偡傞偲EOF偑曉傞偨傔丄摨張棟傪僐儊儞僩傾僂僩偟偰偍偔丅
*/
bool Parser::getStringLiteral(Token & token, int delimitor)
{
int ch;
int prev;
ch = delimitor;
token.value = 1;
token.type = Token::STRINGLITERAL;
token.assign("");
token += static_cast<char>(ch);
while(!current->stream->bad() && !current->stream->eof())
{
prev = ch;
ch = getChar();
token += static_cast<char>(ch);
token.value ++;
if(ch == delimitor && prev != '\\')
return true;
}
//偄偭偨傫暵偠偰嵞僆乕僾儞偟偰丄儕僥儔儖奐巒偺 " 偺師偵堏摦
ExceptionMessage(ExceptionMessage::FATAL, "Unterminated string literal appeared.","暵偠傜傟偰偄側偄暥帤儕僥儔儖傪専弌偟傑偟偨").throwException();
return false;
}
/*
* 僩乕僋儞偺愗弌偟
*/
enum Token::tagTokenType Parser::getToken(Token & token, bool allow_space)
{
int ch;
const char * work;
do {
token.erase();
token.type = Token::ERROR;
token.value = 0;
//僩乕僋儞僗僞僢僋偐傜愗傝弌偡
if(!TokenStack.empty())
{
do {
token = TokenStack.front();
TokenStack.pop_front();
} while(!TokenStack.empty() && !allow_space && token.type == Token::SPACE);
if(!allow_space && token.type != Token::SPACE)
return token.type;
}
//僗僩儕乕儉偐傜愗傝弌偡
if(current == NULL || current->stream == NULL || current->stream->bad())
{
token.assign("<End of stream>");
return (token.type = Token::EOS);
}
//僇儗儞僩偺僗僩儕乕儉偑嬻偵側偭偨
if(current->stream->eof())
{
//僼傽僀儖僗僞僢僋偐傜師偺僗僩儕乕儉傪庢傞
if(!fileStack.empty())
{
if(current->stream != &cin)
delete current->stream;
delete current;
current = *fileStack.begin();
fileStack.pop_front();
}else
{
token.assign("<End of stream>");
return (token.type = Token::EOS);
}
}
ch = getChar();
//First(whitespaces) is [ \n\t\r/#]
if( (ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r') || (ch == '/') || (isHeadofLine && ch == '#'))
{
if(ch == '\n')
isHeadofLine = true;
if(getWhitespace(token, ch, allow_space))
if((token == Token::SPACE && allow_space) || !(token == Token::SPACE || token == Token::ERROR))
return token.type;
continue;
}else
break;
}while(true);
isHeadofLine = false;
token.line = current->line;
//First(identifier) is [a-zA-Z_]
if( (ch >='a' && ch <= 'z') || (ch >='A' && ch <= 'Z') || (ch == '_') )
if(getIdentifier(token, ch))
return Token::IDENTIFIER;
//First(integer) is [\-0-9]
if( (ch >='0' && ch <='9') || (ch == '-') )
if(getInteger(token,ch))
return Token::INTEGER;
//First(string) is ["']
if( ch == '"' || ch == '\'')
if(getStringLiteral(token,ch))
return Token::STRINGLITERAL;
//Operator
if(getOperator(token,ch))
return Token::OPERATOR;
//Punctuator
work = Punctuator;
while(*work != '\x0')
if( *(work++) == ch )
{
token += static_cast<char>(ch);
return (token.type = Token::PUNCTUATOR);
}
token += static_cast<char>(ch);
token.type = Token::UNKNOWN;
return Token::UNKNOWN;
}
/*
* 僩乕僋儞梡 僗僩儕乕儉僆儁儗乕僞 (庡偵僥僗僩栚揑)
*/
ostream & operator << (ostream & out, Token & src)
{
switch(src.type)
{
case Token::IDENTIFIER:
out << "<IDENTIFIER:["; break;
case Token::INTEGER:
out << "<INTEGER:["; break;
case Token::STRINGLITERAL:
out << "<STRINGLITERAL:["; break;
case Token::STRING:
out << "<STRING:["; break;
case Token::OPERATOR:
out << "<OPERATOR:["; break;
case Token::PUNCTUATOR:
out << "<PUNCTUATOR:["; break;
case Token::RESERVEDWORD:
out << "<RESERVEDWORD:["; break;
case Token::SPECIAL:
out << "<SPECIAL:["; break;
case Token::SPACE:
out << "<SPACE:["; break;
case Token::UNKNOWN:
out << "<UNKNOWN>"; return out;
case Token::ERROR:
out << "<ERROR>"; return out;
default:
out << "<???:[";
}
return out << static_cast<string &>(src) << "]("<<src.value<<")>";
}
/*
* 梊栺岅偺愗弌偟(偲偄偆傛傝傕妋擣)
*/
void Parser::getToken(const char * term, const char * second, ...)
{
Token token;
va_list vl;
if(term == NULL)
ExceptionMessage("Internal: GetToken received an empty string as reserved word.","撪晹僄儔乕: GetToken偵嬻暥帤楍偑搉偝傟傑偟偨").throwException();
va_start(vl, second);
vl = (char *)vl - sizeof(const char *);
do {
getToken(token, false);
if(token.compare(term) != 0)
{
lastErrorToken = token;
ExceptionMessage("Token [%] should be replaced by [%]","帤嬪[%]偼[%]偱偁傞傋偒偱偡") << token << term << throwException;
}
term = va_arg(vl, const char *);
}while(term != 0);
}
string Parser::getStreamLocation(void)
{
list<tagFile *>::iterator scope;
string location;
char buffer[16];
if(current == 0)
return string("");
::sprintf(buffer, ":%d", current->line);
location += current->identifier;
location += buffer;
if(!fileStack.empty())
{
location += " (included at ";
scope = fileStack.begin();
while(scope != fileStack.end())
{
::sprintf(buffer, ":%d, ", (*scope)->line);
location += (*scope)->identifier;
location += buffer;
++ scope;
}
location.erase(location.size()-2);
location += ")";
}
return location;
}
void Parser::pushStream(const std::string & filename, std::string strid)
{
fstream * fin;
if(current != 0)
fileStack.push_front(current);
fin = new fstream(filename.c_str(),ios::in);
if(fin->is_open())
{
if(strid.size() == 0)
strid = filename;
current = new tagFile;
current->stream = fin;
current->identifier = strid;
current->line = 1;
}else
{
ExceptionMessage("File operatation failure : [%]","僼傽僀儖憖嶌偵幐攕偟傑偟偨 [%]") << filename << throwException;
delete fin;
}
}
void Parser::pushStdStream(std::string strid)
{
stringstream * work = new stringstream;
char buffer[1024];
int count;
//昗弨擖椡偺忣曬傪偡傋偰庢傝崬傓 (僄儔乕懳張梡偵 seekg/tellg 傪巊偄偨偄)
do {
cin.read(buffer, 1024);
count = cin.gcount();
work->write(buffer, count);
} while(count != 0);
if(current != 0)
fileStack.push_front(current);
current = new tagFile;
current->stream = work;
current->identifier = strid;
current->line = 1;
}
string * Parser::setLogBuffer(string * buffer)
{
string * old = LogBuffer;
LogBuffer = buffer;
PutBackCount = 0;
return old;
}
streampos Parser::getLogBufferPos(int offset)
{
streampos pos;
pos = 0;
if(LogBuffer != 0)
pos = LogBuffer->size();
pos += static_cast<streampos>(offset - PutBackCount);
return pos;
}
void Parser::doPreProcess(const char * cmd)
{
string tempfilename;
char buffer[1024];
int count;
fstream tempfile;
string work;
stringstream * stream;
if(current == NULL || current->stream == NULL)
ExceptionMessage("No stream specified for processing","張棟懳徾偲側傞僗僩儕乕儉偑愝掕偝傟偰偄傑偣傫").throwException();
/* 崱偺僗僩儕乕儉偺撪梕傪偡傋偰僥儞億儔儕偵彂偒弌偡 */
strcpy(buffer,"cfgXXXXXX");
mktemp(buffer);
tempfilename.assign(buffer);
tempfile.open(tempfilename.c_str(),ios::out);
if(!tempfile.is_open())
ExceptionMessage("Failed to open a temporary file","僥儞億儔儕僼傽僀儖偺嶌惉偵幐攕偟傑偟偨").throwException();
do {
current->stream->read(buffer, 1024);
count = current->stream->gcount();
tempfile.write(buffer, count);
} while(count != 0);
tempfile.close();
/* 僗僩儕乕儉嵎偟懼偊 */
preprocessname = tempfilename;
originalname = current->identifier;
if(current->stream != &cin)
delete current->stream;
stream = new stringstream;
current->stream = stream;
/* 僾儕僾儘僙僢僒偺婲摦 & 弌椡偺庢傝崬傒 */
work = string(cmd) + " " + tempfilename;
VerboseMessage(" Start the external preprocessor [%]\n"," 奜晹僾儘僌儔儉傪婲摦偟傑偡 [%]\n") << work;
FILE * pipe = popen(work.c_str(),"r");
while(feof(pipe) == 0)
stream->put((char)fgetc(pipe));
pclose(pipe);
remove(tempfilename.c_str());
isHeadofLine = true;
}
ParseUnit::ParseUnit(void * _container, const char * name)
{
map<string, ParseUnit *> * container;
string work(name);
string apiname;
string::size_type i,j;
i = 0;
container = reinterpret_cast<map<string, ParseUnit *> *>(_container);
do {
j = work.find_first_of(',', i);
apiname = work.substr(i, j-i);
if(container->find(apiname) != container->end())
ExceptionMessage("Multiple registration of [%]\n","[%]偑廳暋偟偰搊榐偝傟傛偆偲偟偰偄傑偡") << apiname << throwException;
(*container)[apiname] = this;
i = j + 1;
}while(j != string::npos);
}
void ParseUnit::printList(void * _container)
{
int i;
map<string, ParseUnit *> * container;
map<string, ParseUnit *>::iterator scope;
container = reinterpret_cast<map<string, ParseUnit *> *>(_container);
if(container->empty())
{
cerr << " " << Message("None of element registed\n", "搊榐偝傟偰偄傞梫慺偼偁傝傑偣傫\n");
return;
}
i = 0;
scope = container->begin();
while(scope != container->end())
{
cerr << '[' << (*scope).first << "] ";
if(i++ >= 6)
{
i = 0;
cerr << '\n';
}
++ scope;
}
if(i != 0)
cerr << '\n';
}
Token & ParseUnit::parseParameter(Parser & p)
{
static Token result;
Token token;
int nest = 0;
result.type = Token::ERROR;
result.value = 0;
result.assign("");
do
{
p.getToken(token);
if(token == Token::PUNCTUATOR)
{
if(token.compare("(") == 0)
nest ++;
else if(token.compare(")") == 0)
nest --;
else if(nest == 0)
break;
if(nest < 0)
ExceptionMessage("')' appeared before '('.","懳墳偟側偄暵偠妵屖偑偁傝傑偡").throwException();
}
if(result == Token::ERROR)
result = token;
else
{
result.type = Token::STRING;
result += ' ';
result += token;
}
}while(true);
p.putBack(token);
result.trim();
return result;
}
int ParseUnit::parseParameters(Parser & p, Directory * container, int min, int max)
{
Token work;
int count = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -