Skip to content

Commit

Permalink
Update 10.0
Browse files Browse the repository at this point in the history
Changes in this update:
- Added multiple features:
    - Added the keyword "import"
    - Added the modulo operator for arithmetic operations
    - Added the ability to comment in the source code
- Fixes:
   - Fixed nearly all the links in the documentation of this project
   - Functions cannot have the same name anymore (Function overloading does not work - It was not even implemented before)
    - Fixed comments in the source code
  • Loading branch information
Christian-2003 authored May 21, 2021
1 parent 5b8bbc3 commit b67eb17
Show file tree
Hide file tree
Showing 10 changed files with 315 additions and 179 deletions.
14 changes: 13 additions & 1 deletion Documentation/Atithmetic operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The result of such arithmetic operations can be used in the source code for diff
<br/>

# Available arithmetic operators:
Currently, there are a total of four operators, which can be used in arithmetic operations:
Currently, there are a total of five operators, which can be used in arithmetic operations:

<br/>

Expand Down Expand Up @@ -83,3 +83,15 @@ The operator `/` is used to divide multiple values. Remember that there is no kn
```

<br/>

## The operator `%`:
The operator `%` is used to get the rest of a division.

### Example:
```Lisp
(defun main () (
(princ (% 5 2)) ;Translates to 5 % 2
))
```

<br/>
2 changes: 1 addition & 1 deletion Documentation/Control characters.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ This character represents a form feed.

<br/>

## `r`:
## `\r`:
This character represents a carriage return.

<br/>
59 changes: 50 additions & 9 deletions Documentation/Keywords.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,51 +19,58 @@ Currently, there are multiple keywords available with this Lisp dialect.
<br/>

### Keywords regarding variables:
[`var`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#var)
[`var`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#var)
<br/>
This keyword is used to declare a new variable.

[`setf`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#setf)
[`setf`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#setf)
<br/>
This keyword is used to change the value of any variable.

<br/>

### Keywords for in- and output:
[`princ`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#princ-princln)
[`princ`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#princ-princln)
<br/>
This keyword is used to output anything in the terminal.

[`princln`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#princ-princln)
[`princln`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#princ-princln)
<br/>
This keyword is used to output anything in the terminal and adds a line break afterwards.

[`scan`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#scan)
[`scan`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#scan)
<br/>
This keyword is used to scan an input from the user.

<br/>

### Keywords for control structures:
[`if`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#if)
[`if`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#if)
<br/>
This keyword indicates an if-statement.

[`while`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#while)
[`while`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#while)
<br/>
This keyword indicates a while-loop.

<br/>

### Keywords for functions:
[`defun`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#defun)
[`defun`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#defun)
<br/>
This keyword is used to define a new function.

[`return`](https://github.com/ChosenChris/LispInterpreter/tree/main/Keywords.md#return)
[`return`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#return)
<br/>
This keyword is used to exit a function and return a value.

<br/>

### Other keywords:
[`import`](https://github.com/ChosenChris/LispInterpreter/blob/main/Documentation/Keywords.md#import)
<br/>
This keyword is used to import source code from another file.

<br/>
<br/>
<br/>
Expand Down Expand Up @@ -344,3 +351,37 @@ This element is returned by the function.
```

<br/>
<br/>
<br/>

## `import`:
The keyword `import` is used to import source code from another file. The functions etc. of the other file can be used in the current file as well.
<br/>
**IMPORTANT:** Please make sure that you do not create a StackOverflow when using the import statement.

<br/>

### Further elements in this list:
_file name_
<br/>
This element represents the file name, which should be imported.

<br/>

### Example:
```Lisp
;File: code.lsp
(defun mul (a b) (
(return (* a b))
))
```
```Lisp
;File: main.lsp
(import "code.lsp")
(defun main () (
(princ mul(2 5)) ;Calls the "mul()"-function from the other file.
))
```

<br/>
95 changes: 94 additions & 1 deletion src/Program.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import java.util.Scanner;

import errorHandling.ReturnValueTypes;
import interpreter.*;


Expand Down Expand Up @@ -57,8 +58,11 @@ else if (sLowerCaseInput.length() >= 4 && sLowerCaseInput.substring(0, 4).equals
String sFilename = sInput.substring(sInput.indexOf(' ') + 1, sInput.length());
//Quellcode ueber den Controller ausfueheren:
Controller controllerObj = new Controller(sFilename);
controllerObj.startController();
int nReturnValue = controllerObj.startController();
System.out.println("\n");
if (nReturnValue != ReturnValueTypes.SUCCESS) {
printErrorMessage("Error: ", nReturnValue, "\n");
}
}

else {
Expand All @@ -67,4 +71,93 @@ else if (sLowerCaseInput.length() >= 4 && sLowerCaseInput.substring(0, 4).equals
}
}
}



