[JEXL-411] Allow optional leading zeroes in floating point literals - #409
Merged
Conversation
JEXL could not parse a floating point literal with an omitted leading zero (e.g. ".1"), so "(1+0.1)*2" evaluated to 2.2 while "(1+.1)*2" raised a parsing error, although ".1" is valid in Java. A leading-dot number is tokenized as "DOT DOT_IDENTIFIER", which is identical to the postfix index access "x.3". The literal is therefore recognized in the parser, in operand position, rather than at the lexer level. FloatLiteral() now also accepts ".<digits>" (only all-digit DOT_IDENTIFIER images, checked via isAllDigits) and rebuilds the value as "." + image before handing it to NumberParser. Dot-based index/property access is left untouched. Add an arithmetic test covering the JEXL-411 reproduction, leading-dot literals, unary sign and the index-access regression.
henrib
self-requested a review
August 12, 2026 12:27
henrib
reviewed
Aug 12, 2026
henrib
left a comment
Contributor
There was a problem hiding this comment.
Good thinking, nicely addressed.
| * @param image the token image | ||
| * @return true if every character is a decimal digit | ||
| */ | ||
| private static boolean isAllDigits(final String image) { |
Contributor
There was a problem hiding this comment.
The method might move to JexlParser since all helpers live there.
| t=<FLOAT_LITERAL> | ||
| { jjtThis.setReal(t.image); } | ||
| | | ||
| <DOT> t=<DOT_IDENTIFIER> |
| array.add("zero"); | ||
| array.add("one"); | ||
| jc.set("array", array); | ||
| assertEquals("one", jexl.createExpression("array.1").evaluate(jc)); |
| assertEquals(0.4d, jexl.createExpression("-.5 - -.9").evaluate(jc)); | ||
| assertEquals(-1.4d, jexl.createExpression("-.5+-.9").evaluate(jc)); | ||
| // unary handling | ||
| assertEquals(-0.1d, jexl.createExpression("-.1").evaluate(jc)); |
Contributor
There was a problem hiding this comment.
Add the "+.1" test for completeness.
Contributor
|
I pushed an additional commit to git remote add upstream https://github.com/apache/commons-jexl.git
git fetch upstream JEXL-411-leading-zeroes
git cherry-pick a4b5751a
git push origin JEXL-411-leading-zeroes |
- update changes.xml;
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary / Why
Fixing bug JEXL-411 (https://issues.apache.org/jira/browse/JEXL-411):
JEXL could not parse a floating point literal with an omitted leading
zero (e.g. ".1"), so "(1+0.1)*2" evaluated to 2.2 while "(1+.1)*2"
raised a parsing error, although ".1" is valid in Java.
How
A leading-dot number is tokenized as "DOT DOT_IDENTIFIER", which is
identical to the postfix index access "x.3" and cannot be told apart at
the lexer level. The literal is therefore recognized in the parser, in
operand position.
FloatLiteral()inParser.jjtnow also accepts"." (only all-digit
DOT_IDENTIFIERimages, checked via a newisAllDigitsguard) and rebuilds the value as "." + image beforehanding it to
NumberParser. Dot-based index/property access isparsed first by
MemberAccess/IdentifierAccessand left untouched.Tests
ArithmeticTest#testLeadingDotFloatLiteral:Verification
mvn(incl. apache-rat license check): BUILD SUCCESSmvn test: 1164 tests, 0 failures, 0 errorsNotes
ticket; the issue is referenced via the key in the branch, commits and
this description.
Thanks for your contribution to Apache Commons! Your help is appreciated!
Before you push a pull request, review this list:
mvn; that'smvnon the command line by itself.