aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSemperVinco <w.deweijer@hotmail.com>2017-03-03 13:05:40 +0100
committerSemperVinco <w.deweijer@hotmail.com>2017-03-03 13:05:40 +0100
commit9f38c82b01c44410bb7778d2607f38daec9dfb35 (patch)
treeb005dd24d6264983672a8c7b07af27b508d04494
parent1a6842e9a3a0c4da7357f9efa002e5041f27f2eb (diff)
Split parsing code into its own file and cleanup includes
-rw-r--r--main.cpp201
-rw-r--r--parse.cpp202
-rw-r--r--parse.h11
-rw-r--r--world.cpp1
-rw-r--r--world.h3
5 files changed, 218 insertions, 200 deletions
diff --git a/main.cpp b/main.cpp
index a6963f1..7786149 100644
--- a/main.cpp
+++ b/main.cpp
@@ -2,15 +2,15 @@
#include <fstream>
#include <vector>
#include <string>
-#include <unordered_map>
#include <unistd.h>
#include <cstdlib>
-#include <tuple>
-#include <cctype>
#include <cassert>
#include <sys/time.h>
+#include <cstring>
+
#include "params.h"
#include "world.h"
+#include "parse.h"
#ifndef _WIN32
# include <signal.h>
@@ -19,201 +19,6 @@
using namespace std;
-void trim(string &str){
- while(str.size()>0&&isspace(str[0]))str.erase(0,1);
- while(str.size()>0&&isspace(str.back()))str.erase(str.size()-1,1);
-}
-
-void squashSpaces(string &str){
- bool sp=false;
- for(size_t i=0;i<str.size();i++){
- if(isspace(str[i])){
- if(sp){
- str.erase(i,1);
- i--;
- } else {
- str[i]=' ';
- sp=true;
- }
- } else {
- sp=false;
- }
- }
-}
-
-vector<string> splittrim(const string &str,char sep){
- if(str.size()==0)return {};
- vector<string> res;
- size_t cursor=0;
- while(true){
- size_t idx=str.find(sep,cursor);
- if(idx==string::npos){
- string s=str.substr(cursor);
- trim(s);
- res.push_back(s);
- return res;
- }
- string s=str.substr(cursor,idx-cursor);
- trim(s);
- res.push_back(s);
- cursor=idx+1;
- }
-}
-
-void lowercase(string &str){
- for(size_t i=0;i<str.size();i++){
- str[i]=tolower(str[i]);
- }
-}
-
-Argument parseArgument(const string &str,const unordered_map<string,Location> &labels,Location ip){
- if(str[0]=='#'||str[0]=='%'){
- bool remote=str[0]=='%';
- if(isdigit(str[1])){
- int num=atoi(str.data()+1);
- assert(num>=1&&num<=20);
- return {arg_t::var,remote,num,{}};
- } else {
- return {arg_t::name,remote,0,str.substr(1)};
- }
- } else if(str[0]=='@'){
- if(labels.find(str.substr(1))==labels.end()){
- return {arg_t::undeflabel,false,0,str.substr(1)};
- }
- Location ref=labels.find(str.substr(1))->second;
- assert(ref.bank==ip.bank);
- return {arg_t::number,false,ref.pos-ip.pos,{}};
- } else if(str[0]=='$'){
- return {arg_t::constant,false,0,str.substr(1)};
- } else if(isdigit(str[0])){
- return {arg_t::number,false,atoi(str.data()),{}};
- } else {
- assert(false);
- }
-}
-
-Team assemble(const string &source){
- Team team;
- unordered_map<string,Location> labels;
-
- for(string line : splittrim(source,'\n')){
- if(line.size()==0)continue;
-
- string word1=line.substr(0,line.find(' '));
- string word2r=line.find(' ')==string::npos?"":line.substr(line.find(' ')+1);
- if(word1=="published"){
- string word2=word2r.substr(0,word2r.find(' '));
- string word3r=word2r.find(' ')==string::npos?"":word2r.substr(word2r.find(' ')+1);
- if(word2=="name"){
- team.name=word3r;
- }
- } else if(word1=="bank"){
- team.banks.emplace_back();
- } else if(word1[0]=='@'){
- assert(line.find(' ')==string::npos);
- assert(labels.find(word1.substr(1))==labels.end());
- labels[word1.substr(1)]={(int)team.banks.size()-1,(int)team.banks.back().size()};
- } else {
- assert(team.banks.size()>0);
- vector<string> args=splittrim(word2r,',');
- vector<Argument> pargs;
- for(const string &s : args){
- pargs.push_back(parseArgument(s,labels,
- {(int)team.banks.size()-1,(int)team.banks.back().size()}));
- }
- if(word1=="jump"||word1=="turn"||word1=="scan")assert(pargs.size()==1);
- else if(word1=="die"||word1=="move")assert(pargs.size()==0);
- else if(word1=="create")assert(pargs.size()==3);
- else assert(pargs.size()==2);
-
- Script &s=team.banks.back();
- if(word1=="set")s.push_back(Instruction::make(ins_t::set,{pargs[0],pargs[1]}));
- else if(word1=="add")s.push_back(Instruction::make(ins_t::add,{pargs[0],pargs[1]}));
- else if(word1=="sub")s.push_back(Instruction::make(ins_t::sub,{pargs[0],pargs[1]}));
- else if(word1=="comp")s.push_back(Instruction::make(ins_t::comp,{pargs[0],pargs[1]}));
- else if(word1=="trans")s.push_back(Instruction::make(ins_t::trans,{pargs[0],pargs[1]}));
- else if(word1=="jump")s.push_back(Instruction::make(ins_t::jump,{pargs[0]}));
- else if(word1=="bjump")s.push_back(Instruction::make(ins_t::bjump,{pargs[0],pargs[1]}));
- else if(word1=="die")s.push_back(Instruction::make(ins_t::die,{}));
- else if(word1=="move")s.push_back(Instruction::make(ins_t::move,{}));
- else if(word1=="turn")s.push_back(Instruction::make(ins_t::turn,{pargs[0]}));
- else if(word1=="scan")s.push_back(Instruction::make(ins_t::scan,{pargs[0]}));
- else if(word1=="create")s.push_back(Instruction::make(ins_t::create,{pargs[0],pargs[1],pargs[2]}));
- else assert(false);
- }
- }
-
- int bank=0;
- for(Script &script : team.banks){
- int pos=0;
- for(Instruction &ins : script){
- for(Argument &arg : ins.args){
- if(arg.type==arg_t::undeflabel){
- assert(labels.find(arg.name)!=labels.end());
- assert(labels[arg.name].bank==bank);
- arg.type=arg_t::number;
- arg.num=labels[arg.name].pos-pos;
- }
- }
- pos++;
- }
- bank++;
- }
-
- return team;
-}
-
-string preprocess(istream &file){
- unordered_map<string,string> defines;
-
- string result;
-
- string line;
- while(getline(file,line)){
- if(line.find(';')!=string::npos){
- line.erase(line.find(';'));
- }
- trim(line);
- if(line.size()==0)continue;
- squashSpaces(line);
- lowercase(line);
-
- string word1=line.substr(0,line.find(' '));
- if(word1=="define"){
- string word2r=line.find(' ')==string::npos?"":line.substr(line.find(' ')+1);
- string word2=word2r.substr(0,word2r.find(' '));
- string word3r=word2r.find(' ')==string::npos?"":word2r.substr(word2r.find(' ')+1);
- assert(defines.find(word2.substr(1))==defines.end());
- assert(word3r[0]=='{');
- string value=word3r.substr(1);
- assert(word3r.find('}')==string::npos||word3r.find('}')==word3r.size()-1);
- if(word3r.back()!='}'){
- while(true){
- char c=file.get();
- if(c=='}')break;
- value+=c;
- }
- assert(file.get()=='\n');
- } else {
- value.erase(value.size()-1);
- }
- defines[word2.substr(1)]=value;
- } else {
- while(line.find('&')!=string::npos){
- size_t start=line.find('&')+1;
- size_t end=line.find_first_not_of("abcdefghijklmnopqrstuvwxyz0123456789._",start);
- if(end==string::npos)end=line.size();
- assert(defines.find(line.substr(start,end-start))!=defines.end());
- line=line.substr(0,start-1)+defines.find(line.substr(start,end-start))->second+line.substr(end);
- }
- result+=line+'\n';
- }
- }
-
- return result;
-}
-
-
static ScreenBuffer *sb;
#ifndef _WIN32
diff --git a/parse.cpp b/parse.cpp
new file mode 100644
index 0000000..a0267cc
--- /dev/null
+++ b/parse.cpp
@@ -0,0 +1,202 @@
+#include <fstream>
+#include <vector>
+#include <string>
+#include <unordered_map>
+#include <cctype>
+#include <cassert>
+
+#include "parse.h"
+
+void trim(string &str){
+ while(str.size()>0&&isspace(str[0]))str.erase(0,1);
+ while(str.size()>0&&isspace(str.back()))str.erase(str.size()-1,1);
+}
+
+void squashSpaces(string &str){
+ bool sp=false;
+ for(size_t i=0;i<str.size();i++){
+ if(isspace(str[i])){
+ if(sp){
+ str.erase(i,1);
+ i--;
+ } else {
+ str[i]=' ';
+ sp=true;
+ }
+ } else {
+ sp=false;
+ }
+ }
+}
+
+vector<string> splittrim(const string &str,char sep){
+ if(str.size()==0)return {};
+ vector<string> res;
+ size_t cursor=0;
+ while(true){
+ size_t idx=str.find(sep,cursor);
+ if(idx==string::npos){
+ string s=str.substr(cursor);
+ trim(s);
+ res.push_back(s);
+ return res;
+ }
+ string s=str.substr(cursor,idx-cursor);
+ trim(s);
+ res.push_back(s);
+ cursor=idx+1;
+ }
+}
+
+void lowercase(string &str){
+ for(size_t i=0;i<str.size();i++){
+ str[i]=tolower(str[i]);
+ }
+}
+
+Argument parseArgument(const string &str,const unordered_map<string,Location> &labels,Location ip){
+ if(str[0]=='#'||str[0]=='%'){
+ bool remote=str[0]=='%';
+ if(isdigit(str[1])){
+ int num=atoi(str.data()+1);
+ assert(num>=1&&num<=20);
+ return {arg_t::var,remote,num,{}};
+ } else {
+ return {arg_t::name,remote,0,str.substr(1)};
+ }
+ } else if(str[0]=='@'){
+ if(labels.find(str.substr(1))==labels.end()){
+ return {arg_t::undeflabel,false,0,str.substr(1)};
+ }
+ Location ref=labels.find(str.substr(1))->second;
+ assert(ref.bank==ip.bank);
+ return {arg_t::number,false,ref.pos-ip.pos,{}};
+ } else if(str[0]=='$'){
+ return {arg_t::constant,false,0,str.substr(1)};
+ } else if(isdigit(str[0])){
+ return {arg_t::number,false,atoi(str.data()),{}};
+ } else {
+ assert(false);
+ }
+}
+
+Team assemble(const string &source){
+ Team team;
+ unordered_map<string,Location> labels;
+
+ for(string line : splittrim(source,'\n')){
+ if(line.size()==0)continue;
+
+ string word1=line.substr(0,line.find(' '));
+ string word2r=line.find(' ')==string::npos?"":line.substr(line.find(' ')+1);
+ if(word1=="published"){
+ string word2=word2r.substr(0,word2r.find(' '));
+ string word3r=word2r.find(' ')==string::npos?"":word2r.substr(word2r.find(' ')+1);
+ if(word2=="name"){
+ team.name=word3r;
+ }
+ } else if(word1=="bank"){
+ team.banks.emplace_back();
+ } else if(word1[0]=='@'){
+ assert(line.find(' ')==string::npos);
+ assert(labels.find(word1.substr(1))==labels.end());
+ labels[word1.substr(1)]={(int)team.banks.size()-1,(int)team.banks.back().size()};
+ } else {
+ assert(team.banks.size()>0);
+ vector<string> args=splittrim(word2r,',');
+ vector<Argument> pargs;
+ for(const string &s : args){
+ pargs.push_back(parseArgument(s,labels,
+ {(int)team.banks.size()-1,(int)team.banks.back().size()}));
+ }
+ if(word1=="jump"||word1=="turn"||word1=="scan")assert(pargs.size()==1);
+ else if(word1=="die"||word1=="move")assert(pargs.size()==0);
+ else if(word1=="create")assert(pargs.size()==3);
+ else assert(pargs.size()==2);
+
+ Script &s=team.banks.back();
+ if(word1=="set")s.push_back(Instruction::make(ins_t::set,{pargs[0],pargs[1]}));
+ else if(word1=="add")s.push_back(Instruction::make(ins_t::add,{pargs[0],pargs[1]}));
+ else if(word1=="sub")s.push_back(Instruction::make(ins_t::sub,{pargs[0],pargs[1]}));
+ else if(word1=="comp")s.push_back(Instruction::make(ins_t::comp,{pargs[0],pargs[1]}));
+ else if(word1=="trans")s.push_back(Instruction::make(ins_t::trans,{pargs[0],pargs[1]}));
+ else if(word1=="jump")s.push_back(Instruction::make(ins_t::jump,{pargs[0]}));
+ else if(word1=="bjump")s.push_back(Instruction::make(ins_t::bjump,{pargs[0],pargs[1]}));
+ else if(word1=="die")s.push_back(Instruction::make(ins_t::die,{}));
+ else if(word1=="move")s.push_back(Instruction::make(ins_t::move,{}));
+ else if(word1=="turn")s.push_back(Instruction::make(ins_t::turn,{pargs[0]}));
+ else if(word1=="scan")s.push_back(Instruction::make(ins_t::scan,{pargs[0]}));
+ else if(word1=="create")s.push_back(Instruction::make(ins_t::create,{pargs[0],pargs[1],pargs[2]}));
+ else assert(false);
+ }
+ }
+
+ int bank=0;
+ for(Script &script : team.banks){
+ int pos=0;
+ for(Instruction &ins : script){
+ for(Argument &arg : ins.args){
+ if(arg.type==arg_t::undeflabel){
+ assert(labels.find(arg.name)!=labels.end());
+ assert(labels[arg.name].bank==bank);
+ arg.type=arg_t::number;
+ arg.num=labels[arg.name].pos-pos;
+ }
+ }
+ pos++;
+ }
+ bank++;
+ }
+
+ return team;
+}
+
+string preprocess(istream &file){
+ unordered_map<string,string> defines;
+
+ string result;
+
+ string line;
+ while(getline(file,line)){
+ if(line.find(';')!=string::npos){
+ line.erase(line.find(';'));
+ }
+ trim(line);
+ if(line.size()==0)continue;
+ squashSpaces(line);
+ lowercase(line);
+
+ string word1=line.substr(0,line.find(' '));
+ if(word1=="define"){
+ string word2r=line.find(' ')==string::npos?"":line.substr(line.find(' ')+1);
+ string word2=word2r.substr(0,word2r.find(' '));
+ string word3r=word2r.find(' ')==string::npos?"":word2r.substr(word2r.find(' ')+1);
+ assert(defines.find(word2.substr(1))==defines.end());
+ assert(word3r[0]=='{');
+ string value=word3r.substr(1);
+ assert(word3r.find('}')==string::npos||word3r.find('}')==word3r.size()-1);
+ if(word3r.back()!='}'){
+ while(true){
+ char c=file.get();
+ if(c=='}')break;
+ value+=c;
+ }
+ assert(file.get()=='\n');
+ } else {
+ value.erase(value.size()-1);
+ }
+ defines[word2.substr(1)]=value;
+ } else {
+ while(line.find('&')!=string::npos){
+ size_t start=line.find('&')+1;
+ size_t end=line.find_first_not_of("abcdefghijklmnopqrstuvwxyz0123456789._",start);
+ if(end==string::npos)end=line.size();
+ assert(defines.find(line.substr(start,end-start))!=defines.end());
+ line=line.substr(0,start-1)+defines.find(line.substr(start,end-start))->second+line.substr(end);
+ }
+ result+=line+'\n';
+ }
+ }
+
+ return result;
+} \ No newline at end of file
diff --git a/parse.h b/parse.h
new file mode 100644
index 0000000..7af8b2a
--- /dev/null
+++ b/parse.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <string>
+
+#include "world.h"
+
+using namespace std;
+
+
+Team assemble(const string &source);
+string preprocess(istream &file); \ No newline at end of file
diff --git a/world.cpp b/world.cpp
index b38979a..bc08f9d 100644
--- a/world.cpp
+++ b/world.cpp
@@ -1,6 +1,7 @@
#include <cstdlib>
#include <cassert>
#include <cstring>
+
#include "world.h"
using namespace std;
diff --git a/world.h b/world.h
index 2532ef5..9d89c98 100644
--- a/world.h
+++ b/world.h
@@ -2,10 +2,9 @@
#include <iostream>
#include <string>
-#include <cstring>
#include <array>
#include <vector>
-#include <cstdint>
+
#include "params.h"
#include "screenbuffer.h"