📄 parser.cpp
字号:
else
{
CSyntaxException e;
e.SetStart(m_tokens[fgopen].GetStart());
if(fgclose == (size_type)-1)
{
e.SetEnd(m_tokens[fgopen].GetEnd());
}
else
{
e.SetEnd(m_tokens[fgclose].GetEnd());
}
throw(e);
}
}
else if(fgopen == start + 1)
{
// Function
if(fgclose == end)
{
// Find function list
CFunctionList *flist = m_expr->GetFunctionList();
if(flist == 0)
{
CNoFunctionListException e;
e.SetStart(m_tokens[start].GetStart());
e.SetEnd(m_tokens[start].GetEnd());
throw(e);
}
// Get name
::std::string ident = m_tokens[start].GetIdentifier();
// Create function node
::std::auto_ptr<CFunctionNode> n(flist->Create(ident, m_expr));
if(n.get())
{
n->Parse(*this, fgopen, fgclose);
}
else
{
CNotFoundException e(ident);
e.SetStart(m_tokens[start].GetStart());
e.SetEnd(m_tokens[start].GetEnd());
throw(e);
}
return n.release();
}
else
{
CSyntaxException e;
e.SetStart(m_tokens[fgopen].GetStart());
if(fgclose == (size_type)-1)
{
e.SetEnd(m_tokens[fgopen].GetEnd());
}
else
{
e.SetEnd(m_tokens[fgclose].GetEnd());
}
throw(e);
}
}
else if(start == end)
{
// Value, variable, or constant
if(m_tokens[start].GetType() == CToken::TypeIdentifier)
{
// Variable/constant
::std::auto_ptr<CNode> n(new CVariableNode(m_expr));
n->Parse(*this, start, end);
return n.release();
}
else
{
// Value
::std::auto_ptr<CNode> n(new CValueNode(m_expr));
n->Parse(*this, start, end);
return n.release();
}
}
else
{
// Unknown, syntax
CSyntaxException e;
e.SetStart(m_tokens[pos].GetStart());
e.SetEnd(m_tokens[pos].GetEnd());
throw(e);
}
}
// Get a token
const CToken& CParser::operator[] (CParser::size_type pos) const
{
return m_tokens[pos];
}
// Build tokens
void CParser::BuildTokens(const ::std::string &exstr)
{
m_tokens.clear();
// Test zero-length expression
if(exstr.length() == 0)
{
throw(CEmptyExpressionException());
}
// Search through list
::std::string::size_type pos;
bool comment = false;
for(pos = 0; pos < exstr.length(); pos++)
{
// Take action based on character
switch(exstr[pos])
{
// Comment
case '#':
{
comment = true;
break;
}
// Newline ends comment
case '\r':
case '\n':
{
comment = false;
break;
}
// Open parenthesis
case '(':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeOpenParenthesis, pos, pos));
}
break;
}
// Close parenthesis
case ')':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeCloseParenthesis, pos, pos));
}
break;
}
// Equal
case '=':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeEqual, pos, pos));
}
break;
}
// Plus
case '+':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypePlus, pos, pos));
}
break;
}
// Hyphen
case '-':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeHyphen, pos, pos));
}
break;
}
// Asterisk
case '*':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeAsterisk, pos, pos));
}
break;
}
// Forward slash
case '/':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeForwardSlash, pos, pos));
}
break;
}
// Hat (exponent)
case '^':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeHat, pos, pos));
}
break;
}
// Ampersand
case '&':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeAmpersand, pos, pos));
}
break;
}
// Comma
case ',':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeComma, pos, pos));
}
break;
}
// Semicolon
case ';':
{
if(comment == false)
{
m_tokens.push_back(CToken(CToken::TypeSemicolon, pos, pos));
}
break;
}
// None of the above, but it may be an identifier or value
default:
{
if(comment == false)
{
// First, test for value
if(exstr[pos] == '.' || expreval_isdigit(exstr[pos]))
{
// We are a value
::std::string::size_type start = pos;
// Digits before period
while(expreval_isdigit(exstr[pos]))
{
pos++;
}
// Period
if(exstr[pos] == '.')
{
pos++;
}
// Digits after period
while(expreval_isdigit(exstr[pos]))
{
pos++;
}
// Create token
::std::string ident = exstr.substr(start, pos - start);
m_tokens.push_back(CToken(expreval_atof(ident.c_str()), start, pos - 1));
// Move pos back so pos++ will set it right
pos--;
}
else if(exstr[pos] == '_' || expreval_isalpha(exstr[pos]))
{
// We are an identifier
::std::string::size_type start = pos;
bool foundname = true; // Found name part
// Search for name, then period, etc
// An identifier can be multiple parts. Each part
// is formed as an identifier and seperated by a period,
// An identifier can not end in a period
//
// color1.red : 1 identifier token
// color1. : color1 is identifier, . begins new token
// color1.1red : Not value (part 2 is not right)
while(foundname)
{
// Part before period
while(exstr[pos] == '_' || expreval_isalnum(exstr[pos]))
{
pos++;
}
// Is there a period
if(exstr[pos] == '.')
{
pos++;
// There is a period, look for the name again
if(exstr[pos] == '_' || expreval_isalpha(exstr[pos]))
{
foundname = true;
}
else
{
// No name after period
foundname = false;
// Remove period from identifier
pos--;
}
}
else
{
// No period after name, so no new name
foundname = false;
}
}
// Create token
m_tokens.push_back(CToken(exstr.substr(start, pos - start), start, pos - 1));
// Move pos back so pos++ will set it right
pos--;
}
else if(expreval_isspace(exstr[pos]))
{
// Do nothing, just ignore white space, but it still
// seperates tokens
}
else
{
// Unknown token
CUnknownTokenException e;
e.SetStart(pos);
e.SetEnd(pos);
throw(e);
}
}
break;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -