summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-11-26 23:26:12 +0100
committertomsmeding <tom.smeding@gmail.com>2016-11-26 23:26:12 +0100
commit8116da5f88b18591decd8fa53d7be8b354ec1fa9 (patch)
treefb17ba771b5f474cc5e5596cc51561639a0cdbae
parentddfec38593bf2aac46685a14f87dce02baeff7a1 (diff)
Strings
-rw-r--r--ast.cpp64
1 files changed, 61 insertions, 3 deletions
diff --git a/ast.cpp b/ast.cpp
index 68d4d4b..f1cbcc0 100644
--- a/ast.cpp
+++ b/ast.cpp
@@ -113,12 +113,40 @@ public:
nextat++;
}
return true;
+ } else if(source[index]=='"'){
+ for(nextat=index+1;nextat<size;nextat++){
+ if(source[nextat]=='\\'){
+ nextat++;
+ if(nextat==size){
+ throw ParseError("Unexpected end of file after '\\' in string");
+ }
+ } else if(source[nextat]=='"'){
+ break;
+ }
+ }
+ if(nextat==size){
+ throw ParseError("Unexpected end of file in string");
+ }
+ nextat++;
+ return true;
} else {
throw ParseError(string("Invalid token starting with '")+source[index]+"'");
}
}
};
+static char parseHex(char c){
+ if(c>='0'&&c<='9'){
+ return c-'0';
+ } else if(c>='a'&&c<='f'){
+ return c-'a'+10;
+ } else if(c>='A'&&c<='F'){
+ return c-'A'+10;
+ } else {
+ return -1;
+ }
+}
+
AST& AST::parse(AST::Tokeniser &tokeniser){
if(tokeniser.eof()){
throw ParseError("No tokens to parse");
@@ -128,15 +156,12 @@ AST& AST::parse(AST::Tokeniser &tokeniser){
throw logic_error("Unexpected empty token from tokeniser");
}
if(isdigit(token[0])||(token.size()>1&&token[0]=='-'&&isdigit(token[1]))){
- // cerr<<"AST::parse: type = number"<<endl;
type=Type::number;
numval=strtol(token.data(),NULL,10);
} else if(iswordchar(token[0])){
- // cerr<<"AST::parse: type = name"<<endl;
type=Type::name;
nameval=token;
} else if(token=="("){
- // cerr<<"AST::parse: type = tuple"<<endl;
type=Type::tuple;
while(true){
if(!tokeniser.advance()){
@@ -165,6 +190,39 @@ AST& AST::parse(AST::Tokeniser &tokeniser){
throw ParseError("Body expected after argument of '\\'");
}
lambdaval.body=AST().parse(tokeniser);
+ } else if(token[0]=='"'){
+ if(token.back()!='"'){
+ throw logic_error("No string terminator at end of string token from tokeniser");
+ }
+ type=Type::string;
+ for(i64 i=1;i<(i64)token.size()-1;i++){
+ if(token[i]=='\\'){
+ switch(token[i+1]){
+ case 't': strval+='\t'; break;
+ case 'n': strval+='\n'; break;
+ case 'r': strval+='\r'; break;
+ case 'x':{
+ if(i+3>=(i64)token.size()-1){
+ throw ParseError("Not enough characters after hexadecimal"
+ " escape sequence");
+ }
+ char hex1=parseHex(token[i+2]),
+ hex2=parseHex(token[i+3]);
+ if(hex1==-1||hex2==-1){
+ throw ParseError("Invalid characters in hexadecimal"
+ " escape sequence");
+ }
+ strval+=(hex1<<4)|hex2;
+ i+=2;
+ break;
+ }
+ default: strval+=token[i+1]; break;
+ }
+ i++;
+ } else {
+ strval+=token[i];
+ }
+ }
} else if(token==")"){
throw ParseError("Unexpected token '"+token+"'");
} else {