日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

M语言编程_所有编程语言大全(Meaning)

發(fā)布時間:2023/12/24 综合教程 26 生活家
生活随笔 收集整理的這篇文章主要介紹了 M语言编程_所有编程语言大全(Meaning) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一直對技術(shù)有很強的興趣,終于,決定要寫自己的語言(m語言)。那就先從最簡單的開始:解釋執(zhí)行器。

一套完整的語言包含的肯定不止解釋執(zhí)行器了,還要有編譯器和IDE,也就還要有語法高亮、智能提示等,不過還沒學(xué)會那些,先搞個最基本的解釋執(zhí)行器。

思路如下:

  1. 定義好希望的語法(基本語句有:順序執(zhí)行、if語句、for語句、while語句、系統(tǒng)自有函數(shù)定義、用戶函數(shù)定義、函數(shù)調(diào)用)
  2. 找一款詞法語法解析器工具,讓字符串流變成語法書(AST)
  3. 編寫解釋執(zhí)行器
    1. 元數(shù)據(jù)收集
    2. 變量作用域定義、查找
    3. 解釋執(zhí)行

先設(shè)想我們的m語言語法要怎么牛b啊,比如下面這段demo語法代碼:

go 計算標(biāo)準(zhǔn)體重(年齡)
{
    體重:年齡*3;
    體重;
}

體重:10;
a:10;
a:輸出(體重);
b:25;
a:100+10+b;
輸出(a);
(a==135)->
{
    a:a+a+a;
    輸出(a);
}
else
{
    輸出(b);
};
a:1;
while a<10 ->{
    a:a+2;
    輸出(a);
};

輸出("WHILE OK");



repeat i from 0 to 100 step 10->{
    輸出(i);
}
init->{
    輸出("FOR INIT");
}
onerror->{
    輸出("FOR ERROR");
}
finally->{
    輸出("FOR FINALLY");
};
輸出('FOR OK');

a:10;
輸出(計算標(biāo)準(zhǔn)體重(a));

很顯然,第一個語句塊是用戶函數(shù)的定義方式,以”go”字符串為函數(shù)定義的開始,接著是常規(guī)的函數(shù)名稱、參數(shù)、函數(shù)方法塊。

剩下的大致上就是順序執(zhí)行了,其中穿插著一些循環(huán)語句等,repeat循環(huán)自定義的比較厲害,好叼。。。感覺。。真的好叼。。。。

每個語句以封號后綴結(jié)束、賦值以冒號來標(biāo)識。

接著來看看基于ANTLR的詞法定義:

m.g4:

grammar m;

import basic,function,assignStmt,ifStmt,forStmt,whileStmt;

nomalStmt
    :assignStmt
    |ifStmt
    |forStmt
    |whileStmt
    ;
declarationStmt
    :functionDeclare
    ;
stmt
    :nomalStmt LS
    |declarationStmt
    ;

program
    : stmt+
    ;  

由于詞法語法定義較多,不貼代碼了,可以下載代碼看全部的(基于ideas/需要安裝antlr4插件)

接下來是時候讓我們load進(jìn)demo代碼解析成AST樹啦:

String code=Utils.readTxtFile("F:\\BaiduYunDownload\\mLanguage(4)\\m_code2.m");//這個是放demo代碼的文件
code=code.substring(1);//去掉第一個特殊字符


CharStream is = CharStreams.fromString(code);                 //antlr對象,讀入字符串
mLexer lexer = new mLexer(is);                          //mLexer是antlr自動生成的一個詞法類
CommonTokenStream tokens = new CommonTokenStream(lexer);           //antlr對象
mParser parser = new mParser(tokens);                     //mParser是antlr自動生成的一個此法解析類

mParser.ProgramContext tree=parser.program();                //program是入口規(guī)則,根規(guī)則

program program= NodeParser.parseProgram(tree);               //自己寫的NodeParser類,需要一堆自定義的節(jié)點類型配合解析整棵AST樹

mRuntime runtime=new mRuntime(program);

runtime.plainInterpreter();                           //解釋器執(zhí)行

System.out.println("");

AST節(jié)點的定義:

  

demo代碼構(gòu)建成AST樹的效果圖(antlr插件中能看):

轉(zhuǎn)換成為AST樹后,剩下的就是編寫解釋執(zhí)行器,其實相當(dāng)于前端編譯器。

主要步驟是3步:

  1. 收集元數(shù)據(jù)
  2. 定義變量作用域
  3. 語句塊的解釋執(zhí)行
