<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    如鵬網(wǎng) 大學(xué)生計(jì)算機(jī)學(xué)習(xí)社區(qū)

    CowNew開源團(tuán)隊(duì)

    http://www.cownew.com 郵件請(qǐng)聯(lián)系 about521 at 163.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      363 隨筆 :: 2 文章 :: 808 評(píng)論 :: 0 Trackbacks

    本章翻譯人 CowNew開源團(tuán)隊(duì) 周曉

    記號(hào)詞表

    每一個(gè)文法都指定了帶有規(guī)則(子結(jié)構(gòu))和詞表語言結(jié)構(gòu)。這些符號(hào)在運(yùn)行時(shí)被轉(zhuǎn)換成整型的"記號(hào)類型"從而可以有效的比較。定義從符號(hào)到記號(hào)類型的映射的文件對(duì)ANTLR和ANTLR生成的分析器來說是基礎(chǔ)。 這份文檔描述了ANTLR使用和生成的這類文件,還介紹了用于控制詞表的選項(xiàng)。

    導(dǎo)言

    在分析時(shí),一個(gè)語法分析器文法通過符號(hào)在它的詞表里引用記號(hào)要符合由詞法分析器或其他幾號(hào)流生成的Token對(duì)象。記號(hào)類型儲(chǔ)存在記號(hào)對(duì)象中,每種符號(hào)的值是唯一的,分析器比較這些整數(shù)來判斷記號(hào)類型。如果分析器期望下一個(gè)記號(hào)類型是23,但發(fā)現(xiàn)第一個(gè)超前掃描記號(hào)類型,LT(1).getType(),不是23,這時(shí)分析器拋出MismatchedTokenException異常。

    一個(gè)文法可能有一個(gè)導(dǎo)入詞表,經(jīng)常也會(huì)有一個(gè)導(dǎo)出詞表,用于被其他文法引用。導(dǎo)入的詞表從未被修改,通過它可以知道詞表的"初始條件"。不要和導(dǎo)入詞匯混淆了。

    下面列出了最常見的問題:

    ANTLR如何決定哪一個(gè)詞法符號(hào)是什么記號(hào)類型?

    每個(gè)文法有一個(gè)記號(hào)管理器來管理文法的導(dǎo)出詞表。從文法的importVocab選項(xiàng),記號(hào)管理器以 符號(hào)/記號(hào)類型 的形式被預(yù)載。這個(gè)選項(xiàng)強(qiáng)制ANTLR尋找有如下映射關(guān)系的文件:

    PLUS=44

    沒有importVocab選項(xiàng),文法的記號(hào)管理器是空的(稍后會(huì)看見一個(gè)警告)。

    你的文法中的任意記號(hào)沒有預(yù)設(shè)值,它們被按照遇到的順序賦值。例如,在下面的文法中,記號(hào)A和B分別是4和5:

    class P extends Parser;
    a : A B ;

    詞法文件以如下形式命名: NameTokenTypes.txt.

    為什么記號(hào)類型從4開始?

    因?yàn)锳NTLR在分析過程中需要一些特殊的記號(hào)類型,用戶定義的記號(hào)類型必須在3后開始。

    ANTLR生成什么樣的詞表文件?

    ANTLR為詞表V生成VTokenTypes.txtVTokenTypes.javaV是文法的名字或者是exportVocab選項(xiàng)指定的名字。文本文件有點(diǎn)像一個(gè)簡化的記號(hào)管理器,保存著ANTLR需要的一些信息,供定義在其他文件中的文法查看其詞表信息等等。Java文件是是一個(gè)包含了記號(hào)類型常量定義的接口。ANTLR生成的分析器實(shí)現(xiàn)了其中的一個(gè)接口,獲得所需要的記號(hào)類型定義。

    ANTLR怎樣同步符號(hào)類型在相同文件和不同文件間文法的映射?

    一個(gè)文法的導(dǎo)出詞表必須是另一個(gè)文法的導(dǎo)入詞表或者2個(gè)文法必須共享一個(gè)公共的導(dǎo)入詞表。

    設(shè)想p.g中有一個(gè)語法分析器P:

    // yields PTokenTypes.txt
    class P extends Parser;
    // options {exportVocab=P;} ---> default!
    decl : "int" ID ;

    l.g中有一個(gè)詞法分析器L

    class L extends Lexer;
    options {
    importVocab=P; // reads PTokenTypes.txt
    }
    ID : ('a'..'z')+ ;

    即使L主要是P的詞表中的值,但ANTLR生成的是LTokenTypes.txt和LTokenTypes。

    不同文件中的文法必須共享同樣的記號(hào)類型空間,使用importVocab選項(xiàng)去預(yù)載同樣的詞表。

    如果這些文法在同一個(gè)文件中,ANTLR會(huì)用同樣的方法處理它。然而,你可以通過設(shè)置它們的導(dǎo)出詞表到同一個(gè)文件來使這2個(gè)文法共享同一個(gè)詞表。例如,如果P和L在一個(gè)文件中,你可以這樣做:

    // yields PTokenTypes.txt
    class P extends Parser;
    // options {exportVocab=P;} ---> default!
    decl : "int" ID ;
    class L extends Lexer;
    options {
    exportVocab=P; // shares vocab P
    }
    ID : ('a'..'z')+ ;

    如果你沒有為L指定詞表,它將會(huì)選擇共享文件中導(dǎo)出的第一個(gè)詞表;在這里,它將共享P的詞表。

    // yields PTokenTypes.txt
    class P extends Parser;
    decl : "int" ID ;
    // shares P's vocab
    class L extends Lexer;
    ID : ('a'..'z')+ ;

    記號(hào)類型映射文件像這樣:

    P    // exported token vocab name
    LITERAL_int="int"=4
    ID=5

    文法繼承和詞表

    文法繼承父文法的規(guī)則,動(dòng)作和選項(xiàng),但是子文法使用什么詞表和記號(hào)詞表呢?ANTLR對(duì)子文法的處理就好像你復(fù)制粘貼父文法的所有非重載規(guī)則到子文法。因此,子文法記號(hào)的集合就是父文法和子文法的交集。所有的文法都導(dǎo)出詞表所以子文法導(dǎo)出并使用一個(gè)和父文法不同的詞表文件。除非你使用importVocab選項(xiàng)重載,否則子文法導(dǎo)入父文法的詞表。

    文法Q繼承P,會(huì)預(yù)先設(shè)置好P的詞表,就好像Q使用了importVocab=P選項(xiàng)。例如,下面的文法有2個(gè)記號(hào)符號(hào)。

    class P extends Parser;
    a : A Z ;

    子文法Q,最初和父文法有相同的詞表,但隨后會(huì)增加一些符號(hào)。

    class Q extends P;
    f : B ;

    在上面的情況,Q定義了幾個(gè)符號(hào),B使得Q的詞表為{A,B,C}.

    一個(gè)子文法的詞表一般是父文法詞表的父集。注意重載規(guī)則不影響最初的詞表。

    如果你的子文法需要父文法未使用過的新詞法結(jié)構(gòu),你或許需要子語法分析器使用一個(gè)子詞法分析器。使用importVocab選項(xiàng)指定子詞法分析器的詞表來重載它初始的詞表。例如,假設(shè)語法分析器P使用詞法分析器PL。不用importVocab重載,Q的詞表將使用P的詞表,即PL的詞表。如果你想讓Q使用另一個(gè)詞法分析器的記號(hào)類型,比如說使用QL,那么做下面的事情:

    class Q extends P;
    options {
    importVocab=QL;
    }
    f : B ;

    Q的詞表現(xiàn)在和QL的詞表相同或者是QL詞表的父集。

    識(shí)別器生成次序

    如果你所有的文法在一個(gè)文件中,你就不用擔(dān)心ANTLR將會(huì)最先處理哪一個(gè)文法文件,不過你仍要擔(dān)心ANTLR處理文件中文法的次序。如果你嘗試去導(dǎo)入一個(gè)會(huì)被另一個(gè)文法導(dǎo)出的詞表,ANTLR將提示它不能讀取這個(gè)文件。下面的文法文件會(huì)造成ANTLR出錯(cuò):

    class P extends Parser;
    options {
    importVocab=L;
    }
    a : "int" ID;
    class L extends Lexer;
    ID : 'a';

    ANTLR在文法文件中還沒有發(fā)現(xiàn)文法L,所以它將提示不能發(fā)現(xiàn)LTokenTypes.txt。另一方面,如果LTokenTypes.txt存在(比如說在文法文件中還沒有P文法的時(shí)候ANTLR運(yùn)行生成的),ANTLR將為P讀取這個(gè)文件,然后在處理L文法的時(shí)候覆蓋掉它。ANTLR不知道它要處理的文法恰好在一個(gè)文件中,所以它假設(shè)是要讀取從另一個(gè)文件生成的詞表。

    一般的,如果你想讓文法B使用文法A的記號(hào)類型(無論什么文法類型),你必須首先對(duì)A運(yùn)行ANTLR。例如,一個(gè)樹文法用到了分析器文法的詞表,應(yīng)該在ANTLR生成了分析器之后再去處理樹文法。

    例如,當(dāng)你想讓一個(gè)詞法分析器和一個(gè)語法分析器共享同一個(gè)詞表空間的時(shí)候,你要做的就是去把它們放到同一個(gè)文件中,設(shè)置它們的導(dǎo)出詞表到同一個(gè)空間。如果它們?cè)诜珠_的文件中,把語法分析器的導(dǎo)入詞表選項(xiàng)設(shè)置為詞法分析器的導(dǎo)出詞表,除非記號(hào)都定義在語法分析器中,這時(shí),換一下導(dǎo)入/導(dǎo)出的關(guān)系讓詞法分析器使用語法分析器的導(dǎo)出詞表。

    詞表的一些使用技巧

    如果你的文法在不同的文件中,你仍想讓它們共享全部或部分記號(hào)空間,該怎么辦。有2種解決方案:(1) 讓文法導(dǎo)入同樣的詞表 (2) 讓文法繼承同一個(gè)父文法,該父文法含有記號(hào)空間。

    第一個(gè)方案在下面情況使用,你有2個(gè)詞法分析器和2個(gè)語法分析器,語法分析器必須要處理從根本上就不同的輸入部分。ANTLR 2.6.0發(fā)行版examples/java/multiLexer中的例子就屬于這種情況。javadoc注釋和Java代碼部分的詞法分析和語法分析過程都不一樣。javadoc詞法分析器有必要識(shí)別"*/"中止注釋的詞法結(jié)構(gòu),但它一般讓Java語法分析器用打開/關(guān)閉的記號(hào)引用來嵌套運(yùn)行javadoc語法分析器:

    javadoc
    : JAVADOC_OPEN
    {
    DemoJavaDocParser jdocparser =
    new DemoJavaDocParser(getInputState());
    jdocparser.content();
    }
    JAVADOC_CLOSE
    ;

    問題在于:javadoc詞法分析器定義了JAVADOC_CLOSE,即也定義了它的記號(hào)類型。不幸的是Java語法分析器的詞表基于Java詞法分析器而不是javadoc詞法分析器。 要讓javadoc詞法分析器和java詞法分析器都可以看到JAVADOC_CLOSE (并且有同樣的記號(hào)類型),2個(gè)詞法分析器都要導(dǎo)入含有這種記號(hào)類型定義的詞表。這里有DemoJavaLexer和DemoJavaDocLexer的頭部:

    class DemoJavaLexer extends Lexer;
    options {
    importVocab = Common;
    }
    ...
    class DemoJavaDocLexer extends Lexer;
    options {
    importVocab = Common;
    }
    ...

    CommonTokenTypes.txt有:

    Common // name of the vocab
    JAVADOC_CLOSE=4

    共享詞表的第二種方案在下面情況使用,你有1個(gè)語法分析器和3個(gè)不同的詞法分析器(比如說為不同類型的C)。如果你只想語法分析器空間利用率高,語法分析器必須可以訪問3個(gè)詞法分析器的詞表,去掉文法不用的結(jié)構(gòu)(大概可以用語義斷言)。給出CLexer,GCCLexer和MSCLexer,CLexer作為父文法定義出所有記號(hào)的集合。例如,如果MSCLexer需要"_int32",那么在CLexer中定義一個(gè)所有詞法分析器可見的記號(hào)類型:

    tokens {
    INT32;
    }

    在MSCLexer中,你可以給它實(shí)際意義的字符。

    tokens {
    INT32="_int32"
    }

    用這種方法,3個(gè)詞法分析器共享同一個(gè)記號(hào)空間,允許你用一個(gè)語法分析器識(shí)別多種C的輸入。

    Version: $Id: //depot/code/org.antlr/release/antlr-2.7.6/doc/vocab.html#1 $
    posted on 2007-11-24 17:40 CowNew開源團(tuán)隊(duì) 閱讀(2205) 評(píng)論(0)  編輯  收藏 所屬分類: 技術(shù)類
    主站蜘蛛池模板: 亚洲精品乱码久久久久久蜜桃图片 | 免费亚洲视频在线观看| 亚洲成年看片在线观看| 黄色视屏在线免费播放| 久久亚洲精品国产精品| 日本一道在线日本一道高清不卡免费| 无遮挡国产高潮视频免费观看 | 亚洲最大中文字幕无码网站| 国产一精品一aⅴ一免费| 成全高清在线观看免费| 精品亚洲AV无码一区二区三区| 国产又黄又爽又猛的免费视频播放| 手机看片国产免费永久| 亚洲丝袜中文字幕| 久久久久亚洲AV成人网人人软件| 亚洲免费精彩视频在线观看| 亚洲AV成人无码网站| 亚洲国产精品一区第二页| 免费涩涩在线视频网| 日本道免费精品一区二区| 亚洲精品女同中文字幕| 亚洲一区二区三区四区在线观看| 国产成人3p视频免费观看 | 色老头永久免费网站| 美女扒开屁股让男人桶爽免费| 亚洲国产人成在线观看69网站| 国产免费人成视频在线观看| 99久9在线|免费| 一个人看的www在线免费视频 | 亚洲最大在线视频| 国产亚洲老熟女视频| 全免费a级毛片免费看不卡| 欧洲人免费视频网站在线| 黄色毛片免费观看| 丁香婷婷亚洲六月综合色| 亚洲成年轻人电影网站www | 国产成人精品免费视频大全五级| 2021精品国产品免费观看| 中国一级毛片视频免费看| 一区免费在线观看| 亚洲AV电影天堂男人的天堂|