InglésFrancésEspañol

Ad


icono de página de OnWorks

freebsd-lex: en línea en la nube

Ejecute freebsd-lex en el proveedor de alojamiento gratuito de OnWorks a través de Ubuntu Online, Fedora Online, emulador en línea de Windows o emulador en línea de MAC OS

Este es el comando freebsd-lex que se puede ejecutar en el proveedor de alojamiento gratuito de OnWorks utilizando una de nuestras múltiples estaciones de trabajo en línea gratuitas, como Ubuntu Online, Fedora Online, emulador en línea de Windows o emulador en línea de MAC OS.

PROGRAMA:

NOMBRE


flex, lex - generador de analizador léxico rápido

SINOPSIS


flexionar [-bcdfhilnpstvwBFILTV78 +? -C [aefFmr] -salida -Pprefijo -Esqueleto] [--ayuda --versión]
[nombre del archivo ...]

Visión general


Este manual describe flexionar, una herramienta para generar programas que realizan una coincidencia de patrones
en el texto. El manual incluye secciones de tutoriales y de referencia:

Descripción
una breve descripción de la herramienta

Algunos ejemplos simples

Formato del archivo de entrada

Patrones
las expresiones regulares extendidas utilizadas por flex

Cómo se empareja la entrada
las reglas para determinar lo que se ha emparejado

Acciones
cómo especificar qué hacer cuando un patrón coincide

El escáner generado
detalles sobre el escáner que produce flex;
cómo controlar la fuente de entrada

Condiciones de inicio
introducir contexto en sus escáneres, y
administrar "mini-escáneres"

Múltiples búferes de entrada
cómo manipular múltiples fuentes de entrada; cómo
escanear desde cadenas en lugar de archivos

Reglas de fin de archivo
reglas especiales para hacer coincidir el final de la entrada

Macros varias
un resumen de las macros disponibles para las acciones

Valores disponibles para el usuario
un resumen de los valores disponibles para las acciones

Interfaz con Yacc
conectar escáneres flexibles junto con analizadores yacc

Opciones
Flex opciones de línea de comandos y la "opción%"
Directivas

Consideraciones de rendimiento
cómo hacer que su escáner funcione lo más rápido posible

Generación de escáneres C ++
la facilidad (experimental) para generar C ++
clases de escáner

Incompatibilidades con Lex y POSIX
en qué se diferencia flex de AT&T lex y POSIX lex
estándar

Diagnóstico
esos mensajes de error producidos por flex (o escáneres
genera) cuyos significados pueden no ser aparentes

archivos
archivos utilizados por flex

Deficiencias / Errores
problemas conocidos con flex

Vea también
otra documentación, herramientas relacionadas

Autor
incluye información de contacto

DESCRIPCIÓN


flexionar es una herramienta para generar escáneres: programas que reconocen patrones léxicos en el texto.
flexionar lee los archivos de entrada dados, o su entrada estándar si no se dan nombres de archivo, por un
descripción de un escáner a generar. La descripción se presenta en forma de pares de
expresiones y código C, llamado reglas. flexionar genera como salida un archivo fuente en C, lex.yy.c,
que define una rutina yylex (). Este archivo está compilado y vinculado con el -ll biblioteca a
producir un ejecutable. Cuando se ejecuta el ejecutable, analiza su entrada en busca de ocurrencias
de las expresiones regulares. Siempre que encuentra uno, ejecuta el código C correspondiente.

ALGUNOS SIMPLE EJEMPLOS


Primero, algunos ejemplos simples para tener una idea de cómo se usa. flexionar. Las siguientes flexionar
entrada especifica un escáner que siempre que encuentre la cadena "nombre de usuario" reemplazará
con el nombre de inicio de sesión del usuario:

%%
nombre de usuario printf ("% s", getlogin ());

De forma predeterminada, cualquier texto que no coincida con un flexionar el escáner se copia en la salida, por lo que la red
El efecto de este escáner es copiar su archivo de entrada a su salida con cada ocurrencia de
"nombre de usuario" expandido. En esta entrada, solo hay una regla. "nombre de usuario" es el patrón
y el "printf" es el acción. El "%%" marca el comienzo de las reglas.

Aquí hay otro ejemplo simple:

%{
int núm_líneas = 0, núm_caracteres = 0;
%}

%%
\ n ++ num_lines; ++ num_chars;
. ++ num_chars;

%%
principal()
{
yylex ();
printf ("# de líneas =% d, # de caracteres =% d \ n",
num_lines, num_chars);
}

Este escáner cuenta el número de caracteres y el número de líneas en su entrada (es
no produce más salida que el informe final sobre los recuentos). La primera línea declara
dos globales, "num_lines" y "num_chars", a los que se puede acceder desde dentro yylex () y en
las principal() rutina declarada después del segundo "%%". Hay dos reglas, una que coincide
una nueva línea ("\ n") e incrementa tanto el recuento de líneas como el recuento de caracteres, y uno que
coincide con cualquier carácter que no sea una nueva línea (indicado por la expresión regular ".").

Un ejemplo algo más complicado:

/ * escáner para un lenguaje de juguete similar a Pascal * /

%{
/ * Necesito esto para la llamada a atof () a continuación * /
#incluir
%}

DÍGITO [0-9]
ID [az] [a-z0-9] *

%%

{DÍGITO} + {
printf ("Un entero:% s (% d) \ n", yytext,
atoi (yytext));
}

{DÍGITO} + "." {DÍGITO} * {
printf ("Un flotante:% s (% g) \ n", yytext,
atof (yytext));
}

si | entonces | comenzar | finalizar | procedimiento | función {
printf ("Una palabra clave:% s \ n", yytext);
}

{ID} printf ("Un identificador:% s \ n", yytext);

"+" | "-" | "*" | "/" printf ("Un operador:% s \ n", yytext);

"{" [^} \ n] * "}" / * come comentarios de una línea * /

[\ t \ n] + / * comerse espacios en blanco * /

. printf ("Carácter no reconocido:% s \ n", yytext);

%%

principal (argc, argv)
intargc;
char ** argv;
{
++ argv, --argc; / * omitir el nombre del programa * /
si (argc> 0)
yyin = fopen (argv [0], "r");
más
yyin = entrada estándar;

yylex ();
}

Este es el comienzo de un escáner simple para un lenguaje como Pascal. Identifica
diferentes tipos de fichas e informa sobre lo que ha visto.

Los detalles de este ejemplo se explicarán en las siguientes secciones.

FORMATO OF EL REINO UNIDO ENTRADA ARCHIVO


El flexionar El archivo de entrada consta de tres secciones, separadas por una línea con %% en eso:

Definiciones
%%
reglas
%%
codigo de usuario

El Definiciones sección contiene declaraciones de simple nombre definiciones para simplificar el
especificación del escáner y declaraciones de comienzo condiciones, que se explican en un
sección posterior.

Las definiciones de nombre tienen la forma:

definición de nombre

El "nombre" es una palabra que comienza con una letra o un guión bajo ('_') seguido de cero o
más letras, dígitos, '_' o '-' (guión). La definición se toma para comenzar en el primer
carácter que no es un espacio en blanco que sigue al nombre y continúa hasta el final de la línea. El
Posteriormente, se puede hacer referencia a la definición mediante "{nombre}", que se expandirá a
"(definición)". Por ejemplo,

DÍGITO [0-9]
ID [az] [a-z0-9] *

define "DIGIT" como una expresión regular que coincide con un solo dígito, y "ID" como un
expresión regular que coincide con una letra seguida de cero o más letras o dígitos. A
referencia posterior a

{DÍGITO} + "." {DÍGITO} *

es idéntico a

([0-9]) + "." ([0-9]) *

y coincide con uno o más dígitos seguidos de un '.' seguido de cero o más dígitos.

El reglas sección de la flexionar input contiene una serie de reglas de la forma:

acción de patrón

donde el patrón no debe tener sangría y la acción debe comenzar en la misma línea.

Consulte a continuación para obtener una descripción más detallada de patrones y acciones.

Finalmente, la sección de código de usuario simplemente se copia a lex.yy.c literal. Se utiliza para
rutinas complementarias que llaman o son llamadas por el escáner. La presencia de esta sección
es opcional; si falta, el segundo %% en el archivo de entrada también se pueden omitir.

En las secciones de definiciones y reglas, cualquier sangrado texto o texto incluido en %{ y %} is
copiado literalmente a la salida (con los% {} eliminados). Los% {} deben aparecer sin sangría.
en líneas por sí mismos.

En la sección de reglas, se puede usar cualquier texto sangrado o% {} que aparezca antes de la primera regla.
para declarar variables que son locales a la rutina de escaneo y (después de las declaraciones)
código que se ejecutará siempre que se ingrese la rutina de escaneo. Otro sangrado o
El texto% {} de la sección de reglas todavía se copia en la salida, pero su significado no está bien.
definido y bien puede causar errores en tiempo de compilación (esta característica está presente para POSIX
cumplimiento; consulte a continuación otras características similares).

En la sección de definiciones (pero no en la sección de reglas), un comentario sin sangría (es decir, un
línea que comienza con "/ *") también se copia literalmente en la salida hasta el siguiente "* /".

PATRONES


Los patrones de la entrada se escriben utilizando un conjunto extendido de expresiones regulares. Estos
son:

x coincide con el carácter 'x'
. cualquier carácter (byte) excepto nueva línea
[xyz] una "clase de carácter"; en este caso, el patrón
coincide con una 'x', una 'y' o una 'z'
[abj-oZ] una "clase de carácter" con un rango en ella; partidos
una 'a', una 'b', cualquier letra de la 'j' a la 'o',
o una 'Z'
[^ AZ] una "clase de carácter negada", es decir, cualquier carácter
pero los de la clase. En este caso, cualquier
carácter EXCEPTO una letra mayúscula.
[^ AZ \ n] cualquier carácter EXCEPTO una letra mayúscula o
una nueva línea
r * cero o más r, donde r es cualquier expresión regular
r + una o más r
r? cero o una r (es decir, "una r opcional")
r {2,5} entre dos y cinco r
r {2,} dos o más r
r {4} exactamente 4 r
{nombre} la expansión de la definición de "nombre"
(véase más arriba)
"[xyz] \" foo "
la cadena literal: [xyz] "foo
\ X si X es una 'a', 'b', 'f', 'n', 'r', 't' o 'v',
luego la interpretación ANSI-C de \ x.
De lo contrario, una 'X' literal (usada para escapar
operadores como '*')
\ 0 un carácter NUL (código ASCII 0)
\ 123 el carácter con valor octal 123
\ x2a el carácter con valor hexadecimal 2a
(r) coincidir con una r; los paréntesis se utilizan para anular
precedencia (ver más abajo)

rs la expresión regular r seguida de la
expresiones regulares; llamado "concatenación"

r | s una r o una s

r / s una r pero solo si va seguida de una s. El
el texto que coincide con s se incluye al determinar
si esta regla es la "coincidencia más larga",
pero luego se devuelve a la entrada antes
la acción se ejecuta. Entonces la acción solo
ve el texto que coincide con r. Este tipo
del patrón se denomina contexto final ".
(Hay algunas combinaciones de r / s que flexionan
no puede coincidir correctamente; ver notas en el
Sección de deficiencias / errores a continuación con respecto a
"contexto de seguimiento peligroso".)
^ r an r, pero solo al principio de una línea (es decir,
cuando recién comienza a escanear, o justo después de un
nueva línea ha sido escaneada).
r $ an r, pero solo al final de una línea (es decir, solo
antes de una nueva línea). Equivalente a "r / \ n".

Tenga en cuenta que la noción de flex de "nueva línea" es exactamente
lo que sea que el compilador de C usó para compilar flex
interpreta '\ n' como; en particular, en algunos DOS
sistemas debe filtrar \ r en el
ingrese usted mismo, o use explícitamente r / \ r \ n para "r $".

r an r, pero solo en condiciones de arranque s (ver
a continuación para discutir las condiciones de inicio)
r
mismo, pero en cualquiera de las condiciones de inicio s1,
s2 o s3
<*> r an r en cualquier condición de inicio, incluso una exclusiva.

< > un final de archivo
< >
un final de archivo cuando está en la condición de inicio s1 o s2

Tenga en cuenta que dentro de una clase de caracteres, todos los operadores de expresiones regulares pierden su especial
significado excepto escape ('\') y los operadores de clase de caracteres, '-', ']', y, en el
comienzo de la clase, '^'.

Las expresiones regulares enumeradas anteriormente se agrupan de acuerdo con la precedencia, desde la más alta
precedencia en la parte superior a la más baja en la parte inferior. Los agrupados tienen igual
precedencia. Por ejemplo,

foo | bar *

es el mismo que

(foo) | (ba (r *))

ya que el operador '*' tiene mayor precedencia que la concatenación, y la concatenación mayor
que la alternancia ('|'). Por lo tanto, este patrón coincide ya sea la cadena "foo" or las
cadena "ba" seguida de cero o más r. Para hacer coincidir "foo" o cero o más "barras", utilice:

foo | (barra) *

y para que coincida con cero o más "foo" 's-o- "bar":

(foo | bar) *

Además de los caracteres y rangos de caracteres, las clases de caracteres también pueden contener
clase de personaje expresiones Estas son expresiones encerradas dentro [: y :] delimitadores
(que deben aparecer entre '[' y ']' de la clase de caracteres; otros
los elementos también pueden ocurrir dentro de la clase de carácter). Las expresiones válidas son:

