//Syntax analyser #include "Parser.h" #include "Format.h" namespace pim { namespace compiler { Parser::Parser(std::stringstream & source_) : source(source_) { scanner = new Scanner(source); generator = new Generator(); token = scanner->NextToken(); } std::vector Parser::Compile() { program(); return generator->Finish(); } /* ::= */ void Parser::program() { functionList(); } /* ::= | */ void Parser::functionList() { function(); while(look(Token::FunctionSymbol)) function(); } /* ::= function identifier ( ) end */ void Parser::function() { std::string functionName; expect(Token::FunctionSymbol); functionName = token.Source; //generator->ScopeLabel(functionName); //Function name generator->PushScope(functionName); expect(Token::Identifier); expect(Token::LeftBracket); if(!accept(Token::RightBracket)) { argumentList(); expect(Token::RightBracket); } block(); expect(Token::EndSymbol); generator->Return(); generator->PopScope(); } /* ::= identifier ( ) */ void Parser::functionCall() { std::string functionName; functionName = token.Source; expect(Token::Identifier); expect(Token::LeftBracket); expressionList(); expect(Token::RightBracket); //generator->Call(functionName); } /* ::= */ void Parser::block() { if(look(Token::IntegerSymbol) || look(Token::DecimalSymbol) || look(Token::ParticleSymbol)) declarationList(); statementList(); } /* ::= | , */ void Parser::argumentList() { argument(); while(accept(Token::CommaSymbol)) argument(); } /* ::= integer identifier | decimal identifier | particle identifier */ void Parser::argument() { generator->ScopeVariableType(token.Symbol); if(!accept(Token::IntegerSymbol)) if(!accept(Token::DecimalSymbol)) if(!accept(Token::ParticleSymbol)) throw ParserExpectException(token, "type name"); generator->ScopeVariable(token.Source); expect(Token::Identifier); } /* ::= | , */ void Parser::declarationList() { declaration(); while(accept(Token::CommaSymbol)) declaration(); } /* ::= integer | decimal | particle */ void Parser::declaration() { generator->ScopeVariableType(token.Symbol); if(!accept(Token::IntegerSymbol)) if(!accept(Token::DecimalSymbol)) if(!accept(Token::ParticleSymbol)) throw ParserExpectException(token, "type name"); identifierList(); } /* ::= identifier | identifier , */ void Parser::identifierList() { generator->ScopeVariable(token.Source); expect(Token::Identifier); while(accept(Token::CommaSymbol)) { generator->ScopeVariable(token.Source); expect(Token::Identifier); } } /* ::= | */ void Parser::statementList() { statement(); while(!look(Token::EndSymbol) && !look(Token::ElseIfSymbol)) statement(); } /* ::= | | | | | break | continue */ void Parser::statement() { //generator->Begin(NonTerminal::Statement); if(look(Token::NeighbourSymbol)) { neighbourStatement(); } else if(look(Token::IfSymbol)) { ifStatement(); } else if(look(Token::CreateSymbol) || look(Token::KillSymbol) || look(Token::GetSymbol) || look(Token::TransformSymbol)) { particleAction(); generator->Discard(); } else if(look(Token::BreakSymbol)) { expect(Token::BreakSymbol); generator->Jump(breakLabel); } else if(look(Token::ContinueSymbol)) { expect(Token::ContinueSymbol); generator->Jump(continueLabel); } else if(look(Token::Identifier)) { assigmentStatement(); } //generator->End(NonTerminal::Statement); } /* ::= | | */ void Parser::particleAction() { if(look(Token::KillSymbol)) { killStatement(); } else if(look(Token::CreateSymbol)) { createStatement(); } else if(look(Token::TransformSymbol)) { transformStatement(); } } /* ::= kill ( ) */ void Parser::killStatement() { expect(Token::KillSymbol); expect(Token::LeftBracket); expression(); expect(Token::RightBracket); generator->KillParticle(); } /* ::= create ( , , , ) */ void Parser::createStatement() { expect(Token::CreateSymbol); expect(Token::LeftBracket); expression(); expect(Token::CommaSymbol); expression(); expect(Token::CommaSymbol); expression(); expect(Token::CommaSymbol); expression(); expect(Token::RightBracket); generator->CreateParticle(); } /* ::= transform ( , ) */ void Parser::transformStatement() { expect(Token::TransformSymbol); expect(Token::LeftBracket); expression(); expect(Token::CommaSymbol); expression(); expect(Token::RightBracket); generator->TransformParticle(); } /* ::= get ( , ) */ void Parser::getStatement() { expect(Token::GetSymbol); expect(Token::LeftBracket); expression(); expect(Token::CommaSymbol); expression(); expect(Token::RightBracket); generator->GetParticle(); } /* ::= neighbour identifier for do end | neighbour identifier for , do end */ void Parser::neighbourStatement() { std::string neighbourVariable; std::string loopLabel = generator->UniqueLabel("neighbour"); std::string xVar = loopLabel+"X"; std::string xMin = loopLabel+"minX"; std::string xMax = loopLabel+"maxX"; std::string yVar = loopLabel+"Y"; std::string yMax = loopLabel+"maxY"; breakLabel = loopLabel+"End"; continueLabel = loopLabel+"Next"; expect(Token::NeighbourSymbol); generator->PushLocalScope(loopLabel+"Start"); neighbourVariable = token.Source; expect(Token::Identifier); generator->ScopeVariableType(Token::IntegerConstant); generator->ScopeVariable(neighbourVariable); generator->ScopeVariable(xVar); generator->ScopeVariable(yVar); generator->ScopeVariable(xMin); generator->ScopeVariable(xMax); generator->ScopeVariable(yMax); generator->LocalEnter(); expect(Token::OfSymbol); //Initialise position expression(); generator->GetPosition(); generator->Duplicate(); generator->Increment("-1"); generator->StoreVariable(yVar); generator->Increment("1"); generator->StoreVariable(yMax); generator->Duplicate(); generator->Increment("-1"); generator->Duplicate(); generator->StoreVariable(xVar); generator->StoreVariable(xMin); generator->Increment("1"); generator->StoreVariable(xMax); //if(accept(Token::CommaSymbol)) // expression(); expect(Token::DoSymbol); generator->ScopeLabel(loopLabel+"Next"); //Check X generator->LoadVariable(xVar); generator->LoadVariable(xMax); //generator->Duplicate(); //Duplicate xvar so it can be used for incrementing generator->JumpLessEqual(loopLabel+"Begin"); //if(xVar > xMax) { //Reset X, increment Y generator->LoadVariable(xMin); generator->StoreVariable(xVar); generator->LoadVariable(yVar); generator->Increment("1"); generator->Duplicate(); generator->StoreVariable(yVar); //Check Y generator->LoadVariable(yMax); generator->JumpGreater(loopLabel+"End"); //} //Start of loop generator->ScopeLabel(loopLabel+"Begin"); generator->LoadVariable(xVar); generator->LoadVariable(yVar); generator->GetParticle(); generator->StoreVariable(neighbourVariable); block(); //Increment X generator->LoadVariable(xVar); generator->Increment("1"); generator->StoreVariable(xVar); //Next element generator->Jump(loopLabel+"Next"); generator->ScopeLabel(loopLabel+"End"); generator->Return(); generator->PopScope(); expect(Token::EndSymbol); } /* ::= if then end */ void Parser::ifStatement() { std::string label = generator->UniqueLabel("if"); int blockNum = 0; expect(Token::IfSymbol); condition(label+format::NumberToString(blockNum)); expect(Token::ThenSymbol); block(); while(accept(Token::ElseIfSymbol)) { generator->ScopeLabel(label+format::NumberToString(blockNum++)); condition(label+format::NumberToString(blockNum)); expect(Token::ThenSymbol); block(); } if(accept(Token::ElseSymbol)) { generator->ScopeLabel(label+format::NumberToString(blockNum++)); block(); } else { generator->ScopeLabel(label+format::NumberToString(blockNum++)); } expect(Token::EndSymbol); //generator->End(NonTerminal::IfStatement); } /* ::= */ void Parser::condition(std::string jumpLabel) { expression(); Token token = forward(); expression(); if(token.Symbol == Token::GreaterSymbol) { generator->JumpLessEqual(jumpLabel); } else if(token.Symbol == Token::GreaterEqualSymbol) { generator->JumpLess(jumpLabel); } 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 throw ParserExpectException(token, "conditional operator"); } /* ::= identifier = | identifier.property = */ void Parser::assigmentStatement() { std::string variable = token.Source; expect(Token::Identifier); if(accept(Token::AssignSymbol)) { expression(); generator->StoreVariable(variable); } else if(accept(Token::DotSymbol)) { std::string property = token.Source; expect(Token::Identifier); expect(Token::AssignSymbol); expression(); generator->LoadVariable(variable); generator->StoreProperty(property); } } /* ::= | , */ void Parser::expressionList() { //generator->Begin(NonTerminal::ExpressionList); expression(); while(accept(Token::CommaSymbol)) expression(); //generator->End(NonTerminal::ExpressionList); } /* ::= | + | - */ void Parser::expression() { term(); int as = token.Symbol; while(accept(Token::PlusSymbol) || accept(Token::MinusSymbol)) { term(); if(as == Token::PlusSymbol) generator->Add(); else if(as == Token::MinusSymbol) generator->Subtract(); } //generator->End(NonTerminal::Expression); } /* ::= | * | / */ void Parser::term() { //generator->Begin(NonTerminal::Term); factor(); int md = token.Symbol; while(accept(Token::MultiplySymbol) || accept(Token::DivideSymbol)) { factor(); if(md == Token::MultiplySymbol) generator->Multiply(); else if(md == Token::DivideSymbol) generator->Divide(); } //generator->End(NonTerminal::Term); } /* ::= | - | numberConstant | - numberConstant | ( ) | - ( ) */ void Parser::factor() { bool doNegate = false; std::string factor = token.Source; if(accept(Token::MinusSymbol)) { factor = token.Source; doNegate = true; } if(accept(Token::IntegerConstant) || accept(Token::DecimalConstant)) { if(doNegate) { doNegate = false; generator->Constant("-" + factor); } else generator->Constant(factor); } else if(accept(Token::LeftBracket)) { expression(); expect(Token::RightBracket); } else { variableValue(); } if(doNegate) generator->Negate(); } /* ::= | identifier | identifier.property | rtmacro | */ void Parser::variableValue() { std::string variable = token.Source; if(accept(Token::Identifier)) { if(look(Token::LeftBracket)) { back(); functionCall(); } else { if(accept(Token::DotSymbol)) { std::string property = token.Source; expect(Token::Identifier); generator->LoadVariable(variable); generator->LoadProperty(property); } else { generator->LoadVariable(variable); } } } else if(accept(Token::RTMacro)) { generator->RTConstant(variable); } else { particleAction(); } } bool Parser::accept(int symbol) { if(symbol == token.Symbol) { lastToken = token; if(previousTokens.size()) { token = previousTokens.top(); previousTokens.pop(); } else token = scanner->NextToken(); //std::cout << "Symbol " << Token::SymbolNames[symbol] << " " << lastToken.Source << std::endl; return true; } //std::cout << "Bad Symbol " << Token::SymbolNames[symbol] << " " << token.Source << " (" << token.GetName() << ")" << std::endl; return false; } bool Parser::look(int symbol) { if(symbol == token.Symbol) return true; return false; } void Parser::back() { previousTokens.push(token); 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) { if(!accept(symbol)) throw ParserExpectException(token, symbol); } } }