summaryrefslogtreecommitdiff
path: root/src/compiler/parser.c
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-04-15 21:54:04 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-04-15 21:54:04 +0330
commitcc12a3a946303ae89ce2076b3c17d5d35d7e864f (patch)
tree3429c081fecb65cf538b213e382016416dbca344 /src/compiler/parser.c
parent52fac2c9232d39b3fe98438a47c22f985b260f58 (diff)
add string
Diffstat (limited to 'src/compiler/parser.c')
-rw-r--r--src/compiler/parser.c139
1 files changed, 100 insertions, 39 deletions
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;
+ }
+}