⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syntaxanalyzer.cpp

📁 a basic interpreter free basic
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	// Now, get the non-optional term and return it,
	// with the appropriate sign.
	return(this->sTerm() * Multiplier);
}

// Get a term from the token stream
float CSyntaxAnalyzer::sTerm(void)
{
	float ReturnValue = 0;
	CToken *Token;

	// Get the first factor, non-optional
	ReturnValue = this->sFactor();

	// Now, get a series of multiplicative
	// operator -> factor sequences
	Token = *this->m_tokenIterator;

	while(Token->GetTokenType() == MULOP)
	{
		char Mulop = this->sMultiplicativeOperator();

		switch(Mulop)
		{
		case '*':
			ReturnValue *= this->sFactor();
			break;
		case '/':
			ReturnValue /= this->sFactor();
			break;
		default:
			throw ILLEGAL_FORMULA;
		}

		Token = *this->m_tokenIterator;
	}

	return ReturnValue;
}

// Get a factor from the input stream
float CSyntaxAnalyzer::sFactor(void)
{
	float ReturnValue = 0;
	CToken *Token = *this->m_tokenIterator;

	// First, check to see whether we're looking at
	// an identifier.
	if(Token->GetTokenType() == ALPHA)
	{
		ReturnValue = this->sIdentifier();
	}
	// Second, check to see whether we're looking at
	// a constant.
	else if(Token->GetTokenType() == DIGIT ||
		    Token->GetTokenType() == T_DECIMAL)
	{
		ReturnValue = this->sConstant();
	}
	// Third, check to see whether it's an expression
	else if(Token->GetTokenType() == PARENTHESIS)
	{
		if(this->sParenthesis() != -1)
		{
			throw ILLEGAL_FORMULA;
		}

		ReturnValue = this->sExpression();

		if(this->sParenthesis() != 1)
		{
			throw ILLEGAL_FORMULA;
		}
	}
	else
	{
		throw ILLEGAL_FORMULA;
	}

	Token = *this->m_tokenIterator;

	// Now, check for an optional exponentiation operator
	// and additional factor.
	if(Token->GetTokenType() == EXPOP)
	{
		this->sExponentiationOperator();
		ReturnValue = pow(ReturnValue, this->sFactor());
	}

	return ReturnValue;
}

// Return true and increment token iterator if the next operator is an exponentiation operator
bool CSyntaxAnalyzer::sExponentiationOperator(void)
{
	CToken *Token = *this->m_tokenIterator;

	// Make sure it's an exponentiation operator
	if(Token->GetTokenType() != EXPOP)
	{
		throw ILLEGAL_FORMULA;
	}

	this->m_tokenIterator++;

	return (bool)(Token->GetLexeme() == "^");
}

// Return with a character for +/- and increment iterator
char CSyntaxAnalyzer::sAdditiveOperator(void)
{
	CToken *Token = *this->m_tokenIterator;

	// Make sure it's an addop
	if(Token->GetTokenType() != ADDOP)
	{
		throw ILLEGAL_FORMULA;
	}

	this->m_tokenIterator++;

	return Token->GetLexeme().c_str()[0];
}

// Return a mulop and increment iterator
char CSyntaxAnalyzer::sMultiplicativeOperator(void)
{
	char ReturnValue = NULL;
	CToken *Token = *this->m_tokenIterator;

	// Make sure it's a mulop
	if(Token->GetTokenType() != MULOP)
	{
		throw ILLEGAL_FORMULA;
	}

	this->m_tokenIterator++;

	return Token->GetLexeme().c_str()[0];
}

// Return relop and increment iterator, or return NULL
relop_t CSyntaxAnalyzer::sRelationalOperator(void)
{
	relop_t ReturnValue;

	CToken *Token = *this->m_tokenIterator;

	// First, make sure that we're looking at a
	// valid relational operator
	if(Token->GetTokenType() != RELOP)
	{
		throw ILLEGAL_RELATION;
	}

	// Evaluate the relational operator
	string Lexeme = Token->GetLexeme();

	if(Lexeme == "<")
		ReturnValue = LESSER_THAN;
	else if(Lexeme == "<=")
		ReturnValue = LESSER_THAN_OR_EQUAL;
	else if(Lexeme == ">")
		ReturnValue = GREATER_THAN;
	else if(Lexeme == ">=")
		ReturnValue = GREATER_THAN_OR_EQUAL;
	else if(Lexeme == "<>")
		ReturnValue = NOT_EQUAL;
	else if(Lexeme == "=")
		ReturnValue = EQUAL;
	else
		throw ILLEGAL_RELATION;

	// Increment the token iterator and return
	this->m_tokenIterator++;

	return ReturnValue;
}

