feat(muscript): V3: enforce new line or semicolon between expressions
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
This commit is contained in:
parent
6ffd67f23f
commit
0ae082e7d0
|
@ -22,6 +22,8 @@ public class Lexer extends VersionedComponent {
|
|||
public final String source;
|
||||
public int start, current;
|
||||
|
||||
public boolean passedNewline = false;
|
||||
|
||||
@Deprecated
|
||||
public Lexer(String source) {
|
||||
this(MuScriptVersion.DEFAULT, source);
|
||||
|
@ -51,6 +53,7 @@ public class Lexer extends VersionedComponent {
|
|||
*/
|
||||
public void next() {
|
||||
start = current;
|
||||
passedNewline = false;
|
||||
|
||||
if (isAtEnd()) {
|
||||
createToken(Token.EOF);
|
||||
|
@ -111,7 +114,10 @@ public class Lexer extends VersionedComponent {
|
|||
case '{' -> createToken(Token.LeftBrace);
|
||||
case '}' -> createToken(Token.RightBrace);
|
||||
|
||||
case ';' -> createToken(Token.Semicolon);
|
||||
case ';' -> {
|
||||
createToken(Token.Semicolon);
|
||||
passedNewline = true;
|
||||
}
|
||||
|
||||
default -> unexpected();
|
||||
}
|
||||
|
@ -177,7 +183,11 @@ public class Lexer extends VersionedComponent {
|
|||
if (isAtEnd()) return;
|
||||
|
||||
switch (peek()) {
|
||||
case ' ', '\r', '\t', '\n' -> advance();
|
||||
case ' ', '\t' -> advance();
|
||||
case '\r', '\n' -> {
|
||||
advance();
|
||||
passedNewline = true;
|
||||
}
|
||||
case '/' -> {
|
||||
switch (peekNext()) {
|
||||
case '/' -> {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package io.gitlab.jfronny.muscript.compiler;
|
||||
|
||||
public enum MuScriptVersion {
|
||||
V1, V2;
|
||||
V1, V2, V3;
|
||||
|
||||
public static final MuScriptVersion DEFAULT = V2;
|
||||
public static final MuScriptVersion DEFAULT = V3;
|
||||
|
||||
public boolean contains(MuScriptVersion version) {
|
||||
return compareTo(version) >= 0;
|
||||
|
|
|
@ -131,7 +131,10 @@ public class Parser extends VersionedComponent {
|
|||
List<Expr<?>> expressions = new LinkedList<>();
|
||||
while (!isAtEnd()) {
|
||||
expressions.add(expression());
|
||||
match(Token.Semicolon); // Consume semicolon if present
|
||||
// Consume semicolon if present
|
||||
if (!lexer.passedNewline & !match(Token.Semicolon) & !isAtEnd() & version.contains(MuScriptVersion.V3)) {
|
||||
throw error("Either a semicolon or a new line must separate expressions in scripts");
|
||||
}
|
||||
}
|
||||
if (expressions.isEmpty()) throw new ParseException(PrettyPrintError.builder(lexer.location()).setMessage("Missing any elements in closure").build());
|
||||
return new Script(expressions);
|
||||
|
@ -401,7 +404,11 @@ public class Parser extends VersionedComponent {
|
|||
List<Expr<?>> expressions = new LinkedList<>();
|
||||
while (!match(Token.RightBrace)) {
|
||||
expressions.add(expression());
|
||||
match(Token.Semicolon); // Consume semicolon if present
|
||||
// Consume semicolon if present
|
||||
if (!lexer.passedNewline & !match(Token.Semicolon) & version.contains(MuScriptVersion.V3)) {
|
||||
if (match(Token.RightBrace)) break;
|
||||
throw error("Either a semicolon or a new line must separate expressions in closures");
|
||||
}
|
||||
}
|
||||
int end = previous.start;
|
||||
return new Closure(location(start, end), boundArgs, expressions, variadic);
|
||||
|
|
|
@ -8,11 +8,12 @@ import org.junit.jupiter.api.Test;
|
|||
import static io.gitlab.jfronny.muscript.test.util.MuTestUtil.makeArgs;
|
||||
import static io.gitlab.jfronny.muscript.test.util.MuTestUtil.number;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class ClosureTest {
|
||||
@Test
|
||||
void testScript() {
|
||||
assertEquals(8, Parser.parseScript("function(2, 1) function(2, 2) function(2, 3)")
|
||||
assertEquals(8, Parser.parseScript("function(2, 1); function(2, 2); function(2, 3)")
|
||||
.run(makeArgs())
|
||||
.asNumber()
|
||||
.getValue());
|
||||
|
@ -23,7 +24,7 @@ class ClosureTest {
|
|||
assertEquals(2, number("{->2}()"));
|
||||
assertEquals(2, number("{n->n}(2)"));
|
||||
assertEquals(2, number("{n->n()}({->2})"));
|
||||
assertEquals(2, number("{->num = 2 num = num * 2 num = num - 2}()"));
|
||||
assertThrows(Parser.ParseException.class, () -> number("{->num = 2 num = num * 2 num = num - 2}()"));
|
||||
assertEquals(2, number("{->num = 2; num = num * 2; num = num - 2}()"));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue