summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/ast-tree.c44
-rw-r--r--src/compiler/ast-tree.h1
-rw-r--r--src/compiler/lexer.c7
-rw-r--r--src/compiler/lexer.h1
-rw-r--r--src/compiler/parser.c139
-rw-r--r--src/compiler/parser.h9
-rw-r--r--src/main.c1
-rw-r--r--src/runner/runner.c12
-rw-r--r--src/utils/file.c2
-rw-r--r--src/utils/log.c1
-rw-r--r--src/utils/log.h1
-rw-r--r--src/utils/memory.c1
12 files changed, 165 insertions, 54 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index e2f31fc..b8fe4a0 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -7,7 +7,6 @@
#include "utils/string.h"
#include <stddef.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
AstTree AST_TREE_TYPE_TYPE = {
@@ -1321,6 +1320,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
case PARSER_TOKEN_VALUE_INT:
case PARSER_TOKEN_VALUE_FLOAT:
case PARSER_TOKEN_VALUE_CHAR:
+ case PARSER_TOKEN_VALUE_STRING:
case PARSER_TOKEN_FUNCTION_DEFINITION:
case PARSER_TOKEN_FUNCTION_CALL:
case PARSER_TOKEN_IDENTIFIER:
@@ -1552,6 +1552,8 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) {
case PARSER_TOKEN_VALUE_CHAR:
return astTreeParseValue(parserNode, AST_TREE_TOKEN_VALUE_INT,
sizeof(AstTreeInt), &AST_TREE_U8_TYPE);
+ case PARSER_TOKEN_VALUE_STRING:
+ return astTreeParseString(parserNode, helper);
case PARSER_TOKEN_KEYWORD_NULL:
return astTreeParseKeyword(parserNode, AST_TREE_TOKEN_VALUE_NULL);
case PARSER_TOKEN_KEYWORD_UNDEFINED:
@@ -1753,6 +1755,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) {
case PARSER_TOKEN_VALUE_FLOAT:
case PARSER_TOKEN_VALUE_BOOL:
case PARSER_TOKEN_VALUE_CHAR:
+ case PARSER_TOKEN_VALUE_STRING:
case PARSER_TOKEN_TYPE_TYPE:
case PARSER_TOKEN_TYPE_FUNCTION:
case PARSER_TOKEN_TYPE_VOID:
@@ -1999,6 +2002,44 @@ AstTree *astTreeParseValue(ParserNode *parserNode, AstTreeToken token,
parserNode->str_end);
}
+AstTree *astTreeParseString(ParserNode *parserNode, AstTreeHelper *helper) {
+ (void)helper;
+ ParserNodeStringMetadata *node_metadata = parserNode->metadata;
+
+ AstTreeObject *metadata = a404m_malloc(sizeof(*metadata));
+
+ metadata->variables.size = node_metadata->end - node_metadata->begin;
+ metadata->variables.data = a404m_malloc(metadata->variables.size *
+ sizeof(*metadata->variables.data));
+
+ for (size_t i = 0; i < metadata->variables.size; ++i) {
+ AstTreeInt *cellMetadata = a404m_malloc(sizeof(*cellMetadata));
+ *cellMetadata = node_metadata->begin[i];
+
+ metadata->variables.data[i] =
+ a404m_malloc(sizeof(*metadata->variables.data[i]));
+ metadata->variables.data[i]->isConst = false;
+ metadata->variables.data[i]->name_begin = NULL;
+ metadata->variables.data[i]->name_end = NULL;
+ metadata->variables.data[i]->type = copyAstTree(&AST_TREE_U8_TYPE);
+ metadata->variables.data[i]->value =
+ newAstTree(AST_TREE_TOKEN_VALUE_INT, cellMetadata,
+ copyAstTree(&AST_TREE_U8_TYPE), NULL, NULL);
+ }
+
+ AstTreeBracket *type_metadata = a404m_malloc(sizeof(*type_metadata));
+ type_metadata->operand = &AST_TREE_U8_TYPE;
+ type_metadata->parameters.size = 1;
+ type_metadata->parameters.data = a404m_malloc(
+ type_metadata->parameters.size * sizeof(*type_metadata->parameters.data));
+ type_metadata->parameters.data[0] = &AST_TREE_U8_TYPE;
+
+ return newAstTree(AST_TREE_TOKEN_VALUE_OBJECT, metadata,
+ newAstTree(AST_TREE_TOKEN_TYPE_ARRAY, type_metadata,
+ &AST_TREE_TYPE_TYPE, NULL, NULL),
+ parserNode->str_begin, parserNode->str_end);
+}
+
AstTree *astTreeParseKeyword(ParserNode *parserNode, AstTreeToken token) {
return newAstTree(token, NULL, NULL, parserNode->str_begin,
parserNode->str_end);
@@ -2293,6 +2334,7 @@ AstTree *astTreeParseCurlyBracket(ParserNode *parserNode,
case PARSER_TOKEN_VALUE_FLOAT:
case PARSER_TOKEN_VALUE_BOOL:
case PARSER_TOKEN_VALUE_CHAR:
+ case PARSER_TOKEN_VALUE_STRING:
case PARSER_TOKEN_TYPE_TYPE:
case PARSER_TOKEN_TYPE_FUNCTION:
case PARSER_TOKEN_TYPE_VOID:
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index 988b48c..a5af775 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -292,6 +292,7 @@ AstTree *astTreeParseFunctionCall(ParserNode *parserNode,
AstTree *astTreeParseIdentifier(ParserNode *parserNode, AstTreeHelper *helper);
AstTree *astTreeParseValue(ParserNode *parserNode, AstTreeToken token,
size_t metadata_size, AstTree *type);
+AstTree *astTreeParseString(ParserNode *parserNode, AstTreeHelper *helper);
AstTree *astTreeParseKeyword(ParserNode *parserNode, AstTreeToken token);
AstTree *astTreeParsePrintU64(ParserNode *parserNode, AstTreeHelper *helper);
AstTree *astTreeParseReturn(ParserNode *parserNode, AstTreeHelper *helper);
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index 53d9f05..754593a 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -6,7 +6,6 @@
#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET",
@@ -37,6 +36,7 @@ const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_KEYWORD_NULL",
"LEXER_TOKEN_NUMBER",
"LEXER_TOKEN_CHAR",
+ "LEXER_TOKEN_STRING",
"LEXER_TOKEN_KEYWORD_UNDEFINED",
"LEXER_TOKEN_SYMBOL_FUNCTION_ARROW",
@@ -244,6 +244,8 @@ LexerNodeArray lexer(char *str) {
LexerToken token;
if (opening == '\'') {
token = LEXER_TOKEN_CHAR;
+ } else if (opening == '\"') {
+ token = LEXER_TOKEN_STRING;
} else {
UNREACHABLE;
}
@@ -258,7 +260,7 @@ LexerNodeArray lexer(char *str) {
goto RETURN_ERROR;
} else if (*iter == '\\') {
++iter;
- } else if (*iter == '\'') {
+ } else if (*iter == opening) {
break;
}
}
@@ -357,6 +359,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
case LEXER_TOKEN_KEYWORD_UNDEFINED:
case LEXER_TOKEN_NUMBER:
case LEXER_TOKEN_CHAR:
+ case LEXER_TOKEN_STRING:
case LEXER_TOKEN_SYMBOL_EOL:
case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
case LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS:
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index ad82b5a..a9b6dcd 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -35,6 +35,7 @@ typedef enum LexerToken {
LEXER_TOKEN_KEYWORD_NULL,
LEXER_TOKEN_NUMBER,
LEXER_TOKEN_CHAR,
+ LEXER_TOKEN_STRING,
LEXER_TOKEN_KEYWORD_UNDEFINED,
LEXER_TOKEN_SYMBOL_FUNCTION_ARROW,
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index ae2db33..6f3e956 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -19,6 +19,7 @@ const char *PARSER_TOKEN_STRINGS[] = {
"PARSER_TOKEN_VALUE_FLOAT",
"PARSER_TOKEN_VALUE_BOOL",
"PARSER_TOKEN_VALUE_CHAR",
+ "PARSER_TOKEN_VALUE_STRING",
"PARSER_TOKEN_TYPE_TYPE",
"PARSER_TOKEN_TYPE_FUNCTION",
@@ -260,6 +261,12 @@ void parserNodePrint(const ParserNode *node, int indent) {
printf(",value=%c", (char)*metadata);
}
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_VALUE_STRING: {
+ ParserNodeStringMetadata *metadata = node->metadata;
+ printf(",value=%.*s", (int)(metadata->end - metadata->begin),
+ metadata->begin);
+ }
+ goto RETURN_SUCCESS;
case PARSER_TOKEN_CONSTANT:
case PARSER_TOKEN_VARIABLE: {
const ParserNodeVariableMetadata *metadata = node->metadata;
@@ -536,6 +543,12 @@ void parserNodeDelete(ParserNode *node) {
free(metadata);
}
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_VALUE_STRING: {
+ ParserNodeStringMetadata *metadata = node->metadata;
+ free(metadata->begin);
+ free(metadata);
+ }
+ goto RETURN_SUCCESS;
case PARSER_TOKEN_CONSTANT:
case PARSER_TOKEN_VARIABLE: {
ParserNodeVariableMetadata *metadata = node->metadata;
@@ -799,6 +812,8 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
return parserNumber(node, parent);
case LEXER_TOKEN_CHAR:
return parserChar(node, parent);
+ case LEXER_TOKEN_STRING:
+ return parserString(node, parent);
case LEXER_TOKEN_SYMBOL_ASSIGN:
return parserBinaryOperator(node, begin, end, parent,
PARSER_TOKEN_OPERATOR_ASSIGN);
@@ -1077,57 +1092,57 @@ ParserNode *parserChar(LexerNode *node, ParserNode *parent) {
if (size == 0) {
printError(node->str_begin, node->str_end,
"Bad character: Character can't be empty");
- return NULL;
+ goto RETURN_ERROR;
} else if (size == 1) {
// knowingly left empty
} else if (size == 2 && c == '\\') {
- c = node->str_begin[2];
- switch (c) {
- case 'a':
- c = '\a';
- break;
- case 'b':
- c = '\b';
- break;
- case 'e':
- c = '\e';
- break;
- case 'f':
- c = '\f';
- break;
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case 't':
- c = '\t';
- break;
- case 'v':
- c = '\v';
- break;
- case '\\':
- c = '\\';
- break;
- case '\'':
- c = '\'';
- break;
- case '"':
- c = '\"';
- break;
- default:
+ bool success;
+ c = escapeChar(node->str_begin + 2, node->str_end, &success);
+ if (!success) {
printError(node->str_begin, node->str_end, "Bad escape character");
- return NULL;
+ goto RETURN_ERROR;
}
} else {
printError(node->str_begin, node->str_end, "Bad character");
- return NULL;
+ goto RETURN_ERROR;
}
*metadata = c;
return node->parserNode =
newParserNode(PARSER_TOKEN_VALUE_CHAR, node->str_begin,
node->str_end, metadata, parent);
+RETURN_ERROR:
+ free(metadata);
+ return NULL;
+}
+
+ParserNode *parserString(LexerNode *node, ParserNode *parent) {
+ ParserNodeStringMetadata *metadata = a404m_malloc(sizeof(*metadata));
+
+ metadata->begin = metadata->end = a404m_malloc(
+ sizeof(*metadata->begin) * (node->str_end - node->str_begin));
+
+ for (char *iter = node->str_begin + 1; iter < node->str_end - 2; ++iter) {
+ if (*iter == '\\') {
+ iter += 1;
+ bool success;
+ *metadata->end = escapeChar(iter, node->str_end, &success);
+ if (!success) {
+ printError(node->str_begin, node->str_end, "Bad escape character");
+ goto RETURN_ERROR;
+ }
+ } else {
+ *metadata->end = *iter;
+ }
+ metadata->end += 1;
+ }
+
+ return node->parserNode =
+ newParserNode(PARSER_TOKEN_VALUE_STRING, node->str_begin,
+ node->str_end, metadata, parent);
+RETURN_ERROR:
+ free(metadata->begin);
+ free(metadata);
+ return NULL;
}
ParserNode *parserBoolValue(LexerNode *node, ParserNode *parent) {
@@ -1464,6 +1479,7 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end,
case PARSER_TOKEN_VALUE_FLOAT:
case PARSER_TOKEN_VALUE_BOOL:
case PARSER_TOKEN_VALUE_CHAR:
+ case PARSER_TOKEN_VALUE_STRING:
case PARSER_TOKEN_TYPE_TYPE:
case PARSER_TOKEN_TYPE_FUNCTION:
case PARSER_TOKEN_TYPE_VOID:
@@ -1958,6 +1974,7 @@ bool isExpression(ParserNode *node) {
case PARSER_TOKEN_VALUE_FLOAT:
case PARSER_TOKEN_VALUE_BOOL:
case PARSER_TOKEN_VALUE_CHAR:
+ case PARSER_TOKEN_VALUE_STRING:
case PARSER_TOKEN_KEYWORD_IF:
case PARSER_TOKEN_KEYWORD_WHILE:
case PARSER_TOKEN_KEYWORD_COMPTIME:
@@ -2039,6 +2056,7 @@ bool isType(ParserNode *node) {
case PARSER_TOKEN_VALUE_FLOAT:
case PARSER_TOKEN_VALUE_BOOL:
case PARSER_TOKEN_VALUE_CHAR:
+ case PARSER_TOKEN_VALUE_STRING:
case PARSER_TOKEN_KEYWORD_PUTC:
case PARSER_TOKEN_KEYWORD_RETURN:
case PARSER_TOKEN_OPERATOR_ASSIGN:
@@ -2079,6 +2097,7 @@ bool isValue(ParserNode *node) {
case PARSER_TOKEN_VALUE_FLOAT:
case PARSER_TOKEN_VALUE_BOOL:
case PARSER_TOKEN_VALUE_CHAR:
+ case PARSER_TOKEN_VALUE_STRING:
case PARSER_TOKEN_IDENTIFIER:
case PARSER_TOKEN_BUILTIN:
case PARSER_TOKEN_OPERATOR_ACCESS:
@@ -2148,3 +2167,45 @@ bool isValue(ParserNode *node) {
}
UNREACHABLE;
}
+
+char escapeChar(char *begin, char *end, bool *success) {
+ (void)end;
+ switch (*begin) {
+ case 'a':
+ *success = true;
+ return '\a';
+ case 'b':
+ *success = true;
+ return '\b';
+ case 'e':
+ *success = true;
+ return '\e';
+ case 'f':
+ *success = true;
+ return '\f';
+ case 'n':
+ *success = true;
+ return '\n';
+ case 'r':
+ *success = true;
+ return '\r';
+ case 't':
+ *success = true;
+ return '\t';
+ case 'v':
+ *success = true;
+ return '\v';
+ case '\\':
+ *success = true;
+ return '\\';
+ case '\'':
+ *success = true;
+ return '\'';
+ case '"':
+ *success = true;
+ return '\"';
+ default:
+ *success = false;
+ return 0;
+ }
+}
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index 120ae39..326849b 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -15,6 +15,7 @@ typedef enum ParserToken {
PARSER_TOKEN_VALUE_FLOAT,
PARSER_TOKEN_VALUE_BOOL,
PARSER_TOKEN_VALUE_CHAR,
+ PARSER_TOKEN_VALUE_STRING,
PARSER_TOKEN_TYPE_TYPE,
PARSER_TOKEN_TYPE_FUNCTION,
@@ -139,6 +140,11 @@ typedef f128 ParserNodeFloatMetadata;
typedef ParserNodeIntMetadata ParserNodeCharMetadata;
+typedef struct ParserNodeStringMetadata {
+ char *begin;
+ char *end;
+} ParserNodeStringMetadata;
+
typedef struct ParserNodeInfixMetadata {
ParserNode *left;
ParserNode *right;
@@ -192,6 +198,7 @@ ParserNode *parserPutc(LexerNode *node, LexerNode *end, ParserNode *parent);
ParserNode *parserReturn(LexerNode *node, LexerNode *end, ParserNode *parent);
ParserNode *parserNumber(LexerNode *node, ParserNode *parent);
ParserNode *parserChar(LexerNode *node, ParserNode *parent);
+ParserNode *parserString(LexerNode *node, ParserNode *parent);
ParserNode *parserBoolValue(LexerNode *node, ParserNode *parent);
ParserNode *parserEol(LexerNode *node, LexerNode *begin, ParserNode *parent);
ParserNode *parserComma(LexerNode *node, LexerNode *begin, ParserNode *parent);
@@ -228,3 +235,5 @@ bool isAllArguments(const ParserNodeArray *nodes);
bool isExpression(ParserNode *node);
bool isType(ParserNode *node);
bool isValue(ParserNode *node);
+
+char escapeChar(char *begin,char *end, bool *success);
diff --git a/src/main.c b/src/main.c
index 6694521..a5721d3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,7 +2,6 @@
#include "utils/file.h"
#include "utils/log.h"
#include <stdio.h>
-#include <stdlib.h>
#include <time.h>
// #define PRINT_COMPILE_TREE
diff --git a/src/runner/runner.c b/src/runner/runner.c
index a0bceed..9490d91 100644
--- a/src/runner/runner.c
+++ b/src/runner/runner.c
@@ -3,7 +3,6 @@
#include "utils/log.h"
#include "utils/memory.h"
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#define doOperation(op0, op1, operator, originalType, type) \
@@ -28,7 +27,6 @@
void runnerVariableSetValue(AstTreeVariable *variable, AstTree *value) {
if (variable->isConst) {
- *(u8 *)0 = 0;
UNREACHABLE;
}
runnerVariableSetValueWihtoutConstCheck(variable, value);
@@ -1185,11 +1183,11 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet,
for (size_t i = 0; i < newMetadata->variables.size; ++i) {
AstTreeVariable *member = newMetadata->variables.data[i];
if (!member->isConst) {
- runnerVariableSetValue(
- member,
- newAstTree(AST_TREE_TOKEN_VALUE_UNDEFINED, NULL,
- copyAstTree(member->type), variable->value->str_begin,
- variable->value->str_end));
+ runnerVariableSetValue(member,
+ newAstTree(AST_TREE_TOKEN_VALUE_UNDEFINED,
+ NULL, copyAstTree(member->type),
+ variable->value->str_begin,
+ variable->value->str_end));
}
}
diff --git a/src/utils/file.c b/src/utils/file.c
index 921befb..6d737f7 100644
--- a/src/utils/file.c
+++ b/src/utils/file.c
@@ -2,9 +2,7 @@
#include "utils/log.h"
#include "utils/memory.h"
-#include <stddef.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
size_t fileCodes_capacity = 0;
diff --git a/src/utils/log.c b/src/utils/log.c
index 9b8f94f..e8eb047 100644
--- a/src/utils/log.c
+++ b/src/utils/log.c
@@ -4,7 +4,6 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
void _printLogBack(const char *format, const char *file, int line, ...) {
diff --git a/src/utils/log.h b/src/utils/log.h
index eb9034f..bcc7aa1 100644
--- a/src/utils/log.h
+++ b/src/utils/log.h
@@ -1,6 +1,7 @@
#pragma once
#include "utils/type.h"
+#include <stdlib.h>
#ifndef __FILE_NAME__
#define __FILE_NAME__ __FILE__
diff --git a/src/utils/memory.c b/src/utils/memory.c
index cde2995..bf3de92 100644
--- a/src/utils/memory.c
+++ b/src/utils/memory.c
@@ -1,6 +1,5 @@
#include "memory.h"
-#include <stdlib.h>
#include <malloc.h>
void *a404m_malloc(size_t size) {