En esta tarea, debe escribir un programa que lea una expresión regular y genere otro programa que muestre si esa expresión regular acepta una cadena de entrada. El resultado debe ser un programa escrito en el mismo idioma que su envío.
Entrada
La entrada es una expresión regular r que coincide con el siguiente ABNF (la regla de producción inicial es REGEX
):
REGEX = *( STAR / GROUP / LITERAL / ALTERNATIVE )
STAR = REGEX '*'
GROUP = '(' REGEX ')'
LITERAL = ALPHA / DIGIT
ALTERNATIVE = REGEX '|' REGEX
Si la entrada no coincide con esta gramática, el comportamiento de su programa no está definido.
Interpretación
Interprete la entrada como una expresión regular, donde *
está la estrella de Kleene (es decir, repita el argumento izquierdo cero o más veces ), |
es una alternativa, (
y el )
grupo y ningún operador están concatenados. La agrupación tiene prioridad sobre la estrella, la estrella tiene prioridad sobre la concatenación, la concatenación tiene prioridad sobre la alternativa.
Se dice que se acepta una cadena si la expresión regular coincide con la cadena completa.
Salida
La salida del programa es otro programa escrito en el mismo lenguaje que su envío que lee una cadena s de una manera definida por la implementación en tiempo de ejecución, emite si r acepta sy luego termina. La salida se puede realizar de una manera definida por el usuario, aunque solo debe haber dos salidas distintas para los programas aceptados y rechazados.
Puede suponer que la entrada de su programa de salida nunca supera los 2 16 -1 Bytes.
Restricciones
Ni su envío ni ningún programa generado por su envío pueden utilizar la funcionalidad integrada o las bibliotecas que
- coincide con expresiones regulares
- transformar expresiones regulares
- compilar expresiones regulares
- generar analizadores a partir de una gramática
- simplifique el problema de manera que su presentación se vuelva trivial
Puntuación
El puntaje de su presentación es la cantidad de caracteres que contiene. La presentación con la puntuación más baja gana.
Casos de prueba
Todos los casos de prueba contienen una expresión regular, un conjunto de cadenas aceptadas, un conjunto de cadenas rechazadas y un programa de ejemplo en C99 que es una salida válida de un envío C99 (hipotético).
(expresión regular vacía)
Cadenas aceptadas
- (entrada vacía)
Cadenas rechazadas
- foo
- bar
- baz
- quux
Programa de ejemplo
#include <stdio.h>
int main() {
char input[65536];
gets(input);
return input[0] != 0;
}
(b|)(ab)*(a|)
( a
y b
alternando)
cadenas aceptadas
a
ba
abababababa
abab
cadenas rechazadas
afba
foo
babba
programa de ejemplo
#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)
(números binarios de coma flotante)
cadenas aceptadas
- 10110100
- 0 0
- 1A00001
cadenas rechazadas
- 011
- 10 A
- 1A00
- 100A010
return (regex.match(stdin) is not null)
no está permitido.Respuestas:
Ruby,
641651543 caracteresEsta versión rubí se hizo bastante larga debido a varios casos de esquina en el analizador de expresiones regulares (tal vez debería intentar un enfoque diferente). Espera la expresión regular en STDIN y genera el código ruby correspondiente para el emparejador en STDOUT.
El programa genera directamente código para un NFA-ε que luego se ejecuta en el emparejador.
Caso de prueba 1: (la salida incluye nuevas líneas adicionales y sangría)
Caso de prueba 2:
Otro ejemplo:
Editar: se agregó una transición para corregir el error. PleaseStand se indica en los comentarios. También cambió la inicialización del estado.
fuente
011
para regex(0|1(0|1)*)(|A(0|1)*1)
da como resultadotrue
, debería serfalse
.C, 627 caracteres
Este programa trata su primer argumento de línea de comandos como la entrada y genera el código C como su salida.
Aquí está su salida para
(0|1(0|1)*)(|A(0|1)*1)
(con nuevas líneas agregadas):Si proporciona una entrada válida como su primer argumento de línea de comandos, devuelve el estado de salida 1. De lo contrario, devuelve el estado de salida 0.
Cualquiera de los dos programas, si no proporciona el argumento de la línea de comandos, elimina la referencia de un puntero nulo, lo que provoca un error de segmentación. Una expresión regular suficientemente larga desbordará las memorias intermedias de este envío, y el tamaño de la entrada a un programa generado está limitado por el tamaño de la pila. Sin embargo, todos los casos de prueba funcionan.
Tenga en cuenta que
e(g=h++,C=h++,0,0);
introduce un comportamiento indefinido. Si, por ejemplo, los programas generados no se compilan, puede intentar reemplazar la declaración conh+=2;e(g=h-1,C=h-2,0,0);
, que tiene cinco caracteres más.fuente