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
cd41355c
Commit
cd41355c
authored
2 years ago
by
Dominic Daniel Krämer
Browse files
Options
Downloads
Plain Diff
Merge branch 'dominicsbranch' into 'main'
Dominicsbranch See merge request
!7
parents
2aca6157
2fd496f2
No related branches found
No related tags found
1 merge request
!7
Dominicsbranch
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
expressions.txt
+1
-3
1 addition, 3 deletions
expressions.txt
src/Application.java
+21
-7
21 additions, 7 deletions
src/Application.java
src/Lexer.java
+3
-0
3 additions, 0 deletions
src/Lexer.java
src/Parser.java
+134
-51
134 additions, 51 deletions
src/Parser.java
with
159 additions
and
61 deletions
expressions.txt
+
1
−
3
View file @
cd41355c
1 + xy^2 - (31 * x)y
1 + x^2 - (3 * x)
2x + 0,5x^2 - 1
\ No newline at end of file
x+2/5223+y+44+4+2^12/222
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/Application.java
+
21
−
7
View file @
cd41355c
...
...
@@ -2,36 +2,50 @@ import java.io.BufferedReader;
import
java.io.FileReader
;
import
java.io.IOException
;
import
java.util.Arrays
;
import
java.util.LinkedList
;
import
java.util.List
;
public
class
Application
{
public
static
void
main
(
String
[]
args
)
{
//LinkedList<String> expressions = new LinkedList<>()
//LinkedList<String> expressions = new List<>();
List
<
String
>
expressions
=
new
LinkedList
<>();
//Reads the file "expressions.txt" and adds its values to a list
BufferedReader
reader
;
String
datapath
=
"expressions.txt"
;
try
{
System
.
out
.
println
(
"Reading the file
:
"
);
System
.
out
.
println
(
"Reading the file
...\n
"
);
reader
=
new
BufferedReader
(
new
FileReader
(
datapath
));
String
line
=
reader
.
readLine
();
while
(
line
!=
null
)
{
System
.
out
.
println
(
line
);
expressions
.
add
(
line
);
line
=
reader
.
readLine
();
}
System
.
out
.
println
();
reader
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
//List with a fitting String to be parsed into multiple tokens
List
<
String
>
test
=
Arrays
.
asList
(
"1 + xy^2 - (31 * x)y"
);
//Iterates through every String
for
(
String
value:
test
)
{
//Iterates through every String and parses them into multiple tokens
for
(
String
value:
expressions
)
{
System
.
out
.
println
(
value
);
//creates a list of tokens out of the String
List
<
Lexer
.
Token
>
tokens
=
Lexer
.
lex
(
value
);
//prints each token out (with .toString())
for
(
Lexer
.
Token
singleToken:
tokens
)
{
System
.
out
.
println
(
singleToken
.
toString
());
}
Parser
parser
=
new
Parser
();
try
{
parser
.
parse
(
tokens
);
System
.
out
.
println
();
}
catch
(
ParserException
e
)
{
System
.
out
.
println
(
e
.
getMessage
());
}
System
.
out
.
println
();
}
}
}
This diff is collapsed.
Click to expand it.
src/Lexer.java
+
3
−
0
View file @
cd41355c
...
...
@@ -47,6 +47,9 @@ public class Lexer {
if
(
endIndex
<
input
.
length
())
{
while
(
Character
.
isDigit
(
input
.
charAt
(
endIndex
))
&&
endIndex
<
input
.
length
())
{
endIndex
+=
1
;
if
(
endIndex
==
input
.
length
())
{
break
;
}
}
}
Token
token
=
new
Token
(
TokenType
.
NUMBER
,
input
.
substring
(
index
,
endIndex
));
...
...
This diff is collapsed.
Click to expand it.
src/Parser.java
+
134
−
51
View file @
cd41355c
...
...
@@ -4,29 +4,45 @@ import java.util.Optional;
public
class
Parser
{
private
abstract
interface
Expression
{
private
abstract
class
Expression
{
}
private
abstract
class
Value
implements
Expression
{
private
class
BinaryOperation
extends
Expression
{
Expression
leftExpression
;
String
operator
;
Expression
rightExpression
;
public
BinaryOperation
(
Expression
leftExpression
,
String
operator
,
Expression
rightExpression
)
{
this
.
leftExpression
=
leftExpression
;
this
.
operator
=
operator
;
this
.
rightExpression
=
rightExpression
;
}
}
private
class
Variable
extends
Expression
{
String
variableName
;
public
Variable
(
String
i
)
{
this
.
variableName
=
i
;
}
}
private
abstract
class
Value
extends
Expression
{
}
private
class
Number
extends
Value
{
public
String
or
igi
nal
;
public
String
d
igi
ts
;
public
Number
(
String
i
)
{
this
.
or
igi
nal
=
i
;
this
.
d
igi
ts
=
i
;
}
}
private
class
Decimal
extends
Value
{
public
Number
beforeDot
;
public
char
dot
;
public
Number
afterDot
;
public
Decimal
(
Number
i1
,
Number
i2
)
{
this
.
beforeDot
=
i1
;
dot
=
'.'
;
this
.
afterDot
=
i2
;
}
}
...
...
@@ -42,9 +58,8 @@ public class Parser {
Expression
ast
=
parseExpression
(
ts
);
if
(!
ts
.
isEmpty
())
{
throw
new
ParserException
(
"
Syntax
Error: "
+
ts
.
size
()
+
"
T
oken(s) left"
);
throw
new
ParserException
(
"
Runtime
Error: "
+
ts
.
size
()
+
"
t
oken(s) left"
);
}
return
ast
;
}
...
...
@@ -52,75 +67,111 @@ public class Parser {
//parses a list of tokens into an expression
private
Expression
parseExpression
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
if
(
ts
.
isEmpty
())
{
throw
new
ParserException
(
"empty token list"
);
throw
new
ParserException
(
"SyntaxError: empty token list"
);
}
Expression
ast
;
ast
=
parseBinaryOperation
(
ts
);
if
(
ast
==
null
)
{
ast
=
parseVariable
(
ts
);
if
(
ast
==
null
)
{
ast
=
parseValue
(
ts
);
}
if
(
ast
==
null
)
{
throw
new
ParserException
(
"SyntaxError: invalid character"
);
}
}
return
parseValue
(
ts
).
orElseGet
(()
->
null
);
return
ast
;
}
//checks if a String only contains an allowed operator with parseCharacter(...)
private
void
parseOperator
(
String
operator
)
throws
ParserException
{
private
Boolean
parseOperator
(
String
operator
)
throws
ParserException
{
if
(
operator
.
length
()>
1
)
{
throw
new
ParserException
(
"RuntimeException: invalid length for an operator: "
+
operator
);
throw
new
ParserException
(
"SyntaxError: invalid length for an operator: "
+
operator
);
}
if
(!
parseCharacter
(
operator
,
"+-*/^"
))
{
throw
new
ParserException
(
"SyntaxError: invalid operator character: "
+
operator
);
}
parseCharacter
(
operator
,
"+-*/^"
)
;
return
true
;
}
//called by methods parseOperator(...), parseDigit(...), parseDigitWithoutZero(...)
//checks if a certain string can be found in a string of allowed character
//if yes: return true
//if not: a ParserException is thrown
private
Boolean
parseCharacter
(
String
data
,
String
allowedCharacters
)
throws
ParserException
{
if
(!
allowedCharacters
.
contains
(
data
))
{
throw
new
ParserException
(
"SyntaxError: Invalid character: "
+
data
);
private
BinaryOperation
parseBinaryOperation
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
if
(
ts
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty token list"
);
}
if
(
ts
.
size
()==
1
)
{
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
);
return
new
BinaryOperation
(
leftExpression
,
operator
,
rightExpression
);
}
private
Variable
parseVariable
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
if
(
ts
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty token list"
);
}
if
(
data
.
isEmpty
()
)
{
throw
new
ParserException
(
"RuntimeException: empty String"
)
;
if
(
ts
.
get
(
0
).
getType
()
!=
Lexer
.
TokenType
.
VARIABLE
)
{
return
null
;
}
return
true
;
String
data
=
ts
.
remove
(
0
).
getData
();
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty token"
);
}
if
(!
parseCharacter
(
data
,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
))
{
throw
new
ParserException
(
"Invalid variable character: "
+
data
);
}
return
new
Variable
(
data
);
}
//called by method parseException(...)
//parses a list of tokens into a value
private
Optional
<
Expression
>
parseValue
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
//parses a
token/
list of tokens into a value
private
Value
parseValue
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
if
(
ts
.
isEmpty
())
{
throw
new
ParserException
(
"
RuntimeException
: empty token list"
);
throw
new
ParserException
(
"
SyntaxError
: empty token list"
);
}
if
(
ts
.
get
(
0
).
getType
()
!=
Lexer
.
TokenType
.
NUMBER
)
{
return
Optional
.
empty
()
;
return
null
;
}
String
data
=
ts
.
remove
(
0
).
getData
();
String
data
=
ts
.
get
(
0
).
getData
();
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"
RuntimeException
: empty token"
);
throw
new
ParserException
(
"
SyntaxError
: empty token"
);
}
if
(
ts
.
size
()>
0
)
{
Value
value
=
null
;
if
(
ts
.
size
()>
1
)
{
//if the next token is of TokenType.SPECIAL, check if it's a comma
//if it is, create a decimal
if
(
ts
.
get
(
0
).
getType
()
==
Lexer
.
TokenType
.
SPECIAL
)
{
if
(
ts
.
size
()>
1
)
{
if
(
parseComma
(
ts
.
get
(
0
).
getData
()))
{
return
Optional
.
of
(
parseDecimal
(
ts
,
data
));
}
if
(
parseComma
(
ts
))
{
value
=
parseDecimal
(
ts
);
}
}
}
//if the next token wasn't a comma, create a number
return
Optional
.
of
(
parseNumber
(
data
));
if
(
value
==
null
)
{
value
=
parseNumber
(
ts
.
remove
(
0
).
getData
());
}
return
value
;
}
//called by method parseValue(...)
//parses a decimal of a list of tokens & a string
private
Expression
parseDecimal
(
List
<
Lexer
.
Token
>
ts
,
String
data
)
throws
ParserException
{
if
(
ts
.
size
()<
1
)
{
throw
new
ParserException
(
"RuntimeException: empty token list"
);
}
if
(
ts
.
get
(
0
).
getType
()
!=
Lexer
.
TokenType
.
SPECIAL
)
{
throw
new
ParserException
(
"SyntaxException: expected a comma"
);
private
Decimal
parseDecimal
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
String
data
=
ts
.
remove
(
0
).
getData
();
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"SyntaxError: empty data"
);
}
if
(
ts
.
get
(
1
).
getType
()
!=
Lexer
.
TokenType
.
NUMBER
)
{
throw
new
ParserException
(
"SyntaxE
xception: expected a number after a com
ma"
);
if
(
ts
.
size
()==
0
)
{
throw
new
ParserException
(
"SyntaxE
rror: no tokens left to create Deci
ma
l
"
);
}
Number
beforeDot
=
(
Number
)
parseNumber
(
data
);
ts
.
remove
(
0
);
...
...
@@ -131,7 +182,7 @@ public class Parser {
//called by method parseValue(...)
//parses a String into a number
private
Expression
parseNumber
(
String
data
)
throws
ParserException
{
private
Number
parseNumber
(
String
data
)
throws
ParserException
{
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"RuntimeException: empty token"
);
}
...
...
@@ -149,7 +200,10 @@ public class Parser {
//checks if a String only contains numbers(including zero) with parseCharacter(...)
private
void
parseDigit
(
String
data
)
throws
ParserException
{
for
(
int
index
=
1
;
index
<
data
.
length
();
index
++)
{
parseCharacter
(
Character
.
toString
(
data
.
charAt
(
index
)),
"0123456789"
);
String
character
=
Character
.
toString
(
data
.
charAt
(
index
));
if
(!
parseCharacter
(
character
,
"0123456789"
))
{
throw
new
ParserException
(
"SyntaxError: unexpected character: "
+
character
);
}
}
}
...
...
@@ -157,11 +211,40 @@ public class Parser {
//checks if a String only contains numbers(excluding zero) with parseCharacter(...)
private
void
parseDigitWithoutZero
(
String
data
)
throws
ParserException
{
for
(
int
index
=
1
;
index
<
data
.
length
();
index
++)
{
parseCharacter
(
Character
.
toString
(
data
.
charAt
(
index
)),
"123456789"
);
String
character
=
Character
.
toString
(
data
.
charAt
(
index
));
if
(!
parseCharacter
(
character
,
"123456789"
))
{
throw
new
ParserException
(
"SyntaxError: unexpected character: "
+
character
);
}
}
}
private
Boolean
parseComma
(
String
data
)
throws
ParserException
{
return
true
;
private
Boolean
parseComma
(
List
<
Lexer
.
Token
>
ts
)
throws
ParserException
{
String
data
=
ts
.
get
(
0
).
getData
();
if
(
parseCharacter
(
data
,
"."
))
{
if
(
ts
.
get
(
1
).
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(...)
//checks if a certain string can be found in a string of allowed character
private
Boolean
parseCharacter
(
String
data
,
String
allowedCharacters
)
throws
ParserException
{
if
(
data
.
isEmpty
())
{
throw
new
ParserException
(
"RuntimeError: empty String"
);
}
return
(
allowedCharacters
.
contains
(
data
));
}
}
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