我正在閱讀編譯器設計書,它說「編譯器有解決中綴表達式的問題,因爲它在確定操作數的優先級方面有困難,你應該總是把它轉換成postfix然後解析表達式」。與後綴表達式相比,爲什麼編譯器在解析中綴表達式時遇到困難?
與後綴表達式相比,爲什麼編譯器在解析中綴表達式時遇到困難?
我正在閱讀編譯器設計書,它說「編譯器有解決中綴表達式的問題,因爲它在確定操作數的優先級方面有困難,你應該總是把它轉換成postfix然後解析表達式」。與後綴表達式相比,爲什麼編譯器在解析中綴表達式時遇到困難?
與後綴表達式相比,爲什麼編譯器在解析中綴表達式時遇到困難?
考慮a + b * c/d e
。根據傳統的優先規則,這應該被解析爲a + ((b * c)/d)
。只需從右向左閱讀將產生((a + b) * c)/d
,這不是你想要的。編譯器需要知道每個操作員的優先級(和關聯性)並將其考慮在內。
另一方面,後綴表達式顯式優先。例如,上面的第一個表達式相當於b c * d/a +
。
不知道我是否知道作者在做什麼「應該始終將其轉換爲postfix然後解析表達式」,但這是主旨。 (在我看來,轉換到後綴需要解析已經)。
你可能會認爲它是編譯器找出括號內容的問題。
考慮兩個運營商,*
和+
如果你有一箇中間符號,你可以有之類的語句
X = A * B + C
其與操作順序的無知,編譯器可能會解釋爲
X = (A * B) + C
或
X = A * (B + C)
如果以後綴表示法編寫,則不存在不和諧情緒。這就像舊的惠普計算器。有一個棧,一個操作員彈出兩個操作數出棧,並推動將結果返回
所以第一個公式將看起來更像(忽略分配給X,技術上另算)
A B * C +
而第二個
A B C + *
這就是說,你的發言弄得我一點,因爲我覺得修復張貼在修復將是做一個編譯器,而不是一個簡單的動作編譯器的一個意向
綴解析是具有遞歸下降語法分析器相當簡單的,如下面的短的Java實施例說明。類似的東西可以很容易地用於表達式樹的生成。
有很多事情,可能是有意義推遲到不同的階段,但我從來沒有見過這個地方重新排序,使多大意義,因爲對原始輸入轉換構建解析樹前的情況。
也許這本書只是過時了嗎?這是哪本書的引用?
public class InfixProcessor {
static final String[] OPERATORS = {"-+", "/*"};
static StreamTokenizer tokenizer;
static double process(String s) throws IOException {
tokenizer = new StreamTokenizer(new StringReader(s));
tokenizer.ordinaryChar('-');
tokenizer.ordinaryChar('/');
tokenizer.nextToken();
return processInfix(0);
}
static double processInfix(int precedence) throws IOException {
if (precedence >= OPERATORS.length) {
return processPrimary();
}
double result = processInfix(precedence + 1);
while (OPERATORS[precedence].indexOf((char) tokenizer.ttype) != -1) {
int op = tokenizer.ttype;
tokenizer.nextToken();
double right = processInfix(precedence + 1);
switch (op) {
case '+': result += right; break;
case '-': result -= right; break;
case '*': result *= right; break;
case '/': result /= right; break;
default: throw new RuntimeException();
}
}
return result;
}
static double processPrimary() throws IOException {
if (tokenizer.ttype != StreamTokenizer.TT_NUMBER) {
throw new RuntimeException("Number expected");
}
double result = tokenizer.nval;
tokenizer.nextToken();
return result;
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.print("Expression> ");
String expr = reader.readLine();
if (expr == null || expr.isEmpty()) break;
System.out.println("Result: " + process(expr));
}
}
}
編譯器在解析前綴,中綴或後綴順序中的表達式時沒有任何問題。語法是easy供編譯器處理。
雖然你看不到很多使用前綴或後綴表示法的編譯器。那是因爲人不習慣。幾乎所有的Forth人都逃避了Postfix,他們的編譯器幾乎是微不足道的,這使得它成爲運行它的小型機器的理想選擇。第四,程序員學會了熱愛postfix,並且憑藉一點經驗相處得很好。
[我不知道是誰告訴「你應該總是把它轉換爲postfix然後解析表達式」,但這是無稽之談。