2017-01-24 5 views
0

J'essaie de lire un nombre connu (à l'exécution) de caractères dans une Lex Flex. Je sais que cela commence avec un CRLF, donc je fais correspondre cela, puis lire les caractères literal_length en utilisant yyinput.Comment puis-je empêcher Flex de rejeter les caractères yyinput?

<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); 
} 

Mais yyinput n'ajoute pas les nouveaux personnages, au lieu qu'il contient:

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

ce qui signifie que yytext ne reçoivent pas les caractères literal_length supplémentaires. Je préfère ne pas créer un nouveau tampon pour les stocker si je peux l'éviter, car je sais que la séquence de caractères est déjà en mémoire. En plus de redéfinir complètement yyinput(), y a-t-il un moyen de conserver les caractères supplémentaires dans yytext?

Répondre

0

Vous faites correspondre le CRLF, donc yytext contient CRLF.

Si vous voulez faire correspondre les chiffres suivants CRLF, vous devez faire correspondre les chiffres:

%x EXPECT_DIGITS 

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

Que les caractères peuvent être lus est déjà un détail de mise en œuvre, vous ne pouvez pas compter.

Vous pouvez probablement simplifier la correspondance un peu plus pour vous en sortir sans un état spécial (par exemple, vous pouvez faire correspondre \r\n[0-9]*, alors les chiffres font déjà partie de yytext).

+0

Merci pour l'information Simon. Mais je ne peux pas créer une correspondance pour un nombre exact de caractères qui n'est pas connu avant l'exécution. Je sais que les caractères sont lus car l'appel à yyinput() les fait lire. Nous pouvons détecter si EOF se produit avant le nombre attendu de caractères, et YYINPUT peut être fait pour attendre s'ils ne sont pas encore prêts. Donc, il est connu que les personnages sont là. Je pourrais réécrire yyinput() pour ne pas détruire les caractères entrants, mais comme cela est exclu par la question, j'accepterai votre réponse comme un "non". – Roderick

+0

@Roderick, c'est ce que fait l'astérisque. Le '[0-9]' correspond à n'importe quel chiffre ASCII, l'astérisque répète cette correspondance. 'yyleng' vous indique alors combien de caractères ont correspondu. –

+0

Un astérisque obtient tous les caractères qu'il peut. La question était d'obtenir des caractères "literal_length", et seulement ce nombre. – Roderick

0

Vous pouvez faire correspondre les chiffres dans un état séparé, et mettre fin à l'état quand vous avez tous:

%{ 
    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 */ 

Il faut un peu plus la gestion des erreurs, évidemment.