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

📄 syntaxanalyzer.cpp

📁 a basic interpreter free basic
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	// Iterate from the first token, lookahead for the keyword
	tokenlist_t::iterator Curtoken = this->m_tokenIterator;

	for(int i = 0; i < 5; i++)
	{
		CToken *Token = *Curtoken;
		string ch = Token->GetLexeme();
		KeyStream << ch;
		Curtoken++;
		if(Curtoken == this->m_tokenlist->end())
			break;
	}

	getline(KeyStream, Keyword);

	// Make sure we're looking at an end statement
	if(Keyword != "GOSUB")
	{
		return false;
	}
	
	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	while(Token->GetTokenType() == ALPHA)
	{
		KeyStream << Token->GetLexeme();

		this->m_tokenIterator++;
		Token = *this->m_tokenIterator;
		if(this->m_tokenIterator == this->m_tokenlist->end())
			break;
	}

	getline(KeyStream, Keyword);

	// Verify that the command was constructed correctly
	if(Keyword != "GOSUB")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// Get a line number from the token stream
	int LineNumber = this->sLineNumber();

	// Push the next (return) line number into the
	// return stack.
	CCodeLine *CodeLine = this->GetContext()->GetCode()->GetNext();

	// If there is no next code line, then end is not last
	if(CodeLine == NULL)
	{
		throw END_IS_NOT_LAST;
	}

	this->GetContext()->GetReturnStack()->push(CodeLine->GetLineNumber());

	// Branch to the subroutine
	this->GetContext()->GetCode()->Find(LineNumber);
	this->GetContext()->SetBranching(true);

	return true;
}

// Get a RETURN statement from the token stream
bool CSyntaxAnalyzer::sReturnStatement(void)
{
	// This statement should occur on its own,
	// with no parameters
	stringstream KeyStream;
	string Keyword;

	// Iterate from the first token, lookahead for the keyword
	tokenlist_t::iterator Curtoken = this->m_tokenIterator;

	for(int i = 0; i < 6; i++)
	{
		CToken *Token = *Curtoken;
		string ch = Token->GetLexeme();
		KeyStream << ch;
		Curtoken++;
		if(Curtoken == this->m_tokenlist->end())
			break;
	}

	getline(KeyStream, Keyword);

	// Make sure we're looking at an end statement
	if(Keyword != "RETURN")
	{
		return false;
	}
	
	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	while(Token->GetTokenType() == ALPHA)
	{
		KeyStream << Token->GetLexeme();

		this->m_tokenIterator++;
		Token = *this->m_tokenIterator;
		if(this->m_tokenIterator == this->m_tokenlist->end())
			break;
	}

	getline(KeyStream, Keyword);

	// Verify that the command was constructed correctly
	if(Keyword != "RETURN")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// If so, pop a return value from the return stack
	// and set the context to branching
	if(this->GetContext()->GetReturnStack()->empty())
	{
		throw ILLEGAL_RETURN;
	}

	// Perform the branching
	int LineNumber = this->GetContext()->GetReturnStack()->top();
	this->GetContext()->GetReturnStack()->pop();
	CCodeLine *CodeLine = this->GetContext()->GetCode()->Find(LineNumber);

	this->GetContext()->SetBranching(true);

	// If the line number isn't found, exception
	if(CodeLine == NULL)
	{
		throw ILLEGAL_LINE_NUMBER;
	}

	return true;
}

// Get a STOP statement from the token stream
bool CSyntaxAnalyzer::sStopStatement(void)
{
	// This statement should occur on its own,
	// with no parameters
	stringstream KeyStream;
	string Keyword;

	// Iterate from the first token, lookahead for the keyword
	tokenlist_t::iterator Curtoken = this->m_tokenIterator;

	for(int i = 0; i < 4; i++)
	{
		CToken *Token = *Curtoken;
		string ch = Token->GetLexeme();
		KeyStream << ch;
		Curtoken++;
		if(Curtoken == this->m_tokenlist->end())
			break;
	}

	getline(KeyStream, Keyword);

	// Make sure we're looking at an end statement
	if(Keyword != "STOP")
	{
		return false;
	}
	
	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	while(Token->GetTokenType() == ALPHA)
	{
		KeyStream << Token->GetLexeme();

		this->m_tokenIterator++;
		Token = *this->m_tokenIterator;
		if(this->m_tokenIterator == this->m_tokenlist->end())
			break;
	}

	getline(KeyStream, Keyword);

	// Verify that the command was constructed correctly
	if(Keyword != "STOP")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// If so, stop the program
	this->m_Context->SetRunning(false);

	return true;
}

