-
Notifications
You must be signed in to change notification settings - Fork 0
Done with LS CAT WC PWD #3
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
grammar Bash; | ||
|
||
start : pipeline EOF #pipe | ||
| assignment EOF #assign | ||
; | ||
|
||
pipeline : command #singleCommand | ||
| left=pipeline (' '*) '|' (' '*) right=command #multipleCommands | ||
; | ||
|
||
command : (part(' '*))+ | ||
; | ||
|
||
part : WORD #partWord | ||
| SQSTR #sqstr | ||
| DQSTR #dqstr | ||
| '$' WORD #partVariable | ||
; | ||
|
||
assignment : name=WORD '=' value=WORD #wordAssignment | ||
| name=WORD '=' '$' value=WORD #variableAssignment | ||
; | ||
|
||
|
||
SQSTR: '\'' .*? '\''; | ||
DQSTR: '"' .*? '"'; | ||
|
||
WORD : [a-zA-Z0-9-]+; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package bntler; | ||
|
||
public record BashAssignment(String result) implements BashNode {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package bntler; | ||
|
||
import java.util.List; | ||
|
||
public record BashCommand (List<String> parts) implements BashNode { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package bntler; | ||
|
||
public interface BashNode { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package bntler; | ||
|
||
import java.util.List; | ||
|
||
public record BashPipeline(BashNode left, BashNode right) implements BashNode{ | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package bntler; | ||
|
||
import antlr.BashBaseVisitor; | ||
import antlr.BashLexer; | ||
import antlr.BashParser; | ||
import org.antlr.v4.runtime.CharStreams; | ||
import org.antlr.v4.runtime.CommonTokenStream; | ||
|
||
import java.util.Objects; | ||
|
||
public class PipelineVisitor extends BashBaseVisitor<BashNode> { | ||
|
||
WordOrStringVisitor wordOrStringVisitor = new WordOrStringVisitor(); | ||
|
||
@Override | ||
public BashNode visitPipe(BashParser.PipeContext ctx) { | ||
return visit(ctx.pipeline()); | ||
} | ||
|
||
@Override | ||
public BashNode visitMultipleCommands(BashParser.MultipleCommandsContext ctx) { | ||
var left = visit(ctx.left); | ||
var right = visit(ctx.right); | ||
return new BashPipeline(left, right); | ||
} | ||
|
||
@Override | ||
public BashNode visitSingleCommand(BashParser.SingleCommandContext ctx) { | ||
return visit(ctx.command()); | ||
} | ||
|
||
@Override | ||
public BashNode visitCommand(BashParser.CommandContext ctx) { | ||
var command = ctx.children.stream() | ||
.map(it -> wordOrStringVisitor.visit(it)) | ||
.filter(Objects::nonNull) | ||
.toList(); | ||
return new BashCommand(command); | ||
} | ||
|
||
@Override | ||
public BashNode visitAssign(BashParser.AssignContext ctx) { | ||
return new BashAssignment(wordOrStringVisitor.visit(ctx.assignment())); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package bntler; | ||
|
||
import antlr.BashBaseVisitor; | ||
import antlr.BashParser; | ||
import parser.Environment; | ||
|
||
import java.util.Map; | ||
|
||
public class WordOrStringVisitor extends BashBaseVisitor<String> { | ||
|
||
@Override | ||
public String visitAssign(BashParser.AssignContext ctx) { | ||
visit(ctx.assignment()); | ||
return ""; | ||
} | ||
|
||
@Override | ||
public String visitPartWord(BashParser.PartWordContext ctx) { | ||
return ctx.WORD().toString(); | ||
} | ||
|
||
@Override | ||
public String visitPartVariable(BashParser.PartVariableContext ctx) { | ||
return Environment.values.get(ctx.WORD().toString()); | ||
} | ||
|
||
@Override | ||
public String visitVariableAssignment(BashParser.VariableAssignmentContext ctx) { | ||
String newVar = Environment.values.get(ctx.WORD(1).toString()); | ||
Environment.values.put(ctx.WORD(0).toString(), newVar); | ||
return ""; | ||
} | ||
|
||
@Override | ||
public String visitWordAssignment(BashParser.WordAssignmentContext ctx) { | ||
// TODO: 02.06.2022 figure out how to make this smoother | ||
Environment.values.put(ctx.WORD(0).toString(), ctx.WORD(1).toString()); | ||
return ""; | ||
} | ||
|
||
@Override | ||
public String visitDqstr(BashParser.DqstrContext ctx) { | ||
String dqstr = ctx.DQSTR().toString(); | ||
String noQuotes = dqstr.substring(1, dqstr.length() - 1); | ||
|
||
for (Map.Entry<String, String> entry : Environment.values.entrySet()) { | ||
if (noQuotes.contains("$"+entry.getKey())) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Пробелы вокруг операторов |
||
noQuotes = noQuotes.replace("$"+entry.getKey(), entry.getValue()); | ||
} | ||
} | ||
return noQuotes; | ||
} | ||
|
||
@Override | ||
public String visitSqstr(BashParser.SqstrContext ctx) { | ||
String sqstr = ctx.SQSTR().toString(); | ||
return sqstr.substring(1, sqstr.length() - 1); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
package builtins; | ||
|
||
import parser.Expr; | ||
import bntler.BashCommand; | ||
|
||
import java.nio.file.Paths; | ||
|
||
public class Pwd { | ||
public static String execute1(Expr.Command command, String stdin) { | ||
return Paths.get(".").toAbsolutePath().normalize().toString(); | ||
public static String execute(BashCommand command, String stdin) { | ||
return Paths.get(".").toAbsolutePath().normalize().toString() + "\n"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
package builtins; | ||
|
||
import bntler.BashCommand; | ||
import parser.Bash; | ||
import parser.Expr; | ||
|
||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
|
@@ -11,31 +11,30 @@ | |
import java.util.regex.Pattern; | ||
|
||
public class Wc { | ||
public static String execute1(Expr.Command command, String stdin) { | ||
if (!command.arguments.isEmpty()) { | ||
try { | ||
Path path = Paths.get(command.arguments.get(0).literal); | ||
String content = Files.readString(path, StandardCharsets.US_ASCII); | ||
return wcInner(content); | ||
} catch (IOException e) { | ||
Bash.error("no such file"); | ||
return ""; | ||
} | ||
public static String execute(BashCommand command, String stdin) throws IOException { | ||
if (command.parts().size() > 1) { | ||
Path path = Paths.get(command.parts().get(1)); | ||
String content = Files.readString(path, StandardCharsets.US_ASCII); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Крайне плохая идея -- считывать весь файл целиком в строку |
||
return wcInner(content, path.getFileName().toString()); | ||
} else if (stdin != null) { | ||
return wcInner(stdin); | ||
return wcInner(stdin, ""); | ||
} else { | ||
throw new IllegalStateException("Not Implemented"); | ||
} | ||
} | ||
|
||
private static String wcInner(String input) { | ||
private static String wcInner(String input, String path) { | ||
|
||
final Pattern nonWordPattern = Pattern.compile("\\W"); | ||
long charCount = input.lines().flatMapToInt(String::chars).count(); | ||
long lineCount = input.lines().count(); | ||
long wordCount = input.lines() | ||
.flatMap(nonWordPattern::splitAsStream) | ||
.filter(str -> !str.isEmpty()).count(); | ||
return lineCount + " " + wordCount + " " + charCount + "\n"; | ||
if (path.isEmpty()) { | ||
return lineCount + " " + wordCount + " " + charCount + "\n"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} else { | ||
return lineCount + " " + wordCount + " " + charCount + " " + path + "\n"; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,18 @@ | ||
package parser; | ||
|
||
import antlr.BashLexer; | ||
import antlr.BashParser; | ||
import bntler.PipelineVisitor; | ||
import org.antlr.v4.runtime.CharStreams; | ||
import org.antlr.v4.runtime.CommonTokenStream; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.util.List; | ||
|
||
public class Bash { | ||
private static final Interpreter interpreter = new Interpreter(); | ||
static boolean hadError = false; | ||
static boolean hadRuntimeError = false; | ||
|
||
public static void main(String[] args) throws IOException { | ||
if (args.length > 1) { | ||
|
@@ -25,7 +29,6 @@ private static void runPrompt() throws IOException { | |
for (;;) { | ||
System.out.print("> "); | ||
run(reader.readLine()); | ||
hadError = false; | ||
} | ||
} | ||
|
||
|
@@ -35,36 +38,24 @@ private static void run(String source) { | |
} | ||
|
||
public static String runExternal(String source) { | ||
Scanner scanner = new Scanner(source); | ||
List<Token> tokens = scanner.scanTokens(); | ||
Parser parser = new Parser(tokens); | ||
Expr statements = parser.parse(); | ||
|
||
// Stop if there was a syntax error. | ||
if (hadError) return ""; | ||
|
||
return interpreter.interpret(statements); | ||
} | ||
|
||
public static void error(String message) { | ||
report("", message); | ||
} | ||
|
||
private static void report(String where, String message) { | ||
System.err.println("Error" + where + ": " + message); | ||
hadError = true; | ||
} | ||
|
||
public static void error(Token token, String message) { | ||
if (token.type == TokenType.EOF) { | ||
report(" at end", message); | ||
} else { | ||
report(" at '" + token.rawText + "'", message); | ||
if (source.isEmpty()) { | ||
return "\n"; | ||
} | ||
} | ||
|
||
public static void runtimeError(RuntimeError error) { | ||
System.err.println(error.getMessage()); | ||
hadRuntimeError = true; | ||
var input = CharStreams.fromString(source); | ||
var lexer = new BashLexer(input); | ||
var tokens = new CommonTokenStream(lexer); | ||
var parser = new BashParser(tokens); | ||
var rootNode = parser.start(); | ||
var rootNodeGood = new PipelineVisitor().visit(rootNode); | ||
String result; | ||
try { | ||
result = interpreter.interpret(rootNodeGood); | ||
} catch (Exception e) { | ||
// e.printStackTrace(); for debug | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Не должно быть закомментированного кода |
||
result = e + "\n"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. А почему игнорируется исключение и тупо |
||
} | ||
return result; | ||
} | ||
} |
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.
Странно, что присваивать можно только
WORD
и$WORD
, а как же строки в кавычках?