国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

從零開始寫個編譯器吧 - 符號分析,編寫 SignParser.java 文件

joyqi / 2063人閱讀

摘要:即創(chuàng)建一個文件,并寫下如下內(nèi)容。然后以此緩存一個字符串,然后,通過調(diào)用來將這個字符串分割成一個一個運算符,并生成。語言中根據(jù)運算符長度分開儲存的。具體來說,如果運算符對應(yīng)的字符串最短的是,最長的是。

上一章留下的那個大大的 TODO 表明,似乎還有什么東西沒寫完。沒錯,所以這一章我們來寫 Sign 狀態(tài)下的代碼。

所謂 Sign 狀態(tài),即是用來處理和生成 Sign 類型的 Token ,即運算符。諸如此類,都是運算符:

  

+、-、*、/、>=、==、&&、||

相對于 String 字符串啊、Identifier 標(biāo)示符之類的可以通過字符本身來劃分開端和結(jié)尾的類型,Sign 運算符運算符類型卻只能以既定形式來劃分開端和結(jié)尾。

例如,

  

"hello world" +-&& str_hello_wold

這段“源碼”可以被分割成如下一組 Token,

  

[""hello world"", " ", "+", "-", "&&", "str_hello_world"]

注意 Sign 運算符類型和 String 字符串類型、Identifier 標(biāo)示符劃分的區(qū)別。對于 “+”、“-” 兩個字符被各自分在一個 Token 中,而 “&&” 卻是由兩個字符組合成一個 Token。因為 tao 語言中沒有 “&” 運算符(沒有與位運算,也沒有短路與非短路與之分),卻擁有 “&&”。

此外,

  

>=

對于這個字符串,到底應(yīng)該劃分成

  

[">", "="]

這樣兩個運算符呢,還是應(yīng)該劃分成

  

[">="]

這樣一個運算符呢?

因為 “>"、"="、">=" 這三個都是合法的 tao 語言運算符。這里為了消除歧義,我規(guī)定必須劃分成 ">=" 。另外,如果存在多種劃分方式,盡量將短的運算符湊成長運算符。

OK,我現(xiàn)在決定把有關(guān) Sign 運算符類型的代碼多帶帶寫一個類。即創(chuàng)建一個 SignParser.java 文件,并寫下如下內(nèi)容。

package com.taozeyu.taolan.analysis;

class SignParser {

    static boolean inCharSet(char c) {
        //TODO
    }

    static List parse(String str)  {
        //TODO
    }
}

對于,LexicalAnalysis.java ,它只會調(diào)用 SignParser.inCharset(...) 來判斷當(dāng)前讀入的字符是不是某個既定運算符的某個字符。然后以此緩存一個字符串,然后,通過調(diào)用 SignParser.parse(str) 來將這個字符串分割成一個一個運算符,并生成 Token。

現(xiàn)把 LexicalAnalysis.java 中 boolean readChar(char c) 函數(shù)中TODO 消滅掉吧。

} else if(state == State.Sign) {

    if(SignParser.inCharSet(c)) {
        readBuffer.append(c);

    } else {
        List list = SignParser.parse(readBuffer.toString());
        for(String signStr:list) {
            createToken(Type.Sign, signStr);
        }
        createType = null;
        state = State.Normal;
        moveCursor = false;
    }

}

當(dāng)然,這里需要重載 createToken 一下。

private void createToken(Type type, String value) {
    Token token = new Token(type, value);
    tokenBuffer.addFirst(token);
    readBuffer = null;
}

OK,我們在回過頭來寫 SignParser.java 吧。首先,定義幾個靜態(tài)常量。

package com.taozeyu.taolan.analysis;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

class SignParser {

    private final static List> signSetList;
    private final static HashSet signCharSet;
    private final static int MaxLength, MinLength;

