diff --git a/build.c b/build.c index e2c5549..f113e1d 100755 --- a/build.c +++ b/build.c @@ -1,11 +1,15 @@ #if 0 -set -eou +set -e if [[ ! -v OUTPUT ]]; then OUTPUT=solstice fi +if [[ ! -v CFLAGS ]]; then + CFLAGS="" +fi + gcc "$0" -o "$OUTPUT" if not [ $# -lt 1 ]; then @@ -30,6 +34,8 @@ exit // -- LEXER -- #include "src/lexer/SolsType.c" +#include "src/lexer/SolsToken.c" +#include "src/lexer/SolsLiteral.c" #include "src/lexer/lexer.c" // -- PARSER -- diff --git a/src/lexer/SolsLiteral.c b/src/lexer/SolsLiteral.c new file mode 100644 index 0000000..5ba3c54 --- /dev/null +++ b/src/lexer/SolsLiteral.c @@ -0,0 +1,48 @@ +#include "SolsLiteral.h" +#include +#include + +ResultType(SolsLiteral, charptr) createSolsLiteral(SolsLiteralType type, ...) { + va_list args; + va_start(args, type); + SolsLiteral literal = { + .type = type + }; + switch (type) { + case SLT_INT: { + literal.as.intv = va_arg(args, int64_t); + break; + } + case SLT_DOUBLE: { + literal.as.doublev = va_arg(args, double); + break; + } + case SLT_BOOL: { + literal.as.boolv = (bool) va_arg(args, int); + break; + } + case SLT_CHAR: { + literal.as.charv = (char) va_arg(args, int); + break; + } + case SLT_STRING: { + char* input = va_arg(args, char*); + if (input == NULL) { + return Error(SolsLiteral, charptr, "Unexpected NULL value (in createSolsLiteral() function)"); + } + literal.as.stringv = malloc(strlen(input) + 1); + if (literal.as.stringv == NULL) { + return Error(SolsLiteral, charptr, "Couldn't allocate memory (in createSolsLiteral() function)"); + } + strcpy(literal.as.stringv, input); + } + } + return Success(SolsLiteral, charptr, literal); + va_end(args); +} + +void freeSolsLiteral(SolsLiteral* lit) { + if (lit->type == SLT_STRING && lit->as.stringv != NULL) { + free(lit->as.stringv); + } +} diff --git a/src/lexer/SolsLiteral.h b/src/lexer/SolsLiteral.h new file mode 100644 index 0000000..d35df40 --- /dev/null +++ b/src/lexer/SolsLiteral.h @@ -0,0 +1,44 @@ +#ifndef SOLSLITERAL_H +#define SOLSLITERAL_H + +#include +#include +#include "../include/error.h" + +typedef char* charptr; + +typedef enum SolsLiteralType { + SLT_INT, SLT_STRING, SLT_DOUBLE, SLT_BOOL, SLT_CHAR +} SolsLiteralType; + +// Stores literal values which will be added to the Ground code. +// Not much explaining needed here. +typedef struct SolsLiteral { + SolsLiteralType type; + union { + int64_t intv; + char* stringv; + double doublev; + bool boolv; + char charv; + } as; +} SolsLiteral; + +Result(SolsLiteral, charptr); + +// Creates a SolsLiteral, based on the type provided. +// SolsLiteralType -> C type: +// SLT_INT -> int64_t +// SLT_STRING -> char* +// SLT_DOUBLE -> double +// SLT_BOOL -> bool +// SL_CHAR -> char +// An error will only be returned if there is an issue copying a provided char*. +// There is no way to detect incorrectly provided types, so ensure that the right type +// is provided!!!! +ResultType(SolsLiteral, charptr) createSolsLiteral(SolsLiteralType type, ...); + +// Frees a SolsLiteral. Primarily concerned with freeing .as.stringv +void freeSolsLiteral(SolsLiteral* lit); + +#endif diff --git a/src/lexer/SolsToken.c b/src/lexer/SolsToken.c new file mode 100644 index 0000000..e69de29 diff --git a/src/lexer/SolsToken.h b/src/lexer/SolsToken.h new file mode 100644 index 0000000..a664659 --- /dev/null +++ b/src/lexer/SolsToken.h @@ -0,0 +1,40 @@ +#ifndef SOLSTOKEN_H +#define SOLSTOKEN_H + +#include "SolsType.h" +#include "SolsLiteral.h" + +typedef enum SolsTokenType { + STT_IDENTIFIER, STT_LITERAL, STT_TYPE, STT_OPEN_CURLY, STT_CLOSE_CURLY, STT_OPEN_PAREN, STT_CLOSE_PAREN, STT_OP_ADD, STT_OP_SUB, STT_OP_MUL, STT_OP_DIV, STT_OP_SET, STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER, STT_KW_DEF, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_GROUND +} SolsTokenType; + +// Represents a token lexed by the lex() function. +// Most token types exclusively use the .type field, however some tokens require storing +// more data, inside the .as union. +// Those tokens are: +// STT_LITERAL: A literal value. Uses field .as.literal +// STT_TYPE: A type descriptor. Uses field .as.type +// STT_IDENTIFIER: An identifier. Uses field .as.idName +// STT_KW_GROUND: Ground code embedded inside Solstice. Uses field .as.inlineGround +typedef struct SolsToken { + SolsTokenType type; + union { + SolsLiteral literal; + SolsType type; + char* idName; + char* inlineGround; + } as; +} SolsToken; + +// Represents a Solstice program, seperated into tokens. +// .at is a pointer to the tokens +// .count is how many tokens are currently being stored +// .capacity is how many tokens worth of memory is allocated +typedef struct SolsTokens { + SolsToken* at; + size_t count; + size_t capacity; +} SolsTokens; + + +#endif diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index e69de29..51e335a 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -0,0 +1,25 @@ +#include "lexer.h" +#include "../include/error.h" + +ResultType(SolsLexer, charptr) createLexer(char* input) { + char* inputcopy = malloc(strlen(input) + 1); + if (inputcopy == NULL) { + return Error(SolsLexer, charptr, "Couldn't copy string into lexer (in createLexer() function)"); + } + strcpy(inputcopy, input); + SolsLexer lexer = { + .input = inputcopy, + .current = 0, + }; + return Success(SolsLexer, charptr, lexer); +} + +ResultType(voidptr, charptr) lex(SolsLexer* lexer) { + if (lexer->input == NULL) { + return Error(voidptr, charptr, "Lexer is not initialised"); + } + + lexer->current = 0; + + return Success(voidptr, charptr, NULL); +} diff --git a/src/lexer/lexer.h b/src/lexer/lexer.h index 013f0d4..abe5850 100644 --- a/src/lexer/lexer.h +++ b/src/lexer/lexer.h @@ -8,55 +8,8 @@ #include "../include/error.h" #include "SolsType.h" - -typedef enum SolsTokenType { - STT_IDENTIFIER, STT_LITERAL, STT_TYPE, STT_OPEN_CURLY, STT_CLOSE_CURLY, STT_OPEN_PAREN, STT_CLOSE_PAREN, STT_OP_ADD, STT_OP_SUB, STT_OP_MUL, STT_OP_DIV, STT_OP_SET, STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER, STT_KW_DEF, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_GROUND -} SolsTokenType; - -typedef enum SolsLiteralType { - SLT_INT, SLT_STRING, SLT_DOUBLE, SLT_BOOL, SLT_CHAR -} SolsLiteralType; - -// Stores literal values which will be added to the Ground code. -// Not much explaining needed here. -typedef struct SolsLiteral { - SolsLiteralType type; - union { - int64_t intv; - char* stringv; - double doublev; - bool boolv; - char charv; - } as; -} SolsLiteral; - -// Represents a token lexed by the lex() function. -// Most token types exclusively use the .type field, however some tokens require storing -// more data, inside the .as union. -// Those tokens are: -// STT_LITERAL: A literal value. Uses field .as.literal -// STT_TYPE: A type descriptor. Uses field .as.type -// STT_IDENTIFIER: An identifier. Uses field .as.idName -// STT_KW_GROUND: Ground code embedded inside Solstice. Uses field .as.inlineGround -typedef struct SolsToken { - SolsTokenType type; - union { - SolsLiteral literal; - SolsType type; - char* idName; - char* inlineGround; - } as; -} SolsToken; - -// Represents a Solstice program, seperated into tokens. -// .at is a pointer to the tokens -// .count is how many tokens are currently being stored -// .capacity is how many tokens worth of memory is allocated -typedef struct SolsTokens { - SolsToken* at; - size_t count; - size_t capacity; -} SolsTokens; +#include "SolsToken.h" +#include "SolsLiteral.h" // Represents the current state of the lexer. // .input is the Solstice program as written by the user. @@ -69,9 +22,10 @@ typedef struct SolsLexer { } SolsLexer; // Creates a lexer for use by the lex() function. -SolsLexer createLexer(char* input); +Result(SolsLexer, charptr); +ResultType(SolsLexer, charptr) createLexer(char* input); // Uses the provided lexer to scan the code, and create tokens. -void lex(SolsLexer* lexer); +ResultType(voidptr, charptr) lex(SolsLexer* lexer); #endif diff --git a/src/main.c b/src/main.c index 7e22b22..71fa585 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,11 @@ #include "lexer/lexer.h" +#include int main() { + ResultType(SolsLexer, charptr) lexer = createLexer("puts \"dingus\""); + if (lexer.error) { + printf("Error while creating lexer: %s", lexer.as.error); + } + lex(&lexer.as.success); return 0; }