initial commit
This commit is contained in:
commit
1f4f58b3fb
11 changed files with 313 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
./main
|
6
Makefile
Normal file
6
Makefile
Normal file
|
@ -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}
|
82
README.md
Normal file
82
README.md
Normal file
|
@ -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)
|
||||
```
|
1
examples/basic_1.basic
Normal file
1
examples/basic_1.basic
Normal file
|
@ -0,0 +1 @@
|
|||
PRINT 1
|
1
examples/basic_2.basic
Normal file
1
examples/basic_2.basic
Normal file
|
@ -0,0 +1 @@
|
|||
PRINT (1+2)
|
5
examples/calc_1.basic
Normal file
5
examples/calc_1.basic
Normal file
|
@ -0,0 +1,5 @@
|
|||
LET A BE 0
|
||||
WHILE NOT A DO
|
||||
PRINT A
|
||||
LET A BE A+1
|
||||
ENDWHILE
|
1
examples/hello_world.basic
Normal file
1
examples/hello_world.basic
Normal file
|
@ -0,0 +1 @@
|
|||
PRINT "Hello World"
|
BIN
main
Executable file
BIN
main
Executable file
Binary file not shown.
193
src/main.c
Normal file
193
src/main.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#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));
|
||||
}
|
14
src/stack.c
Normal file
14
src/stack.c
Normal file
|
@ -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);
|
||||
}
|
||||
|
9
src/stack.h
Normal file
9
src/stack.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef STACK_H_
|
||||
#define STACK_H_
|
||||
|
||||
#define SOME_CST_A 42
|
||||
|
||||
int stack_create(int a, int b);
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue