大战熟女丰满人妻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视频在线国产 | 国内精品久久久久久久影视麻豆 | 午夜精品久久久久久久 | 亚洲精品国产精品乱码不卞 | 久久最稳定资源站在线 | 亚洲乱淫| 黄黄网| 特黄特黄aaaa级毛片免费看 | 天天爽天天干 | 亚洲精品一二三四区 | 中文字幕亚洲无线码在线一区 | 中文字幕在线观看日本 | a亚洲视频| 欧美成人激情在线 | 高清视频在线播放 | 美女hdxxxx中国| 一本大道香蕉大在线最新 | 亚洲国产99在线精品一区69堂 | 国产伦久视频免费观看 视频 | 九九影院韩国理伦片 | 亚洲国产欧美精品 | 久夜色精品国产一区二区三区 | 久久精品国产精品亚洲 | 日韩中文字幕在线有码视频网 | 久久影院朴妮唛 | 免费观看午夜在线欧差毛片 | 欧美80岁老妇一级毛片 | 日本一二区视频 | 午夜宅男免费完整在线观看 | 亚洲四虎永久在线播放 | 在线91精品亚洲网站精品成人 | 国产精品一区二区久久精品 | 日本高清在线一区二区三区 | 99久久成人 | 欧美日韩视频在线 | 激情影院免费看 | 国产亚洲第一 |