Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
04ace52
Modifico función principal
fcalabrow Jul 17, 2022
af0ed8c
Agrego parser y añado métodos a la clase Derivation
fcalabrow Jul 17, 2022
be86065
Agrego palabras en español
fcalabrow Jul 17, 2022
b4b114e
Algoritmo de parser.py
fcalabrow Jul 17, 2022
24bcade
Agrego parser
fcalabrow Jul 17, 2022
98b066e
Transfer y restricciones al merge interno
fcalabrow Jul 23, 2022
53e4009
Cambio de interfaz
fcalabrow Jul 23, 2022
e099525
Rasgos de merge interno
fcalabrow Jul 23, 2022
b7d0149
Parámetro opcional filename
fcalabrow Jul 23, 2022
3752484
Cambio operación transfer
fcalabrow Jul 26, 2022
7898a74
Procesamiento de input (sentence)
fcalabrow Jul 26, 2022
e7b75c6
Categorías funcionales
fcalabrow Jul 28, 2022
03b15b1
Modificación función get_place_fc
fcalabrow Jul 29, 2022
5e62ca6
Elimino get_fc_place y modifico Rule 3
fcalabrow Jul 29, 2022
c18229d
Agrego categorías funcionales
fcalabrow Jul 29, 2022
db24161
Manejo de duplicados (incompleto)
fcalabrow Jul 30, 2022
2752985
Debug
fcalabrow Jul 30, 2022
2def01b
Agrego traducción al inglés
fcalabrow Jul 31, 2022
10157f9
Agrego stage-by-stage view
fcalabrow Jul 31, 2022
538edfa
Corrijo función parse
fcalabrow Jul 31, 2022
698512e
Deepcopy al lexicalitem
fcalabrow Jul 31, 2022
048a56d
Categorías funcionales
fcalabrow Jul 31, 2022
ec44c37
Actualizo documentación
fcalabrow Jul 31, 2022
7b4d16b
Update README.md
fcalabrow Jul 31, 2022
de13a90
Update README.md
fcalabrow Jul 31, 2022
e759ae8
Update README.md
fcalabrow Jul 31, 2022
39cbd27
Update README.md
fcalabrow Jul 31, 2022
6c9bd27
Update README.md
fcalabrow Jul 31, 2022
c95b44a
Update README.md
fcalabrow Jul 31, 2022
f405bc0
Modifico numeración de reglas
fcalabrow Aug 1, 2022
5ee5afc
Delete rules.pdf
fcalabrow Aug 1, 2022
7f5a3fb
Update README.md
fcalabrow Aug 2, 2022
7c811b5
Update README.md
fcalabrow Aug 2, 2022
26f3a53
Update README.md
fcalabrow Aug 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 107 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,107 @@
# minimalism
Implementation of A Formalization of Minimalist Syntax (Collins & Stabler, 2016)
# Parser minimalista

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tené en cuenta que haciendo las instrucciones en español en el mismo archivo README de él, no vas a poder hacerle una pr, si ese fuera tu interés.

