정규 표현식 또는 모든 가능성을 열거하는 것 이외의 다른 CFG를 사용하여 작업을 수행 할 수는 없습니다. (그룹화하여 실제 크기는 줄일 수 있지만 여전히 지수 적입니다.) 하나의 인스턴스 만 있고 토큰이 3 개만있는 경우 목록이 가장 쉬운 솔루션 일 것입니다.
그러나 다양한 토큰이 있고 앞으로 목록을 확장하려는 경우 모든 토큰 조합을 허용하는 것이 더 쉽지만 토큰 목록에 비트 맵을 연결하면 쉽게 중복을 확인할 수 있습니다 아마도 오류 메시지가 나타납니다.
당신이 언급 한 정확한 사례에 대한 간단한 flex
해결책이 있습니다. (원래는 필자가 많은 코드를 복제했지만 다음과 같이 읽기 쉽다고 생각합니다.) <MODS>
시작 조건은 첫 번째 모양이 [&^!]
일 때 트리거되고 그 나머지 부분을 흡수합니다. 다른 문자가 발견되면 다시 스캔하도록 표시되고 (yyless(0)
) 수정 자의 현재 마스크가 반환됩니다.
%{
// The MODS token has %type <ModMask>, and the associated
// semantic value will be the union of the enum bits.
typedef unsigned int ModMask;
enum { MOD_HAT=1, MOD_BANG=2, MOD_AMP=4 };
// This function maps a character to a modmask value.
// A real implementation would use a lookup table. I just included
// this definition so the snippet is usable.
ModMask tokenToMask(unsigned char c) {
return c == '^' ? MOD_HAT :
c == '!' ? MOD_BANG :
c == '&' ? MOD_AMP : 0;
%}
%x SC_MODS
%%
[&^!] { yylval.modmask = tokenToMask(yytext[0]; BEGIN(MODS); }
<MODS>[&^!] { ModMask m = tokenToMask(yytext[0];
if (yylval.modmask & m) {
yyerror("Duplicate modifier");
}
yylval.modmask |= m;
}
<MODS>.|\n { yyless(0); BEGIN(INITIAL); return MODS; }
지구상에서 '최대 1 개는 ... 어떤 순서로든'을 의미합니까? 뭐가 순서 야? 그리고 당신의 예는 * 2를 보여줍니다. * 명확히하십시오. – EJP
@EJP : "최대 하나의 집합"은 집합에서 각 요소의 0 또는 1을 선택하지만 1을 넘지 않는 것을 의미합니다. {A, B, C}의 집합에서 {A , C}는 괜찮습니다. A가 두 번 이상 선택 되었기 때문에 {A, A, C}는 아닙니다. "어떤 순서로든"은 항목의 순서가 A, B, C 또는 B, C, A 또는 기타 가능한 순서 일 수 있음을 의미합니다. – kkm
@EJP : 이것을 더 읽기 쉽게 만드는 방법에 대해 알고 있습니까? – kkm