Skip to content

Conversation

@Geckostya
Copy link
Owner

Парсер и команды в чём-то имеют несколько другую семантику, но, судя по заданию, это не страшно

Copy link

@ArtyomLobanov ArtyomLobanov left a comment

Choose a reason for hiding this comment

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

  1. Добавьте интеграцию с Travis
  2. Обрабатывайте ошибки аккуратнее.
    cat fghjftgh | wc
    выводит информацию о количестве строк/слов/байт в сообщении об ошибке, а пользователь так и не узнает, что опечатался в имени файла. Не стесняйтесь кидать исключения. Их не просто так придумали.
  3. На одинокий пайп в конце команды интерпретатор не ругается.
    cat f.txt |

}

dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"

Choose a reason for hiding this comment

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

А JUint из воздуха возьмётся?

repositories {
mavenCentral()
}

Choose a reason for hiding this comment

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

Собирающийся jar файл нельзя запустить т.к. не указана точка входа в программу


private var state = Identifier
private var sb = StringBuilder()
private var vsb = StringBuilder()

Choose a reason for hiding this comment

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

Не очень говорящие названия. Называть переменные лучше по их смыслу, а не типу.

Copy link
Owner Author

Choose a reason for hiding this comment

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

У них смысл строки собирать, что поделать, чисто утилитарные штуки. Названия лучше я не придумал, но расписал подробнее хоть


fun isIdentifier(c: Char): Char = if (c in 'a'..'z' || c in 'z'..'Z' || c == '_' || c == '-') c else '_'

fun isDigit(c: Char): Char = if (c in '0'..'9') c else '0'
Copy link

@ArtyomLobanov ArtyomLobanov Feb 21, 2019

Choose a reason for hiding this comment

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

А почему метод, начинающийся на is, возвращает не boolean?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Для матча, переименовал is в match

} catch (e: Exception) {
output.write("cat: ${e.message}")
}
output.write("\n")

Choose a reason for hiding this comment

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

private fun startProcess(process: Process, output: PipedWriter) {
val streamGobbler = StreamGobbler(process.inputStream) { s -> output.write("$s\n") }
val errorGobbler = StreamGobbler(process.errorStream) { s -> output.write("$s\n") }
val executor = Executors.newSingleThreadExecutor()

Choose a reason for hiding this comment

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

Что-то как-то вы тут всё усложнили. Это было необходимо? В любом случае, Executor надо завершать

Copy link
Owner Author

Choose a reason for hiding this comment

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

Я, естественно, не знал от рождения, как на джаве запускать команды кроссплатформенно, поэтому такое решение нагуглил

val result = WCResult()
input.forEachLine {
result.lines++
result.words += it.split(' ').size

Choose a reason for hiding this comment

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

Плохой разделитель. Подумайте, когда это приводит к ошибкам.

input.forEachLine {
result.lines++
result.words += it.split(' ').size
result.bytes += it.toByteArray().size

Choose a reason for hiding this comment

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

Окончания строк не учитываются.

bash/README.md Outdated

Сначала строка из stdin попадает в парсер, где разбивается на токены

Оттуда токены передаются в лексер вместе с окружением, где по пайпам токены делятся на команды: первый токен - имя, остальные - аргументы

Choose a reason for hiding this comment

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

Как-то у вас всё с ног на голову перевернулось. Обычно лексер разбивает текст на маркированные токены, а парсер строит AST. Я бы у вас названия местами поменял.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Мой мир перевернулся, почему-то у меня до этого успело сложиться впечатление, что я всё называю своими именами, а тут вот как. Хотя по факту можно и то и другое парсером назвать, но всё же лексер более подходит

}
}

private fun makeFlow(commands: ArrayList<Command>) =

Choose a reason for hiding this comment

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

Мы же хотим расширяемую и поддерживаемую архитектуру? Давайте создадим отдельный класс Интерпретатор, который будет содержать всю эту логику, а на вход принимать лексер, парсер и, например, входной и выходной потоки. Это позволит в будущем легко подменять налету отдельные части интерпретатора, создавать подпроцессы и т.д.

throw Exception("wc: ${e.message}" + System.lineSeparator())
}
}
output.write("${result.lines} ${result.words} ${result.bytes} total" + System.lineSeparator())

Choose a reason for hiding this comment

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

Всегда выводит 0 0 0 т.к. переменная result нигде не модифицируется

val result = WCResult()
input.forEachLine {
result.lines++
result.words += it.split(Regex("\\s+")).size

Choose a reason for hiding this comment

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

Теперь другая проблема: " some text ".split("\\s+") вернёт ["", "some", "text"]

input.forEachLine {
result.lines++
result.words += it.split(Regex("\\s+")).size
result.bytes += (it + System.lineSeparator()).toByteArray().size

Choose a reason for hiding this comment

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

У последней строки может и не быть перевода строки. Для определения размера файла есть стандартные методы. Например, File.length Не надо изобретать велосипед.

private fun calcInput(input: Reader): WCResult {
val result = WCResult()
val text = input.readText()
result.lines = text.split("\r\n|\r|\n").size

Choose a reason for hiding this comment

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

val executor = Executors.newSingleThreadExecutor()
executor.submit(streamGobbler)
executor.submit(errorGobbler)
executor.shutdown()

Choose a reason for hiding this comment

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

Теперь внешние команды вообще не запускаются. Вы хоть тестируйте, прежде чем пушить в репозиторий.
Я предлагал просто использовать waitFor без аргументов

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ссори, постараюсь ответственнее относиться к этому

@Geckostya
Copy link
Owner Author

@ArtyomLobanov починил

@ArtyomLobanov
Copy link

Ок. @yurii-litvinov

Copy link

@yurii-litvinov yurii-litvinov left a comment

Choose a reason for hiding this comment

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

Мне всё нравится, зачтена

import java.io.PipedWriter


class Controller(val exceptionHandler: (Exception) -> Unit) {

Choose a reason for hiding this comment

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

Вообще, каждому классу нужны комментарии

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.

4 participants