2010-11-11 50 views
0

J'ai le problème suivant.REGEX (PCRE) correspondant seulement si zéro ou une fois

Prenons l'entrée (wikitext)

======hello((my first program)) world====== 

Je veux correspondre « bonjour », « mon premier programme » et « monde » (notez l'espace).

Mais pour l'entrée.

======hello(my first program)) world====== 

Je veux correspondre « bonjour (mon premier programme » et « monde »

En d'autres termes, je veux correspondre des lettres, des espaces et de plus tous les symboles simples (pas de double ou plus).

Cela devrait être fait avec les propriétés de caractères unicode comme \ p {L}, \ p {S} ou \ p {Z}, tel que documenté here.

Des idées?

Addendum 1

Le regex vient d'arrêter avant tout symbole double ou de ponctuation en termes unicode, qui est, avant tout \ p {S} {2,} ou \ p {P} {2 ,}. Je n'essaie pas d'analyser tout le wikitext avec ceci, lisez attentivement ma question. La regex que je cherche EST pour la lexer sur laquelle je travaille, et la faire correspondre à de telles entrées simplifiera énormément mon analyseur.

Addendum 2

Le modèle doit travailler avec preg_match(). Je peux imaginer comment je devrais le diviser d'abord. Peut-être utiliserait-il un peu de lookahead, je ne sais pas, j'ai essayé tout ce que je pouvais imaginer.

En utilisant seulement preg_match() est une exigence dans la pierre par la mise en œuvre actuelle du lexer. Il doit en être ainsi, car c'est la manière naturelle de fonctionner des lexers: ils correspondent aux séquences du flux d'entrée.

Répondre

1
return preg_split('/([\pS\pP])\\1+/', $theString); 

Résultat: http://www.ideone.com/YcbIf

(Vous devez vous débarrasser des chaînes vides manuellement.)


Edit: comme preg_match regex:

'/(?:^|([\pS\pP])\\1+)((?:[^\pS\pP]|([\pS\pP])(?!\\3))*)/' 

prendre la 2ème groupe de capture quand il est apparié.Exemple: http://www.ideone.com/ErTVA

Mais vous pouvez simplement consommer ([\pS\pP])\\1+ et jeter, ou si ne correspond pas, consommer (?:[^\pS\pP]|([\pS\pP])(?!\\3))* et enregistrer, depuis votre lexer va utiliser plus de 1 regex de toute façon?

+0

Si vous pouviez penser à "addendum 2" dans la question ce serait génial. L'utilisation de preg_match() est une exigence imposée par l'implémentation actuelle du lexer. Il doit en être ainsi, car c'est la manière naturelle de fonctionner des lexers: ils correspondent aux séquences du flux d'entrée. – Flavius

+0

Merci, ''/((?: [^ \ PS \ pP] | ([\ pS \ pP]) (?! \\ 2)) *)/mu'' l'a fait. Je n'ai pas besoin de faire correspondre le "======" parce que celui-ci est déjà reconnu par le lexeur, et ensuite il met le lexeur dans le contexte de la tentative de faire correspondre l'expression rationnelle que vous m'avez donné. Quoi qu'il en soit, cela a résolu mon problème. – Flavius

0

Les expressions régulières sont notoirement surutilisées et mal adaptées pour l'analyse de langages comme celui-ci. Vous pouvez vous en sortir pendant un petit moment, mais vous finirez par trouver quelque chose qui casse votre parser, nécessitant un tweak après tweak et une énorme bibliothèque de tests unitaires pour assurer la conformité.

Vous devriez envisager sérieusement d'écrire un lexeur et un analyseur appropriés à la place.

+0

Ceci est en fait pour un lexer que j'écris. La chaîne correspondante sera un jeton. Si je parviens à le faire dans la lexer (en utilisant l'expression rationnelle que je recherche maintenant), l'analyseur sera extrêmement simplifié. – Flavius

+0

Lorsque vous écrivez des lexers, vous lisez généralement un caractère et décidez quoi en faire, puis vous en lisez un autre. Dans l'étape d'analyse, vous déciderez exactement comment gérer ce cas, mais le lexer devrait juste retourner des jetons comme (en pseudo-code) '[LEVEL_6_HEADING, TEXT (" bonjour "), LPAREN, TEXT (" mon premier programme "), RPAREN, RPAREN, LEVEL_6_HEADING] 'pour le deuxième exemple. L'analyseur devra donner un sens à ces jetons. – cdhowie

+0

Je sais comment fonctionne un lexer classique. Celui sur lequel je travaille n'est pas classique. L '"utilisateur" sera capable de s'y accrocher (donc pas de "générateur lexer" impliqué ici). Ecoute, je ne cherche pas de conseils sur quoi faire et quoi, je connais déjà mes exigences et la façon dont je le fais est la meilleure. Je cherche seulement un motif. – Flavius