fixed lab6 + report
This commit is contained in:
24
src/ast_parser/BinaryOperatorExpr.java
Normal file
24
src/ast_parser/BinaryOperatorExpr.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package ast_parser;
|
||||
|
||||
class BinaryOperatorExpr extends Expr {
|
||||
Expr left;
|
||||
Expr right;
|
||||
char operator;
|
||||
|
||||
BinaryOperatorExpr(Expr left, Expr right, char operator) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
double evaluate() {
|
||||
return switch (operator) {
|
||||
case '+' -> left.evaluate() + right.evaluate();
|
||||
case '-' -> left.evaluate() - right.evaluate();
|
||||
case '*' -> left.evaluate() * right.evaluate();
|
||||
case '/' -> left.evaluate() / right.evaluate();
|
||||
default -> throw new RuntimeException("Unsupported operator: " + operator);
|
||||
};
|
||||
}
|
||||
}
|
||||
5
src/ast_parser/Expr.java
Normal file
5
src/ast_parser/Expr.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package ast_parser;
|
||||
|
||||
abstract class Expr {
|
||||
abstract double evaluate();
|
||||
}
|
||||
50
src/ast_parser/FunctionExpr.java
Normal file
50
src/ast_parser/FunctionExpr.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package ast_parser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class FunctionExpr extends Expr {
|
||||
String function;
|
||||
List<Expr> arguments;
|
||||
|
||||
FunctionExpr(String function, List<Expr> arguments) {
|
||||
this.function = function;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
double evaluate() {
|
||||
return switch (function) {
|
||||
case "sqrt" -> {
|
||||
if (arguments.size() != 1) {
|
||||
throw new RuntimeException("sqrt expects exactly one argument");
|
||||
}
|
||||
yield Math.sqrt(arguments.get(0).evaluate());
|
||||
}
|
||||
case "logtwo" -> {
|
||||
if (arguments.size() != 1) {
|
||||
throw new RuntimeException("log2 expects exactly one argument");
|
||||
}
|
||||
yield Math.log(arguments.get(0).evaluate()) / Math.log(2);
|
||||
}
|
||||
case "logten" -> {
|
||||
if (arguments.size() != 1) {
|
||||
throw new RuntimeException("log10 expects exactly one argument");
|
||||
}
|
||||
yield Math.log10(arguments.get(0).evaluate());
|
||||
}
|
||||
case "loge" -> {
|
||||
if (arguments.size() != 1) {
|
||||
throw new RuntimeException("loge expects exactly one argument");
|
||||
}
|
||||
yield Math.log(arguments.get(0).evaluate());
|
||||
}
|
||||
case "powtwo" -> {
|
||||
if (arguments.size() != 1) {
|
||||
throw new RuntimeException("pow2 expects exactly one argument");
|
||||
}
|
||||
yield Math.pow(2, arguments.get(0).evaluate());
|
||||
}
|
||||
default -> throw new RuntimeException("Unsupported function or wrong number of arguments: " + function);
|
||||
};
|
||||
}
|
||||
}
|
||||
51
src/ast_parser/Lexer.java
Normal file
51
src/ast_parser/Lexer.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package ast_parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Lexer {
|
||||
public static List<Token> tokenize(String input) {
|
||||
List<Token> tokens = new ArrayList<>();
|
||||
input = input.replaceAll("\\s", "");
|
||||
int i = 0;
|
||||
while (i < input.length()) {
|
||||
char ch = input.charAt(i);
|
||||
if (Character.isDigit(ch)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (i < input.length() && (Character.isDigit(input.charAt(i)) || input.charAt(i) == '.')) {
|
||||
sb.append(input.charAt(i));
|
||||
i++;
|
||||
}
|
||||
tokens.add(new Token(TokenType.NUMBER, sb.toString()));
|
||||
} else if (Character.isLetter(ch)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (i < input.length() && Character.isLetter(input.charAt(i))) {
|
||||
sb.append(input.charAt(i));
|
||||
i++;
|
||||
}
|
||||
tokens.add(new Token(TokenType.FUNCTION, sb.toString()));
|
||||
} else {
|
||||
switch (ch) {
|
||||
case '(':
|
||||
tokens.add(new Token(TokenType.LPAREN, "("));
|
||||
i++;
|
||||
break;
|
||||
case ')':
|
||||
tokens.add(new Token(TokenType.RPAREN, ")"));
|
||||
i++;
|
||||
break;
|
||||
case ',':
|
||||
tokens.add(new Token(TokenType.COMMA, ","));
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
tokens.add(new Token(TokenType.OPERATOR, String.valueOf(ch)));
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
tokens.add(new Token(TokenType.EOF, ""));
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
17
src/ast_parser/MainParser.java
Normal file
17
src/ast_parser/MainParser.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package ast_parser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MainParser {
|
||||
public static void main(String[] args) {
|
||||
String input = "(3 + 5) * sqrt(16) + powtwo(5)";
|
||||
List<Token> tokens = Lexer.tokenize(input);
|
||||
System.out.println("Tokens:");
|
||||
tokens.forEach(System.out::println);
|
||||
|
||||
Parser parser = new Parser(tokens);
|
||||
Expr expression = parser.parse();
|
||||
double result = expression.evaluate();
|
||||
System.out.println("Result: " + result);
|
||||
}
|
||||
}
|
||||
14
src/ast_parser/NumberExpr.java
Normal file
14
src/ast_parser/NumberExpr.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package ast_parser;
|
||||
|
||||
class NumberExpr extends Expr {
|
||||
double value;
|
||||
|
||||
NumberExpr(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
double evaluate() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
78
src/ast_parser/Parser.java
Normal file
78
src/ast_parser/Parser.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package ast_parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Parser {
|
||||
private final List<Token> tokens;
|
||||
private int current = 0;
|
||||
|
||||
public Parser(List<Token> tokens) {
|
||||
this.tokens = tokens;
|
||||
}
|
||||
|
||||
public Expr parse() {
|
||||
return expression();
|
||||
}
|
||||
|
||||
private Expr expression() {
|
||||
Expr expr = term();
|
||||
while (match(TokenType.OPERATOR)) {
|
||||
char operator = tokens.get(current - 1).value.charAt(0);
|
||||
Expr right = term();
|
||||
expr = new BinaryOperatorExpr(expr, right, operator);
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
private Expr term() {
|
||||
if (match(TokenType.NUMBER)) {
|
||||
return new NumberExpr(Double.parseDouble(previous().value));
|
||||
} else if (match(TokenType.LPAREN)) {
|
||||
Expr expr = expression();
|
||||
consume(TokenType.RPAREN, "Expect ')' after expression.");
|
||||
return expr;
|
||||
} else if (match(TokenType.FUNCTION)) {
|
||||
String functionName = previous().value;
|
||||
consume(TokenType.LPAREN, "Expect '(' after function name.");
|
||||
List<Expr> args = new ArrayList<>();
|
||||
if (!check(TokenType.RPAREN)) {
|
||||
do {
|
||||
args.add(expression());
|
||||
} while (match(TokenType.COMMA));
|
||||
}
|
||||
consume(TokenType.RPAREN, "Expect ')' after arguments.");
|
||||
return new FunctionExpr(functionName, args);
|
||||
}
|
||||
throw new RuntimeException("Unexpected token.");
|
||||
}
|
||||
|
||||
private boolean match(TokenType type) {
|
||||
if (check(type)) {
|
||||
current++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean check(TokenType type) {
|
||||
if (isAtEnd()) return false;
|
||||
return tokens.get(current).type == type;
|
||||
}
|
||||
|
||||
private Token previous() {
|
||||
return tokens.get(current - 1);
|
||||
}
|
||||
|
||||
private void consume(TokenType type, String message) {
|
||||
if (check(type)) {
|
||||
current++;
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
|
||||
private boolean isAtEnd() {
|
||||
return current >= tokens.size() || tokens.get(current).type == TokenType.EOF;
|
||||
}
|
||||
}
|
||||
16
src/ast_parser/Token.java
Normal file
16
src/ast_parser/Token.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package ast_parser;
|
||||
|
||||
public class Token {
|
||||
public TokenType type;
|
||||
public String value;
|
||||
|
||||
public Token(TokenType type, String value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type + " : " + value;
|
||||
}
|
||||
}
|
||||
11
src/ast_parser/TokenType.java
Normal file
11
src/ast_parser/TokenType.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package ast_parser;
|
||||
|
||||
public enum TokenType {
|
||||
NUMBER,
|
||||
OPERATOR,
|
||||
LPAREN,
|
||||
RPAREN,
|
||||
FUNCTION,
|
||||
COMMA,
|
||||
EOF
|
||||
}
|
||||
BIN
src/reports/lab_five.pdf
Normal file
BIN
src/reports/lab_five.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user