2017-01-24 1 views
0

Ich versuche, eine bekannte Anzahl (zur Laufzeit) von Zeichen in einem Flex-Lexer zu lesen. Ich weiß, dass es mit einer CRLF beginnt, also passe ich das an, dann lese literal_length Zeichen mit yyinput.Wie kann ich verhindern, dass Flex yyinput-Zeichen verwirft?

<EXPECT_LITERAL>"\r\n"  { 
    for(int i=0;i<literal_length;i++){ 
     int c= yyinput(yyg); 
     if(c == EOF) break; 
    } 
    *yylval = val_new_s(yytext); 
    return(LITERAL); 
} 

Aber yyinput nicht die neuen Charaktere hinzufügen, sondern es enthält:

*yy_c_buf_p = '\0'; /* preserve yytext */ 
yy_hold_char = *++yy_c_buf_p; 

was bedeutet, dass yytext nicht die zusätzlichen literal_length Zeichen nicht erhalten. Ich würde lieber keinen neuen Puffer erstellen, um sie zu speichern, wenn ich es vermeiden kann, weil ich weiß, dass die Zeichenfolge bereits im Speicher ist.

Abgesehen davon, dass yyinput() völlig neu definiert wird, gibt es eine Möglichkeit, die zusätzlichen Zeichen in yytext zu behalten?

Antwort

0

Sie stimmen mit der CRLF überein, daher enthält yytext CRLF.

Wenn Sie Ziffern entsprechen CRLF folgen, dann müssen Sie die Ziffern entsprechen:

%x EXPECT_DIGITS 

<EXPECT_LITERAL>\r\n BEGIN(EXPECT_DIGITS); /* ignore otherwise */ 
<EXPECT_DIGITS>[0-9]* BEGIN(INITIAL);  /* parse yytext here */ return LITERAL; 

Dass die Zeichen bereits gelesen werden kann, ist eine Implementierung Detail kann man nicht vertrauen.

Sie können wahrscheinlich die Übereinstimmung ein wenig mehr vereinfachen, um ohne einen speziellen Zustand wegzukommen (zum Beispiel können Sie \r\n[0-9]* zusammenbringen, dann sind die Ziffern bereits ein Teil von yytext).

+0

Danke für die Informationen Simon. Aber ich kann keine Übereinstimmung für eine genaue Anzahl von Zeichen erstellen, die bis zur Laufzeit nicht bekannt ist. Ich weiß, dass die Zeichen gelesen werden, weil der Aufruf von yyinput() bewirkt, dass sie gelesen werden. Wir können feststellen, ob EOF vor der erwarteten Anzahl von Zeichen auftritt, und YYINPUT kann warten, wenn sie noch nicht bereit sind. So ist bekannt, dass die Charaktere da sind. Ich könnte yyinput() umschreiben, um die eingehenden Zeichen NICHT zu zerstören, aber da dies durch die Frage ausgeschlossen ist, akzeptiere ich deine Antwort als "nein". – Roderick

+0

@Roderick, das ist, was der Stern tut. Die '[0-9]' entspricht einer beliebigen ASCII-Ziffer, der Stern wiederholt diese Übereinstimmung. 'yyleng' sagt Ihnen dann, wie viele Zeichen übereinstimmen. –

+0

Ein Sternchen erhält alle Zeichen, die es kann. Die Frage war, "literal_length" -Zeichen zu bekommen, und nur so viele. – Roderick

0

Sie können die Ziffern in einem separaten Zustand entsprechen, und den Zustand beenden, wenn Sie alle von ihnen haben:

%{ 
    uint64_t accumulator; 
    unsigned int remaining_digits; 
%} 

%x EXPECT_DIGITS 

<EXPECT_LITERAL>\r\n BEGIN(EXPECT_DIGITS); remaining_digits = literal_length; accumulator = 0; 
<EXPECT_DIGITS>[0-9] accumulator = accumulator * 10 + *yytext - '0'; if(!--remaining_digits) { BEGIN(INITIAL); *yylval = accumulator; return LITERAL; } 
<EXPECT_DIGITS>.  /* handle non-digits */ 

Dies benötigt etwas mehr Fehlerbehandlung, offensichtlich.

Verwandte Themen