Compare commits

...

3 Commits

Author SHA1 Message Date
SpookyDervish
9da2bb5404 ast 2025-12-27 10:17:56 +11:00
SpookyDervish
bd07952569 make file added 2025-12-26 18:56:51 +11:00
SpookyDervish
b69a6c6eec makefile added 2025-12-26 18:56:47 +11:00
25 changed files with 392 additions and 105 deletions

54
.gitignore vendored
View File

@@ -1,54 +0,0 @@
# ---> C
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

24
Makefile Normal file
View File

@@ -0,0 +1,24 @@
CC=gcc
CFLAGS=-O3 -Wall
SRC=src
BIN=bin
VMBL_FILES=$(wildcard $(SRC)/vmbl/*.c)
SYLT_FILES=$(wildcard $(SRC)/sylt/*.c)
UTIL_FILES=$(wildcard $(SRC)/utils/*.c)
all: vmbl sylt
$(BIN)/vmbl: $(VMBL_FILES)
mkdir -p $(BIN)
$(CC) $(CFLAGS) $(UTIL_FILES) $(VMBL_FILES) -o $(BIN)/vmbl
vmbl: $(BIN)/vmbl
$(BIN)/sylt: $(SYLT_FILES)
mkdir -p $(BIN)
$(CC) $(CFLAGS) $(UTIL_FILES) $(SYLT_FILES) -o $(BIN)/sylt
sylt: $(BIN)/sylt
clean:
rm -r $(BIN)

View File

@@ -9,7 +9,7 @@
But uhh that's the name of the VM itself, the name of the programming language I made is Sylt, named after the German island. But uhh that's the name of the VM itself, the name of the programming language I made is Sylt, named after the German island.
To compile the VM for Linux: `gcc src/main.c src/vmbl.c src/exception.c src/file_utils.c -o vmbl -O3` To compile the VM for Linux: `gcc src/main.c src/vmbl.c src/exception.c src/file_utils.c -o vmbl -O3`
To compile the SYLT compiler for Linux: `gcc src/sylt/main.c src/file_utils.c src/sylt/lexer.c -o sylt -O3` To compile the SYLT compiler for Linux: `gcc src/sylt/main.c src/sylt/exception.c src/sylt/token.c src/file_utils.c src/sylt/lexer.c -o sylt -O3`
SASM and Sylt are written in Python for now as I'm too mentally challenged to write C code rn. SASM and Sylt are written in Python for now as I'm too mentally challenged to write C code rn.

BIN
sasm

Binary file not shown.

1
src/sylt/ast.c Normal file
View File

@@ -0,0 +1 @@
#include "ast.h"

65
src/sylt/ast.h Normal file
View File

@@ -0,0 +1,65 @@
#ifndef AST_H
#define AST_H
#include <stdlib.h>
typedef enum {
NODE_PROGRAM,
// Statements
NODE_EXPRESSION_STATEMENT,
// Expressions
NODE_INFIX_EXPRESSION,
// Literals
NODE_INT_LITERAL,
NODE_FLOAT_LITERAL
} AST_Type;
typedef struct AST AST;
struct AST
{
AST_Type type;
char *(*to_json)(AST *node);
};
typedef struct
{
AST base;
AST **statements;
size_t statementCount;
} Program;
char *programToJSON(AST *node);
// statements
typedef struct
{
AST base;
AST *expr;
} ExpressionStatement;
char *expressionStatementToJSON(AST *node);
// expressions
typedef struct {
AST base;
AST *left;
char *operator;
AST *right;
} InfixExpression;
char *infixExpressionToJSON(AST *node);
// literals
typedef struct {
AST base;
int value;
} IntegerLiteral;
char *integerLiteralToJSON(AST *node);
typedef struct {
AST base;
double value;
} FloatLiteral;
char *floatLiteralToJSON(AST *node);
#endif // !AST_H

21
src/sylt/exception.c Normal file
View File

@@ -0,0 +1,21 @@
#include "exception.h"
#include <stdio.h>
#include "../utils/ansii.h"
char *exceptionTypeToCString(ExceptionType type) {
switch (type)
{
case EXCEPTION_MALFORMED_NUMBER:
return "MalformedNumberException";
case EXCEPTION_MEMORY_ALLOCATION_FAILURE:
return "MemoryAllocationFailException";
default:
return "UnkownException (fix me please)";
}
}
void exceptionMessage(ExceptionType type, char *message, int lineNumber, int position) {
printf(ESC_RED_FG ESC_BOLD "%s: %s" ESC_RESET "\n", exceptionTypeToCString(type), message);
}

12
src/sylt/exception.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef EXCEPTION_H
#define EXCEPTION_H
typedef enum {
EXCEPTION_MALFORMED_NUMBER,
EXCEPTION_MEMORY_ALLOCATION_FAILURE
} ExceptionType;
char *exceptionTypeToCString(ExceptionType type);
void exceptionMessage(ExceptionType type, char *message, int lineNumber, int position);
#endif // !EXCEPTION_H

View File

@@ -1,7 +1,9 @@
#include "lexer.h" #include "lexer.h"
#include "exception.h"
#include <string.h> #include <string.h>
#include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio,h> #include <stdio.h>
Lexer initLexer(char *source) { Lexer initLexer(char *source) {
Lexer newLexer = { Lexer newLexer = {
@@ -11,6 +13,7 @@ Lexer initLexer(char *source) {
.lineNumber = 1, .lineNumber = 1,
.currentChar = '\0' .currentChar = '\0'
}; };
readChar(&newLexer);
return newLexer; return newLexer;
} }
@@ -25,63 +28,134 @@ void readChar(Lexer *lexer) {
} }
void skipWhitespace(Lexer *lexer) { void skipWhitespace(Lexer *lexer) {
switch (lexer->currentChar) bool whitespace = true;
{
case ' ':
case '\t':
case '\n':
case '\r':
if (lexer->currentChar == '\n')
lexer->lineNumber++;
readChar(lexer); while (whitespace)
break; {
switch (lexer->currentChar)
default: {
break; case ' ':
case '\t':
case '\n':
case '\r':
if (lexer->currentChar == '\n')
lexer->lineNumber++;
readChar(lexer);
break;
default:
whitespace = false;
break;
}
} }
}
Token readNumber(Lexer *lexer) {
int startPos = lexer->position;
int dotCount = 0;
int strLength = 0;
size_t outputCap = 8;
char *output = malloc(outputCap);
if (!output) {
exceptionMessage(EXCEPTION_MEMORY_ALLOCATION_FAILURE, "Lexer failed to allocate memory.", lexer->lineNumber, lexer->position);
exit(1);
}
while (isdigit(lexer->currentChar) || lexer->currentChar == '.')
{
if (lexer->currentChar == '.') {
dotCount++;
if (dotCount > 1) {
exceptionMessage(EXCEPTION_MALFORMED_NUMBER, "Too many dots in decimal.", lexer->lineNumber, lexer->position);
char buffer[strLength+1];
strncpy(buffer, lexer->source + startPos, strLength+1);
buffer[strLength+1] = 0;
return NEW_TOKEN(lexer, TOKEN_ILLEGAL, buffer);
}
}
// allocate more memory if we reach the end of our buffer
if (strLength + 1 >= outputCap) {
char *temp = realloc(output, outputCap*=2);
if (!temp) {
exceptionMessage(EXCEPTION_MEMORY_ALLOCATION_FAILURE, "Lexer failed to allocate memory.", lexer->lineNumber, lexer->position);
exit(1);
}
output = temp;
}
output[strLength] = lexer->source[lexer->position];
strLength++;
readChar(lexer);
if (lexer->currentChar == '\0')
break;
}
output[strLength] = 0;
if (dotCount == 0)
return NEW_TOKEN(lexer, TOKEN_INT, output);
else
return NEW_TOKEN(lexer, TOKEN_FLOAT, output);
} }
Token nextToken(Lexer *lexer) { Token nextToken(Lexer *lexer) {
//Token tok; Token tok;
skipWhitespace(lexer); skipWhitespace(lexer);
switch (lexer->currentChar) switch (lexer->currentChar)
{ {
case '+': case '+':
return NEW_TOKEN(lexer, PLUS, "+"); tok = NEW_TOKEN(lexer, TOKEN_PLUS, "+");
break; break;
case '-': case '-':
return NEW_TOKEN(lexer, MINUS, "-"); tok = NEW_TOKEN(lexer, TOKEN_MINUS, "-");
break; break;
case '*': case '*':
return NEW_TOKEN(lexer, ASTERISK, "*"); tok = NEW_TOKEN(lexer, TOKEN_ASTERISK, "*");
break; break;
case '/': case '/':
return NEW_TOKEN(lexer, SLASH, "/"); tok = NEW_TOKEN(lexer, TOKEN_SLASH, "/");
break; break;
case '%': case '%':
return NEW_TOKEN(lexer, MODULUS, "%"); tok = NEW_TOKEN(lexer, TOKEN_MODULUS, "%");
break; break;
case '^': case '^':
return NEW_TOKEN(lexer, POW, "^"); tok = NEW_TOKEN(lexer, TOKEN_POW, "^");
break; break;
case '(': case '(':
return NEW_TOKEN(lexer, LPAREN, "("); tok = NEW_TOKEN(lexer, TOKEN_LPAREN, "(");
break; break;
case ')': case ')':
return NEW_TOKEN(lexer, RPAREN, ")"); tok = NEW_TOKEN(lexer, TOKEN_RPAREN, ")");
break; break;
case '\0':
return NEW_TOKEN(lexer, EOF, ""); case '\0': // EOF
tok = NEW_TOKEN(lexer, TOKEN_EOF, "EOF");
break; break;
default: default:
if (isdigit()) if (isdigit(lexer->currentChar)) {
tok = readNumber(lexer);
} else {
tok = NEW_TOKEN(lexer, TOKEN_ILLEGAL, &lexer->currentChar);
}
break; break;
} }
//return tok; readChar(lexer);
return tok;
} }

View File

@@ -17,6 +17,6 @@ Lexer initLexer(char *source);
void readChar(Lexer *lexer); void readChar(Lexer *lexer);
void skipWhitespace(Lexer *lexer); void skipWhitespace(Lexer *lexer);
Token nextToken(Lexer *lexer); Token nextToken(Lexer *lexer);
char *tokenToCStr(Token token); Token readNumber(Lexer *lexer);
#endif // !LEXER_H #endif // !LEXER_H

View File

@@ -1,10 +1,16 @@
#include "lexer.h" #include "lexer.h"
#include <stdio.h> #include <stdio.h>
#include "../file_utils.h" #include "../utils/file_utils.h"
#include "../utils/ansii.h"
int main() { int main() {
Lexer lexer = initLexer("const x, y = 1, 3\n"); Lexer lexer = initLexer("123 456.789 + - * / % ^ ()");
printf(nextToken(&lexer).literal);
while (lexer.currentChar != 0)
{
Token next = nextToken(&lexer);
printf("%s: %s\n", tokenTypeToCString(next.type), next.literal);
}
return 0; return 0;
} }

1
src/sylt/parser.c Normal file
View File

@@ -0,0 +1 @@
#include "parser.h"

28
src/sylt/parser.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef PARSER_H
#define PARSER_H
#include "lexer.h"
#include "ast.h"
typedef enum {
PRECEDENCE_LOWEST = 0,
PRECEDENCE_EQUALS,
PRECEDENCE_LESSGREATER,
PRECEDENCE_SUM,
PRECEDENCE_PRODUCT,
PRECEDENCE_EXPONENT,
PRECEDENCE_PREFIX,
PRECEDENCE_CALL,
PRECEDENCE_INDEX,
} PrecedenceType;
PrecedenceType PRECEDENCES[] = {
[TOKEN_PLUS] = PRECEDENCE_SUM,
[TOKEN_MINUS] = PRECEDENCE_SUM,
[TOKEN_SLASH] = PRECEDENCE_PRODUCT,
[TOKEN_ASTERISK] = PRECEDENCE_PRODUCT,
[TOKEN_MODULUS] = PRECEDENCE_PRODUCT,
[TOKEN_POW] = PRECEDENCE_EXPONENT,
};
#endif // !PARSER_H

45
src/sylt/token.c Normal file
View File

@@ -0,0 +1,45 @@
#include "token.h"
char *tokenTypeToCString(TokenType type) {
switch (type)
{
case TOKEN_EOF:
return "TOKEN_EOF";
case TOKEN_ILLEGAL:
return "TOKEN_ILLEGAL";
case TOKEN_INT:
return "TOKEN_INT";
case TOKEN_FLOAT:
return "TOKEN_FLOAT";
case TOKEN_PLUS:
return "TOKEN_EOF";
case TOKEN_MINUS:
return "TOKEN_MINUS";
case TOKEN_ASTERISK:
return "TOKEN_ASTERISK";
case TOKEN_SLASH:
return "TOKEN_SLASH";
case TOKEN_POW:
return "TOKEN_POW";
case TOKEN_MODULUS:
return "TOKEN_MODULUS";
case TOKEN_LPAREN:
return "TOKEN_LPAREN";
case TOKEN_RPAREN:
return "TOKEN_RPAREN";
default:
return "UNKOWN (fix me please)";
}
}

View File

@@ -3,24 +3,24 @@
typedef enum { typedef enum {
// Special Tokens // Special Tokens
EOF, TOKEN_EOF,
ILLEGAL, TOKEN_ILLEGAL,
// Data Types // Data Types
INT, TOKEN_INT,
FLOAT, TOKEN_FLOAT,
// Arithmetic Symbols // Arithmetic Symbols
PLUS, TOKEN_PLUS,
MINUS, TOKEN_MINUS,
ASTERISK, TOKEN_ASTERISK,
SLASH, TOKEN_SLASH,
POW, TOKEN_POW,
MODULUS, TOKEN_MODULUS,
// Symbols // Symbols
LPAREN, TOKEN_LPAREN,
RPAREN TOKEN_RPAREN
} TokenType; } TokenType;
typedef struct typedef struct
@@ -33,4 +33,6 @@ typedef struct
#define NEW_TOKEN(lexer, tokType, tokLiteral) (Token){ .type = (tokType), .literal = (tokLiteral), .lineNumber = (lexer->lineNumber), .position = (lexer->position) } #define NEW_TOKEN(lexer, tokType, tokLiteral) (Token){ .type = (tokType), .literal = (tokLiteral), .lineNumber = (lexer->lineNumber), .position = (lexer->position) }
char *tokenTypeToCString(TokenType type);
#endif // !TOKEN_H #endif // !TOKEN_H

67
src/utils/ansii.h Normal file
View File

@@ -0,0 +1,67 @@
// ansii.h - made by SpookyDervish
// version 1.0.0
// do with this whatever you want
//
// example usage with printf: printf(ESC_BOLD ESC_RED_FG "hi\n");
#ifndef ANSII_H
#define ANSII_H
#define ESC_RESET "\x1b[0m"
#define ESC_BOLD "\x1b[1m"
#define ESC_DIM "\x1b[2m"
#define ESC_ITALIC "\x1b[3m"
#define ESC_UNDERLINE "\x1b[4m"
#define ESC_BLINKING "\x1b[5m"
#define ESC_REVERSE "\x1b[7m"
#define ESC_HIDDEN "\x1b[8m"
#define ESC_STRIKETHROUGH "\x1b[8m"
#define ESC_TERMINAL_BELL "\a"
#define ESC_BLACK_FG "\x1b[30m"
#define ESC_RED_FG "\x1b[31m"
#define ESC_GREEN_FG "\x1b[32m"
#define ESC_YELLOW_FG "\x1b[33m"
#define ESC_BLUE_FG "\x1b[34m"
#define ESC_MAGENTA_FG "\x1b[35m"
#define ESC_CYAN_FG "\x1b[36m"
#define ESC_WHITE_FG "\x1b[37m"
#define ESC_BLACK_FG "\x1b[30m"
#define ESC_RED_FG "\x1b[31m"
#define ESC_GREEN_FG "\x1b[32m"
#define ESC_YELLOW_FG "\x1b[33m"
#define ESC_BLUE_FG "\x1b[34m"
#define ESC_MAGENTA_FG "\x1b[35m"
#define ESC_CYAN_FG "\x1b[36m"
#define ESC_WHITE_FG "\x1b[37m"
#define ESC_BRIGHT_BLACK_FG "\x1b[90m"
#define ESC_BRIGHT_RED_FG "\x1b[91m"
#define ESC_BRIGHT_GREEN_FG "\x1b[92m"
#define ESC_BRIGHT_YELLOW_FG "\x1b[93m"
#define ESC_BRIGHT_BLUE_FG "\x1b[94m"
#define ESC_BRIGHT_MAGENTA_FG "\x1b[95m"
#define ESC_BRIGHT_CYAN_FG "\x1b[96m"
#define ESC_BRIGHT_WHITE_FG "\x1b[97m"
#define ESC_BLACK_BG "\x1b[40m"
#define ESC_RED_BG "\x1b[41m"
#define ESC_GREEN_BG "\x1b[42m"
#define ESC_YELLOW_BG "\x1b[43m"
#define ESC_BLUE_BG "\x1b[44m"
#define ESC_MAGENTA_BG "\x1b[45m"
#define ESC_CYAN_BG "\x1b[46m"
#define ESC_WHITE_BG "\x1b[47m"
#define ESC_BRIGHT_BLACK_BG "\x1b[100m"
#define ESC_BRIGHT_RED_BG "\x1b[101m"
#define ESC_BRIGHT_GREEN_BG "\x1b[102m"
#define ESC_BRIGHT_YELLOW_BG "\x1b[103m"
#define ESC_BRIGHT_BLUE_BG "\x1b[104m"
#define ESC_BRIGHT_MAGENTA_BG "\x1b[105m"
#define ESC_BRIGHT_CYAN_BG "\x1b[106m"
#define ESC_BRIGHT_WHITE_BG "\x1b[107m"
#define ESC_DEFAULT_FG "\x1b[39m"
#endif // !ANSII_H

View File

@@ -4,12 +4,7 @@
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])); #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]));
VMBL_Instruction program[] = { VMBL_Instruction program[] = {
MAKE_INST_PUSH(0), MAKE_INST_JMP(0)
MAKE_INST_PUSH(1),
MAKE_INST_DUP(1),
MAKE_INST_DUP(1),
MAKE_INST_ADD,
MAKE_INST_JMP(2)
}; };
int main() { int main() {

View File

@@ -1,5 +1,5 @@
#include "vmbl.h" #include "vmbl.h"
#include "file_utils.h" #include "../utils/file_utils.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

BIN
sylt

Binary file not shown.

BIN
vmbl

Binary file not shown.