// Returns -1 for left parenthesis, 1 for right parenthesis, and 0 for no parenthesis
int CSyntaxAnalyzer::sParenthesis(void)
{
	int ReturnValue = 0;

	CToken *CurToken = *this->m_tokenIterator;

	// Next, figure out which one it is
	switch(CurToken->GetLexeme().c_str()[0])
	{
	case '(':
		ReturnValue = -1;
		break;
	case ')':
		ReturnValue = 1;
		break;
	default:
		ReturnValue = 0;
	}

	this->m_tokenIterator++;

	return ReturnValue;
}

// Return a constant from the token stream
float CSyntaxAnalyzer::sConstant(void)
{
	float ReturnValue = 0;
	float Mantissa = 0;
	int Exponent = 0;

	CToken *Token = *this->m_tokenIterator;

	// Technically, any digits preceding a
	// decimal point are optional, meaning
	// that numbers in the form of
	// .12345 are acceptable.
	// The grammar states:
	// [(Digit)*][.](Digit)*[Exponent]
	// However, if we lead off with digits
	// and find neither a decimal nor a
	// letter 'E', we have to retain the value.

	while(Token->GetTokenType() == DIGIT)
	{
		ReturnValue *= 10;
		ReturnValue += this->sDigit();
		Token = *this->m_tokenIterator;
	}

	// Now, see if there's a decimal point, and if
	// so, process the mantissa
	if(Token->GetTokenType() == T_DECIMAL)
	{
		// Verify the token
		if(Token->GetLexeme() != ".")
		{
			throw ILLEGAL_CONSTANT;
		}

		this->m_tokenIterator++;
		Token = *this->m_tokenIterator;

		// Process the mantissa.
		// (must have at least one digit in the mantissa,
		//  if there is a leading decimal).
		// First, grab the mantissa into a string
		string strMantissa = "0.";
		do
		{
			strMantissa.append(string(1, (char)this->sDigit() + '0'));
			Token = *this->m_tokenIterator;
		} while(Token->GetTokenType() == DIGIT);

		// Use sscanf to read in the floating point number
		sscanf_s(strMantissa.c_str(), "%f", &Mantissa, sizeof(float));
	}

	// Grab the exponent value, if there is one
	if(Token->GetLexeme() == "E")
	{
		Exponent = this->sExponent();
	}

	// Return the value plus the mantissa times 10 to the exponent
	return((ReturnValue + Mantissa) * pow((float)10, Exponent));
}

// Get an exponent portion of a constant (x.xEx)
int CSyntaxAnalyzer::sExponent(void)
{
	int ReturnValue = NULL;
	int Multiplier = 1;

	CToken *Token = *this->m_tokenIterator;

	// First, get the 'E'
	if(Token->GetLexeme() != "E")
	{
		throw ILLEGAL_CONSTANT;
	}

	this->m_tokenIterator++;
	Token = *this->m_tokenIterator;

	// Next, get an optional addition operator (+/-)
	if(Token->GetTokenType() == ADDOP)
	{
		char Addop = this->sAdditiveOperator();
		switch(Addop)
		{
		case '+':
			// Leave the multiplier alone
			break;
		case '-':
			Multiplier = -1;
			break;
		default:
			throw ILLEGAL_CONSTANT;
		}
	}

	// Finally, get a non-optional sequence of digits,
	// concatenate them into an integer, and multiply
	// it by the sign multiplier.
	do
	{
		ReturnValue *= 10;
		ReturnValue += this->sDigit();
		Token = *this->m_tokenIterator;
	} while(Token->GetTokenType() == DIGIT);

	return(ReturnValue * Multiplier);
}

// Get an identifier from the token stream
float CSyntaxAnalyzer::sIdentifier(void)
{
	float ReturnValue = NULL;
	CToken *Token = *this->m_tokenIterator;
	tokenlist_t::iterator LastChar = this->m_tokenIterator;

	// Our options for parsing identifiers
	// are somewhat limited, since we need
	// to support both functions and variables,
	// but we only have single-character tokens.
	// To implement this, I've decided to go
	// ahead with using a lookahead to determine
	// whether the forthcoming string meets
	// the qualifications of being a function
	// identifier, and if not, default to
	// evaluating it as a variable.
	// This is inefficient, as it requires
	// a lookup in the function table with almost
	// every run.  Maybe I'll fix this later.
	stringstream tempStringStream;
	string tempString;

	// Look up the next three characters
	for(int i = 0; i < 3; i++)
	{
		CToken *LastToken = *LastChar;
		tempStringStream << LastToken->GetLexeme();
		LastChar++;
		if(LastChar == this->m_tokenlist->end())
			break;
	}

	getline(tempStringStream, tempString);

	// See if it matches the DEF FN profile or it
	// exists in the function table
	if(tempString.substr(0, 2) == "FN" ||
	   this->m_Context->GetFunctionTable()->Find(tempString))
	{
		ReturnValue = this->sFunction();
	}
	else
	{
		// Otherwise, it's a variable

		ReturnValue = this->sVariable()->Get();
	}

	return ReturnValue;
}

// Get an unsubscripted variable from the token stream
string CSyntaxAnalyzer::sUnsubscriptedVariable(void)
{
	string ReturnValue = "";
	CToken *Token = *this->m_tokenIterator;

	this->m_tokenIterator++;

	// An unsubscripted variable takes the form
	// ('A'...'Z')[digit]
	// First, get the letter (nonoptional)
	if(Token->GetTokenType() != ALPHA)
	{
		throw ILLEGAL_VARIABLE;
	}

	ReturnValue = Token->GetLexeme();

	// Now, fetch the optional digit
	Token = *this->m_tokenIterator;
	if(Token->GetTokenType() == DIGIT)
	{
		// Retrieve the token, convert it to a string and
		// return it
		int Digit = this->sDigit();

		ReturnValue.append((size_t)1, (char)Digit + '0');
	}

	return ReturnValue;
}

// Get a subscripted variable from the token stream
string CSyntaxAnalyzer::sSubscriptedVariable(void)
{
	string ReturnValue = "";
	stringstream ReturnValueStream;

	CToken *Token = *this->m_tokenIterator;

	this->m_tokenIterator++;

	// A subscripted variable takes the form
	// ('A'...'Z') '(' Expression[','Expression] ')'
	// Start with the nonoptional letter
	if(Token->GetTokenType() != ALPHA)
	{
		throw ILLEGAL_VARIABLE;
	}

	ReturnValueStream << Token->GetLexeme();

	// Next, get a non-optional left-parenthesis
	if(this->sParenthesis() != -1)
	{
		throw ILLEGAL_VARIABLE;
	}

	// Now, evaluate a non-optional expression, and take
	// its integer value
	ReturnValueStream << '(' << (int)this->sExpression();

	// At this point, there may be a optional second dimension
	// subscript that requires evaluating.
	Token = *this->m_tokenIterator;
	if(Token->GetTokenType() == COMMA)
	{
		// If there was a comma, evaluate for another subscript
		this->m_tokenIterator++;
		ReturnValueStream << ',' << (int)this->sExpression();
	}

	// And finally, a nonoptional right parenthesis
	if(this->sParenthesis() != 1)
	{
		throw ILLEGAL_VARIABLE;
	}

	ReturnValueStream << ')';
	// Grab the full string and return it
	getline(ReturnValueStream, ReturnValue);

	return ReturnValue;	
}

// Get a single digit from the token stream
int CSyntaxAnalyzer::sDigit(void)
{
	CToken *Token = *this->m_tokenIterator;
	
	// If the current token is not a digit,
	// throw an exception
	if(Token->GetTokenType() != DIGIT)
	{
		throw ILLEGAL_FORMULA;
	}

	// Otherwise, increment the iterator and return
	// the digit as an integer
	int DigitValue = atoi(Token->GetLexeme().c_str());
	this->m_tokenIterator++;

	return DigitValue;
}

// Evaluate a function from the token stream
float CSyntaxAnalyzer::sFunction(void)
{
	float ReturnValue = 0;

	string FunctionDef;

	// Grab a function identifier, and evaluate
	// the expression within its parentheses
	string FunctionID = this->sFunctionIdentifier();
	
	// If the next token is not a left parenthesis
	if(this->sParenthesis() != -1)
	{
		throw ILLEGAL_FORMULA;
	}

	// Evaluate the expression in the parentheses
	float ExpValue = this->sExpression();

	// If the next token is not a right parenthesis
	if(this->sParenthesis() != 1)
	{
		throw ILLEGAL_FORMULA;
	}

	// Determine which type of function it is, and run it
	CFunction *Function = this->m_Context->GetFunctionTable()->Find(FunctionID);

	if(Function == NULL)
	{
		throw UNDEFINED_FUNCTION;
	}

	switch(Function->GetBuiltin())
	{
	case true:
		// If it's a builtin, run the builtin
		ReturnValue = Function->ExecuteBuiltin(ExpValue);
		break;
	case false:
		// Otherwise, we'll need to lex and parse the
		// function definition within the current runtime
		// context, but outside of the current syntax
		// context.  This will necessitate a recursive
		// call to CSyntaxAnalyzer
		FunctionDef = Function->GetExpression();
		Function->GetSymbol()->Set(ExpValue);
		
		ReturnValue = this->Expression(FunctionDef);

		break;
	}

	return ReturnValue;
}

// Get a function identifier from the token stream
string CSyntaxAnalyzer::sFunctionIdentifier(void)
{
	string FunctionValue;

	// Grab the next three characters from the
	// input stream.  If any of the next three
	// tokens are not characters, throw an
	// exception
	for(int i = 0; i < 3; i++)
	{
		CToken *CurToken = *this->m_tokenIterator;

		if(CurToken->GetTokenType() != ALPHA)
		{
			throw UNDEFINED_FUNCTION;
		}

		FunctionValue += CurToken->GetLexeme();

		this->m_tokenIterator++;
	}

	return FunctionValue;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -