Skip to content

Commit 6a92f19

Browse files
authored
GH-5407 Fix Turtle integer-literal + dot at EOF (#5428)
2 parents 5260244 + 05d9815 commit 6a92f19

3 files changed

Lines changed: 47 additions & 1 deletion

File tree

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ Do **not** modify existing headers’ years.
510510
511511
## Branch & PR Workflow (Agent)
512512
513+
- Confirm issue number first (mandatory): before creating a branch, pause and request/confirm the GitHub issue number. Do not proceed to branch creation until the issue number is provided or confirmed.
513514
- Name branch: `GH-<issue>-<short-slug>` (kebab‑case slug).
514515
- Create branch: `git checkout -b GH-XXXX-your-slug`.
515516
- Stage changes: `git add -A` (ensure new Java files have the required header).

core/rio/turtle/src/main/java/org/eclipse/rdf4j/rio/turtle/TurtleParser.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,11 @@ protected Literal parseNumber() throws IOException, RDFParseException {
808808
// read optional fractional digits
809809
if (c == '.') {
810810

811-
if (TurtleUtil.isWhitespace(peekCodePoint())) {
811+
int next = peekCodePoint();
812+
// Treat '.' as statement terminator at EOF only when we already parsed at least one digit
813+
// (e.g., "30.") or when whitespace follows. Otherwise, attempt to parse as decimal
814+
// which will surface a useful error for a stray '.' token.
815+
if ((value.length() > 0 && next == -1) || TurtleUtil.isWhitespace(next)) {
812816
// We're parsing an integer that did not have a space before
813817
// the
814818
// period to end the statement

core/rio/turtle/src/test/java/org/eclipse/rdf4j/rio/turtle/TurtleParserTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,47 @@ public void testParseDots() throws IOException {
8989

9090
}
9191

92+
@Test
93+
public void testIntegerFollowedByDotAtEOF() throws IOException {
94+
// Reproduces bug: integer literal immediately followed by statement terminator '.' at EOF
95+
String data = prefixes + ":alice :age 30."; // no trailing whitespace/newline
96+
97+
parser.parse(new StringReader(data), baseURI);
98+
99+
assertTrue(errorCollector.getWarnings().isEmpty());
100+
assertTrue(errorCollector.getErrors().isEmpty());
101+
assertTrue(errorCollector.getFatalErrors().isEmpty());
102+
103+
assertEquals(1, statementCollector.getStatements().size());
104+
Statement st = statementCollector.getStatements().iterator().next();
105+
assertEquals(vf.createIRI("http://example.org/alice"), st.getSubject());
106+
assertEquals(vf.createIRI("http://example.org/age"), st.getPredicate());
107+
assertTrue(st.getObject() instanceof Literal);
108+
Literal lit = (Literal) st.getObject();
109+
assertEquals("30", lit.getLabel());
110+
assertEquals(XSD.INTEGER, lit.getDatatype());
111+
}
112+
113+
@Test
114+
public void testLetterFollowedByDotAtEOF() throws IOException {
115+
String data = prefixes + ":alice :age \"a\"."; // no trailing whitespace/newline
116+
117+
parser.parse(new StringReader(data), baseURI);
118+
119+
assertTrue(errorCollector.getWarnings().isEmpty());
120+
assertTrue(errorCollector.getErrors().isEmpty());
121+
assertTrue(errorCollector.getFatalErrors().isEmpty());
122+
123+
assertEquals(1, statementCollector.getStatements().size());
124+
Statement st = statementCollector.getStatements().iterator().next();
125+
assertEquals(vf.createIRI("http://example.org/alice"), st.getSubject());
126+
assertEquals(vf.createIRI("http://example.org/age"), st.getPredicate());
127+
assertTrue(st.getObject() instanceof Literal);
128+
Literal lit = (Literal) st.getObject();
129+
assertEquals("a", lit.getLabel());
130+
assertEquals(XSD.STRING, lit.getDatatype());
131+
}
132+
92133
@Test
93134
public void testParseIllegalURIFatal() throws IOException {
94135
String data = " <urn:foo_bar\\r> <urn:foo> <urn:bar> ; <urn:foo2> <urn:bar2> . <urn:foobar> <urn:food> <urn:barf> . ";

0 commit comments

Comments
 (0)