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
6eda657f
Commit
6eda657f
authored
2 years ago
by
Dominic Daniel Krämer
Browse files
Options
Downloads
Plain Diff
Merge branch 'dominicsbranch' into 'main'
Dominicsbranch See merge request
!9
parents
acfa97d0
e04b6e92
No related branches found
Branches containing commit
No related tags found
1 merge request
!9
Dominicsbranch
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
expressions.txt
+1
-1
1 addition, 1 deletion
expressions.txt
src/Application.java
+4
-4
4 additions, 4 deletions
src/Application.java
src/Lexer.java
+4
-1
4 additions, 1 deletion
src/Lexer.java
src/Parser.java
+107
-106
107 additions, 106 deletions
src/Parser.java
with
116 additions
and
112 deletions
expressions.txt
+
1
−
1
View file @
6eda657f
40.2+3*x
(5*2-(5^2)+3*(201.01-15))
\ No newline at end of file
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/Application.java
+
4
−
4
View file @
6eda657f
...
@@ -12,10 +12,10 @@ public class Application {
...
@@ -12,10 +12,10 @@ public class Application {
List
<
String
>
expressions
=
new
LinkedList
<>();
List
<
String
>
expressions
=
new
LinkedList
<>();
//Reads the file "expressions.txt" and adds its values to a list
//Reads the file "expressions.txt" and adds its values to a list
BufferedReader
reader
;
BufferedReader
reader
;
String
data
p
ath
=
"expressions.txt"
;
String
data
P
ath
=
"expressions.txt"
;
try
{
try
{
System
.
out
.
println
(
"Reading the file...\n"
);
System
.
out
.
println
(
"Reading the file...\n"
);
reader
=
new
BufferedReader
(
new
FileReader
(
data
p
ath
));
reader
=
new
BufferedReader
(
new
FileReader
(
data
P
ath
));
String
line
=
reader
.
readLine
();
String
line
=
reader
.
readLine
();
while
(
line
!=
null
)
{
while
(
line
!=
null
)
{
expressions
.
add
(
line
);
expressions
.
add
(
line
);
...
@@ -39,8 +39,8 @@ public class Application {
...
@@ -39,8 +39,8 @@ public class Application {
}
}
Parser
parser
=
new
Parser
();
Parser
parser
=
new
Parser
();
try
{
try
{
parser
.
parse
(
tokens
);
Parser
.
Expression
exp
=
parser
.
parse
(
tokens
);
System
.
out
.
println
();
System
.
out
.
println
(
exp
.
toString
()
);
}
}
catch
(
ParserException
e
)
{
catch
(
ParserException
e
)
{
System
.
out
.
println
(
e
.
getMessage
());
System
.
out
.
println
(
e
.
getMessage
());
...
...
This diff is collapsed.
Click to expand it.
src/Lexer.java
+
4
−
1
View file @
6eda657f
...
@@ -43,13 +43,16 @@ public class Lexer {
...
@@ -43,13 +43,16 @@ public class Lexer {
//checks if a character is a digit, then creates a token with one or multiple numbers
//checks if a character is a digit, then creates a token with one or multiple numbers
//with TokenType=NUMBER
//with TokenType=NUMBER
if
(
Character
.
isDigit
(
current
))
{
if
(
Character
.
isDigit
(
current
))
{
int
endIndex
=
index
+
1
;
int
endIndex
=
index
;
if
(
endIndex
<
input
.
length
())
{
if
(
endIndex
<
input
.
length
())
{
while
(
Character
.
isDigit
(
input
.
charAt
(
endIndex
))
&&
endIndex
<
input
.
length
())
{
while
(
Character
.
isDigit
(
input
.
charAt
(
endIndex
))
&&
endIndex
<
input
.
length
())
{
endIndex
+=
1
;
endIndex
+=
1
;
if
(
endIndex
==
input
.
length
())
{
if
(
endIndex
==
input
.
length
())
{
break
;
break
;
}
}
if
(
input
.
charAt
(
endIndex
)
==
'.'
)
{
endIndex
+=
1
;
}
}
}
}
}
Token
token
=
new
Token
(
TokenType
.
NUMBER
,
input
.
substring
(
index
,
endIndex
));
Token
token
=
new
Token
(
TokenType
.
NUMBER
,
input
.
substring
(
index
,
endIndex
));
...
...
This diff is collapsed.
Click to expand it.
src/Parser.java
+
107
−
106
View file @
6eda657f
import
java.util.LinkedList
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Optional
;
public
class
Parser
{
public
class
Parser
{
private
abstract
class
Expression
{
public
static
class
Expression
{
@Override
public
String
toString
()
{
return
""
;
}
}
}
private
class
BinaryOperation
extends
Expression
{
private
class
BinaryOperation
extends
Expression
{
Expression
leftExpression
;
Expression
leftExpression
;
String
operator
;
String
operator
;
Expression
rightExpression
;
Expression
rightExpression
;
public
BinaryOperation
(
Expression
leftExpression
,
String
operator
,
Expression
rightExpression
)
{
Boolean
capsuled
;
public
BinaryOperation
(
Expression
leftExpression
,
String
operator
,
Expression
rightExpression
,
Boolean
capsuled
)
{
this
.
leftExpression
=
leftExpression
;
this
.
leftExpression
=
leftExpression
;
this
.
operator
=
operator
;
this
.
operator
=
operator
;
this
.
rightExpression
=
rightExpression
;
this
.
rightExpression
=
rightExpression
;
this
.
capsuled
=
capsuled
;
}
@Override
public
String
toString
()
{
if
(
capsuled
)
{
return
"("
+
leftExpression
.
toString
()
+
operator
+
rightExpression
.
toString
()
+
")"
;
}
return
leftExpression
.
toString
()
+
operator
+
rightExpression
.
toString
();
}
}
}
}
private
class
Variable
extends
Expression
{
private
class
Variable
extends
Expression
{
String
variableName
;
String
variableName
;
public
Variable
(
String
i
)
{
public
Variable
(
String
i
,
Boolean
capsuled
)
{
this
.
variableName
=
i
;
this
.
variableName
=
i
;
}
}
@Override
public
String
toString
()
{
return
variableName
;
}
}
}
private
abstract
class
Value
extends
Expression
{
private
abstract
class
Value
extends
Expression
{
...
@@ -35,6 +50,10 @@ public class Parser {
...
@@ -35,6 +50,10 @@ public class Parser {
public
Number
(
String
i
)
{
public
Number
(
String
i
)
{
this
.
digits
=
i
;
this
.
digits
=
i
;
}
}
@Override
public
String
toString
()
{
return
digits
;
}
}
}
private
class
Decimal
extends
Value
{
private
class
Decimal
extends
Value
{
...
@@ -45,6 +64,10 @@ public class Parser {
...
@@ -45,6 +64,10 @@ public class Parser {
this
.
beforeDot
=
i1
;
this
.
beforeDot
=
i1
;
this
.
afterDot
=
i2
;
this
.
afterDot
=
i2
;
}
}
@Override
public
String
toString
()
{
return
beforeDot
.
toString
()
+
"."
+
afterDot
.
toString
();
}
}
}
//starting method of the parser
//starting method of the parser
...
@@ -58,7 +81,7 @@ public class Parser {
...
@@ -58,7 +81,7 @@ public class Parser {
Expression
ast
=
parseExpression
(
ts
);
Expression
ast
=
parseExpression
(
ts
);
if
(!
ts
.
isEmpty
())
{
if
(!
ts
.
isEmpty
())
{
throw
new
ParserException
(
"
Runtime
Error: "
+
ts
.
size
()
+
" token(s) left"
);
throw
new
ParserException
(
"
Syntax
Error: "
+
ts
.
size
()
+
" token(s) left"
);
}
}
return
ast
;
return
ast
;
}
}
...
@@ -69,22 +92,21 @@ public class Parser {
...
@@ -69,22 +92,21 @@ public class Parser {
if
(
ts
.
isEmpty
())
{
if
(
ts
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty token list"
);
throw
new
ParserException
(
"SyntaxError: empty token list"
);
}
}
Expression
ast
;
Expression
ast
=
parseBinaryOperation
(
ts
);
ast
=
parseBinaryOperation
(
ts
);
if
(
ast
==
null
)
{
ast
=
parseVariable
(
ts
);
if
(
ast
==
null
)
{
if
(
ast
==
null
)
{
ast
=
parseValue
(
ts
);
ast
=
parseVariable
(
ts
);
}
if
(
ast
==
null
)
{
if
(
ast
==
null
)
{
ast
=
parseValue
(
ts
);
throw
new
ParserException
(
"SyntaxError: invalid character"
);
}
if
(
ast
==
null
)
{
throw
new
ParserException
(
"SyntaxError: invalid character"
);
}
}
}
}
return
ast
;
return
ast
;
}
}
//checks if a String only contains an allowed operator with parseCharacter(...)
//checks if a String only contains an allowed operator with parseCharacter(...)
private
B
oolean
parseOperator
(
String
operator
)
throws
ParserException
{
private
b
oolean
parseOperator
(
String
operator
)
throws
ParserException
{
if
(
operator
.
length
()>
1
)
{
if
(
operator
.
length
()>
1
)
{
throw
new
ParserException
(
"SyntaxError: invalid length for an operator: "
+
operator
);
throw
new
ParserException
(
"SyntaxError: invalid length for an operator: "
+
operator
);
}
}
...
@@ -94,6 +116,35 @@ public class Parser {
...
@@ -94,6 +116,35 @@ public class Parser {
return
true
;
return
true
;
}
}
private
int
parseBrackets
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
if
(
parseCharacter
(
ts
.
get
(
0
).
getData
(),
"("
))
{
int
index
;
int
lBrackets
=
0
;
int
rBrackets
=
0
;
boolean
found
=
false
;
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
(
rBrackets
>
lBrackets
)
{
found
=
true
;
break
;
}
}
}
if
(!
found
)
{
throw
new
ParserException
(
"SyntaxError: brackets never got closed"
);
}
if
(
index
==
1
)
{
throw
new
ParserException
(
"SyntaxError: no value inside brackets"
);
}
return
index
;
}
return
-
1
;
}
private
BinaryOperation
parseBinaryOperation
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
private
BinaryOperation
parseBinaryOperation
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
if
(
ts
.
isEmpty
())
{
if
(
ts
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty token list"
);
throw
new
ParserException
(
"SyntaxError: empty token list"
);
...
@@ -101,52 +152,32 @@ public class Parser {
...
@@ -101,52 +152,32 @@ public class Parser {
if
(
ts
.
size
()==
1
)
{
if
(
ts
.
size
()==
1
)
{
return
null
;
return
null
;
}
}
int
index
;
int
index
=
0
;
for
(
index
=
0
;
index
<
ts
.
size
();
index
++)
{
int
tokensInBracket
=
parseBrackets
(
ts
);
if
(
ts
.
get
(
index
).
getType
()==
Lexer
.
TokenType
.
SPECIAL
)
{
boolean
capsuled
;
if
(!
parseCharacter
(
ts
.
get
(
index
).
getData
(),
"."
))
{
if
(
tokensInBracket
+
1
==
ts
.
size
())
{
break
;
ts
.
remove
(
tokensInBracket
);
}
ts
.
remove
(
0
);
}
capsuled
=
true
;
index
=
1
;
}
}
if
(
index
==
ts
.
size
())
{
else
if
(
tokensInBracket
==-
1
)
{
return
null
;
capsuled
=
false
;
parseOperator
(
ts
.
get
(
1
).
getData
());
index
=
1
;
}
else
{
capsuled
=
false
;
index
=
tokensInBracket
+
1
;
}
}
//0
//1
//2
//3
//4 * => index=4
//5
//6
//7
List
<
Lexer
.
Token
>
leftList
=
new
LinkedList
<>();
List
<
Lexer
.
Token
>
leftList
=
new
LinkedList
<>();
for
(
int
i
=
0
;
i
<
index
;
i
++)
{
for
(
int
i
terator
=
0
;
iterator
<
index
;
i
terator
++)
{
leftList
.
add
(
ts
.
remove
(
0
));
leftList
.
add
(
ts
.
remove
(
0
));
}
}
Expression
leftExpression
=
parseExpression
(
leftList
);
Expression
leftExpression
=
parseExpression
(
leftList
);
String
operator
=
ts
.
remove
(
0
).
getData
();
String
operator
=
ts
.
remove
(
0
).
getData
();
parseOperator
(
operator
);
Expression
rightExpression
=
parseExpression
(
ts
);
/*
if(parseCharacter(ts.get(1).getData(), ".")) {
return null;
}
BinaryOperation operation;
if(ts.get(1).getType()!= Lexer.TokenType.SPECIAL) {
throw new ParserException("SyntaxError: unexpected operator: " + ts.get(1).getData());
}
List<Lexer.Token> leftList = new LinkedList<>();
leftList.add(ts.remove(0));
Expression leftExpression = parseExpression(leftList);
String operator = ts.remove(0).getData();
parseOperator(operator);
Expression
rightExpression
=
parseExpression
(
ts
);
Expression
rightExpression
=
parseExpression
(
ts
);
return
new
BinaryOperation
(
leftExpression
,
operator
,
rightExpression
,
capsuled
);
*/
return
new
BinaryOperation
(
leftExpression
,
operator
,
rightExpression
);
}
}
private
Variable
parseVariable
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
private
Variable
parseVariable
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
...
@@ -165,7 +196,7 @@ public class Parser {
...
@@ -165,7 +196,7 @@ public class Parser {
if
(!
parseCharacter
(
data
,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
))
{
if
(!
parseCharacter
(
data
,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
))
{
throw
new
ParserException
(
"Invalid variable character: "
+
data
);
throw
new
ParserException
(
"Invalid variable character: "
+
data
);
}
}
return
new
Variable
(
data
);
return
new
Variable
(
data
,
false
);
}
}
//called by method parseException(...)
//called by method parseException(...)
...
@@ -177,47 +208,34 @@ public class Parser {
...
@@ -177,47 +208,34 @@ public class Parser {
if
(
ts
.
get
(
0
).
getType
()
!=
Lexer
.
TokenType
.
NUMBER
)
{
if
(
ts
.
get
(
0
).
getType
()
!=
Lexer
.
TokenType
.
NUMBER
)
{
return
null
;
return
null
;
}
}
String
data
=
ts
.
get
(
0
).
getData
();
String
data
=
ts
.
remove
(
0
).
getData
();
if
(
data
.
isEmpty
())
{
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty token"
);
throw
new
ParserException
(
"SyntaxError: empty token"
);
}
}
Value
value
=
null
;
if
(
data
.
contains
(
"."
))
{
if
(
ts
.
size
()>
1
)
{
return
parseDecimal
(
data
);
//if the next token is of TokenType.SPECIAL, check if it's a comma
//if it is, create a decimal
if
(
ts
.
get
(
1
).
getType
()
==
Lexer
.
TokenType
.
SPECIAL
)
{
if
(
parseComma
(
ts
))
{
value
=
parseDecimal
(
ts
);
}
}
}
}
if
(
value
==
null
)
{
return
parseNumber
(
data
,
false
);
value
=
parseNumber
(
ts
.
remove
(
0
).
getData
());
}
return
value
;
}
}
//called by method parseValue(...)
//called by method parseValue(...)
//parses a decimal of a list of tokens & a string
//parses a decimal of a list of tokens & a string
private
Decimal
parseDecimal
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
private
Decimal
parseDecimal
(
String
data
)
throws
ParserException
{
String
data
=
ts
.
remove
(
0
).
getData
();
if
(
data
.
isEmpty
())
{
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty data"
);
throw
new
ParserException
(
"SyntaxError: empty data"
);
}
}
if
(
ts
.
size
()==
0
)
{
int
dot
=
data
.
indexOf
(
'.'
);
throw
new
ParserException
(
"SyntaxError: no tokens left to create Decimal"
);
String
number1
=
data
.
substring
(
0
,
dot
);
}
String
number2
=
data
.
substring
(
dot
+
1
);
Number
beforeDot
=
(
Number
)
parseNumber
(
data
);
Number
beforeDot
=
(
Number
)
parseNumber
(
number1
,
true
);
ts
.
remove
(
0
);
Number
afterDot
=
(
Number
)
parseNumber
(
number2
,
false
);
data
=
ts
.
remove
(
0
).
getData
();
Number
afterDot
=
(
Number
)
parseNumber
(
data
);
return
new
Decimal
(
beforeDot
,
afterDot
);
return
new
Decimal
(
beforeDot
,
afterDot
);
}
}
//called by method parseValue(...)
//called by method parseValue(...)
//parses a String into a number
//parses a String into a number
private
Number
parseNumber
(
String
data
)
throws
ParserException
{
private
Number
parseNumber
(
String
data
,
boolean
afterDot
)
throws
ParserException
{
if
(
data
.
isEmpty
())
{
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"RuntimeException: empty token"
);
throw
new
ParserException
(
"RuntimeException: empty token"
);
}
}
...
@@ -225,16 +243,20 @@ public class Parser {
...
@@ -225,16 +243,20 @@ public class Parser {
if
(
data
.
startsWith
(
"0"
)
&&
data
.
length
()
==
1
)
{
if
(
data
.
startsWith
(
"0"
)
&&
data
.
length
()
==
1
)
{
return
new
Number
(
data
);
return
new
Number
(
data
);
}
}
if
(
afterDot
)
{
parseDigitWithoutZero
(
data
.
substring
(
0
,
1
));
parseDigitWithoutZero
(
data
.
substring
(
0
,
1
));
parseDigit
(
data
.
substring
(
1
));
parseDigit
(
data
.
substring
(
1
));
}
else
{
parseDigit
(
data
);
}
return
new
Number
(
data
);
return
new
Number
(
data
);
}
}
//called by method parseNumber(...)
//called by method parseNumber(...)
//checks if a String only contains numbers(including zero) with parseCharacter(...)
//checks if a String only contains numbers(including zero) with parseCharacter(...)
private
void
parseDigit
(
String
data
)
throws
ParserException
{
private
void
parseDigit
(
String
data
)
throws
ParserException
{
for
(
int
index
=
1
;
index
<
data
.
length
();
index
++)
{
for
(
int
index
=
0
;
index
<
data
.
length
();
index
++)
{
String
character
=
Character
.
toString
(
data
.
charAt
(
index
));
String
character
=
Character
.
toString
(
data
.
charAt
(
index
));
if
(!
parseCharacter
(
character
,
"0123456789"
))
{
if
(!
parseCharacter
(
character
,
"0123456789"
))
{
throw
new
ParserException
(
"SyntaxError: unexpected character: "
+
character
);
throw
new
ParserException
(
"SyntaxError: unexpected character: "
+
character
);
...
@@ -245,7 +267,7 @@ public class Parser {
...
@@ -245,7 +267,7 @@ public class Parser {
//called by method parseNumber(...)
//called by method parseNumber(...)
//checks if a String only contains numbers(excluding zero) with parseCharacter(...)
//checks if a String only contains numbers(excluding zero) with parseCharacter(...)
private
void
parseDigitWithoutZero
(
String
data
)
throws
ParserException
{
private
void
parseDigitWithoutZero
(
String
data
)
throws
ParserException
{
for
(
int
index
=
1
;
index
<
data
.
length
();
index
++)
{
for
(
int
index
=
0
;
index
<
data
.
length
();
index
++)
{
String
character
=
Character
.
toString
(
data
.
charAt
(
index
));
String
character
=
Character
.
toString
(
data
.
charAt
(
index
));
if
(!
parseCharacter
(
character
,
"123456789"
))
{
if
(!
parseCharacter
(
character
,
"123456789"
))
{
throw
new
ParserException
(
"SyntaxError: unexpected character: "
+
character
);
throw
new
ParserException
(
"SyntaxError: unexpected character: "
+
character
);
...
@@ -253,30 +275,9 @@ public class Parser {
...
@@ -253,30 +275,9 @@ public class Parser {
}
}
}
}
private
Boolean
parseComma
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
String
data
=
ts
.
get
(
1
).
getData
();
if
(
parseCharacter
(
data
,
"."
))
{
if
(
ts
.
get
(
2
).
getType
()!=
Lexer
.
TokenType
.
NUMBER
)
{
throw
new
ParserException
(
"SyntaxError: no number after comma"
);
}
return
true
;
}
return
false
;
}
private
Boolean
parseBracket
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
String
data
=
ts
.
get
(
0
).
getData
();
if
(
parseCharacter
(
data
,
"("
))
{
return
true
;
}
else
{
return
false
;
}
}
//called by methods parseOperator(...), parseDigit(...), parseDigitWithoutZero(...)
//called by methods parseOperator(...), parseDigit(...), parseDigitWithoutZero(...)
//checks if a certain string can be found in a string of allowed character
//checks if a certain string can be found in a string of allowed character
private
B
oolean
parseCharacter
(
String
data
,
String
allowedCharacters
)
throws
ParserException
{
private
b
oolean
parseCharacter
(
String
data
,
String
allowedCharacters
)
throws
ParserException
{
if
(
data
.
isEmpty
())
{
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"RuntimeError: empty String"
);
throw
new
ParserException
(
"RuntimeError: empty String"
);
}
}
...
...
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