[: alnum:] [: alpha:] [: blank:]
[: cntrl:] [: dígito:] [: gráfico:]
[: inferior:] [: imprimir:] [: puntuar:]
[: espacio:] [: superior:] [: xdígito:]

Todas estas expresiones designan un conjunto de caracteres equivalente al correspondiente
estándar C esXXX función. Por ejemplo, [: alnum:] designa aquellos caracteres para los que
isalnum () devuelve verdadero, es decir, cualquier alfabético o numérico. Algunos sistemas no proporcionan
está en blanco(), entonces flex define [:blanco:] como un espacio en blanco o una pestaña.

Por ejemplo, las siguientes clases de caracteres son todas equivalentes:

[[: alnum:]]
[[: alfa:] [: dígito:]]
[[: alpha:] 0-9]
[a-zA-Z0-9]

Si su escáner no distingue entre mayúsculas y minúsculas (el -i bandera), entonces [:superior:] y [:más bajo:] en
equivalente a [:alfa:].

Algunas notas sobre patrones:

- Una clase de caracteres negada como el ejemplo "[^ AZ]" anterior seguirá partido a nueva línea
a menos que "\ n" (o una secuencia de escape equivalente) sea uno de los caracteres explícitamente
presente en la clase de caracteres negada (por ejemplo, "[^ AZ \ n]"). Esto es diferente a cuantos
otras herramientas de expresión regular tratan las clases de caracteres negadas, pero desafortunadamente
la inconsistencia está arraigada históricamente. La coincidencia de nuevas líneas significa que un
patrón como [^ "] * puede coincidir con toda la entrada a menos que haya otra comilla en el
entrada.

- Una regla puede tener como máximo una instancia de contexto final (el operador '/' o el
operador '$'). La condición de inicio, '^' y "< > "los patrones solo pueden ocurrir en
el comienzo de un patrón y, al igual que con '/' y '$', no se pueden agrupar
entre paréntesis. Un '^' que no aparece al principio de una regla o un '$'
que no ocurre al final de una regla pierde sus propiedades especiales y es
tratado como un personaje normal.

Los siguientes son ilegales:

foo / bar $
foo bar

Tenga en cuenta que el primero de ellos puede escribirse "foo / bar \ n".

Lo siguiente dará como resultado que '$' o '^' se traten como un carácter normal:

foo | (barra $)
foo | ^ bar

Si lo que se busca es un "foo" o una barra seguida de una nueva línea, lo siguiente podría ser
utilizado (la acción especial '|' se explica a continuación):

foo |
bar $ / * la acción va aquí * /

Un truco similar funcionará para hacer coincidir un foo o una barra al principio de una línea.

COMO LAS EL REINO UNIDO ENTRADA IS EMPAREJADO


Cuando se ejecuta el escáner generado, analiza su entrada en busca de cadenas que coincidan
cualquiera de sus patrones. Si encuentra más de una coincidencia, toma la que más coincide
texto (para las reglas de contexto final, esto incluye la longitud de la parte final, incluso
aunque luego volverá a la entrada). Si encuentra dos o más coincidencias del
misma longitud, la regla enumerada primero en el flexionar se elige el archivo de entrada.

Una vez que se determina la coincidencia, el texto correspondiente a la coincidencia (llamado simbólico) is
disponible en el puntero de carácter global ytexto, y su duración en el mundo
entero yyleng. El DE ACTUAR! correspondiente al patrón emparejado se ejecuta (una más
sigue una descripción detallada de las acciones), y luego se escanea la entrada restante para
otro partido.

Si no se encuentra ninguna coincidencia, entonces el tu préstamo estudiantil gobernar se ejecuta: el siguiente carácter en la entrada
se considera emparejado y copiado a la salida estándar. Por lo tanto, el más simple legal flexionar
la entrada es:

%%

que genera un escáner que simplemente copia su entrada (un carácter a la vez) a su
salida.

Tenga en cuenta que yytexto se puede definir de dos formas diferentes: ya sea como un personaje puntero o como
un carácter formación. Puedes controlar qué definición flexionar usos incluyendo uno de los
directivas especiales %puntero or %formación en la primera sección (definiciones) de tu flex
aporte. El valor predeterminado es %puntero, a menos que uses el -l opción de compatibilidad lex, en la que
case yytexto será una matriz. La ventaja de usar %puntero es sustancialmente más rápido
escaneo y sin desbordamiento de búfer al hacer coincidir tokens muy grandes (a menos que se quede sin
memoria dinámica). La desventaja es que está restringido en la forma en que sus acciones pueden
modificar yytexto (ver la siguiente sección), y llamadas al unput () función destruye el
presente contenido de ytexto, lo que puede ser un dolor de cabeza considerable para portar cuando se mueve
entre los diferentes lex versiones.

La ventaja de %formación es que luego puedes modificar yytexto al contenido de su corazón, y
llamadas a unput () no destruir yytexto (vea abajo). Además, existente lex programas
a veces acceden yytexto externamente usando declaraciones de la forma:
extern char yytext [];
Esta definición es errónea cuando se usa con %puntero, pero correcto para %formación.

%formación define yytexto ser una matriz de YYLMAX caracteres, que por defecto es bastante
gran valor. Puede cambiar el tamaño simplemente # definiendo YYLMAX a un valor diferente en
la primera sección de tu flexionar aporte. Como se mencionó anteriormente, con %puntero yytext crece
dinámicamente para acomodar tokens grandes. Si bien esto significa tu %puntero el escáner puede
acomodar tokens muy grandes (como hacer coincidir bloques enteros de comentarios), tenga en cuenta
que cada vez que el escáner debe cambiar de tamaño yytexto también debe volver a escanear todo el token de
al principio, por lo que hacer coincidir esos tokens puede resultar lento. yytexto actualmente lo hace no
crecer dinámicamente si una llamada a unput () da como resultado que se retrase demasiado texto; en lugar de,
se produce un error en tiempo de ejecución.

También tenga en cuenta que no puede usar %formación con clases de escáner C ++ (el c ++ opción; vea abajo).

ACCIONES


Cada patrón de una regla tiene una acción correspondiente, que puede ser cualquier instrucción C arbitraria.
El patrón termina en el primer carácter de espacio en blanco sin escape; el resto de la línea
es su acción. Si la acción está vacía, cuando el patrón coincide con el token de entrada
simplemente se descarta. Por ejemplo, aquí está la especificación de un programa que elimina
todas las apariciones de "zap me" de su entrada:

%%
"zap me"

(Copiará todos los demás caracteres de la entrada a la salida, ya que coincidirán
por la regla predeterminada.)

Aquí hay un programa que comprime múltiples espacios en blanco y pestañas hasta un solo espacio en blanco, y
tira los espacios en blanco que se encuentran al final de una línea:

%%
[\ t] + putchar ('');
[\ t] + $ / * ignora este token * /

Si la acción contiene un '{', entonces la acción se extiende hasta que se encuentra el equilibrio '}' y
la acción puede cruzar varias líneas. flexionar conoce las cadenas de C y los comentarios y no lo estará
engañado por los frenos que se encuentran dentro de ellos, pero también permite que las acciones comiencen con %{ y la voluntad
Considere que la acción es todo el texto hasta el siguiente. %} (independientemente de los aparatos ortopédicos ordinarios
dentro de la acción).

Una acción que consta únicamente de una barra vertical ('|') significa "lo mismo que la acción de la siguiente
regla ". Consulte a continuación para ver una ilustración.

Las acciones pueden incluir código C arbitrario, incluyendo volvemos declaraciones para devolver un valor a
cualquier rutina llamada yylex (). Cada vez yylex () se llama sigue procesando
tokens desde donde lo dejó por última vez hasta que llegue al final del archivo o se ejecute
un retorno.

Las acciones se pueden modificar libremente yytexto excepto para alargarlo (añadiendo caracteres a su
end: estos sobrescribirán los caracteres posteriores en el flujo de entrada). Sin embargo, esto no
aplicar al usar %formación (véase más arriba); en ese caso, yytexto puede ser modificado libremente en cualquier
.

Las acciones se pueden modificar libremente yyleng excepto que no deben hacerlo si la acción también incluye
uso de yymore () (vea abajo).

Hay una serie de directivas especiales que se pueden incluir dentro de una acción:

- ECHO copia yytext en la salida del escáner.

- EMPEZAR seguido del nombre de una condición de inicio coloca el escáner en el
condición de inicio correspondiente (ver más abajo).

- RECHAZAR indica al escáner que proceda a la regla "segunda mejor" que coincidió
la entrada (o un prefijo de la entrada). La regla se elige como se describe arriba en
"Cómo se hace coincidir la entrada" y yytexto y yyleng configurar adecuadamente. Puede
ser uno que coincida con tanto texto como la regla elegida originalmente, pero vino
más tarde en el flexionar archivo de entrada, o uno que coincida con menos texto. Por ejemplo, el
lo siguiente contará las palabras en la entrada y llamará a la rutina especial ()
siempre que se ve "frob":

int recuento_palabras = 0;
%%

frob especial (); RECHAZAR;
[^ \ t \ n] + ++ recuento_palabras;

Sin el RECHAZAR, cualquier "frob" en la entrada no se contará como palabras, ya que
el escáner normalmente ejecuta solo una acción por token. Múltiple RECHAZAR en
permitido, cada uno encuentra la siguiente mejor opción a la regla actualmente activa. Para
ejemplo, cuando el siguiente escáner escanea el token "abcd", escribirá
"abcdabcaba" a la salida:

%%
un |
ab |
abc |
abcd ECHO; RECHAZAR;
. | \ n / * comerse cualquier carácter incomparable * /

(Las primeras tres reglas comparten la acción de la cuarta, ya que usan el especial '|'
acción.) RECHAZAR es una característica particularmente cara en términos de escáner
rendimiento; si se usa en cualquier de las acciones del escáner, se ralentizará todos of
el escáner coincide. Además, RECHAZAR no se puede utilizar con el -cf or -CF
opciones (ver más abajo).

Tenga en cuenta también que, a diferencia de las otras acciones especiales, RECHAZAR es un rama; código
inmediatamente después de él en la acción no ser ejecutado.

- yymore () le dice al escáner que la próxima vez que coincida con una regla, el correspondiente
el token debe ser anexado sobre el valor actual de yytexto en lugar de reemplazarlo.
Por ejemplo, dada la entrada "mega-kludge", lo siguiente escribirá "mega-mega-
kludge "a la salida:

%%
mega-ECHO; yymore ();
chocar con ECHO;

El primer "mega-" se empareja y se repite en la salida. Entonces "kludge" coincide, pero
el "mega-" anterior todavía está rondando al comienzo de yytexto por lo que el ECHO
porque la regla "kludge" en realidad escribirá "mega-kludge".

Dos notas sobre el uso de yymore (). En primer lugar, yymore () depende del valor de yyleng
reflejando correctamente el tamaño del token actual, por lo que no debe modificar yyleng si tu
están usando yymore (). En segundo lugar, la presencia de yymore () en la acción del escáner implica un
penalización menor de rendimiento en la velocidad de coincidencia del escáner.

- yyless (n) devuelve todos menos el primero n caracteres del token actual hasta el
flujo de entrada, donde se volverán a escanear cuando el escáner busque el siguiente
partido. yytexto y yyleng se ajustan adecuadamente (p. ej., yyleng ahora será
igual a n ). Por ejemplo, en la entrada "foobar" se escribirá lo siguiente
"foobarbar":

%%
foobar ECO; yyless(3);
[az] + ECHO;

Un argumento de 0 a yyless hará que se escanee toda la cadena de entrada actual
de nuevo. A menos que haya cambiado la forma en que el escáner procesará posteriormente su entrada
(utilizando EMPEZAR, por ejemplo), esto resultará en un bucle sin fin.

Tenga en cuenta que yyless es una macro y solo se puede usar en el archivo de entrada flexible, no desde otro
archivos fuente.

- no puesto (c) pone el personaje c de nuevo al flujo de entrada. Sera el proximo
personaje escaneado. La siguiente acción tomará el token actual y lo hará
para volver a escanear entre paréntesis.

{
int i;
/ * Copiar yytext porque unput () destruye yytext * /
char * yycopy = strdup (yytext);
unput (')');
para (i = yyleng - 1; i> = 0; --i)
unput (yycopy [i]);
unput ('(');
gratis (yycopy);
}

Tenga en cuenta que dado que cada unput () vuelve a poner el personaje dado en el comienzo de las
flujo de entrada, empujar las cadenas hacia atrás debe hacerse de atrás hacia adelante.

Un problema potencial importante al usar unput () es que si estas usando %puntero (la
predeterminado), una llamada a unput () destruye los contenidos de ytexto, comenzando con su más a la derecha
personaje y devorando un personaje a la izquierda con cada llamada. Si necesitas el valor
de yytext conservado después de una llamada a unput () (como en el ejemplo anterior), debe
primero cópielo en otro lugar, o cree su escáner usando %formación en su lugar (ver Cómo es la entrada
Emparejado).

Finalmente, tenga en cuenta que no puede volver EOF para intentar marcar el flujo de entrada con un
fin del documento.

- aporte() lee el siguiente carácter del flujo de entrada. Por ejemplo, lo siguiente
es una forma de comerse los comentarios de C:

%%
"/ *" {
intc;

por ( ; ; )
{
while ((c = input ())! = '*' &&
c! = EOF)
; / * devorar el texto del comentario * /

si (c == '*')
{
while ((c = input ()) == '*')
;
si (c == '/')
descanso; / * encontré el final * /
}

si (c == EOF)
{
error ("EOF en comentario");
break;
}
}
}

(Tenga en cuenta que si el escáner se compila utilizando C ++ luego aporte() es en cambio referido
a como yyinput (), para evitar un choque de nombres con el C + + corriente por el nombre de
aporte.)

- YY_FLUSH_BUFFER limpia el búfer interno del escáner para que la próxima vez
el escáner intenta hacer coincidir un token, primero rellenará el búfer usando YY_ENTRADA
(consulte El escáner generado a continuación). Esta acción es un caso especial de los más
general yy_flush_buffer () función, que se describe a continuación en la sección Entrada múltiple
Tampones.

- yyterminate () se puede utilizar en lugar de una declaración de devolución en una acción. Eso
termina el escáner y devuelve un 0 a la persona que llama del escáner, lo que indica "todos
done ". De forma predeterminada, yyterminate () también se llama cuando un final de archivo es
encontrado. Es una macro y puede redefinirse.

EL REINO UNIDO GENERADO ESCANEAR


La salida de flexionar es el archivo lex.yy.c, que contiene la rutina de escaneo yylex (), a
número de tablas utilizadas por él para hacer coincidir tokens, y un número de rutinas auxiliares y
macros. Por defecto, yylex () se declara de la siguiente manera:

int yylex ()
{
... varias definiciones y las acciones aquí ...
}

(Si su entorno admite prototipos de funciones, será "int yylex (void)".)
Esta definición se puede cambiar definiendo la macro "YY_DECL". Por ejemplo, podrías
utilizar:

#define YY_DECL float lexscan (a, b) float a, b;

dar el nombre a la rutina de escaneo escaneo lex, devolviendo un flotador, y tomando dos flotadores como
argumentos. Tenga en cuenta que si le da argumentos a la rutina de escaneo usando un estilo K & R / no
declaración de función prototipada, debe terminar la definición con un punto y coma (;).

Siempre que yylex () se llama, escanea tokens del archivo de entrada global yin (cual
por defecto es stdin). Continúa hasta que llega al final del archivo (en ese momento
devuelve el valor 0) o una de sus acciones ejecuta un volvemos .

Si el escáner llega al final del archivo, las llamadas posteriores no están definidas a menos que yin
apunta a un nuevo archivo de entrada (en cuyo caso el escaneo continúa desde ese archivo), o
yyrestart () se llama. yyrestart () toma un argumento, un ARCHIVO * puntero (que puede ser
nil, si ha configurado YY_ENTRADA para escanear desde una fuente que no sea yin), e inicializa
yin para escanear desde ese archivo. Básicamente, no hay diferencia entre solo
asignando yin a un nuevo archivo de entrada o usando yyrestart () para hacerlo; este último está disponible
para compatibilidad con versiones anteriores de flexionar, y porque se puede utilizar para cambiar
archivos de entrada en medio del escaneo. También se puede utilizar para tirar la corriente.
búfer de entrada, llamándolo con un argumento de yin; pero mejor es usar YY_FLUSH_BUFFER
(véase más arriba). Tenga en cuenta que yyrestart ()no restablecer la condición de inicio a INICIAL (consulta:
Condiciones de inicio, a continuación).

If yylex () detiene el escaneo debido a la ejecución de un volvemos declaración en una de las acciones, el
Es posible que se vuelva a llamar al escáner y se reanudará el escaneo donde lo dejó.

De forma predeterminada (y con fines de eficiencia), el escáner utiliza lecturas en bloque en lugar de
simples getc () llamadas para leer caracteres de yin La naturaleza de cómo obtiene su entrada puede
ser controlado definiendo el YY_ENTRADA macro. La secuencia de llamada de YY_INPUT es
"YY_INPUT (buf, resultado, tamaño_máximo)". Su acción es colocar hasta tamaño máximo personajes en el
conjunto de caracteres buf y regresa en la variable entera resultado ya sea el número de
caracteres leídos o la constante YY_NULL (0 en sistemas Unix) para indicar EOF. El valor por defecto
YY_INPUT lee desde el puntero de archivo global "yyin".

Una definición de muestra de YY_INPUT (en la sección de definiciones del archivo de entrada):

%{
#define YY_INPUT (buf, resultado, tamaño_máximo) \
{\
int c = getchar (); \
resultado = (c == EOF)? YY_NULL: (buf [0] = c, 1); \
}
%}

Esta definición cambiará el procesamiento de entrada para que ocurra un carácter a la vez.

Cuando el escáner recibe una indicación de fin de archivo de YY_INPUT, luego verifica la
yywrap () función. Si yywrap () devuelve falso (cero), entonces se supone que la función
ha seguido adelante y configurado yin para apuntar a otro archivo de entrada, y el escaneo continúa. Si
devuelve verdadero (distinto de cero), luego el escáner termina y devuelve 0 a su llamador. Nota
que en cualquier caso, la condición de inicio permanece sin cambios; lo hace no volver a INICIAL.

Si no proporciona su propia versión de yywrap (), entonces debes usar %opción
noyywrap (en cuyo caso el escáner se comporta como si yywrap () devuelto 1), o debe
enlazar con -ll para obtener la versión predeterminada de la rutina, que siempre devuelve 1.

Hay tres rutinas disponibles para escanear desde búferes en memoria en lugar de archivos:
yy_scan_string (), yy_scan_bytes (), y yy_scan_buffer (). Vea la discusión de ellos a continuación
en la sección Múltiples búferes de entrada.

El escáner escribe su ECHO salida a la tu global (predeterminado, stdout), que puede ser
redefinido por el usuario simplemente asignándolo a algún otro ARCHIVO puntero.

EMPIEZA CONDICIONES


flexionar proporciona un mecanismo para activar reglas condicionalmente. Cualquier regla cuyo patrón sea
con el prefijo " "solo estará activo cuando el escáner esté en la condición de inicio denominada
"Carolina del Sur". Por ejemplo,

[^ "] * {/ * come el cuerpo de la cuerda ... * /
...
}

estará activo solo cuando el escáner esté en la condición de inicio "STRING", y

\. {/ * manejar un escape ... * /
...
}

estará activo solo cuando la condición de inicio actual sea "INICIAL", "CADENA" o
"CITA".

Las condiciones de inicio se declaran en la sección de definiciones (primera) de la entrada usando
líneas sin sangría que comienzan con %s or %x seguido de una lista de nombres. El primero
declara incluso condiciones de inicio, este último EXCLUSIVO PROGRAMA condiciones de inicio. Un inicio
La condición se activa usando el EMPEZAR acción. Hasta el siguiente EMPEZAR se ejecuta la acción,
las reglas con la condición de inicio dada estarán activas y las reglas con otras condiciones de inicio
estará inactivo. Si la condición de inicio es inclusivo, entonces gobierna sin comienzo
las condiciones en absoluto también estarán activas. Si esto es exclusivo, luego , solamente reglas calificadas con
la condición de inicio estará activa. Un conjunto de reglas supeditadas al mismo comienzo exclusivo
condición describe un escáner que es independiente de cualquiera de las otras reglas en el flexionar
aporte. Debido a esto, las condiciones de inicio exclusivas facilitan la especificación de "mini-
escáneres "que escanean partes de la entrada que son sintácticamente diferentes del resto
(por ejemplo, comentarios).

Si la distinción entre condiciones de inicio inclusivas y exclusivas es todavía un poco
vago, aquí hay un ejemplo simple que ilustra la conexión entre los dos. El conjunto de
reglas:

% s ejemplo
%%

foo do_something ();

bar something_else ();

es equivalente a

% x ejemplo
%%

foo do_something ();

bar something_else ();

Sin el calificador, el de caramelos patrón en el segundo ejemplo no sería
activo (es decir, no pudo coincidir) cuando está en condición de inicio ejemplo. Si solo usáramos
para calificar bar, sin embargo, solo estaría activo en ejemplo y no en INICIAL, mientras
en el primer ejemplo está activo en ambos, porque en el primer ejemplo el ejemplo comienzo
la condición es una incluso (%s) condición de inicio.

También tenga en cuenta que el especificador de condición de inicio especial <*> coincide con todas las condiciones de inicio.
Por lo tanto, el ejemplo anterior también podría haberse escrito;

% x ejemplo
%%

foo do_something ();

<*> barra algo_else ();

La regla predeterminada (para ECHO cualquier carácter no coincidente) permanece activo en condiciones de inicio. Eso
es equivalente a:

<*>. | \ n ECHO;

EMPEZAR(0) regresa al estado original donde solo las reglas sin condiciones de inicio son
activo. Este estado también puede denominarse condición de inicio "INICIAL", por lo que
COMIENZO (INICIAL) es equivalente a EMPEZAR(0). (Los paréntesis alrededor de la condición de inicio
nombre no son obligatorios pero se consideran de buen estilo.)

EMPEZAR Las acciones también se pueden dar como código sangrado al comienzo de la sección de reglas.
Por ejemplo, lo siguiente hará que el escáner ingrese en la condición de inicio "ESPECIAL"
cuando yylex () se llama y la variable global entrar_especial es verdad:

int entrar_especial;

% x ESPECIAL
%%
si (enter_special)
COMIENZO (ESPECIAL);

bla, bla, bla
... siguen más reglas ...

Para ilustrar los usos de las condiciones de inicio, aquí hay un escáner que proporciona dos
interpretaciones de una cadena como "123.456". De forma predeterminada, lo tratará como tres tokens,
el número entero "123", un punto ('.') y el número entero "456". Pero si la cuerda va precedida
antes en la línea por la cadena "espera-flotante" lo tratará como un solo token, el
número de coma flotante 123.456:

%{
#incluir
%}
% s espera

%%
esperar-flota BEGIN (esperar);

[0-9] + "." [0-9] + {
printf ("encontró un flotante, =% f \ n",
atof (yytext));
}
\ n {
/ * ese es el final de la línea, así que
* necesitamos otro "número esperado"
* antes de que reconozcamos más
* numeros
*/
COMIENZO (INICIAL);
}

[0-9] + {
printf ("encontró un número entero, =% d \ n",
atoi (yytext));
}

"." printf ("encontró un punto \ n");

Aquí hay un escáner que reconoce (y descarta) los comentarios de C mientras mantiene un recuento de
la línea de entrada actual.

% x comentario
%%
int núm_línea = 1;

"/ *" BEGIN (comentario);

[^ * \ n] * / * come cualquier cosa que no sea un '*' * /
"*" + [^ * / \ n] * / * comer '*' no seguido de '/' * /
\ n ++ núm_línea;
"*" + "/" COMIENZO (INICIAL);

Este escáner se toma un poco de problemas para hacer coincidir la mayor cantidad de texto posible con cada regla.
En general, cuando intente escribir un escáner de alta velocidad, intente hacer coincidir tanto como sea posible en
cada regla, ya que es una gran victoria.

Tenga en cuenta que los nombres de las condiciones de inicio son en realidad valores enteros y se pueden almacenar como tales.
Así, lo anterior podría extenderse de la siguiente manera:

% x comenta foo
%%
int núm_línea = 1;
int llamador_comentario;

"/ *" {
llamador_comentario = INICIAL;
COMIENZO (comentario);
}

...

"/ *" {
llamador_comentario = foo;
COMIENZO (comentario);
}

[^ * \ n] * / * come cualquier cosa que no sea un '*' * /
"*" + [^ * / \ n] * / * comer '*' no seguido de '/' * /
\ n ++ núm_línea;
"*" + "/" BEGIN (llamador_comentario);

Además, puede acceder a la condición de inicio actual utilizando el valor entero AA_START
macro. Por ejemplo, las asignaciones anteriores a llamador_comentario en su lugar podría ser escrito

llamador_comentario = YY_START;

Flex proporciona YYESTADO como un alias para AA_START (ya que eso es lo que usa AT&T lex).

Tenga en cuenta que las condiciones de inicio no tienen su propio espacio de nombres; % s y% x declaran nombres
de la misma manera que # define's.

Finalmente, aquí hay un ejemplo de cómo hacer coincidir cadenas entre comillas de estilo C usando inicio exclusivo
condiciones, incluidas las secuencias de escape expandidas (pero sin incluir la comprobación de una cadena
eso es muy largo):

% x str

%%
char string_buf [MAX_STR_CONST];
char * string_buf_ptr;

\ "string_buf_ptr = string_buf; BEGIN (str);

\ "{/ * vi la cita de cierre - todo listo * /
COMIENZO (INICIAL);
* string_buf_ptr = '\ 0';
/ * devuelve el tipo de token constante de cadena y
* valor al analizador
*/
}

