add operations
This commit is contained in:
26
.vscode/launch.json
vendored
Normal file
26
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "C/C++ Debug (gdb Launch)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/bin/argon",
|
||||
"args": ["test.ar"],
|
||||
"stopAtEntry": true,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
8
Makefile
8
Makefile
@@ -3,7 +3,7 @@ LEXER_C = src/lexer/lex.yy.c
|
||||
LEXER_H = src/lexer/lex.yy.h
|
||||
|
||||
CFILES = $(shell find src -name '*.c')
|
||||
CFLAGS = -lm -lcjson -lgc -lgmp -Wall -Wextra -Wno-unused-function -s
|
||||
CFLAGS = -lm -lcjson -lgc -lgmp -Wall -Wextra -Wno-unused-function
|
||||
BINARY = bin/argon
|
||||
|
||||
all: $(BINARY)
|
||||
@@ -13,12 +13,16 @@ $(LEXER_C) $(LEXER_H): $(LEXER_SRC)
|
||||
|
||||
$(BINARY): $(CFILES) $(LEXER_C) $(LEXER_H)
|
||||
mkdir -p bin
|
||||
gcc -O3 -o $(BINARY) $(CFILES) $(CFLAGS)
|
||||
gcc -O3 -o $(BINARY) $(CFILES) $(CFLAGS) -s
|
||||
|
||||
debug: $(CFILES) $(LEXER_C) $(LEXER_H)
|
||||
mkdir -p bin
|
||||
gcc -g -O0 -o $(BINARY) $(CFILES) $(CFLAGS)
|
||||
|
||||
full-debug: $(CFILES) $(LEXER_C) $(LEXER_H)
|
||||
mkdir -p bin
|
||||
gcc -g -O0 -fsanitize=address -fno-omit-frame-pointer -o $(BINARY) $(CFILES) $(CFLAGS)
|
||||
|
||||
optimised: $(CFILES) $(LEXER_C) $(LEXER_H)
|
||||
mkdir -p bin
|
||||
gcc -O3 -fprofile-generate -o $(BINARY) $(CFILES) $(CFLAGS)
|
||||
|
||||
@@ -21,22 +21,22 @@ typedef enum {
|
||||
TOKEN_ASSIGN_CARET,
|
||||
|
||||
// Operators
|
||||
TOKEN_AND, // &&
|
||||
TOKEN_OR, // ||
|
||||
TOKEN_NOT_IN, // not in
|
||||
TOKEN_LE, // <=
|
||||
TOKEN_GE, // >=
|
||||
TOKEN_CARET, // ^ (Exponentiation)
|
||||
TOKEN_STAR, // * (Multiplication)
|
||||
TOKEN_SLASH, // / (Division)
|
||||
TOKEN_FLOORDIV, // // (Floor Division)
|
||||
TOKEN_MODULO, // % (Modulo)
|
||||
TOKEN_PLUS, // + (Addition)
|
||||
TOKEN_MINUS, // - (Subtraction)
|
||||
TOKEN_LT, // <
|
||||
TOKEN_GT, // >
|
||||
TOKEN_NE, // !=
|
||||
TOKEN_LE, // <=
|
||||
TOKEN_GE, // >=
|
||||
TOKEN_EQ, // ==
|
||||
TOKEN_PLUS, // +
|
||||
TOKEN_MINUS, // -
|
||||
TOKEN_MODULO, // %
|
||||
TOKEN_STAR, // *
|
||||
TOKEN_FLOORDIV, // //
|
||||
TOKEN_SLASH, // /
|
||||
TOKEN_CARET, // ^
|
||||
TOKEN_NE, // !=
|
||||
TOKEN_NOT_IN, // not in (Usually treated like a comparison)
|
||||
TOKEN_AND, // &&
|
||||
TOKEN_OR, // ||
|
||||
|
||||
// Keywords
|
||||
TOKEN_IF,
|
||||
|
||||
@@ -16,8 +16,8 @@ ParsedValue *parse_assign(char *file, DArray *tokens, ParsedValue *assign_to,
|
||||
break;
|
||||
case AST_CALL:;
|
||||
ParsedCall *call = assign_to->data;
|
||||
for (size_t i = 0; i < call->args->size; i++) {
|
||||
if (((ParsedValue *)darray_get(call->args, i))->type != AST_IDENTIFIER) {
|
||||
for (size_t i = 0; i < call->args.size; i++) {
|
||||
if (((ParsedValue *)darray_get(&call->args, i))->type != AST_IDENTIFIER) {
|
||||
fprintf(stderr,
|
||||
"%s:%zu:%zu error: parameter names need to start with a letter "
|
||||
"or _, "
|
||||
|
||||
@@ -13,8 +13,7 @@ ParsedValue *parse_call(char *file, DArray *tokens, size_t *index,
|
||||
call->to_call = to_call;
|
||||
parsedValue->data = call;
|
||||
parsedValue->type = AST_CALL;
|
||||
call->args = checked_malloc(sizeof(DArray));
|
||||
darray_init(call->args, sizeof(ParsedValue));
|
||||
darray_init(&call->args, sizeof(ParsedValue));
|
||||
(*index)++;
|
||||
error_if_finished(file, tokens, index);
|
||||
Token *token = darray_get(tokens, *index);
|
||||
@@ -23,7 +22,7 @@ ParsedValue *parse_call(char *file, DArray *tokens, size_t *index,
|
||||
skip_newlines_and_indents(tokens, index);
|
||||
error_if_finished(file, tokens, index);
|
||||
ParsedValue *parsedArg = parse_token(file, tokens, index, true);
|
||||
darray_push(call->args, parsedArg);
|
||||
darray_push(&call->args, parsedArg);
|
||||
free(parsedArg);
|
||||
error_if_finished(file, tokens, index);
|
||||
skip_newlines_and_indents(tokens, index);
|
||||
@@ -48,7 +47,7 @@ void free_parse_call(void *ptr) {
|
||||
ParsedValue *parsedValue = ptr;
|
||||
ParsedCall *parsedCall = parsedValue->data;
|
||||
|
||||
darray_free(parsedCall->args, free_parsed);
|
||||
darray_free(&parsedCall->args, free_parsed);
|
||||
free_parsed(parsedCall->to_call);
|
||||
free(parsedCall);
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
typedef struct {
|
||||
ParsedValue * to_call;
|
||||
DArray * args;
|
||||
DArray args;
|
||||
} ParsedCall;
|
||||
|
||||
// Function declaration for parsing an identifier
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// parser.h
|
||||
|
||||
#ifndef IDENTIFIER_H
|
||||
#define IDENTIFIER_H
|
||||
#include "../../parser.h"
|
||||
|
||||
@@ -39,8 +39,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
|
||||
token = darray_get(tokens, *index);
|
||||
if (token->type == TOKEN_LPAREN) {
|
||||
declaration->is_function = true;
|
||||
declaration->parameters = checked_malloc(sizeof(DArray));
|
||||
darray_init(declaration->parameters, sizeof(char *));
|
||||
darray_init(&declaration->parameters, sizeof(char *));
|
||||
(*index)++;
|
||||
error_if_finished(file, tokens, index);
|
||||
token = darray_get(tokens, *index);
|
||||
@@ -62,7 +61,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
|
||||
}
|
||||
char *parameter_name =
|
||||
strcpy(checked_malloc(strlen(token->value) + 1), token->value);
|
||||
darray_push(declaration->parameters, ¶meter_name);
|
||||
darray_push(&declaration->parameters, ¶meter_name);
|
||||
(*index)++;
|
||||
error_if_finished(file, tokens, index);
|
||||
skip_newlines_and_indents(tokens, index);
|
||||
@@ -127,7 +126,7 @@ void free_single_declaration(void *ptr) {
|
||||
ParsedSingleDeclaration *declaration = ptr;
|
||||
free(declaration->name);
|
||||
if (declaration->is_function)
|
||||
darray_free(declaration->parameters, free_string);
|
||||
darray_free(&declaration->parameters, free_string);
|
||||
free_parsed(declaration->from);
|
||||
free(declaration->from);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
typedef struct {
|
||||
char * name;
|
||||
bool is_function;
|
||||
DArray * parameters; // string[]
|
||||
DArray parameters; // string[]
|
||||
ParsedValue * from;
|
||||
} ParsedSingleDeclaration;
|
||||
|
||||
|
||||
@@ -48,8 +48,6 @@ ParsedValue *parse_dowrap(char *file, DArray *tokens, size_t *index) {
|
||||
DArray to_free;
|
||||
darray_init(&to_free, sizeof(char *));
|
||||
|
||||
size_t starting_index = *index;
|
||||
|
||||
size_t temp_index_count = 0;
|
||||
|
||||
while (!pass && ++(*index) < tokens->size) {
|
||||
|
||||
@@ -35,7 +35,7 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) {
|
||||
}
|
||||
}
|
||||
|
||||
DArray *condition = NULL;
|
||||
ParsedValue *condition = NULL;
|
||||
|
||||
if (token->type != TOKEN_ELSE) {
|
||||
// Parse ( condition )
|
||||
@@ -48,22 +48,11 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) {
|
||||
|
||||
(*index)++;
|
||||
error_if_finished(file, tokens, index);
|
||||
skip_newlines_and_indents(tokens, index);
|
||||
condition = parse_token(file, tokens, index, true);
|
||||
skip_newlines_and_indents(tokens, index);
|
||||
|
||||
condition = checked_malloc(sizeof(DArray));
|
||||
darray_init(condition, sizeof(ParsedValue));
|
||||
|
||||
while (*index < tokens->size) {
|
||||
ParsedValue *parsed_code = parse_token(file, tokens, index, true);
|
||||
if (parsed_code) {
|
||||
darray_push(condition, parsed_code);
|
||||
free(parsed_code);
|
||||
}
|
||||
|
||||
token = darray_get(tokens, *index);
|
||||
if (token->type == TOKEN_RPAREN)
|
||||
break;
|
||||
}
|
||||
|
||||
token = darray_get(tokens, *index);
|
||||
if (token->type != TOKEN_RPAREN) {
|
||||
fprintf(stderr, "%s:%zu:%zu error: missing closing ')' in condition\n",
|
||||
file, token->line, token->column);
|
||||
@@ -114,8 +103,10 @@ ParsedValue *parse_if(char *file, DArray *tokens, size_t *index) {
|
||||
|
||||
void free_conditional(void *ptr) {
|
||||
ParsedConditional *conditional = ptr;
|
||||
if (conditional->condition)
|
||||
darray_free(conditional->condition, free_parsed);
|
||||
if (conditional->condition) {
|
||||
free_parsed(conditional->condition);
|
||||
free(conditional->condition);
|
||||
}
|
||||
free_parsed(conditional->content);
|
||||
free(conditional->content);
|
||||
}
|
||||
@@ -124,4 +115,5 @@ void free_parsed_if(void *ptr) {
|
||||
ParsedValue *parsedValue = ptr;
|
||||
DArray *parsed_if = parsedValue->data;
|
||||
darray_free(parsed_if, free_conditional);
|
||||
free(parsedValue->data);
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
// parser.h
|
||||
|
||||
#ifndef iF_H
|
||||
#define iF_H
|
||||
#include "../../lexer/token.h" // for Token
|
||||
#include "../parser.h"
|
||||
|
||||
typedef struct {
|
||||
DArray *condition; // NULL for 'else'
|
||||
ParsedValue * condition; // NULL for 'else'
|
||||
ParsedValue *content;
|
||||
} ParsedConditional;
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// parser.h
|
||||
|
||||
#ifndef NUMBER_H
|
||||
#define NUMBER_H
|
||||
#include "../parser.h"
|
||||
|
||||
81
src/parser/operations/operations.c
Normal file
81
src/parser/operations/operations.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "operations.h"
|
||||
#include "../parser.h"
|
||||
#include "../../memory.h"
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
ParsedValue *convert_to_operation(DArray * to_operate_on, DArray * operations) {
|
||||
if (to_operate_on->size == 1) {
|
||||
return darray_get(to_operate_on, 0);
|
||||
}
|
||||
TokenType operation = 0;
|
||||
DArray positions;
|
||||
for (size_t i = 0; i<operations->size;i++) {
|
||||
TokenType * current_operation = darray_get(operations, i);
|
||||
if (operation < *current_operation) {
|
||||
if (operation!=0) {
|
||||
darray_free(&positions, NULL);
|
||||
}
|
||||
operation = *current_operation;
|
||||
darray_init(&positions, sizeof(size_t));
|
||||
}
|
||||
darray_push(&positions, &i);
|
||||
}
|
||||
size_t last_position = operations->size-1;
|
||||
darray_push(&positions, &last_position);
|
||||
ParsedValue * parsedValue = checked_malloc(sizeof(ParsedValue));
|
||||
parsedValue->type = AST_OPERATION;
|
||||
ParsedOperation * operationStruct = checked_malloc(sizeof(ParsedOperation));
|
||||
parsedValue->data = operationStruct;
|
||||
operationStruct->operation = operation;
|
||||
darray_init(&operationStruct->to_operate_on, sizeof(ParsedValue));
|
||||
last_position = 0;
|
||||
for (size_t i = 0; i<positions.size;i++) {
|
||||
size_t *position = darray_get(&positions, i);
|
||||
DArray to_operate_on_slice = darray_slice(to_operate_on, last_position, *position+1);
|
||||
DArray operations_slice = darray_slice(operations, last_position, *position);
|
||||
darray_push(&operationStruct->to_operate_on, convert_to_operation(&to_operate_on_slice, &operations_slice));
|
||||
last_position = *position;
|
||||
}
|
||||
darray_free(&positions, NULL);
|
||||
return parsedValue;
|
||||
}
|
||||
|
||||
ParsedValue *parse_operations(char *file, DArray *tokens, size_t *index,
|
||||
ParsedValue *first_parsed_value) {
|
||||
DArray to_operate_on;
|
||||
darray_init(&to_operate_on, sizeof(ParsedValue));
|
||||
darray_push(&to_operate_on, first_parsed_value);
|
||||
|
||||
DArray operations;
|
||||
darray_init(&operations, sizeof(TokenType));
|
||||
|
||||
while (tokens->size > *index) {
|
||||
bool to_break = false;
|
||||
Token *token = darray_get(tokens, *index);
|
||||
switch (token->type) {
|
||||
SWITCH_OPERATIONS
|
||||
break;
|
||||
default:
|
||||
to_break = true;
|
||||
}
|
||||
if (to_break)
|
||||
break;
|
||||
darray_push(&operations, &token->type);
|
||||
(*index)++;
|
||||
error_if_finished(file, tokens, index);
|
||||
darray_push(&to_operate_on, parse_token_full(file, tokens, index, true, false));
|
||||
}
|
||||
ParsedValue *output = convert_to_operation(&to_operate_on, &operations);
|
||||
darray_free(&to_operate_on, free_parsed);
|
||||
darray_free(&operations, free_parsed);
|
||||
return output;
|
||||
}
|
||||
|
||||
void free_operation(void *ptr) {
|
||||
ParsedValue *parsedValue = ptr;
|
||||
ParsedOperation *parsed_operation = parsedValue->data;
|
||||
darray_free(&parsed_operation->to_operate_on, free_parsed);
|
||||
free(parsed_operation);
|
||||
}
|
||||
15
src/parser/operations/operations.h
Normal file
15
src/parser/operations/operations.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef OPERATIONS_H
|
||||
#define OPERATIONS_H
|
||||
#include "../parser.h"
|
||||
#include "../../lexer/token.h" // for Token
|
||||
|
||||
typedef struct {
|
||||
TokenType operation;
|
||||
DArray to_operate_on; // ParsedValue[]
|
||||
} ParsedOperation;
|
||||
|
||||
ParsedValue *parse_operations(char*file,DArray *tokens, size_t * index, ParsedValue * first_parsed_value);
|
||||
|
||||
void free_operation(void *ptr);
|
||||
|
||||
#endif // OPERATIONS_H
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "assignable/call/call.h"
|
||||
#include "assignable/identifier/identifier.h"
|
||||
#include "declaration/declaration.h"
|
||||
#include "operations/operations.h"
|
||||
#include "dowrap/dowrap.h"
|
||||
#include "if/if.h"
|
||||
#include "literals/literals.h"
|
||||
@@ -19,7 +20,7 @@
|
||||
|
||||
const char *ValueTypeNames[] = {
|
||||
"string", "assign", "identifier", "number", "if statement", "access",
|
||||
"call", "declaration", "null", "boolean", "do wrap"};
|
||||
"call", "declaration", "null", "boolean", "do wrap", "operations"};
|
||||
|
||||
void error_if_finished(char *file, DArray *tokens, size_t *index) {
|
||||
if ((*index) >= tokens->size) {
|
||||
@@ -48,8 +49,8 @@ size_t skip_newlines_and_indents(DArray *tokens, size_t *index) {
|
||||
return count;
|
||||
}
|
||||
|
||||
ParsedValue *parse_token(char *file, DArray *tokens, size_t *index,
|
||||
bool inline_flag) {
|
||||
ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index,
|
||||
bool inline_flag, bool process_operations) {
|
||||
Token *token = darray_get(tokens, *index);
|
||||
|
||||
ParsedValue *output = NULL;
|
||||
@@ -134,6 +135,12 @@ ParsedValue *parse_token(char *file, DArray *tokens, size_t *index,
|
||||
case TOKEN_DOT:
|
||||
output = parse_access(file, tokens, index, output);
|
||||
break;
|
||||
SWITCH_OPERATIONS
|
||||
if (process_operations) {
|
||||
output = parse_operations(file, tokens, index, output);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
passed = true;
|
||||
}
|
||||
@@ -142,6 +149,11 @@ ParsedValue *parse_token(char *file, DArray *tokens, size_t *index,
|
||||
return output;
|
||||
}
|
||||
|
||||
ParsedValue *parse_token(char *file, DArray *tokens, size_t *index,
|
||||
bool inline_flag) {
|
||||
return parse_token_full(file, tokens, index, inline_flag, true);
|
||||
}
|
||||
|
||||
void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) {
|
||||
size_t index = 0;
|
||||
bool expecting_new_line = false;
|
||||
@@ -151,8 +163,8 @@ void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) {
|
||||
if (parsed_code) {
|
||||
if (expecting_new_line) {
|
||||
Token *token = darray_get(tokens, old_index);
|
||||
fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line,
|
||||
token->column);
|
||||
fprintf(stderr, "%s:%zu:%zu error: expected a new line\n", file,
|
||||
token->line, token->column);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
expecting_new_line = true;
|
||||
@@ -190,6 +202,9 @@ void free_parsed(void *ptr) {
|
||||
case AST_IF:
|
||||
free_parsed_if(parsed);
|
||||
break;
|
||||
case AST_OPERATION:
|
||||
free_operation(parsed);
|
||||
break;
|
||||
case AST_DOWRAP:
|
||||
free_dowrap(parsed);
|
||||
break;
|
||||
|
||||
@@ -5,6 +5,23 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define SWITCH_OPERATIONS case TOKEN_AND:\
|
||||
case TOKEN_OR:\
|
||||
case TOKEN_NOT_IN:\
|
||||
case TOKEN_LE:\
|
||||
case TOKEN_GE:\
|
||||
case TOKEN_LT:\
|
||||
case TOKEN_GT:\
|
||||
case TOKEN_NE:\
|
||||
case TOKEN_EQ:\
|
||||
case TOKEN_PLUS:\
|
||||
case TOKEN_MINUS:\
|
||||
case TOKEN_MODULO:\
|
||||
case TOKEN_STAR:\
|
||||
case TOKEN_FLOORDIV:\
|
||||
case TOKEN_SLASH:\
|
||||
case TOKEN_CARET:
|
||||
|
||||
typedef struct LinkedList LinkedList;
|
||||
|
||||
typedef enum {
|
||||
@@ -18,7 +35,8 @@ typedef enum {
|
||||
AST_DECLARATION,
|
||||
AST_NULL,
|
||||
AST_BOOLEAN,
|
||||
AST_DOWRAP
|
||||
AST_DOWRAP,
|
||||
AST_OPERATION
|
||||
} ValueType;
|
||||
|
||||
extern const char* ValueTypeNames[];
|
||||
@@ -30,8 +48,11 @@ typedef struct {
|
||||
|
||||
void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag);
|
||||
|
||||
ParsedValue *parse_token(char *file, DArray *tokens,
|
||||
size_t *index, bool inline_flag);
|
||||
ParsedValue *parse_token_full(char *file, DArray *tokens, size_t *index,
|
||||
bool inline_flag, bool process_operations);
|
||||
|
||||
ParsedValue *parse_token(char *file, DArray *tokens, size_t *index,
|
||||
bool inline_flag);
|
||||
|
||||
void free_parsed(void *ptr);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user