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

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

Java實現編譯器詞法解析入門

更新時間:2021-04-30 10:51:02 來源:動力節點 瀏覽988次

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

1+2*3+4, 經過編譯后轉換成:

t0 = 1

t1 = 2

t2 = 3

t1 *= t2

t0 += t1

t1 = 4

t0 += t1

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

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

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

1+2*3+4; 可以分割成 1+, 2*, 3+, 4; 但這些子字符串沒有實質意義,有意義的分割是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 用于判斷輸入的字符是否是數字或字母。lex() 函數開始了詞法分析的流程,31到40行從控制臺讀入語句,語句以"end"表明結束,例如在控制臺輸入:

1+2*3+4;

end

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

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

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

接下來我們在main函數中,跑起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: ;

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

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

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 欧美国产亚洲一区 | 五月天婷亚洲天综合网精品偷 | 亚洲精品香蕉一区二区在线观看 | 成人黄色小视频 | 久久精品视频网 | 久久99久久99精品免观看不卡 | 一本到中文字幕高清不卡在线 | 欧美毛片在线播放观看 | 波多野结中文字幕在线69视频 | 成人性色生活片全黄 | 色综合天天综合网看在线影院 | 国产欧美亚洲精品第二区首页 | 国产乱在线观看视频 | 亚洲精品一区二区久久久久 | 亚洲国产99| 久久99国产乱子伦精品免费 | 美女黄频免费观看 | 国产在线视频一区 | 青娱乐国产在线视频 | 天天色天天射综合网 | 亚洲综合中文网 | 精品久久久久久蜜臂a∨ | aaa毛片视频免费观看 | 奇米视频在线 | 国产欧美日韩中文久久 | 国产极品福利视频在线观看 | 奇米影视第四色777 奇米影视第四色7777 | 香蕉视频在线免费看 | 夜色私人影院永久地址入口 | 国产区精品一区二区不卡中文 | 五月天亚洲婷婷 | 日本一区二区三区精品 | 天天干妹子 | 九九热精品视频在线 | 网红福利在线 | 日韩精品中文字幕一区二区三区 | 丁香久久 | 99ri国产| 久青草视频97国内免费影视 | 天天摸天天碰色综合网 | 国产成人18黄网站免费 |