[SCM] Lisaac eclipse plugin branch, master, updated. d4c84b7fca3d50fce0cac8f2602a7becd6faa910

Damien Bouvarel dams.bouvarel at wanadoo.fr
Thu Apr 16 12:17:46 UTC 2009


The following commit has been merged in the master branch:
commit d4c84b7fca3d50fce0cac8f2602a7becd6faa910
Author: Damien Bouvarel <dams.bouvarel at wanadoo.fr>
Date:   Thu Apr 16 13:57:43 2009 +0200

    "put to to" bug OK  + slot hyperlink + slot hover

diff --git a/src/org/eclipse/lisaac/editors/LisaacCompletionProcessor.java b/src/org/eclipse/lisaac/editors/LisaacCompletionProcessor.java
index 036e35b..2f99d6d 100644
--- a/src/org/eclipse/lisaac/editors/LisaacCompletionProcessor.java
+++ b/src/org/eclipse/lisaac/editors/LisaacCompletionProcessor.java
@@ -6,7 +6,6 @@ import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.contentassist.CompletionProposal;
 import org.eclipse.jface.text.contentassist.ICompletionProposal;
 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
 import org.eclipse.jface.text.contentassist.IContextInformation;
@@ -39,8 +38,6 @@ public class LisaacCompletionProcessor implements IContentAssistProcessor {
 				result.add(props[t]);
 			}
 			
-			String prefix = lastWord(document, offset);
-
 
 			return (ICompletionProposal[]) result.toArray(new ICompletionProposal[result.size()]);
 		} catch (Exception e) {
@@ -80,7 +77,7 @@ public class LisaacCompletionProcessor implements IContentAssistProcessor {
 				//
 				String contents = document.get(pos+1, baseOffset-1 - pos);
 
-				LisaacCompletionParser parser = new LisaacCompletionParser(contents);
+				LisaacCompletionParser parser = new LisaacCompletionParser(contents, null);
 				parser.parseCompletions(pos+1, baseOffset, proposals);
 			}
 		} catch (BadLocationException e) {
@@ -90,21 +87,6 @@ public class LisaacCompletionProcessor implements IContentAssistProcessor {
 		}
 	}
 
-	
-
-	private String lastWord(IDocument doc, int offset) {
-		try {
-			for (int n = offset-1; n >= 0; n--) {
-				char c = doc.getChar(n);
-				if (!Character.isJavaIdentifierPart(c))
-					return doc.get(n + 1, offset-n-1);
-			}
-		} catch (BadLocationException e) {
-			// ... log the exception ...
-		}
-		return "";
-	}
-
 
 	public IContextInformation[] computeContextInformation(ITextViewer viewer,
 			int offset) {
diff --git a/src/org/eclipse/lisaac/editors/LisaacConfiguration.java b/src/org/eclipse/lisaac/editors/LisaacConfiguration.java
index 61372eb..205b4ba 100644
--- a/src/org/eclipse/lisaac/editors/LisaacConfiguration.java
+++ b/src/org/eclipse/lisaac/editors/LisaacConfiguration.java
@@ -84,7 +84,7 @@ public class LisaacConfiguration extends SourceViewerConfiguration {
 			IProject project = editor.getProject();
 	
 			LisaacModel model = LisaacModel.getModel(project);
-			textHover = new LisaacTextHover(model);
+			textHover = new LisaacTextHover(model, editor.getFileName());
 		}
 		return textHover;
 	}
