If/elseif with simple conditions

This commit is contained in:
Simon Robertshaw
2012-09-23 15:14:56 +01:00
parent 1905e49744
commit 2ddbd57677
5 changed files with 139 additions and 39 deletions

View File

@@ -225,6 +225,8 @@ namespace pim
Scope * prevScope = currentScope; Scope * prevScope = currentScope;
currentScope = new Scope(); currentScope = new Scope();
defineLabel(label); defineLabel(label);
output << "." << label << std::endl;
} }
void Generator::PushLocalScope(std::string label) void Generator::PushLocalScope(std::string label)
@@ -235,6 +237,8 @@ namespace pim
currentScope->Definitions.insert(currentScope->Definitions.begin(), prevScope->Definitions.begin(), prevScope->Definitions.end()); currentScope->Definitions.insert(currentScope->Definitions.begin(), prevScope->Definitions.begin(), prevScope->Definitions.end());
currentScope->FrameSize = prevScope->FrameSize; currentScope->FrameSize = prevScope->FrameSize;
defineLabel(label); defineLabel(label);
output << "." << label << std::endl;
} }
void Generator::PopScope() void Generator::PopScope()
@@ -242,6 +246,9 @@ namespace pim
writeOpcode(Opcode::Return); writeOpcode(Opcode::Return);
writeConstant(currentScope->LocalFrameSize); writeConstant(currentScope->LocalFrameSize);
output << "return " << currentScope->LocalFrameSize << std::endl;
currentScope = scopes.top(); currentScope = scopes.top();
scopes.pop(); scopes.pop();
} }
@@ -250,12 +257,16 @@ namespace pim
{ {
//defineLabelwriteOpcode("." << label); //defineLabelwriteOpcode("." << label);
defineLabel(label); defineLabel(label);
output << "." << label << std::endl;
} }
void Generator::LocalEnter() void Generator::LocalEnter()
{ {
writeOpcode(Opcode::LocalEnter); writeOpcode(Opcode::LocalEnter);
writeConstantPlaceholder(&(currentScope->LocalFrameSize)); writeConstantPlaceholder(&(currentScope->LocalFrameSize));
output << "enter " << "#" << std::endl;
} }
void Generator::ScopeVariableType(int type) void Generator::ScopeVariableType(int type)
@@ -268,6 +279,8 @@ namespace pim
currentScope->Definitions.push_back(Definition(label, variableType, currentScope->FrameSize)); currentScope->Definitions.push_back(Definition(label, variableType, currentScope->FrameSize));
currentScope->FrameSize += 4; currentScope->FrameSize += 4;
currentScope->LocalFrameSize += 4; currentScope->LocalFrameSize += 4;
output << "#declare " << label << " " << currentScope->FrameSize-4 << std::endl;
} }
void Generator::PushVariableAddress(std::string label) void Generator::PushVariableAddress(std::string label)
@@ -279,108 +292,148 @@ namespace pim
{ {
writeOpcode(Opcode::Load); writeOpcode(Opcode::Load);
writeConstant(currentScope->GetDefinition(label).StackPosition); writeConstant(currentScope->GetDefinition(label).StackPosition);
output << "load " << label << std::endl;
} }
void Generator::StoreVariable(std::string label) void Generator::StoreVariable(std::string label)
{ {
writeOpcode(Opcode::Store); writeOpcode(Opcode::Store);
writeConstant(currentScope->GetDefinition(label).StackPosition); writeConstant(currentScope->GetDefinition(label).StackPosition);
output << "store " << label << std::endl;
} }
void Generator::RTConstant(std::string name) void Generator::RTConstant(std::string name)
{ {
writeOpcode(Opcode::Constant); writeOpcode(Opcode::Constant);
writeConstantMacroPlaceholder(name); writeConstantMacroPlaceholder(name);
output << "const " << name << std::endl;
} }
void Generator::Constant(std::string constant) void Generator::Constant(std::string constant)
{ {
writeOpcode(Opcode::Constant); writeOpcode(Opcode::Constant);
writeConstant(constant); writeConstant(constant);
output << "const " << constant << std::endl;
} }
void Generator::Increment(std::string constant) void Generator::Increment(std::string constant)
{ {
writeOpcode(Opcode::Increment); writeOpcode(Opcode::Increment);
writeConstant(constant); writeConstant(constant);
output << "inc " << constant << std::endl;
} }
void Generator::Discard() void Generator::Discard()
{ {
writeOpcode(Opcode::Discard); writeOpcode(Opcode::Discard);
output << "discard" << std::endl;
} }
void Generator::Duplicate() void Generator::Duplicate()
{ {
writeOpcode(Opcode::Duplicate); writeOpcode(Opcode::Duplicate);
output << "duplicate" << std::endl;
} }
void Generator::Add() void Generator::Add()
{ {
writeOpcode(Opcode::Add); writeOpcode(Opcode::Add);
output << "add" << std::endl;
} }
void Generator::Subtract() void Generator::Subtract()
{ {
writeOpcode(Opcode::Subtract); writeOpcode(Opcode::Subtract);
output << "sub" << std::endl;
} }
void Generator::Multiply() void Generator::Multiply()
{ {
writeOpcode(Opcode::Multiply); writeOpcode(Opcode::Multiply);
output << "mul" << std::endl;
} }
void Generator::Divide() void Generator::Divide()
{ {
writeOpcode(Opcode::Divide); writeOpcode(Opcode::Divide);
output << "div" << std::endl;
} }
void Generator::Modulus() void Generator::Modulus()
{ {
writeOpcode(Opcode::Modulus); writeOpcode(Opcode::Modulus);
output << "add" << std::endl;
} }
void Generator::Negate() void Generator::Negate()
{ {
writeOpcode(Opcode::Negate); writeOpcode(Opcode::Negate);
output << "neg" << std::endl;
} }
void Generator::CreateParticle() void Generator::CreateParticle()
{ {
writeOpcode(Opcode::Create); writeOpcode(Opcode::Create);
output << "create" << std::endl;
} }
void Generator::TransformParticle() void Generator::TransformParticle()
{ {
writeOpcode(Opcode::Transform); writeOpcode(Opcode::Transform);
output << "transform" << std::endl;
} }
void Generator::GetParticle() void Generator::GetParticle()
{ {
writeOpcode(Opcode::Get); writeOpcode(Opcode::Get);
output << "getpart" << std::endl;
} }
void Generator::GetPosition() void Generator::GetPosition()
{ {
writeOpcode(Opcode::Position); writeOpcode(Opcode::Position);
output << "getpos" << std::endl;
} }
void Generator::KillParticle() void Generator::KillParticle()
{ {
writeOpcode(Opcode::Kill); writeOpcode(Opcode::Kill);
output << "kill" << std::endl;
} }
void Generator::LoadProperty(std::string property) void Generator::LoadProperty(std::string property)
{ {
writeOpcode(Opcode::LoadProperty); writeOpcode(Opcode::LoadProperty);
writeConstantPropertyPlaceholder(property); writeConstantPropertyPlaceholder(property);
output << "loadprop " << property << std::endl;
} }
void Generator::StoreProperty(std::string property) void Generator::StoreProperty(std::string property)
{ {
writeOpcode(Opcode::StoreProperty); writeOpcode(Opcode::StoreProperty);
writeConstantPropertyPlaceholder(property); writeConstantPropertyPlaceholder(property);
output << "storeprop " << property << std::endl;
} }
void Generator::IntegerToDecimal() void Generator::IntegerToDecimal()
@@ -398,42 +451,56 @@ namespace pim
{ {
writeOpcode(Opcode::JumpEqual); writeOpcode(Opcode::JumpEqual);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
output << "jumpe " << label << std::endl;
} }
void Generator::JumpNotEqual(std::string label) void Generator::JumpNotEqual(std::string label)
{ {
writeOpcode(Opcode::JumpNotEqual); writeOpcode(Opcode::JumpNotEqual);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
output << "jumpne " << label << std::endl;
} }
void Generator::JumpGreater(std::string label) void Generator::JumpGreater(std::string label)
{ {
writeOpcode(Opcode::JumpGreater); writeOpcode(Opcode::JumpGreater);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
output << "jumpg " << label << std::endl;
} }
void Generator::JumpGreaterEqual(std::string label) void Generator::JumpGreaterEqual(std::string label)
{ {
writeOpcode(Opcode::JumpGreaterEqual); writeOpcode(Opcode::JumpGreaterEqual);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
output << "jumpge " << label << std::endl;
} }
void Generator::JumpLess(std::string label) void Generator::JumpLess(std::string label)
{ {
writeOpcode(Opcode::JumpLess); writeOpcode(Opcode::JumpLess);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
output << "jumpl " << label << std::endl;
} }
void Generator::JumpLessEqual(std::string label) void Generator::JumpLessEqual(std::string label)
{ {
writeOpcode(Opcode::JumpLessEqual); writeOpcode(Opcode::JumpLessEqual);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
output << "jumple " << label << std::endl;
} }
void Generator::Jump(std::string label) void Generator::Jump(std::string label)
{ {
writeOpcode(Opcode::Jump); writeOpcode(Opcode::Jump);
writeConstantPlaceholder(label); writeConstantPlaceholder(label);
output << "jump " << label << std::endl;
} }

