Skip to content

Instantly share code, notes, and snippets.

@fivemoreminix
Created October 29, 2019 12:56
Show Gist options
  • Save fivemoreminix/9f9328539d05cfdde5dc97dc3f952683 to your computer and use it in GitHub Desktop.
Save fivemoreminix/9f9328539d05cfdde5dc97dc3f952683 to your computer and use it in GitHub Desktop.
A pseudo-programming language made to overengineer a guessing game.
/*
NUMBER GUESSING DOMAIN-SPECIFIC LANGUAGE IN JAVA
BY LUKE I. WILSON
*/
package org.vv;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Random;
public class GuessingGame {
public enum Token {
GOTO, RET, SETRAND, READ, SAY, LBL, JL, JG, JE
}
public static class Instr {
public Token t; // instruction
public String op; // operand
public Instr(Token t, String op) {
this.t = t;
this.op = op;
}
}
// translate the instructions to a pseudo-abstract syntax tree of Instr
public static ArrayList<Instr> lex(String[] lines) {
ArrayList<Instr> instrs = new ArrayList<>();
for (int i = 0; i < lines.length; i++) {
String l = lines[i].strip().toLowerCase();
if (l.isEmpty()) continue;
else if (l.startsWith("goto")) {
String r = l.substring(5);
instrs.add(new Instr(Token.GOTO, r));
}
else if (l.startsWith("ret")) instrs.add(new Instr(Token.RET, null));
else if (l.startsWith("setrand")) instrs.add(new Instr(Token.SETRAND, null));
else if (l.startsWith("read")) instrs.add(new Instr(Token.READ, null));
else if (l.startsWith("say")) {
String r = l.substring(4);
instrs.add(new Instr(Token.SAY, r));
}
else if (l.startsWith("lbl")) {
String r = l.substring(4);
instrs.add(new Instr(Token.LBL, r));
}
else if (l.startsWith("jl")) {
String r = l.substring(3);
instrs.add(new Instr(Token.JL, r));
}
else if (l.startsWith("jg")) {
String r = l.substring(3);
instrs.add(new Instr(Token.JG, r));
}
else if (l.startsWith("je")) {
String r = l.substring(3);
instrs.add(new Instr(Token.JE, r));
}
}
return instrs;
}
public static void interpret(ArrayList<Instr> instrs) {
Scanner scan = new Scanner(System.in);
Random rando = new Random();
int r = 0, x = 0, y = 0; // Program registers
loop: for (int pc = 0; pc < instrs.size(); pc++) {
Instr instr = instrs.get(pc);
switch (instr.t) {
case GOTO:
for (pc = 0; pc < instrs.size(); pc++) {
if (instrs.get(pc).t == Token.LBL && instrs.get(pc).op.equals(instr.op)) break;
}
break;
case RET: break loop;
case SETRAND: r = rando.nextInt(10) + 1; break;
case READ: x = scan.nextInt(); break;
case SAY: System.out.println(instr.op.toUpperCase()); break;
case LBL: break;
case JL: if (x >= r) break;
for (pc = 0; pc < instrs.size(); pc++) {
if (instrs.get(pc).t == Token.LBL && instrs.get(pc).op.equals(instr.op)) break;
}
break;
case JG: if (x <= r) break;
for (pc = 0; pc < instrs.size(); pc++) {
if (instrs.get(pc).t == Token.LBL && instrs.get(pc).op.equals(instr.op)) break;
}
break;
case JE: if (x != r) break;
for (pc = 0; pc < instrs.size(); pc++) {
if (instrs.get(pc).t == Token.LBL && instrs.get(pc).op.equals(instr.op)) break;
}
break;
default:
throw new IllegalStateException("Unexpected value: " + instr.t);
}
}
}
public static void main(String[] args) {
// Only three available registers: r, x, and y
String[] dsl_prog = new String[]{
" SETRAND", // rand -> r
" SAY Guess my number.", // print
"LBL loop",
" READ", // read value to x
" JE eq", // jump to eq if value at x is equal to r
" JL l", // jump to l if value at x is less than r
" JG g", // jump to g if value at x is greater than r
"LBL l",
" SAY Number too small!",
" GOTO loop",
"LBL g",
" SAY Number too big!",
" GOTO loop",
"LBL eq", // the jump label for equal
" SAY Goodbye!",
" RET" // exit program
};
ArrayList<Instr> dsl_ast = lex(dsl_prog);
interpret(dsl_ast);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment