From 48a95ec3c9a4a8601f97c8ac1adbd7d94ba15465 Mon Sep 17 00:00:00 2001
From: Dale Weiler <killfieldengine@gmail.com>
Date: Mon, 9 Apr 2012 06:42:06 -0400
Subject: [PATCH] initial commit

---
 Makefile |  12 ++
 README   |  41 +++++++
 error.c  |  87 ++++++++++++++
 gmqcc    | Bin 0 -> 16675 bytes
 gmqcc.h  | 174 ++++++++++++++++++++++++++++
 lex.c    | 345 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 main.c   |  37 ++++++
 parse.c  |  42 +++++++
 8 files changed, 738 insertions(+)
 create mode 100644 Makefile
 create mode 100644 README
 create mode 100644 error.c
 create mode 100755 gmqcc
 create mode 100644 gmqcc.h
 create mode 100644 lex.c
 create mode 100644 main.c
 create mode 100644 parse.c

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ae46f26
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+CC     = gcc
+CFLAGS = -O3 -Wall
+OBJ    = main.o lex.o error.o parse.o
+
+%.o: %.c
+	$(CC) -c -o $@ $< $(CFLAGS)
+
+gmqcc: $(OBJ)
+	$(CC) -o $@ $^ $(CFLAGS)
+	
+clean:
+	rm -f *.o dpqcc
diff --git a/README b/README
new file mode 100644
index 0000000..d069def
--- /dev/null
+++ b/README
@@ -0,0 +1,41 @@
+This is my work in progress C compiler.  There are very few _good_ qc
+compilers out there on the internet that can be used in the opensource
+community.  There are a lot of mediocre compilers, but no one wants those.
+This is the solution for that, for once a proper quake c compiler that is
+capable of doing proper optimization.  The design so far of this compiler
+is basic, because it doesn't actually compile code yet.
+
+gmqcc.h
+	This is the common header with all definitions, structures, and
+	constants for everything.
+
+error.c
+	This is the error subsystem, this handles the output of good detailed
+	error messages (not currently, but will), with colors and such.
+	
+lex.c
+	This is the lexer, a very small basic step-seek lexer that can be easily
+	changed to add new tokens, very retargetable.
+	
+main.c
+	This is the core compiler entry, handles switches (will) to toggle on
+	and off certian compiler features.
+	
+parse.c
+	This is the parser which goes over all tokens and generates a parse tree
+	(not currently, but will) and check for syntax correctness.
+	
+README
+	This is the file you're currently reading
+	
+Makefile
+	The makefile, when sources are added you should add them to the SRC=
+	line otherwise the build will not pick it up.  Trivial stuff, small
+	easy to manage makefile, no need to complicate it.
+	Some targets:
+		#make gmqcc
+			Builds gmqcc, creating a gmqcc binary file in the current
+			directory as the makefile.
+			
+		#make clean
+			Cleans the build files left behind by a previous build
diff --git a/error.c b/error.c
new file mode 100644
index 0000000..c220d72
--- /dev/null
+++ b/error.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 
+ * 	Dale Weiler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+/*
+ * Compiler error system, this handles the error printing, and managing
+ * such as after so many errors just stop the compilation, and other
+ * intereting like colors for the console.
+ */
+#ifndef WIN32
+#	define CON_BLACK   30
+#	define CON_RED     31
+#	define CON_GREEN   32
+#	define CON_BROWN   33
+#	define CON_BLUE    34
+#	define CON_MAGENTA 35
+#	define CON_CYAN    36
+#	define CON_WHITE   37
+static const int error_color[] = {
+	CON_RED,
+	CON_CYAN,
+	CON_MAGENTA
+};
+#endif
+int error_total = 0;
+int error_max   = 10;
+
+static const char *const error_list[] = {
+	"Parsing Error:",
+	"Lexing Error:",
+	"Internal Error:"
+};
+
+int error(int status, const char *msg, ...) {
+	char      bu[1024*4]; /* enough? */
+	char      fu[1024*4]; /* enough? */
+	va_list   va;
+	
+	if (error_total + 1 > error_max) {
+		fprintf(stderr, "%d errors and more following, bailing\n", error_total);
+		exit (-1);
+	}
+	error_total ++;
+/* color */
+#	ifndef WIN32
+	sprintf  (bu, "\033[0;%dm%s \033[0;%dm", error_color[status-SHRT_MAX], error_list[status-SHRT_MAX], error_color[(status-1)-SHRT_MAX]);
+#else
+	sprintf  (bu, "%s ", error_list[status-SHRT_MAX]);
+#endif
+	va_start (va, msg);
+	vsprintf (fu, msg, va);
+	va_end   (va);
+	fputs    (bu, stderr);
+	fputs    (fu, stderr);
+
+/* color */
+#	ifndef WIN32
+	fputs    ("\033[0m", stderr);
+#	endif
+	
+	fflush   (stderr);
+	
+	return status;
+}
diff --git a/gmqcc b/gmqcc
new file mode 100755
index 0000000000000000000000000000000000000000..5ee60435edddb90c524391dec00a7aae948bfebc
GIT binary patch
literal 16675
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

