mirror of
https://github.com/Noratrieb/GRSBPL.git
synced 2026-01-15 20:25:01 +01:00
great commit history
This commit is contained in:
parent
af55c80677
commit
0b96e0dd0d
14 changed files with 1279 additions and 0 deletions
45
src/test/java/com/github/nilstrieb/grsbpl/IntStackTest.java
Normal file
45
src/test/java/com/github/nilstrieb/grsbpl/IntStackTest.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package com.github.nilstrieb.grsbpl;
|
||||
|
||||
import com.github.nilstrieb.grsbpl.language.IntStack;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class IntStackTest {
|
||||
|
||||
@Test
|
||||
void pushPop() {
|
||||
IntStack s = new IntStack();
|
||||
|
||||
s.push(100);
|
||||
s.push(50);
|
||||
|
||||
assertEquals(50, s.pop());
|
||||
assertEquals(100, s.pop());
|
||||
|
||||
assertThrows(IndexOutOfBoundsException.class, s::pop);
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyFunction() {
|
||||
IntStack s = new IntStack();
|
||||
s.push(10);
|
||||
s.push(2);
|
||||
s.apply2((i1, i2) -> i1 / i2);
|
||||
assertEquals(5, s.pop());
|
||||
assertThrows(IndexOutOfBoundsException.class, s::pop);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resize() {
|
||||
IntStack s = new IntStack();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
s.push(i);
|
||||
}
|
||||
|
||||
for (int i = 999; i >= 0; i--) {
|
||||
assertEquals(i, s.pop());
|
||||
}
|
||||
}
|
||||
}
|
||||
195
src/test/java/com/github/nilstrieb/grsbpl/InterpreterTest.java
Normal file
195
src/test/java/com/github/nilstrieb/grsbpl/InterpreterTest.java
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
package com.github.nilstrieb.grsbpl;
|
||||
|
||||
import com.github.nilstrieb.grsbpl.language.Interpreter;
|
||||
import com.github.nilstrieb.grsbpl.language.Lexer;
|
||||
import com.github.nilstrieb.grsbpl.language.Token;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class InterpreterTest {
|
||||
|
||||
static Interpreter interpreter;
|
||||
|
||||
static OutStream out;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
interpreter = new Interpreter();
|
||||
out = new OutStream();
|
||||
System.setOut(out);
|
||||
}
|
||||
|
||||
@Test
|
||||
void arithmeticOperations() {
|
||||
String program = "1 1 * 2 +";
|
||||
assertEquals(3, run(program));
|
||||
String program2 = "10 5 /";
|
||||
assertEquals(2, run(program2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void bigNumbers() {
|
||||
String program = "1000 1234 +";
|
||||
assertEquals(2234, run(program));
|
||||
}
|
||||
|
||||
@Test
|
||||
void comment() {
|
||||
String program = "1 # sdkfjsaf se9 83 252h43ui\n 2 # test 5 # +";
|
||||
assertEquals(3, run(program));
|
||||
}
|
||||
|
||||
@Test
|
||||
void variables() {
|
||||
String program = "1 &one 2 &two 3 &three 8 @two +";
|
||||
assertEquals(10, run(program));
|
||||
}
|
||||
|
||||
@Test
|
||||
void labels() {
|
||||
String program = "1 :first 2 0";
|
||||
assertEquals(0, run(program));
|
||||
}
|
||||
|
||||
@Test
|
||||
void gotoBack() {
|
||||
String program = "100000000 &i \n" +
|
||||
":start \n" +
|
||||
"@i nout '\n' out \n" +
|
||||
"@i 1 - &i \n" +
|
||||
"@i goto start \n" +
|
||||
" 0";
|
||||
int result = 0;
|
||||
assertEquals(result, run(program));
|
||||
}
|
||||
|
||||
@Test
|
||||
void gotoSkip() {
|
||||
String program = "1 :first 0 goto first 1 goto skip 3754 78349758 :skip";
|
||||
int result = 1;
|
||||
assertEquals(result, run(program));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fizzBuzz() throws IOException, URISyntaxException {
|
||||
String program = Files.readString(Path.of(getClass().getClassLoader().getResource("fizzbuzz.grsbpl").toURI()));
|
||||
int result = 0;
|
||||
StringBuilder resultString = new StringBuilder();
|
||||
for (int i = 1; i < 100; i++) {
|
||||
if (i % 15 == 0) resultString.append("FizzBuzz\n");
|
||||
else if (i % 5 == 0) resultString.append("Buzz\n");
|
||||
else if (i % 3 == 0) resultString.append("Fizz\n");
|
||||
else resultString.append(i).append("\n");
|
||||
}
|
||||
assertEquals(result, run(program));
|
||||
assertEquals(resultString.toString(), out.getOut());
|
||||
}
|
||||
|
||||
@Test
|
||||
void stackManipulationTest() {
|
||||
String program = "1 2 swap";
|
||||
assertEquals(1, run(program));
|
||||
|
||||
String program2 = "0 not";
|
||||
assertEquals(1, run(program2));
|
||||
|
||||
String program3 = "1 not";
|
||||
assertEquals(0, run(program3));
|
||||
|
||||
String program4 = "5 dup pop";
|
||||
assertEquals(5, run(program4));
|
||||
|
||||
String program5 = "1 2 pop";
|
||||
assertEquals(1, run(program5));
|
||||
}
|
||||
|
||||
@Test
|
||||
void bitwise() {
|
||||
String p1 = "10 10 xor";
|
||||
assertEquals(0, run(p1));
|
||||
|
||||
String p2 = "1 bnot";
|
||||
assertEquals(~1, run(p2));
|
||||
|
||||
String p3 = 0xFF + " 1 and";
|
||||
assertEquals(1, run(p3));
|
||||
|
||||
String p4 = 0b001 + " " + 0b101 + " or";
|
||||
assertEquals(0b101, run(p4));
|
||||
}
|
||||
|
||||
@Test
|
||||
void functionTest() {
|
||||
String program = "" +
|
||||
"1 printNumber " +
|
||||
"2 printNumber " +
|
||||
"3 printNumber " +
|
||||
"1 goto end" +
|
||||
" " +
|
||||
"function printNumber 1 nout 0 return" +
|
||||
":end 0";
|
||||
int result = 0;
|
||||
assertEquals(result, run(program));
|
||||
assertEquals("123", out.getOut());
|
||||
}
|
||||
|
||||
@Test
|
||||
void factorial() throws URISyntaxException, IOException {
|
||||
String program0 = 0 + Files.readString(Path.of(getClass().getClassLoader().getResource("factorial.grsbpl").toURI()));
|
||||
String program1 = 1 + Files.readString(Path.of(getClass().getClassLoader().getResource("factorial.grsbpl").toURI()));
|
||||
String program10 = 10 + Files.readString(Path.of(getClass().getClassLoader().getResource("factorial.grsbpl").toURI()));
|
||||
|
||||
assertEquals(1, run(program0));
|
||||
assertEquals(1, run(program1));
|
||||
assertEquals(3628800, run(program10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outTest() {
|
||||
String program = "'\n' '!' 'd' 'l' 'r' 'o' 'w' ' ' 'o' 'l' 'l' 'e' 'h' out out out out out out out out out out out out out 0";
|
||||
|
||||
assertEquals(0, run(program));
|
||||
assertEquals("hello world!\n", out.getOut());
|
||||
}
|
||||
|
||||
static class OutStream extends PrintStream {
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
|
||||
public OutStream() {
|
||||
super(new OutputStream() {
|
||||
@Override
|
||||
public void write(int b) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(char c) {
|
||||
builder.append(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(int i) {
|
||||
builder.append(i);
|
||||
}
|
||||
|
||||
public String getOut() {
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
int run(String program) {
|
||||
List<Token> tokens = new Lexer().lex(program.toCharArray());
|
||||
return interpreter.run(tokens);
|
||||
}
|
||||
}
|
||||
122
src/test/java/com/github/nilstrieb/grsbpl/LexerTest.java
Normal file
122
src/test/java/com/github/nilstrieb/grsbpl/LexerTest.java
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package com.github.nilstrieb.grsbpl;
|
||||
|
||||
import com.github.nilstrieb.grsbpl.language.Lexer;
|
||||
import com.github.nilstrieb.grsbpl.language.Token;
|
||||
import com.github.nilstrieb.grsbpl.language.TokenType;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.github.nilstrieb.grsbpl.language.TokenType.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LexerTest {
|
||||
|
||||
Lexer lexer;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
lexer = new Lexer();
|
||||
}
|
||||
|
||||
@Test
|
||||
void keywords() {
|
||||
String program = "out in nout xor or and not bnot pop dup swap goto function return not";
|
||||
List<TokenType> expected = List.of(OUT, IN, NOUT, XOR, OR, AND, NOT, BNOT, POP, DUP, SWAP, GOTO, FUNCTION, RETURN, NOT, EOF);
|
||||
List<TokenType> actual = getTypes(lex(program));
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void symbols() {
|
||||
String program = "+ & @ - % / * : +";
|
||||
List<TokenType> expected = List.of(PLUS, AMPERSAND, AT, MINUS, PERCENT, SLASH, STAR, COLUMN, PLUS, EOF);
|
||||
List<TokenType> actual = getTypes(lex(program));
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void identifiers() {
|
||||
String program = "out test xor hallo + stack";
|
||||
List<TokenType> expected = List.of(OUT, IDENTIFIER, XOR, IDENTIFIER, PLUS, IDENTIFIER, EOF);
|
||||
List<Token> actual = lex(program);
|
||||
assertEquals(expected, getTypes(actual));
|
||||
|
||||
Token test = new Token(IDENTIFIER, "test", 1, 4);
|
||||
assertEquals(test, actual.get(1));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void numbers() {
|
||||
String program = "out 347 test 64006 in";
|
||||
List<TokenType> expected = List.of(OUT, CHARACTER, IDENTIFIER, CHARACTER, IN, EOF);
|
||||
List<Token> actual = lex(program);
|
||||
assertEquals(expected, getTypes(actual));
|
||||
|
||||
Token test = new Token(CHARACTER, 347, 1, 4);
|
||||
assertEquals(test, actual.get(1));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void chars() {
|
||||
String program = "'h' '\\n' '\\r' '\\f' '\\\\' '\\b' '\\'' '\\0'";
|
||||
List<Character> expected = List.of('h', '\n', '\r', '\f', '\\', '\b', '\'', '\0');
|
||||
List<Token> actual = lex(program);
|
||||
assertEquals(expected, actual.stream()
|
||||
.map(Token::getValue)
|
||||
.filter(Objects::nonNull)
|
||||
.limit(8)
|
||||
.collect(Collectors.toUnmodifiableList()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void comments() {
|
||||
String program = "goto # hallo # goto #test\n goto";
|
||||
List<TokenType> expected = List.of(GOTO, GOTO, GOTO, EOF);
|
||||
List<TokenType> actual = getTypes(lex(program));
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void lineNumber() {
|
||||
String program = "goto \n \n goto \ngoto";
|
||||
List<TokenType> expected = List.of(GOTO, GOTO, GOTO, EOF);
|
||||
List<Token> actual = lex(program);
|
||||
assertEquals(expected, getTypes(actual));
|
||||
|
||||
Token test = new Token(GOTO, null, 4, 0);
|
||||
assertEquals(test, actual.get(2));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void identifierName() {
|
||||
String program = "test ABC g9tgq fe_53f";
|
||||
List<String> expected = List.of("test", "ABC", "g9tgq", "fe_53f");
|
||||
assertEquals(expected, getValues(lex(program)));
|
||||
}
|
||||
|
||||
List<Token> lex(String program) {
|
||||
return lexer.lex(program.toCharArray());
|
||||
}
|
||||
|
||||
List<Object> getValues(List<Token> tokens) {
|
||||
return tokens.stream()
|
||||
.map(Token::getValue)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
List<TokenType> getTypes(List<Token> tokens) {
|
||||
return tokens.stream()
|
||||
.map(Token::getType)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue