commit 1f4f58b3fb9bbc77ec16c74fd2dec216cd575735 Author: Matthieu Bessat Date: Wed Apr 20 20:10:00 2022 +0200 initial commit 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 0000000..c27a9db Binary files /dev/null and b/main differ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..dd54bdc --- /dev/null +++ b/src/main.c @@ -0,0 +1,193 @@ +#include +#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