This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new 8cc0a5eb8b GH-2102: Parse and accept [], with warning
8cc0a5eb8b is described below
commit 8cc0a5eb8b147b8fc300cde461ce8bbe1cfcdc05
Author: Andy Seaborne <[email protected]>
AuthorDate: Fri Dec 1 11:08:45 2023 +0000
GH-2102: Parse and accept [], with warning
---
.../apache/jena/sparql/lang/QueryParserBase.java | 397 +++++++++++----------
.../org/apache/jena/sparql/syntax/TS_Syntax.java | 3 +-
.../apache/jena/sparql/syntax/TestQueryParser.java | 87 +++++
3 files changed, 298 insertions(+), 189 deletions(-)
diff --git
a/jena-arq/src/main/java/org/apache/jena/sparql/lang/QueryParserBase.java
b/jena-arq/src/main/java/org/apache/jena/sparql/lang/QueryParserBase.java
index 0cd59e4327..75920d7f05 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/lang/QueryParserBase.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/lang/QueryParserBase.java
@@ -18,91 +18,94 @@
package org.apache.jena.sparql.lang;
-import java.math.BigInteger ;
-import java.util.HashSet ;
-import java.util.Set ;
-
-import org.apache.jena.atlas.AtlasException ;
-import org.apache.jena.atlas.lib.EscapeStr ;
-import org.apache.jena.atlas.logging.Log ;
-import org.apache.jena.datatypes.RDFDatatype ;
-import org.apache.jena.datatypes.TypeMapper ;
-import org.apache.jena.datatypes.xsd.XSDDatatype ;
-import org.apache.jena.graph.Node ;
-import org.apache.jena.graph.NodeFactory ;
-import org.apache.jena.graph.Triple ;
+import java.math.BigInteger;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.jena.atlas.AtlasException;
+import org.apache.jena.atlas.lib.EscapeStr;
+import org.apache.jena.atlas.logging.Log;
+import org.apache.jena.datatypes.RDFDatatype;
+import org.apache.jena.datatypes.TypeMapper;
+import org.apache.jena.datatypes.xsd.XSDDatatype;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.graph.Triple;
import org.apache.jena.irix.IRIException;
-import org.apache.jena.query.ARQ ;
-import org.apache.jena.query.QueryParseException ;
+import org.apache.jena.irix.IRIx;
+import org.apache.jena.irix.RelativeIRIException;
+import org.apache.jena.query.ARQ;
+import org.apache.jena.query.QueryParseException;
import org.apache.jena.riot.lang.extra.LangParserLib;
-import org.apache.jena.riot.system.ErrorHandler ;
-import org.apache.jena.riot.system.ErrorHandlerFactory ;
-import org.apache.jena.riot.system.RiotLib ;
-import org.apache.jena.sparql.ARQInternalErrorException ;
-import org.apache.jena.sparql.core.Prologue ;
-import org.apache.jena.sparql.core.TriplePath ;
-import org.apache.jena.sparql.core.Var ;
+import org.apache.jena.riot.system.Checker;
+import org.apache.jena.riot.system.ErrorHandler;
+import org.apache.jena.riot.system.ErrorHandlerFactory;
+import org.apache.jena.riot.system.RiotLib;
+import org.apache.jena.sparql.ARQInternalErrorException;
+import org.apache.jena.sparql.core.Prologue;
+import org.apache.jena.sparql.core.TriplePath;
+import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.expr.*;
-import org.apache.jena.sparql.graph.NodeConst ;
-import org.apache.jena.sparql.modify.request.QuadAccSink ;
+import org.apache.jena.sparql.graph.NodeConst;
+import org.apache.jena.sparql.modify.request.QuadAccSink;
import org.apache.jena.sparql.path.P_Link;
-import org.apache.jena.sparql.path.Path ;
-import org.apache.jena.sparql.syntax.* ;
-import org.apache.jena.vocabulary.RDF ;
-import org.slf4j.Logger ;
-import org.slf4j.LoggerFactory ;
+import org.apache.jena.sparql.path.Path;
+import org.apache.jena.sparql.syntax.*;
+import org.apache.jena.vocabulary.RDF;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/** Base class parsers, mainly SPARQL related */
public class QueryParserBase
{
// NodeConst
- protected final Node XSD_TRUE = NodeConst.nodeTrue ;
- protected final Node XSD_FALSE = NodeConst.nodeFalse ;
+ protected final Node XSD_TRUE = NodeConst.nodeTrue;
+ protected final Node XSD_FALSE = NodeConst.nodeFalse;
- protected final Node nRDFtype = NodeConst.nodeRDFType ;
+ protected final Node nRDFtype = NodeConst.nodeRDFType;
- protected final Node nRDFnil = NodeConst.nodeNil ;
- protected final Node nRDFfirst = NodeConst.nodeFirst ;
- protected final Node nRDFrest = NodeConst.nodeRest ;
+ protected final Node nRDFnil = NodeConst.nodeNil;
+ protected final Node nRDFfirst = NodeConst.nodeFirst;
+ protected final Node nRDFrest = NodeConst.nodeRest;
- protected final Node nRDFsubject = RDF.Nodes.subject ;
- protected final Node nRDFpredicate = RDF.Nodes.predicate ;
- protected final Node nRDFobject = RDF.Nodes.object ;
+ protected final Node nRDFsubject = RDF.Nodes.subject;
+ protected final Node nRDFpredicate = RDF.Nodes.predicate;
+ protected final Node nRDFobject = RDF.Nodes.object;
// ----
// Graph patterns, true; in templates, false.
- private boolean bNodesAreVariables = true ;
+ private boolean bNodesAreVariables = true;
// In DELETE, false.
- private boolean bNodesAreAllowed = true ;
+ private boolean bNodesAreAllowed = true;
// label => bNode for construct templates patterns
@SuppressWarnings("deprecation")
- final LabelToNodeMap bNodeLabels = LabelToNodeMap.createBNodeMap() ;
+ final LabelToNodeMap bNodeLabels = LabelToNodeMap.createBNodeMap();
// label => bNode (as variable) for graph patterns
- final LabelToNodeMap anonVarLabels = LabelToNodeMap.createVarMap() ;
+ final LabelToNodeMap anonVarLabels = LabelToNodeMap.createVarMap();
// This is the map used allocate blank node labels during parsing.
// 1/ It is different between CONSTRUCT and the query pattern
// 2/ Each BasicGraphPattern is a scope for blank node labels so each
// BGP causes the map to be cleared at the start of the BGP
- protected LabelToNodeMap activeLabelMap = anonVarLabels ;
- protected Set<String> previousLabels = new HashSet<>() ;
+ protected LabelToNodeMap activeLabelMap = anonVarLabels;
+ protected Set<String> previousLabels = new HashSet<>();
// Aggregates are only allowed in places where grouping can happen.
// e.g. SELECT clause but not a FILTER.
- private boolean allowAggregatesInExpressions = false ;
- private int aggregateDepth = 0 ;
+ private boolean allowAggregatesInExpressions = false;
+ private int aggregateDepth = 0;
- //LabelToNodeMap listLabelMap = new LabelToNodeMap(true, new
VarAlloc("L")) ;
+ //LabelToNodeMap listLabelMap = new LabelToNodeMap(true, new
VarAlloc("L"));
// ----
public QueryParserBase() {}
- protected Prologue prologue ;
- public void setPrologue(Prologue prologue) { this.prologue = prologue ; }
- public Prologue getPrologue() { return prologue ; }
+ protected Prologue prologue;
+ public void setPrologue(Prologue prologue) { this.prologue = prologue; }
+ public Prologue getPrologue() { return prologue; }
protected void setBase(String iriStr, int line, int column) {
if ( isBNodeIRI(iriStr) )
@@ -118,27 +121,27 @@ public class QueryParserBase
}
protected void setInConstructTemplate(boolean b) {
- setBNodesAreVariables(!b) ;
+ setBNodesAreVariables(!b);
}
- protected boolean getBNodesAreVariables() { return bNodesAreVariables ; }
+ protected boolean getBNodesAreVariables() { return bNodesAreVariables; }
protected void setBNodesAreVariables(boolean bNodesAreVariables) {
- this.bNodesAreVariables = bNodesAreVariables ;
+ this.bNodesAreVariables = bNodesAreVariables;
if ( bNodesAreVariables )
- activeLabelMap = anonVarLabels ;
+ activeLabelMap = anonVarLabels;
else
- activeLabelMap = bNodeLabels ;
+ activeLabelMap = bNodeLabels;
}
- protected boolean getBNodesAreAllowed() { return bNodesAreAllowed ; }
+ protected boolean getBNodesAreAllowed() { return bNodesAreAllowed; }
protected void setBNodesAreAllowed(boolean bNodesAreAllowed) {
- this.bNodesAreAllowed = bNodesAreAllowed ;
+ this.bNodesAreAllowed = bNodesAreAllowed;
}
protected boolean getAllowAggregatesInExpressions() {
- return allowAggregatesInExpressions ;
+ return allowAggregatesInExpressions;
}
protected void setAllowAggregatesInExpressions(boolean
allowAggregatesInExpressions) {
@@ -153,41 +156,41 @@ public class QueryParserBase
protected Element compressGroupOfOneGroup(ElementGroup elg) {
// remove group of one group.
if ( elg.size() == 1 ) {
- Element e1 = elg.get(0) ;
+ Element e1 = elg.get(0);
if ( e1 instanceof ElementGroup )
- return e1 ;
+ return e1;
}
- return elg ;
+ return elg;
}
protected Node createLiteralInteger(String lexicalForm) {
- return NodeFactory.createLiteral(lexicalForm, XSDDatatype.XSDinteger) ;
+ return NodeFactory.createLiteral(lexicalForm, XSDDatatype.XSDinteger);
}
protected Node createLiteralDouble(String lexicalForm) {
- return NodeFactory.createLiteral(lexicalForm, XSDDatatype.XSDdouble) ;
+ return NodeFactory.createLiteral(lexicalForm, XSDDatatype.XSDdouble);
}
protected Node createLiteralDecimal(String lexicalForm) {
- return NodeFactory.createLiteral(lexicalForm, XSDDatatype.XSDdecimal) ;
+ return NodeFactory.createLiteral(lexicalForm, XSDDatatype.XSDdecimal);
}
protected Node stripSign(Node node) {
if ( !node.isLiteral() )
- return node ;
- String lex = node.getLiteralLexicalForm() ;
- String lang = node.getLiteralLanguage() ;
- RDFDatatype dt = node.getLiteralDatatype() ;
+ return node;
+ String lex = node.getLiteralLexicalForm();
+ String lang = node.getLiteralLanguage();
+ RDFDatatype dt = node.getLiteralDatatype();
if ( !lex.startsWith("-") && !lex.startsWith("+") )
- throw new ARQInternalErrorException("Literal does not start with a
sign: " + lex) ;
+ throw new ARQInternalErrorException("Literal does not start with a
sign: " + lex);
- lex = lex.substring(1) ;
- return NodeFactory.createLiteral(lex, lang, dt) ;
+ lex = lex.substring(1);
+ return NodeFactory.createLiteral(lex, lang, dt);
}
protected void checkString(String string, int line, int column) {
- for ( int i = 0 ; i < string.length() ; i++ ) {
+ for ( int i = 0; i < string.length(); i++ ) {
// Not "codePointAt" which does surrogate processing.
char ch = string.charAt(i);
// Check surrogate pairs are pairs.
@@ -206,55 +209,55 @@ public class QueryParserBase
}
protected Node createLiteral(String lexicalForm, String langTag, String
datatypeURI) {
- Node n = null ;
+ Node n = null;
// Can't have type and lang tag in parsing.
if ( datatypeURI != null ) {
- RDFDatatype dType =
TypeMapper.getInstance().getSafeTypeByName(datatypeURI) ;
- n = NodeFactory.createLiteral(lexicalForm, dType) ;
+ RDFDatatype dType =
TypeMapper.getInstance().getSafeTypeByName(datatypeURI);
+ n = NodeFactory.createLiteral(lexicalForm, dType);
} else if ( langTag != null && !langTag.isEmpty() )
- n = NodeFactory.createLiteral(lexicalForm, langTag) ;
+ n = NodeFactory.createLiteral(lexicalForm, langTag);
else
- n = NodeFactory.createLiteral(lexicalForm) ;
- return n ;
+ n = NodeFactory.createLiteral(lexicalForm);
+ return n;
}
protected long integerValue(String s) {
try {
if ( s.startsWith("+") )
- s = s.substring(1) ;
+ s = s.substring(1);
if ( s.startsWith("0x") ) {
// Hex
- s = s.substring(2) ;
- return Long.parseLong(s, 16) ;
+ s = s.substring(2);
+ return Long.parseLong(s, 16);
}
- return Long.parseLong(s) ;
+ return Long.parseLong(s);
}
catch (NumberFormatException ex) {
try {
// Possible too large for a long.
- BigInteger integer = new BigInteger(s) ;
- throwParseException("Number '" + s + "' is a valid number but
can't not be stored in a long") ;
+ BigInteger integer = new BigInteger(s);
+ throwParseException("Number '" + s + "' is a valid number but
can't not be stored in a long");
}
catch (NumberFormatException ex2) {}
- throw new QueryParseException(ex, -1, -1) ;
+ throw new QueryParseException(ex, -1, -1);
}
}
protected double doubleValue(String s) {
if ( s.startsWith("+") )
- s = s.substring(1) ;
- double valDouble = Double.parseDouble(s) ;
- return valDouble ;
+ s = s.substring(1);
+ double valDouble = Double.parseDouble(s);
+ return valDouble;
}
/** Remove first and last characters (e.g. ' or "") from a string */
protected static String stripQuotes(String s) {
- return s.substring(1, s.length() - 1) ;
+ return s.substring(1, s.length() - 1);
}
/** Remove first 3 and last 3 characters (e.g. ''' or """) from a string */
protected static String stripQuotes3(String s) {
- return s.substring(3, s.length() - 3) ;
+ return s.substring(3, s.length() - 3);
}
/** remove the first n characters from the string */
@@ -263,73 +266,91 @@ public class QueryParserBase
}
protected Var createVariable(String s, int line, int column) {
- s = s.substring(1) ; // Drop the marker
+ s = s.substring(1); // Drop the marker
// This is done by the parser input stream nowadays.
- // s = unescapeCodePoint(s, line, column) ;
+ // s = unescapeCodePoint(s, line, column);
// Check \ u did not put in any illegals.
- return Var.alloc(s) ;
+ return Var.alloc(s);
}
// ---- IRIs and Nodes
protected String resolveQuotedIRI(String iriStr, int line, int column) {
- iriStr = stripQuotes(iriStr) ;
+ iriStr = stripQuotes(iriStr);
iriStr = unescapeUnicode(iriStr, line, column);
- return resolveIRI(iriStr, line, column) ;
+ return resolveIRI(iriStr, line, column);
}
- public static final String ParserLoggerName = "SPARQL" ;
- private static Logger parserLog =
LoggerFactory.getLogger(ParserLoggerName) ;
- private static ErrorHandler errorHandler =
ErrorHandlerFactory.errorHandlerStd(parserLog) ;
+ public static final String ParserLoggerName = "SPARQL";
+ public static Logger parserLog = LoggerFactory.getLogger(ParserLoggerName);
+ private static final ErrorHandler errorHandler =
ErrorHandlerFactory.errorHandlerStd(parserLog);
protected String resolveIRI(String iriStr, int line, int column) {
if ( isBNodeIRI(iriStr) )
- return iriStr ;
-
- if ( getPrologue() != null ) {
- if ( getPrologue().getBase() != null ) {
- try {
- iriStr =
getPrologue().getBase().resolve(iriStr).toString();
- } catch (IRIException ex) {
- errorHandler.error("Bad IRI: '"+iriStr+"':
"+ex.getMessage(), line, column);
- }
- }
+ return iriStr;
+ if ( getPrologue() == null )
+ return iriStr;
+ if ( getPrologue().getBase() == null )
+ return iriStr;
+ IRIx irix = resolveIRIx(iriStr, line, column);
+ return irix.toString();
+ }
+
+ private IRIx resolveIRIx(String iriStr, long line, long col) {
+ // Aligns with ParserProfileStd.internalMakeIRI
+ // Hard to do a meaning DRY because SPARQL works in strings
+ // where as ParserProfile works in IRix.
+ if ( iriStr.contains(" ") ) {
+ // Specific check for spaces.
+ errorHandler.warning("Bad IRI: <" + iriStr + "> Spaces are not
legal in URIs/IRIs.", line, col);
+ return IRIx.createAny(iriStr);
+ }
+ try {
+ IRIx resolvedIRIx = getPrologue().getBase().resolve(iriStr);
+ return resolvedIRIx;
+ } catch (RelativeIRIException ex ) {
+ errorHandler.error("Relative IRI: " + iriStr, line, col);
+ return IRIx.createAny(iriStr);
+ } catch (IRIException ex) {
+ // Same code as Checker.iriViolations
+ String msg = ex.getMessage();
+ Checker.iriViolationMessage(iriStr, true, msg, line, col,
errorHandler);
+ return IRIx.createAny(iriStr);
}
- return iriStr ;
}
protected String resolvePName(String prefixedName, int line, int column) {
// It's legal.
- int idx = prefixedName.indexOf(':') ;
+ int idx = prefixedName.indexOf(':');
// -- Escapes in local name
- String prefix = prefixedName.substring(0, idx) ;
- String local = prefixedName.substring(idx + 1) ;
- local = unescapePName(local, line, column) ;
- prefixedName = prefix + ":" + local ;
+ String prefix = prefixedName.substring(0, idx);
+ String local = prefixedName.substring(idx + 1);
+ local = unescapePName(local, line, column);
+ prefixedName = prefix + ":" + local;
// --
- String s = getPrologue().expandPrefixedName(prefixedName) ;
+ String s = getPrologue().expandPrefixedName(prefixedName);
if ( s == null ) {
if ( ARQ.isTrue(ARQ.fixupUndefinedPrefixes) )
- return RiotLib.fixupPrefixes.apply(prefixedName) ;
- throwParseException("Unresolved prefixed name: " + prefixedName,
line, column) ;
+ return RiotLib.fixupPrefixes.apply(prefixedName);
+ throwParseException("Unresolved prefixed name: " + prefixedName,
line, column);
}
- return s ;
+ return s;
}
- private boolean skolomizedBNodes = ARQ.isTrue(ARQ.constantBNodeLabels) ;
+ private boolean skolomizedBNodes = ARQ.isTrue(ARQ.constantBNodeLabels);
protected Node createNode(String iri) {
if ( skolomizedBNodes )
- return RiotLib.createIRIorBNode(iri) ;
+ return RiotLib.createIRIorBNode(iri);
else
- return NodeFactory.createURI(iri) ;
+ return NodeFactory.createURI(iri);
}
protected boolean isBNodeIRI(String iri) {
- return skolomizedBNodes && RiotLib.isBNodeIRI(iri) ;
+ return skolomizedBNodes && RiotLib.isBNodeIRI(iri);
}
// -------- Basic Graph Patterns and Blank Node label scopes
@@ -338,10 +359,10 @@ public class QueryParserBase
// but not by other graph patterns.
protected void startBasicGraphPattern()
- { activeLabelMap.clear() ; }
+ { activeLabelMap.clear(); }
protected void endBasicGraphPattern()
- { previousLabels.addAll(activeLabelMap.getLabels()) ; }
+ { previousLabels.addAll(activeLabelMap.getLabels()); }
protected void startTriplesBlock()
{ }
@@ -351,43 +372,43 @@ public class QueryParserBase
// On entry to a new group, the current BGP is ended.
protected void startGroup(ElementGroup elg) {
- endBasicGraphPattern() ;
- startBasicGraphPattern() ;
+ endBasicGraphPattern();
+ startBasicGraphPattern();
}
protected void endGroup(ElementGroup elg) {
- endBasicGraphPattern() ;
+ endBasicGraphPattern();
}
// --------
protected void checkConcrete(Node n, int line, int column) {
if ( ! n.isConcrete() )
- throwParseException("Term is not concrete: "+n, line, column) ;
+ throwParseException("Term is not concrete: "+n, line, column);
}
// BNode from a list
// protected Node createListNode()
-// { return listLabelMap.allocNode() ; }
+// { return listLabelMap.allocNode(); }
- protected Node createListNode(int line, int column) { return
createBNode(line, column) ; }
+ protected Node createListNode(int line, int column) { return
createBNode(line, column); }
// Unlabelled bNode.
protected Node createBNode(int line, int column) {
if ( !bNodesAreAllowed )
- throwParseException("Blank nodes not allowed in DELETE templates",
line, column) ;
- return activeLabelMap.allocNode() ;
+ throwParseException("Blank nodes not allowed in DELETE templates",
line, column);
+ return activeLabelMap.allocNode();
}
// Labelled bNode.
protected Node createBNode(String label, int line, int column) {
if ( !bNodesAreAllowed )
- throwParseException("Blank nodes not allowed in DELETE templates:
" + label, line, column) ;
+ throwParseException("Blank nodes not allowed in DELETE templates:
" + label, line, column);
if ( previousLabels.contains(label) )
- throwParseException("Blank node label reuse not allowed at this
point: " + label, line, column) ;
+ throwParseException("Blank node label reuse not allowed at this
point: " + label, line, column);
- // label = unescapeCodePoint(label, line, column) ;
- return activeLabelMap.asNode(label) ;
+ // label = unescapeCodePoint(label, line, column);
+ return activeLabelMap.asNode(label);
}
protected Node preConditionAnnotation(Node s, Node p, Path path, Node o,
int line, int column) {
@@ -395,7 +416,7 @@ public class QueryParserBase
return p;
if ( path instanceof P_Link )
return ((P_Link)path).getNode();
- throwParseException("Only simple paths allowed with annotation
syntax", line, column) ;
+ throwParseException("Only simple paths allowed with annotation
syntax", line, column);
return null;
}
@@ -404,68 +425,68 @@ public class QueryParserBase
}
protected Expr createExprExists(Element element) {
- return new E_Exists(element) ;
+ return new E_Exists(element);
}
protected Expr createExprNotExists(Element element) {
// Could negate here.
- return new E_NotExists(element) ;
+ return new E_NotExists(element);
}
// Convert a parser token, which includes the final ":", to a prefix name.
protected String fixupPrefix(String prefix, int line, int column) {
// \ u processing!
if ( prefix.endsWith(":") )
- prefix = prefix.substring(0, prefix.length() - 1) ;
- return prefix ;
+ prefix = prefix.substring(0, prefix.length() - 1);
+ return prefix;
}
protected void setAccGraph(QuadAccSink acc, Node gn) {
- acc.setGraph(gn) ;
+ acc.setGraph(gn);
}
protected void insert(TripleCollector acc, Node s, Node p, Node o) {
- acc.addTriple(Triple.create(s, p, o)) ;
+ acc.addTriple(Triple.create(s, p, o));
}
protected void insert(TripleCollectorMark acc, int index, Node s, Node p,
Node o) {
- acc.addTriple(index, Triple.create(s, p, o)) ;
+ acc.addTriple(index, Triple.create(s, p, o));
}
protected void insert(TripleCollector acc, Node s, Node p, Path path, Node
o) {
if ( p == null )
- acc.addTriplePath(new TriplePath(s, path, o)) ;
+ acc.addTriplePath(new TriplePath(s, path, o));
else
- acc.addTriple(Triple.create(s, p, o)) ;
+ acc.addTriple(Triple.create(s, p, o));
}
protected void insert(TripleCollectorMark acc, int index, Node s, Node p,
Path path, Node o) {
if ( p == null )
- acc.addTriplePath(index, new TriplePath(s, path, o)) ;
+ acc.addTriplePath(index, new TriplePath(s, path, o));
else
- acc.addTriple(index, Triple.create(s, p, o)) ;
+ acc.addTriple(index, Triple.create(s, p, o));
}
protected void insert(TripleCollector target, ElementPathBlock source) {
for ( TriplePath path : source.getPattern() ) {
if ( path.isTriple() ) {
- target.addTriple(path.asTriple()) ;
+ target.addTriple(path.asTriple());
} else {
- target.addTriplePath(path) ;
+ target.addTriplePath(path);
}
}
}
protected Expr asExpr(Node n) {
- return ExprLib.nodeToExpr(n) ;
+ return ExprLib.nodeToExpr(n);
}
protected Expr asExprNoSign(Node n) {
- String lex = n.getLiteralLexicalForm() ;
- String lang = n.getLiteralLanguage() ;
- String dtURI = n.getLiteralDatatypeURI() ;
- n = createLiteral(lex, lang, dtURI) ;
- return ExprLib.nodeToExpr(n) ;
+ String lex = n.getLiteralLexicalForm();
+ String lang = n.getLiteralLanguage();
+ String dtURI = n.getLiteralDatatypeURI();
+ n = createLiteral(lex, lang, dtURI);
+ return ExprLib.nodeToExpr(n);
}
// Makers of functions that need more than just a simple "new E_...".
@@ -504,28 +525,28 @@ public class QueryParserBase
// Utilities to remove escapes in strings.
/*package-testing*/ static String unescapeStr(String s)
- { return unescapeStr(s, -1, -1) ; }
+ { return unescapeStr(s, -1, -1); }
//
// public static String unescapeCodePoint(String s)
-// { return unescape(s, '\\', true, 1, 1) ; }
+// { return unescape(s, '\\', true, 1, 1); }
//
// protected String unescapeCodePoint(String s, int line, int column)
-// { return unescape(s, '\\', true, line, column) ; }
+// { return unescape(s, '\\', true, line, column); }
// Do we need the line/column versions?
// Why not catch exceptions and comvert to QueryParseException
protected static String unescapeStr(String s, int line, int column)
- { return unescape(s, '\\', false, line, column) ; }
+ { return unescape(s, '\\', false, line, column); }
// Worker function
protected static String unescape(String s, char escape, boolean
pointCodeOnly, int line, int column) {
try {
- return EscapeStr.unescape(s, escape, pointCodeOnly) ;
+ return EscapeStr.unescape(s, escape, pointCodeOnly);
} catch (AtlasException ex) {
- throwParseException(ex.getMessage(), line, column) ;
- return null ;
+ throwParseException(ex.getMessage(), line, column);
+ return null;
}
}
@@ -534,40 +555,40 @@ public class QueryParserBase
}
protected static String unescapePName(String s, int line, int column) {
- char escape = '\\' ;
- int idx = s.indexOf(escape) ;
+ char escape = '\\';
+ int idx = s.indexOf(escape);
if ( idx == -1 )
- return s ;
+ return s;
- int len = s.length() ;
- StringBuilder sb = new StringBuilder() ;
+ int len = s.length();
+ StringBuilder sb = new StringBuilder();
- for ( int i = 0 ; i < len ; i++ ) {
- char ch = s.charAt(i) ;
+ for ( int i = 0; i < len; i++ ) {
+ char ch = s.charAt(i);
// Keep line and column numbers.
switch (ch) {
case '\n' :
case '\r' :
- line++ ;
- column = 1 ;
- break ;
+ line++;
+ column = 1;
+ break;
default :
- column++ ;
- break ;
+ column++;
+ break;
}
if ( ch != escape ) {
- sb.append(ch) ;
- continue ;
+ sb.append(ch);
+ continue;
}
// Escape
if ( i >= s.length() - 1 )
- throwParseException("Illegal escape at end of string", line,
column) ;
- char ch2 = s.charAt(i + 1) ;
- column = column + 1 ;
- i = i + 1 ;
+ throwParseException("Illegal escape at end of string", line,
column);
+ char ch2 = s.charAt(i + 1);
+ column = column + 1;
+ i = i + 1;
switch (ch2) { // PN_LOCAL_ESC
case '_' :
@@ -591,24 +612,24 @@ public class QueryParserBase
case '#' :
case '@' :
case '%' :
- sb.append(ch2) ;
- break ;
+ sb.append(ch2);
+ break;
default :
- throwParseException("Illegal prefix name escape: " + ch2,
line, column) ;
+ throwParseException("Illegal prefix name escape: " + ch2,
line, column);
}
}
- return sb.toString() ;
+ return sb.toString();
}
protected void warnDeprecation(String msg) {
- Log.warn(this, msg) ;
+ Log.warn(this, msg);
}
public static void throwParseException(String msg, int line, int column) {
- throw new QueryParseException("Line " + line + ", column " + column +
": " + msg, line, column) ;
+ throw new QueryParseException("Line " + line + ", column " + column +
": " + msg, line, column);
}
public static void throwParseException(String msg) {
- throw new QueryParseException(msg, -1, -1) ;
+ throw new QueryParseException(msg, -1, -1);
}
}
diff --git
a/jena-arq/src/test/java/org/apache/jena/sparql/syntax/TS_Syntax.java
b/jena-arq/src/test/java/org/apache/jena/sparql/syntax/TS_Syntax.java
index b01904ce6a..21053ce632 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/syntax/TS_Syntax.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/syntax/TS_Syntax.java
@@ -27,7 +27,8 @@ import org.junit.runners.Suite.SuiteClasses ;
@RunWith(Suite.class)
@SuiteClasses( {
- TestSerialization.class
+ TestQueryParser.class
+ , TestSerialization.class
, TestQueryOps.class
, TestSyntaxTransform.class
, TestFlattenSyntax.class
diff --git
a/jena-arq/src/test/java/org/apache/jena/sparql/syntax/TestQueryParser.java
b/jena-arq/src/test/java/org/apache/jena/sparql/syntax/TestQueryParser.java
new file mode 100644
index 0000000000..8e25334fc2
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/syntax/TestQueryParser.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.syntax;
+
+import org.apache.jena.atlas.logging.LogCtl;
+import org.apache.jena.query.QueryFactory;
+import org.apache.jena.query.QueryParseException;
+import org.apache.jena.sparql.lang.QueryParserBase;
+import org.junit.Test;
+import org.slf4j.Logger;
+
+/**
+ * Query parsing is primarily tested by the scripts in the test suite.
+ * This class adds a few tests that are more conveniently done
+ * in code rather than scripts.
+ */
+public class TestQueryParser {
+ private static final Logger loggerSPARQL = QueryParserBase.parserLog;
+
+ private static void silent(Runnable action) {
+ LogCtl.withLevel(loggerSPARQL, "fatal", action);
+ }
+
+ @Test public void syntax_uri_brackets_1() {
+ testParseIRIs("<http://example/#[]>");
+ }
+
+ @Test public void syntax_uri_brackets_2() {
+ testParseIRIs("<http://example/abc[]>");
+ }
+
+ @Test public void syntax_uri_brackets_3() {
+ testParseIRIs("<http://[::1]/abc>");
+ }
+
+ @Test(expected = QueryParseException.class)
+ public void syntax_uri_brace_1() {
+ testParseIRIs("<http://example/{}>");
+ }
+
+ @Test(expected = QueryParseException.class)
+ public void syntax_uri_brace_2() {
+ testParseIRIs("<http://example/#{}>");
+ }
+
+ @Test(expected = QueryParseException.class)
+ public void syntax_uri_space_1() {
+ testParseIRIs("<http://example/abc def>");
+ }
+
+ @Test(expected = QueryParseException.class)
+ public void syntax_uri_space_2() {
+ testParseIRIs("<http://example/abc?q= def>");
+ }
+
+ @Test(expected = QueryParseException.class)
+ public void syntax_uri_space_3() {
+ testParseIRIs("< http://example/abc>");
+ }
+
+ @Test(expected = QueryParseException.class)
+ public void syntax_uri_space_4() {
+ testParseIRIs("<http://example/abc >");
+ }
+
+ // Test that a URI string can be used in Turtle data
+ // and in SPARQL in the same way.
+ public static void testParseIRIs(String string) {
+ silent(()->QueryFactory.create("SELECT * { "+string+" a
<http://example/TYPE> }"));
+ }
+}