-
Notifications
You must be signed in to change notification settings - Fork 1
HW 01 Bash #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
HW 01 Bash #1
Conversation
ArtyomLobanov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Добавьте интеграцию с Travis
- Обрабатывайте ошибки аккуратнее.
cat fghjftgh | wc
выводит информацию о количестве строк/слов/байт в сообщении об ошибке, а пользователь так и не узнает, что опечатался в имени файла. Не стесняйтесь кидать исключения. Их не просто так придумали. - На одинокий пайп в конце команды интерпретатор не ругается.
cat f.txt |
| } | ||
|
|
||
| dependencies { | ||
| compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А JUint из воздуха возьмётся?
| repositories { | ||
| mavenCentral() | ||
| } | ||
|
|
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не очень говорящие названия. Называть переменные лучше по их смыслу, а не типу.
There was a problem hiding this comment.
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' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А почему метод, начинающийся на is, возвращает не boolean?
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Что-то как-то вы тут всё усложнили. Это было необходимо? В любом случае, Executor надо завершать
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 попадает в парсер, где разбивается на токены | ||
|
|
||
| Оттуда токены передаются в лексер вместе с окружением, где по пайпам токены делятся на команды: первый токен - имя, остальные - аргументы |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Как-то у вас всё с ног на голову перевернулось. Обычно лексер разбивает текст на маркированные токены, а парсер строит AST. Я бы у вас названия местами поменял.
There was a problem hiding this comment.
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>) = |
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Теперь внешние команды вообще не запускаются. Вы хоть тестируйте, прежде чем пушить в репозиторий.
Я предлагал просто использовать waitFor без аргументов
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ссори, постараюсь ответственнее относиться к этому
|
@ArtyomLobanov починил |
|
Ок. @yurii-litvinov |
yurii-litvinov
left a comment
There was a problem hiding this 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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вообще, каждому классу нужны комментарии
Парсер и команды в чём-то имеют несколько другую семантику, но, судя по заданию, это не страшно