1. 程式人生 > >C語言源程式詞法分析器(Java實現)

C語言源程式詞法分析器(Java實現)

一. 介紹

詞法分析器,又稱掃描器,輸入源程式,進行詞法分析,輸出單詞符號。詞法分析僅僅是編譯程式工作中的一部分,編譯程式一般可以劃分為5個階段:詞法分析,語法分析,語義分析與中間程式碼產生,優化,目的碼生成。我們這裡編寫一個簡單的C語言源程式詞法分析器。

二. 目的

設計並實現一個包含預處理功能的詞法分析程式,加深對編譯中詞法分析過程的理解。

四. 要求

1、實現預處理功能

源程式中可能包含有對程式執行無意義的符號,要求將其剔除。
首先編制一個源程式的輸入過程,從鍵盤、檔案或文字框輸入若干行語句,依次存入輸入緩衝區(字元型資料);然後編制一個預處理子程式,去掉輸入串中的回車符、換行符和跳格符等編輯性文字;把多個空白符合併為一個;去掉註釋。

2、實現詞法分析功能

輸入:所給文法的源程式字串。
輸出:二元組(syn,token或sum)構成的序列。其中,
syn為單詞種別碼。
Token為存放的單詞自身字串。
Sum為整型常量。
具體實現時,可以將單詞的二元組用結構進行處理。

3、待分析的C語言子集的詞法

1)關鍵字
main if then while do static int double struct break else long switch case typedef char return const float short continue for void default sizeof do
所有的關鍵字都是小寫。
2)運算子和界符
+ - * / : := < <> <= > >= = ; ( ) #
3)其他標記ID和NUM
通過以下正規式定義其他標記:
ID→letter(letter|digit)*
NUM→digit digit*
letter→a|…|z|A|…|Z
digit→0|…|9…
4)空格由空白、製表符和換行符組成
空格一般用來分隔ID、NUM、專用符號和關鍵字,詞法分析階段通常被忽略。

4、各種單詞符號對應的種別碼

單詞符號    種別碼        單詞符號    種別碼       
main        1            void       23     
if          2            sizeof     24     
then        3            ID         25  
while       4            NUM        26
do          5             +         27   
static      6             -         28
int 7 * 29 double 8 / 30 struct 9 ** 31 break 10 == 32 else 11 < 33 long 12 <> 34 switch 13 <= 35 case 14 > 36 typedef 15 >= 37 char 16 = 38 return 17 [ 39 const 18 ] 40 float 19 ; 41 short 20 ( 42 continue 21 ) 43 for 22 # 0

