This commit is contained in:
nora 2021-05-28 14:40:57 +02:00 committed by GitHub
parent 0b96e0dd0d
commit e8967b3273
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 237 additions and 0 deletions

159
README.md Normal file
View file

@ -0,0 +1,159 @@
# GRSBPL - Generic Random Stack Based Programming Language
## line numbers are broken I know
uses some form of reverse polish notation
```
1 5 * 5 +
> 10
```
There is a stack and variables. Operations are done on the stack, and you can store results in variables (a bit like in
the JVM). The stack contains integer values. Floating point numbers are not supported.
When the program finishes (run to the end of the program), the last value on the stack is returned. If the stack is
clear, 0 is always returned. If there is an error during execution, -1 is returned along with an error message to
stderr.
## Operators and keywords:
### Values
* any number `<number>` -> push the numeric value of n
* any character `'<character>'` -> push c as its escaped ascii value
* `&<ident>` -> pop and store it in a variable
* `@<ident>` -> load variable and push it, does not consume the variable
### Binary Operators
* `+` -> add two values on the stack, pops both and pushes the result
* `-` -> subtract two values on the stack, pops both and pushes the result
* `*` -> multiply two values on the stack, pops both and pushes the result
* `/` -> divide, pops both and pushes the result
* `%` -> mod, pops both and pushes the result
* `bnot` bitwise not on stack value
* `and` bitwise and
* `or` bitwise or
* `xor` bitwise xor
### Other operators
* `not` -> invert stack value (!=0 -> 0, 0 -> 1)
* `dup` -> duplicate the value on the stack
* `swap` -> swaps the 2 top stack values
* `pop`-> pop a value and discard it
### IO
* `out` -> pop and output it to the console as ascii
* `nout` -> pop and output as a number to the console
* `in` -> push input char as ascii to the stack
### Control flow
* `:<ident>` -> define a label
* `goto <ident>` -> goto a label if the value on the stack is !=0, peek
* `function <ident> <digit>` -> define a function with the arg count, always return a single number
* `<ident>` -> call a function, args have to be in the stack
* `return` -> return from a function
### Other
* `# comment #` text between # is ignored
* `# comment\n` text after # is ignored
`<ident>`: \w+, not a keyword
`<number>`: \d+
`<digit>`: \d
`<character>`: single character
Character escape sequences:
\n, \r, \\, \0, \', \b, \f
Same meaning as in Java
## Functions
When a function is called, a new stack frame for that function is created. The amount of args that function expects is
then popped of the stack and pushed onto that new stack frame, keeping the same order. After a function is finished, it
can return, deleting the stack frame and all local variables, and returning the top value on the stack. This value is
then pushed onto the parent stack. Execution now continues.
Since there are no blocks, a function missing a return keyword will simply continue to execute until it reaches the end
or jumps due to gotos.
Function 'bodies' (there are no bodies) are not ignored by the main flow, and have to be explicitly skipped by gotos.
It's recommended to place all functions at the end, and have one goto that ends the program by jumping to a label at the
end
## Examples:
FizzBuzz
```grsbpl
1 &i # init loop counter
:start # set start label
@i 100 - not goto exit # if i is 100, exit
@i 15 % not goto print_fizz_buzz # fizzbuzz
@i 5 % not goto print_buzz # buzz
@i 3 % not goto print_fizz # fizz
@i nout '\n' out # normal number
:end # go back here after printing
@i 1 + &i # increment i
1 goto start # go back to the start
:print_fizz_buzz
'F' out 'i' out 'z' out 'z' out 'B' out 'u' out 'z' out 'z' out '\n' out
goto end
:print_fizz
'F' out 'i' out 'z' out 'z' out '\n' out
goto end
:print_buzz
'B' out 'u' out 'z' out 'z' out '\n' out
goto end
:exit 0
```
Add function
```grsbpl
1 2 add
function add 2
+ return
```
Recursive Factorial
```grsbpl
10 factorial 1 goto exit
function factorial 1
dup not goto isZero
&del dup 1 - factorial * return
:isZero
1 return
:exit swap
```
## Some Tips
* Increment a variable:
`@i 1 + &i`
* Goto if equal
`@i 100 - not goto finished`
* Goto not equal
`@i 100 - goto finished`
* Exit the program
`... goto exit ... :exit 0`
* Exit with exit code depending on the branch
```grsbpl
...
69 swap goto exit # push 69 to the 2nd stack position
...
5 swap goto exit # push 5 to the 2nd stack position
...
:exit &del # pop the top stack value to expose the pushed value
```

38
errors.md Normal file
View file

@ -0,0 +1,38 @@
# All GRSBPL Error Messages
## Syntax Errors
- Any uncaught exception occurs during lexing:
`Unknown Syntax Error. <exceptionname>: <exceptionmessage>`
- Invalid character escaped:
`Invalid escape sequence <escaped>`
- Integer parse failed (can only happen because number is too big)
`Value not an integer: <number>`
## Runtime Errors
- Label not found
`Label '<name>' not found`
- Function not found
`Function '<name>' not found`
- Stack empty on return
`Function has to return some value, but no value was found on the stack`
- Pop called on empty stack
`Cannot pop empty stack`
- No stack frame left after return
`Tried to return outside of function, probably forgot to skip a function`
- Stackoverflow - limit 1 000 000
`Stackoverflow. Limit of <STACK_LIMIT> stack frames reached.`
- Invalid token found
`Excepted token '<name>' but found '<name>'`
- Failed to read input from stdin
`[VM] - Error reading input`

9
fizzbuzz.grsbpl Normal file
View file

@ -0,0 +1,9 @@
10 factorial 1 goto exit
function factorial 1
dup not goto isZero
pop dup 1 - factorial * return
:isZero
1 pop return
:exit pop dup nout

31
pom.xml Normal file
View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.nilstrieb</groupId>
<artifactId>GRSBPL</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>