package translation.tag_parser;
import java.util.HashSet;
import java.util.Set;
import translation.trees.ElementaryTree;
import translation.trees.GornAddress;
public class State {
private Set<Item> items = new HashSet<Item>();
private Set<ElementaryTree> sourceTrees;
private boolean finalState;
private boolean acceptingState;
public State () {
sourceTrees = new HashSet<ElementaryTree>();
}
public State (Set<ElementaryTree> sourceTrees) {
this.sourceTrees = sourceTrees;
finalState = false;
acceptingState = false;
}
public void buildInitialItems() {
for (ElementaryTree tree : sourceTrees)
if (tree.getRootCat().equals("S")) {
Item it = new Item(
tree,
new GornAddress(), //dot=0. Pas tree.getRootAddress()!
DotPos.LEFT_ABOVE,
0);
items.add(it);
}
}
/*
* Cette méthode remplace la règle scan, elle n'est pas
* utilisée par processState mais par parse.
* Elle cherche cherche les items de l'état précédent
* dont le point est en haut à gauche d'un noeud lexical
* et construit des items identiques à cela près que leur
* point est à droite, pour les mettre dans le nouvel état.
* Si aucun mot n'est reconnu, on informe qu'il faut arrêter
* l'analyse.
*/
public boolean buildFromState(State prevState, String wordRead) {
Set<Item> prevItems = prevState.getItems();
boolean wordRecognized = false;
for (Item it : prevItems) {
if (it.dotAtLexNode()
&& it.getPos() == DotPos.LEFT_ABOVE
&& it.getWordAtDottedNode().equals(wordRead)) {
Item newItem = it.clone();
newItem.setPos(DotPos.RIGHT_ABOVE);
items.add(newItem);
wordRecognized = true;
}
}
return wordRecognized;
}
/*
* Pour le moment il n'y a pas d'adjonctions.
*
* Pour tout item de l'état, regarde si les "gardes" sont vraies,
* si oui on lance la règle dont ce sont les gardes et on ajoute
* à la liste des items les items qu'elle calcule et retourne.
*
* Quand aucune règle n'a été appliquée au dernier tour,
* on s'arrête, tous les items de l'état ont été calculés.
*
* Certaines règles renvoie un seul item, d'autres une liste.
*
* Ne pas mettre des else if là où il y a de simples if
* (car sur certains items on peut appliquer plusieurs
* règles différentes), ni l'inverse pour les règles
* moveDown, moveRight et moveUp, dont certaines ne doivent
* être appliquée que si certaines autres ne le sont pas.
*/
public void processState(int stateNum) {
// items sur lesquels on essaie d'appliquer les règles
Set<Item> currentItems = new HashSet<Item>();
currentItems = items;
// nouveaux items générés en appliquant les règles
Set<Item> newItems = new HashSet<Item>();
boolean ruleApplied;
do {
ruleApplied = false;
System.out.println("\ncurrentItems = " + currentItems.toString());
for (Item it : currentItems) {
// La présence dans l'état final d'un item
// correspondant à une acceptation potentielle
// provoque effectivement l'acceptation.
if (isFinalState())
if (it.potentialAcceptationItem()) {
acceptingState = true;
break;
}
if (it.canMoveDown()) {
Item newItem = it.moveDown();
if (newItem != null)
System.out.println("moveDown from " + it.toString());
addItem(newItem, newItems);
}
else if (it.canMoveRight()) {
Item newItem = it.moveRight();
if (newItem != null)
System.out.println("moveRight from " + it.toString());
addItem(newItem, newItems);
}
else if (it.canMoveUp()) {
Item newItem = it.moveUp();
if (newItem != null)
System.out.println("moveUp from " + it.toString());
addItem(newItem, newItems);
}
else if (it.canPredictSubst()) {
Set<Item> newItemsSet =
it.predictSubstituable(sourceTrees, stateNum);
if (! newItemsSet.isEmpty())
System.out.println("predictLeftSubst from " + it.toString());
addItems(newItemsSet, newItems);
}
else if (it.canCompleteSubst()) {
Set<Item> newItemsSet = it.completeSubstitution();
if (! newItemsSet.isEmpty())
System.out.println("completeSubst from " + it.toString());
addItems(newItemsSet, newItems);
}
if (it.canPredictLeftAdj()) {
Set<Item> newItemsSet =
it.predictLeftAdjoinable(sourceTrees, stateNum);
if (! newItemsSet.isEmpty())
System.out.println("predictLeftAdj from " + it.toString());
addItems(newItemsSet, newItems);
}
if (it.canExploreUnderFoot()) {
Set<Item> newItemsSet = it.exploreUnderFoot();
if (! newItemsSet.isEmpty())
System.out.println("exploreUnderFoot from " + it.toString());
addItems(newItemsSet, newItems);
}
if (it.canResumeAdj()) {
Item newItem = it.resumeAdj();
if (newItem != null)
System.out.println("ResumeAdj from " + it.toString());
addItem(newItem, newItems);
}
if (it.canPredictNoLeftAdjToComplete()) {
Item newItem = it.predictNoLeftAdjToComplete();
if (newItem != null)
System.out.println("predictNoLeftAdjToComplete from " + it.toString());
addItem(newItem, newItems);
}
if (it.canCompleteLeftAdj()) {
Item newItem = it.completeLeftAdjunction();
if (newItem != null)
System.out.println("CompleteLeftAdj from " + it.toString());
addItem(newItem, newItems);
}
if (it.canPredictRightAdj()) {
Set<Item> newItemsSet =
it.predictRightAdjoinable(sourceTrees, stateNum);
if (! newItemsSet.isEmpty())
System.out.println("PredictAdjRight from " + it.toString());
addItems(newItemsSet, newItems);
}
if (it.canCompleteRightAdj()) {
Item newItem = it.completeRightAdjunction();
if (newItem != null)
System.out.println("CompleteRightAdj from " + it.toString());
addItem(newItem, newItems);
}
}
if (isFinalState() && isAcceptingState())
break;
/*
* Quand on a fini avec les currentItems,
* on ne recommence pas à chercher à appliquer
* les règles dessus, mais on passe aux nouveaux
* items trouvés à partie d'eux.
*/
if (! newItems.isEmpty()) {
ruleApplied = true;
items.addAll(newItems);
currentItems = new HashSet<Item>();
for (Item newItem : newItems)
currentItems.add(newItem);
newItems = new HashSet<Item>();
}
} while (ruleApplied);
}
/*
* Ajoute un nouvel item à newItems s'il n'y
* en n'a pas d'égal déjà dedans. Le contenu
* de currentItems est déjà dans items donc pas
* la peine de faire une autre boucle pour vérifier
* que le nouvel item n'est pas dans currentItems.
*/
public void addItem(Item newItem, Set<Item> newItems) {
boolean alreadyAdded = false;
for (Item item : newItems)
if (newItem.equals(item)) {
alreadyAdded = true;
break;
}
for (Item item : this.items)
if (newItem.equals(item)) {
alreadyAdded = true;
break;
}
if (! alreadyAdded)
newItems.add(newItem);
}
/*
* Ajoute à newItems les éléments de itemsSet
* qui ne sont pas déjà dans items ou dans newItems.
*/
public void addItems(Set<Item> itemsSet, Set<Item> newItems) {
boolean alreadyAdded = false;
if (! itemsSet.isEmpty()) {
for (Item newItem : itemsSet) {
alreadyAdded = false;
for (Item item : items)
if (newItem.equals(item)) {
alreadyAdded = true;
break;
}
if (alreadyAdded)
continue;
for (Item item : newItems)
if (newItem.equals(item)) {
alreadyAdded = true;
break;
}
if (! alreadyAdded)
newItems.add(newItem);
}
}
}
public Set<Item> getItems() {
return items;
}
public void setFinalState(boolean finalState) {
this.finalState = finalState;
}
public boolean isFinalState() {
return finalState;
}
public boolean isAcceptingState() {
return acceptingState;
}
}