Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
Abgabe4Java
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Dominic Daniel Krämer
Abgabe4Java
Commits
16856cd8
Commit
16856cd8
authored
2 years ago
by
Dominic Daniel Krämer
Browse files
Options
Downloads
Patches
Plain Diff
implemented final version of Parser.java and a fitting test class ParserTest.java
parent
7a28a1b0
No related branches found
No related tags found
1 merge request
!13
Dominicsbranch
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
expressions.txt
+4
-0
4 additions, 0 deletions
expressions.txt
src/main/Parser.java
+62
-23
62 additions, 23 deletions
src/main/Parser.java
src/test/ParserTest.java
+37
-2
37 additions, 2 deletions
src/test/ParserTest.java
with
103 additions
and
25 deletions
expressions.txt
+
4
−
0
View file @
16856cd8
2*(4^2)
(4+2)*4
(4+2*(4-2))
((3+2)*(12+2))
1+(x^2.22)-(3*x)
2*x+0.5*(x^2+4)-1
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/main/Parser.java
+
62
−
23
View file @
16856cd8
...
...
@@ -116,11 +116,12 @@ public class Parser {
return
ast
;
}
//called by parseExpression
//checks if there are multiple tokens left, which indicates that they build up a BinaryOperation
//It splits up the tokens into a left and right expression and with a recursive call of parseExpression
//each part will be determined, until all BinaryOperations consist of finite left and right expressions
//Then a new BinaryOperation will be returned, which saves the left- & right expression and the operator
//between them
private
BinaryOperation
parseBinaryOperation
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
if
(
ts
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty token list"
);
...
...
@@ -128,76 +129,111 @@ public class Parser {
if
(
ts
.
size
()==
1
)
{
return
null
;
}
int
index
=
0
;
//Index will be determined in the next if/else statement
//It will indicate the position of the operator that separates the left- and right expression
int
index
;
int
tokensInBracket
=
parseBrackets
(
ts
);
boolean
capsuled
;
//If the result of parseBrackets(ts)+1 is the same as ts.size the current BinaryOperation is capsuled
if
(
tokensInBracket
+
1
==
ts
.
size
())
{
//removes the tokens with the capsuling brackets
ts
.
remove
(
tokensInBracket
);
ts
.
remove
(
0
);
capsuled
=
true
;
index
=
1
;
//Checks again for brackets
tokensInBracket
=
parseBrackets
(
ts
);
//If no bracket is following, the operator needs to be at position 1 of ts
if
(
tokensInBracket
==-
1
)
{
index
=
1
;
}
else
{
//If brackets are following, the operator is at position tokensInBracket+1
index
=
tokensInBracket
+
1
;
}
}
//If tokensInBracket is -1 this expression is not capsuled and the operator needs to be at position 1 of ts
else
if
(
tokensInBracket
==-
1
)
{
capsuled
=
false
;
parseOperator
(
ts
.
get
(
1
).
getData
());
index
=
1
;
}
//If both other cases were not fulfilled an inner expression is capsuled
//Then this BinaryOperation is not capsuled, no brackets need to be removed and the operator is at
//position tokensInBracket+1
else
{
capsuled
=
false
;
index
=
tokensInBracket
+
1
;
}
//Checks if the operator of this BinaryOperation is permitted
parseOperator
(
ts
.
get
(
index
).
getData
());
List
<
Lexer
.
Token
>
leftList
=
new
LinkedList
<>();
//Splits the token list ts into a left and right expression
for
(
int
iterator
=
0
;
iterator
<
index
;
iterator
++)
{
leftList
.
add
(
ts
.
remove
(
0
));
}
Expression
leftExpression
=
parseExpression
(
leftList
);
//Operator is now at position 0
String
operator
=
ts
.
remove
(
0
).
getData
();
Expression
rightExpression
=
parseExpression
(
ts
);
return
new
BinaryOperation
(
leftExpression
,
operator
,
rightExpression
,
capsuled
);
}
//checks if a String only contains an allowed operator with parseCharacter(...)
private
boolean
parseOperator
(
String
operator
)
throws
ParserException
{
if
(
operator
.
length
()>
1
)
{
throw
new
ParserException
(
"SyntaxError: invalid length for an operator: "
+
operator
);
}
if
(!
parseCharacter
(
operator
,
"+-*/^"
))
{
throw
new
ParserException
(
"SyntaxError: invalid operator character: "
+
operator
);
}
return
true
;
}
//called by parseBinaryOperator
//checks if the first token is a bracket
//If yes: checks if the bracket gets closed correctly and returns the index of the closing bracket
//If no: returns -1
private
int
parseBrackets
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
if
(
ts
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty token list"
);
}
if
(
parseCharacter
(
ts
.
get
(
0
).
getData
(),
"("
))
{
int
index
;
int
lBrackets
=
0
;
int
rBrackets
=
0
;
boolean
found
=
false
;
//Iterates through every token, until the closing bracket got found
for
(
index
=
1
;
index
<
ts
.
size
();
index
++)
{
if
(
parseCharacter
(
ts
.
get
(
index
).
getData
(),
"("
))
{
lBrackets
+=
1
;
}
else
if
(
parseCharacter
(
ts
.
get
(
index
).
getData
(),
")"
))
{
rBrackets
+=
1
;
//If more ')' got found then '(' the bracket got closed correctly and the loop can be interrupted
if
(
rBrackets
>
lBrackets
)
{
found
=
true
;
break
;
}
}
}
//If no matching closing bracket was found a ParserException will be thrown
if
(!
found
)
{
throw
new
ParserException
(
"SyntaxError: brackets never got closed"
);
}
//If the closing bracket was placed immediately after the opening bracket a ParserException will be thrown
if
(
index
==
1
)
{
throw
new
ParserException
(
"SyntaxError: no value inside brackets"
);
}
//Returns the index of the closing bracket
return
index
;
}
return
-
1
;
}
//called by parseBinaryOperation
//checks if a String only contains an allowed operator with parseCharacter
//if not: throws a ParserException
private
void
parseOperator
(
String
operator
)
throws
ParserException
{
if
(
operator
.
isEmpty
())
{
throw
new
ParserException
(
"RuntimeError: empty String instead of an operator (+, -, *, /, ^"
);
}
if
(
operator
.
length
()>
1
)
{
throw
new
ParserException
(
"SyntaxError: invalid length for an operator: "
+
operator
);
}
if
(!
parseCharacter
(
operator
,
"+-*/^"
))
{
throw
new
ParserException
(
"SyntaxError: invalid operator character: "
+
operator
);
}
}
//called by parseExpression
//Checks if a token is a variable:
...
...
@@ -280,7 +316,10 @@ public class Parser {
//If afterDot is false, the first digit is not allowed to be 0
if
(!
afterDot
)
{
parseDigitWithoutZero
(
data
.
substring
(
0
,
1
));
parseDigit
(
data
.
substring
(
1
));
if
(
data
.
length
()>
1
)
{
parseDigit
(
data
.
substring
(
1
));
}
}
//Checks if all digits of the number are permitted
else
{
...
...
@@ -293,10 +332,10 @@ public class Parser {
//checks if a String only contains numbers(including zero) with parseCharacter
//if not, a ParserException is thrown
private
void
parseDigit
(
String
data
)
throws
ParserException
{
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"RuntimeError: empty String instead of a digit(0-9)"
);
}
for
(
int
index
=
0
;
index
<
data
.
length
();
index
++)
{
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"RuntimeError: empty String instead of a digit(0-9)"
);
}
String
character
=
Character
.
toString
(
data
.
charAt
(
index
));
if
(!
parseCharacter
(
character
,
"0123456789"
))
{
throw
new
ParserException
(
"SyntaxError: unexpected character: "
+
character
);
...
...
This diff is collapsed.
Click to expand it.
src/test/ParserTest.java
+
37
−
2
View file @
16856cd8
...
...
@@ -7,8 +7,6 @@ import org.junit.Test;
import
java.util.LinkedList
;
import
java.util.List
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
public
class
ParserTest
{
@Test
...
...
@@ -62,4 +60,41 @@ public class ParserTest {
e
.
printStackTrace
();
}
}
@Test
void
testParseBinaryOperation
()
{
List
<
Lexer
.
Token
>
tokens
=
new
LinkedList
<>();
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
SPECIAL
,
"("
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
NUMBER
,
"5"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
SPECIAL
,
"*"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
NUMBER
,
"2"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
SPECIAL
,
")"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
NUMBER
,
"*"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
NUMBER
,
"3"
));
var
parser
=
new
Parser
();
try
{
var
ast
=
parser
.
parse
(
tokens
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
@Test
void
testParseWrongBinaryOperation
()
{
List
<
Lexer
.
Token
>
tokens
=
new
LinkedList
<>();
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
SPECIAL
,
"("
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
NUMBER
,
"5"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
SPECIAL
,
"*"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
NUMBER
,
"2"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
SPECIAL
,
")"
));
tokens
.
add
(
new
Lexer
.
Token
(
Lexer
.
TokenType
.
NUMBER
,
"3"
));
var
parser
=
new
Parser
();
try
{
var
ast
=
parser
.
parse
(
tokens
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment