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;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
ANTLR 및 C#을 사용하여 외부 DSL 만들기이 게시물에서는 ANTLR을 사용하여 C#에서 간단한 DSL을 작성하는 방법을 보여줍니다. A domain-specific language is a computer language specialized to a pa...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.