📄 syntaxanalyzer.cpp
字号:
#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 + -