diff --git a/src/org/eclipse/lisaac/editors/LisaacScanner.java b/src/org/eclipse/lisaac/editors/LisaacScanner.java
index 39c66ea..705dcee 100644
--- a/src/org/eclipse/lisaac/editors/LisaacScanner.java
+++ b/src/org/eclipse/lisaac/editors/LisaacScanner.java
@@ -320,6 +320,10 @@ public class LisaacScanner extends RuleBasedScanner {
 	public static boolean isPrototypeIdentifier(String word) {
 		return detectKeyword(word, new LisaacPrototypeDetector());
 	}
+	
+	public static boolean isIdentifier(String word) {
+		return detectKeyword(word, new LisaacWordDetector());
+	}
 
 	private static boolean detectKeyword(String word, IWordDetector detector) {
 		int i = 0;
diff --git a/src/org/eclipse/lisaac/editors/LisaacTextHover.java b/src/org/eclipse/lisaac/editors/LisaacTextHover.java
index 9e8d0c4..0cd7d85 100644
--- a/src/org/eclipse/lisaac/editors/LisaacTextHover.java
+++ b/src/org/eclipse/lisaac/editors/LisaacTextHover.java
@@ -15,16 +15,18 @@ import org.eclipse.jface.text.Region;
 import org.eclipse.lisaac.model.LisaacCompletionParser;
 import org.eclipse.lisaac.model.LisaacModel;
 import org.eclipse.lisaac.model.items.Prototype;
+import org.eclipse.lisaac.model.items.Slot;
 import org.eclipse.swt.widgets.Shell;
 
 public class LisaacTextHover implements ITextHover, ITextHoverExtension {
 
 	protected LisaacModel model;
-	
-	
-	public LisaacTextHover(LisaacModel model) {
+	protected String filename;
+
+	public LisaacTextHover(LisaacModel model, String filename) {
 		super();
 		this.model = model;
+		this.filename = filename;
 	}
 
 	public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
@@ -32,11 +34,21 @@ public class LisaacTextHover implements ITextHover, ITextHoverExtension {
 			String text = textViewer.getDocument().get(hoverRegion.getOffset(), hoverRegion.getLength());
 			if (LisaacScanner.isPrototypeIdentifier(text)) {
 				// get prototype info
-			
+
 				Prototype prototype = LisaacCompletionParser.findPrototype(text, model);
 				if (prototype != null) {
 					return "<I>Prototype : </I> "+prototype.getHoverInformation();
 				}
+			} else if (LisaacScanner.isIdentifier(text)) {
+				// get slot info
+
+				Prototype prototype = model.getPrototype(LisaacModel.extractPrototypeName(filename));
+				if (prototype != null) {
+					Slot slot = prototype.getSlotFromKeyword(text, prototype.openParser(), hoverRegion.getOffset());
+					if (slot != null) {
+						return "<I>Slot : </I> "+slot.getHoverInformation();
+					}
+				}
 			}
 		} catch (BadLocationException e) {
 		} catch (CoreException e) {
@@ -55,16 +67,16 @@ public class LisaacTextHover implements ITextHover, ITextHoverExtension {
 
 
 	/*
-     * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
-     */
-    public IInformationControlCreator getHoverControlCreator() {
-        return new IInformationControlCreator() {
-            public IInformationControl createInformationControl(Shell parent) {
-                return new DefaultInformationControl(parent, "", new HTMLTextPresenter());
-            }
-        };
-    }
-	
+	 * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
+	 */
+	public IInformationControlCreator getHoverControlCreator() {
+		return new IInformationControlCreator() {
+			public IInformationControl createInformationControl(Shell parent) {
+				return new DefaultInformationControl(parent, "", new HTMLTextPresenter());
+			}
+		};
+	}
+
 	protected IRegion selectWord(IDocument doc, int caretPos) throws BadLocationException {
 		int startPos, endPos;
 
diff --git a/src/org/eclipse/lisaac/editors/LisaacWordRule.java b/src/org/eclipse/lisaac/editors/LisaacWordRule.java
index baadd77..08da2b4 100644
--- a/src/org/eclipse/lisaac/editors/LisaacWordRule.java
+++ b/src/org/eclipse/lisaac/editors/LisaacWordRule.java
@@ -1,5 +1,6 @@
 package org.eclipse.lisaac.editors;
 
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jface.text.rules.ICharacterScanner;
 import org.eclipse.jface.text.rules.IToken;
 import org.eclipse.jface.text.rules.IWordDetector;
@@ -35,10 +36,21 @@ public class LisaacWordRule extends WordRule {
 			}
 			//
 			int offset = ((LisaacScanner) scanner).getOffset();
+			String word = fBuffer.toString();
+			
+			try {
+				Slot slot = prototype.getSlotFromKeyword(word, prototype.openParser(), offset-word.length());
+				if (slot != null) {
+					return result;
+				}
+			} catch (CoreException e) {
+				e.printStackTrace();
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
 			
 			Slot slot = prototype.getSlot(offset);
 			if (slot != null) {
-				String word = fBuffer.toString();
 				
 				// is current word a slot argument?
 				if (slot.hasArgument(word)) {
diff --git a/src/org/eclipse/lisaac/editors/PrototypeHyperLink.java b/src/org/eclipse/lisaac/editors/PrototypeHyperLink.java
index 19766e1..af1080f 100644
--- a/src/org/eclipse/lisaac/editors/PrototypeHyperLink.java
+++ b/src/org/eclipse/lisaac/editors/PrototypeHyperLink.java
@@ -12,6 +12,8 @@ import org.eclipse.jface.text.hyperlink.IHyperlink;
 import org.eclipse.lisaac.LisaacPlugin;
 import org.eclipse.lisaac.model.LisaacModel;
 import org.eclipse.lisaac.model.items.Prototype;
+import org.eclipse.lisaac.model.items.Slot;
+import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IWorkbenchPage;
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.ui.IWorkbenchWindow;
@@ -55,23 +57,41 @@ public class PrototypeHyperLink implements IHyperlink {
 			if (part instanceof LipEditor) {
 				return;
 			}
+
 			if (project != null) {
 				String prototypePath;
 				boolean createLink=false;
-
+				Prototype prototype;
+				Slot slot = null;
+				
 				LisaacModel model = LisaacModel.getModel(project);
-				Prototype prototype = model.getPrototype(fPrototypeString);
+
+				// Slot Hyperlink
+				prototype = LisaacModel.getCurrentPrototype();
+				try {
+					slot = prototype.getSlotFromKeyword(fPrototypeString, prototype.openParser(), fRegion.getOffset());
+				} catch (CoreException e1) {
+					e1.printStackTrace();
+				}
+				if (slot != null) {
+					// slot hyperlink
+					prototype = slot.getPrototype();
+				} else {
+					// prototype hyperlink
+					prototype = model.getPrototype(fPrototypeString);
+				}
+				
 				if (prototype != null) {
 					prototypePath = prototype.getFileName();
 				} else {
 					prototypePath = model.getPathManager().getFullPath(fPrototypeString);
 					createLink = true;
 				}
-
 				if (prototypePath != null) {
 					final IProject p = project;
 					final String filename = prototypePath;
 					final boolean link = createLink;
+					final Slot selectSlot = slot;
 
 					part.getSite().getShell().getDisplay().asyncExec(new Runnable() {
 						public void run() {
@@ -98,6 +118,12 @@ public class PrototypeHyperLink implements IHyperlink {
 									file.createLink(location, IResource.NONE, null);
 								}
 								IDE.openEditor(page, file);
+								if (selectSlot != null) {
+									IWorkbenchPart part = w.getPartService().getActivePart();
+									if (part instanceof LisaacEditor) {
+										((LisaacEditor)part).selectAndReveal(selectSlot.getPosition().offset, selectSlot.getPosition().length);
+									}
+								}
 								if (link) {
 									//file.delete(true, null);
 								}
diff --git a/src/org/eclipse/lisaac/model/AbstractLisaacParser.java b/src/org/eclipse/lisaac/model/AbstractLisaacParser.java
index 5674b82..acb27fe 100644
--- a/src/org/eclipse/lisaac/model/AbstractLisaacParser.java
+++ b/src/org/eclipse/lisaac/model/AbstractLisaacParser.java
@@ -1,791 +1,795 @@
-package org.eclipse.lisaac.model;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
-
-import org.eclipse.lisaac.builder.ILisaacErrorHandler;
-
-
-public class AbstractLisaacParser {
-	
-	protected ILisaacErrorHandler reporter;
-
-	protected ILisaacModel model;
-	
-	protected String source;
-
-	protected int position;
-
-	protected int pos_cur, pos_line, pos_col;
-	protected int begin_position;
-
-	protected String string_tmp="";
-
-	
-	public Position getPosition() {
-		return getPosition(0);
-	}
-	
-	public Position getPosition(int len) {
-		Position result=null;
-
-		while (pos_cur != position) {
-			if (source.charAt(pos_cur) == '\n') {
-				pos_col = 0;
-				pos_line++;
-			} else {
-				pos_col++;
-			}
-			pos_cur++;
-		}
-		if (pos_line > 32767) {
-			result = new Position(32767, pos_col, pos_cur);
-			reporter.syntaxError ("Line counter overflow.",result);
-		}
-		if (pos_col > 255) {
-			result = new Position(pos_line, 255, pos_cur);
-			reporter.syntaxError ("Column counter overflow (line too long).",result);
-		};
-		result = new Position(pos_line, pos_col, pos_cur, len);
-		return result;
-	}
-	public String getSource() {
-		return source;
-	}
-
-	public boolean isEOF() {
-		return position > source.length()-1;
-	}
-
-
-	protected long lastInteger;
-	protected String lastReal;
-	protected String lastString;
-
-	protected static String lastComment;
-	protected boolean isCatchComment;
-	
-	protected boolean isParameterType;
-	
-	protected void setCatchComment() {
-		isCatchComment = true;
-		lastComment = "";
-	}
-	protected void setCatchCommentOff() {
-		isCatchComment = false;
-	}
-	
-	public String getLastString() {
-		return lastString;
-	}
-	
-	public char lastCharacter() {
-		if (position > source.length()-1) {
-			return 0;
-		} 
-		return source.charAt(position);
-	}
-
-	//
-	// AMBIGU Manager.
-	//
-
-	protected int old_position;
-	protected int old_pos_cur;
-	protected int old_pos_line;
-	protected int old_pos_col;
-
-	protected void saveContext() {
-		old_position = position;
-		old_pos_cur  = pos_cur;
-		old_pos_line = pos_line;
-		old_pos_col  = pos_col;
-	}
-	protected void restoreContext() {
-		position = old_position;
-		pos_cur  = old_pos_cur;
-		pos_line = old_pos_line;
-		pos_col  = old_pos_col;
-	}
-	
-	public AbstractLisaacParser(InputStream contents, ILisaacModel model) {
-		this.model = model;
-		this.reporter = model.getReporter();
-		
-		// convert the input stream into string
-		try {
-			InputStreamReader reader = new InputStreamReader (contents);
-			BufferedReader buffer = new BufferedReader(reader);
-
-			StringWriter writer = new StringWriter();
-
-			String line="";
-			do {
-				line = buffer.readLine();
-				if (line != null) {
-					writer.write(line+"\n"); 
-				}
-			} while (line != null);
-			//
-			source = writer.toString();
-			//
-		} catch (IOException e) {
-			return; // ERROR
-		}
-		initialize();
-	}
-	
-	public AbstractLisaacParser(String contents) {
-		// null reporter
-		this.reporter = new ILisaacErrorHandler() {
-			public void fatalError(String msg, Position position) {
-			}
-			public void semanticError(String msg, Position position) {
-			}
-			public void syntaxError(String msg, Position position) {
-			}
-			public void warning(String msg, Position position) {
-			}
-		};
-		source = contents;
-		initialize();
-	}
-	
-	public void initialize() {
-		position = 0;
-		pos_cur = 0;
-		pos_line = 1;
-		pos_col = 0;
-	}
-	
-	//
-	// Lisaac Parser
-	//
-
-	public boolean readSpace() {
-		int pos,posold;
-		int level_comment = 0;
-
-		pos = position;
-		posold = -1;
-		while (posold != position) {
-			posold = position;
-
-			// skip spaces
-			while ((lastCharacter() != 0) && (lastCharacter() <= ' ')) {
-				position++;
-			}
-			if (position < source.length()-1) {
-				// Skip C++ comment style :
-				if (lastCharacter() == '/' && source.charAt(position+1) == '/') {
-					position += 2;
-
-					if (isCatchComment) 
-						lastComment += "\t";
-
-					while ((lastCharacter() != 0) && (lastCharacter() != '\n')) {
-						if (isCatchComment) 
-							lastComment += lastCharacter();
-
-						lastCharacter();
-						position++;
-					}
-					if (isCatchComment) 
-						lastComment += "\n";
-				}
-			}
-			if (position < source.length()-1) {
-				// Skip C comment style :
-				if (lastCharacter() == '/' && source.charAt(position+1) == '*') {
-					position += 2;
-					level_comment++;
-
-					while (lastCharacter() != 0 && level_comment != 0) {
-						if (lastCharacter() == '/' && source.charAt(position+1) == '*') {
-							position += 2;
-							level_comment++;
-						} else if (lastCharacter() == '*' && source.charAt(position+1) == '/') {
-							position += 2;
-							level_comment--;
-						} else {
-							position++;
-						}
-					}
-					if (level_comment != 0) {
-						reporter.syntaxError("End of comment not found !", getPosition());
-					}
-				}
-			}
-		}
-		// FALSE : Last character.
-		begin_position = position;
-		return (position != pos) || (lastCharacter() != 0);
-	}
-
-	public boolean readSymbol(String st) {
-		int posold,j;
-		boolean result=false;
-
-		if (! readSpace()) {
-			result = false;
-		} else {
-			posold = position;
-			j = 0;
-			while (lastCharacter() != 0 && (j <= st.length()-1 && lastCharacter() == st.charAt(j))) {
-				position++;
-				j++;
-			}
-			if (j > st.length()-1) {
-				result = true;
-				lastString = st;
-			} else {
-				position = posold;
-				result = false;
-			}
-		}
-		return result;
-	}
-
-	public boolean readCharacter (char ch) {
-		boolean result=false;
-
-		if (! readSpace()) {
-			result = false;
-		} else {
-			if (lastCharacter() == ch) {
-				position++;
-				result = true;
-			}
-		}
-		return result;
-	}
-
-	//-- affect -> ":=" | "<-" | "?="
-	public boolean readAffect() {
-		return readSymbol(ILisaacModel.symbol_affect_immediate) ||
-		readSymbol(ILisaacModel.symbol_affect_cast) ||
-		readSymbol(ILisaacModel.symbol_affect_code);
-	}
-
-	//-- style         -> '-' | '+'
-	public char readStyle() {
-		char result;
-
-		if (readCharacter('-')) {
-			result = '-';
-		} else if (readCharacter('+')) {
-			result = '+';
-		} else {
-			result = ' ';
-		}
-		return result;
-	}
-
-	//-- identifier    -> 'a'-'z' {'a'-'z' | '0'-'9' | '_'}
-	public boolean readIdentifier() {
-		boolean result=false;
-		int posold,idx;
-
-		if (! readSpace() || !Character.isLowerCase(lastCharacter())) {
-			result = false;
-		} else {
-			posold = position;
-			string_tmp = "";
-
-			while (lastCharacter() != 0 && 
-					(Character.isLowerCase(lastCharacter()) ||
-							Character.isDigit(lastCharacter()) ||
-							lastCharacter() == '_')) {
-				string_tmp += lastCharacter();
-				position++;
-			}
-			if (string_tmp.length() > 0) {
-				idx = string_tmp.lastIndexOf("__");
-				if (idx != -1) {
-					position = posold+idx;
-					reporter.syntaxError("Identifier is incorrect.", getPosition());
-				}
-				lastString = getString(string_tmp);
-				result = true;
-			}
-		}
-		return result;
-	}
-
-	public boolean readWord(String st) {
-		int posold,idx;
-		boolean result=false;
-
-		if (! readSpace()) {
-			result = false;
-		} else {
-			posold = position;
-			idx = 0;
-
-			while (idx <= st.length()-1 && lastCharacter() == st.charAt(idx)) {
-				position++;
-				idx++;
-			}
-			if (idx > st.length()-1) {
-				lastString = st;
-				result = true;
-			} else {
-				position = posold;
-			}
-		}
-		return result;
-	}
-
-	public boolean readThisKeyword(String st) {
-		return readWord(st);
-	}
-
-	//-- keyword -> 'A'-'Z' 'a'-'z' {'a'-'z' | '0'-'9' | '_'}
-	public boolean readKeyword() {
-		boolean result=false;
-
-		if (! readSpace() || ! Character.isUpperCase(lastCharacter())) {
-			result = false;
-		} else {
-			string_tmp = "";
-			string_tmp += lastCharacter();
-			position++;
-
-			if (Character.isLowerCase(lastCharacter())) {
-				string_tmp += lastCharacter();
-				position++;				
-				while (lastCharacter() != 0 &&
-						(Character.isLowerCase(lastCharacter()) ||
-								Character.isDigit(lastCharacter()) ||
-								lastCharacter() == '_')) {
-					string_tmp += lastCharacter();
-					position++;
-				}
-				lastString = getString(string_tmp);
-				result = true;
-			} else {
-				position--;
-				result = false;
-			}
-		}
-		return result;
-	}
-
-	//-- cap_identifier -> 'A'-'Z' {'A'-'Z' | '0'-'9' | '_'}
-	public boolean readCapIdentifier() {
-		int posold,idx;
-		boolean result=false;
-		char car;
-
-		if (! readSpace() || ! Character.isUpperCase(lastCharacter())) {
-			result = false;
-		} else {
-			posold = position;
-			string_tmp = ""+lastCharacter();
-			position++;
-			isParameterType = true;
-			while (lastCharacter() != 0 && 
-					(Character.isUpperCase(lastCharacter()) ||
-							Character.isDigit(lastCharacter()) ||
-							lastCharacter() == '_')) {
-				car = lastCharacter();
-				isParameterType = isParameterType && (Character.isDigit(car));
-
-				string_tmp += car;
-				position++;
-			}
-			if (Character.isLetter(lastCharacter()) ||
-					Character.isDigit(lastCharacter()) ||
-					lastCharacter() == '_') {
-				reporter.syntaxError("Identifier is incorrect.", getPosition());
-				return false;
-			} 
-			idx = string_tmp.lastIndexOf("__");
-			if (idx != -1) {
-				position = posold + idx;
-				reporter.syntaxError("Identifier is incorrect.", getPosition());
-				return false;
-			}
-			lastString = getString(string_tmp);
-			result = true;
-		}
-		return result;
-	}
-
-	//-- integer -> number 
-	//-- number  -> {'0'-'9'} ['d'] 
-	//--          | '0'-'9' {'0'-'9' | 'A'-'F' | 'a'-'f'} 'h'
-	//--          | {'0'-'7'} 'o'
-	//--          | {'0' | '1'} 'b'
-	public boolean readInteger() {
-		boolean result=false;
-		//int pos_old;
-
-		if (readSpace() && Character.isDigit(lastCharacter())) {
-			result = true;
-			string_tmp = ""+lastCharacter();
-			//pos_old = position;
-			position++;
-
-			while (isHexadecimalDigit(lastCharacter()) || lastCharacter() == '_') {
-				if (lastCharacter() != '_') {
-					string_tmp += lastCharacter();
-				}
-				position++;
-			}
-			if (lastCharacter() == 'h') {
-				try {
-					Integer integer = Integer.valueOf(string_tmp, 16);
-					lastInteger = integer.intValue();
-				} catch (Exception e) {
-					System.out.println("Warning readInteger : "+e);// FIXME hex string
-					lastInteger = 0;
-				}
-				position++;
-			} else {
-				if (string_tmp.charAt(string_tmp.length()-1) > '9') {
-					string_tmp = string_tmp.substring(0, string_tmp.length()-1);// remove last
-					position--;
-				}
-				if (lastCharacter() == 'o') {
-					if (!isOctal(string_tmp)) {
-						reporter.syntaxError("Incorrect octal number.", getPosition());
-					}
-					lastInteger = Integer.valueOf(string_tmp, 8).intValue();
-					position++;
-				} else if (lastCharacter() == 'b') {
-					if (!isBinary(string_tmp)) {
-						reporter.syntaxError("Incorrect binary number.", getPosition());
-					}
-					lastInteger = Integer.valueOf(string_tmp, 2).intValue();
-					position++;
-				} else {
-					if (lastCharacter() == 'd') {
-						position++;
-					}
-					if (! isInteger(string_tmp)) {
-						reporter.syntaxError("Incorrect decimal number.", getPosition());
-					}
-					lastInteger = Integer.valueOf(string_tmp);
-				}
-			}
-		}
-		return result;
-	}
-
-	private boolean isInteger(String s) {
-		try {
-			Integer.parseInt(s);
-		} catch (NumberFormatException e) {
-			return false;
-		}
-		return true;
-	}
-
-	// True when the contents is a sequence of bits (i.e., mixed
-	// characters `0' and characters `1').
-	private boolean isBinary(String s) {
-		boolean result;
-		int i;
-
-		i = s.length()-1;
-		result = true;
-		while (result && i != 0) {
-			result = s.charAt(i) == '0' || s.charAt(i) == '1';
-			i--;
-		}
-		return result;
-	}
-
-	private boolean isOctal(String s) {
-		try {
-			Integer.parseInt(s, 8);
-		} catch (NumberFormatException e) {
-			return false;
-		}
-		return true;
-	}
-
-	private boolean isHexadecimalDigit(char c) {
-		boolean result=false;
-
-		if (Character.isDigit(c)) {
-			result = true;
-		} else if (c >= 'a') {
-			result = c <= 'f';
-		} else if (c >= 'A') {
-			result = c <= 'F';
-		}
-		return result;
-	}
-
-	//-- real -> '0'-'9' {'0'-'9'_} [ '.' {'0'-'9'} ] [ 'E' ['+'|'-'] '0'-'9' {'0'-'9'}
-	public boolean readReal() {
-		boolean result=false;
-		int pos_old;
-
-		if (readSpace() && Character.isDigit(lastCharacter())) {
-			string_tmp = ""+lastCharacter();
-			pos_old = position;
-			position++;
-
-			while (Character.isDigit(lastCharacter()) || lastCharacter() == '_') {
-				if (lastCharacter() != '_') {
-					string_tmp += lastCharacter();
-				}
-				position++;
-			}
-			if (lastCharacter() == '.') {
-				string_tmp += '.';
-				position++;
-
-				if (Character.isDigit(lastCharacter())) {
-					result = true;
-					string_tmp += lastCharacter();
-					position++;
-
-					while (Character.isDigit(lastCharacter())) {
-						string_tmp += lastCharacter();
-						position++;
-					}
-				}
-				if (lastCharacter() == 'E') {
-					result = true;
-					string_tmp += 'E';
-					position++;
-
-					if (lastCharacter() == '+' || lastCharacter() == '-') {
-						string_tmp += lastCharacter();
-						position++;
-					}
-					if (Character.isDigit(lastCharacter())) {
-						string_tmp += lastCharacter();
-						position++;
-						while (Character.isDigit(lastCharacter())) {
-							string_tmp += lastCharacter();
-							position++;
-						}
-					} else {
-						reporter.syntaxError("Incorrect real number.", getPosition());
-					}
-				}
-			}
-			if (result) {
-				lastReal = getString(string_tmp);
-			} else {
-				position = pos_old;
-			}
-		}
-		return result;
-	}
-
-	public void readEscapeCharacter() {
-		int val;
-
-		if (isSeparator(lastCharacter())) {
-			position++;
-			while (lastCharacter() != 0 && isSeparator(lastCharacter())) {
-				position++;
-			}
-			if (lastCharacter() == '\\') {
-				string_tmp.substring(0, string_tmp.length()-2); // remove last
-				position++;
-			} else if (lastCharacter() != 0) {
-				reporter.syntaxError("Unknown escape sequence.", getPosition());
-			}
-		} else if (lastCharacter() != 0) {
-			char c = lastCharacter();
-
-			if (c == 'a' ||
-					c == 'b' ||
-					c == 'f' ||
-					c == 'n' ||
-					c == 'r' ||
-					c == 't' ||
-					c == 'v' ||
-					c == '\\' ||
-					c == '?' ||
-					c == '\'' ||
-					c == '\"') {
-				string_tmp += c;
-				position++;
-			} else if (lastCharacter() >= '0' && lastCharacter() <= '9') {
-				if (lastCharacter() == '0' && 
-						position < source.length() &&
-						! isHexadecimalDigit(source.charAt(position+1))) {
-
-					string_tmp += lastCharacter();
-					position++;
-				} else {
-					String string_tmp2 = new String(string_tmp);
-					readInteger(); // result is Always TRUE.
-					string_tmp = string_tmp2;
-
-					if (lastInteger > 255) {
-						reporter.syntaxError("Invalid range character number [0,255].", getPosition());
-					}
-					val = (int) lastInteger;
-					string_tmp += (val / 64);
-					string_tmp += ((val % 64) / 8);
-					string_tmp += (val % 8);
-					if (lastCharacter() == '\\') {
-						position++;
-					} else {
-						reporter.syntaxError("Character '\' is needed.", getPosition());
-					}
-				}
-			} else {
-				reporter.syntaxError("Unknown escape sequence.", getPosition());
-			}
-		}
-	}
-
-	//-- character  -> '\'' ascii '\''
-	public boolean readCharacters() {
-		boolean result=false;
-		int count=0;
-
-		if (readSpace() && lastCharacter() == '\'') {
-			//old_pos = position;
-			position++;
-			string_tmp = "";
-			while (lastCharacter() != 0 && lastCharacter() != '\n' && lastCharacter() != '\'') {
-				string_tmp += lastCharacter();
-				if (lastCharacter() == '\\') {
-					position++;
-					readEscapeCharacter();
-					count++;
-				} else {
-					position++;
-					count++;
-				}
-			}
-			if (lastCharacter() == '\'') {
-				position++;
-				lastString = getString(string_tmp);
-				if (count != 1) {
-					position = begin_position;
-					reporter.syntaxError("Character constant too long.", getPosition());
-				}
-				result = true;
-			} else {
-				position = begin_position;
-				reporter.syntaxError("Unterminated character constant.", getPosition());
-			}
-		}
-		return result;
-	}
-
-	//-- string -> '\"' ascii_string '\"'
-	public boolean readString() {
-		boolean result=false;
-		//	int old_pos;
-
-		if (readSpace() && lastCharacter() == '\"') {
-			//	old_pos = position;
-			position = position+1;
-			string_tmp = "";
-			while (lastCharacter() != 0 && lastCharacter() != '\n' && lastCharacter() != '\"') {
-				string_tmp += lastCharacter();
-				if (lastCharacter() == '\\') {
-					position = position+1;
-					readEscapeCharacter();
-				} else {
-					position = position+1;
-				}
-			}
-			if (lastCharacter() == '\"') {
-				position = position+1;
-				lastString = getString(string_tmp);
-				result = true;
-			} else {
-				position = begin_position;
-				reporter.syntaxError("Unterminated string constant.", getPosition());
-			}
-		}
-		return result;
-	}
-
-	//-- external -> '`' ascii_c_code '`'
-	public boolean readExternal() {
-		boolean result=false;
-		//	int pos_old;
-
-		if ((! readSpace()) || lastCharacter() != '`') {
-			result = false;
-		} else {
-			//	pos_old=position;
-			position = position+1;
-			string_tmp = "";
-			while (lastCharacter() != 0 && lastCharacter() != '`') {
-				string_tmp += lastCharacter();
-				if (lastCharacter() == '\\') {
-					position = position+1;
-					string_tmp += lastCharacter();
-					if (lastCharacter() != 0) {
-						position = position+1;
-					}
-				} else {
-					position = position+1;
-				}
-			}
-			if (lastCharacter() != 0) {
-				position = position+1;
-				lastString = getString(string_tmp);
-				result = true;
-			} else {
-				result = false;
-			}
-		}
-		return result;
-	}
-
-	private final String operators = "!@#$%^&<|*-+=~/?\\>";
-
-	//-- operator -> '!' | '@' | '#' | '$' | '%' | '^' | '&' | '<' | '|'  
-	//--           | '*' | '-' | '+' | '=' | '~' | '/' | '?' | '\' | '>'
-	public boolean readOperator() {
-		boolean result=false;
-		//		int old_pos;
-
-		readSpace();
-		//	old_pos = position;
-		string_tmp = "";
-		while (lastCharacter() != 0 &&
-				operators.indexOf(lastCharacter()) != -1) {
-			string_tmp += lastCharacter();
-			position = position+1;
-		}
-		if (string_tmp.length() > 0) {
-			lastString = getString(string_tmp);
-			if (lastString.equals(ILisaacModel.symbol_affect_immediate) ||
-					lastString.equals(ILisaacModel.symbol_affect_code) ||
-					lastString.equals(ILisaacModel.symbol_affect_cast)) {
-				reporter.syntaxError("Incorrect operator.", getPosition());
-			}
-			result = true;
-		}
-		return result;
-	}
-
-	// True when character is a separator.
-	private boolean isSeparator(char c) {
-		return c == ' ' || c == '\t' || c == '\n' ||
-		c == '\r' || c == '\0' || c == '\f'; // || c == '\v';
-	}
-	
-	public String getString(String str) {
-		if (model == null) {
-			return str;
-		}
-		return model.getAliasString().get(str);
-	}
-
-	
-	public ILisaacErrorHandler getReporter() {
-		return reporter;
-	}
-}
+package org.eclipse.lisaac.model;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+
+import org.eclipse.lisaac.builder.ILisaacErrorHandler;
+
+
+public class AbstractLisaacParser {
+	
+	protected ILisaacErrorHandler reporter;
+
+	protected ILisaacModel model;
+	
+	protected String source;
+
+	protected int position;
+
+	protected int pos_cur, pos_line, pos_col;
+	protected int begin_position;
+
+	protected String string_tmp="";
+
+	
+	public Position getPosition() {
+		return getPosition(0);
+	}
+	
+	public Position getPosition(int len) {
+		Position result=null;
+
+		while (pos_cur != position) {
+			if (source.charAt(pos_cur) == '\n') {
+				pos_col = 0;
+				pos_line++;
+			} else {
+				pos_col++;
+			}
+			pos_cur++;
+		}
+		if (pos_line > 32767) {
+			result = new Position(32767, pos_col, pos_cur);
+			reporter.syntaxError ("Line counter overflow.",result);
+		}
+		if (pos_col > 255) {
+			result = new Position(pos_line, 255, pos_cur);
+			reporter.syntaxError ("Column counter overflow (line too long).",result);
+		};
+		result = new Position(pos_line, pos_col, pos_cur, len);
+		return result;
+	}
+	public String getSource() {
+		return source;
+	}
+
+	public boolean isEOF() {
+		return position > source.length()-1;
+	}
+
+	public void setPosition(int pos) {
+		initialize();
+		position = pos;
+	}
+
+	protected long lastInteger;
+	protected String lastReal;
+	protected String lastString;
+
+	protected static String lastComment;
+	protected boolean isCatchComment;
+	
+	protected boolean isParameterType;
+	
+	protected void setCatchComment() {
+		isCatchComment = true;
+		lastComment = "";
+	}
+	protected void setCatchCommentOff() {
+		isCatchComment = false;
+	}
+	
+	public String getLastString() {
+		return lastString;
+	}
+	
+	public char lastCharacter() {
+		if (position > source.length()-1) {
+			return 0;
+		} 
+		return source.charAt(position);
+	}
+
+	//
+	// AMBIGU Manager.
+	//
+
+	protected int old_position;
+	protected int old_pos_cur;
+	protected int old_pos_line;
+	protected int old_pos_col;
+
+	protected void saveContext() {
+		old_position = position;
+		old_pos_cur  = pos_cur;
+		old_pos_line = pos_line;
+		old_pos_col  = pos_col;
+	}
+	protected void restoreContext() {
+		position = old_position;
+		pos_cur  = old_pos_cur;
+		pos_line = old_pos_line;
+		pos_col  = old_pos_col;
+	}
+	
+	public AbstractLisaacParser(InputStream contents, ILisaacModel model) {
+		this.model = model;
+		this.reporter = model.getReporter();
+		
+		// convert the input stream into string
+		try {
+			InputStreamReader reader = new InputStreamReader (contents);
+			BufferedReader buffer = new BufferedReader(reader);
+
+			StringWriter writer = new StringWriter();
+
+			String line="";
+			do {
+				line = buffer.readLine();
+				if (line != null) {
+					writer.write(line+"\n"); 
+				}
+			} while (line != null);
+			//
+			source = writer.toString();
+			//
+		} catch (IOException e) {
+			return; // ERROR
+		}
+		initialize();
+	}
+	
+	public AbstractLisaacParser(String contents) {
+		// null reporter
+		this.reporter = new ILisaacErrorHandler() {
+			public void fatalError(String msg, Position position) {
+			}
+			public void semanticError(String msg, Position position) {
+			}
+			public void syntaxError(String msg, Position position) {
+			}
+			public void warning(String msg, Position position) {
+			}
+		};
+		source = contents;
+		initialize();
+	}
+	
+	public void initialize() {
+		position = 0;
+		pos_cur = 0;
+		pos_line = 1;
+		pos_col = 0;
+	}
+	
+	//
+	// Lisaac Parser
+	//
+
+	public boolean readSpace() {
+		int pos,posold;
+		int level_comment = 0;
+
+		pos = position;
+		posold = -1;
+		while (posold != position) {
+			posold = position;
+
+			// skip spaces
+			while ((lastCharacter() != 0) && (lastCharacter() <= ' ')) {
+				position++;
+			}
+			if (position < source.length()-1) {
+				// Skip C++ comment style :
+				if (lastCharacter() == '/' && source.charAt(position+1) == '/') {
+					position += 2;
+
+					if (isCatchComment) 
+						lastComment += "\t";
+
+					while ((lastCharacter() != 0) && (lastCharacter() != '\n')) {
+						if (isCatchComment) 
+							lastComment += lastCharacter();
+
+						lastCharacter();
+						position++;
+					}
+					if (isCatchComment) 
+						lastComment += "\n";
+				}
+			}
+			if (position < source.length()-1) {
+				// Skip C comment style :
+				if (lastCharacter() == '/' && source.charAt(position+1) == '*') {
+					position += 2;
+					level_comment++;
+
+					while (lastCharacter() != 0 && level_comment != 0) {
+						if (lastCharacter() == '/' && source.charAt(position+1) == '*') {
+							position += 2;
+							level_comment++;
+						} else if (lastCharacter() == '*' && source.charAt(position+1) == '/') {
+							position += 2;
+							level_comment--;
+						} else {
+							position++;
+						}
+					}
+					if (level_comment != 0) {
+						reporter.syntaxError("End of comment not found !", getPosition());
+					}
+				}
+			}
+		}
+		// FALSE : Last character.
+		begin_position = position;
+		return (position != pos) || (lastCharacter() != 0);
+	}
+
+	public boolean readSymbol(String st) {
+		int posold,j;
+		boolean result=false;
+
+		if (! readSpace()) {
+			result = false;
+		} else {
+			posold = position;
+			j = 0;
+			while (lastCharacter() != 0 && (j <= st.length()-1 && lastCharacter() == st.charAt(j))) {
+				position++;
+				j++;
+			}
+			if (j > st.length()-1) {
+				result = true;
+				lastString = st;
+			} else {
+				position = posold;
+				result = false;
+			}
+		}
+		return result;
+	}
+
+	public boolean readCharacter (char ch) {
+		boolean result=false;
+
+		if (! readSpace()) {
+			result = false;
+		} else {
+			if (lastCharacter() == ch) {
+				position++;
+				result = true;
+			}
+		}
+		return result;
+	}
+
+	//-- affect -> ":=" | "<-" | "?="
+	public boolean readAffect() {
+		return readSymbol(ILisaacModel.symbol_affect_immediate) ||
+		readSymbol(ILisaacModel.symbol_affect_cast) ||
+		readSymbol(ILisaacModel.symbol_affect_code);
+	}
+
+	//-- style         -> '-' | '+'
+	public char readStyle() {
+		char result;
+
+		if (readCharacter('-')) {
+			result = '-';
+		} else if (readCharacter('+')) {
+			result = '+';
+		} else {
+			result = ' ';
+		}
+		return result;
+	}
+
+	//-- identifier    -> 'a'-'z' {'a'-'z' | '0'-'9' | '_'}
+	public boolean readIdentifier() {
+		boolean result=false;
+		int posold,idx;
+
+		if (! readSpace() || !Character.isLowerCase(lastCharacter())) {
+			result = false;
+		} else {
+			posold = position;
+			string_tmp = "";
+
+			while (lastCharacter() != 0 && 
+					(Character.isLowerCase(lastCharacter()) ||
+							Character.isDigit(lastCharacter()) ||
+							lastCharacter() == '_')) {
+				string_tmp += lastCharacter();
+				position++;
+			}
+			if (string_tmp.length() > 0) {
+				idx = string_tmp.lastIndexOf("__");
+				if (idx != -1) {
+					position = posold+idx;
+					reporter.syntaxError("Identifier is incorrect.", getPosition());
+				}
+				lastString = getString(string_tmp);
+				result = true;
+			}
+		}
+		return result;
+	}
+
+	public boolean readWord(String st) {
+		int posold,idx;
+		boolean result=false;
+
+		if (! readSpace()) {
+			result = false;
+		} else {
+			posold = position;
+			idx = 0;
+
+			while (idx <= st.length()-1 && lastCharacter() == st.charAt(idx)) {
+				position++;
+				idx++;
+			}
+			if (idx > st.length()-1) {
+				lastString = st;
+				result = true;
+			} else {
+				position = posold;
+			}
+		}
+		return result;
+	}
+
+	public boolean readThisKeyword(String st) {
+		return readWord(st);
+	}
+
+	//-- keyword -> 'A'-'Z' 'a'-'z' {'a'-'z' | '0'-'9' | '_'}
+	public boolean readKeyword() {
+		boolean result=false;
+
+		if (! readSpace() || ! Character.isUpperCase(lastCharacter())) {
+			result = false;
+		} else {
+			string_tmp = "";
+			string_tmp += lastCharacter();
+			position++;
+
+			if (Character.isLowerCase(lastCharacter())) {
+				string_tmp += lastCharacter();
+				position++;				
+				while (lastCharacter() != 0 &&
+						(Character.isLowerCase(lastCharacter()) ||
+								Character.isDigit(lastCharacter()) ||
+								lastCharacter() == '_')) {
+					string_tmp += lastCharacter();
+					position++;
+				}
+				lastString = getString(string_tmp);
+				result = true;
+			} else {
+				position--;
+				result = false;
+			}
+		}
+		return result;
+	}
+
+	//-- cap_identifier -> 'A'-'Z' {'A'-'Z' | '0'-'9' | '_'}
+	public boolean readCapIdentifier() {
+		int posold,idx;
+		boolean result=false;
+		char car;
+
+		if (! readSpace() || ! Character.isUpperCase(lastCharacter())) {
+			result = false;
+		} else {
+			posold = position;
+			string_tmp = ""+lastCharacter();
+			position++;
+			isParameterType = true;
+			while (lastCharacter() != 0 && 
+					(Character.isUpperCase(lastCharacter()) ||
+							Character.isDigit(lastCharacter()) ||
+							lastCharacter() == '_')) {
+				car = lastCharacter();
+				isParameterType = isParameterType && (Character.isDigit(car));
+
+				string_tmp += car;
+				position++;
+			}
+			if (Character.isLetter(lastCharacter()) ||
+					Character.isDigit(lastCharacter()) ||
+					lastCharacter() == '_') {
+				reporter.syntaxError("Identifier is incorrect.", getPosition());
+				return false;
+			} 
+			idx = string_tmp.lastIndexOf("__");
+			if (idx != -1) {
+				position = posold + idx;
+				reporter.syntaxError("Identifier is incorrect.", getPosition());
+				return false;
+			}
+			lastString = getString(string_tmp);
+			result = true;
+		}
+		return result;
+	}
+
+	//-- integer -> number 
+	//-- number  -> {'0'-'9'} ['d'] 
+	//--          | '0'-'9' {'0'-'9' | 'A'-'F' | 'a'-'f'} 'h'
+	//--          | {'0'-'7'} 'o'
+	//--          | {'0' | '1'} 'b'
+	public boolean readInteger() {
+		boolean result=false;
+		//int pos_old;
+
+		if (readSpace() && Character.isDigit(lastCharacter())) {
+			result = true;
+			string_tmp = ""+lastCharacter();
+			//pos_old = position;
+			position++;
+
+			while (isHexadecimalDigit(lastCharacter()) || lastCharacter() == '_') {
+				if (lastCharacter() != '_') {
+					string_tmp += lastCharacter();
+				}
+				position++;
+			}
+			if (lastCharacter() == 'h') {
+				try {
+					Integer integer = Integer.valueOf(string_tmp, 16);
+					lastInteger = integer.intValue();
+				} catch (Exception e) {
+					System.out.println("Warning readInteger : "+e);// FIXME hex string
+					lastInteger = 0;
+				}
+				position++;
+			} else {
+				if (string_tmp.charAt(string_tmp.length()-1) > '9') {
+					string_tmp = string_tmp.substring(0, string_tmp.length()-1);// remove last
+					position--;
+				}
+				if (lastCharacter() == 'o') {
+					if (!isOctal(string_tmp)) {
+						reporter.syntaxError("Incorrect octal number.", getPosition());
+					}
+					lastInteger = Integer.valueOf(string_tmp, 8).intValue();
+					position++;
+				} else if (lastCharacter() == 'b') {
+					if (!isBinary(string_tmp)) {
+						reporter.syntaxError("Incorrect binary number.", getPosition());
+					}
+					lastInteger = Integer.valueOf(string_tmp, 2).intValue();
+					position++;
+				} else {
+					if (lastCharacter() == 'd') {
+						position++;
+					}
+					if (! isInteger(string_tmp)) {
+						reporter.syntaxError("Incorrect decimal number.", getPosition());
+					}
+					lastInteger = Integer.valueOf(string_tmp);
+				}
+			}
+		}
+		return result;
+	}
+
+	private boolean isInteger(String s) {
+		try {
+			Integer.parseInt(s);
+		} catch (NumberFormatException e) {
+			return false;
+		}
+		return true;
+	}
+
+	// True when the contents is a sequence of bits (i.e., mixed
+	// characters `0' and characters `1').
+	private boolean isBinary(String s) {
+		boolean result;
+		int i;
+
+		i = s.length()-1;
+		result = true;
+		while (result && i != 0) {
+			result = s.charAt(i) == '0' || s.charAt(i) == '1';
+			i--;
+		}
+		return result;
+	}
+
+	private boolean isOctal(String s) {
+		try {
+			Integer.parseInt(s, 8);
+		} catch (NumberFormatException e) {
+			return false;
+		}
+		return true;
+	}
+
+	private boolean isHexadecimalDigit(char c) {
+		boolean result=false;
+
+		if (Character.isDigit(c)) {
+			result = true;
+		} else if (c >= 'a') {
+			result = c <= 'f';
+		} else if (c >= 'A') {
+			result = c <= 'F';
+		}
+		return result;
+	}
+
+	//-- real -> '0'-'9' {'0'-'9'_} [ '.' {'0'-'9'} ] [ 'E' ['+'|'-'] '0'-'9' {'0'-'9'}
+	public boolean readReal() {
+		boolean result=false;
+		int pos_old;
+
+		if (readSpace() && Character.isDigit(lastCharacter())) {
+			string_tmp = ""+lastCharacter();
+			pos_old = position;
+			position++;
+
+			while (Character.isDigit(lastCharacter()) || lastCharacter() == '_') {
+				if (lastCharacter() != '_') {
+					string_tmp += lastCharacter();
+				}
+				position++;
+			}
+			if (lastCharacter() == '.') {
+				string_tmp += '.';
+				position++;
+
+				if (Character.isDigit(lastCharacter())) {
+					result = true;
+					string_tmp += lastCharacter();
+					position++;
+
+					while (Character.isDigit(lastCharacter())) {
+						string_tmp += lastCharacter();
+						position++;
+					}
+				}
+				if (lastCharacter() == 'E') {
+					result = true;
+					string_tmp += 'E';
+					position++;
+
+					if (lastCharacter() == '+' || lastCharacter() == '-') {
+						string_tmp += lastCharacter();
+						position++;
+					}
+					if (Character.isDigit(lastCharacter())) {
+						string_tmp += lastCharacter();
+						position++;
+						while (Character.isDigit(lastCharacter())) {
+							string_tmp += lastCharacter();
+							position++;
+						}
+					} else {
+						reporter.syntaxError("Incorrect real number.", getPosition());
+					}
+				}
+			}
+			if (result) {
+				lastReal = getString(string_tmp);
+			} else {
+				position = pos_old;
+			}
+		}
+		return result;
+	}
+
+	public void readEscapeCharacter() {
+		int val;
+
+		if (isSeparator(lastCharacter())) {
+			position++;
+			while (lastCharacter() != 0 && isSeparator(lastCharacter())) {
+				position++;
+			}
+			if (lastCharacter() == '\\') {
+				string_tmp.substring(0, string_tmp.length()-2); // remove last
+				position++;
+			} else if (lastCharacter() != 0) {
+				reporter.syntaxError("Unknown escape sequence.", getPosition());
+			}
+		} else if (lastCharacter() != 0) {
+			char c = lastCharacter();
+
+			if (c == 'a' ||
+					c == 'b' ||
+					c == 'f' ||
+					c == 'n' ||
+					c == 'r' ||
+					c == 't' ||
+					c == 'v' ||
+					c == '\\' ||
+					c == '?' ||
+					c == '\'' ||
+					c == '\"') {
+				string_tmp += c;
+				position++;
+			} else if (lastCharacter() >= '0' && lastCharacter() <= '9') {
+				if (lastCharacter() == '0' && 
+						position < source.length() &&
+						! isHexadecimalDigit(source.charAt(position+1))) {
+
+					string_tmp += lastCharacter();
+					position++;
+				} else {
+					String string_tmp2 = new String(string_tmp);
+					readInteger(); // result is Always TRUE.
+					string_tmp = string_tmp2;
+
+					if (lastInteger > 255) {
+						reporter.syntaxError("Invalid range character number [0,255].", getPosition());
+					}
+					val = (int) lastInteger;
+					string_tmp += (val / 64);
+					string_tmp += ((val % 64) / 8);
+					string_tmp += (val % 8);
+					if (lastCharacter() == '\\') {
+						position++;
+					} else {
+						reporter.syntaxError("Character '\' is needed.", getPosition());
+					}
+				}
+			} else {
+				reporter.syntaxError("Unknown escape sequence.", getPosition());
+			}
+		}
+	}
+
+	//-- character  -> '\'' ascii '\''
+	public boolean readCharacters() {
+		boolean result=false;
+		int count=0;
+
+		if (readSpace() && lastCharacter() == '\'') {
+			//old_pos = position;
+			position++;
+			string_tmp = "";
+			while (lastCharacter() != 0 && lastCharacter() != '\n' && lastCharacter() != '\'') {
+				string_tmp += lastCharacter();
+				if (lastCharacter() == '\\') {
+					position++;
+					readEscapeCharacter();
+					count++;
+				} else {
+					position++;
+					count++;
+				}
+			}
+			if (lastCharacter() == '\'') {
+				position++;
+				lastString = getString(string_tmp);
+				if (count != 1) {
+					position = begin_position;
+					reporter.syntaxError("Character constant too long.", getPosition());
+				}
+				result = true;
+			} else {
+				position = begin_position;
+				reporter.syntaxError("Unterminated character constant.", getPosition());
+			}
+		}
+		return result;
+	}
+
+	//-- string -> '\"' ascii_string '\"'
+	public boolean readString() {
+		boolean result=false;
+		//	int old_pos;
+
+		if (readSpace() && lastCharacter() == '\"') {
+			//	old_pos = position;
+			position = position+1;
+			string_tmp = "";
+			while (lastCharacter() != 0 && lastCharacter() != '\n' && lastCharacter() != '\"') {
+				string_tmp += lastCharacter();
+				if (lastCharacter() == '\\') {
+					position = position+1;
+					readEscapeCharacter();
+				} else {
+					position = position+1;
+				}
+			}
+			if (lastCharacter() == '\"') {
+				position = position+1;
+				lastString = getString(string_tmp);
+				result = true;
+			} else {
+				position = begin_position;
+				reporter.syntaxError("Unterminated string constant.", getPosition());
+			}
+		}
+		return result;
+	}
+
+	//-- external -> '`' ascii_c_code '`'
+	public boolean readExternal() {
+		boolean result=false;
+		//	int pos_old;
+
+		if ((! readSpace()) || lastCharacter() != '`') {
+			result = false;
+		} else {
+			//	pos_old=position;
+			position = position+1;
+			string_tmp = "";
+			while (lastCharacter() != 0 && lastCharacter() != '`') {
+				string_tmp += lastCharacter();
+				if (lastCharacter() == '\\') {
+					position = position+1;
+					string_tmp += lastCharacter();
+					if (lastCharacter() != 0) {
+						position = position+1;
+					}
+				} else {
+					position = position+1;
+				}
+			}
+			if (lastCharacter() != 0) {
+				position = position+1;
+				lastString = getString(string_tmp);
+				result = true;
+			} else {
+				result = false;
+			}
+		}
+		return result;
+	}
+
+	private final String operators = "!@#$%^&<|*-+=~/?\\>";
+
+	//-- operator -> '!' | '@' | '#' | '$' | '%' | '^' | '&' | '<' | '|'  
+	//--           | '*' | '-' | '+' | '=' | '~' | '/' | '?' | '\' | '>'
+	public boolean readOperator() {
+		boolean result=false;
+		//		int old_pos;
+
+		readSpace();
+		//	old_pos = position;
+		string_tmp = "";
+		while (lastCharacter() != 0 &&
+				operators.indexOf(lastCharacter()) != -1) {
+			string_tmp += lastCharacter();
+			position = position+1;
+		}
+		if (string_tmp.length() > 0) {
+			lastString = getString(string_tmp);
+			if (lastString.equals(ILisaacModel.symbol_affect_immediate) ||
+					lastString.equals(ILisaacModel.symbol_affect_code) ||
+					lastString.equals(ILisaacModel.symbol_affect_cast)) {
+				reporter.syntaxError("Incorrect operator.", getPosition());
+			}
+			result = true;
+		}
+		return result;
+	}
+
+	// True when character is a separator.
+	private boolean isSeparator(char c) {
+		return c == ' ' || c == '\t' || c == '\n' ||
+		c == '\r' || c == '\0' || c == '\f'; // || c == '\v';
+	}
+	
+	public String getString(String str) {
+		if (model == null) {
+			return str;
+		}
+		return model.getAliasString().get(str);
+	}
+
+	
+	public ILisaacErrorHandler getReporter() {
+		return reporter;
+	}
+}
diff --git a/src/org/eclipse/lisaac/model/LisaacCompletionParser.java b/src/org/eclipse/lisaac/model/LisaacCompletionParser.java
index 62c3862..419978a 100644
--- a/src/org/eclipse/lisaac/model/LisaacCompletionParser.java
+++ b/src/org/eclipse/lisaac/model/LisaacCompletionParser.java
@@ -19,17 +19,22 @@ import org.eclipse.lisaac.model.items.ITMRead;
 import org.eclipse.lisaac.model.items.Prototype;
 import org.eclipse.lisaac.model.items.Slot;
 import org.eclipse.lisaac.model.types.IType;
-import org.eclipse.lisaac.model.types.TypeSimple;
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.ui.IWorkbenchWindow;
 
 public class LisaacCompletionParser extends LisaacParser {
+	protected static LisaacModel model;
 
 	protected Prototype currentPrototype;
 	protected Slot currentSlot;
 
-	public LisaacCompletionParser(String contents) {
+	protected int endOffset;
+
+
+
+	public LisaacCompletionParser(String contents, LisaacModel model) {
 		super(contents);
+		LisaacCompletionParser.model = model;
 	}
 
 	/**
@@ -45,6 +50,7 @@ public class LisaacCompletionParser extends LisaacParser {
 
 		currentPrototype = LisaacModel.getCurrentPrototype();
 		currentSlot = currentPrototype.getSlot(startOffset);
+		endOffset = -1;
 
 		ICode code = readExpr();
 		if (code != null && currentPrototype != null) {
@@ -58,8 +64,8 @@ public class LisaacCompletionParser extends LisaacParser {
 				proposals.add(new CompletionProposal(""+type,baseOffset,0,0));
 			} else {
 				// partial slot name (first keyword)
-	 			if (code instanceof ITMRead) {
-	 				String prefix = ((ITMRead) code).getName();
+				if (code instanceof ITMRead) {
+					String prefix = ((ITMRead) code).getName();
 					currentPrototype.lookupSlotMatch(prefix, proposals, baseOffset, 0);
 				}
 			}
@@ -72,6 +78,9 @@ public class LisaacCompletionParser extends LisaacParser {
 		ICode result = readExprBase();
 		if (result != null) {
 			while (readCharacter('.')) {
+				if (endOffset != -1 && position == endOffset+1) {
+					break;
+				}
 				ICode lastResult = result;
 				result = readSendMsg(result);
 				if (result == null) {
@@ -100,6 +109,36 @@ public class LisaacCompletionParser extends LisaacParser {
 		return result;
 	}
 
+
+	public Prototype readReceiver(int startOffset, int endOffset, Prototype currentPrototype) throws CoreException {
+		Prototype result=null;
+		IType type;
+
+		this.currentPrototype = currentPrototype;//LisaacModel.getCurrentPrototype();
+		currentSlot = currentPrototype.getSlot(startOffset);
+		this.endOffset = endOffset;
+
+		setPosition(startOffset);
+		readSpace();
+
+		ICode code = readExpr();
+		if (code != null && currentPrototype != null) {
+			type = code.getType(currentSlot, currentPrototype);
+			if (type != null) {
+				//if (! type.equals(TypeSimple.getTypeSelf())) {
+				if ("SELF".compareTo(type.toString()) != 0) {
+					Prototype save = currentPrototype;
+					currentPrototype = findPrototype(type.toString());
+					if (currentPrototype == null) {
+						currentPrototype = save;
+					}
+				}
+				result = currentPrototype;	
+			}
+		}
+		return result;
+	}
+
 	/**
 	 * Find and parse a lisaac prototype according to its name.
 	 */
@@ -107,43 +146,47 @@ public class LisaacCompletionParser extends LisaacParser {
 		IProject project = null;
 		Prototype result = null;
 
-		IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
-		if (w == null) {
+		if (model == null) {
+			IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+			if (w == null) {
+				return null;
+			} 
+			IWorkbenchPart part = w.getPartService().getActivePart();
+			if (part instanceof LisaacEditor) {
+				project = ((LisaacEditor)part).getProject();
+			}
+			if (project != null) {
+				model = LisaacModel.getModel(project);
+			}
+		}
+		if (model == null) {
 			return null;
 		}
-		IWorkbenchPart part = w.getPartService().getActivePart();
-		if (part instanceof LisaacEditor) {
-			project = ((LisaacEditor)part).getProject();
+		Prototype prototype = model.getPrototype(prototypeName);
+		if (prototype != null) {
+			// prototype is already cached
+			return prototype;	
 		}
-		if (project != null) {
-			LisaacModel model = LisaacModel.getModel(project);
 
-			Prototype prototype = model.getPrototype(prototypeName);
-			if (prototype != null) {
-				// prototype is already cached
-				return prototype;	
-			}
-
-			// cache new prototype
-			String prototypePath = model.getPathManager().getFullPath(prototypeName);
-			if (prototypePath != null) {
-				IPath location = new Path(prototypePath);
+		// cache new prototype
+		String prototypePath = model.getPathManager().getFullPath(prototypeName);
+		if (prototypePath != null) {
+			IPath location = new Path(prototypePath);
 
-				IFile file = project.getFile(location.lastSegment());
-				if (! file.isAccessible()) {
-					file.createLink(location, IResource.REPLACE, null);
-				}
-				result = model.parsePrototype(prototypeName, file.getContents(), new ILisaacErrorHandler() {
-					public void fatalError(String msg, Position position) {				
-					}
-					public void semanticError(String msg, Position position) {					
-					}
-					public void syntaxError(String msg, Position position) {			
-					}
-					public void warning(String msg, Position position) {
-					}
-				});
+			IFile file = project.getFile(location.lastSegment());
+			if (! file.isAccessible()) {
+				file.createLink(location, IResource.REPLACE, null);
 			}
+			result = model.parsePrototype(prototypeName, file.getContents(), new ILisaacErrorHandler() {
+				public void fatalError(String msg, Position position) {				
+				}
+				public void semanticError(String msg, Position position) {					
+				}
+				public void syntaxError(String msg, Position position) {			
+				}
+				public void warning(String msg, Position position) {
+				}
+			});
 		}
 		return result;
 	}
@@ -153,7 +196,7 @@ public class LisaacCompletionParser extends LisaacParser {
 	 */
 	public static Prototype findPrototype(String prototypeName, LisaacModel model) throws CoreException {
 		Prototype result = null;
-	
+
 		Prototype prototype = model.getPrototype(prototypeName);
 		if (prototype != null) {
 			// prototype is already cached
@@ -165,7 +208,7 @@ public class LisaacCompletionParser extends LisaacParser {
 		if (prototypePath != null) {
 			IPath location = new Path(prototypePath);
 			IProject project = model.getProject();
-			
+
 			IFile file = project.getFile(location.lastSegment());
 			if (! file.isAccessible()) {
 				file.createLink(location, IResource.REPLACE | IResource.HIDDEN, null);
diff --git a/src/org/eclipse/lisaac/model/LisaacModel.java b/src/org/eclipse/lisaac/model/LisaacModel.java
index 32f2b9e..87f8545 100644
--- a/src/org/eclipse/lisaac/model/LisaacModel.java
+++ b/src/org/eclipse/lisaac/model/LisaacModel.java
@@ -15,6 +15,7 @@ import org.eclipse.lisaac.editors.AbstractLisaacEditor;
 import org.eclipse.lisaac.editors.LisaacEditor;
 import org.eclipse.lisaac.model.items.Prototype;
 import org.eclipse.lisaac.model.lip.LIP;
+import org.eclipse.ui.IPartService;
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.ui.IWorkbenchWindow;
 
@@ -29,13 +30,13 @@ public class LisaacModel implements ILisaacModel{
 
 	/** list of all legal prototypes path */
 	private LisaacPath modelPath;
-	
+
 	/** list of all encountered prototypes */
 	private HashMap<String,Prototype> prototypes;
 
 	/** lip makefile of this model */
 	private LIP lipCode;
-	
+
 	/** project associated with this model */
 	private IProject project;
 
@@ -44,27 +45,27 @@ public class LisaacModel implements ILisaacModel{
 
 	/** error handler */
 	private ILisaacErrorHandler reporter;
-	
+
 	/** lisaac parser */
 	private LisaacParser parser;
-	
+
 	/** string aliaser */
 	private AliasString aliasString;
-	
+
 
 	public LisaacModel(IProject project) {
 		this.project = project;
 		prototypes = new HashMap<String,Prototype>();
 		aliasString = new AliasString();
-		
+
 		builder = new LisaacBuilder(this);
-		
+
 		// add this model to the model list
 		if (modelList == null) {
 			modelList = new HashMap<IProject,LisaacModel>();
 		}
 		modelList.put(project, this);
-		
+
 		// create lisaac path
 		modelPath = new LisaacPath(project, "make.lip"); // TODO get lip from property page
 	}
@@ -76,7 +77,7 @@ public class LisaacModel implements ILisaacModel{
 	public void setProject(IProject project) {
 		this.project = project;
 	}
-	
+
 	public LisaacBuilder getBuilder() {
 		return builder;
 	}
@@ -92,7 +93,7 @@ public class LisaacModel implements ILisaacModel{
 	public LIP getLipCode() {
 		return lipCode;
 	}
-	
+
 	public Prototype getPrototype(String name) {
 		if (prototypes != null) {
 			return prototypes.get(name);
@@ -103,7 +104,7 @@ public class LisaacModel implements ILisaacModel{
 	public void buildAll() {		
 		try {
 			builder.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null, null);
-			
+
 			// refresh editor coloring
 			IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
 			IWorkbenchPart part = w.getPartService().getActivePart();
@@ -114,14 +115,14 @@ public class LisaacModel implements ILisaacModel{
 			e.printStackTrace();
 		}
 	}
-	
+
 	/** parse and create part of current model */
 	public Prototype parsePrototype(String name, InputStream contents, ILisaacErrorHandler reporter) {
 		this.reporter = reporter;
-		
+
 		parser = new LisaacParser(contents, this);
 		Prototype prototype = new Prototype(name, extractPrototypeName(name),this);
-		
+
 		ILisaacContext context = parser.readContext();
 		while (context != null) {
 			if (context.parseDefinition(prototype)) { 
@@ -139,19 +140,19 @@ public class LisaacModel implements ILisaacModel{
 	public void removePrototype(IResource resource) {
 		prototypes.remove(extractPrototypeName(resource.getName()));
 	}
-	
+
 	/** parse and create part of current model 
 	 * @throws CoreException */
 	public void parseLip(String name, InputStream contents, ILisaacErrorHandler reporter) throws CoreException {
 		this.reporter = reporter;
-		
+
 		lipCode = new LIP(name);
 		LipParser lipParser = new LipParser(contents, this);
 		if (! lipParser.parse()) {
 			reporter.syntaxError("Syntax error.", lipParser.getPosition());
 			return;
 		}
-		
+
 		// parse lip parents
 		for (int i=0; i<lipCode.getParentCount(); i++) {
 			String parent = lipCode.getParent(i);
@@ -168,12 +169,12 @@ public class LisaacModel implements ILisaacModel{
 			}
 		}
 	}
-	
+
 	/** remove part of current model */
 	public void removeLip(IResource resource) {
 		// TODO remove lip
 	}
-	
+
 	/** get little name of prototype instead of full path */
 	public static String extractPrototypeName(String s) {
 		int idx = s.indexOf('.');
@@ -182,11 +183,11 @@ public class LisaacModel implements ILisaacModel{
 		}
 		return s.toUpperCase();
 	}
-	
+
 	public ILisaacErrorHandler getReporter() {
 		return reporter;
 	}
-	
+
 	/**
 	 * Get the lisaac model associated with the given project.
 	 * @param p A lisaac project
@@ -198,15 +199,21 @@ public class LisaacModel implements ILisaacModel{
 		}
 		return null;
 	}
-	
+
 	public static Prototype getCurrentPrototype() {
 		IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
-		
-		IWorkbenchPart part = w.getPartService().getActivePart();
+		if (w == null) {
+			return null;
+		}
+		IPartService service = w.getPartService(); 
+		if (service == null) {
+			return null;
+		}
+		IWorkbenchPart part = service.getActivePart();
 		if (part instanceof LisaacEditor) {
 			IProject project = ((LisaacEditor)part).getProject();
 			String filename = ((LisaacEditor)part).getFileName();
-			
+
 			LisaacModel model = LisaacModel.getModel(project);
 			if (model != null) {
 				return model.getPrototype(extractPrototypeName(filename));
diff --git a/src/org/eclipse/lisaac/model/LisaacParser.java b/src/org/eclipse/lisaac/model/LisaacParser.java
index 64d325a..85b74f0 100644
--- a/src/org/eclipse/lisaac/model/LisaacParser.java
+++ b/src/org/eclipse/lisaac/model/LisaacParser.java
@@ -805,7 +805,7 @@ public class LisaacParser extends AbstractLisaacParser {
 	//++ EXPR_BASE    -> "Old" EXPR
 	//++               | EXPR_PRIMARY
 	//++               | SEND_MSG
-	protected ICode readExprBase() {
+	public ICode readExprBase() {
 		ICode result=null;
 
 		if (readThisKeyword(ILisaacModel.keyword_old)) {
@@ -1026,7 +1026,7 @@ public class LisaacParser extends AbstractLisaacParser {
 	}
 
 	//++ SEND_MSG     -> identifier [ ARGUMENT { identifier ARGUMENT } ]
-	protected ICode readSendMsg(ICode firstArg) {
+	public ICode readSendMsg(ICode firstArg) {
 		ICode result=null;
 
 		if (readIdentifier()) {
@@ -1414,6 +1414,42 @@ public class LisaacParser extends AbstractLisaacParser {
 		return true;
 	}
 
+	//++ SEND_MSG     -> identifier [ ARGUMENT { identifier ARGUMENT } ]
+	public String readKeywordInSendMsg(String keyword, int keywordOffset) {
+		String result=null;
+		boolean keywordFound=false;
+
+		if (readIdentifier()) {
+			//
+			// Classic Message.
+			//
+			String n = getString(lastString);// create alias
+			if (n.compareTo(keyword) == 0 && position == keywordOffset+keyword.length()) {
+				keywordFound = true;
+			}
+			// Argument list.
+			ICode arg = readArgument();
+			if (arg != null) {
+				while (readIdentifier()) {
+					if (lastString.compareTo(keyword) == 0 && position == keywordOffset+keyword.length()) {
+						keywordFound = true;
+					}
+					n += "__" + lastString; // FIXME: alias pb
+					arg = readArgument();
+					if (arg == null) {
+						reporter.syntaxError("Incorrect argument.", getPosition());
+						return null;
+					}
+				}
+			}
+			// return slot full name
+			result = getString(n); // FIXME alias pb
+		}	
+		if (! keywordFound) {
+			result = null;
+		}
+		return result;
+	}
 
 	/**
 	 * Read the next context in lisaac code.
diff --git a/src/org/eclipse/lisaac/model/items/Prototype.java b/src/org/eclipse/lisaac/model/items/Prototype.java
index 546b7d2..3300509 100644
--- a/src/org/eclipse/lisaac/model/items/Prototype.java
+++ b/src/org/eclipse/lisaac/model/items/Prototype.java
@@ -7,9 +7,11 @@ import java.util.Iterator;
 import java.util.List;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.contentassist.ICompletionProposal;
 import org.eclipse.lisaac.model.ILisaacModel;
 import org.eclipse.lisaac.model.LisaacCompletionParser;
+import org.eclipse.lisaac.model.LisaacModel;
 import org.eclipse.lisaac.model.LisaacParser;
 import org.eclipse.lisaac.model.types.IType;
 import org.eclipse.lisaac.outline.OutlineItem;
@@ -241,7 +243,121 @@ public class Prototype {
 			}
 		}
 	}
-	
+
+	public Slot getSlotFromKeyword(String keyword, LisaacParser parser, int baseOffset) throws CoreException {
+		String source = parser.getSource();
+		int bracketLevel = 0;
+		Prototype receiver = null;
+		Slot result = null;
+		char c = 0;
+
+		int offset = baseOffset;
+		if (offset >= source.length()-1) {
+			return null;
+		}
+
+		while (offset > 0) {
+			//
+			// find beginning of SEND_MSG grammar rule
+			//
+
+			// Rewind to '('  ';' '[' '.'
+			c = source.charAt(offset);
+			if (c == ';' || c == '.') {
+				break;
+			}
+			if (c == '(' || c == '[') {
+				if (bracketLevel == 0) {
+					break;
+				}
+				bracketLevel--;
+			}
+			if (c == ')' || c == ']') {
+				bracketLevel++;
+			}
+
+			// look at indentation
+			if (c == '\n' && source.length() - offset > 4) {
+				if (source.charAt(offset+1) == ' ' &&
+						source.charAt(offset+2) == ' ' &&
+						(source.charAt(offset+3) == '+' || source.charAt(offset+3) == '-')) {
+					String slotName = parser.readSlotNameFromOffset(offset+4);
+					if (slotName != null) {
+						result = getSlot(slotName);
+						if (result == null) {
+							return null;
+						}
+						if (result.keywordCount() == 1) {
+							if (result.getName().compareTo(keyword) == 0) {
+								return result;
+							}
+						} else {
+							// find keyword next token
+							offset = baseOffset;
+							while (offset < source.length()-1 && 
+									Character.isJavaIdentifierPart(source.charAt(offset))) {
+								offset++;
+							}
+							// read space
+							while (offset < source.length()-1 && 
+									Character.isWhitespace(source.charAt(offset))) {
+								offset++;
+							}
+							if (source.charAt(offset) != ':') {
+								return result;// 'keyword' is a slot keyword
+							}
+							return null;
+						}
+					}
+				}
+			}
+			offset--;
+		}
+		if (result == null) {
+			// Slot Call.
+
+			if (c == '.') {
+				int pointOffset = offset;
+				offset--;
+				bracketLevel = 0;
+
+				// rewind until ';' '(' '['
+				while (offset > 0) {
+					c = source.charAt(offset);
+					if (c == ';') {
+						break;
+					}
+					if (c == '(' || c == '[') {
+						if (bracketLevel == 0) {
+							break;
+						}
+						bracketLevel--;
+					}
+					if (c == ')' || c == ']') {
+						bracketLevel++;
+					}
+					offset--;
+				}
+				if (offset > 0) {
+					LisaacCompletionParser p = new LisaacCompletionParser(source, (LisaacModel)getModel());
+					receiver = p.readReceiver(offset+1, pointOffset, this);
+					
+					offset = pointOffset;
+				}
+			} else {
+				receiver = this;
+			}
+			parser.setPosition(offset+1);
+			parser.readSpace();
+			String slotName = parser.readKeywordInSendMsg(keyword, baseOffset);
+
+			if (slotName != null && receiver != null) {
+				result = receiver.lookupSlot(slotName);
+			}
+		}
+		return result;
+	}
+
 	public void addSlot(Slot s) {
 		slotList.put(s.getName(), s);
 	}
@@ -286,7 +402,7 @@ public class Prototype {
 			Slot slot = it.next();
 			slot.getSlotProposals(proposals, offset, length);
 		}
-		
+
 		values = parentList.values();
 		it = values.iterator() ;
 		while (it.hasNext()) {
diff --git a/src/org/eclipse/lisaac/model/items/Slot.java b/src/org/eclipse/lisaac/model/items/Slot.java
index ac132d6..ce4ac7a 100644
--- a/src/org/eclipse/lisaac/model/items/Slot.java
+++ b/src/org/eclipse/lisaac/model/items/Slot.java
@@ -77,6 +77,10 @@ public class Slot  {
 	public Position getPosition() {
 		return position;
 	}
+	
+	public int keywordCount() {
+		return keywordList.length;
+	}
 
 	//
 	// Value.
@@ -235,5 +239,9 @@ public class Slot  {
 	public boolean match(String n) {
 		return name.startsWith(n);
 	}
+
+	public String getHoverInformation() {
+		return getSignature(false);
+	}
 }
 

-- 
Lisaac eclipse plugin



More information about the Lisaac-commits mailing list