\ n {
/ * error - constante de cadena no terminada * /
/ * generar mensaje de error * /
}

\\ [0-7] {1,3} {
/ * secuencia de escape octal * /
resultado int;

(void) sscanf (yytext + 1, "% o", & resultado);

si (resultado> 0xff)
/ * error, la constante está fuera de límites * /

* string_buf_ptr ++ = resultado;
}

\\ [0-9] + {
/ * generar error - secuencia de escape incorrecta; algo
* como '\ 48' o '\ 0777777'
*/
}

\\ n * string_buf_ptr ++ = '\ n';
\\ t * string_buf_ptr ++ = '\ t';
\\ r * string_buf_ptr ++ = '\ r';
\\ b * string_buf_ptr ++ = '\ b';
\\ f * string_buf_ptr ++ = '\ f';

\\ (. | \ n) * string_buf_ptr ++ = yytext [1];

[^ \\\ n \ "] + {
char * yptr = yytext;

while (* yptr)
* string_buf_ptr ++ = * yptr ++;
}

A menudo, como en algunos de los ejemplos anteriores, terminas escribiendo un montón de reglas
todo precedido por las mismas condiciones de inicio. Flex hace que esto sea un poco más fácil y limpio
introduciendo una noción de condición de inicio alcance. El alcance de una condición de inicio comienza con:

{

donde SC es una lista de una o más condiciones de inicio. Dentro del alcance de la condición de inicio,
cada regla tiene automáticamente el prefijo aplicado a él, hasta que un '}' que coincide con el
inicial '{'. Así por ejemplo,

{
"\\ n" return '\ n';
"\\ r" return '\ r';
"\\ f" return '\ f';
"\\ 0" return '\ 0';
}

es equivalente a:

"\\ n" return '\ n';
"\\ r" return '\ r';
"\\ f" return '\ f';
"\\ 0" return '\ 0';

Los ámbitos de la condición de inicio pueden estar anidados.

Hay tres rutinas disponibles para manipular pilas de condiciones de inicio:

vacío yy_push_state (int nuevo_estado)
empuja la condición de inicio actual a la parte superior de la pila de condiciones de inicio y
cambia a nuevo_estado como si hubieras usado EMPEZAR nuevo_estado (recuerda ese comienzo
los nombres de las condiciones también son números enteros).

vacío yy_pop_state ()
aparece la parte superior de la pila y cambia a ella a través de COMENZAR.

int yy_top_state ()
devuelve la parte superior de la pila sin alterar el contenido de la pila.

La pila de condiciones de inicio crece dinámicamente y, por lo tanto, no tiene una limitación de tamaño incorporada. Si
la memoria está agotada, la ejecución del programa se interrumpe.

Para utilizar pilas de condiciones de inicio, su escáner debe incluir un %opción montón directiva (ver
Opciones a continuación).

MÚLTIPLE ENTRADA Amortiguadores


Algunos escáneres (como los que admiten archivos "incluir") requieren la lectura de varios
flujos de entrada. Como flexionar los escáneres hacen una gran cantidad de almacenamiento en búfer, no se puede controlar dónde
la siguiente entrada se leerá simplemente escribiendo un YY_ENTRADA que es sensible a la
contexto de escaneo. YY_ENTRADA solo se llama cuando el escáner llega al final de su búfer,
que puede pasar mucho tiempo después de escanear una declaración como un "incluir" que requiere
cambiar la fuente de entrada.

Para negociar este tipo de problemas, flexionar proporciona un mecanismo para crear y cambiar
entre varios búferes de entrada. Un búfer de entrada se crea usando:

YY_BUFFER_STATE yy_create_buffer (ARCHIVO * archivo, tamaño int)

que toma un ARCHIVO puntero y un tamaño y crea un búfer asociado con el archivo dado
y lo suficientemente grande para sostener tamaño caracteres (en caso de duda, utilice YY_BUF_TAMAÑO por el tamaño).
Devuelve un YY_BUFFER_ESTADO manejar, que luego se puede pasar a otras rutinas (ver
debajo). los YY_BUFFER_ESTADO tipo es un puntero a un opaco struct yy_buffer_state
estructura, por lo que puede inicializar de forma segura las variables YY_BUFFER_STATE para ((YY_BUFFER_ESTADO) 0)
si lo desea, y también consulte la estructura opaca para declarar correctamente la entrada
búferes en archivos de origen que no sean los de su escáner. Tenga en cuenta que el ARCHIVO puntero en
la llamada a yy_create_buffer solo se usa como el valor de yin visto por YY_ENTRADA; si tu
redefinir YY_ENTRADA por lo que ya no usa yin, entonces puedes pasar un cero con seguridad ARCHIVO puntero
a yy_create_buffer. Selecciona un búfer en particular para escanear usando:

void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer)

cambia el búfer de entrada del escáner para que los siguientes tokens provengan de nuevo_búfer. Note
esa yy_switch_to_buffer () yywrap () puede usarlo para configurar las cosas para continuar
escanear, en lugar de abrir un nuevo archivo y señalar yin en eso. Tenga en cuenta también que el cambio
fuentes de entrada a través de yy_switch_to_buffer () or yywrap ()no cambiar el comienzo
condición.

void yy_delete_buffer (búfer YY_BUFFER_STATE)

se utiliza para recuperar el almacenamiento asociado con un búfer. ( buffer puede ser nulo, en el que
caso de que la rutina no haga nada.) También puede borrar el contenido actual de un búfer
mediante:

void yy_flush_buffer (búfer YY_BUFFER_STATE)

Esta función descarta el contenido del búfer, por lo que la próxima vez que el escáner intente
coincidir con un token del búfer, primero llenará el búfer de nuevo usando YY_ENTRADA.

yy_new_buffer () es un alias para yy_create_buffer (), proporcionado para la compatibilidad con el
C ++ uso de nueva y borrar para crear y destruir objetos dinámicos.

Finalmente, la YY_CURRENT_BUFFER macro devuelve un YY_BUFFER_ESTADO manejar a la corriente
tampón.

A continuación, se muestra un ejemplo del uso de estas funciones para escribir un escáner que se expande incluyen
archivos (el < > característica se analiza a continuación):

/ * el estado "incl" se usa para elegir el nombre
* de un archivo de inclusión
*/
% x incl

%{
#definir MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack [MAX_INCLUDE_DEPTH];
int incluir_stack_ptr = 0;
%}

%%
incluir BEGIN (incl);

[az] + ECHO;
[^ az \ n] * \ n? ECO;

[\ t] * / * come el espacio en blanco * /
[^ \ t \ n] + {/ * obtuvo el nombre del archivo de inclusión * /
si (include_stack_ptr> = MAX_INCLUDE_DEPTH)
{
fprintf (stderr, "Incluye anidado demasiado profundo");
salida (1);
}

include_stack [include_stack_ptr ++] =
YY_CURRENT_BUFFER;

yyin = fopen (yytext, "r");

si (! yyin)
error( ... );

yy_switch_to_buffer (
yy_create_buffer (yyin, YY_BUF_SIZE));

COMIENZO (INICIAL);
}

< > {
si (--include_stack_ptr <0)
{
yyterminate ();
}

más
{
yy_delete_buffer (YY_CURRENT_BUFFER);
yy_switch_to_buffer (
include_stack [include_stack_ptr]);
}
}

Hay tres rutinas disponibles para configurar búferes de entrada para escanear cadenas en memoria
en lugar de archivos. Todos ellos crean un nuevo búfer de entrada para escanear la cadena y
devolver un correspondiente YY_BUFFER_ESTADO manejar (que debes eliminar con
yy_delete_buffer () cuando termine con él). También cambian al nuevo búfer usando
yy_switch_to_buffer (), así que la próxima llamada a yylex () comenzará a escanear la cadena.

yy_scan_string (const tanque * str)
escanea una cadena terminada en NUL.

yy_scan_bytes (const tanque * bytes, int Len)
escanea len bytes (incluidos posiblemente NUL) comenzando en la ubicación bytes

Tenga en cuenta que ambas funciones crean y escanean copia de la cadena o bytes. (Esta
puede ser deseable, ya que yylex () modifica el contenido del búfer que está escaneando).
puede evitar la copia usando:

yy_scan_buffer (char *base, aa_tamaño_t Talla)
que escanea en su lugar el búfer comenzando en base, que consiste en tamaño bytes, el
últimos dos bytes de los cuales debe be YY_END_OF_BUFFER_CHAR (ASCII NUL). Estos dos ultimos
los bytes no se escanean; por lo tanto, el escaneo consiste en base [0] a base [tamaño-2],
inclusivo.

Si no puede configurar bases de esta manera (es decir, olvídate de los dos últimos
YY_END_OF_BUFFER_CHAR bytes), luego yy_scan_buffer () devuelve un puntero nulo en su lugar
de crear un nuevo búfer de entrada.

El tipo aa_tamaño_t es un tipo integral al que puede convertir una expresión entera
reflejando el tamaño del búfer.

FIN DEL DOCUMENTO REGLAS


La regla especial "< > "indica las acciones que se deben realizar cuando se finaliza un archivo
encontrado y yywrap () devuelve un valor distinto de cero (es decir, indica que no hay más archivos para procesar).
La acción debe terminar haciendo una de estas cuatro cosas:

- asignando yin a un nuevo archivo de entrada (en versiones anteriores de flex, después de hacer el
asignación que tenías que llamar a la acción especial YY_NUEVO_ARCHIVO; esto ya no es
necesario);

- ejecutando un volvemos declaración;

- ejecutando el especial yyterminate () acción

- o, cambiando a un nuevo búfer usando yy_switch_to_buffer () como se muestra en el ejemplo
anterior.

< > las reglas no se pueden utilizar con otros patrones; solo pueden ser calificados con una lista
de las condiciones de inicio. Si un no calificado < > se da la regla, se aplica a todos comienzo
condiciones que aún no tienen < > acciones. Para especificar un < > regla por solo
la condición de inicio inicial, utilice

< >

Estas reglas son útiles para capturar cosas como comentarios no cerrados. Un ejemplo:

% x cotización
%%

... otras reglas para manejar las cotizaciones ...

< > {
error ("cita sin terminar");
yyterminate ();
}
< > {
if (* ++ lista de archivos)
yyin = fopen (* lista de archivos, "r");
más
yyterminate ();
}

OTRO MACROS


La macro YY_USER_ACTION se puede definir para proporcionar una acción que siempre se ejecuta
antes de la acción de la regla coincidente. Por ejemplo, podría estar # definido para llamar a una rutina
para convertir yytext a minúsculas. Cuándo YY_USER_ACTION se invoca, la variable yy_actuar
da el número de la regla correspondiente (las reglas se numeran comenzando con 1). Suponga que usted
desea hacer un perfil de la frecuencia con la que se ajusta cada una de sus reglas. Lo siguiente haría el
truco:

#define YY_USER_ACTION ++ ctr [yy_act]

donde ctr es una matriz para contener los recuentos de las diferentes reglas. Tenga en cuenta que la macro
AA_NUM_RULES da el número total de reglas (incluida la regla predeterminada, incluso si usa
-s), así que una declaración correcta para ctr :

int ctr [YY_NUM_RULES];

La macro YY_USER_INIT puede definirse para proporcionar una acción que siempre se ejecuta antes
el primer escaneo (y antes de que se realicen las inicializaciones internas del escáner). Por ejemplo,
podría usarse para llamar a una rutina para leer en una tabla de datos o abrir un archivo de registro.

La macro yy_set_interactive (es_interactive) se puede utilizar para controlar si la corriente
se considera tampón interactiva. Un búfer interactivo se procesa más lentamente, pero
debe usarse cuando la fuente de entrada del escáner es realmente interactiva para evitar problemas debido
a esperar para llenar los búferes (ver la discusión de la -I bandera a continuación). Un valor distinto de cero en
la invocación de la macro marca el búfer como interactivo, un valor cero como no interactivo.
Tenga en cuenta que el uso de esta macro anula %opción interactivo , %opción siempre interactivo or
%opción nunca interactivo (ver Opciones a continuación). yy_set_interactive () debe invocarse antes
para comenzar a escanear el búfer que es (o no) para ser considerado interactivo.

La macro yy_set_bol (at_bol) se puede utilizar para controlar si el escaneo del búfer actual
El contexto para la siguiente coincidencia de token se realiza como si estuviera al principio de una línea. Un no cero
El argumento macro crea reglas ancladas en

La macro YY_AT_BOL () devuelve verdadero si el siguiente token escaneado del búfer actual
tener reglas '^' activas, falso en caso contrario.

En el escáner generado, todas las acciones se recopilan en una declaración de cambio grande y
separado usando AA_BREAK, que puede redefinirse. Por defecto, es simplemente un "descanso", para
separe la acción de cada regla de la siguiente. Redefiniendo AA_BREAK permite para
Por ejemplo, los usuarios de C ++ deben #definir YY_BREAK no hacer nada (teniendo mucho cuidado de que cada
¡La regla termina con un "descanso" o un "retorno"!) para evitar sufrir una declaración inalcanzable
advertencias donde debido a que la acción de una regla termina con "return", el AA_BREAK es inaccesible.

VALORES DISPONIBLE A EL REINO UNIDO USUARIO


Esta sección resume los distintos valores disponibles para el usuario en las acciones de la regla.

- tanque * yytext contiene el texto del token actual. Puede modificarse pero no
alargado (no puede agregar caracteres al final).

Si la directiva especial %formación aparece en la primera sección del escáner
descripción, entonces yytexto en cambio se declara tanque yytext [YYLMAX], donde YYLMAX es un
definición de macro que puede redefinir en la primera sección si no le gusta la
valor predeterminado (generalmente 8 KB). Utilizando %formación resulta en escáneres algo más lentos,
pero el valor de yytexto se vuelve inmune a las llamadas a aporte() y unput (), que
potencialmente destruir su valor cuando yytexto es un puntero de carácter. Lo contrario a
%formación is %puntero, que es el predeterminado.

No se puede utilizar %formación al generar clases de analizador C ++ (el -+ bandera).

- int yyleng contiene la longitud del token actual.

- ARCHIVO * yyin es el archivo que por defecto flexionar lee de. Puede ser redefinido pero
hacerlo solo tiene sentido antes de que comience el escaneo o después de que se haya
encontrado. Cambiarlo en medio del escaneo tendrá resultados inesperados
desde flexionar amortigua su entrada; usar yyrestart () en lugar de. Una vez que finaliza el escaneo
debido a que se ha visto un final de archivo, puede asignar yin en el nuevo archivo de entrada y
luego llame al escáner nuevamente para continuar escaneando.

- vacío yyrestart ( ARCHIVO *archivo nuevo ) puede ser llamado a señalar yin en el nuevo archivo de entrada.
El cambio al nuevo archivo es inmediato (cualquier entrada almacenada previamente en búfer es
perdió). Tenga en cuenta que llamando yyrestart () yin como argumento desecha así el
búfer de entrada actual y continúa escaneando el mismo archivo de entrada.

- ARCHIVO * yyout es el archivo al que ECHO se realizan acciones. Puede ser reasignado por
el usuario.

- YY_CURRENT_BUFFER devuelve un YY_BUFFER_ESTADO manejar al búfer actual.

- AA_START devuelve un valor entero correspondiente a la condición de inicio actual.
Posteriormente puede utilizar este valor con EMPEZAR para volver a esa condición de inicio.

INTERFAZ HE TRABAJADO YACC


Uno de los principales usos de flexionar es como un compañero de la yacc analizador-generador. yacc analizadores
espera llamar a una rutina llamada yylex () para encontrar el siguiente token de entrada. La rutina es
se supone que debe devolver el tipo del siguiente token, así como poner cualquier valor asociado en
el mundial yylval. Para utilizar flexionar yacc, uno especifica el -d opción de yacc instruir
es para generar el archivo y.tab.h que contiene definiciones de todos los % tokens apareciendo en el
yacc aporte. A continuación, este archivo se incluye en el flexionar escáner. Por ejemplo, si uno de los
tokens es "TOK_NUMBER", parte del escáner podría verse así:

%{
#include "y.tab.h"
%}

%%

[0-9] + yylval = atoi (yytext); devuelve TOK_NUMBER;

CAMPUS


flexionar tiene las siguientes opciones:

-B, --respaldo
Genere información de respaldo para lex.copia de seguridad. Esta es una lista de los estados del escáner
que requieren copia de seguridad y los caracteres de entrada en los que lo hacen. Añadiendo
reglas que se pueden eliminar de los estados de respaldo. Si todos se eliminan los estados de respaldo
y -cf or -CF se utiliza, el escáner generado se ejecutará más rápido (consulte la -p bandera).
Solo los usuarios que deseen exprimir hasta el último ciclo de sus escáneres deben preocuparse
acerca de esta opción. (Consulte la sección sobre Consideraciones de rendimiento a continuación).

-c es una opción obsoleta y sin hacer nada incluida para el cumplimiento de POSIX.

-D, --depurar
hace que el escáner generado se ejecute en depurar modo. Siempre que se reconoce un patrón
y lo global yy_flex_debug es distinto de cero (que es el valor predeterminado), el escáner
escribir a stderr una línea de la forma:

- aceptar la regla en la línea 53 ("el texto coincidente")

El número de línea se refiere a la ubicación de la regla en el archivo que define el escáner.
(es decir, el archivo que se alimentó a flexionar). Los mensajes también se generan cuando el
el escáner realiza una copia de seguridad, acepta la regla predeterminada, llega al final de su búfer de entrada (o
encuentra un NUL; En este punto, los dos tienen el mismo aspecto en cuanto a la
en cuestión), o llega al final del archivo.

-F, --lleno
especifica rápido escáner. No se realiza ninguna compresión de tabla y se omite stdio. El
el resultado es grande pero rápido. Esta opción es equivalente a -Cfr (vea abajo).

-h, --ayuda
genera un resumen de "ayuda" de flexión opciones para stdout y luego sale. -? y
--ayuda son sinónimos de -h.

-I, no distingue entre mayúsculas y minúsculas
instruye flexionar generar un no distingue entre mayúsculas y minúsculas escáner. El caso de las cartas dadas
existentes flexionar los patrones de entrada se ignorarán y los tokens de la entrada coincidirán
independientemente del caso. El texto coincidente dado en yytexto tendrá el caso preservado
(es decir, no se doblará).

-yo, --lex-compat
activa la máxima compatibilidad con el AT&T original lex implementación. Nota
que esto no significa ser completados compatibilidad. El uso de esta opción cuesta un
cantidad considerable de rendimiento, y no se puede utilizar con el - +, -F, -F, -Cf,
or -CF opciones. Para obtener detalles sobre las compatibilidades que proporciona, consulte la sección
"Incompatibilidades con Lex y POSIX" a continuación. Esta opción también da como resultado el nombre
YY_FLEX_LEX_COMPAT siendo # definido en el escáner generado.

-n es otra opción obsoleta que no hace nada y que se incluye solo para el cumplimiento de POSIX.

-pag, --perf-informe
genera un informe de rendimiento para stderr. El informe consta de comentarios
con respecto a las características del flexionar archivo de entrada que causará una pérdida grave de
rendimiento en el escáner resultante. Si das la bandera dos veces, también
Obtenga comentarios sobre las características que conducen a pérdidas menores de rendimiento.

Tenga en cuenta que el uso de RECHAZAR, %opción yylineno, y contexto de seguimiento variable (ver
la sección de Deficiencias / Errores a continuación) conlleva una penalización sustancial en el desempeño;
uso de yymore (), las ^ operador, y el -I bandera implica un rendimiento menor
sanciones.

-s, --ningún valor predeterminado
causa el tu préstamo estudiantil gobernar (esa entrada inigualable del escáner se repite a salida estándar) para ser
suprimido. Si el escáner encuentra una entrada que no coincide con ninguna de sus reglas,
aborta con un error. Esta opción es útil para encontrar agujeros en el escáner.
conjunto de reglas.

-t, --salida estándar
instruye flexionar para escribir el escáner que genera en la salida estándar en lugar de
lex.yy.c.

-v, --verboso
especifica que flexionar debería escribir a stderr un resumen de las estadísticas sobre el
escáner que genera. La mayoría de las estadísticas no tienen sentido para los informales. flexionar
usuario, pero la primera línea identifica la versión de flexionar (igual que reportado por -V),
y en la siguiente línea, las banderas utilizadas al generar el escáner, incluidas las que
están activados de forma predeterminada.

-w, --ahora advertir
suprime los mensajes de advertencia.

-B, --lote
instruye flexionar generar un lote escáner, lo contrario de interactivo escáneres
generado por -I (vea abajo). En general, usas -B cuando estas a ciertos Que tu
el escáner nunca se utilizará de forma interactiva y desea exprimir un pequeño más,
rendimiento fuera de ella. Si su objetivo es, en cambio, exprimir un montón más,
rendimiento, debe utilizar el -cf or -CF opciones (discutidas a continuación), que
encender -B automáticamente de todos modos.

-F, --rápido
especifica que el rápido Se debe utilizar la representación de la tabla del escáner (y stdio
omitido). Esta representación es tan rápida como la representación de la tabla completa
(-F), y para algunos conjuntos de patrones será considerablemente más pequeño (y para otros,
más grande). En general, si el conjunto de patrones contiene tanto "palabras clave" como un comodín,
regla de "identificador", como en el conjunto:

"caso" return TOK_CASE;
"cambiar" return TOK_SWITCH;
...
"predeterminado" return TOK_DEFAULT;
[az] + return TOK_ID;

entonces es mejor usar la representación de la tabla completa. Si solo el
La regla de "identificador" está presente y luego usa una tabla hash o algo similar para detectar
las palabras clave, es mejor usarlas -F.

Esta opción es equivalente a -CFr (vea abajo). No se puede usar con - +.

-YO, --interactivo
instruye flexionar para generar un interactivo escáner. Un escáner interactivo es uno
que solo mira hacia adelante para decidir qué token se ha emparejado si es absolutamente necesario.
Resulta que siempre mirando un carácter adicional hacia adelante, incluso si el escáner tiene
ya visto suficiente texto para eliminar la ambigüedad del token actual, es un poco más rápido que
solo mirando hacia adelante cuando sea necesario. Pero los escáneres que siempre miran hacia adelante dan
terrible actuación interactiva; por ejemplo, cuando un usuario escribe una nueva línea, es
no se reconoce como un token de nueva línea hasta que ingresan una alternativa, token, que a menudo significa
escribiendo otra línea completa.

Flex los escáneres están predeterminados interactivo a menos que uses el -cf or -CF mesa-
opciones de compresión (ver más abajo). Eso es porque si lo que buscas es alto
rendimiento, debería utilizar una de estas opciones, por lo que si no lo hizo, flexionar
asume que prefiere intercambiar un poco de rendimiento en tiempo de ejecución por intuitivo
comportamiento interactivo. Tenga en cuenta también que usted no puede utilizan el -I junto con -cf or
-CF. Por tanto, esta opción no es realmente necesaria; está activado de forma predeterminada para todos aquellos
casos en los que está permitido.

Tenga en cuenta que si isatty () devuelve falso para la entrada del escáner, flex volverá a
modo por lotes, incluso si -I fue especificado. Para forzar el modo interactivo pase lo que pase,
utilizan el %opción siempre interactivo (ver Opciones a continuación).

Puede forzar a un escáner a no ser interactivo usando -B (véase más arriba).

-l, --no hay línea
instruye flexionar no generar #línea directivas. Sin esta opción, flexionar pimientos
el escáner generado con directivas #line, por lo que los mensajes de error en las acciones
estar correctamente ubicado con respecto al original flexionar archivo de entrada (si el
los errores se deben al código en el archivo de entrada), o lex.yy.c (si los errores son flexión
error: debe informar este tipo de errores a la dirección de correo electrónico que se indica a continuación).

-T, --rastro
hace flexionar entrar corriendo rastrear modo. Generará muchos mensajes para stderr
con respecto a la forma de la entrada y la resultante no determinista y
autómatas finitos deterministas. Esta opción se utiliza principalmente para mantener flexionar.

-V, --versión
imprime el número de versión para stdout y salidas. --versión es sinónimo de -V.

-7, --7 bits
instruye flexionar para generar un escáner de 7 bits, es decir, uno que solo puede reconocer
Caracteres de 7 bits en su entrada. La ventaja de usar -7 es que el escáner
Las tablas pueden tener hasta la mitad del tamaño de las generadas con el -8 opción (ver
debajo). La desventaja es que estos escáneres a menudo se cuelgan o fallan si su entrada
contiene un carácter de 8 bits.

Sin embargo, tenga en cuenta que, a menos que genere su escáner utilizando el -cf or -CF mesa
opciones de compresión, uso de -7 ahorrará solo una pequeña cantidad de espacio en la tabla, y
haga que su escáner sea considerablemente menos portátil. Flex el comportamiento predeterminado es
generar un escáner de 8 bits a menos que utilice el -cf or -CF, en ese caso flexionar
predeterminado para generar escáneres de 7 bits a menos que su sitio siempre haya sido configurado para
generar escáneres de 8 bits (como suele ser el caso con sitios fuera de EE. UU.). Usted puede
decir si flex generó un escáner de 7 u 8 bits inspeccionando la bandera
resumen en el -v salida como se describe arriba.

Tenga en cuenta que si usa -Cfe or -CFe (esas opciones de compresión de tablas, pero también usando
clases de equivalencia como se discute ver a continuación), flex todavía por defecto genera una
Escáner de 8 bits, ya que normalmente con estas opciones de compresión se utilizan tablas completas de 8 bits.
no mucho más caro que las tablas de 7 bits.

-8, --8 bits
instruye flexionar para generar un escáner de 8 bits, es decir, uno que pueda reconocer 8 bits
caracteres. Esta bandera solo es necesaria para los escáneres generados con -cf or -CF, as
de lo contrario, flex predeterminada para generar un escáner de 8 bits de todos modos.

Ver la discusión de -7 arriba para el comportamiento predeterminado de flex y las compensaciones
entre escáneres de 7 y 8 bits.

- +, --c ++
especifica que desea que flex genere una clase de analizador de C ++. Ver la sección sobre
Generación de escáneres C ++ a continuación para obtener más detalles.

-C [aefFmr]
controla el grado de compresión de la tabla y, de manera más general, las compensaciones entre
escáneres pequeños y escáneres rápidos.

-California, --alinear ("alinear") indica a flex que intercambie tablas más grandes en el
escáner para un rendimiento más rápido porque los elementos de las tablas son mejores
alineado para el acceso a la memoria y el cálculo. En algunas arquitecturas RISC, buscar
y manipular palabras largas es más eficiente que con unidades de menor tamaño como
palabras cortas. Esta opción puede duplicar el tamaño de las tablas que utiliza su escáner.

-Ce, --ecs directo flexionar para construir equivalencia clases es decir, conjuntos de personajes
que tienen propiedades léxicas idénticas (por ejemplo, si la única apariencia de
dígitos en el flexionar la entrada está en la clase de caracteres "[0-9]", luego los dígitos '0',
'1', ..., '9' se colocarán todos en la misma clase de equivalencia). Clases de equivalencia
generalmente dan reducciones dramáticas en los tamaños de archivo de la tabla / objeto final (generalmente un
factor de 2-5) y son bastante económicos en cuanto a rendimiento (una búsqueda de matriz por
personaje escaneado).

-cf especifica que el ser completados se deben generar tablas de escáner - flexionar no debe
Comprimir las tablas aprovechando las ventajas de funciones de transición similares para
diferentes estados.

-CF especifica que la representación alternativa del escáner rápido (descrita anteriormente
bajo el -F bandera). Esta opción no se puede utilizar con - +.

-Cm, --meta-ecs directo flexionar para construir metaequivalencia clases que son conjuntos
de clases de equivalencia (o caracteres, si no se utilizan clases de equivalencia)
que se utilizan comúnmente juntos. Las clases de metaequivalencia suelen ser una gran ventaja cuando
utilizando tablas comprimidas, pero tienen un impacto moderado en el rendimiento (uno o dos
pruebas "si" y una búsqueda de matriz por carácter escaneado).

-Cr, --leer hace que el escáner generado evitar uso de la biblioteca de E / S estándar
(stdio) para la entrada. En lugar de llamar fread () or getc (), el escáner utilizará el
leer() llamada al sistema, lo que resulta en una ganancia de rendimiento que varía de un sistema a otro.
sistema, pero en general es probablemente insignificante a menos que también esté utilizando -cf or -CF.
Usar -Cr puede causar un comportamiento extraño si, por ejemplo, lee de yin usando
stdio antes de llamar al escáner (porque el escáner perderá cualquier texto
sus lecturas anteriores quedan en el búfer de entrada stdio).

-Cr no tiene efecto si define YY_ENTRADA (consulte El escáner generado más arriba).

Solo -C especifica que las tablas del escáner deben estar comprimidas pero ninguna
Deben utilizarse clases de equivalencia ni clases de metaequivalencia.

Las opciones -cf or -CF y -Cm no tienen sentido juntos - no hay oportunidad
para clases de metaequivalencia si la tabla no se comprime. De lo contrario, el
las opciones pueden mezclarse libremente y son acumulativas.

La configuración predeterminada es -cem, que especifica que flexionar debe generar equivalencia
clases y clases de metaequivalencia. Este ajuste proporciona el mayor grado de
Compresión de mesa. Puede intercambiar escáneres de ejecución más rápida a costa de
tablas más grandes con lo siguiente generalmente cierto:

más lento y más pequeño
-cem
-Cm
-ce
-C
-C {f, F} e
-C {f, F}
-C {f, F} a
más rápido y más grande

Tenga en cuenta que los escáneres con las tablas más pequeñas generalmente se generan y compilan
más rápido, por lo que durante el desarrollo, por lo general, querrá utilizar el valor predeterminado, máximo
compresión.

-Cfe suele ser un buen compromiso entre velocidad y tamaño para los escáneres de producción.

-salida, --outputfile = ARCHIVO
ordena a flex que escriba el escáner en el archivo salida en lugar de lex.yy.c. Si
combinar -o con el -t opción, entonces el escáner se escribe en stdout pero su #línea
directivas (ver el -L opción anterior) consulte el archivo salida.

-Pprefijo, --prefijo = CADENA
cambia el valor predeterminado yy prefijo utilizado por flexionar para todas las variables globalmente visibles y
nombres de funciones para ser en su lugar prefijo. Por ejemplo, -Pfoo cambia el nombre de yytexto
a pie de página También cambia el nombre del archivo de salida predeterminado de lex.yy.c a
lex.foo.c. Aquí están todos los nombres afectados:

yy_create_buffer
yy_delete_buffer
yy_flex_debug
yy_init_buffer
yy_flush_buffer
yy_load_buffer_state
yy_cambiar_a_búfer
yin
yyleng
yylex
yylineno
tu
aareiniciar
yytexto
envolver

(Si está utilizando un escáner C ++, solo envolver y yyFlexLexer Son afectados.)
Dentro de su escáner, aún puede consultar las variables globales y
funciones que utilizan cualquiera de las versiones de su nombre; pero externamente, tienen la
nombre modificado.

Esta opción le permite vincular fácilmente varios flexionar programas en el mismo
ejecutable. Sin embargo, tenga en cuenta que el uso de esta opción también cambia el nombre yywrap (), entonces tu ahora
debe proporcione su propia versión (con el nombre apropiado) de la rutina para su
escáner, o usar %opción noyywrap, como enlazar con -ll ya no proporciona uno para
usted por defecto.

-Archivo_esqueleto, --skel = ARCHIVO
anula el archivo de esqueleto predeterminado del que flexionar construye sus escáneres.
Nunca necesitará esta opción a menos que esté haciendo flexionar mantenimiento o desarrollo.

-X, --posix-compatible
máxima compatibilidad con POSIX lex.

--yylineno
conteo de líneas de seguimiento en yylineno.

--yyclass = NOMBRE
nombre de la clase C ++.

--header-file = ARCHIVO
cree un archivo de encabezado C además del escáner.

--tables-file [= ARCHIVO]
escribir tablas en ARCHIVO.

-Dmacro [= defn]
#define macro defn (la definición predeterminada es '1').

-R, --entrante
generar un escáner C reentrante

- puente de bisontes
escáner para el analizador sintáctico puro de bisonte.

--ubicaciones de bisontes
incluir soporte de yylloc.

--stdinit
inicialice yyin / yyout en stdin / stdout.

--noansi-definiciones viejo estilo función definiciones.

--noansi-prototipos
lista de parámetros vacía en prototipos.

--sustantivo
no incluye .

--sin función
no generan una FUNCIÓN en particular.

flexionar también proporciona un mecanismo para controlar las opciones dentro de la especificación del escáner
en sí mismo, en lugar de desde la línea de comandos de flex. Esto se hace incluyendo %opción
directivas en la primera sección de la especificación del escáner. Puede especificar varios
opciones con un solo %opción directiva, y directivas múltiples en la primera sección de
su archivo de entrada flexible.

La mayoría de las opciones se dan simplemente como nombres, opcionalmente precedidas por la palabra "no" (sin
espacio en blanco intermedio) para negar su significado. Un número es equivalente a banderas flexibles o
su negación:

Opción 7bit -7
Opción 8bit -8
opción alinear -Ca
opción de copia de seguridad -b
opción lote -B
c ++ - + opción

caso o
distingue entre mayúsculas y minúsculas de -i (predeterminado)

no distingue entre mayúsculas y minúsculas o
opción -i sin carcasa

opción debug -d
opuesto predeterminado de la opción -s
opción ecs -Ce
opción rápida -F
opción -f completa
opción interactiva -I
opción lex-compat -l
opción meta-ecs -Cm
opción perf-report -p
opción leer -Cr
opción stdout -t
opción verbose -v
advertir opuesto a la opción -w
(use "% option nowarn" para -w)

matriz equivalente a "% matriz"
puntero equivalente a "% puntero" (predeterminado)

Cosas % de opciones proporcionar funciones que de otro modo no estarán disponibles:

siempre interactivo
le indica a flex que genere un escáner que siempre considere su entrada
"interactivo". Normalmente, en cada nuevo archivo de entrada, el escáner llama isatty () en una
intentar determinar si la fuente de entrada del escáner es interactiva y, por lo tanto,
debe leerse un carácter a la vez. Sin embargo, cuando se utiliza esta opción, no
tal llamada se hace.

principal ordena a flex que proporcione un valor predeterminado principal() programa para el escáner, que simplemente
llamadas yylex (). Esta opción implica noyywrap (vea abajo).

nunca interactivo
indica a flex que genere un escáner que nunca considera su entrada "interactiva"
(de nuevo, no se hizo ninguna llamada a isatty ()). Esto es lo contrario de siempre interactivo.

montón habilita el uso de pilas de condiciones de inicio (consulte Condiciones de inicio más arriba).

unidad estándar
si está configurado (es decir, %opción estándar) inicializa yin y tu a stdin y stdout
en lugar del valor predeterminado de nulo. Algunos existentes lex los programas dependen de este comportamiento,
aunque no cumple con ANSI C, que no requiere stdin y
stdout para ser constante en tiempo de compilación.

yylineno
directo flexionar para generar un escáner que mantiene el número de la línea actual
leer de su entrada en la variable global yylineno. Esta opción está implícita en
%opción lex-compatible.

envolver si no está configurado (es decir, %opción noyywrap), hace que el escáner no llame yywrap () sobre un final
archivo, pero simplemente asuma que no hay más archivos para escanear (hasta que el usuario
puntos yin en un nuevo archivo y llamadas yylex () otra vez).

flexionar analiza las acciones de sus reglas para determinar si utiliza el RECHAZAR or yymore () características.
El rechazar y yymore Hay opciones disponibles para anular su decisión sobre si usa
las opciones, ya sea configurándolas (p. ej., %opción rechazar) para indicar que la característica es
efectivamente utilizado, o desarmarlos para indicar que en realidad no se utiliza (p. ej., %opción
ya no más).

Tres opciones toman valores delimitados por cadenas, compensados ​​con '=':

% option outfile = "ABC"

es equivalente a -oABC, y

% option prefix = "XYZ"

es equivalente a -PXYZ. Finalmente,

% option yyclass = "foo"

solo se aplica al generar un escáner C ++ ( -+ opción). Informa flexionar que tienes
derivado foo como una subclase de yyFlexLexer, so flexionar colocará sus acciones en el miembro
función foo :: yylex () en lugar de yyFlexLexer :: yylex (). También genera una
yyFlexLexer :: yylex () función miembro que emite un error en tiempo de ejecución (invocando
yyFlexLexer :: LexerError ()) si se llama. Consulte Generación de escáneres C ++, a continuación, para obtener información adicional.
información.

Hay varias opciones disponibles para los puristas de la pelusa que desean suprimir la aparición de
rutinas innecesarias en el escáner generado. Cada uno de los siguientes, si no está configurado (p. Ej.,
%opción sustantivo ), da como resultado que la rutina correspondiente no aparezca en el
escáner:

entrada, unput
yy_push_state, yy_pop_state, yy_top_state
yy_scan_buffer, yy_scan_bytes, yy_scan_string

(aunque el yy_push_state () y los amigos no aparecerán de todos modos a menos que uses %opción apilar).

ACTUACIÓN CONSIDERACIONES


El principal objetivo de diseño de flexionar es que genera escáneres de alto rendimiento. Ha sido
optimizado para tratar bien con grandes conjuntos de reglas. Aparte de los efectos en el escáner
velocidad de la compresión de la mesa -C opciones descritas anteriormente, hay una serie de
opciones / acciones que degradan el rendimiento. Estos son, del más caro al menos:

RECHAZAR
% opción yylineno
contexto final arbitrario

conjuntos de patrones que requieren copia de seguridad
%formación
% opción interactiva
% opción siempre interactiva

'^' operador de principio de línea
yymore ()

siendo los tres primeros bastante caros y los dos últimos bastante baratos. Nota
también eso unput () se implementa como una llamada de rutina que potencialmente hace bastante
trabajar, mientras yyless () es una macro bastante barata; así que si solo devuelves el texto sobrante,
escaneado yyless ().

RECHAZAR debe evitarse a toda costa cuando el rendimiento es importante. Es un particular
opción cara.

Deshacerse de la copia de seguridad es complicado y, a menudo, puede suponer una enorme cantidad de trabajo para un
escáner complicado. En principio, uno comienza usando el -b bandera para generar un
copia de seguridad de lex Archivo. Por ejemplo, en la entrada

%%
foo devuelve TOK_KEYWORD;
foobar devuelve TOK_KEYWORD;

el archivo se parece a:

El estado # 6 no acepta -
números de línea de regla asociados:
2 3
transiciones externas: [o]
transiciones de jam: EOF [\ 001-n p- \ 177]

