GreenLight : Added a syntax checker feature!

Introduction

GreenLight is a new simple programming language created by Marc. This new simple language can help to make CLI program much easier and faster. It takes all the good features from JAVASCRIPT and other many languages.
Variables:
```var hello = "world"; // Mutable variable const constant = "light"; // Constant variable```
Objects/Array:
```let array = [498, 49, 299, 18]; // Declare a new array array[1] = 133; // Modify the second element of the array print(array[1]); // Print the second element of the array let object = { // Declare a new object... "key": "hello world" }; print(object>>key); // Print the value located at the key "key" ```
It also, provides general standard library!
```sqrt(16); // => 4 Get the square root of a number log(1); // => 0 Get the natural logarithm of a number pow(2, 10); // => 1024 Raise a number to an arbitrary power exp(1); // => 2.718281828459045 Get the exponential of a number ... ```

Getting start

There was a one good issue on this project. It didn't catch syntax errors and handle them properly. So, GreenLight decided to improve this feature and let someone help them. Luckily, I was there for help!

Step 1: Testing

The first thing to do is always testing first! So I have run the demo `hello_world.gl` file.

``````print("Welcome to GreenLight!");
print("Hello world!");
logError("I'm an error.");

print("---Cryptography---");
print("The SHA256 hash of 'Hello World' is " + sha256("Hello World") + "!");
print("The SHA3-256 hash of 'Hello World' is " + sha3("Hello World") + "!");

print("A random number between 50 and 100 is " + randomNumberBetween(50, 100));

print("---Array Functions---");

print("- Array Difference:");
const school_subjects = ['Math', 'Geography','History'];
var approved_school_subjects = ['Geography'];
const pending_subjects = arrDiff(school_subjects, approved_school_subjects);
print("The school subjects that still need approval are: " + pending_subjects);

print("- Array Difference Symmetric:");
const female_animals = ['Duck', 'Cat','Elephant','Tiger'];
var male_animals = ['Duck', 'Dog','Elephant','Tiger'];
const animals_alone = arrDiffSymmetric(female_animals, male_animals);
print("Animals that do not have a pair are: " + animals_alone);

print("- Array Intersection:");
const fruits = ['Banana', 'Apple', 'Grape', 'Strawberry'];
var fruits_find = ['Strawberry', 'Apple', 'Watermelon'];
const fruits_found = arrIntersect(fruits, fruits_find);
print("The fruits found were: " + fruits_found);
``````

It was a simple code file, just printed some messages. After compiling this, it showed that the compilations is OK, and ready to run

``````[*] Executing lexer...
[OK] Lexer finished successfully!
[*] Transpiling...
[OK] Transpilation complete!
[*] Running syntax checker & linter...
[OK] Syntax checker finished, no issues found!
``````

and following output message.

``````Welcome to GreenLight!
Hello world!
I'm an error.
---Cryptography---
The SHA256 hash of 'Hello World' is a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e!
The SHA3-256 hash of 'Hello World' is e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51!
A random number between 50 and 100 is 100
---Array Functions---
- Array Difference:
The school subjects that still need approval are: Math,History
- Array Difference Symmetric:
Animals that do not have a pair are: Cat,Dog
- Array Intersection:
The fruits found were: Apple,Strawberry
``````

So far, it seems OK when we correctly write the code using GreenLight syntax. However, what if I intentionally break this?

So, I deleted the ')' on the first line `print("Welcome to GreenLight!");`. It turned out the program didn't catch the syntax error `UnhandledPromiseRejectionWarning: ReferenceError:`.

Step 2: Spot the exact code file that should be improved!

To make an enhancement, I needed to find out which code file is dealing with syntax checking function among the dozens of `.js` code files. Luckily there is a hint from Marc and code itself. When I compiled the code, it showed that `[*] Transpiling...` is ahead of `[*] Running syntax checker & linter...` That means somehow the `Transpiling` process will transform the `.gl` file to '.js' file, and then it will run the `syntax checker`.

Step 3: Inside `transpiler.js`

In the `transpiler.js` file, there is:

``````function runChecks() {
return syntaxChecker.checkSyntax(code);
}
``````

The "code" is already transformed to `.js` syntax. So, in this stage the "code" looks like
```console.log("Welcome to GreenLight!";print("Helloworld!");greenlight_internal_log_error("I'm an error.");console.log("---Cryptography---"); ...```

As we can see, `console.log("Welcome to GreenLight!";` is not closed with ')'.

Step 4: Inside `syntax_checker.js`

In this file, there was no syntax checking feature. It only catched if the user-built function was properly called with `call`.

``````function checkSyntax(compiledCode) {
let checkPassed = true;
let splitCode = compiledCode.split(" ");
if (!checkAsyncFunctionCalls(splitCode)) checkPassed = false;

return checkPassed;
}

function checkAsyncFunctionCalls(code) {
let passed = true;
let withinString = false;
...
return passed;
}
``````

Step 4: Added bracket checking feature

It is impossible for me to added all the syntax checking functions for the "GreenLight." So, I decided to specifically deal with open and close bracket syntax checker. First of all creating a function,
`checkParenthesesBracket` it should `return false` if the bracket doesn't open and close properly.

For example)
`({)}` false
`({[]})` true
`([[])` false

The `checkParenthesesBracket` takes code as parameter. The code was separated by whitespace, but it wouldn't be good idea for this. So It had to be separated by `;`. `let splitCode = compiledCode.split(";");` As a result, `code` is lines of the entire code.

For each line, `for (let i = 0; i < code.length; i++)` must have closing bracket if the open bracket is used.

``````if (code[i].includes("(")) {
let flag = true; // check '(', ')' is a pair
code[i].split("").forEach(char => {
if (flag && char === "(") flag = false; // needs ')'
if (!flag && char === ")") flag = true; // needs '('
});
``````

same for `[]`

``````if (code[i].includes("[")) {
...
}
``````

Step 5: Testing and Wrap up

`if (!checkParenthesesBracket(splitCode)) checkPassed = false;` is added in the `checkSyntax` function right before `checkAsyncFunctionCalls`.

Now run the code again.

``````[*] Executing lexer...
[OK] Lexer finished successfully!
[*] Transpiling...
[OK] Transpilation complete!
[*] Running syntax checker & linter...
[WARN] '(' is not closed. This could cause syntax errors: console.log("Welcome to GreenLight!"
[WARN] Syntax checker found at least one issue in your code!
``````

Now, we can catch the error!