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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

关于ANTLR的通用库的需求:使用反射来构建元模型

發(fā)布時(shí)間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于ANTLR的通用库的需求:使用反射来构建元模型 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我是一名語言工程師:我使用多種工具來定義和處理語言。 在其他工具中,我使用ANTLR:它簡單,靈活,可以圍繞它進(jìn)行構(gòu)建。

但是,我發(fā)現(xiàn)自己圍繞ANTLR為不同的項(xiàng)目重建了類似的工具。 我看到兩個(gè)問題:

  • ANTLR是一個(gè)非常好的構(gòu)建基塊,但是僅使用ANTLR并不能做很多事情:價(jià)值在于我們可以在AST上進(jìn)行的處理,而且我看不到ANTLR周圍的圖書館生態(tài)系統(tǒng)
  • ANTLR不會(huì)產(chǎn)生語法的元模型:沒有它,就很難圍繞ANTLR構(gòu)建通用工具

讓我解釋一下:

  • 對于具有EMF經(jīng)驗(yàn)的人:我們基本上每個(gè)語法都需要一個(gè)Ecore等效項(xiàng)。
  • 對于其他:請閱讀下一段

為什么我們需要一個(gè)元模型

假設(shè)我想構(gòu)建一個(gè)通用庫,以通過ANTLR生成的AST生成XML文件或JSON文檔。 我該怎么辦?

好吧,給定一個(gè)ParseRuleContext,我可以獲取規(guī)則索引并找到名稱。 我為Python語法生成了解析器,并提供了一些示例,因此,讓我們看一下如何使用實(shí)際的類:

Python3Parser.Single_inputContext astRoot = pythonParse(...my code...); String ruleName = Python3Parser.ruleNames[astRoot.getRuleIndex()];

讓我們看一下類Single_inputContext:

public static class Single_inputContext extends ParserRuleContext {public TerminalNode NEWLINE() { return getToken(Python3Parser.NEWLINE, 0); }public Simple_stmtContext simple_stmt() {return getRuleContext(Simple_stmtContext.class,0);}public Compound_stmtContext compound_stmt() {return getRuleContext(Compound_stmtContext.class,0);}public Single_inputContext(ParserRuleContext parent, int invokingState) {super(parent, invokingState);}@Override public int getRuleIndex() { return RULE_single_input; }@Overridepublic void enterRule(ParseTreeListener listener) {if ( listener instanceof Python3Listener ) ((Python3Listener)listener).enterSingle_input(this);}@Overridepublic void exitRule(ParseTreeListener listener) {if ( listener instanceof Python3Listener ) ((Python3Listener)listener).exitSingle_input(this);} }

我應(yīng)該得到這樣的東西:

<Single_input NEWLINES="..."><Simple_stmt>...</Simple_stmt><Compund_stmt>...</Compunt_stmt> </root>

好。 對我來說,看課并識(shí)別這些元素非常容易,但是我如何自動(dòng)做到這一點(diǎn)呢?

反思,顯然,您會(huì)思考。

是。 那行得通。 但是,如果我們有多個(gè)元素怎么辦? 參加本課:

public static class File_inputContext extends ParserRuleContext {public TerminalNode EOF() { return getToken(Python3Parser.EOF, 0); }public List NEWLINE() { return getTokens(Python3Parser.NEWLINE); }public TerminalNode NEWLINE(int i) {return getToken(Python3Parser.NEWLINE, i);}public List stmt() {return getRuleContexts(StmtContext.class);}public StmtContext stmt(int i) {return getRuleContext(StmtContext.class,i);}public File_inputContext(ParserRuleContext parent, int invokingState) {super(parent, invokingState);}@Override public int getRuleIndex() { return RULE_file_input; }@Overridepublic void enterRule(ParseTreeListener listener) {if ( listener instanceof Python3Listener ) ((Python3Listener)listener).enterFile_input(this);}@Overridepublic void exitRule(ParseTreeListener listener) {if ( listener instanceof Python3Listener ) ((Python3Listener)listener).exitFile_input(this);} }

