2013-11-15 2 views
1

flex + bison C++를 사용하여 mgf 파일 구문 분석기 (구문 : http://www.matrixscience.com/help/data_file_help.html)에서 작업하고 있습니다.flex 및 bison : 따옴표없이 구문 분석 문자열

저는 렉서 (lex)와 파서 (yacc)를 깨달았습니다. 하지만 해결할 수없는 문제가 있습니다. 문자열을 파싱하려고 할 때.

중요 여기서

CHARGE=1+, 2+ and 3+ 
#some comments 

BEGIN IONS 
TITLE= Cmpd 1, +MSn(417.2108), 10.0 min //line 20 
PEPMASS=417.21083 35173 
CHARGE=3+ 
123.79550 20 
285.16455 56 
302.14335 146 1+ 
[other datas ...] 
END IONS 

BEGIN IONS 
[an other one ... ] 

제 (최소) 렉서 :. MGF_TOKEN_DEBUG가 juste 인쇄 a하는 매크로이다 여기

입력의 예는 문자열 주위가 '또는'없다 라인

#define MGF_TOKEN_DEBUG(val) std::cout<<"token: "<<val<<std::endl 

\n { 
    MGF_TOKEN_DEBUG("T_EOL"); 
    return token::T_EOL; 
} 

^[#;!/][^\n]* { 
    MGF_TOKEN_DEBUG("T_COMMENT"); 
    return token::T_COMMENT; 
} 

[[:space:]] {} 

/** values **/ 
[0-9]+ { 
    MGF_TOKEN_DEBUG("V_INTEGER"<<" (="<<yytext<<")"); 
    return token::V_INTEGER; 
} 

[0-9]+"."[0-9]* { 
    MGF_TOKEN_DEBUG("V_DOUBLE"<<" (="<<yytext<<")"); 
    return token::V_DOUBLE; 
} 

[0-9]+("."[0-9]+)?[eE][+-][0-9]+ { 
    MGF_TOKEN_DEBUG("V_DOUBLE"<<" (="<<yytext<<")"); 
    return token::V_DOUBLE; 
} 

"+" { 
    MGF_TOKEN_DEBUG("T_PLUS"); 
    return token::T_PLUS; 
} 


"=" { 
    MGF_TOKEN_DEBUG("T_EQUALS"); 
    return token::T_EQUALS; 
} 

"," { 
    MGF_TOKEN_DEBUG("T_COMA"); 
    return token::T_COMA; 
} 

"and" { 
    MGF_TOKEN_DEBUG("T_AND"); 
    return token::T_AND; 
} 
/*** keywords */ 
^"CHARGE" { 
    MGF_TOKEN_DEBUG("K_CHARGE"); 
    return token::K_CHARGE; 
} 

^"TITLE" { 
    MGF_TOKEN_DEBUG("K_TITLE"); 
    return token::K_TITLE; 
} 
[ others keywords ...] 

/**** string : problem here **/ 
[A-Za-z]([:;,()A-Za-z0-9_.-]|[[:space]])* { 
    MGF_TOKEN_DEBUG("V_STRING"<<" (="<<yytext<<")"); 
    return token::V_STRING; 
} 

그리고 (최소화) 파서.

내가 좋아하는 것
[...] 
[line 20] 
token: K_TITLE 
token: T_EQUALS 
token: v_STRING (= Cmpd) 
token: V_INTEGER (= 1) 
Error line 20: syntax error, unexpected integer, expecting end of line 

이 가지고 : 4,593,210

내 문제는 내가 다음 토큰을 얻을 수 있다는 것입니다

[...] 
[line 20] 
token: K_TITLE 
token: T_EQUALS 
token: v_STRING (Cmpd 1, +MSn (417.2108), 10.0 min) 
token: T_EOL 

누군가가 나를 도울 수 있다면 ...


편집 # 1 토큰의 연결을 사용하여 문제를 "해결"했습니다 :

렉스 :

[A-Za-z][^\n[:space:]+-=,]* { 
    MGF_TOKEN_DEBUG("V_STRING"<<" (="<<yytext<<")")) 
    return token::V_STRING;t 
} 

은 yacc :

string_st : V_STRING 
     | string_st V_STRING 
     | string_st number 
     | string_st T_COMA 
     | string_st T_PLUS 
     | string_st T_MINUS 
     ; 

blockparam : K_CHARGE T_EQUALS charge T_EOL | K_TITLE T_EQUALS string_st T_EOL | [others...]; 
+1

적절한 태그는 'flex-lexer'이며,'flex '는 Adobe와 관련이 있습니다. – crashmstr

답변

1

당신의 캐릭터는 항상 곁에 텍스트 TITLE 시작하고 난 당신이 start conditions를 사용하는 것이 좋습니다 것입니다
텍스트 \n (줄 바꿈 문자)로 끝납니다 경우 ,

%x IN_TITLE 

"TITLE"  { /* return V_STRING of TITILE in c++ code */ BEGIN(IN_TITLE); } 
<IN_TITLE>= { /* return T_EQUALS in c++ code */; } 
<IN_TITLE>"\n" { BEGIN(INITIAL); } 
<IN_TITLE>.* { MGF_TOKEN_DEBUG("V_STRING"<<" (="<<yytext<<")");return token::V_STRING; } 

% x IN_TITLEIN_TITLE 상태를 정의하고 패턴 텍스트 TITLE이 패턴을 시작하게합니다. 시작되면 \n은 초기 상태 (INITIAL은 사전 정의 됨)로 돌아가고 다른 모든 문자는 특별한 조치없이 V_STRING으로 소비됩니다. 당신은 실제로 | 연산자를 필요가 없습니다

[A-Za-z]([:;,()A-Za-z0-9_.-]|[[:space:]])* 
            ^

:

[A-Za-z]([:;,()A-Za-z0-9_.-]|[[:space]])* 

가 있어야한다 :

1

기본적인 문제는 단순한 오타입니다.예를 들어, 키워드 (TITLE : 당신이 것을 해결 한 후에는 다른 문제가 있음을 확인할 수 있습니다

[A-Za-z][[:space:]:;,()A-Za-z0-9_.-]* 

:; 다음은 완벽하게 합법적 (아래 참조하지만 아마 당신이 원하지 않는 것 중 하나))은 STRING 패턴이 길기 때문에 STRING으로 어소싱됩니다. ([:space:]\n을 포함하기 때문에 실제로는 STRING 패턴은 아마 입력의 끝으로 확장됩니다. 당신은 아마 [:blank:]을 원했다.)

난 당신이 구문 분석하려는 형식의 설명에 순간적으로했다, 그러나 그것은 아주 정확한 설명이 아닙니다. 그러나 매개 변수 행의 형식이 나타납니다 :

^[[:alpha:]]+=.*$ 

는 아마도 :alpha::alnum: 또는 뭔가 더 허용되어야한다; 내가 말했듯이, 설명은 정확하지 않았습니다.

  • 키워드는 대소 문자를 구분, 그래서 모두 TITLEtitle은 동일하게 작동하며,
  • = 기호 의무와 그것의 양쪽에 공간이 없을 수 있습니다 : 무엇 분명하기 때문이다. (따라서 귀하의 TITLE= 행은 올바르지 않지만 중요하지 않을 수 있습니다.)

는 데이터의 분석을 방해하지하려면 그 값이 = 후 일부이며 그 유형 (대소 정규화) 키워드에 해당하는 하나의 "토큰"위의 수 있도록 할 수 있습니다. 물론, 각 매개 변수 유형은 고유 조건 구문 분석기를 요구할 수 있으며 이는 시작 조건을 사용하여 flex에서만 얻을 수 있습니다. 어쨌든 STRING 패턴의 일부가 아닌 TITLE에있는 길잃은 문자의 결과에 대해 생각하고 결과 어휘 오류를 어떻게 처리할지 제안해야합니다.


귀하의 코드는 렉스러에서 파서로 텍스트 값을 전달하는 방법을 명확하게하지 않습니다. yytext의 값은 해당하는 토큰에 대한 렉서 동작 내부에서만 안전하다는 점을 알아야합니다. 렉서에 대한 다음 호출은 그것을 무효화 할 것이고, 바이손 파서는 거의 항상 룩어 헤드 토큰을 가지기 때문에 렉서는 토큰이 처리되기 전에 다시 호출 될 것이다. 따라서 복사본 yytext을 파서에 전달해야하며 파서는 메모리 누수가 발생하지 않도록 복사본의 소유권을 가져와야합니다.