# if 陳述

December 18, 2021

if…else 這類語法，是語言中最基本的條件控制語法。

## Toy 語法

``````name = input('名稱：')
if name == '' {
name = 'Guest'
}
println('Hello, {0}'.format(name))
``````

`if` 可以搭配 `else`，在 `if` 條件不成立時，執行 `else` 中定義的程式碼，上例也可以這麼寫：

``````name = input('名稱：')
if name == '' {
println('Hello, {0}'.format('Guest'))
}
else {
println('Hello, {0}'.format(name))
}
``````

``````score = Number.parseInt(input('輸入分數：'))
if score >= 90 {
println('得 A')
}
else {
if score >= 80 and score < 90 {
println('得 B')
}
else {
if score >= 70 and score < 80 {
println('得 C')
}
else {
if score >= 60 and score < 70 {
println('得 D')
}
else {
println('不及格')
}
}
}
}
``````

``````name = input('名稱：')
println('Hello, {0}'.format('Guest' if name == '' else name))
``````

``````input = Number.parseInt(input('輸入整數：'))
desc = '奇數' if input % 2 == 1 else '偶數'
println('{0} 為 {1}'.format(input, desc))
``````

## Toy 實作

``````class If {
constructor(cond, trueStmt, falseStmt) {
this.cond = cond;
this.trueStmt = trueStmt;
this.falseStmt = falseStmt;
}

evaluate(context) {
if(this.cond.evaluate(context).value) {
return this.trueStmt.evaluate(context);
}
return this.falseStmt.evaluate(context);
}
}
``````

`if` 陳述句的難處，或者說 Toy Lang 中其他具有區塊結構的陳述句，它們的難處就在於，如何知道區塊的邊界，也就是說，難處還是在於 Parser。

``````class Stmt {
constructor(lineCount) {
this.lineCount = lineCount;
}
}
``````

``````StmtSequence.EMPTY = {
lineCount : 0,
// We don't care about emtpy statements so the lineNumber 0 is enough.
lineNumber : 0,
evaluate(context) {
return context;
}
};
``````

``````function ifLineCount(trueStmt, falseStmt) {
const trueLineCount = trueStmt.lineCount;
const falseLineCount = falseStmt.lineCount;
return 2 + trueLineCount + (falseLineCount ? falseLineCount + 2 : 0)
}
class If extends Stmt {
constructor(boolean, trueStmt, falseStmt) {
super(ifLineCount(trueStmt, falseStmt));
...
``````

``````function isElseLine(tokenableLine) {
}

function createIf(tokenableLines, argTokenable) {
const remains = tokenableLines.slice(1);
const trueStmt = LINE_PARSER.parse(remains);
const trueLineCount = trueStmt.lineCount;

const i = trueLineCount + 1;
const falseStmt = isElseLine(remains[i]) ?
LINE_PARSER.parse(remains.slice(i + 1)) :
StmtSequence.EMPTY;
const falseLineCount = falseStmt.lineCount;

const linesAfterIfElse = tokenableLines.slice(
2 + trueLineCount + (falseLineCount ? falseLineCount + 2 : 0)
);

return new StmtSequence(
new If(
EXPR_PARSER.parse(argTokenable),
trueStmt,
falseStmt
),
LINE_PARSER.parse(linesAfterIfElse),
tokenableLines[0].lineNumber
);
}
``````