    static {
        String[] signArray = new String[] {
            "+", "-", "*", "/", "%", 
            ">", "<", ">=", "<=", "=", "!=", "==", "=~",
            "+=", "-=", "*=", "/=", "%=",
            "&&", "||", "!", "^",
            "&&=", "||=", "^=",
            "<<", ">>", "->", "<-",
            "?", ":",
            ".", ",", ";", "..",
            "(", ")", "[", "]", "{", "}",
            "@", "@@", "$",
        };

        int maxLength = Integer.MIN_VALUE,
            minLength = Integer.MAX_VALUE;

        signCharSet = new HashSet<>();
        for(String sign:signArray) {
            int length = sign.length();
            if(length > maxLength) {
                maxLength = length;
            }
            if(length < minLength) {
                minLength = length;
            }
            for(int i=0; i(maxLength - minLength + 1);
        for(int i=0; i< maxLength - minLength + 1; ++i) {
            signSetList.add(new HashSet<>());
        }
        for(String sign:signArray) {
            int length = sign.length();
            HashSet signSet = signSetList.get(length - minLength);
            signSet.add(sign);
        }
        MaxLength = maxLength;
        MinLength = minLength;
    }

    static boolean inCharSet(char c) {
        //TODO
    }

    static List parse(String str)  {
        //TODO
    }
}

static 塊中的 signArray 變量定義了 tao 語言所用到的所有運算符。之后的代碼解析 signArray 并生成 4 個靜態(tài)常量。

signCharSet:tao 語言所有運算符中可能出現(xiàn)的字符集合。

signSetList:tao 語言中根據(jù)運算符長度分開儲存的 List。具體來說,如果運算符對應(yīng)的字符串最短的 length 是 n,最長的是 m。那么 List 的索引范圍從 0 到 (m - n) 分別儲存字符 length 從 n 到 m 的所有運算符。

MinLength:運算符中字符串 length 的最小長度。

MaxLength:運算符中字符串 length 的最大長度。

然后是填滿那兩個寫著 TODO 的函數(shù)。

static boolean inCharSet(char c) {
    return signCharSet.contains(c);
}

static List parse(String str) throws LexicalAnalysisException {
    LinkedList rsContainer = new LinkedList<>(); 
    int startIndex = 0;
    while(startIndex < str.length()) {
        String matchStr = match(startIndex, str);
        if(matchStr == null) {
            throw new LexicalAnalysisException(str.substring(startIndex));
        } else {
            rsContainer.add(matchStr);
            startIndex += matchStr.length();
        }
    }
    return rsContainer;
}

private static String match(int startIndex, String str) {
    String matchStr = null;
    int length = str.length() - startIndex;
    length = Math.min(length, MaxLength);
    if(length >= MinLength) {
        for(int i=length - MinLength; i>=0; i--) {
            int matchLength = i + MinLength;
            HashSet signSet = signSetList.get(i);
            matchStr = str.substring(startIndex, startIndex + matchLength);
            if(signSet.contains(matchStr)) {
                break;
            }
            matchStr = null;
        }
    }
    return matchStr;
}

OK,搞定。特別的,如果 parse 劃分運算符過程中發(fā)現(xiàn)留下一個尾巴匹配不了,那么將拋出一個詞法錯誤異常。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64265.html

相關(guān)文章

  • 從零開始寫個譯器系列

    摘要:是的,這個系列將呈現(xiàn)一個完整的編譯器從無到有的過程。但在寫這個編譯器的過程中,我可不會偷工減料,該有的一定會寫上的。該語言的虛擬機將運行于之上,同時編譯器將使用實現(xiàn)。我早有寫編譯器的想法之前沒寫過,故希望一邊寫編譯器一邊完成這個系列。 是的,這個系列將呈現(xiàn)一個完整的編譯器從無到有的過程。當(dāng)然,為了保證該系列內(nèi)容的簡潔(也為了降低難度),僅僅保證編譯器的最低要求,即僅能用。但在寫這個編譯...

    genedna 評論0 收藏0
  • 從零開始寫個譯器 - 開始寫詞法分析器(3)

    摘要:在之前的章節(jié)第章從零開始寫個編譯器吧開始寫詞法分析器中我有說,我將函數(shù)設(shè)計成主動調(diào)用的形式,而則是被動調(diào)用的形式。接下來本系列將進(jìn)入編寫語法分析器的階段,不過在此之前,我將抽出一點時間介紹一下語言本身。 上周周末旅游去了,就沒更新了,雖然回到海拔0m的地區(qū),不過目前似乎還在缺氧,所以本次就少更點吧。 這章將結(jié)束詞法分析的部分。 在之前的章節(jié)(第7章從零開始寫個編譯器吧 - 開始寫詞...

    Barrior 評論0 收藏0
  • 從零開始寫個譯器 - tao語言的詞法分析器(Tokenizer)的類型定義

    摘要:要為語言設(shè)計詞法分析器,首先得知道語言是一種什么樣的語言。,不過首先我們得把詞法分析器能生成的單詞類型定義好了。 要為 tao 語言設(shè)計詞法分析器,首先得知道 tao 語言是一種什么樣的語言。不過呢,我腦海里還沒有 tao 語言具體形象。我還是先貼一段 tao 語言的代碼,大概展示下這是怎么回事吧。 def say_hello_world(who) print hello ...

    qpal 評論0 收藏0
  • 從零開始寫個譯器 - Token.java 文件編寫

    摘要:現(xiàn)在,讓我們來動手寫編譯器的第一個個文件吧。如其名字所示,這個類實例化的對象用于表示詞法分析器的產(chǎn)物。我希望詞法分析器從源代碼中提取出語素,并根據(jù)上下文推測出單詞類型,從而構(gòu)造出對象。只需要構(gòu)造出類型即可,進(jìn)一步細(xì)分將在的構(gòu)造函數(shù)中進(jìn)行。 現(xiàn)在,讓我們來動手寫編譯器的第一個個java文件吧。本章要寫的類,是Token類。如其名字所示,這個類實例化的對象用于表示詞法分析器 Tokeniz...

    Eirunye 評論0 收藏0
  • 從零開始寫個譯器 - Parser 語法分析

    摘要:這樣的程序或稱工具有很多現(xiàn)成的可供選擇包括在平臺上可用的,但既然我這個系列叫做從零開始寫個編譯器吧,那顯然如果我用現(xiàn)成的工具,那是犯規(guī)行為。 Parser(語法分析器)的編寫相對于 Tokenizer (詞法分析器)要復(fù)雜得多,因此,在編寫之前可能也會鋪墊得更多一些。當(dāng)然,本系列旨在寫出一個編譯器,所以理論方面只會簡單介紹 tao 語言所涉及的部分。 之前的幾章中,我純手寫了tao 語...

    fai1017 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<