Este es un parser basado en la implementación de Alex Warstadt del formalismo descrito en ["A Formalization of Minimalist Syntax"](https://onlinelibrary.wiley.com/doi/abs/10.1111/synt.12117) por Chris Collins y Edward Stabler (2016). Su objetivo es determinar si las oraciones introducidas por el usuario son o no gramaticales, y devolver en caso positivo una estructura sintáctica.

El parser es capaz de reconocer oraciones transitivas (*el perro comió el hueso/the dog ate the bone*), oraciones inergativas (*el perro corrió/the dog run*) y oraciones inacusativas (*el perro llegó*/*the dog arrived*)

## Modo de uso
Para utilizar el programa es necesario ejecutar el archivo `main.py`, ubicado en la carpeta principal del repositorio. Hecho esto, el usuario verá un menú de cinco opciones:

**1. Parser** *(Permite introducir la oración a parsear)*<br>
**2. Manual derivation** *(Permite generar la derivación manualmente, como en la implementación de Warstadt)*<br>
**3. Change grammar** *(Permite seleccionar una gramática distinta)*<br>
**4. Enable/disable stage-by-stage view** *(Cuando está activado, muestra el paso a paso de una derivación, incluyendo las reglas aplicadas)*<br>
**5. Quit** *(Finaliza el programa)*

### La gramática
Por defecto, el Lexicon de la gramática se genera a partir del archivo `lexicon.xml` de la carpeta `data`. La elección de este archivo puede ser modificada mediante la opción 3 del menú principal.<br>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Por defecto, el Lexicon de la gramática se genera a partir del archivo `lexicon.xml` de la carpeta `data`. La elección de este archivo puede ser modificada mediante la opción 3 del menú principal.<br>
Por defecto, el léxico de la gramática se genera a partir del archivo `lexicon.xml` de la carpeta `data`. La elección de este archivo puede ser modificada mediante la opción 3 del menú principal.<br>

Las gramáticas están definidas en el formato XML, que organiza el léxico como un árbol de nodos. A cada ítem le corresponde un elemento con la etiqueta `<word>`, dentro del cual se insertan nuevos elementos con una etiqueta distinta para cada rasgo: la etiqueta `<phon>` corresponde a los rasgos fonético, `<syn>` a los sintácticos, y `<sem>` a los semánticos (aunque estos últimos no son utilizados en la implementación actual). Por ejemplo, la entrada léxica correspondiente a un verbo como *corrió* sería la siguiente:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Las gramáticas están definidas en el formato XML, que organiza el léxico como un árbol de nodos. A cada ítem le corresponde un elemento con la etiqueta `<word>`, dentro del cual se insertan nuevos elementos con una etiqueta distinta para cada rasgo: la etiqueta `<phon>` corresponde a los rasgos fonético, `<syn>` a los sintácticos, y `<sem>` a los semánticos (aunque estos últimos no son utilizados en la implementación actual). Por ejemplo, la entrada léxica correspondiente a un verbo como *corrió* sería la siguiente:
Las gramáticas están definidas en el formato XML, que organiza el léxico como un árbol de nodos. A cada ítem le corresponde un elemento con la etiqueta `<word>`, dentro del cual se insertan nuevos elementos con una etiqueta distinta para cada rasgo: la etiqueta `<phon>` corresponde a los rasgos fonéticos, `<syn>` a los sintácticos, y `<sem>` a los semánticos (aunque estos últimos no son utilizados en la implementación actual). Por ejemplo, la entrada léxica correspondiente a un verbo como *llegó* sería la siguiente:

```
<word>
<phon>llegó</phon>
<syn>
<cat>V</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>comió</phon>
<syn>
<cat>V</cat>
<sel>D</sel>
<sel>D/</sel>
</syn>
<sem>none</sem>
</word>
```
Los rasgos sintácticos se subdividen en rasgos categoriales (`Cat_Feature`) y de selección (`Trigger_Feature`). Los primeros se insertan dentro de la etiqueta `<syn>`; y los segundos, dentro de `<sel>`. <br>
#### Merge interno
Los rasgos de selección pueden ir acompañados de una **barra al final** (`D/`). Este operador le indica a la gramática que el ítem léxico en cuestión se somete a merge interno junto a otro ítem de la categoría declarada (en este caso, *llegó* primero se combina mediante merge externo con un determinante, y luego se combina con este determinante mediante merge interno, lo que en la práctica supone que el D se "mueva" o más bien se copie en la posición de especificador del SV). Este operador hace que el merge interno sólo pueda efectuarse con ciertos ítems léxicos, y una vez que los demás rasgos de selección ya fueron cotejados. Fue necesario añadir esta restricción, que no aparece en la implementación original, con el fin de subsanar el hecho de que los rasgos de selección (y todos los rasgos) constituyen un conjunto, y por lo tanto no están ordenados.
#### Categorías funcionales
Para indicar que un item léxico es una categoría funcional se necesitan dos cosas: 1) el contenido del rasgo fonético debe aparecer entre corchetes, y 2) la categoría del primer elemento con el que se combina debe estar precedida por una barra. La **barra al comienzo** (`/V`) permite que el algoritmo sepa en qué momento de la derivación debe seleccionarse la categoría funcional. Por ejemplo, así quedaría la entrada léxica de un *v* que se pudiera combinar con *llegó*:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Para indicar que un item léxico es una categoría funcional se necesitan dos cosas: 1) el contenido del rasgo fonético debe aparecer entre corchetes, y 2) la categoría del primer elemento con el que se combina debe estar precedida por una barra. La **barra al comienzo** (`/V`) permite que el algoritmo sepa en qué momento de la derivación debe seleccionarse la categoría funcional. Por ejemplo, así quedaría la entrada léxica de un *v* que se pudiera combinar con *llegó*:
Para indicar que un ítem léxico es una categoría funcional se necesitan dos cosas: 1) el contenido del rasgo fonético debe aparecer entre corchetes, y 2) la categoría del primer elemento con el que se combina debe estar precedida por una barra. La **barra al comienzo** (`/V`) permite que el algoritmo sepa en qué momento de la derivación debe seleccionarse la categoría funcional. Por ejemplo, así quedaría la entrada léxica de un *v* que se pudiera combinar con *llegó*:

```
<word>
<phon>[]</phon>
<syn>
<cat>v</cat>
<sel>/V</sel>
<sel>D/</sel>
</syn>
<sem>none</sem>
</word>
```
Dada esta gramática, una oración como *El perro llegó* pasaría por las siguientes etapas: una vez satisfechos los rasgos de selección del *V*, el *v* es seleccionado, luego se combina por merge externo con el *V*, y finalmente se combina por merge interno con el *D*, dando lugar a la siguiente estructura:

![](https://img001.prntscr.com/file/img001/YnnsxD8ASmy8ea0zR2ilIQ.png)

Como se ve, es posible definir una gramática de tal modo que dos o más categorías funcionales se combinen entre sí.
<br>También es posible declarar dos ítems con los mismos rasgos fonéticos y categoriales, pero diferentes rasgos de selección. En este caso, el programa generará dos lexical arrays distintos, e imprimirá todas las derivaciones exitosas.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<br>También es posible declarar dos ítems con los mismos rasgos fonéticos y categoriales, pero diferentes rasgos de selección. En este caso, el programa generará dos lexical arrays distintos, e imprimirá todas las derivaciones exitosas.
<br>También es posible declarar dos ítems con los mismos rasgos fonéticos y categoriales, pero diferentes rasgos de selección. En este caso, el programa generará dos *lexical arrays* distintos, e imprimirá todas las derivaciones exitosas.

### Implementación
#### Reglas
El programa utiliza un algoritmo bottom-up que se basa en las siguientes reglas (utilizamos el nombre de las variables tal como aparecen en la función `autotf()` del módulo `derivations/parser`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
El programa utiliza un algoritmo bottom-up que se basa en las siguientes reglas (utilizamos el nombre de las variables tal como aparecen en la función `autotf()` del módulo `derivations/parser`.
El programa utiliza un algoritmo *bottom-up* que se basa en las siguientes reglas (utilizamos el nombre de las variables tal como aparecen en la función `autotf()` del módulo `derivations/parser`.


| N° | If len(x.triggers) | & len(workspace.w) | & len(lexical_array.the_list) | then:
| ------------- |:-------------:| -------- | --------- | ------- |
| 0 | | | | select(x)
| 1 | 0 | 1 | 0 | *success*

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No terminamos de entender esta tabla, si hay una diferencia entre el uso de los iguales y los casos en que no hay un igual.

| 2| = 1 (con /) | = 1 | | *internal* merge(x,y)
| 3| | = 1 | > 0 | select(y)
| 4| 0 | = 2 | > 0 | select(z)
| 5| = 0 | = 2 & len(y.triggers) > 0 | | merge(y,x)
| 6| = 1 | = 2 | | merge(x,y)
| 7| = 1 | = 3 | | merge(z,y)

La numeración de las reglas indica precedencia en cuanto a su aplicación. *x* es el elemento a analizar en cada etapa de la derivación, mientras que *y* es un segundo elemento que puede pertenecer al lexical array (en la regla 2, *y* es el elemento con el índice inmediatamente superior a *x*, salvo cuando se trata de una categoría funcional) o al workspace, e incluso estar contenido en *x* (en el caso del merge interno). El primer valor que toma *x* es el *lexical item token* correspondiente a la última palabra de la oración (i.e., que coincide con sus rasgos fonéticos), el cual aparece indexado en el *lexical array* con el número 0 (`x.idx = 0`).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Esta explicación no se termina de entender bien. Faltaría además explicar qué es la variable z.

La derivación falla cuando su último estado no coincide con ninguna de las posibilidades ilustradas en la tabla, o cuando falla el merge (si el rasgo de selección de *x* no coincide con el de *y*, o si coincide pero *y* tiene rasgos de selección todavía sin satisfacer).

#### Transfer
La operación Transfer, tal como se encuentra definida en el trabajo de Collins-Stabler, interviene en el pasaje entre la estructura sintáctica y las formas fonética (Transfer<sub>PF</sub>) y semántica (Transfer<sub>LF</sub>). Nuestro programa implementa una versión simplificada de Transfer<sub>PF</sub>, que se aplica a toda derivación exitosa mediante la función recursiva `transfer()`. Este algoritmo opera de la siguiente manera:

* Si *x* e *y* son ítems léxicos (i.e., objetos sintácticos simples), se añaden a la lista `transferred_sentence` sus respectivos rasgos `Phon`, en este orden: primero el elemento con rasgos de selección (es decir, el núcleo) y luego el elemento seleccionado por aquél (que será el complemento).
* Si *x* es núcleo pero, al mismo tiempo, un conjunto de objetos sintácticos (i.e., un objeto sintáctico complejo), entonces se añade a la lista en primer lugar el rasgo `Phon` de *y* (especificador), en caso de que éste sea un item léxico, y luego se aplica nuevamente `transfer()` sobre *x*. En cambio, si *y* también es un objeto complejo, entonces se aplica `transfer()` primeramente a *y*, y luego a *x*.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e. es un latinismo crudo, así que técnicamente debería ir por normativa en itálicas. No es, de todos modos, una normativa muy extendida, así que queda a tu criterio. La normativa que abolió la tilde de "este" en todos sus usos sí está bastante aceptada, así que eso sugeriría cambiarlo.


Mediante estas reglas el programa obtiene la forma lineal de la estructura sintáctica generada, y luego evalúa si coincide con la de la oración introducida por el usuario. En caso afirmativo, la derivación es exitosa.

#### Categorías funcionales
Las categorías funcionales se añaden mediante la función `add_functional_categories()`. Sencillamente, aquí el algoritmo revisa la lista de ítems y evalúa si para cada elemento (sea funcional o léxico) existe una categoría funcional que lo seleccione. En caso afirmativo, se añade en último lugar a la lista con la que se elaborará el *lexical array*.
#### Manejo de ítems duplicados
Cuando dos o más entradas léxicas coinciden en sus rasgos fonéticos y categoriales, la función `get_possible_lexicons()` genera todas las combinaciones posibles de ítems, de tal modo que en cada combinación no haya más que un ítem con dichos rasgos. Estas listas son recogidas luego por la función `parse()`, que produce tantas derivaciones como listas haya. Finalmente se imprimen todas las derivaciones exitosas. En `data/lexicon.xml` hay dos `v` con distintos rasgos, uno para la oración inacusativa (con merge interno) y otro para las oraciones transitiva e inergativa.

### Problemas conocidos
La mayoría de los escollos que presenta este parser se deben a que utiliza la forma fonética (de la oración-input) para reconstruir la estructura sintáctica: un camino inverso al que proponen las gramáticas generativas. Y si bien la implementación de *transfer* subsana desde el punto de vista teórico esta limitación, lo cierto es que la estructura sintáctica se mantiene atada a la linealidad de la frase, en la medida en que los dos primeros elementos (empezando desde la derecha) siempre intentarán combinarse entre sí, o a lo sumo se seleccionará un tercero (regla 4). Esto vuelve imposible el reconocimiento de -por ejemplo- oraciones interrogativas o focalizadas donde el elemento sintáctico de la derecha (el primero en combinarse) se realiza luego en el margen izquierdo de la oración. Y asimismo dificulta el análisis de oraciones ditransitivas (como *el perro entregó el hueso al dueño*, en las que el OD ocuparía la posición de especificador y el OI, la de complemento. En nuestra implementación, en cambio, estas posiciones aparecen invertidas, debido al orden en que se da el merge.

![](https://img001.prntscr.com/file/img001/yzdTEc4TQW-G-MTzhEvQsQ.png)

Nótese que `12,V` es un objeto complejo, y que por lo tanto en `13,V`, `10,P` es especificador. Esto supone que la oración generada por `transfer()` será *el perro al dueño entregó el hueso*. A su vez, un merge interno entre `12,V` y `13,V` resulta imposible, ya que el primer objeto tiene rasgos de selección sin satisfacer. El objeto `14,V` sí podría combinarse con `13,V`, pero sólo después del merge externo con `15,D`, por lo que el sintagma verbal quedaría por encima del argumento externo. De todos modos, un Lexicon con rasgos de selección y/o categorías funcionales distintas podría llegar a dar cuenta de esta oración sin necesidad de modificar el código.

### A futuro
Elegimos el parser bottom-up porque es el que mejor se adapta a la implementación y el formalismo originales. Tal vez sería posible mejorarlo mediante la adición de nuevos operadores (como una o varias categorías iniciales), y permitiendo que se combinen elementos independientemente del orden lineal.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Elegimos el parser bottom-up porque es el que mejor se adapta a la implementación y el formalismo originales. Tal vez sería posible mejorarlo mediante la adición de nuevos operadores (como una o varias categorías iniciales), y permitiendo que se combinen elementos independientemente del orden lineal.
Elegimos el parser *bottom-up* porque es el que mejor se adapta a la implementación y el formalismo originales. Tal vez sería posible mejorarlo mediante la adición de nuevos operadores (como una o varias categorías iniciales), y permitiendo que se combinen elementos independientemente del orden lineal.


Otra alternativa sería recurrir a un parser top-down capaz de generar todas las oraciones posibles de una gramática, y luego evaluar si la oración ingresada por el usuario coincide con alguna de ellas. Para esto, podríamos seguir el mecanismo descrito por [Shieber et al. (2005)](https://arxiv.org/abs/cmp-lg/9404008):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Otra alternativa sería recurrir a un parser top-down capaz de generar todas las oraciones posibles de una gramática, y luego evaluar si la oración ingresada por el usuario coincide con alguna de ellas. Para esto, podríamos seguir el mecanismo descrito por [Shieber et al. (2005)](https://arxiv.org/abs/cmp-lg/9404008):
Otra alternativa sería recurrir a un parser *top-down* capaz de generar todas las oraciones posibles de una gramática, y luego evaluar si la oración ingresada por el usuario coincide con alguna de ellas. Para esto, podríamos seguir el mecanismo descrito por [Shieber et al. (2005)](https://arxiv.org/abs/cmp-lg/9404008):

1. Initialize the chart to the empty set of items and the agenda to the axioms of the deduction system.
2. Repeat the following steps until the agenda is exhausted:
* a) Select an item from the agenda, called the trigger item, and remove it.
* b) Add the trigger item to the chart, if the item is not already in the chart.
* c) If the trigger item was added to the chart, generate all items that can be derived from the trigger item and any items in the chart by one application of a rule of inference, and add these generated items to the agenda.
3. If a goal item is in the chart, the goal is proved, i.e., the string is recognized, otherwise it is not.

Queda por ver cuán compatible sería esta solución con la propuesta de Collins-Stabler.
87 changes: 80 additions & 7 deletions data/lexicon.xml
Original file line number Diff line number Diff line change
@@ -1,34 +1,107 @@
<?xml version='1.0' ?>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Si querés hacerle la PR a Warstadt, correspondería que no pises tu lexicon con el de él. Quizás conviene que llames lexicon_en al de él y lexicon_es al tuyo y que dejes como versión por defecto el de él en lugar del tuyo.

<root>
<word>
<phon>K8</phon>
<phon>corrió</phon>
<syn>
<cat>N</cat>
<cat>V</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>runs</phon>
<phon>comió</phon>
<syn>
<cat>V</cat>
<sel>N</sel>
<sel>D</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>llegó</phon>
<syn>
<cat>V</cat>
<sel>D</sel>
<sel>D/</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>ate</phon>
<phon>entregó</phon>
<syn>
<cat>V</cat>
<sel>N</sel>
<sel>D</sel>
<sel>P</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>hueso</phon>
<syn>
<cat>N</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>el</phon>
<syn>
<cat>D</cat>
<sel>N</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>apples</phon>
<phon>al</phon>
<syn>
<cat>P</cat>
<sel>N</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>perro</phon>
<syn>
<cat>N</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>dueño</phon>
<syn>
<cat>N</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>[]</phon>
<syn>
<cat>v</cat>
<sel>/V</sel>
<sel>D</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>[]</phon>
<syn>
<cat>v</cat>
<sel>/V</sel>
<sel>D/</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>[]</phon>
<syn>
<cat>T</cat>
<sel>/v</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>[]</phon>
<syn>
<cat>C</cat>
<sel>/T</sel>
</syn>
<sem>none</sem>
</word>
</root>
107 changes: 107 additions & 0 deletions data/lexicon_en.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?xml version='1.0' ?>
<root>
<word>
<phon>run</phon>
<syn>
<cat>V</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>ate</phon>
<syn>
<cat>V</cat>
<sel>D</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>arrived</phon>
<syn>
<cat>V</cat>
<sel>D</sel>
<sel>D/</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>gave</phon>
<syn>
<cat>V</cat>
<sel>D</sel>
<sel>P</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>bone</phon>
<syn>
<cat>N</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>the</phon>
<syn>
<cat>D</cat>
<sel>N</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>to</phon>
<syn>
<cat>P</cat>
<sel>D</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>dog</phon>
<syn>
<cat>N</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>owner</phon>
<syn>
<cat>N</cat>
</syn>
<sem>none</sem>
</word>
<word>
<phon>[]</phon>
<syn>
<cat>v</cat>
<sel>/V</sel>
<sel>D</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>[]</phon>
<syn>
<cat>v</cat>
<sel>/V</sel>
<sel>D/</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>[]</phon>
<syn>
<cat>T</cat>
<sel>/v</sel>
</syn>
<sem>none</sem>
</word>
<word>
<phon>[]</phon>
<syn>
<cat>C</cat>
<sel>/T</sel>
</syn>
<sem>none</sem>
</word>
</root>
5 changes: 3 additions & 2 deletions derivations/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__all__ = ["Derivation"]
__all__ = ["Derivation","parse","phrase_to_list","word_to_lex"]

from .derivation import *
from .derivation import *

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tanto derivation como parser tiene una clase llamada Derivation. Deberías llamarlas de manera distinta para saber cuál estás incluyendo en el __all__.
PS: O, más bien, de ser posible, podrías modificar la clase Derivation original y agregarle la funcionalidad que desarrollaste.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mi idea acá era extender la clase Derivation en el módulo parser, para no tocar el archivo original (cosa que igual terminé haciendo). Por eso al "redefinirla", ponía: class Derivation(derivation.Derivation):. Pero puede que la haya duplicado sin querer, la verdad es que no encontré información muy clara sobre esto. Gracias

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claro. Acá hay varias cosas. Voy por partes y lo podemos ir charlando de todas formas:

  1. ¿Por qué no querías tocar el archivo original? Si vos estás de acuerdo con que exista una clase llamada Derivation y que esa clase tenga determinados métodos y atributos, lo lógico sería que, al ir desarrollando nueva funcionalidad (lo que vos hiciste), vayas expandiendo los métodos de esa clase, pero no duplicándola.
  2. Al definir una nueva clase Derivation que hereda de la primera clase, estás generando una nueva clase que tiene todos los atributos de la primera más los que vos sumaste. En tanto estás usando el mismo nombre es casi como si la redefinieras. Pero no es exactamente eso. O sea, si yo importo la clase Derivation de derivation.py voy a tener la clase original sin ampliar. Si la importo desde parser.py voy a tener la clase ampliada. La pregunta es ¿por qué no tener una única clase que tenga todo? Y, si te fuera de interés que el usuario pueda distinguir entre la clase amppliada y la original, consideraría cambiarle el nombre. De todos modos, recordá que las definiciones de clases también tienen que tener cierto sentido lógico desde la atribución de responsabilidades. Si tenés dudas de esto, decime. Por ahí podemos charlar 15 minutos y queda más claro.
  3. Si bien sería un poco raro, podría ser que tengas dos clases llamadas Derivation en archivos distintos de tu código. El problema acá es que vos estás importando todo lo que hay en el archivo parser.py y todo lo que hay en el archivo derivation.py. Y después, en __all__ le indicás que seleccione Derivation: ¿a qué clase Derivation te referís? ¿a la que está en el primero o en el segundo archivo?

from .parser import *
Loading