Guest User

Untitled

a guest
Jul 12th, 2024
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.10 KB | None | 0 0
  1. import java.util.ArrayList;
  2. import java.util.List;
  3.  
  4. public class AST {
  5.   private final List<AST> children = new ArrayList<>();
  6.   private final String token;
  7.  
  8.   public AST(String token) {
  9.     this.token = token;
  10.   }
  11.  
  12.   public void add(AST child) {
  13.     children.add(child);
  14.   }
  15.  
  16.   public String token() {
  17.     return token;
  18.   }
  19.  
  20.   public Double numValue() {
  21.     return Double.parseDouble(token);
  22.   }
  23.  
  24.   public boolean boolValue() {
  25.     if (token.equals("true") || token.equals("false"))
  26.       return Boolean.parseBoolean(token);
  27.     else
  28.       throw new IllegalArgumentException("not a boolean: " + token());
  29.   }
  30.  
  31.   public boolean isAtom() {
  32.     return children.isEmpty();
  33.   }
  34.  
  35.   public AST head() {
  36.     return children.get(0);
  37.   }
  38.  
  39.   public List<AST> tail() {
  40.     return children.subList(1, children.size());
  41.   }
  42.  
  43.   public int size() {
  44.     return children.size();
  45.   }
  46.  
  47.   public AST at(int i) {
  48.     return children.get(i);
  49.   }
  50.  
  51.   @Override
  52.   public String toString() {
  53.     return isAtom() ? token : children.toString();
  54.   }
  55. }
  56. //////////
  57. import java.util.HashMap;
  58. import java.util.Map;
  59.  
  60. public class Environment {
  61.   private final Map<String, Object> vars = new HashMap<>();
  62.   private final Environment parent;
  63.  
  64.   public Environment(Environment parent) {
  65.     this.parent = parent;
  66.   }
  67.  
  68.   public Object put(String key, Object value) {
  69.     return vars.put(key, value);
  70.   }
  71.  
  72.   public Object at(String key) {
  73.     if (vars.containsKey(key))
  74.       return vars.get(key);
  75.     else if (parent != null)
  76.       return parent.at(key);
  77.     else
  78.       return null;
  79.   }
  80. }
  81. //////////
  82. import java.util.HashMap;
  83. import java.util.List;
  84. import java.util.Map;
  85. import static java.util.stream.Collectors.toList;
  86.  
  87. public class Interpreter {
  88.   private final Map<String, SpecialForm> specialForms = new HashMap<>();
  89.   private final Environment environment = new Environment(null);
  90.  
  91.   public interface Func {
  92.     Object call(List<Object> parameters);
  93.   }
  94.  
  95.   public interface SpecialForm {
  96.     Object call(Environment env, List<AST> parameters);
  97.   }
  98.  
  99.   public Interpreter() {
  100.     addSpecialForm("lambda", this::lambda);
  101.     addSpecialForm("or", (env, args) -> args.stream().anyMatch(each -> (boolean)eval(env, each)));
  102.     addSpecialForm("and", (env, args) -> args.stream().allMatch(each -> (boolean)eval(env, each)));
  103.     addSpecialForm("if", (env, args) -> (boolean) eval(env, args.get(0))
  104.               ? eval(env, args.get(1))
  105.               : (args.size() > 2 ? eval(env, args.get(2)) : null));
  106.     addSpecialForm("define", (env, args) -> env.put(args.get(0).token(), eval(env, args.get(1))));
  107.     environment.put("=", (Func) args -> args.get(0).equals(args.get(1)));
  108.     environment.put("+", (Func) args -> (Double) args.get(0) + (Double) args.get(1));
  109.     environment.put("-", (Func) args -> (Double) args.get(0) - (Double) args.get(1));
  110.     environment.put("*", (Func) args -> (Double) args.get(0) * (Double) args.get(1));
  111.     environment.put("/", (Func) args -> (Double) args.get(0) / (Double) args.get(1));
  112.     environment.put("not", (Func) args -> !(boolean) args.get(0));
  113.   }
  114.  
  115.   private Object lambda(Environment parent, List<AST> lambda) {
  116.     AST paramNames = lambda.get(0);
  117.     AST lambdaBody = lambda.get(1);
  118.     return (Func) arguments -> {
  119.       Environment env = new Environment(parent);
  120.       for (int i = 0; i < paramNames.size(); i++)
  121.         env.put(paramNames.at(i).token(), arguments.get(i));
  122.       return eval(env, lambdaBody);
  123.     };
  124.   }
  125.  
  126.   public void addSpecialForm(String name, SpecialForm func) {
  127.     specialForms.put(name, func);
  128.   }
  129.  
  130.   public Object eval(AST ast) {
  131.     return eval(environment, ast);
  132.   }
  133.  
  134.   private Object eval(Environment env, AST ast) {
  135.     if (ast.isAtom())
  136.       return evalAtom(env, ast);
  137.     SpecialForm specialForm = specialForms.get(ast.head().token());
  138.     if (specialForm != null)
  139.       return specialForm.call(env, ast.tail());
  140.     Func func = (Func) eval(env, ast.head());
  141.     return func.call(ast.tail().stream().map(a -> eval(env, a)).collect(toList()));
  142.   }
  143.  
  144.   private static Object evalAtom(Environment env, AST ast) {
  145.     try {
  146.       return ast.numValue();
  147.     } catch (NumberFormatException e) {
  148.       try {
  149.         return ast.boolValue();
  150.       } catch (IllegalArgumentException ie) {
  151.         return env.at(ast.token());
  152.       }
  153.     }
  154.   }
  155. }
  156. /////////
  157. import java.io.IOException;
  158. import java.io.PushbackReader;
  159. import java.io.StringReader;
  160.  
  161. public class Parser {
  162.   public AST parse(String str) throws IOException {
  163.     try (PushbackReader reader = new PushbackReader(new StringReader(str))) {
  164.       AST ast = parse(reader);
  165.       String rest = peek(reader);
  166.       if (rest != null)
  167.         throw new RuntimeException("Unexpected tokens: " + rest);
  168.       return ast;
  169.     }
  170.   }
  171.  
  172.   private AST parse(PushbackReader reader) throws IOException {
  173.     String token = nextToken(reader);
  174.     if (")".equals(token) || "".equals(token))
  175.       throw new RuntimeException("Unbalanced parenthesis");
  176.     if ("(".equals(token)) {
  177.       AST list = new AST(token);
  178.       while (!")".equals(peek(reader)))
  179.         list.add(parse(reader));
  180.       nextToken(reader); // skip )
  181.       return list;
  182.     }
  183.     return new AST(token); // atom
  184.   }
  185.  
  186.   private String nextToken(PushbackReader reader) throws IOException {
  187.     String chr = peek(reader);
  188.     return "(".equals(chr) || ")".equals(chr)
  189.             ? String.valueOf((char) reader.read())
  190.             : nextAtom(reader);
  191.   }
  192.  
  193.   private String nextAtom(PushbackReader reader) throws IOException {
  194.     StringBuilder buffer = new StringBuilder();
  195.     int chr = reader.read();
  196.     while (chr != -1 && !Character.isWhitespace(chr) && ')' != chr) {
  197.       buffer.append((char)chr);
  198.       chr = reader.read();
  199.     }
  200.     if (chr == ')')
  201.       reader.unread(')');
  202.     return buffer.toString();
  203.   }
  204.  
  205.   private String peek(PushbackReader reader) throws IOException {
  206.     int chr = reader.read();
  207.     while (chr != -1 && Character.isWhitespace(chr))
  208.       chr = reader.read();
  209.     if (chr == -1)
  210.       return null;
  211.     reader.unread(chr);
  212.     return String.valueOf((char) chr);
  213.   }
  214. }
  215.  
Advertisement
Add Comment
Please, Sign In to add comment