summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-02-03 23:09:04 +0100
committertomsmeding <tom.smeding@gmail.com>2017-02-03 23:09:04 +0100
commitb3ad2e88c9462391fb6d323f6f7737ed5ceedb46 (patch)
tree925a32579ef9368c378368f8d9bf3842ec6ca65c
parent7c785439fca59b3801ca2a1118ae25a98d03750d (diff)
Progress
-rw-r--r--Makefile2
-rw-r--r--parser.cpp105
2 files changed, 95 insertions, 12 deletions
diff --git a/Makefile b/Makefile
index 4e9ed24..5bfd9c0 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ remake: clean
$(TARGET): $(patsubst %.cpp,%.o,$(wildcard *.cpp))
- $(CXX) -o $@ $<
+ $(CXX) -o $@ $^
%.o: %.cpp $(wildcard *.h)
$(CXX) $(CXXFLAGS) -c -o $@ $<
diff --git a/parser.cpp b/parser.cpp
index 73ae368..56fb035 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -1,4 +1,5 @@
#include <stdexcept>
+#include <stack>
#include <cstring>
#include <cctype>
#include <cassert>
@@ -52,6 +53,7 @@ public:
number,
string,
symbol,
+ terminator,
};
Type type;
@@ -70,6 +72,14 @@ class Tokeniser{
i64 lnum,linex;
Token::Type ttype;
+ /*struct State{
+ i64 idx,nextidx;
+ i64 lnum,lineidx;
+ Token::Type ttype;
+ };
+
+ stack<State> statestack;*/
+
bool eof(i64 at){
return at>=(i64)source.size();
}
@@ -88,11 +98,39 @@ public:
idx(0),nextidx(-1),
lnum(1),linex(1){}
+ Tokeniser& operator=(const Tokeniser &other){
+ if(&source!=&other.source||&filename!=&other.filename){
+ throw runtime_error("Tokeniser::operator= on incompatible Tokeniser");
+ }
+ idx=other.idx; nextidx=other.nextidx;
+ lnum=other.lnum; linex=other.linex;
+ ttype=other.ttype;
+ return *this;
+ }
+
+ /*void save(){
+ statestack.push({idx,nextidx,lnum,lineidx,ttype});
+ }
+
+ void restore(){
+ if(statestack.size()==0)throw runtime_error("Tokeniser::restore() on empty stack");
+ const State &st=statestack.top();
+ idx=st.idx; nextidx=st.nextidx;
+ lnum=st.lnum; linex=st.linex;
+ ttype=st.ttype;
+ statestack.pop();
+ }
+
+ void discardstate(){
+ if(statestack.size()==0)throw runtime_error("Tokeniser::discardstate() on empty stack");
+ statestack.pop();
+ }*/
+
bool eof() const {
return idx>=(i64)source.size();
}
- Token get() const {
+ Token get(){
return Token(ttype,get_(),Site(filename,lnum,linex));
}
@@ -100,6 +138,7 @@ public:
bool advance(){
if(eof())return false;
+ // Let nextidx catch up with idx
while(idx<nextidx){
if(source[idx]=='\n'){
lnum++;
@@ -110,25 +149,26 @@ public:
idx++;
}
+ // Skip any whitespace and/or comments, emitting a terminator on a newline
while(true){
i64 origidx=idx;
while(!eof()&&isspace(source[idx])){
if(source[idx]=='\n'){
- lnum++;
- linex=1;
- } else {
- linex++;
+ nextidx=idx+1;
+ ttype=Token::Type::terminator;
+ return true;
}
+ linex++;
idx++;
}
if(eof())return false;
if(source[idx]=='#'){
while(!eof()&&source[idx]!='\n')idx++;
- idx++;
- lnum++;
- linex=1;
if(eof())return false;
+ nextidx=idx+1;
+ ttype=Token::Type::terminator;
+ return true;
}
if(idx==origidx)break;
@@ -136,6 +176,13 @@ public:
nextidx=idx;
+ // Terminator semicolon
+ if(source[nextidx]==';'){
+ ttype=Token::Type::terminator;
+ nextidx++;
+ return true;
+ }
+
// Word
if(isinitwordchar(source[nextidx])){
ttype=Token::Type::word;
@@ -200,12 +247,48 @@ public:
}
};
+
+static Expression parseExpression(Tokeniser &tokeniser){
+ ;
+}
+
+static Statement parseStatement(Tokeniser &tokeniser){
+ Token tok=tokeniser.get();
+ switch(tok.type){
+ case Token::Type::word:{
+ Tokeniser copyiser(tokeniser);
+ copyiser.advance();
+ Token tok2=copyiser.get();
+ if(tok2.type==Token::Type::symbol&&tok2.str==":="){
+ tokeniser=copyiser;
+ tokeniser.advance();
+ return Statement(Statement::Type::create,tok.str,parseExpression(tokeniser));
+ } else if(tok2.type==Token::Type::symbol&&tok2.str=="="){
+ tokeniser=copyiser;
+ tokeniser.advance();
+ return Statement(Statement::Type::assign,tok.str,parseExpression(tokeniser));
+ } else {
+ return Statement(Statement::Type::expression,parseExpression(tokeniser));
+ }
+ }
+
+ case Token::Type::number:
+ case Token::Type::string:
+ case Token::Type::symbol:
+ return Statement(Statement::Type::expression,parseExpression(tokeniser));
+
+ case Token::Type::terminator:
+ throw runtime_error("Unexpected terminator in parseStatement()");
+ }
+}
+
StatementList parse(const string &source,const string &filename){
Tokeniser tokeniser(source,filename);
+ if(!tokeniser.advance())return {};
StatementList stl;
- while(tokeniser.advance()){
- Token tok=tokeniser.get();
-
+ while(!tokeniser.eof()){
+ if(tokeniser.get().type==Token::Type::terminator)continue;
+ stl.push_back(parseStatement(tokeniser));
}
return stl;
}