web-dev-qa-db-fra.com

Expression régulière pour un littéral chaîne dans flex/lex

J'expérimente pour apprendre le flex et aimerais faire correspondre les littéraux de chaîne. Mon code ressemble actuellement à:

"\""([^\n\"\\]*(\\[.\n])*)*"\""        {/*matches string-literal*/;}

Je suis aux prises avec des variations depuis une heure environ et je ne peux pas le faire fonctionner comme il se doit. J'espère essentiellement faire correspondre un littéral de chaîne qui ne peut pas contenir de nouvelle ligne (sauf s'il est échappé) et prend en charge les caractères échappés.

Je suis probablement en train d'écrire une expression régulière médiocre ou incompatible avec flex. S'il vous plaît donnez votre avis!

45
Thomas

Une chaîne consiste en un guillemet

"

suivi de zéro ou plus d'un élément échappé

\\.

ou un caractère non-quote

[^"\\]

et enfin une citation finale

"

Mettez tout cela ensemble, et vous avez

\"(\\.|[^"\\])*\"

Les guillemets de délimitation sont échappés car il s’agit de méta-caractères Flex.

103
Jonathan Feinberg

Pour une seule ligne ... vous pouvez utiliser ceci:

\"([^\\\"]|\\.)*\"  {/*matches string-literal on a single line*/;}
18
Pete

Pourquoi ne pas utiliser un état de départ ...

 int enter_dblquotes = 0; 

% x DBLQUOTES 
 %% 

 "" BEGIN (DBLQUOTES); enter_dblquotes ++;} 

 <DBLQUOTES> *\"
 {
 if (enter_dblquotes) {
 handle_this_dblquotes (yytext); 
 COMMENCE (INITIAL);/* revient à la normale */
 enter_dblquotes--; 
 } 
} 
 ... plus de règles suivent ...

Il était similaire à cet effet (flex utilise %s ou %x pour indiquer l’état attendu. Lorsque l’entrée flex détecte un devis, elle passe à un autre état, puis continue à lexer jusqu’à atteindre un autre devis, dans lequel elle retourne à la position. état normal.

8
t0mm13b

Collez mon extrait de code sur la gestion des chaînes en flex, espérons inspirer votre réflexion.

Utilisez Condition initiale pour gérer le littéral de chaîne sera plus évolutif et clair.

%x SINGLE_STRING

%%

\"                          BEGIN(SINGLE_STRING);
<SINGLE_STRING>{
  \n                        yyerror("the string misses \" to termiate before newline");
  <<EOF>>                   yyerror("the string misses \" to terminate before EOF");
  ([^\\\"]|\\.)*            {/* do your work like save in here */}
  \"                        BEGIN(INITIAL);
  .                         ;
}
0
pwxcoo

Une réponse qui arrive en retard mais qui peut être utile au prochain qui en aura besoin: 

\"(([^\"]|\\\")*[^\\])?\"
0
david