El estado # 8 no acepta -
números de línea de regla asociados:
3
transiciones externas: [a]
jam-transitions: EOF [\ 001-`b- \ 177]

El estado # 9 no acepta -
números de línea de regla asociados:
3
transiciones externas: [r]
transiciones de jam: EOF [\ 001-q s- \ 177]

Las tablas comprimidas siempre se respaldan.

Las primeras líneas nos dicen que hay un estado del escáner en el que puede hacer una transición
en una 'o' pero no en ningún otro carácter, y que en ese estado el escaneado actual
el texto no coincide con ninguna regla. El estado ocurre cuando se intenta hacer coincidir las reglas que se encuentran en
líneas 2 y 3 en el archivo de entrada. Si el escáner está en ese estado y luego lee algo
que no sea una 'o', tendrá que hacer una copia de seguridad para encontrar una regla que coincida. Con un poco de
Al rascarse la cabeza, uno puede ver que este debe ser el estado en el que se encuentra cuando ha visto "fo".
Cuando esto ha sucedido, si se ve cualquier otra cosa que no sea otra 'o', el escáner tendrá
para hacer una copia de seguridad para que coincida simplemente con la 'f' (por la regla predeterminada).

El comentario sobre el estado n. ° 8 indica que hay un problema cuando se escanea "foob".
De hecho, en cualquier carácter que no sea una 'a', el escáner tendrá que retroceder para aceptar
"foo". De manera similar, el comentario para el estado n. ° 9 se refiere a cuándo se ha escaneado "fooba" y
'r' no sigue.

El comentario final nos recuerda que no tiene sentido tomarse la molestia de eliminar
retrocediendo de las reglas a menos que estemos usando -cf or -CF, ya que no hay ganancia de rendimiento
hacerlo con escáneres comprimidos.

La forma de eliminar la copia de seguridad es agregar reglas de "error":

%%
foo devuelve TOK_KEYWORD;
foobar devuelve TOK_KEYWORD;

Fooba |
foob ​​|
para {
/ * falsa alarma, no es realmente una palabra clave * /
devolver TOK_ID;
}

También se puede eliminar la copia de seguridad entre una lista de palabras clave mediante una regla "general":

%%
foo devuelve TOK_KEYWORD;
foobar devuelve TOK_KEYWORD;

[az] + return TOK_ID;

Esta suele ser la mejor solución cuando es apropiado.

Las copias de seguridad de los mensajes tienden a ser una cascada. Con un conjunto complicado de reglas, no es raro
recibe cientos de mensajes. Sin embargo, si uno puede descifrarlos, a menudo solo se necesitan una docena
más o menos reglas para eliminar la copia de seguridad (aunque es fácil cometer un error y tener una
La regla de error coincide accidentalmente con un token válido. Un futuro posible flexionar la característica será
agregar reglas automáticamente para eliminar la copia de seguridad).

Es importante tener en cuenta que obtiene los beneficios de eliminar solo las copias de seguridad
si eliminas cada instancia de copia de seguridad. Dejar solo uno significa que no ganas nada.

Variable contexto final (donde las partes inicial y final no tienen un contexto fijo
longitud) conlleva casi la misma pérdida de rendimiento que RECHAZAR (es decir, sustancial). Así que cuando
posible una regla como:

%%
ratón | rata / (gato | perro) correr ();

está mejor escrito:

%%
ratón / gato | perro correr ();
rata / gato | perro correr ();

o como

%%
ratón | rata / gato correr ();
ratón | rata / perro correr ();

Tenga en cuenta que aquí el especial '|' la acción hace no proporcionar cualquier ahorro, e incluso puede hacer
las cosas empeoran (consulte Deficiencias / Errores a continuación).

Otra área en la que el usuario puede aumentar el rendimiento de un escáner (y una que es más fácil de
implementar) surge del hecho de que cuanto más tiempo coinciden los tokens, más rápido el escáner
se ejecutará. Esto se debe a que con tokens largos, el procesamiento de la mayoría de los caracteres de entrada toma
lugar en el bucle de escaneo interno (corto) y, a menudo, no tiene que pasar por el
trabajo adicional de configurar el entorno de escaneo (p. ej., yytexto) para la acción.
Recuerde el escáner para comentarios de C:

% x comentario
%%
int núm_línea = 1;

"/ *" BEGIN (comentario);

[^ * \ n] *
"*" + [^ * / \ n] *
\ n ++ núm_línea;
"*" + "/" COMIENZO (INICIAL);

Esto podría acelerarse escribiéndolo como:

% x comentario
%%
int núm_línea = 1;

"/ *" BEGIN (comentario);

[^ * \ n] *
[^ * \ n] * \ n ++ line_num;
"*" + [^ * / \ n] *
"*" + [^ * / \ n] * \ n ++ número_línea;
"*" + "/" COMIENZO (INICIAL);

Ahora, en lugar de que cada nueva línea requiera el procesamiento de otra acción, reconociendo la
las nuevas líneas se "distribuyen" sobre las otras reglas para mantener el texto coincidente siempre que
posible. Tenga en cuenta que la adición de las reglas lo hacen no ralentizar el escáner! La velocidad del
escáner es independiente del número de reglas o (módulo las consideraciones dadas en el
comienzo de esta sección) cuán complicadas son las reglas con respecto a operadores como
'*' y '|'.

Un último ejemplo de cómo acelerar un escáner: suponga que desea escanear un archivo
que contengan identificadores y palabras clave, uno por línea y sin otros caracteres extraños,
y reconocer todas las palabras clave. Un primer enfoque natural es:

%%
mont |
automóvil |
descanso |
...etc...
volátil |
while / * es una palabra clave * /

. | \ n / * no es una palabra clave * /

Para eliminar el retroceso, introduzca una regla general:

%%
mont |
automóvil |
descanso |
...etc...
volátil |
while / * es una palabra clave * /

[az] + |
. | \ n / * no es una palabra clave * /

Ahora, si se garantiza que hay exactamente una palabra por línea, podemos reducir la
el número total de coincidencias a la mitad al fusionar el reconocimiento de nuevas líneas con el de
las otras fichas:

%%
asm \ n |
auto \ n |
romper \ n |
...etc...
volátil \ n |
mientras que \ n / * es una palabra clave * /

[az] + \ n |
. | \ n / * no es una palabra clave * /

Hay que tener cuidado aquí, ya que ahora hemos reintroducido la copia de seguridad en el escáner. En
particular, mientras we saber que nunca habrá caracteres en el flujo de entrada
que no sean letras o nuevas líneas, flexionar no puedo resolver esto, y planeará posiblemente
necesita hacer una copia de seguridad cuando ha escaneado un token como "auto" y luego el siguiente carácter es
algo que no sea una nueva línea o una letra. Anteriormente, coincidiría con el
regla "auto" y listo, pero ahora no tiene regla "auto", solo una regla "auto \ n". A
eliminar la posibilidad de realizar una copia de seguridad, podríamos duplicar todas las reglas pero sin
saltos de línea finales, o, dado que nunca esperamos encontrar una entrada de este tipo y, por lo tanto, no
cómo está clasificado, podemos introducir una regla general más, esta que no
incluir una nueva línea:

%%
asm \ n |
auto \ n |
romper \ n |
...etc...
volátil \ n |
mientras que \ n / * es una palabra clave * /

[az] + \ n |
[az] + |
. | \ n / * no es una palabra clave * /

Compilado con -Cf, esto es lo más rápido que se puede obtener flexionar escáner para ir a por esto
Problema particular.

Una nota final: flexionar es lento cuando coincide con NUL, especialmente cuando un token contiene
múltiples NUL. Es mejor escribir reglas que coincidan Corto cantidades de texto si es
anticipó que el texto a menudo incluirá NUL.

Otra nota final con respecto al rendimiento: como se mencionó anteriormente en la sección Cómo la entrada
coincide, cambia de tamaño dinámicamente yytexto acomodar tokens enormes es un proceso lento
porque actualmente requiere que el token (enorme) se vuelva a escanear desde el principio. Por lo tanto
si el rendimiento es vital, debe intentar hacer coincidir cantidades "grandes" de texto, pero no
Cantidades "enormes", donde el límite entre los dos es de aproximadamente 8K caracteres / token.

GENERANDO C + + ESCÁNERES


flexionar proporciona dos formas diferentes de generar escáneres para usar con C ++. La primera forma es
para simplemente compilar un escáner generado por flexionar usando un compilador C ++ en lugar de un C
compilador. No debería encontrar ningún error de compilación (informe cualquier error que encuentre a
la dirección de correo electrónico proporcionada en la sección Autor a continuación). A continuación, puede utilizar el código C ++ en su
acciones de reglas en lugar de código C. Tenga en cuenta que la fuente de entrada predeterminada para su escáner
permanece yin, y el eco predeterminado todavía se hace para tu. Ambos permanecen ARCHIVO *
variables y no C ++ arroyos.

También puedes usar flexionar para generar una clase de escáner C ++, usando el -+ opción (o,
equivalentemente, %opción c ++), que se especifica automáticamente si el nombre del flex
ejecutable termina en un '+', como flex ++. Cuando se utiliza esta opción, el valor predeterminado de flex es
generando el escáner en el archivo lex.yy.cc en lugar de lex.yy.c. El escáner generado
incluye el archivo de encabezado FlexLexer.h, que define la interfaz para dos clases de C ++.

La primera clase, flexlexer, proporciona una clase base abstracta que define el escáner general
interfaz de clase. Proporciona las siguientes funciones de miembro:

const char * YYText ()
devuelve el texto del token coincidente más recientemente, el equivalente de ytexto.

int YYLeng ()
devuelve la longitud del token coincidente más recientemente, el equivalente de yyleng.

int lineno () const
devuelve el número de línea de entrada actual (ver %opción yylineno), or 1 if %opción
yylineno no se utilizó.

vacío set_debug ( int bandera )
establece la bandera de depuración para el escáner, equivalente a asignar a yy_flex_debug
(consulte la sección Opciones más arriba). Tenga en cuenta que debe construir el escáner usando
%opción depurar para incluir información de depuración en él.

int depurar() const
devuelve la configuración actual del indicador de depuración.

También se proporcionan funciones miembro equivalentes a yy_switch_to_buffer (), yy_create_buffer ()
(aunque el primer argumento es un std :: istream * puntero de objeto y no un ARCHIVO*),
yy_flush_buffer (), yy_delete_buffer (), y yyrestart () (de nuevo, el primer argumento es un
std :: istream * puntero de objeto).

La segunda clase definida en FlexLexer.h is yyFlexLexer, que se deriva de FlexLexer.
Define las siguientes funciones de miembros adicionales:

yyFlexLexer ( std :: istream * arg_yyin = 0, std :: ostream * arg_yyout = 0 )
construye un yyFlexLexer objeto utilizando los flujos dados para entrada y salida. Si
no especificado, los flujos predeterminados a cin y cout respectivamente.

virtual int yylex ()
realiza el mismo papel es yylex () lo hace para los escáneres flexibles ordinarios: escanea el
flujo de entrada, consumiendo tokens, hasta que la acción de una regla devuelve un valor. Si tu
derivar una subclase S en yyFlexLexer y desea acceder a las funciones miembro y
variables de S dentro yylex (), entonces necesitas usar %opción yyclass = "S" para informar
flexionar que usará esa subclase en lugar de yyFlexLexer. En este caso,
en lugar de generar yyFlexLexer :: yylex (), flexionar genera S :: yylex () (y también
genera un maniquí yyFlexLexer :: yylex () que llama yyFlexLexer :: LexerError () if
llamada).

virtual vacío switch_streams (estándar :: istream * nuevo en = 0,
std :: ostream * nuevo_fuera = 0) reasigna yin a nuevo en (si no es nulo) y tu a
nuevo_fuera (ídem), eliminando el búfer de entrada anterior si yin se reasigna.

int yylex std :: istream * nuevo en, std :: ostream * nuevo_fuera = 0 )
primero cambia los flujos de entrada a través de switch_streams nuevo en, nuevo_fuera ) y luego
devuelve el valor de yylex ().

Además, yyFlexLexer define las siguientes funciones virtuales protegidas que puede
redefinir en clases derivadas para personalizar el escáner:

virtual int LexerInput ( char * buf int tamaño máximo )
lee hasta tamaño máximo personajes en buf y devuelve el número de caracteres leídos.
Para indicar el final de la entrada, devuelve 0 caracteres. Tenga en cuenta que los escáneres "interactivos"
(Véase el -B y -I banderas) definen la macro YY_INTERACTIVO. Si redefine
LexerInput () y necesitan tomar diferentes acciones dependiendo de si el
es posible que el escáner esté escaneando una fuente de entrada interactiva, puede probar la
presencia de este nombre a través de #ifdef.

virtual vacío LexerOutput ( const char * buf int tamaño )
escribe tamaño caracteres del búfer buf que, aunque termina en NUL, puede
también contienen NUL "internos" si las reglas del escáner pueden hacer coincidir el texto con NUL en
de ellas.

virtual vacío LexerError ( const char * MSG )
informa un mensaje de error fatal. La versión predeterminada de esta función escribe el
mensaje a la corriente cerrar y salidas.

Tenga en cuenta que una yyFlexLexer el objeto contiene su toda estado de escaneo. Por lo tanto, puede utilizar tales
objetos para crear escáneres reentrantes. Puede instanciar varias instancias del mismo
yyFlexLexer clase, y también puede combinar varias clases de escáner de C ++ juntas en el
mismo programa usando el -P opción discutida anteriormente.

Finalmente, tenga en cuenta que el %formación la función no está disponible para las clases de analizadores de C ++; debes
utilizan el %puntero (el valor por defecto).

A continuación, se muestra un ejemplo de un escáner de C ++ simple:

// Un ejemplo del uso de la clase de escáner flex C ++.

%{
int mylineno = 0;
%}

cadena \ "[^ \ n"] + \ "

ws [\ t] +

alfa [A-Za-z]
cavar [0-9]
nombre ({alpha} | {dig} | \ $) ({alpha} | {dig} | [_. \ - / $]) *
num1 [- +]? {dig} + \.? ([eE] [- +]? {dig} +)?
num2 [- +]? {dig} * \. {dig} + ([eE] [- +]? {dig} +)?
número {num1} | {num2}

%%

{ws} / * omitir espacios en blanco y tabulaciones * /

"/ *" {
intc;

while ((c = yyinput ())! = 0)
{
si (c == '\ n')
++ mylineno;

más si (c == '*')
{
si ((c = yyinput ()) == '/')
break;
más
unput (c);
}
}
}

{número} cout << "número" << YYText () << '\ n';

\ n mylineno ++;

{nombre} cout << "nombre" << YYText () << '\ n';

{cadena} cout << "cadena" << YYText () << '\ n';

%%

int main (int / * argc * /, char ** / * argv * /)
{
FlexLexer * lexer = new yyFlexLexer;
while (lexer-> yylex ()! = 0)
;
0 regresar;
}
Si desea crear varias clases de lexer (diferentes), utilice la -P bandera (o la
prefijo = opción) para cambiar el nombre de cada yyFlexLexer a algún otro xxFlexLexer. Entonces puedes
incluir en sus otras fuentes una vez por clase lexer, primero renombrando
yyFlexLexer como sigue:

#undef yyFlexLexer
#definir yyFlexLexer xxFlexLexer
#incluir

#undef yyFlexLexer
#definir yyFlexLexer zzFlexLexer
#incluir

si, por ejemplo, usaste %opción prefijo = "xx" para uno de sus escáneres y %opción
prefijo = "zz" para el otro.

IMPORTANTE: la forma actual de la clase de escaneo es experimental y puede cambiar
considerablemente entre los principales lanzamientos.

INCOMPATIBILIDADES HE TRABAJADO LEX Y POSIX


flexionar es una reescritura del AT&T Unix lex herramienta (las dos implementaciones no comparten ninguna
código, sin embargo), con algunas extensiones e incompatibilidades, las cuales son de interés para
aquellos que deseen escribir escáneres aceptables para cualquier implementación. Flex es completamente
compatible con POSIX lex especificación, excepto que cuando se utiliza %puntero (el valor por defecto),
una llamada a unput () destruye el contenido de ytexto, que es contrario al POSIX
especificación.

En esta sección discutimos todas las áreas conocidas de incompatibilidad entre flex, AT&T
lex y la especificación POSIX.

flexión -l La opción activa la máxima compatibilidad con el AT&T original. lex implementación,
a costa de una pérdida importante en el rendimiento del escáner generado. Anotamos debajo de cuál
las incompatibilidades se pueden superar utilizando el -l .

flexionar Es totalmente compatible con lex con las siguientes excepciones:

- Los indocumentados lex variable interna del escáner yylineno no es compatible a menos que -l
or %opción yylineno se utiliza.

yylineno debe mantenerse por búfer, en lugar de por escáner
(variable global única).

yylineno no forma parte de la especificación POSIX.

El aporte() La rutina no es redefinible, aunque se puede llamar para leer caracteres.
siguiendo lo que haya sido igualado por una regla. Si aporte() encuentra un final de
archivar el normal yywrap () el procesamiento está hecho. Un final de archivo `` real '' es devuelto por
aporte() as FEO.

En cambio, la entrada se controla definiendo el YY_ENTRADA macro.

El flexionar restricción que aporte() no se puede redefinir está de acuerdo con el
Especificación POSIX, que simplemente no especifica ninguna forma de controlar el
entrada del escáner que no sea haciendo una asignación inicial a yin

El unput () la rutina no es redefinible. Esta restricción está de acuerdo con
POSIX.

- flexionar los escáneres no son tan reentrantes como lex escáneres. En particular, si tiene un
escáner interactivo y un controlador de interrupciones que salta del escáner,
y posteriormente se vuelve a llamar al escáner, es posible que reciba el siguiente mensaje:

Error interno del escáner de flex fatal: se perdió el final del búfer

Para volver a ingresar al escáner, primero use

yyrestart (yyin);

Tenga en cuenta que esta llamada eliminará cualquier entrada almacenada en búfer; normalmente esto no es un
Problema con un escáner interactivo.

También tenga en cuenta que las clases de escáner Flex C ++ en reentrante, por lo que si usar C ++ es una opción
para ti, deberías usarlos en su lugar. Consulte "Generación de escáneres C ++" más arriba para
Detalles.

- producción() no es apoyado. Salida del ECHO La macro se realiza en el puntero de archivo.
tu (defecto salida estándar).

producción() no forma parte de la especificación POSIX.

- lex no admite condiciones de inicio exclusivas (% x), aunque están en POSIX
especificación.

- Cuando se amplían las definiciones, flexionar los encierra entre paréntesis. Con Lex, el
siguientes:

NOMBRE [AZ] [A-Z0-9] *
%%
foo {NAME}? printf ("Lo encontré \ n");
%%

no coincidirá con la cadena "foo" porque cuando se expande la macro, la regla es
equivalente a "foo [AZ] [A-Z0-9] *?" y la precedencia es tal que el '?' es
asociado con "[A-Z0-9] *". Con flexionar, la regla se ampliará a "foo ([AZ] [A-
Z0-9] *)? "Y la cadena" foo "coincidirá.

Tenga en cuenta que si la definición comienza con ^ o termina con $ entonces es no expandido
entre paréntesis, para permitir que estos operadores aparezcan en las definiciones sin perder
sus significados especiales. Pero el , /, y < > los operadores no se pueden utilizar en un
flexionar definición.

Usar -l resultados en el lex comportamiento sin paréntesis alrededor de la definición.

La especificación POSIX es que la definición se incluya entre paréntesis.

- Algunas implementaciones de lex permitir que la acción de una regla comience en una línea separada, si
el patrón de la regla tiene espacios en blanco al final:

%%
foo | bar
{foobar_action (); }

flexionar no es compatible con esta función.

El lex %r (generar un escáner Ratfor) no es compatible. No es parte de
la especificación POSIX.

- Después de una llamada a unput (), yytexto no está definido hasta que coincida con el siguiente token,
a menos que el escáner haya sido construido usando %formación. Este no es el caso con lex o de
Especificación POSIX. El -l La opción elimina esta incompatibilidad.

- La precedencia de la {} El operador (rango numérico) es diferente. lex Intérpretes
"abc {1,3}" como "coincide con una, dos o tres apariciones de 'abc'", mientras que flexionar
lo interpreta como "coincidir con 'ab' seguido de una, dos o tres apariciones de 'c'".
Este último está de acuerdo con la especificación POSIX.

- La precedencia de la ^ El operador es diferente. lex interpreta "^ foo | bar" como "coincidencia
ya sea 'foo' al principio de una línea, o 'bar' en cualquier lugar ", mientras que flexionar
lo interpreta como "coincidir con 'foo' o 'bar' si vienen al principio de un
line ". Este último está de acuerdo con la especificación POSIX.

- Las declaraciones especiales de tamaño de tabla como %a CON EL APOYO DE lex no son requeridos por
flexionar escáneres flexionar los ignora.

- El nombre FLEX_ESCÁNER está # definido, por lo que los escáneres pueden escribirse para su uso con
flexionar or la ex. Los escáneres también incluyen YY_FLEX_MAJOR_VERSION y YY_FLEX_MENOR_VERSIÓN
indicando qué versión de flexionar generado el escáner (por ejemplo, para el 2.5
lanzamiento, estas definiciones serían 2 y 5 respectivamente).

Las siguientes flexionar las características no están incluidas en lex o la especificación POSIX:

Escáneres C ++
%opción
ámbitos de condición de inicio
pilas de condiciones de inicio
escáneres interactivos / no interactivos
yy_scan_string () y amigos
yyterminate ()
yy_set_interactive ()
yy_set_bol ()
YY_AT_BOL ()
< >
<*>
AA_DECL
AA_START
YY_USER_ACTION
YY_USER_INIT
directivas #line
% {} está en torno a las acciones
múltiples acciones en una línea

además de casi todas las banderas flexibles. La última característica de la lista se refiere al hecho de que
flexionar puede poner varias acciones en la misma línea, separadas por punto y coma, mientras que
la ex, el siguiente

foo handle_foo (); ++ num_foos_seen;

está (bastante sorprendentemente) truncado a

foo handle_foo ();

flexionar no trunca la acción. Las acciones que no están entre llaves son simplemente
terminado al final de la línea.

La diagnostica


advertencia, gobernar no puede be emparejado indica que la regla dada no se puede igualar porque
sigue otras reglas que siempre coincidirán con el mismo texto. Por ejemplo, en el
siguiente "foo" no puede coincidir porque viene después de una regla de identificador "catch-all":

[az] + got_identifier ();
foo got_foo ();

Usar RECHAZAR en un escáner suprime esta advertencia.

advertencia, -s opción dado pero tu préstamo estudiantil gobernar podemos be emparejado significa que es posible
(tal vez solo en una condición de inicio en particular) que la regla predeterminada (coincida con cualquier
carácter) es el único que coincidirá con una entrada en particular. Ya que -s se le dio,
presumiblemente esto no es lo que se pretende.

rechazar_usado_pero_no_detectado indefinido or yymore_usado_pero_no_detectado indefinido - Estas
pueden ocurrir errores en tiempo de compilación. Indican que el escáner utiliza RECHAZAR or yymore ()
pero eso flexionar no se dio cuenta del hecho, lo que significa que flexionar escaneado las dos primeras secciones
buscando ocurrencias de estas acciones y no pudo encontrar ninguna, pero de alguna manera se coló
algunos en (a través de un archivo #include, por ejemplo). Usar %opción rechazar or %opción yymore a
indique a flex que realmente usa estas funciones.

flexionar escáner apretado - un escáner compilado con -s ha encontrado una cadena de entrada que
no se correspondía con ninguna de sus reglas. Este error también puede ocurrir debido a problemas internos.

ficha demasiado grande, excede YYLMAX - su escáner utiliza %formación y una de sus reglas coincidía con un
cuerda más larga que la YYLMAX constante (8K bytes por defecto). Puedes incrementar el valor
por # define'ing YYLMAX en la sección de definiciones de tu flexionar entrada.

escáner requiere -8 bandera a utilizan el las personaje 'X' - La especificación de su escáner incluye
reconocer el carácter de 8 bits 'X' y no especificó el indicador -8, y su escáner
predeterminado a 7 bits porque usó el -cf or -CF opciones de compresión de tablas. Ver el
discusión de la -7 bandera para más detalles.

flexionar escáner hacer retroceder desbordarse - usaste unput () para hacer retroceder tanto texto que el
El búfer del escáner no pudo contener tanto el texto retrocedido como el token actual en ytexto.
Idealmente, el escáner debería redimensionar dinámicamente el búfer en este caso, pero actualmente
no.

Las opciones de entrada buffer Desbordamiento, no puedes ampliar buffer porque escáner usos RECHAZAR - el escáner fue
trabajando para hacer coincidir un token extremadamente grande y necesitaba expandir el búfer de entrada. Esta
no funciona con escáneres que usan RECHAZAR.

fatal flexionar escáner interno error - fin of buffer perdida - Esto puede ocurrir en un escáner.
que se vuelve a ingresar después de que un salto largo haya saltado (o superado) la activación del escáner
marco. Antes de volver a ingresar al escáner, use:

yyrestart (yyin);

o, como se indicó anteriormente, cambie al uso de la clase de analizador C ++.

demasiado muchos comienzo condiciones in <> ¡construir! - enumeraste más condiciones de inicio en un <>
construir que existen (por lo que debe haber enumerado al menos uno de ellos dos veces).

Use freebsd-lex en línea usando los servicios de onworks.net


Servidores y estaciones de trabajo gratuitos

Descargar aplicaciones de Windows y Linux

  • 1
    fre: ac - convertidor de audio gratuito
    fre: ac - convertidor de audio gratuito
    fre:ac es un conversor de audio y CD gratuito
    Destripador para varios formatos y codificadores.
    Cuenta con MP3, MP4/M4A, WMA, Ogg
    Formato Vorbis, FLAC, AAC y Bonk
    apoyo, ...
    Descargar fre:ac - convertidor de audio gratuito
  • 2
    matplotlib
    matplotlib
    Matplotlib es una biblioteca completa
    para crear estática, animada y
    visualizaciones interactivas en Python.
    Matplotlib facilita las cosas fáciles y
    cosa dura ...
    Descargar Matplotlib
  • 3
    hombrebot
    hombrebot
    Escribe la lógica de tu chatbot una vez y
    conectarlo a uno de los disponibles
    servicios de mensajería, incluido Amazon
    Alexa, Mensajero de Facebook, Slack,
    Telegram o incluso yo...
    Descargar BotMan
  • 4
    Joplin
    Joplin
    Joplin es un código abierto y gratuito
    aplicación para tomar notas y tareas
    puede manejar una gran cantidad de notas en
    Formato de rebajas, organízalas en
    cuadernos y ...
    Descargar Joplin
  • 5
    gerbv: un visor Gerber (RS-274X)
    gerbv: un visor Gerber (RS-274X)
    Gerbv es un archivo Gerber de código abierto
    (solo RS-274X) visor. Gerbv te permite
    cargar varios archivos uno encima del otro,
    hacer mediciones en la imagen mostrada,
    etc ...
    Descargar gerbv, un visor Gerber (RS-274X)
  • 6
    Iómetro
    Iómetro
    Herramienta de análisis de rendimiento de E/S.
    Público: Desarrolladores, Información
    Tecnología, Ciencia / Investigación, Sistema
    Administradores. Interfaz de usuario: Win32
    (MS Windows). Progr ...
    Descargar Iómetro
  • Más "

Comandos de Linux

Ad