Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,33 @@ public abstract class AbstractSemanticValidationRule implements SemanticValidati
protected abstract String getDiagnosticSource();

protected QueryDiagnostic buildOutOfScopeDiagnostic(String variableName, String clause) {
return buildOutOfScopeDiagnostic(getDiagnosticSource(), variableName, clause);
}

public static QueryDiagnostic buildOutOfScopeDiagnostic(String source, String variableName, String clause) {
return new QueryDiagnostic(
QueryDiagnostic.Kind.SEMANTIC_ERROR,
QueryDiagnostic.Severity.ERROR,
"Variable ?" + variableName + " used in " + clause + " is not visible in WHERE clause",
-1,
-1,
"?" + variableName,
getDiagnosticSource());
source);
}

protected QueryDiagnostic buildIncorrectTypeDiagnostic(String variableName, String clause, String expectedType) {
return buildIncorrectTypeDiagnostic(getDiagnosticSource(), variableName, clause, expectedType);
}

public static QueryDiagnostic buildIncorrectTypeDiagnostic(String source, String variableName, String clause, String expectedType) {
return new QueryDiagnostic(
QueryDiagnostic.Kind.SEMANTIC_ERROR,
QueryDiagnostic.Severity.ERROR,
variableName + " used in " + clause + " should be resolvable to a " + expectedType,
-1,
-1,
variableName,
source);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package fr.inria.corese.core.next.query.impl.parser.semantic.rule;

import fr.inria.corese.core.next.query.api.validation.QueryDiagnostic;
import fr.inria.corese.core.next.query.impl.parser.semantic.support.AbstractAstVisitor;
import fr.inria.corese.core.next.query.impl.sparql.ast.*;
import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.*;

import java.util.ArrayList;
import java.util.List;

import static fr.inria.corese.core.next.query.impl.parser.semantic.support.SemanticValidationUtils.checkTermIsPotentialBoolean;

/**
* This rule checks the operators used in Filter asts
*/
public final class FilterArgumentsValidationRule extends AbstractSemanticValidationRule {

@Override
protected String getDiagnosticSource() {
return FilterArgumentsValidationRule.class.getSimpleName();
}

@Override
public List<QueryDiagnostic> validate(QueryAst queryAst) {
FilterArgumentsValidationVisitor visitor = new FilterArgumentsValidationVisitor();
queryAst.accept(visitor);
return visitor.getResult();
}

private class FilterArgumentsValidationVisitor extends AbstractAstVisitor {
private final List<QueryDiagnostic> result = new ArrayList<>();

public List<QueryDiagnostic> getResult() {
return result;
}

@Override
public void visit(PatternAst patternAst) {
if (patternAst instanceof FilterAst(TermAst operator) && !checkTermIsPotentialBoolean(operator)) {
result.add(buildIncorrectTypeDiagnostic(operator.getName(), "FILTER", "boolean"));
}
}

@Override
public void visit(HavingAst havingAst) {
for (TermAst condition : havingAst.conditions()) {
if (!checkTermIsPotentialBoolean(condition)) {
result.add(buildIncorrectTypeDiagnostic(condition.getName(), "HAVING", "boolean"));
}
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package fr.inria.corese.core.next.query.impl.parser.semantic.rule;

import fr.inria.corese.core.next.query.api.validation.QueryDiagnostic;
import fr.inria.corese.core.next.query.impl.parser.semantic.support.AbstractAstVisitor;
import fr.inria.corese.core.next.query.impl.sparql.ast.QueryAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.TermAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.AndAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.BinaryConstraintAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.BooleanNotAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.OrAst;

import java.util.ArrayList;
import java.util.List;

import static fr.inria.corese.core.next.query.impl.parser.semantic.support.SemanticValidationUtils.checkTermIsPotentialBoolean;

public class OperandArgumentBooleanTypeValidationRule extends AbstractSemanticValidationRule {
@Override
protected String getDiagnosticSource() {
return OperandArgumentBooleanTypeValidationRule.class.getSimpleName();
}

@Override
public List<QueryDiagnostic> validate(QueryAst queryAst) {
OperandBooleanArgumentTypeVisitor visitor = new OperandBooleanArgumentTypeVisitor();
queryAst.accept(visitor);
return visitor.getResult();
}

private class OperandBooleanArgumentTypeVisitor extends AbstractAstVisitor {
private final List<QueryDiagnostic> result = new ArrayList<>();

public List<QueryDiagnostic> getResult() {
return result;
}

@Override
public void visit(TermAst termAst) {
if(termAst instanceof BooleanNotAst booleanNotAst) {
if(! checkTermIsPotentialBoolean( booleanNotAst.argument())) {
result.add(buildIncorrectTypeDiagnostic(booleanNotAst.argument().getName(), booleanNotAst.getName(), "boolean"));
}
}
if(termAst instanceof BinaryConstraintAst binaryConstraintAst) {
if(binaryConstraintAst instanceof AndAst
|| binaryConstraintAst instanceof OrAst) {
if(! checkTermIsPotentialBoolean( binaryConstraintAst.getLeftArgument())) {
result.add(buildIncorrectTypeDiagnostic(binaryConstraintAst.getLeftArgument().getName(), binaryConstraintAst.getName(), "boolean"));
}
if(! checkTermIsPotentialBoolean( binaryConstraintAst.getRightArgument())) {
result.add(buildIncorrectTypeDiagnostic(binaryConstraintAst.getRightArgument().getName(), binaryConstraintAst.getName(), "boolean"));
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package fr.inria.corese.core.next.query.impl.parser.semantic.rule;

import fr.inria.corese.core.next.query.api.validation.QueryDiagnostic;
import fr.inria.corese.core.next.query.impl.parser.semantic.support.AbstractAstVisitor;
import fr.inria.corese.core.next.query.impl.sparql.ast.QueryAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.TermAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.*;

import java.util.ArrayList;
import java.util.List;

import static fr.inria.corese.core.next.query.impl.parser.semantic.support.SemanticValidationUtils.checkTermIsPotentialIri;

/**
* Check that the comparison operand do not compare IRIs (except for the different != operator)
*/
public class OperandArgumentIRITypeValidationRule extends AbstractSemanticValidationRule {

@Override
protected String getDiagnosticSource() {
return OperandArgumentIRITypeValidationRule.class.getSimpleName();
}
Comment thread
MaillPierre marked this conversation as resolved.

@Override
public List<QueryDiagnostic> validate(QueryAst queryAst) {
OperandIRIArgumentTypeVisitor visitor = new OperandIRIArgumentTypeVisitor();
queryAst.accept(visitor);
return visitor.getResult();
}

private class OperandIRIArgumentTypeVisitor extends AbstractAstVisitor {
private final List<QueryDiagnostic> result = new ArrayList<>();

public List<QueryDiagnostic> getResult() {
return result;
}

@Override
public void visit(TermAst termAst) {
if(termAst instanceof BinaryConstraintAst binaryConstraintAst) {
if(binaryConstraintAst instanceof LowerThanAst
|| binaryConstraintAst instanceof LowerOrEqualThanAst
|| binaryConstraintAst instanceof GreaterThanAst
|| binaryConstraintAst instanceof GreaterOrEqualThanAst) {
if(checkTermIsPotentialIri(binaryConstraintAst.getLeftArgument())) {
result.add(buildIncorrectTypeDiagnostic(binaryConstraintAst.getLeftArgument().getName(), binaryConstraintAst.getName(), "not an IRI"));
}
if(checkTermIsPotentialIri(binaryConstraintAst.getRightArgument())) {
result.add(buildIncorrectTypeDiagnostic(binaryConstraintAst.getRightArgument().getName(), binaryConstraintAst.getName(), "not an IRI"));
}
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package fr.inria.corese.core.next.query.impl.parser.semantic.rule;

import fr.inria.corese.core.next.query.api.validation.QueryDiagnostic;
import fr.inria.corese.core.next.query.impl.parser.semantic.support.AbstractAstVisitor;
import fr.inria.corese.core.next.query.impl.sparql.ast.QueryAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.TermAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.*;

import java.util.ArrayList;
import java.util.List;

import static fr.inria.corese.core.next.query.impl.parser.semantic.support.SemanticValidationUtils.checkTermIsPotentialNumeric;

/**
* Check that the operands and numeric functions use numeric arguments
*/
public final class OperandArgumentNumericTypeValidationRule extends AbstractSemanticValidationRule {

@Override
protected String getDiagnosticSource() {
return OperandArgumentNumericTypeValidationRule.class.getSimpleName();
}

@Override
public List<QueryDiagnostic> validate(QueryAst queryAst) {
OperandNumericArgumentTypeVisitor visitor = new OperandNumericArgumentTypeVisitor();
queryAst.accept(visitor);
return visitor.getResult();
}

private class OperandNumericArgumentTypeVisitor extends AbstractAstVisitor {
private final List<QueryDiagnostic> result = new ArrayList<>();

public List<QueryDiagnostic> getResult() {
return result;
}

@Override
public void visit(TermAst termAst) {
if (termAst instanceof UnaryConstraintAst unaryConstraintAst) {
if (
(unaryConstraintAst instanceof AbsAst
|| unaryConstraintAst instanceof CeilAst
|| unaryConstraintAst instanceof FloorAst
|| unaryConstraintAst instanceof RoundAst
|| unaryConstraintAst instanceof UnaryMinusAst
|| unaryConstraintAst instanceof UnaryPlusAst)
&& !checkTermIsPotentialNumeric(unaryConstraintAst.argument())) {
result.add(buildIncorrectTypeDiagnostic(unaryConstraintAst.argument().getName(), unaryConstraintAst.getName(), "numeric"));
}
}

if (termAst instanceof BinaryConstraintAst binaryConstraintAst) { // Numeric only operands
if (binaryConstraintAst instanceof AddAst
|| binaryConstraintAst instanceof DivideAst
|| binaryConstraintAst instanceof MultiplyAst
|| binaryConstraintAst instanceof SubtractAst
) {
if (!checkTermIsPotentialNumeric(binaryConstraintAst.getLeftArgument())) {
result.add(buildIncorrectTypeDiagnostic(binaryConstraintAst.getLeftArgument().getName(), binaryConstraintAst.getName(), "numeric"));
}
if (!checkTermIsPotentialNumeric(binaryConstraintAst.getRightArgument())) {
result.add(buildIncorrectTypeDiagnostic(binaryConstraintAst.getRightArgument().getName(), binaryConstraintAst.getName(), "numeric"));
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package fr.inria.corese.core.next.query.impl.parser.semantic.support;

import fr.inria.corese.core.next.query.impl.sparql.ast.*;

/**
* Default implementation for AstVisitor
*/
public abstract class AbstractAstVisitor implements AstVisitor {

@Override
public void visit(PatternAst ast) {

}

@Override
public void visit(QueryAst ast) {

}

@Override
public void visit(UpdateRequestUnitAst ast) {

}

@Override
public void visit(TermAst ast) {

}

@Override
public void visit(ProjectionAst ast) {

}

@Override
public void visit(QueryPrologueAst ast) {

}

@Override
public void visit(ValuesAst ast) {

}

@Override
public void visit(ValueMappingAst ast) {

}

@Override
public void visit(SolutionModifierAst ast) {

}

@Override
public void visit(GroupGraphPatternAst ast) {

}

@Override
public void visit(TriplePatternAst ast) {

}

@Override
public void visit(ConstructTemplateAst ast) {

}

@Override
public void visit(DatasetClauseAst ast) {

}

@Override
public void visit(GroupByAst ast) {

}

@Override
public void visit(HavingAst ast) {

}

@Override
public void visit(OrderConditionAst ast) {

}

@Override
public void visit(PrefixDeclarationAst ast) {

}

@Override
public void visit(ServiceAst ast) {

}

@Override
public void visit(GraphRefAst ast) {

}
}
Loading
Loading