五. 原始碼

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class LexicalAnalyzer {

    static String[] rwtab=new String[]{"main","if","then","while","do","static",
                                "int","double","struct","break","else",
                                "long","switch","case","typedef","char",
                                "return","const","float","short","continue",
                                "for","void","sizeof"};   //已經定義的24個關鍵字,種別碼從1開始
    static String storage="";   //儲存源程式字串
    static StringBuilder token=new StringBuilder("");     //儲存單詞自身組成的字串

    static char ch;
    static int index;
    static int syn, sum=0, row;

     //分析器
    static void analyzer(){
        token.delete(0, token.length());                //置空token物件,清除
        ch=storage.charAt(index++);
        while(ch==' '){
            ch=storage.charAt(index++);      //去除空格符號
        }

        if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){         //可能是關鍵字或者自定義的識別符號
            while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
                token.append(ch);
                ch=storage.charAt(index++);
            }
            index--;      //此次識別的最後一個字元未識別入,需要將標記退原處 
            syn=25;       //預設為識別出的字串為自定義的識別符號,種別碼為25
            String s=token.toString();
            for(int i=0; i<rwtab.length; i++){
                if(s.equals(rwtab[i])){     
                    syn=i+1;
                    break;        //識別出是關鍵字
                }
            }
        }
        else if((ch>='0'&&ch<='9')){
            sum=0;
            while((ch>='0'&&ch<='9')){
                sum=sum*10+ch-'0';
                ch=storage.charAt(index++);
            }
            index--;
            syn=26;
        }
        else switch(ch){

        case '<':
            token.append(ch);
            ch=storage.charAt(index++);
            if(ch=='='){
                token.append(ch);
                syn=35;
            }
            else if(ch=='>'){
                token.append(ch);
                syn=34;
            }
            else{
                syn=33;
                index--;
            }
            break;
        case '>':
            token.append(ch);
            ch=storage.charAt(index++);
            if(ch=='='){
                token.append(ch);
                syn=37;
            }
            else{
                syn=36;
                index--;
            }
            break;
        case '*':
            token.append(ch);
            ch=storage.charAt(index++);
            if(ch=='*'){
                token.append(ch);
                syn=31;
            }
            else{
                syn=13;
                index--;
            }
            break;
        case '=':
            token.append(ch);
            ch=storage.charAt(index++);
            if(ch=='='){
                syn=32;
                token.append(ch);
            }
            else{
                syn=38;
                index--;
            }
            break;
        case '/':
            token.append(ch);
            ch=storage.charAt(index++);
            if(ch=='/'){
                while(ch!=' '){
                    ch=storage.charAt(index++);  //忽略掉註釋,以空格為界定
                }
                syn=-2;
                break;
            }
            else{
                syn=30;
                index--;
            }
            break;
        case '+':
            syn=27;
            token.append(ch);
            break;
        case '-':
            syn=28;
            token.append(ch);
            break;
        case ';':
            syn=41;
            token.append(ch);
            break;
        case '(':
            syn=42;
            token.append(ch);
            break;
        case ')':
            syn=43;
            token.append(ch);
            break;
        case '#':
            syn=0;
            token.append(ch);
            break;
        case '\n':
            syn=-2;
            token.append(ch);
            break;
        default:
            syn=-1;
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));
        index=0;
        row=1;
        String tempString;
        System.out.println("請輸入C語言源程式字串(以#結尾):");

        //輸入過程
        try{
            do{
                tempString=stdin.readLine();
                storage+=tempString;
                ch=tempString.charAt(tempString.length()-1);  //得到一行中最後一個字元
            }while(ch!='#');        //輸入以#字元結尾
        }catch(IOException e){
            e.printStackTrace();
        }

        index=0; 
        //輸出過程
        do{
            analyzer();
            switch(syn){
            case 26:
                System.out.println("("+syn+","+sum+")");
                break;
            case -1:
                System.out.println("Error in row"+row+"!");
                break;
            case -2:
                break;
            default:
                System.out.println("("+syn+","+token+")");
            }
        }while(syn!=0);
    }

}

六. 執行結果

這裡寫圖片描述

相關推薦

C語言源程式詞法分析器Java實現

一. 介紹 詞法分析器,又稱掃描器,輸入源程式,進行詞法分析,輸出單詞符號。詞法分析僅僅是編譯程式工作中的一部分,編譯程式一般可以劃分為5個階段:詞法分析,語法分析,語義分析與中間程式碼產生,優化,目的碼生成。我們這裡編寫一個簡單的C語言源程式詞法分析器。

c詞法分析程式java實現原始碼1

package wordanalyse;   import java.io.*; public class InputFile {  private String path="";  public InputFile(){     }  /**   * @author 楊武兵   *function:從鍵盤獲

1117-C語言實驗——求絕對值選擇結構-JAVA

C語言實驗——求絕對值(選擇結構) Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 從鍵盤上輸入任意一個整數,然後輸

一個簡單C語言詞法分析器

一個簡單C語言的詞法分析器 語言的詞法構成: 識別符號 id 同C語言識別符號 常量 num 數字 ch 字元 str 字串 關鍵字 kw_int int kw_char char kw_void void kw_if

表示數值的字符串Java實現

har str 表示 pre false div scan char log 請實現一個函數用來判斷字符串是否表示數值(包括整數和小數)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示數值。 但是"12e","1a3.14","

數據結構之中序遍歷轉興許遍歷JAVA實現

百度 empty 表達 pty 中序 tor opera lin sem 算法流程: 主要分為四步: 1.當前字符為數字或者字母,則直接輸出 2.當前字符為)。則在棧中匹配輸出。一直匹配到),則停止輸出(就是將)及其

冒泡排序JAVA實現

[] string 個數 -1 out 進行 image args com 基本思想:在要排序的一組數中,對當前還未排好序的範圍內的全部數,自上而下對相鄰的兩個數依次進行比較和調整,讓較大的數往下沈,較小的往上冒。 即:每當兩相鄰的數比較後發現它們的排序與排序要求相反時,就

查找算法Java實現

pac binary while n) println pub ret gin 需要 1、二分查找算法 package other; public class BinarySearch { /* * 循環實現二分查找算法arr 已排好序的數

排序算法入門之希爾排序java實現

入門 介紹 插入 一次 變化 shells ngx i++ ava 希爾排序是對插入排序的改進。插入排序是前面元素已經有序了,移動元素是一個一個一次往後移動,當插入的元素比前面排好序的所有元素都小時,則需要將前面所有元素都往後移動。希爾排序有了自己的增量,可以理

排序算法入門之快速排序java實現

大小 ava 相對 其余 時間 個數 技術分享 算法 元素交換   快速排序也是一種分治的排序算法。快速排序和歸並排序是互補的:歸並排序將數組分成兩個子數組分別排序,並將有序的子數組歸並以將整個數組排序,會需要一個額外的數組;而快速排序的排序方式是當兩個子數組都有序

求較大整數n的階乘,因為n較大時n的階乘超出了正常類型的表示範圍,采用數組進行操作java實現

階乘 大數字package net.yk.mlgorithm; /** * 求較大數的階乘 * @author Administrator * * @param <T> */ public class ArraysMul<T> { public static void

奇怪的表達式求值 java實現

name 所在 cas 生活 div img num rar java 題目參考:http://blog.csdn.net/fuxuemingzhu/article/details/68484749 問題描述; 題目描述: 常規的表達式求值,我們都會根據計算的優先級來計算。

棧的數組和鏈表實現Java實現

javascrip search 分享圖片 sys blog inter () 結果 length 我以前用JavaScript寫過棧和隊列,這裏初學Java,於是想來實現棧,基於數組和鏈表。 下面上代碼: 1 import java.io.*; 2 //用接口來

數據結構與算法—插入排序Java實現

數據結構 算法 Java 插入排序 [toc] 插入排序 程序代碼 package com.uplooking.bigdata.datastructure; import java.util.Arrays; public class InsertSort { public st

數據結構與算法—冒泡排序Java實現

數據結構 算法 Java 冒泡排序 [toc] 冒泡排序 程序代碼 package com.uplooking.bigdata.datastructure; import java.util.Arrays; public class BubbleSort { public st

2004: C語言實驗——數日子數組

我們 這一 post HR submit 某年 inpu 時間 ret 2004: C語言實驗——數日子 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 213 Solved: 111[Submit][Status][Web

C語言占位符待完善

tps %u c語言 語言 待完善 csdn 有效 article 指數 %c       讀入一個字符 %s       讀入一個字符串,遇到空格制表符或者換行符時結束。 %d       讀入一個十進制整數 %x或者%X    讀入一個十六進制整數 %o      

數組中只出現一次的數字java實現

num 整型 根據 長度 問題 程序 oid [] 情況 問題描述 一個整型數組裏除了兩個數字之外,其他的數字都出現了偶數次。請寫程序找出這兩個只出現一次的數字。 解題思路 如果數組中只有一個數字出現奇數次,則將數組中所有的數字做異或可得該數字。 數組中有兩個數

軟件工程實踐項目-WCJava實現

ddb 使用 odin ace rup find sys tca sub 軟件工程實踐項目-WC(Java實現) 本文項目Github地址:https://github.com/MeiJinpen/wc 要求 基本要求 [x] -c 統計文件字符數 (實現) [x]

【模板小程序】任意長度十進制數轉化為二進制java實現

轉換 obi number 格式 bigint reverse com rev ole 媽媽再也不用擔心十進制數過大了233 import com.google.common.base.Strings; import java.math.BigInteger; impor