// Get an END statement from the input stream
bool CSyntaxAnalyzer::sEndStatement(void)
{
	// This statement should occur on its own,
	// with no parameters
	stringstream KeyStream;
	string Keyword;

	// Iterate from the first token, lookahead for the keyword
	tokenlist_t::iterator Curtoken = this->m_tokenIterator;

	for(int i = 0; i < 3; i++)
	{
		CToken *Token = *Curtoken;
		string ch = Token->GetLexeme();
		KeyStream << ch;
		Curtoken++;
		if(Curtoken == this->m_tokenlist->end())
			break;
	}

	getline(KeyStream, Keyword);

	// Make sure we're looking at an end statement
	if(Keyword != "END")
	{
		return false;
	}
	
	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	while(Token->GetTokenType() == ALPHA)
	{
		KeyStream << Token->GetLexeme();

		this->m_tokenIterator++;
		Token = *this->m_tokenIterator;
		if(this->m_tokenIterator == this->m_tokenlist->end())
			break;
	}

	getline(KeyStream, Keyword);

	// Verify that the command was constructed correctly
	if(Keyword != "END")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// If so, stop the program
	this->m_Context->SetRunning(false);

	return true;
}

// Get a variable from the token stream
// Make sure to set up the selection for
// subscripted variables.  If the variable
// doesn't exist yet, go ahead and create it.
CSymbol * CSyntaxAnalyzer::sVariable(void)
{
	CSymbol *ReturnValue = NULL;
	CToken *Token;
	bool unsubscripted = true;

	// The complications here are that in order
	// to tell the difference between a subscripted
	// and an unsubscripted variable, we'll need to
	// look ahead to see whether there is a
	// parenthesis.  Fortunately, it won't be too
	// far ahead.
	tokenlist_t::iterator Curtoken = this->m_tokenIterator;
	tokenlist_t::iterator Lasttoken = this->m_tokenIterator;

	// Start at the next token in the stream
	Lasttoken++;

	for(int i = 0; i < 2; i++)
	{
		Token = *Lasttoken;
		if(Token->GetTokenType() == PARENTHESIS &&
		   Token->GetLexeme() == "(")
		{
			unsubscripted = false;
		}

		Lasttoken++;
		if(Lasttoken == this->m_tokenlist->end())
			break;
	}

	// Now, get the string that represents the variable
	string Variable;

	// If the variable is unsubscripted
	if(unsubscripted)
	{
		Variable = this->sUnsubscriptedVariable();

		// Check the symbol table for its existence
		ReturnValue = this->m_Context->GetSymbolTable()->Find(Variable);

		// If it doesn't already exist, add it and default it to 0
		if(ReturnValue == NULL)
		{
			ReturnValue = new CSymbol(Variable, VARIABLE);
			ReturnValue->Set(0);
			this->m_Context->GetSymbolTable()->Add(ReturnValue);
		}
	}
	// Otherwise, we have to do a lot of additional parsing
	else
	{
		Variable = this->sSubscriptedVariable();

		// Tokenize the variable into portions
		size_t OpenParen = Variable.find_first_of('(');
		size_t CloseParen = Variable.find_last_of(')');
		size_t Comma = Variable.find_first_of(',');

		string VariableName = Variable.substr(0, OpenParen);

		// If there is a comma, it's a matrix.  Otherwise,
		// it's a vector.
		if(Comma != string::npos)
		{
			int FirstDim = atoi(Variable.substr(OpenParen + 1, Comma - (OpenParen + 1)).c_str());
			int SecondDim = atoi(Variable.substr(Comma + 1, CloseParen - (Comma + 1)).c_str());

			// Check the symbol for existence
			ReturnValue = this->m_Context->GetSymbolTable()->Find(VariableName);

			// If it doesn't exist, create it with defaults
			if(ReturnValue == NULL && this->m_Dim == false)
			{
				ReturnValue = new CSymbol(VariableName, MATRIX);
				this->m_Context->GetSymbolTable()->Add(ReturnValue);
			}
			// If we're in a DIM statement, create it with appropriate
			// dimensions
			else if(ReturnValue == NULL && this->m_Dim == true)
			{
				ReturnValue = new CSymbol(VariableName);
				ReturnValue->CreateMatrix(FirstDim, SecondDim);
				this->m_Context->GetSymbolTable()->Add(ReturnValue);
			}

			// Select the subscript
			ReturnValue->SetSubscript(FirstDim, SecondDim);
		}
		// Select for vector
		else
		{
			int Dim = atoi(Variable.substr(OpenParen + 1, CloseParen - 1).c_str());

			// Check for existence
			ReturnValue = this->m_Context->GetSymbolTable()->Find(VariableName);

			// If it doesn't exist, create it
			if(ReturnValue == NULL && this->m_Dim == false)
			{
				ReturnValue = new CSymbol(VariableName, VECTOR);
				this->m_Context->GetSymbolTable()->Add(ReturnValue);
			}
			else if(ReturnValue == NULL && this->m_Dim == true)
			{
				ReturnValue = new CSymbol(VariableName);
				ReturnValue->CreateVector(Dim);
				this->m_Context->GetSymbolTable()->Add(ReturnValue);
			}

			// Select the subscript
			ReturnValue->SetSubscript(Dim);
		}
	}

	// Return the symbol
	return ReturnValue;
}


