Skip to content

Commit 849f956

Browse files
authored
Merge pull request #5 from Pyrokines17/lab2
Lab2
2 parents ae2ef51 + d9ddf87 commit 849f956

42 files changed

Lines changed: 890 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎lab2/.gitignore‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
target/
2+
!.mvn/wrapper/maven-wrapper.jar
3+
!**/src/main/**/target/
4+
!**/src/test/**/target/
5+
6+
### IntelliJ IDEA ###
7+
.idea/modules.xml
8+
.idea/jarRepositories.xml
9+
.idea/compiler.xml
10+
.idea/libraries/
11+
*.iws
12+
*.iml
13+
*.ipr
14+
15+
### Eclipse ###
16+
.apt_generated
17+
.classpath
18+
.factorypath
19+
.project
20+
.settings
21+
.springBeans
22+
.sts4-cache
23+
24+
### NetBeans ###
25+
/nbproject/private/
26+
/nbbuild/
27+
/dist/
28+
/nbdist/
29+
/.nb-gradle/
30+
build/
31+
!**/src/main/**/build/
32+
!**/src/test/**/build/
33+
34+
### VS Code ###
35+
.vscode/
36+
37+
### Mac OS ###
38+
.DS_Store

‎lab2/pom.xml‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>ru.nsu.gunko</groupId>
8+
<artifactId>lab2</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<properties>
12+
<maven.compiler.source>17</maven.compiler.source>
13+
<maven.compiler.target>17</maven.compiler.target>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
</properties>
16+
<dependencies>
17+
<dependency>
18+
<groupId>org.junit.jupiter</groupId>
19+
<artifactId>junit-jupiter</artifactId>
20+
<version>RELEASE</version>
21+
<scope>test</scope>
22+
</dependency>
23+
</dependencies>
24+
25+
</project>

