mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-08 16:56:07 +00:00
improve ParseException
This commit is contained in:
@@ -87,7 +87,7 @@ public class Parser {
|
||||
try {
|
||||
while(tokenizer.hasNext()) tokens.add(tokenizer.fetch());
|
||||
} catch(TokenizerException e) {
|
||||
throw new ParseException("Failed to tokenize input", e);
|
||||
throw new ParseException("Failed to tokenize input", new Position(0, 0), e);
|
||||
}
|
||||
|
||||
// Parse ID
|
||||
@@ -102,9 +102,10 @@ public class Parser {
|
||||
for(Token t : tokens.getTokens()) {
|
||||
if(t.getType().equals(Token.Type.BLOCK_BEGIN)) blockLevel++;
|
||||
else if(t.getType().equals(Token.Type.BLOCK_END)) blockLevel--;
|
||||
if(blockLevel < 0) throw new ParseException("Dangling closing brace: " + t.getPosition());
|
||||
if(blockLevel < 0) throw new ParseException("Dangling closing brace", t.getPosition());
|
||||
}
|
||||
if(blockLevel != 0) throw new ParseException("Dangling opening brace");
|
||||
if(blockLevel != 0)
|
||||
throw new ParseException("Dangling opening brace", tokens.getTokens().get(tokens.getTokens().size() - 1).getPosition());
|
||||
|
||||
return parseBlock(tokens, new HashMap<>());
|
||||
}
|
||||
@@ -129,7 +130,7 @@ public class Parser {
|
||||
Token name = tokens.get();
|
||||
|
||||
if(functions.containsKey(name.getContent()) || variableMap.containsKey(name.getContent()) || builtinFunctions.contains(name.getContent()))
|
||||
throw new ParseException(name.getContent() + " is already defined in this scope: " + name.getPosition());
|
||||
throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition());
|
||||
|
||||
initializer = parseAssignment(forVar, tokens, variableMap);
|
||||
variableMap.put(name.getContent(), forVar);
|
||||
@@ -190,7 +191,7 @@ public class Parser {
|
||||
else if(variableMap.containsKey(id.getContent())) {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER);
|
||||
expression = new Getter(variableMap.get(id.getContent()));
|
||||
} else throw new ParseException("Unexpected token: " + id.getContent() + " at " + id.getPosition());
|
||||
} else throw new ParseException("Unexpected token \" " + id.getContent() + "\"", id.getPosition());
|
||||
}
|
||||
|
||||
if(booleanInverted) { // Invert operation if boolean not detected
|
||||
@@ -323,7 +324,7 @@ public class Parser {
|
||||
ParserUtil.checkType(name, Token.Type.IDENTIFIER); // Name must be an identifier.
|
||||
|
||||
if(functions.containsKey(name.getContent()) || parsedVariables.containsKey(name.getContent()) || builtinFunctions.contains(name.getContent()))
|
||||
throw new ParseException(name.getContent() + " is already defined in this scope: " + name.getPosition());
|
||||
throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition());
|
||||
|
||||
parsedVariables.put(name.getContent(), temp);
|
||||
|
||||
@@ -361,7 +362,7 @@ public class Parser {
|
||||
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
|
||||
|
||||
if(!functions.containsKey(identifier.getContent()) && !builtinFunctions.contains(identifier.getContent()))
|
||||
throw new ParseException("No such function " + identifier.getContent() + ": " + identifier.getPosition());
|
||||
throw new ParseException("No such function \"" + identifier.getContent() + "\"", identifier.getPosition());
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); // Second is body begin
|
||||
|
||||
@@ -376,12 +377,12 @@ public class Parser {
|
||||
FunctionBuilder<?> builder = functions.get(identifier.getContent());
|
||||
|
||||
if(builder.argNumber() != -1 && args.size() != builder.argNumber())
|
||||
throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size() + ": " + identifier.getPosition());
|
||||
throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size(), identifier.getPosition());
|
||||
|
||||
for(int i = 0; i < args.size(); i++) {
|
||||
Returnable<?> argument = args.get(i);
|
||||
if(builder.getArgument(i) == null)
|
||||
throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent() + ": " + identifier.getPosition());
|
||||
throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(), identifier.getPosition());
|
||||
ParserUtil.checkReturnType(argument, builder.getArgument(i));
|
||||
}
|
||||
return builder.build(args, identifier.getPosition());
|
||||
@@ -390,18 +391,18 @@ public class Parser {
|
||||
case "abs":
|
||||
ParserUtil.checkReturnType(args.get(0), Returnable.ReturnType.NUMBER);
|
||||
if(args.size() != 1)
|
||||
throw new ParseException("Expected 1 arguments; found " + args.size() + ": " + identifier.getPosition());
|
||||
throw new ParseException("Expected 1 argument; found " + args.size(), identifier.getPosition());
|
||||
return new AbsFunction(identifier.getPosition(), (Returnable<Number>) args.get(0));
|
||||
case "sqrt":
|
||||
ParserUtil.checkReturnType(args.get(0), Returnable.ReturnType.NUMBER);
|
||||
if(args.size() != 1)
|
||||
throw new ParseException("Expected 1 arguments; found " + args.size() + ": " + identifier.getPosition());
|
||||
throw new ParseException("Expected 1 argument; found " + args.size(), identifier.getPosition());
|
||||
return new SqrtFunction(identifier.getPosition(), (Returnable<Number>) args.get(0));
|
||||
case "pow":
|
||||
ParserUtil.checkReturnType(args.get(0), Returnable.ReturnType.NUMBER);
|
||||
ParserUtil.checkReturnType(args.get(1), Returnable.ReturnType.NUMBER);
|
||||
if(args.size() != 2)
|
||||
throw new ParseException("Expected 1 arguments; found " + args.size() + ": " + identifier.getPosition());
|
||||
throw new ParseException("Expected 1 argument; found " + args.size(), identifier.getPosition());
|
||||
return new PowFunction(identifier.getPosition(), (Returnable<Number>) args.get(0), (Returnable<Number>) args.get(1));
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent());
|
||||
|
||||
@@ -9,23 +9,23 @@ import java.util.Arrays;
|
||||
public class ParserUtil {
|
||||
public static void checkType(Token token, Token.Type... expected) throws ParseException {
|
||||
for(Token.Type type : expected) if(token.getType().equals(type)) return;
|
||||
throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType() + ": " + token.getPosition());
|
||||
throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
public static void checkReturnType(Returnable<?> returnable, Returnable.ReturnType... types) throws ParseException {
|
||||
for(Returnable.ReturnType type : types) if(returnable.returnType().equals(type)) return;
|
||||
throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType() + ": " + returnable.getPosition());
|
||||
throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType(), returnable.getPosition());
|
||||
}
|
||||
|
||||
public static void checkArithmeticOperation(Returnable<?> left, Returnable<?> right, Token operation) throws ParseException {
|
||||
if(!left.returnType().equals(Returnable.ReturnType.NUMBER) || !right.returnType().equals(Returnable.ReturnType.NUMBER)) {
|
||||
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType() + ": " + operation.getPosition());
|
||||
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), operation.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkBooleanOperation(Returnable<?> left, Returnable<?> right, Token operation) throws ParseException {
|
||||
if(!left.returnType().equals(Returnable.ReturnType.BOOLEAN) || !right.returnType().equals(Returnable.ReturnType.BOOLEAN)) {
|
||||
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType() + ": " + operation.getPosition());
|
||||
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), operation.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class ParserUtil {
|
||||
if(returnType.equals(Returnable.ReturnType.STRING) && token.getType().equals(Token.Type.STRING_VARIABLE)) return;
|
||||
if(returnType.equals(Returnable.ReturnType.NUMBER) && token.getType().equals(Token.Type.NUMBER_VARIABLE)) return;
|
||||
if(returnType.equals(Returnable.ReturnType.BOOLEAN) && token.getType().equals(Token.Type.BOOLEAN_VARIABLE)) return;
|
||||
throw new ParseException("Type mismatch, cannot convert from " + returnType + " to " + token.getType() + ": " + token.getPosition());
|
||||
throw new ParseException("Type mismatch, cannot convert from " + returnType + " to " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +44,7 @@ public class ParserUtil {
|
||||
*/
|
||||
public static void checkBinaryOperator(Token token) throws ParseException {
|
||||
if(!token.isBinaryOperator())
|
||||
throw new ParseException("Expected binary operator, found " + token.getType() + ": " + token.getPosition());
|
||||
throw new ParseException("Expected binary operator, found " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
public static Returnable.ReturnType getVariableReturnType(Token varToken) throws ParseException {
|
||||
@@ -56,7 +56,7 @@ public class ParserUtil {
|
||||
case BOOLEAN_VARIABLE:
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
default:
|
||||
throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration: " + varToken.getPosition());
|
||||
throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration", varToken.getPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.api.structures.parser;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Token;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
|
||||
@@ -11,6 +12,7 @@ import java.util.List;
|
||||
*/
|
||||
public class TokenHolder {
|
||||
private final List<Token> tokens = new GlueList<>();
|
||||
private Position last;
|
||||
|
||||
/**
|
||||
* Add a token to the top of the stack.
|
||||
@@ -28,8 +30,10 @@ public class TokenHolder {
|
||||
* @throws ParseException If stack is empty
|
||||
*/
|
||||
public Token get() throws ParseException {
|
||||
if(!hasNext()) throw new ParseException("Unexpected end of input");
|
||||
return tokens.get(0);
|
||||
if(!hasNext()) throw new ParseException("Unexpected end of input", last);
|
||||
Token token = tokens.get(0);
|
||||
last = token.getPosition();
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,8 +43,10 @@ public class TokenHolder {
|
||||
* @throws ParseException If stack is empty
|
||||
*/
|
||||
public Token consume() throws ParseException {
|
||||
if(!hasNext()) throw new ParseException("Unexpected end of input");
|
||||
return tokens.remove(0);
|
||||
if(!hasNext()) throw new ParseException("Unexpected end of input", last);
|
||||
Token token = tokens.remove(0);
|
||||
last = token.getPosition();
|
||||
return token;
|
||||
}
|
||||
|
||||
public List<Token> getTokens() {
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
package com.dfsek.terra.api.structures.parser.exceptions;
|
||||
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class ParseException extends Exception {
|
||||
public ParseException() {
|
||||
super();
|
||||
}
|
||||
private final Position position;
|
||||
|
||||
public ParseException(String message) {
|
||||
public ParseException(String message, Position position) {
|
||||
super(message);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public ParseException(String message, Throwable cause) {
|
||||
public ParseException(String message, Position position, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public ParseException(Throwable cause) {
|
||||
super(cause);
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return super.getMessage() + ": " + position;
|
||||
}
|
||||
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public class StructureFunctionBuilder implements FunctionBuilder<StructureFuncti
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public StructureFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
if(argumentList.size() < 5) throw new ParseException("Expected rotations: " + position);
|
||||
if(argumentList.size() < 5) throw new ParseException("Expected rotations", position);
|
||||
|
||||
return new StructureFunction((Returnable<Number>) argumentList.remove(0), (Returnable<Number>) argumentList.remove(0), (Returnable<Number>) argumentList.remove(0), (Returnable<String>) argumentList.remove(0),
|
||||
argumentList.stream().map(item -> ((Returnable<String>) item)).collect(Collectors.toList()), registry, position, main);
|
||||
|
||||
@@ -22,7 +22,7 @@ public class BlockFunction implements Function<Void> {
|
||||
|
||||
public BlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) throws ParseException {
|
||||
this.position = position;
|
||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant.");
|
||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
|
||||
|
||||
this.data = main.getWorldHandle().createBlockData(((ConstantExpression<String>) data).getConstant());
|
||||
this.x = x;
|
||||
|
||||
Reference in New Issue
Block a user