Initial commit
This commit is contained in:
		
						commit
						ea5bea79d5
					
				
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| bin/* | ||||
| test/* | ||||
| test | ||||
| bin | ||||
							
								
								
									
										20
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| Copyright (c) 2015 Benjamin Moir | ||||
| Copyright (c) 2015 Marrub <marrub@greyserv.net> | ||||
| 
 | ||||
| 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. | ||||
							
								
								
									
										8
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| # sorry this makefile doesn't include anything cross-platform
 | ||||
| # was hurriedly made to test it
 | ||||
| 
 | ||||
| all: | ||||
| 	mkdir -p bin | ||||
| 	mingw32-gcc --std=c99 -g -ggdb -c -o bin/lt.o lt.c | ||||
| 	mingw32-gcc -shared -g -ggdb -o bin/LoveToken.dll bin/lt.o -Wl,--out-implib,bin/libLoveToken.a | ||||
| 	# cp bin/LoveToken.dll test/LoveToken.dll | ||||
							
								
								
									
										488
									
								
								lt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										488
									
								
								lt.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,488 @@ | |||
| /*
 | ||||
| Copyright (c) 2015 Benjamin Moir | ||||
| Copyright (c) 2015 Marrub <marrub@greyserv.net> | ||||
| 
 | ||||
| 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 <ctype.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdbool.h> | ||||
| #include "lt.h" | ||||
| 
 | ||||
| FILE *LT_ParseFile; | ||||
| bool LT_AssertError = false; | ||||
| LT_GarbageList *gbHead, *gbRover; | ||||
| 
 | ||||
| static bool escapeChars = true; | ||||
| 
 | ||||
| static char *tokenTypes[] = { | ||||
| 	// [marrub] So, this was an interesting bug. This was completely misordered from the enum.
 | ||||
| 	//          As can be guessed, this caused many issues. Seriously, all of them.
 | ||||
| 	"TOK_Colon", "TOK_Comma", "TOK_Div", "TOK_Mod", "TOK_Mul", "TOK_Query", | ||||
| 	"TOK_BraceO", "TOK_BraceC", "TOK_BrackO", "TOK_BrackC", "TOK_ParenO", "TOK_ParenC", | ||||
| 	"TOK_LnEnd", "TOK_Add2", "TOK_Add", "TOK_And2", "TOK_And", "TOK_CmpGE", | ||||
| 	"TOK_ShR", "TOK_CmpGT", "TOK_CmpLE", "TOK_ShL", "TOK_CmpNE", "TOK_CmpLT", | ||||
| 	"TOK_CmpEQ", "TOK_Equal", "TOK_Not", "TOK_OrI2", "TOK_OrI", "TOK_OrX2", | ||||
| 	"TOK_OrX", "TOK_Sub2", "TOK_Sub", "TOK_String", "TOK_Charac", "TOK_Number", | ||||
| 	"TOK_Identi", "TOK_EOF", "TOK_ChrSeq" | ||||
| }; | ||||
| 
 | ||||
| void LT_Init(LT_InitInfo initInfo) | ||||
| { | ||||
| 	escapeChars = initInfo.escapeChars; | ||||
| 	 | ||||
| 	gbHead = malloc(sizeof(LT_GarbageList)); | ||||
| 	gbHead->next = NULL; | ||||
| 	gbHead->ptr = NULL; | ||||
| 	 | ||||
| 	gbRover = gbHead; | ||||
| } | ||||
| 
 | ||||
| void LT_Quit() | ||||
| { | ||||
| 	gbRover = gbHead; | ||||
| 	 | ||||
| 	while(gbRover != NULL) | ||||
| 	{ | ||||
| 		LT_GarbageList *next = gbRover->next; | ||||
| 		 | ||||
| 		if(gbRover->ptr != NULL) | ||||
| 		{ | ||||
| 			free(gbRover->ptr); | ||||
| 			gbRover->ptr = NULL; | ||||
| 		} | ||||
| 		 | ||||
| 		free(gbRover); | ||||
| 		 | ||||
| 		gbRover = next; | ||||
| 	} | ||||
| 	 | ||||
| 	gbRover = NULL; | ||||
| 	gbHead = NULL; | ||||
| } | ||||
| 
 | ||||
| bool LT_Assert(bool assertion, const char *str) | ||||
| { | ||||
| 	if(assertion) | ||||
| 	{ | ||||
| 		LT_AssertError = true; | ||||
| 		fprintf(stderr, "LT_Assert: %s", str); | ||||
| 	} | ||||
| 	 | ||||
| 	return assertion; | ||||
| } | ||||
| 
 | ||||
| bool LT_OpenFile(const char *filePath) | ||||
| { | ||||
| 	LT_ParseFile = fopen(filePath, "r"); | ||||
| 	 | ||||
| 	if(LT_ParseFile == NULL) | ||||
| 	{ | ||||
| 		perror("LT_OpenFile"); | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void LT_CloseFile() | ||||
| { | ||||
| 	if(LT_ParseFile != NULL) | ||||
| 	{ | ||||
| 		fclose(LT_ParseFile); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| char *LT_ReadNumber() | ||||
| { | ||||
| 	size_t i = 0, str_blocks = 1; | ||||
| 	char c, *str = malloc(TOKEN_STR_BLOCK_LENGTH); | ||||
| 	 | ||||
| 	while(!feof(LT_ParseFile)) | ||||
| 	{ | ||||
| 		fread(&c, 1, 1, LT_ParseFile); | ||||
| 		 | ||||
| 		if(!isalnum(c)) | ||||
| 		{ | ||||
| 			fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 			break; | ||||
| 		} | ||||
| 		 | ||||
| 		if(i > TOKEN_STR_BLOCK_LENGTH) | ||||
| 		{ | ||||
| 			realloc(str, TOKEN_STR_BLOCK_LENGTH * str_blocks++); | ||||
| 		} | ||||
| 		 | ||||
| 		str[i++] = c; | ||||
| 	} | ||||
| 	 | ||||
| 	str[i++] = '\0'; | ||||
| 	 | ||||
| 	gbRover->next = malloc(sizeof(LT_GarbageList)); | ||||
| 	gbRover = gbRover->next; | ||||
| 	gbRover->ptr = realloc(str, i); | ||||
| 	gbRover->next = NULL; | ||||
| 	 | ||||
| 	return gbRover->ptr; | ||||
| } | ||||
| 
 | ||||
| char *LT_ReadString(char term) | ||||
| { | ||||
| 	size_t i = 0, str_blocks = 1; | ||||
| 	char c, *str = malloc(TOKEN_STR_BLOCK_LENGTH); | ||||
| 	static char *emptyString = ""; | ||||
| 	 | ||||
| 	while(true) | ||||
| 	{ | ||||
| 		fread(&c, 1, 1, LT_ParseFile); | ||||
| 		 | ||||
| 		if(c == term) | ||||
| 		{ | ||||
| 			break; | ||||
| 		} | ||||
| 		 | ||||
| 		if(LT_Assert(feof(LT_ParseFile) || c == '\n', "unterminated string literal")) | ||||
| 		{ | ||||
| 			return emptyString; | ||||
| 		} | ||||
| 		 | ||||
| 		if(c == '\\' && escapeChars) | ||||
| 		{ | ||||
| 			fread(&c, 1, 1, LT_ParseFile); | ||||
| 			 | ||||
| 			if(LT_Assert(feof(LT_ParseFile) || c == '\n', "unterminated string literal")) | ||||
| 			{ | ||||
| 				str[i] = '\0'; | ||||
| 				return str; | ||||
| 			} | ||||
| 			 | ||||
| 			if(i > TOKEN_STR_BLOCK_LENGTH) | ||||
| 			{ | ||||
| 				realloc(str, TOKEN_STR_BLOCK_LENGTH * str_blocks++); | ||||
| 			} | ||||
| 			 | ||||
| 			str = LT_Escaper(str, i++, c); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if(i > TOKEN_STR_BLOCK_LENGTH) | ||||
| 			{ | ||||
| 				realloc(str, TOKEN_STR_BLOCK_LENGTH * str_blocks++); | ||||
| 			} | ||||
| 			 | ||||
| 			str[i++] = c; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	str[i++] = '\0'; | ||||
| 	 | ||||
| 	gbRover->next = malloc(sizeof(LT_GarbageList)); | ||||
| 	gbRover = gbRover->next; | ||||
| 	gbRover->ptr = realloc(str, i); | ||||
| 	gbRover->next = NULL; | ||||
| 	 | ||||
| 	return gbRover->ptr; | ||||
| } | ||||
| 
 | ||||
| char *LT_Escaper(char *str, size_t pos, char escape) | ||||
| { | ||||
| 	switch(escape) | ||||
| 	{ | ||||
| 		case '\\': case '\'': case '"':  str[pos] = escape; break; | ||||
| 		case 'C': str[pos] = '\x1C'; break; | ||||
| 		case 'a': str[pos] = '\a'; break; | ||||
| 		case 'b': str[pos] = '\b'; break; | ||||
| 		case 'f': str[pos] = '\f'; break; | ||||
| 		case 'n': str[pos] = '\n'; break; | ||||
| 		case 'r': str[pos] = '\r'; break; | ||||
| 		case 't': str[pos] = '\t'; break; | ||||
| 		case 'v': str[pos] = '\v'; break; | ||||
| 		case 'x': // [marrub] THIS ONE IS FUN
 | ||||
| 			for(unsigned int i = 0;;) | ||||
| 			{ | ||||
| 				char c; | ||||
| 				fread(&c, 1, 1, LT_ParseFile); | ||||
| 				 | ||||
| 				switch(c) | ||||
| 				{ | ||||
| 					case '0': i = i * 16 + 0x0; break; | ||||
| 					case '1': i = i * 16 + 0x1; break; | ||||
| 					case '2': i = i * 16 + 0x2; break; | ||||
| 					case '3': i = i * 16 + 0x3; break; | ||||
| 					case '4': i = i * 16 + 0x4; break; | ||||
| 					case '5': i = i * 16 + 0x5; break; | ||||
| 					case '6': i = i * 16 + 0x6; break; | ||||
| 					case '7': i = i * 16 + 0x7; break; | ||||
| 					case '8': i = i * 16 + 0x8; break; | ||||
| 					case '9': i = i * 16 + 0x9; break; | ||||
| 					case 'a': case 'A': i = i * 16 + 0xA; break; | ||||
| 					case 'b': case 'B': i = i * 16 + 0xB; break; | ||||
| 					case 'c': case 'C': i = i * 16 + 0xC; break; | ||||
| 					case 'd': case 'D': i = i * 16 + 0xD; break; | ||||
| 					case 'e': case 'E': i = i * 16 + 0xE; break; | ||||
| 					case 'f': case 'F': i = i * 16 + 0xF; break; | ||||
| 					 | ||||
| 					default: | ||||
| 						fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 						str[pos] = i; | ||||
| 						break; | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			break; | ||||
| 		 | ||||
| 		case '0': case '1': case '2': case '3': | ||||
| 		case '4': case '5': case '6': case '7': | ||||
| 			{ | ||||
| 				char c = escape; | ||||
| 				unsigned int i = 0; | ||||
| 				 | ||||
| 				for(unsigned int n = 2; n != 0; n--) | ||||
| 				{ | ||||
| 					switch(c) | ||||
| 					{ | ||||
| 						case '0': i = i * 8 + 00; break; | ||||
| 						case '1': i = i * 8 + 01; break; | ||||
| 						case '2': i = i * 8 + 02; break; | ||||
| 						case '3': i = i * 8 + 03; break; | ||||
| 						case '4': i = i * 8 + 04; break; | ||||
| 						case '5': i = i * 8 + 05; break; | ||||
| 						case '6': i = i * 8 + 06; break; | ||||
| 						case '7': i = i * 8 + 07; break; | ||||
| 						default: | ||||
| 							fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 							str[pos] = i; | ||||
| 							return str; | ||||
| 					} | ||||
| 					 | ||||
| 					fread(&c, 1, 1, LT_ParseFile); | ||||
| 				} | ||||
| 				 | ||||
| 				str[pos] = i; | ||||
| 				break; | ||||
| 			} | ||||
| 			 | ||||
| 			break; | ||||
| 		default: LT_Assert(true, "unknown escape character"); break; | ||||
| 	} | ||||
| 	 | ||||
| 	return str; | ||||
| } | ||||
| 
 | ||||
| LT_Token LT_GetToken() | ||||
| { | ||||
| 	char c; | ||||
| 	LT_Token tk = { 0 }; | ||||
| 	 | ||||
| 	fread(&c, 1, 1, LT_ParseFile); | ||||
| 	 | ||||
| 	if(feof(LT_ParseFile)) | ||||
| 	{ | ||||
| 		tk.token = tokenTypes[TOK_EOF]; | ||||
| 		tk.string = NULL; | ||||
| 		tk.pos = ftell(LT_ParseFile); | ||||
| 		return tk; | ||||
| 	} | ||||
| 	 | ||||
| 	while(isspace(c) && c != '\n') | ||||
| 	{ | ||||
| 		fread(&c, 1, 1, LT_ParseFile); | ||||
| 		 | ||||
| 		if(feof(LT_ParseFile)) // [marrub] This could have caused issues if there was whitespace before EOF.
 | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_EOF]; | ||||
| 			tk.string = NULL; | ||||
| 			tk.pos = ftell(LT_ParseFile); | ||||
| 			return tk; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	tk.pos = ftell(LT_ParseFile); | ||||
| 	 | ||||
| 	switch(c) | ||||
| 	{ | ||||
| 	case ':':  tk.token = tokenTypes[TOK_Colon];  return tk; | ||||
| 	case ',':  tk.token = tokenTypes[TOK_Comma];  return tk; | ||||
| 	case '/':  tk.token = tokenTypes[TOK_Div];    return tk; | ||||
| 	case '%':  tk.token = tokenTypes[TOK_Mod];    return tk; | ||||
| 	case '*':  tk.token = tokenTypes[TOK_Mul];    return tk; | ||||
| 	case '?':  tk.token = tokenTypes[TOK_Query];  return tk; | ||||
| 	case '{':  tk.token = tokenTypes[TOK_BraceO]; return tk; | ||||
| 	case '}':  tk.token = tokenTypes[TOK_BraceC]; return tk; | ||||
| 	case '[':  tk.token = tokenTypes[TOK_BrackO]; return tk; | ||||
| 	case ']':  tk.token = tokenTypes[TOK_BrackC]; return tk; | ||||
| 	case '(':  tk.token = tokenTypes[TOK_ParenO]; return tk; | ||||
| 	case ')':  tk.token = tokenTypes[TOK_ParenC]; return tk; | ||||
| 	case '\n': tk.token = tokenTypes[TOK_LnEnd];  return tk; | ||||
| 	 | ||||
| 	// [marrub] Sorry, I wouldn't normally do a quick and dirty hack like this,
 | ||||
| 	//          but sometimes I really do care about my sanity. And wrists.
 | ||||
| #define DoubleTokDef(ch, t1, t2) \ | ||||
| 	case ch: \ | ||||
| 		fread(&c, 1, 1, LT_ParseFile); \ | ||||
| 		\ | ||||
| 		if(c == ch) \ | ||||
| 		{ \ | ||||
| 			tk.token = tokenTypes[t2]; \ | ||||
| 		} \ | ||||
| 		else \ | ||||
| 		{ \ | ||||
| 			tk.token = tokenTypes[t1]; \ | ||||
| 			fseek(LT_ParseFile, -1, SEEK_CUR); \ | ||||
| 		} \ | ||||
| 		\ | ||||
| 		return tk; | ||||
| 	 | ||||
| 	DoubleTokDef('+', TOK_Add, TOK_Add2); | ||||
| 	DoubleTokDef('-', TOK_Sub, TOK_Sub2); | ||||
| 	DoubleTokDef('&', TOK_And, TOK_And2); | ||||
| 	DoubleTokDef('=', TOK_Equal, TOK_CmpEQ); | ||||
| 	DoubleTokDef('^', TOK_OrX, TOK_OrX2); | ||||
| 	DoubleTokDef('|', TOK_OrI, TOK_OrI2); | ||||
| 	 | ||||
| #undef DoubleTokDef | ||||
| 	 | ||||
| 	// [marrub] Special god damn snowflakes
 | ||||
| 	case '>': | ||||
| 		fread(&c, 1, 1, LT_ParseFile); | ||||
| 		 | ||||
| 		if(c == '=') | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_CmpGE]; | ||||
| 		} | ||||
| 		else if(c == '>') | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_ShR]; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_CmpGT]; | ||||
| 			fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 		} | ||||
| 		 | ||||
| 		return tk; | ||||
| 	case '<': | ||||
| 		fread(&c, 1, 1, LT_ParseFile); | ||||
| 		 | ||||
| 		if(c == '=') | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_CmpLE]; | ||||
| 		} | ||||
| 		else if(c == '<') | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_ShL]; | ||||
| 		} | ||||
| 		else if(c == '>') | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_CmpNE]; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_CmpLT]; | ||||
| 			fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 		} | ||||
| 		 | ||||
| 		return tk; | ||||
| 	case '!': | ||||
| 		fread(&c, 1, 1, LT_ParseFile); | ||||
| 		 | ||||
| 		if(c == '=') | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_CmpNE]; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_Not]; | ||||
| 			fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 		} | ||||
| 		 | ||||
| 		return tk; | ||||
| 	case '~': | ||||
| 		fread(&c, 1, 1, LT_ParseFile); | ||||
| 		 | ||||
| 		if(c == '=') | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_CmpNE]; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 			LT_Assert(true, "syntax error"); // [marrub] Yet more error checking that was forgotten before.
 | ||||
| 		} | ||||
| 		 | ||||
| 		return tk; | ||||
| 	case '"': case '\'': | ||||
| 		tk.string = LT_ReadString(c); | ||||
| 		 | ||||
| 		if(c == '"') | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_String]; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			tk.token = tokenTypes[TOK_Charac]; | ||||
| 		} | ||||
| 		 | ||||
| 		return tk; | ||||
| 	} | ||||
| 	 | ||||
| 	if(isdigit(c)) | ||||
| 	{ | ||||
| 		fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 		 | ||||
| 		tk.string = LT_ReadNumber(); | ||||
| 		tk.token = tokenTypes[TOK_Number]; | ||||
| 		return tk; | ||||
| 	} | ||||
| 	 | ||||
| 	if(isalpha(c) || c == '_') | ||||
| 	{ | ||||
| 		size_t i = 0, str_blocks = 1; | ||||
| 		char *str = malloc(TOKEN_STR_BLOCK_LENGTH); | ||||
| 		 | ||||
| 		while(!(feof(LT_ParseFile)) && (isalnum(c) || c == '_')) | ||||
| 		{ | ||||
| 			if(i > TOKEN_STR_BLOCK_LENGTH) | ||||
| 			{ | ||||
| 				realloc(str, TOKEN_STR_BLOCK_LENGTH * str_blocks++); | ||||
| 			} | ||||
| 			 | ||||
| 			str[i++] = c; | ||||
| 			fread(&c, 1, 1, LT_ParseFile); | ||||
| 		} | ||||
| 		 | ||||
| 		str[i++] = '\0'; // [marrub] Completely forgot this line earlier. Really screwed up everything.
 | ||||
| 		 | ||||
| 		gbRover->next = malloc(sizeof(LT_GarbageList)); | ||||
| 		gbRover = gbRover->next; | ||||
| 		gbRover->ptr = realloc(str, i); | ||||
| 		gbRover->next = NULL; | ||||
| 		 | ||||
| 		fseek(LT_ParseFile, -1, SEEK_CUR); | ||||
| 		 | ||||
| 		tk.string = gbRover->ptr; | ||||
| 		tk.token = tokenTypes[TOK_Identi]; | ||||
| 		return tk; | ||||
| 	} | ||||
| 	 | ||||
| 	return tk; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										117
									
								
								lt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								lt.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | |||
| /*
 | ||||
| Copyright (c) 2015 Benjamin Moir | ||||
| Copyright (c) 2015 Marrub <marrub@greyserv.net> | ||||
| 
 | ||||
| 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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef LOVETOKEN_LT_H | ||||
| #define LOVETOKEN_LT_H | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdio.h> | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| #define TOKEN_STR_BLOCK_LENGTH 512 | ||||
| 
 | ||||
| // [marrub] When using in FFI, remove this from the definitions
 | ||||
| //          Also redefine this for cross-platform.
 | ||||
| #define LT_EXPORT __declspec(dllexport) | ||||
| 
 | ||||
| typedef struct | ||||
| { | ||||
| 	bool escapeChars; | ||||
| } LT_InitInfo; | ||||
| 
 | ||||
| typedef struct | ||||
| { | ||||
| 	char *token; | ||||
| 	char *string; | ||||
| 	int pos; | ||||
| } LT_Token; | ||||
| 
 | ||||
| extern bool LT_EXPORT LT_AssertError; | ||||
| 
 | ||||
| void LT_EXPORT LT_Init(LT_InitInfo initInfo); | ||||
| void LT_EXPORT LT_Quit(); | ||||
| bool LT_EXPORT LT_Assert(bool assertion, const char *str); | ||||
| 
 | ||||
| bool LT_EXPORT LT_OpenFile(const char *filePath); | ||||
| void LT_EXPORT LT_CloseFile(); | ||||
| 
 | ||||
| char *LT_EXPORT LT_ReadNumber(); | ||||
| char *LT_EXPORT LT_ReadString(char term); | ||||
| char *LT_EXPORT LT_Escaper(char *str, size_t pos, char escape); | ||||
| LT_Token LT_EXPORT LT_GetToken(); | ||||
| 
 | ||||
| // [marrub] Don't include stuff below here into the FFI definitions
 | ||||
| 
 | ||||
| typedef struct LT_GarbageList_s | ||||
| { | ||||
| 	struct LT_GarbageList_s *next; | ||||
| 	void *ptr; | ||||
| } LT_GarbageList; | ||||
| 
 | ||||
| extern FILE *LT_ParseFile; | ||||
| 
 | ||||
| enum | ||||
| { | ||||
| 	TOK_Colon, | ||||
| 	TOK_Comma, | ||||
| 	TOK_Div, | ||||
| 	TOK_Mod, | ||||
| 	TOK_Mul, | ||||
| 	TOK_Query, | ||||
| 	TOK_BraceO, | ||||
| 	TOK_BraceC, | ||||
| 	TOK_BrackO, | ||||
| 	TOK_BrackC, | ||||
| 	TOK_ParenO, | ||||
| 	TOK_ParenC, | ||||
| 	TOK_LnEnd, | ||||
| 	TOK_Add2, | ||||
| 	TOK_Add, | ||||
| 	TOK_And2, | ||||
| 	TOK_And, | ||||
| 	TOK_CmpGE, | ||||
| 	TOK_ShR, | ||||
| 	TOK_CmpGT, | ||||
| 	TOK_CmpLE, | ||||
| 	TOK_ShL, | ||||
| 	TOK_CmpNE, | ||||
| 	TOK_CmpLT, | ||||
| 	TOK_CmpEQ, | ||||
| 	TOK_Equal, | ||||
| 	TOK_Not, | ||||
| 	TOK_OrI2, | ||||
| 	TOK_OrI, | ||||
| 	TOK_OrX2, | ||||
| 	TOK_OrX, | ||||
| 	TOK_Sub2, | ||||
| 	TOK_Sub, | ||||
| 	TOK_String, | ||||
| 	TOK_Charac, | ||||
| 	TOK_Number, | ||||
| 	TOK_Identi, | ||||
| 	TOK_EOF, | ||||
| 	TOK_ChrSeq | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										96
									
								
								parser.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								parser.lua
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,96 @@ | |||
| --[[ | ||||
| 
 | ||||
| Copyright (c) 2015 Benjamin Moir | ||||
| Copyright (c) 2015 Marrub <marrub@greyserv.net> | ||||
| 
 | ||||
| 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. | ||||
| 
 | ||||
| --]] | ||||
| 
 | ||||
| local ffi = require("ffi") | ||||
| local parser = {} | ||||
| 
 | ||||
| local loveToken = ffi.load("LoveToken") | ||||
| ffi.cdef([[ | ||||
| typedef struct | ||||
| { | ||||
| 	bool escapeChars; | ||||
| } LT_InitInfo; | ||||
| 
 | ||||
| typedef struct | ||||
| { | ||||
| 	char *token; | ||||
| 	char *string; | ||||
| 	int pos; | ||||
| } LT_Token; | ||||
| 
 | ||||
| extern bool LT_AssertError; | ||||
| 
 | ||||
| void LT_Init(LT_InitInfo initInfo); | ||||
| void LT_Quit(); | ||||
| bool LT_Assert(bool assertion, const char *str); | ||||
| 
 | ||||
| bool LT_OpenFile(const char *filePath); | ||||
| void LT_CloseFile(); | ||||
| 
 | ||||
| char *LT_ReadNumber(); | ||||
| char *LT_ReadString(char term); | ||||
| char *LT_Escaper(char *str, size_t pos, char escape); | ||||
| LT_Token LT_GetToken(); | ||||
| ]]) | ||||
| 
 | ||||
| function parser:init(initInfo, filePath) | ||||
| 	loveToken.LT_Init(initInfo) | ||||
| 	loveToken.LT_OpenFile(filePath) | ||||
| end | ||||
| 
 | ||||
| function parser:assert(assertion, str) | ||||
| 	return loveToken.LT_Assert(assertion, str) | ||||
| end | ||||
| 
 | ||||
| function parser:openFile(filePath) | ||||
| 	return loveToken.LT_OpenFile(filePath) | ||||
| end | ||||
| 
 | ||||
| function parser:closeFile() | ||||
| 	loveToken.LT_CloseFile() | ||||
| end | ||||
| 
 | ||||
| function parser:quit() | ||||
| 	loveToken.LT_CloseFile() | ||||
| 	loveToken.LT_Quit() | ||||
| end | ||||
| 
 | ||||
| function parser:readNumber() | ||||
| 	return ffi.string(loveToken.LT_ReadNumber()) | ||||
| end | ||||
| 
 | ||||
| function parser:readString(term) | ||||
| 	return ffi.string(loveToken.LT_ReadString(term)) | ||||
| end | ||||
| 
 | ||||
| function parser:escaper(str, pos, escape) | ||||
| 	return ffi.string(loveToken.LT_Escaper(str, pos, escape)) | ||||
| end | ||||
| 
 | ||||
| function parser:getToken() | ||||
| 	return loveToken.LT_GetToken() | ||||
| end | ||||
| 
 | ||||
| return parser | ||||
		Reference in New Issue
	
	Block a user