From 679c2df6d8d712803d884c8d4cc871c5da923b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thiago=20Henrique=20H=C3=BCpner?= Date: Tue, 7 May 2024 15:11:08 -0300 Subject: [PATCH] Add interpreter module --- .../frontend/impl/antlr/VisuAlgParser.g4 | 2 +- .../frontend/VisuAlgParserVisitor.java | 14 +- .../thihup/jvisualg/frontend/node/Node.java | 13 +- .../src/main/java/module-info.java | 9 +- dev.thihup.jvisualg.interpreter/pom.xml | 22 + .../jvisualg/interpreter/Interpreter.java | 234 +++++++++ .../src/main/java/module-info.java | 3 + .../jvisualg/interpreter/InterpreterTest.java | 463 ++++++++++++++++++ pom.xml | 1 + 9 files changed, 745 insertions(+), 16 deletions(-) create mode 100644 dev.thihup.jvisualg.interpreter/pom.xml create mode 100644 dev.thihup.jvisualg.interpreter/src/main/java/dev/thihup/jvisualg/interpreter/Interpreter.java create mode 100644 dev.thihup.jvisualg.interpreter/src/main/java/module-info.java create mode 100644 dev.thihup.jvisualg.interpreter/src/test/java/dev/thihup/jvisualg/interpreter/InterpreterTest.java diff --git a/dev.thihup.jvisualg.frontend/src/main/antlr4/dev/thihup/jvisualg/frontend/impl/antlr/VisuAlgParser.g4 b/dev.thihup.jvisualg.frontend/src/main/antlr4/dev/thihup/jvisualg/frontend/impl/antlr/VisuAlgParser.g4 index 89bd9be..dc2a32b 100644 --- a/dev.thihup.jvisualg.frontend/src/main/antlr4/dev/thihup/jvisualg/frontend/impl/antlr/VisuAlgParser.g4 +++ b/dev.thihup.jvisualg.frontend/src/main/antlr4/dev/thihup/jvisualg/frontend/impl/antlr/VisuAlgParser.g4 @@ -86,7 +86,7 @@ readCommand : LEIA LPAREN exprList RPAREN; // Write command writeCommand : (ESCREVA | ESCREVAL) (LPAREN writeList? RPAREN)?; writeList : writeItem (COMMA writeItem)*; -writeItem : expr (COLON INT_LITERAL (COLON INT_LITERAL)?)?; +writeItem : expr (COLON expr (COLON expr)?)?; // Conditional commands conditionalCommand : SE expr ENTAO commands FIMSE diff --git a/dev.thihup.jvisualg.frontend/src/main/java/dev/thihup/jvisualg/frontend/VisuAlgParserVisitor.java b/dev.thihup.jvisualg.frontend/src/main/java/dev/thihup/jvisualg/frontend/VisuAlgParserVisitor.java index c64050a..b7a23ac 100644 --- a/dev.thihup.jvisualg.frontend/src/main/java/dev/thihup/jvisualg/frontend/VisuAlgParserVisitor.java +++ b/dev.thihup.jvisualg.frontend/src/main/java/dev/thihup/jvisualg/frontend/VisuAlgParserVisitor.java @@ -139,7 +139,7 @@ public Node visitLiterais(VisuAlgParser.LiteraisContext ctx) { } TerminalNode string = ctx.STRING(); if (string != null) { - return new StringLiteralNode(string.getText(), fromTerminalNode(string)); + return new StringLiteralNode(string.getText().substring(1, string.getText().length() - 1), fromTerminalNode(string)); } TerminalNode real = ctx.REAL_LITERAL(); if (real != null) { @@ -147,7 +147,7 @@ public Node visitLiterais(VisuAlgParser.LiteraisContext ctx) { } TerminalNode inteiro = ctx.INT_LITERAL(); if (inteiro != null) { - return new IntLiteralNode(Integer.parseInt(inteiro.getText()), fromTerminalNode(inteiro)); + return new RealLiteralNode(Integer.parseInt(inteiro.getText()), fromTerminalNode(inteiro)); } throw new RuntimeException("Unknown literal: " + ctx.getText()); } @@ -288,13 +288,11 @@ public Node visitWriteCommand(VisuAlgParser.WriteCommandContext ctx) { @Override public Node visitWriteItem(VisuAlgParser.WriteItemContext ctx) { - Node expr = visit(ctx.expr()); - TerminalNode spaces = ctx.INT_LITERAL(0); - TerminalNode precision = ctx.INT_LITERAL(1); - Node spaces1 = spaces != null ? new IntLiteralNode(Integer.parseInt(spaces.getText()), fromTerminalNode(spaces)) : EmptyNode.INSTANCE; - Node precision1 = precision != null ? new IntLiteralNode(Integer.parseInt(precision.getText()), fromTerminalNode(precision)) : EmptyNode.INSTANCE; + Node expr = visit(ctx.expr(0)); + Node spaces = ctx.expr(1) != null ? visit(ctx.expr(1)) : EmptyNode.INSTANCE; + Node precision = ctx.expr(2) != null ? visit(ctx.expr(2)) : EmptyNode.INSTANCE; - return new WriteItemNode(expr, spaces1, precision1, fromRuleContext(ctx)); + return new WriteItemNode(expr, spaces, precision, fromRuleContext(ctx)); } diff --git a/dev.thihup.jvisualg.frontend/src/main/java/dev/thihup/jvisualg/frontend/node/Node.java b/dev.thihup.jvisualg.frontend/src/main/java/dev/thihup/jvisualg/frontend/node/Node.java index d0a2a9e..1a2ce0a 100644 --- a/dev.thihup.jvisualg.frontend/src/main/java/dev/thihup/jvisualg/frontend/node/Node.java +++ b/dev.thihup.jvisualg.frontend/src/main/java/dev/thihup/jvisualg/frontend/node/Node.java @@ -199,7 +199,10 @@ record ConstantNode(IdNode name, Node value, Optional location) implem } } - sealed interface LiteralNode extends Node { + sealed interface ExpressionNode extends Node { + } + + sealed interface LiteralNode extends ExpressionNode { } record BooleanLiteralNode(boolean value, Optional location) implements LiteralNode { @@ -269,7 +272,7 @@ record AssignmentNode(Node idOrArray, Node expr, Optional location) im } } - record IdNode(String id, Optional location) implements Node { + record IdNode(String id, Optional location) implements ExpressionNode { public IdNode { Objects.requireNonNull(id); Objects.requireNonNull(location); @@ -376,7 +379,7 @@ record ProcedureCallNode(IdNode name, CompundNode args, Optional locat } } - record FunctionCallNode(IdNode name, CompundNode args, Optional location) implements CommandNode { + record FunctionCallNode(IdNode name, CompundNode args, Optional location) implements CommandNode, ExpressionNode { public FunctionCallNode { Objects.requireNonNull(name); Objects.requireNonNull(args); @@ -384,7 +387,7 @@ record FunctionCallNode(IdNode name, CompundNode args, Optional locati } } - sealed interface BinaryNode extends CommandNode { + sealed interface BinaryNode extends CommandNode, ExpressionNode { Node left(); Node right(); @@ -438,7 +441,7 @@ record PowNode(Node left, Node right, Optional location) implements Bi } } - sealed interface BooleanNode extends CommandNode {} + sealed interface BooleanNode extends CommandNode, ExpressionNode {} record AndNode(Node left, Node right, Optional location) implements BooleanNode, BinaryNode { public AndNode { diff --git a/dev.thihup.jvisualg.frontend/src/main/java/module-info.java b/dev.thihup.jvisualg.frontend/src/main/java/module-info.java index 4817463..e651bac 100644 --- a/dev.thihup.jvisualg.frontend/src/main/java/module-info.java +++ b/dev.thihup.jvisualg.frontend/src/main/java/module-info.java @@ -1,7 +1,12 @@ module dev.thihup.jvisualg.frontend { requires org.antlr.antlr4.runtime; - exports dev.thihup.jvisualg.frontend.node to dev.thihup.jvisualg.backend.java, dev.thihup.jvisualg.lsp; - exports dev.thihup.jvisualg.frontend to dev.thihup.jvisualg.lsp; + exports dev.thihup.jvisualg.frontend.node to + dev.thihup.jvisualg.backend.java, + dev.thihup.jvisualg.lsp, + dev.thihup.jvisualg.interpreter; + exports dev.thihup.jvisualg.frontend to + dev.thihup.jvisualg.lsp, + dev.thihup.jvisualg.interpreter; } diff --git a/dev.thihup.jvisualg.interpreter/pom.xml b/dev.thihup.jvisualg.interpreter/pom.xml new file mode 100644 index 0000000..8a95ae7 --- /dev/null +++ b/dev.thihup.jvisualg.interpreter/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + + dev.thihup.jvisualg + jvisualg-parent + 1.0-SNAPSHOT + + + dev.thihup.jvisualg.interpreter + + + + dev.thihup.jvisualg + dev.thihup.jvisualg.frontend + ${project.version} + + + + diff --git a/dev.thihup.jvisualg.interpreter/src/main/java/dev/thihup/jvisualg/interpreter/Interpreter.java b/dev.thihup.jvisualg.interpreter/src/main/java/dev/thihup/jvisualg/interpreter/Interpreter.java new file mode 100644 index 0000000..cdf9c5e --- /dev/null +++ b/dev.thihup.jvisualg.interpreter/src/main/java/dev/thihup/jvisualg/interpreter/Interpreter.java @@ -0,0 +1,234 @@ +package dev.thihup.jvisualg.interpreter; + +import dev.thihup.jvisualg.frontend.ASTResult; +import dev.thihup.jvisualg.frontend.Main; +import dev.thihup.jvisualg.frontend.node.Node; + +import java.io.*; +import java.math.RoundingMode; +import java.text.NumberFormat; +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Scanner; + +public class Interpreter { + + private final Map global = new LinkedHashMap<>(); + private final Reader originalInput; + private final Writer output; + private boolean running = true; + private Scanner input; + + Interpreter(Reader input, Writer output) { + this.originalInput = input; + this.input = new Scanner(input); + this.output = output; + } + + public void run(Node node) { + if (!running) { + return; + } + try { + switch (node) { + case Node.AlgoritimoNode algoritimoNode -> runAlgoritmo(algoritimoNode); + case Node.ArrayTypeNode arrayTypeNode -> throw new UnsupportedOperationException("ArrayTypeNode not implemented"); + case Node.CommandNode commandNode -> runCommand(commandNode); + case Node.CompundNode compundNode -> compundNode.nodes().forEach(this::run); + case Node.ConstantNode constantNode -> throw new UnsupportedOperationException("ConstantNode not implemented"); + case Node.DosNode dosNode -> {} + case Node.EmptyNode emptyNode -> {} + case Node.IdNode idNode -> throw new UnsupportedOperationException("IdNode not implemented"); + case Node.LiteralNode literalNode -> throw new UnsupportedOperationException("LiteralNode not implemented"); + case Node.RangeNode rangeNode -> throw new UnsupportedOperationException("RangeNode not implemented"); + case Node.RegistroDeclarationNode registroDeclarationNode -> throw new UnsupportedOperationException("RegistroDeclarationNode not implemented"); + case Node.SubprogramDeclarationNode subprogramDeclarationNode -> throw new UnsupportedOperationException("SubprogramDeclarationNode not implemented"); + case Node.TypeNode typeNode -> throw new UnsupportedOperationException("TypeNode not implemented"); + case Node.VariableDeclarationNode variableDeclarationNode -> runVariableDeclaration(variableDeclarationNode); + } + } catch (InterruptedException | IOException _) { + running = false; + } + } + + private void runCommand(Node.CommandNode commandNode) throws IOException { + switch (commandNode) { + case Node.AleatorioCommandNode aleatorioCommandNode -> throw new UnsupportedOperationException("AleatorioCommandNode not implemented"); + case Node.ArquivoCommandNode arquivoCommandNode -> throw new UnsupportedOperationException("ArquivoCommandNode not implemented"); + case Node.ArrayAccessNode arrayAccessNode -> throw new UnsupportedOperationException("ArrayAccessNode not implemented"); + case Node.AssignmentNode assignmentNode -> throw new UnsupportedOperationException("AssignmentNode not implemented"); + case Node.BinaryNode binaryNode -> throw new UnsupportedOperationException("BinaryNode not implemented"); + case Node.BooleanNode booleanNode -> throw new UnsupportedOperationException("BooleanNode not implemented"); + case Node.ChooseCaseNode chooseCaseNode -> throw new UnsupportedOperationException("ChooseCaseNode not implemented"); + case Node.ChooseCommandNode chooseCommandNode -> throw new UnsupportedOperationException("ChooseCommandNode not implemented"); + case Node.ConditionalCommandNode conditionalCommandNode -> throw new UnsupportedOperationException("ConditionalCommandNode not implemented"); + case Node.CronometroCommandNode cronometroCommandNode -> throw new UnsupportedOperationException("CronometroCommandNode not implemented"); + case Node.DebugCommandNode debugCommandNode -> throw new UnsupportedOperationException("DebugCommandNode not implemented"); + case Node.EcoCommandNode ecoCommandNode -> throw new UnsupportedOperationException("EcoCommandNode not implemented"); + case Node.ForCommandNode forCommandNode -> runForCommand(forCommandNode); + case Node.FunctionCallNode functionCallNode -> throw new UnsupportedOperationException("FunctionCallNode not implemented"); + case Node.IncrementNode incrementNode -> throw new UnsupportedOperationException("IncrementNode not implemented"); + case Node.InterrompaCommandNode interrompaCommandNode -> throw new UnsupportedOperationException("InterrompaCommandNode not implemented"); + case Node.LimpatelaCommandNode limpatelaCommandNode -> throw new UnsupportedOperationException("LimpatelaCommandNode not implemented"); + case Node.MemberAccessNode memberAccessNode -> throw new UnsupportedOperationException("MemberAccessNode not implemented"); + case Node.NegNode negNode -> throw new UnsupportedOperationException("NegNode not implemented"); + case Node.PausaCommandNode pausaCommandNode -> throw new UnsupportedOperationException("PausaCommandNode not implemented"); + case Node.PosNode posNode -> throw new UnsupportedOperationException("PosNode not implemented"); + case Node.ProcedureCallNode procedureCallNode -> throw new UnsupportedOperationException("ProcedureCallNode not implemented"); + case Node.ReadCommandNode readCommandNode -> runReadCommand(readCommandNode); + case Node.ReturnNode returnNode -> throw new UnsupportedOperationException("ReturnNode not implemented"); + case Node.TimerCommandNode timerCommandNode -> throw new UnsupportedOperationException("TimerCommandNode not implemented"); + case Node.WhileCommandNode whileCommandNode -> throw new UnsupportedOperationException("WhileCommandNode not implemented"); + case Node.WriteCommandNode writeCommandNode -> { + run(writeCommandNode.writeList()); + if (writeCommandNode.newLine()) { + output.write("\n"); + } + output.flush(); + } + case Node.WriteItemNode(Node.ExpressionNode expr, Node spaces, Node precision, _) -> { + Object value = evaluate(expr); + printValue(value, spaces, precision); + } + case Node.WriteItemNode(Node a, _, _, _) -> throw new UnsupportedOperationException("the value to write must be an expression: " + a.getClass()); + } + } + + private void runReadCommand(Node.ReadCommandNode readCommandNode) { + + readCommandNode.exprList().nodes().forEach(expr -> { + + if (expr instanceof Node.IdNode idNode) { + Object o = global.get(idNode.id()); + switch (o) { + case Integer _ when input.hasNextInt() -> global.put(idNode.id(), input.nextInt()); + case Double _ when input.hasNextDouble() -> global.put(idNode.id(), input.nextDouble()); + case String _ when input.hasNextLine() -> global.put(idNode.id(), input.nextLine()); + case Boolean _ when input.hasNextBoolean() -> global.put(idNode.id(), input.nextBoolean()); + default -> throw new UnsupportedOperationException("Unsupported type: " + o.getClass()); + } + } else { + throw new UnsupportedOperationException("Unsupported type: " + expr.getClass()); + } + }); + + } + + private void runForCommand(Node.ForCommandNode forCommandNode) { + Node.IdNode identifier = forCommandNode.identifier(); + if (global.containsKey(identifier.id())) { + switch(forCommandNode) { + case Node.ForCommandNode(Node.IdNode id, Node.ExpressionNode start, Node.ExpressionNode end, Node.ExpressionNode step, Node.CompundNode command, _) -> { + int startValue = ((Number)evaluate(start)).intValue(); + int endValue = ((Number)evaluate(end)).intValue();; + int stepValue = ((Number)evaluate(step)).intValue(); + int i; + for (i = startValue; i <= endValue; i += stepValue) { + global.put(id.id(), i); + run(command); + } + global.put(id.id(), i); + } + default -> throw new UnsupportedOperationException("Unsupported type: " + forCommandNode.getClass()); + } + } + } + + private void printValue(Object value, Node spaces, Node precision) throws IOException { + + int spacesValue = switch (spaces) { + case Node.ExpressionNode e when evaluate(e) instanceof Number p -> p.intValue(); + case Node.EmptyNode _ -> 0; + default -> throw new UnsupportedOperationException("Unsupported type: " + precision.getClass()); + }; + + int precisionValue = switch (precision) { + case Node.ExpressionNode e when evaluate(e) instanceof Number p -> p.intValue(); + case Node.EmptyNode _ -> 0; + default -> throw new UnsupportedOperationException("Unsupported type: " + precision.getClass()); + }; + + NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US); + numberFormat.setRoundingMode(RoundingMode.HALF_UP); + numberFormat.setMaximumFractionDigits(0); + numberFormat.setMinimumFractionDigits(0); + output.write(switch (value) { + case Integer integer when spacesValue >= 2 -> String.format("%s%d", " ".repeat(spacesValue - 1), integer); + case Integer integer -> String.format(" %d", integer); + + case Double doubleValue when spacesValue >= 1 && precisionValue >= 1 -> { + numberFormat.setMinimumFractionDigits(precisionValue); + numberFormat.setMaximumFractionDigits(precisionValue); + yield numberFormat.format(doubleValue); + } + case Double doubleValue when spacesValue >= 1 && precisionValue == 0 -> { + numberFormat.setMaximumFractionDigits(0); + numberFormat.setMinimumFractionDigits(0); + yield " ".repeat(spacesValue - 1) + numberFormat.format(doubleValue); + } + case Double doubleValue -> { + numberFormat.setMinimumFractionDigits(0); + numberFormat.setMaximumFractionDigits(99999); + yield " " + numberFormat.format(doubleValue); + } + + case String string -> spacesValue > 0 ? string.substring(0, spacesValue) : string; + case Boolean bool -> bool ? " VERDADEIRO" : " FALSO"; + default -> throw new UnsupportedOperationException("Unsupported type: " + value.getClass()); + }); + } + + private Object evaluate(Node.ExpressionNode node){ + return switch (node) { + case Node.StringLiteralNode(var value, _) -> value; + case Node.BinaryNode binaryNode -> throw new UnsupportedOperationException("BinaryNode not implemented"); + case Node.BooleanLiteralNode(var value, _) -> value; + case Node.BooleanNode booleanNode -> throw new UnsupportedOperationException("BooleanNode not implemented"); + case Node.FunctionCallNode functionCallNode -> throw new UnsupportedOperationException("FunctionCallNode not implemented"); + case Node.IntLiteralNode(var value, _) -> value; + case Node.RealLiteralNode(var value, _) -> value; + case Node.IdNode idNode -> global.get(idNode.id()); + }; + } + + public void stop() { + running = false; + Thread.currentThread().interrupt(); + } + + private void runAlgoritmo(Node.AlgoritimoNode algoritimoNode) throws InterruptedException { + run(algoritimoNode.declarations()); + run(algoritimoNode.commands()); + } + + private void runVariableDeclaration(Node.VariableDeclarationNode variableDeclarationNode) { + global.put(variableDeclarationNode.name().id(), newInstance(variableDeclarationNode.type())); + } + + private Class getType(Node typeNode) { + return switch (typeNode) { + case Node.TypeNode(Node.StringLiteralNode(var type, _), _) -> switch (type.toLowerCase()) { + case "inteiro" -> Integer.class; + case "real" -> Double.class; + case "caracter" -> String.class; + case "logico" -> Boolean.class; + default -> throw new IllegalStateException("Unexpected value: " + type); + }; + default -> throw new IllegalStateException("Unexpected value: " + typeNode); + }; + } + + private Object newInstance(Node typeNode) { + return switch (typeNode) { + case Node.TypeNode(Node.StringLiteralNode(var type, _), _) -> switch (type.toLowerCase()) { + case "inteiro" -> 0; + case "real" -> 0.0; + case "caracter" -> ""; + case "logico" -> false; + default -> throw new IllegalStateException("Unexpected value: " + type); + }; + default -> throw new IllegalStateException("Unexpected value: " + typeNode); + }; + } +} diff --git a/dev.thihup.jvisualg.interpreter/src/main/java/module-info.java b/dev.thihup.jvisualg.interpreter/src/main/java/module-info.java new file mode 100644 index 0000000..bb845a1 --- /dev/null +++ b/dev.thihup.jvisualg.interpreter/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module dev.thihup.jvisualg.interpreter { + requires dev.thihup.jvisualg.frontend; +} diff --git a/dev.thihup.jvisualg.interpreter/src/test/java/dev/thihup/jvisualg/interpreter/InterpreterTest.java b/dev.thihup.jvisualg.interpreter/src/test/java/dev/thihup/jvisualg/interpreter/InterpreterTest.java new file mode 100644 index 0000000..c0d4135 --- /dev/null +++ b/dev.thihup.jvisualg.interpreter/src/test/java/dev/thihup/jvisualg/interpreter/InterpreterTest.java @@ -0,0 +1,463 @@ +package dev.thihup.jvisualg.interpreter; + +import dev.thihup.jvisualg.frontend.Main; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.io.*; +import java.math.RoundingMode; + +import static org.junit.jupiter.api.Assertions.*; + +class InterpreterTest { + @Test + void test() { + StringWriter stringWriter = new StringWriter(); + new Interpreter(Reader.nullReader(), stringWriter) + .run(Main.buildAST(new ByteArrayInputStream(""" + algoritmo "Teste" + var + a: inteiro + inicio + escreval("Hello, World!", 5) + + escreval(5) + escreval(5.1) + escreval(5.10) + escreval(5.100) + escreval(5.1000) + + escreval(6.12) + escreval(6.125) + escreval(6.1258) + escreval(6.20000) + + para a de 0 ate 10 faca + escreval("VALOR ESPACO", a) + escreval(5 : a) + escreval(5.1 : a) + escreval(5.10 : a) + escreval(5.100 : a) + escreval(5.1000 : a) + + escreval(6.12 : a) + escreval(6.125 : a) + escreval(6.1258 : a) + escreval(6.20000 : a) + + escreval("VALOR ESPACO E PRECISAO", a) + escreval(5 : a : a) + escreval(5.1 : a : a) + escreval(5.10 : a : a) + escreval(5.100 : a : a) + escreval(5.1000 : a : a) + + escreval(6.12 : a : a) + escreval(6.125 : a : a) + escreval(6.1258 : a : a) + escreval(6.20000 : a : a) + + escreval("VALOR ESPACO 0 E PRECISAO", a) + escreval(5 : 0 : a) + escreval(5.1 : 0 : a) + escreval(5.10 : 0 : a) + escreval(5.100 : 0 : a) + escreval(5.1000 : 0 : a) + + escreval(6.12 : 0 : a) + escreval(6.125 : 0 : a) + escreval(6.1258 : 0 : a) + escreval(6.20000 : 0 : a) + fimpara + + escreval(verdadeiro) + escreval(falso) + escreval(a) + fimalgoritmo + """.getBytes())).node().get()); + assertEquals( + """ + Hello, World! 5 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 0 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO E PRECISAO 0 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 0 E PRECISAO 0 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 1 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 1 + 5.0 + 5.1 + 5.1 + 5.1 + 5.1 + 6.1 + 6.1 + 6.1 + 6.2 + VALOR ESPACO 0 E PRECISAO 1 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 2 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 2 + 5.00 + 5.10 + 5.10 + 5.10 + 5.10 + 6.12 + 6.13 + 6.13 + 6.20 + VALOR ESPACO 0 E PRECISAO 2 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 3 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 3 + 5.000 + 5.100 + 5.100 + 5.100 + 5.100 + 6.120 + 6.125 + 6.126 + 6.200 + VALOR ESPACO 0 E PRECISAO 3 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 4 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 4 + 5.0000 + 5.1000 + 5.1000 + 5.1000 + 5.1000 + 6.1200 + 6.1250 + 6.1258 + 6.2000 + VALOR ESPACO 0 E PRECISAO 4 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 5 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 5 + 5.00000 + 5.10000 + 5.10000 + 5.10000 + 5.10000 + 6.12000 + 6.12500 + 6.12580 + 6.20000 + VALOR ESPACO 0 E PRECISAO 5 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 6 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 6 + 5.000000 + 5.100000 + 5.100000 + 5.100000 + 5.100000 + 6.120000 + 6.125000 + 6.125800 + 6.200000 + VALOR ESPACO 0 E PRECISAO 6 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 7 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 7 + 5.0000000 + 5.1000000 + 5.1000000 + 5.1000000 + 5.1000000 + 6.1200000 + 6.1250000 + 6.1258000 + 6.2000000 + VALOR ESPACO 0 E PRECISAO 7 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 8 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 8 + 5.00000000 + 5.10000000 + 5.10000000 + 5.10000000 + 5.10000000 + 6.12000000 + 6.12500000 + 6.12580000 + 6.20000000 + VALOR ESPACO 0 E PRECISAO 8 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 9 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 9 + 5.000000000 + 5.100000000 + 5.100000000 + 5.100000000 + 5.100000000 + 6.120000000 + 6.125000000 + 6.125800000 + 6.200000000 + VALOR ESPACO 0 E PRECISAO 9 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VALOR ESPACO 10 + 5 + 5 + 5 + 5 + 5 + 6 + 6 + 6 + 6 + VALOR ESPACO E PRECISAO 10 + 5.0000000000 + 5.1000000000 + 5.1000000000 + 5.1000000000 + 5.1000000000 + 6.1200000000 + 6.1250000000 + 6.1258000000 + 6.2000000000 + VALOR ESPACO 0 E PRECISAO 10 + 5 + 5.1 + 5.1 + 5.1 + 5.1 + 6.12 + 6.125 + 6.1258 + 6.2 + VERDADEIRO + FALSO + 11 + """, stringWriter.toString()); + } + + @Test + void testRead() { + StringWriter stringWriter = new StringWriter(); + StringReader stringReader = new StringReader("5\n") { + @Override + public int read() throws IOException { + int read = super.read(); + stringWriter.write(read); + return read; + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + int read = super.read(cbuf, off, len); + stringWriter.write(cbuf, off, read); + return read; + } + }; + + new Interpreter(stringReader, stringWriter) + .run(Main.buildAST(new ByteArrayInputStream(""" + algoritmo "Teste" + var + a: inteiro + inicio + escreva("Number: ") + leia(a) + escreval(a) + fimalgoritmo + """.getBytes())).node().get()); + assertEquals( + """ + Number: 5 + 5 + """, stringWriter.toString()); + } +} diff --git a/pom.xml b/pom.xml index e35f676..d5f2ab7 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ dev.thihup.jvisualg.backend dev.thihup.jvisualg.lsp dev.thihup.jvisualg.ide + dev.thihup.jvisualg.interpreter