ANTLR3 완전 참조지침 독서노트[05]

17285 단어 antlr
전언
true/false를 제공하는 식별기만 생성하는 것은 그다지 쓸모가 없다. 식별 과정에서 특정한 구조를 만났을 때 코드를 실행하고 이 구조의 정보를 저장할 생각은 자연히 있다.
ANTLR은 문법에 속성과 동작을 삽입하는 슈퍼 혼합'문법'을 제공하여 내부 표현인 AST나 템플릿을 생성할 수 있습니다.물론 부분 구조 식별 결과를 직접 출력하면 동작도 대처할 수 있다.
 
컨텐트
기본적으로 원문 6장과 일치한다
속성 및 작업
문법 동작
2 Token 속성
3 미리 정의된 규칙 속성
4 속성 역할 영역
5 동작에서 속성 참조
 
속성 및 작업
동작의 언어는 Java라는 몇 가지 인스턴스를 사용하여 설명합니다.
[ex1] 동작은 규칙이 끝나지 않은 위치에서 할 수 있습니다.
decl : type ID {System.out.println($ID.text);}';';

type : 'int' | 'float';

  
[ex2] 동작을 규칙의 끝 위치에 놓기
decl : type ID ';' {System.out.println("var " + $ID.text+":"+$type.text+";");};

type : 'int' | 'float';

  
[ex3] 속성 탭, 동명 규칙 구분
decl : type ID ';' {System.out.println("var " + $ID.text+":"+$type.text+";");}

        | t=ID id=ID ';' {System.out.println("var " + $id.text+":"+$t.text+";");};

  
[ex4] 규칙에 * +
decl : type ids+=ID (',' ids+=ID)* ';'; //ids ID token List

  
[ex5] 규칙 매개 변수와 반환값
decl : type declarator[$type.text] ';' ;//      

declarator[String typeText]

    : '*' ID {"var " + $ID.text+":^"+$typeText+";")}

       | ID {System.out.println("var " + $ID.text+":"+$typeText+";")};

 

field : d=decl ';' 

