문제

동일한 문법에서 유효한 날짜와 숫자를 모두 구문 분석하는 가장 단순한 (가장 짧고, 가장 적은 규칙 및 경고 없음)는 무엇입니까? 내 문제는 유효한 달 (1-12)과 일치하는 Lexer 규칙이 1-12의 발생과 일치한다는 것입니다. 숫자를 일치시키려면 다음과 같은 구문 분석 규칙이 필요합니다.

number: (MONTH|INT);

낮과 연도에 Lexer 규칙을 추가 할 때만 더 복잡해집니다. 나는 다음과 같은 날짜의 구문 분석 규칙을 원한다 :

date: month '/' day ( '/' year )? -> ^('DATE' year month day);

나는 달, 요일 및 연도가 구문 분석 또는 렉서 규칙인지 상관하지 않습니다. 같은 나무 구조로 끝나는 한. 또한 다른 곳에서 숫자를 인식 할 수 있어야합니다.

foo: STRING OP number -> ^(OP STRING number);
STRING: ('a'..'z')+;
OP: ('<'|'>');
도움이 되었습니까?

해결책

문제는 Lexer 및/또는 파서에서 구문 및 의미 적 검사를 수행하고 싶다는 것입니다. 그것은 일반적인 실수이며 매우 간단한 언어로만 가능한 것입니다.

당신이 정말로해야 할 일은 Lexer와 Parser에서 더 광범위하게 받아들이고 의미 론적 검사를 수행하는 것입니다. 당신이 당신의 록싱에 얼마나 엄격한 지, 그러나 당신은 매월의 날에 앞서 제로를 받아 들여야하는지 여부에 따라 두 가지 기본 옵션이 있습니다. 1) ints를 실제로 받아들이십시오. 유효한 날이지만 유효한 int는 유효한 토큰 만 허용합니다. 코드의 뒷부분에서 필요한 의미 론적 점검이 적을 것이기 때문에 두 번째 권장 (INTS는 구문 수준에서 확인 가능하므로 날짜에 시맨틱 검사 만 수행하면됩니다. 첫 번째 접근법 : 첫 번째 접근 방식 :.

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

두 번째 접근법 :

DATENUM: '0' '1'..'9';
INT: '0' | SIGN? '1'..'9' '0'..'9'*;

Lexer 에서이 규칙을 사용하는 후에는 날짜 필드가 다음과 같습니다.

date: INT '/' INT ( '/' INT )?

또는:

date: (INT | DATENUM) '/' (INT | DATENUM) ('/' (INT | DATENUM) )?

그 후, 당신은 당신의 날짜가 유효한지 확인하기 위해 당신의 AST를 통해 시맨틱 런을 수행합니다.

그러나 문법에서 시맨틱 점검을 수행하는 데 세워진 경우 ANTLR은 구문 분석기에서 시맨틱 곤경을 허용하므로 다음과 같은 값을 확인하는 날짜 필드를 만들 수 있습니다.

date: month=INT '/' day=INT ( year='/' INT )? { year==null ? (/* First check /*) : (/* Second check */)}

그러나 이렇게하면 문법에 언어 별 코드를 포함 시키며 대상 전체에서 휴대 할 수 없습니다.

다른 팁

Antlr4를 사용하여 여기에 내가 사용한 간단한 결합 문법이 있습니다. Lexer를 사용하여 간단한 토큰에 대해서만 사용하여 파서 규칙이 날짜 대 번호를 해석하기위한 규칙을 남깁니다.

// parser rules

date 
    : INT SEPARATOR month SEPARATOR INT
    | INT SEPARATOR month SEPARATOR INT4
    | INT SEPARATOR INT SEPARATOR INT4;

month : JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC ;

number : FLOAT | INT | INT4 ;

// lexer rules

FLOAT : DIGIT+ '.' DIGIT+ ;

INT4 : DIGIT DIGIT DIGIT DIGIT;
INT : DIGIT+;

JAN : [Jj][Aa][Nn] ;
FEB : [Ff][Ee][Bb] ;
MAR : [Mm][Aa][Rr] ;
APR : [Aa][Pp][Rr] ;
MAY : [Mm][Aa][Yy] ; 
JUN : [Jj][Uu][Nn] ;
JUL : [Jj][Uu][Ll] ;
AUG : [Aa][Uu][Gg] ;
SEP : [Ss][Ee][Pp] ; 
OCT : [Oo][Cc][Tt] ; 
NOV : [Nn][Oo][Vv] ;
DEC : [Dd][Ee][Cc] ;

SEPARATOR : [/\\\-] ;

fragment DIGIT : [0-9];
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top