parsing functions and inline functions
and return too
This commit is contained in:
28
src/ast.h
28
src/ast.h
@@ -20,6 +20,8 @@ typedef enum {
|
||||
AST_IDENTIFIER,
|
||||
AST_TYPE_NAME,
|
||||
|
||||
AST_ARG_DEF,
|
||||
|
||||
AST_PROGRAM,
|
||||
|
||||
// statements
|
||||
@@ -31,6 +33,8 @@ typedef enum {
|
||||
AST_IF_STATEMENT,
|
||||
AST_BREAK_STATEMENT,
|
||||
AST_CONTINUE_STATEMENT,
|
||||
AST_FUNC_DEF_STATEMENT,
|
||||
AST_RETURN_STATEMENT,
|
||||
|
||||
// expressions
|
||||
AST_INFIX_EXPRESSION
|
||||
@@ -38,6 +42,10 @@ typedef enum {
|
||||
|
||||
// Main ASTNode struct, this can hold the different types of nodes.
|
||||
typedef struct CometASTNode CometASTNode;
|
||||
typedef CometASTNode* astNodePtr;
|
||||
|
||||
UseList(astNodePtr);
|
||||
|
||||
struct CometASTNode {
|
||||
CometASTNodeType nodeType;
|
||||
union {
|
||||
@@ -46,6 +54,8 @@ struct CometASTNode {
|
||||
struct AST_IDENTIFIER { char* ident; } AST_IDENTIFIER;
|
||||
struct AST_TYPE_NAME { char* name; } AST_TYPE_NAME;
|
||||
|
||||
struct AST_ARG_DEF { CometASTNode* type; CometASTNode* ident; } AST_ARG_DEF;
|
||||
|
||||
struct AST_PROGRAM { CometASTNode** statements; size_t numStatements; size_t statementsArraySize; } AST_PROGRAM;
|
||||
|
||||
struct AST_INFIX_EXPRESSION { CometASTNode* left; CometASTNode* right; char* op; } AST_INFIX_EXPRESSION;
|
||||
@@ -54,10 +64,26 @@ struct CometASTNode {
|
||||
struct AST_ASSIGN_STATEMENT { CometASTNode* ident; CometASTNode* expression; CometASTNode* type; } AST_ASSIGN_STATEMENT;
|
||||
struct AST_REASSIGN_STATEMENT { CometASTNode* ident; CometASTNode* expression; } AST_REASSIGN_STATEMENT;
|
||||
struct AST_WHILE_STATEMENT { CometASTNode* expression; CometASTNode* program; } AST_WHILE_STATEMENT;
|
||||
struct AST_FOR_STATEMENT { CometASTNode* ident; CometASTNode* start; CometASTNode* end; CometASTNode* step; CometASTNode* program; } AST_FOR_STATEMENT;
|
||||
struct AST_FOR_STATEMENT {
|
||||
CometASTNode* ident;
|
||||
CometASTNode* start;
|
||||
CometASTNode* end;
|
||||
CometASTNode* step;
|
||||
CometASTNode* program;
|
||||
} AST_FOR_STATEMENT;
|
||||
struct AST_IF_STATEMENT { CometASTNode* expression; CometASTNode* program; } AST_IF_STATEMENT;
|
||||
struct AST_BREAK_STATEMENT { } AST_BREAK_STATEMENT;
|
||||
struct AST_CONTINUE_STATEMENT { } AST_CONTINUE_STATEMENT;
|
||||
struct AST_FUNC_DEF_STATEMENT {
|
||||
CometASTNode* ident;
|
||||
CometASTNode* program;
|
||||
List(astNodePtr) args;
|
||||
CometASTNode* returnType;
|
||||
bool isInline;
|
||||
CometASTNode* inlineExpr;
|
||||
} AST_FUNC_DEF_STATEMENT;
|
||||
struct AST_RETURN_STATEMENT { CometASTNode* expression; } AST_RETURN_STATEMENT;
|
||||
|
||||
} data;
|
||||
};
|
||||
|
||||
|
||||
40
src/lexer.c
40
src/lexer.c
@@ -121,7 +121,13 @@ ResultType(CometToken, charptr) lexerParseWord(CometLexer* lexer) {
|
||||
buffer = newPtr;
|
||||
}
|
||||
|
||||
lexerConsume(lexer);
|
||||
char peek = lexer->source[lexer->pos+1];
|
||||
if (isspace(peek) || !(isalnum(peek) || peek == '_')) {
|
||||
break;
|
||||
} else {
|
||||
lexerConsume(lexer);
|
||||
}
|
||||
|
||||
}
|
||||
buffer[bufferPos] = 0;
|
||||
|
||||
@@ -262,13 +268,21 @@ ResultType(tokenList, charptr) lex(CometLexer* lexer) {
|
||||
case '\r':
|
||||
break;
|
||||
case '=':
|
||||
ResultType(char, charptr) nextEq = lexerPeek(lexer);
|
||||
ResultType(char, charptr) next = lexerPeek(lexer);
|
||||
|
||||
if (!nextEq.error && nextEq.as.success == '=') {
|
||||
lexerConsume(lexer);
|
||||
append(tokens, TOKEN_LITERAL(CT_EQ_EQ, "=="));
|
||||
} else {
|
||||
if (next.error) {
|
||||
append(tokens, TOKEN_LITERAL(CT_EQ, "="));
|
||||
break;
|
||||
}
|
||||
lexerConsume(lexer);
|
||||
|
||||
if (next.as.success == '=') {
|
||||
|
||||
append(tokens, TOKEN_LITERAL(CT_EQ_EQ, "=="));
|
||||
} else if (next.as.success == '>') {
|
||||
append(tokens, TOKEN_LITERAL(CT_INLINE_FUNC_ARROW, "=>"))
|
||||
} else {
|
||||
return Error(tokenList, charptr, "Expected '=' or '>' after '='.");
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -324,12 +338,24 @@ ResultType(tokenList, charptr) lex(CometLexer* lexer) {
|
||||
|
||||
|
||||
case '+': append(tokens, TOKEN_LITERAL(CT_PLUS, "+")); break;
|
||||
case '-': append(tokens, TOKEN_LITERAL(CT_MINUS, "-")); break;
|
||||
case '-':
|
||||
ResultType(char, charptr) arrow = lexerPeek(lexer);
|
||||
|
||||
if (!arrow.error && arrow.as.success == '>') {
|
||||
lexerConsume(lexer);
|
||||
append(tokens, TOKEN_LITERAL(CT_ARROW, "->"));
|
||||
} else {
|
||||
append(tokens, TOKEN_LITERAL(CT_MINUS, "-"));
|
||||
}
|
||||
|
||||
break;
|
||||
case '*': append(tokens, TOKEN_LITERAL(CT_TIMES, "*")); break;
|
||||
case '/': append(tokens, TOKEN_LITERAL(CT_DIVIDE, "/")); break;
|
||||
case '%': append(tokens, TOKEN_LITERAL(CT_MOD, "%")); break;
|
||||
case '^': append(tokens, TOKEN_LITERAL(CT_POW, "^")); break;
|
||||
|
||||
case ',': append(tokens, TOKEN_LITERAL(CT_COMMA, ",")) break;
|
||||
|
||||
case '<':
|
||||
ResultType(char, charptr) ltEq = lexerPeek(lexer);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "lexer.h"
|
||||
#include "parser.h"
|
||||
#include "token.h"
|
||||
#include "util.h"
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -13,7 +14,7 @@ int main() {
|
||||
printf("lexer error: %s\n", tokens.as.error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
ResultType(parserPtr, charptr) parser = newParser(tokens.as.success);
|
||||
if (parser.error) {
|
||||
printf("error while creating parser: %s\n", parser.as.error);
|
||||
|
||||
157
src/parser.c
157
src/parser.c
@@ -2,6 +2,7 @@
|
||||
#include "ast.h"
|
||||
#include "lexer.h"
|
||||
#include "token.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -255,6 +256,42 @@ void printNode(CometASTNode* node) {
|
||||
case AST_CONTINUE_STATEMENT:
|
||||
printf("continue");
|
||||
break;
|
||||
case AST_ARG_DEF:
|
||||
printNode(node->data.AST_ARG_DEF.type);
|
||||
printf(" ");
|
||||
printNode(node->data.AST_ARG_DEF.ident);
|
||||
break;
|
||||
case AST_FUNC_DEF_STATEMENT:
|
||||
printf("func ");
|
||||
printNode(node->data.AST_FUNC_DEF_STATEMENT.ident);
|
||||
printf("(");
|
||||
|
||||
for (size_t i = 0; i < node->data.AST_FUNC_DEF_STATEMENT.args.count; i++) {
|
||||
CometASTNode* arg = *get(node->data.AST_FUNC_DEF_STATEMENT.args, i);
|
||||
printNode(arg);
|
||||
|
||||
if (i < node->data.AST_FUNC_DEF_STATEMENT.args.count-1)
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
printf(") -> ");
|
||||
printNode(node->data.AST_FUNC_DEF_STATEMENT.returnType);
|
||||
printf(" ");
|
||||
|
||||
if (node->data.AST_FUNC_DEF_STATEMENT.isInline) {
|
||||
printf("=> ");
|
||||
printNode(node->data.AST_FUNC_DEF_STATEMENT.inlineExpr);
|
||||
} else {
|
||||
printf("{\n");
|
||||
printNode(node->data.AST_FUNC_DEF_STATEMENT.program);
|
||||
printf(" }");
|
||||
}
|
||||
|
||||
break;
|
||||
case AST_RETURN_STATEMENT:
|
||||
printf("return ");
|
||||
printNode(node->data.AST_RETURN_STATEMENT.expression);
|
||||
break;
|
||||
case AST_IF_STATEMENT:
|
||||
printf("if ");
|
||||
printNode(node->data.AST_IF_STATEMENT.expression);
|
||||
@@ -576,6 +613,122 @@ ResultType(astNodePtr, charptr) parseReassignStatement(CometParser* parser) {
|
||||
return Success(astNodePtr, charptr, stmt);
|
||||
}
|
||||
|
||||
ResultType(astNodePtr, charptr) parseFunctionDefStatement(CometParser* parser) {
|
||||
// basic format
|
||||
// func func_name(type arg_name, type2 arg_name2) -> return_type {
|
||||
// return arg_name + arg_name2
|
||||
// }
|
||||
//
|
||||
// inline body func
|
||||
// func func_name(type arg_name, type2 arg_name2) => arg_name + arg_name2
|
||||
|
||||
ResultType(int, charptr) expectName = expectPeek(parser, CT_IDENT);
|
||||
if (expectName.error) {
|
||||
return Error(astNodePtr, charptr, expectName.as.error);
|
||||
}
|
||||
|
||||
CometASTNode* ident = AST_NODE(AST_IDENTIFIER, parser->currentToken->value.literal);
|
||||
bool isInline = false;
|
||||
|
||||
ResultType(int, charptr) expectOpenParen = expectPeek(parser, CT_OPEN_PAREN);
|
||||
if (expectOpenParen.error) {
|
||||
return Error(astNodePtr, charptr, expectOpenParen.as.error);
|
||||
}
|
||||
|
||||
// parse args
|
||||
List(astNodePtr) args = newList(astNodePtr);
|
||||
|
||||
while (parser->currentToken->type != CT_CLOSE_PAREN) {
|
||||
if (parser->peekToken->type == CT_EOF) {
|
||||
return Error(astNodePtr, charptr, "Function args were not closed!");
|
||||
} else if (parser->peekToken->type == CT_CLOSE_PAREN) {
|
||||
parserNextToken(parser);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ResultType(int, charptr) expectType = expectPeek(parser, CT_TYPE_NAME);
|
||||
if (expectType.error) {
|
||||
return Error(astNodePtr, charptr, expectType.as.error);
|
||||
}
|
||||
CometASTNode* type = AST_NODE(AST_TYPE_NAME, parser->currentToken->value.literal);
|
||||
|
||||
ResultType(int, charptr) expectArgName = expectPeek(parser, CT_IDENT);
|
||||
if (expectArgName.error) {
|
||||
return Error(astNodePtr, charptr, expectArgName.as.error);
|
||||
}
|
||||
CometASTNode* argName = AST_NODE(AST_IDENTIFIER, parser->currentToken->value.literal);
|
||||
|
||||
append(args, AST_NODE(AST_ARG_DEF, type, argName));
|
||||
|
||||
ResultType(int, charptr) expectComma = expectPeek(parser, CT_COMMA);
|
||||
if (expectComma.error && !peekTokenIs(parser, CT_CLOSE_PAREN)) {
|
||||
return Error(astNodePtr, charptr, expectComma.as.error);
|
||||
}
|
||||
}
|
||||
|
||||
ResultType(int, charptr) expectArrow = expectPeek(parser, CT_ARROW);
|
||||
if (expectArrow.error) {
|
||||
return Error(astNodePtr, charptr, expectArrow.as.error);
|
||||
}
|
||||
|
||||
ResultType(int, charptr) expectReturnType = expectPeek(parser, CT_TYPE_NAME);
|
||||
if (expectReturnType.error) {
|
||||
return Error(astNodePtr, charptr, expectReturnType.as.error);
|
||||
}
|
||||
|
||||
CometASTNode* returnType = AST_NODE(AST_TYPE_NAME, parser->currentToken->value.literal);
|
||||
|
||||
isInline = peekTokenIs(parser, CT_INLINE_FUNC_ARROW);
|
||||
|
||||
if (!(isInline || peekTokenIs(parser, CT_OPEN_CURLY))) {
|
||||
return Error(astNodePtr, charptr, "Expected next token to be '{' '=>'.");
|
||||
}
|
||||
|
||||
CometASTNode* block = NULL;
|
||||
CometASTNode* inlineExpr = NULL;
|
||||
if (!isInline) {
|
||||
ResultType(astNodePtr, charptr) blockResult = parseBlockStatement(parser);
|
||||
if (blockResult.error) {
|
||||
return blockResult;
|
||||
}
|
||||
|
||||
block = blockResult.as.success;
|
||||
} else {
|
||||
parserNextToken(parser); // skip return type
|
||||
parserNextToken(parser); // skip the arrow
|
||||
ResultType(astNodePtr, charptr) exprResult = parseExpression(parser, PRECEDENCE_LOWEST);
|
||||
if (exprResult.error) {
|
||||
return exprResult;
|
||||
}
|
||||
|
||||
inlineExpr = exprResult.as.success;
|
||||
}
|
||||
|
||||
|
||||
CometASTNode* stmt = AST_NODE(
|
||||
AST_FUNC_DEF_STATEMENT,
|
||||
ident,
|
||||
block,
|
||||
args,
|
||||
returnType,
|
||||
isInline,
|
||||
inlineExpr
|
||||
);
|
||||
return Success(astNodePtr, charptr, stmt);
|
||||
}
|
||||
|
||||
ResultType(astNodePtr, charptr) parseReturnStatement(CometParser* parser) {
|
||||
parserNextToken(parser);
|
||||
ResultType(astNodePtr, charptr) expr = parseExpression(parser, PRECEDENCE_LOWEST);
|
||||
if (expr.error) {
|
||||
return expr;
|
||||
}
|
||||
|
||||
return Success(astNodePtr, charptr, AST_NODE(AST_RETURN_STATEMENT, expr.as.success));
|
||||
}
|
||||
|
||||
ResultType(astNodePtr, charptr) parseKeyword(CometParser* parser) {
|
||||
char* keyword = parser->currentToken->value.literal;
|
||||
|
||||
@@ -589,6 +742,10 @@ ResultType(astNodePtr, charptr) parseKeyword(CometParser* parser) {
|
||||
return parseBreakStatement(parser);
|
||||
} else if (strcmp(keyword, "continue") == 0) {
|
||||
return parseContinueStatement(parser);
|
||||
} else if (strcmp(keyword, "func") == 0) {
|
||||
return parseFunctionDefStatement(parser);
|
||||
} else if (strcmp(keyword, "return") == 0) {
|
||||
return parseReturnStatement(parser);
|
||||
} else {
|
||||
char* buffer = malloc(256);
|
||||
sprintf(buffer, "No parse method for keyword \"%s\"", keyword);
|
||||
|
||||
@@ -21,7 +21,6 @@ typedef struct {
|
||||
} CometParser;
|
||||
|
||||
typedef CometParser* parserPtr;
|
||||
typedef CometASTNode* astNodePtr;
|
||||
|
||||
Result(astNodePtr, charptr);
|
||||
|
||||
|
||||
@@ -58,6 +58,10 @@ char* tokenTypeToCStr(CometTokenType tokType) {
|
||||
return "CT_POW";
|
||||
case CT_EOF:
|
||||
return "CT_EOF";
|
||||
case CT_ARROW:
|
||||
return "CT_ARROW";
|
||||
case CT_INLINE_FUNC_ARROW:
|
||||
return "CT_INLINE_FUNC_ARROW";
|
||||
default:
|
||||
return "FIXME";
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ typedef enum {
|
||||
CT_COLON,
|
||||
CT_EQ,
|
||||
CT_PLUS, CT_MINUS, CT_DIVIDE, CT_TIMES, CT_MOD, CT_POW,
|
||||
CT_DOT, CT_DOT_DOT, CT_ARROW,
|
||||
CT_OPEN_CURLY, CT_CLOSE_CURLY, CT_OPEN_PAREN, CT_CLOSE_PAREN,
|
||||
CT_DOT, CT_DOT_DOT, CT_ARROW, CT_INLINE_FUNC_ARROW,
|
||||
CT_OPEN_CURLY, CT_CLOSE_CURLY, CT_OPEN_PAREN, CT_CLOSE_PAREN, CT_COMMA,
|
||||
|
||||
// other
|
||||
CT_COMMENT, CT_END_LABEL, CT_EOF
|
||||
|
||||
Reference in New Issue
Block a user