{System.out.println("type=)+$d.type+", vars="+$d.vars);};//       

decl returns[String type, List vars]

: t=type ids+=ID (',' ids+=ID)* {$type=$t.text;$vars=ids;}

  
[ex6] 규칙 간 통신: 공유 변수
@members{String methodName;}//          

method : type ID {methodName=$ID.text;} body ;

body : '{' statement+ '}' ;

statement : decl {...methodName...} ';'//    

| ... ;

 

method scope {String name;}//       

: type ID {$method::name=$ID.text;} body ;

body : '{' statement+ '}' ;

statement : decl {...$method::name...} ';'//    

| ... ;

  
문법 동작
동작은 목표 언어로 작성된 문법에 삽입된 코드 세션입니다.
 
전역 작업 이름 지정
이름:
설명
 header
생성된 코드에서 클래스 정의 전의 코드는 항상 패키지 정의와 패키지 가져오기 문장이다
 memebers
인스턴스 변수 및 방법 정의
 rulecatch
동작에서 문법이 잘못된 기본catch 문장
 synpredgate
문법 술어 스위치
전역 동작의 작용역(scope)은lexer,parser 또는treeparser입니다.
 
문법 규칙에 삽입된 명명 동작
 
이름:
설명
 init
해석 규칙의 코드 실행 전 코드 배치
 after
해석 규칙의 코드가 실행된 코드를 놓다
 catch
해석 규칙을 배치한 코드에 이상한 처리 코드가 발생했습니다
 finally
해석 규칙을 배치한 코드에 이상이 있는 최종 처리 코드
 
sample:
parser grammar T;

@header{package p;}

@members{

int i;

public TParser(TokenStream input, int foo){

this(input); 

i = foo;

} 

 

 

 

}

a[int x] returns [int y]

@init {int z=0;}

@after {System.out.println("after matching rule, before finally");}

: {<<action1>>} A {<<action2>>}

;

catch[RecognitionException re] {

System.err.println("error");

}

finally {<<do-this-no-matter-what-happened>>}

  
2 Token 속성
Token은lexer가 Parser에게 제출한 최소 단원으로서 동작에서 인용할 수 있는 Token 속성은
등록 정보
타입
설명
 text
 String
token에 대응하는 텍스트, Token#getText() 호출
 type
 int
token의 유형(정수), Token#getType() 호출
 line
 int
token의 행(1에서 계산), Token#getLine() 호출
 pos
 int
이 줄에서 Token 첫 문자의 위치(0에서 계수), Token#getCharPositionInLine() 호출
 index
 int
token 흐름에서 이 token의 인덱스 (0 계수에서) 를 사용하고Toekn#getTokenIndex () 를 호출합니다
 channel
 int
Token의 채널 번호, 두 개의 값이 Token입니다.DEFAULT_CHANNEL, Token.HIDDEN_CHANNEL
 tree
 Object
AST를 구축할 때, 이 속성은token에 의해 만들어진 트리 노드를 가리킨다
참조 방법 $label.attribute, label은token의 탭입니다; $label은 Token 자체를 인용합니다.
 
예외:lexer 규칙 중 일부 label은token이 아니라 문자입니다.
sample:
lexer grammar T;

R : a='c' b='hin' c=. {$a, $b.text, $c};// a,c   token,b token

 
 
3 미리 정의된 규칙 속성
미리 정의된 속성은 보통 읽기만 합니다. 유일한 예외는AST를 생성할 때 애프터 동작에서tree와st 속성을 설정할 수 있습니다.
$attribute 또는 $enclosingRuleName을 사용합니다.attribute 인용.
 
미리 정의된 Parser 규칙 속성
등록 정보
타입
설명
 text
 String
일치하는 규칙이 $text 표시식 값을 구할 때까지 시작되는 텍스트입니다.hidden channel의token 텍스트를 포함합니다
 start
 Token
비hidden channel에서 이 규칙과 일치하는 첫 번째 token
 stop
 Token
비hidden channel에서 이 규칙과 일치하는 마지막 token
 tree
 Object
규칙이 계산한AST는 통상적으로 규칙을 다시 쓴 결과이다.현재 규칙을 참조할 때 애프터 작업에서만 사용 가능
 st
 StringTemplate
규칙이 계산한 템플릿은 보통 규칙을 다시 쓴 결과입니다.현재 규칙을 참조할 때 애프터 작업에서만 사용 가능
 
예약된lexer 규칙 속성
등록 정보
타입
설명
 text
 String
가장 바깥쪽 규칙과 일치하는 첫 번째 Token에서 현재 위치의 텍스트로
 type
 int
포위 규칙의token 유형
 line
 int
이 규칙의 첫 번째 문자가 있는 줄 번호 (계수에서 1)
 pos
 int
이 규칙의 첫 번째 문자가 행에 있는 위치(0에서 계산됨)
 channel
 int
이 규칙이 있는 채널
 
미리 정의된tree grammar 규칙 속성
등록 정보
타입
설명
 text
 String
이 규칙이 일치하는 첫 번째 노드에서 유도된 텍스트
 start
 Object
이 규칙과 일치하는 첫 번째 트리 노드
 st
 StringTemplate
규칙이 계산한 템플릿은 보통 규칙을 다시 쓴 결과입니다.현재 규칙을 참조할 때 애프터 작업에서만 사용 가능
4 속성 역할 영역
Dynamic scoping
sample:
void foo(){int x=0; bar();}

void bar(){int y=x;}

체인을 호출하는 방법은 이전에 정의된 국부 변수에 접근할 수 있습니다
 
속성은 규칙 간의 통신 중간 기록 역할을 하고 ANTLR은 두 가지 속성 역할 영역을 제공한다. 전역 역할 영역과 규칙 내 역할 영역이다.
 
규칙 내 역할 영역
sample:
코드 참조[1] 규칙 내 작용역
 
전역 역할 영역
sample:
코드[2] 전역 역할 영역 참조
 
5 동작에서 속성 참조
ANTLR은 작업에 $및% 접두어가 있는 표현식을 특수 처리합니다. 값/코드를 입력합니다.
% 인용은 템플릿 표현식입니다. 다른 노트에 남겨 두십시오.
이름:
설명
 $tokenRef
token 자체 참조 ID {$ID}(ELSE stat)?{if($ELSE!=null)...}
 $tokenRef.attr
token 속성 참조 id=ID {$id.text} INT {$INT.line}
 $listLabel
+ = 조작부호로 표시된 탭으로Listids + = ID (',' ids + = ID) * {$ids}
 $ruleRef
규칙이 동적 작용역이 있고 다른 뜻이 없는 경우parser/treegrammar에서 규칙을 이렇게 인용할 수 있습니다.이 표현식은 Stack$Block입니다.size()
 $ruleRef.attr
규칙 속성 e=expr {$e.value, $expre.tree}
 $lexerRuleRef
lexer 규칙 인용은 Token(DIGIT {$DIGIT, $DIGIT.text})+
 $attr
규칙 반환 값, 매개 변수 또는 미리 정의된 속성 r[int x] returns[Token t]: {$t=$start;$x};
 $enclosingRule.attr
규칙 반환 값, 매개 변수 또는 미리 정의된 속성의 전체 한정명 r[int x] returns[Token t]: {$r.t=$r.start;$r.x};
 $globalScopeName
전역 동적 역할 영역 참조 $symbols.size()
 $x::y
동적 역할 영역 x에서 속성 y 참조 $CScope::symbols
 $x[-1]::y
동적 역할 영역 x 이전 역할 영역의 속성 y 인용 $block[-1]: symbols
 $x[-i]::y
동적 역할 영역 x 이전 i 개의 역할 영역에서 속성 y 인용 $block[-i]: symbols
 $x[i]::y
동적 역할 영역 Stack에서 창고 밑에 있는 i번째 역할 영역에서 속성 y 인용 (0 계수에서) $block[2]: symbols
 $x[0]::y
동적 역할 영역 Stack의 창고 밑 역할 영역에서 속성 y 참조 (0 계수에서) $block[0]: symbols
 
 
 
코드
[1] 규칙 내 역할 영역
설명: 변수가 정의되어 있으며, 플러그인 코드 블록에서 변수가 정의된 단계를 추적하고, 출력은 변수와 그 단계를 정의하지 않습니다
문법 정의
grammar T;

 

@members{//1

int level = 0;

boolean isDefined(String variable){

boolean result = false;

    // :                ,           

    //    i level-1    :   (block)   1  , block   Stack 0  

for(int i=level-1; i>=0; i--){

if($block[i]::symbols.contains(variable)){

System.out.println(variable + " found in nesting level " + (i+1));

result = true;

}

}

return result;

}

}

 

prog : block;

 

block

scope{//1

List symbols;

}

@init{

$block::symbols = new ArrayList();

level++;//1

}

@after{//1

System.out.println("symbols level " + level + " = " + $block::symbols);

level--;

}

: '{'decl* stat+'}'

;

 

decl : 'int' ID {$block::symbols.add($ID.text);}';'

;

 

stat : ID '=' INT ';'

{

if(!isDefined($ID.text)){//2

System.err.println("undefined variable level  " + level + ": "+ $ID.text);//1

}

}

| block//1

;

 

ID  : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;

INT : '0'..'9'+;

WS  :   ( ' '| '\t'| '\r'| '
') {$channel=HIDDEN;};

  
테스트 입력
{

int i;

int j;

i = 0;

{

int i;

int x;

x = 5;

}

x = 3;

}

  
[2] 전역 역할 영역 Sample
설명: 변수가 정의되어 있으며 방법과 코드 블록에서 변수가 정의한 차원 이름을 추적하고 출력에 정의되지 않은 변수와 차원 이름을 출력합니다
문법 정의
grammar T;

scope CScope{

String name;

List symbols;

}

 

@members{

  boolean isDefined(String variable){

        boolean result = false;

          for(int i=$CScope.size()-1; i>=0; i--){

                if($CScope[i]::symbols.contains(variable)){

                          System.out.println(">" + variable + " found in " +$CScope[i]::name);

                          result = true;

                  }

          }

          return result;

}

 }

 

prog scope CScope;

@init {

$CScope::symbols = new ArrayList();

$CScope::name = "global";

}

@after {

System.out.println("global symbols = " + $CScope::symbols);

}

: decl* func*;

func scope CScope;

@init {

$CScope::symbols = new ArrayList();

}

@after {

System.out.println("function " + $CScope::name + "()'s symbols = " +$CScope::symbols);

}

: 'void' ID{$CScope::name=$ID.text;} '(' ')' '{' decl* stat+ '}'

;

block scope CScope;

@init {

$CScope::symbols = new ArrayList();

$CScope::name = "level " + $CScope.size();

}

@after{ 

System.out.println("code block level " + $CScope.size() + " symbols = " +$CScope::symbols);

}

: '{'decl* stat+'}'

;

// :                ,           

//       ,decl()    Stack#peek(),

// ,        Stack       ,      block(   decl)    

decl : 'int' ID {$CScope::symbols.add($ID.text);}';'

;

stat : ID '=' INT ';'

{

if(!isDefined($ID.text)){ 

System.err.println("undefined variable in  " + $CScope::name + ": "+ $ID.text); 

}

}

| block 

;

 

ID  : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;

INT : '0'..'9'+;

WS  :   ( ' '| '\t'| '\r'| '
') {$channel=HIDDEN;};

  
테스트 입력
int i;

void f() {

     int i;

     {

int i;

i = 2;

     }

     i = 1;

}

void g(){

     i = 0;

     x = 3;

}

좋은 웹페이지 즐겨찾기