summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2016-07-30 18:26:24 +0200
committerTom Smeding <tom.smeding@gmail.com>2016-07-30 18:26:24 +0200
commit8b49e73d6089e4a9195ce01c3f4c95e85336397d (patch)
tree814dff997ccba703a5108e50520fdef52661d3a5
parent94fd6ce2902ebb8b933763bda8c3280914d6ae20 (diff)
Second
-rw-r--r--.gitignore3
-rw-r--r--LANGUAGE.txt4
-rw-r--r--Makefile16
-rw-r--r--iets.txt2
-rw-r--r--main.c81
-rw-r--r--parser.c4
-rw-r--r--parser.h79
7 files changed, 189 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..01254ad
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+main
+*.o
+*.dSYM
diff --git a/LANGUAGE.txt b/LANGUAGE.txt
index 0f55887..9d72f08 100644
--- a/LANGUAGE.txt
+++ b/LANGUAGE.txt
@@ -16,3 +16,7 @@ The usual infix expression rules apply, with the following precedence table:
^^ 11 Left
|| 12 Left (short-circuiting)
= 13 Right (also += -= *= /= %= **= &= ^= |=)
+
+
+break and continue get parsed to calls to the __break() and __continue()
+compiler intrinsics (thus become AST_CALL nodes).
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..55b2ef8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+CC = gcc
+CFLAGS = -Wall -Wextra -std=c11 -O2 -fwrapv
+BIN = main
+
+.PHONY: all clean remake
+
+all: $(BIN)
+
+clean:
+ rm -f $(BIN) *.o *.dSYM
+
+remake: clean all
+
+
+$(BIN): $(wildcard *.c *.h)
+ $(CC) $(CFLAGS) -o $@ $(filter %.c,$^)
diff --git a/iets.txt b/iets.txt
new file mode 100644
index 0000000..471fb1b
--- /dev/null
+++ b/iets.txt
@@ -0,0 +1,2 @@
+a = 1;
+b = 2;
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..7def025
--- /dev/null
+++ b/main.c
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+
+#include "parser.h"
+
+char* readfile(const char *fname){
+ FILE *f=fopen(fname,"rb");
+ if(!f)return NULL;
+ if(fseek(f,0,SEEK_END)==-1){fclose(f); return NULL;}
+ long flen=ftell(f);
+ if(flen==-1){fclose(f); return NULL;}
+ rewind(f);
+
+ char *buf=malloc(flen+1);
+ if(!buf){fclose(f); return NULL;}
+ fread(buf,1,flen,f);
+ if(ferror(f)){fclose(f); free(buf); return NULL;}
+ if(memchr(buf,'\0',flen)!=NULL){
+ fprintf(stderr,"Invalid null char in file '%s'\n",fname);
+ exit(1);
+ }
+ buf[flen]='\0';
+ fclose(f);
+ return buf;
+}
+
+char *readstdin(void){
+ int bufsz=1024,cursor=0;
+ char *buf=malloc(bufsz);
+ if(!buf)return NULL;
+ while(true){
+ if(cursor==bufsz-1){
+ bufsz*=2;
+ char *newbuf=realloc(buf,bufsz);
+ if(!newbuf){
+ free(buf);
+ return NULL;
+ }
+ buf=newbuf;
+ }
+ int nread=fread(buf,1,bufsz-cursor-1,stdin);
+ if(nread>0&&memchr(buf,'\0',nread)!=NULL){
+ fprintf(stderr,"Invalid null char on stdin file\n");
+ exit(1);
+ }
+ cursor+=nread;
+ if(nread<bufsz-cursor-1){
+ if(feof(stdin))break;
+ if(ferror(stdin)){
+ free(buf);
+ return NULL;
+ }
+ }
+ }
+ buf[cursor]='\0';
+ return buf;
+}
+
+
+void usage(const char *argv0){
+ fprintf(stderr,"Usage: %s <source file>\n",argv0);
+}
+
+int main(int argc,char **argv){
+ if(argc!=2){
+ usage(argv[0]);
+ return 1;
+ }
+ char *source;
+ if(strcmp(argv[1],"-")==0)source=readstdin();
+ else source=readfile(argv[1]);
+ if(!source){
+ fprintf(stderr,"Error reading %s\n",strcmp(argv[1],"-")==0?"from stdin":argv[1]);
+ return 1;
+ }
+
+ ;
+}
diff --git a/parser.c b/parser.c
new file mode 100644
index 0000000..c1bedeb
--- /dev/null
+++ b/parser.c
@@ -0,0 +1,4 @@
+#include <stdio.h>
+#include <string.h>
+
+
diff --git a/parser.h b/parser.h
new file mode 100644
index 0000000..d5f4978
--- /dev/null
+++ b/parser.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <stdint.h>
+
+typedef enum ASTtype{
+ AST_BLOCK,
+ AST_OP,
+ AST_NUM,
+ AST_STR,
+ AST_VAR,
+ AST_CALL,
+ AST_IF,
+ AST_WHILE,
+} ASTtype;
+
+
+typedef struct AST AST;
+typedef struct ASTblock ASTblock;
+typedef struct ASTop ASTop;
+typedef struct ASTnum ASTnum;
+typedef struct ASTstr ASTstr;
+typedef struct ASTvar ASTvar;
+typedef struct ASTcall ASTcall;
+typedef struct ASTif ASTif;
+typedef struct ASTwhile ASTwhile;
+
+
+struct ASTblock{
+ int len;
+ AST *exprs;
+};
+struct ASTop{
+ const char *op; // Constant string, does not need to be freed
+ AST *left,*right;
+};
+struct ASTnum{
+ bool isint;
+ union {
+ int64_t i;
+ double d;
+ };
+};
+struct ASTstr{
+ int len; // Excludes terminating null char
+ char *str; // May contain null chars before terminating null char
+};
+struct ASTvar{
+ char *name;
+};
+struct ASTcall{
+ char *func;
+ int nargs;
+ AST *args; // Array<AST>
+};
+struct ASTif{
+ AST *cond;
+ AST *thenb,*elseb;
+};
+struct ASTwhile{
+ AST *cond;
+ AST *body;
+};
+
+typedef struct AST{
+ ASTtype type;
+ union {
+ ASTblock b;
+ ASTop o;
+ ASTnum n;
+ ASTstr s;
+ ASTvar v;
+ ASTcall c;
+ ASTif i;
+ ASTwhile w;
+ };
+} AST;
+
+
+AST* parse(const char *source);