‎lab2/readme.md‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
# Задача 2. Стековый калькулятор
3+
4+
Написать стековый калькулятор, который принимает в качестве аргумента командой строки имя файла, содержащего команды. Если аргумента нет, то использовать стандартный поток ввода для чтения команд. Использовать вещественные числа.
5+
6+
Реализовать следующий набор команд:
7+
1. `#` - строка с комментарием.
8+
2. `POP, PUSH` - снять/положить число со/на стек(а).
9+
3. `+ , - , * , /, SQRT` - арифметические операции. Используют один или два верхних элемента стека, изымают их из стека, помещая результат назад.
10+
4. `PRINT` - печать верхнего элемента стека (без удаления).
11+
5. `DEFINE` - задать значение параметра. В дальнейшем везде использовать вместо параметра это значение.
12+
13+
Пример (должно вывести 2):
14+
```
15+
DEFINE a 4
16+
PUSH a
17+
SQRT
18+
PRINT
19+
```
20+
21+
## Технические требования
22+
23+
1. Создание команд реализуйте с помощью шаблона проектирования [«фабричный метод»](https://ru.wikipedia.org/wiki/%D0%A4%D0%B0%D0%B1%D1%80%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)). Реализация команд не зависит от остальной системы. Остальной код работает только с фабрикой команд и интерфейсами, про конкретные команды ничего не знает.
24+
2. Разбор текстового файла с командами и их аргументами реализуйте отдельным классом, который не зависит от остальной системы.
25+
3. Загрузку классов команд при создании в фабрике осуществляйте по полному квалифицированному имени класса (включая имя пакета) посредством `Class.forName()` с последующим созданием объектов команд методом `Class.newInstance()`. Фабрика конфигурируется с помощью файла содержащего соответствия между именами команд и классами, реализующими эти команды. Зависимости фабрики от конкретных классов команд (кроме корневого-абстрактного) быть не должно. Файл конфигурации должен храниться рядом с файлом класса-фабрики.
26+
4. Содержимое стека и именованные параметры передавать команде в виде специального объекта - контекста исполнения. При желании, аргументы команды тоже можно брать из контекста.
27+
5. Разработать иерархию исключений, которые будут выбрасывать команды при исполнении. В случае возникновения исключения — выводить информацию об ошибке
28+
и продолжать исполнение программы (из файла или команд вводимых с консоли).
29+
6. Напишите тесты с использованием JUnit (см. [шаблон проекта](https://github.com/dsavenko/nsu-oop-java-template/tree/master/testlab)).
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package ru.nsu.gunko;
2+
3+
import java.util.*;
4+
5+
public class ArgsParser {
6+
List<String> result;
7+
8+
public ArgsParser() {
9+
result = new ArrayList<>();
10+
}
11+
12+
public List<String> parse(List<String> args) {
13+
if (args.isEmpty()) {
14+
result.add("none");
15+
result.add("base");
16+
} else if (args.size() == 1) {
17+
if (args.get(0).equals("base") || args.get(0).equals("add")) {
18+
result.add("none");
19+
result.add(args.get(0));
20+
} else {
21+
result.add(args.get(0));
22+
result.add("base");
23+
}
24+
} else if (args.size() == 2) {
25+
if (args.get(0).equals("base") || args.get(0).equals("add")) {
26+
result.add(args.get(1));
27+
result.add(args.get(0));
28+
} else {
29+
result.add(args.get(0));
30+
result.add(args.get(1));
31+
}
32+
}
33+
return result;
34+
}
35+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package ru.nsu.gunko;
2+
3+
import java.io.*;
4+
import java.util.*;
5+
6+
public class CommandReader {
7+
private final BufferedReader bufReader;
8+
9+
public CommandReader(BufferedReader newReader) {
10+
bufReader = newReader;
11+
}
12+
13+
public List<List<String>> getCommands() throws IOException {
14+
String line;
15+
List<List<String>> res = new ArrayList<>();
16+
17+
while ((line = bufReader.readLine()) != null) {
18+
String[] sepStr = line.split("\\s+");
19+
res.add(new ArrayList<>(Arrays.asList(sepStr)));
20+
}
21+
22+
return res;
23+
}
24+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package ru.nsu.gunko;
2+
3+
import java.util.*;
4+
5+
public class Context {
6+
private final Stack<Double> stack;
7+
private final Map<String, Double> map;
8+
private final List<String> arguments;
9+
10+
public Context() {
11+
stack = new Stack<>();
12+
map = new HashMap<>();
13+
arguments = new ArrayList<>();
14+
}
15+
16+
public Stack<Double> getStack() {
17+
return stack;
18+
}
19+
20+
public Map<String, Double> getMap() {
21+
return map;
22+
}
23+
24+
public List<String> getArguments() {
25+
return arguments;
26+
}
27+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package ru.nsu.gunko;
2+
3+
import ru.nsu.gunko.factory.commands.Operation;
4+
import ru.nsu.gunko.factory.exceptions.*;
5+
import ru.nsu.gunko.factory.*;
6+
7+
import java.io.*;
8+
import java.util.*;
9+
10+
public class Main {
11+
public static void main(String[] args) {
12+
List<List<String>> commands = new ArrayList<>();
13+
Context context = new Context();
14+
ArgsParser argsParser = new ArgsParser();
15+
16+
List<String> list = argsParser.parse(Arrays.asList(args));
17+
18+
if (!list.get(0).equals("none")) {
19+
try (BufferedReader br = new BufferedReader(new FileReader(list.get(0)))) {
20+
CommandReader cr = new CommandReader(br);
21+
commands = cr.getCommands();
22+
} catch (IOException e) {
23+
System.err.println("Error while reading commands: " + e.getLocalizedMessage());
24+
}
25+
} else {
26+
Scanner in = new Scanner(System.in);
27+
String line = in.nextLine();
28+
29+
while (!line.isEmpty()) {
30+
String[] sepStr = line.split("\\s+");
31+
commands.add(new ArrayList<>(Arrays.asList(sepStr)));
32+
line = in.nextLine();
33+
}
34+
}
35+
36+
try {
37+
Factory factory;
38+
39+
if (list.get(1).equals("base")) {
40+
factory = new BaseFactory();
41+
} else {
42+
Factory base = new BaseFactory();
43+
factory = new AddFactory(base);
44+
}
45+
46+
for (List<String> command : commands) {
47+
try {
48+
Operation operation = factory.getOperation(command);
49+
50+
if (command.size() > 1) {
51+
context.getArguments().addAll(command.subList(1, command.size()));
52+
}
53+
54+
operation.perform(context);
55+
} catch (EmptyStackException e) {
56+
System.err.println("Can't do perform (empty stack): " + command.get(0));
57+
} catch (DefineNotFoundException | NotEnoughParamException e) {
58+
System.err.println("Error while do perform: " + e.getLocalizedMessage());
59+
} catch (NameOfClassNotFoundException e) {
60+
System.err.println("Error while finding operation: " + e.getLocalizedMessage());
61+
} catch (BadCreatingException e) {
62+
System.err.println("Error while creating operation: " + e.getLocalizedMessage());
63+
}
64+
65+
if (!context.getArguments().isEmpty()) {
66+
context.getArguments().clear();
67+
}
68+
}
69+
} catch (IOException e) {
70+
System.err.println("Error while creating factory: " + e.getLocalizedMessage());
71+
}
72+
}
73+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package ru.nsu.gunko.factory;
2+
3+
import ru.nsu.gunko.factory.commands.Operation;
4+
5+
import java.util.*;
6+
7+
public class AddFactory implements Factory {
8+
private final Factory factory;
9+
private final Map<String, Operation> map;
10+
11+
public AddFactory(Factory newFactory) {
12+
factory = newFactory;
13+
map = new HashMap<>();
14+
}
15+
16+
@Override
17+
public Operation getOperation(List<String> command) {
18+
if (!map.containsKey(command.get(0))) {
19+
Operation operation = factory.getOperation(command);
20+
map.put(command.get(0), operation);
21+
return operation;
22+
} else {
23+
return map.get(command.get(0));
24+
}
25+
}
26+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package ru.nsu.gunko.factory;
2+
3+
import ru.nsu.gunko.factory.commands.Operation;
4+
import ru.nsu.gunko.factory.exceptions.*;
5+
6+
import java.io.*;
7+
import java.util.*;
8+
9+
public class BaseFactory implements Factory {
10+
private final Map<String, String> arrOfClass;
11+
12+
public BaseFactory() throws IOException {
13+
arrOfClass = this.getMap();
14+
}
15+
16+
@Override
17+
public Operation getOperation(List<String> command) {
18+
String nameOfClass;
19+
20+
if (arrOfClass.containsKey(command.get(0))) {
21+
nameOfClass = arrOfClass.get(command.get(0));
22+
} else {
23+
throw new NameOfClassNotFoundException(command.get(0));
24+
}
25+
26+
Operation operation;
27+
28+
try {
29+
operation = (Operation) Class.forName(nameOfClass).newInstance();
30+
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
31+
throw new BadCreatingException(command.get(0), e);
32+
}
33+
34+
return operation;
35+
}
36+
37+
private Map<String, String> getMap() throws IOException {
38+
Map<String, String> map = new HashMap<>();
39+
String line;
40+
41+
try (InputStream is = this.getClass().getResourceAsStream("/Conf");
42+
InputStreamReader isr = new InputStreamReader(is);
43+
BufferedReader br = new BufferedReader(isr)
44+
) {
45+
while ((line = br.readLine()) != null) {
46+
String[] sepStr = line.split("\\s+");
47+
map.put(sepStr[0], sepStr[1]);
48+
}
49+
}
50+
51+
return map;
52+
}
53+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package ru.nsu.gunko.factory;
2+
3+
import ru.nsu.gunko.factory.commands.Operation;
4+
5+
import java.util.List;
6+
7+
public interface Factory {
8+
Operation getOperation(List<String> command);
9+
}

0 commit comments

Comments
 (0)