[SCM] Lisaac eclipse plugin branch, master, updated. 1e9a8850aa3ddcb8a5814d0cb348e3088a103270
Damien Bouvarel
dams.bouvarel at wanadoo.fr
Fri Mar 20 22:09:18 UTC 2009
The following commit has been merged in the master branch:
commit 1e9a8850aa3ddcb8a5814d0cb348e3088a103270
Author: Damien Bouvarel <dams.bouvarel at wanadoo.fr>
Date: Fri Mar 20 23:03:03 2009 +0100
git migration
diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/.project b/.project
new file mode 100644
index 0000000..7afc5a4
--- /dev/null
+++ b/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>eclipse.git</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..2fd4063
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Fri Feb 13 13:38:46 CET 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..cf7a09a
--- /dev/null
+++ b/META-INF/MANIFEST.MF
@@ -0,0 +1,25 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Lisaac Plug-in
+Bundle-SymbolicName: org.eclipse.lisaac; singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.lisaac.LisaacPlugin
+Bundle-Vendor: Damien Bouvarel
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.jface.text,
+ org.eclipse.ui.editors,
+ org.eclipse.ui.ide,
+ org.eclipse.ui.console,
+ org.eclipse.jdt.ui,
+ org.eclipse.debug.ui,
+ org.eclipse.ui.cheatsheets
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Bundle-ClassPath: .
+Import-Package: org.eclipse.ant.core,
+ org.eclipse.debug.core,
+ org.eclipse.debug.core.model,
+ org.eclipse.debug.ui,
+ org.eclipse.ui.views.contentoutline
diff --git a/build.properties b/build.properties
new file mode 100644
index 0000000..b476d07
--- /dev/null
+++ b/build.properties
@@ -0,0 +1,9 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .,\
+ icons/,\
+ help/html/,\
+ *.xml,\
+ help/contexts.xml
diff --git a/help/html/maintopic.html b/help/html/maintopic.html
new file mode 100644
index 0000000..a476078
--- /dev/null
+++ b/help/html/maintopic.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Main Topic</title>
+</head>
+
+<body>
+<h1>Main Topic</h1>
+Please enter your text here.
+</body>
+</html>
\ No newline at end of file
diff --git a/help/html/overview.html b/help/html/overview.html
new file mode 100644
index 0000000..a476078
--- /dev/null
+++ b/help/html/overview.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Main Topic</title>
+</head>
+
+<body>
+<h1>Main Topic</h1>
+Please enter your text here.
+</body>
+</html>
\ No newline at end of file
diff --git a/help/html/subtopic.html b/help/html/subtopic.html
new file mode 100644
index 0000000..8a61c50
--- /dev/null
+++ b/help/html/subtopic.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Sub Topic</title>
+</head>
+
+<body>
+<h1>Sub Topic</h1>
+Please enter your text here.
+</body>
+</html>
\ No newline at end of file
diff --git a/help/html/toc.html b/help/html/toc.html
new file mode 100644
index 0000000..326f0a9
--- /dev/null
+++ b/help/html/toc.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Table of Contents</title>
+</head>
+
+<body>
+<h1>Table of Contents</h1>
+Please enter your text here.
+</body>
+</html>
\ No newline at end of file
diff --git a/help/sheet1_HelloWorld.xml b/help/sheet1_HelloWorld.xml
new file mode 100644
index 0000000..3324a79
--- /dev/null
+++ b/help/sheet1_HelloWorld.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cheatsheet
+ title="Create a Hello World application">
+ <intro>
+ <description>
+ This cheat sheet shows you how to create a "Hello World" Lisaac application.
+
+ The application will print "Hello World" in the console when run.
+ Enter Lisaac World!
+ </description>
+ </intro>
+ <item
+ title="Open the Lisaac perspective">
+ <description>
+ If you're not already in a Lisaac perspective, in the main menu select <b>Window > Open Perspective > Lisaac</b>.
+
+ </description>
+ <command
+ required="false"
+ serialization="org.eclipse.ui.perspectives.showPerspective"/>
+ </item>
+ <item
+ title="Create a Lisaac Project">
+ <description>
+ We need a project to create an application. Click on the <b>New Lisaac Project</b> button, or click on the link below. Enter <b>HelloWorld</b> for the project name, then click <b>Finish</b>.
+
+ </description>
+ <command
+ required="false"
+ serialization="org.eclipse.ui.newWizard"/>
+ </item>
+
+ <item
+ skip="false"
+ title="Create your HelloWorld Prototype">
+ <description>
+ The next step is to create a new prototype.
+If the project wizard has not created a main prototype, click on the <b>New Prototype</b> button, select the checkbox to create the <b>main</b> slot.
+ </description>
+ <command
+ required="false"
+ serialization="org.eclipse.ui.newWizard"/>
+ </item>
+ <item
+ title="Add a print statement">
+ <description>
+ Now that you have your HelloWorld prototype, in the <b>main</b> slot, add the following statement:
+"Hello World!".print;
+then <b>save</b> your changes, the prototype will automatically compile.
+ </description>
+ </item>
+ <item
+ title="Run your Lisaac application">
+ <description>
+ To run your application, select <b>Run-> Run configurations</b> menu, select <b>Lisaac Application</b>.
+The <b>Console</b> view should appear at the bottom and display the "Hello, world!" output.
+
+Congratulations! You have successfully created a Lisaac Hello World application!
+ </description>
+ </item>
+
+</cheatsheet>
diff --git a/help/testToc.xml b/help/testToc.xml
new file mode 100644
index 0000000..ca7402e
--- /dev/null
+++ b/help/testToc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<toc label="Lisaac Development user Guide" topic="html/toc.html">
+ <link toc="toc.xml" />
+</toc>
diff --git a/help/toc.xml b/help/toc.xml
new file mode 100644
index 0000000..6ad67be
--- /dev/null
+++ b/help/toc.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?NLS TYPE="org.eclipse.help.toc"?>
+
+<toc label="Lisaac Table of Contents">
+ <topic label="Lisaac development overview" href="html/overview.html">
+ </topic>
+ <topic href="html/maintopic.html" label="Getting Started">
+ <topic label="Topic">
+ </topic>
+ </topic>
+ <topic href="html/maintopic.html" label="Reference">
+ <topic label="Topic">
+ </topic>
+ </topic>
+ <topic label="Tips and Tricks">
+ </topic>
+ <topic label="Legal">
+ </topic>
+</toc>
diff --git a/icons/Thumbs.db b/icons/Thumbs.db
new file mode 100644
index 0000000..4c557a0
Binary files /dev/null and b/icons/Thumbs.db differ
diff --git a/icons/blank.gif b/icons/blank.gif
new file mode 100644
index 0000000..ede75be
Binary files /dev/null and b/icons/blank.gif differ
diff --git a/icons/private-nonshared.gif b/icons/private-nonshared.gif
new file mode 100644
index 0000000..39891e1
Binary files /dev/null and b/icons/private-nonshared.gif differ
diff --git a/icons/private-shared.gif b/icons/private-shared.gif
new file mode 100644
index 0000000..e4c1859
Binary files /dev/null and b/icons/private-shared.gif differ
diff --git a/icons/prototype.gif b/icons/prototype.gif
new file mode 100644
index 0000000..eb6e0b6
Binary files /dev/null and b/icons/prototype.gif differ
diff --git a/icons/public-nonshared.gif b/icons/public-nonshared.gif
new file mode 100644
index 0000000..828590b
Binary files /dev/null and b/icons/public-nonshared.gif differ
diff --git a/icons/public-shared.gif b/icons/public-shared.gif
new file mode 100644
index 0000000..698f668
Binary files /dev/null and b/icons/public-shared.gif differ
diff --git a/icons/releng_gears.gif b/icons/releng_gears.gif
new file mode 100644
index 0000000..81fb7b4
Binary files /dev/null and b/icons/releng_gears.gif differ
diff --git a/icons/sample.gif b/icons/sample.gif
new file mode 100644
index 0000000..34fb3c9
Binary files /dev/null and b/icons/sample.gif differ
diff --git a/plugin.xml b/plugin.xml
new file mode 100644
index 0000000..0d2cc72
--- /dev/null
+++ b/plugin.xml
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+
+ <extension
+ id="lisaacProblem"
+ name="Lisaac Problem"
+ point="org.eclipse.core.resources.markers">
+ <super
+ type="org.eclipse.core.resources.problemmarker">
+ </super>
+ <persistent
+ value="true">
+ </persistent>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ name="Lisaac Editor"
+ extensions="li"
+ icon="icons/sample.gif"
+ contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
+ class="org.eclipse.lisaac.editors.LisaacEditor"
+ id="org.eclipse.lisaac.editors.LisaacEditor">
+ </editor>
+ <editor
+ class="org.eclipse.lisaac.editors.LipEditor"
+ contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
+ default="false"
+ extensions="lip"
+ icon="icons/releng_gears.gif"
+ id="org.eclipse.lisaac.editors.LipEditor"
+ name="Lip Editor">
+ </editor>
+ </extension>
+ <extension
+ point="org.eclipse.ui.handlers">
+ <handler
+ commandId="org.eclipse.lisaac.commands.sampleCommand"
+ class="org.eclipse.lisaac.handlers.SampleHandler">
+ </handler>
+ </extension>
+ <extension
+ point="org.eclipse.help.toc">
+ <toc
+ file="help/toc.xml">
+ </toc>
+ <toc
+ file="help/testToc.xml"
+ primary="true">
+ </toc>
+ </extension>
+ <extension
+ point="org.eclipse.ui.perspectives">
+ <perspective
+ name="Lisaac Perspective"
+ icon="icons/releng_gears.gif"
+ class="org.eclipse.lisaac.perspectives.LisaacPerspective"
+ id="org.eclipse.lisaac.perspectives.LisaacPerspective">
+ </perspective>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ name="Lisaac Preferences"
+ class="org.eclipse.lisaac.preferences.LisaacPreferencePage"
+ id="org.eclipse.lisaac.preferences.LisaacPreferencePage">
+ </page>
+ </extension>
+ <extension
+ point="org.eclipse.core.runtime.preferences">
+ <initializer
+ class="org.eclipse.lisaac.preferences.PreferenceInitializer">
+ </initializer>
+ </extension>
+ <extension
+ point="org.eclipse.ui.propertyPages">
+ <page
+ class="org.eclipse.lisaac.properties.LisaacPropertyPage"
+ id="org.eclipse.lisaac.properties.lisaacPropertyPage"
+ name="Lisaac File Property"
+ nameFilter="*.li"
+ objectClass="org.eclipse.core.resources.IFile">
+ </page>
+ <page
+ class="org.eclipse.lisaac.properties.LisaacProjectPropertyPage"
+ id="org.eclipse.lisaac.properties.projectPropertyPage"
+ name="Lisaac Compiler"
+ objectClass="org.eclipse.core.resources.IProject">
+ </page>
+ </extension>
+ <extension
+ id="org.eclipse.lisaac.newWizard"
+ name="Lisaac Project Wizard"
+ point="org.eclipse.ui.newWizards">
+ <category
+ id="Lisaac"
+ name="Lisaac">
+ </category>
+ <wizard
+ canFinishEarly="false"
+ category="Lisaac"
+ class="org.eclipse.lisaac.wizards.NewProjectWizard"
+ finalPerspective="org.eclipse.lisaac.perspectives.LisaacPerspective"
+ hasPages="true"
+ icon="icons/sample.gif"
+ id="org.eclipse.lisaac.wizard"
+ name="Lisaac Project"
+ project="true">
+ </wizard>
+ <wizard
+ canFinishEarly="false"
+ category="Lisaac"
+ class="org.eclipse.lisaac.wizards.NewPrototypeWizard"
+ hasPages="true"
+ icon="icons/lisaac-file.png"
+ id="org.eclipse.lisaac.prototype"
+ name="Lisaac Prototype"
+ project="false">
+ </wizard>
+ </extension>
+ <extension
+ id="builder"
+ name="Lisaac Builder"
+ point="org.eclipse.core.resources.builders">
+ <builder
+ callOnEmptyDelta="false"
+ hasNature="true"
+ isConfigurable="false">
+ <run
+ class="org.eclipse.lisaac.builder.LisaacBuilder">
+ </run>
+ </builder>
+ </extension>
+ <extension
+ id="lisaac"
+ name="Lisaac Nature"
+ point="org.eclipse.core.resources.natures">
+ <runtime>
+ <run
+ class="org.eclipse.lisaac.builder.LisaacNature">
+ </run>
+ </runtime>
+ <builder
+ id="org.lisaac.builder">
+ </builder>
+ </extension>
+ <extension
+ point="org.eclipse.ui.console.consoleFactories">
+ <consoleFactory
+ class="org.eclipse.lisaac.views.ConsoleFactory"
+ label="Lisaac Console">
+ </consoleFactory>
+ </extension>
+ <extension
+ point="org.eclipse.debug.core.launchConfigurationTypes">
+ <launchConfigurationType
+ delegate="org.eclipse.lisaac.launch.LaunchConfiguration"
+ id="org.eclipse.lisaac.launchConfiguration"
+ modes="run"
+ name="Lisaac Application"
+ public="true">
+ </launchConfigurationType>
+ </extension>
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTabGroups">
+ <launchConfigurationTabGroup
+ class="org.eclipse.lisaac.launch.LaunchConfigurationTabGroup"
+ id="org.eclipse.lisaac.LaunchConfigurationTabGroup"
+ type="org.eclipse.lisaac.launchConfiguration">
+ </launchConfigurationTabGroup>
+ </extension>
+ <extension
+ point="org.eclipse.ui.actionSets">
+ <actionSet
+ description="Lisaac Source Tools"
+ id="org.eclipse.lisaac.source"
+ label="Source"
+ visible="true">
+ <menu
+ id="org.eclipse.lisaac.sourcemenu"
+ label="Source">
+ <groupMarker
+ name="indent">
+ </groupMarker>
+ </menu>
+ <action
+ class="org.eclipse.lisaac.actions.IndentAction"
+ definitionId="org.eclipse.lisaac.cmd1"
+ id="org.eclipse.lisaac.indentaction"
+ label="Correct Indentation"
+ menubarPath="org.eclipse.lisaac.sourcemenu/indent">
+ </action>
+ </actionSet>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ categoryId="org.eclipse.lisaac.commands"
+ id="org.eclipse.lisaac.cmd1"
+ name="Indentation">
+ </command>
+ <category
+ id="org.eclipse.lisaac.commands"
+ name="Lisaac Command">
+ </category>
+ </extension>
+ <extension
+ point="org.eclipse.ui.bindings">
+ <key
+ commandId="org.eclipse.lisaac.cmd1"
+ contextId="org.eclipse.ui.textEditorScope"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="F2">
+ </key>
+ </extension>
+ <extension
+ point="org.eclipse.ui.cheatsheets.cheatSheetContent">
+ <category
+ id="org.eclipse.lisaac.cheatsheet"
+ name="Lisaac Development">
+ </category>
+ <cheatsheet
+ category="org.eclipse.lisaac.cheatsheet"
+ composite="false"
+ contentFile="help/sheet1_HelloWorld.xml"
+ id="org.eclipse.lisaac.cheatsheet1"
+ name="Lisaac HelloWorld">
+ <description>
+ Create a "Hello World" Lisaac application from scratch.
+ </description>
+ </cheatsheet>
+ </extension>
+
+</plugin>
diff --git a/src/org/eclipse/lisaac/LisaacPlugin.java b/src/org/eclipse/lisaac/LisaacPlugin.java
new file mode 100644
index 0000000..6f0b780
--- /dev/null
+++ b/src/org/eclipse/lisaac/LisaacPlugin.java
@@ -0,0 +1,82 @@
+package org.eclipse.lisaac;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class LisaacPlugin extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.lisaac";
+
+ // The shared instance
+ private static LisaacPlugin plugin;
+
+ /**
+ * The constructor
+ */
+ public LisaacPlugin() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ for (int i=0; i<projects.length; i++) {
+ // create lisaac model
+ new LisaacModel(projects[i]);
+ //
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static LisaacPlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given
+ * plug-in relative path
+ *
+ * @param path the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return imageDescriptorFromPlugin(PLUGIN_ID, path);
+ }
+
+ /**
+ * Logs the specified status with this plug-in's log.
+ *
+ * @param status status to log.
+ */
+ public static void log(final IStatus status) {
+ getDefault().getLog().log(status);
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/actions/IndentAction.java b/src/org/eclipse/lisaac/actions/IndentAction.java
new file mode 100644
index 0000000..73298a8
--- /dev/null
+++ b/src/org/eclipse/lisaac/actions/IndentAction.java
@@ -0,0 +1,79 @@
+package org.eclipse.lisaac.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.lisaac.editors.LisaacAutoEditStrategy;
+import org.eclipse.lisaac.editors.LisaacEditor;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * Our sample action implements workbench action delegate.
+ * The action proxy will be created by the workbench and
+ * shown in the UI. When the user tries to use the action,
+ * this delegate will be created and execution will be
+ * delegated to it.
+ * @see IWorkbenchWindowActionDelegate
+ */
+public class IndentAction implements IWorkbenchWindowActionDelegate {
+ /**
+ * The constructor.
+ */
+ public IndentAction() {
+ }
+
+ /**
+ * The action has been activated. The argument of the
+ * method represents the 'real' action sitting
+ * in the workbench UI.
+ * @see IWorkbenchWindowActionDelegate#run
+ */
+ public void run(IAction action) {
+ IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+
+ IWorkbenchPart part = w.getPartService().getActivePart();
+ if (part instanceof LisaacEditor) {
+ IDocument document = ((LisaacEditor)part).getDocument();
+ //
+ LisaacAutoEditStrategy.fullIndentDocument(document);
+ //
+ }
+ }
+
+ /**
+ * Selection in the workbench has been changed. We
+ * can change the state of the 'real' action here
+ * if we want, but this can only happen after
+ * the delegate has been created.
+ * @see IWorkbenchWindowActionDelegate#selectionChanged
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+
+ IWorkbenchPart part = w.getPartService().getActivePart();
+ if (part instanceof LisaacEditor) {
+ action.setEnabled(true);
+ } else {
+ action.setEnabled(false);
+ }
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose() {
+ }
+
+ /**
+ * We will cache window object in order to
+ * be able to provide parent shell for the message dialog.
+ * @see IWorkbenchWindowActionDelegate#init
+ */
+ public void init(IWorkbenchWindow window) {
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/builder/ILisaacErrorHandler.java b/src/org/eclipse/lisaac/builder/ILisaacErrorHandler.java
new file mode 100644
index 0000000..a6c7ed3
--- /dev/null
+++ b/src/org/eclipse/lisaac/builder/ILisaacErrorHandler.java
@@ -0,0 +1,14 @@
+package org.eclipse.lisaac.builder;
+
+import org.eclipse.lisaac.model.Position;
+
+public interface ILisaacErrorHandler {
+
+ void syntaxError(String msg, Position position);
+
+ void fatalError(String msg, Position position);
+
+ void warning(String msg, Position position);
+
+ void semanticError(String msg, Position position);
+}
diff --git a/src/org/eclipse/lisaac/builder/LisaacBuilder.java b/src/org/eclipse/lisaac/builder/LisaacBuilder.java
new file mode 100644
index 0000000..5307435
--- /dev/null
+++ b/src/org/eclipse/lisaac/builder/LisaacBuilder.java
@@ -0,0 +1,205 @@
+package org.eclipse.lisaac.builder;
+
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.lisaac.model.Position;
+
+public class LisaacBuilder extends IncrementalProjectBuilder {
+
+ private LisaacModel model;
+
+ public LisaacBuilder(LisaacModel model) {
+ this.model = model;
+ }
+
+ class LisaacDeltaVisitor implements IResourceDeltaVisitor {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+ */
+ public boolean visit(IResourceDelta delta) throws CoreException {
+ IResource resource = delta.getResource();
+ switch (delta.getKind()) {
+ case IResourceDelta.ADDED:
+ // handle added resource
+ buildLisaacFile(resource);
+ break;
+ case IResourceDelta.REMOVED:
+ // handle removed resource
+ removeLisaacFile(resource);
+ break;
+ case IResourceDelta.CHANGED:
+ // handle changed resource
+ buildLisaacFile(resource);
+ break;
+ }
+ //return true to continue visiting children.
+ return true;
+ }
+ }
+
+ class LisaacResourceVisitor implements IResourceVisitor {
+ public boolean visit(IResource resource) {
+ buildLisaacFile(resource);
+ //return true to continue visiting children.
+ return true;
+ }
+ }
+
+ class LisaacErrorHandler implements ILisaacErrorHandler {
+
+ private IFile file;
+
+ public LisaacErrorHandler(IFile file) {
+ this.file = file;
+ }
+
+ private void addMarker(String msg, Position position, int severity) {
+ IMarker marker = LisaacBuilder.this.addMarker(file, msg, position.getLine(), severity);
+ if (marker != null && position.hasRange()) {
+ try {
+ marker.setAttribute(IMarker.CHAR_START, position.getCharStart());
+ marker.setAttribute(IMarker.CHAR_END, position.getCharEnd());
+ } catch (CoreException e) {
+ }
+ }
+ }
+
+ public void syntaxError(String msg, Position position) {
+ addMarker(msg, position, IMarker.SEVERITY_ERROR);
+ }
+
+ public void semanticError(String msg, Position position) {
+ addMarker(msg, position, IMarker.SEVERITY_ERROR);
+ }
+
+ public void fatalError(String msg, Position position) {
+ addMarker(msg, position, IMarker.SEVERITY_ERROR);
+ }
+
+ public void warning(String msg, Position position) {
+ addMarker(msg, position, IMarker.SEVERITY_WARNING);
+ }
+ }
+
+ public static final String BUILDER_ID = "org.eclipse.lisaac.builder";
+
+ private static final String MARKER_TYPE = "org.eclipse.lisaac.lisaacProblem";
+
+
+ private IMarker addMarker(IFile file, String message, int lineNumber,
+ int severity) {
+ try {
+ IMarker marker = file.createMarker(MARKER_TYPE);
+ marker.setAttribute(IMarker.MESSAGE, message);
+ marker.setAttribute(IMarker.SEVERITY, severity);
+ if (lineNumber == -1) {
+ lineNumber = 1;
+ }
+ marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+ return marker;
+ } catch (CoreException e) {
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.internal.events.InternalBuilder#build(int,
+ * java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IProject[] build(int kind, Map args, IProgressMonitor monitor)
+ throws CoreException {
+ if (kind == FULL_BUILD) {
+ fullBuild(monitor);
+ } else {
+ IResourceDelta delta = getDelta(model.getProject());
+ if (delta == null) {
+ fullBuild(monitor);
+ } else {
+ incrementalBuild(delta, monitor);
+ }
+ }
+ return null;
+ }
+
+ private void buildLisaacFile(IResource resource) {
+ if (resource instanceof IFile) {
+ IFile file = (IFile) resource;
+
+ if (resource.getName().endsWith(".li")) {
+ deleteMarkers(file);
+ try {
+ LisaacErrorHandler reporter = new LisaacErrorHandler(file);
+ model.parsePrototype(file.getName(), file.getContents(), reporter);
+ } catch (Exception e) {
+ }
+ } else if (resource.getName().endsWith(".lip")) {
+ deleteMarkers(file);
+ try {
+ LisaacErrorHandler reporter = new LisaacErrorHandler(file);
+ model.parseLip(file.getName(), file.getContents(), reporter);
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ private void removeLisaacFile(IResource resource) {
+ if (resource instanceof IFile) {
+ IFile file = (IFile) resource;
+ if (resource.getName().endsWith(".li")) {
+ deleteMarkers(file);
+ try {
+ model.removePrototype(file);
+ } catch (Exception e) {
+ }
+ } else if (resource.getName().endsWith(".lip")) {
+ deleteMarkers(file);
+ try {
+ model.removeLip(file);
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ private void deleteMarkers(IFile file) {
+ try {
+ file.deleteMarkers(MARKER_TYPE, false, IResource.DEPTH_ZERO);
+ } catch (CoreException ce) {
+ }
+ }
+
+ protected void fullBuild(final IProgressMonitor monitor)
+ throws CoreException {
+ try {
+ if (model.getProject() != null) {
+ model.getProject().accept(new LisaacResourceVisitor());
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ protected void incrementalBuild(IResourceDelta delta,
+ IProgressMonitor monitor) throws CoreException {
+ // the visitor does the work.
+ delta.accept(new LisaacDeltaVisitor());
+ }
+
+ protected void startupOnInitialize() {
+ }
+}
diff --git a/src/org/eclipse/lisaac/builder/LisaacNature.java b/src/org/eclipse/lisaac/builder/LisaacNature.java
new file mode 100644
index 0000000..0743aea
--- /dev/null
+++ b/src/org/eclipse/lisaac/builder/LisaacNature.java
@@ -0,0 +1,80 @@
+package org.eclipse.lisaac.builder;
+
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.runtime.CoreException;
+
+public class LisaacNature implements IProjectNature {
+
+ /**
+ * ID of this project nature
+ */
+ public static final String NATURE_ID = "org.eclipse.lisaac.lisaac";
+
+ private IProject project;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IProjectNature#configure()
+ */
+ public void configure() throws CoreException {
+ IProjectDescription desc = project.getDescription();
+ ICommand[] commands = desc.getBuildSpec();
+
+ for (int i = 0; i < commands.length; ++i) {
+ if (commands[i].getBuilderName().equals(LisaacBuilder.BUILDER_ID)) {
+ return;
+ }
+ }
+
+ ICommand[] newCommands = new ICommand[commands.length + 1];
+ System.arraycopy(commands, 0, newCommands, 0, commands.length);
+ ICommand command = desc.newCommand();
+ command.setBuilderName(LisaacBuilder.BUILDER_ID);
+ newCommands[newCommands.length - 1] = command;
+ desc.setBuildSpec(newCommands);
+ project.setDescription(desc, null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IProjectNature#deconfigure()
+ */
+ public void deconfigure() throws CoreException {
+ IProjectDescription description = getProject().getDescription();
+ ICommand[] commands = description.getBuildSpec();
+ for (int i = 0; i < commands.length; ++i) {
+ if (commands[i].getBuilderName().equals(LisaacBuilder.BUILDER_ID)) {
+ ICommand[] newCommands = new ICommand[commands.length - 1];
+ System.arraycopy(commands, 0, newCommands, 0, i);
+ System.arraycopy(commands, i + 1, newCommands, i,
+ commands.length - i - 1);
+ description.setBuildSpec(newCommands);
+ return;
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IProjectNature#getProject()
+ */
+ public IProject getProject() {
+ return project;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
+ */
+ public void setProject(IProject project) {
+ this.project = project;
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/builder/LisaacParseException.java b/src/org/eclipse/lisaac/builder/LisaacParseException.java
new file mode 100644
index 0000000..aae6c0f
--- /dev/null
+++ b/src/org/eclipse/lisaac/builder/LisaacParseException.java
@@ -0,0 +1,14 @@
+package org.eclipse.lisaac.builder;
+
+public class LisaacParseException extends Exception {
+
+ int line;
+
+ LisaacParseException(String msg, int line) {
+ super(msg);
+ }
+
+ public int getLineNumber() {
+ return line;
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/AbstractLisaacEditor.java b/src/org/eclipse/lisaac/editors/AbstractLisaacEditor.java
new file mode 100644
index 0000000..f92c2f5
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/AbstractLisaacEditor.java
@@ -0,0 +1,133 @@
+package org.eclipse.lisaac.editors;
+
+import java.util.ListResourceBundle;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewerExtension2;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.lisaac.views.LisaacOutlineView;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+/**
+ * Main class for the Lisaac editor
+ * @author Damien Bouvarel
+ */
+public class AbstractLisaacEditor extends TextEditor {
+
+ private ColorManager colorManager;
+
+ /** the outline view. */
+ private LisaacOutlineView outlineView;
+
+ public AbstractLisaacEditor() {
+ super();
+ colorManager = new ColorManager();
+
+ setSourceViewerConfiguration(new LisaacConfiguration(colorManager));
+ setDocumentProvider(new LisaacDocumentProvider());
+ }
+
+ public IDocument getDocument() {
+ return getDocumentProvider().getDocument(getEditorInput());
+ }
+
+ public void dispose() {
+ colorManager.dispose();
+ super.dispose();
+ }
+
+ public static class MyResources extends ListResourceBundle {
+ public Object[][] getContents() {
+ return contents;
+ }
+
+ static final Object[][] contents = { { "CorrectionAssist", "CorrectionAssist" }, { "ContentAssistProposal", "ContentAssistProposal" }, { "TemplateProposals", "TemplateProposals" }, };
+ }
+
+ protected void createActions() {
+ super.createActions();
+
+ MyResources ressources = new MyResources();
+
+ Action action = new ContentAssistAction(ressources, "ContentAssistProposal.", this); //$NON-NLS-1$
+ String id = ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS;
+ action.setActionDefinitionId(id);
+ setAction("ContentAssistProposal", action);
+ markAsStateDependentAction("ContentAssistProposal", true);
+ }
+
+ public void doSave(IProgressMonitor progressMonitor) {
+ super.doSave(progressMonitor);
+
+ LisaacModel model = LisaacModel.getModel(getProject());
+ if (model != null) {
+ model.buildAll();
+ }
+ }
+ /**
+ * Redraw whole text presentation of the editor
+ */
+ public void refreshPresentation() {
+ refreshPresentation(0, getDocument().getLength());
+ }
+ /**
+ * Redraw region of text presentation of the editor
+ * @param offset redraw region offset
+ * @param length redraw region length
+ */
+ public void refreshPresentation(int offset, int length) {
+ ISourceViewer viewer = getSourceViewer();
+ if (viewer instanceof ITextViewerExtension2) {
+ ITextViewerExtension2 ext = (ITextViewerExtension2) viewer;
+ ext.invalidateTextPresentation(offset, length);
+ }
+ }
+
+ /**
+ * @return the project for the file that's being edited (or null if not available)
+ */
+ public IProject getProject() {
+ IEditorInput editorInput = this.getEditorInput();
+ if (editorInput instanceof FileEditorInput) {
+ IFile file = (IFile) ((FileEditorInput) editorInput).getAdapter(IFile.class);
+ return file.getProject();
+ }
+ return null;
+ }
+
+ /**
+ * @return the file name for the file that's being edited (or null if not available)
+ */
+ public String getFileName() {
+ IEditorInput editorInput = this.getEditorInput();
+ if (editorInput instanceof FileEditorInput) {
+ IFile file = (IFile) ((FileEditorInput) editorInput).getAdapter(IFile.class);
+ return file.getName();
+ }
+ return null;
+ }
+
+ /**
+ * @see AbstractTextEditor#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class required) {
+ if (IContentOutlinePage.class.equals(required)) {
+ if (outlineView == null) {
+ outlineView = new LisaacOutlineView(getDocumentProvider(), this);
+ }
+ return outlineView;
+ } else {
+ return super.getAdapter(required);
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/ColorManager.java b/src/org/eclipse/lisaac/editors/ColorManager.java
new file mode 100644
index 0000000..a16ed75
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/ColorManager.java
@@ -0,0 +1,28 @@
+package org.eclipse.lisaac.editors;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+public class ColorManager {
+
+ protected Map<RGB,Color> fColorTable = new HashMap<RGB,Color>(10);
+
+ public void dispose() {
+ Iterator<Color> e = fColorTable.values().iterator();
+ while (e.hasNext())
+ ((Color) e.next()).dispose();
+ }
+ public Color getColor(RGB rgb) {
+ Color color = (Color) fColorTable.get(rgb);
+ if (color == null) {
+ color = new Color(Display.getCurrent(), rgb);
+ fColorTable.put(rgb, color);
+ }
+ return color;
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/ILisaacColor.java b/src/org/eclipse/lisaac/editors/ILisaacColor.java
new file mode 100644
index 0000000..42d27f2
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/ILisaacColor.java
@@ -0,0 +1,23 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * Associate a color to each token lexical class.
+ * @author Damien Bouvarel
+ */
+public interface ILisaacColor {
+ RGB COMMENT = new RGB(200, 50, 0);
+ RGB PROTOTYPE = new RGB(0, 128, 0);
+ RGB PROTOTYPE_STYLE = new RGB(255, 0, 0);
+ RGB KEYWORD = new RGB(128, 0, 255);
+ RGB CHARACTER = new RGB(128, 128, 255);
+ RGB STRING = new RGB(210, 150, 150);
+ RGB NUMBER = new RGB(128, 0, 255);
+ RGB OPERATOR = new RGB(200, 130, 0);
+ RGB EXTERNAL = new RGB(128, 255, 128);
+ RGB UNDEFINED = new RGB(0, 0, 255);
+ RGB DEFAULT = new RGB(0, 0, 0);
+
+ RGB PROC_INSTR = new RGB(128, 128, 128);// xml a virer
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/editors/LipEditor.java b/src/org/eclipse/lisaac/editors/LipEditor.java
new file mode 100644
index 0000000..35dffe5
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LipEditor.java
@@ -0,0 +1,25 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+/**
+ * Main class for the Lip editor
+ * @author Damien Bouvarel
+ */
+public class LipEditor extends AbstractLisaacEditor {
+
+ public LipEditor() {
+ super();
+ }
+
+ /**
+ * @see AbstractTextEditor#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class required) {
+ if (IContentOutlinePage.class.equals(required)) {
+ return null; // no outline
+ } else {
+ return super.getAdapter(required);
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/LisaacAutoEditStrategy.java b/src/org/eclipse/lisaac/editors/LisaacAutoEditStrategy.java
new file mode 100644
index 0000000..e444a56
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacAutoEditStrategy.java
@@ -0,0 +1,359 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+
+
+public class LisaacAutoEditStrategy extends DefaultIndentLineAutoEditStrategy {
+
+ /**
+ * @see DefaultIndentLineAutoEditStrategy#customizeDocumentCommand(IDocument, DocumentCommand)
+ */
+ public void customizeDocumentCommand(IDocument d, DocumentCommand c) {
+ editDocumentCommand(d, c);
+ }
+
+ /**
+ * Customizes the given document command to edit the given document.
+ * @param document the document
+ * @param command the command
+ * @see DefaultIndentLineAutoEditStrategy#customizeDocumentCommand(IDocument, DocumentCommand)
+ */
+ protected void editDocumentCommand(IDocument document, DocumentCommand command) {
+ String textCommand = command.text;
+
+ if (textCommand != null) {
+ String[] lineDelimiters = document.getLegalLineDelimiters();
+ int endOfLineIndex = TextUtilities.endsWith(lineDelimiters, textCommand);
+
+ if (endOfLineIndex > -1) {
+ // this is an end of line
+ indentOnNewLine(document, command);
+ } else if (textCommand.equals("\t")) {
+ // this is a tab
+ indentOnTab(document, command);
+ } else {
+ // this is another character or string
+ indentOnSpecificChar(document, command);
+ }
+ }
+ }
+
+ /**
+ * Indent One line.
+ * @param indentLine line to be indented
+ * @param document
+ * @param command
+ * @return last indentation for the next line
+ */
+ private static void doIndentLine(int indentLine, IDocument document, DocumentCommand command) {
+ try {
+ //
+ // find last line indent
+ //
+
+ int lastIndent = getIndentWithPreviousLine(indentLine, document);
+
+ //
+ // current line indent
+ //
+ IRegion currentLineInfo = document.getLineInformation(indentLine);
+
+ int lineStart = currentLineInfo.getOffset();
+ int lineEnd = currentLineInfo.getOffset() + currentLineInfo.getLength();
+
+ IRegion originalBlankRegion = getBlankAfterOffset(document, lineStart);
+ int currentIndent = originalBlankRegion.getLength();
+
+ // special case
+ if (lineEnd - originalBlankRegion.getOffset()+currentIndent > 8) {
+ String instr = document.get(originalBlankRegion.getOffset()+currentIndent,8);
+ if (instr.startsWith("Section ")) {
+ lastIndent = 2;
+
+ // insertion in current line
+ if (command != null) {
+ command.text = "";
+ command.offset = lineStart;
+ command.length = currentIndent;
+ } else {
+ document.replace(lineStart, currentIndent, "");
+ }
+ return;
+ }
+ }
+ int i = lineEnd-1;
+ int indent2 = 0;
+ while (i >= lineStart) {
+ char c = document.getChar(i);
+ switch (c) {
+ case '{':
+ case '(':
+ case '[':
+ if (indent2 != 0) {
+ indent2 -= 2;
+ }
+ break;
+ case '}':
+ case ')':
+ case ']':
+ indent2 += 2;
+ break;
+ case '\"':// string " "
+ do {
+ i--;
+ if (i >= lineStart) {
+ c = document.getChar(i);
+ }
+ } while (i >= lineStart && c != '\"');
+ break;
+ case '\'':// string ' '
+ do {
+ i--;
+ if (i >= lineStart) {
+ c = document.getChar(i);
+ }
+ } while (i >= lineStart && c != '\'');
+ break;
+ }
+ i--;
+ }
+ //
+ // insertion in current line
+ //
+ lastIndent -= indent2;
+
+ if (command != null) {
+ command.text = createString(lastIndent);
+ command.offset = lineStart;
+ command.length = currentIndent;
+ } else {
+ document.replace(lineStart, currentIndent, createString(lastIndent));
+ }
+
+ } catch (BadLocationException excp) {
+ // stop work
+ }
+ }
+
+ /**
+ * Get line indentation using previous line.
+ */
+ private static int getIndentWithPreviousLine(int line, IDocument document) {
+ int result = 0;
+ try {
+ //
+ // find last line indent
+ //
+ while (line > 0) {
+ line--;
+ IRegion lineRegion = document.getLineInformation(line);
+
+ int lineStart = lineRegion.getOffset();
+ int lineEnd = lineRegion.getOffset() + lineRegion.getLength();
+
+ IRegion originalBlankRegion = getBlankAfterOffset(document, document.getLineOffset(line));
+ result = originalBlankRegion.getLength();
+
+ // special case
+ if (lineEnd - originalBlankRegion.getOffset()+result > 8) {
+ String instr = document.get(originalBlankRegion.getOffset()+result,8);
+ if (instr.startsWith("Section ")) {
+ result = 2;
+ break;
+ }
+ }
+ int i = lineStart;
+ int deltaIndent = 0;
+ while (i < lineEnd) {
+ char c = document.getChar(i);
+ switch (c) {
+ case '{':
+ case '(':
+ case '[':
+ deltaIndent += 2;
+ break;
+ case '}':
+ case ')':
+ case ']':
+ if (deltaIndent != 0) {
+ deltaIndent -= 2;
+ }
+ break;
+ case '\"':// string " "
+ do {
+ i++;
+ if (i < lineEnd) {
+ c = document.getChar(i);
+ }
+ } while (i < lineEnd && c != '\"');
+ break;
+ case '\'':// string ' '
+ do {
+ i++;
+ if (i < lineEnd) {
+ c = document.getChar(i);
+ }
+ } while (i < lineEnd && c != '\'');
+ break;
+ }
+ i++;
+ }
+ result += deltaIndent;
+
+ if (getBlankEnd(document,lineStart) != lineEnd) {
+ // not empty line
+ break;
+ }
+ }
+ } catch (BadLocationException excp) {
+ // stop work
+ }
+ return result;
+ }
+
+ /**
+ * Get the blank region of given line after offset
+ */
+ private static int getBlankEnd(IDocument document, int offset) throws BadLocationException {
+ IRegion lineRegion = document.getLineInformationOfOffset(offset);
+ int blankEnd = offset;
+ int maxBlankEnd = lineRegion.getOffset() + lineRegion.getLength();
+
+ while (blankEnd < maxBlankEnd) {
+ char c = document.getChar(blankEnd);
+ if (c != ' ' && c != '\t') {
+ break;
+ }
+ blankEnd++;
+ }
+ return blankEnd;
+ }
+
+ /**
+ * Customizes the given command to edit the given document when a newline is pressed.
+ * @param document the document
+ * @param command the command
+ */
+ protected void indentOnNewLine(IDocument document, DocumentCommand command) {
+ try {
+ int p = (command.offset == document.getLength() ? command.offset - 1 : command.offset);
+ int line = document.getLineOfOffset(p);
+
+ // indent previous line
+ doIndentLine(line, document, command);
+
+ // get indent for new line
+ int indent = getIndentWithPreviousLine(line+1, document);
+
+ //
+ // indent new line
+ //
+ IRegion info = document.getLineInformation(line);
+ command.addCommand(info.getOffset() + info.getLength(), 0, "\n"+createString(indent), null);
+ command.shiftsCaret = true;
+ command.caretOffset = info.getOffset() + info.getLength();
+
+ } catch (BadLocationException excp) {
+ // stop work
+ }
+ }
+
+ /**
+ * Get the blank region of given line after offset
+ */
+ private static IRegion getBlankAfterOffset(IDocument document, int offset) throws BadLocationException {
+ IRegion lineRegion = document.getLineInformationOfOffset(offset);
+ int blankEnd = offset;
+ int maxBlankEnd = lineRegion.getOffset() + lineRegion.getLength();
+
+ while (blankEnd < maxBlankEnd) {
+ char c = document.getChar(blankEnd);
+ if (c != ' ' && c != '\t') {
+ break;
+ }
+ blankEnd++;
+ }
+ return new Region(offset, blankEnd - offset);
+ }
+
+ /**
+ * Returns a blank string of the given length.
+ * @param length the length of the string to create
+ * @return a blank string of the given length
+ */
+ public static String createString(int length) {
+ StringBuffer buffer = new StringBuffer(length);
+
+ for (int index = 0 ; index < length ; index++) {
+ buffer.append(' ');
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Customizes the given command to edit the given document when a tabulation is pressed.
+ * @param document the document
+ * @param command the command
+ */
+ protected void indentOnTab(IDocument document, DocumentCommand command) {
+
+ //fullIndentDocument(document);
+
+ try {
+ int p = (command.offset == document.getLength() ? command.offset - 1 : command.offset);
+ int line = document.getLineOfOffset(p);
+
+ doIndentLine(line, document, command);
+
+ } catch (BadLocationException excp) {
+ // stop work
+ }
+ }
+
+ /**
+ * Customizes the given command to edit the given document when a specific character is pressed.
+ * @param document the document
+ * @param command the command
+ */
+ protected void indentOnSpecificChar(IDocument document, DocumentCommand command) {
+ // TODO code templates!!!
+ }
+
+ /**
+ * Indent correctly the whole document
+ * @param document the document
+ */
+ public static void fullIndentDocument(IDocument document) {
+ int line = 0;
+ int maxLine = document.getNumberOfLines();
+
+ while (line < maxLine) {
+ doIndentLine(line, document, null);
+ line++;
+ }
+ }
+
+ /**
+ * Indent correctly part of a document
+ * @param document the document
+ */
+ public static void fullIndentDocument(IDocument document, int offset, int length) {
+ try {
+ int line = document.getLineOfOffset(offset);
+ int maxLine = document.getNumberOfLines(offset, length);
+
+ while (line < maxLine) { // TODO indent part of document
+ // indentLine(line, document);
+ line++;
+ }
+ } catch (BadLocationException excp) {
+ // stop work
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/LisaacCompletionProcessor.java b/src/org/eclipse/lisaac/editors/LisaacCompletionProcessor.java
new file mode 100644
index 0000000..dee94b3
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacCompletionProcessor.java
@@ -0,0 +1,140 @@
+package org.eclipse.lisaac.editors;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+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;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.lisaac.builder.ILisaacErrorHandler;
+import org.eclipse.lisaac.model.LisaacCompletionParser;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.lisaac.model.LisaacParser;
+import org.eclipse.lisaac.model.Position;
+import org.eclipse.lisaac.model.items.ICode;
+import org.eclipse.lisaac.model.items.Prototype;
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+
+
+public class LisaacCompletionProcessor implements IContentAssistProcessor {
+
+ private final IContextInformation[] NO_CONTEXTS = new IContextInformation[0];
+ private final char[] PROPOSAL_ACTIVATION_CHARS = new char[] { '.', '('};
+ private ICompletionProposal[] NO_COMPLETIONS = new ICompletionProposal[0];
+
+
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+ try {
+ IDocument document = viewer.getDocument();
+ ArrayList<CompletionProposal> result = new ArrayList<CompletionProposal>();
+
+ //
+ computeLisaacCompletion(document, offset, result);
+ //
+ String prefix = lastWord(document, offset);
+
+ if (prefix.startsWith("Sec")) {
+ result.add(new CompletionProposal("Section",3,4,3));
+ }
+
+ return (ICompletionProposal[]) result.toArray(new ICompletionProposal[result.size()]);
+ } catch (Exception e) {
+ // ... log the exception ...
+ return NO_COMPLETIONS;
+ }
+
+ }
+
+ private void computeLisaacCompletion(IDocument document, int baseOffset,
+ ArrayList<CompletionProposal> proposals) {
+ int bracketLevel=0;
+ //
+ // Rewind to '(' ';' '['
+ //
+ try {
+ int pos = baseOffset-1;
+ while (pos > 0) {
+ char c = document.getChar(pos);
+ if (c == ';') {
+ break;
+ }
+ if (c == '(' || c == '[') {
+ if (bracketLevel == 0) {
+ break;
+ }
+ bracketLevel--;
+ }
+ if (c == ')' || c == ']') {
+ bracketLevel++;
+ }
+ pos--;
+ }
+ if (pos > 0) {
+ //
+ // compute lisaac expression type
+ //
+ String contents = document.get(pos+1, baseOffset-1 - pos);
+
+ LisaacCompletionParser parser = new LisaacCompletionParser(contents);
+ parser.parseCompletions(pos+1, baseOffset, proposals);
+ }
+ } catch (BadLocationException e) {
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+
+
+ 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) {
+ return NO_CONTEXTS;
+ }
+
+
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return PROPOSAL_ACTIVATION_CHARS;
+ }
+
+
+ public char[] getContextInformationAutoActivationCharacters() {
+ return null;
+ }
+
+ public IContextInformationValidator getContextInformationValidator() {
+ return null;
+ }
+
+ public String getErrorMessage() {
+ return "Lisaac Completion error";
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/editors/LisaacConfiguration.java b/src/org/eclipse/lisaac/editors/LisaacConfiguration.java
new file mode 100644
index 0000000..a9f26b1
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacConfiguration.java
@@ -0,0 +1,132 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
+import org.eclipse.jface.text.IAutoEditStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
+import org.eclipse.jface.text.hyperlink.URLHyperlinkDetector;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+
+/**
+ * Manage the configuration of syntax coloration for lisaac documents.
+ */
+public class LisaacConfiguration extends SourceViewerConfiguration {
+ private LisaacDoubleClickStrategy doubleClickStrategy;
+ private LisaacScanner scanner;
+ private ColorManager colorManager;
+
+ private ContentAssistant contentAssistant = null;
+
+ public LisaacConfiguration(ColorManager colorManager) {
+ this.colorManager = colorManager;
+ }
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+ return new String[] {
+ IDocument.DEFAULT_CONTENT_TYPE,
+ LisaacPartitionScanner.LISAAC_COMMENT
+ };
+ }
+
+ public ITextDoubleClickStrategy getDoubleClickStrategy(
+ ISourceViewer sourceViewer,
+ String contentType) {
+ if (doubleClickStrategy == null)
+ doubleClickStrategy = new LisaacDoubleClickStrategy();
+ return doubleClickStrategy;
+ }
+
+ /**
+ * Returns the content assistant ready to be used with the given source viewer.
+ * This implementation always returns <code>null</code>.
+ *
+ * @param sourceViewer the source viewer to be configured by this configuration
+ * @return a content assistant or <code>null</code> if content assist should not be supported
+ */
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+ if (contentAssistant == null) {
+ contentAssistant = new ContentAssistant();
+ IContentAssistProcessor cap = new LisaacCompletionProcessor();
+ contentAssistant.setContentAssistProcessor(cap, IDocument.DEFAULT_CONTENT_TYPE);
+ // contentAssistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
+
+ contentAssistant.enableAutoActivation(true);
+ contentAssistant.setAutoActivationDelay(500);
+ contentAssistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
+ }
+ return contentAssistant;
+ }
+
+ /**
+ * @see SourceViewerConfiguration#getAutoEditStrategies(ISourceViewer, String)
+ */
+ public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) {
+
+ if (contentType.equals(LisaacPartitionScanner.LISAAC_COMMENT)) {
+ return new IAutoEditStrategy[] { new DefaultIndentLineAutoEditStrategy() };
+
+ } else if (contentType.equals(IDocument.DEFAULT_CONTENT_TYPE)) {
+ return new IAutoEditStrategy[] { new LisaacAutoEditStrategy() };
+
+ } else {
+ return super.getAutoEditStrategies(sourceViewer, contentType);
+ }
+ }
+
+ /**
+ * @see SourceViewerConfiguration#getIndentPrefixes(ISourceViewer, String)
+ */
+ public String[] getIndentPrefixes(ISourceViewer sourceViewer, String contentType) {
+ return new String[]{ new String(" "), new String() };
+ }
+
+ /**
+ * Returns the hyperlink detectors which be used to detect hyperlinks
+ * in the given source viewer.
+ * @param sourceViewer the source viewer to be configured by this configuration
+ * @return an array with hyperlink detectors or <code>null</code> if no hyperlink support should be installed
+ * @since 3.1
+ */
+ public IHyperlinkDetector[] getHyperlinkDetectors(ISourceViewer sourceViewer) {
+ if (sourceViewer == null)
+ return null;
+
+ return new IHyperlinkDetector[] { new LisaacHyperLinkDetector(), new URLHyperlinkDetector() };
+ }
+
+ protected LisaacScanner getLisaacScanner() {
+ if (scanner == null) {
+ scanner = new LisaacScanner(colorManager);
+ scanner.setDefaultReturnToken(
+ new Token(
+ new TextAttribute(
+ colorManager.getColor(ILisaacColor.DEFAULT))));
+ }
+ return scanner;
+ }
+
+ public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+ PresentationReconciler reconciler = new PresentationReconciler();
+
+ LisaacDamagerRepairer dr = new LisaacDamagerRepairer(getLisaacScanner());
+ reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+ NonRuleBasedDamagerRepairer ndr =
+ new NonRuleBasedDamagerRepairer(
+ new TextAttribute(
+ colorManager.getColor(ILisaacColor.COMMENT)));
+ reconciler.setDamager(ndr, LisaacPartitionScanner.LISAAC_COMMENT);
+ reconciler.setRepairer(ndr, LisaacPartitionScanner.LISAAC_COMMENT);
+
+ return reconciler;
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/editors/LisaacDamagerRepairer.java b/src/org/eclipse/lisaac/editors/LisaacDamagerRepairer.java
new file mode 100644
index 0000000..f1ca3ab
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacDamagerRepairer.java
@@ -0,0 +1,60 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.ITokenScanner;
+import org.eclipse.jface.text.rules.Token;
+
+public class LisaacDamagerRepairer extends DefaultDamagerRepairer{
+
+ public LisaacDamagerRepairer(ITokenScanner scanner) {
+ super(scanner);
+ }
+
+ /*
+ * @see IPresentationRepairer#createPresentation(TextPresentation, ITypedRegion)
+ */
+ public void createPresentation(TextPresentation presentation, ITypedRegion region) {
+
+ if (fScanner == null) {
+ // will be removed if deprecated constructor will be removed
+ addRange(presentation, region.getOffset(), region.getLength(), fDefaultTextAttribute);
+ return;
+ }
+
+ int lastStart= region.getOffset();
+ int length= 0;
+ boolean firstToken= true;
+ IToken lastToken= Token.UNDEFINED;
+ TextAttribute lastAttribute= getTokenTextAttribute(lastToken);
+
+ fScanner.setRange(fDocument, lastStart, region.getLength());
+
+ while (true) {
+ IToken token= fScanner.nextToken();
+ if (token.isEOF())
+ break;
+
+ // define text attribute for this token
+ TextAttribute attribute= getTokenTextAttribute(token);
+ if (lastAttribute != null && lastAttribute.equals(attribute)) {
+ length += fScanner.getTokenLength();
+ firstToken= false;
+ } else {
+ if (!firstToken)
+ addRange(presentation, lastStart, length, lastAttribute);
+ firstToken= false;
+ lastToken= token;
+ lastAttribute= attribute;
+ lastStart= fScanner.getTokenOffset();
+ length= fScanner.getTokenLength();
+ }
+ }
+
+ // process last token
+ addRange(presentation, lastStart, length, lastAttribute);
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/LisaacDocumentProvider.java b/src/org/eclipse/lisaac/editors/LisaacDocumentProvider.java
new file mode 100644
index 0000000..5c2e0f6
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacDocumentProvider.java
@@ -0,0 +1,44 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.ui.editors.text.FileDocumentProvider;
+import org.eclipse.ui.part.FileEditorInput;
+
+/**
+ * Handle the creation of lisaac document.<br>
+ * Attach lisaac partitioning to this documents.
+ */
+public class LisaacDocumentProvider extends FileDocumentProvider {
+
+ protected IDocument createDocument(Object element) throws CoreException {
+ IDocument document = super.createDocument(element);
+ if (document != null) {
+ IDocumentPartitioner partitioner =
+ new FastPartitioner(
+ new LisaacPartitionScanner(),
+ new String[] {
+ LisaacPartitionScanner.LISAAC_DEFAULT,
+ LisaacPartitionScanner.LISAAC_COMMENT });
+ partitioner.connect(document);
+ document.setDocumentPartitioner(partitioner);
+ }
+ return document;
+ }
+
+ public void setupDocument(Object element, IDocument document) {
+ // first lisaac build.
+ if (element instanceof FileEditorInput) {
+ IFile file = ((FileEditorInput) element).getFile();
+
+ LisaacModel model = LisaacModel.getModel(file.getProject());
+ if (model != null) {
+ model.buildAll();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/editors/LisaacDoubleClickStrategy.java b/src/org/eclipse/lisaac/editors/LisaacDoubleClickStrategy.java
new file mode 100644
index 0000000..7e2c477
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacDoubleClickStrategy.java
@@ -0,0 +1,56 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.*;
+
+public class LisaacDoubleClickStrategy implements ITextDoubleClickStrategy {
+ protected ITextViewer fText;
+
+ public void doubleClicked(ITextViewer part) {
+ int pos = part.getSelectedRange().x;
+
+ if (pos < 0)
+ return;
+
+ fText = part;
+ selectWord(pos);
+ }
+
+ protected boolean selectWord(int caretPos) {
+ IDocument doc = fText.getDocument();
+ int startPos, endPos;
+
+ try {
+ int pos = caretPos;
+ char c;
+
+ while (pos >= 0) {
+ c = doc.getChar(pos);
+ if (!Character.isJavaIdentifierPart(c))
+ break;
+ --pos;
+ }
+ startPos = pos;
+ pos = caretPos;
+ int length = doc.getLength();
+
+ while (pos < length) {
+ c = doc.getChar(pos);
+ if (!Character.isJavaIdentifierPart(c))
+ break;
+ ++pos;
+ }
+ endPos = pos;
+ selectRange(startPos, endPos);
+ return true;
+
+ } catch (BadLocationException x) {
+ }
+ return false;
+ }
+
+ private void selectRange(int startPos, int stopPos) {
+ int offset = startPos + 1;
+ int length = stopPos - offset;
+ fText.setSelectedRange(offset, length);
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/editors/LisaacEditor.java b/src/org/eclipse/lisaac/editors/LisaacEditor.java
new file mode 100644
index 0000000..b165549
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacEditor.java
@@ -0,0 +1,13 @@
+package org.eclipse.lisaac.editors;
+
+
+/**
+ * Main class for the Lisaac editor
+ * @author Damien Bouvarel
+ */
+public class LisaacEditor extends AbstractLisaacEditor {
+
+ public LisaacEditor() {
+ super();
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/LisaacHyperLinkDetector.java b/src/org/eclipse/lisaac/editors/LisaacHyperLinkDetector.java
new file mode 100644
index 0000000..a65f116
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacHyperLinkDetector.java
@@ -0,0 +1,62 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+
+
+public class LisaacHyperLinkDetector extends AbstractHyperlinkDetector {
+
+ public IHyperlink[] detectHyperlinks(ITextViewer textViewer,
+ IRegion region, boolean canShowMultipleHyperlinks) {
+
+ if (region == null || textViewer == null)
+ return null;
+
+ IDocument document= textViewer.getDocument();
+ if (document == null)
+ return null;
+
+ try {
+ int offset= region.getOffset();
+
+ IRegion wordRegion = selectWord(document, offset);
+ String prototypeString = document.get(wordRegion.getOffset(), wordRegion.getLength());
+
+ return new IHyperlink[] {new PrototypeHyperLink(wordRegion, prototypeString)};
+
+ } catch (BadLocationException e) {
+ return null;
+ }
+ }
+
+ protected IRegion selectWord(IDocument doc, int caretPos) throws BadLocationException {
+ int startPos, endPos;
+
+ int pos = caretPos;
+ char c;
+
+ while (pos >= 0) {
+ c = doc.getChar(pos);
+ if (!Character.isJavaIdentifierPart(c))
+ break;
+ --pos;
+ }
+ startPos = pos+1;
+ pos = caretPos;
+ int length = doc.getLength();
+
+ while (pos < length) {
+ c = doc.getChar(pos);
+ if (!Character.isJavaIdentifierPart(c))
+ break;
+ ++pos;
+ }
+ endPos = pos;
+ return new Region(startPos, endPos - startPos);
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/LisaacPartitionScanner.java b/src/org/eclipse/lisaac/editors/LisaacPartitionScanner.java
new file mode 100644
index 0000000..8cbca3a
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacPartitionScanner.java
@@ -0,0 +1,30 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.rules.*;
+
+/**
+ * Define rules to allow document partitioning.<br>
+ * We have two types of partition: lisaac code and lisaac comments.
+ */
+public class LisaacPartitionScanner extends RuleBasedPartitionScanner {
+ public final static String LISAAC_COMMENT = "__lisaac_comment";
+ public final static String LISAAC_DEFAULT = "__lisaac_default";
+
+ public LisaacPartitionScanner() {
+ /*
+ * Define rules to identify comment partition, the rest of documents is default partition
+ */
+ IToken comment = new Token(LISAAC_COMMENT);
+
+ IPredicateRule[] rules = new IPredicateRule[4];
+
+ rules[0] = new MultiLineRule("/*", "*/", comment);
+ rules[1] = new EndOfLineRule("//", comment);
+
+ // avoid processing comment inside lisaac strings
+ rules[2] = new SingleLineRule("\"", "\"", Token.UNDEFINED, '\0', true);
+ rules[3] = new SingleLineRule("`", "`", Token.UNDEFINED, '\0', true);
+
+ setPredicateRules(rules);
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/LisaacScanner.java b/src/org/eclipse/lisaac/editors/LisaacScanner.java
new file mode 100644
index 0000000..6528940
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacScanner.java
@@ -0,0 +1,322 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.*;
+import org.eclipse.jface.text.rules.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+
+class LisaacWhitespaceDetector implements IWhitespaceDetector {
+ public boolean isWhitespace(char c) {
+ return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+ // return c.isWhitespace();
+ }
+}
+
+class LisaacPrototypeDetector implements IWordDetector {
+ public boolean isWordPart(char c) {
+ return (Character.isLetter(c) && Character.isUpperCase(c))
+ || Character.isDigit(c) || c == '_';
+ }
+
+ public boolean isWordStart(char c) {
+ return (Character.isLetter(c) && Character.isUpperCase(c)) || c == '_';
+ }
+}
+
+class LisaacNumberDetector implements IWordDetector {
+ public boolean isWordPart(char c) {
+ return Character.isLetterOrDigit(c);
+ }
+
+ public boolean isWordStart(char c) {
+ return Character.isDigit(c);
+ }
+}
+
+class LisaacKeywordDetector implements IWordDetector {
+ public boolean isWordPart(char c) {
+ return Character.isLetter(c) && Character.isLowerCase(c);
+ }
+
+ public boolean isWordStart(char c) {
+ return Character.isLetter(c) && Character.isUpperCase(c);
+ }
+}
+
+class LisaacWordDetector implements IWordDetector {
+ public boolean isWordPart(char c) {
+ return (Character.isLetter(c) && Character.isLowerCase(c))
+ || Character.isDigit(c) || c == '_';
+ }
+
+ public boolean isWordStart(char c) {
+ return (Character.isLetter(c) && Character.isLowerCase(c)) || c == '_';
+ }
+}
+
+/**
+ * Lisaac code scanner.<br>
+ * Scan a range of a document into tokens, the scanner is used by the repairer
+ * to create the text presentation.
+ */
+public class LisaacScanner extends RuleBasedScanner {
+ private ColorManager manager;
+
+ private static String[] keywords = new String[] { "Section", "Public",
+ "Private", "Inherit", "Header", "Insert", "Mapping", "Interrupt",
+ "External", "Directory",
+ "Expanded", "Strict",
+ "Left", "Right",
+ "Self",};
+
+ // Lisaac tokens
+ private IToken stringToken;
+ private IToken characterToken;
+ private IToken numberToken;
+ private IToken prototypeToken;
+ private IToken prototypeStyleToken;
+ private IToken keywordToken;
+ private IToken localVariableToken;
+ private IToken operatorToken;
+ private IToken externalToken;
+ private IToken undefinedToken;
+
+ private TextAttribute getAttribute(RGB rgb) {
+ return new TextAttribute(manager.getColor(rgb));
+ }
+
+ /*// italic, bold, etc..
+ * private TextAttribute getAttributeSpecial(RGB rgb, int font) { return new
+ * TextAttribute(manager.getColor(rgb),null, font); }
+ */
+
+ /**
+ * Creates a new Lisaac scanner.
+ */
+ public LisaacScanner(ColorManager manager) {
+ this.manager = manager;
+ /*
+ * Create lisaac tokens.
+ */
+
+ stringToken = new Token(getAttribute(ILisaacColor.STRING));
+ characterToken = new Token(getAttribute(ILisaacColor.CHARACTER));
+ numberToken = new Token(getAttribute(ILisaacColor.NUMBER));
+ prototypeToken = new Token(getAttribute(ILisaacColor.PROTOTYPE));
+ prototypeStyleToken = new Token(
+ getAttribute(ILisaacColor.PROTOTYPE_STYLE));
+ keywordToken = new Token(getAttribute(ILisaacColor.KEYWORD));
+ localVariableToken = new Token(getAttribute(ILisaacColor.DEFAULT));
+ operatorToken = new Token(getAttribute(ILisaacColor.OPERATOR));
+ externalToken = new Token(new TextAttribute(manager
+ .getColor(ILisaacColor.DEFAULT), manager
+ .getColor(ILisaacColor.EXTERNAL), SWT.NORMAL));
+ undefinedToken = new Token(getAttribute(ILisaacColor.UNDEFINED));
+
+ /*
+ * Create basic lisaac rules.
+ */
+ IRule[] rules = new IRule[8];
+
+ // Add rule for processing strings
+ rules[0] = new SingleLineRule("\"", "\"", stringToken, '\0', true);// double
+ // quotes
+ rules[1] = new SingleLineRule("'", "'", characterToken, '\0', true);// simple
+ // quotes
+
+ // Add generic whitespace rule.
+ rules[2] = new WhitespaceRule(new LisaacWhitespaceDetector());
+
+ // keywords rule
+ WordRule wr = new WordRule(new LisaacKeywordDetector(), Token.UNDEFINED);
+ for (int i = 0; i < keywords.length; i++) {
+ wr.addWord(keywords[i], keywordToken);
+ }
+ rules[3] = wr;
+
+ // prototype rule
+ rules[4] = new WordRule(new LisaacPrototypeDetector(), prototypeToken);
+
+ // simple lisaac word rule
+ //rules[5] = new WordRule(new LisaacWordDetector(), undefinedToken);
+ rules[5] = new LisaacWordRule(new LisaacWordDetector(), undefinedToken, localVariableToken);
+
+ // lisaac external
+ rules[6] = new SingleLineRule("`", "`", externalToken, '\0', true);// back
+ // quotes
+
+ // number rule
+ rules[7] = new WordRule(new LisaacNumberDetector(), numberToken);
+
+ // add basic rules
+ setRules(rules);
+ }
+
+ /*
+ * @see ITokenScanner#nextToken()
+ */
+ public IToken nextToken() {
+
+ fTokenOffset = fOffset;
+ fColumn = UNDEFINED;
+
+ //
+ // Lisaac scan
+ //
+
+ // start processing basic rules first
+ if (fRules != null) {
+ for (int i = 0; i < fRules.length; i++) {
+ IToken token = (fRules[i].evaluate(this));
+ if (!token.isUndefined())
+ return token;
+ }
+ }
+
+ // none of the basic rules fired
+ char c = (char) read();
+ if (c != ICharacterScanner.EOF) {
+ if (c == '+' || c == '-') {
+ if (getColumn() == 3) {// slot style
+ return prototypeStyleToken;
+ }
+ if (detectLocalSlot()) { // local slot style
+ return prototypeStyleToken;
+ }
+ return operatorToken;// arithmetic + or -
+ }
+ if (c == '<') {// list affect
+ c = (char) read();
+ if (c == '-') {
+ return fDefaultReturnToken;
+ } else {
+ unread();
+ return operatorToken;
+ }
+ }
+ if (c == ':') {// slot affect
+ c = (char) read();
+ if (c != '=') {
+ unread();
+ if (detectBlockType()) {
+ return prototypeToken;
+ }
+ }
+ return fDefaultReturnToken;
+ }
+ if (c == '?') {// ?= affect
+ c = (char) read();
+ if (c == '=') {
+ return fDefaultReturnToken;
+ }
+ unread();
+ return operatorToken;
+ }
+ if (c == '*' || c == '/' || c == '&' || c == '$' || c == '|'
+ || c == '>' || c == '=' || c == '!' || c == '~' || c == '@'
+ || c == '#' || c == '^') {
+ return operatorToken;
+ }
+ if (c == '{' || c == '}') {
+ return operatorToken;
+ }
+ }
+
+ unread();
+ //
+ // End of Lisaac scan
+ //
+
+ if (read() == EOF)
+ return Token.EOF;
+ return fDefaultReturnToken;
+ }
+
+ private boolean readIndentifier() {
+ char c;
+ int i = 0;
+
+ do {
+ c = (char) read();
+ i++;
+ } while (c != ICharacterScanner.EOF
+ && (Character.isLetterOrDigit(c) || c == '_'));
+ unread();
+
+ return i > 1;
+ }
+
+ private void readSpace() {
+ char c;
+
+ do {
+ c = (char) read();
+ } while (c != ICharacterScanner.EOF && Character.isWhitespace(c));
+ unread();
+ }
+
+ private boolean detectLocalSlot() {
+ int oldOffset = fOffset;
+ boolean result = false;
+
+ readSpace();
+ while (readIndentifier()) {
+ readSpace();
+ char c = (char) read();
+ if (c == ICharacterScanner.EOF)
+ break;
+
+ if (c == ':') {
+ result = true;
+ break;
+ }
+ if (c != ',')
+ break;
+
+ readSpace();
+ }
+ fOffset = oldOffset;// unread all
+ fColumn = UNDEFINED;
+ return result;
+ }
+
+ private boolean detectBlockType() {
+ int oldOffset = fOffset;
+ boolean result = false;
+
+ readSpace();
+ char c = (char) read();
+ if (c != ICharacterScanner.EOF && c == '{') {
+ int level = 1;
+ do {
+ c = (char) read();
+ if (c != ICharacterScanner.EOF) {
+ if (c == '{') {
+ level++;
+ } else if (c == '}') {
+ level--;
+
+ } else if (c == '\n' || c == '\r') {
+ break; // no multiline type
+
+ } else if (((int)c) == 65535) {
+ break; // bug!
+ }
+ }
+ } while (c != ICharacterScanner.EOF && level != 0);
+
+ if (level == 0) {
+ result = true;
+ }
+ }
+ if (! result) {
+ fOffset = oldOffset;// unread all
+ fColumn = UNDEFINED;
+ }
+ return result;
+ }
+
+ public int getOffset() {
+ return fOffset;
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/LisaacWordRule.java b/src/org/eclipse/lisaac/editors/LisaacWordRule.java
new file mode 100644
index 0000000..6fe5d70
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/LisaacWordRule.java
@@ -0,0 +1,87 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WordRule;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.lisaac.model.items.ITMList;
+import org.eclipse.lisaac.model.items.Prototype;
+import org.eclipse.lisaac.model.items.Slot;
+
+public class LisaacWordRule extends WordRule {
+
+ private IToken localVariableToken;
+
+ private StringBuffer fBuffer= new StringBuffer();
+
+
+ public LisaacWordRule(IWordDetector detector, IToken defaultToken, IToken localVariableToken) {
+ super(detector, defaultToken);
+ this.localVariableToken = localVariableToken;
+ }
+
+ /*
+ * @see IRule#evaluate(ICharacterScanner)
+ */
+ public IToken evaluate(ICharacterScanner scanner) {
+ IToken result = doEvaluate(scanner);
+
+ if (result == fDefaultToken) {
+ //
+ Prototype prototype = LisaacModel.getCurrentPrototype();
+ if (prototype == null) {
+ return result;
+ }
+ //
+ int offset = ((LisaacScanner) scanner).getOffset();
+
+ Slot slot = prototype.getSlot(offset);
+ if (slot != null) {
+ String word = fBuffer.toString();
+
+ if (slot.hasArgument(word)) {
+ return localVariableToken;
+ }
+ if (slot.getValue() instanceof ITMList) {
+ ITMList code = (ITMList) slot.getValue();
+
+ if (code.hasVariableDefinition(word)) {
+ return localVariableToken;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+
+ public IToken doEvaluate(ICharacterScanner scanner) {
+ int c= scanner.read();
+ if (c != ICharacterScanner.EOF && fDetector.isWordStart((char) c)) {
+ if (fColumn == UNDEFINED || (fColumn == scanner.getColumn() - 1)) {
+
+ fBuffer.setLength(0);
+ do {
+ fBuffer.append((char) c);
+ c= scanner.read();
+ } while (c != ICharacterScanner.EOF && fDetector.isWordPart((char) c));
+ scanner.unread();
+
+ String buffer= fBuffer.toString();
+ IToken token= (IToken)fWords.get(buffer);
+
+ if (token != null)
+ return token;
+
+ if (fDefaultToken.isUndefined())
+ unreadBuffer(scanner);
+
+ return fDefaultToken;
+ }
+ }
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+}
diff --git a/src/org/eclipse/lisaac/editors/NonRuleBasedDamagerRepairer.java b/src/org/eclipse/lisaac/editors/NonRuleBasedDamagerRepairer.java
new file mode 100644
index 0000000..200b4b8
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/NonRuleBasedDamagerRepairer.java
@@ -0,0 +1,138 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.presentation.IPresentationDamager;
+import org.eclipse.jface.text.presentation.IPresentationRepairer;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.swt.custom.StyleRange;
+
+public class NonRuleBasedDamagerRepairer
+ implements IPresentationDamager, IPresentationRepairer {
+
+ /** The document this object works on */
+ protected IDocument fDocument;
+ /** The default text attribute if non is returned as data by the current token */
+ protected TextAttribute fDefaultTextAttribute;
+
+ /**
+ * Constructor for NonRuleBasedDamagerRepairer.
+ */
+ public NonRuleBasedDamagerRepairer(TextAttribute defaultTextAttribute) {
+ Assert.isNotNull(defaultTextAttribute);
+
+ fDefaultTextAttribute = defaultTextAttribute;
+ }
+
+ /**
+ * @see IPresentationRepairer#setDocument(IDocument)
+ */
+ public void setDocument(IDocument document) {
+ fDocument = document;
+ }
+
+ /**
+ * Returns the end offset of the line that contains the specified offset or
+ * if the offset is inside a line delimiter, the end offset of the next line.
+ *
+ * @param offset the offset whose line end offset must be computed
+ * @return the line end offset for the given offset
+ * @exception BadLocationException if offset is invalid in the current document
+ */
+ protected int endOfLineOf(int offset) throws BadLocationException {
+
+ IRegion info = fDocument.getLineInformationOfOffset(offset);
+ if (offset <= info.getOffset() + info.getLength())
+ return info.getOffset() + info.getLength();
+
+ int line = fDocument.getLineOfOffset(offset);
+ try {
+ info = fDocument.getLineInformation(line + 1);
+ return info.getOffset() + info.getLength();
+ } catch (BadLocationException x) {
+ return fDocument.getLength();
+ }
+ }
+
+ /**
+ * @see IPresentationDamager#getDamageRegion(ITypedRegion, DocumentEvent, boolean)
+ */
+ public IRegion getDamageRegion(
+ ITypedRegion partition,
+ DocumentEvent event,
+ boolean documentPartitioningChanged) {
+ if (!documentPartitioningChanged) {
+ try {
+
+ IRegion info =
+ fDocument.getLineInformationOfOffset(event.getOffset());
+ int start = Math.max(partition.getOffset(), info.getOffset());
+
+ int end =
+ event.getOffset()
+ + (event.getText() == null
+ ? event.getLength()
+ : event.getText().length());
+
+ if (info.getOffset() <= end
+ && end <= info.getOffset() + info.getLength()) {
+ // optimize the case of the same line
+ end = info.getOffset() + info.getLength();
+ } else
+ end = endOfLineOf(end);
+
+ end =
+ Math.min(
+ partition.getOffset() + partition.getLength(),
+ end);
+ return new Region(start, end - start);
+
+ } catch (BadLocationException x) {
+ }
+ }
+
+ return partition;
+ }
+
+ /**
+ * @see IPresentationRepairer#createPresentation(TextPresentation, ITypedRegion)
+ */
+ public void createPresentation(
+ TextPresentation presentation,
+ ITypedRegion region) {
+ addRange(
+ presentation,
+ region.getOffset(),
+ region.getLength(),
+ fDefaultTextAttribute);
+ }
+
+ /**
+ * Adds style information to the given text presentation.
+ *
+ * @param presentation the text presentation to be extended
+ * @param offset the offset of the range to be styled
+ * @param length the length of the range to be styled
+ * @param attr the attribute describing the style of the range to be styled
+ */
+ protected void addRange(
+ TextPresentation presentation,
+ int offset,
+ int length,
+ TextAttribute attr) {
+ if (attr != null)
+ presentation.addStyleRange(
+ new StyleRange(
+ offset,
+ length,
+ attr.getForeground(),
+ attr.getBackground(),
+ attr.getStyle()));
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/editors/PrototypeHyperLink.java b/src/org/eclipse/lisaac/editors/PrototypeHyperLink.java
new file mode 100644
index 0000000..abf8946
--- /dev/null
+++ b/src/org/eclipse/lisaac/editors/PrototypeHyperLink.java
@@ -0,0 +1,124 @@
+package org.eclipse.lisaac.editors;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.text.IRegion;
+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.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.ide.IDE;
+
+
+
+public class PrototypeHyperLink implements IHyperlink {
+
+ private String fPrototypeString;
+ private IRegion fRegion;
+
+ /**
+ * Creates a new Prototype hyperlink.
+ * @param region
+ * @param urlString
+ */
+ public PrototypeHyperLink(IRegion region, String string) {
+ fRegion= region;
+ fPrototypeString= string;
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.javaeditor.IHyperlink#getHyperlinkRegion()
+ */
+ public IRegion getHyperlinkRegion() {
+ return fRegion;
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.javaeditor.IHyperlink#open()
+ */
+ public void open() {
+ if (fPrototypeString != null) {
+ IProject project = null;
+ final IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPart part = w.getPartService().getActivePart();
+ if (part instanceof LisaacEditor) {
+ project = ((LisaacEditor)part).getProject();
+ }
+
+ if (project != null) {
+ String prototypePath;
+ boolean createLink=false;
+
+ LisaacModel model = LisaacModel.getModel(project);
+ Prototype 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;
+
+ part.getSite().getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage page = w.getActivePage();
+ if (page == null) {
+ return;
+ }
+ IFile file;
+ IPath location = new Path(filename);
+ if (! link) {
+ IContainer src = p.getFolder("src");
+ if (src == null) {
+ src = p;
+ }
+ file = src.getFile(location/*.lastSegment()*/);
+ } else {
+ file = p.getFile(location.lastSegment());
+ }
+ try {
+ if (link) {
+ file.createLink(location, IResource.NONE, null);
+ }
+ IDE.openEditor(page, file);
+ if (link) {
+ //file.delete(true, null);
+ }
+ } catch (CoreException e) {
+ // TODO open editor error
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+ }
+ fPrototypeString = null;
+ }
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.javaeditor.IHyperlink#getHyperlinkText()
+ */
+ public String getHyperlinkText() {
+ return fPrototypeString;
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.javaeditor.IHyperlink#getTypeLabel()
+ */
+ public String getTypeLabel() {
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/handlers/SampleHandler.java b/src/org/eclipse/lisaac/handlers/SampleHandler.java
new file mode 100644
index 0000000..68a230f
--- /dev/null
+++ b/src/org/eclipse/lisaac/handlers/SampleHandler.java
@@ -0,0 +1,70 @@
+package org.eclipse.lisaac.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.lisaac.editors.LisaacEditor;
+import org.eclipse.lisaac.launch.LisaacLauncher;
+import org.eclipse.lisaac.model.LisaacModel;
+
+/**
+ * Our sample handler extends AbstractHandler, an IHandler base class.
+ * @see org.eclipse.core.commands.IHandler
+ * @see org.eclipse.core.commands.AbstractHandler
+ */
+public class SampleHandler extends AbstractHandler {
+ /**
+ * The constructor.
+ */
+ public SampleHandler() {
+ }
+
+ /**
+ * the command has been executed, so extract extract the needed information
+ * from the application context.
+ */
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ IProject project=null;
+ IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+
+ IWorkbenchPart part = w.getPartService().getActivePart();
+ if (part instanceof LisaacEditor) {
+ project = ((LisaacEditor)part).getProject();
+ } else {
+
+ ISelection selection = w.getSelectionService().getSelection();
+ if (selection instanceof IStructuredSelection) {
+ PlatformObject obj = (PlatformObject)((IStructuredSelection)selection).getFirstElement();
+
+ IResource res = ((IResource) obj.getAdapter(IResource.class)).getProject();
+ if (res instanceof IProject) {
+ project = (IProject) res;
+ }
+ }
+ }
+ LisaacModel model = LisaacModel.getModel(project);
+ if (model != null && project != null) {
+ //
+ model.buildAll();
+ //
+ } else {
+ IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
+ MessageDialog.openInformation(
+ window.getShell(),
+ "Lisaac Plug-in",
+ "Please select a project to build.");
+ }
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/launch/LaunchConfiguration.java b/src/org/eclipse/lisaac/launch/LaunchConfiguration.java
new file mode 100644
index 0000000..cd122bd
--- /dev/null
+++ b/src/org/eclipse/lisaac/launch/LaunchConfiguration.java
@@ -0,0 +1,71 @@
+package org.eclipse.lisaac.launch;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
+import org.eclipse.jface.dialogs.MessageDialog;
+
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.lisaac.model.items.Prototype;
+
+
+public class LaunchConfiguration implements ILaunchConfigurationDelegate {
+
+ protected LisaacCompiler compiler;
+
+ public void launch(ILaunchConfiguration configuration, String mode,
+ ILaunch launch, IProgressMonitor monitor) throws CoreException {
+
+ // get project to run
+ String projectName = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_PROJECT, "");
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+
+ // get run informations
+ String mainPrototype = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_PROTOTYPE, "main.li");
+ String lip = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_LIP, "");
+ String programArguments = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_ARGUMENTS, "");
+
+ compiler = new LisaacCompiler(mainPrototype, lip);
+
+ // options
+ int count = 0;
+ String option;
+ do {
+ option = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_OPTION+count, "");
+ if (option != null && ! option.equals("")) {
+ compiler.addOption("-"+option);
+
+ String optionArg = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_OPTION_ARG+count, "");
+ if (! optionArg.equals("")) {
+ compiler.addOption(optionArg);
+ }
+ }
+ count++;
+ } while (option != null && ! option.equals(""));
+
+ LisaacModel model = LisaacModel.getModel(project);
+ if (model != null) {
+ Prototype main = model.getPrototype(mainPrototype.toUpperCase());
+ if (main == null || main.getSlot("main") == null) {
+ // TODO Messsage box : missing main slot
+ /*MessageDialog.openInformation(
+ null,
+ "Lisaac Plug-in",
+ mainPrototype+ " : Slot 'main' is missing.");*/ // do not work
+
+ }
+ }
+
+ // compile & launch project;
+ if (! compiler.launchInConsole(project, monitor)) {
+ MessageDialog.openInformation(
+ null,
+ "Lisaac Plug-in",
+ "Compilation Error!");
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/launch/LaunchConfigurationTab.java b/src/org/eclipse/lisaac/launch/LaunchConfigurationTab.java
new file mode 100644
index 0000000..9058ce4
--- /dev/null
+++ b/src/org/eclipse/lisaac/launch/LaunchConfigurationTab.java
@@ -0,0 +1,414 @@
+package org.eclipse.lisaac.launch;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.lisaac.model.lip.LIP;
+import org.eclipse.lisaac.model.lip.LIPSlotCode;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TableEditor;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+
+public class LaunchConfigurationTab extends AbstractLaunchConfigurationTab {
+
+ public static final String LISAAC_LAUNCH_PROJECT = "launchProject";
+ public static final String LISAAC_LAUNCH_PROTOTYPE = "mainPrototype";
+ public static final String LISAAC_LAUNCH_ARGUMENTS = "programArguments";
+ public static final String LISAAC_LAUNCH_LIP = "lipFile";
+ public static final String LISAAC_LAUNCH_OPTION = "lipOption";
+ public static final String LISAAC_LAUNCH_OPTION_ARG = "lipOptionARG";
+
+ // Project UI widget.
+ private Text projectText;
+ private Text mainPrototypeText;
+ private Text argumentsText;
+ private Text lipText;
+ private Table lipTable;
+
+ // associated lip
+ private LIP lipCode;
+
+ /**
+ * @see ILaunchConfigurationTab#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ Font font = parent.getFont();
+
+ Composite comp = new Composite(parent, SWT.NONE);
+ setControl(comp);
+ GridLayout topLayout = new GridLayout();
+ comp.setLayout(topLayout);
+
+ // Project Options
+ Group projComp = new Group(comp, SWT.SHADOW_IN);
+ projComp.setText("Project Options");
+ GridLayout projLayout = new GridLayout();
+ projLayout.numColumns = 3;
+ projLayout.marginHeight = 0;
+ projLayout.marginWidth = 0;
+ projComp.setLayout(projLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ projComp.setLayoutData(gd);
+ projComp.setFont(font);
+
+ Label fProjLabel = new Label(projComp, SWT.NONE);
+ fProjLabel.setText("Project: ");
+ gd = new GridData();
+ gd.horizontalSpan = 1;
+ fProjLabel.setLayoutData(gd);
+ fProjLabel.setFont(font);
+
+ projectText = new Text(projComp, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ projectText.setLayoutData(gd);
+ projectText.setFont(font);
+ this.projectText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ Label label = new Label(projComp, SWT.NONE);
+ label.setText("Main Prototype to run :");
+ gd = new GridData();
+ gd.horizontalSpan = 1;
+ label.setLayoutData(gd);
+ label.setFont(font);
+
+ mainPrototypeText = new Text(projComp, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 1;
+ mainPrototypeText.setLayoutData(gd);
+ mainPrototypeText.setFont(font);
+ mainPrototypeText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ Button browseButton = new Button(projComp, SWT.PUSH);
+ browseButton.setText("Browse");
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
+ gd.horizontalSpan = 1;
+ browseButton.setLayoutData(gd);
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse(mainPrototypeText);
+ }
+ });
+
+ // Program Options
+ Group programOptions = new Group(comp, SWT.SHADOW_IN);
+ programOptions.setText("Program Options");
+ programOptions.setLayout(new GridLayout());
+
+ label = new Label(programOptions, SWT.NONE);
+ label.setText("Program Arguments: ");
+ gd = new GridData();
+ gd.horizontalSpan = 3;
+ label.setLayoutData(gd);
+ label.setFont(font);
+
+ argumentsText = new Text(programOptions, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ argumentsText.setLayoutData(gd);
+ argumentsText.setFont(font);
+ this.argumentsText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ // compiler options
+ Group compilerOptions = new Group(comp, SWT.SHADOW_IN);
+ compilerOptions.setText("Compiler Options");
+ GridLayout gl = new GridLayout();
+ gl.numColumns = 3;
+ compilerOptions.setLayout(gl);
+
+ label = new Label(compilerOptions, SWT.NONE);
+ label.setText("Lisaac Path File (default : make.lip): ");
+ gd = new GridData();
+ gd.horizontalSpan = 3;
+ label.setLayoutData(gd);
+ label.setFont(font);
+
+ lipText = new Text(compilerOptions, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ lipText.setLayoutData(gd);
+ lipText.setFont(font);
+ this.lipText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ browseButton = new Button(compilerOptions, SWT.PUSH);
+ browseButton.setText("Browse");
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 1;
+ browseButton.setLayoutData(gd);
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse(lipText);
+ }
+ });
+
+ // lip options
+ Composite tableGroup = new Composite(compilerOptions, SWT.NONE);
+ tableGroup.//setLayout(new RowLayout());
+ setLayout(new GridLayout(1, false));
+
+ lipTable = new Table(tableGroup, SWT.BORDER | SWT.SINGLE |
+ SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.CHECK);
+ final TableColumn c1 = new TableColumn(lipTable, SWT.LEFT);
+ c1.setText("Option");
+ c1.setWidth(130);
+ final TableColumn c2 = new TableColumn(lipTable, SWT.LEFT);
+ c2.setText("Argument");
+ c2.setWidth(60);
+ final TableColumn c3 = new TableColumn(lipTable, SWT.LEFT);
+ c3.setText("Description");
+ c3.setWidth(100);
+ lipTable.setHeaderVisible(true);
+ lipTable.setLinesVisible(true);
+
+ final TableEditor editor = new TableEditor(lipTable);
+ // The editor must have the same size as the cell and must
+ // not be any smaller than 50 pixels.
+ editor.horizontalAlignment = SWT.LEFT;
+ editor.grabHorizontal = true;
+ editor.minimumWidth = 50;
+
+ lipTable.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ //
+ // Clean up any previous editor control
+ Control oldEditor = editor.getEditor();
+ if (oldEditor != null)
+ oldEditor.dispose();
+
+ // Identify the selected row
+ TableItem item = (TableItem) e.item;
+ if (item == null)
+ return;
+
+ // The control that will be the editor must be a child of the
+ // Table
+ Text newEditor = new Text(lipTable, SWT.NONE);
+ newEditor.setText(item.getText(1));
+ newEditor.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent me) {
+ Text text = (Text) editor.getEditor();
+ editor.getItem().setText(1, text.getText());
+ }
+ });
+ newEditor.selectAll();
+ newEditor.setFocus();
+ editor.setEditor(newEditor, item, 1);
+ //
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ tableGroup.setLayoutData(gridData);
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+ */
+ public String getName() {
+ return "Main";
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ try {
+ String projectName = configuration.getAttribute(LISAAC_LAUNCH_PROJECT, "");
+ projectText.setText(projectName);
+
+ String mainPrototypeName = configuration.getAttribute(LISAAC_LAUNCH_PROTOTYPE, "");
+ mainPrototypeText.setText(mainPrototypeName);
+
+ String argumentsName = configuration.getAttribute(LISAAC_LAUNCH_ARGUMENTS, "");
+ argumentsText.setText(argumentsName);
+
+ String lipName = configuration.getAttribute(LISAAC_LAUNCH_LIP, "");
+ lipText.setText(lipName);
+
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ LisaacModel model = LisaacModel.getModel(project);
+ if (model != null) {
+ lipCode = model.getLipCode();
+ if (lipCode != null) {
+ // update table
+ lipTable.setItemCount(0);
+ for (int i=0; i<lipCode.getMethodCount(); i++) {
+ LIPSlotCode method = lipCode.getMethod(i);
+ if (method.isPublic()) {
+ String methodComment = method.getComment();
+ if (methodComment == null) {
+ methodComment = "No comment";
+ }
+ methodComment = methodComment.replaceAll("\t", "");
+ methodComment = methodComment.replaceAll("\n", "");
+
+ if (! lipTable.isDisposed()) {
+ TableItem item = new TableItem (lipTable, SWT.NONE);
+ item.setText(0, method.getName());
+ item.setText(2, methodComment);
+ }
+ }
+ }
+ }
+ }
+ } catch (CoreException ce) {
+ // Log the error to the Eclipse log.
+ IStatus status = new Status(IStatus.ERROR,
+ LisaacPlugin.PLUGIN_ID, 0,
+ "Error in Lisaac launch: " +
+ ce.getMessage(), ce);
+ LisaacPlugin.log(status);
+ }
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ configuration.setAttribute(LISAAC_LAUNCH_PROJECT, projectText.getText());
+ configuration.setAttribute(LISAAC_LAUNCH_PROTOTYPE, mainPrototypeText.getText());
+ configuration.setAttribute(LISAAC_LAUNCH_ARGUMENTS, argumentsText.getText());
+ configuration.setAttribute(LISAAC_LAUNCH_LIP, lipText.getText());
+
+ TableItem[] options = lipTable.getItems();
+ if (options != null && options.length > 0) {
+ for (int i=0; i<options.length; i++) {
+ configuration.removeAttribute(LISAAC_LAUNCH_OPTION+i);// remove options
+ configuration.removeAttribute(LISAAC_LAUNCH_OPTION_ARG+i);// remove options
+ }
+ int count = 0;
+ for (int i=0; i<options.length; i++) {
+ TableItem item = options[i];
+ if (item.getChecked()) {
+ configuration.setAttribute(LISAAC_LAUNCH_OPTION+count, item.getText(0));
+ configuration.setAttribute(LISAAC_LAUNCH_OPTION_ARG+count, item.getText(1));
+ count++;
+ }
+ }
+ }
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+ IProject project = getSelectedProject(configuration);
+ String projectName = "";
+ String mainPrototypeName = "";
+
+ if (project != null) {
+ projectName = project.getName();
+ mainPrototypeName = projectName + ".li";
+ }
+ configuration.setAttribute(LISAAC_LAUNCH_PROJECT, projectName);
+ configuration.setAttribute(LISAAC_LAUNCH_PROTOTYPE, mainPrototypeName);
+ configuration.setAttribute(LISAAC_LAUNCH_ARGUMENTS, "");
+ configuration.setAttribute(LISAAC_LAUNCH_LIP, "");
+
+ TableItem[] options = lipTable.getItems();
+ if (options != null && options.length > 0) {
+ for (int i=0; i<options.length; i++) {
+ configuration.removeAttribute(LISAAC_LAUNCH_OPTION+i);// remove options
+ configuration.removeAttribute(LISAAC_LAUNCH_OPTION_ARG+i);// remove options
+ }
+ }
+ }
+
+ /**
+ * Gets the current project selected in the workbench.
+ *
+ * @param config
+ * @return the current project selected in the workbench.
+ */
+ private IProject getSelectedProject(ILaunchConfigurationWorkingCopy config) {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window != null) {
+ IWorkbenchPage page = window.getActivePage();
+ if (page != null) {
+ ISelection selection = page.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ss = (IStructuredSelection)selection;
+ if (!ss.isEmpty()) {
+ Object obj = ss.getFirstElement();
+ if (obj instanceof IResource) {
+ IResource i = (IResource) obj;
+ IProject pro = i.getProject();
+ return pro;
+ }
+ }
+ }
+ // If the editor has the focus...
+ IEditorPart part = page.getActiveEditor();
+ if (part != null) {
+ IEditorInput input = part.getEditorInput();
+ IFile file = (IFile) input.getAdapter(IFile.class);
+ return file.getProject();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Uses the standard container selection dialog to choose the new value for
+ * the container field.
+ */
+ private void handleBrowse(Text text) {
+ FileDialog dialog = new FileDialog(getShell());
+
+ String result = dialog.open();
+ if (result != null) {
+ text.setText(result);
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/launch/LaunchConfigurationTabGroup.java b/src/org/eclipse/lisaac/launch/LaunchConfigurationTabGroup.java
new file mode 100644
index 0000000..04c3440
--- /dev/null
+++ b/src/org/eclipse/lisaac/launch/LaunchConfigurationTabGroup.java
@@ -0,0 +1,20 @@
+package org.eclipse.lisaac.launch;
+
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+
+public class LaunchConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+ /**
+ * @see ILaunchConfigurationTabGroup#createTabs(ILaunchConfigurationDialog, String)
+ */
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ ILaunchConfigurationTab[] tabs = {
+ new LaunchConfigurationTab(),
+ new CommonTab()
+ };
+ setTabs(tabs);
+ }
+}
diff --git a/src/org/eclipse/lisaac/launch/LisaacCompiler.java b/src/org/eclipse/lisaac/launch/LisaacCompiler.java
new file mode 100644
index 0000000..f693ddb
--- /dev/null
+++ b/src/org/eclipse/lisaac/launch/LisaacCompiler.java
@@ -0,0 +1,86 @@
+package org.eclipse.lisaac.launch;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public class LisaacCompiler {
+
+ protected String inputFile;
+ protected String lipFile;
+
+ protected ArrayList<String> options;
+
+ public LisaacCompiler(String inputFile, String lipFile) {
+ super();
+ this.inputFile = inputFile;
+ this.lipFile = lipFile;
+ }
+
+ public LisaacCompiler(String inputFile) {
+ this.inputFile = inputFile;
+ }
+
+
+ public boolean launchInConsole(IProject project, IProgressMonitor monitor) throws CoreException {
+ IContainer src = project.getFolder("src");
+ if (src != null) {
+ return LisaacLauncher.executeCommandInConsole(monitor, src, this.toCommandLineArray());
+ }
+ return LisaacLauncher.executeCommandInConsole(monitor, project, this.toCommandLineArray());
+ }
+
+ public Process launch(IProject project, IProgressMonitor monitor) throws CoreException {
+ IContainer src = project.getFolder("src");
+ if (src != null) {
+ return LisaacLauncher.executeCommand(monitor, src, this.toCommandLineArray());
+ }
+ return LisaacLauncher.executeCommand(monitor, project, this.toCommandLineArray());
+ }
+
+ public String[] toCommandLineArray() {
+ ArrayList<String> cmd = new ArrayList<String>();
+
+ cmd.add("lisaac ");
+ if (lipFile != null) {
+ cmd.add(lipFile);
+ }
+ if (inputFile != null) {
+ cmd.add(inputFile);
+ }
+ if (options != null) {
+ cmd.addAll(options);
+ }
+
+ System.out.println("\n\n============>> "+toCommandLine());
+
+ return cmd.toArray(new String[cmd.size()]);
+ }
+
+ public String toCommandLine() {
+ StringBuffer result = new StringBuffer("lisaac ");
+ if (lipFile != null) {
+ result.append(lipFile);
+ }
+ if (inputFile != null) {
+ result.append(" "+inputFile);
+ }
+ if (options != null) {
+ for (int i=0; i<options.size(); i++) {
+ result.append(" "+options.get(i));
+ }
+ }
+ return result.toString();
+ }
+
+ public void addOption(String option) {
+ if (options == null) {
+ options = new ArrayList<String>();
+ }
+ options.add(option);
+ }
+}
diff --git a/src/org/eclipse/lisaac/launch/LisaacLauncher.java b/src/org/eclipse/lisaac/launch/LisaacLauncher.java
new file mode 100644
index 0000000..8815aaf
--- /dev/null
+++ b/src/org/eclipse/lisaac/launch/LisaacLauncher.java
@@ -0,0 +1,167 @@
+package org.eclipse.lisaac.launch;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.lisaac.views.ConsoleFactory;
+import org.eclipse.lisaac.views.LisaacConsole;
+import org.eclipse.swt.widgets.Display;
+
+
+public class LisaacLauncher {
+
+ /** the size of the read buffers. */
+ private static final int BUFFER_SIZE = 256;
+
+
+ public static boolean executeCommandInConsole(final IProgressMonitor monitor, final IContainer project, final String[] commandLine) throws CoreException {
+ // get & clear lisaac console
+ final LisaacConsole console = ConsoleFactory.getConsole();
+ console.clearConsole();
+ console.activate();// show console
+
+ /* if (AntRunner.isBuildRunning()) {
+ //throw new Exception("Another build is already running");
+ return false;
+ }
+ AntRunner runner = new AntRunner();
+ runner.setBuildFileLocation(project.getFullPath()+"/build.xml");
+ runner.setArguments("-Dmessage=Building -verbose");
+ runner.run(monitor);
+ */
+
+ Runnable getStandardOutput = new Runnable() {
+ public void run() {
+
+ monitor.beginTask("Executing...", 100);
+
+ Process process = null;
+ try {
+ process = launchProcess(commandLine, project);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ monitor.worked(20);
+ if (monitor.isCanceled()) {
+ return;
+ }
+
+ InputStream inputStream = process.getInputStream();
+ //readOutput(inputStream, console.newOutputStream());
+ String output = getProcessOutput(commandLine, inputStream, console.newOutputStream());
+ System.out.println(output);
+
+ monitor.worked(100);
+ monitor.done();
+ }
+ };
+ // execute action in a new thread UI safe
+ Display.getDefault().asyncExec(getStandardOutput);
+ //Thread runCommand = new Thread(getStandardOutput);
+ //runCommand.start();
+
+ return true;
+ }
+
+ public static Process executeCommand(IProgressMonitor monitor, IContainer project, String[] commandLine) throws CoreException {
+ monitor.beginTask("Executing...", 100);
+
+ Process process = null;
+ try {
+ process = launchProcess(commandLine, project);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ monitor.worked(20);
+ if (monitor.isCanceled()) {
+ return null;
+ }
+ return process; // .getInputStream();
+ }
+
+ public static void readOutput(InputStream inputStream, OutputStream outputStream) {
+ String line=null;
+
+ BufferedReader bufferIn =
+ new BufferedReader (new InputStreamReader (inputStream));
+ try {
+ while ((line = bufferIn.readLine ()) != null) {
+ outputStream.write(line.getBytes());
+ System.out.println("==> "+line);
+ }
+ //bufferIn.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns the content of the process output.
+ * @param inputStream the stream that contains the process output
+ * @param outputStream the stream to which output is written
+ * @return the process output string
+ */
+ public static String getProcessOutput(String[] debug, InputStream inputStream, OutputStream outputStream) {
+ StringBuffer processOutput = new StringBuffer();
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int byteRead = 0;
+
+ try {
+ for (int i=0; i<debug.length; i++) {
+ outputStream.write(debug[i].getBytes());
+ }
+
+ while (true) {
+ byteRead = inputStream.read(buffer);
+
+ if (byteRead == -1) {
+ break;
+ } else {
+ byte[] realOutput = new byte[byteRead];
+ System.arraycopy(buffer, 0, realOutput, 0, byteRead);
+ outputStream.write(realOutput);
+
+ String output = new String(realOutput);
+ processOutput.append(output);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return processOutput.toString();
+ }
+
+ /**
+ * Executes the command line at the given project location, and returns the
+ * corresponding process.
+ * @param commandLine the command line
+ * @param project the project in which the command line is executed
+ * @return the corresponding process
+ * @throws IOException if the command line can't be executed
+ */
+ public static Process launchProcess(String[] commandLine, IContainer project) throws IOException {
+ File projectDirectory =
+ (project != null) ? new File(project.getLocationURI()) : null;
+
+ try {
+ Process process = DebugPlugin.exec(commandLine, projectDirectory);
+ return process;
+ } catch (CoreException e) {
+ // TODO runtime error
+ }
+
+ //Process process = Runtime.getRuntime().exec(commandLine, null, projectDirectory);
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/AbstractLisaacParser.java b/src/org/eclipse/lisaac/model/AbstractLisaacParser.java
new file mode 100644
index 0000000..5674b82
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/AbstractLisaacParser.java
@@ -0,0 +1,791 @@
+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;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/AliasString.java b/src/org/eclipse/lisaac/model/AliasString.java
new file mode 100644
index 0000000..df65f8c
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/AliasString.java
@@ -0,0 +1,82 @@
+package org.eclipse.lisaac.model;
+
+import java.util.HashSet;
+
+public class AliasString {
+ private HashSet<String> list;
+
+ public AliasString() {
+ list = new HashSet<String>();
+
+ // add model string constants
+ list.add(ILisaacModel.section_header);
+ list.add(ILisaacModel.section_inherit);
+ list.add(ILisaacModel.section_insert);
+ list.add(ILisaacModel.section_public);
+ list.add(ILisaacModel.section_private);
+ list.add(ILisaacModel.section_interrupt);
+ list.add(ILisaacModel.section_mapping);
+ list.add(ILisaacModel.section_directory);
+ list.add(ILisaacModel.section_external);
+
+ list.add(ILisaacModel.keyword_section);
+ list.add(ILisaacModel.keyword_right);
+ list.add(ILisaacModel.keyword_left);
+ list.add(ILisaacModel.keyword_ldots);
+ list.add(ILisaacModel.keyword_old);
+ list.add(ILisaacModel.keyword_expanded);
+ list.add(ILisaacModel.keyword_strict);
+ list.add(ILisaacModel.keyword_result);
+
+ list.add(ILisaacModel.symbol_affect_immediate);
+ list.add(ILisaacModel.symbol_affect_cast);
+ list.add(ILisaacModel.symbol_affect_code);
+ list.add(ILisaacModel.symbol_auto_export);
+ list.add(ILisaacModel.symbol_equal);
+ list.add(ILisaacModel.symbol_not_equal);
+ list.add(ILisaacModel.symbol_great);
+ list.add(ILisaacModel.symbol_great_equal);
+ list.add(ILisaacModel.symbol_less);
+ list.add(ILisaacModel.symbol_less_equal);
+
+ list.add(ILisaacModel.slot_name);
+ list.add(ILisaacModel.slot_export);
+ list.add(ILisaacModel.slot_import);
+ list.add(ILisaacModel.slot_external);
+ list.add(ILisaacModel.slot_default);
+ list.add(ILisaacModel.slot_type);
+ list.add(ILisaacModel.slot_version);
+ list.add(ILisaacModel.slot_date);
+ list.add(ILisaacModel.slot_comment);
+ list.add(ILisaacModel.slot_author);
+ list.add(ILisaacModel.slot_bibliography);
+ list.add(ILisaacModel.slot_language);
+ list.add(ILisaacModel.slot_copyright);
+ list.add(ILisaacModel.slot_bug_report);
+
+ list.add(ILisaacModel.prototype_true);
+ list.add(ILisaacModel.prototype_false);
+ list.add(ILisaacModel.prototype_self);
+ list.add(ILisaacModel.prototype_string);
+ list.add(ILisaacModel.prototype_integer);
+ list.add(ILisaacModel.prototype_real);
+ list.add(ILisaacModel.prototype_boolean);
+ list.add(ILisaacModel.prototype_character);
+
+ list.add(ILisaacModel.variable_null);
+ list.add(ILisaacModel.variable_void);
+ list.add(ILisaacModel.variable_self);
+
+ // lip
+ list.add(ILisaacModel.slot_if);
+ list.add(ILisaacModel.slot_else);
+ list.add(ILisaacModel.slot_print);
+ }
+
+ public String get (String str) {
+ if (! list.contains(str)) {
+ list.add(str);
+ }
+ return str;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/ILisaacContext.java b/src/org/eclipse/lisaac/model/ILisaacContext.java
new file mode 100644
index 0000000..716a728
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/ILisaacContext.java
@@ -0,0 +1,20 @@
+package org.eclipse.lisaac.model;
+
+import org.eclipse.lisaac.model.items.Prototype;
+
+public interface ILisaacContext {
+ /**
+ * Parse the definition of the context. Returns true if the
+ * context is correctly parsed. <br>
+ * Automatically report parse errors.
+ * @param prototype The model to fill
+ * @return false if the definition of context contains at least one error
+ */
+ boolean parseDefinition(Prototype prototype);
+
+ /**
+ * Get the following context of same category in the lisaac code.
+ * @return next context in current prototype
+ */
+ ILisaacContext getNextContext();
+}
diff --git a/src/org/eclipse/lisaac/model/ILisaacModel.java b/src/org/eclipse/lisaac/model/ILisaacModel.java
new file mode 100644
index 0000000..14e72e9
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/ILisaacModel.java
@@ -0,0 +1,82 @@
+package org.eclipse.lisaac.model;
+
+import org.eclipse.lisaac.builder.ILisaacErrorHandler;
+import org.eclipse.lisaac.model.lip.LIP;
+
+public interface ILisaacModel {
+
+ final String inherit_shared = "Shared";
+ final String inherit_shared_expanded = "Shared Expanded";
+ final String inherit_nonshared = "Non Shared";
+ final String inherit_nonshared_expanded = "Non Shared Expanded";
+
+ //
+ final String keyword_section = "Section";
+ final String keyword_right = "Right";
+ final String keyword_left = "Left";
+ final String keyword_ldots = "...";
+ final String keyword_old = "Old";
+ final String keyword_expanded = "Expanded";
+ final String keyword_strict = "Strict";
+ final String keyword_result = "Result";
+
+ final String symbol_affect_immediate = ":=";
+ final String symbol_affect_cast = "?=";
+ final String symbol_affect_code = "<-";
+ final String symbol_auto_export = "->";
+ final String symbol_auto_import = symbol_affect_code;
+ final String symbol_equal = "=";
+ final String symbol_not_equal = "!=";
+ final String symbol_great = ">";
+ final String symbol_great_equal = ">=";
+ final String symbol_less = "<";
+ final String symbol_less_equal = "<=";
+
+ final String section_header = "Header";
+ final String section_inherit = "Inherit";
+ final String section_insert = "Insert";
+ final String section_public = "Public";
+ final String section_private = "Private";
+ final String section_interrupt = "Interrupt";
+ final String section_mapping = "Mapping";
+ final String section_directory = "Directory";
+ final String section_external = "External";
+
+ final String slot_name = "name";
+ final String slot_export = "export";
+ final String slot_import = "import";
+ final String slot_external = "external";
+ final String slot_default = "default";
+ final String slot_type = "type";
+ final String slot_version = "version";
+ final String slot_date = "date";
+ final String slot_comment = "comment";
+ final String slot_author = "author";
+ final String slot_bibliography = "bibliography";
+ final String slot_language = "language";
+ final String slot_copyright = "copyright";
+ final String slot_bug_report = "bug_report";
+
+ final String prototype_true = "TRUE";
+ final String prototype_false = "FALSE";
+ final String prototype_self = "SELF";
+ final String prototype_string = "STRING";
+ final String prototype_integer = "INTEGER";
+ final String prototype_real = "REAL";
+ final String prototype_boolean = "BOOLEAN";
+ final String prototype_character = "CHARACTER";
+
+ final String variable_null = "NULL";
+ final String variable_void = "VOID";
+ final String variable_self = "Self";
+
+ // lip
+ final String slot_if = "if";
+ final String slot_else = "else";
+ final String slot_print = "print";
+
+ ILisaacErrorHandler getReporter();
+ AliasString getAliasString();
+ LisaacParser getParser();
+ LIP getLipCode();
+}
diff --git a/src/org/eclipse/lisaac/model/LipParser.java b/src/org/eclipse/lisaac/model/LipParser.java
new file mode 100644
index 0000000..c5af3b4
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/LipParser.java
@@ -0,0 +1,458 @@
+package org.eclipse.lisaac.model;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+
+import org.eclipse.lisaac.model.lip.*;
+
+
+public class LipParser extends AbstractLisaacParser {
+
+ public LIP lipFile;
+
+ public LipParser(InputStream contents, ILisaacModel model) {
+ super(contents, model);
+ this.lipFile = model.getLipCode();
+ }
+
+ //
+ // Parser for LIP file.
+ //
+
+ ////PROGRAM -> { 'Section' ('Inherit' | 'Public' | 'Private') { SLOT ';' } }
+ public boolean parse() {
+ boolean result=false;
+
+ while (readThisKeyword(ILisaacModel.keyword_section)) {
+ if (readThisKeyword(ILisaacModel.section_inherit)) {
+ // { '+' string ':' STRING [ ':=' string ] ';' }
+ while (readCharacter('+')) {
+ if (! readIdentifier()) {
+ reporter.syntaxError("Identifier needed.", getPosition());
+ return false;
+ }
+ if (! readCharacter(':')) {
+ reporter.syntaxError("Added ':' is needed.", getPosition());
+ return false;
+ }
+ if (! readWord(ILisaacModel.prototype_string)) {
+ reporter.warning("`STRING' type needed.", getPosition());
+ }
+ if (readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ if (! readString()) {
+ reporter.syntaxError("String needed.", getPosition());
+ return false;
+ }
+ string_tmp = new String(lipFile.getFileName());
+ while (string_tmp.length() > 0) {
+ char c = string_tmp.charAt(string_tmp.length()-1);
+ if (c == '/' || c == '\\') {
+ break;
+ }// FIXME use index
+ string_tmp = string_tmp.substring(0, string_tmp.length()-1);
+ }
+ string_tmp += lastString;
+ } else {
+ string_tmp = "";
+ }
+ // add parent slot
+ lipFile.addParent(getString(string_tmp));
+ //
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';' is needed.", getPosition());
+ return false;
+ }
+ result = true;
+ }
+ } else if (readThisKeyword(ILisaacModel.section_public) ||
+ readThisKeyword(ILisaacModel.section_private)) {
+ String section = new String(lastString);
+ while (readSlot(section)) {
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';' is needed.", getPosition());
+ return false;
+ }
+ result = true;
+ }
+ } else {
+ reporter.syntaxError("`Public' or `Private' or `Inherit' needed.", getPosition());
+ return false;
+ }
+ }
+ if (position < source.length()-2) {
+ result = false;
+ }
+ return result;
+ }
+
+ //// SLOT -> '+' identifier ':' TYPE [ ':=' EXPR_CONSTANT ]
+ //// | '-' identifier [ identifier ':' TYPE ] '<-' '(' { EXPR ';' } ')'
+ private boolean readSlot(String sec) {
+ boolean result=false;
+ LIPSlotData data=null;
+
+ if (readCharacter('+')) {
+ // Data.
+ result = true;
+ if (sec.equals(ILisaacModel.section_public)) {
+ reporter.syntaxError("No data in Public section.", getPosition());
+ }
+ if (! readIdentifier()) {
+ reporter.syntaxError("Identifier is incorrect.", getPosition());
+ return false;
+ }
+ String n = new String(lastString);
+ if (! readCharacter(':')) {
+ reporter.syntaxError("Added ':' is needed.", getPosition());
+ return false;
+ }
+ LIPConstant t = readType();
+ if (t == null) {
+ reporter.syntaxError("type is incorrect.", getPosition());
+ return false;
+ }
+ data = new LIPSlotData(n, t);
+ //
+ lipFile.addData(data);
+ //
+ if (readSymbol(LisaacModel.symbol_affect_immediate)) {
+ LIPConstant cst = readExprConstant();
+ if (cst == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return false;
+ }
+ data.setValue(cst);
+ cst.free();
+ }
+ } else if (readCharacter('-')) {
+ // Function.
+ result = true;
+ if (! readIdentifier()) {
+ reporter.syntaxError("Identifier is incorrect.", getPosition());
+ return false;
+ }
+ //Position pos = getPosition();
+ setCatchComment();
+
+ String n = new String(lastString);
+ if (readIdentifier()) {
+ String na = new String(lastString);
+ if (! readCharacter(':')) {
+ reporter.syntaxError("Added ':' is needed.", getPosition());
+ return false;
+ }
+ LIPConstant t = readType();
+ if (t == null) {
+ reporter.syntaxError("Incorrect type.", getPosition());
+ return false;
+ }
+ data = new LIPSlotData(na, t);// do not add argument do lipFile
+ }
+ //
+ if (! readSymbol(ILisaacModel.symbol_affect_code)) {
+ reporter.syntaxError("Added '<-' is needed.", getPosition());
+ return false;
+ }
+ if (! readCharacter('(')) {
+ reporter.syntaxError("Added '(' is needed.", getPosition());
+ return false;
+ }
+ setCatchCommentOff();
+ ArrayList<LIPCode> code = new ArrayList<LIPCode>();
+ LIPCode instr;
+ while ((instr = readExpr()) != null) {
+ code.add(instr);
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';' is needed.", getPosition());
+ return false;
+ }
+ }
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')' is needed.", getPosition());
+ return false;
+ }
+ LIPSlotCode slotCode = new LIPSlotCode(sec, n, data, code.toArray(new LIPCode[code.size()]));
+ lipFile.addMethod(slotCode);
+ if (sec.equals(ILisaacModel.section_public)) {
+ if (lastComment == null || lastComment.length() == 0) {
+ reporter.syntaxError("Comment needed.", getPosition());
+ } else {
+ slotCode.setComment(lastComment);
+ }
+ }
+ }
+ return result;
+ }
+
+ ////TYPE -> 'BOOLEAN' | 'STRING' | 'INTEGER'
+ private LIPConstant readType() {
+ LIPConstant result=null;
+
+ if (readCapIdentifier()) {
+ if (lastString.equals(ILisaacModel.prototype_integer)) {
+ result = LIPInteger.get(0);
+ } else if (lastString.equals(ILisaacModel.prototype_string)) {
+ result = LIPString.get(getString(""));
+ } else if (lastString.equals(ILisaacModel.prototype_boolean)) {
+ result = LIPBoolean.get(false);
+ } else {
+ reporter.syntaxError("Incorrect type.", getPosition());
+ }
+ }
+ return result;
+ }
+
+ //// EXPR -> [ identifier !!AMBIGU!! ':=' ] EXPR_OPERATOR [ '.' FUNCTION ]
+ private LIPCode readExpr() {
+ LIPCode result=null;
+
+ saveContext(); // !! SAVE CONTEXT !!
+
+ if (readIdentifier()) {
+ String name = new String(lastString);
+ if (readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ LIPCode val = readExprOperator();
+ if (val == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return null;
+ }
+ result = new LIPAffect(name, val);
+ } else {
+ restoreContext(); // !! RESTORE CONTEXT !!
+ }
+ }
+ if (result == null) {
+ result = readExprOperator();
+ if (result != null && readCharacter('.')) {
+ result = readFunction(result);
+ if (result == null) {
+ reporter.syntaxError("Incorrect slot.", getPosition());
+ return null;
+ }
+ }
+ }
+ return result;
+ }
+
+ //// FUNCTION -> 'if' '{' { EXPR ';' } '}' [ 'else' '{' { EXPR ';' } '}' ]
+ //// | 'print'
+ private LIPCode readFunction(LIPCode rec) {
+ LIPCode result=null;
+ ArrayList<LIPCode> thenArray=null, elseArray=null;
+
+ if (readWord(ILisaacModel.slot_if)) {
+ thenArray = new ArrayList<LIPCode>();
+ if (! readCharacter('{')) {
+ reporter.syntaxError("Added '{' is needed.", getPosition());
+ return null;
+ }
+ LIPCode val;
+ while ((val = readExpr()) != null) {
+ thenArray.add(val);
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';' is needed.", getPosition());
+ return null;
+ }
+ }
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}' is needed.", getPosition());
+ return null;
+ }
+ if (readWord(ILisaacModel.slot_else)) {
+ elseArray = new ArrayList<LIPCode>();
+ if (! readCharacter('{')) {
+ reporter.syntaxError("Added '{' is needed.", getPosition());
+ return null;
+ }
+ while ((val = readExpr()) != null) {
+ elseArray.add(val);
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';' is needed.", getPosition());
+ return null;
+ }
+ }
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}' is needed.", getPosition());
+ return null;
+ }
+ }
+ result = new LIPIf(rec, thenArray.toArray(new LIPCode[thenArray.size()]),
+ elseArray.toArray(new LIPCode[elseArray.size()]));
+ } else if (readWord(ILisaacModel.slot_print)) {
+ result = new LIPPrint(rec);
+ }
+ return result;
+ }
+
+ ////EXPR_OPERATOR-> EXPR_CMP { ('|' | '&') EXPR_CMP }
+ private LIPCode readExprOperator() {
+ LIPCode result=null;
+ boolean isOr=false;
+
+ result = readExprCmp();
+ if (result != null) {
+ while ((isOr = readCharacter('|')) || readCharacter('&')) {
+ LIPCode right = readExprCmp();
+ if (right == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return null;
+ }
+ if (isOr) {
+ result = new LIPBinary(result, '|', right);
+ } else {
+ result = new LIPBinary(result, '&', right);
+ }
+ }
+ }
+ return result;
+ }
+
+ ////EXPR_CMP -> EXPR_BINARY { ('='|'!='|'>'|'<'|'>='|'<=') EXPR_BINARY }
+ private LIPCode readExprCmp() {
+
+ LIPCode result = readExprBinary();
+ if (result != null) {
+ while (readSymbol(ILisaacModel.symbol_great_equal) ||
+ readSymbol(ILisaacModel.symbol_less_equal) ||
+ readSymbol(ILisaacModel.symbol_not_equal) ||
+ readSymbol(ILisaacModel.symbol_equal) ||
+ readSymbol(ILisaacModel.symbol_great) ||
+ readSymbol(ILisaacModel.symbol_less)) {
+ String op = new String(lastString);
+ LIPCode right = readExprBinary();
+ if (right == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return null;
+ }
+ char type = 0;
+ if (op.equals(">=")) {
+ type = 'S';
+ } else if (op.equals("<=")) {
+ type = 'I';
+ } else if (op.equals("!=")) {
+ type = 'E';
+ } else if (op.equals("=")) {
+ type = '=';
+ } else if (op.equals(">")) {
+ type = '>';
+ } else if (op.equals("<")) {
+ type = '<';
+ }
+ result = new LIPBinary(result, type, right);
+ }
+ }
+ return result;
+ }
+
+ ////EXPR_BINARY -> EXPR_UNARY { ('-'|'+') EXPR_UNARY }
+ private LIPCode readExprBinary() {
+ boolean isSub;
+
+ LIPCode result = readExprUnary();
+ if (result != null) {
+ while ((isSub = readCharacter('-')) || readCharacter('+')) {
+ LIPCode right = readExprUnary();
+ if (right == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return null;
+ }
+ if (isSub) {
+ result = new LIPBinary(result, '-', right);
+ } else {
+ result = new LIPBinary(result, '+', right);
+ }
+ }
+ }
+ return result;
+ }
+
+ //// EXPR_UNARY -> ( '-' | '!' ) EXPR_UNARY
+ //// | EXPR_BASE
+ //// | identifier [ EXPR_ARGUMENT ]
+ private LIPCode readExprUnary() {
+ LIPCode result=null;
+ boolean isNeg;
+
+ if ((isNeg = readCharacter('-')) || readCharacter('!')) {
+ result = readExprUnary();
+ if (result == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return null;
+ }
+ char type;
+ if (isNeg) {
+ type = '-';
+ } else {
+ type = '+';
+ }
+ result = new LIPUnary(type, result);
+ } else if (readIdentifier()) {
+ String name = new String(lastString);
+ LIPCode arg = readExprArgument();
+ result = new LIPCall(name, arg);
+ } else {
+ result = readExprBase();
+ }
+ return result;
+ }
+
+ //// EXPR_BASE -> '(' EXPR_OPERATOR ')'
+ //// | EXPR_CONSTANT
+ private LIPCode readExprBase() {
+ LIPCode result=null;
+
+ if (readCharacter('(')) {
+ result = readExprOperator();
+ if (result == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return null;
+ }
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')' is needed.", getPosition());
+ return null;
+ }
+ } else {
+ LIPConstant v = readExprConstant();
+ if (v != null) {
+ result = new LIPValue(v);
+ }
+ }
+ return result;
+ }
+
+ ////EXPR_CONSTANT-> integer
+ //// | string
+ //// | TRUE
+ //// | FALSE
+ private LIPConstant readExprConstant() {
+ LIPConstant result=null;
+
+ if (readInteger()) {
+ result = LIPInteger.get((int)lastInteger);
+ } else if (readString()) {
+ result = LIPString.get(lastString);
+ } else if (readCapIdentifier()) {
+ if (lastString.equals(ILisaacModel.prototype_true)) {
+ result = LIPBoolean.get(true);
+ } else if (lastString.equals(ILisaacModel.prototype_false)){
+ result = LIPBoolean.get(false);
+ } else {
+ reporter.syntaxError("Type incorrect.", getPosition());
+ }
+ }
+ return result;
+ }
+
+ //// EXPR_ARGUMENT-> identifier
+ //// | EXPR_BASE
+ private LIPCode readExprArgument() {
+ LIPCode result=null;
+
+ if (readIdentifier()) {
+ result = new LIPCall(lastString, null);
+ } else {
+ result = readExprBase();
+ }
+ return result;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/LisaacCompletionParser.java b/src/org/eclipse/lisaac/model/LisaacCompletionParser.java
new file mode 100644
index 0000000..0f7b4ed
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/LisaacCompletionParser.java
@@ -0,0 +1,141 @@
+package org.eclipse.lisaac.model;
+
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.lisaac.builder.ILisaacErrorHandler;
+import org.eclipse.lisaac.editors.LisaacEditor;
+import org.eclipse.lisaac.model.items.ICode;
+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.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+
+public class LisaacCompletionParser extends LisaacParser {
+
+ protected Prototype currentPrototype;
+ protected Slot currentSlot;
+
+ public LisaacCompletionParser(String contents) {
+ super(contents);
+ }
+
+ /**
+ * Get the lisaac completions at baseOffset
+ * @param startOffset start offset for completion parsing
+ * @param baseOffset completion offset
+ * @param proposals list of proposals to be filled
+ * @throws CoreException
+ */
+ public void parseCompletions(int startOffset, int baseOffset, ArrayList<CompletionProposal> proposals)
+ throws CoreException {
+ IType type;
+
+ currentPrototype = LisaacModel.getCurrentPrototype();
+ currentSlot = currentPrototype.getSlot(startOffset);
+
+ ICode code = readExpr();
+ if (code != null) {
+ if (currentSlot != null) {
+ type = code.getType(currentSlot);
+ } else {
+ type = code.getType(currentSlot);
+ }
+ if (type != null) {
+ currentPrototype = findPrototype(type.toString());
+ if (currentPrototype != null) {
+ currentPrototype.getSlotProposals(proposals, baseOffset, 0);
+ }
+ proposals.add(new CompletionProposal(""+type,baseOffset,0,0));
+ }
+ }
+ }
+
+ //++ EXPR_MESSAGE -> EXPR_BASE { '.' SEND_MSG }
+ protected ICode readExprMessage() {
+
+ ICode result = readExprBase();
+ if (result != null) {
+ while (readCharacter('.')) {
+ ICode lastResult = result;
+ result = readSendMsg(result);
+ if (result == null) {
+ return lastResult;
+ }
+ // update source of completion
+ IType type = lastResult.getType(currentSlot);
+ if (type != null) {
+ try {
+ currentPrototype = findPrototype(type.toString());
+ } catch(CoreException e) {
+ return null;
+ }
+ if (currentPrototype == null) {
+ return null;
+ }
+ if (result instanceof ITMRead) {
+ currentSlot = currentPrototype.getSlot(((ITMRead) result).getName());
+ } else {
+ currentSlot = null;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Find and parse a lisaac prototype according to its name.
+ */
+ private Prototype findPrototype(String prototypeName) throws CoreException {
+ IProject project = null;
+ Prototype result = null;
+
+ IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPart part = w.getPartService().getActivePart();
+ if (part instanceof LisaacEditor) {
+ project = ((LisaacEditor)part).getProject();
+ }
+ 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);
+
+ 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;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/LisaacModel.java b/src/org/eclipse/lisaac/model/LisaacModel.java
new file mode 100644
index 0000000..ce7f838
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/LisaacModel.java
@@ -0,0 +1,217 @@
+package org.eclipse.lisaac.model;
+
+import java.io.InputStream;
+import java.util.HashMap;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.lisaac.builder.LisaacBuilder;
+import org.eclipse.lisaac.builder.ILisaacErrorHandler;
+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.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+
+/**
+ * Represents Lisaac model of a project
+ * @author Damien Bouvarel
+ */
+public class LisaacModel implements ILisaacModel{
+
+ /** list of all encoutered models */
+ private static HashMap<IProject,LisaacModel> modelList;
+
+ /** 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;
+
+ /** lisaac builder */
+ private LisaacBuilder builder;
+
+ /** 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
+ }
+
+
+ public IProject getProject() {
+ return project;
+ }
+ public void setProject(IProject project) {
+ this.project = project;
+ }
+
+ public LisaacBuilder getBuilder() {
+ return builder;
+ }
+ public AliasString getAliasString() {
+ return aliasString;
+ }
+ public LisaacParser getParser() {
+ return parser;
+ }
+ public LisaacPath getPathManager() {
+ return modelPath;
+ }
+ public LIP getLipCode() {
+ return lipCode;
+ }
+
+ public Prototype getPrototype(String name) {
+ if (prototypes != null) {
+ return prototypes.get(name);
+ }
+ return null;
+ }
+
+ 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();
+ if (part instanceof AbstractLisaacEditor) {
+ ((LisaacEditor)part).refreshPresentation();
+ }
+ } catch (CoreException e) {
+ 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)) {
+ context = parser.readContext();
+ } else {
+ context = context.getNextContext();
+ }
+ }
+ // add new prototype to current model
+ prototypes.put(prototype.getName(), prototype);
+ return prototype;
+ }
+
+ /** remove part of current model */
+ 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);
+ IFile file=null;
+ if (parent.equals("")) { // lisaac make.lip
+ // TODO get lisaac directory
+ return;
+ } else {
+ file = project.getFile(parent);
+ }
+ lipParser = new LipParser(file.getContents(), this);
+ if (! lipParser.parse()) {
+ reporter.syntaxError("Syntax error.", lipParser.getPosition());
+ }
+ }
+ }
+
+ /** 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('.');
+ if (idx != -1) {
+ return (s.substring(0, idx)).toUpperCase();
+ }
+ return s.toUpperCase();
+ }
+
+ public ILisaacErrorHandler getReporter() {
+ return reporter;
+ }
+
+ /**
+ * Get the lisaac model associated with the given project.
+ * @param p A lisaac project
+ * @return The associated lisaac model
+ */
+ public static LisaacModel getModel(IProject p) {
+ if (modelList != null) {
+ return modelList.get(p);
+ }
+ return null;
+ }
+
+ public static Prototype getCurrentPrototype() {
+ IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+
+ IWorkbenchPart part = w.getPartService().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));
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/LisaacParser.java b/src/org/eclipse/lisaac/model/LisaacParser.java
new file mode 100644
index 0000000..c03738e
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/LisaacParser.java
@@ -0,0 +1,1415 @@
+package org.eclipse.lisaac.model;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.lisaac.builder.LisaacParseException;
+import org.eclipse.lisaac.model.items.*;
+import org.eclipse.lisaac.model.types.*;
+
+/**
+ * Lisaac Prototype Parser
+ */
+public class LisaacParser extends AbstractLisaacParser {
+
+ private ILisaacContext sectionContext;
+ private ILisaacContext slotContext;
+
+ //
+ private Slot lastSlot;
+ private ITMList lastGroup;
+ private Section lastSection;
+ //
+
+ public LisaacParser(InputStream contents, ILisaacModel model) {
+ super(contents, model);
+ this.model = model;
+
+ sectionContext = new SectionContext(this);
+ slotContext = new SlotContext(this);
+
+ initialize();
+ }
+
+ public LisaacParser(String contents) {
+ super(contents);
+ initialize();
+ }
+
+ public void initialize() {
+ //
+ // initialisations
+ //
+ super.initialize();
+ TypeSimple.init();
+ }
+
+ public ILisaacContext getSectionContext() {
+ return sectionContext;
+ }
+
+ public Slot getLastSlot() {
+ return lastSlot;
+ }
+
+ public void setLastSection(Section section) {
+ lastSection = section;
+ }
+
+ //
+ // Lisaac Prototype Parser
+ //
+
+ //++ TYPE_LIST -> TYPE { ',' TYPE }
+ public ITypeMono[] readTypeList(boolean isSection) {
+ ArrayList<ITypeMono> lst=null;
+ ITypeMono t;
+
+ t = readType(false);
+ if (t != null) {
+ if (isSection) {
+ if (! (t instanceof TypeSimple)) {
+ reporter.syntaxError("For a section, the prototype name only (without '('...')').", getPosition());
+ return null;
+ }
+ }
+ lst = new ArrayList<ITypeMono>();
+ lst.add(t);
+ while (readCharacter(',')) {
+ t = readType(false);
+ if (t == null) {
+ reporter.syntaxError("Incorrect type list.", getPosition());
+ return null;
+ }
+ if (isSection) {
+ if (! (t instanceof TypeSimple)) {
+ reporter.syntaxError("For a section, the prototype name only (without '('...')').", getPosition());
+ return null;
+ }
+ }
+ lst.add(t);
+ }
+ // TODO alias lst
+ }
+ if (lst != null) {
+ return lst.toArray(new ITypeMono[lst.size()]);
+ }
+ return null;
+ }
+
+ //++ TYPE -> '{' [ (TYPE | '(' TYPE_LIST ')') ';' ] [ TYPE_LIST ] '}'
+ //++ | [type] PROTOTYPE [ CONTRACT ]
+ public ITypeMono readType (boolean isLocal) {
+ ITypeMono result=null;
+ ITypeMono[] lst=null;
+ IType typ_arg=null,typ_res=null;
+ String style=null;
+
+ if (readCharacter('{')) {
+ // '{' [ (TYPE | '(' TYPE_LIST ')') ';' ] [ TYPE_LIST ] '}'
+ if (readCharacter('(')) {
+ // Read vector argument.
+ lst = readTypeList(false);
+ if (lst == null) {
+ reporter.syntaxError("Incorrect type list.", getPosition());
+ return null;
+ }
+ if (lst.length == 1) {
+ typ_arg = lst[0];
+ } else {
+ typ_arg = TypeMulti.get(lst);
+ }
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')'.", getPosition());
+ return null;
+ }
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';'.", getPosition());
+ }
+ // Read result type.
+ lst = readTypeList(false);
+ } else {
+
+ lst = readTypeList(false);
+ if (lst != null) {
+ if (readCharacter(';')) {
+ if (lst.length == 1) {
+ typ_arg = lst[0];
+ } else {
+ typ_arg = TypeMulti.get(lst);
+ // TODO warning "Added 'typ_arg'."
+ }
+ // Read result type.
+ lst = readTypeList(false);
+ }
+ }
+ }
+ if (lst != null) {
+ if (lst.length == 1) {
+ typ_res = lst[0];
+ } else {
+ typ_res = TypeMulti.get(lst);
+ }
+ }
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}'.", getPosition());
+ return null;
+ }
+ result = TypeBlock.get(typ_arg, typ_res);
+ } else {
+ // Expanded | Strict
+ if (readThisKeyword(ILisaacModel.keyword_expanded) ||
+ readThisKeyword(ILisaacModel.keyword_strict)) {
+
+ style = getLastString();
+ if (isLocal && (style.equals(ILisaacModel.keyword_expanded))) {
+ reporter.syntaxError("`Expanded' is not possible.", getPosition());
+ }
+ }
+ // PROTOTYPE
+ result = readPrototype(style);
+
+ // TODO read contract
+ }
+ return result;
+ }
+
+ //++ PROTOTYPE -> cap_identifier{('.'|'...')cap_identifier}['('PARAM_TYPE{','PARAM_TYPE}')']
+ public ITypeMono readPrototype(String style) {
+ ITypeMono result=null;
+ String name=null;
+
+ if (readCapIdentifier()) {
+ // TODO syntax {('.'|'...')cap_identifier}
+ name = getString(lastString);
+
+ if (readCharacter('(')) {
+ //
+ // Genericity.
+ //
+ ArrayList<ITypeMono> genericity = new ArrayList<ITypeMono>();
+ do {
+ ITypeMono t = readParamType();
+ if (t == null) {
+ reporter.syntaxError("Type needed.", getPosition());
+ return null;
+ }
+ genericity.add(t);
+ } while (readCharacter(','));
+ // alias genericity array...
+ result = new TypeGeneric(name, style, genericity.toArray(new ITypeMono[genericity.size()]));
+
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')'.", getPosition());
+ return result;
+ }
+ } else {
+ // Simple type.
+ if (isParameterType) {
+ if (style != null) {
+ reporter.warning("Style `"+style+"' for parameter type is ignored.", getPosition());
+ }
+ result = TypeParameter.get(name);
+ } else if (style == null) {
+ result = TypeSimple.get(name);
+ } else {
+ if (name.equals(ILisaacModel.prototype_self)) {
+ reporter.warning("Style `"+style+"' ignored.", getPosition());
+ result = TypeSimple.getTypeSelf();
+ } else {
+ result = TypeStyle.get(name,style);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ //++ PARAM_TYPE -> TYPE
+ //++ | CONSTANT
+ //++ | identifier
+ private ITypeMono readParamType() {
+ ITypeMono result = readType(false);
+ if (result == null) {
+ IConstant cst = readConstant();
+ if (cst != null) {
+ // TODO compiler not yet implemented
+ } else if (readIdentifier()) {
+ // TODO compiler not yet implemented
+ }
+ }
+ return result;
+ }
+
+ //++ SLOT -> style TYPE_SLOT [':' (TYPE|'('TYPE_LIST')') ][ affect DEF_SLOT ]';'
+ public boolean readSlot(Prototype prototype) {
+ char affect;
+ boolean result=false;
+ IType t;
+
+ char style = readStyle();
+ if (style != ' ') {
+ //
+ // Classic slot.
+ //
+ result = true;
+ lastSlot = readTypeSlot();
+ if (lastSlot == null) {
+ reporter.syntaxError("Incorrect slot declaration.", getPosition());
+ return false;
+ }
+ lastSlot.setStyle(style);
+
+ if (readAffect()) {
+ affect = lastString.charAt(0);
+ } else {
+ affect = ' ';
+ }
+ // ':' (TYPE|'('TYPE_LIST')'
+ if (affect == ' ' && readCharacter(':')) {
+ if (readCharacter('(')) {
+ ITypeMono[] lt = readTypeList(false);
+ if (lt == null) {
+ reporter.syntaxError("Incorrect result type.", getPosition());
+ return false;
+ }
+ if (! readCharacter(')')) {
+ reporter.warning("Added ')' is needed.", getPosition());
+ }
+ t = TypeMulti.get(lt);
+ } else {
+ t = readType(false);
+ if (t == null) {
+ reporter.syntaxError("Incorrect result type.", getPosition());
+ return false;
+ }
+ }
+ if (readAffect()) {
+ affect = lastString.charAt(0);
+ }
+ } else {
+ t = TypeSimple.getTypeVoid();
+ }
+ lastSlot.setResultType(t);
+ lastSlot.setAffect(affect);
+
+ if (affect != ' ') {
+ readSpace();
+ //old_pos = position;
+ //
+ readDefSlot();
+ //
+ }
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';'.", getPosition());
+ return false;
+ }
+ // Added slot in prototype :
+ Slot s = prototype.getSlot(lastSlot.getName());
+ if (s != null) {
+ reporter.semanticError("Double slot declaration.", getPosition());
+ } else {
+ prototype.addSlot(lastSlot);
+ }
+ }
+ return result;
+ }
+
+ //++ DEF_SLOT -> [CONTRACT] EXPR [CONTRACT]
+ private void readDefSlot() {
+
+ readRequire();
+ ICode expr = readExpr();
+ if (expr == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ }
+ lastSlot.setValue(expr);
+ readEnsure();
+ }
+
+ //++ TYPE_SLOT -> [ LOC_ARG '.' ] identifier [ LOC_ARG { identifier LOC_ARG } ]
+ //++ | [ LOC_ARG ] '\'' operator '\'' [("Left"|"Right") [integer]] [LOC_ARG]
+ public Slot readTypeSlot() {
+ Slot result=null;
+ IArgument arg=null;
+
+ ArrayList<IArgument> list_arg = new ArrayList<IArgument>();
+
+ arg = readLocArg(false,true);
+ if (arg == null) {
+ if (readCharacter('\'')) {
+ result = readSlotOperator(list_arg);
+ } else {
+ //arg = new ITMArgument(ILisaacModel.variable_self, TypeSimple.getTypeSelf());
+ //list_arg.add(arg); no use here?
+
+ result = readSlotKeyword(list_arg);
+ }
+ } else {
+ list_arg.add(arg);
+ if (readCharacter('.')) {
+ result = readSlotKeyword(list_arg);
+ } else if (readCharacter('\'')) {
+ result = readSlotOperator(list_arg);
+ }
+ }
+ if (result != null) {
+ result.setArgumentList(list_arg.toArray(new IArgument[list_arg.size()]));
+ }
+ return result;
+ }
+
+ private Slot readSlotKeyword(ArrayList<IArgument> list_arg) {
+ Slot result=null;
+ Position slotPosition = getPosition();
+ int start_pos = position;
+
+ if (readIdentifier()) {
+ String n = new String(lastString);
+
+ ArrayList<String> keywords = new ArrayList<String>();
+ keywords.add(n);
+
+ IArgument arg = readLocArg(false,false);
+ if (arg != null) {
+ list_arg.add(arg);
+ if (readIdentifier()) {
+ // TODO section external -> syntax error
+ do {
+ n += "__" + lastString;
+ keywords.add(new String(lastString));
+
+ arg = readLocArg(false,false);
+ if (arg == null) {
+ reporter.syntaxError("Incorrect symbol.", getPosition());
+ return null;
+ }
+ list_arg.add(arg);
+ } while (readIdentifier());
+ }
+ }
+ slotPosition.setLength(position - start_pos);
+ result = new Slot(slotPosition, getString(n), lastSection);
+ //
+ result.setKeywordList(keywords.toArray(new String[keywords.size()]));
+ //
+ }
+ return result;
+ }
+
+ //++ LOC_ARG -> identifier ':' TYPE
+ //++ | '(' LOCAL ')'
+ public IArgument readLocArg(boolean mute, boolean selfFirst) {
+ IArgument result=null;
+
+ if ((selfFirst && readThisKeyword(ILisaacModel.variable_self)) ||
+ (! selfFirst && readIdentifier())) {
+
+ //Position pos = getPosition();
+ String n = new String(lastString);
+ if (readCharacter(':') && lastCharacter() != '=') {
+ ITypeMono t = readType(true);
+ if (t == null) {
+ reporter.syntaxError("Incorrect type.", getPosition());
+ return null;
+ }
+
+ // TODO SELF
+ /*if (selfFirst && (t != TypeSimple.getTypeSelf()) &&
+ ((object.name != ALIAS_STR.prototype_block) ||
+ {tb ?= t; tb = NULL})) {
+ reporter.syntaxError("Type `SELF' is needed.", getPosition());
+ }*/
+ result = new ITMArgument(n, t);
+ } else {
+ if (! mute) {
+ reporter.warning("Added ':' is needed.", getPosition());
+ }
+ }
+ } else if (readCharacter('(')) {
+ result = readLocalArg(mute, selfFirst);
+ if (result == null) {
+ if (! mute) {
+ reporter.syntaxError("Incorrect argument definition.", getPosition());
+ return null;
+ }
+ } else {
+ if (! readCharacter(')')) {
+ reporter.warning("Added ')'.", getPosition());
+ }
+ }
+ }
+ return result;
+ }
+
+ private IArgument readLocalArg(boolean m, boolean s) {
+ IArgument result=null;
+ boolean mute = m;
+
+ if ((s && readThisKeyword(ILisaacModel.variable_self)) ||
+ readIdentifier()) {
+ List<String> name = new ArrayList<String>();
+ List<ITypeMono> type = new ArrayList<ITypeMono>();
+ int beg = 0;
+
+ do {
+ if (name.size() != 0 && !readIdentifier() && !mute) {
+ reporter.syntaxError("Incorrect argument identifier.", getPosition());
+ return null;
+ }
+ name.add(lastString);
+ if (readCharacter(':') && lastCharacter() != '=') {
+ mute = false;
+ ITypeMono t = readType(true);
+
+ if (t == null) {
+ reporter.syntaxError("Incorrect argument type.", getPosition());
+ return null;
+ }
+ for (int i=beg; i<name.size(); i++) {
+ type.add(t);
+ }
+ beg = name.size();
+ }
+ } while (readCharacter(','));
+
+ if (beg != name.size()) {
+ if (! mute) {
+ reporter.syntaxError("Incorrect argument type.", getPosition());
+ return null;
+ }
+ // free arrays..
+ } else {
+ /*if (s && (
+ type.get(0) != TypeSimple.getTypeSelf() ||
+ )) {
+ // TODO syntax_error (current_position,"Type `SELF' is needed.");
+ }*/
+
+ if (name.size() == 1) {
+ // Single Argument.
+ result = new ITMArgument(name.get(0), type.get(0));
+ // free arrays
+ } else {
+ // Vector Arguments.
+ // alias arrays...
+ TypeMulti tm = new TypeMulti(type.toArray(new ITypeMono[type.size()]));
+ result = new ITMArgs(name.toArray(new String[name.size()]), tm);
+ }
+ }
+ }
+ return result;
+ }
+
+ private Slot readSlotOperator(ArrayList<IArgument> list_arg) {
+ Slot result=null;
+ String associativity=null;
+ int priority=0;
+ Position slotPosition = getPosition();
+
+ if (! readOperator()) {
+ reporter.syntaxError("Operator is needed.", getPosition());
+ return null;
+ }
+ if (lastString.equals(ILisaacModel.symbol_equal) ||
+ lastString.equals(ILisaacModel.symbol_not_equal)) {
+ reporter.syntaxError("Incorrect operator.", getPosition());
+ return null;
+ }
+ String name = new String(lastString);
+ slotPosition.setLength(name.length());
+
+ if (! readCharacter('\'')) {
+ reporter.warning("Added `''.", getPosition());
+ }
+ if (readThisKeyword(ILisaacModel.keyword_left) ||
+ readThisKeyword(ILisaacModel.keyword_right)) {
+ associativity = new String(lastString);
+ if (readInteger()) {
+ priority = (int) lastInteger;
+ }
+ }
+ if (list_arg.isEmpty()) {
+ // Prefix operator.
+ IArgument arg = readLocArg(false,true);
+ if (arg == null) {
+ reporter.syntaxError("Operator declaration invalid.", getPosition());
+ return null;
+ }
+ list_arg.add(arg);
+ name = getOperator("__prefix", name);
+ if (associativity != null) {
+ reporter.syntaxError("No associativity for postfix operator.", getPosition());
+ }
+ } else {
+ IArgument arg = readLocArg(false,false);
+ if (arg != null) {
+ // Infix operator.
+ list_arg.add(arg);
+ name = getOperator("__infix", name);
+ if (associativity == null) {
+ associativity = ILisaacModel.keyword_left;
+ }
+ } else {
+ // Postfix operator.
+ name = getOperator("__postfix", name);
+ if (associativity != null) {
+ reporter.syntaxError("No associativity for prefix operator.", getPosition());
+ }
+ }
+ }
+ result = new Slot(slotPosition, name, lastSection);
+ result.setAssociativity(associativity, priority);
+
+ return result;
+ }
+
+ private String getOperator(String typ, String op) {
+ String s = new String(typ);
+
+ for (int i=0; i<op.length(); i++) {
+ char c = op.charAt(i);
+ switch (c) {
+ case '+': s += "_add"; break;
+ case '-': s += "_sub"; break;
+ case '~': s += "_logicnot"; break;
+ case '!': s += "_not"; break;
+ case '/': s += "_div"; break;
+ case '*': s += "_mul"; break;
+ case '^': s += "_xor"; break;
+ case '%': s += "_mod"; break;
+ case '>': s += "_greater"; break;
+ case '<': s += "_less"; break;
+ case '=': s += "_equal"; break;
+ case '\\': s += "_notdiv"; break;
+ case '|': s += "_or"; break;
+ case '&': s += "_and"; break;
+ case '$': s += "_dollar"; break;
+ case '#': s += "_diese"; break;
+ case '@': s += "_at"; break;
+ case '?': s += "_ask"; break;
+ }
+ }
+ return getString(s); // alias string
+ }
+
+ //++ EXPR -> { ASSIGN !!AMBIGU!! affect } EXPR_OPERATOR
+ //++ ASSIGN -> '(' IDF_ASSIGN { ',' IDF_ASSIGN } ')'
+ //++ | IDF_ASSIGN
+ //++ IDF_ASSIGN -> identifier { identifier }
+ public ICode readExpr() {
+ ICode result=null;
+ boolean again;
+ String string_tmp2="";
+
+ // !! AMBIGU resolution !!
+ saveContext();
+
+ if (readCharacter('(')) {
+ ArrayList<String> l_assignment = new ArrayList<String>();
+ do {
+ again = false;
+ if (readIdentifier()) {
+ //p = position - lastString.length();
+
+ string_tmp2 = new String(lastString);
+ while (readIdentifier()) {
+ string_tmp2 += "__" + lastString;
+ }
+ String name = getString(string_tmp2);
+ l_assignment.add(name);
+
+ if (readCharacter(',')) {
+ again = true;
+ }
+ }
+ } while(again);
+
+ if (!l_assignment.isEmpty() && readCharacter(')') && readAffect()) {
+ // result = ITM_LIST_IDF
+ // TODO get code result
+ result = new ITMFixme();
+
+ char affect = lastString.charAt(0);
+ ICode value = readExpr();
+ if (value == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return null;
+ }
+ switch (affect) {
+ case ':': break; // TODO code
+ case '<':
+ reporter.syntaxError("Impossible '<-' style assignment with vector.", getPosition());
+ return null;
+ case '?': break; // TODO code
+ }
+ } else {
+ // FREE l_assignment
+ }
+ } else if (readIdentifier()) {
+ //p = position - lastString.length();
+ string_tmp2 = new String(lastString);
+ while (readIdentifier()) {
+ string_tmp2 += "__" + lastString;
+ }
+ String name = getString(string_tmp2);
+
+ if (readAffect()) {
+ result = new ITMRead(name);
+
+ char affect = lastString.charAt(0);
+ ICode value = readExpr();
+ if (value == null) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ return null;
+ }
+ switch (affect) {
+ case ':': break; // TODO code
+ case '<': break; // TODO code
+ case '?': break; // TODO code
+ }
+ }
+ }
+ if (result == null) {
+ restoreContext();
+ result = readExprOperator();
+ }
+ return result;
+ }
+
+ //++ EXPR_OPERATOR-> { operator } EXPR_MESSAGE { operator {operator} EXPR_MESSAGE } {operator}
+ private ICode readExprOperator() {
+ ICode result=null;
+ int first_msg,last_msg;
+
+ ArrayList<ICode> l_expr = new ArrayList<ICode>();
+ while (readOperator()) {
+ ICode expr = new ITMOperator(new String(lastString));
+ l_expr.add(expr);
+ }
+ ICode expr = readExprMessage();
+ if (expr == null) {
+ // Error.
+ if (l_expr.size() > 0) {
+ reporter.syntaxError("Incorrect expression.", getPosition());
+ }
+ // free l_expr
+ } else {
+ // { operator {operator} EXPR_MESSAGE } {operator}
+ first_msg = l_expr.size();
+ do {
+ last_msg = l_expr.size();
+ l_expr.add(expr);
+ if (readOperator()) {
+ do {
+ expr = new ITMOperator(new String(lastString));
+ l_expr.add(expr);
+ } while (readOperator());
+
+ expr = readExprMessage();
+ } else {
+ expr = null;
+ }
+ } while (expr != null);
+
+ // Last Post-fix operator.
+ while (last_msg < l_expr.size()-1) {
+ ITMOperator itm_op = (ITMOperator) l_expr.get(last_msg+1);
+ expr = new ITMReadArg1(getOperator("__postfix", itm_op.getName()), l_expr.get(last_msg));
+
+ l_expr.add(last_msg, expr);
+ l_expr.remove(last_msg+1);
+ }
+ if (last_msg - first_msg < 3) {
+ // First Pre-fix operator.
+ while (first_msg != 0) {
+ ITMOperator itm_op = (ITMOperator) l_expr.get(first_msg - 1);
+ expr = new ITMReadArg1(getOperator("__prefix", itm_op.getName()), l_expr.get(first_msg));
+
+ l_expr.add(first_msg, expr);
+ first_msg = first_msg - 1;
+ l_expr.remove(first_msg);
+ }
+ }
+ if (l_expr.size() == 1) {
+ result = l_expr.get(0);// first
+ // free l_expr
+ } else if (l_expr.size() == 3) {
+ // Simple binary message.
+ ITMOperator itm_op = (ITMOperator) l_expr.get(1);// second
+ result = new ITMReadArg2(getOperator("__infix", itm_op.getName()),
+ l_expr.get(0),
+ l_expr.get(2));
+ // free l_expr
+ } else {
+ // Complex expression.
+ result = new ITMExpression(l_expr.toArray(new ICode[l_expr.size()]));
+ }
+ }
+ return result;
+ }
+
+ //++ EXPR_MESSAGE -> EXPR_BASE { '.' SEND_MSG }
+ protected ICode readExprMessage() {
+
+ ICode result = readExprBase();
+ if (result != null) {
+ while (readCharacter('.')) {
+ result = readSendMsg(result);
+ if (result == null) {
+ reporter.syntaxError("Incorrect message.", getPosition());
+ return null;
+ }
+ }
+ }
+ return result;
+ }
+
+ //++ EXPR_BASE -> "Old" EXPR
+ //++ | EXPR_PRIMARY
+ //++ | SEND_MSG
+ protected ICode readExprBase() {
+ ICode result=null;
+
+ if (readThisKeyword(ILisaacModel.keyword_old)) {
+ ICode old_value = readExpr();
+ if (old_value == null) {
+ reporter.syntaxError("Incorrect `Old' expression.", getPosition());
+ return null;
+ }
+ result = new ITMOld(old_value);
+ } else {
+ result = readExprPrimary();
+ if (result == null) {
+ result = readSendMsg(null);
+ }
+ }
+ return result;
+ }
+
+ //++ EXPR_PRIMARY -> "Self"
+ //++ | result
+ //++ | PROTOTYPE
+ //++ | CONSTANT
+ //++ | '(' GROUP ')'
+ //++ | '{' [ LOC_ARG ';' !! AMBIGU!! ] GROUP '}'
+ //++ | external [ ':' ['('] TYPE ['{' TYPE_LIST '}'] [')'] ]
+ public ICode readExprPrimary() {
+ ICode result=null;
+ String result_id=null;
+ ITypeMono type=null;
+ ITMList group_sav=null;
+
+ if (readThisKeyword(ILisaacModel.variable_self)) {
+ result = new ITMRead(new String(lastString));
+ } else if (readThisKeyword(ILisaacModel.keyword_result)) {
+ if (lastCharacter() == '_') {
+ position = position + 1;
+ string_tmp = "" + ILisaacModel.keyword_result + "_";
+
+ while (Character.isDigit(lastCharacter())) {
+ string_tmp += lastCharacter();
+ position = position + 1;
+ }
+ if (string_tmp.length() <= 0) {
+ reporter.syntaxError("Incorrect Result number.", getPosition());
+ }
+ result_id = getString(string_tmp);
+ } else {
+ result_id = ILisaacModel.keyword_result;
+ }
+ result = new ITMRead(result_id);
+
+ } else if ((type = readPrototype(null)) != null) {
+ result = new ITMPrototype(type);
+
+ } else if ((result = readConstant()) != null) {
+ } else if (readCharacter('(')) {
+ group_sav = lastGroup;
+ lastGroup = new ITMList();
+ result = lastGroup;
+
+ lastGroup.setCode(readGroup());
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')'.", getPosition());
+ return null;
+ }
+ lastGroup = group_sav;
+ } else if (readCharacter('{')) {
+ group_sav = lastGroup;
+ lastGroup = new ITMList();
+
+ saveContext(); // !! SAVE CONTEXT !!
+
+ //
+ IArgument arg = readLocArg(true,false);
+ //
+ if (arg != null) {
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';'.", getPosition());
+ return null;
+ }
+ } else {
+ restoreContext(); // !! RESTORE CONTEXT !!
+ }
+ result = new ITMBlock(lastGroup, arg);
+
+ lastGroup.setCode(readGroup());
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}'.", getPosition());
+ return null;
+ }
+ lastGroup = group_sav;
+ } else if (readExternal()) {
+ if (! readCharacter(':')) {
+ result = new ITMExternal(new String(lastString));
+ } else {
+ boolean persistant = readCharacter('(');
+ ITMExternalType ext = new ITMExternalType(new String(lastString), persistant);
+ type = readType(false);
+ if (type == null) {
+ reporter.syntaxError("Incorrect type.", getPosition());
+ return null;
+ }
+ ext.setType(type);
+ if (readCharacter('{')) {
+ ITypeMono[] ltype = readTypeList(false);
+ if (ltype == null) {
+ reporter.syntaxError("Incorrect live type list.", getPosition());
+ return null;
+ }
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}'.", getPosition());
+ return null;
+ }
+ ext.setTypeList(ltype);
+ }
+ if (ext.isPersistant() && (! readCharacter(')'))) {
+ reporter.syntaxError("Added '}'.", getPosition());
+ return null;
+ }
+ result = ext;
+ }
+ }
+ return result;
+ }
+
+ //++ CONSTANT -> integer
+ //++ | real
+ //++ | characters
+ //++ | string
+ private IConstant readConstant() {
+ IConstant result=null;
+
+ if (readReal()) {
+ result = new ITMReal(new String(lastReal));
+ } else if (readInteger()) {
+ result = new ITMNumber(lastInteger);
+ } else if (readCharacters()) {
+ result = new ITMCharacter(new String(lastString));
+ } else if (readString()) {
+ result = new ITMString(new String(lastString));
+ }
+ return result;
+ }
+
+ //++ GROUP -> DEF_LOCAL {EXPR ';'} [ EXPR {',' {EXPR ';'} EXPR } ]
+ private ICode[] readGroup() {
+ readDefLocal();
+
+ ArrayList<ICode> result = new ArrayList<ICode>();
+ ICode e = readExpr();
+ while (e != null && readCharacter(';')) {
+ result.add(e);
+ e = readExpr();
+ }
+ if (e != null) {
+ if (readCharacter(',')) {
+ do {
+ e = new ITMResult(e);
+ result.add(e);
+ e = readExpr();
+ while (e != null && readCharacter(';')) {
+ result.add(e);
+ e = readExpr();
+ }
+ if (e == null) {
+ reporter.syntaxError("Incorrect multiple result expression.", getPosition());
+ return null;
+ }
+ } while (readCharacter(','));
+ }
+ e = new ITMResult(e);
+ result.add(e);
+ }
+ return result.toArray(new ICode[result.size()]);
+ }
+
+ //++ DEF_LOCAL -> { style LOCAL ';' } !! AMBIGU !!
+ private void readDefLocal() {
+ List<ITMLocal> loc_lst;
+
+ saveContext(); // !! SAVE CONTEXT !!
+
+ char style = readStyle();
+ ArrayList<ITMLocal> local_list = new ArrayList<ITMLocal>();
+ ArrayList<ITMLocal> static_list = new ArrayList<ITMLocal>();
+
+ while (style != ' ') {
+ loc_lst = readLocal(true);
+ if (loc_lst != null) {
+ if (style == '+') {
+ local_list.addAll(loc_lst);
+ } else {
+ static_list.addAll(loc_lst);
+ }
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';'.", getPosition());
+ }
+ saveContext(); // !! SAVE CONTEXT !!
+
+ style = readStyle();
+ } else {
+ restoreContext(); // !! RESTORE CONTEXT !!
+ style = ' ';
+ }
+ }
+ if (local_list.isEmpty()) {
+ // free local_list
+ } else {
+ lastGroup.setLocalList(local_list.toArray(new ITMLocal[local_list.size()]));
+ }
+ if (static_list.isEmpty()) {
+ // free static_list
+ } else {
+ lastGroup.setStaticList(static_list.toArray(new ITMLocal[static_list.size()]));
+ }
+ }
+
+ //++ SEND_MSG -> identifier [ ARGUMENT { identifier ARGUMENT } ]
+ protected ICode readSendMsg(ICode firstArg) {
+ ICode result=null;
+
+ if (readIdentifier()) {
+ //
+ // Classic Message.
+ //
+ String n = getString(lastString);// create alias
+
+ // Argument list.
+ LinkedList<ICode> l_arg = new LinkedList<ICode>();
+ ICode arg = readArgument();
+ if (arg != null) {
+ l_arg.addLast(arg);
+ while (readIdentifier()) {
+ n += "__" + lastString; // FIXME: alias pb
+ arg = readArgument();
+ if (arg == null) {
+ reporter.syntaxError("Incorrect argument.", getPosition());
+ return null;
+ }
+ l_arg.addLast(arg);
+ }
+ }
+ String name = getString(n); // FIXME alias pb
+ if (l_arg.isEmpty()) {
+ if (firstArg == null) {
+ // Local ou Implicite Slot without argument.
+ result = new ITMRead(name);
+ } else {
+ result = new ITMReadArg1(name, firstArg);
+ }
+ // free l_arg
+ } else if (l_arg.size() == 1) {
+ result = new ITMReadArg2(name, firstArg, l_arg.get(0));
+ // free l_arg
+ } else {
+ l_arg.addFirst(firstArg);
+ result = new ITMReadArgs(name, l_arg.toArray(new ICode[l_arg.size()]));
+ }
+ }
+ return result;
+ }
+
+ //++ ARGUMENT -> EXPR_PRIMARY
+ //++ | identifier
+ private ICode readArgument() {
+ ICode result = readExprPrimary();
+ if (result == null && readIdentifier()) {
+ result = new ITMRead(new String(lastString));
+ }
+ return result;
+ }
+
+ //++ LOCAL -> { identifier [ ':' TYPE ] ',' } identifier ':' TYPE
+ private List<ITMLocal> readLocal(boolean m) {
+ List<ITMLocal> result=null;
+ int beg = 0;
+
+ boolean mute = m;
+ if (readIdentifier()) {
+ result = new LinkedList<ITMLocal>();
+ do {
+ if (result.size() != 0 && !readIdentifier() && !mute) {
+ reporter.syntaxError("Incorrect identifier.", getPosition());
+ return null;
+ }
+ ITMLocal loc = new ITMLocal(new String(lastString));
+ result.add(loc);
+ if (readCharacter(':') && lastCharacter() != '=') {
+ mute = false;
+ ITypeMono t = readType(false);
+ if (t == null) {
+ reporter.syntaxError("Incorrect local type.", getPosition());
+ return null;
+ }
+ for (int j=beg; j<result.size(); j++) {
+ result.get(j).setType(t);
+ }
+ beg = result.size(); // upper+1
+ }
+ } while(readCharacter(','));
+ if (beg != result.size()) {
+ if (mute) {
+ // free result
+ result = null;
+ } else {
+ reporter.syntaxError("Incorrect local type.", getPosition());
+ return null;
+ }
+ } else {
+ }
+ }
+ return result;
+ }
+
+ public boolean readRequire() {
+ boolean result=false;
+
+ ITMList lst = readContract();
+ if (lst != null) {
+ // lastSlot.setRequire lst
+ result = true;
+ }
+ return result;
+ }
+
+ public boolean readEnsure() {
+ boolean result=false;
+
+ ITMList lst = readContract();
+ if (lst != null) {
+ // lastSlot.setEnsure lst
+ result = true;
+ }
+ return result;
+ }
+
+ //++ CONTRACT -> '[' DEF_LOCAL { ( EXPR ';' | "..." ) } ']'
+ private ITMList readContract() {
+ ITMList result = null;
+
+ if (readCharacter('[')) {
+ result = new ITMList();
+ lastGroup = result;
+
+ readDefLocal();
+
+ ArrayList<ICode> lst = new ArrayList<ICode>();
+ boolean doContinue = false;
+ do {
+ ICode e = readExpr();
+ if (e == null) {
+ doContinue = readWord(ILisaacModel.keyword_ldots);
+ if (doContinue) {
+ lst.add(new ITMLDots());
+ }
+ } else {
+ lst.add(e);
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';'.", getPosition());
+ return null;
+ }
+ doContinue = true;
+ }
+ } while (doContinue);
+
+ if (! readCharacter(']')) {
+ reporter.syntaxError("Added ']'.", getPosition());
+ return null;
+ }
+ // TODO lst add prototype void
+ result.setCode(lst.toArray(new ICode[lst.size()]));
+ }
+ return result;
+ }
+
+ public boolean skipUntilThisKeyword(String st) {
+ int idx;
+ int posold;
+ boolean result=false;
+
+ while (! isEOF() && ! result) {
+ idx = 0;
+ while ((readSpace() || lastCharacter() == '\n') && lastCharacter() != st.charAt(idx)) {
+ position++;
+ }
+ posold = position;
+ position++;
+ idx++;
+ if (! isEOF()) {
+ while (idx <= st.length()-1 && lastCharacter() == st.charAt(idx)) {
+ position++;
+ idx++;
+ }
+ if (idx > st.length()-1) {
+ lastString = st;
+ position = posold;
+ result = true;
+ }
+ }
+ }
+ return result;
+ }
+
+ public String readSlotNameFromOffset(int offset) {
+ String result=null;
+ int oldPosition = position;
+ position = offset;
+
+ //++ TYPE_SLOT -> [ LOC_ARG '.' ] identifier [ LOC_ARG { identifier LOC_ARG } ]
+ //++ | [ LOC_ARG ] '\'' operator '\'' [("Left"|"Right") [integer]] [LOC_ARG]
+ if (! skipLocalArg(true)) {
+ if (readCharacter('\'')) {
+ result = readSlotNameOperator();
+ } else {
+ result = readSlotNameKeyword();
+ }
+ } else {
+ if (readCharacter('.')) {
+ result = readSlotNameKeyword();
+ } else if (readCharacter('\'')) {
+ result = readSlotNameOperator();
+ }
+ }
+ position = oldPosition;
+ return result;
+ }
+
+ //++ LOC_ARG -> identifier ':' TYPE
+ //++ | '(' LOCAL ')'
+ public boolean skipLocalArg(boolean selfFirst) {
+ boolean result=false;
+ if ((selfFirst && readThisKeyword(ILisaacModel.variable_self)) ||
+ (! selfFirst && readIdentifier())) {
+ if (readCharacter(':') && lastCharacter() != '=') {
+ return skipType();
+ }
+ } else if (readCharacter('(')) {
+ result = skipLocal(selfFirst);
+ if (! result) {
+ return false;
+ } else {
+ if (! readCharacter(')')) {
+ return false;
+ }
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ private boolean skipLocal(boolean s) {
+ boolean result = false;
+
+ if ((s && readThisKeyword(ILisaacModel.variable_self)) ||
+ readIdentifier()) {
+ int size = 0;
+ do {
+ if (size != 0 && !readIdentifier()) {
+ return false;
+ }
+ size++;
+ if (readCharacter(':') && lastCharacter() != '=') {
+ if (!skipType()) {
+ return false;
+ }
+ result = true;
+ }
+ } while (readCharacter(','));
+ }
+ return result;
+ }
+
+ private String readSlotNameKeyword() {
+ String result=null;
+
+ if (readIdentifier()) {
+ result = new String(lastString);
+
+ if (skipLocalArg(false)) {
+ if (readIdentifier()) {
+ do {
+ result += "__" + lastString;
+ if (! skipLocalArg(false)) {
+ return null;
+ }
+ } while (readIdentifier());
+ }
+ }
+ }
+ return result;
+ }
+
+ private String readSlotNameOperator() {
+ String result=null;
+
+ if (! readOperator()) {
+ return null;
+ }
+ result = new String(lastString);
+ result = getOperator("__infix", result);// TODO fix!! prefix postfix
+
+ return result;
+ }
+
+ //++ TYPE -> '{' [ (TYPE | '(' TYPE_LIST ')') ';' ] [ TYPE_LIST ] '}'
+ //++ | [type] PROTOTYPE [ CONTRACT ]
+ public boolean skipType () {
+ boolean result=false;
+
+ if (readCharacter('{')) {
+ // '{' [ (TYPE | '(' TYPE_LIST ')') ';' ] [ TYPE_LIST ] '}'
+ if (readCharacter('(')) {
+ // Read vector argument.
+ result = skipTypeList();
+ if (! result) {
+ return false;
+ }
+ if (! readCharacter(')')) {
+ return false;
+ }
+ if (! readCharacter(';')) {
+ return false;
+ }
+ // Read result type.
+ result = skipTypeList();
+ } else {
+
+ result = skipTypeList();
+ if (result) {
+ if (readCharacter(';')) {
+ // Read result type.
+ result = skipTypeList();
+ }
+ }
+ }
+ if (! readCharacter('}')) {
+ return false;
+ }
+ result = true;
+ } else {
+ // Expanded | Strict
+ if (readThisKeyword(ILisaacModel.keyword_expanded) ||
+ readThisKeyword(ILisaacModel.keyword_strict)) {
+ }
+ // PROTOTYPE
+ result = skipPrototype();
+ // TODO read contract
+ }
+ return result;
+ }
+
+ //++ TYPE_LIST -> TYPE { ',' TYPE }
+ public boolean skipTypeList() {
+ boolean result=false;
+
+ result = skipType();
+ if (result) {
+ while (readCharacter(',')) {
+ result = skipType();
+ if (! result) {
+ return false;
+ }
+ }
+ }
+ return result;
+ }
+
+ //++ PROTOTYPE -> cap_identifier{('.'|'...')cap_identifier}['('PARAM_TYPE{','PARAM_TYPE}')']
+ public boolean skipPrototype() {
+ boolean result=false;
+
+ if (readCapIdentifier()) {
+ // TODO syntax {('.'|'...')cap_identifier}
+ if (readCharacter('(')) {
+ //
+ // Genericity.
+ //
+ do {
+ if (! skipParamType()) {
+ return false;
+ }
+ } while (readCharacter(','));
+ if (! readCharacter(')')) {
+ return false;
+ }
+ result = true;
+ } else {
+ // Simple type.
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ //++ PARAM_TYPE -> TYPE
+ //++ | CONSTANT
+ //++ | identifier
+ private boolean skipParamType() {
+ if (! skipType()) {
+ // TODO compiler not yet implemented
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
+ * Read the next context in lisaac code.
+ * @return Context at parser position
+ */
+ public ILisaacContext readContext() {
+ readSpace();
+
+ int old_pos = position;
+
+ //
+ // Try read Section Context.
+ //
+ if (readThisKeyword (ILisaacModel.keyword_section)) {
+ position = old_pos;
+ return sectionContext;
+ }
+
+ //
+ // Try read Slot Context.
+ //
+ if (readCharacter('-') || readCharacter('+')) {
+ position = old_pos;
+ return slotContext;
+ }
+ // restore old position (unread)
+ position = old_pos;
+
+ if (position >= source.length()-1) {
+ return null;
+ } else {
+ // error
+ reporter.syntaxError("Syntax error", getPosition());
+ return sectionContext.getNextContext(); // go to next section
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/LisaacPath.java b/src/org/eclipse/lisaac/model/LisaacPath.java
new file mode 100644
index 0000000..3bd79de
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/LisaacPath.java
@@ -0,0 +1,85 @@
+package org.eclipse.lisaac.model;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.lisaac.launch.LisaacCompiler;
+import org.eclipse.swt.widgets.Display;
+
+
+public class LisaacPath {
+
+ private HashMap<String,String> prototypesPath;
+
+ private LisaacCompiler compiler;
+
+ public LisaacPath(final IProject project, String lipFile) {
+ prototypesPath = new HashMap<String,String>();
+
+ compiler = new LisaacCompiler("", lipFile);
+ compiler.addOption("--p");
+ try {
+ final Process process = compiler.launch(project, new NullProgressMonitor());
+ if (process != null) {
+
+ Runnable getPathFile = new Runnable() {
+ public void run() {
+ try {
+ // wait for end of process
+ process.waitFor();
+
+ BufferedReader bufferIn = new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(project.getLocation()+"/src/current_path.txt")));
+
+ String line;
+ while ((line = bufferIn.readLine()) != null) {
+ createPath(line);
+ }
+ bufferIn.close();
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ };
+ // execute action in a new thread UI safe
+ Display.getDefault().asyncExec(getPathFile);
+ //Thread runCommand = new Thread(getStandardOutput);
+ //runCommand.start();
+ }
+ } catch (CoreException e) {
+ //LisaacPlugin.log(status) // TODO log error
+ e.printStackTrace();
+ }
+ }
+
+ public String getFullPath(String prototypeName) {
+ if (prototypesPath.containsKey(prototypeName)) {
+ return prototypesPath.get(prototypeName);
+ }
+ return null;
+ }
+
+ private void createPath(String fullPath) {
+ int index = fullPath.lastIndexOf("/");
+ String prototypeName = fullPath.substring(index+1);
+ index = prototypeName.lastIndexOf(".");
+ prototypeName = prototypeName.substring(0, index).toUpperCase();
+ prototypesPath.put(prototypeName, fullPath);
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/Position.java b/src/org/eclipse/lisaac/model/Position.java
new file mode 100644
index 0000000..8ea2432
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/Position.java
@@ -0,0 +1,52 @@
+package org.eclipse.lisaac.model;
+
+public class Position {
+ public int line;
+ public int column;
+ public int offset;
+ public int length;
+
+ public Position(int line, int column, int offset) {
+ super();
+ this.line = line;
+ this.column = column;
+ this.offset = offset;
+ length = 0;
+ }
+ public Position(int line, int column, int offset, int len) {
+ super();
+ this.line = line;
+ this.column = column;
+ this.offset = offset;
+ length = len;
+ }
+
+ public int getLine() {
+ return line;
+ }
+ public int getColumn() {
+ return column;
+ }
+
+ public boolean hasRange() {
+ return length != 0;
+ }
+
+ public int getCharStart() {
+ return column;
+ }
+ public int getCharEnd() {
+ return column+length;
+ }
+
+ public int getStartOffset() {
+ return offset;
+ }
+
+ public int length() {
+ return length;
+ }
+ public void setLength(int l) {
+ length = l;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/SectionContext.java b/src/org/eclipse/lisaac/model/SectionContext.java
new file mode 100644
index 0000000..485f4c0
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/SectionContext.java
@@ -0,0 +1,263 @@
+package org.eclipse.lisaac.model;
+
+import org.eclipse.lisaac.model.items.Prototype;
+import org.eclipse.lisaac.model.items.Section;
+import org.eclipse.lisaac.model.types.ITypeMono;
+
+public class SectionContext implements ILisaacContext {
+
+ private LisaacParser parser;
+ private boolean firstSection;
+
+ public SectionContext(LisaacParser parser) {
+ this.parser = parser;
+ firstSection = true;
+ }
+
+ public boolean parseDefinition(Prototype prototype) {
+
+ parser.readSpace();
+
+ // read Section
+ if (! parser.readThisKeyword (ILisaacModel.keyword_section)) {
+ parser.getReporter().syntaxError("`Section' is needed.", parser.getPosition());
+ return false;
+ }
+
+ if (firstSection) {
+ //
+ // Read Section Header.
+ //
+ if (! parser.readThisKeyword (ILisaacModel.section_header)) {
+ parser.getReporter().syntaxError("Section `Header' is needed.", parser.getPosition());
+ return false;
+ }
+ firstSection = false;
+ if (! readSectionHeaderContent(prototype)) {
+ return false;
+ }
+ } else {
+ //
+ // Read Other Section.
+ //
+ if (parser.readKeyword()) {
+ String section = parser.getLastString();
+ if (section.equals(ILisaacModel.section_inherit) ||
+ section.equals(ILisaacModel.section_insert) ||
+ section.equals(ILisaacModel.section_interrupt) ||
+ section.equals(ILisaacModel.section_private) ||
+ section.equals(ILisaacModel.section_public) ||
+ section.equals(ILisaacModel.section_mapping) ||
+ section.equals(ILisaacModel.section_directory) ||
+ section.equals(ILisaacModel.section_external)) {
+
+ Section lastSection = new Section(prototype, section);
+ parser.setLastSection(lastSection);
+
+ if (lastSection.isInheritOrInsert() &&
+ parser.getLastSlot() != null &&
+ ! parser.getLastSlot().getSectionId().isInheritOrInsert()) {
+ parser.getReporter().syntaxError("`Section Inherit/Insert' must to be first section.", parser.getPosition());
+ return false;
+
+ } else if (prototype.isExpanded() && section.equals(ILisaacModel.section_inherit)) {
+ parser.getReporter().warning("`Section Inherit' is not possible with Expanded object (Use `Section Insert').", parser.getPosition());
+ }
+ } else {
+ parser.getReporter().syntaxError("Incorrect type section.", parser.getPosition());
+ return false;
+ }
+ } else {
+ // TYPE_LIST.
+ ITypeMono[] t = parser.readTypeList(true);
+ if (t == null) {
+ parser.getReporter().syntaxError("Incorrect type section.", parser.getPosition());
+ return false;
+ }
+ parser.setLastSection(new Section(prototype, t));
+ }
+ // content of section is out of this context
+ }
+ return true;
+ }
+
+ private boolean readSectionHeaderContent(Prototype prototype) {
+ boolean result;
+ boolean first=true;
+
+ //
+ // Read Slots of Section Header.
+ //
+ do {
+ result = false;
+
+ char style = parser.readStyle();
+ if (style != ' ') {
+ result = true;
+
+ if (!first && style == '+') {
+ parser.getReporter().warning("Incorrect style slot ('-').", parser.getPosition());
+ }
+ if (first) {
+ first = false;
+
+ if (parser.readWord(ILisaacModel.slot_name)) {
+ //
+ // Read `name' slot.
+ //
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getPosition());
+ return false;
+ }
+ if (parser.readThisKeyword(ILisaacModel.keyword_expanded) ||
+ parser.readThisKeyword(ILisaacModel.keyword_strict)) {
+ prototype.setTypeStyle(parser.getLastString());
+ }
+ if (! parser.readCapIdentifier()) {
+ parser.getReporter().syntaxError("Prototype identifier is needed.", parser.getPosition());
+ return false;
+ }
+ if (parser.getLastString().compareTo(prototype.getName()) != 0) {
+ parser.getReporter().syntaxError("Incorrect name (filename != name).", parser.getPosition());
+ }
+
+ if (parser.readCharacter('(')) {
+ //
+ // Generic loader.
+ //
+ // TODO error for non generic object
+ if (parser.readIdentifier()) {
+ return false;
+ // TODO syntax identifier : PROTO
+ } else if (parser.readCapIdentifier()) {
+ // TODO error Identifier parameter type is needed.
+
+ while (parser.readCharacter(',')) {
+ // TODO error Identifier parameter type is needed.
+ if (! parser.readCapIdentifier()) {
+ parser.getReporter().syntaxError("Identifier parameter type is needed.", parser.getPosition());
+ return false;
+ }
+ }
+ if (! parser.readCharacter(')')) {
+ parser.getReporter().syntaxError("Added ')'.", parser.getPosition());
+ return false;
+ }
+ } else {
+ parser.getReporter().syntaxError("Identifier parameter type is needed.", parser.getPosition());
+ return false;
+ }
+ }
+
+ } else {
+ parser.getReporter().syntaxError("Slot `name' must to be first slot.", parser.getPosition());
+ }
+
+ } else if (parser.readWord(ILisaacModel.slot_export) ||
+ parser.readWord(ILisaacModel.slot_import)) {
+
+ // - ("export"|"import") ':=' TYPE_LIST
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getPosition());
+ return false;
+ }
+ if (parser.readTypeList(false) == null) {
+ parser.getReporter().syntaxError("Incorrect type list.", parser.getPosition());
+ return false;
+ }
+ // TODO store export / import
+
+ } else if (parser.readWord(ILisaacModel.slot_external)) {
+ // - "external" ':=' `<code_c>`
+
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getPosition());
+ return false;
+ }
+ if (! parser.readExternal()) {
+ parser.getReporter().syntaxError("Incorrect external.", parser.getPosition());
+ return false;
+ }
+ } else if (parser.readWord(ILisaacModel.slot_default)) {
+ // '-' "default" ':=' EXPR_PRIMARY
+
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getPosition());
+ return false;
+ }
+ if (parser.readExprPrimary() == null) {
+ parser.getReporter().syntaxError("Incorrect expr.", parser.getPosition());
+ return false;
+ }
+ // TODO check double default slot
+ // TODO set prototyp default value
+ } else if (parser.readWord(ILisaacModel.slot_type)) {
+ // '-' "type" ':=' `<type C>`
+
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getPosition());
+ return false;
+ }
+ if (! parser.readExternal()) {
+ parser.getReporter().syntaxError("Incorrect external.", parser.getPosition());
+ return false;
+ }
+ // TODO check double type declaration
+
+ } else if (parser.readWord(ILisaacModel.slot_version)) {
+ //
+ // Read `version' slot.
+ //
+
+ // '-' "version" ':=' integer
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getPosition());
+ return false;
+ }
+ if (! parser.readInteger()) {
+ parser.getReporter().syntaxError("Incorrect number.", parser.getPosition());
+ return false;
+ }
+ // } else if () { TODO lip
+ } else if (parser.readWord(ILisaacModel.slot_date) ||
+ parser.readWord(ILisaacModel.slot_comment) ||
+ parser.readWord(ILisaacModel.slot_author) ||
+ parser.readWord(ILisaacModel.slot_bibliography) ||
+ parser.readWord(ILisaacModel.slot_language) ||
+ parser.readWord(ILisaacModel.slot_copyright) ||
+ parser.readWord(ILisaacModel.slot_bug_report)) {
+ //
+ // Read `date', `comment', `author', `bibliography',
+ // `language', `copyright' or `bug_report' slots.
+ //
+
+ // '-' ("date"|"comment"|"author"|"bibliography"|"language"|"copyright"|"bug_report")
+ // ':=' string
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getPosition());
+ return false;
+ }
+ if (! parser.readString()) {
+ parser.getReporter().syntaxError("Incorrect string.", parser.getPosition());
+ return false;
+ }
+ } else {
+ parser.getReporter().syntaxError("Incorrect slot.", parser.getPosition());
+ return false;
+ }
+ if (! parser.readCharacter(';')) {
+ parser.getReporter().warning("Added ';'.", parser.getPosition());
+ }
+ }
+ } while (! parser.isEOF() && result);
+
+ return true;
+ }
+
+ public ILisaacContext getNextContext() {
+ if (parser.skipUntilThisKeyword(ILisaacModel.keyword_section)) {
+ return this;
+ }
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/SlotContext.java b/src/org/eclipse/lisaac/model/SlotContext.java
new file mode 100644
index 0000000..08ce9a7
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/SlotContext.java
@@ -0,0 +1,29 @@
+package org.eclipse.lisaac.model;
+
+import org.eclipse.lisaac.model.items.Prototype;
+
+public class SlotContext implements ILisaacContext {
+ private LisaacParser parser;
+
+ public SlotContext(LisaacParser parser) {
+ this.parser = parser;
+ }
+
+ //++ SLOT -> style TYPE_SLOT [':' (TYPE|'('TYPE_LIST')') ][ affect DEF_SLOT ]';'
+ public boolean parseDefinition(Prototype prototype) {
+ boolean result=false;
+
+ result = parser.readSlot(prototype);
+
+ return result;
+ }
+
+ public ILisaacContext getNextContext() {
+ // FIXME skip until next slot !!!!
+ if (parser.skipUntilThisKeyword(ILisaacModel.keyword_section)) {
+ return parser.getSectionContext();
+ }
+ return null;
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/items/IArgument.java b/src/org/eclipse/lisaac/model/items/IArgument.java
new file mode 100644
index 0000000..6e8d761
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/IArgument.java
@@ -0,0 +1,12 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public interface IArgument {
+
+ String getName();
+
+ IType getType();
+
+ void printIn(StringBuffer buffer);
+}
diff --git a/src/org/eclipse/lisaac/model/items/ICode.java b/src/org/eclipse/lisaac/model/items/ICode.java
new file mode 100644
index 0000000..7983b18
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ICode.java
@@ -0,0 +1,8 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public interface ICode {
+
+ IType getType(Slot slot);
+}
diff --git a/src/org/eclipse/lisaac/model/items/IConstant.java b/src/org/eclipse/lisaac/model/items/IConstant.java
new file mode 100644
index 0000000..1747e69
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/IConstant.java
@@ -0,0 +1,5 @@
+package org.eclipse.lisaac.model.items;
+
+public interface IConstant extends ICode {
+
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMArgs.java b/src/org/eclipse/lisaac/model/items/ITMArgs.java
new file mode 100644
index 0000000..ebfd082
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMArgs.java
@@ -0,0 +1,51 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.TypeMulti;
+
+public class ITMArgs implements IArgument {
+
+ protected String[] name;
+ protected TypeMulti type;
+
+ public ITMArgs(String[] name, TypeMulti type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public String getName() {
+ return "(ARGS)"; // TODO print arguments
+ }
+
+ private int lastIndexOf(String word) {
+ for (int i=0; i<name.length; i++) {
+ if (name[i].compareTo(word) == 0) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public boolean hasArgument(String word) {
+ return lastIndexOf(word) != -1;
+ }
+
+ public IType getType() {
+ // TODO Auto-generated method stub
+ return null;// FIXME list arg type
+ }
+
+ public IType getArgType(String name) {
+ int index = lastIndexOf(name);
+ if (index != -1) {
+ return type.getSubType(index);
+ }
+ return null;
+ }
+
+ public void printIn(StringBuffer buffer) {
+ // TODO print multi
+ buffer.append("TODO");
+ }
+}
+
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/model/items/ITMArgument.java b/src/org/eclipse/lisaac/model/items/ITMArgument.java
new file mode 100644
index 0000000..ff002a2
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMArgument.java
@@ -0,0 +1,29 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.ITypeMono;
+
+public class ITMArgument implements IArgument {
+
+ protected String name;
+ protected ITypeMono type;
+
+ public ITMArgument(String name, ITypeMono type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public IType getType() {
+ return type;
+ }
+
+ public void printIn(StringBuffer buffer) {
+ buffer.append(name);
+ buffer.append(':');
+ buffer.append(type);
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMBlock.java b/src/org/eclipse/lisaac/model/items/ITMBlock.java
new file mode 100644
index 0000000..ee9077b
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMBlock.java
@@ -0,0 +1,18 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.TypeBlock;
+
+public class ITMBlock implements ICode {
+ protected ITMList list;
+ protected IArgument argument;
+
+ public ITMBlock(ITMList list, IArgument argument) {
+ this.list = list;
+ this.argument = argument;
+ }
+
+ public IType getType(Slot slot) {
+ return TypeBlock.get(null, null); // FIXME empty block
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMCharacter.java b/src/org/eclipse/lisaac/model/items/ITMCharacter.java
new file mode 100644
index 0000000..87c9253
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMCharacter.java
@@ -0,0 +1,17 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.TypeSimple;
+
+public class ITMCharacter implements IConstant {
+
+ public ITMCharacter(String string) {
+ // TODO Auto-generated constructor stub
+ }
+
+ public IType getType(Slot slot) {
+ return TypeSimple.get(ILisaacModel.prototype_character);
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMExpression.java b/src/org/eclipse/lisaac/model/items/ITMExpression.java
new file mode 100644
index 0000000..7c827e5
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMExpression.java
@@ -0,0 +1,21 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+/**
+ * operator list message
+ */
+public class ITMExpression implements ICode {
+ protected ICode[] valueList;
+
+ public ITMExpression(ICode[] list) {
+ valueList = list;
+ }
+
+ public IType getType(Slot slot) {
+ if (valueList != null && valueList.length > 0) {
+ return valueList[valueList.length-1].getType(slot); // FIXME expr type
+ }
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMExternal.java b/src/org/eclipse/lisaac/model/items/ITMExternal.java
new file mode 100644
index 0000000..793dec1
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMExternal.java
@@ -0,0 +1,15 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public class ITMExternal implements ICode {
+ protected String extern;
+
+ public ITMExternal(String extern) {
+ this.extern = extern;
+ }
+
+ public IType getType(Slot slot) {
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMExternalType.java b/src/org/eclipse/lisaac/model/items/ITMExternalType.java
new file mode 100644
index 0000000..579ea33
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMExternalType.java
@@ -0,0 +1,36 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.ITypeMono;
+
+public class ITMExternalType extends ITMExternal {
+
+ protected ITypeMono type;
+ protected ITypeMono[] typeList;
+ protected boolean persistant;
+
+ public ITMExternalType(String extern, boolean persistant) {
+ super(extern);
+ this.persistant = persistant;
+ }
+
+ public boolean isPersistant() {
+ return persistant;
+ }
+
+ public ITypeMono getType(Prototype prototype) {
+ return type;
+ }
+
+ public void setType(ITypeMono type) {
+ this.type = type;
+ }
+
+ public ITypeMono[] getTypeList() {
+ return typeList;
+ }
+
+ public void setTypeList(ITypeMono[] typeList) {
+ this.typeList = typeList;
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMFixme.java b/src/org/eclipse/lisaac/model/items/ITMFixme.java
new file mode 100644
index 0000000..6c9f69c
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMFixme.java
@@ -0,0 +1,10 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public class ITMFixme implements ICode {
+
+ public IType getType(Slot slot) {
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMLDots.java b/src/org/eclipse/lisaac/model/items/ITMLDots.java
new file mode 100644
index 0000000..b030a66
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMLDots.java
@@ -0,0 +1,10 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public class ITMLDots implements ICode {
+
+ public IType getType(Slot slot) {
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMList.java b/src/org/eclipse/lisaac/model/items/ITMList.java
new file mode 100644
index 0000000..c6f437e
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMList.java
@@ -0,0 +1,52 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public class ITMList implements ICode {
+ protected ICode[] code;
+ protected ITMLocal[] localList;
+ protected ITMLocal[] staticList;
+
+ public ITMList() {
+ }
+
+ public void setCode(ICode[] code) {
+ this.code = code;
+ }
+
+ public void setLocalList(ITMLocal[] list) {
+ localList = list;
+ }
+ public void setStaticList(ITMLocal[] list) {
+ staticList = list;
+ }
+
+ public boolean hasVariableDefinition(String word) {
+ return getLocal(word) != null;
+ }
+
+ public ITMLocal getLocal(String word) {
+ if (localList != null) {
+ for (int i=0; i<localList.length; i++) {
+ if (localList[i].name.compareTo(word) == 0) {
+ return localList[i];
+ }
+ }
+ }
+ if (staticList != null) {
+ for (int i=0; i<staticList.length; i++) {
+ if (staticList[i].name.compareTo(word) == 0) {
+ return staticList[i];
+ }
+ }
+ }
+ return null;
+ }
+
+ public IType getType(Slot slot) {
+ if (code != null && code.length > 0) {
+ return code[code.length-1].getType(slot); // FIXME list type
+ }
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMLocal.java b/src/org/eclipse/lisaac/model/items/ITMLocal.java
new file mode 100644
index 0000000..ed305de
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMLocal.java
@@ -0,0 +1,29 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.ITypeMono;
+
+/**
+ * Local declaration slot
+ */
+public class ITMLocal {
+ protected ITypeMono type;
+ protected String name;
+
+ public ITMLocal(String name) {
+ this.name = name;
+ }
+
+ public ITMLocal(ITypeMono type, String name) {
+ this.type = type;
+ this.name = name;
+ }
+
+ public IType getType() {
+ return type;
+ }
+
+ public void setType(ITypeMono type) {
+ this.type = type;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMNumber.java b/src/org/eclipse/lisaac/model/items/ITMNumber.java
new file mode 100644
index 0000000..f98f100
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMNumber.java
@@ -0,0 +1,16 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.TypeSimple;
+
+public class ITMNumber implements IConstant {
+
+ public ITMNumber(long lastInteger) {
+ // TODO Auto-generated constructor stub
+ }
+
+ public IType getType(Slot slot) {
+ return TypeSimple.get(ILisaacModel.prototype_integer);
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMOld.java b/src/org/eclipse/lisaac/model/items/ITMOld.java
new file mode 100644
index 0000000..904d18e
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMOld.java
@@ -0,0 +1,18 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public class ITMOld implements ICode {
+ protected ICode value;
+
+ public ITMOld(ICode value) {
+ this.value = value;
+ }
+
+ public IType getType(Slot slot) {
+ if (value != null) {
+ return value.getType(slot);
+ }
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMOperator.java b/src/org/eclipse/lisaac/model/items/ITMOperator.java
new file mode 100644
index 0000000..89624a9
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMOperator.java
@@ -0,0 +1,20 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public class ITMOperator implements ICode {
+ protected String name;
+
+ public ITMOperator(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public IType getType(Slot slot) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMPrototype.java b/src/org/eclipse/lisaac/model/items/ITMPrototype.java
new file mode 100644
index 0000000..2e5b9ca
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMPrototype.java
@@ -0,0 +1,17 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.ITypeMono;
+import org.eclipse.lisaac.model.types.TypeSimple;
+
+public class ITMPrototype implements ICode {
+ protected ITypeMono type;
+
+ public ITMPrototype(ITypeMono type) {
+ this.type = type;
+ }
+
+ public IType getType(Slot slot) {
+ return type;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMRead.java b/src/org/eclipse/lisaac/model/items/ITMRead.java
new file mode 100644
index 0000000..0bbd632
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMRead.java
@@ -0,0 +1,48 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.TypeSimple;
+
+public class ITMRead implements ICode {
+ protected String name;
+
+ public ITMRead(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public IType getType(Slot slot) {
+ if (slot != null) {
+ if (name.equals(ILisaacModel.variable_self)) {// type simple?
+ return TypeSimple.get(slot.getPrototype().getName());
+ }
+ IArgument arg = slot.getArgument(name);
+ if (arg != null) {
+ if (arg instanceof ITMArgs) {
+ return ((ITMArgs) arg).getArgType(name);
+ }
+ return arg.getType();
+ }
+ if (slot.getValue() instanceof ITMList) {
+ ITMList list = (ITMList) slot.getValue();
+ ITMLocal local = list.getLocal(name);
+ if (local != null) {
+ return local.getType();
+ }
+ }
+ // TODO lookup in parent proto slots
+ Prototype parent = slot.getPrototype();
+ if (parent != null) {
+ Slot s = parent.getSlot(name);
+ if (s != null) {
+ return s.getResultType();
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMReadArg1.java b/src/org/eclipse/lisaac/model/items/ITMReadArg1.java
new file mode 100644
index 0000000..34bd833
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMReadArg1.java
@@ -0,0 +1,11 @@
+package org.eclipse.lisaac.model.items;
+
+public class ITMReadArg1 extends ITMRead {
+
+ protected ICode arg;
+
+ public ITMReadArg1(String name, ICode arg) {
+ super(name);
+ this.arg = arg;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMReadArg2.java b/src/org/eclipse/lisaac/model/items/ITMReadArg2.java
new file mode 100644
index 0000000..9a34388
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMReadArg2.java
@@ -0,0 +1,14 @@
+package org.eclipse.lisaac.model.items;
+
+public class ITMReadArg2 extends ITMRead {
+
+ protected ICode argFirst;
+ protected ICode argSecond;
+
+ public ITMReadArg2(String name, ICode a1, ICode a2) {
+ super(name);
+ this.argFirst = a1;
+ this.argSecond = a2;
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMReadArgs.java b/src/org/eclipse/lisaac/model/items/ITMReadArgs.java
new file mode 100644
index 0000000..92731f3
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMReadArgs.java
@@ -0,0 +1,10 @@
+package org.eclipse.lisaac.model.items;
+
+public class ITMReadArgs extends ITMRead {
+ protected ICode[] args;
+
+ public ITMReadArgs(String name, ICode[] args) {
+ super(name);
+ this.args = args;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMReal.java b/src/org/eclipse/lisaac/model/items/ITMReal.java
new file mode 100644
index 0000000..0e2c156
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMReal.java
@@ -0,0 +1,16 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.TypeSimple;
+
+public class ITMReal implements IConstant {
+
+ public ITMReal(String string) {
+ // TODO Auto-generated constructor stub
+ }
+
+ public IType getType(Slot slot) {
+ return TypeSimple.get(ILisaacModel.prototype_real);
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMResult.java b/src/org/eclipse/lisaac/model/items/ITMResult.java
new file mode 100644
index 0000000..fcea19e
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMResult.java
@@ -0,0 +1,18 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.types.IType;
+
+public class ITMResult implements ICode {
+ protected ICode value;
+
+ public ITMResult(ICode value) {
+ this.value = value;
+ }
+
+ public IType getType(Slot slot) {
+ if (value != null) {
+ return value.getType(slot);
+ }
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/ITMString.java b/src/org/eclipse/lisaac/model/items/ITMString.java
new file mode 100644
index 0000000..154ffb6
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/ITMString.java
@@ -0,0 +1,18 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.lisaac.model.types.TypeSimple;
+
+public class ITMString implements IConstant {
+
+ protected String string;
+
+ public ITMString(String string) {
+ this.string = string;
+ }
+
+ public IType getType(Slot slot) {
+ return TypeSimple.get(ILisaacModel.prototype_string);
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/Prototype.java b/src/org/eclipse/lisaac/model/items/Prototype.java
new file mode 100644
index 0000000..1dbd53a
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/Prototype.java
@@ -0,0 +1,173 @@
+package org.eclipse.lisaac.model.items;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.lisaac.model.LisaacParser;
+import org.eclipse.lisaac.outline.OutlineItem;
+import org.eclipse.lisaac.outline.OutlinePrototype;
+import org.eclipse.lisaac.outline.OutlineSlot;
+import org.eclipse.swt.graphics.Image;
+
+
+public class Prototype {
+ protected String filename;
+
+ protected ILisaacModel parent;
+ protected LisaacParser parser;
+
+ protected String name;
+ protected String typeStyle;
+
+ protected HashMap<String,Slot> slotList;
+
+ public Prototype(String filename, String name, ILisaacModel model) {
+ this.filename = filename;
+ this.name = name;
+ this.parent = model;
+ this.parser = model.getParser();
+
+ slotList = new HashMap<String,Slot>();
+ }
+
+ public ILisaacModel getModel() {
+ return parent;
+ }
+
+ public boolean setName(String n) {
+ if (name != null && name.equals(n)) {
+ return false;
+ }
+ name = n;
+ return true;
+ }
+
+ public String getFileName() {
+ return filename;
+ }
+ public String getName() {
+ return name;
+ }
+
+ public LisaacParser openParser() {
+ parser.initialize();
+ return parser;
+ }
+
+ public void setTypeStyle(String s) {
+ typeStyle = s;
+ }
+ public String getTypeStyle() {
+ return typeStyle;
+ }
+
+ public boolean isExpanded() {
+ if (typeStyle != null) {
+ return typeStyle.equals(ILisaacModel.keyword_expanded) ||
+ name.equals(ILisaacModel.prototype_true) ||
+ name.equals(ILisaacModel.prototype_false);
+ }
+ return false;
+ }
+
+ public Slot getSlot(String n) {
+ if (slotList.containsKey(n)) {
+ return slotList.get(n);
+ }
+ return null;
+ }
+
+ public Slot getSlot(int offset) {
+ return getSlot(openParser(), offset);
+ }
+ public Slot getSlot(String s, int offset) {
+ return getSlot(new LisaacParser(s), offset);
+ }
+
+ public Slot getSlot(LisaacParser parser, int offset) {
+ //
+ // Use indentation to get slot
+ //
+ String source = parser.getSource();
+ boolean again;
+
+ if (offset >= source.length()) {
+ return null;
+ }
+
+ do {
+ again = false;
+
+ // find beginning of line
+ while (offset > 0 && source.charAt(offset) != '\n') {
+ offset--;
+ }
+ // look at indentation
+ if (offset > 0 && source.length() > 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) {
+ return getSlot(slotName);
+ }
+ } else {
+ again = true;
+ offset--;
+ }
+ }
+ } while (again);
+
+ return null;
+ }
+
+ public void addSlot(Slot s) {
+ slotList.put(s.getName(), s);
+ }
+
+ public List<OutlineItem> getOutlineItems() {
+ List<OutlineItem> slots = new ArrayList<OutlineItem>();
+
+ Collection<Slot> values = slotList.values() ;
+ Iterator<Slot> it = values.iterator() ;
+ while (it.hasNext()) {
+ Slot slot = it.next();
+ slots.add(new OutlineSlot(slot));
+ }
+ List<OutlineItem> result = new ArrayList<OutlineItem>();
+ result.add(new OutlinePrototype(this, slots));
+ return result;
+ }
+
+ public void getSlotProposals(ArrayList<CompletionProposal> proposals,
+ int offset, int length) {
+ Collection<Slot> values = slotList.values() ;
+ Iterator<Slot> it = values.iterator() ;
+ while (it.hasNext()) {
+ Slot slot = it.next();
+ Image image = new OutlineSlot(slot).getImage();
+ String displayString = slot.getSignature(true);
+
+ proposals.add(new CompletionProposal(displayString,
+ offset, length, displayString.length(), image,
+ slot.getSignature(false), null, null));
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/eclipse/lisaac/model/items/Section.java b/src/org/eclipse/lisaac/model/items/Section.java
new file mode 100644
index 0000000..c1fa84b
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/Section.java
@@ -0,0 +1,108 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.lisaac.model.types.ITypeMono;
+
+public class Section {
+ protected Prototype prototype;
+
+ protected String name;
+ protected ITypeMono[] typeList;
+
+ public Section(Prototype prototype, String name) {
+ this.name = name;
+ this.prototype = prototype;
+ }
+
+ public Section(Prototype prototype, ITypeMono[] typeList) {
+ this.typeList = typeList;
+ this.prototype = prototype;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ITypeMono[] getTypeList() {
+ return typeList;
+ }
+
+ //
+ // Consultation
+ //
+
+ public boolean isMapping() {
+ if (name == null) {
+ return false;
+ }
+ return name.equals(ILisaacModel.section_mapping);
+ }
+
+ public boolean isPrivate() {
+ if (name == null) {
+ return true;
+ }
+ return name.equals(ILisaacModel.section_private);
+ }
+
+ public boolean isPublic() {
+ if (name != null) {
+ return name.equals(ILisaacModel.section_public);
+ }
+ return false;
+ }
+
+ public boolean isHeader() {
+ if (name == null) {
+ return false;
+ }
+ return name.equals(ILisaacModel.section_header);
+ }
+
+ public boolean isInherit() {
+ if (name == null) {
+ return false;
+ }
+ return name.equals(ILisaacModel.section_inherit);
+ }
+
+ public boolean isInsert() {
+ if (name == null) {
+ return false;
+ }
+ return name.equals(ILisaacModel.section_insert);
+ }
+
+ public boolean isInheritOrInsert() {
+ return isInherit() || isInsert();
+ }
+
+ public boolean isInterrupt() {
+ if (name == null) {
+ return false;
+ }
+ return name.equals(ILisaacModel.section_interrupt);
+ }
+
+ public boolean isDirectory() {
+ if (name == null) {
+ return false;
+ }
+ return name.equals(ILisaacModel.section_directory);
+ }
+
+ public boolean isExternal() {
+ if (name == null) {
+ return false;
+ }
+ return name.equals(ILisaacModel.section_external);
+ }
+
+ public boolean isPrivateStyle() {
+ return !isPublic() && typeList == null;
+ }
+
+ public Prototype getPrototype() {
+ return prototype;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/items/Slot.java b/src/org/eclipse/lisaac/model/items/Slot.java
new file mode 100644
index 0000000..d3701d3
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/items/Slot.java
@@ -0,0 +1,174 @@
+package org.eclipse.lisaac.model.items;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.lisaac.model.Position;
+import org.eclipse.lisaac.model.types.IType;
+
+public class Slot {
+
+ protected Section sectionId;
+ protected Position position;
+
+ protected String name;
+ protected char style;
+ protected char affect; // ':', '?', '<'
+
+ protected IArgument[] argumentList;
+ protected IType resultType;
+
+ protected String[] keywordList;
+
+
+ public Slot(Position position, String name, Section sectionId) {
+ this.name = name;
+ this.position = position;
+ this.sectionId = sectionId;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public char getStyle() {
+ return style;
+ }
+
+ public char getAffect() {
+ return affect;
+ }
+
+ public IArgument getArgument(int i) {
+ return argumentList[i];
+ }
+
+ public Section getSectionId() {
+ return sectionId;
+ }
+
+ public IType getResultType() {
+ return resultType;
+ }
+
+ public void setArgumentList(IArgument[] argumentList) {
+ this.argumentList = argumentList;
+ }
+
+ public void setResultType(IType resultType) {
+ this.resultType = resultType;
+ }
+
+ public void setKeywordList(String[] keywordList) {
+ this.keywordList = keywordList;
+ }
+
+ public void setAffect(char affect) {
+ this.affect = affect;
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+
+ //
+ // Value.
+ //
+ ICode value;
+
+ public void setValue(ICode v) {
+ if (affect == '<') {
+ value = v;
+ } else {
+ // TODO not yet implemented
+ }
+ }
+ public ICode getValue() {
+ return value;
+ }
+
+ //
+ // Access associativity & priority level.
+ //
+ protected int priorityAndLevel;
+
+ public void setAssociativity(String p, int l) {
+ if (p == null || p.equals(ILisaacModel.keyword_left)) {
+ priorityAndLevel = l;
+ } else {
+ priorityAndLevel = -l;
+ }
+ }
+
+ public String getAssociativity() {
+ String result;
+
+ if (priorityAndLevel >= 0) {
+ result = ILisaacModel.keyword_left;
+ } else {
+ result = ILisaacModel.keyword_right;
+ }
+ return result;
+ }
+
+ public int getPriority() {
+ if (priorityAndLevel < 0) {
+ return -priorityAndLevel;
+ }
+ return priorityAndLevel;
+ }
+
+ public void setStyle(char style) {
+ this.style = style;
+ }
+
+ public boolean hasArgument(String word) {
+ return getArgument(word) != null;
+ }
+
+ public IArgument getArgument(String word) {
+ if (argumentList != null) {
+ for (int i=0; i<argumentList.length; i++) {
+ if (argumentList[i] instanceof ITMArgs) {
+ if (((ITMArgs)argumentList[i]).hasArgument(word)) {
+ return argumentList[i];
+ }
+ } else if (argumentList[i].getName().compareTo(word) == 0) {
+ return argumentList[i];
+ }
+ }
+ }
+ return null;
+ }
+
+ public Prototype getPrototype() {
+ return sectionId.getPrototype();
+ }
+
+ public String getSignature(boolean isCall) {
+ if (keywordList == null || keywordList.length < 1) {
+ return name;
+ }
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(keywordList[0]);
+ buffer.append(" ");
+
+ int keywordIndex = 1;
+ for (int argIndex=0; argIndex < argumentList.length; argIndex++) {
+ if (isCall) {
+ buffer.append(argumentList[argIndex].getName());
+ } else {
+ argumentList[argIndex].printIn(buffer);
+ }
+ buffer.append(" ");
+
+ if (keywordIndex < keywordList.length) {
+ buffer.append(keywordList[keywordIndex]);
+ buffer.append(" ");
+ keywordIndex++;
+ }
+ }
+ if (! isCall && resultType.toString() != null) {
+ buffer.append(" : "+resultType);
+ }
+ return buffer.toString();
+ }
+}
+
diff --git a/src/org/eclipse/lisaac/model/lip/LIP.java b/src/org/eclipse/lisaac/model/lip/LIP.java
new file mode 100644
index 0000000..0d15db3
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIP.java
@@ -0,0 +1,77 @@
+package org.eclipse.lisaac.model.lip;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class LIP {
+
+ private String filename;
+
+ /** parent lip files */
+ protected ArrayList<String> listParent = new ArrayList<String>();
+
+ /** lip method list */
+ protected ArrayList<LIPSlotCode> listMethod = new ArrayList<LIPSlotCode>();
+
+ /** lip data */
+ protected HashMap<String,LIPSlotData> listData = new HashMap<String,LIPSlotData>();
+
+
+ public LIP(String filename) {
+ this.filename = filename;
+ }
+
+ public String getFileName() {
+ return filename;
+ }
+
+ public void addParent(String string) {
+ listParent.add(string);
+ }
+ public void addMethod(LIPSlotCode m) {
+ listMethod.add(m);
+ }
+ public void addData(LIPSlotData data) {
+ listData.put(data.getName(),data);
+ }
+
+ public String getParent(int i) {
+ return listParent.get(i);
+ }
+ public int getParentCount() {
+ return listParent.size();
+ }
+
+ public LIPSlotCode getMethod(int i) {
+ return listMethod.get(i);
+ }
+ public int getMethodCount() {
+ return listMethod.size();
+ }
+
+ public LIPSlotCode getPublicMethod(int index) {
+ int count = 0;
+ for (int i=0; i<getMethodCount(); i++) {
+ LIPSlotCode method = getMethod(i);
+ if (method.isPublic()) {
+ if (index == count) {
+ return method;
+ }
+ count++;
+ }
+ }
+ return null;
+ }
+
+ public int getPublicMethodCount() {
+ int count = 0;
+ for (int i=0; i<getMethodCount(); i++) {
+ LIPSlotCode method = getMethod(i);
+ if (method.isPublic()) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPAffect.java b/src/org/eclipse/lisaac/model/lip/LIPAffect.java
new file mode 100644
index 0000000..cca1188
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPAffect.java
@@ -0,0 +1,12 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPAffect extends LIPCode {
+
+ protected String name;
+ protected LIPCode value;
+
+ public LIPAffect(String name, LIPCode value) {
+ this.name = name;
+ this.value = value;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPBinary.java b/src/org/eclipse/lisaac/model/lip/LIPBinary.java
new file mode 100644
index 0000000..85b890d
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPBinary.java
@@ -0,0 +1,13 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPBinary extends LIPCode {
+
+ protected LIPCode left, right;
+ protected char operator;
+
+ public LIPBinary(LIPCode left, char operator, LIPCode right) {
+ this.left = left;
+ this.right = right;
+ this.operator = operator;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPBoolean.java b/src/org/eclipse/lisaac/model/lip/LIPBoolean.java
new file mode 100644
index 0000000..6e1a97b
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPBoolean.java
@@ -0,0 +1,28 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPBoolean extends LIPConstant {
+
+ private static LIPBoolean lipTrue = new LIPBoolean(true);
+ private static LIPBoolean lipFalse = new LIPBoolean(false);
+
+ protected boolean value;
+
+ LIPBoolean(boolean i) {
+ value = i;
+ }
+
+ public static LIPBoolean get(boolean b) {
+ if (b) {
+ return lipTrue;
+ } else {
+ return lipFalse;
+ }
+ }
+
+ public void free() {;
+ }
+
+ public String getName() {
+ return "BOOLEAN";
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPCall.java b/src/org/eclipse/lisaac/model/lip/LIPCall.java
new file mode 100644
index 0000000..e688e20
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPCall.java
@@ -0,0 +1,13 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPCall extends LIPCode {
+
+ protected String name;
+ protected LIPCode argument;
+
+ public LIPCall(String name, LIPCode argument) {
+ this.name = name;
+ this.argument = argument;
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPCode.java b/src/org/eclipse/lisaac/model/lip/LIPCode.java
new file mode 100644
index 0000000..4534f6a
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPCode.java
@@ -0,0 +1,4 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPCode {
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPConstant.java b/src/org/eclipse/lisaac/model/lip/LIPConstant.java
new file mode 100644
index 0000000..3d8ffa7
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPConstant.java
@@ -0,0 +1,8 @@
+package org.eclipse.lisaac.model.lip;
+
+public abstract class LIPConstant {
+
+ public abstract String getName();
+
+ public abstract void free();
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPIf.java b/src/org/eclipse/lisaac/model/lip/LIPIf.java
new file mode 100644
index 0000000..7eda13e
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPIf.java
@@ -0,0 +1,15 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPIf extends LIPCode {
+
+ protected LIPCode condition;
+ protected LIPCode[] thenCode;
+ protected LIPCode[] elseCode;
+
+ public LIPIf(LIPCode condition, LIPCode[] thenCode, LIPCode[] elseCode) {
+ this.condition = condition;
+ this.thenCode = thenCode;
+ this.elseCode = elseCode;
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPInteger.java b/src/org/eclipse/lisaac/model/lip/LIPInteger.java
new file mode 100644
index 0000000..0f0c8b0
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPInteger.java
@@ -0,0 +1,23 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPInteger extends LIPConstant {
+
+ protected int value;
+
+ LIPInteger(int i) {
+ value = i;
+ }
+
+ public static LIPInteger get(int i) {
+ // TODO storage..
+ return new LIPInteger(i);
+ }
+
+ public void free() {
+ // TODO storage.add_last Self;
+ }
+
+ public String getName() {
+ return "INTEGER";
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPPrint.java b/src/org/eclipse/lisaac/model/lip/LIPPrint.java
new file mode 100644
index 0000000..c02337f
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPPrint.java
@@ -0,0 +1,10 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPPrint extends LIPCode {
+
+ protected LIPCode message;
+
+ public LIPPrint(LIPCode message) {
+ this.message = message;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPSlotCode.java b/src/org/eclipse/lisaac/model/lip/LIPSlotCode.java
new file mode 100644
index 0000000..e410060
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPSlotCode.java
@@ -0,0 +1,53 @@
+package org.eclipse.lisaac.model.lip;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+
+public class LIPSlotCode extends LIPCode {
+ protected String section;
+
+ protected String name;
+ protected String comment;
+
+ protected LIPSlotData argument;
+ protected LIPCode[] code;
+
+ public LIPSlotCode(String section, String name, LIPSlotData argument, LIPCode[] code) {
+ this.section = section;
+ this.name = name;
+ this.argument = argument;
+ this.code = code;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+
+ public boolean isPublic() {
+ return section.equals(ILisaacModel.section_public);
+ }
+
+ public String toString() {
+ StringBuffer result = new StringBuffer(" -");
+ result.append(name);
+ if (argument != null) {
+ result.append(" <");
+ result.append(argument);
+ result.append(">");
+ }
+ result.append(" :\n");
+ if (comment != null) {
+ result.append(comment);
+ } else {
+ result.append("\t Sorry, no comment (see `make.lip').\n");
+ }
+ return result.toString();
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPSlotData.java b/src/org/eclipse/lisaac/model/lip/LIPSlotData.java
new file mode 100644
index 0000000..0ca3134
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPSlotData.java
@@ -0,0 +1,29 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPSlotData extends LIPCode {
+
+ protected String name;
+ protected LIPConstant value;
+
+ public LIPSlotData(String name, LIPConstant value) {
+ this.name = name;
+ this.value = value;
+ // TODO check double declaration
+ }
+
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+ result.append(name);
+ result.append(":");
+ result.append(value.getName());
+ return result.toString();
+ }
+
+ public void setValue(LIPConstant value) {
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPString.java b/src/org/eclipse/lisaac/model/lip/LIPString.java
new file mode 100644
index 0000000..ce6b00d
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPString.java
@@ -0,0 +1,23 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPString extends LIPConstant {
+
+ protected String value;
+
+ LIPString(String i) {
+ value = i;
+ }
+
+ public static LIPString get(String i) {
+ // TODO storage..
+ return new LIPString(i);
+ }
+
+ public void free() {
+ // TODO storage.add_last Self;
+ }
+
+ public String getName() {
+ return "STRING";
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPUnary.java b/src/org/eclipse/lisaac/model/lip/LIPUnary.java
new file mode 100644
index 0000000..9dc6af5
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPUnary.java
@@ -0,0 +1,13 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPUnary extends LIPCode {
+
+ protected LIPCode value;
+ protected char operator;
+
+ public LIPUnary(char operator, LIPCode value) {
+ this.value = value;
+ this.operator = operator;
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/lip/LIPValue.java b/src/org/eclipse/lisaac/model/lip/LIPValue.java
new file mode 100644
index 0000000..aa8b0be
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/lip/LIPValue.java
@@ -0,0 +1,10 @@
+package org.eclipse.lisaac.model.lip;
+
+public class LIPValue extends LIPCode {
+
+ protected LIPConstant value;
+
+ public LIPValue(LIPConstant value) {
+ this.value = value;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/types/IType.java b/src/org/eclipse/lisaac/model/types/IType.java
new file mode 100644
index 0000000..be7588a
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/types/IType.java
@@ -0,0 +1,5 @@
+package org.eclipse.lisaac.model.types;
+
+public interface IType {
+ public String toString();
+}
diff --git a/src/org/eclipse/lisaac/model/types/ITypeMono.java b/src/org/eclipse/lisaac/model/types/ITypeMono.java
new file mode 100644
index 0000000..688db83
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/types/ITypeMono.java
@@ -0,0 +1,5 @@
+package org.eclipse.lisaac.model.types;
+
+public interface ITypeMono extends IType {
+
+}
diff --git a/src/org/eclipse/lisaac/model/types/TypeBlock.java b/src/org/eclipse/lisaac/model/types/TypeBlock.java
new file mode 100644
index 0000000..7e1b839
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/types/TypeBlock.java
@@ -0,0 +1,53 @@
+package org.eclipse.lisaac.model.types;
+
+import java.util.*;
+
+/**
+ * Type block definition
+ */
+public class TypeBlock implements ITypeMono {
+
+ private static List<TypeBlock> dico;
+
+ protected IType typeArgument;
+ protected IType typeResult;
+
+ TypeBlock(IType typeArgument, IType typeResult) {
+ this.typeArgument = typeArgument;
+ this.typeResult = typeResult;
+ }
+
+ public static TypeBlock get(IType typ_arg, IType typ_res) {
+
+ return new TypeBlock(typ_arg, typ_res);
+
+ /*TypeBlock result=null;
+
+ if (dico == null) {
+ dico = new ArrayList<TypeBlock>();
+ }
+ int idx = 0;
+ while (idx < dico.size() &&
+ (!dico.get(idx).getTypeArg().equals(typ_arg) || !dico.get(idx).getTypeRes().equals(typ_res))) {
+ idx++;
+ }
+ if (idx <= dico.size()-1) {
+ result = dico.get(idx);
+ } else {
+ result = new TypeBlock(typ_arg, typ_res);
+ dico.add(result);
+ }
+ return result;*/
+ }
+
+ public IType getTypeArg() {
+ return typeArgument;
+ }
+ public IType getTypeRes() {
+ return typeResult;
+ }
+
+ public String toString() {
+ return "{}"; // TODO block print
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/types/TypeGeneric.java b/src/org/eclipse/lisaac/model/types/TypeGeneric.java
new file mode 100644
index 0000000..9151da9
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/types/TypeGeneric.java
@@ -0,0 +1,11 @@
+package org.eclipse.lisaac.model.types;
+
+public class TypeGeneric extends TypeStyle {
+
+ protected ITypeMono[] listType;
+
+ public TypeGeneric(String name, String style, ITypeMono[] lt) {
+ super(name, style);
+ listType = lt;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/types/TypeMulti.java b/src/org/eclipse/lisaac/model/types/TypeMulti.java
new file mode 100644
index 0000000..e38d841
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/types/TypeMulti.java
@@ -0,0 +1,48 @@
+package org.eclipse.lisaac.model.types;
+
+import java.util.*;
+
+/**
+ * List of type
+ */
+public class TypeMulti implements IType {
+
+ private static List<TypeMulti> dico;
+
+ protected ITypeMono[] listType;
+
+ public TypeMulti(ITypeMono[] lst) {
+ listType = lst;
+ }
+
+ public ITypeMono[] getTypeList() {
+ return listType;
+ }
+
+ public IType getSubType(int index) {
+ return listType[index];
+ }
+
+ public static IType get(ITypeMono[] lst) {
+ TypeMulti result=null;
+
+ if (dico == null) {
+ dico = new ArrayList<TypeMulti>();
+ }
+ int idx = 0;
+ while (idx < dico.size() && !dico.get(idx).getTypeList().equals(lst)) {
+ idx++;
+ }
+ if (idx <= dico.size()-1) {
+ result = dico.get(idx);
+ } else {
+ result = new TypeMulti(lst);
+ dico.add(result);
+ }
+ return result;
+ }
+
+ public String toString() {
+ return "(...)"; // TODO multi type print
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/types/TypeParameter.java b/src/org/eclipse/lisaac/model/types/TypeParameter.java
new file mode 100644
index 0000000..2df4747
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/types/TypeParameter.java
@@ -0,0 +1,12 @@
+package org.eclipse.lisaac.model.types;
+
+/**
+ * Parameter type for argument define.
+ */
+public class TypeParameter extends TypeSimple {
+
+ public TypeParameter(String name) {
+ super(name);
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/model/types/TypeSimple.java b/src/org/eclipse/lisaac/model/types/TypeSimple.java
new file mode 100644
index 0000000..55987a9
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/types/TypeSimple.java
@@ -0,0 +1,65 @@
+package org.eclipse.lisaac.model.types;
+
+import java.util.HashMap;
+
+import org.eclipse.lisaac.model.ILisaacModel;
+
+public class TypeSimple implements ITypeMono {
+
+ private static HashMap<String,TypeSimple> dico;
+
+ protected String name;
+
+ TypeSimple(String name) {
+ this.name = name;
+
+ if (dico == null) {
+ dico = new HashMap<String,TypeSimple>();
+ }
+ dico.put(name, this);
+ }
+ public String getName() {
+ return name;
+ }
+
+ protected static TypeSimple typeNull;
+ protected static TypeSimple typeVoid;
+ protected static TypeSimple typeSelf;
+
+
+ public static void init() {
+ typeNull = new TypeSimple(ILisaacModel.variable_null);
+ typeVoid = new TypeSimple(ILisaacModel.variable_void);
+ typeSelf = new TypeParameter(ILisaacModel.prototype_self);
+ }
+
+ public static TypeSimple get(String n) {
+ TypeSimple result=null;
+
+ if (dico == null) {
+ dico = new HashMap<String,TypeSimple>();
+ }
+ result = dico.get(n);
+ if (result == null) {
+ result = new TypeSimple(n);
+ }
+ return result;
+ }
+
+ public static ITypeMono getTypeSelf() {
+ return typeSelf;
+ }
+ public static ITypeMono getTypeVoid() {
+ return typeVoid;
+ }
+ public static ITypeMono getTypeNull() {
+ return typeNull;
+ }
+
+ public String toString() {
+ if (this.equals(typeVoid)) {
+ return null; // do not print void type
+ }
+ return name;
+ }
+}
diff --git a/src/org/eclipse/lisaac/model/types/TypeStyle.java b/src/org/eclipse/lisaac/model/types/TypeStyle.java
new file mode 100644
index 0000000..2a8ba9c
--- /dev/null
+++ b/src/org/eclipse/lisaac/model/types/TypeStyle.java
@@ -0,0 +1,43 @@
+package org.eclipse.lisaac.model.types;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type with style
+ */
+public class TypeStyle extends TypeSimple {
+
+ private static List<TypeStyle> dico;
+
+ protected String style;
+
+ TypeStyle(String name, String style) {
+ super(name);
+ this.style = style;
+ }
+
+ public String getStyle() {
+ return style;
+ }
+
+ public static TypeStyle get(String n, String s) {
+ TypeStyle result=null;
+
+ if (dico == null) {
+ dico = new ArrayList<TypeStyle>();
+ }
+ int idx = 0;
+ while (idx < dico.size() &&
+ (!dico.get(idx).getName().equals(n) || !dico.get(idx).getStyle().equals(s))) {
+ idx++;
+ }
+ if (idx <= dico.size()-1) {
+ result = dico.get(idx);
+ } else {
+ result = new TypeStyle(n, s);
+ dico.add(result);
+ }
+ return result;
+ }
+}
diff --git a/src/org/eclipse/lisaac/outline/OutlineContentProvider.java b/src/org/eclipse/lisaac/outline/OutlineContentProvider.java
new file mode 100644
index 0000000..a3c939e
--- /dev/null
+++ b/src/org/eclipse/lisaac/outline/OutlineContentProvider.java
@@ -0,0 +1,53 @@
+package org.eclipse.lisaac.outline;
+
+import java.util.List;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+public class OutlineContentProvider implements ITreeContentProvider {
+
+ /**
+ * @see ITreeContentProvider#getChildren(Object)
+ */
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof OutlineItem) {
+ OutlineItem outlineElement = (OutlineItem) parentElement;
+ List<OutlineItem> children = outlineElement.getChildren();
+ if (children != null) {
+ return children.toArray(new Object[children.size()]);
+ }
+ } else if (parentElement instanceof Object[]) {
+ return ((Object[]) parentElement);
+ }
+ return new Object[0];
+ }
+
+
+ /**
+ * @see ITreeContentProvider#getParent(Object)
+ */
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ /**
+ * @see ITreeContentProvider#hasChildren(Object)
+ */
+ public boolean hasChildren(Object element) {
+ return (getChildren(element).length > 0);
+ }
+
+ /**
+ * @see IStructuredContentProvider#getElements(Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+}
diff --git a/src/org/eclipse/lisaac/outline/OutlineImages.java b/src/org/eclipse/lisaac/outline/OutlineImages.java
new file mode 100644
index 0000000..96708c6
--- /dev/null
+++ b/src/org/eclipse/lisaac/outline/OutlineImages.java
@@ -0,0 +1,21 @@
+package org.eclipse.lisaac.outline;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.swt.graphics.Image;
+
+public class OutlineImages {
+ public static final Image PROTOTYPE = getImage("/icons/prototype.gif");
+
+ public static final Image PUBLIC_SHARED = getImage("/icons/public-shared.gif");
+ public static final Image PRIVATE_SHARED = getImage("/icons/private-shared.gif");
+ public static final Image PUBLIC_NONSHARED = getImage("/icons/public-nonshared.gif");
+ public static final Image PRIVATE_NONSHARED = getImage("/icons/private-nonshared.gif");
+
+ public static final Image BLANK = getImage("/icons/blank.gif");
+
+ private static Image getImage(String path) {
+ ImageDescriptor descr = LisaacPlugin.getImageDescriptor(path);
+ return descr.createImage();
+ }
+}
diff --git a/src/org/eclipse/lisaac/outline/OutlineItem.java b/src/org/eclipse/lisaac/outline/OutlineItem.java
new file mode 100644
index 0000000..ffbab67
--- /dev/null
+++ b/src/org/eclipse/lisaac/outline/OutlineItem.java
@@ -0,0 +1,37 @@
+package org.eclipse.lisaac.outline;
+
+import java.util.List;
+import org.eclipse.swt.graphics.Image;
+
+public abstract class OutlineItem {
+
+ protected int fstartOffset;
+ protected int fLength;
+
+ /**
+ * Returns the image which corresponds to the element, null otherwise.
+ * @see ILabelProvider#getImage(Object)
+ */
+ public abstract Image getImage();
+
+
+ /**
+ * Returns the label which corresponds to the element, null otherwise.
+ * @see ILabelProvider#getText(Object)
+ */
+ public abstract String getText();
+
+ /**
+ * Returns the children of this element.
+ */
+ public abstract List<OutlineItem> getChildren();
+
+
+ public int startOffset() {
+ return fstartOffset;
+ }
+
+ public int length() {
+ return fLength;
+ }
+}
diff --git a/src/org/eclipse/lisaac/outline/OutlineLabelProvider.java b/src/org/eclipse/lisaac/outline/OutlineLabelProvider.java
new file mode 100644
index 0000000..e34945c
--- /dev/null
+++ b/src/org/eclipse/lisaac/outline/OutlineLabelProvider.java
@@ -0,0 +1,41 @@
+package org.eclipse.lisaac.outline;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+public class OutlineLabelProvider extends LabelProvider {
+
+ /**
+ * @see WorkbenchLabelProvider#getImage(Object)
+ * @param element the element for which an image is created
+ * @return the image associated to the element
+ */
+ public Image getImage(Object element) {
+ if (element instanceof OutlineItem) {
+ OutlineItem item = (OutlineItem) element;
+ Image image = item.getImage();
+
+ if (image != null) {
+ return image;
+ }
+ }
+ return OutlineImages.BLANK;
+ }
+
+ /**
+ * @see WorkbenchLabelProvider#getText(Object)
+ * @param element the element for which a label is created
+ * @return the label associated to the element
+ */
+ public String getText(Object element) {
+ if (element instanceof OutlineItem) {
+ OutlineItem item = (OutlineItem) element;
+ return item.getText();
+ }
+ if (element != null) {
+ return element.toString();
+ } else {
+ return new String();
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/outline/OutlinePrototype.java b/src/org/eclipse/lisaac/outline/OutlinePrototype.java
new file mode 100644
index 0000000..e50a8a4
--- /dev/null
+++ b/src/org/eclipse/lisaac/outline/OutlinePrototype.java
@@ -0,0 +1,42 @@
+package org.eclipse.lisaac.outline;
+
+import java.util.List;
+
+import org.eclipse.lisaac.model.items.Prototype;
+import org.eclipse.swt.graphics.Image;
+
+public class OutlinePrototype extends OutlineItem {
+ protected String name;
+
+ protected List<OutlineItem> slots;
+
+
+ public OutlinePrototype(Prototype prototype, List<OutlineItem> slots) {
+ name = prototype.getName();
+ this.slots = slots;
+ }
+
+ /**
+ * Returns the label which corresponds to the element, null otherwise.
+ * @see ILabelProvider#getText(Object)
+ */
+ public String getText() {
+ return name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * Returns the image which corresponds to the element, null otherwise.
+ * @see ILabelProvider#getImage(Object)
+ */
+ public Image getImage() {
+ return OutlineImages.PROTOTYPE;
+ }
+
+ public List<OutlineItem> getChildren() {
+ return slots;
+ }
+}
diff --git a/src/org/eclipse/lisaac/outline/OutlineSlot.java b/src/org/eclipse/lisaac/outline/OutlineSlot.java
new file mode 100644
index 0000000..8a8ea4a
--- /dev/null
+++ b/src/org/eclipse/lisaac/outline/OutlineSlot.java
@@ -0,0 +1,71 @@
+package org.eclipse.lisaac.outline;
+
+import java.util.List;
+
+import org.eclipse.lisaac.model.Position;
+import org.eclipse.lisaac.model.items.Slot;
+import org.eclipse.lisaac.model.types.IType;
+import org.eclipse.swt.graphics.Image;
+
+public class OutlineSlot extends OutlineItem {
+
+ protected Slot slot;
+
+ public OutlineSlot(Slot slot) {
+ this.slot = slot;
+
+ Position position = slot.getPosition();
+
+ fstartOffset = position.getStartOffset();
+ fLength = position.length();
+ }
+
+ /**
+ * Returns the label which corresponds to the element, null otherwise.
+ * @see ILabelProvider#getText(Object)
+ */
+ public String getText() {
+ String result=null;
+ if (slot != null) {
+ result = slot.getName();
+ IType t = slot.getResultType();
+ if (t != null && t.toString() != null) {
+ result += " : " + t;// TODO resut type in italics
+ }
+ }
+ return result;
+ }
+
+ public String toString() {
+ return getText();
+ }
+
+ /**
+ * Returns the image which corresponds to the element, null otherwise.
+ * @see ILabelProvider#getImage(Object)
+ */
+ public Image getImage() {
+ if (slot != null) {
+ if (slot.getStyle() == '+') {
+ if (slot.getSectionId() != null &&
+ slot.getSectionId().isPrivateStyle()) {
+ return OutlineImages.PRIVATE_NONSHARED;
+ } else {
+ return OutlineImages.PUBLIC_NONSHARED;
+ }
+ } else {
+ if (slot.getSectionId() != null &&
+ slot.getSectionId().isPrivateStyle()) {
+ return OutlineImages.PRIVATE_SHARED;
+ } else {
+ return OutlineImages.PUBLIC_SHARED;
+ }
+ }
+ }
+ return null;
+ }
+
+ public List<OutlineItem> getChildren() {
+ return null;
+ }
+}
diff --git a/src/org/eclipse/lisaac/perspectives/LisaacPerspective.java b/src/org/eclipse/lisaac/perspectives/LisaacPerspective.java
new file mode 100644
index 0000000..b670060
--- /dev/null
+++ b/src/org/eclipse/lisaac/perspectives/LisaacPerspective.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lisaac.perspectives;
+
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+import org.eclipse.ui.console.IConsoleConstants;
+
+/**
+ * This class is meant to serve as an example for how various contributions
+ * are made to a perspective. Note that some of the extension point id's are
+ * referred to as API constants while others are hardcoded and may be subject
+ * to change.
+ */
+public class LisaacPerspective implements IPerspectiveFactory {
+
+ private IPageLayout factory;
+
+ public LisaacPerspective() {
+ super();
+ }
+
+ public void createInitialLayout(IPageLayout factory) {
+ this.factory = factory;
+ addViews();
+ addActionSets();
+ addNewWizardShortcuts();
+ addPerspectiveShortcuts();
+ addViewShortcuts();
+ }
+
+ private void addViews() {
+ // Creates the overall folder layout.
+ // Note that each new Folder uses a percentage of the remaining EditorArea.
+
+ IFolderLayout bottom =
+ factory.createFolder(
+ "bottomRight", //NON-NLS-1
+ IPageLayout.BOTTOM,
+ 0.75f,
+ factory.getEditorArea());
+ bottom.addView(IPageLayout.ID_PROBLEM_VIEW);
+ bottom.addView("org.eclipse.team.ui.GenericHistoryView"); //NON-NLS-1
+ bottom.addPlaceholder(IConsoleConstants.ID_CONSOLE_VIEW);
+
+ IFolderLayout topLeft =
+ factory.createFolder(
+ "topLeft", //NON-NLS-1
+ IPageLayout.LEFT,
+ 0.25f,
+ factory.getEditorArea());
+ topLeft.addView(IPageLayout.ID_RES_NAV);
+ topLeft.addView(IPageLayout.ID_OUTLINE);
+
+ factory.addFastView("org.eclipse.team.sync.views.SynchronizeView", 0.50f); //NON-NLS-1
+ }
+
+ private void addActionSets() {
+ factory.addActionSet("org.eclipse.debug.ui.launchActionSet"); //NON-NLS-1
+ factory.addActionSet("org.eclipse.debug.ui.debugActionSet"); //NON-NLS-1
+ //factory.addActionSet("org.eclipse.debug.ui.profileActionSet"); //NON-NLS-1
+ factory.addActionSet("org.eclipse.jdt.debug.ui.JDTDebugActionSet"); //NON-NLS-1
+ factory.addActionSet("org.eclipse.team.ui.actionSet"); //NON-NLS-1
+ //factory.addActionSet("org.eclipse.ant.ui.actionSet.presentation"); //NON-NLS-1
+ factory.addActionSet(IPageLayout.ID_NAVIGATE_ACTION_SET); //NON-NLS-1
+ }
+
+ private void addPerspectiveShortcuts() {
+ factory.addPerspectiveShortcut("org.eclipse.team.ui.TeamSynchronizingPerspective"); //NON-NLS-1
+ factory.addPerspectiveShortcut("org.eclipse.ui.resourcePerspective"); //NON-NLS-1
+ }
+
+ private void addNewWizardShortcuts() {
+ factory.addNewWizardShortcut("org.eclipse.ui.wizards.new.folder");//NON-NLS-1
+ factory.addNewWizardShortcut("org.eclipse.ui.wizards.new.file");//NON-NLS-1
+ }
+
+ private void addViewShortcuts() {
+ factory.addShowViewShortcut("org.eclipse.pde.ui.DependenciesView"); //NON-NLS-1
+ factory.addShowViewShortcut("org.eclipse.team.ui.GenericHistoryView"); //NON-NLS-1
+ factory.addShowViewShortcut(IConsoleConstants.ID_CONSOLE_VIEW);
+ factory.addShowViewShortcut(IPageLayout.ID_RES_NAV);
+ factory.addShowViewShortcut(IPageLayout.ID_PROBLEM_VIEW);
+ factory.addShowViewShortcut(IPageLayout.ID_OUTLINE);
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/preferences/LisaacPreferencePage.java b/src/org/eclipse/lisaac/preferences/LisaacPreferencePage.java
new file mode 100644
index 0000000..b017432
--- /dev/null
+++ b/src/org/eclipse/lisaac/preferences/LisaacPreferencePage.java
@@ -0,0 +1,65 @@
+package org.eclipse.lisaac.preferences;
+
+import org.eclipse.jface.preference.*;
+import org.eclipse.lisaac.LisaacPlugin;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * This class represents a preference page that
+ * is contributed to the Preferences dialog. By
+ * subclassing <samp>FieldEditorPreferencePage</samp>, we
+ * can use the field support built into JFace that allows
+ * us to create a page that is small and knows how to
+ * save, restore and apply itself.
+ * <p>
+ * This page is used to modify preferences only. They
+ * are stored in the preference store that belongs to
+ * the main plug-in class. That way, preferences can
+ * be accessed directly via the preference store.
+ */
+
+public class LisaacPreferencePage
+ extends FieldEditorPreferencePage
+ implements IWorkbenchPreferencePage {
+
+ public LisaacPreferencePage() {
+ super(GRID);
+ setPreferenceStore(LisaacPlugin.getDefault().getPreferenceStore());
+ setDescription("General settings for Lisaac Development");
+ }
+
+ /**
+ * Creates the field editors. Field editors are abstractions of
+ * the common GUI blocks needed to manipulate various types
+ * of preferences. Each field editor knows how to save and
+ * restore itself.
+ */
+ public void createFieldEditors() {
+ //addField(new DirectoryFieldEditor(PreferenceConstants.P_LISAAC_PATH,
+ // "&Lisaac Environment Directory:", getFieldEditorParent()));
+ /*addField(
+ new BooleanFieldEditor(
+ PreferenceConstants.P_BOOLEAN,
+ "&An example of a boolean preference",
+ getFieldEditorParent()));
+
+ addField(new RadioGroupFieldEditor(
+ PreferenceConstants.P_CHOICE,
+ "An example of a multiple-choice preference",
+ 1,
+ new String[][] { { "&Choice 1", "choice1" }, {
+ "C&hoice 2", "choice2" }
+ }, getFieldEditorParent()));
+ addField(
+ new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent()));
+ */
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/preferences/PreferenceConstants.java b/src/org/eclipse/lisaac/preferences/PreferenceConstants.java
new file mode 100644
index 0000000..46013e6
--- /dev/null
+++ b/src/org/eclipse/lisaac/preferences/PreferenceConstants.java
@@ -0,0 +1,10 @@
+package org.eclipse.lisaac.preferences;
+
+/**
+ * Constant definitions for plug-in preferences
+ */
+public class PreferenceConstants {
+
+ public static final String P_LISAAC_PATH = "";
+
+}
diff --git a/src/org/eclipse/lisaac/preferences/PreferenceInitializer.java b/src/org/eclipse/lisaac/preferences/PreferenceInitializer.java
new file mode 100644
index 0000000..da3e063
--- /dev/null
+++ b/src/org/eclipse/lisaac/preferences/PreferenceInitializer.java
@@ -0,0 +1,23 @@
+package org.eclipse.lisaac.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.lisaac.LisaacPlugin;
+
+
+/**
+ * Class used to initialize default preference values.
+ */
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+ */
+ public void initializeDefaultPreferences() {
+ //IPreferenceStore store = LisaacPlugin.getDefault().getPreferenceStore();
+ //store.setDefault(PreferenceConstants.P_LISAAC_PATH, "TODO");
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/properties/LisaacProjectPropertyPage.java b/src/org/eclipse/lisaac/properties/LisaacProjectPropertyPage.java
new file mode 100644
index 0000000..d029685
--- /dev/null
+++ b/src/org/eclipse/lisaac/properties/LisaacProjectPropertyPage.java
@@ -0,0 +1,212 @@
+package org.eclipse.lisaac.properties;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+public class LisaacProjectPropertyPage extends PropertyPage {
+
+ public static final String LISAAC_PATH = "Lisaac Environment Path";
+
+ private Text pathValueText;
+
+ private Button browseButton;
+
+ /**
+ * Constructor for SamplePropertyPage.
+ */
+ public LisaacProjectPropertyPage() {
+ super();
+ }
+
+ private void addFirstSection(Composite parent) {
+ Composite composite = createDefaultComposite(parent);
+
+ Group group = new Group(composite, SWT.SHADOW_IN);
+ group.setText(LISAAC_PATH);
+ group.setLayout(new GridLayout());
+
+ final Button b1 = new Button(group, SWT.RADIO);
+ b1.setFont(parent.getFont());
+ b1.setText("Use default Lisaac Environment");
+
+ final Button b2 = new Button(group, SWT.RADIO);
+ b2.setFont(parent.getFont());
+ b2.setText("Use a project specific Lisaac Environment : ");
+
+ Composite envGroup = new Composite(group, SWT.NONE);
+ envGroup.setLayout(new RowLayout());
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ gridData.grabExcessHorizontalSpace = true;
+ envGroup.setLayoutData(gridData);
+
+ // Path text field
+ pathValueText = new Text(envGroup, SWT.BORDER/*SWT.WRAP | SWT.READ_ONLY*/);
+ pathValueText.setText(getDefaultLisaacPath((IProject)getElement()));
+ RowData rowData = new RowData();
+ rowData.width = 200;
+ pathValueText.setLayoutData(rowData);
+
+ //pathValueText.setText(((IResource) getElement()).getFullPath().toString());
+ pathValueText.setEnabled(false);
+
+ b2.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (b2.getSelection()) {
+ pathValueText.setEnabled(true);
+ browseButton.setEnabled(true);
+ } else {
+ pathValueText.setEnabled(false);
+ browseButton.setEnabled(false);
+ }
+ }
+ });
+ browseButton = new Button(envGroup, SWT.PUSH);
+ browseButton.setText("Browse");
+ browseButton.setEnabled(false);
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+ }
+
+ private void addSeparator(Composite parent) {
+ Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
+ GridData gridData = new GridData();
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.grabExcessHorizontalSpace = true;
+ separator.setLayoutData(gridData);
+ }
+
+ private void addSecondSection(Composite parent) {
+/*
+ Composite composite = createDefaultComposite(parent);
+ // Label for owner field
+ Label ownerLabel = new Label(composite, SWT.NONE);
+ ownerLabel.setText(OWNER_TITLE);
+
+ // Owner text field
+ ownerText = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ GridData gd = new GridData();
+ gd.widthHint = convertWidthInCharsToPixels(TEXT_FIELD_WIDTH);
+ ownerText.setLayoutData(gd);
+
+ // Populate owner text field
+ try {
+ String owner =
+ ((IResource) getElement()).getPersistentProperty(
+ new QualifiedName("", OWNER_PROPERTY));
+ ownerText.setText((owner != null) ? owner : DEFAULT_OWNER);
+ } catch (CoreException e) {
+ ownerText.setText(DEFAULT_OWNER);
+ }*/
+ }
+
+ /**
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ composite.setLayout(layout);
+ GridData data = new GridData(GridData.FILL);
+ data.grabExcessHorizontalSpace = true;
+ composite.setLayoutData(data);
+
+ addFirstSection(composite);
+ addSeparator(composite);
+ addSecondSection(composite);
+ return composite;
+ }
+
+ private Composite createDefaultComposite(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ composite.setLayout(layout);
+
+ GridData data = new GridData();
+ data.verticalAlignment = GridData.FILL;
+ data.horizontalAlignment = GridData.FILL;
+ composite.setLayoutData(data);
+
+ return composite;
+ }
+
+ public static String getDefaultLisaacPath(IProject project) {
+ try {
+ return project.getPersistentProperty(
+ new QualifiedName("", LISAAC_PATH));
+ } catch (CoreException e) {
+ return getDefaultLisaacPath();
+ }
+ }
+
+ public static String getDefaultLisaacPath() {
+
+ String env = System.getenv("LISAAC");
+ if (env != null) {
+ return env;
+ }
+ return ""; // TODO error compiler not installed
+ }
+
+ protected void performDefaults() {
+ // Populate the lisaac path field with the default value
+ pathValueText.setText(getDefaultLisaacPath((IProject)getElement()));
+ }
+
+ public boolean performOk() {
+ // store the value in the lisaac project field
+ try {
+ ((IResource) getElement()).setPersistentProperty(
+ new QualifiedName("", LISAAC_PATH),
+ pathValueText.getText());
+ } catch (CoreException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Uses the standard container selection dialog to choose the new value for
+ * the container field.
+ */
+
+ private void handleBrowse() { // FIXME browse outside workspace
+ ContainerSelectionDialog dialog = new ContainerSelectionDialog(
+ getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
+ "Select Lisaac Environment Directory.");
+ if (dialog.open() == ContainerSelectionDialog.OK) {
+ Object[] results = dialog.getResult();
+ if (results.length == 1) {
+ Object result = results[0];
+ if (result instanceof IPath) {
+ IPath ipath = (IPath) result;
+ pathValueText.setText(ipath.toString());
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/properties/LisaacPropertyPage.java b/src/org/eclipse/lisaac/properties/LisaacPropertyPage.java
new file mode 100644
index 0000000..ab522d2
--- /dev/null
+++ b/src/org/eclipse/lisaac/properties/LisaacPropertyPage.java
@@ -0,0 +1,125 @@
+package org.eclipse.lisaac.properties;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+public class LisaacPropertyPage extends PropertyPage {
+
+ private static final String PATH_TITLE = "Path:";
+ private static final String OWNER_TITLE = "&Owner:";
+ private static final String OWNER_PROPERTY = "OWNER";
+ private static final String DEFAULT_OWNER = "John Doe";
+
+ private static final int TEXT_FIELD_WIDTH = 50;
+
+ private Text ownerText;
+
+ /**
+ * Constructor for SamplePropertyPage.
+ */
+ public LisaacPropertyPage() {
+ super();
+ }
+
+ private void addFirstSection(Composite parent) {
+ Composite composite = createDefaultComposite(parent);
+
+ //Label for path field
+ Label pathLabel = new Label(composite, SWT.NONE);
+ pathLabel.setText(PATH_TITLE);
+
+ // Path text field
+ Text pathValueText = new Text(composite, SWT.WRAP | SWT.READ_ONLY);
+ pathValueText.setText(((IResource) getElement()).getFullPath().toString());
+ }
+
+ private void addSeparator(Composite parent) {
+ Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
+ GridData gridData = new GridData();
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.grabExcessHorizontalSpace = true;
+ separator.setLayoutData(gridData);
+ }
+
+ private void addSecondSection(Composite parent) {
+ Composite composite = createDefaultComposite(parent);
+
+ // Label for owner field
+ Label ownerLabel = new Label(composite, SWT.NONE);
+ ownerLabel.setText(OWNER_TITLE);
+
+ // Owner text field
+ ownerText = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ GridData gd = new GridData();
+ gd.widthHint = convertWidthInCharsToPixels(TEXT_FIELD_WIDTH);
+ ownerText.setLayoutData(gd);
+
+ // Populate owner text field
+ try {
+ String owner =
+ ((IResource) getElement()).getPersistentProperty(
+ new QualifiedName("", OWNER_PROPERTY));
+ ownerText.setText((owner != null) ? owner : DEFAULT_OWNER);
+ } catch (CoreException e) {
+ ownerText.setText(DEFAULT_OWNER);
+ }
+ }
+
+ /**
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ composite.setLayout(layout);
+ GridData data = new GridData(GridData.FILL);
+ data.grabExcessHorizontalSpace = true;
+ composite.setLayoutData(data);
+
+ addFirstSection(composite);
+ addSeparator(composite);
+ addSecondSection(composite);
+ return composite;
+ }
+
+ private Composite createDefaultComposite(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ composite.setLayout(layout);
+
+ GridData data = new GridData();
+ data.verticalAlignment = GridData.FILL;
+ data.horizontalAlignment = GridData.FILL;
+ composite.setLayoutData(data);
+
+ return composite;
+ }
+
+ protected void performDefaults() {
+ // Populate the owner text field with the default value
+ ownerText.setText(DEFAULT_OWNER);
+ }
+
+ public boolean performOk() {
+ // store the value in the owner text field
+ try {
+ ((IResource) getElement()).setPersistentProperty(
+ new QualifiedName("", OWNER_PROPERTY),
+ ownerText.getText());
+ } catch (CoreException e) {
+ return false;
+ }
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/eclipse/lisaac/views/ConsoleFactory.java b/src/org/eclipse/lisaac/views/ConsoleFactory.java
new file mode 100644
index 0000000..d710e10
--- /dev/null
+++ b/src/org/eclipse/lisaac/views/ConsoleFactory.java
@@ -0,0 +1,54 @@
+package org.eclipse.lisaac.views;
+
+import java.util.Arrays;
+
+import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.IConsoleFactory;
+import org.eclipse.ui.console.IConsoleListener;
+import org.eclipse.ui.console.IConsoleManager;
+
+public class ConsoleFactory implements IConsoleFactory{
+
+ /** The console created by this factory if any. */
+ private static LisaacConsole openConsole = null;
+
+ public ConsoleFactory() {
+
+ ConsolePlugin.getDefault().getConsoleManager().addConsoleListener(new IConsoleListener() {
+ public void consolesAdded(IConsole[] consoles) {
+ }
+ public void consolesRemoved(IConsole[] consoles) {
+ if (Arrays.asList(consoles).contains(openConsole)) {
+ openConsole = null;
+ }
+ }
+ });
+ }
+
+ /**
+ * Opens a new console.
+ */
+ public void openConsole() {
+ createConsole();
+ }
+
+ public static void createConsole() {
+ IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
+
+ if (openConsole == null) {
+ openConsole = new LisaacConsole();
+ openConsole.initializeDocument();
+
+ consoleManager.addConsoles(new IConsole[] {openConsole});
+ }
+ consoleManager.showConsoleView(openConsole);
+ }
+
+ public static LisaacConsole getConsole() {
+ if (openConsole == null) {
+ createConsole();
+ }
+ return openConsole;
+ }
+}
diff --git a/src/org/eclipse/lisaac/views/LisaacConsole.java b/src/org/eclipse/lisaac/views/LisaacConsole.java
new file mode 100644
index 0000000..b8f6abf
--- /dev/null
+++ b/src/org/eclipse/lisaac/views/LisaacConsole.java
@@ -0,0 +1,26 @@
+package org.eclipse.lisaac.views;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.ui.console.IOConsole;
+
+public class LisaacConsole extends IOConsole {
+
+ public final static String CONSOLE_TYPE = "lisaacConsole"; //$NON-NLS-1$
+ public static final String CONSOLE_FONT= "org.eclipse.debug.ui.consoleFont";
+
+ public LisaacConsole() {
+ super("Lisaac Console", CONSOLE_TYPE, null, true);
+
+ Font font = JFaceResources.getFont(CONSOLE_FONT);
+ setFont(font);
+ }
+
+ /**
+ * Set the document's initial contents.
+ * Called by ConsoleFactory.
+ */
+ void initializeDocument() {
+ getDocument().set("");
+ }
+}
diff --git a/src/org/eclipse/lisaac/views/LisaacOutlineView.java b/src/org/eclipse/lisaac/views/LisaacOutlineView.java
new file mode 100644
index 0000000..1965f53
--- /dev/null
+++ b/src/org/eclipse/lisaac/views/LisaacOutlineView.java
@@ -0,0 +1,191 @@
+package org.eclipse.lisaac.views;
+
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.lisaac.editors.LisaacEditor;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.lisaac.model.items.Prototype;
+import org.eclipse.lisaac.outline.OutlineContentProvider;
+import org.eclipse.lisaac.outline.OutlineItem;
+import org.eclipse.lisaac.outline.OutlineLabelProvider;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+public class LisaacOutlineView extends ContentOutlinePage implements IDocumentListener {
+
+ /** the delay before the outline view is updated. */
+ private static final long UPDATE_DELAY = 1000;
+
+ /** the document provider. */
+ private IDocumentProvider documentProvider;
+
+ /** the text editor. */
+ private AbstractDecoratedTextEditor textEditor;
+
+ /** the current document. */
+ private IDocument document;
+
+ /** the update timer which manages update task scheduling. */
+ private Timer updateTimer;
+
+
+ public LisaacOutlineView(IDocumentProvider documentProvider, AbstractDecoratedTextEditor textEditor) {
+ super();
+ this.documentProvider = documentProvider;
+ this.textEditor = textEditor;
+ createTimer();
+ }
+
+ /**
+ * @see ContentOutlinePage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+
+ TreeViewer viewer = getTreeViewer();
+ viewer.setContentProvider(new OutlineContentProvider());
+ viewer.setLabelProvider(new OutlineLabelProvider());
+ viewer.addSelectionChangedListener(this);
+
+ document = getDocument();
+ if (document != null) {
+ document.addDocumentListener(this);
+ }
+ update();
+ }
+
+ /**
+ * Returns the document attached to this view.
+ * @return the document attached to this view
+ */
+ public IDocument getDocument() {
+ if (document == null) {
+ document = documentProvider.getDocument(textEditor.getEditorInput());
+ }
+ return document;
+ }
+
+ /**
+ * Fired when Outline selection changed
+ * @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent)
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection abstractSelection = event.getSelection();
+ IDocument document = getDocument();
+
+ if (document != null) {
+ if ((abstractSelection != null) && (abstractSelection instanceof TreeSelection)) {
+ TreeSelection selection = (TreeSelection) abstractSelection;
+ Object selectedElement = selection.getFirstElement();
+
+ if ((selectedElement != null) && (selectedElement instanceof OutlineItem)) {
+ OutlineItem item = (OutlineItem) selectedElement;
+ // select current outline item in editor
+ textEditor.selectAndReveal(item.startOffset(), item.length());
+ }
+ }
+ }
+ }
+
+ /**
+ * Sends the input to the tree viewer.
+ * @param input the input
+ */
+ public void setInput(Object input) {
+ if (!getTreeViewer().getControl().isDisposed()) {
+ getTreeViewer().setInput(input);
+ //getTreeViewer().collapseAll();// doesn't work..
+ }
+ }
+
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ }
+ /**
+ * Notify document modifications.
+ */
+ public void documentChanged(DocumentEvent event) {
+ document = event.getDocument();
+ update();
+ }
+
+ /**
+ * Get the outline data.
+ *
+ * @param project Current project
+ * @param filename File to outline
+ * @return List of outline items
+ */
+ public List<OutlineItem> getSourceOutline(IProject project, String filename) {
+ LisaacModel model = LisaacModel.getModel(project);
+ if (model != null) {
+ Prototype prototype = model.getPrototype(LisaacModel.extractPrototypeName(filename));
+
+ if (prototype != null) {
+ return prototype.getOutlineItems();
+ }
+ }
+ return null;
+ }
+
+ private void createTimer() {
+ updateTimer = new Timer("org.eclipse.lisaac.outlinetimer");
+ }
+
+ /**
+ * Updates the outline content view.
+ */
+ public void update() {
+ updateTimer.cancel();
+ updateTimer.purge();
+ createTimer();
+
+ OutlineUpdateTask updateTask = new OutlineUpdateTask();
+ updateTimer.schedule(updateTask, UPDATE_DELAY);
+ }
+
+ /**
+ * This class is in charge of updating the outline.
+ */
+ class OutlineUpdateTask extends TimerTask {
+ public OutlineUpdateTask() {
+ super();
+ }
+
+ /**
+ * Updates the outline content view.
+ * @see TimerTask#run()
+ */
+ public void run() {
+ final IDocument document = getDocument();
+ Display display = PlatformUI.getWorkbench().getDisplay();
+
+ if (document != null && (textEditor instanceof LisaacEditor)) {
+ IProject project = ((LisaacEditor) textEditor).getProject();
+ String filename = ((LisaacEditor) textEditor).getFileName();
+
+ final List<OutlineItem> items = getSourceOutline(project, filename);
+
+ display.asyncExec(new Runnable() {
+ public void run() {
+ setInput(items.toArray(new OutlineItem[items.size()]));
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/wizards/AbstractNewFileWizard.java b/src/org/eclipse/lisaac/wizards/AbstractNewFileWizard.java
new file mode 100644
index 0000000..fef68a0
--- /dev/null
+++ b/src/org/eclipse/lisaac/wizards/AbstractNewFileWizard.java
@@ -0,0 +1,155 @@
+package org.eclipse.lisaac.wizards;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+public abstract class AbstractNewFileWizard extends Wizard implements INewWizard {
+
+ private AbstractNewFileWizardPage page;
+
+ private IStructuredSelection selection;
+
+
+ public AbstractNewFileWizard() {
+ super();
+ setNeedsProgressMonitor(true);
+ }
+
+ abstract protected AbstractNewFileWizardPage createPage();
+
+ /**
+ * Adding the page to the wizard.
+ */
+ public void addPages() {
+ page = createPage();
+ addPage(page);
+ }
+
+ /**
+ * This method is called when 'Finish' button is pressed in the wizard. We
+ * will create an operation and run it using wizard as execution context.
+ */
+ public boolean performFinish() {
+ final String containerName = page.getContainerName();
+ final String fileName = getFileNameWithExtension();
+ final InputStream stream = page.getInitialContents(fileName);
+
+ IRunnableWithProgress op = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException {
+ try {
+ doFinish(containerName, fileName, stream, monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ try {
+ getContainer().run(true, false, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ Throwable realException = e.getTargetException();
+ MessageDialog.openError(getShell(),
+ "Wizard error", realException.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * The worker method. It will find the container, create the file if missing
+ * or just replace its contents, and open the editor on the newly created
+ * file.
+ */
+ private void doFinish(String containerName, String fileName, InputStream stream,
+ IProgressMonitor monitor) throws CoreException {
+ // create a sample file
+ monitor.beginTask("Creating File " + fileName, 2);
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IResource resource = root.findMember(new Path(containerName));
+ if (!resource.exists() || !(resource instanceof IContainer)) {
+ throwCoreException("Container does not exist.");
+ }
+ IContainer container = (IContainer) resource;
+ final IFile file = container.getFile(new Path(fileName));
+
+ try {
+ if (file.exists()) {
+ file.setContents(stream, true, true, monitor);
+ } else {
+ file.create(stream, true, monitor);
+ }
+ stream.close();
+ } catch (IOException e) {
+ }
+ monitor.worked(1);
+ monitor.setTaskName("Opening file...");
+
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage page = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage();
+ try {
+ IDE.openEditor(page, file, true);
+ } catch (PartInitException e) {
+ }
+ }
+ });
+ monitor.worked(1);
+ }
+
+ public String getFileNameWithExtension() {
+ String filename = page.getFileName();
+ int index = filename.lastIndexOf('.');
+ if (index == -1) {
+ filename += page.getFileExtension();
+ }
+ return filename;
+ }
+
+
+ private void throwCoreException(String message) throws CoreException {
+ IStatus status = new Status(IStatus.ERROR,
+ "org.eclipse.lisaac.wizards", IStatus.OK, message, null);
+ throw new CoreException(status);
+ }
+
+ /**
+ * We will accept the selection in the workbench to see if we can initialize
+ * from it.
+ *
+ * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
+ */
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.selection = selection;
+ }
+
+ protected IStructuredSelection getSelection() {
+ return selection;
+ }
+}
diff --git a/src/org/eclipse/lisaac/wizards/AbstractNewFileWizardPage.java b/src/org/eclipse/lisaac/wizards/AbstractNewFileWizardPage.java
new file mode 100644
index 0000000..44ec0e4
--- /dev/null
+++ b/src/org/eclipse/lisaac/wizards/AbstractNewFileWizardPage.java
@@ -0,0 +1,256 @@
+package org.eclipse.lisaac.wizards;
+
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+
+
+public abstract class AbstractNewFileWizardPage extends WizardPage {
+
+ /** initial source folder selection */
+ private IStructuredSelection selection;
+
+ /** source folder path */
+ private Text containerText;
+
+ /** file name */
+ private Text fileText;
+
+ /** file extension */
+ private String fileExtension = "";
+
+
+ protected AbstractNewFileWizardPage(String pageName, IStructuredSelection selection) {
+ super(pageName);
+ this.selection = selection;
+ setPageComplete(false);
+ }
+
+ public String getContainerName() {
+ return containerText.getText();
+ }
+
+ public String getFileName() {
+ return fileText.getText();
+ }
+
+ public String getFileExtension() {
+ return fileExtension;
+ }
+
+ /**
+ * set the extension of files created with this wizard.
+ */
+ protected void setFileExtension(String ext) {
+ fileExtension = ext;
+ }
+
+ /**
+ * Content File Initialisation.
+ */
+ abstract protected InputStream getInitialContents(String filename);
+
+
+ /**
+ * @see IDialogPage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ container.setLayout(layout);
+ layout.numColumns = 3;
+ layout.verticalSpacing = 9;
+ Label label = new Label(container, SWT.NULL);
+ label.setText("Source folder : ");
+
+ containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ containerText.setLayoutData(gd);
+ containerText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ });
+
+ Button button = new Button(container, SWT.PUSH);
+ button.setText("Browse");
+ button.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+ label = new Label(container, SWT.NULL);
+ label.setText("File name : ");
+
+ fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 1;
+ fileText.setLayoutData(gd);
+ fileText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ });
+ Composite dummy = new Composite(container, SWT.NONE);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 1;
+ dummy.setLayoutData(gd);
+
+ //
+ createAdvancedControls(container);
+ //
+ initialize();
+ dialogChanged();
+ setControl(container);
+ }
+
+ protected void createAdvancedControls(Composite parent) {
+ // should be override
+ }
+
+ /**
+ * Tests if the current workbench selection is a suitable container to use.
+ */
+ private void initialize() {
+ if (selection != null && selection.isEmpty() == false
+ && selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ if (ssel.size() > 1)
+ return;
+ Object obj = ssel.getFirstElement();
+ if (obj instanceof IResource) {
+ IContainer container;
+ if (obj instanceof IContainer)
+ container = (IContainer) obj;
+ else
+ container = ((IResource) obj).getParent();
+ containerText.setText(container.getFullPath().toString());
+ fileText.setFocus();
+ }
+ }
+ fileText.setText(getInitialFileName());
+ }
+
+ protected abstract String getInitialFileName();
+
+ /**
+ * Uses the standard container selection dialog to choose the new value for
+ * the container field.
+ */
+
+ private void handleBrowse() {
+ ContainerSelectionDialog dialog = new ContainerSelectionDialog(
+ getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
+ "Select container.");
+ if (dialog.open() == ContainerSelectionDialog.OK) {
+ Object[] results = dialog.getResult();
+ if (results.length == 1) {
+ Object result = results[0];
+ if (result instanceof IPath) {
+ IPath ipath = (IPath) result;
+ containerText.setText(ipath.toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * Ensures that both text fields are set.
+ */
+ private void dialogChanged() {
+ String container = getContainerName();
+ String fileName = getFileName();
+
+ if (container.length() == 0) {
+ updateStatus("Source folder must be specified.");
+ return;
+ }
+ if (fileName.length() == 0) {
+ updateStatus("File name must be specified.");
+ return;
+ }
+ updateStatus(null);
+ }
+
+ private void updateStatus(String message) {
+ setErrorMessage(message);
+ setPageComplete(message == null);
+ }
+
+ /**
+ * @see WizardPage#isPageComplete()
+ */
+ public boolean isPageComplete() {
+ return !checkFolderForExistingFile() && super.isPageComplete();
+ }
+
+ /**
+ * Finds the current directory where the file should be created
+ */
+ protected boolean checkFolderForExistingFile() {
+ IContainer container = getFileContainer();
+ if (container != null) {
+ IResource file = container.getFile(new Path(fileText.getText()
+ .trim()));
+ if (file != null && file.exists()) {
+ this.setErrorMessage("File already exists.");
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private IContainer getFileContainer() {
+ if (containerText.getText() != null) {
+ IPath containerPath = new Path(containerText.getText().trim());
+ IContainer container = null;
+ if (containerPath.segmentCount() > 1) {
+ container = ResourcesPlugin.getWorkspace().getRoot().getFolder(
+ containerPath);
+ } else {
+ if (containerPath.segmentCount() == 1) {
+ // this is a project
+ container = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(containerText.getText().trim());
+ }
+ }
+ if (container != null && container.exists()) {
+ return container;
+ }
+ }
+ return null;
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) {
+ String fileName = fileText.getText().trim();
+ if (getFileContainer() != null
+ && fileName.equalsIgnoreCase(getInitialFileName())) {
+ fileText.setFocus();
+ fileText.setText(fileName);
+ fileText.setSelection(0, fileName.length()
+ - (new Path(getInitialFileName())).getFileExtension()
+ .length() - 1);
+ }
+ }
+ }
+}
diff --git a/src/org/eclipse/lisaac/wizards/NewProjectWizard.java b/src/org/eclipse/lisaac/wizards/NewProjectWizard.java
new file mode 100644
index 0000000..0cf15f1
--- /dev/null
+++ b/src/org/eclipse/lisaac/wizards/NewProjectWizard.java
@@ -0,0 +1,299 @@
+package org.eclipse.lisaac.wizards;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.lisaac.builder.LisaacNature;
+import org.eclipse.lisaac.model.LisaacModel;
+import org.eclipse.lisaac.properties.LisaacProjectPropertyPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
+
+
+public class NewProjectWizard extends Wizard implements INewWizard {
+
+ NewProjectWizardPage mainPage;
+
+ public NewProjectWizard() {
+ super();
+ setNeedsProgressMonitor(true);
+ }
+
+ // called with the 'finish' button
+ public boolean performFinish() {
+ final String name, lisaacPath;
+ final IPath path;
+ IRunnableWithProgress op = null;
+ try {
+ name = mainPage.getProjectName();
+ path = mainPage.getLocationPath() ;
+ lisaacPath = mainPage.getLisaacPath();
+ op = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException {
+ try {
+ doFinish(name, path, lisaacPath, monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ } catch (NullPointerException e1) {
+ e1.printStackTrace();
+ }
+
+ try {
+ getContainer().run(true, false, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ Throwable realException = e.getTargetException();
+ MessageDialog.openError(getShell(), "Error !", realException.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ private void doFinish(String projectName, IPath nomRep, String lisaacPath, IProgressMonitor monitor)
+ throws CoreException
+ {
+ monitor.beginTask("Project Creation " + projectName, 2);
+
+ // get project root
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+
+ try {
+ IProject project = root.getProject(projectName);
+ if (project.exists() && !project.isOpen()) {
+ project.open(null);
+ } else {
+ project.create(null);
+ project.open(null);
+ }
+ try {
+
+ // set lisaac builder
+ LisaacNature nature = new LisaacNature();
+ nature.setProject(project);
+ nature.configure();
+
+ // set lisaac nature
+ IProjectDescription description = project.getDescription();
+ description.setNatureIds(new String[]{LisaacNature.NATURE_ID});
+ project.setDescription(description, null);
+
+ } catch (CoreException e) {
+ // Something went wrong
+ }
+ //
+ new LisaacModel(project);
+ //
+
+ // create make file for project
+ IFile lipFile = project.getFile("make.lip");
+ lipFile.create(new ByteArrayInputStream(getLipStream(project)), false, monitor);
+
+ // create default folder & files in project
+ IFolder src = project.getFolder("src");
+ if (! src.exists())
+ src.create(false, false, null);
+
+ IFile mainPrototype = src.getFile(projectName.toLowerCase()+".li");
+ mainPrototype.create(new ByteArrayInputStream(getMainPrototypeStream(projectName)), false, monitor);
+
+ IFolder bin = project.getFolder("bin");
+ if (! bin.exists())
+ bin.create(false,false,null);
+
+ // store the value in the lisaac project field
+ project.setPersistentProperty(
+ new QualifiedName("", LisaacProjectPropertyPage.LISAAC_PATH),
+ lisaacPath);
+
+ } catch (IOException e) {
+ MessageDialog.openError(getShell(), "Project creation Error !", e.getMessage());
+ } catch (CoreException e) {
+ MessageDialog.openError(getShell(), "Project settings Error !", e.getMessage());
+ }
+
+ monitor.worked(1);
+ monitor.setTaskName("Opening project ...");
+ monitor.worked(1);
+ // ...
+ monitor.done();
+ }
+
+
+ public byte[] getMainPrototypeStream(String projectName) throws IOException {
+ String contents = "// Lisaac main prototype\n";
+ contents += "\nSection Header\n\n";
+ contents += " + name := "+projectName.toUpperCase()+";\n";
+ contents += " - comment := \"Main Prototype\";\n";
+ contents += "\nSection Inherit\n\n";
+ contents += " - parent_object:OBJECT := OBJECT;\n";
+ contents += "\nSection Public\n\n";
+ contents += " - main <- \n";
+ contents += " // Main entry point.\n";
+ contents += " (\n\n";
+ contents += " \n";
+ contents += " );\n";
+ return contents.getBytes();
+ }
+
+ public byte[] getLipStream(IProject project) throws IOException {
+ String contents = "//\n// `"+project.getName()+"` LIsaac Project file\n//";
+ contents += "\nSection Inherit\n\n";
+ contents += " + parent:STRING;\n";
+ contents += "\nSection Private\n\n";
+ contents += " + project_root:STRING := \""+project.getLocationURI().getPath()+"\";\n\n";
+ contents += " - project_src_path <- \n";
+ contents += " // Define the project path for source code.\n";
+ contents += " (\n";
+ contents += " path (project_root + \"src/\");\n";
+ contents += " );\n\n";
+ contents += " - front_end <- \n";
+ contents += " // Executed by compiler, before compilation step.\n";
+ contents += " (\n";
+ contents += " project_src_path;\n";
+ contents += " general_front_end;\n";
+ contents += " );\n";
+ contents += "\nSection Public\n\n";
+ contents += " - clean <- \n";
+ contents += " // Clean project.\n";
+ contents += " (\n";
+ contents += " );\n";
+ return contents.getBytes();
+ }
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ setWindowTitle("New Lisaac Project Wizard");
+ setNeedsProgressMonitor(true);
+ mainPage = new NewProjectWizardPage("New Lisaac Project");
+ }
+
+ public void addPages() {
+ super.addPages();
+ addPage(mainPage);
+ }
+}
+
+class NewProjectWizardPage extends WizardNewProjectCreationPage {
+
+ private Text pathValueText;
+
+ private Button browseButton;
+
+ NewProjectWizardPage(String pageName) {
+ super(pageName);
+ setTitle(pageName);
+ setDescription("Create a lisaac project");
+ }
+
+ public String getLisaacPath() {
+ return pathValueText.getText();
+ }
+
+ public void createControl(Composite parent) {
+ // inherit default container and name specification widgets
+ super.createControl(parent);
+
+ Composite composite = (Composite)getControl();
+
+ Group group = new Group(composite, SWT.SHADOW_IN);
+ group.setText(LisaacProjectPropertyPage.LISAAC_PATH);
+ group.setLayout(new GridLayout());
+
+ final Button b1 = new Button(group, SWT.RADIO);
+ b1.setFont(parent.getFont());
+ b1.setText("Use default Lisaac Environment");
+
+ final Button b2 = new Button(group, SWT.RADIO);
+ b2.setFont(parent.getFont());
+ b2.setText("Use a project specific Lisaac Environment : ");
+
+ Composite envGroup = new Composite(group, SWT.NONE);
+ envGroup.setLayout(new RowLayout());
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ gridData.grabExcessHorizontalSpace = true;
+ envGroup.setLayoutData(gridData);
+
+ // Path text field
+ pathValueText = new Text(envGroup, SWT.BORDER/*SWT.WRAP | SWT.READ_ONLY*/);
+ pathValueText.setText(LisaacProjectPropertyPage.getDefaultLisaacPath());
+ pathValueText.setEnabled(false);
+ RowData rowData = new RowData();
+ rowData.width = 200;
+ pathValueText.setLayoutData(rowData);
+
+ b2.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (b2.getSelection()) {
+ pathValueText.setEnabled(true);
+ browseButton.setEnabled(true);
+ } else {
+ pathValueText.setEnabled(false);
+ browseButton.setEnabled(false);
+ }
+ }
+ });
+ browseButton = new Button(envGroup, SWT.PUSH);
+ browseButton.setText("Browse");
+ browseButton.setEnabled(false);
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ //handleBrowse();
+ }
+ });
+
+
+ // Composite composite = (Composite)getControl();
+
+ // sample section generation group
+ /* Group group = new Group(composite,SWT.NONE);
+ group.setLayout(new GridLayout());
+ group.setText("Automatic_sample_section_generation");
+ group.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL |
+ GridData.HORIZONTAL_ALIGN_FILL));
+
+ // sample section generation checkboxes
+ Button sectionCheckbox = new Button(group,SWT.CHECK);
+ sectionCheckbox.setText("Generate_sample_section_titles");
+ sectionCheckbox.setSelection(true);
+ /// sectionCheckbox.addListener(SWT.Selection,this);
+
+ Button subsectionCheckbox = new Button(group,SWT.CHECK);
+ subsectionCheckbox.setText("Generate_sample_subsection_titles");
+ subsectionCheckbox.setSelection(true);
+ // subsectionCheckbox.addListener(SWT.Selection,this);*/
+ }
+
+}
diff --git a/src/org/eclipse/lisaac/wizards/NewPrototypeWizard.java b/src/org/eclipse/lisaac/wizards/NewPrototypeWizard.java
new file mode 100644
index 0000000..6da91ff
--- /dev/null
+++ b/src/org/eclipse/lisaac/wizards/NewPrototypeWizard.java
@@ -0,0 +1,232 @@
+package org.eclipse.lisaac.wizards;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.lisaac.model.ILisaacModel;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+
+
+/**
+ * Lisaac source file creator.
+ */
+public class NewPrototypeWizard extends AbstractNewFileWizard {
+
+ public NewPrototypeWizard() {
+ super();
+ setWindowTitle("New Prototype");
+ }
+
+ /**
+ * Create wizard page
+ */
+ protected AbstractNewFileWizardPage createPage() {
+ return new NewPrototypeWizardPage(getSelection());
+ }
+}
+
+/**
+ * Represent the main page in "new lisaac prototype" wizard.
+ */
+class NewPrototypeWizardPage extends AbstractNewFileWizardPage {
+ final private String INITIAL_PROTOTYPE_NAME = "prototype.li";
+
+ protected Text commentField;
+
+ protected Button styleNone;
+ protected Button styleExpanded;
+ protected Button styleStrict;
+
+ protected Table tableInherit;
+
+ protected NewPrototypeWizardPage(IStructuredSelection selection) {
+ super(NewPrototypeWizardPage.class.getName(), selection);
+
+ setTitle("Prototype File");
+ setDescription("Creates a new source file into a project");
+ setFileExtension(".li");
+ }
+
+ public String getPrototypeDescription() {
+ return commentField.getText();
+ }
+
+ /**
+ * Return the initial content of new file.
+ */
+ protected InputStream getInitialContents(String filename) {
+ try {
+ int index = filename.lastIndexOf('.');
+ if (index != -1) {
+ filename = filename.substring(0, index);
+ }
+ return new ByteArrayInputStream(getPrototypeStream(filename));
+ } catch (IOException e) {
+ return null; // ignore and create empty comments
+ }
+ }
+
+ public byte[] getPrototypeStream(String filename) throws IOException {
+ boolean isExpanded = styleExpanded.getSelection();
+ boolean isStrict = styleExpanded.getSelection();
+
+ String contents = "\nSection Header\n\n";
+ contents += " + name := ";
+ if (isExpanded) {
+ contents += "Expanded ";
+ } else if (isStrict) {
+ contents += "Strict ";
+ }
+ contents += filename.toUpperCase()+";\n";
+
+ String descr = getPrototypeDescription();
+ if (descr != null && descr.length() > 0) {
+ contents += " - comment := \""+descr+"\";\n";
+ }
+ if (! isExpanded) {
+ contents += "\nSection Inherit\n\n";
+ } else {
+ contents += "\nSection Insert\n\n";
+ }
+ int n = tableInherit.getItemCount();
+ if (n > 0) {
+ for (int i=0; i<n; i++) {
+ TableItem item = tableInherit.getItem(i);
+ String type = item.getText(1);
+ if (type.equals(ILisaacModel.inherit_shared) ||
+ type.equals(ILisaacModel.inherit_shared_expanded)) {
+ contents += " - ";
+ } else {
+ contents += " + ";
+ }
+ contents += "parent_";
+ contents += item.getText(0).toLowerCase() + ":";
+ if (type.equals(ILisaacModel.inherit_shared_expanded) ||
+ type.equals(ILisaacModel.inherit_nonshared_expanded)) {
+ contents += "Expanded " + item.getText(0);
+ } else {
+ contents += item.getText(0) + " := " + item.getText(0);
+ }
+ contents += ";\n";
+ }
+ } else {
+ contents += " - parent_object:OBJECT := OBJECT;\n";
+ }
+ contents += "\nSection Public\n\n";
+ return contents.getBytes();
+ }
+
+ /**
+ * Additional wizard information
+ */
+ public void createAdvancedControls(Composite parent) {
+
+ // -- Style --
+ Label label = new Label(parent, SWT.NONE);
+ label.setText("Prototype Style : ");
+ label.setFont(parent.getFont());
+
+ Composite radioGroup = new Composite(parent, SWT.NONE);
+ radioGroup.setLayout(new RowLayout());
+ styleNone = new Button(radioGroup, SWT.RADIO);
+ styleNone.setFont(parent.getFont());
+ styleNone.setText("None");
+ styleExpanded = new Button(radioGroup, SWT.RADIO);
+ styleExpanded.setFont(parent.getFont());
+ styleExpanded.setText("Expanded");
+ styleStrict = new Button(radioGroup, SWT.RADIO);
+ styleStrict.setFont(parent.getFont());
+ styleStrict.setText("Strict");
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ radioGroup.setLayoutData(gridData);
+ //
+
+ // -- Description --
+ label = new Label(parent, SWT.NONE);
+ label.setText("Description : ");
+ label.setFont(parent.getFont());
+ gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 1;
+ label.setLayoutData(gridData);
+
+ commentField = new Text(parent, SWT.BORDER);
+ commentField.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+ gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ commentField.setLayoutData(gridData);
+ //
+
+ // -- inherits --
+ label = new Label(parent, SWT.NONE);
+ label.setText("Inheritance : ");
+ label.setFont(parent.getFont());
+ gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 1;
+ label.setLayoutData(gridData);
+
+ Composite tableGroup = new Composite(parent, SWT.NONE);
+ tableGroup.setLayout(new RowLayout());
+
+ final Table table = new Table(tableGroup, SWT.BORDER | SWT.SINGLE |
+ SWT.H_SCROLL | SWT.FULL_SELECTION);
+ final TableColumn c1 = new TableColumn(table, SWT.LEFT);
+ c1.setText("Prototype");
+ c1.setWidth(150);
+ final TableColumn c2 = new TableColumn(table, SWT.LEFT);
+ c2.setText("Inheritance Type");
+ c2.setWidth(100);
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+
+ final TableItem itemDefault = new TableItem(table, SWT.NONE);
+ itemDefault.setText(new String[] {"OBJECT", ILisaacModel.inherit_shared});
+
+ Composite buttonGroup = new Composite(tableGroup, SWT.NONE);
+ buttonGroup.setLayout(new GridLayout());
+ Button tableAdd = new Button(buttonGroup, SWT.PUSH);
+ tableAdd.setFont(parent.getFont());
+ tableAdd.setText("Add");
+ tableAdd.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ // TODO dialog to create inherit table item
+ }
+ });
+ Button tableRemove= new Button(buttonGroup, SWT.PUSH);
+ tableRemove.setFont(parent.getFont());
+ tableRemove.setText("Remove");
+ tableRemove.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ int[] indices = table.getSelectionIndices();
+ if (indices != null && indices.length > 0) {
+ int index = indices[0];
+ table.remove(index);
+ }
+ }
+ });
+ gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ tableGroup.setLayoutData(gridData);
+
+ tableInherit = table;
+ //
+ }
+
+ protected String getInitialFileName() {
+ return INITIAL_PROTOTYPE_NAME;
+ }
+}
--
Lisaac eclipse plugin
More information about the Lisaac-commits
mailing list