Created
October 29, 2019 12:56
-
-
Save lukewilson2002/9f9328539d05cfdde5dc97dc3f952683 to your computer and use it in GitHub Desktop.
A pseudo-programming language made to overengineer a guessing game.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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