/**
* Diese Methode gibt Fehlermeldungen in der Konsole aus.
*
* @param psPrefix Text, welcher vor der Fehlermeldung angezeigt werden soll.
* @param pnErrorMessage Fehlermeldung.
* @param psSuffix Text, welcher nach der Fehlermeldung angezeigt werden soll.
*/
private static void printErrorMessage(String psPrefix, int pnErrorMessage, String psSuffix) {
System.out.print(psPrefix); //Prefix ausgeben.

//Fehlermeldung ausgeben:
if (pnErrorMessage == ReturnValueTypes.SUCCESS) {
System.out.print("Success");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_UNKNOWN) {
System.out.print("Unknown");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_DIVIDE_BY_ZERO) {
System.out.print("Cannot divide by zero");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_UNEQUAL_DATA) {
System.out.print("Operands are of different type");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_SYNTAX) {
System.out.print("Syntax");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_UNKNOWN_OPERATOR) {
System.out.print("Unknown operator");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_UNKNOWN_IDENTIFIER) {
System.out.print("Unknown identifier");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_NOT_ENOUGH_OPERANDS) {
System.out.print("The operation needs more operands");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_CANNOT_OFFSET_STRING_TO_NUMBER) {
System.out.print("Cannot offset String to number");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_UNKNOWN_TOKEN) {
System.out.print("Encountered unknown token.");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_UNKNOWN_KEYWORD) {
System.out.print("Encountered onknown keyword");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_VARIABLE_NAME_DOES_EXIST) {
System.out.print("Variable name does already exist");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_FILE_DOES_NOT_EXIST) {
System.out.print("File does not exist");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_FILE_CANNOT_BE_READ) {
System.out.print("Cannot read file");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_NO_MAIN_FUNCTION) {
System.out.print("Main function is missing");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_MAIN_FUNCTION_HAS_PARAMETER) {
System.out.print("Main function has too many parameters");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_INCORRECT_PARAMETER_NUMBER) {
System.out.print("Function call has an incorrect number of arguments");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_NO_RETURN_VALUE) {
System.out.print("Non-existing return value was expected");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_INSTANCE_NAME_DOES_EXIST) {
System.out.print("The name of an instance is already used");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_INSTANCE_NAME_CANNOT_BE_CLASS_NAME) {
System.out.print("Instance name cannot be class name");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_UNKNOWN_CLASS) {
System.out.print("Unknown class type");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_STACK_OVERFLOW) {
System.out.print("StackOverflow");
}
else if (pnErrorMessage == ReturnValueTypes.ERROR_FUNCTION_NAME_IS_IDENTICAL) {
System.out.println("Multiple functions are defined with the same name");
}
else {
System.out.print("unknwon error occured. Error message: " + pnErrorMessage);
}

System.out.println(psSuffix); //Suffix ausgeben.
}
}
10 changes: 10 additions & 0 deletions src/errorHandling/ReturnValueTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,14 @@ public class ReturnValueTypes {
* Speichert die Fehlermeldung fuer ein unbekanntes Steuerzeichen.
*/
public static int ERROR_UNKNOWN_CTRL_CHAR = 24;

/**
* Speichert die Fehlermeldung fuer einen Funktionsnamen, der mehrmals vorkommt.
*/
public static int ERROR_FUNCTION_NAME_IS_IDENTICAL = 25;

/**
* Speichert die Fehlermeldung fuer import-Schluesselwoerter, die einen StackOverflow erzeugen.
*/
public static int ERROR_IMPORT_STACK_OVERFLOW = 26;
}
15 changes: 11 additions & 4 deletions src/fileScanner/FileScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ else if (!fileObj.canRead()) {
sFileContent = Files.readString(filePathObj);
}
catch (IOException e){
e.printStackTrace();
return new ReturnValue<LinkedList<String>>(null, ReturnValueTypes.ERROR_FILE_CANNOT_BE_READ);
}

//Inhalt der Datei in einzelne Lisp-Ausdruecke unterteilen:
Expand All @@ -61,9 +61,8 @@ else if (!fileObj.canRead()) {
int nBracketsClosed = 0; //Speichert die Anzahl an geschlossenen Klammern.
int nBracketsOpened = 0; //Speichert die Anzahl an geoeffneten Klammern.

//Zeilenumbrueche und Tabulatoren aus dem Quellcode entfernen, da diese den Tokenizer verwirren:
//Tabulatoren aus dem Quellcode entfernen, da diese den Tokenizer verwirren:
sFileContent = sFileContent.replaceAll("\t", "");
sFileContent = sFileContent.replaceAll("\n", "");
sFileContent = sFileContent.replaceAll("\r", "");

//Quellcode zeichenweise durchlaufen um diesen in Ausdruecke zu unterteilen:
Expand All @@ -79,11 +78,19 @@ else if (chCurrentCharacter == ')') {
nBracketsClosed++;
}

if (chCurrentCharacter == ';') {
//Es wurde ein Kommentar gefunden -> Kommentar wird entfernt:
while (!sFileContent.isEmpty() && sFileContent.charAt(0) != '\n') {
sFileContent = sFileContent.substring(1);
}
continue;
}

sCurrentExpression += chCurrentCharacter; //Aktuelles Zeichen dem aktuellen Ausdruck anfuegen.

if ((nBracketsOpened != 0 && nBracketsClosed != 0) && (nBracketsOpened == nBracketsClosed)) {
//Es wurden gleich viele Klammern geoeffnet und geschlossen:
lsSourceCode.add(sCurrentExpression);
lsSourceCode.add(sCurrentExpression.replaceAll("\n", "")); //Zeilenumbruecke entfernen.
sCurrentExpression = "";
nBracketsClosed = 0;
nBracketsOpened = 0;
Expand Down
Loading

0 comments on commit b67eb17

Please sign in to comment.