View File

@@ -1,5 +1,6 @@
//Syntax analyser //Syntax analyser
#include "Parser.h" #include "Parser.h"
#include "Format.h"
namespace pim namespace pim
{ {
namespace compiler namespace compiler
@@ -157,7 +158,7 @@ namespace pim
void Parser::statementList() void Parser::statementList()
{ {
statement(); statement();
while(!look(Token::EndSymbol)) while(!look(Token::EndSymbol) && !look(Token::ElseIfSymbol))
statement(); statement();
} }
@@ -387,54 +388,69 @@ namespace pim
*/ */
void Parser::ifStatement() void Parser::ifStatement()
{ {
//generator->Begin(NonTerminal::IfStatement); std::string label = generator->UniqueLabel("if");
int blockNum = 0;
expect(Token::IfSymbol); expect(Token::IfSymbol);
condition(); condition(label+format::NumberToString<int>(blockNum));
expect(Token::ThenSymbol); expect(Token::ThenSymbol);
block(); block();
while(accept(Token::ElseIfSymbol))
{
generator->ScopeLabel(label+format::NumberToString<int>(blockNum++));
condition(label+format::NumberToString<int>(blockNum));
expect(Token::ThenSymbol);
block();
}
if(accept(Token::ElseSymbol))
{
generator->ScopeLabel(label+format::NumberToString<int>(blockNum++));
block();
}
else
{
generator->ScopeLabel(label+format::NumberToString<int>(blockNum++));
}
expect(Token::EndSymbol); expect(Token::EndSymbol);
//generator->End(NonTerminal::IfStatement); //generator->End(NonTerminal::IfStatement);
} }
/* /*
<condition> ::= identifier <conditional operator> identifier | identifier <conditional operator> numberConstant | numberConstant <conditional operator> identifier | numberConstant <conditional operator> numberConstant <condition> ::= <expression> <conditional operator> <expression>
*/ */
void Parser::condition() void Parser::condition(std::string jumpLabel)
{ {
//generator->Begin(NonTerminal::Condition); expression();
if(look(Token::Identifier))
Token token = forward();
expression();
if(token.Symbol == Token::GreaterSymbol)
{ {
conditionalOperator(); generator->JumpLessEqual(jumpLabel);
if(!accept(Token::Identifier) && !accept(Token::IntegerConstant) && !accept(Token::DecimalConstant))
throw ParserExpectException(token, "identifier or constant");
} }
else if(look(Token::DecimalConstant) || look(Token::IntegerConstant)) else if(token.Symbol == Token::GreaterEqualSymbol)
{ {
conditionalOperator(); generator->JumpLess(jumpLabel);
if(!accept(Token::Identifier) && !accept(Token::IntegerConstant) && !accept(Token::DecimalConstant)) }
throw ParserExpectException(token, "identifier or constant"); else if(token.Symbol == Token::EqualSymbol)
{
generator->JumpNotEqual(jumpLabel);
}
else if(token.Symbol == Token::NotEqualSymbol)
{
generator->JumpEqual(jumpLabel);
}
else if(token.Symbol == Token::LessSymbol)
{
generator->JumpGreaterEqual(jumpLabel);
}
else if(token.Symbol == Token::LessEqualSymbol)
{
generator->JumpGreater(jumpLabel);
} }
else else
{ throw ParserExpectException(token, "conditional operator");
throw ParserExpectException(token, "condition");
}
//generator->End(NonTerminal::Condition);
}
/*
<conditional operator> ::= > | >= | == | != | < | <=
*/
void Parser::conditionalOperator()
{
//generator->Begin(NonTerminal::ConditionalOperator);
if(!accept(Token::GreaterSymbol))
if(!accept(Token::GreaterEqualSymbol))
if(!accept(Token::EqualSymbol))
if(!accept(Token::NotEqualSymbol))
if(!accept(Token::LessSymbol))
if(!accept(Token::LessEqualSymbol))
throw ParserExpectException(token, "conditional operator");
//generator->End(NonTerminal::ConditionalOperator);
} }
/* /*
@@ -586,7 +602,6 @@ namespace pim
{ {
if(symbol == token.Symbol) if(symbol == token.Symbol)
{ {
//generator->Insert(token);
lastToken = token; lastToken = token;
if(previousTokens.size()) if(previousTokens.size())
{ {
@@ -595,10 +610,10 @@ namespace pim
} }
else else
token = scanner->NextToken(); token = scanner->NextToken();
std::cout << "Symbol " << Token::SymbolNames[symbol] << " " << lastToken.Source << std::endl; //std::cout << "Symbol " << Token::SymbolNames[symbol] << " " << lastToken.Source << std::endl;
return true; return true;
} }
std::cout << "Bad Symbol " << Token::SymbolNames[symbol] << " " << token.Source << " (" << token.GetName() << ")" << std::endl; //std::cout << "Bad Symbol " << Token::SymbolNames[symbol] << " " << token.Source << " (" << token.GetName() << ")" << std::endl;
return false; return false;
} }
@@ -616,6 +631,19 @@ namespace pim
token = lastToken; token = lastToken;
} }
Token Parser::forward()
{
lastToken = token;
if(previousTokens.size())
{
token = previousTokens.top();
previousTokens.pop();
}
else
token = scanner->NextToken();
return lastToken;
}
void Parser::expect(int symbol) void Parser::expect(int symbol)
{ {
if(!accept(symbol)) if(!accept(symbol))

View File

@@ -51,8 +51,7 @@ namespace pim
void statement(); void statement();
void neighbourStatement(); void neighbourStatement();
void ifStatement(); void ifStatement();
void condition(); void condition(std::string jumpLabel);
void conditionalOperator();
void assigmentStatement(); void assigmentStatement();
void particleAction(); void particleAction();
void killStatement(); void killStatement();
@@ -60,11 +59,13 @@ namespace pim
void createStatement(); void createStatement();
void transformStatement(); void transformStatement();
void expressionList(); void expressionList();
void expression(); void expression();
void term(); void term();
void factor(); void factor();
void variableValue(); void variableValue();
Token forward();
bool accept(int symbol); bool accept(int symbol);
bool look(int symbol); bool look(int symbol);
void back(); void back();

View File

@@ -33,6 +33,8 @@ namespace pim
"break", "break",
"continue", "continue",
"if", "if",
"else",
"elseif",
"then", "then",
"end", "end",
"kill", "kill",

View File

@@ -45,6 +45,8 @@ namespace pim
BreakSymbol, BreakSymbol,
ContinueSymbol, ContinueSymbol,
IfSymbol, IfSymbol,
ElseSymbol,
ElseIfSymbol,
ThenSymbol, ThenSymbol,
EndSymbol, EndSymbol,