diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | LANGUAGE.txt | 4 | ||||
-rw-r--r-- | Makefile | 16 | ||||
-rw-r--r-- | iets.txt | 2 | ||||
-rw-r--r-- | main.c | 81 | ||||
-rw-r--r-- | parser.c | 4 | ||||
-rw-r--r-- | parser.h | 79 |
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; @@ -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); |