literal 0
HcmV?d00001

diff --git a/gmqcc.h b/gmqcc.h
new file mode 100644
index 0000000..da17ac0
--- /dev/null
+++ b/gmqcc.h
@@ -0,0 +1,174 @@
+/*
+ * Compiler error system, this handles the error printing, and managing
+ * such as after so many errors just stop the compilation, and other
+ * intereting like colors for the console.
+ */
+#ifndef DPQCC_HDR
+#define DPQCC_HDR
+#include <stdio.h>
+
+/* The types supported by the language */
+#define TYPE_VOID     0
+#define TYPE_STRING   1
+#define TYPE_FLOAT    2
+#define TYPE_VECTOR   3
+#define TYPE_ENTITY   4
+#define TYPE_FIELD    5
+#define TYPE_FUNCTION 6
+#define TYPE_POINTER  7
+
+/*
+ * there are 3 accessible memory zones -
+ * globals
+ *     array of 32bit ints/floats, mixed, LE,
+ * entities
+ *     structure is up to the engine but the fields are a linear array
+ *     of mixed ints/floats, there are globals referring to the offsets
+ *     of these in the entity struct so there are ADDRESS and STOREP and
+ *     LOAD instructions that use globals containing field offsets.
+ * strings
+ *     a static array in the progs.dat, with file parsing creating
+ *     additional constants, and some engine fields are mapped by 
+ *     address as well to unique string offsets
+ */
+ 
+/* 
+ * Instructions 
+ * These are the external instructions supported by the interperter
+ * this is what things compile to (from the C code). This is not internal
+ * instructions for support like int, and such (which are translated)
+ */
+#define INSTR_DONE      0
+// math
+#define INSTR_MUL_F     1 /* multiplication float         */
+#define INSTR_MUL_V     2 /* multiplication vector        */
+#define INSTR_MUL_FV    3 /* multiplication float->vector */
+#define INSTR_MUL_VF    4 /* multiplication vector->float */
+#define INSTR_DIV_F     5
+#define INSTR_ADD_F     6
+#define INSTR_ADD_V     7
+#define INSTR_SUB_F     8
+#define INSTR_SUB_V     9
+// compare
+#define INSTR_EQ_F      10
+#define INSTR_EQ_V      11
+#define INSTR_EQ_S      12
+#define INSTR_EQ_E      13
+#define INSTR_EQ_FNC    14
+#define INSTR_NE_F      15
+#define INSTR_NE_V      16
+#define INSTR_NE_S      17
+#define INSTR_NE_E      18
+#define INSTR_NE_FNC    19
+// multi compare
+#define INSTR_LE        20
+#define INSTR_GE        21
+#define INSTR_LT        22
+#define INSTR_GT        23
+// load and store
+#define INSTR_LOAD_F    24
+#define INSTR_LOAD_V    25
+#define INSTR_LOAD_S    26
+#define INSTR_LOAD_ENT  27
+#define INSTR_LOAD_FLD  28
+#define INSTR_LOAD_FNC  29
+#define INSTR_STORE_F   31
+#define INSTR_STORE_V   32
+#define INSTR_STORE_S   33
+#define INSTR_STORE_ENT 34
+#define INSTR_STORE_FLD 35
+#define INSTR_STORE_FNC 36
+// others
+#define INSTR_ADDRESS   30
+#define INSTR_RETURN    37
+#define INSTR_NOT_F     38
+#define INSTR_NOT_V     39
+#define INSTR_NOT_S     40
+#define INSTR_NOT_ENT   41
+#define INSTR_NOT_FNC   42
+#define INSTR_IF        43
+#define INSTR_IFNOT     44
+#define INSTR_CALL0     45
+#define INSTR_CALL1     46
+#define INSTR_CALL2     47
+#define INSTR_CALL3     48
+#define INSTR_CALL4     49
+#define INSTR_CALL5     50
+#define INSTR_CALL6     51
+#define INSTR_CALL7     52
+#define INSTR_CALL8     53
+#define INSTR_STATE     54
+#define INSTR_GOTO      55
+#define INSTR_AND       56
+#define INSTR_OR        57
+#define INSTR_BITAND    59
+#define INSTR_BITOR     60
+
+#define mem_a(x) malloc(x)
+#define mem_d(x) free  (x)
+
+/*
+ * This is the smallest lexer I've ever wrote: and I must say, it's quite
+ * more nicer than those large bulky complex parsers that most people write
+ * which has some sort of a complex state.
+ */
+struct lex_file {
+	/*
+	 * This is a simple state for lexing, no need to be complex for qc
+	 * code.  It's trivial stuff.
+	 */
+	FILE *file;
+	char  peek[5]; /* extend for depthier peeks */
+	int   last;
+	int   current;
+	int   length;
+	int   size;
+	char  lastok[8192]; /* No token shall ever be bigger than this! */
+};
+
+/*
+ * It's important that this table never exceed 32 keywords, the ascii
+ * table starts at 33 (which we need)
+ */
+#define TOKEN_DO       0
+#define TOKEN_ELSE     1
+#define TOKEN_IF       2
+#define TOKEN_WHILE    3
+#define TOKEN_BREAK    4
+#define TOKEN_CONTINUE 5
+#define TOKEN_RETURN   6
+#define TOKEN_GOTO     7
+#define TOKEN_FOR      8
+
+/*
+ * Lexer state constants, these are numbers for where exactly in
+ * the lexing the lexer is at. Or where it decided to stop if a lexer
+ * error occurs.
+ */
+#define LEX_COMMENT  128 /* higher than ascii */
+#define LEX_CHRLIT   129
+#define LEX_STRLIT   130
+#define LEX_IDENT    131
+#define LEX_DO       132
+#define LEX_ELSE     133
+#define LEX_IF       134
+#define LEX_WHILE    135
+#define LEX_INCLUDE  136
+#define LEX_DEFINE   137
+
+int              lex_token(struct lex_file *);
+void             lex_reset(struct lex_file *);
+int              lex_debug(struct lex_file *);
+int              lex_close(struct lex_file *);
+struct lex_file *lex_open (const char *);
+
+/* errors */
+#define ERROR_LEX      (SHRT_MAX+0)
+#define ERROR_PARSE    (SHRT_MAX+1)
+#define ERROR_INTERNAL (SHRT_MAX+2)
+int error(int, const char *, ...);
+
+/* parse.c */
+int parse(struct lex_file *);
+
+#endif
diff --git a/lex.c b/lex.c
new file mode 100644
index 0000000..1cb8d0c
--- /dev/null
+++ b/lex.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2012 
+ * 	Dale Weiler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "gmqcc.h"
+
+static const char *const lex_keywords[] = {
+	"do",    "else",     "if",     "while",
+	"break", "continue", "return", "goto",
+	"for"
+};
+
+struct lex_file *lex_open(const char *name) {
+	struct lex_file *lex = mem_a(sizeof(struct lex_file));
+	if (lex) {
+		lex->file = fopen(name, "r");
+		fseek(lex->file, 0, SEEK_END);
+		lex->length = ftell(lex->file);
+		lex->size   = lex->length; /* copy, this is never changed */
+		fseek(lex->file, 0, SEEK_SET);
+		lex->last = 0;
+		
+		memset(lex->peek, 0, sizeof(lex->peek));
+	}
+	return lex;
+}
+
+int lex_close(struct lex_file *file) {
+	int ret = -1;
+	if (file) {
+		ret = fclose(file->file);
+		mem_d(file);
+	}
+	return ret;
+}
+
+static void lex_addch(int ch, struct lex_file *file) {
+	if (file->current <  sizeof(file->lastok)-1)
+		file->lastok[file->current++] = (char)ch;
+	if (file->current == sizeof(file->lastok)-1)
+		file->lastok[file->current]   = (char)'\0';
+}
+static inline void lex_clear(struct lex_file *file) {
+	file->current = 0;
+}
+
+/*
+ * read in inget/unget character from a lexer stream.
+ * This doesn't play with file streams, the lexer has
+ * it's own internal state for this.
+ */
+static int lex_inget(struct lex_file *file) {
+	file->length --;
+	if (file->last > 0)
+		return file->peek[--file->last];
+	return fgetc(file->file);
+}
+static void lex_unget(int ch, struct lex_file *file) {
+	if (file->last < sizeof(file->peek))
+		file->peek[file->last++] = ch;
+	file->length ++;
+}
+
+/*
+ * This is trigraph and digraph support, a feature not qc compiler
+ * supports.  Moving up in this world!
+ */
+static int lex_trigraph(struct lex_file *file) {
+	int  ch;
+	if ((ch = lex_inget(file)) != '?') {
+		lex_unget(ch, file);
+		return '?';
+	}
+	
+	ch = lex_inget(file);
+	switch (ch) {
+		case '(' : return '[' ;
+		case ')' : return ']' ;
+		case '/' : return '\\';
+		case '\'': return '^' ;
+		case '<' : return '{' ;
+		case '>' : return '}' ;
+		case '!' : return '|' ;
+		case '-' : return '~' ;
+		case '=' : return '#' ;
+		default:
+			lex_unget('?', file);
+			lex_unget(ch , file);
+			return '?';
+	}
+	return '?';
+}
+static int lex_digraph(struct lex_file *file, int first) {
+	int ch = lex_inget(file);
+	switch (first) {
+		case '<':
+			if (ch == '%') return '{';
+			if (ch == ':') return '[';
+			break;
+		case '%':
+			if (ch == '>') return '}';
+			if (ch == ':') return '#';
+			break;
+		case ':':
+			if (ch == '>') return ']';
+			break;
+	}
+	
+	lex_unget(ch, file);
+	return first;
+}
+
+static int lex_getch(struct lex_file *file) {
+	int ch = lex_inget(file);
+	if (ch == '?')
+		return lex_trigraph(file);
+	if (ch == '<' || ch == ':' || ch == '%')
+		return lex_digraph (file, ch);
+		
+	return ch;
+}
+
+static int lex_get(struct lex_file *file) {
+	int ch;
+	if (!isspace(ch = lex_getch(file)))
+		return ch;
+	
+	/* skip over all spaces */
+	while (isspace(ch) && ch != '\n')
+		ch = lex_getch(file);
+		
+	if (ch == '\n')
+		return ch;
+		
+	lex_unget(ch, file);
+	return ' ';
+}
+
+static int lex_skipchr(struct lex_file *file) {
+	int ch;
+	int it;
+	
+	lex_clear(file);
+	lex_addch('\'', file);
+	
+	for (it = 0; it < 2 && ((ch = lex_inget(file)) != '\''); it++) {
+		lex_addch(ch, file);
+		
+		if (ch == '\n')
+			return ERROR_LEX;
+		if (ch == '\\')
+			lex_addch(lex_getch(file), file);
+	}
+	lex_addch('\'', file);
+	lex_addch('\0', file);
+	
+	if (it > 2)
+		return ERROR_LEX;
+		
+	return LEX_CHRLIT;
+}
+
+static int lex_skipstr(struct lex_file *file) {
+	int ch;
+	lex_clear(file);
+	lex_addch('"', file);
+	
+	while ((ch = lex_getch(file)) != '"') {
+		if (ch == '\n' || ch == EOF)
+			return ERROR_LEX;
+			
+		lex_addch(ch, file);
+		if (ch == '\\')
+			lex_addch(lex_inget(file), file);
+	}
+	
+	lex_addch('"', file);
+	lex_addch('\0', file);
+	
+	return LEX_STRLIT;
+}
+static int lex_skipcmt(struct lex_file *file) {
+	int ch;
+	lex_clear(file);
+	ch = lex_getch(file);
+	
+	if (ch == '/') {
+		lex_addch('/', file);
+		lex_addch('/', file);
+		
+		while ((ch = lex_getch(file)) != '\n') {
+			if (ch == '\\') {
+				lex_addch(ch, file);
+				lex_addch(lex_getch(file), file);
+			} else {
+				lex_addch(ch, file);
+			}
+		}
+		lex_addch('\0', file);
+		return LEX_COMMENT;
+	}
+	
+	if (ch != '*') {
+		lex_unget(ch, file);
+		return '/';
+	}
+	
+	lex_addch('/', file);
+	
+	/* hate this */
+	do {
+		lex_addch(ch, file);
+		while ((ch = lex_getch(file)) != '*') {
+			if (ch == EOF)
+				return error(ERROR_LEX, "malformatted comment"," ");
+			else
+				lex_addch(ch, file);
+		}
+		lex_addch(ch, file);
+	} while ((ch = lex_getch(file)) != '/');
+	
+	lex_addch('/',  file);
+	lex_addch('\0', file);
+	
+	return LEX_COMMENT;
+}
+
+static int lex_getsource(struct lex_file *file) {
+	int ch = lex_get(file);
+	
+	/* skip char/string/comment */
+	switch (ch) {
+		case '\'': return lex_skipchr(file);
+		case '"':  return lex_skipstr(file);
+		case '/':  return lex_skipcmt(file);
+		default:   return ch;
+	}
+}
+
+int lex_token(struct lex_file *file) {
+	int ch = lex_getsource(file);
+	int it;
+	
+	/* valid identifier */
+	if (ch > 0 && (ch == '_' || isalpha(ch))) {
+		lex_clear(file);
+		while (ch > 0 && (isalpha(ch) || isdigit(ch) || ch == '_')) {
+			lex_addch(ch, file);
+			ch = lex_getsource(file);
+		}
+		lex_unget(ch,   file);
+		lex_addch('\0', file);
+		
+		/* look inside the table for a keyword .. */
+		for (it = 0; it < sizeof(lex_keywords)/sizeof(*lex_keywords); it++)
+			if (!strncmp(file->lastok, lex_keywords[it], sizeof(lex_keywords[it])))
+				return it;
+				
+		return LEX_IDENT;
+	}
+	return ch;
+}
+
+void lex_reset(struct lex_file *file) {
+	file->current = 0;
+	file->last    = 0;
+	file->length  = file->size;
+	fseek(file->file, 0, SEEK_SET);
+	
+	memset(file->peek,   0, sizeof(file->peek  ));
+	memset(file->lastok, 0, sizeof(file->lastok));
+}
+
+int lex_debug(struct lex_file *file) {
+	int list_do       = 0;
+	int list_else     = 0;
+	int list_if       = 0;
+	int list_while    = 0;
+	int list_break    = 0;
+	int list_continue = 0;
+	int list_return   = 0;
+	int list_goto     = 0;
+	int list_for      = 0;
+	int token         = 0;
+	printf("===========================\nTOKENS:   \n===========================\n");
+	while ((token = lex_token(file)) != ERROR_LEX && file->length >= 0) {
+		if (token != -1) {
+			switch (token) {
+				case 0: list_do      ++; break;
+				case 1: list_else    ++; break;
+				case 2: list_if      ++; break;
+				case 3: list_while   ++; break;
+				case 4: list_break   ++; break;
+				case 5: list_continue++; break;
+				case 6: list_return  ++; break;
+				case 7: list_goto    ++; break;
+				case 8: list_for     ++; break;
+			}
+		}
+		if (token >= 33 && token <= 126)
+			putchar(token);
+	}
+	printf("\n===========================\nBRANCHES \n===========================\n");
+	printf("\t if       % 8d\n", list_if);
+	printf("\t else     % 8d\n", list_else);
+	printf("===========================\nLOOPS      \n===========================\n");
+	printf("\t for      % 8d\n", list_for);
+	printf("\t while    % 8d\n", list_while);
+	printf("\t do       % 8d\n", list_do);
+	printf("===========================\nSTATEMENTS \n===========================\n");
+	printf("\t break    % 8d\n", list_break);
+	printf("\t continue % 8d\n", list_continue);
+	printf("\t return   % 8d\n", list_return);
+	printf("\t goto     % 8d\n", list_goto);
+	printf("===========================\nIDENTIFIERS\n===========================\n");
+	lex_reset(file);
+	while ((token = lex_token(file)) != ERROR_LEX && file->length >= 0)
+		if (token == LEX_IDENT)
+			printf("%s ", file->lastok);
+	lex_reset(file);
+	return 1;
+}
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..8718a72
--- /dev/null
+++ b/main.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 
+ * 	Dale Weiler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "gmqcc.h"
+
+int main(int argc, char **argv) {
+	if (argc <= 1) {
+		printf("Usage: %s infile.qc outfile\n", *argv);
+		return -1;
+	}
+	
+	struct lex_file *lex = lex_open(argv[1]);
+	lex_debug(lex);
+	parse    (lex);
+	lex_close(lex);
+	
+	return 0;
+}
diff --git a/parse.c b/parse.c
new file mode 100644
index 0000000..a43981f
--- /dev/null
+++ b/parse.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 
+ * 	Dale Weiler
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <limits.h>
+#include "gmqcc.h"
+int parse(struct lex_file *file) {
+	int     token = 0;
+	while ((token = lex_token(file)) != ERROR_LEX && file->length >= 0) {
+		switch (token) {
+			case TOKEN_IF:
+				token = lex_token(file);
+				while ((token == ' ' || token == '\n') && file->length >= 0)
+					token = lex_token(file);
+					
+				if (token != '(')
+					error(ERROR_PARSE, "Expected `(` after if\n", "");
+				break;
+		}
+	}
+	lex_reset(file);
+	
+	return 1;
+}	
-- 
2.39.5