public void execute(program program) {
        //1. 先掃描函數(shù)定義,收集元數(shù)據(jù)
        collectMetaData(program);

        //2. 變量作用域
        walkAST4Variables(program);

        //3. 解釋執(zhí)行代碼
        runCode(program);
}

1. 收集元數(shù)據(jù),其實就是對自定義函數(shù)的收集,統(tǒng)一放到一個Dictionary里,以便到時候引用到了執(zhí)行語句塊(和參數(shù)的傳遞)

private void collectMetaData(program program) {
        for(com.mckay.language.m.core.nodes.m.stmt stmt:program.stmts)
            if(stmt.declarationStmt!=null)
                this.userDefinedFunctionSymbols.defineMethod(stmt.declarationStmt.functionDeclare.functionIdentifier.getIdentifier(), stmt.declarationStmt.functionDeclare);
    }


public class UserDefinedFunctionSymbols {
    private Dictionary<String, functionDeclare> methods=new Hashtable<>();
    public functionDeclare getMethod(String identifier) {
        return methods.get(identifier);
    }

    public void defineMethod(String identifier, functionDeclare ast) {
        methods.put(identifier, ast);
    }
}

functionDeclare是具體的node,屬于AST中眾多節(jié)點類型中的一種,代表函數(shù)聲明節(jié)點。

2. 定義變量作用域,由于存在函數(shù)(自定義函數(shù)、系統(tǒng)自帶函數(shù)),因此需要有變量Scope的概念,存在局部變量覆蓋全局變量現(xiàn)象

private void walkAST4Variables(program program)
    {
        program.VariableSymbols=globalVariableSymbol;
        for(com.mckay.language.m.core.nodes.m.stmt stmt:program.stmts)
        {
            stmt.VariableSymbols=program.VariableSymbols;
            if(stmt.declarationStmt!=null)
            {
                stmt.declarationStmt.VariableSymbols=stmt.VariableSymbols;
                VarWalker.walk(stmt.declarationStmt);
            }

            if(stmt.nomalStmt!=null)
            {
                stmt.nomalStmt.VariableSymbols=stmt.VariableSymbols;
                VarWalker.walk(stmt.nomalStmt);
            }
        }
    }




public class VariableSymbol {
    private Dictionary<String, Variable> variables=new Hashtable<>();
    private VariableSymbol parentVariableSymbol;

    public void setParentVariableSymbol(VariableSymbol parentVariableSymbol)
    {
        this.parentVariableSymbol=parentVariableSymbol;
    }

    public void defineVariable(String name, Variable variable) {
        variables.put(name, variable);
    }

    public void setValue(String name, Object value)
    {
        Variable variable=getVariable(name);
        variable.Value=value;
    }
    public Object getValue(String name)
    {
        Variable variable=getVariable(name);
        return variable.Value;
    }

    private Variable getVariable(String name) {
        List<String> keys=Collections.list(variables.keys());
        if(keys.contains(name))
            return this.variables.get(name);

        if(this.parentVariableSymbol!=null)
            return this.parentVariableSymbol.getVariable(name);

        throw new RuntimeException("變量未定義");
    }
}  

當(dāng)局部變量中沒有找到本地變量定義時,會根據(jù)parent關(guān)聯(lián)向上找變量,直到為null。

3. 語句塊的解釋執(zhí)行,這個可以說是最容易理解的地方了

private void runCode(program program) {
        StmtExecutor executor=new StmtExecutor(this);

        for(com.mckay.language.m.core.nodes.m.stmt stmt:program.stmts)
            if(stmt.nomalStmt!=null)
                executor.execute(stmt.nomalStmt);
}

StmtExecutor.execute(nomalStmt)會調(diào)用一系列子語句,如下圖就一圖就懂:

如上圖中,針對expression是調(diào)用calc的,一堆calc,expression中套expression。

system built-in函數(shù)的定義,是通過NativeMethodNode.setCode來標(biāo)識的,比如當(dāng)前實現(xiàn)的code為OUTPUT,功能如下:System.out.print/Console.Write()

第一個紅框是native node中判斷code是哪個system built-in函數(shù)的編碼代號

第二個紅框是對應(yīng)built-in函數(shù)的java語句執(zhí)行。

demo m代碼對應(yīng)的解釋執(zhí)行輸出:

10 
135 
405 
3 
5 
7 
9 
11 
WHILE OK 
FOR INIT 
0 
10 
20 
30 
40 
50 
60 
70 
80 
90 
100 
FOR FINALLY 
FOR OK 
30 
ok  

代碼下載(基于java)

總結(jié)

以上是生活随笔為你收集整理的M语言编程_所有编程语言大全(Meaning)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。