Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improves code coverage #314

Merged
merged 1 commit into from
Sep 28, 2022
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
distribution: 'corretto'
cache: maven
- name: Verify and analyze with SonarCloud
run: mvn --batch-mode verify sonar:sonar -Dsonar.projectKey=ezylang_EvalEx -Dsonar.organization=ezylang -Dsonar.host.url=https://sonarcloud.io -Dsonar.coverage.jacoco.xmlReportPaths=/home/runner/work/EvalEx/EvalEx/target/site/jacoco/jacoco.xml
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
distribution: 'corretto'
cache: maven
server-id: ossrh
server-username: MAVEN_USERNAME
Expand All @@ -25,6 +25,7 @@ jobs:
uses: ncipollo/release-action@v1
with:
allowUpdates: true
generateReleaseNotes: true
artifacts: "${{ github.workspace }}/target/*.jar"
token: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to the Maven Central Repository
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<version>0.8.8</version>
<executions>
<execution>
<id>prepare-agent</id>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ private void processStructureSeparator(Token currentToken) throws ParseException
while (nextToken != null && nextToken.getType() == STRUCTURE_SEPARATOR) {
Token token = operatorStack.pop();
createOperatorNode(token);
nextToken = operatorStack.isEmpty() ? null : operatorStack.peek();
nextToken = operatorStack.peek();
}
operatorStack.push(currentToken);
}
Expand All @@ -144,7 +144,7 @@ private void processBraceClose() throws ParseException {
if (!operatorStack.isEmpty() && operatorStack.peek().getType() == FUNCTION) {
Token functionToken = operatorStack.pop();
ArrayList<ASTNode> parameters = new ArrayList<>();
while (!operandStack.isEmpty()) {
while (true) {
// add all parameters in reverse order from stack to the parameter array
ASTNode node = operandStack.pop();
if (node.getToken().getType() == TokenType.FUNCTION_PARAM_START) {
Expand Down
26 changes: 12 additions & 14 deletions src/main/java/com/ezylang/evalex/parser/Tokenizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ private Token getPreviousToken() {
private Token parseOperator() throws ParseException {
int tokenStartIndex = currentColumnIndex;
StringBuilder tokenValue = new StringBuilder();
while (isNotOtherTokenStart(currentChar)) {
while (true) {
tokenValue.append((char) currentChar);
String tokenString = tokenValue.toString();
String possibleNextOperator = tokenString + (char) peekNextChar();
Expand Down Expand Up @@ -325,7 +325,7 @@ private boolean infixOperatorAllowed() {
}
}

private Token parseNumberLiteral() {
private Token parseNumberLiteral() throws ParseException {
int tokenStartIndex = currentColumnIndex;
StringBuilder tokenValue = new StringBuilder();
int nextChar = peekNextChar();
Expand All @@ -341,10 +341,18 @@ private Token parseNumberLiteral() {
}
} else {
// decimal number
int lastChar = -1;
while (currentChar != -1 && isNumberChar(currentChar)) {
tokenValue.append((char) currentChar);
lastChar = currentChar;
consumeChar();
}
// illegal scientific format literal
if (lastChar == 'e' || lastChar == 'E' || lastChar == '+' || lastChar == '-') {
throw new ParseException(
new Token(tokenStartIndex, tokenValue.toString(), TokenType.NUMBER_LITERAL),
"Illegal scientific format");
}
}
return new Token(tokenStartIndex, tokenValue.toString(), TokenType.NUMBER_LITERAL);
}
Expand All @@ -370,7 +378,7 @@ private Token parseIdentifier() throws ParseException {
tokenName,
TokenType.POSTFIX_OPERATOR,
operatorDictionary.getPostfixOperator(tokenName));
} else if (infixOperatorAllowed() && operatorDictionary.hasInfixOperator(tokenName)) {
} else if (operatorDictionary.hasInfixOperator(tokenName)) {
return new Token(
tokenStartIndex,
tokenName,
Expand Down Expand Up @@ -442,16 +450,6 @@ private char escapeCharacter(int character) throws ParseException {
}
}

private boolean isNotOtherTokenStart(int ch) {
return !(Character.isWhitespace(ch)
|| isNumberStart(ch)
|| isIdentifierStart(ch)
|| ch == '"'
|| ch == '('
|| ch == ')'
|| ch == ',');
}

private boolean isNumberStart(int ch) {
if (Character.isDigit(ch)) {
return true;
Expand All @@ -462,7 +460,7 @@ private boolean isNumberStart(int ch) {
private boolean isNumberChar(int ch) {
int previousChar = peekPreviousChar();
if (previousChar == 'e' || previousChar == 'E') {
return Character.isDigit(ch) || ch == '.' || ch == '+' || ch == '-';
return Character.isDigit(ch) || ch == '+' || ch == '-';
} else {
return Character.isDigit(ch) || ch == '.' || ch == 'e' || ch == 'E';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ class ExpressionEvaluatorScientificTest extends BaseExpressionEvaluatorTest {
delimiter = ':',
value = {
"2e3 : 2000 ",
"2e10 : 20000000000 ",
"2E3 : 2000",
"0.5e2 : 50",
"0.35E4 + 0.5e1 : 3505",
"1e-10 : 0.0000000001",
"1E-10 : 0.0000000001",
"2135E-4 : 0.2135",
"1e+10 : 10000000000",
"1E+10 : 10000000000",
"2e10 : 20000000000 ",
"0.5e2 : 50",
"0.35E4 + 0.5e1 : 3505",
"2135E-4 : 0.2135",
"2135E+4 : 21350000"
})
void testScientificLiteralsEvaluation(String expression, String expectedResult)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ void testEmptyExpressionBraces() {
.hasMessage("Empty expression");
}

@Test
void testComma() {
Expression expression = new Expression(",");

assertThatThrownBy(expression::evaluate)
.isInstanceOf(ParseException.class)
.hasMessage("Empty expression");
}

@Test
void testDoubleStructureOperator() {
List<Token> tokens =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,59 +15,78 @@
*/
package com.ezylang.evalex.parser;

import com.ezylang.evalex.parser.Token.TokenType;
import static com.ezylang.evalex.parser.Token.TokenType.NUMBER_LITERAL;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class TokenizerNumberLiteralTest extends BaseParserTest {

@Test
void testSingleDigit() throws ParseException {
assertAllTokensParsedCorrectly("7", new Token(1, "7", TokenType.NUMBER_LITERAL));
assertAllTokensParsedCorrectly("7", new Token(1, "7", NUMBER_LITERAL));
}

@Test
void testMultipleDigit() throws ParseException {
assertAllTokensParsedCorrectly("888", new Token(1, "888", TokenType.NUMBER_LITERAL));
assertAllTokensParsedCorrectly("888", new Token(1, "888", NUMBER_LITERAL));
}

@Test
void testBlanks() throws ParseException {
assertAllTokensParsedCorrectly("\t 123 \r\n", new Token(3, "123", TokenType.NUMBER_LITERAL));
assertAllTokensParsedCorrectly("\t 123 \r\n", new Token(3, "123", NUMBER_LITERAL));
}

@Test
void testDecimal() throws ParseException {
assertAllTokensParsedCorrectly("123.834", new Token(1, "123.834", TokenType.NUMBER_LITERAL));
assertAllTokensParsedCorrectly("123.834", new Token(1, "123.834", NUMBER_LITERAL));
}

@Test
void testDecimalStart() throws ParseException {
assertAllTokensParsedCorrectly(".9", new Token(1, ".9", TokenType.NUMBER_LITERAL));
assertAllTokensParsedCorrectly(".9", new Token(1, ".9", NUMBER_LITERAL));
}

@Test
void testDecimalEnd() throws ParseException {
assertAllTokensParsedCorrectly("123.", new Token(1, "123.", TokenType.NUMBER_LITERAL));
assertAllTokensParsedCorrectly("123.", new Token(1, "123.", NUMBER_LITERAL));
}

@Test
void testHexNumberSimple() throws ParseException {
assertAllTokensParsedCorrectly("0x0", new Token(1, "0x0", TokenType.NUMBER_LITERAL));
assertAllTokensParsedCorrectly("0x0", new Token(1, "0x0", NUMBER_LITERAL));
}

@Test
void testHexNumberLong() throws ParseException {
assertAllTokensParsedCorrectly("0x3ABCDEF0", new Token(1, "0x3ABCDEF0", NUMBER_LITERAL));
assertAllTokensParsedCorrectly(
"0x3ABCDEF0", new Token(1, "0x3ABCDEF0", TokenType.NUMBER_LITERAL));
assertAllTokensParsedCorrectly(
" \t0x3abcdefAbcdef09873EE ",
new Token(3, "0x3abcdefAbcdef09873EE", TokenType.NUMBER_LITERAL));
" \t0x3abcdefAbcdef09873EE ", new Token(3, "0x3abcdefAbcdef09873EE", NUMBER_LITERAL));
}

@Test
void testHexNumberBlank() throws ParseException {
assertAllTokensParsedCorrectly(
" \t0x3abcdefAbcdef09873EE ",
new Token(3, "0x3abcdefAbcdef09873EE", TokenType.NUMBER_LITERAL));
" \t0x3abcdefAbcdef09873EE ", new Token(3, "0x3abcdefAbcdef09873EE", NUMBER_LITERAL));
}

@Test
void testSciOK() throws ParseException {
assertAllTokensParsedCorrectly("2e1", new Token(1, "2e1", NUMBER_LITERAL));
assertAllTokensParsedCorrectly("2E1", new Token(1, "2E1", NUMBER_LITERAL));
assertAllTokensParsedCorrectly("2e-1", new Token(1, "2e-1", NUMBER_LITERAL));
assertAllTokensParsedCorrectly("2E-1", new Token(1, "2E-1", NUMBER_LITERAL));
assertAllTokensParsedCorrectly("2e+1", new Token(1, "2e+1", NUMBER_LITERAL));
assertAllTokensParsedCorrectly("2E+1", new Token(1, "2E+1", NUMBER_LITERAL));
}

@ParameterizedTest
@ValueSource(strings = {"2e", "2E", "2e+", "2E+", "2e-", "2E-", "2e."})
void testScientificLiteralsParseException(String expression) {
assertThatThrownBy(() -> new Tokenizer(expression, configuration).parse())
.isInstanceOf(ParseException.class)
.hasMessage("Illegal scientific format");
}
}