PA1 done
This commit is contained in:
parent
3ecd8f4478
commit
8f24012862
12
CS143体验报告.md
12
CS143体验报告.md
@ -20,5 +20,15 @@
|
|||||||
|
|
||||||
第一个实验是用 COOL 写一个简单的程序,程序的功能是解释一个简单的 Stack Machine 语言,会输入一些序列然后按照文档的说明进行操作。
|
第一个实验是用 COOL 写一个简单的程序,程序的功能是解释一个简单的 Stack Machine 语言,会输入一些序列然后按照文档的说明进行操作。
|
||||||
|
|
||||||
推荐的实现方式是,定义一个 `StackCommand` 类,然后为每一条命令实现一个子类用来执行具体的操作。这里还给了一个工具类 `atoi.cl`,里面实现了 `String` 到 `int` 的转换。不需要实现错误处理,假设给出的序列都是合法的。
|
推荐的实现方式是,定义一个 `StackCommand` 类,然后为每一条命令实现一个子类用来执行具体的操作。这里还给了一个工具类 `atoi.cl`,里面实现了 `String` 到 `int` 的转换。不需要实现错误处理,假设给出的序列都是合法的。不过本人才疏学浅,就写了几个 if 就写完了,压根没写这么复杂。
|
||||||
|
|
||||||
|
首先我们需要一个 List 作为栈,这个可以从 `examples/list.cl` 里面抄过来,然后把数据类型改成 String 就可以了。然后就是处理输入输出,定义一个输入变量,一个大循环判断是不是 `input = "x"`,里面一个大 `if-else-then` 判断输入的命令,如果是 `d` 就调用前面抄过来的 `print_list`(需要修改一下格式和类型);如果是 `e` 需要再来一个 `if-else-then` 来处理求值操作;其他的就直接塞进栈里面,这里不做错误处理,假设都是合法的。具体到 `e` 命令里面,`pop` 并判断栈顶,如果是 `+`,`pop` 两次,调用 `a2i` 做运算然后再 `i2a` 变回字符串 `push` 到栈上;如果是 `s`,依然需要 `pop` 两次并保存 `pop` 出来的东西,然后逆序 `push` 进去就完成了交换操作。
|
||||||
|
|
||||||
|
主要的困难在于 COOL 的智障语法,其他的倒是没啥难度。
|
||||||
|
- 最智障的是它的 `expr`。绝大部分的东西都是个表达式,两个大括号也是表达式 `{ [[expr; ]]+}`,两个大括号中间的表达式后面必须跟分号(其他的不需要),`if - fi` 后面都必须跟分号我也是绷不住了。然后它的函数定义后面跟着那两个大括号是个语法符号(摆设)而不是 `expr`,这种就很不直觉,让我困惑了半天然后翻它的文法声明才发现这个事情。`feature::=ID( [ formal [[, formal]]∗ ] ) : TYPE { expr }`,也就是说,只能写一个表达式,不然就得再加一个单独的大括号然后里面写多个分号隔开的表达式。
|
||||||
|
- 其次是它的 `if-then-else` 居然不能没有 `else`!这导致我不得不像个傻子一样定义一个 `dummy(): Object {0};`,然后放在根本不需要的 `else` 子句里面。
|
||||||
|
- 还有它的 `while` 循环居然没有 `break` ?!
|
||||||
|
- `let` 语法也是究极奇葩,我是不能理解为什么要设计成这个样子。想定义一个局部变量都得加一层嵌套,这个嵌套多得让我觉得我 tm 是在写 `scheme`。
|
||||||
|
- 它的 `case` 也是奇葩,居然是用来做动态类型匹配的,匹配的是类型而不是值,和正常的 `switch-case` 完全不一样,倒是有点像 `rust` 里面的那种感觉。
|
||||||
|
|
||||||
|
测试的话,虽然 handout 里面说是直接 `make test` 然后对比输出,不过我也没看到它哪里有所谓的 reference implementation,自己看了看测例觉着没啥问题就行了。
|
||||||
@ -20,5 +20,8 @@ test: compile
|
|||||||
@echo stack.test
|
@echo stack.test
|
||||||
${CLASSDIR}/bin/spim -file stack.s < stack.test
|
${CLASSDIR}/bin/spim -file stack.s < stack.test
|
||||||
|
|
||||||
|
run: compile
|
||||||
|
${CLASSDIR}/bin/spim -file stack.s
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f *.s core *~
|
rm -f *.s core *~
|
||||||
|
|||||||
@ -33,30 +33,86 @@ class Cons inherits List {
|
|||||||
|
|
||||||
class Main inherits IO {
|
class Main inherits IO {
|
||||||
stack : List;
|
stack : List;
|
||||||
|
converter: A2I <- new A2I;
|
||||||
print_list(l: List) : Object {
|
print_list(l: List) : Object {
|
||||||
if l.isNil() then {
|
if l.isNil() then {
|
||||||
out_string("\n");
|
dummy();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
out_string(l.head());
|
out_string(l.head());
|
||||||
out_string(" ");
|
out_string("\n");
|
||||||
print_list(l.tail());
|
print_list(l.tail());
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pop_stack() : Object {
|
||||||
|
stack <- stack.tail()
|
||||||
|
};
|
||||||
|
|
||||||
|
push_stack(s: String) : Object {
|
||||||
|
stack <- stack.cons(s)
|
||||||
|
};
|
||||||
|
|
||||||
|
read_input() : String {
|
||||||
|
{
|
||||||
|
out_string(">");
|
||||||
|
in_string();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dummy() : Object {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
main() : Object {
|
main() : Object {
|
||||||
{
|
{
|
||||||
stack <- new List;
|
stack <- new List;
|
||||||
let x: String <- "" in {
|
let input: String <- read_input() in {
|
||||||
while (not(x = "x")) loop {
|
while (not(input = "x")) loop {
|
||||||
x <- in_string();
|
if (input = "e") then {
|
||||||
stack <- stack.cons(x);
|
if (not stack.isNil()) then
|
||||||
|
if (stack.head() = "+") then {
|
||||||
|
pop_stack();
|
||||||
|
let val1 : Int <- converter.a2i(stack.head()) in {
|
||||||
|
pop_stack();
|
||||||
|
let val2 : Int <- converter.a2i(stack.head()) in {
|
||||||
|
pop_stack();
|
||||||
|
push_stack(converter.i2a(val1 + val2));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (stack.head() = "s") then {
|
||||||
|
pop_stack();
|
||||||
|
let val1 : String <- stack.head() in {
|
||||||
|
pop_stack();
|
||||||
|
let val2 : String <- stack.head() in {
|
||||||
|
pop_stack();
|
||||||
|
push_stack(val1);
|
||||||
|
push_stack(val2);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dummy();
|
||||||
|
}
|
||||||
|
fi fi
|
||||||
|
else {
|
||||||
|
dummy();
|
||||||
|
}
|
||||||
|
fi;
|
||||||
|
}
|
||||||
|
else if (input = "d") then {
|
||||||
|
print_list(stack);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
push_stack(input);
|
||||||
|
}
|
||||||
|
fi fi;
|
||||||
|
input <- read_input();
|
||||||
}
|
}
|
||||||
pool;
|
pool;
|
||||||
};
|
};
|
||||||
stack <- stack.tail();
|
|
||||||
print_list(stack);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user