import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.regex.*;
class Basic
{
{
System.
out.
println("*** BASIC Interpreter ***"); try {
Excutor excutor = new Excutor();
while ((line = in.readLine()) != null) {
try {
List<Token> tokens = Tokenizer.tokenize(line);
if (excutor.doEditorCommand(tokens) < 0) {
break;
}
} catch (SyntaxError er) {
}
}
// System.out.println(excutor);
}
}
}
enum TokenType
{
INT, DBL, STR, NAME, SYMBL, SHARP, SEMICOLON,
OP_BRKT, CL_BRKT, COMMA, COLON,
UNKNOWN}
final class Token
{
final TokenType type;
public Token
(TokenType type,
String token
) {
this.type = type;
this.token = token;
}
public TokenType getType() { return type; }
public String getToken
() { return token
; } @Override
{
return "[" + type + " : " + token + "]";
}
public boolean isInt() { return TokenType.INT.equals(type); }
public boolean isStr() { return TokenType.STR.equals(type); }
public boolean isDbl() { return TokenType.DBL.equals(type); }
public boolean isName() { return TokenType.NAME.equals(type); }
public boolean isSymbl() { return TokenType.SYMBL.equals(type); }
public boolean isOpBrkt() { return TokenType.OP_BRKT.equals(type); }
public boolean isClBrkt() { return TokenType.CL_BRKT.equals(type); }
public boolean isColon() { return TokenType.COLON.equals(type); }
public boolean isSemiColon() { return TokenType.SEMICOLON.equals(type); }
public boolean isComma() { return TokenType.COMMA.equals(type); }
public boolean isSharp() { return TokenType.SHARP.equals(type); }
}
class SyntaxError
extends java.
lang.
Exception {
public SyntaxError
(String msg
) { super(msg
); } public SyntaxError
(Throwable ex
) { super(ex
); } public SyntaxError(List<Token> tokens, int index)
{
super("token index(" + index + "): " + tokens.toString());
}
}
final class TokenError extends SyntaxError
{
public TokenError
(String line
) { super(line
); } }
final class Tokenizer
{
private static Pattern p_space = Pattern.compile("^\\s+");
private static Pattern p_int = Pattern.compile("^\\d+");
private static Pattern p_dbl = Pattern.compile("^\\d*\\.\\d+");
private static Pattern p_str = Pattern.compile("^\"(\"\"|[^\"])*\"");
private static Pattern p_name = Pattern.compile("^[A-Za-z][A-Za-z0-9]*\\$?");
private static Pattern p_symbl = Pattern.compile("^(>=|<=|<>|[=<>+\\*/-])");
public static List
<Token
> tokenize
(String line
) throws TokenError
{
List<Token> list = new ArrayList<Token>();
Matcher m = null;
TokenType type = null;
int offset = 0;
while (line.length() > 0) {
if ((m = p_space.matcher(line)).lookingAt()) {
line = line.substring(m.end());
continue;
} else if ((m = p_dbl.matcher(line)).lookingAt()) {
type = TokenType.DBL;
} else if ((m = p_int.matcher(line)).lookingAt()) {
type = TokenType.INT;
} else if ((m = p_str.matcher(line)).lookingAt()) {
type = TokenType.STR;
} else if ((m = p_name.matcher(line)).lookingAt()) {
type = TokenType.NAME;
} else if ((m = p_symbl.matcher(line)).lookingAt()) {
type = TokenType.SYMBL;
} else {
m = null;
offset = 1;
if (line.startsWith(token = "(")) {
type = TokenType.OP_BRKT;
} else if (line.startsWith(token = ")")) {
type = TokenType.CL_BRKT;
} else if (line.startsWith(token = ":")) {
type = TokenType.COLON;
} else if (line.startsWith(token = ",")) {
type = TokenType.COMMA;
} else if (line.startsWith(token = "#")) {
type = TokenType.SHARP;
} else if (line.startsWith(token = ";")) {
type = TokenType.SEMICOLON;
} else {
throw new TokenError(line);
}
}
if (m != null) {
token = m.group();
if (TokenType.NAME.equals(type)) {
token = token.toUpperCase();
}
offset = m.end();
}
list.add(new Token(type, token));
line = line.substring(offset);
}
return list;
}
}
final class ExcuteError extends SyntaxError
{
public ExcuteError
(Throwable ex
) { super(ex
); } public ExcuteError
(String msg
) { super(msg
); } }
class VarArray<T>
{
}
enum ResultType
{
}
class Result
{
public static final Result getTrue() {
return new Result((int)-1);
}
public static final Result getFalse() {
return new Result((int)0);
}
public static final Result getBool(boolean bool) {
return bool ? getTrue() : getFalse();
}
private int offset;
private int intvalue = 0;
private double dblvalue = 0;
private String strvalue
= null; private ResultType type;
Result() {
type = ResultType.EOL;
}
static Result getEOL(int offset) {
Result temp = new Result();
temp.offset = offset;
return temp;
}
Result(int value) {
intvalue = value;
type = ResultType.INT;
}
Result(double value) {
dblvalue = value;
type = ResultType.DBL;
}
if (Integer.
class.
equals(value.
getClass())) { intvalue = value.intValue();
type = ResultType.INT;
} else if (Double.
class.
equals(value.
getClass())) { dblvalue = value.doubleValue();
type = ResultType.DBL;
} else {
}
}
strvalue = value;
type = ResultType.STR;
}
Result(int value, int offset) {
this(value);
this.offset = offset;
}
Result(double value, int offset) {
this(value);
this.offset = offset;
}
Result
(Number value,
int offset
) { this(value);
this.offset = offset;
}
Result
(String value,
int offset
) { this(value);
this.offset = offset;
}
public ResultType getType()
{
return type;
}
public int getOffset()
{
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getIntValue() {
return intvalue;
}
public double getDblValue() {
return dblvalue;
}
{
if (ResultType.INT.equals(type)) {
} else if (ResultType.DBL.equals(type)) {
return Double.
valueOf(dblvalue
); } else {
return null;
}
}
{
return strvalue;
}
public boolean isNumber() {
return ResultType.INT.equals(type) || ResultType.DBL.equals(type);
}
public boolean isInt() {
return ResultType.INT.equals(type);
}
public boolean isDbl() {
return ResultType.DBL.equals(type);
}
public boolean isString() {
return ResultType.STR.equals(type);
}
}
final class Excutor
{
private NavigableMap
<Integer, List
<Token
>> program
= new TreeMap
<Integer, List
<Token
>>();
private Map
<String, VarArray
<String
>> strarrs
= new HashMap
<String, VarArray
<String
>>(); private Map
<String, VarArray
<Number
>> numarrs
= new HashMap
<String, VarArray
<Number
>>(); private Map
<String, String
> strvars
= new HashMap
<String, String
>(); private Map
<String, Number
> numvars
= new HashMap
<String, Number
>();
private Integer programcounter
= null; private Deque<Integer> programcounterstack = new ArrayDeque<Integer>();
private int arraybase = 0;
private boolean jumpflag = false;
private boolean stopflag = false;
private boolean endflag = false;
private Set<String> editorcommandnames = new HashSet<String>();
private Set<String> commandnames = new HashSet<String>();
private Set<String> functionnames = new HashSet<String>();
private Set<String> keywordnames = new HashSet<String>();
private Map
<String, Integer
> opepriority
= new HashMap
<String, Integer
>();
private double lastrand = 0;
private int tabcount = 0;
public Excutor() {
String[] edcmd
= { "RUN",
"LOAD",
"SAVE",
"LIST",
"RENUM",
"CONT" }; String[] cmd
= { "PRINT",
"INPUT",
"LET",
"REM",
"STOP",
"END",
"GOTO",
"GO", "TO", "GOSUB", "RETURN", "BASE", "DIM", "IF", "THEN", "ELSE",
"FOR", "NEXT", "STEP", "BREAK", "RESTORE", "FILE", "READ", "DATA", "WRITE"};
String[] fnc
= { "INT",
"STR$",
"RND",
"CLK",
"ABS",
"VAL",
"SIN",
"COS",
"TAN",
"SGN", "SQRT", "EXP", "LOG", "LEFT$", "RIGHT$", "MID$"};
String[] key
= { "AND",
"OR" }; String[] ope
= { "OR",
"AND",
"=",
">=",
"<=",
"<",
">",
"+",
"-",
"*",
"/" };
for (String s
: edcmd
) editorcommandnames.
add(s
); for (String s
: cmd
) commandnames.
add(s
); for (String s
: fnc
) functionnames.
add(s
); for (String s
: key
) keywordnames.
add(s
);
for (int i = 0; i < ope.length; i++) {
opepriority.
put(ope
[i
],
Integer.
valueOf(i
)); }
}
private boolean checkKeyword
(String name
) { return editorcommandnames.contains(name)
|| commandnames.contains(name)
|| functionnames.contains(name)
|| keywordnames.contains(name);
}
private void printLine(List<Token> tokens) {
printLine
(Integer.
valueOf(tokens.
get(0).
getToken()), tokens
); }
private void printLine
(Integer linenum, List
<Token
> tokens
) {
int s = 0;
if (linenum != null) {
System.
out.
printf("%05d ", linenum.
intValue()); s = 1;
}
TokenType before = null, type;
for (int i = s; i < tokens.size(); i++) {
Token token = tokens.get(i);
type = token.getType();
if (TokenType.NAME.equals(before)) {
switch (type) {
case NAME:
case INT:
case DBL:
case SHARP:
case STR:
break;
default:
break;
}
}
System.
out.
print(tokens.
get(i
).
getToken()); before = type;
}
}
private Result checksign(Result temp, int sign) throws SyntaxError {
switch (temp.getType()) {
case INT:
if (sign < 0) {
return new Result( - temp.getNumValue().intValue(), temp.getOffset());
}
break;
case DBL:
if (sign < 0) {
return new Result( - temp.getNumValue().doubleValue(), temp.getOffset());
}
break;
case STR:
if (sign == 0) {
break;
}
default:
throw new SyntaxError("invalid sign character");
}
return temp;
}
private Result calc2
(int temp1,
int temp2,
String op
) throws SyntaxError
{ int res = 0;
switch (op) {
case "+": res = temp1 + temp2; break; // TODO OverFlow どした
case "-": res = temp1 - temp2; break;
case "*": res = temp1 * temp2; break;
case "/": if (temp2 == 0) {
throw new ExcuteError("Zero divided");
}
res = temp1 / temp2; break;
case "=": res = temp1 == temp2 ? -1 : 0; break;
case ">": res = temp1 > temp2 ? -1 : 0; break;
case "<": res = temp1 < temp2 ? -1 : 0; break;
case ">=": res = temp1 >= temp2 ? -1 : 0; break;
case "<=": res = temp1 <= temp2 ? -1 : 0; break;
case "AND": res = (temp1 & temp2) != 0 ? -1 : 0; break;
case "OR": res = (temp1 | temp2) != 0 ? -1 : 0; break;
default:
throw new SyntaxError("Invalid operator: " + op);
}
return new Result(res);
}
private Result calc2
(double temp1,
double temp2,
String op
) throws SyntaxError
{ double res = 0;
switch (op) {
case "+": res = temp1 + temp2; break; // TODO OverFlow どした
case "-": res = temp1 - temp2; break;
case "*": res = temp1 * temp2; break;
case "/": if (temp2 == 0) {
throw new ExcuteError("Zero divided");
}
res = temp1 / temp2; break;
case "=": return Result.getBool(temp1 == temp2);
case ">": return Result.getBool(temp1 > temp2);
case "<": return Result.getBool(temp1 < temp2);
case ">=": return Result.getBool(temp1 >= temp2);
case "<=": return Result.getBool(temp1 <= temp2);
case "AND": return Result.getBool(temp1 * temp2 != 0.0);
case "OR": return Result.getBool(temp1 != 0.0 || temp2 != 0.0);
default:
throw new SyntaxError("Invalid operator: " + op);
}
return new Result(res);
}
switch (op) {
case "-":
case "*":
case "/":
case "AND":
case "OR": throw new SyntaxError("Invalid str operetor: " + op);
case "+": return new Result(temp1 + temp2);
case "=": return Result.getBool(temp1.equals(temp2));
case ">": return Result.getBool(temp1.compareTo(temp2) > 0);
case "<": return Result.getBool(temp1.compareTo(temp2) < 0);
case ">=": return Result.getBool(temp1.compareTo(temp2) >= 0);
case "<=": return Result.getBool(temp1.compareTo(temp2) <= 0);
default:
throw new SyntaxError("Invalid operator: " + op);
}
}
private Result calc2
(Result temp1, Result temp2,
String op
) throws SyntaxError
{ if (temp1.getType().equals(temp2.getType())) {
switch (temp1.getType()) {
case INT:
return calc2(temp1.getIntValue(), temp2.getIntValue(), op);
case DBL:
return calc2(temp1.getDblValue(), temp2.getDblValue(), op);
case STR:
return calc2(temp1.getStrValue(), temp2.getStrValue(), op);
default:
throw new ExcuteError("Invalid type value");
}
} else if (ResultType.INT.equals(temp1.getType())
&& ResultType.DBL.equals(temp2.getType())) {
return calc2(temp1.getNumValue().doubleValue(), temp2.getDblValue(), op);
} else if (ResultType.DBL.equals(temp1.getType())
&& ResultType.INT.equals(temp2.getType())) {
return calc2(temp1.getDblValue(), temp2.getNumValue().doubleValue(), op);
} else {
throw new ExcuteError("Invalid type value");
}
}
private boolean calccheck
(String op1,
String op2
) throws SyntaxError
{ if (p1 == null || p2 == null) {
throw new SyntaxError("Invalid expression symbol");
}
return p2.compareTo(p1) < 0;
}
private Result calc(List<Token> tokens, int index) throws SyntaxError
{
if (index >= tokens.size()) {
throw new SyntaxError(tokens, index);
}
Deque<Result> r_stack = new ArrayDeque<Result>();
Deque<String> s_stack = new ArrayDeque<String>();
int sign = 0;
int flag = 0;
Result temp, temp2;
for (; index < tokens.size(); index++) {
Token cur = tokens.get(index);
TokenType type = cur.getType();
String token
= cur.
getToken();
if (flag == 0) {
flag = 1;
switch (type) {
case SYMBL:
if (sign != 0) {
throw new SyntaxError(tokens, index);
}
if ("+".equals(token)) {
sign = 1;
} else if ("-".equals(token)) {
sign = -1;
} else {
throw new SyntaxError(tokens, index);
}
flag = 0;
break;
case INT:
r_stack.
push(checksign
(new Result
(Integer.
parseInt(token
), index
), sign
)); break;
case DBL:
r_stack.
push(checksign
(new Result
(Double.
parseDouble(token
), index
), sign
)); break;
case STR:
r_stack.push(checksign(new Result(token.substring(1, token.length() - 1), index), sign));
break;
case OP_BRKT:
temp = calc(tokens, index + 1);
index = temp.getOffset();
if (TokenType.CL_BRKT.equals(tokens.get(index).getType()) == false) {
throw new SyntaxError(tokens, index);
}
r_stack.push(checksign(temp, sign));
break;
case NAME:
if (functionnames.contains(token)) {
temp = doFunction(tokens, index);
index = temp.getOffset();
r_stack.push(checksign(temp, sign));
} else if (strarrs.containsKey(token)) {
temp = get_strarr(tokens, index);
index = temp.getOffset();
r_stack.push(checksign(temp, sign));
} else if (strvars.containsKey(token)) {
r_stack.push(checksign(new Result(strvars.get(token), index), sign));
} else if (numarrs.containsKey(token)) {
temp = get_numarr(tokens, index);
index = temp.getOffset();
r_stack.push(checksign(temp, sign));
} else if (numvars.containsKey(token)) {
r_stack.push(checksign(new Result(numvars.get(token), index), sign));
} else if (checkKeyword(token)) {
throw new SyntaxError("Invalid name");
} else if (token.lastIndexOf("$") > 0) {
// 未定義 文字列 変数
if (index + 1 < tokens.size() && "(".equals(tokens.get(index + 1).getToken())) {
// 配列
temp = get_strarr(tokens, index);
index = temp.getOffset();
r_stack.push(checksign(temp, sign));
} else {
strvars.put(token, "");
r_stack.push(checksign(new Result("", index), sign));
}
} else {
// 未定義 数値 変数
if (index + 1 < tokens.size() && "(".equals(tokens.get(index + 1).getToken())) {
// 配列
temp = get_numarr(tokens, index);
index = temp.getOffset();
r_stack.push(checksign(temp, sign));
} else {
numvars.
put(token,
Integer.
valueOf(0)); r_stack.push(checksign(new Result(0, index), sign));
}
}
break;
default:
throw new SyntaxError(tokens, index);
}
} else if (flag == 1) {
flag = 0;
sign = 0;
switch (type) {
case NAME:
switch (token) {
case "OR":
case "AND":
temp = r_stack.peek();
if (ResultType.STR.equals(temp.getType())) {
throw new ExcuteError("Invalid expression symbol");
}
break;
default:
throw new SyntaxError(tokens, index);
}
case SYMBL:
switch (token) {
case "-":
case "*":
case "/":
temp = r_stack.peek();
if (ResultType.STR.equals(temp.getType())) {
throw new ExcuteError("Invalid expression symbol");
}
default:
break;
}
while (s_stack.size() > 0 && calccheck(s_stack.peek(), token)) {
if (r_stack.size() < 2) {
throw new ExcuteError("Unknown error");
}
temp2 = r_stack.pop();
temp = r_stack.pop();
temp = calc2(temp, temp2, s_stack.pop());
r_stack.push(temp);
}
s_stack.push(token);
break;
case COLON:
case SEMICOLON:
case COMMA:
case CL_BRKT:
while (s_stack.size() > 0) {
if (r_stack.size() < 2) {
throw new ExcuteError("Unknown error");
}
temp2 = r_stack.pop();
temp = r_stack.pop();
temp = calc2(temp, temp2, s_stack.pop());
r_stack.push(temp);
}
if (r_stack.size() != 1) {
throw new ExcuteError("Unknown error");
}
temp = r_stack.pop();
temp.setOffset(index);
return temp;
default:
throw new SyntaxError(tokens, index);
}
}
}
if (flag == 0) {
if (r_stack.size() > 0 || s_stack.size() > 0) {
throw new SyntaxError(tokens, index);
}
return Result.getEOL(index);
}
while (s_stack.size() > 0) {
if (r_stack.size() < 2) {
throw new ExcuteError("Unknown error");
}
temp2 = r_stack.pop();
temp = r_stack.pop();
temp = calc2(temp, temp2, s_stack.pop());
r_stack.push(temp);
}
if (r_stack.size() != 1) {
throw new ExcuteError("Unknown error");
}
temp = r_stack.pop();
temp.setOffset(index);
return temp;
}
public Result get_strarr(List<Token> tokens, int index) throws SyntaxError
{
return Result.getEOL(index);
}
public Result get_numarr(List<Token> tokens, int index) throws SyntaxError
{
return Result.getEOL(index);
}
public Result doFunction(List<Token> tokens, int index) throws SyntaxError
{
if (index + 1 >= tokens.size()) {
throw new SyntaxError(tokens, index);
}
if (TokenType.OP_BRKT.equals(tokens.get(index + 1).getType()) == false) {
throw new SyntaxError(tokens, index);
}
String name
= tokens.
get(index
).
getToken(); Result temp;
switch (name) {
case "INT":
temp = calc(tokens, index + 2);
index = temp.getOffset();
if (TokenType.CL_BRKT.equals(tokens.get(index).getType())) {
switch (temp.getType()) {
case INT:
return temp;
case DBL:
return new Result(temp.getNumValue().intValue(), index);
default:
break;
}
}
throw new SyntaxError(tokens, index);
case "RND":
temp = calc(tokens, index + 2);
index = temp.getOffset();
if (TokenType.CL_BRKT.equals(tokens.get(index).getType())) {
switch (temp.getType()) {
case INT:
case DBL:
int s = temp.getNumValue().intValue();
if (s == 0) {
return new Result(lastrand = rand.nextDouble(), index);
} else if (s > 0) {
rand.setSeed((long)s);
lastrand = rand.nextDouble();
}
return new Result(lastrand, index);
default:
break;
}
}
throw new SyntaxError(tokens, index);
case "CLK":
temp = calc(tokens, index + 2);
index = temp.getOffset();
if (TokenType.CL_BRKT.equals(tokens.get(index).getType())) {
switch (temp.getType()) {
case INT:
case DBL:
double t = temp.getNumValue().doubleValue();
t *= 24;
return new Result((int)t, index);
default:
break;
}
}
throw new SyntaxError(tokens, index);
case "ABS":
temp = calc(tokens, index + 2);
index = temp.getOffset();
if (TokenType.CL_BRKT.equals(tokens.get(index).getType())) {
switch (temp.getType()) {
case INT:
return new Result
(Math.
abs(temp.
getIntValue()), index
); case DBL:
return new Result
(Math.
abs(temp.
getDblValue()), index
); default:
break;
}
}
throw new SyntaxError(tokens, index);
case "VAL":
temp = calc(tokens, index + 2);
index = temp.getOffset();
if (TokenType.CL_BRKT.equals(tokens.get(index).getType())) {
switch (temp.getType()) {
case STR:
Matcher mt;
if ((mt = Pattern.compile("^(\\d*\\.\\d+)").matcher(temp.getStrValue())).lookingAt()) {
return new Result
(Double.
parseDouble(mt.
group(1)), index
); } else if ((mt = Pattern.compile("^(\\d+)").matcher(temp.getStrValue())).lookingAt()) {
return new Result
(Integer.
parseInt(mt.
group(1)), index
); } else {
return new Result(0.0, index);
}
default:
break;
}
}
throw new SyntaxError(tokens, index);
default:
break;
}
return Result.getEOL(index);
}
public int doEditorCommand(List<Token> tokens) throws SyntaxError
{
if (tokens == null || tokens.isEmpty()) {
return 0;
}
Token first = tokens.get(0);
String token
= first.
getToken(); TokenType type = first.getType();
if (TokenType.INT.equals(type)) {
if (tmpint.intValue() < 1) {
throw new SyntaxError(token);
}
if (tokens.size() > 1) {
program.put(tmpint, tokens);
} else {
program.remove(tmpint);
}
return 0;
} else if (TokenType.NAME.equals(type) == false) {
throw new ExcuteError(token);
}
/* */
printLine(null, tokens); // IDEONE上じゃ入力が見えないので
/* */
switch (token) {
case "CONT": // プログラムの再開
// TODO 処理
break;
case "EXIT": // インタプリタの終了
return -1;
case "LIST": // プログラムの表示
do_list(tokens);
break;
case "LOAD": // プログラムのロード
// TODO 処理
break;
case "NEW": // プログラムと変数の全消去
// TODO 処理
break;
case "RENUM": // プログラムの行番号再割り当て
// TODO 処理
break;
case "RUN": // プログラムの実行
do_run(tokens);
break;
case "SAVE": // プログラムの保存
// TODO 処理
break;
default:
excute(tokens, 0);
break;
}
if (stopflag) {
stopflag = false;
return 0;
}
return 0;
}
private void do_list(List<Token> tokens) throws SyntaxError
{
Token first, second, third;
Map
<Integer, List
<Token
>> list
= null; try {
switch (tokens.size()) {
case 1:
list = program;
break;
case 2:
first = tokens.get(1);
if (TokenType.INT.equals(first.getType()) == false) {
throw new SyntaxError(tokens ,1);
}
end
= start
= Integer.
valueOf(first.
getToken()); if (start.intValue() < 1) {
throw new SyntaxError(tokens ,1);
}
list = program.subMap(start, true, end, true);
break;
case 3:
first = tokens.get(1);
second = tokens.get(2);
if ("-".equals(first.getToken())) {
if (TokenType.INT.equals(second.getType()) == false) {
throw new SyntaxError(tokens ,2);
}
end
= Integer.
valueOf(second.
getToken()); if (end.intValue() < 1) {
throw new SyntaxError(tokens ,2);
}
list = program.headMap(end, true);
} else if (TokenType.INT.equals(first.getType())) {
start
= Integer.
valueOf(first.
getToken()); if (start.intValue() < 1) {
throw new SyntaxError(tokens , 1);
}
if ("-".equals(second.getToken()) == false) {
throw new SyntaxError(tokens ,2);
}
list = program.tailMap(start);
} else {
throw new SyntaxError(tokens ,1);
}
break;
case 4:
first = tokens.get(1);
if (TokenType.INT.equals(first.getType()) == false) {
throw new SyntaxError(tokens ,1);
}
start
= Integer.
valueOf(first.
getToken()); if (start.intValue() < 1) {
throw new SyntaxError(tokens ,1);
}
if ("-".equals(tokens.get(2).getToken()) == false) {
throw new SyntaxError(tokens ,2);
}
third = tokens.get(3);
if (TokenType.INT.equals(third.getType()) == false) {
throw new SyntaxError(tokens ,3);
}
end
= Integer.
valueOf(third.
getToken()); if (end.intValue() < 1) {
throw new SyntaxError(tokens ,3);
}
list = program.subMap(start, true, end, true);
break;
default:
throw new SyntaxError(tokens, 0);
}
} catch (SyntaxError er) {
throw er;
throw new ExcuteError(ex);
}
if (list == null) {
return;
}
printLine(key, list.get(key));
}
}
private void do_run(List<Token> tokens) throws SyntaxError
{
switch (tokens.size()) {
case 1:
programcounter
= program.
ceilingKey(Integer.
valueOf(1)); if (programcounter == null) {
throw new SyntaxError("Program is not found");
}
break;
case 2:
Token first = tokens.get(1);
if (TokenType.INT.equals(first.getType()) == false) {
throw new SyntaxError("Illegal Argument");
}
programcounter
= Integer.
valueOf(first.
getToken()); if (programcounter.intValue() < 1) {
throw new SyntaxError("Wrong Line Number");
}
if (program.containsKey(programcounter) == false) {
throw new SyntaxError("Not found Line Number");
}
break;
default:
throw new SyntaxError("Illegal Arguments");
}
stopflag = endflag = false;
List<Token> line = null;
try {
while (programcounter != null) {
line = program.get(programcounter);
excute(line, 1);
if (jumpflag == false) {
programcounter = program.higherKey(programcounter);
if (stopflag) {
break;
} else if (endflag) {
break;
}
} else {
jumpflag = false;
}
}
} catch (SyntaxError er) {
printLine(line);
throw er;
}
}
private int excute(List<Token> tokens, int index) throws SyntaxError
{
if (index < 0 || index >= tokens.size()) {
return tokens.size();
}
Token first = tokens.get(index);
TokenType type = first.getType();
while (TokenType.COLON.equals(type)) {
index++;
if (index == tokens.size()) {
return index;
}
first = tokens.get(index);
type = first.getType();
}
if (TokenType.NAME.equals(type) == false) {
throw new SyntaxError(first.toString());
}
String cmd
= first.
getToken(); int offset = index;
switch (cmd) {
case "BASE": // 配列の下限(0/1)の設定
offset = cmd_base(tokens, index + 1);
break;
case "BREAK": // FORループの脱出
// TODO 処理
break;
case "DATA": // データの列挙
// TODO 処理
break;
case "DIM": // 配列変数の宣言
// TODO 処理
break;
case "ELSE": // IF文のELSE節の開始
// TODO 処理
break;
case "END": // プログラムの終了
endflag = true;
return tokens.size();
case "FILE": // ファイルの割り当て
// TODO 処理
break;
case "FOR": // 繰り返し
// TODO 処理
break;
case "GO": // GOTOの分割トークン
if (index + 2 >= tokens.size()) {
throw new SyntaxError(tokens, index);
}
if ("TO".equals(tokens.get(index + 1).getToken()) == false) {
throw new SyntaxError(tokens, index);
}
offset = cmd_goto(tokens, index + 2);
break;
case "GOTO": // ジャンプ
offset = cmd_goto(tokens, index + 1);
break;
case "GOSUB": // サブルーチンジャンプ
offset = cmd_gosub(tokens, index + 1);
break;
case "IF": // 条件節
// TODO 処理
break;
case "INPUT": // キーボードからの値の入力
// TODO 処理
break;
case "LET": // 変数への代入
offset = cmd_let(tokens, index + 1);
break;
case "NEXT": // FOR文の末端
// TODO 処理
break;
case "PRINT": // 画面へ値を出力
offset = cmd_print(tokens, index + 1);
break;
case "REM": // コメント行
offset = tokens.size();
break;
case "RESTORE": // データ・ファイルの読み込み位置のリセット
// TODO 処理
break;
case "RETURN": // サブルーチンからの脱出
offset = cmd_return(tokens, index);
break;
case "STOP": // プログラムの中断
stopflag = true;
return tokens.size();
default:
offset = cmd_let(tokens, index);
break;
}
return offset;
}
@Override
{
return program.toString().replaceAll("(\\d+=\\[\\[)", "\n$1");
}
private int cmd_goto(List<Token> tokens, int index) throws SyntaxError
{
if (index >= tokens.size()) {
throw new SyntaxError(tokens, index);
}
if (index + 1 < tokens.size()) {
if (TokenType.COLON.equals(tokens.get(index + 1).getType()) == false) {
throw new SyntaxError(tokens, index + 1);
}
}
Token first = tokens.get(index);
if (TokenType.INT.equals(first.getType()) == false) {
throw new SyntaxError(tokens, index);
}
if (program.containsKey(next) == false) {
throw new SyntaxError(tokens, index);
}
programcounter = next;
jumpflag = true;
return tokens.size();
}
private int cmd_gosub(List<Token> tokens, int index) throws SyntaxError
{
if (index >= tokens.size()) {
throw new SyntaxError(tokens, index);
}
if (index + 1 < tokens.size()) {
if (TokenType.COLON.equals(tokens.get(index + 1).getType()) == false) {
throw new SyntaxError(tokens, index + 1);
}
}
Token first = tokens.get(index);
if (TokenType.INT.equals(first.getType()) == false) {
throw new SyntaxError(tokens, index);
}
if (program.containsKey(next) == false) {
throw new SyntaxError(tokens, index);
}
try {
programcounterstack.push(programcounter);
programcounter = next;
jumpflag = true;
return tokens.size();
throw new ExcuteError(ex);
}
}
private int cmd_return(List<Token> tokens, int index) throws SyntaxError
{
if (index < tokens.size()) {
if (TokenType.COLON.equals(tokens.get(index).getType()) == false) {
throw new SyntaxError(tokens, index);
}
}
try {
Integer back
= programcounterstack.
pop(); programcounter = program.higherKey(back);
jumpflag = true;
return tokens.size();
throw new ExcuteError(ex);
}
}
private int cmd_base(List<Token> tokens, int index) throws SyntaxError
{
try {
Token first = tokens.get(index);
if (TokenType.INT.equals(first.getType()) == false) {
throw new SyntaxError(tokens, index);
}
int tmpint
= Integer.
parseInt(first.
getToken()); if (tmpint != 0 && tmpint != 1) {
throw new SyntaxError(tokens, index + 1);
}
arraybase = tmpint;
return excute(tokens, index + 1);
} catch (SyntaxError er) {
throw er;
throw new ExcuteError(ex);
}
}
private int cmd_print(List<Token> tokens, int index) throws SyntaxError
{
if (index == tokens.size()) {
tabcount = 0;
return tokens.size();
} else if (index > tokens.size()) {
throw new ExcuteError("Unknown error");
}
StringBuilder output = new StringBuilder();
boolean nl = true;
for (; index < tokens.size(); index++) {
Token cur = tokens.get(index);
switch (cur.getType()) {
case COLON:
if (nl) {
tabcount = 0;
} else {
tabcount += output.length();
}
return excute(tokens, index + 1);
case COMMA:
output.append('\t');
nl = false;
break;
case SEMICOLON:
nl = false;
break;
case INT:
case DBL:
case STR:
case NAME:
Result temp = calc(tokens, index);
index = temp.getOffset() - 1;
switch (temp.getType()) {
case INT: output.append(temp.getIntValue()); break;
case DBL: output.append(temp.getDblValue()); break;
case STR: output.append(temp.getStrValue()); break;
default:
throw new ExcuteError("Unknown error");
}
nl = true;
break;
}
}
if (nl) {
tabcount = 0;
} else {
tabcount += output.length();
}
return excute(tokens, index);
}
private int cmd_let(List<Token> tokens, int index) throws SyntaxError
{
try {
if (index + 2 >= tokens.size()) {
throw new SyntaxError(tokens, index);
}
Token first = tokens.get(index);
String name
= first.
getToken(); if (checkKeyword(name)) { // 予約語チェック
throw new SyntaxError("Wrong variable name: " + name);
}
index++;
Result temp;
if (name.lastIndexOf("$") > 0) {
if (strarrs.containsKey(name)) {
if (TokenType.OP_BRKT.equals(tokens.get(index).getType()) == false) {
throw new SyntaxError(tokens, index);
}
// TODO 配列の添え字の読み取りとか
} else {
if ("=".equals(tokens.get(index).getToken()) == false) {
throw new SyntaxError(tokens, index);
}
index++;
temp = calc(tokens, index);
if (ResultType.STR.equals(temp.getType()) == false) {
throw new ExcuteError("Invalid type value");
}
index = temp.getOffset();
strvars.put(name, temp.getStrValue());
}
} else {
if (numarrs.containsKey(name)) {
if (TokenType.OP_BRKT.equals(tokens.get(index).getType()) == false) {
throw new SyntaxError(tokens, index);
}
// TODO 配列の添え字の読み取りとか
} else if (numvars.containsKey(name)) {
if ("=".equals(tokens.get(index).getToken()) == false) {
throw new SyntaxError(tokens ,index);
}
index++;
temp = calc(tokens, index);
index = temp.getOffset();
Number num
= numvars.
get(name
); switch (temp.getType()) {
case INT:
if (Integer.
class.
equals(num.
getClass())) { numvars.put(name, temp.getNumValue());
} else if (Double.
class.
equals(num.
getClass())) { numvars.
put(name,
Double.
valueOf(temp.
getNumValue().
doubleValue())); } else {
throw new ExcuteError("Invalid type value");
}
break;
case DBL:
if (Integer.
class.
equals(num.
getClass())) { numvars.
put(name,
Integer.
valueOf(temp.
getNumValue().
intValue())); } else if (Double.
class.
equals(num.
getClass())) { numvars.put(name, temp.getNumValue());
} else {
throw new ExcuteError("Invalid type value");
}
break;
default:
throw new ExcuteError("Invalid type value");
}
} else {
if ("=".equals(tokens.get(index).getToken()) == false) {
throw new SyntaxError(tokens, index);
}
index++;
temp = calc(tokens, index);
index = temp.getOffset();
switch (temp.getType()) {
case INT:
case DBL:
numvars.put(name, temp.getNumValue());
break;
default:
throw new ExcuteError("Invalid type value");
}
}
}
return excute(tokens, index + 1);
} catch (SyntaxError er) {
throw er;
// ex.printStackTrace();
throw new ExcuteError(tokens.toString());
}
}
}