現(xiàn)在,方法NEWLINE和stmt返回列表。 您可能還記得,一般而言,泛型在Java的反射中不能很好地工作。 在這種情況下,我們很幸運(yùn),因?yàn)橛幸粋€(gè)解決方案:

Class clazz = Python3Parser.File_inputContext.class; Method method = clazz.getMethod("stmt"); Type listType = method.getGenericReturnType(); if (listType instanceof ParameterizedType) {Type elementType = ((ParameterizedType) listType).getActualTypeArguments()[0];System.out.println("ELEMENT TYPE "+elementType); }

這將打印:

元素類型類me.tomassetti.antlrplus.python.Python3Parser $ StmtContext

因此,我們也可以介紹泛型。 好的,使用反射并不理想,但是我們可以從中提取一些信息。

我不是100%肯定會(huì)足夠,但是我們可以開始。

元模型應(yīng)該如何?

為了定義元模型,我不會(huì)嘗試任何幻想。 我將使用基于EMF的經(jīng)典模式,該模式類似于MPS中提供的模式。

我將添加一種名為Package或Metamodel的容器。 包中將列出幾個(gè)實(shí)體。 我們也可以將其中一個(gè)實(shí)體標(biāo)記為根實(shí)體。

每個(gè)實(shí)體將具有:

  • 一個(gè)名字
  • 可選的父實(shí)體(從其繼承屬性和關(guān)系)
  • 屬性列表
  • 關(guān)系清單

每個(gè)屬性將具有:

  • 一個(gè)名字
  • 從原始類型中選擇的一種類型。 實(shí)際上,我希望只使用String和Integers。 將來可能枚舉
  • 多重性(1個(gè)或多個(gè))

每個(gè)關(guān)系將具有:

  • 一個(gè)名字
  • 種類: 包含或引用 。 現(xiàn)在,AST只知道容器 ,但是稍后我們可以實(shí)現(xiàn)符號(hào)解析和模型轉(zhuǎn)換,在那個(gè)階段我們將需要引用
  • 目標(biāo)類型:另一個(gè)實(shí)體
  • 多重性(1個(gè)或多個(gè))

下一步

我將開始構(gòu)建一個(gè)元模型,然后再利用該元模型來構(gòu)建通用工具。

通常還需要執(zhí)行其他操作:

  • 轉(zhuǎn)換:我通常從ANTLR獲得的AST是由我如何表達(dá)語法以獲取可解析內(nèi)容的方式?jīng)Q定的。 有時(shí)我還必須進(jìn)行一些重構(gòu)以提高性能。 我想在解析后轉(zhuǎn)換AST,以更接近語言的邏輯結(jié)構(gòu)。
  • 取消編組:我想從AST進(jìn)行測試
  • 符號(hào)解析:這絕對不是一件容易的事,因?yàn)槲野l(fā)現(xiàn)為Java構(gòu)建符號(hào)求解器

是的,我知道有些人在想: 只需使用Xtext即可 。 雖然我喜歡EMF(Xtext建立在它上面),但它的學(xué)習(xí)曲線陡峭,我看到很多人對此感到困惑。 我也不喜歡OSGi在非OSGi世界中的表現(xiàn)。 最終,Xtext帶有很多依賴項(xiàng)。

別誤會(huì):我認(rèn)為Xtext在許多情況下都是一個(gè)了不起的解決方案。 但是,有些客戶更喜歡精簡的方法。 對于有意義的情況,我們需要一種替代方法。 我認(rèn)為它可以建立在ANTLR之上,但是還有很多工作要做。

幾年前,我為.NET構(gòu)建了類似的東西,并將其稱為NetModelingFramework 。

翻譯自: https://www.javacodegeeks.com/2016/05/need-generic-library-around-antlr-using-reflection-build-metamodel.html

總結(jié)

以上是生活随笔為你收集整理的关于ANTLR的通用库的需求:使用反射来构建元模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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