Dans cette tâche, vous devez écrire un programme qui lit une expression régulière et génère un autre programme qui affiche si une chaîne d'entrée est acceptée par cette expression régulière. La sortie doit être un programme écrit dans la même langue que votre soumission.
Contribution
L'entrée est une expression régulière r correspondant à l'ABNF suivant (la règle de production initiale est REGEX
):
REGEX = *( STAR / GROUP / LITERAL / ALTERNATIVE )
STAR = REGEX '*'
GROUP = '(' REGEX ')'
LITERAL = ALPHA / DIGIT
ALTERNATIVE = REGEX '|' REGEX
Si l'entrée ne correspond pas à cette grammaire, le comportement de votre programme n'est pas défini.
Interprétation
Interpréter l'entrée comme une expression régulière, où se *
trouve l'étoile de Kleene (signifiant répéter l'argument gauche zéro ou plusieurs fois ), |
est une alternative (
et )
regrouper et aucun opérateur du tout concaténé. Le regroupement a la priorité sur l'étoile, l'étoile a la priorité sur la concaténation, la concaténation a la priorité sur l'alternative.
Une chaîne est réputée acceptée si l'expression régulière correspond à la chaîne entière.
Production
La sortie du programme est un autre programme écrit dans le même langage que votre soumission qui lit une chaîne s d'une manière définie par l'implémentation au moment de l'exécution, affiche si r accepte s puis se termine. La sortie peut être effectuée d'une manière définie par l'utilisateur bien qu'il ne doive y avoir que deux sorties distinctes pour les programmes acceptés et rejetés.
Vous pouvez supposer que l'entrée de votre programme de sortie ne dépasse jamais 2 16 -1 octets.
Restrictions
Ni votre soumission ni aucun programme généré par votre soumission ne peut utiliser des fonctionnalités intégrées ou des bibliothèques qui
- match regexes
- transformer des expressions régulières
- compiler des expressions régulières
- générer des analyseurs à partir d'une grammaire
- simplifier le problème de manière à ce que votre soumission devienne triviale
Notation
Le score de votre soumission est le nombre de caractères qu'il contient. La soumission avec le score le plus bas gagne.
Cas de test
Toutes les testcases contiennent une expression régulière, un ensemble de chaînes acceptées, un ensemble de chaînes rejetées et un exemple de programme en C99 qui est une sortie valide d'une soumission (hyptothétique) C99.
(expression régulière vide)
Chaînes acceptées
- (entrée vide)
Chaînes rejetées
- foo
- bar
- baz
- quux
Exemple de programme
#include <stdio.h>
int main() {
char input[65536];
gets(input);
return input[0] != 0;
}
(b|)(ab)*(a|)
( a
et en b
alternance)
chaînes acceptées
a
ba
abababababa
abab
chaînes rejetées
afba
foo
babba
exemple de programme
#include <stdio.h>
int main() {
char input[65536];
int state = 0;
for (;;) switch (state) {
case 0: switch (getchar()) {
case 'a': state = 1; break;
case 'b': state = 2; break;
case EOF: return 0;
default: return 1;
} break;
case 1: switch (getchar()) {
case 'b': state = 2; break;
case EOF: return 0;
default: return 1;
} break;
case 2: switch (getchar()) {
case 'a': state = 1; break;
case EOF: return 0;
default: return 1;
} break;
}
(0|1(0|1)*)(|A(0|1)*1)
(nombres à virgule flottante binaires)
chaînes acceptées
- 10110100
- 0
- 1A00001
chaînes rejetées
- 011
- 10A
- 1A00
- 100A010
return (regex.match(stdin) is not null)
n'est pas permis d' avoir un programme comme .Réponses:
Ruby,
641651543 caractèresCette version rubis est devenue assez longue à cause de plusieurs cas d'angle dans l'analyseur d'expressions rationnelles (je devrais peut-être essayer une approche différente). Il attend l'expression régulière sur STDIN et sort le code rubis correspondant pour le matcher vers STDOUT.
Le programme génère directement du code pour un NFA-ε qui est ensuite exécuté dans le matcher.
Cas de test 1: (la sortie comprend des sauts de ligne et une indentation supplémentaires)
Cas de test 2:
Un autre exemple:
Éditer: Ajout d'une transition pour corriger le bug PleaseStand noté dans les commentaires. Modification également de l'initialisation de l'état.
la source
011
des regex se(0|1(0|1)*)(|A(0|1)*1)
traduit partrue
- elle devrait l'êtrefalse
.C, 627 caractères
Ce programme traite son premier argument de ligne de commande comme entrée et génère du code C comme sortie.
Voici sa sortie pour
(0|1(0|1)*)(|A(0|1)*1)
(avec ajout de nouvelles lignes):Si vous fournissez une entrée valide comme premier argument de ligne de commande, elle renvoie l'état de sortie 1. Sinon, elle renvoie l'état de sortie 0.
L'un ou l'autre programme, si vous ne fournissez pas l'argument de ligne de commande, déréférence un pointeur nul, provoquant une erreur de segmentation. Un regex suffisamment long débordera les tampons de cette soumission, et la taille de l'entrée d'un programme généré est limitée par la taille de la pile. Cependant, tous les cas de test fonctionnent.
Notez que
e(g=h++,C=h++,0,0);
introduit un comportement indéfini. Si, par exemple, les programmes générés ne se compilent pas, vous pouvez essayer de remplacer l'instruction parh+=2;e(g=h-1,C=h-2,0,0);
, qui comporte cinq caractères de plus.la source