Skip to content

Commit

Permalink
[interval] Implements basic interval
Browse files Browse the repository at this point in the history
  • Loading branch information
Hazurl committed Jun 23, 2023
1 parent 9b77209 commit d7e45fe
Show file tree
Hide file tree
Showing 12 changed files with 268 additions and 28 deletions.
1 change: 1 addition & 0 deletions src/main/java/leekscript/common/Error.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,5 @@ public enum Error {
OVERRIDDEN_METHOD_DIFFERENT_TYPE, // 135
USELESS_CAST, // 136
TOO_MUCH_ERRORS, // 137
INTERVAL, // 138
}
1 change: 1 addition & 0 deletions src/main/java/leekscript/common/Type.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class Type {
public static final Type VOID = new Type("void", "v", "Object", "Object", "null");
public static final Type LEGACY_ARRAY = new LegacyArrayType();
public static final Type ARRAY = array(Type.ANY);
public static final Type INTERVAL = new Type("interval", "t", "IntervalLeekValue", "IntervalLeekValue", "new IntervalLeekValue()");
public static final Type ARRAY_INT = array(Type.INT);
public static final Type ARRAY_STRING = array(Type.STRING);
public static final Type INT_OR_NULL = compound(Type.INT, Type.NULL);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/leekscript/compiler/LeekScript.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

public class LeekScript {

public final static int LATEST_VERSION = 4;
public final static int LATEST_VERSION = 5;
private static long id = 1;

private static ResourceFileSystem defaultFileSystem = new ResourceFileSystem();
Expand Down
47 changes: 32 additions & 15 deletions src/main/java/leekscript/compiler/LexicalParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ private boolean tryParseOperator() {
return true;
}

if (version >= 5 && tryParseExact("..", TokenType.DOT_DOT)) {
return true;
}

if (version >= 2 && tryParseExact('.', TokenType.DOT)) {
return true;
}
Expand Down Expand Up @@ -134,6 +138,25 @@ private boolean tryParseIdentifier() {
return true;
}

private boolean isCharacterAcceptedInNumber(char c, char previous) {
if (c >= '0' && c <= '9') return true;
if (c >= 'A' && c <= 'Z') return true;
if (c >= 'a' && c <= 'z') return true;
if (c >= 'À' && c <= 'Ö') return true;
if (c >= 'à' && c <= 'ö') return true;
if (c >= 'Ø' && c <= 'Ý') return true;
if (c >= 'ø' && c <= 'ý') return true;
if (c >= 'Œ' && c <= 'œ') return true;
if (c == '_' || c == 'ÿ') return true;
if (c == '-' || c == '+') {
if (stream.peek(-1) == 'e' || stream.peek(-1) == 'p') {
return true;
}
}

return false;
}

private boolean tryParseNumber(ErrorReporter error) throws LeekCompilerException {
var startingPoint = stream.getRestorePoint();

Expand All @@ -144,28 +167,22 @@ private boolean tryParseNumber(ErrorReporter error) throws LeekCompilerException
stream.next();

for (char c = stream.peek(); stream.hasMore(); c = stream.next()) {
if (c >= '0' && c <= '9') continue;
if (c >= 'A' && c <= 'Z') continue;
if (c >= 'a' && c <= 'z') continue;
if (c >= 'À' && c <= 'Ö') continue;
if (c >= 'à' && c <= 'ö') continue;
if (c >= 'Ø' && c <= 'Ý') continue;
if (c >= 'ø' && c <= 'ý') continue;
if (c >= 'Œ' && c <= 'œ') continue;
if (c == '_' || c == 'ÿ') continue;
if (c == '-' || c == '+') {
if (stream.peek(-1) == 'e' || stream.peek(-1) == 'p') {
continue;
} else {
break;
}

if (isCharacterAcceptedInNumber(c, stream.peek(-1))) {
continue;
}

if (c == '.') {
if (stream.getSubStringSince(startingPoint).contains(".")) {
error.report(new AnalyzeError(new Token(TokenType.NOTHING, ".", aiFile, stream.getLineCounter(), stream.getCharCounter() + 1), AnalyzeErrorLevel.ERROR, Error.INVALID_CHAR));
break;
}

// We don't eat the dot if the number doesn't continue
if (version >= 5 && !isCharacterAcceptedInNumber(stream.peek(1), c)) {
break;
}

continue;
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/leekscript/compiler/TokenType.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public enum TokenType {
BRACKET_LEFT,
BRACKET_RIGHT,
DOUBLE_POINT,
DOT,
DOT,
DOT_DOT,
ARROW,
END_OF_FILE,
}
38 changes: 29 additions & 9 deletions src/main/java/leekscript/compiler/WordCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import leekscript.compiler.expression.LeekExpression;
import leekscript.compiler.expression.LeekExpressionException;
import leekscript.compiler.expression.LeekFunctionCall;
import leekscript.compiler.expression.LeekInterval;
import leekscript.compiler.expression.LeekMap;
import leekscript.compiler.expression.LeekNull;
import leekscript.compiler.expression.LeekNumber;
Expand Down Expand Up @@ -1466,7 +1467,7 @@ public Expression readExpression(boolean inList) throws LeekCompilerException {
retour.addExpression(new LeekString(word, word.getWord()));

} else if (word.getType() == TokenType.BRACKET_LEFT) {
retour.addExpression(readArrayOrMap(mTokens.eat()));
retour.addExpression(readArrayOrMapOrInterval(mTokens.eat()));

} else if (getVersion() >= 2 && word.getType() == TokenType.ACCOLADE_LEFT) {

Expand Down Expand Up @@ -1588,7 +1589,7 @@ private boolean wordEquals(Token word, String expected) {
return word.getWord().equals(expected);
}

private Expression readArrayOrMap(Token openingBracket) throws LeekCompilerException {
private Expression readArrayOrMapOrInterval(Token openingBracket) throws LeekCompilerException {
if (version < 4) {
return readLegacyHybridContainer(openingBracket);
}
Expand All @@ -1614,17 +1615,18 @@ private Expression readArrayOrMap(Token openingBracket) throws LeekCompilerExcep
}

var firstExpression = readExpression(true);
boolean isMap = mTokens.get().getWord().equals(":");

if (isMap) {
if (mTokens.get().getWord().equals(":")) {
mTokens.skip();
return readMap(openingBracket, firstExpression, mTokens.get());
return readMap(openingBracket, firstExpression);
} else if (version >= 5 && mTokens.get().getType() == TokenType.DOT_DOT) {
mTokens.skip();
return readInterval(openingBracket, firstExpression);
} else {
return readArray(openingBracket, firstExpression, mTokens.get());
return readArray(openingBracket, firstExpression);
}
}

private Expression readMap(Token openingBracket, Expression firstExpression, Token firstToken) throws LeekCompilerException {
private Expression readMap(Token openingBracket, Expression firstExpression) throws LeekCompilerException {
var container = new LeekMap(openingBracket);

var secondExpression = readExpression(true);
Expand Down Expand Up @@ -1654,7 +1656,7 @@ private Expression readMap(Token openingBracket, Expression firstExpression, Tok
return container;
}

private Expression readArray(Token openingBracket, Expression firstExpression, Token firstToken) throws LeekCompilerException {
private Expression readArray(Token openingBracket, Expression firstExpression) throws LeekCompilerException {
var container = new LeekArray(openingBracket);

container.addValue(firstExpression);
Expand Down Expand Up @@ -1745,6 +1747,24 @@ private Expression readLegacyHybridContainer(Token openingBracket) throws LeekCo
return container;
}

private Expression readInterval(Token openingBracket, Expression fromExpression) throws LeekCompilerException {
// Although an interval is not comma separated, we still parse the second
// expression as if we did. This is in order to be more consitent as the first
// expression is parsed as if it was comma separated
var toExpression = readExpression(true);

var nextToken = mTokens.get();
if (nextToken.getWord().equals(":")) {
throw new LeekCompilerException(mTokens.get(), Error.ASSOCIATIVE_ARRAY);
} else if (nextToken.getType() == TokenType.VIRG) {
throw new LeekCompilerException(mTokens.get(), Error.SIMPLE_ARRAY);
} else if (nextToken.getType() != TokenType.BRACKET_RIGHT) {
throw new LeekCompilerException(mTokens.get(), Error.PARENTHESIS_EXPECTED_AFTER_PARAMETERS);
}

return new LeekInterval(openingBracket, fromExpression, toExpression, mTokens.eat());
}

private LeekAnonymousFunction readAnonymousFunction() throws LeekCompilerException {
var token = mTokens.eat();
if (mTokens.get().getType() != TokenType.PAR_LEFT) {
Expand Down
81 changes: 81 additions & 0 deletions src/main/java/leekscript/compiler/expression/LeekInterval.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package leekscript.compiler.expression;

import leekscript.common.Type;
import leekscript.compiler.Hover;
import leekscript.compiler.Token;
import leekscript.compiler.JavaWriter;
import leekscript.compiler.Location;
import leekscript.compiler.WordCompiler;
import leekscript.compiler.bloc.MainLeekBlock;
import leekscript.compiler.exceptions.LeekCompilerException;

public class LeekInterval extends Expression {

private Expression mFrom;
private Expression mTo;
private Token openingBracket;
private Token closingBracket;

public LeekInterval(Token openingBracket, Expression from, Expression to, Token closingBracket) {
this.openingBracket = openingBracket;
this.closingBracket = closingBracket;
this.mFrom = from;
this.mTo = to;

openingBracket.setExpression(this);
closingBracket.setExpression(this);
}

@Override
public int getNature() {
return ARRAY;
}

@Override
public Type getType() {
return Type.INTERVAL;
}

@Override
public String toString() {
return "[" + mFrom + ".." + mTo + "]";
}

@Override
public boolean validExpression(WordCompiler compiler, MainLeekBlock mainBlock) throws LeekExpressionException {
return mFrom.validExpression(compiler, mainBlock) && mTo.validExpression(compiler, mainBlock);
}

@Override
public void preAnalyze(WordCompiler compiler) throws LeekCompilerException {
mFrom.preAnalyze(compiler);
mTo.preAnalyze(compiler);
}

@Override
public void analyze(WordCompiler compiler) throws LeekCompilerException {
operations = 2 + mFrom.getOperations() + mTo.getOperations();
mFrom.analyze(compiler);
mTo.analyze(compiler);
}

@Override
public void writeJavaCode(MainLeekBlock mainBlock, JavaWriter writer) {
writer.addCode("new IntervalLeekValue(" + writer.getAIThis() + ", ");
mFrom.writeJavaCode(mainBlock, writer);
writer.addCode(", ");
mTo.writeJavaCode(mainBlock, writer);
writer.addCode(")");
}

@Override
public Location getLocation() {
return new Location(openingBracket.getLocation(), closingBracket.getLocation());
}

@Override
public Hover hover(Token token) {
var hover = new Hover(getType(), getLocation(), toString());
return hover;
}
}
Loading

0 comments on commit d7e45fe

Please sign in to comment.