// Get a string from the token list
string CSyntaxAnalyzer::sString(void)
{
	// The next token is expected to be a string
	CToken *Token = *this->m_tokenIterator;

	if(Token->GetTokenType() != STRING)
	{
		throw INCORRECT_FORMAT;
	}

	string ReturnValue = Token->GetLexeme();

	this->m_tokenIterator++;

	// If it passes the test, just return the token lexeme.
	return(ReturnValue);
}

// Get a variable list from the token stream
list<CSymbol *> * CSyntaxAnalyzer::sVariableList(void)
{
	// Return a list of symbol pointers
	list<CSymbol *> *ReturnList = new list<CSymbol *>();

	CToken *Token;

	// Get at least one variable
	ReturnList->push_back(this->sVariable());

	// And get a list of optional variables
	Token = *this->m_tokenIterator;

	while(Token->GetTokenType() == COMMA)
	{
		this->m_tokenIterator++;

		ReturnList->push_back(this->sVariable());

		Token = *this->m_tokenIterator;
	}

	return ReturnList;
}

// Get a list of evaluated expressions
list<float> * CSyntaxAnalyzer::sExpressionList(void)
{
	list<float> *ReturnList = new list<float>();

	// One non-optional expression in the list
	ReturnList->push_back(this->sExpression());

	// And any number of optional expressions
	CToken *Token = *this->m_tokenIterator;

	while(Token->GetTokenType() == COMMA)
	{
		this->m_tokenIterator++;

		// Evaluate the expression and add it to the list
		ReturnList->push_back(this->sExpression());

		Token = *this->m_tokenIterator;
	}

	return ReturnList;
}

// Get a label/expression list from the token stream
string CSyntaxAnalyzer::sLabelExpressionList(void)
{
	string ReturnValue;
	stringstream ListStream;

	// At least one LabelExpression
	ListStream << this->sLabelExpression() << "\t";

	// And a list of optional LabelExpressions
	CToken *Token = *this->m_tokenIterator;

	while(Token->GetTokenType() == COMMA)
	{
		this->m_tokenIterator++;
		ListStream << this->sLabelExpression() << "\t";
		Token = *this->m_tokenIterator;
	}

	getline(ListStream, ReturnValue);

	return ReturnValue;
}

// Get a label/expression from the token stream, return it as a string
string CSyntaxAnalyzer::sLabelExpression(void)
{
	stringstream LabelExpressionStream;
	string ReturnValue;

	CToken *Token = *this->m_tokenIterator;

	// This should be either a string, an expression,
	// or both, in order.
	if(Token->GetTokenType() == STRING)
	{
		LabelExpressionStream << this->sString();
	}

	// If we hit either a comma or the end of line,
	// no need to process an expression.
	// This is a bit of a cheat, but I couldn't find
	// a truly elegant way to validate an expression
	// in advance of actually calculating it.
	Token = *this->m_tokenIterator;

	if(Token->GetTokenType() != COMMA &&
	   Token->GetTokenType() != EOL)
	{
		LabelExpressionStream << this->sExpression();
	}

	getline(LabelExpressionStream, ReturnValue);

	return ReturnValue;
}

// Evaluate an expression
float CSyntaxAnalyzer::sExpression(void)
{
	float ReturnValue = 0;
	CToken *Token;

	// Get a non-optional signed term
	ReturnValue = this->sSignedTerm();

	// Now, get optional addition operator
	// -> term sequences
	Token = *this->m_tokenIterator;

	while(Token->GetTokenType() == ADDOP)
	{
		char Addop = this->sAdditiveOperator();
		switch(Addop)
		{
		case '+':
			ReturnValue += this->sFactor();
			break;
		case '-':
			ReturnValue -= this->sFactor();
			break;
		}

		Token = *this->m_tokenIterator;
	}

	return ReturnValue;
}

// Get a signed term from the token stream
float CSyntaxAnalyzer::sSignedTerm(void)
{
	float ReturnValue = 0;
	int Multiplier = 1;

	CToken *Token = *this->m_tokenIterator;

	// Get an optional sign modifier
	if(Token->GetTokenType() == ADDOP)
	{
		char Addop = this->sAdditiveOperator();
		switch(Addop)
		{
		case '+':
			// Leave the multiplier be
			break;
		case '-':
			Multiplier = -1;
		}
	}

⌨️ 快捷键说明

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