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

📄 syntaxanalyzer.cpp

📁 a basic interpreter free basic
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#include "StdAfx.h"
#include "SyntaxAnalyzer.h"

CSyntaxAnalyzer::CSyntaxAnalyzer(void)
: m_Context(NULL),
  m_tokenlist(NULL),
  m_Dim(false)
{
}

// Allow full construction
CSyntaxAnalyzer::CSyntaxAnalyzer(CContext *Context, tokenlist_t *TokenList)
: m_Context(Context),
  m_tokenlist(TokenList),
  m_Dim(false)
{
	this->m_tokenIterator = this->m_tokenlist->begin();
}

CSyntaxAnalyzer::~CSyntaxAnalyzer(void)
{
}

// Set the runtime context (runtime context is required)
void CSyntaxAnalyzer::SetContext(CContext * Context)
{
	this->m_Context = Context;
}

// Get the runtime context
CContext * CSyntaxAnalyzer::GetContext(void)
{
	return this->m_Context;
}

// Set the token list for the current run
void CSyntaxAnalyzer::SetTokenList(tokenlist_t * TokenList)
{
	this->m_tokenlist = TokenList;
	this->m_tokenIterator = this->m_tokenlist->begin();
}

// Get the current token list
tokenlist_t * CSyntaxAnalyzer::GetTokenList(void)
{
	return this->m_tokenlist;
}

// Analyze a program statement
void CSyntaxAnalyzer::Analyze(void)
{
	this->sProgramStatement();
}

// Wrapper for parsing an expression, for
// defined functions
float CSyntaxAnalyzer::Expression(string strExpression)
{
	CLexicalAnalyzer Lexer;
	CSyntaxAnalyzer Parser(this->m_Context, Lexer.Analyze(strExpression));
	return(Parser.sExpression());
}

/*
 * BEGIN PRIVATE PARSING METHODS
 */

// Parse a program statement
void CSyntaxAnalyzer::sProgramStatement(void)
{
	// Get an optional line number
	CToken *Token = *this->m_tokenIterator;

	int LineNumber = 0;

	if(Token->GetTokenType() == DIGIT)
	{
		LineNumber = this->sLineNumber();
	}

	// If the statement was begun with a line number
	if(LineNumber)
	{
		// Just store the line in the code list
		string strCode;

		Token = *this->m_tokenIterator;

		while(Token->GetTokenType() != EOL)
		{
			// Need to do some special handling of strings here
			if(Token->GetTokenType() == STRING)
			{
				strCode.append("\"" + Token->GetLexeme() + "\"");
			}
			else
			{
				strCode.append(Token->GetLexeme());
			}
			this->m_tokenIterator++;
			Token = *this->m_tokenIterator;
		}

		CCodeLine *CodeLine = new CCodeLine(LineNumber, strCode);

		this->GetContext()->GetCode()->Add(CodeLine);
	}
	// Otherwise, assume it's a standalone statement and execute it
	else
	{
		this->sStatement();
	}

	return;	
}

// Get a line number from the token stream
int CSyntaxAnalyzer::sLineNumber(void)
{
	int ReturnValue = 0;

	// A line number is a sequence of digits
	CToken *Token = *this->m_tokenIterator;

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

	// It must be a positive number greater than 0
	if(ReturnValue < 1)
	{
		throw ILLEGAL_LINE_NUMBER;
	}

	return ReturnValue;
}

// Get a statement from the token stream
void CSyntaxAnalyzer::sStatement(void)
{
	// Go through each possible statement and try
	// to execute it.
	if(this->sLetStatement())
		return;
	if(this->sReadStatement())
		return;
	if(this->sDataStatement())
		return;
	if(this->sPrintStatement())
		return;
	if(this->sGotoStatement())
		return;
	if(this->sIfThenStatement())
		return;
	if(this->sForStatement())
		return;
	if(this->sNextStatement())
		return;
	if(this->sRemStatement())
		return;
	if(this->sDimStatement())
		return;
	if(this->sDefStatement())
		return;
	if(this->sGoSubStatement())
		return;
	if(this->sReturnStatement())
		return;
	if(this->sStopStatement())
		return;
	if(this->sEndStatement())
		return;

	// If we've gotten this far, then the statement
	// is invalid.
	throw ILLEGAL_INSTRUCTION;
}

// Get a LET statement from the token stream
bool CSyntaxAnalyzer::sLetStatement(void)
{
	// This statement can occur with any string of characters after it
	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 a next statement
	if(Keyword != "LET")
	{
		return false;
	}

	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	for(int i = 0; i < 3; i++)
	{
		KeyStream << Token->GetLexeme();

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

	getline(KeyStream, Keyword);

	// Make sure we're looking at a read statement
	if(Keyword != "LET")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// Find (or create) the referenced variable
	CSymbol *Symbol = this->sVariable();

	// Get an equals sign
	Token = *this->m_tokenIterator;
	if(Token->GetLexeme() != "=")
	{
		throw INCORRECT_FORMAT;
	}

	this->m_tokenIterator++;

	// Get the expression and set the value of the symbol
	Symbol->Set(this->sExpression());

	return true;
}

// Get a READ statement from the token stream
bool CSyntaxAnalyzer::sReadStatement(void)
{
	// This statement can occur with any string of characters after it
	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 a next statement
	if(Keyword != "READ")
	{
		return false;
	}

	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	for(int i = 0; i < 4; i++)
	{
		KeyStream << Token->GetLexeme();

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

	getline(KeyStream, Keyword);

	// Make sure we're looking at a read statement
	if(Keyword != "READ")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// Unstack the data into the given variables
	list<CSymbol *> *VarList = this->sVariableList();
	
	list<CSymbol *>::iterator VarIterator = VarList->begin();

	while(VarIterator != VarList->end())
	{
		if(this->GetContext()->GetDataQueue()->empty())
		{
			throw ERR_NO_DATA;
		}

		CSymbol *Symbol = *VarIterator;
		Symbol->Set(this->GetContext()->GetDataQueue()->front());
		this->GetContext()->GetDataQueue()->pop();

		VarIterator++;
	}

	return true;
}

// Get a DATA statement from the token stream
bool CSyntaxAnalyzer::sDataStatement(void)
{
	// This statement can occur with any string of characters after it
	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 a next statement
	if(Keyword != "DATA")
	{
		return false;
	}

	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	for(int i = 0; i < 4; i++)
	{
		KeyStream << Token->GetLexeme();

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

	getline(KeyStream, Keyword);

	// Make sure we're looking at a data statement
	if(Keyword != "DATA")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// Stack the expression list
	list<float> *ExpList = this->sExpressionList();
	
	list<float>::iterator ExpIterator = ExpList->begin();

	while(ExpIterator != ExpList->end())
	{
		this->GetContext()->GetDataQueue()->push(*ExpIterator);
		ExpIterator++;
	}

	return true;
}

// Get a PRINT statement from the token stream
bool CSyntaxAnalyzer::sPrintStatement(void)
{
	// This statement can occur with any string of characters after it
	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 < 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 a next statement
	if(Keyword != "PRINT")
	{
		return false;
	}

	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	for(int i = 0; i < 5; i++)
	{
		KeyStream << Token->GetLexeme();

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

	getline(KeyStream, Keyword);

	// Make sure we're looking at a PRINT statement
	if(Keyword != "PRINT")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// Print the LabelExpressionList to the screen
	cout << this->sLabelExpressionList();

	return true;
}

// Get a GOTO statement from the token stream
bool CSyntaxAnalyzer::sGotoStatement(void)
{
	// This statement can occur with any string of characters after it
	stringstream KeyStream;
	string Keyword;

	// Line number to jump to
	int LineNumber;

	// 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 a next statement
	if(Keyword != "GOTO")
	{
		return false;
	}
	
	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	for(int i = 0; i < 4; i++)
	{
		KeyStream << Token->GetLexeme();

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

	getline(KeyStream, Keyword);

	// Make sure we're looking at a GOTO statement
	if(Keyword != "GOTO")
	{
		throw ILLEGAL_INSTRUCTION;
	}

	// Get the line number
	LineNumber = this->sLineNumber();

	if(this->GetContext()->GetCode()->Find(LineNumber) == NULL)
	{
		throw ILLEGAL_LINE_NUMBER;
	}
	else
	{
		this->GetContext()->SetBranching(true);
	}

	return true;
}

// Get an IF THEN statement from the token stream
bool CSyntaxAnalyzer::sIfThenStatement(void)
{
	// This statement can occur with any string of characters after it
	stringstream KeyStream;
	string Keyword;

	// Expressions
	float LeftExp;
	float RightExp;
	relop_t Relationship;

	// Line number to jump to
	int LineNumber;

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

	for(int i = 0; i < 2; 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 a next statement
	if(Keyword != "IF")
	{
		return false;
	}
	
	// Go ahead and soak up the line
	CToken *Token = *this->m_tokenIterator;
	KeyStream.clear();

	for(int i = 0; i < 2; i++)
	{
		KeyStream << Token->GetLexeme();

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

⌨️ 快捷键说明

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