summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-01-27 01:25:24 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-01-27 01:25:24 +0330
commit64331c144518b8ab1c3cf08473771e0d3f14f67b (patch)
treec378fccbddcc4e0972a7a426b4bf464efc1129bf
parentbb87887ec288f341256d324f271bac6267fc83f4 (diff)
add print_u64 to be able to print u64 numbers
-rw-r--r--src/compiler/ast-tree.c66
-rw-r--r--src/compiler/ast-tree.h11
-rw-r--r--src/compiler/code-generator.c43
-rw-r--r--src/compiler/code-generator.h6
-rw-r--r--src/compiler/lexer.c4
-rw-r--r--src/compiler/lexer.h1
-rw-r--r--src/compiler/parser.c80
-rw-r--r--src/compiler/parser.h10
-rw-r--r--src/main.c2
-rw-r--r--src/utils/string.c18
-rw-r--r--src/utils/string.h7
-rw-r--r--test/main.felan10
12 files changed, 222 insertions, 36 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 729aa18..22ce146 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -7,9 +7,14 @@
#include <string.h>
const char *AST_TREE_TOKEN_STRINGS[] = {
- "AST_TREE_TOKEN_FUNCTION", "AST_TREE_TOKEN_KEYWORD_PRINT",
- "AST_TREE_TOKEN_NONE", "AST_TREE_TOKEN_TYPE_FUNCTION",
- "AST_TREE_TOKEN_TYPE_VOID", "AST_TREE_TOKEN_FUNCTION_CALL",
+ "AST_TREE_TOKEN_FUNCTION",
+ "AST_TREE_TOKEN_KEYWORD_PRINT",
+ "AST_TREE_TOKEN_KEYWORD_PRINT_U64",
+
+ "AST_TREE_TOKEN_NONE",
+ "AST_TREE_TOKEN_TYPE_FUNCTION",
+ "AST_TREE_TOKEN_TYPE_VOID",
+ "AST_TREE_TOKEN_FUNCTION_CALL",
"AST_TREE_TOKEN_IDENTIFIER",
};
@@ -58,6 +63,20 @@ void astTreePrint(const AstTree *tree, int indent) {
case AST_TREE_TOKEN_KEYWORD_PRINT:
case AST_TREE_TOKEN_TYPE_VOID:
goto RETURN_SUCCESS;
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
+ AstTreeSingleChild *metadata = tree->metadata;
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("child=\n");
+ astTreePrint(metadata, indent + 1);
+ }
+ goto RETURN_SUCCESS;
+ case AST_TREE_TOKEN_VALUE_U64: {
+ AstTreeU64 metadata = (AstTreeU64)tree->metadata;
+ printf(",value=%lu", metadata);
+ }
+ goto RETURN_SUCCESS;
case AST_TREE_TOKEN_TYPE_FUNCTION: {
AstTreeTypeFunction *metadata = tree->metadata;
printf(",\n");
@@ -143,6 +162,12 @@ void astTreeDestroy(AstTree tree) {
return;
case AST_TREE_TOKEN_KEYWORD_PRINT:
case AST_TREE_TOKEN_TYPE_VOID:
+ case AST_TREE_TOKEN_VALUE_U64:
+ return;
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
+ AstTreeSingleChild *metadata = tree.metadata;
+ astTreeDelete(metadata);
+ }
return;
case AST_TREE_TOKEN_TYPE_FUNCTION: {
AstTreeTypeFunction *metadata = tree.metadata;
@@ -224,7 +249,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
printLog("Unexpected %s", PARSER_TOKEN_STRINGS[eol->token]);
goto RETURN_ERROR;
}
- ParserNode *node = (ParserNodeEOLMetadata *)eol->metadata;
+ ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata;
if (node->token != PARSER_TOKEN_CONSTANT) {
printLog("Unexpected %s", PARSER_TOKEN_STRINGS[node->token]);
goto RETURN_ERROR;
@@ -239,7 +264,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
}
for (size_t i = 0; i < nodes->size; ++i) {
- ParserNode *node = (ParserNodeEOLMetadata *)nodes->data[i]->metadata;
+ ParserNode *node =
+ (ParserNodeSingleChildMetadata *)nodes->data[i]->metadata;
ParserNodeVariableMetadata *node_metadata = node->metadata;
AstTree *type;
@@ -319,6 +345,12 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables,
return astTreeParseFunctionCall(parserNode, variables, variables_size);
case PARSER_TOKEN_IDENTIFIER:
return astTreeParseIdentifier(parserNode, variables, variables_size);
+ case PARSER_TOKEN_VALUE_U64:
+ return newAstTree(
+ AST_TREE_TOKEN_VALUE_U64,
+ (void *)(AstTreeU64)(ParserNodeU64Metadata)parserNode->metadata);
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
+ return astTreeParsePrintU64(parserNode, variables, variables_size);
case PARSER_TOKEN_SYMBOL_EOL:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
@@ -393,7 +425,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode,
printLog("Unexpected %s", PARSER_TOKEN_STRINGS[eol->token]);
goto RETURN_ERROR;
}
- ParserNode *node = (ParserNodeEOLMetadata *)eol->metadata;
+ ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata;
AstTree *tree = astTreeParse(node, variables, variables_size);
if (tree == NULL) {
@@ -528,6 +560,22 @@ AstTree *astTreeParseIdentifier(ParserNode *parserNode,
return newAstTree(AST_TREE_TOKEN_IDENTIFIER, (AstTreeIdentifier *)var);
}
+AstTree *astTreeParsePrintU64(ParserNode *parserNode,
+ AstTreeVariables *variables,
+ size_t variables_size) {
+ ParserNodeSingleChildMetadata *node_metadata = parserNode->metadata;
+
+ AstTree *operand = astTreeParse(node_metadata, variables, variables_size);
+ if (operand == NULL) {
+ return NULL;
+ }
+
+ // TODO: check type to be u64
+
+ return newAstTree(AST_TREE_TOKEN_KEYWORD_PRINT_U64,
+ (AstTreeSingleChild *)operand);
+}
+
bool hasTypeOf(AstTree *value, AstTree *type) {
switch (type->token) {
case AST_TREE_TOKEN_TYPE_FUNCTION:
@@ -576,9 +624,9 @@ bool typeIsEqual(AstTree *type0, AstTree *type1) {
case AST_TREE_TOKEN_TYPE_VOID:
return type1->token == AST_TREE_TOKEN_TYPE_VOID;
case AST_TREE_TOKEN_TYPE_FUNCTION:
- if(type1->token != AST_TREE_TOKEN_TYPE_FUNCTION){
- return false;
- }
+ if (type1->token != AST_TREE_TOKEN_TYPE_FUNCTION) {
+ return false;
+ }
printLog("Not implemented yet");
exit(1);
case AST_TREE_TOKEN_FUNCTION_CALL:
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index e92cb08..8a7617d 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -2,14 +2,17 @@
#include "compiler/parser.h"
#include <stddef.h>
+#include <stdint.h>
typedef enum AstTreeToken {
AST_TREE_TOKEN_FUNCTION,
AST_TREE_TOKEN_KEYWORD_PRINT,
+ AST_TREE_TOKEN_KEYWORD_PRINT_U64,
AST_TREE_TOKEN_TYPE_FUNCTION,
AST_TREE_TOKEN_TYPE_VOID,
AST_TREE_TOKEN_FUNCTION_CALL,
AST_TREE_TOKEN_IDENTIFIER,
+ AST_TREE_TOKEN_VALUE_U64,
AST_TREE_TOKEN_NONE,
} AstTreeToken;
@@ -62,6 +65,10 @@ typedef struct AstTreeFunctionCall {
typedef AstTreeVariable AstTreeIdentifier;
+typedef uint64_t AstTreeU64;
+
+typedef AstTree AstTreeSingleChild;
+
extern const char *AST_TREE_TOKEN_STRINGS[];
void astTreePrint(const AstTree *tree, int indent);
@@ -100,5 +107,9 @@ AstTree *astTreeParseIdentifier(ParserNode *parserNode,
AstTreeVariables *variables,
size_t variables_size);
+AstTree *astTreeParsePrintU64(ParserNode *parserNode,
+ AstTreeVariables *variables,
+ size_t variables_size);
+
bool hasTypeOf(AstTree *value, AstTree *type);
bool typeIsEqual(AstTree *type0, AstTree *type1);
diff --git a/src/compiler/code-generator.c b/src/compiler/code-generator.c
index d9fc05d..fb843d0 100644
--- a/src/compiler/code-generator.c
+++ b/src/compiler/code-generator.c
@@ -3,6 +3,7 @@
#include "utils/log.h"
#include "utils/memory.h"
#include <assert.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -12,6 +13,7 @@ void codeGeneratorDelete(CodeGeneratorCodes *code) {
CodeGeneratorCode current = code->codes[i];
switch (current.instruction) {
case CODE_GENERATOR_INSTRUCTION_PRINT:
+ case CODE_GENERATOR_INSTRUCTION_PRINT_U64:
case CODE_GENERATOR_INSTRUCTION_RET:
continue;
case CODE_GENERATOR_INSTRUCTION_CALL: {
@@ -122,6 +124,21 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end,
callMetadata));
}
goto OK;
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
+ AstTreeSingleChild *metadata = tree.metadata;
+ if (metadata->token == AST_TREE_TOKEN_VALUE_U64) {
+ CodeGeneratorOperandU64 value = (AstTreeU64)metadata->metadata;
+ generateCodePushCode(
+ codes, createGenerateCode(label_begin, label_end,
+ CODE_GENERATOR_INSTRUCTION_PRINT_U64,
+ (void *)value));
+ } else {
+ printLog("Not implemented yet");
+ exit(1);
+ }
+ }
+ goto OK;
+ case AST_TREE_TOKEN_VALUE_U64:
case AST_TREE_TOKEN_IDENTIFIER:
case AST_TREE_TOKEN_FUNCTION:
case AST_TREE_TOKEN_TYPE_FUNCTION:
@@ -143,13 +160,16 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end,
}
static const char TEMPLATE[] =
- "format ELF64 executable 3\nSYS_exit = 60\nSYS_write = 1\nSTDOUT = "
- "1\nsegment readable writable\nhello: db \"Hello, "
- "World!\",0xa\nhello_len = $-hello\nsegment readable executable\nentry "
- "_start\nprint:\nmov rax, SYS_write\nmov rdi, STDOUT\nmov rsi, "
- "hello\nmov rdx, hello_len\nsyscall\nret\n_start:\ncall main\nmov rax, "
- "SYS_exit\nxor "
- "rdi,rdi\nsyscall\n";
+ "format ELF64 executable 3\n\nSYS_exit = 60\nSYS_write = 1\nSTDOUT = "
+ "1\n\nsegment readable writable\nhello: db \"Hello, "
+ "World!\",0xa\nhello_len = $-hello\n\nsegment readable executable\nentry "
+ "_start\n\nprint:\nmov rax, SYS_write\nmov rdi, STDOUT\nmov rsi, "
+ "hello\nmov rdx, hello_len\nsyscall\nret\n\n; rdi = the "
+ "number\nprint_u64:\nmov rcx, rsp\nmov rax, rdi\nmov rbx, 10\n\n.L:\nxor "
+ "rdx, rdx\ndiv rbx\nadd dl, '0'\ndec rcx\nmov [rcx],dl\ncmp rax, 0\njnz "
+ ".L\n\nmov rax, SYS_write\nmov rdi, STDOUT\nmov rsi, rcx\n\nmov rdx, "
+ "rsp\nsub rdx, rcx\n\nsyscall\nret\n\n_start:\ncall main\nmov rax, "
+ "SYS_exit\nxor rdi,rdi\nsyscall\n";
static const size_t TEMPLATE_LEN =
sizeof(TEMPLATE) / sizeof(*TEMPLATE) - sizeof(*TEMPLATE);
@@ -191,6 +211,15 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) {
strlen(INST));
}
continue;
+ case CODE_GENERATOR_INSTRUCTION_PRINT_U64: {
+ CodeGeneratorOperandU64 metadata = (CodeGeneratorOperandU64)code.metadata;
+ char *inst;
+ asprintf(&inst, "mov rdi,%lu\ncall print_u64\n", (uint64_t)metadata);
+ codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, inst,
+ strlen(inst));
+ free(inst);
+ }
+ continue;
case CODE_GENERATOR_INSTRUCTION_CALL: {
CodeGeneratorCall *metadata = code.metadata;
constexpr char CALL_INST[] = "call ";
diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h
index 94552ed..ace6e97 100644
--- a/src/compiler/code-generator.h
+++ b/src/compiler/code-generator.h
@@ -6,6 +6,7 @@
typedef enum CodeGeneratorInstruction : uint8_t {
CODE_GENERATOR_INSTRUCTION_PRINT,
+ CODE_GENERATOR_INSTRUCTION_PRINT_U64,
CODE_GENERATOR_INSTRUCTION_CALL,
CODE_GENERATOR_INSTRUCTION_RET,
} CodeGeneratorInstruction;
@@ -22,6 +23,8 @@ typedef struct CodeGeneratorCall {
char *label_end;
} CodeGeneratorCall;
+typedef uint64_t CodeGeneratorOperandU64;
+
typedef struct CodeGeneratorCodes {
CodeGeneratorCode *codes;
size_t codes_size;
@@ -30,7 +33,8 @@ typedef struct CodeGeneratorCodes {
void codeGeneratorDelete(CodeGeneratorCodes *code);
CodeGeneratorCode createGenerateCode(char *label_begin, char *label_end,
- CodeGeneratorInstruction instruction,void *metadata);
+ CodeGeneratorInstruction instruction,
+ void *metadata);
CodeGeneratorCode *newGenerateCode(char *label_begin, char *label_end,
CodeGeneratorInstruction instruction);
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index 8994bce..8b8b6bb 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -12,6 +12,7 @@ const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_IDENTIFIER",
"LEXER_TOKEN_KEYWORD_VOID",
"LEXER_TOKEN_KEYWORD_PRINT",
+ "LEXER_TOKEN_KEYWORD_PRINT_U64",
"LEXER_TOKEN_NUMBER",
@@ -47,10 +48,12 @@ const size_t LEXER_SYMBOL_SIZE =
const char *LEXER_KEYWORD_STRINGS[] = {
"void",
"print",
+ "print_u64",
};
const LexerToken LEXER_KEYWORD_TOKENS[] = {
LEXER_TOKEN_KEYWORD_VOID,
LEXER_TOKEN_KEYWORD_PRINT,
+ LEXER_TOKEN_KEYWORD_PRINT_U64,
};
const size_t LEXER_KEYWORD_SIZE =
sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS);
@@ -169,6 +172,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
PUSH:
case LEXER_TOKEN_KEYWORD_VOID:
case LEXER_TOKEN_KEYWORD_PRINT:
+ case LEXER_TOKEN_KEYWORD_PRINT_U64:
case LEXER_TOKEN_NUMBER:
case LEXER_TOKEN_SYMBOL_EOL:
case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index f77522d..c3871e0 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -6,6 +6,7 @@ typedef enum LexerToken {
LEXER_TOKEN_IDENTIFIER,
LEXER_TOKEN_KEYWORD_VOID,
LEXER_TOKEN_KEYWORD_PRINT,
+ LEXER_TOKEN_KEYWORD_PRINT_U64,
LEXER_TOKEN_NUMBER,
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index 14125cc..333d755 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -2,6 +2,7 @@
#include "compiler/lexer.h"
#include "utils/log.h"
#include "utils/memory.h"
+#include "utils/string.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@@ -12,10 +13,13 @@ const char *PARSER_TOKEN_STRINGS[] = {
"PARSER_TOKEN_IDENTIFIER",
+ "PARSER_TOKEN_VALUE_U64",
+
"PARSER_TOKEN_TYPE_FUNCTION",
"PARSER_TOKEN_TYPE_VOID",
"PARSER_TOKEN_KEYWORD_PRINT",
+ "PARSER_TOKEN_KEYWORD_PRINT_U64",
"PARSER_TOKEN_CONSTANT",
@@ -42,12 +46,13 @@ static constexpr ParserOrder PARSER_ORDER[] = {
},
{
.ltr = true,
- .size = 3,
+ .size = 4,
.data =
{
LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS,
LEXER_TOKEN_IDENTIFIER,
LEXER_TOKEN_KEYWORD_VOID,
+ LEXER_TOKEN_NUMBER,
},
},
{
@@ -60,11 +65,12 @@ static constexpr ParserOrder PARSER_ORDER[] = {
},
{
.ltr = true,
- .size = 2,
+ .size = 3,
.data =
{
LEXER_TOKEN_SYMBOL_COLON,
LEXER_TOKEN_KEYWORD_PRINT,
+ LEXER_TOKEN_KEYWORD_PRINT_U64,
},
},
{
@@ -111,6 +117,11 @@ void parserNodePrint(const ParserNode *node, int indent) {
case PARSER_TOKEN_TYPE_VOID:
case PARSER_TOKEN_KEYWORD_PRINT:
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_VALUE_U64: {
+ ParserNodeU64Metadata metadata = (ParserNodeU64Metadata)node->metadata;
+ printf(",operand=%lu", metadata);
+ }
+ goto RETURN_SUCCESS;
case PARSER_TOKEN_CONSTANT: {
const ParserNodeVariableMetadata *metadata = node->metadata;
printf(",\n");
@@ -133,9 +144,10 @@ void parserNodePrint(const ParserNode *node, int indent) {
printf(" ");
}
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
case PARSER_TOKEN_SYMBOL_COMMA:
case PARSER_TOKEN_SYMBOL_EOL: {
- const ParserNodeEOLMetadata *metadata = node->metadata;
+ const ParserNodeSingleChildMetadata *metadata = node->metadata;
printf(",\n");
for (int i = 0; i < indent; ++i)
printf(" ");
@@ -233,6 +245,7 @@ void parserNodeDelete(ParserNode *node) {
case PARSER_TOKEN_IDENTIFIER:
case PARSER_TOKEN_TYPE_VOID:
case PARSER_TOKEN_KEYWORD_PRINT:
+ case PARSER_TOKEN_VALUE_U64:
goto RETURN_SUCCESS;
case PARSER_TOKEN_CONSTANT: {
ParserNodeVariableMetadata *metadata = node->metadata;
@@ -242,9 +255,10 @@ void parserNodeDelete(ParserNode *node) {
free(metadata);
}
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
case PARSER_TOKEN_SYMBOL_COMMA:
case PARSER_TOKEN_SYMBOL_EOL: {
- ParserNodeEOLMetadata *metadata = node->metadata;
+ ParserNodeSingleChildMetadata *metadata = node->metadata;
parserNodeDelete(metadata);
}
goto RETURN_SUCCESS;
@@ -384,6 +398,8 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
return parserVoid(node, parent);
case LEXER_TOKEN_KEYWORD_PRINT:
return parserPrint(node, parent);
+ case LEXER_TOKEN_KEYWORD_PRINT_U64:
+ return parserPrintU64(node, end, parent);
case LEXER_TOKEN_SYMBOL_EOL:
return parserEol(node, begin, parent);
case LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS:
@@ -396,8 +412,9 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
return parserVariable(node, begin, end, parent);
case LEXER_TOKEN_SYMBOL_COMMA:
return parserComma(node, begin, parent);
- case LEXER_TOKEN_NONE:
case LEXER_TOKEN_NUMBER:
+ return parserNumber(node, parent);
+ case LEXER_TOKEN_NONE:
case LEXER_TOKEN_SYMBOL:
case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
case LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET:
@@ -431,6 +448,49 @@ ParserNode *parserPrint(LexerNode *node, ParserNode *parent) {
node->str_end, NULL, parent);
}
+ParserNode *parserPrintU64(LexerNode *node, LexerNode *end,
+ ParserNode *parent) {
+ LexerNode *afterNode = node + 1;
+ if (afterNode >= end) {
+ printLog("No param");
+ return NULL;
+ } else if (afterNode->parserNode == NULL) {
+ printLog("Bad param");
+ return NULL;
+ }
+
+ ParserNode *operand = getUntilCommonParent(afterNode->parserNode, parent);
+ if (operand == NULL) {
+ printLog("No param");
+ return NULL;
+ }
+
+ return operand->parent = node->parserNode = newParserNode(
+ PARSER_TOKEN_KEYWORD_PRINT_U64, node->str_begin, node->str_end,
+ (ParserNodeSingleChildMetadata *)operand, parent);
+}
+
+ParserNode *parserNumber(LexerNode *node, ParserNode *parent) {
+ ParserNode *parserNode;
+ switch (*node->str_begin) {
+ case '0':
+ printLog("Not implemented");
+ return NULL;
+ default: {
+ bool success;
+ uint64_t value = decimalToU64(node->str_begin, node->str_end, &success);
+ if (!success) {
+ printLog("Error in parsing number");
+ return NULL;
+ }
+ parserNode =
+ newParserNode(PARSER_TOKEN_VALUE_U64, node->str_begin, node->str_end,
+ (void *)(ParserNodeU64Metadata)value, parent);
+ }
+ }
+ return node->parserNode = parserNode;
+}
+
ParserNode *parserEol(LexerNode *node, LexerNode *begin, ParserNode *parent) {
LexerNode *nodeBeore = node - 1;
ParserNode *parserNodeBefore;
@@ -448,7 +508,7 @@ ParserNode *parserEol(LexerNode *node, LexerNode *begin, ParserNode *parent) {
}
ParserNode *parserNode =
newParserNode(PARSER_TOKEN_SYMBOL_EOL, node->str_begin, node->str_end,
- (ParserNodeEOLMetadata *)parserNodeBefore, parent);
+ (ParserNodeSingleChildMetadata *)parserNodeBefore, parent);
node->parserNode = parserNode;
if (parserNodeBefore != NULL) {
parserNodeBefore->parent = parserNode;
@@ -471,7 +531,7 @@ ParserNode *parserComma(LexerNode *node, LexerNode *begin, ParserNode *parent) {
}
return node->parserNode = parserNodeBefore->parent = newParserNode(
PARSER_TOKEN_SYMBOL_COMMA, node->str_begin, node->str_end,
- (ParserNodeEOLMetadata *)parserNodeBefore, parent);
+ (ParserNodeSingleChildMetadata *)parserNodeBefore, parent);
}
ParserNode *parserParenthesis(LexerNode *closing, LexerNode *begin,
@@ -742,6 +802,7 @@ bool isExpression(ParserNode *node) {
case PARSER_TOKEN_FUNCTION_DEFINITION:
case PARSER_TOKEN_KEYWORD_PRINT:
case PARSER_TOKEN_FUNCTION_CALL:
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
return true;
case PARSER_TOKEN_ROOT:
case PARSER_TOKEN_TYPE_FUNCTION:
@@ -749,6 +810,7 @@ bool isExpression(ParserNode *node) {
case PARSER_TOKEN_SYMBOL_EOL:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_COMMA:
+ case PARSER_TOKEN_VALUE_U64:
return false;
case PARSER_TOKEN_NONE:
}
@@ -771,6 +833,8 @@ bool isType(ParserNode *node) {
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_COMMA:
case PARSER_TOKEN_FUNCTION_CALL:
+ case PARSER_TOKEN_VALUE_U64:
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
return false;
case PARSER_TOKEN_NONE:
}
@@ -782,6 +846,7 @@ bool isValue(ParserNode *node) {
switch (node->token) {
case PARSER_TOKEN_FUNCTION_DEFINITION:
case PARSER_TOKEN_FUNCTION_CALL:
+ case PARSER_TOKEN_VALUE_U64:
return true;
case PARSER_TOKEN_TYPE_VOID:
case PARSER_TOKEN_IDENTIFIER:
@@ -793,6 +858,7 @@ bool isValue(ParserNode *node) {
case PARSER_TOKEN_SYMBOL_EOL:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_COMMA:
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
return false;
case PARSER_TOKEN_NONE:
}
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index fb65358..974fdd5 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -2,16 +2,20 @@
#include "compiler/lexer.h"
#include <stddef.h>
+#include <stdint.h>
typedef enum ParserToken {
PARSER_TOKEN_ROOT,
PARSER_TOKEN_IDENTIFIER,
+ PARSER_TOKEN_VALUE_U64,
+
PARSER_TOKEN_TYPE_FUNCTION,
PARSER_TOKEN_TYPE_VOID,
PARSER_TOKEN_KEYWORD_PRINT,
+ PARSER_TOKEN_KEYWORD_PRINT_U64,
PARSER_TOKEN_CONSTANT,
@@ -70,7 +74,9 @@ typedef struct ParserNodeFunctionCall {
ParserNodeArray *params;
} ParserNodeFunctionCall;
-typedef ParserNode ParserNodeEOLMetadata;
+typedef ParserNode ParserNodeSingleChildMetadata;
+
+typedef uint64_t ParserNodeU64Metadata;
void parserNodePrint(const ParserNode *node, int indent);
void parserNodeDelete(ParserNode *node);
@@ -89,6 +95,8 @@ ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent);
ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent);
ParserNode *parserVoid(LexerNode *node, ParserNode *parent);
ParserNode *parserPrint(LexerNode *node, ParserNode *parent);
+ParserNode *parserPrintU64(LexerNode *node, LexerNode *end, ParserNode *parent);
+ParserNode *parserNumber(LexerNode *node, ParserNode *parent);
ParserNode *parserEol(LexerNode *node, LexerNode *begin, ParserNode *parent);
ParserNode *parserComma(LexerNode *node, LexerNode *begin, ParserNode *parent);
ParserNode *parserParenthesis(LexerNode *closing, LexerNode *begin,
diff --git a/src/main.c b/src/main.c
index 90478a3..86d8858 100644
--- a/src/main.c
+++ b/src/main.c
@@ -77,5 +77,5 @@ int main(int argc, char *argv[]) {
return 1;
}
- return run(argv[1], argv[2]);
+ return runWithPrint(argv[1], argv[2]);
}
diff --git a/src/utils/string.c b/src/utils/string.c
index 81be415..e01d1b6 100644
--- a/src/utils/string.c
+++ b/src/utils/string.c
@@ -1,5 +1,6 @@
#include "string.h"
+#include <stdint.h>
#include <string.h>
size_t searchInStringArray(const char *array[], size_t array_size,
@@ -12,3 +13,20 @@ size_t searchInStringArray(const char *array[], size_t array_size,
}
return array_size;
}
+
+uint64_t decimalToU64(char *str_begin, char *str_end, bool *success) {
+ uint64_t result = 0;
+
+ while (str_begin < str_end) {
+ if (*str_begin < '0' || *str_begin > '9') {
+ *success = false;
+ return 0;
+ }
+ result *= 10;
+ result += *str_begin - '0';
+ str_begin += 1;
+ }
+
+ *success = true;
+ return result;
+}
diff --git a/src/utils/string.h b/src/utils/string.h
index 79af8a9..7d0a5c8 100644
--- a/src/utils/string.h
+++ b/src/utils/string.h
@@ -1,6 +1,9 @@
#pragma once
#include <stddef.h>
+#include <stdint.h>
-size_t searchInStringArray(const char *array[], size_t array_size, const char *str,
- size_t str_size);
+size_t searchInStringArray(const char *array[], size_t array_size,
+ const char *str, size_t str_size);
+
+uint64_t decimalToU64(char *str_begin, char *str_end, bool *success);
diff --git a/test/main.felan b/test/main.felan
index 9c39bc6..2858216 100644
--- a/test/main.felan
+++ b/test/main.felan
@@ -1,10 +1,4 @@
-main : ()->void : () -> void {
- a();
- a();
-};
-
-a :: () -> void {
- print;
- print;
+main :: () -> void {
print;
+ print_u64 158234;
};