Skip to content

Stage 7#1

Open
kostylevv wants to merge 10 commits intohyperskill:masterfrom
kostylevv:master
Open

Stage 7#1
kostylevv wants to merge 10 commits intohyperskill:masterfrom
kostylevv:master

Conversation

@kostylevv
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown
Contributor

@swsms swsms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed

Comment thread Repl.java Outdated
* The Repl class implements a simple REPL.
* It supports addition and substraction including unary.
* It calculates the expressions like these: 4 + 6 - 8, 2 - 3 - 4 and so on.
* \help command explains these operations
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello! Why do you use different types of slashes for different commands? In this project, we suppose to use the forward slash like jshell does.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, thank you very much for review. Instructions here https://hyperskill.org/projects/1/stages/3 requires to use \help but /exit. I just strictlly followed it) I fixed it in next commit.

Copy link
Copy Markdown
Contributor

@swsms swsms Jul 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, it is just a typo in the stage description! In this project, we chose slash for commands because it is used by jshell (since Java 9).

Comment thread Repl.java Outdated
/**
* The Repl class implements a simple REPL.
* It supports addition and substraction including unary.
* It calculates the expressions like these: 4 + 6 - 8, 2 - 3 - 4 and so on.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, It cannot calculate expressions without spaces: 2+8 -> Unsupported expression.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks

Comment thread Repl.java Outdated
if (line.contains("/") || line.contains("\\")) {
switch (line.trim()) {
case "/help":
System.out.println("Program calculates the expressions like these: 4 + 6 - 8, 2 - 3 - 4 and so on. It supports both unary and binary minuses. Enter '/exit' to terminate program.");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The terminate command is not /exit in your program, but the text prints it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread Repl.java Outdated
* @param postfix arithmetic expression in postfix notation
* @return result of calculation
**/
private static int calculatePostfix(String[] postfix) throws IllegalArgumentException {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do not need to specify an unchecked exception in the method declaration. Usually, they are written in the Javadoc section @throws.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks

Comment thread Repl.java Outdated
* @param words arithmetic expression in infix notation
* @return expression in postfix notation
**/
private static String[] infixToPostfix(String[] words) throws IllegalArgumentException {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a good idea to use postfix notation here. It allows you to support multiplication, division and brackets in future.

Comment thread Repl.java Outdated
String line = sc.nextLine();

if (line != null && line.length() > 0) {
if (line.contains("/") || line.contains("\\")) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be better to skip lines containing only spaces as well.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread Repl.java Outdated

/**
* Converts operations to unified form.
* E.g: --- = -, ++++ = +, -- = + etc.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you process the operations like "++-" like a simple "-"? As an example, the Python REPL does it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now it can

Comment thread Repl.java Outdated
}


private static String[] lineToInfix(String line) throws IllegalArgumentException {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is good that you decompose the program into a set of methods. You can also decompose it into a set of classes to make it easy to read and develop.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a long line to read it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to decompose, but it is still look like spaghetti code. I would be grateful for the advice on decomposition.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would take some of the repetitive logic to a class like Utils. You can either create a separate file containing a public class, or declare it right here if it is not a public class.

public class Repl {
 // ...
}

final class Utils {
    private Utils() { }

   // methods...
}

The class may contain a set of static methods which perform typical transformations of strings using regular expressions. You can also define patterns of regular expressions as static fields of this class. It is a quite popular approach.

You can also try to model the Expression as a class or interface with a single method evaluate(). Then you can extend or implement the class using a PostfixExpression with the overridden method to perform evaluation logic.

So, your main class will contain code only to read/output results.

But this is just one of many ways to decompose it as simple as possible.

By the way, we have added a new stage for this project. It uses the postfix notation like your program.

Comment thread Repl.java Outdated

for (String word : expr) {
if ((!word.matches("[0-9+-]+")) || (word.contains("-") && word.contains("+"))) throw new IllegalArgumentException("Unsupported expression: " + word);
if (word.matches("[\\+]+[0-9]+")) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be better to use Pattern and Matcher if you take a regex multiple times because it has a better performance. The matches method of a string is often used when you need just match a string only once.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Copy Markdown
Contributor

@swsms swsms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, but there are small remarks and recommendations.

Comment thread Repl.java Outdated

if (line != null && line.length() > 0 && line.trim().replace(" ","").length() > 0) {
//processing commands
if (line.contains("/")) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be better to use startsWith(...) instead of contains(...).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread Repl.java
}

//This class represents an expression
class Expression {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you made a good decomposition! I wrote about it in the previous review.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Comment thread Repl.java


/**
* Evaluates arithmetic expression in postfix notation.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, there is a new stage describing this algorithm: https://hyperskill.org/projects/1/stages/21.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented

Copy link
Copy Markdown
Contributor

@swsms swsms Oct 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've added a new stage with large arithmetics to REPL.

There is a number of new projects as well:
Encryption-decryption: https://hyperskill.org/projects/12/
Online chat with networking: https://hyperskill.org/projects/13/

Comment thread Repl.java Outdated
* @return operation in unified form: + or -
* @throws IllegalArgumentException if operation can not be converted to unified form
**/
private static String convertOperation (String word) throws IllegalArgumentException {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually, unchecked exceptions are not declared in a method declaration. But you can still catch them.

Comment thread Repl.java

//case for "assign" type of expression e.g. "x = ..."
if (expAssignsValueToVariable) {
//extract right side of an expression
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would hide this code in a separate private method to make this method more readable and concise.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks!

Comment thread Repl.java Outdated
}
} else {
//substitute variables
substLine = substituteVariables(infixLine, variables);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, it is the "main" routine of this method and this code is short. You may read this topic.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment thread Repl.java Outdated
if (operator == null) throw new IllegalArgumentException("Unsupported operator NULL");

//equals
Pattern pattern = Pattern.compile("^[=]*$");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can try to move all patterns to a special class like ExUtils as well as methods that checks/parses/etc strings.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially implemented, thanks.

Adre13 added a commit to Adre13/repl that referenced this pull request Aug 23, 2018
MaxHlystov added a commit to MaxHlystov/repl that referenced this pull request Sep 12, 2018
@kostylevv kostylevv changed the title The sum of two integers Stage 7 Oct 5, 2018
Comment thread Repl.java
private static final Pattern ALLOWED_CHARS = Pattern.compile("^[a-zA-Z0-9+-=*/()^]*$");

//operator patterns
private static final Pattern EQUALS_PATTERN = Pattern.compile("^[=]*$");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a set of good regexes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants