2016-10-12 1 views
0

저는 ANTLR을 완전히 신인입니다.ANTLR 구문 분석에서 정확한 렉서 (lexer) 부분을 찾지 못함

나는 다음과 같은 ANTLR 문법이 있습니다

grammar DrugEntityRecognition; 

// Parser Rules 

derSentence : ACTION (INT | FRACTION | RANGE) FORM TEXT; 

// Lexer Rules 

ACTION : 'TAKE' | 'INFUSE' | 'INJECT' | 'INHALE' | 'APPLY' | 'SPRAY' ; 

INT : [0-9]+ ; 

FRACTION : [1] '/' [1-9] ; 

RANGE : INT '-' INT ; 

FORM : ('TABLET' | 'TABLETS' | 'CAPSULE' | 'CAPSULES' | 'SYRINGE') ; 

TEXT : ('A'..'Z' | WHITESPACE | ',')+ ; 

WHITESPACE : ('\t' | ' ' | '\r' | '\n' | '\u000C')+ -> skip ; 

을 그리고 문장을 구문 분석 할 때 다음과 같이

String upperLine = line.toUpperCase(); 
org.antlr.v4.runtime.CharStream stream = new ANTLRInputStream(upperLine); 
DrugEntityRecognitionLexer lexer = new DrugEntityRecognitionLexer(stream); 
lexer.removeErrorListeners(); 
lexer.addErrorListener(ThrowingErrorListener.INSTANCE); 

CommonTokenStream tokenStream = new CommonTokenStream(lexer); 
DrugEntityRecognitionParser parser = new DrugEntityRecognitionParser(tokenStream); 

try { 
     DrugEntityRecognitionParser.DerSentenceContext ctx = parser.derSentence(); 

     StringBuilder sb = new StringBuilder(); 

     sb.append("ACTION: ").append(ctx.ACTION()); 
     sb.append(", "); 
     sb.append("FORM: ").append(ctx.FORM()); 
     sb.append(", "); 
     sb.append("INT: ").append(ctx.INT()); 
     sb.append(", "); 
     sb.append("FRACTION: ").append(ctx.FRACTION()); 
     sb.append(", "); 
     sb.append("RANGE: ").append(ctx.RANGE()); 

     System.out.println(upperLine); 
     System.out.println(sb.toString()); 

    } catch (ParseCancellationException e) { 
     //e.printStackTrace(); 
    } 

렉서의 입력의 예 :

take 10 Tablet (25MG) by oral route every week 

이 경우 ACTION 노드는 채워지지 않지만 take은 다음과 같이 인식됩니다. ACTION 노드가 아닌 TEXT 노드. 그러나 10은 INT 노드로 인식됩니다.

정확히 어떻게 작동하는이 문법을 수정할 수 있습니까? ACTION 노드가 올바르게 채워지는 FORM과 채워지지 않는 FORM은 모두 올바르게 작동합니까?

답변

1

는 문법의 몇 가지 문제가 있습니다

  1. 텍스트 규칙은 대문자와 일치합니다. ACTION과 동일합니다.
  2. 단일 텍스트 규칙 (여기서는 쉼표)에 구두점과 텍스트를 섞어서는 안됩니다. 그렇지 않으면 토큰 사이에 공백을 자유롭게 허용 할 수 없습니다.
  3. 괄호와 일치하지 않으므로 (25MG)은 유효하지 않으며 파서는 오류 상태로 돌아갑니다.
  4. 구문 오류가 있는지 확인하지 않았으므로 인식 중에 무엇이 잘못되었는지 확인하지 않았습니다. 의심, 항상 예상대로 입력이 실제로 토큰 화되어 있는지 확인하기 위해 토큰 소스에서 토큰 순서를 인쇄 또한

. 파서에 가기 전에 문법을 수정하십시오. 대소 문자 구분에 대해

: 일반적으로 다음과 같은 규칙이 있습니다 (언어는 대소 문자를 구분하는 경우) :

ACTION : T A K E | I N F U S E | I N J E C T | I N H A L E | A P P L Y | S P R A Y; 
:

fragment A: [aA]; 
fragment B: [bB]; 
fragment C: [cC]; 
fragment D: [dD]; 
... 

그래서 당신의 키워드를 정의 다음 두 경우에 문자와 일치하고

+0

1. 렉서를 실행하기 전에 문장을 대문자로 변환합니다. 2. 고마워, 나는 그것을 바꿀 것이고 그것이 어떻게되는지 보게 될 것이다. 3. 일치하는 괄호는 어떻게 처리해야합니까? 4. 동일합니다. 구문 오류를 확인하려면 어떻게해야합니까? 또한 토큰 소스에서 내 토큰 시퀀스를 인쇄하여 토큰 화되었는지 예상하는 방법은 무엇입니까? 다시 말하지만, 완전한 초보자 - 구체적인 도움이 필요합니다. – daniel0mullins

+0

괄호 부분의 경우 괄호 부분과 일치하는 다른 규칙을 만듭니다. '복용량 :'('INT ('M '|'μ ')'G '') '또는 유사하거나, 아마도 선택 사항으로. 토큰 목록은 쉽게 얻을 수 있습니다. 토큰 스트림과 그것의'getTokens()'메소드를 보라. ANTLR 런타임의 대부분의 클래스에는 일부 정보를 인쇄하는 데 사용할 수있는 toString() 메서드가 있습니다. 오류의 경우 Parser.getNumberOfSyntaxErrors()를 사용할 수 있지만 실제 오류 처리는 약간의 작업 (자체 오류 수신기 사용)입니다. 이 문제는 자체 질문으로 처리해야합니다. –

관련 문제