From 1f4f58b3fb9bbc77ec16c74fd2dec216cd575735 Mon Sep 17 00:00:00 2001 From: Matthieu Bessat Date: Wed, 20 Apr 2022 20:10:00 +0200 Subject: [PATCH] initial commit --- .gitignore | 1 + Makefile | 6 ++ README.md | 82 ++++++++++++++++ examples/basic_1.basic | 1 + examples/basic_2.basic | 1 + examples/calc_1.basic | 5 + examples/hello_world.basic | 1 + main | Bin 0 -> 16344 bytes src/main.c | 193 +++++++++++++++++++++++++++++++++++++ src/stack.c | 14 +++ src/stack.h | 9 ++ 11 files changed, 313 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 examples/basic_1.basic create mode 100644 examples/basic_2.basic create mode 100644 examples/calc_1.basic create mode 100644 examples/hello_world.basic create mode 100755 main create mode 100644 src/main.c create mode 100644 src/stack.c create mode 100644 src/stack.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b81853 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +./main diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ad9abfa --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +WERROR?= +CFLAGS=-Wall -Wextra $(WERROR) -pedantic -I. +CXXFLAGS_WITHOUT_PKGS=$(CFLAGS) -fno-exceptions -Wno-missing-braces -Wswitch-enum -lm + +build: + gcc src/* -o ./main ${CXXFLAGS_WITHOUT_PKGS} diff --git a/README.md b/README.md new file mode 100644 index 0000000..86ddf60 --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# Simple BASIC language implementation + +The goal of this project is to create a simple implementation of a BASIC-like language. +No need to do complex thing, just to create a simple interpreted language that can be used to do some arithmetics +and create for ex a number guessing game. + +## Technology + +We will create our own regex engine + +## Syntax + +One instruction set per line + +Instruction sets avalaibles: + +### Commentary + +can only use single line comments with `#` + +``` +# this is a comment +``` + +### Expression evaluation + +can only operate on integer + +function calls: func(arg_a, arg_b) +operators: +, *, / +booleans operators: not, and, or, + +### function definition + +``` +function {NAME} +begin +... +end +``` + +### Set a variable + +``` +set {VARNAME} to {EXPRESSION} +``` + +### Conditional structure + +``` +if {EXPRESSION} then +begin + ... +end +``` + +### Conditional loop + +``` +while {EXPRESSION} do +begin + ... +end +``` + +### Unconditional loop + +``` +repeat {EXPRESSION THAT EVALUATE TO INT} +begin + +end +``` + +### std functions + +``` +put_stdout() +take_stdin() +int_of_string() +random_int(min, max) +``` diff --git a/examples/basic_1.basic b/examples/basic_1.basic new file mode 100644 index 0000000..f754f45 --- /dev/null +++ b/examples/basic_1.basic @@ -0,0 +1 @@ +PRINT 1 \ No newline at end of file diff --git a/examples/basic_2.basic b/examples/basic_2.basic new file mode 100644 index 0000000..46dbaa8 --- /dev/null +++ b/examples/basic_2.basic @@ -0,0 +1 @@ +PRINT (1+2) \ No newline at end of file diff --git a/examples/calc_1.basic b/examples/calc_1.basic new file mode 100644 index 0000000..1b459c0 --- /dev/null +++ b/examples/calc_1.basic @@ -0,0 +1,5 @@ +LET A BE 0 +WHILE NOT A DO +PRINT A +LET A BE A+1 +ENDWHILE diff --git a/examples/hello_world.basic b/examples/hello_world.basic new file mode 100644 index 0000000..9e5807f --- /dev/null +++ b/examples/hello_world.basic @@ -0,0 +1 @@ +PRINT "Hello World" diff --git a/main b/main new file mode 100755 index 0000000000000000000000000000000000000000..c27a9db9ac3d8c2a28e6562863233f68d1f37e70 GIT binary patch literal 16344 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 q)0Ue3;q~(xVC*}xl~in3*$;S(bG +#include +#include +#include "./stack.h" + +struct IntParsingResult { + bool hasError; + int value; +}; + +bool is_operator(char candidate) { + return ( + candidate == '*' || + candidate == '+' + ); +} + +bool is_char_numeral(char candidate) { + int n = (int) candidate; + return n >= 48 && n <= 57; +} + +int integer_pow(int base, int exponent) +{ + if (exponent == 0) return 1; + int r = 1; + int multiplier = base; + while (exponent) { + // if exponent is even + if (exponent & 1) { + r *= multiplier; + } + + multiplier *= multiplier; + exponent >>= 1; // divide by two the exponent + } + + return r; +} + +int parse_clean_positive_integer(int inputStrLen, char* inputStr, int* result) { + /** + Parse an integer that is just a continus stream of decimal numbers + without any negative sign + **/ + int i = 0; + int value = 0; + + while (inputStr[i] != 0) { + if (!is_char_numeral(inputStr[i])) { + return 1; + } + int numeralIndex = (int) inputStr[i]; + value += ( + integer_pow(10, inputStrLen-(i+1)) * + (numeralIndex & 0b001111) + ); + i++; + } + + *result = value; + + return 0; +} + +int parse_int(char* inputStr, int* result) { + int i = 0; + char cleanStr[sizeof(inputStr)]; + int cleanStrLen = 0; + int signIndex = -1; + while (inputStr[i] != 0) { + if ( + !is_char_numeral(inputStr[i]) && + inputStr[i] != '-' && + inputStr[i] != ' ' && + inputStr[i] != '_' + ) { + // we've encounter a unexpected char + return 1; + } + if (signIndex >= 0 && inputStr[i] == '-') { + // we'v encounter a sign but we already have one + return 1; + } + if (signIndex == -1 && inputStr[i] == '-') { + signIndex = i; + } + if (is_char_numeral(inputStr[i])) { + cleanStr[cleanStrLen] = inputStr[i]; + cleanStrLen++; + } + i++; + } + printf("clean str: %s \n", cleanStr); + + parse_clean_positive_integer(cleanStrLen, cleanStr, result); + + if (signIndex >= 0) { + *result *= -1; + } + + return 0; +} + + +int evaluate(char *inputStr) { + int i = 0; + int leftOperand = 0; + int len = strlen(inputStr); + // we want first to parse the expression and create a stack + // for 4*81 : ["4", "*", "81"] + // for -4*(5+42) : ["-4", "*", "(", "5", "+", "42", ")"] + // as a matter of fact, this is a partition + // so we can treat that as a list of tuple (start,finish) + int partitionStartPos[len]; + int partitionStopPos[len]; + char buff[len]; + int buffPtr = 0; + int partitionPtr = 0; + int lastStartPos = 0; + while (inputStr[i] != 0) { + if ( + is_operator(inputStr[i]) || + inputStr[i] == '(' || + inputStr[i] == ')' + ) { + if (lastStartPos != i) { + partitionStartPos[partitionPtr] = lastStartPos; + partitionStopPos[partitionPtr] = i; + partitionPtr++; + } + + partitionStartPos[partitionPtr] = i; + partitionStopPos[partitionPtr] = i+1; + partitionPtr++; + + lastStartPos = i+1; + i++; + continue; + } + i++; + } + if (lastStartPos != i) { + partitionStartPos[partitionPtr] = lastStartPos; + partitionStopPos[partitionPtr] = i; + partitionPtr++; + } + + // display the partition + printf("partitionPtr: %d \n", partitionPtr); + for (int j = 0; j < partitionPtr; j++) { + printf("start %d ", partitionStartPos[j]); + printf("stop %d ", partitionStopPos[j]); + int len = partitionStopPos[j] - partitionStartPos[j]; + + char buff[sizeof(inputStr)]; + for (int z = 0; z < sizeof(inputStr); z++) { + if (z < len) { + buff[z] = inputStr[partitionStartPos[j]+z]; + } + if (z == len) { + buff[z] = 0; + } + } + + printf("content %s \n", buff); + } + + + return 0; +} + +//int create_stack(int a, int b) + +int main () { + char *inputStr = "4732*(-5851+55)+899"; + + // int i = 0; + // while (inputStr[i] != 0) { + // printf("%d : '%c' \n", i, inputStr[i]); + // i++; + // } + + // int parsedValue = 0; + // if (parse_int("-999", &parsedValue) > 0) { + // printf("Error parsing int \n"); + // } + // printf("Value of int %d \n", parsedValue); + + // read the file + // + printf("result is: %d \n", evaluate(inputStr)); +} diff --git a/src/stack.c b/src/stack.c new file mode 100644 index 0000000..7a8c582 --- /dev/null +++ b/src/stack.c @@ -0,0 +1,14 @@ +#include "./stack.h" + +#define STACK_LEN = 255 + +struct IntStack { + int end_pos; + int data[STACK_LEN]; +} + +int stack_create(int a, int b) +{ + return (a+b); +} + diff --git a/src/stack.h b/src/stack.h new file mode 100644 index 0000000..3a0609c --- /dev/null +++ b/src/stack.h @@ -0,0 +1,9 @@ +#ifndef STACK_H_ +#define STACK_H_ + +#define SOME_CST_A 42 + +int stack_create(int a, int b); + + +#endif