summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-09-01 20:42:28 +0200
committertomsmeding <tom.smeding@gmail.com>2016-09-01 20:42:28 +0200
commitabeb43aa08efba521e3cb94cffd30f9c7dd48250 (patch)
treee7dc95ac8b781857f3370da990d0355345b92312
parentf0b90a58bf587501a1b5814929b3df33bb8e5a94 (diff)
Parse break, continue, return as builtins
-rw-r--r--LANGUAGE.txt4
-rw-r--r--parser.c57
2 files changed, 50 insertions, 11 deletions
diff --git a/LANGUAGE.txt b/LANGUAGE.txt
index 48dcb95..049dbda 100644
--- a/LANGUAGE.txt
+++ b/LANGUAGE.txt
@@ -20,5 +20,5 @@ The usual infix expression rules apply, with the following precedence table:
** 13 Right
-break and continue get parsed to calls to the __break() and __continue()
-compiler intrinsics (thus become AST_CALL nodes).
+break and continue get parsed to calls to the __builtin_break() and
+__builtin_continue() compiler intrinsics (thus become AST_CALL nodes).
diff --git a/parser.c b/parser.c
index 6309e65..1042edb 100644
--- a/parser.c
+++ b/parser.c
@@ -203,6 +203,12 @@ static void printtoken(FILE *stream,Token tok,const char *msg){
#endif
+static const char *builtin_keywords[]={
+ "break", "continue", "return"
+};
+static const int nbuiltin_keywords=sizeof(builtin_keywords)/sizeof(builtin_keywords[0]);
+
+
static AST* parseexpr(const char *source,int *reslen,int minprec,int maxprec);
static AST* parseterm(const char *source,int *reslen){
@@ -380,10 +386,25 @@ static AST* parseterm(const char *source,int *reslen){
node=malloc(sizeof(AST));
if(!node)outofmem();
node->type=AST_CALL;
- node->c.func=malloc(tok.len+1);
- if(!node->c.func)outofmem();
- memcpy(node->c.func,tok.str,tok.len);
- node->c.func[tok.len]='\0';
+ int i;
+ for(i=0;i<nbuiltin_keywords;i++){
+ if(tok.len==(int)strlen(builtin_keywords[i])&&memcmp(builtin_keywords[i],tok.str,tok.len)==0){
+ break;
+ }
+ }
+ if(i<nbuiltin_keywords){
+ int prefixlen=strlen("__builtin_");
+ node->c.func=malloc(tok.len+prefixlen+1);
+ if(!node->c.func)outofmem();
+ memcpy(node->c.func,"__builtin_",prefixlen);
+ memcpy(node->c.func+prefixlen,tok.str,tok.len);
+ node->c.func[prefixlen+tok.len]='\0';
+ } else {
+ node->c.func=malloc(tok.len+1);
+ if(!node->c.func)outofmem();
+ memcpy(node->c.func,tok.str,tok.len);
+ node->c.func[tok.len]='\0';
+ }
node->c.nargs=nargs;
node->c.args=args;
#undef FREEARGSRETNULL
@@ -391,11 +412,29 @@ static AST* parseterm(const char *source,int *reslen){
source=tempsource;
node=malloc(sizeof(AST));
if(!node)outofmem();
- node->type=AST_VAR;
- node->v.name=malloc(tok.len+1);
- if(!node->v.name)outofmem();
- memcpy(node->v.name,tok.str,tok.len);
- node->v.name[tok.len]='\0';
+ int i;
+ for(i=0;i<nbuiltin_keywords;i++){
+ if(tok.len==(int)strlen(builtin_keywords[i])&&memcmp(builtin_keywords[i],tok.str,tok.len)==0){
+ break;
+ }
+ }
+ if(i<nbuiltin_keywords){
+ node->type=AST_CALL;
+ int prefixlen=strlen("__builtin_");
+ node->c.func=malloc(tok.len+prefixlen+1);
+ if(!node->c.func)outofmem();
+ memcpy(node->c.func,"__builtin_",prefixlen);
+ memcpy(node->c.func+prefixlen,tok.str,tok.len);
+ node->c.func[prefixlen+tok.len]='\0';
+ node->c.nargs=0;
+ node->c.args=malloc(1);
+ } else {
+ node->type=AST_VAR;
+ node->v.name=malloc(tok.len+1);
+ if(!node->v.name)outofmem();
+ memcpy(node->v.name,tok.str,tok.len);
+ node->v.name[tok.len]='\0';
+ }
}
break;
}