El análisis sintáctico, el análisis sintáctico o el análisis sintáctico es el proceso de analizar una cadena de símbolos, ya sea en lenguaje natural, lenguajes informáticos o estructuras de datos, conforme a las reglas de una gramática formal. El término análisis proviene del latín pars ( orationis), que significa parte (del habla).
El término tiene significados ligeramente diferentes en diferentes ramas de la lingüística y la informática. El análisis tradicional de oraciones se realiza a menudo como un método para comprender el significado exacto de una oración o palabra, a veces con la ayuda de dispositivos como diagramas de oraciones. Por lo general, enfatiza la importancia de las divisiones gramaticales como sujeto y predicado.
Dentro de la lingüística computacional, el término se usa para referirse al análisis formal por una computadora de una oración u otra cadena de palabras en sus constituyentes, lo que resulta en un árbol de análisis sintáctico que muestra su relación sintáctica entre sí, que también puede contener información semántica y de otro tipo ( valores p ). Algunos algoritmos de análisis pueden generar un bosque de análisis o una lista de árboles de análisis para una entrada sintácticamente ambigua.
El término también se utiliza en psicolingüística para describir la comprensión del lenguaje. En este contexto, el análisis sintáctico se refiere a la forma en que los seres humanos analizan una oración o frase (en lenguaje o texto hablado) "en términos de constituyentes gramaticales, identificando las partes del habla, relaciones sintácticas, etc." Este término es especialmente común cuando se discute qué señales lingüísticas ayudan a los hablantes a interpretar oraciones de senderos de jardín.
Dentro de la informática, el término se utiliza en el análisis de lenguajes informáticos, refiriéndose al análisis sintáctico del código de entrada en sus partes componentes para facilitar la escritura de compiladores e intérpretes. El término también puede usarse para describir una escisión o separación.
El ejercicio gramatical tradicional de análisis sintáctico, a veces conocido como análisis de cláusulas, implica dividir un texto en sus partes componentes del discurso con una explicación de la forma, función y relación sintáctica de cada parte. Esto se determina en gran parte a partir del estudio de las conjugaciones y declinaciones del idioma, que pueden ser bastante intrincadas para idiomas con muchas inflexiones. Analizar una frase como 'hombre muerde a perro' implica señalar que el sustantivo singular 'hombre' es el sujeto de la oración, el verbo 'muerde' es la tercera persona del singular del tiempo presente del verbo 'morder', y el sustantivo singular 'perro' es el objeto de la oración. A veces se utilizan técnicas como los diagramas de oraciones para indicar la relación entre los elementos de la oración.
El análisis era fundamental para la enseñanza de la gramática en todo el mundo de habla inglesa y, en general, se lo consideraba básico para el uso y la comprensión del lenguaje escrito. Sin embargo, la enseñanza general de tales técnicas ya no es actual.
En algunos sistemas de procesamiento de lenguaje natural y traducción automática, los textos escritos en lenguajes humanos son analizados por programas de computadora. Los programas no pueden analizar fácilmente las oraciones humanas, ya que existe una ambigüedad sustancial en la estructura del lenguaje humano, cuyo uso es para transmitir significado (o semántica ) entre una gama potencialmente ilimitada de posibilidades, pero solo algunas de las cuales son pertinentes para el caso particular. Por lo tanto, una expresión "El hombre muerde a un perro" frente a "El perro muerde al hombre" es definida en un detalle, pero en otro idioma podría aparecer como "El hombre muerde a un perro" con una dependencia del contexto más amplio para distinguir entre esas dos posibilidades, si es que esa diferencia fue de preocupación. Es difícil preparar reglas formales para describir el comportamiento informal, aunque está claro que se están siguiendo algunas reglas.
Para analizar los datos del lenguaje natural, los investigadores primero deben ponerse de acuerdo sobre la gramática que se utilizará. La elección de la sintaxis se ve afectada por preocupaciones tanto lingüísticas como computacionales; por ejemplo, algunos sistemas de análisis sintáctico utilizan gramática funcional léxica, pero en general, se sabe que el análisis sintáctico de gramáticas de este tipo es NP-completo. La gramática de la estructura de frases dirigida por la cabeza es otro formalismo lingüístico que ha sido popular en la comunidad de análisis sintáctico, pero otros esfuerzos de investigación se han centrado en formalismos menos complejos, como el utilizado en Penn Treebank. El análisis poco profundo tiene como objetivo encontrar solo los límites de los componentes principales, como las frases nominales. Otra estrategia popular para evitar controversias lingüísticas es el análisis gramatical de dependencia.
La mayoría de los analizadores sintácticos modernos son, al menos en parte, estadísticos ; es decir, se basan en un corpus de datos de entrenamiento que ya ha sido anotado (analizado a mano). Este enfoque permite que el sistema recopile información sobre la frecuencia con la que ocurren diversas construcciones en contextos específicos. (Consulte aprendizaje automático ). Los enfoques que se han utilizado incluyen PCFG ( gramáticas probabilísticas libres de contexto) sencillas, entropía máxima y redes neuronales. La mayoría de los sistemas más exitosos utilizan estadísticas léxicas (es decir, consideran las identidades de las palabras involucradas, así como su parte del discurso ). Sin embargo, estos sistemas son vulnerables al sobreajuste y requieren algún tipo de suavizado para ser efectivos.
Los algoritmos de análisis para el lenguaje natural no pueden depender de que la gramática tenga propiedades "agradables" como ocurre con las gramáticas diseñadas manualmente para los lenguajes de programación. Como se mencionó anteriormente, algunos formalismos gramaticales son muy difíciles de analizar computacionalmente; en general, incluso si la estructura deseada no está libre de contexto, se utiliza algún tipo de aproximación libre de contexto a la gramática para realizar una primera pasada. Los algoritmos que usan gramáticas libres de contexto a menudo se basan en alguna variante del algoritmo CYK, generalmente con algo de heurística para eliminar análisis poco probables y ahorrar tiempo. (Ver análisis sintáctico del gráfico ). Sin embargo, algunos sistemas intercambian velocidad por precisión utilizando, por ejemplo, versiones de tiempo lineal del algoritmo shift-reduce. Un desarrollo algo reciente ha sido el cambio de clasificación del análisis sintáctico en el que el analizador propone una gran cantidad de análisis y un sistema más complejo selecciona la mejor opción. Los analizadores semánticos convierten los textos en representaciones de sus significados.
En psicolingüística, el análisis sintáctico implica no solo la asignación de palabras a categorías (formación de percepciones ontológicas), sino la evaluación del significado de una oración de acuerdo con las reglas de sintaxis extraídas por inferencias hechas de cada palabra en la oración (conocido como connotación ). Esto ocurre normalmente cuando se escuchan o se leen las palabras. En consecuencia, los modelos psicolingüísticos de análisis sintáctico son necesariamente incrementales, lo que significa que construyen una interpretación a medida que se procesa la oración, que normalmente se expresa en términos de una estructura sintáctica parcial. La creación de estructuras inicialmente incorrectas ocurre cuando se interpretan oraciones de senderos de jardín.
El análisis del discurso examina formas de analizar el uso del lenguaje y los eventos semióticos. El lenguaje persuasivo puede llamarse retórica.
Un analizador es un componente de software que toma datos de entrada (frecuentemente texto) y construye una estructura de datos, a menudo algún tipo de árbol de análisis, árbol de sintaxis abstracta u otra estructura jerárquica, dando una representación estructural de la entrada mientras verifica la sintaxis correcta. El análisis sintáctico puede ir precedido o seguido de otros pasos, o estos pueden combinarse en un solo paso. El analizador suele estar precedido por un analizador léxico independiente, que crea tokens a partir de la secuencia de caracteres de entrada; alternativamente, estos se pueden combinar en el análisis sintáctico sin escáner. Los analizadores pueden programarse a mano o pueden generarse automática o semiautomáticamente mediante un generador de analizadores sintácticos. El análisis es complementario a la creación de plantillas, que produce una salida formateada. Estos se pueden aplicar a diferentes dominios, pero a menudo aparecen juntos, como el par scanf / printf, o las etapas de entrada (análisis frontal) y salida (generación de código back-end) de un compilador.
La entrada a un analizador a menudo es texto en algún lenguaje de computadora, pero también puede ser texto en un lenguaje natural o datos textuales menos estructurados, en cuyo caso generalmente solo se extraen ciertas partes del texto, en lugar de construir un árbol de análisis sintáctico. Los analizadores van desde funciones muy simples como scanf, hasta programas complejos como la interfaz de un compilador de C ++ o el analizador de HTML de un navegador web. Una clase importante de análisis simple se realiza mediante expresiones regulares, en las que un grupo de expresiones regulares define un lenguaje regular y un motor de expresiones regulares que genera automáticamente un analizador para ese idioma, lo que permite la coincidencia de patrones y la extracción de texto. En otros contextos, las expresiones regulares se utilizan antes del análisis, como el paso de lexing, cuya salida luego es utilizada por el analizador.
El uso de analizadores sintácticos varía según la entrada. En el caso de los lenguajes de datos, un analizador se encuentra a menudo como la función de lectura de archivos de un programa, como la lectura de texto HTML o XML ; estos ejemplos son lenguajes de marcado. En el caso de los lenguajes de programación, un analizador es un componente de un compilador o intérprete, que analiza el código fuente de un lenguaje de programación de computadoras para crear alguna forma de representación interna; el analizador es un paso clave en la interfaz del compilador. Los lenguajes de programación tienden a especificarse en términos de una gramática libre de contexto determinista porque se pueden escribir analizadores rápidos y eficientes para ellos. En el caso de los compiladores, el análisis sintáctico en sí se puede realizar en una o varias pasadas; consulte el compilador de una pasada y el compilador de varias pasadas.
Las desventajas implícitas de un compilador de un solo paso se pueden superar en gran medida agregando arreglos, donde se prevé la reubicación del código durante el paso hacia adelante, y los arreglos se aplican al revés cuando se ha reconocido que el segmento del programa actual ha sido terminado. Un ejemplo en el que un mecanismo de reparación de este tipo sería útil sería una instrucción GOTO hacia adelante, donde se desconoce el objetivo del GOTO hasta que se complete el segmento del programa. En este caso, la aplicación de la corrección se retrasaría hasta que se reconociera el objetivo del GOTO. Por el contrario, un GOTO hacia atrás no requiere una reparación, ya que la ubicación ya se conocerá.
Las gramáticas libres de contexto están limitadas en la medida en que pueden expresar todos los requisitos de un idioma. De manera informal, la razón es que la memoria de tal lenguaje es limitada. La gramática no puede recordar la presencia de una construcción sobre una entrada arbitrariamente larga; esto es necesario para un idioma en el que, por ejemplo, se debe declarar un nombre antes de que se pueda hacer referencia a él. Sin embargo, las gramáticas más poderosas que pueden expresar esta restricción no se pueden analizar de manera eficiente. Por lo tanto, es una estrategia común crear un analizador relajado para una gramática libre de contexto que acepta un superconjunto de las construcciones de lenguaje deseadas (es decir, acepta algunas construcciones no válidas); más tarde, los constructos no deseados se pueden filtrar en el paso del análisis semántico (análisis contextual).
Por ejemplo, en Python, el siguiente es un código sintácticamente válido:
x = 1 print(x)
Sin embargo, el siguiente código es sintácticamente válido en términos de la gramática libre de contexto, lo que produce un árbol de sintaxis con la misma estructura que el anterior, pero es sintácticamente inválido en términos de la gramática sensible al contexto, que requiere que las variables se inicialicen antes usar:
x = 1 print(y)
En lugar de analizarse en la etapa de análisis sintáctico, esto se detecta verificando los valores en el árbol de sintaxis, por lo tanto, como parte del análisis semántico: en la práctica, la sintaxis sensible al contexto se analiza más fácilmente como semántica.
El siguiente ejemplo demuestra el caso común de analizar un lenguaje de computadora con dos niveles de gramática: léxico y sintáctico.
La primera etapa es la generación de tokens, o análisis léxico, mediante el cual el flujo de caracteres de entrada se divide en símbolos significativos definidos por una gramática de expresiones regulares. Por ejemplo, un programa de cálculo se vería en una entrada como " 12 * (3 + 4)^2
" y dividirlo en las fichas 12
, *
, (
, 3
, +
, 4
, )
, ^
, 2
, cada uno de los cuales es un símbolo significativo en el contexto de una expresión aritmética. El analizador léxico contendría normas para decirle que los personajes *
, +
, ^
, (
y )
marcan el inicio de un nuevo token, fichas tan sin sentido como " 12*
" o " (3
no se generarán".
La siguiente etapa es el análisis sintáctico o el análisis sintáctico, que consiste en comprobar que los tokens forman una expresión permitida. Esto generalmente se hace con referencia a una gramática libre de contexto que define de manera recursiva los componentes que pueden formar una expresión y el orden en el que deben aparecer. Sin embargo, no todas las reglas que definen los lenguajes de programación pueden expresarse únicamente con gramáticas libres de contexto, por ejemplo, la validez de tipo y la declaración adecuada de identificadores. Estas reglas se pueden expresar formalmente con gramáticas de atributos.
La fase final es el análisis sintáctico semántico, que consiste en resolver las implicaciones de la expresión recién validada y tomar la acción adecuada. En el caso de una calculadora o intérprete, la acción es evaluar la expresión o programa; un compilador, por otro lado, generaría algún tipo de código. También se pueden utilizar gramáticas de atributos para definir estas acciones.
La tarea del analizador es esencialmente determinar si la entrada se puede derivar del símbolo de inicio de la gramática y cómo. Esto se puede hacer esencialmente de dos formas:
Los analizadores de LL y el analizador de descendencia recursiva son ejemplos de analizadores de arriba hacia abajo que no pueden adaptarse a las reglas de producción recursivas izquierdas. Aunque se ha creído que las implementaciones simples de análisis de arriba hacia abajo no pueden acomodar la recursividad directa e indirecta por la izquierda y pueden requerir una complejidad exponencial de tiempo y espacio mientras se analizan gramáticas ambiguas libres de contexto, Frost ha creado algoritmos más sofisticados para el análisis de arriba hacia abajo., Hafiz y Callaghan que acomodan la ambigüedad y la recursividad izquierda en el tiempo polinomial y que generan representaciones de tamaño polinomial del número potencialmente exponencial de árboles de análisis sintáctico. Su algoritmo es capaz de producir derivaciones tanto a la izquierda como a la derecha de una entrada con respecto a una gramática libre de contexto dada.
Una distinción importante con respecto a los analizadores es si un analizador genera una derivación más a la izquierda o una derivación más a la derecha (consulte la gramática libre de contexto ). Los analizadores sintácticos LL generarán una derivación más a la izquierda y los analizadores LR generarán una derivación más a la derecha (aunque normalmente a la inversa).
Algunos Se han diseñado algoritmos de análisis sintáctico para lenguajes de programación visual. Los analizadores de lenguajes visuales a veces se basan en gramáticas gráficas.
Se han utilizado algoritmos de análisis adaptativo para construir interfaces de usuario de lenguaje natural "autoexpandibles".
Algunas de las herramientas de desarrollo de analizadores más conocidas incluyen las siguientes:
int v;main(){
v
Lookahead establece el máximo de tokens entrantes que un analizador puede usar para decidir qué regla debe usar. La búsqueda anticipada es especialmente relevante para los analizadores sintácticos LL, LR y LALR, donde a menudo se indica explícitamente colocando la búsqueda anticipada en el nombre del algoritmo entre paréntesis, como LALR (1).
La mayoría de los lenguajes de programación, el objetivo principal de los analizadores, se definen cuidadosamente de tal manera que un analizador con una búsqueda anticipada limitada, normalmente uno, puede analizarlos, porque los analizadores con una búsqueda anticipada limitada suelen ser más eficientes. Un cambio importante en esta tendencia se produjo en 1990 cuando Terence Parr creó ANTLR para su doctorado. tesis, un generador de analizador sintáctico para analizadores sintácticos LL ( k) eficientes, donde k es cualquier valor fijo.
Los analizadores LR suelen tener solo unas pocas acciones después de ver cada token. Son shift (agregue esta ficha a la pila para una reducción posterior), reduzca (saque fichas de la pila y forme una construcción sintáctica), final, error (no se aplica ninguna regla conocida) o conflicto (no sabe si cambiar o reducir).
Lookahead tiene dos ventajas.
Ejemplo: analizar la expresión 1 + 2 * 3
El conjunto de reglas de análisis de expresiones (llamado gramática) es el siguiente, | ||
Regla 1: | E → E + E | La expresión es la suma de dos expresiones. |
Regla 2: | E → E * E | La expresión es el producto de dos expresiones. |
Regla 3: | E → número | La expresión es un número simple |
Regla 4: | + tiene menos precedencia que * |
La mayoría de los lenguajes de programación (excepto algunos como APL y Smalltalk) y las fórmulas algebraicas dan mayor prioridad a la multiplicación que a la suma, en cuyo caso la interpretación correcta del ejemplo anterior es 1 + (2 * 3). Tenga en cuenta que Rule4 anterior es una regla semántica. Es posible reescribir la gramática para incorporarla a la sintaxis. Sin embargo, no todas estas reglas pueden traducirse en sintaxis.
Entrada inicial = [1, +, 2, *, 3]
El árbol de análisis y el código resultante no es correcto según la semántica del lenguaje.
Para analizar correctamente sin mirar hacia adelante, hay tres soluciones:
El árbol de análisis generado es correcto y simplemente más eficiente que los analizadores no anticipados. Esta es la estrategia que se sigue en los analizadores sintácticos LALR.
21. Códigos HTML de análisis libre [1]
![]() | Busque parse o parseing en Wiktionary, el diccionario gratuito. |