diff options
| author | Simon Robertshaw <simon@hardwired.org.uk> | 2012-09-21 14:05:50 (GMT) |
|---|---|---|
| committer | Simon Robertshaw <simon@hardwired.org.uk> | 2012-09-21 14:05:50 (GMT) |
| commit | 939a04d3c77bf9aa8d54e912f5e12817de51756c (patch) | |
| tree | 750119bf74b8fbcb409eaf02d03877c00056613d /src | |
| parent | 6e44ebc358d1206c147f514225373da07b43c015 (diff) | |
| download | powder-939a04d3c77bf9aa8d54e912f5e12817de51756c.zip powder-939a04d3c77bf9aa8d54e912f5e12817de51756c.tar.gz | |
Testing new vm/language WIP
Diffstat (limited to 'src')
| -rw-r--r-- | src/cat/LuaScriptInterface.cpp | 38 | ||||
| -rw-r--r-- | src/cat/LuaScriptInterface.h | 4 | ||||
| -rw-r--r-- | src/dialogues/LegacyDialogues.h | 11 | ||||
| -rw-r--r-- | src/interface/LuaProgressBar.h | 30 | ||||
| -rw-r--r-- | src/pim/Generator.cpp | 326 | ||||
| -rw-r--r-- | src/pim/Generator.h | 164 | ||||
| -rw-r--r-- | src/pim/Machine.cpp | 271 | ||||
| -rw-r--r-- | src/pim/Machine.h | 88 | ||||
| -rw-r--r-- | src/pim/Opcodes.h | 12 | ||||
| -rw-r--r-- | src/pim/Opcodes.inl | 26 | ||||
| -rw-r--r-- | src/pim/Parser.cpp | 646 | ||||
| -rw-r--r-- | src/pim/Parser.h | 78 | ||||
| -rw-r--r-- | src/pim/Scanner.cpp | 178 | ||||
| -rw-r--r-- | src/pim/Scanner.h | 22 | ||||
| -rw-r--r-- | src/pim/Token.cpp | 47 | ||||
| -rw-r--r-- | src/pim/Token.h | 79 | ||||
| -rw-r--r-- | src/tests/PowderInteractionMachine.cpp | 21 |
17 files changed, 2031 insertions, 10 deletions
diff --git a/src/cat/LuaScriptInterface.cpp b/src/cat/LuaScriptInterface.cpp index ff282ff..19c9ac8 100644 --- a/src/cat/LuaScriptInterface.cpp +++ b/src/cat/LuaScriptInterface.cpp @@ -20,11 +20,14 @@ #include "dialogues/TextPrompt.h" #include "dialogues/ConfirmPrompt.h" #include "simulation/Simulation.h" -#include "virtualmachine/VirtualMachine.h" #include "game/GameModel.h" #include "LuaScriptHelper.h" #include "client/HTTP.h" +//#include "virtualmachine/VirtualMachine.h" +#include "pim/Parser.h" +#include "pim/Machine.h" + #include "LuaBit.h" #include "LuaWindow.h" @@ -665,17 +668,24 @@ void LuaScriptInterface::initElementsAPI() } } -vm::VirtualMachine * LuaScriptInterface::updateVirtualMachines[PT_NUM]; +pim::VirtualMachine * LuaScriptInterface::updateVirtualMachines[PT_NUM]; int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS) { - vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type]; + pim::VirtualMachine * machine = updateVirtualMachines[parts[i].type]; + + machine->CSPush(i); + machine->CSPush(x); + machine->CSPush(y); + machine->Call(0); + + + /*vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type]; vm::word w; int argAddr = 0, argCount = 5; vMachine->sim = sim; - /* Set up call. */ vMachine->OpPUSH(w); //Pointless null in stack w.int4 = (argCount + 2) * sizeof(vm::word); vMachine->OpENTER(w); @@ -696,7 +706,7 @@ int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS) w.int4 = (argCount + 2) * sizeof(vm::word); vMachine->OpLEAVE(w); vMachine->OpPOP(w); //Pop pointless null - vMachine->End(); + vMachine->End();*/ return 0; } @@ -1017,7 +1027,7 @@ int LuaScriptInterface::elements_property(lua_State * l) } else if(lua_type(l, 3) == LUA_TLIGHTUSERDATA) { - updateVirtualMachines[id] = (vm::VirtualMachine*)lua_touserdata(l, 3); + updateVirtualMachines[id] = (pim::VirtualMachine*)lua_touserdata(l, 3); luacon_sim->elements[id].Update = &updateVM; } else if(lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3)) @@ -1142,7 +1152,7 @@ void LuaScriptInterface::initVirtualMachineAPI() int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l) { - luaL_checktype(l, 1, LUA_TSTRING); + /*luaL_checktype(l, 1, LUA_TSTRING); vm::VirtualMachine * newVM = new vm::VirtualMachine(1); try @@ -1156,7 +1166,19 @@ int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l) { return luaL_error(l, "Unable to load program"); } - lua_pushlightuserdata(l, newVM); + lua_pushlightuserdata(l, newVM);*/ + std::string programSource(lua_tostring(l, 1)); + std::stringstream input(programSource); + + + pim::compiler::Parser * parser = new pim::compiler::Parser(input); + + std::vector<unsigned char> programData = parser->Compile(); + + pim::VirtualMachine * machine = new pim::VirtualMachine(luacon_sim); + machine->LoadProgram(programData); + + lua_pushlightuserdata(l, machine); return 1; } diff --git a/src/cat/LuaScriptInterface.h b/src/cat/LuaScriptInterface.h index c40728c..9758157 100644 --- a/src/cat/LuaScriptInterface.h +++ b/src/cat/LuaScriptInterface.h @@ -23,7 +23,7 @@ namespace ui class Window; } -namespace vm +namespace pim { class VirtualMachine; } @@ -65,7 +65,7 @@ class LuaScriptInterface: public CommandInterface { static int renderer_colourMode(lua_State * l); //Elements - static vm::VirtualMachine * updateVirtualMachines[PT_NUM]; + static pim::VirtualMachine * updateVirtualMachines[PT_NUM]; static int updateVM(UPDATE_FUNC_ARGS); // void initElementsAPI(); diff --git a/src/dialogues/LegacyDialogues.h b/src/dialogues/LegacyDialogues.h new file mode 100644 index 0000000..7f6097d --- /dev/null +++ b/src/dialogues/LegacyDialogues.h @@ -0,0 +1,11 @@ +#pragma once + +//Legacy blocking prompts +//This are not implemented here, but rather in the engine bootstrapper +bool ConfirmUI(std::string title, std::string message, std::string confirmText) {} + +void ErrorUI(std::string title, std::string message) {} + +void InformationUI(std::string title, std::string message) {} + +std::string MessagePromptUI(std::string title, std::string message, std::string text, std::string placeholder) {}
\ No newline at end of file diff --git a/src/interface/LuaProgressBar.h b/src/interface/LuaProgressBar.h new file mode 100644 index 0000000..dc2ef4e --- /dev/null +++ b/src/interface/LuaProgressBar.h @@ -0,0 +1,30 @@ +#pragma once + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" +} + +#include "LuaLuna.h" +#include "LuaComponent.h" + +namespace ui +{ + class ProgressBar; +} + +class LuaScriptInterface; + +class LuaProgressBar: public LuaComponent +{ + ui::ProgressBar * progressBar; + int onValueChangedFunction; + int value(lua_State * l); +public: + static const char className[]; + static Luna<LuaProgressBar>::RegType methods[]; + + LuaProgressBar(lua_State * l); + ~LuaProgressBar(); +};
\ No newline at end of file diff --git a/src/pim/Generator.cpp b/src/pim/Generator.cpp new file mode 100644 index 0000000..b2ea84c --- /dev/null +++ b/src/pim/Generator.cpp @@ -0,0 +1,326 @@ +//Code generator for bytecode +#include <sstream> +#include "Format.h" +#include "Generator.h" +#include "Opcodes.h" +namespace pim +{ + namespace compiler + { + Generator::Generator() : + output(std::cout), + labelCounter(0), + programCounter(0) + { + + } + + void Generator::defineLabel(std::string label) + { + Label newLabel; + newLabel.Name = label; + newLabel.Position = programCounter;//program.size(); + labelPositions.push_back(newLabel); + } + + void Generator::writeOpcode(int opcode) + { + programCounter++; + program.push_back(opcode); + } + + void Generator::writeConstant(std::string constant) + { + writeConstant(format::StringToNumber<int>(constant)); + } + + void Generator::writeConstant(int constant) + { + program.push_back(constant & 0xFF); + program.push_back((constant>>8) & 0xFF); + program.push_back((constant>>16) & 0xFF); + program.push_back((constant>>24) & 0xFF); + } + + void Generator::writeConstantPlaceholder(std::string label) + { + placeholders.push_back(Placeholder(program.size(), label)); + program.push_back(0); + program.push_back(0); + program.push_back(0); + program.push_back(0); + } + + void Generator::writeConstantPlaceholder(int * value) + { + valuePlaceholders.push_back(ValuePlaceholder(program.size(), value)); + program.push_back(0); + program.push_back(0); + program.push_back(0); + program.push_back(0); + } + + std::vector<unsigned char> Generator::Finish() + { + for(std::vector<Placeholder>::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter) + { + bool found = false; + Placeholder cPosition = *iter; + for(std::vector<Label>::iterator iter2 = labelPositions.begin(), end2 = labelPositions.end(); iter2 != end2; ++iter2) + { + Label cLabel = *iter2; + if(cPosition.second == cLabel.Name) + { + std::cout << "Setting placeholder at " << cPosition.first << " with " << cLabel.Position << " for" << cPosition.second << std::endl; + found = true; + program[cPosition.first] = cLabel.Position & 0xFF; + program[cPosition.first+1] = (cLabel.Position >> 8) & 0xFF; + program[cPosition.first+2] = (cLabel.Position >> 16) & 0xFF; + program[cPosition.first+3] = (cLabel.Position >> 24) & 0xFF; + break; + } + } + if(!found) + throw SymbolNotFoundException(cPosition.second); + } + + for(std::vector<ValuePlaceholder>::iterator iter = valuePlaceholders.begin(), end = valuePlaceholders.end(); iter != end; ++iter) + { + ValuePlaceholder cPosition = *iter; + int value = *cPosition.second; + + std::cout << "Setting value placeholder at " << cPosition.first << " with " << value << std::endl; + + + program[cPosition.first] = value & 0xFF; + program[cPosition.first+1] = (value >> 8) & 0xFF; + program[cPosition.first+2] = (value >> 16) & 0xFF; + program[cPosition.first+3] = (value >> 24) & 0xFF; + } + + return program; + } + + std::string Generator::UniqueLabel(std::string prefix) + { + std::stringstream label; + label << prefix; + label << "_"; + label << labelCounter; + label << "_"; + return label.str(); + } + + void Generator::PushScope(std::string label) + { + scopes.push(currentScope); + Scope * prevScope = currentScope; + currentScope = new Scope(); + defineLabel(label); + } + + void Generator::PushLocalScope(std::string label) + { + scopes.push(currentScope); + Scope * prevScope = currentScope; + currentScope = new Scope(); + currentScope->Definitions.insert(currentScope->Definitions.begin(), prevScope->Definitions.begin(), prevScope->Definitions.end()); + currentScope->FrameSize = prevScope->FrameSize; + defineLabel(label); + } + + void Generator::PopScope() + { + + writeOpcode(Opcode::Return); + writeConstant(currentScope->LocalFrameSize); + currentScope = scopes.top(); + scopes.pop(); + } + + void Generator::ScopeLabel(std::string label) + { + //defineLabelwriteOpcode("." << label); + defineLabel(label); + } + + void Generator::LocalEnter() + { + writeOpcode(Opcode::LocalEnter); + writeConstantPlaceholder(&(currentScope->LocalFrameSize)); + } + + void Generator::ScopeVariableType(int type) + { + variableType = type; + } + + void Generator::ScopeVariable(std::string label) + { + currentScope->Definitions.push_back(Definition(label, variableType, currentScope->FrameSize)); + currentScope->FrameSize += 4; + currentScope->LocalFrameSize += 4; + } + + void Generator::PushVariableAddress(std::string label) + { + //writeOpcode("address"); << " " << currentScope->GetDefinition(label).StackPosition + } + + void Generator::LoadVariable(std::string label) + { + writeOpcode(Opcode::Load); + writeConstant(currentScope->GetDefinition(label).StackPosition); + } + + void Generator::StoreVariable(std::string label) + { + writeOpcode(Opcode::Store); + writeConstant(currentScope->GetDefinition(label).StackPosition); + } + + void Generator::Constant(std::string constant) + { + writeOpcode(Opcode::Constant); + writeConstant(constant); + } + + void Generator::Increment(std::string constant) + { + writeOpcode(Opcode::Increment); + writeConstant(constant); + } + + void Generator::Discard() + { + writeOpcode(Opcode::Discard); + } + + void Generator::Duplicate() + { + writeOpcode(Opcode::Duplicate); + } + + void Generator::Add() + { + writeOpcode(Opcode::Add); + } + + void Generator::Subtract() + { + writeOpcode(Opcode::Subtract); + } + + void Generator::Multiply() + { + writeOpcode(Opcode::Multiply); + } + + void Generator::Divide() + { + writeOpcode(Opcode::Divide); + } + + void Generator::Modulus() + { + writeOpcode(Opcode::Modulus); + } + + void Generator::Negate() + { + writeOpcode(Opcode::Negate); + } + + void Generator::CreateParticle() + { + writeOpcode(Opcode::Create); + + } + + void Generator::TransformParticle() + { + writeOpcode(Opcode::Transform); + } + + void Generator::GetParticle() + { + writeOpcode(Opcode::Get); + } + + void Generator::GetPosition() + { + writeOpcode(Opcode::Position); + } + + void Generator::KillParticle() + { + writeOpcode(Opcode::Kill); + } + + + void Generator::IntegerToDecimal() + { + + } + + void Generator::DecimalToInteger() + { + + } + + + void Generator::JumpEqual(std::string label) + { + writeOpcode(Opcode::JumpEqual); + writeConstantPlaceholder(label); + } + + void Generator::JumpNotEqual(std::string label) + { + writeOpcode(Opcode::JumpNotEqual); + writeConstantPlaceholder(label); + } + + void Generator::JumpGreater(std::string label) + { + writeOpcode(Opcode::JumpGreater); + writeConstantPlaceholder(label); + } + + void Generator::JumpGreaterEqual(std::string label) + { + writeOpcode(Opcode::JumpGreaterEqual); + writeConstantPlaceholder(label); + } + + void Generator::JumpLess(std::string label) + { + writeOpcode(Opcode::JumpLess); + writeConstantPlaceholder(label); + } + + void Generator::JumpLessEqual(std::string label) + { + writeOpcode(Opcode::JumpLessEqual); + writeConstantPlaceholder(label); + } + + void Generator::Jump(std::string label) + { + writeOpcode(Opcode::Jump); + writeConstantPlaceholder(label); + } + + + void Generator::Call(int arguments, std::string label) + { + + } + + void Generator::Return() + { + + } + + } +}
\ No newline at end of file diff --git a/src/pim/Generator.h b/src/pim/Generator.h new file mode 100644 index 0000000..0121c13 --- /dev/null +++ b/src/pim/Generator.h @@ -0,0 +1,164 @@ +#pragma once + +#include <cstring> +#include <vector> +#include <stack> +#include <iostream> +#include "Token.h" +namespace pim +{ + namespace compiler + { + class VariableNotFoundException: public std::exception + { + char * error; + public: + VariableNotFoundException(std::string variable) { + error = strdup(std::string("Could not find the variable \""+variable+"\" in the current scope").c_str()); + } + const char * what() const throw() + { + return error; + } + ~VariableNotFoundException() throw() {}; + }; + + class SymbolNotFoundException: public std::exception + { + char * error; + public: + SymbolNotFoundException(std::string variable) { + error = strdup(std::string("Could not find the symbol \""+variable+"\".").c_str()); + } + const char * what() const throw() + { + return error; + } + ~SymbolNotFoundException() throw() {}; + }; + class Definition + { + public: + enum { Integer = Token::IntegerSymbol, Decimal = Token::DecimalSymbol }; + std::string Name; + int Type; + int StackPosition; + Definition(std::string name, int type, int position) : + Type(type), + Name(name), + StackPosition(position) + { + + } + }; + + struct Label + { + std::string Name; + int Position; + }; + + class Scope + { + public: + std::vector<Definition> Definitions; + std::vector<Label> Labels; + int FrameSize; + int LocalFrameSize; + Scope(): + FrameSize(0), + LocalFrameSize(0) + { + + } + Definition GetDefinition(std::string name) + { + for(std::vector<Definition>::iterator iter = Definitions.begin(), end = Definitions.end(); iter != end; ++iter) + { + if((*iter).Name == name) + return *iter; + } + throw VariableNotFoundException(name); + } + }; + + class Generator + { + int variableType; + std::stack<Scope*> scopes; + Scope * currentScope; + std::ostream & output; + int labelCounter; + int programCounter; + + typedef std::pair<int, std::string> Placeholder; + std::vector<Placeholder> placeholders; + + typedef std::pair<int, int*> ValuePlaceholder; + std::vector<ValuePlaceholder> valuePlaceholders; + + std::vector<Label> labelPositions; + + std::vector<unsigned char> program; + + void defineLabel(std::string label); + void writeOpcode(int opcode); + void writeConstant(std::string constant); + void writeConstant(int constant); + void writeConstantPlaceholder(std::string label); + void writeConstantPlaceholder(int * value); + + public: + Generator(); + + std::vector<unsigned char> Finish(); + + std::string UniqueLabel(std::string prefix); + + void PushScope(std::string label); + void PushLocalScope(std::string label); + void LocalEnter(); + void PopScope(); + + void ScopeLabel(std::string label); + void ScopeVariableType(int type); + void ScopeVariable(std::string label); + + void PushVariableAddress(std::string label); +// void Store(); + void LoadVariable(std::string label); + void StoreVariable(std::string label); + + void Duplicate(); + void Discard(); + void Constant(std::string constant); + void Increment(std::string constant); + void Add(); + void Subtract(); + void Multiply(); + void Divide(); + void Modulus(); + void Negate(); + + void TransformParticle(); + void CreateParticle(); + void GetParticle(); + void GetPosition(); + void KillParticle(); + + void IntegerToDecimal(); + void DecimalToInteger(); + + void JumpEqual(std::string label); + void JumpNotEqual(std::string label); + void JumpGreater(std::string label); + void JumpGreaterEqual(std::string label); + void JumpLess(std::string label); + void JumpLessEqual(std::string label); + void Jump(std::string label); + + void Call(int arguments, std::string label); + void Return(); + }; + } +}
\ No newline at end of file diff --git a/src/pim/Machine.cpp b/src/pim/Machine.cpp new file mode 100644 index 0000000..4c07514 --- /dev/null +++ b/src/pim/Machine.cpp @@ -0,0 +1,271 @@ +//Virtual machine + +#include <iostream> +#include "Machine.h" +#include "Opcodes.h" +#include "simulation/Simulation.h" +namespace pim +{ + /*unsigned char * rom; + int romSize; + int romMask; + + unsigned char * ram; + int ramSize; + int ramMask; + + int programStack; + int callStack;*/ + + VirtualMachine::VirtualMachine(Simulation * simulation) : + rom(NULL), + ram(NULL), + sim(simulation) + { + + } + + void VirtualMachine::LoadProgram(std::vector<unsigned char> programData) + { + int lastBit = 0; + + romSize = programData.size(); + + for (lastBit = 0; romSize > (1 << lastBit); lastBit++ ) { } + romSize = 1 << lastBit; + romMask = romSize - 1; + + rom = new Instruction[romSize]; + + int programPosition = 0; + int pc = 0; + while(programPosition < programData.size()) + { + int argSize = 0; + Instruction instruction; + instruction.Opcode = programData[programPosition++]; + if(argSize = OpcodeArgSize(instruction.Opcode)) + { + if(argSize == 4) + { + int tempInt = 0; + tempInt |= programData[programPosition]; + tempInt |= programData[programPosition+1] << 8; + tempInt |= programData[programPosition+2] << 16; + tempInt |= programData[programPosition+3] << 24; + + + std::cout << "Got integer " << tempInt << std::endl; + //std::cout << "Got byte " << (int)(programData[programPosition]) << std::endl; + //std::cout << "Got byte " << (int)(programData[programPosition+1]) << std::endl; + //std::cout << "Got byte " << (int)(programData[programPosition+2]) << std::endl; + //std::cout << "Got byte " << (int)(programData[programPosition+3]) << std::endl; + + //*(int*)&rom[programPosition] = tempInt; + instruction.Parameter.Integer = tempInt; + + programPosition += 4; + } + } + else + { + instruction.Parameter.Integer = 0; + } + rom[pc++] = instruction; + } + romSize = pc; + //std::copy(programData.begin(), programData.end(), rom); + + + ramSize = 1024; + ramMask = ramSize - 1; + + ram = new unsigned char[ramSize]; + programStack = ramSize-1; + callStack = ramSize-260; + + framePointer = callStack; + callStack += WORDSIZE; //Since there's nothing on the stack, it shouldn't point to the item on the bottom + } + + int VirtualMachine::OpcodeArgSize(int opcode) + { + switch(opcode) + { + case Opcode::Load: + case Opcode::Store: + case Opcode::Constant: + case Opcode::Increment: + case Opcode::JumpEqual: + case Opcode::JumpNotEqual: + case Opcode::JumpGreater: + case Opcode::JumpGreaterEqual: + case Opcode::JumpLess: + case Opcode::JumpLessEqual: + case Opcode::Jump: + case Opcode::Return: + case Opcode::LocalEnter: + return 4; + case Opcode::Discard: + case Opcode::Duplicate: + case Opcode::Add: + case Opcode::Subtract: + case Opcode::Multiply: + case Opcode::Divide: + case Opcode::Modulus: + case Opcode::Negate: + case Opcode::Create: + case Opcode::Transform: + case Opcode::Get: + case Opcode::Position: + case Opcode::Kill: + return 0; + } + } + + void VirtualMachine::Run() + { + //std::cout << "CS: " << callStack << " PS: " << programStack << std::endl; + //std::string names[] = { "Load", "Store", "Constant", "Increment", "Discard", "Duplicate", "Add", "Subtract", "Multiply", "Divide", "Modulus", "Negate", "Create", "Transform", "Get", "Position", "Kill", "JumpEqual", "JumpNotEqual", "JumpGreater", "JumpGreaterEqual", "JumpLess", "JumpLessEqual", "Jump", "Return", "LocalEnter"}; + + Word temp1; + Word temp2; + Word temp3; + Word temp4; + int temp; + while(programCounter < romSize) + { + Word argument = rom[programCounter].Parameter; + //std::cerr << programCounter << "\t" << names[rom[programCounter].Opcode] << "\t" << argument.Integer << std::endl;//"\t"; + switch(rom[programCounter].Opcode) + { + case Opcode::Load: + PSPush(CSA(argument.Integer)); + break; + case Opcode::Store: + CSA(argument.Integer) = PSPop(); + break; + case Opcode::Constant: + PSPush(argument); + break; + case Opcode::Increment: + PS().Integer += argument.Integer; + break; + case Opcode::Discard: + programStack += WORDSIZE; + break; + case Opcode::Duplicate: + PSPush(PS()); + break; + case Opcode::Add: + PSPush(PSPop().Integer + PSPop().Integer); + break; + case Opcode::Subtract: + temp1 = PSPop(); + PSPush(PSPop().Integer - temp1.Integer); + break; + case Opcode::Multiply: + PSPush(PSPop().Integer * PSPop().Integer); + break; + case Opcode::Divide: + temp1 = PSPop(); + PSPush(PSPop().Integer / temp1.Integer); + break; + case Opcode::Modulus: + temp1 = PSPop(); + PSPush(PSPop().Integer % temp1.Integer); + break; + case Opcode::Negate: + PS().Integer = -PS().Integer; + break; + case Opcode::Create: + temp1 = PSPop(); + temp2 = PSPop(); + temp3 = PSPop(); + PSPush(sim->create_part(PSPop().Integer, temp3.Integer, temp2.Integer, temp1.Integer)); + break; + case Opcode::Transform: + PSPop(); + PSPop(); + PSPush((Word)-1); + break; + case Opcode::Get: + temp1 = PSPop(); + temp2 = PSPop(); + if(temp1.Integer < 0 || temp1.Integer >= YRES || temp2.Integer < 0 || temp2.Integer >= XRES || !(temp = sim->pmap[temp1.Integer][temp2.Integer])) + { + PSPush(-1); + break; + } + PSPush(temp>>8); + break; + case Opcode::Position: + temp1 = PSPop(); + if(temp1.Integer < 0 || temp1.Integer >= NPART || !sim->parts[temp1.Integer].type) + { + PSPush(-1); + PSPush(-1); + break; + } + PSPush((int)sim->parts[temp1.Integer].x); + PSPush((int)sim->parts[temp1.Integer].y); + break; + case Opcode::Kill: + sim->kill_part(PSPop().Integer); + PSPush((Word)0); + break; + case Opcode::JumpEqual: + if(PSPop().Integer == PSPop().Integer) + programCounter = argument.Integer-1; + break; + case Opcode::JumpNotEqual: + if(PSPop().Integer != PSPop().Integer) + programCounter = argument.Integer-1; + break; + case Opcode::JumpGreater: + temp1 = PSPop(); + if(PSPop().Integer > temp1.Integer) + programCounter = argument.Integer-1; + break; + case Opcode::JumpGreaterEqual: + temp1 = PSPop(); + if(PSPop().Integer >= temp1.Integer) + programCounter = argument.Integer-1; + break; + case Opcode::JumpLess: + temp1 = PSPop(); + if(PSPop().Integer < temp1.Integer) + programCounter = argument.Integer-1; + break; + case Opcode::JumpLessEqual: + temp1 = PSPop(); + if(PSPop().Integer <= temp1.Integer) + programCounter = argument.Integer-1; + break; + case Opcode::Jump: + programCounter = argument.Integer-1; + break; + case Opcode::Return: + callStack += argument.Integer; + break; + case Opcode::LocalEnter: + callStack -= argument.Integer; + break; + } + //std::cout << programStack << std::endl; + programCounter++; + } + //std::cout << "CS: " << callStack << " PS: " << programStack << std::endl; + } + + void VirtualMachine::Call(std::string entryPoint) + { + + } + + void VirtualMachine::Call(int entryPoint) + { + programCounter = entryPoint; + Run(); + } +}
\ No newline at end of file diff --git a/src/pim/Machine.h b/src/pim/Machine.h new file mode 100644 index 0000000..dcaef92 --- /dev/null +++ b/src/pim/Machine.h @@ -0,0 +1,88 @@ +#pragma once + +#include <vector> +#include <string> + +class Simulation; +namespace pim +{ + union Word + { + int Integer; + float Decimal; + + Word(int integer) : Integer(integer) {} + Word(float decimal) : Decimal(decimal) {} + Word() {} + }; + struct Instruction + { + int Opcode; + Word Parameter; + }; + class VirtualMachine + { + + #define WORDSIZE 4 + + //#define OPDEF(name) void op##name(int parameter); + //#include "Opcodes.inl" + //#undef OPDEF + + Simulation * sim; + + Instruction * rom; + int romSize; + int romMask; + + unsigned char * ram; + int ramSize; + int ramMask; + + #define CSA(argument) (*((Word*)&ram[framePointer-argument])) + #define CS() (*((Word*)&ram[callStack])) + #define PS() (*((Word*)&ram[programStack])) + + int programStack; //Points to the item on top of the Program Stack + int callStack; //Points to the item on top of the call stack + int framePointer; //Points to the bottom (first item) on the current frame of the call stack + + //Instruction * instructions; + + int programCounter; + + + public: + VirtualMachine(Simulation * sim); + int OpcodeArgSize(int opcode); + void LoadProgram(std::vector<unsigned char> programData); + void Run(); + void Call(std::string entryPoint); + void Call(int entryPoint); + inline void PSPush(Word word) + { + programStack -= WORDSIZE; + PS() = word; + } + + inline Word PSPop() + { + Word word = PS(); + programStack += WORDSIZE; + return word; + } + + inline void CSPush(Word word) + { + callStack -= WORDSIZE; + CS() = word; + } + + inline Word CSPop() + { + Word word = CS(); + callStack += WORDSIZE; + return word; + } + }; +}
\ No newline at end of file diff --git a/src/pim/Opcodes.h b/src/pim/Opcodes.h new file mode 100644 index 0000000..4e1a7ce --- /dev/null +++ b/src/pim/Opcodes.h @@ -0,0 +1,12 @@ +namespace pim +{ + struct Opcode + { + enum + { + #define OPDEF(name) name, + #include "Opcodes.inl" + #undef OPDEF + }; + }; +}
\ No newline at end of file diff --git a/src/pim/Opcodes.inl b/src/pim/Opcodes.inl new file mode 100644 index 0000000..3c18da5 --- /dev/null +++ b/src/pim/Opcodes.inl @@ -0,0 +1,26 @@ +OPDEF(Load) +OPDEF(Store) +OPDEF(Constant) +OPDEF(Increment) +OPDEF(Discard) +OPDEF(Duplicate) +OPDEF(Add) +OPDEF(Subtract) +OPDEF(Multiply) +OPDEF(Divide) +OPDEF(Modulus) +OPDEF(Negate) +OPDEF(Create) +OPDEF(Transform) +OPDEF(Get) +OPDEF(Position) +OPDEF(Kill) +OPDEF(JumpEqual) +OPDEF(JumpNotEqual) +OPDEF(JumpGreater) +OPDEF(JumpGreaterEqual) +OPDEF(JumpLess) +OPDEF(JumpLessEqual) +OPDEF(Jump) +OPDEF(Return) +OPDEF(LocalEnter)
\ No newline at end of file diff --git a/src/pim/Parser.cpp b/src/pim/Parser.cpp new file mode 100644 index 0000000..75af21d --- /dev/null +++ b/src/pim/Parser.cpp @@ -0,0 +1,646 @@ +//Syntax analyser +#include "Parser.h" +namespace pim +{ + namespace compiler + { + Parser::Parser(std::stringstream & source_) : + source(source_) + { + scanner = new Scanner(source); + generator = new Generator(); + + token = scanner->NextToken(); + + } + + std::vector<unsigned char> Parser::Compile() + { + program(); + return generator->Finish(); + } + + /* + <program> ::= <function list> + */ + void Parser::program() + { + functionList(); + } + + /* + <function list> ::= <function> | <function> <function list> + */ + void Parser::functionList() + { + function(); + while(look(Token::FunctionSymbol)) + function(); + } + + /* + <function> ::= function identifier ( <declaration list> ) <block> 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(); + } + + /* + <function call> ::= identifier ( <expression list> ) + */ + void Parser::functionCall() + { + std::string functionName; + + functionName = token.Source; + expect(Token::Identifier); + expect(Token::LeftBracket); + expressionList(); + expect(Token::RightBracket); + //generator->Call(functionName); + } + + /* + <block> ::= <declaration list> <statement list> + */ + void Parser::block() + { + if(look(Token::IntegerSymbol) || look(Token::DecimalSymbol) || look(Token::ParticleSymbol)) + declarationList(); + statementList(); + } + + /* + <argument list> ::= <argument> | <argument> , <argument list> + */ + void Parser::argumentList() + { + argument(); + while(accept(Token::CommaSymbol)) + argument(); + } + + /* + <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); + } + + /* + <declaration list> ::= <declaration> | <declaration> , <declaration list> + */ + void Parser::declarationList() + { + declaration(); + while(accept(Token::CommaSymbol)) + declaration(); + } + + /* + <declaration> ::= integer <identifier list> | decimal <identifier list> | particle <identifier list> + */ + 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 list> ::= identifier | identifier , <identifier list> + */ + void Parser::identifierList() + { + generator->ScopeVariable(token.Source); + expect(Token::Identifier); + while(accept(Token::CommaSymbol)) + { + generator->ScopeVariable(token.Source); + expect(Token::Identifier); + } + } + + /* + <statement list> ::= <statement> | <statement> <statement list> + */ + void Parser::statementList() + { + statement(); + while(!look(Token::EndSymbol)) + statement(); + } + + /* + <statement> ::= <neighbour statement> | <if statement> | <assignment statement> | <function call> | <particle action> | 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); + } + + /* + <particle action> ::= <kill statement> | <create statement> | <transform statement> + */ + void Parser::particleAction() + { + if(look(Token::KillSymbol)) + { + killStatement(); + } + else if(look(Token::CreateSymbol)) + { + createStatement(); + } + else if(look(Token::TransformSymbol)) + { + transformStatement(); + } + + } + + /* + <kill statement> ::= kill ( <expression> ) + */ + void Parser::killStatement() + { + expect(Token::KillSymbol); + expect(Token::LeftBracket); + expression(); + expect(Token::RightBracket); + generator->KillParticle(); + } + + /* + <create statement> ::= create ( <expression>, <expression>, <expression>, <expression> ) + */ + 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 statement> ::= transform ( <expression>, <expression> ) + */ + void Parser::transformStatement() + { + expect(Token::TransformSymbol); + expect(Token::LeftBracket); + expression(); + expect(Token::CommaSymbol); + expression(); + expect(Token::RightBracket); + generator->TransformParticle(); + } + + /* + <get statement> ::= get ( <expression>, <expression> ) + */ + void Parser::getStatement() + { + expect(Token::GetSymbol); + expect(Token::LeftBracket); + expression(); + expect(Token::CommaSymbol); + expression(); + expect(Token::RightBracket); + generator->GetParticle(); + } + + /* + <neighbour statement> ::= neighbour identifier for <expression> do <block> end | neighbour identifier for <expression>, <expression> do <block> 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 statement> ::= if <condition> then <block> end + */ + void Parser::ifStatement() + { + //generator->Begin(NonTerminal::IfStatement); + expect(Token::IfSymbol); + condition(); + expect(Token::ThenSymbol); + block(); + expect(Token::EndSymbol); + //generator->End(NonTerminal::IfStatement); + } + + /* + <condition> ::= identifier <conditional operator> identifier | identifier <conditional operator> numberConstant | numberConstant <conditional operator> identifier | numberConstant <conditional operator> numberConstant + */ + void Parser::condition() + { + //generator->Begin(NonTerminal::Condition); + if(look(Token::Identifier)) + { + conditionalOperator(); + if(!accept(Token::Identifier) && !accept(Token::IntegerConstant) && !accept(Token::DecimalConstant)) + throw ParserExpectException(token, "identifier or constant"); + } + else if(look(Token::DecimalConstant) || look(Token::IntegerConstant)) + { + conditionalOperator(); + if(!accept(Token::Identifier) && !accept(Token::IntegerConstant) && !accept(Token::DecimalConstant)) + throw ParserExpectException(token, "identifier or constant"); + } + else + { + 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); + } + + /* + <assigment statement> ::= identifier = <expression> + */ + void Parser::assigmentStatement() + { + std::string variable = token.Source; + //generator->PushVariableAddress(token.Source); + expect(Token::Identifier); + expect(Token::AssignSymbol); + expression(); + //generator->Store(); + generator->StoreVariable(variable); + } + + /* + <expression list> ::= <expression> | <expression> , <expression list> + */ + void Parser::expressionList() + { + //generator->Begin(NonTerminal::ExpressionList); + expression(); + while(accept(Token::CommaSymbol)) + expression(); + //generator->End(NonTerminal::ExpressionList); + } + + /* + <expression> ::= <term> | <expression> + <term> | <expression> - <term> + */ + 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); + } + + /* + <term> ::= <factor> | <term> * <factor> | <term> / <factor> + */ + 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); + } + + /* + <factor> ::= <variable value> | - <variable value> | numberConstant | - numberConstant | ( <expression> ) | - ( <expression> ) + */ + 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(); + /*if(!accept(Token::Identifier)) + { + if(!accept(Token::IntegerConstant)) + { + if(!accept(Token::DecimalConstant)) + { + if(!accept(Token::LeftBracket)) + { + throw ParserExpectException(token, "identifier or constant"); + } + else + { + expression(); + expect(Token::RightBracket); + } + } + else + { + if(doNegate) + { + doNegate = false; + generator->Constant("-" + factor); + } + else + generator->Constant(factor); + } + } + else + { + if(doNegate) + { + doNegate = false; + generator->Constant("-" + factor); + } + else + generator->Constant(factor); + } + } + else + { + generator->LoadVariable(factor); + } + if(doNegate) + { + generator->Negate(); + }*/ + } + + /* + <variable value> ::= <function call> | identifier | <particle action> + */ + void Parser::variableValue() + { + std::string variable = token.Source; + if(accept(Token::Identifier)) + { + if(look(Token::LeftBracket)) + { + back(); + functionCall(); + } + else + { + generator->LoadVariable(variable); + } + } + else + { + particleAction(); + } + } + + bool Parser::accept(int symbol) + { + if(symbol == token.Symbol) + { + //generator->Insert(token); + lastToken = token; + if(previousTokens.size()) + { + token = previousTokens.top(); + previousTokens.pop(); + } + else + token = scanner->NextToken(); + return true; + } + return false; + } + + + bool Parser::look(int symbol) + { + if(symbol == token.Symbol) + return true; + return false; + } + + void Parser::back() + { + previousTokens.push(token); + token = lastToken; + } + + void Parser::expect(int symbol) + { + if(!accept(symbol)) + throw ParserExpectException(token, symbol); + } + } +}
\ No newline at end of file diff --git a/src/pim/Parser.h b/src/pim/Parser.h new file mode 100644 index 0000000..c66011e --- /dev/null +++ b/src/pim/Parser.h @@ -0,0 +1,78 @@ +#pragma once + +#include <string> +#include <cstring> +#include <sstream> +#include "Scanner.h" +#include "Generator.h" +#include "Token.h" +namespace pim +{ + namespace compiler + { + class ParserExpectException: public std::exception + { + char * error; + public: + ParserExpectException(Token token, int expectingSymbol) { + error = strdup(std::string("Expecting " + Token::SymbolNames[expectingSymbol] + " got " + token.Source).c_str()); + } + ParserExpectException(Token token, std::string expectingString) { + error = strdup(std::string("Expecting " + expectingString + " got " + token.Source).c_str()); + } + const char * what() const throw() + { + return error; + } + ~ParserExpectException() throw() {}; + }; + class Parser + { + std::stringstream & source; + Generator * generator; + Scanner * scanner; + Token token; + Token lastToken; + std::string breakLabel; + std::string continueLabel; + std::stack<Token> previousTokens; + + void program(); + void functionList(); + void function(); + void functionCall(); + void block(); + void argumentList(); + void argument(); + void declarationList(); + void declaration(); + void identifierList(); + void statementList(); + void statement(); + void neighbourStatement(); + void ifStatement(); + void condition(); + void conditionalOperator(); + void assigmentStatement(); + void particleAction(); + void killStatement(); + void getStatement(); + void createStatement(); + void transformStatement(); + void expressionList(); + void expression(); + void term(); + void factor(); + void variableValue(); + + bool accept(int symbol); + bool look(int symbol); + void back(); + void expect(int symbol); + public: + Parser(std::stringstream & source_); + + std::vector<unsigned char> Compile(); + }; + } +}
\ No newline at end of file diff --git a/src/pim/Scanner.cpp b/src/pim/Scanner.cpp new file mode 100644 index 0000000..32e64d0 --- /dev/null +++ b/src/pim/Scanner.cpp @@ -0,0 +1,178 @@ +//Lexical analyser +#include <algorithm> +#include "Scanner.h" + +namespace pim +{ + namespace compiler + { + Scanner::Scanner(std::stringstream & source_) : + source(source_) + { + nextCharacter(); + } + + Token Scanner::NextToken() + { + //Read whitespace, newlines and comments + while( + cChar == ' ' || cChar == '\t' || + cChar == '\r' || cChar == '\n' || + cChar == '/') + { + if(cChar == '/') + { + nextCharacter(); + if(cChar == '/') + { + while(cChar != '\n' && cChar != '\r') + nextCharacter(); + } + else + return Token(Token::DivideSymbol, "/", cLine); + } + + if(cChar == '\r') + { + nextCharacter(); + if(cChar == '\n') + cLine++; + else + continue; + } + else if(cChar == '\n') + cLine++; + + nextCharacter(); + } + + if(std::isalpha(cChar)) //Read alphanumeric symbols + { + cToken.clear(); + while(std::isalpha(cChar) || std::isdigit(cChar)) + { + cToken.push_back(cChar); + nextCharacter(); + } + + std::transform(cToken.begin(), cToken.end(), cToken.begin(), ::tolower); + + for(int i = 0; i < Token::SymbolNumber; i++) + if(Token::SymbolNames[i] == cToken) + return Token(i, cToken, cLine); + return Token(Token::Identifier, cToken, cLine); + } + else if(std::isdigit(cChar)) //Read numeric constants + { + bool decimal = false; + cToken.clear(); + while(std::isdigit(cChar)) + { + cToken.push_back(cChar); + nextCharacter(); + } + if(cChar == '.') + { + decimal = true; + cToken.push_back(cChar); + nextCharacter(); + while(std::isdigit(cChar)) + { + cToken.push_back(cChar); + nextCharacter(); + } + } + if(decimal) + return Token(Token::DecimalConstant, cToken, cLine); + return Token(Token::IntegerConstant, cToken, cLine); + } + else if(cChar == '=') + { + nextCharacter(); + if(cChar == '=') + { + nextCharacter(); + return Token(Token::EqualSymbol, "==", cLine); + } + return Token(Token::AssignSymbol, "=", cLine); + } + else if(cChar == '!') + { + nextCharacter(); + if(cChar == '=') + return Token(Token::NotEqualSymbol, "==", cLine); + } + else if(cChar == '(') + { + nextCharacter(); + return Token(Token::LeftBracket, "(", cLine); + } + else if(cChar == ')') + { + nextCharacter(); + return Token(Token::RightBracket, ")", cLine); + } + else if(cChar == '/') + { + nextCharacter(); + return Token(Token::DivideSymbol, "/", cLine); + } + else if(cChar == '*') + { + nextCharacter(); + return Token(Token::MultiplySymbol, "*", cLine); + } + else if(cChar == '+') + { + nextCharacter(); + return Token(Token::PlusSymbol, "+", cLine); + } + else if(cChar == '-') + { + nextCharacter(); + return Token(Token::MinusSymbol, "-", cLine); + } + else if(cChar == '%') + { + nextCharacter(); + return Token(Token::ModuloSymbol, "%", cLine); + } + else if(cChar == '<') + { + nextCharacter(); + if(cChar == '=') + { + return Token(Token::LessEqualSymbol, "<=", cLine); + } + return Token(Token::LessSymbol, "<", cLine); + } + else if(cChar == '>') + { + nextCharacter(); + if(cChar == '=') + { + return Token(Token::GreaterEqualSymbol, ">=", cLine); + } + return Token(Token::GreaterSymbol, ">", cLine); + } + else if(cChar == ',') + { + nextCharacter(); + return Token(Token::CommaSymbol, ",", cLine); + } + else + { + nextCharacter(); + return Token(Token::InvalidSymbol, std::string(1, cChar), cLine); + } + } + + void Scanner::nextCharacter() + { + if(source.good()) + cChar = source.get(); + else + cChar = 0; + } + } +}
\ No newline at end of file diff --git a/src/pim/Scanner.h b/src/pim/Scanner.h new file mode 100644 index 0000000..2e8143c --- /dev/null +++ b/src/pim/Scanner.h @@ -0,0 +1,22 @@ +#pragma once + +#include <string> +#include <sstream> +#include "Token.h" +namespace pim +{ + namespace compiler + { + class Scanner + { + char cChar; + int cLine; + std::string cToken; + std::stringstream & source; + void nextCharacter(); + public: + Scanner(std::stringstream & source_); + Token NextToken(); + }; + } +}
\ No newline at end of file diff --git a/src/pim/Token.cpp b/src/pim/Token.cpp new file mode 100644 index 0000000..2db451e --- /dev/null +++ b/src/pim/Token.cpp @@ -0,0 +1,47 @@ +#include "Token.h" + +namespace pim +{ + namespace compiler + { + std::string Token::SymbolNames[] = { + "=", + "function", + "(", + ")", + "/", + "*", + "+", + "-", + "%", + "INTEGER", + "DECIMAL", + "PARTICLE", + "integer", + "decimal", + "particle", + "is", + "<", + "<=", + ">", + ">=", + "==", + "!=", + "neighbour", + "do", + "of", + "break", + "continue", + "if", + "then", + "end", + "kill", + "create", + "transform", + "get", + "IDENTIFIER", + ",", + "INVALID SYMBOL" + }; + } +}
\ No newline at end of file diff --git a/src/pim/Token.h b/src/pim/Token.h new file mode 100644 index 0000000..6a80f49 --- /dev/null +++ b/src/pim/Token.h @@ -0,0 +1,79 @@ +#pragma once + +#include <string> +namespace pim +{ + namespace compiler + { + class Token + { + public: + static std::string SymbolNames[]; + + enum + { + AssignSymbol = 0, + FunctionSymbol, + + LeftBracket, + RightBracket, + DivideSymbol, + MultiplySymbol, + PlusSymbol, + MinusSymbol, + ModuloSymbol, + + IntegerConstant, + DecimalConstant, + ParticleConstant, + + IntegerSymbol, + DecimalSymbol, + ParticleSymbol, + + IsSymbol, + LessSymbol, + LessEqualSymbol, + GreaterSymbol, + GreaterEqualSymbol, + NotEqualSymbol, + EqualSymbol, + + NeighbourSymbol, + DoSymbol, + OfSymbol, + BreakSymbol, + ContinueSymbol, + IfSymbol, + ThenSymbol, + EndSymbol, + + KillSymbol, + CreateSymbol, + TransformSymbol, + GetSymbol, + + Identifier, + + CommaSymbol, + + InvalidSymbol, + + SymbolNumber + }; + int Symbol; + int LineNumber; + std::string Source; + + Token(int symbol = InvalidSymbol, std::string source = "HERP DERP", int lineNumber = 0) : + Symbol(symbol), + Source(source), + LineNumber(lineNumber) {} + + std::string GetName() + { + return SymbolNames[Symbol]; + } + }; + } +}
\ No newline at end of file diff --git a/src/tests/PowderInteractionMachine.cpp b/src/tests/PowderInteractionMachine.cpp new file mode 100644 index 0000000..c2b37a2 --- /dev/null +++ b/src/tests/PowderInteractionMachine.cpp @@ -0,0 +1,21 @@ +#ifdef TEST + +#include <iostream> +#include <fstream> +#include <sstream> +#include "pim/Parser.h" + +int main(int argc, char * argv[]) +{ + std::ifstream file("test.p"); + + std::stringstream buffer; + + buffer << file.rdbuf(); + file.close(); + + pim::compiler::Parser * parser = new pim::compiler::Parser(buffer); + + parser->Compile(); +} +#endif
\ No newline at end of file |
