大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節(jié)點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 Java實現(xiàn)編譯器詞法解析入門

Java實現(xiàn)編譯器詞法解析入門

更新時間:2021-04-30 10:51:02 來源:動力節(jié)點 瀏覽1030次

編譯器作用就是將一種計算機無法理解的文本,轉(zhuǎn)譯成計算機能執(zhí)行的語句,我們要做的編譯器如下,將帶有加法和乘法的算術式子,轉(zhuǎn)譯成機器能執(zhí)行的匯編語句,例如語句:

1+2*3+4, 經(jīng)過編譯后轉(zhuǎn)換成:

t0 = 1

t1 = 2

t2 = 3

t1 *= t2

t0 += t1

t1 = 4

t0 += t1

t0, t1 是對寄存器的模擬,上述語句基本上就類似計算機能執(zhí)行的匯編語句了。

本章首先專注于詞法解析的探討。

編譯原理由兩部分組成,一是詞法分析,一是語義分析。先說詞法分析,詞法分析就是將一個語句分割成若干個有意義的字符串的組合,然后給分割的字符串打標簽。例如語句:

1+2*3+4; 可以分割成 1+, 2*, 3+, 4; 但這些子字符串沒有實質(zhì)意義,有意義的分割是1, +, 2, * , 3, +, 4, ;. 接著就是給這些分割后的字符串打標簽,例如給1, 2, 3, 4 打上的標簽是NUM_OR_ID, + 打的標簽是PLUS, *的標簽是TIMES, ;的標簽是SEMI, 好了,看看詞法分析的代碼,大家可能更容易理解:

Lexer.java:

import java.util.Scanner;  
public class Lexer {  
    public static final int  EOI = 0;  
    public static final int  SEMI = 1;  
    public static final int  PLUS = 2;  
    public static final int  TIMES = 3;  
    public static final int  LP = 4;  
    public static final int  RP = 5;  
    public static final int  NUM_OR_ID = 6;        
    private int lookAhead = -1;        
    public String yytext = "";  
    public int yyleng = 0;  
    public int yylineno = 0;       
    private String input_buffer = "";  
    private String current = "";        
    private boolean isAlnum(char c) {  
        if (Character.isAlphabetic(c) == true ||  
                Character.isDigit(c) == true) {  
            return true;  
        }            
        return false;  
    }  
      
    private int lex() {        
        while (true) {  
                while (current == "") {  
                Scanner s = new Scanner(System.in);  
                while (true) {  
                    String line = s.nextLine();  
                    if (line.equals("end")) {  
                        break;  
                    }  
                    input_buffer += line;  
                }  
                s.close();                    
                if (input_buffer.length() == 0) {  
                    current = "";  
                    return EOI;  
                }                    
                current = input_buffer;  
                ++yylineno;  
                current.trim();  
            }//while (current != "")  
                    for (int i = 0; i < current.length(); i++) {                        
                    yyleng = 0;  
                    yytext = current.substring(0, 1);  
                    switch (current.charAt(i)) {  
                    case ';': current = current.substring(1); return SEMI;  
                    case '+': current = current.substring(1); return PLUS;  
                    case '*': current = current.substring(1);return TIMES;  
                    case '(': current = current.substring(1);return LP;  
                    case ')': current = current.substring(1);return RP;                        
                    case '\n':  
                    case '\t':  
                    case ' ': current = current.substring(1); break;                        
                    default:  
                        if (isAlnum(current.charAt(i)) == false) {  
                            System.out.println("Ignoring illegal input: " + current.charAt(i));  
                        }  
                        else {                                
                            while (isAlnum(current.charAt(i))) {  
                                i++;  
                                yyleng++;  
                            } // while (isAlnum(current.charAt(i)))                                
                            yytext = current.substring(0, yyleng);  
                            current = current.substring(yyleng);   
                            return NUM_OR_ID;  
                        }                            
                        break;                            
                    } //switch (current.charAt(i))  
                }//  for (int i = 0; i < current.length(); i++)                 
        }//while (true)   
    }//lex()        
    public boolean match(int token) {  
        if (lookAhead == -1) {  
            lookAhead = lex();  
        }            
        return token == lookAhead;  
    }        
    public void advance() {  
        lookAhead = lex();  
    }        
    public void runLexer() {  
        while (!match(EOI)) {  
            System.out.println("Token: " + token() + " ,Symbol: " + yytext );  
            advance();  
        }  
    }        
    private String token() {  
        String token = "";  
        switch (lookAhead) {  
        case EOI:  
            token = "EOI";  
            break;  
        case PLUS:  
            token = "PLUS";  
            break;  
        case TIMES:  
            token = "TIMES";  
            break;  
        case NUM_OR_ID:  
            token = "NUM_OR_ID";  
            break;  
        case SEMI:  
            token = "SEMI";  
            break;  
        case LP:  
            token = "LP";  
            break;  
        case RP:  
            token = "RP";  
            break;  
        }            
        return token;  
    }  
}  

代碼中2到6行是對標簽的定義,其中LP 代表左括號(, RP代表右括號), EOI 表示語句末尾, 第10行的lookAhead 變量用于表明當前分割的字符串指向的標簽值,yytext用于存儲當前正在分析的字符串,yyleng是當前分析的字符串的長度,yylineno是當前分析的字符串所在的行號。input_buffer 用于存儲要分析的語句例如: 1+2*3+4; isAlNum 用于判斷輸入的字符是否是數(shù)字或字母。lex() 函數(shù)開始了詞法分析的流程,31到40行從控制臺讀入語句,語句以"end"表明結(jié)束,例如在控制臺輸入:

1+2*3+4;

end

回車后,從52行開始執(zhí)行詞法解析流程。以上面的輸入為例,input_buffer 存儲語句 1+2*3+4, 由于第一個字符是 1, 在for 循環(huán)中,落入switch 的default 部分,isAlNum 返回為真,yyleng 自加后值為1, yytext 存儲的字符串就是 "1", current前進一個字符變?yōu)?2*3+4, 再次執(zhí)行l(wèi)ex(), 則解析的字符是+, 在for 循環(huán)中,落入switch的case '+' 分支,于是yytext為"+", 返回的標簽就是PLUS依次類推, advance 調(diào)用一次, lex()就執(zhí)行一次詞法分析,當lex執(zhí)行若干次后,語句1+2*3+4;會被分解成1, +, 2, *, 3, +, 4, ; 。字符串1, 2, 3, 4具有的標簽是NUM_OR_ID, + 具有的標簽是PLUS, *的標簽是TIMES, ;的標簽是SEMI.

runLexer() 將驅(qū)動詞法解析器,執(zhí)行解析流程,如果解析到的當前字符串,其標簽不是EOI(end of input), 也就是沒有達到輸入末尾,那么就打印出當前分割的字符串和它所屬的標簽,接著調(diào)用advance() 進行下一次解析。

match, advance 會被稍后我們將看到的語法解析器調(diào)用。

接下來我們在main函數(shù)中,跑起Lexer, 看看詞法解析過程:

Compiler.java

public class Compiler {    
    public static void main(String[] args) {  
        Lexer lexer = new Lexer();  
        //Parser parser = new Parser(lexer);  
        //parser.statements();  
        lexer.runLexer();  
    }  
}  

在eclipse 中運行給定代碼,然后在控制臺中輸入如下:

1+2*3+4;

end

程序運行后輸出:

Token: NUM_OR_ID ,Symbol: 1

Token: PLUS ,Symbol: +

Token: NUM_OR_ID ,Symbol: 2

Token: TIMES ,Symbol: *

Token: NUM_OR_ID ,Symbol: 3

Token: PLUS ,Symbol: +

Token: NUM_OR_ID ,Symbol: 4

Token: SEMI ,Symbol: ;

以上就是動力節(jié)點小編介紹的"Java實現(xiàn)編譯器詞法解析入門"的內(nèi)容,希望對大家有幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為您服務。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 中文在线亚洲 | 日本香蕉网 | 久久久精| 亚洲毛片| 国内精品自在欧美一区 | 图片专区亚洲 欧美 另类 | 欧美高清日韩 | 国产一级毛片午夜 | 精品老司机在线观看视频 | 成人欧美视频在线观看播放 | 日本黄 色 成 年 人免费观看 | 人人干人人模 | 欧美劲爆第一页 | 久久99精品国产自在现线小黄鸭 | 男女一级毛片免费播放 | 狠狠干夜夜操 | 亚洲国产精品看片在线观看 | 亚洲国产清纯 | 亚洲和欧美毛片久久久久 | 国产色综合天天综合网 | 亚洲黄色免费在线观看 | 全黄h全肉边做边吃奶在线观看 | 亚洲综合在线播放 | 久久成人国产精品 | 亚洲精品字幕一区二区三区 | 久久99热精品免费观看无卡顿 | 久久a毛片| 午夜在线观看网站 | 久久香蕉影视 | 亚洲成aⅴ人片在线观 | 奇米影视777第四色 奇米影视777狠狠狠888不卡 | 在线欧美国产 | 免费一级a毛片在线播放视 免费一级成人毛片 | 精品国产免费一区二区三区 | 国产视频一二 | 插插天天 | 国产精品玖玖玖在线观看 | 天天摸日日 | 久久国产精品国产精品 | 日日操日日摸 | jizzjizz中国丝袜美女 |