Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // PARSER
- import java.io.IOException;
- import java.io.PushbackReader;
- import java.io.StringReader;
- public class Parser {
- public AST parse(String str) throws IOException {
- try (PushbackReader reader = new PushbackReader(new StringReader(str))) {
- AST ast = parse(reader);
- String rest = peek(reader);
- if (rest != null)
- throw new RuntimeException("Unexpected tokens: " + rest);
- return ast;
- }
- }
- private AST parse(PushbackReader reader) throws IOException {
- String token = nextToken(reader);
- if (")".equals(token) || "".equals(token))
- throw new RuntimeException("Unbalanced parenthesis");
- if ("(".equals(token)) {
- AST list = new AST(token);
- while (!")".equals(peek(reader)))
- list.add(parse(reader));
- nextToken(reader); // skip )
- return list;
- }
- return new AST(token); // atom
- }
- private String nextToken(PushbackReader reader) throws IOException {
- String chr = peek(reader);
- return "(".equals(chr) || ")".equals(chr)
- ? String.valueOf((char) reader.read())
- : nextAtom(reader);
- }
- private String nextAtom(PushbackReader reader) throws IOException {
- StringBuilder buffer = new StringBuilder();
- int chr = reader.read();
- while (chr != -1 && !Character.isWhitespace(chr) && ')' != chr) {
- buffer.append((char)chr);
- chr = reader.read();
- }
- if (chr == ')')
- reader.unread(')');
- return buffer.toString();
- }
- private String peek(PushbackReader reader) throws IOException {
- int chr = reader.read();
- while (chr != -1 && Character.isWhitespace(chr))
- chr = reader.read();
- if (chr == -1)
- return null;
- reader.unread(chr);
- return String.valueOf((char) chr);
- }
- }
- // AST
- import java.util.ArrayList;
- import java.util.List;
- public class AST {
- private final List<AST> children = new ArrayList<>();
- private final String token;
- public AST(String token) {
- this.token = token;
- }
- public void add(AST child) {
- children.add(child);
- }
- public String token() {
- return token;
- }
- public Double numValue() {
- return Double.parseDouble(token);
- }
- public boolean boolValue() {
- System.out.println("Token: " + token);
- return Boolean.parseBoolean(token);
- }
- public boolean isAtom() {
- return children.isEmpty();
- }
- public AST head() {
- return children.get(0);
- }
- public List<AST> tail() {
- return children.subList(1, children.size());
- }
- @Override
- public String toString() {
- return isAtom() ? token : children.toString();
- }
- }
- // INTERPRETER
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import static java.util.stream.Collectors.toList;
- public class Interpreter {
- private final Map<String, Func> functions = new HashMap<>();
- private final Map<String, SpecialForm> specialForms = new HashMap<>();
- public interface Func {
- Object call(List<Object> parameters);
- }
- public interface SpecialForm {
- Object call(List<AST> parameters);
- }
- public Interpreter() {
- addFunction("=", args -> args.get(0).equals(args.get(1)));
- addFunction("+", args -> (Double) args.get(0) + (Double) args.get(1));
- addFunction("-", args -> (Double) args.get(0) - (Double) args.get(1));
- addFunction("*", args -> (Double) args.get(0) * (Double) args.get(1));
- addFunction("/", args -> (Double) args.get(0) / (Double) args.get(1));
- addFunction("not", args -> !(boolean) args.get(0));
- addSpecialForm("or", args -> args.stream().anyMatch(each -> (boolean)eval(each)));
- addSpecialForm("and", args -> args.stream().allMatch(each -> (boolean)eval(each)));
- addSpecialForm("if", args -> (boolean) eval(args.get(0))
- ? eval(args.get(1))
- : (args.size() > 2 ? eval(args.get(2)) : null));
- }
- public void addFunction(String name, Func func) {
- functions.put(name, func);
- }
- public void addSpecialForm(String name, SpecialForm func) {
- specialForms.put(name, func);
- }
- public Object eval(AST ast) {
- if (ast.isAtom()) {
- try {
- return ast.numValue();
- } catch (NumberFormatException e) {
- return ast.boolValue();
- }
- }
- SpecialForm specialForm = specialForms.get(ast.head().token());
- if (specialForm != null) {
- return specialForm.call(ast.tail());
- }
- Func func = functions.get(ast.head().token());
- if (func == null)
- throw new RuntimeException("Unknown function: " + ast.head().token());
- return func.call(ast.tail().stream().map(this::eval).collect(toList()));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment