1

いくつかのフラグメントを使用する字句規則(整数)があります。パーサールール(解析)では、問題のトークンを生成したフラグメントに応じて、ツリーを別の方法で書き直したいと思います。私が試みていることを示すために、小さな文法を作成しました。

grammar subrange;

options {
    output=AST;
}

tokens {
    NumberNode;
    DecimalNode;
    BinaryNode;
    HexNode;
    OctalNode;
}

parse
    : Integer+ -> ^(NumberNode Integer)+
    ;

Integer
    : DECIMAL_LITERAL
    | BINARY_LITERAL
    | HEX_LITERAL
    | OCTAL_LITERAL
    ;

fragment BINARY_LITERAL
    : '2#' ('0' | '1')+
    ;

fragment HEX_LITERAL 
    : ('16#' | '0' ('x'|'X')) HEX_DIGIT+
    ;

fragment HEX_DIGIT
    : (DIGIT|'a'..'f'|'A'..'F')
    ;

fragment DECIMAL_LITERAL 
    : ('0' | '1'..'9' DIGIT*)
    ;

fragment OCTAL_LITERAL 
    : '8#' ('0'..'7')+
    ;

fragment DIGIT
    : '0'..'9'
    ;

SPACE : (' ' | '\t' | '\r' | '\n')+ {skip();};

解析ルールで、架空のDecimalNodeではDECIMAL_LITERALを、BinaryNodeではBINARY_LITERAL(NumberNodeの下のすべてではなく)を書き換えたいと思います。

字句ルール内のトークンタイプを変更してこれを実行しようとしています。これにより、解析ルール内でそれに応じて書き換えることができます。

アクションでこれを行うことができるはずですが、タイプを変更するために返されたトークンを見つける方法を理解できませんでした。http://www.antlr.org/wiki/display/ANTLR3/Special+symbols+in+actionsは、$ tokenrefが機能するはずであることを示しているようですが、まったく翻訳されていません。

または、これを達成する別の方法はありますか?

前もって感謝します。

4

1 に答える 1

2

私には少し奇妙に思えます。そのようなすべてのリテラルを1つのIntegerトークンにグループ化してから、パーサールールでそれらを再度分離する必要があります。

Integer削除して実行しないのはなぜですか。

integer
    : BINARY_LITERAL // when output=AST, this creates a CommonTree with type 'BINARY_LITERAL'
    | HEX_LITERAL    // ...
    | DECIMAL_LITERAL
    | OCTAL_LITERAL 
    ;

BINARY_LITERAL
    : '2#' ('0' | '1')+
    ;

HEX_LITERAL 
    : ('16#' | '0' ('x'|'X')) HEX_DIGIT+
    ;

DECIMAL_LITERAL 
    : ('0' | '1'..'9' DIGIT*)
    ;

OCTAL_LITERAL 
    : '8#' ('0'..'7')+
    ;

または、Int(eger)ルールを維持しながら、次のようにしてさまざまな整数リテラルの数値を設定することもできます。

Int
@init{int skip = 0, base = 10;}
    : ( DECIMAL_LITERAL
      | BINARY_LITERAL  {base = 2;  skip = 2;} 
      | OCTAL_LITERAL   {base = 8;  skip = 2;} 
      | HEX_LITERAL     {base = 16; skip = $text.contains("#") ? 3 : 2;} 
      )
      {
        setText(String.valueOf(Integer.parseInt($text.substring(skip), base)));
      }
    ;

fragment BINARY_LITERAL
    : '2#' ('0' | '1')+
    ;

fragment HEX_LITERAL 
    : ('16#' | '0' ('x'|'X')) HEX_DIGIT+
    ;

fragment DECIMAL_LITERAL 
    : ('0' | '1'..'9' DIGIT*)
    ;

fragment OCTAL_LITERAL 
    : '8#' ('0'..'7')+
    ;

ターゲット言語のオブジェクト/クラス/予約語が持つ可能性があるため、ルールに名前を付けるように注意してください(IntegerJavaの場合)。


編集

わかった。通行人がなぜ私がこれを提案しているのか疑問に思っている場合に備えて、他の答えをそこに残しておきます... :)

これが(私が思うに)あなたが求めているものです:

grammar T;

options {
  output=AST;
}

tokens {
  BinaryNode;
  OctalNode;
  HexNode;
  DecimalNode;
}

parse
 : integer+
 ;

integer
 : i=Integer -> {$i.text.startsWith("2#")}?         ^(BinaryNode Integer)
             -> {$i.text.startsWith("8#")}?         ^(OctalNode Integer)
             -> {$i.text.matches("(16#|0[xX]).*")}? ^(HexNode Integer)
             ->                                     ^(DecimalNode Integer)
 ;

Integer
 : DECIMAL_LITERAL
 | BINARY_LITERAL
 | HEX_LITERAL
 | OCTAL_LITERAL
 ;

fragment BINARY_LITERAL
 : '2#' ('0' | '1')+
 ;

fragment HEX_LITERAL 
 : ('16#' | '0' ('x'|'X')) HEX_DIGIT+
 ;

fragment HEX_DIGIT
 : (DIGIT|'a'..'f'|'A'..'F')
 ;

fragment DECIMAL_LITERAL 
 : ('0' | '1'..'9' DIGIT*)
 ;

fragment OCTAL_LITERAL 
 : '8#' ('0'..'7')+
 ;

fragment DIGIT
 : '0'..'9'
 ;

SPACE 
 : (' ' | '\t' | '\r' | '\n')+ {skip();}
 ;

入力を解析する"2#1111 8#77 0xff 16#ff 123"と、次のASTが生成されます。

ここに画像の説明を入力してください

各リテラルのタイプに関する情報を失ったので、 -rule(書き換えルールの後のもの)Integerでこのチェックを行う必要があります。integer-> {boolean-expression}? ...

于 2012-07-18T16:09:38.823 に答える