Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> 編譯器開發系列--Ocelot語言5.表達式的有效性檢查,--ocelot有效性

編譯器開發系列--Ocelot語言5.表達式的有效性檢查,--ocelot有效性

編輯:關於android開發

編譯器開發系列--Ocelot語言5.表達式的有效性檢查,--ocelot有效性


本篇將對“1=3”“&5”這樣無法求值的不正確的表達式進行檢查。

將檢查如下這些問題。
●為無法賦值的表達式賦值(例:1 = 2 + 2)
●使用非法的函數名調用函數(例:"string"("%d\n", i))
●操作數非法的數組引用(例:1[0])
●操作數非法的成員引用(例:1.memb)
●操作數非法的指針間接引用(例:1->memb)
●對非指針的對象取值(例:*1)
●對非左值的表達式取地址

具體例子以及問題的檢測方法如表10.1所示,其中包括了剛才列舉的問題。

非指針類型取值操作的檢查

    /*非指針類型取值操作的檢查
     * 表示取值運算符(*)的DereferenceNode的處理。
     * 該方法檢查取值運算符的操作數的類型是否為指針。
     */
    // #@@range/DereferenceNode{
    public Void visit(DereferenceNode node) {
    	/*
    	 * 首先,通過super.visit(node) 調用基類Visitor 的方法遍歷操作數(node.expr())
		(即檢查操作數)。
    	 */
        super.visit(node);
        /*
         * 接著,調用操作數node.expr() 的isPointer 方法,檢查操作數的類型是否是指針,
			即檢查是否可以進行取值。如果無法取值,則調用undereferableError 方法輸出編譯錯誤。
         */
        if (! node.expr().isPointer()) {
            undereferableError(node.location());
        }
        /*
         * 最後,調用handleImplicitAddress 方法對數組類型和函數類型進行特別處理。該處
			理還和接下來AddressNode 的處理相關,
         */
        handleImplicitAddress(node);
        return null;
    }

獲取非左值表達式地址的檢查

    /*獲取非左值表達式地址的檢查
     * 檢查操作數是否為左值。表示地址運算符的AddressNode 的處理
     */
    // #@@range/AddressNode{
    public Void visit(AddressNode node) {
        super.visit(node);
        /*
         * 首先對node.expr() 調用isLvalue 方法,檢查&expr 中的expr 是否是可以進行取
			址操作的表達式。
			ExprNode#isLvalue 是檢查該節點的表達式是否能夠獲取地址的方法。
         */
        if (! node.expr().isLvalue()) {
            semanticError(node.location(), "invalid expression for &");
        }
        /*
         * 剩余的語句用於確定AddressNode 的類型。通常node.expr().isLoadable() 會
			返回true,即執行else 部分的處理。&expr 的類型是指向expr 類型的指針,因此指向
			node.expr().type() 的指針類型可以作為節點整體的類型來使用。
         */
        Type base = node.expr().type();
        /*
         * 在將puts 的類型設置為指向函數的指針的同時,還必須將&puts 的類型也設置為指向函
			數的指針。
			node.expr() 的類型是數組或函數的情況下進行特別處理,使得&puts 的類型
			和puts 的類型相一致。
         */
        if (! node.expr().isLoadable()) {
            // node.expr.type is already pointer.
            node.setType(base);
        }
        else {
            node.setType(typeTable.pointerTo(base));
        }
        return null;
    }

隱式的指針生成

單個數組類型或函數類型的變量表示數組或函數的地址。例如,假設變量puts 的類型為函數類型(一般稱為函數指針),那麼puts 和&puts 得到的值是相同的。

    /*
     * handleImplicitAddress 方法將數組類型或函數類型轉換為了指向
		數組或函數類型的指針,即隱式地生成指針類型。
     */
    private void handleImplicitAddress(LHSNode node) {
        if (! node.isLoadable()) {
            Type t = node.type();
            if (t.isArray()) {
                // int[4] ary; ary; should generate int*
                node.setType(typeTable.pointerTo(t.baseType()));
            }
            else {
                node.setType(typeTable.pointerTo(t));
            }
        }
    }

puts 是指向函數的指針,因此它的取值運算*puts 的結果是函數類型,但這樣又會隱式地轉換為指向函數的指針。*puts 還是指向函數的指針,因此仍然可以進行取值運算,仍然會轉換為指向函數的指針。像這樣可以無限重復下去。所以C 語言中“&puts”“puts”“*puts”“**puts”“***puts”的值都是相同的。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved