[SCM] Lisaac compiler branch, master, updated. lisaac-0.12-417-g653c1fc
Damien Bouvarel
dams.bouvarel at wanadoo.fr
Wed Aug 19 22:37:04 UTC 2009
The following commit has been merged in the master branch:
commit 653c1fc98ddcd2993046d7ebb9c2c75f2ab1f2ac
Author: Damien Bouvarel <dams.bouvarel at wanadoo.fr>
Date: Thu Aug 20 00:35:45 2009 +0200
add eclisaac sources
diff --git a/editor/eclipse/.classpath b/editor/eclipse/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/editor/eclipse/.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/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/editor/eclipse/.project b/editor/eclipse/.project
new file mode 100644
index 0000000..35beef2
--- /dev/null
+++ b/editor/eclipse/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>eclipse</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/editor/eclipse/.settings/org.eclipse.jdt.core.prefs b/editor/eclipse/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5cab958
--- /dev/null
+++ b/editor/eclipse/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Tue Jun 16 14:27:35 CEST 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/editor/eclipse/META-INF/MANIFEST.MF b/editor/eclipse/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..982f333
--- /dev/null
+++ b/editor/eclipse/META-INF/MANIFEST.MF
@@ -0,0 +1,97 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.lisaac.ldt;singleton:=true
+Bundle-Version: 1.1.4
+Bundle-Activator: org.lisaac.ldt.LisaacPlugin
+Bundle-Vendor: %Bundle-Vendor.0
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.jface.text,
+ org.eclipse.ui.editors,
+ org.eclipse.ui.ide,
+ org.eclipse.ui.console,
+ org.eclipse.debug.ui,
+ org.eclipse.ltk.core.refactoring
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ActivationPolicy: lazy
+Bundle-ClassPath: .,
+ bin/
+Import-Package: org.eclipse.debug.core,
+ org.eclipse.debug.core.model,
+ org.eclipse.debug.ui,
+ org.eclipse.ltk.ui.refactoring,
+ org.eclipse.ui.texteditor.templates,
+ org.eclipse.ui.views.contentoutline
+Export-Package: org.lisaac.ldt;
+ uses:="org.eclipse.core.runtime,
+ org.eclipse.jface.resource,
+ org.eclipse.ui.plugin,
+ org.eclipse.jface.text.templates.persistence,
+ org.osgi.framework,
+ org.eclipse.jface.text.templates",
+ org.lisaac.ldt.actions;
+ uses:="org.eclipse.jface.action,
+ org.eclipse.ui,
+ org.eclipse.jface.viewers,
+ org.eclipse.swt.widgets",
+ org.lisaac.ldt.builder;uses:="org.lisaac.ldt.model,org.eclipse.core.runtime,org.eclipse.core.resources",
+ org.lisaac.ldt.editors;
+ uses:="org.eclipse.jface.text,
+ org.eclipse.jface.text.hyperlink,
+ org.eclipse.core.runtime,
+ org.eclipse.jface.text.source,
+ org.eclipse.jface.text.rules,
+ org.eclipse.jface.text.contentassist,
+ org.lisaac.ldt.model,
+ org.eclipse.jface.preference,
+ org.eclipse.jface.text.presentation,
+ org.eclipse.core.resources,
+ org.eclipse.jface.viewers,
+ org.eclipse.swt.graphics,
+ org.eclipse.jface.util,
+ org.eclipse.swt.widgets,
+ org.eclipse.ui.editors.text",
+ org.lisaac.ldt.launch;
+ uses:="org.eclipse.debug.core,
+ org.eclipse.debug.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.ui,
+ org.eclipse.debug.core.model,
+ org.eclipse.core.resources,
+ org.eclipse.jface.viewers,
+ org.eclipse.swt.graphics,
+ org.eclipse.swt.widgets",
+ org.lisaac.ldt.model;
+ uses:="org.lisaac.ldt.model.types,
+ org.lisaac.ldt.model.items,
+ org.lisaac.ldt.model.lip,
+ org.eclipse.core.resources,
+ org.lisaac.ldt.builder",
+ org.lisaac.ldt.model.items;uses:="org.lisaac.ldt.model,org.lisaac.ldt.model.types",
+ org.lisaac.ldt.model.lip,
+ org.lisaac.ldt.model.types,
+ org.lisaac.ldt.outline;uses:="org.lisaac.ldt.model.items,org.eclipse.jface.viewers,org.eclipse.swt.graphics",
+ org.lisaac.ldt.perspectives;uses:="org.eclipse.ui",
+ org.lisaac.ldt.preferences;
+ uses:="org.eclipse.ui.texteditor.templates,
+ org.eclipse.jface.preference,
+ org.eclipse.ui,
+ org.eclipse.core.runtime.preferences",
+ org.lisaac.ldt.properties;uses:="org.eclipse.core.resources,org.eclipse.ui.dialogs,org.eclipse.swt.widgets",
+ org.lisaac.ldt.templates;uses:="org.eclipse.jface.text,org.eclipse.swt.graphics,org.eclipse.jface.text.templates",
+ org.lisaac.ldt.views;
+ uses:="org.eclipse.jface.text,
+ org.eclipse.ui.texteditor,
+ org.eclipse.ui.console,
+ org.eclipse.ui.views.contentoutline,
+ org.eclipse.core.resources,
+ org.eclipse.jface.viewers,
+ org.eclipse.swt.widgets",
+ org.lisaac.ldt.wizards;
+ uses:="org.eclipse.jface.wizard,
+ org.eclipse.ui,
+ org.eclipse.core.resources,
+ org.eclipse.jface.viewers,
+ org.eclipse.swt.widgets"
+Bundle-Localization: plugin
+Bundle-Name: %Bundle-Name.0
diff --git a/editor/eclipse/build.properties b/editor/eclipse/build.properties
new file mode 100644
index 0000000..f67e7f3
--- /dev/null
+++ b/editor/eclipse/build.properties
@@ -0,0 +1,21 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ bin/,\
+ icons/,\
+ plugin.xml,\
+ plugin.properties,\
+ help/,\
+ build.properties
+bin.excludes = icons/Thumbs.db
+src.excludes = icons/Thumbs.db
+src.includes = META-INF/,\
+ README,\
+ bin/,\
+ build.properties,\
+ help/,\
+ icons/,\
+ plugin.properties,\
+ plugin.xml,\
+ src/
diff --git a/editor/eclipse/help/html/maintopic.html b/editor/eclipse/help/html/maintopic.html
new file mode 100644
index 0000000..a476078
--- /dev/null
+++ b/editor/eclipse/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/editor/eclipse/help/html/overview.html b/editor/eclipse/help/html/overview.html
new file mode 100644
index 0000000..a476078
--- /dev/null
+++ b/editor/eclipse/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/editor/eclipse/help/html/subtopic.html b/editor/eclipse/help/html/subtopic.html
new file mode 100644
index 0000000..8a61c50
--- /dev/null
+++ b/editor/eclipse/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/editor/eclipse/help/html/toc.html b/editor/eclipse/help/html/toc.html
new file mode 100644
index 0000000..326f0a9
--- /dev/null
+++ b/editor/eclipse/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/editor/eclipse/help/sheet1_HelloWorld.xml b/editor/eclipse/help/sheet1_HelloWorld.xml
new file mode 100644
index 0000000..3324a79
--- /dev/null
+++ b/editor/eclipse/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/editor/eclipse/help/testToc.xml b/editor/eclipse/help/testToc.xml
new file mode 100644
index 0000000..ca7402e
--- /dev/null
+++ b/editor/eclipse/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/editor/eclipse/help/toc.xml b/editor/eclipse/help/toc.xml
new file mode 100644
index 0000000..6ad67be
--- /dev/null
+++ b/editor/eclipse/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/editor/eclipse/icons/Thumbs.db b/editor/eclipse/icons/Thumbs.db
new file mode 100644
index 0000000..7571e9a
Binary files /dev/null and b/editor/eclipse/icons/Thumbs.db differ
diff --git a/editor/eclipse/icons/alphab_sort_co.gif b/editor/eclipse/icons/alphab_sort_co.gif
new file mode 100644
index 0000000..6d77244
Binary files /dev/null and b/editor/eclipse/icons/alphab_sort_co.gif differ
diff --git a/editor/eclipse/icons/blank.gif b/editor/eclipse/icons/blank.gif
new file mode 100644
index 0000000..ede75be
Binary files /dev/null and b/editor/eclipse/icons/blank.gif differ
diff --git a/editor/eclipse/icons/error_co.gif b/editor/eclipse/icons/error_co.gif
new file mode 100644
index 0000000..8612eaf
Binary files /dev/null and b/editor/eclipse/icons/error_co.gif differ
diff --git a/editor/eclipse/icons/keyword.gif b/editor/eclipse/icons/keyword.gif
new file mode 100644
index 0000000..435d62e
Binary files /dev/null and b/editor/eclipse/icons/keyword.gif differ
diff --git a/editor/eclipse/icons/library.gif b/editor/eclipse/icons/library.gif
new file mode 100644
index 0000000..cb55e33
Binary files /dev/null and b/editor/eclipse/icons/library.gif differ
diff --git a/editor/eclipse/icons/private-nonshared.gif b/editor/eclipse/icons/private-nonshared.gif
new file mode 100644
index 0000000..39891e1
Binary files /dev/null and b/editor/eclipse/icons/private-nonshared.gif differ
diff --git a/editor/eclipse/icons/private-shared.gif b/editor/eclipse/icons/private-shared.gif
new file mode 100644
index 0000000..e4c1859
Binary files /dev/null and b/editor/eclipse/icons/private-shared.gif differ
diff --git a/editor/eclipse/icons/prototype.gif b/editor/eclipse/icons/prototype.gif
new file mode 100644
index 0000000..eb6e0b6
Binary files /dev/null and b/editor/eclipse/icons/prototype.gif differ
diff --git a/editor/eclipse/icons/public-nonshared.gif b/editor/eclipse/icons/public-nonshared.gif
new file mode 100644
index 0000000..828590b
Binary files /dev/null and b/editor/eclipse/icons/public-nonshared.gif differ
diff --git a/editor/eclipse/icons/public-shared.gif b/editor/eclipse/icons/public-shared.gif
new file mode 100644
index 0000000..698f668
Binary files /dev/null and b/editor/eclipse/icons/public-shared.gif differ
diff --git a/editor/eclipse/icons/sample.gif b/editor/eclipse/icons/sample.gif
new file mode 100644
index 0000000..34fb3c9
Binary files /dev/null and b/editor/eclipse/icons/sample.gif differ
diff --git a/editor/eclipse/icons/sections_co.gif b/editor/eclipse/icons/sections_co.gif
new file mode 100644
index 0000000..82bc04e
Binary files /dev/null and b/editor/eclipse/icons/sections_co.gif differ
diff --git a/editor/eclipse/icons/source-folder.gif b/editor/eclipse/icons/source-folder.gif
new file mode 100644
index 0000000..fca9c53
Binary files /dev/null and b/editor/eclipse/icons/source-folder.gif differ
diff --git a/editor/eclipse/icons/template.gif b/editor/eclipse/icons/template.gif
new file mode 100644
index 0000000..fdde5fb
Binary files /dev/null and b/editor/eclipse/icons/template.gif differ
diff --git a/editor/eclipse/icons/warning_co.gif b/editor/eclipse/icons/warning_co.gif
new file mode 100644
index 0000000..3af228c
Binary files /dev/null and b/editor/eclipse/icons/warning_co.gif differ
diff --git a/editor/eclipse/plugin.properties b/editor/eclipse/plugin.properties
new file mode 100644
index 0000000..164a6d3
--- /dev/null
+++ b/editor/eclipse/plugin.properties
@@ -0,0 +1,43 @@
+#Properties file for eclipse
+Bundle-Name.0 = Lisaac Plug-in
+editor.name.0 = Lisaac Editor
+editor.name.1 = Lip Editor
+perspective.name.0 = Lisaac
+page.name.0 = Lisaac
+page.name.1 = Templates
+page.name.2 = Syntax Coloring
+page.name.3 = Editor
+page.name.5 = Lisaac Compiler
+category.name.0 = Lisaac
+wizard.name.0 = Lisaac Project
+wizard.name.1 = Lisaac Prototype
+consoleFactory.label.0 = Lisaac Console
+launchConfigurationType.name.0 = Lisaac Application
+actionSet.description.0 = Lisaac Source Tools
+actionSet.label.0 = Source
+menu.label.0 = Source
+action.label.0 = Correct Indentation
+action.label.1 = Generate Constructor
+menu.label.1 = New Prototype
+action.label.2 = New Prototype
+action.tooltip.0 = Create new prototype
+action.label.3 = Toggle Comment
+command.name.0 = Indentation
+category.name.1 = Lisaac Command
+command.name.1 = Generate Constructor
+command.name.2 = New Prototype
+command.name.3 = Toggle comment
+shortcut.label.0 = Lisaac Application
+
+perspective.description.0 = Perspective for Lisaac Development
+template.description.0 = While loop
+template.description.1 = Until Loop
+template.description.2 = If statement
+template.description.3 = If Else statement
+template.description.4 = If false statement
+template.description.5 = For loop
+Bundle-Vendor.0 = Damien Bouvarel
+wizard.name.2 = Source folder
+action.label.4 = Rename Prototype...
+menu.label.2 = Refactor
+command.name.4 = Rename Prototype
\ No newline at end of file
diff --git a/editor/eclipse/plugin.xml b/editor/eclipse/plugin.xml
new file mode 100644
index 0000000..cfadac6
--- /dev/null
+++ b/editor/eclipse/plugin.xml
@@ -0,0 +1,513 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+
+ <extension
+ id="lisaacProblem"
+ name="Lisaac Problem"
+ point="org.eclipse.core.resources.markers">
+ <persistent
+ value="true">
+ </persistent>
+ <super
+ type="org.eclipse.core.resources.problemmarker">
+ </super>
+ <super
+ type="org.eclipse.core.resources.textmarker">
+ </super>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ name="%editor.name.0"
+ extensions="li"
+ icon="$nl$/icons/prototype.gif"
+ contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
+ class="org.lisaac.ldt.editors.LisaacEditor"
+ id="org.lisaac.ldt.editors.LisaacEditor">
+ </editor>
+ <editor
+ class="org.lisaac.ldt.editors.LipEditor"
+ contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
+ default="false"
+ extensions="lip"
+ icon="$nl$/icons/releng_gears.gif"
+ id="org.lisaac.ldt.editors.LipEditor"
+ name="%editor.name.1">
+ </editor>
+ </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="%perspective.name.0"
+ class="org.lisaac.ldt.perspectives.LisaacPerspective"
+ id="org.lisaac.ldt.perspectives.LisaacPerspective">
+ <description>
+ %perspective.description.0
+ </description>
+ </perspective>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ name="%page.name.0"
+ class="org.lisaac.ldt.preferences.LisaacPreferencePage"
+ id="org.lisaac.ldt.preferences.LisaacPreferencePage">
+ </page>
+ <page
+ category="org.lisaac.ldt.editorpreferences"
+ class="org.lisaac.ldt.preferences.LisaacTemplatePage"
+ id="org.lisaac.ldt.templatepreferences"
+ name="%page.name.1">
+ </page>
+ <page
+ category="org.lisaac.ldt.editorpreferences"
+ class="org.lisaac.ldt.preferences.LisaacColoringPage"
+ id="org.lisaac.ldt.editorcolorpreferences"
+ name="%page.name.2">
+ </page>
+ <page
+ category="org.lisaac.ldt.preferences.LisaacPreferencePage"
+ class="org.lisaac.ldt.preferences.LisaacEditorPage"
+ id="org.lisaac.ldt.editorpreferences"
+ name="%page.name.3">
+ <keywordReference
+ id="org.eclipse.ui.editors.general">
+ </keywordReference>
+ </page>
+ </extension>
+ <extension
+ point="org.eclipse.core.runtime.preferences">
+ <initializer
+ class="org.lisaac.ldt.preferences.PreferenceInitializer">
+ </initializer>
+ </extension>
+ <extension
+ point="org.eclipse.ui.propertyPages">
+ <page
+ class="org.lisaac.ldt.properties.LisaacProjectPropertyPage"
+ id="org.lisaac.ldt.properties.projectPropertyPage"
+ name="%page.name.5"
+ objectClass="org.eclipse.core.resources.IProject">
+ </page>
+ </extension>
+ <extension
+ id="org.lisaac.ldt.newWizard"
+ name="Lisaac Project Wizard"
+ point="org.eclipse.ui.newWizards">
+ <category
+ id="Lisaac"
+ name="%category.name.0">
+ </category>
+ <wizard
+ canFinishEarly="true"
+ category="Lisaac"
+ class="org.lisaac.ldt.wizards.NewProjectWizard"
+ finalPerspective="org.lisaac.ldt.perspectives.LisaacPerspective"
+ hasPages="true"
+ icon="$nl$/icons/sample.gif"
+ id="org.lisaac.ldt.wizard"
+ name="%wizard.name.0"
+ preferredPerspectives="org.lisaac.ldt.perspectives.LisaacPerspective"
+ project="true">
+ </wizard>
+ <wizard
+ canFinishEarly="false"
+ category="Lisaac"
+ class="org.lisaac.ldt.wizards.NewPrototypeWizard"
+ finalPerspective="org.lisaac.ldt.perspectives.LisaacPerspective"
+ hasPages="true"
+ icon="$nl$/icons/prototype.gif"
+ id="org.lisaac.ldt.prototype"
+ name="%wizard.name.1"
+ preferredPerspectives="org.lisaac.ldt.perspectives.LisaacPerspective"
+ 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.lisaac.ldt.builder.LisaacBuilder">
+ </run>
+ </builder>
+ </extension>
+ <extension
+ id="lisaac"
+ name="Lisaac Nature"
+ point="org.eclipse.core.resources.natures">
+ <runtime>
+ <run
+ class="org.lisaac.ldt.builder.LisaacNature">
+ </run>
+ </runtime>
+ <builder
+ id="org.lisaac.ldt.builder">
+ </builder>
+ </extension>
+ <extension
+ point="org.eclipse.ui.console.consoleFactories">
+ <consoleFactory
+ class="org.lisaac.ldt.views.ConsoleFactory"
+ label="%consoleFactory.label.0">
+ </consoleFactory>
+ </extension>
+ <extension
+ point="org.eclipse.debug.core.launchConfigurationTypes">
+ <launchConfigurationType
+ delegate="org.lisaac.ldt.launch.LaunchConfiguration"
+ id="org.lisaac.ldt.launchConfiguration"
+ modes="run,debug"
+ name="%launchConfigurationType.name.0"
+ public="true">
+ </launchConfigurationType>
+ </extension>
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTabGroups">
+ <launchConfigurationTabGroup
+ class="org.lisaac.ldt.launch.LaunchConfigurationTabGroup"
+ id="org.lisaac.ldt.LaunchConfigurationTabGroup"
+ type="org.lisaac.ldt.launchConfiguration">
+ </launchConfigurationTabGroup>
+ </extension>
+ <extension
+ point="org.eclipse.ui.actionSets">
+ <actionSet
+ description="%actionSet.description.0"
+ id="org.lisaac.ldt.source"
+ label="%actionSet.label.0"
+ visible="true">
+ <menu
+ id="org.lisaac.ldt.sourcemenu"
+ label="%menu.label.0"
+ path="edit">
+ <groupMarker
+ name="toggle">
+ </groupMarker>
+ <separator
+ name="org.lisaac.ldt.separator1">
+ </separator>
+ <groupMarker
+ name="indent">
+ </groupMarker>
+ <separator
+ name="org.lisaac.ldt.separator2">
+ </separator>
+ <groupMarker
+ name="generate">
+ </groupMarker>
+ </menu>
+ <action
+ class="org.lisaac.ldt.actions.IndentAction"
+ definitionId="org.lisaac.ldt.cmd1"
+ id="org.lisaac.ldt.indentaction"
+ label="%action.label.0"
+ menubarPath="org.lisaac.ldt.sourcemenu/indent">
+ </action>
+ <action
+ class="org.lisaac.ldt.actions.GenerateConstructor"
+ definitionId="org.lisaac.ldt.cmd2"
+ id="org.lisaac.ldt.generateconstructor"
+ label="%action.label.1"
+ menubarPath="org.lisaac.ldt.sourcemenu/generate">
+ </action>
+ <menu
+ id="org.lisaac.ldt.toolbar"
+ label="%menu.label.1">
+ </menu>
+ <action
+ class="org.lisaac.ldt.actions.CreatePrototype"
+ definitionId="org.lisaac.ldt.cmd3"
+ icon="$nl$/icons/prototype.gif"
+ id="org.lisaac.ldt.toolbar_action1"
+ label="%action.label.2"
+ style="push"
+ toolbarPath="org.lisaac.ldt.toolbar"
+ tooltip="%action.tooltip.0">
+ </action>
+ <action
+ class="org.lisaac.ldt.actions.ToggleComment"
+ definitionId="org.lisaac.ldt.cmd4"
+ id="org.lisaac.ldt.comment1"
+ label="%action.label.3"
+ menubarPath="org.lisaac.ldt.sourcemenu/toggle">
+ </action>
+ <action
+ class="org.lisaac.ldt.actions.RenamePrototype"
+ definitionId="org.lisaac.ldt.cmd5"
+ enablesFor="1"
+ id="org.lisaac.ldt.action.refactor1"
+ label="%action.label.4"
+ menubarPath="org.lisaac.ldt.refactor.menu/renameproto"
+ style="push">
+ </action>
+ <menu
+ id="org.lisaac.ldt.refactor.menu"
+ label="%menu.label.2"
+ path="org.lisaac.ldt.sourcemenu">
+ </menu>
+ <action
+ class="org.lisaac.ldt.actions.ChangeHeader"
+ definitionId="org.lisaac.ldt.cmd6"
+ id="org.lisaac.ldt.action.refactor2"
+ label="Change Project Headers"
+ menubarPath="org.lisaac.ldt.refactor.menu/changeheader"
+ style="push">
+ </action>
+ </actionSet>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ categoryId="org.lisaac.ldt.commands"
+ id="org.lisaac.ldt.cmd1"
+ name="%command.name.0">
+ </command>
+ <category
+ id="org.lisaac.ldt.commands"
+ name="%category.name.1">
+ </category>
+ <command
+ categoryId="org.lisaac.ldt.commands"
+ id="org.lisaac.ldt.cmd2"
+ name="%command.name.1">
+ </command>
+ <command
+ categoryId="org.lisaac.ldt.commands"
+ id="org.lisaac.ldt.cmd3"
+ name="%command.name.2">
+ </command>
+ <command
+ categoryId="org.lisaac.ldt.commands"
+ id="org.lisaac.ldt.cmd4"
+ name="%command.name.3">
+ </command>
+ <command
+ categoryId="org.lisaac.ldt.commands"
+ id="org.lisaac.ldt.cmd5"
+ name="%command.name.4">
+ </command>
+ <command
+ categoryId="org.lisaac.ldt.commands"
+ id="org.lisaac.ldt.cmd6"
+ name="Change Header">
+ </command>
+ </extension>
+ <extension
+ point="org.eclipse.ui.bindings">
+ <key
+ commandId="org.lisaac.ldt.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.lisaac.ldt.cheatsheet"
+ name="Lisaac Development">
+ </category>
+ <cheatsheet
+ category="org.lisaac.ldt.cheatsheet"
+ composite="false"
+ contentFile="help/sheet1_HelloWorld.xml"
+ id="org.lisaac.ldt.cheatsheet1"
+ name="Lisaac HelloWorld">
+ <description>
+ Create a "Hello World" Lisaac application from scratch.
+ </description>
+ </cheatsheet>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors.templates">
+ <contextType
+ class="org.lisaac.ldt.templates.LisaacContextType"
+ id="org.lisaac.ldt.contexttype"
+ name="Lisaac context type">
+ </contextType>
+ <template
+ autoinsert="true"
+ contextTypeId="org.lisaac.ldt.contexttype"
+ description="%template.description.0"
+ icon="$nl$/icons/template.gif"
+ id="org.lisaac.ldt.template_whiledo"
+ name="while_do">
+ <pattern>
+ while_do {
+ ${cursor}
+};
+ </pattern>
+ </template>
+ <template
+ autoinsert="true"
+ contextTypeId="org.lisaac.ldt.contexttype"
+ description="%template.description.1"
+ icon="$nl$/icons/template.gif"
+ id="org.lisaac.ldt.template_untildo"
+ name="until_do">
+ <pattern>
+ until_do {
+ ${cursor}
+};
+ </pattern>
+ </template>
+ <template
+ autoinsert="true"
+ contextTypeId="org.lisaac.ldt.contexttype"
+ description="%template.description.2"
+ icon="$nl$/icons/template.gif"
+ id="org.lisaac.ldt.template_if"
+ name="if">
+ <pattern>
+ if {
+ ${cursor}
+};
+ </pattern>
+ </template>
+ <template
+ autoinsert="true"
+ contextTypeId="org.lisaac.ldt.contexttype"
+ description="%template.description.3"
+ icon="$nl$/icons/template.gif"
+ id="org.lisaac.ldt.template_ifelse"
+ name="if__else">
+ <pattern>
+ if {
+ ${cursor}
+} else {
+};
+ </pattern>
+ </template>
+ <template
+ autoinsert="true"
+ contextTypeId="org.lisaac.ldt.contexttype"
+ description="%template.description.4"
+ icon="$nl$/icons/template.gif"
+ id="org.lisaac.ldt.template_iffalse"
+ name="if_false">
+ <pattern>
+ if_false {
+ ${cursor}
+};
+ </pattern>
+ </template>
+ <template
+ autoinsert="true"
+ contextTypeId="org.lisaac.ldt.contexttype"
+ description="%template.description.5"
+ icon="$nl$/icons/template.gif"
+ id="org.lisaac.ldt.template_for"
+ name="to__do">
+ <pattern>
+ to ${cursor} do { i:INTEGER;
+};
+ </pattern>
+ </template>
+ </extension>
+ <extension
+ point="org.eclipse.debug.ui.launchShortcuts">
+ <shortcut
+ class="org.lisaac.ldt.launch.LisaacApplicationShortcut"
+ icon="$nl$/icons/prototype.gif"
+ id="org.lisaac.ldt.launch.shortcut"
+ label="%shortcut.label.0"
+ modes="run,debug">
+ <perspective
+ id="org.lisaac.ldt.perspectives.LisaacPerspective">
+ </perspective>
+ <contextualLaunch>
+ <enablement>
+ <with variable="selection">
+ <count value="1"/>
+ <iterate>
+ <or><test property="org.eclipse.debug.ui.matchesPattern" value="*.li"/></or>
+ </iterate>
+ </with>
+ </enablement>
+ </contextualLaunch>
+ </shortcut>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors.annotationTypes">
+ <type
+ markerSeverity="2"
+ markerType="org.lisaac.ldt.lisaacProblem"
+ name="org.lisaac.ldt.annotationtype"
+ super="org.eclipse.ui.workbench.texteditor.error">
+ </type>
+ </extension>
+ <extension
+ point="org.eclipse.ui.decorators">
+ <decorator
+ class="org.lisaac.ldt.editors.LisaacResourceDecorator"
+ id="org.lisaac.ldt.decorator"
+ label="%decorator.label.0"
+ lightweight="true"
+ location="BOTTOM_LEFT"
+ state="true">
+ <enablement>
+ <objectClass
+ name="org.eclipse.core.resources.IResource">
+ </objectClass>
+ </enablement>
+ </decorator>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors.markerAnnotationSpecification">
+ <specification
+ annotationType="org.lisaac.ldt.annotationtype"
+ colorPreferenceKey="errorIndicationColor"
+ colorPreferenceValue="255,0,128"
+ contributesToHeader="true"
+ highlightPreferenceKey="errorIndicationHighlighting"
+ highlightPreferenceValue="false"
+ includeOnPreferencePage="true"
+ isGoToNextNavigationTarget="true"
+ isGoToNextNavigationTargetKey="isErrorGoToNextNavigationTarget"
+ isGoToPreviousNavigationTarget="true"
+ isGoToPreviousNavigationTargetKey="isErrorGoToPreviousNavigationTarget"
+ label="Lisaac Problem"
+ overviewRulerPreferenceKey="errorIndicationInOverviewRuler"
+ overviewRulerPreferenceValue="true"
+ presentationLayer="6"
+ showInNextPrevDropdownToolbarAction="true"
+ showInNextPrevDropdownToolbarActionKey="showErrorInNextPrevDropdownToolbarAction"
+ symbolicIcon="error"
+ textPreferenceKey="errorIndication"
+ textPreferenceValue="true"
+ textStylePreferenceKey="errorTextStyle"
+ textStylePreferenceValue="PROBLEM_UNDERLINE"
+ verticalRulerPreferenceKey="errorIndicationInVerticalRuler"
+ verticalRulerPreferenceValue="true">
+ </specification>
+ </extension>
+ <extension
+ point="org.eclipse.ui.popupMenus">
+ <viewerContribution
+ id="org.lisaac.ldt.editoraction"
+ targetID="#TextEditorContext">
+ <action
+ class="org.lisaac.ldt.actions.RefreshEditor"
+ id="org.lisaac.ldt.editoraction1"
+ label="Refresh Editor">
+ </action>
+ </viewerContribution>
+ </extension>
+
+</plugin>
diff --git a/editor/eclipse/src/org/lisaac/ldt/LisaacMessages.java b/editor/eclipse/src/org/lisaac/ldt/LisaacMessages.java
new file mode 100644
index 0000000..928e1dc
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/LisaacMessages.java
@@ -0,0 +1,22 @@
+package org.lisaac.ldt;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class LisaacMessages {
+ private static final String BUNDLE_NAME = "org.lisaac.ldt.messages"; //$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ private LisaacMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/LisaacPlugin.java b/editor/eclipse/src/org/lisaac/ldt/LisaacPlugin.java
new file mode 100644
index 0000000..06acca3
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/LisaacPlugin.java
@@ -0,0 +1,153 @@
+package org.lisaac.ldt;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ISaveContext;
+import org.eclipse.core.resources.ISaveParticipant;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+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.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
+import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.lisaac.ldt.builder.LisaacChangeListener;
+import org.lisaac.ldt.builder.LisaacNature;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.templates.LisaacContextType;
+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.lisaac.ldt"; //$NON-NLS-1$
+
+ // The shared instance
+ private static LisaacPlugin plugin;
+
+
+ /** The template store. */
+ private TemplateStore fStore;
+ /** The context type registry. */
+ private ContextTypeRegistry fRegistry;
+
+
+ private static final String TEMPLATES_KEY = "org.lisaac.ldt.templatepreferences"; //$NON-NLS-1$
+
+
+ public TemplateStore getTemplateStore() {
+ if (fStore == null) {
+ fStore = new ContributionTemplateStore (
+ getContextTypeRegistry(), LisaacPlugin
+ .getDefault().getPreferenceStore(),
+ TEMPLATES_KEY);
+ try {
+ fStore.load();
+ } catch (IOException e) {
+ LisaacPlugin
+ .getDefault()
+ .getLog()
+ .log(
+ new Status(
+ IStatus.ERROR,
+ PLUGIN_ID, IStatus.OK, "", e)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ return fStore;
+ }
+
+ public ContextTypeRegistry getContextTypeRegistry() {
+ if (fRegistry == null) {
+ // create an configure the contexts available in the template editor
+ ContributionContextTypeRegistry registry= new ContributionContextTypeRegistry();
+ registry.addContextType(LisaacContextType.ID_CONTEXT_TYPE);
+
+ fRegistry= registry;
+ }
+ return fRegistry;
+ }
+
+ /**
+ * 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;
+
+ // to notify project modifications
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(new LisaacChangeListener());
+
+ // build all lisaac projects
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ for (int i=0; i<projects.length; i++) {
+ try {
+ if (projects[i] != null && projects[i].isOpen()) {
+ if (projects[i].getNature(LisaacNature.NATURE_ID) != null) {
+ try {
+ // clean all lisaac projects to get started
+ projects[i].build(IncrementalProjectBuilder.FULL_BUILD, null);
+
+ } catch (Exception e) {
+ log(new Status(IStatus.ERROR,
+ PLUGIN_ID, IStatus.OK, "Error loading "+projects[i].getName(), e)); //$NON-NLS-1$
+ }
+ }
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ /*
+ * (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/editor/eclipse/src/org/lisaac/ldt/actions/ChangeHeader.java b/editor/eclipse/src/org/lisaac/ldt/actions/ChangeHeader.java
new file mode 100644
index 0000000..05296ef
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/actions/ChangeHeader.java
@@ -0,0 +1,74 @@
+package org.lisaac.ldt.actions;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.lisaac.ldt.editors.AbstractLisaacEditor;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.refactor.ChangeHeaderRefactor;
+import org.lisaac.ldt.refactor.ChangeHeaderWizard;
+
+public class ChangeHeader implements IWorkbenchWindowActionDelegate {
+
+ private IWorkbenchWindow fWindow = null;
+
+ private LisaacModel model;
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ fWindow = window;
+ }
+
+ public void run(IAction action) {
+ if (fWindow != null&& model != null) {
+ ChangeHeaderRefactor refactoring = new ChangeHeaderRefactor(model);
+ String name = "Change Project Headers";
+ run(new ChangeHeaderWizard(refactoring, name),
+ fWindow.getShell(), name);
+ }
+ }
+
+ public void run(RefactoringWizard wizard, Shell parent, String dialogTitle) {
+ try {
+ RefactoringWizardOpenOperation operation = new RefactoringWizardOpenOperation(wizard);
+ operation.run(parent, dialogTitle);
+ } catch (InterruptedException exception) {
+ // Do nothing
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ model = null;
+
+ if (selection instanceof ITextSelection) {
+ if (fWindow != null) {
+ // get surrounding word
+ IWorkbenchPart part = fWindow.getPartService().getActivePart();
+ if (part instanceof AbstractLisaacEditor) {
+ IProject project = ((AbstractLisaacEditor) part)
+ .getProject();
+ model = LisaacModel.getModel(project);
+ }
+ }
+ } else if (selection instanceof IStructuredSelection) {
+ if (((IStructuredSelection) selection).getFirstElement() instanceof IResource) {
+ IResource res = (IResource) ((IStructuredSelection) selection).getFirstElement();
+ if (res.getProject() != null) {
+ model = LisaacModel.getModel(res.getProject());
+ }
+ }
+ }
+ action.setEnabled(model != null);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/actions/CreatePrototype.java b/editor/eclipse/src/org/lisaac/ldt/actions/CreatePrototype.java
new file mode 100644
index 0000000..eb7b5f2
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/actions/CreatePrototype.java
@@ -0,0 +1,110 @@
+package org.lisaac.ldt.actions;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.eclipse.ui.PlatformUI;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.wizards.NewPrototypeWizard;
+
+public class CreatePrototype extends Action implements IWorkbenchWindowActionDelegate {
+
+ private Shell fShell;
+ private IStructuredSelection fSelection;
+
+
+ public CreatePrototype() {
+ }
+
+ /**
+ * 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) {
+ Shell shell= getShell();
+
+ try {
+ INewWizard wizard= createWizard();
+ wizard.init(PlatformUI.getWorkbench(), getSelection());
+
+ WizardDialog dialog= new WizardDialog(shell, wizard);
+ dialog.create();
+ int res= dialog.open();
+ if (res != Window.OK) {
+ // TODO log error
+ }
+ } catch (CoreException e) {
+ // TODO log error
+ }
+ }
+
+ /**
+ * Returns the configured selection. If no selection has been configured using {@link #setSelection(IStructuredSelection)},
+ * the currently selected element of the active workbench is returned.
+ * @return the configured selection
+ */
+ protected IStructuredSelection getSelection() {
+ if (fSelection == null) {
+ return evaluateCurrentSelection();
+ }
+ return fSelection;
+ }
+
+ private IStructuredSelection evaluateCurrentSelection() {
+ IWorkbenchWindow window = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+
+ if (window != null) {
+ ISelection selection= window.getSelectionService().getSelection();
+ if (selection instanceof IStructuredSelection) {
+ return (IStructuredSelection) selection;
+ }
+ }
+ return StructuredSelection.EMPTY;
+ }
+
+ protected Shell getShell() {
+ return fShell;
+ }
+
+ // make it an abstract method if more wizard shortcuts are created
+ protected final INewWizard createWizard() throws CoreException {
+ return new NewPrototypeWizard();
+ }
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose() {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/actions/GenerateConstructor.java b/editor/eclipse/src/org/lisaac/ldt/actions/GenerateConstructor.java
new file mode 100644
index 0000000..207ba42
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/actions/GenerateConstructor.java
@@ -0,0 +1,80 @@
+package org.lisaac.ldt.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.editors.LisaacEditor;
+
+public class GenerateConstructor implements IWorkbenchWindowActionDelegate {
+
+
+ /**
+ * 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();
+ //
+ int caret = ((LisaacEditor)part).getViewer().getTextWidget().getCaretOffset();
+ String constructor = getConstructor();
+ try {
+ document.replace(caret, 0, constructor);
+ } catch (BadLocationException e) {
+ }
+ //
+ }
+ }
+
+ public static String getConstructor() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("\n //\n // Creation.\n //\n"); //$NON-NLS-1$
+ buffer.append("\n - create:SELF <-"); //$NON-NLS-1$
+ buffer.append("\n ( + result:SELF;"); //$NON-NLS-1$
+ buffer.append("\n result := clone;"); //$NON-NLS-1$
+ buffer.append("\n result.make;"); //$NON-NLS-1$
+ buffer.append("\n result"); //$NON-NLS-1$
+ buffer.append("\n );"); //$NON-NLS-1$
+ buffer.append("\n"); //$NON-NLS-1$
+ buffer.append("\n - make <-"); //$NON-NLS-1$
+ buffer.append("\n ("); //$NON-NLS-1$
+ buffer.append("\n );\n\n"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose() {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/actions/IndentAction.java b/editor/eclipse/src/org/lisaac/ldt/actions/IndentAction.java
new file mode 100644
index 0000000..96a09e0
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/actions/IndentAction.java
@@ -0,0 +1,79 @@
+package org.lisaac.ldt.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.editors.AbstractLisaacEditor;
+import org.lisaac.ldt.editors.LisaacAutoEditStrategy;
+
+/**
+ * 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 AbstractLisaacEditor) {
+ IDocument document = ((AbstractLisaacEditor)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 AbstractLisaacEditor) {
+ 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/editor/eclipse/src/org/lisaac/ldt/actions/RefreshEditor.java b/editor/eclipse/src/org/lisaac/ldt/actions/RefreshEditor.java
new file mode 100644
index 0000000..7bf43a3
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/actions/RefreshEditor.java
@@ -0,0 +1,28 @@
+package org.lisaac.ldt.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.lisaac.ldt.editors.AbstractLisaacEditor;
+import org.lisaac.ldt.model.LisaacModel;
+
+public class RefreshEditor implements IEditorActionDelegate {
+
+ AbstractLisaacEditor targetEditor;
+
+ public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+ if (targetEditor instanceof AbstractLisaacEditor) {
+ this.targetEditor = (AbstractLisaacEditor) targetEditor;
+ } else {
+ this.targetEditor = null;
+ }
+ LisaacModel.currentEditor = this.targetEditor;
+ }
+
+ public void run(IAction action) {
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/actions/RenamePrototype.java b/editor/eclipse/src/org/lisaac/ldt/actions/RenamePrototype.java
new file mode 100644
index 0000000..854c08a
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/actions/RenamePrototype.java
@@ -0,0 +1,114 @@
+package org.lisaac.ldt.actions;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.editors.AbstractLisaacEditor;
+import org.lisaac.ldt.editors.LisaacScanner;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.refactor.RenamePrototypeRefactor;
+import org.lisaac.ldt.refactor.RenamePrototypeWizard;
+
+public class RenamePrototype implements IWorkbenchWindowActionDelegate {
+
+ private String prototypeName;
+
+ private LisaacModel model;
+
+ private IWorkbenchWindow fWindow = null;
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ fWindow = window;
+ }
+
+ public void run(IAction action) {
+ if (fWindow != null && prototypeName != null && model != null) {
+ RenamePrototypeRefactor refactoring = new RenamePrototypeRefactor(
+ prototypeName, model);
+ String name = LisaacMessages.getString("RenamePrototype.0"); //$NON-NLS-1$
+ run(new RenamePrototypeWizard(refactoring, prototypeName, name),
+ fWindow.getShell(), name);
+ }
+ }
+
+ public void run(RefactoringWizard wizard, Shell parent, String dialogTitle) {
+ try {
+ RefactoringWizardOpenOperation operation = new RefactoringWizardOpenOperation(
+ wizard);
+ operation.run(parent, dialogTitle);
+ } catch (InterruptedException exception) {
+ // Do nothing
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ prototypeName = null;
+
+ if (selection instanceof ITextSelection) {
+ String text = ((ITextSelection) selection).getText();
+ if (/* text.length() == 0 && */fWindow != null) {
+ // get surrounding word
+ IWorkbenchPart part = fWindow.getPartService().getActivePart();
+ if (part instanceof AbstractLisaacEditor) {
+ IDocument document = ((AbstractLisaacEditor) part)
+ .getDocument();
+ IProject project = ((AbstractLisaacEditor) part)
+ .getProject();
+ model = LisaacModel.getModel(project);
+
+ try {
+ text = selectWord(document,
+ ((ITextSelection) selection).getOffset());
+ } catch (BadLocationException e) {
+ action.setEnabled(false);
+ return;
+ }
+ }
+ }
+ if (LisaacScanner.isPrototypeIdentifier(text)) {
+ prototypeName = text;
+ }
+ }
+ action.setEnabled(prototypeName != null);
+ }
+
+ protected String 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 doc.get(startPos, endPos - startPos);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/actions/ToggleComment.java b/editor/eclipse/src/org/lisaac/ldt/actions/ToggleComment.java
new file mode 100644
index 0000000..f815259
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/actions/ToggleComment.java
@@ -0,0 +1,128 @@
+package org.lisaac.ldt.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.editors.AbstractLisaacEditor;
+
+public class ToggleComment implements IWorkbenchWindowActionDelegate {
+
+ /**
+ * 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 AbstractLisaacEditor) {
+ IDocument document = ((AbstractLisaacEditor)part).getDocument();
+ //
+ ITextSelection selection = (ITextSelection) ((AbstractLisaacEditor)part).getSelectionProvider().getSelection();
+
+ try {
+ if (selection.getStartLine() == selection.getEndLine()) {
+ // single line comment
+
+ int startPos = document.getLineOffset(selection.getStartLine());
+ int pos = startPos;
+ char c;
+ do {
+ c = document.getChar(pos);
+ if (c != ICharacterScanner.EOF) {
+ if (c == '/') {
+ pos++;
+ c = document.getChar(pos);
+ if (c != ICharacterScanner.EOF && c == '/') {
+ document.replace(pos-1, 2, "");// delete comment //$NON-NLS-1$
+ return;
+ }
+ }
+ }
+ pos++;
+ } while (c != ICharacterScanner.EOF && pos <= startPos+selection.getLength());
+
+ // add comment
+ document.replace(startPos, 0, "//"); //$NON-NLS-1$
+
+ } else {
+ // multiline comment
+ int startPos = document.getLineOffset(selection.getStartLine());
+ int pos = startPos;
+ boolean deleteComment=false;
+ char c;
+ do {
+ c = document.getChar(pos);
+ if (c != ICharacterScanner.EOF) {
+ if (c == '/') {
+ pos++;
+ c = document.getChar(pos);
+ if (c != ICharacterScanner.EOF && c == '*') {
+ document.replace(pos-1, 2, "");// delete comment //$NON-NLS-1$
+ deleteComment = true;
+ pos++;
+ }
+ }
+ if (c == '*') {
+ pos++;
+ c = document.getChar(pos);
+ if (c != ICharacterScanner.EOF && c == '/') {
+ if (deleteComment) {
+ document.replace(pos-1, 2, "");// delete comment //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ pos++;
+ } while (c != ICharacterScanner.EOF && pos <= startPos+selection.getLength());
+
+ // add comment
+ if (! deleteComment) {
+ document.replace(startPos, 0, "/*"); //$NON-NLS-1$
+ int ofs = document.getLineOffset(selection.getEndLine());
+ ofs += document.getLineLength(selection.getEndLine());
+ document.replace(ofs, 0, "*/"); //$NON-NLS-1$
+ }
+ }
+
+ } catch(BadLocationException e) {
+ }
+ //
+ }
+ }
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose() {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/builder/ILisaacErrorHandler.java b/editor/eclipse/src/org/lisaac/ldt/builder/ILisaacErrorHandler.java
new file mode 100644
index 0000000..9e43856
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/builder/ILisaacErrorHandler.java
@@ -0,0 +1,14 @@
+package org.lisaac.ldt.builder;
+
+import org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/builder/LisaacBuilder.java b/editor/eclipse/src/org/lisaac/ldt/builder/LisaacBuilder.java
new file mode 100644
index 0000000..e79b445
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/builder/LisaacBuilder.java
@@ -0,0 +1,236 @@
+package org.lisaac.ldt.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.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.Position;
+
+public class LisaacBuilder extends IncrementalProjectBuilder {
+
+ private LisaacModel model;
+
+
+ class LisaacDeltaVisitor implements IResourceDeltaVisitor {
+
+ IProgressMonitor monitor;
+
+ LisaacDeltaVisitor(IProgressMonitor monitor) {
+ this.monitor = monitor;
+ }
+
+ public boolean visit(IResourceDelta delta) throws CoreException {
+ IResource resource = delta.getResource();
+ switch (delta.getKind()) {
+ case IResourceDelta.ADDED:
+ // handle added resource
+ buildLisaacFile(resource, monitor);
+ break;
+ case IResourceDelta.REMOVED:
+ // handle removed resource
+ removeLisaacFile(resource);
+ break;
+ case IResourceDelta.CHANGED:
+ // handle changed resource
+ buildLisaacFile(resource, monitor);
+ break;
+ }
+ //return true to continue visiting children.
+ return true;
+ }
+ }
+
+ class LisaacResourceVisitor implements IResourceVisitor {
+ IProgressMonitor monitor;
+
+ LisaacResourceVisitor(IProgressMonitor monitor) {
+ this.monitor = monitor;
+ }
+ public boolean visit(IResource resource) {
+ buildLisaacFile(resource, monitor);
+ //return true to continue visiting children.
+ return true;
+ }
+ }
+
+ class LisaacErrorHandler implements ILisaacErrorHandler {
+
+ private IFile file;
+
+ public LisaacErrorHandler(IFile file) {
+ this.file = file;
+ }
+
+ public void syntaxError(String msg, Position position) {
+ addMarker(file, msg, position, IMarker.SEVERITY_ERROR);
+ }
+
+ public void semanticError(String msg, Position position) {
+ addMarker(file, msg, position, IMarker.SEVERITY_ERROR);
+ }
+
+ public void fatalError(String msg, Position position) {
+ addMarker(file, msg, position, IMarker.SEVERITY_ERROR);
+ }
+
+ public void warning(String msg, Position position) {
+ addMarker(file, msg, position, IMarker.SEVERITY_WARNING);
+ }
+ }
+
+ public static final String BUILDER_ID = "org.lisaac.ldt.builder"; //$NON-NLS-1$
+
+ private static final String MARKER_TYPE = "org.lisaac.ldt.lisaacProblem"; //$NON-NLS-1$
+
+
+ public static void addMarker(IFile file, String msg, Position position, int severity) {
+ IMarker marker = LisaacBuilder.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 static 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 {
+
+ IProject project = getProject();
+ model = LisaacModel.getModel(project);
+ if (model == null) {
+ // create lisaac model
+ model = new LisaacModel(project);
+
+ }
+
+ monitor.beginTask(LisaacMessages.getString("LisaacBuilder.2"), 100); //$NON-NLS-1$
+
+ model.refreshPresentation();
+ monitor.worked(1);
+
+ if (kind == CLEAN_BUILD) {
+ model.refreshPath();
+ monitor.worked(10);
+ }
+
+ 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, IProgressMonitor monitor) {
+ if (resource instanceof IFile) {
+ IFile file = (IFile) resource;
+
+ if (file.isHidden()) {
+ return;
+ }
+
+ //System.out.println("VISITING => "+file.getName());
+
+ if (resource.getName().endsWith(".li")) { //$NON-NLS-1$
+ deleteMarkers(file);
+ try {
+ LisaacErrorHandler reporter = new LisaacErrorHandler(file);
+ model.parsePrototype(file, file.getContents(), reporter);
+ } catch (Exception e) {
+ }
+ } else if (resource.getName().endsWith(".lip")) { //$NON-NLS-1$
+ deleteMarkers(file);
+ try {
+ LisaacErrorHandler reporter = new LisaacErrorHandler(file);
+ model.parseLip(file.getName(), file.getContents(), reporter);
+ } catch (Exception e) {
+ }
+ }
+ monitor.worked(1);
+ }
+ }
+
+ private void removeLisaacFile(IResource resource) {
+ if (resource instanceof IFile) {
+ IFile file = (IFile) resource;
+ if (resource.getName().endsWith(".li")) { //$NON-NLS-1$
+ deleteMarkers(file);
+ try {
+ model.removePrototype(file);
+ } catch (Exception e) {
+ }
+ } else if (resource.getName().endsWith(".lip")) { //$NON-NLS-1$
+ deleteMarkers(file);
+ try {
+ model.removeLip(file);
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ public static 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(monitor));
+ monitor.done();
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ protected void incrementalBuild(IResourceDelta delta,
+ IProgressMonitor monitor) throws CoreException {
+ // the visitor does the work.
+ delta.accept(new LisaacDeltaVisitor(monitor));
+ monitor.done();
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/builder/LisaacChangeListener.java b/editor/eclipse/src/org/lisaac/ldt/builder/LisaacChangeListener.java
new file mode 100644
index 0000000..ddb9125
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/builder/LisaacChangeListener.java
@@ -0,0 +1,32 @@
+package org.lisaac.ldt.builder;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.lisaac.ldt.model.LisaacModel;
+
+public class LisaacChangeListener implements IResourceChangeListener {
+
+ public void resourceChanged(IResourceChangeEvent event) {
+ IResourceDelta delta = event.getDelta();
+
+ IResource resource = delta.getResource();
+ if (resource != null) {
+ if (resource instanceof IWorkspaceRoot) {
+ delta = (IResourceDelta) (delta.getAffectedChildren())[0];// TODO go deeper in the delta
+ resource = delta.getResource();
+ }
+ if (resource != null) {
+ IProject project = (IProject) resource.getProject();
+ LisaacModel model = LisaacModel.getModel(project);
+
+ if (model != null) {
+ model.setCompiled(false);
+ }
+ }
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/builder/LisaacNature.java b/editor/eclipse/src/org/lisaac/ldt/builder/LisaacNature.java
new file mode 100644
index 0000000..5b1faa9
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/builder/LisaacNature.java
@@ -0,0 +1,80 @@
+package org.lisaac.ldt.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.lisaac.ldt.lisaac"; //$NON-NLS-1$
+
+ 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/editor/eclipse/src/org/lisaac/ldt/builder/LisaacParseException.java b/editor/eclipse/src/org/lisaac/ldt/builder/LisaacParseException.java
new file mode 100644
index 0000000..ab7c99e
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/builder/LisaacParseException.java
@@ -0,0 +1,14 @@
+package org.lisaac.ldt.builder;
+
+public class LisaacParseException extends Exception {
+
+ int line;
+
+ LisaacParseException(String msg, int line) {
+ super(msg);
+ }
+
+ public int getLineNumber() {
+ return line;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/AbstractLisaacEditor.java b/editor/eclipse/src/org/lisaac/ldt/editors/AbstractLisaacEditor.java
new file mode 100644
index 0000000..b37056e
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/AbstractLisaacEditor.java
@@ -0,0 +1,269 @@
+package org.lisaac.ldt.editors;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+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.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewerExtension2;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
+import org.eclipse.jface.text.source.projection.ProjectionSupport;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.preferences.PreferenceConstants;
+import org.lisaac.ldt.views.LisaacOutlineView;
+
+/**
+ * Main class for the Lisaac editor
+ * @author Damien Bouvarel
+ */
+public class AbstractLisaacEditor extends TextEditor {
+
+ private ColorManager colorManager;
+
+ /** the outline view. */
+ private LisaacOutlineView outlineView;
+
+ private ProjectionSupport projectionSupport;
+
+
+ public AbstractLisaacEditor() {
+ super();
+ colorManager = new ColorManager(LisaacPlugin.getDefault().getPreferenceStore());
+
+ setSourceViewerConfiguration(new LisaacConfiguration(colorManager,this));
+ setDocumentProvider(new LisaacDocumentProvider());
+
+ IPreferenceStore store = LisaacPlugin.getDefault().getPreferenceStore();
+
+ // wide caret
+ store.setDefault(PREFERENCE_USE_CUSTOM_CARETS, true);
+ store.setDefault(PREFERENCE_WIDE_CARET, true);
+
+ store = getChainedPreferenceStore();
+ setPreferenceStore(store);
+ }
+
+ /**
+ * Returns the preference store to be used by this editor.
+ * @return the preference store to be used by this editor
+ */
+ private IPreferenceStore getChainedPreferenceStore() {
+ List<IPreferenceStore> stores = new ArrayList<IPreferenceStore>();
+
+ stores.add(LisaacPlugin.getDefault().getPreferenceStore());
+ stores.add(EditorsUI.getPreferenceStore());
+
+ return new ChainedPreferenceStore(stores.toArray(new IPreferenceStore[0]));
+ }
+
+ public void createPartControl(Composite parent) {
+ super.createPartControl(parent);
+
+ ProjectionViewer viewer =(ProjectionViewer)getSourceViewer();
+
+ projectionSupport = new ProjectionSupport(viewer,getAnnotationAccess(),getSharedColors());
+ projectionSupport.install();
+
+ //turn projection mode on
+ viewer.doOperation(ProjectionViewer.TOGGLE);
+
+ annotationModel = viewer.getProjectionAnnotationModel();
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, int)
+ */
+ protected ISourceViewer createSourceViewer(Composite parent,
+ IVerticalRuler ruler, int styles) {
+ ISourceViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles);
+
+ // ensure decoration support has been created and configured.
+ getSourceViewerDecorationSupport(viewer);
+
+ return viewer;
+ }
+
+ private Annotation[] oldAnnotations;
+ private ProjectionAnnotationModel annotationModel;
+
+ public void updateFoldingStructure(ArrayList positions) {
+
+ if (annotationModel == null) {
+ return;
+ }
+
+ Annotation[] annotations = new Annotation[positions.size()];
+
+ //this will hold the new annotations along
+ //with their corresponding positions
+ HashMap newAnnotations = new HashMap();
+
+ for(int i =0;i<positions.size();i++)
+ {
+ ProjectionAnnotation annotation = new ProjectionAnnotation();
+ newAnnotations.put(annotation,positions.get(i));
+ annotations[i] = annotation;
+ }
+ annotationModel.modifyAnnotations(oldAnnotations,newAnnotations,null);
+ oldAnnotations=annotations;
+ }
+
+ public void removeFoldingStructure() {
+ annotationModel.removeAllAnnotations();
+ }
+
+ public IDocument getDocument() {
+ if (getDocumentProvider() == null) {
+ return null;
+ }
+ 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); //$NON-NLS-1$
+ markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
+ }
+
+ public void doSave(IProgressMonitor progressMonitor) {
+ super.doSave(progressMonitor);
+
+ /*LisaacModel model = LisaacModel.getModel(getProject());
+ if (model != null) {
+ model.incrementalBuild();
+ }*/
+ }
+
+ public ISourceViewer getViewer() {
+ return getSourceViewer();
+ }
+
+ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+ colorManager.handlePreferenceStoreChanged(event);
+ super.handlePreferenceStoreChanged(event);
+
+ String prop = event.getProperty();
+ if (prop.equals(PreferenceConstants.P_LISAAC_COMPLETION_DELAY)) {
+ IContentAssistant assistant = getSourceViewerConfiguration().getContentAssistant(getSourceViewer());
+
+ Integer delay;
+ try {
+ delay = Integer.valueOf(((String)event.getNewValue()));
+ } catch (Exception e) {
+ delay = 500;
+ }
+ ((ContentAssistant) assistant).setAutoActivationDelay(delay);
+ }
+ }
+
+ protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+ return super.affectsTextPresentation(event)
+ || colorManager.affectsTextPresentation(event);
+ }
+
+
+ /**
+ * Redraw whole text presentation of the editor
+ */
+ public void refreshPresentation() {
+ IDocument document = getDocument();
+ if (document != null) {
+ refreshPresentation(0, document.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/editor/eclipse/src/org/lisaac/ldt/editors/ColorManager.java b/editor/eclipse/src/org/lisaac/ldt/editors/ColorManager.java
new file mode 100644
index 0000000..cef19a8
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/ColorManager.java
@@ -0,0 +1,126 @@
+package org.lisaac.ldt.editors;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.StringConverter;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.swt.SWT;
+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);
+ private Map<String,IToken> tokenTable = new HashMap<String,IToken>(10);
+ private Map<String,String> styleTable = new HashMap<String,String>(10);
+
+ private final IPreferenceStore preferenceStore;
+
+ public ColorManager(IPreferenceStore preferenceStore) {
+ this.preferenceStore = preferenceStore;
+ }
+
+ 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;
+ }
+
+ public IToken getToken(String prefKey, String styleKey) {
+ Token token = (Token) tokenTable.get(prefKey);
+ int style = convertToStyle(styleKey);
+
+ if (token == null) {
+ String colorName = preferenceStore.getString(prefKey);
+ RGB rgb = StringConverter.asRGB(colorName);
+
+ token = new Token(new TextAttribute(getColor(rgb), null, style));
+ tokenTable.put(prefKey, token);
+ styleTable.put(styleKey, prefKey);
+ } else {
+ TextAttribute attrib = (TextAttribute) token.getData();
+ if (attrib.getStyle() != style) {
+ token = new Token(new TextAttribute(attrib.getForeground(), null, style));
+ tokenTable.put(prefKey, token);
+ }
+ }
+ return token;
+ }
+
+ public IToken getToken2(String prefKey, String prefKey2) {
+ Token token = (Token) tokenTable.get(prefKey);
+ if (token == null) {
+ String colorName = preferenceStore.getString(prefKey);
+ RGB rgb = StringConverter.asRGB(colorName);
+ String colorName2 = preferenceStore.getString(prefKey2);
+ RGB rgb2 = StringConverter.asRGB(colorName2);
+ token = new Token(new TextAttribute(getColor(rgb2), getColor(rgb), SWT.NORMAL));
+ tokenTable.put(prefKey, token);
+ }
+ return token;
+ }
+
+ public boolean affectsTextPresentation(PropertyChangeEvent event) {
+ Token token = (Token) tokenTable.get(event.getProperty());
+ return (token != null) || styleTable.get(event.getProperty()) != null;
+ }
+
+ public void handlePreferenceStoreChanged (PropertyChangeEvent event) {
+ String prefKey = event.getProperty();
+ Token token = (Token) tokenTable.get(prefKey);
+ if (token != null) {
+ String colorName = preferenceStore.getString(prefKey);
+ RGB rgb = StringConverter.asRGB(colorName);
+
+ if (prefKey.equals(ILisaacColor.PREF_EXTERNAL)) {
+ String colorName2 = preferenceStore.getString(ILisaacColor.PREF_LOCAL_SLOT);
+ RGB rgb2 = StringConverter.asRGB(colorName2);
+ token.setData(new TextAttribute(getColor(rgb2), getColor(rgb), SWT.NORMAL));
+ } else {
+ token.setData(new TextAttribute(getColor(rgb)));
+ }
+ } else { // update style
+ String key = (String) styleTable.get(prefKey);
+ if (key != null) {
+ token = (Token) tokenTable.get(key);
+ if (token != null) {
+ int style = convertToStyle(prefKey);
+ TextAttribute attrib = (TextAttribute) token.getData();
+ token.setData(new TextAttribute(attrib.getForeground(), null, style));
+ }
+ }
+ }
+ }
+
+ public int convertToStyle(String prefKey) {
+ String pref = preferenceStore.getString(prefKey);
+ if (pref.equals(ILisaacColor.PREF_NORMAL)) {
+ return SWT.NORMAL;
+ }
+ if (pref.equals(ILisaacColor.PREF_BOLD)) {
+ return SWT.BOLD;
+ }
+ if (pref.equals(ILisaacColor.PREF_ITALICS)) {
+ return SWT.ITALIC;
+ }
+ if (pref.equals(ILisaacColor.PREF_UNDERLINE)) {
+ return TextAttribute.UNDERLINE;
+ }
+ return SWT.NORMAL;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/HoverPresenter.java b/editor/eclipse/src/org/lisaac/ldt/editors/HoverPresenter.java
new file mode 100644
index 0000000..d30d9aa
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/HoverPresenter.java
@@ -0,0 +1,136 @@
+package org.lisaac.ldt.editors;
+
+import java.util.Stack;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Drawable;
+import org.eclipse.swt.widgets.Display;
+
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.TextPresentation;
+
+
+/**
+ * Format Lisaac hover text.
+ */
+public class HoverPresenter implements DefaultInformationControl.IInformationPresenter, DefaultInformationControl.IInformationPresenterExtension {
+
+ private static final int NONE = 0;
+ private static final int BOLD = 1;
+ private static final int ITALIC = 2;
+ private static final int GRAY = 3;
+
+ protected ColorManager colorManager;
+
+ public HoverPresenter(ColorManager colorManager) {
+ this.colorManager = colorManager;
+ }
+
+ /*
+ * @see IHoverInformationPresenterExtension#updatePresentation(Drawable drawable, String, TextPresentation, int, int)
+ * @since 3.2
+ */
+ public String updatePresentation(Drawable drawable, String hoverInfo,
+ TextPresentation presentation, int maxWidth, int maxHeight) {
+
+ if (hoverInfo == null)
+ return null;
+
+ StringBuffer buffer= new StringBuffer();
+
+ int style = NONE;
+ Stack<Integer> styles = new Stack<Integer>();
+ int startOffset = 0;
+
+ int len = hoverInfo.length();
+ int i = 0;
+ int derive = 0;
+
+ while (i < len) {
+ char c = hoverInfo.charAt(i);
+
+ if (c == '<' && i < len-3) {
+ if (hoverInfo.charAt(i+1) == '/') {
+ // end of style
+
+ c = Character.toLowerCase(hoverInfo.charAt(i+2));
+ if (hoverInfo.charAt(i+3) == '>') {
+ style = styles.pop();
+ startOffset = styles.pop();
+ int styleDerive = styles.pop();
+
+ int lengthDerive = derive - styleDerive;
+
+ if (lengthDerive > 0) {
+ // FIXME ranges cannot overlap...
+ style = NONE;
+ }
+
+ switch(style) {
+ case BOLD:
+ presentation.addStyleRange(new StyleRange(
+ startOffset - styleDerive, i - startOffset - lengthDerive, null, null, SWT.BOLD));
+ break;
+ case ITALIC:
+ presentation.addStyleRange(new StyleRange(
+ startOffset - styleDerive, i - startOffset - lengthDerive, null, null, SWT.ITALIC));
+ break;
+ case GRAY:
+ Color gray = colorManager.getColor(ILisaacColor.GRAY);
+ presentation.addStyleRange(new StyleRange(
+ startOffset - styleDerive, i - startOffset - lengthDerive, gray, null, SWT.NONE));
+ break;
+ }
+ i += 3;
+ derive += 4;
+ }
+ style = NONE;
+ } else {
+ c = Character.toLowerCase(hoverInfo.charAt(i+1));
+ startOffset = i+3;
+ switch(c) {
+ case 'b':
+ style = BOLD;
+ break;
+ case 'i':
+ style = ITALIC;
+ break;
+ case 'g':
+ style = GRAY;
+ break;
+ }
+ c = hoverInfo.charAt(i+2);
+ if (c != '>') {
+ buffer.append(c);
+ style = NONE;
+ } else {
+ i += 2;
+ derive += 3;
+
+ styles.push(derive);
+ styles.push(startOffset);
+ styles.push(style);
+ }
+ }
+ } else {
+ buffer.append(c);
+ }
+ i++;
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.text.DefaultInformationControl.IInformationPresenter#updatePresentation(org.eclipse.swt.widgets.Display, java.lang.String, org.eclipse.jface.text.TextPresentation, int, int)
+ * @deprecated
+ */
+ public String updatePresentation(Display display, String hoverInfo, TextPresentation presentation, int maxWidth, int maxHeight) {
+ return updatePresentation((Drawable)display, hoverInfo, presentation, maxWidth, maxHeight);
+ }
+}
+
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/ILisaacColor.java b/editor/eclipse/src/org/lisaac/ldt/editors/ILisaacColor.java
new file mode 100644
index 0000000..662de00
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/ILisaacColor.java
@@ -0,0 +1,50 @@
+package org.lisaac.ldt.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 GRAY = new RGB(128, 128, 128);
+
+ String PREF_NORMAL = "normal";
+ String PREF_BOLD = "bold";
+ String PREF_ITALICS = "italic";
+ String PREF_UNDERLINE = "underline";
+
+ String PREF_COMMENT = "comment_color";
+ String PREF_PROTOTYPE = "prototype_color";
+ String PREF_PROTOTYPE_STYLE = "prototype_style_color";
+ String PREF_KEYWORD = "keyword_color";
+ String PREF_SLOT = "slot_color";
+ String PREF_LOCAL_SLOT = "local_slot_color";
+ String PREF_CHARACTER = "character_color";
+ String PREF_STRING = "string_color";
+ String PREF_NUMBER = "number_color";
+ String PREF_OPERATOR = "operator_color";
+ String PREF_EXTERNAL = "external_color";
+
+ String STYLE_PROTOTYPE = "prototype_style";
+ String STYLE_PROTOTYPE_STYLE = "prototype_style_style";
+ String STYLE_KEYWORD = "keyword_style";
+ String STYLE_SLOT = "slot_style";
+ String STYLE_LOCAL_SLOT = "local_slot_style";
+ String STYLE_CHARACTER = "character_style";
+ String STYLE_STRING = "string_style";
+ String STYLE_NUMBER = "number_style";
+ String STYLE_OPERATOR = "operator_style";
+}
\ No newline at end of file
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/LipEditor.java b/editor/eclipse/src/org/lisaac/ldt/editors/LipEditor.java
new file mode 100644
index 0000000..61457a2
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LipEditor.java
@@ -0,0 +1,25 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/editors/LisaacAutoEditStrategy.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacAutoEditStrategy.java
new file mode 100644
index 0000000..08adc58
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacAutoEditStrategy.java
@@ -0,0 +1,352 @@
+package org.lisaac.ldt.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;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.preferences.PreferenceConstants;
+
+
+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) {
+
+ boolean enableIndent = LisaacPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.P_LISAAC_INDENT);
+ if (! enableIndent) {
+ return;
+ }
+ 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(p/*info.getOffset() + info.getLength()*/, 0, "\n"+createString(indent), null);
+ command.shiftsCaret = true;
+ command.caretOffset = p /*info.getOffset() + info.getLength()*/;
+
+ } catch (BadLocationException e) {
+ // 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++;
+ }
+ }
+
+ public static void indentLine(int line, IDocument document) {
+ doIndentLine(line, document, null);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/LisaacCompletionProcessor.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacCompletionProcessor.java
new file mode 100644
index 0000000..935351c
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacCompletionProcessor.java
@@ -0,0 +1,148 @@
+package org.lisaac.ldt.editors;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.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.jface.text.templates.TemplateProposal;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.model.LisaacCompletionParser;
+import org.lisaac.ldt.preferences.PreferenceConstants;
+import org.lisaac.ldt.templates.LisaacTemplateProcessor;
+
+
+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];
+
+ private LisaacTemplateProcessor templates;
+
+
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+ try {
+ boolean enableCompletion = LisaacPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.P_LISAAC_COMPLETION);
+ if (! enableCompletion) {
+ return null;
+ }
+
+ IDocument document = viewer.getDocument();
+ ArrayList<ICompletionProposal> result = new ArrayList<ICompletionProposal>();
+
+ //
+ computeLisaacCompletion(document, offset, result);
+ //
+
+ String prefix= extractPrefix(document, offset);
+
+ if (prefix != null && prefix.length() > 0) {
+ templates = new LisaacTemplateProcessor();
+ ICompletionProposal[] props = templates.computeCompletionProposals(viewer, offset);
+ for (int t=0; t<props.length; t++) {
+ TemplateProposal tp = (TemplateProposal) props[t];
+ if (tp.getDisplayString().startsWith(prefix)) {
+ result.add(props[t]);
+ }
+ }
+ }
+
+ 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<ICompletionProposal> proposals) {
+ int bracketLevel=0;
+ //
+ // Rewind to '(' '{' ';' '[' ':' '<-'
+ //
+ try {
+ int pos = baseOffset-1;
+ while (pos > 0) {
+ char c = document.getChar(pos);
+ if (c == ';' || c == ':') {
+ break;
+ }
+ if (c == '-' && pos-1 > 0 && document.getChar(pos-1) == '<') {
+ break;
+ }
+ if (c == '(' || c == '{' || c == '[') {
+ if (bracketLevel == 0) {
+ break;
+ }
+ bracketLevel--;
+ }
+ if (c == ')' || 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, null);
+ parser.parseCompletions(pos+1, baseOffset, proposals);
+ }
+ } catch (BadLocationException e) {
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ protected String extractPrefix(IDocument document, int offset) {
+ int i= offset;
+ if (i > document.getLength())
+ return ""; //$NON-NLS-1$
+
+ try {
+ while (i > 0) {
+ char ch= document.getChar(i - 1);
+ if (!Character.isJavaIdentifierPart(ch))
+ break;
+ i--;
+ }
+
+ return document.get(i, offset - i);
+ } catch (BadLocationException e) {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ 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/editor/eclipse/src/org/lisaac/ldt/editors/LisaacConfiguration.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacConfiguration.java
new file mode 100644
index 0000000..4af210f
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacConfiguration.java
@@ -0,0 +1,195 @@
+package org.lisaac.ldt.editors;
+
+import org.eclipse.core.resources.IProject;
+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.ITextHover;
+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;
+import org.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.preferences.PreferenceConstants;
+
+/**
+ * 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;
+ private ITextHover textHover = null;
+
+ private AbstractLisaacEditor editor;
+
+ public LisaacConfiguration(ColorManager colorManager, AbstractLisaacEditor editor) {
+ this.colorManager = colorManager;
+ this.editor = editor;
+ }
+ 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.setRepeatedInvocationMode(true);
+ contentAssistant.setStatusLineVisible(true);
+ contentAssistant.setStatusMessage(LisaacMessages.getString("LisaacConfiguration_0")); //$NON-NLS-1$
+ //
+
+ int delay;
+ try {
+ delay = LisaacPlugin.getDefault().getPreferenceStore().getInt(PreferenceConstants.P_LISAAC_COMPLETION_DELAY);
+ } catch (Exception e) {
+ delay = 500;
+ }
+ contentAssistant.enableAutoActivation(true);
+ contentAssistant.setAutoActivationDelay(delay);
+ contentAssistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
+ }
+ return contentAssistant;
+ }
+
+
+ public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
+ if (textHover != null) {
+ return textHover;
+ }
+ if (editor != null) {
+ IProject project = editor.getProject();
+
+ LisaacModel model = LisaacModel.getModel(project);
+ textHover = new LisaacTextHover(model, editor.getFileName(), colorManager);
+ }
+ return textHover;
+ }
+
+ /**
+ * @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() }; //$NON-NLS-1$
+ }
+
+ /**
+ * 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;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getQuickAssistAssistant(org.eclipse.jface.text.source.ISourceViewer)
+ */
+ /* public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
+ // create a content assistant:
+
+ QuickAssistAssistant assistant = new QuickAssistAssistant();
+ assistant.setQuickAssistProcessor(new LisaacQuickAssistProcessor());
+ assistant.setStatusLineVisible(true);
+ assistant.setStatusMessage("Lisaac QuickFix");
+
+
+ assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
+
+
+ return assistant;
+ }
+*/
+ /*
+ public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer){
+ QuickAssistAssistant qaa = new QuickAssistAssistant();
+ qaa.setQuickAssistProcessor(new LisaacQuickAssistProcessor());
+ qaa.setStatusLineVisible(true);
+ qaa.setStatusMessage("Lisaac QuickFix");
+ return qaa;
+ }*/
+}
\ No newline at end of file
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDamagerRepairer.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDamagerRepairer.java
new file mode 100644
index 0000000..6589696
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDamagerRepairer.java
@@ -0,0 +1,60 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDocumentProvider.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDocumentProvider.java
new file mode 100644
index 0000000..af20e26
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDocumentProvider.java
@@ -0,0 +1,29 @@
+package org.lisaac.ldt.editors;
+
+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.ui.editors.text.FileDocumentProvider;
+
+/**
+ * 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;
+ }
+}
\ No newline at end of file
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDoubleClickStrategy.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDoubleClickStrategy.java
new file mode 100644
index 0000000..7aa3ea7
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacDoubleClickStrategy.java
@@ -0,0 +1,56 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/editors/LisaacEditor.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacEditor.java
new file mode 100644
index 0000000..e11fb81
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacEditor.java
@@ -0,0 +1,41 @@
+package org.lisaac.ldt.editors;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.preferences.PreferenceConstants;
+
+/**
+ * Main class for the Lisaac editor
+ * @author Damien Bouvarel
+ */
+public class LisaacEditor extends AbstractLisaacEditor {
+
+ public LisaacEditor() {
+ super();
+ }
+
+ public void refreshPresentation() {
+ super.refreshPresentation();
+
+ // refresh folding
+ boolean doFold = LisaacPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.P_LISAAC_FOLD);
+ if (! doFold) {
+ removeFoldingStructure();
+ return;
+ }
+ LisaacModel model = LisaacModel.getModel(getProject());
+ if (model != null) {
+ Prototype p;
+ try {
+ p = model.getPrototype(LisaacModel.extractPrototypeName(getFileName()));
+ if (p != null) {
+ updateFoldingStructure(p.getPositions());
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/LisaacHyperLinkDetector.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacHyperLinkDetector.java
new file mode 100644
index 0000000..5bfa51e
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacHyperLinkDetector.java
@@ -0,0 +1,62 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/editors/LisaacPartitionScanner.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacPartitionScanner.java
new file mode 100644
index 0000000..0ef3916
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacPartitionScanner.java
@@ -0,0 +1,30 @@
+package org.lisaac.ldt.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 MultiLineRule("\"", "\"", Token.UNDEFINED, '\0', true);
+ rules[3] = new SingleLineRule("`", "`", Token.UNDEFINED, '\0', true);
+
+ setPredicateRules(rules);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/LisaacResourceDecorator.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacResourceDecorator.java
new file mode 100644
index 0000000..8e9babe
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacResourceDecorator.java
@@ -0,0 +1,94 @@
+package org.lisaac.ldt.editors;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+import org.lisaac.ldt.LisaacPlugin;
+
+/**
+ * Handle image decoration in Navigator View
+ */
+public class LisaacResourceDecorator implements ILightweightLabelDecorator {
+
+ private static ImageDescriptor OVERLAY_ERROR = LisaacPlugin.getImageDescriptor("/icons/error_co.gif");
+ private static ImageDescriptor OVERLAY_WARNING = LisaacPlugin.getImageDescriptor("/icons/warning_co.gif");
+
+ private static ImageDescriptor OVERLAY_SOURCE_FOLDER = LisaacPlugin.getImageDescriptor("/icons/source-folder.gif");
+ private static ImageDescriptor OVERLAY_LIB = LisaacPlugin.getImageDescriptor("/icons/library.gif");
+
+ public static String SOURCE_FOLDER_PROPERTY = "source_folder";
+ public static String LIB_PROPERTY = "lib";
+
+ public void decorate(Object element, IDecoration decoration) {
+ if (element instanceof IResource) {
+ int type;
+ try {
+ type = getTypeFromMarkers((IResource) element);
+ if (type == 1) {
+ decoration.addOverlay(OVERLAY_WARNING);
+ } else if (type == 2) {
+ decoration.addOverlay(OVERLAY_ERROR);
+ }
+ if (element instanceof IFolder) {
+ String sourceFolder = ((IResource) element).getPersistentProperty(
+ new QualifiedName("", SOURCE_FOLDER_PROPERTY));
+ if (sourceFolder != null && sourceFolder != "") {
+ decoration.addOverlay(OVERLAY_SOURCE_FOLDER);
+ } else {
+ String lib = ((IResource) element).getPersistentProperty(
+ new QualifiedName("", LIB_PROPERTY));
+ if (lib != null && lib != "") {
+ decoration.addOverlay(OVERLAY_LIB);
+ }
+ }
+ }
+ } catch (CoreException e) {
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private int getTypeFromMarkers(IResource res) throws CoreException {
+ if (res == null || !res.isAccessible()) {
+ return 0;
+ }
+ int markerType = 0;
+
+ IMarker[] markers = res.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
+ if (markers != null) {
+ for (int i = 0; i < markers.length && (markerType != 2); i++) {
+ IMarker curr = markers[i];
+
+ int priority = curr.getAttribute(IMarker.SEVERITY, -1);
+ if (priority == IMarker.SEVERITY_WARNING) {
+ markerType = 1;
+ } else if (priority == IMarker.SEVERITY_ERROR) {
+ markerType = 2;
+ }
+ }
+ }
+ return markerType;
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return true;
+ }
+
+ // TODO refresh decorator on marker update
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/LisaacScanner.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacScanner.java
new file mode 100644
index 0000000..1690eb1
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacScanner.java
@@ -0,0 +1,336 @@
+package org.lisaac.ldt.editors;
+
+import org.eclipse.jface.text.rules.*;
+import org.lisaac.ldt.model.ILisaacModel;
+
+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 {
+
+ // 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;
+
+ /**
+ * Creates a new Lisaac scanner.
+ */
+ public LisaacScanner(ColorManager manager) {
+ /*
+ * Create lisaac tokens.
+ */
+
+ stringToken = manager.getToken(ILisaacColor.PREF_STRING, ILisaacColor.STYLE_STRING);
+ characterToken = manager.getToken(ILisaacColor.PREF_CHARACTER, ILisaacColor.STYLE_CHARACTER);
+ numberToken = manager.getToken(ILisaacColor.PREF_NUMBER, ILisaacColor.STYLE_NUMBER);
+ prototypeToken = manager.getToken(ILisaacColor.PREF_PROTOTYPE, ILisaacColor.STYLE_PROTOTYPE);
+ prototypeStyleToken = manager.getToken(ILisaacColor.PREF_PROTOTYPE_STYLE, ILisaacColor.STYLE_PROTOTYPE_STYLE);
+ keywordToken = manager.getToken(ILisaacColor.PREF_KEYWORD, ILisaacColor.STYLE_KEYWORD);
+ localVariableToken = manager.getToken(ILisaacColor.PREF_LOCAL_SLOT, ILisaacColor.STYLE_LOCAL_SLOT);
+ operatorToken = manager.getToken(ILisaacColor.PREF_OPERATOR, ILisaacColor.STYLE_OPERATOR);
+ externalToken = manager.getToken2(ILisaacColor.PREF_EXTERNAL, ILisaacColor.PREF_LOCAL_SLOT);
+
+ undefinedToken = manager.getToken(ILisaacColor.PREF_SLOT, ILisaacColor.STYLE_SLOT);
+ //new Token(getAttribute(ILisaacColor.UNDEFINED));
+
+ /*
+ * Create basic lisaac rules.
+ */
+ IRule[] rules = new IRule[8];
+
+ // Add rule for processing strings
+ rules[0] = new MultiLineRule("\"", "\"", 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);
+ String[] keywords = ILisaacModel.keywords;
+ 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;
+ }
+
+ public static boolean isPrototypeIdentifier(String word) {
+ return detectKeyword(word, new LisaacPrototypeDetector());
+ }
+
+ public static boolean isIdentifier(String word) {
+ return detectKeyword(word, new LisaacWordDetector());
+ }
+
+ public static boolean isKeywordIdentifier(String word) {
+ return detectKeyword(word, new LisaacKeywordDetector());
+ }
+
+ private static boolean detectKeyword(String word, IWordDetector detector) {
+ int i = 0;
+ char c;
+ boolean b = true;
+
+ if (word.length() > 0 && detector.isWordStart(word.charAt(0))) {
+ if (word.length() == 1) {
+ return true;
+ }
+ i = 1;
+ do {
+ c = word.charAt(i);
+ b = detector.isWordPart(c);
+ i++;
+ } while (i < word.length() && b);
+ if (! b) {
+ return false;
+ }
+ }
+ return i == word.length();
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/editors/LisaacTextHover.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacTextHover.java
new file mode 100644
index 0000000..1ffb8dc
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacTextHover.java
@@ -0,0 +1,119 @@
+package org.lisaac.ldt.editors;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextHoverExtension;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.swt.widgets.Shell;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.items.IVariable;
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.model.items.Slot;
+import org.lisaac.ldt.preferences.PreferenceConstants;
+
+public class LisaacTextHover implements ITextHover, ITextHoverExtension {
+
+ protected LisaacModel model;
+ protected String filename;
+ protected ColorManager colorManager;
+
+ public LisaacTextHover(LisaacModel model, String filename, ColorManager colorManager) {
+ super();
+ this.model = model;
+ this.filename = filename;
+ this.colorManager = colorManager;
+ }
+
+ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+ try {
+ boolean enableHover = LisaacPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.P_LISAAC_HOVER);
+ if (! enableHover) {
+ return null;
+ }
+
+ String text = textViewer.getDocument().get(hoverRegion.getOffset(), hoverRegion.getLength());
+ if (LisaacScanner.isPrototypeIdentifier(text)) {
+ // get prototype info
+
+ Prototype prototype = model.getPrototype(text);
+ if (prototype != null) {
+ return "<I>Prototype</I> : "+prototype.getHoverInformation();
+ }
+ } else if (LisaacScanner.isIdentifier(text)) {
+ // get slot info
+
+ Prototype prototype = model.getPrototype(LisaacModel.extractPrototypeName(filename));
+ if (prototype != null) {
+ Slot slot = prototype.getSlotFromKeyword(text, prototype.openParser(), hoverRegion.getOffset());
+ if (slot != null) {
+ return "<I>Slot</I> : "+slot.getHoverInformation();
+ } else {
+ slot = prototype.getSlot(hoverRegion.getOffset());
+ IVariable variable = slot.getVariable(text, hoverRegion.getOffset());
+ if (variable != null) {
+ return variable.getHoverInformation();
+ }
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ } catch (CoreException e) {
+ }
+ return null;
+ }
+
+
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ try {
+ return selectWord(textViewer.getDocument(), offset);
+ } catch (BadLocationException e) {
+ }
+ return new Region(offset, 0);
+ }
+
+
+ /*
+ * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
+ */
+ public IInformationControlCreator getHoverControlCreator() {
+ return new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ return new DefaultInformationControl(parent, "Lisaac", new HoverPresenter(colorManager));
+ }
+ };
+ }
+
+ 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/editor/eclipse/src/org/lisaac/ldt/editors/LisaacWordRule.java b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacWordRule.java
new file mode 100644
index 0000000..17839ed
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/LisaacWordRule.java
@@ -0,0 +1,99 @@
+package org.lisaac.ldt.editors;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WordRule;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.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 = null;
+ try {
+ prototype = LisaacModel.getCurrentPrototype();
+ } catch (CoreException e1) {
+ }
+ if (prototype == null) {
+ return result;
+ }
+ //
+ int offset = ((LisaacScanner) scanner).getOffset();
+ String word = fBuffer.toString();
+
+ Slot slot = prototype.getSlot(offset);
+ if (slot != null) {
+
+ // is current word a slot argument?
+ if (slot.hasArgument(word)) {
+ return localVariableToken;
+ }
+ // is current word a slot variable?
+ if (slot.hasVariableDefinition(word, offset)) {
+ return localVariableToken;
+ }
+ }
+ try {
+ slot = prototype.getSlotFromKeyword(word, prototype.openParser(), offset-word.length());
+ if (slot != null) {
+ return result;
+ }
+ } catch (CoreException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ 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/editor/eclipse/src/org/lisaac/ldt/editors/NonRuleBasedDamagerRepairer.java b/editor/eclipse/src/org/lisaac/ldt/editors/NonRuleBasedDamagerRepairer.java
new file mode 100644
index 0000000..f176cb3
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/NonRuleBasedDamagerRepairer.java
@@ -0,0 +1,138 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/editors/PrototypeHyperLink.java b/editor/eclipse/src/org/lisaac/ldt/editors/PrototypeHyperLink.java
new file mode 100644
index 0000000..48a45ae
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/editors/PrototypeHyperLink.java
@@ -0,0 +1,168 @@
+package org.lisaac.ldt.editors;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+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.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.ide.IDE;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.items.IVariable;
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.model.items.Slot;
+
+
+
+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 (part instanceof LipEditor) {
+ return;
+ }
+
+ if (project != null) {// open 'prototype' in editor, select 'slot' at 'position'
+ Prototype prototype = null;
+ Slot slot = null;
+ Position position = null;
+
+ LisaacModel model = LisaacModel.getModel(project);
+
+ if (LisaacScanner.isPrototypeIdentifier(fPrototypeString)) {
+ // prototype hyperlink
+ try {
+ prototype = model.getPrototype(fPrototypeString);
+ } catch (CoreException e) {
+ return;
+ }
+ } else {
+
+ // Slot Hyperlink
+ try {
+ prototype = LisaacModel.getCurrentPrototype();
+ slot = prototype.getSlotFromKeyword(fPrototypeString, prototype.openParser(), fRegion.getOffset());
+
+ } catch (CoreException e) {
+ return;
+ }
+ if (slot != null) {
+ // slot hyperlink
+ prototype = slot.getPrototype();
+ position = slot.getPosition();
+ } else {
+
+ // variable hyperlink
+ IVariable variable = null;
+ slot = prototype.getSlot(fRegion.getOffset());
+ if (slot != null) {
+ variable = slot.getVariable(fPrototypeString, fRegion.getOffset());
+ }
+ if (variable != null) {
+ Position p = variable.getPosition();
+ int len = fPrototypeString.length();
+ if (p.length > 0) {
+ len = p.length;
+ }
+ position = new Position(0, 0, p.offset-len, len);
+ } else {
+ prototype = null;
+ }
+ }
+ }
+ if (prototype != null) {
+ final IProject p = project;
+ final String filename = prototype.getFileName();
+ final Position selectPosition = position;
+
+ part.getSite().getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage page = w.getActivePage();
+ if (page == null) {
+ return;
+ }
+ IFile file=null;
+ IPath location = new Path(filename);
+
+ IContainer src = p.getFolder("src");
+ if (src == null) {
+ src = p;
+ }
+ file = src.getFile(location);
+ if (!file.isAccessible()) {
+ IContainer lib = p.getFolder("lib");
+ if (lib == null) {
+ lib = p;
+ }
+ file = lib.getFile(location);
+ }
+ try {
+ IDE.openEditor(page, file);
+ if (selectPosition != null) {
+ IWorkbenchPart part = w.getPartService().getActivePart();
+ if (part instanceof LisaacEditor) {
+ ((LisaacEditor)part).selectAndReveal(selectPosition.offset, selectPosition.length);
+ }
+ }
+ } 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/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfiguration.java b/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfiguration.java
new file mode 100644
index 0000000..d7705b0
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfiguration.java
@@ -0,0 +1,109 @@
+package org.lisaac.ldt.launch;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+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.core.runtime.Path;
+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.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.items.Prototype;
+
+
+public class LaunchConfiguration implements ILaunchConfigurationDelegate {
+
+ public static final String TYPE_ID = "org.lisaac.ldt.launchConfiguration";
+
+ 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 programArguments = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_ARGUMENTS, "");
+
+ boolean doAlwaysCompile = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_COMPILER, true);
+ boolean doRun = configuration.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_PROGRAM, true);
+ boolean hasCompiled = false;
+
+ int index = mainPrototype.lastIndexOf('/');
+ if (index != -1) {
+ mainPrototype = mainPrototype.substring(index+1);
+ }
+
+ LisaacModel model = LisaacModel.getModel(project);
+ if (model != null) {
+ Prototype main = model.getPrototype(LisaacModel.extractPrototypeName(mainPrototype));
+ if (main == null || main.getSlot("main") == null) {
+ MessageDialog.openInformation(
+ null,
+ "Lisaac Plug-in",
+ mainPrototype+ " : Slot 'main' is missing.");
+ monitor.done();
+ return;
+ }
+ String outputName = main.getName().toLowerCase();
+ monitor.worked(5);
+
+ // 1. Compile project
+ if ((!doAlwaysCompile && model.needCompilation()) || doAlwaysCompile) {
+ compiler = new LisaacCompiler(model, mainPrototype, outputName, "make.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(""));
+
+ // compile & launch project;
+ IContainer output = compiler.launchInConsole(launch, project, monitor);
+ if (output == null) {
+ MessageDialog.openInformation(
+ null,
+ "Lisaac Plug-in",
+ "Compilation Error!");
+ }
+ monitor.worked(50);
+
+ //
+ hasCompiled = true;
+ model.setCompiled(true);
+ monitor.worked(1);
+ }
+
+ // 2. Run program
+ if (doRun && !hasCompiled) {
+ IContainer bin = project.getFolder("bin");
+ if (bin == null) {
+ bin = project;
+ }
+ IFile executable = bin.getFile(new Path(outputName));
+ String[] commandLine = {executable.getLocation().toString(), programArguments};
+ LisaacLauncher.executeCommandInConsole(launch, monitor, bin, commandLine, null);
+ }
+ }
+ monitor.done();
+ }
+
+
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfigurationTab.java b/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfigurationTab.java
new file mode 100644
index 0000000..b426bbf
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfigurationTab.java
@@ -0,0 +1,486 @@
+package org.lisaac.ldt.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.IPath;
+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.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.events.SelectionListener;
+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.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;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+import org.eclipse.ui.dialogs.ResourceSelectionDialog;
+import org.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.lip.LIP;
+import org.lisaac.ldt.model.lip.LIPSlotCode;
+
+
+public class LaunchConfigurationTab extends AbstractLaunchConfigurationTab {
+
+ public static final String LISAAC_LAUNCH_PROJECT = "launchProject"; //$NON-NLS-1$
+
+ public static final String LISAAC_LAUNCH_PROTOTYPE = "mainPrototype"; //$NON-NLS-1$
+ public static final String LISAAC_LAUNCH_COMPILER = "launchCompiler"; //$NON-NLS-1$
+
+ public static final String LISAAC_LAUNCH_PROGRAM = "launchProgram"; //$NON-NLS-1$
+ public static final String LISAAC_LAUNCH_ARGUMENTS = "programArguments"; //$NON-NLS-1$
+
+ public static final String LISAAC_LAUNCH_OPTION = "lipOption"; //$NON-NLS-1$
+ public static final String LISAAC_LAUNCH_OPTION_ARG = "lipOptionARG"; //$NON-NLS-1$
+
+ // Project UI widget.
+ private Text projectText;
+ private Text mainPrototypeText;
+ private Table lipTable;
+
+ // associated lip
+ private LIP lipCode;
+
+ private Button doLaunchCompiler;
+
+ private Button doLaunchProgram;
+ private Text argumentsText;
+
+ /**
+ * @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();
+ topLayout.numColumns = 1;
+ comp.setLayout(topLayout);
+
+ // Project Options
+ Group projComp = new Group(comp, SWT.SHADOW_IN);
+ projComp.setText(LisaacMessages.getString("LaunchConfigurationTab.6")); //$NON-NLS-1$
+ 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(LisaacMessages.getString("LaunchConfigurationTab.7")); //$NON-NLS-1$
+ 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 = 1;
+ projectText.setLayoutData(gd);
+ projectText.setFont(font);
+ this.projectText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ Button browseButton = new Button(projComp, SWT.PUSH);
+ browseButton.setText(LisaacMessages.getString("LaunchConfigurationTab.9")); //$NON-NLS-1$
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
+ gd.horizontalSpan = 1;
+ browseButton.setLayoutData(gd);
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowseContainer(projectText);
+ }
+ });
+
+ Label label = new Label(projComp, SWT.NONE);
+ label.setText(LisaacMessages.getString("LaunchConfigurationTab.8")); //$NON-NLS-1$
+ gd = new GridData();
+ label.setLayoutData(gd);
+ label.setFont(font);
+
+ mainPrototypeText = new Text(projComp, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ mainPrototypeText.setLayoutData(gd);
+ mainPrototypeText.setFont(font);
+ mainPrototypeText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ browseButton = new Button(projComp, SWT.PUSH);
+ browseButton.setText(LisaacMessages.getString("LaunchConfigurationTab.9")); //$NON-NLS-1$
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
+ browseButton.setLayoutData(gd);
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowseFile(mainPrototypeText);
+ }
+ });
+
+ Label separator = new Label (comp, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // compiler options
+ Group compilerOptions = new Group(comp, SWT.SHADOW_IN);
+ compilerOptions.setText(LisaacMessages.getString("LaunchConfigurationTab.12")); //$NON-NLS-1$
+ GridLayout gl = new GridLayout();
+ gl.numColumns = 3;
+ compilerOptions.setLayout(gl);
+ gd = new GridData(GridData.FILL_BOTH);
+ compilerOptions.setLayoutData(gd);
+
+ doLaunchCompiler = new Button(compilerOptions, SWT.CHECK);
+ doLaunchCompiler.setText("Always Compile (cannot run program)");
+ doLaunchCompiler.setSelection(false);
+ gd = new GridData();
+ gd.horizontalSpan = 3;
+ doLaunchCompiler.setLayoutData(gd);
+ doLaunchCompiler.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ doLaunchProgram.setEnabled(! doLaunchCompiler.getSelection());
+ argumentsText.setEnabled(! doLaunchCompiler.getSelection());
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ // lip options
+ Composite tableGroup = new Composite(compilerOptions, SWT.NONE);
+ tableGroup.setLayout(new GridLayout(1, false));
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = 1;
+ gd.verticalSpan = 3;
+ tableGroup.setLayoutData(gd);
+
+ 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(LisaacMessages.getString("LaunchConfigurationTab.15")); //$NON-NLS-1$
+ c1.setWidth(130);
+ final TableColumn c2 = new TableColumn(lipTable, SWT.LEFT);
+ c2.setText(LisaacMessages.getString("LaunchConfigurationTab.16")); //$NON-NLS-1$
+ c2.setWidth(80);
+ final TableColumn c3 = new TableColumn(lipTable, SWT.LEFT);
+ c3.setText(LisaacMessages.getString("LaunchConfigurationTab.17")); //$NON-NLS-1$
+ c3.setWidth(100);
+ lipTable.setHeaderVisible(true);
+ lipTable.setLinesVisible(true);
+ lipTable.setItemCount(4);
+ lipTable.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ 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.FILL_BOTH);
+ gridData.horizontalSpan = 2;
+ tableGroup.setLayoutData(gridData);
+
+ separator = new Label (comp, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // program options
+ Group programOptions = new Group(comp, SWT.SHADOW_IN);
+ programOptions.setText("Program Options"); //$NON-NLS-1$
+ gl = new GridLayout();
+ gl.numColumns = 2;
+ programOptions.setLayout(gl);
+ programOptions.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ doLaunchProgram = new Button(programOptions, SWT.CHECK);
+ doLaunchProgram.setText("Run the program");
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ doLaunchProgram.setLayoutData(gd);
+ doLaunchProgram.setSelection(true);
+ doLaunchProgram.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (argumentsText != null) {
+ argumentsText.setEnabled(doLaunchProgram.getSelection());
+ }
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ label = new Label(programOptions, SWT.NONE);
+ label.setText("Command-Line:");
+ label.setLayoutData(new GridData(GridData.BEGINNING));
+
+ argumentsText = new Text(programOptions, SWT.SINGLE | SWT.BORDER);
+ argumentsText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ argumentsText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+ */
+ public String getName() {
+ return LisaacMessages.getString("LaunchConfigurationTab.18"); //$NON-NLS-1$
+ }
+
+ /**
+ * @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, ""); //$NON-NLS-1$
+ projectText.setText(projectName);
+
+ String mainPrototypeName = configuration.getAttribute(LISAAC_LAUNCH_PROTOTYPE, ""); //$NON-NLS-1$
+ mainPrototypeText.setText(mainPrototypeName);
+
+ boolean check = configuration.getAttribute(LISAAC_LAUNCH_COMPILER, false);
+ doLaunchCompiler.setSelection(check);
+
+ check = configuration.getAttribute(LISAAC_LAUNCH_PROGRAM, true);
+ doLaunchProgram.setSelection(check);
+
+ String commandLine = configuration.getAttribute(LISAAC_LAUNCH_ARGUMENTS, ""); //$NON-NLS-1$
+ argumentsText.setText(commandLine);
+
+ 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 = LisaacMessages.getString("LaunchConfigurationTab.23"); //$NON-NLS-1$
+ }
+ methodComment = methodComment.replaceAll("\t", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ methodComment = methodComment.replaceAll("\n", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
+ if (! lipTable.isDisposed()) {
+ TableItem item = new TableItem (lipTable, SWT.NONE);
+ item.setText(0, method.getName());
+ item.setText(2, methodComment);
+
+ if (method.getName().compareTo(ILisaacModel.slot_debug_mode) == 0) {
+ if (getLaunchConfigurationDialog().getMode().compareTo("debug") == 0) {
+ item.setChecked(true);
+ } else {
+ item.setChecked(false);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (CoreException ce) {
+ // Log the error to the Eclipse log.
+ IStatus status = new Status(IStatus.ERROR,
+ LisaacPlugin.PLUGIN_ID, 0,
+ "Error in Lisaac launch: " + //$NON-NLS-1$
+ 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_COMPILER, doLaunchCompiler.getSelection());
+ configuration.setAttribute(LISAAC_LAUNCH_PROGRAM, doLaunchProgram.getSelection());
+ configuration.setAttribute(LISAAC_LAUNCH_ARGUMENTS, argumentsText.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();
+ String projectName = ""; //$NON-NLS-1$
+ String mainPrototypeName = ""; //$NON-NLS-1$
+
+ if (project != null) {
+ projectName = project.getName();
+ mainPrototypeName = projectName + ".li"; //$NON-NLS-1$
+ }
+ configuration.setAttribute(LISAAC_LAUNCH_PROJECT, projectName);
+ configuration.setAttribute(LISAAC_LAUNCH_PROTOTYPE, mainPrototypeName);
+
+ configuration.setAttribute(LISAAC_LAUNCH_COMPILER, false);
+ configuration.setAttribute(LISAAC_LAUNCH_PROGRAM, true);
+ configuration.setAttribute(LISAAC_LAUNCH_ARGUMENTS, ""); //$NON-NLS-1$
+
+ if (lipTable != null) {
+ 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.
+ * @return the current project selected in the workbench.
+ */
+ private IProject getSelectedProject() {
+ 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 handleBrowseContainer(Text text) {
+ ContainerSelectionDialog dialog = new ContainerSelectionDialog(
+ getShell(), null, false,
+ "Select Folder"); //$NON-NLS-1$
+ 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;
+ text.setText(ipath.toString());
+ }
+ }
+ }
+ }
+
+ private void handleBrowseFile(Text text) {
+ ResourceSelectionDialog dialog = new ResourceSelectionDialog(
+ getShell(), ResourcesPlugin.getWorkspace().getRoot(), "Select File"); //$NON-NLS-1$
+ dialog.setInitialSelections(new Object[0]);
+ if (dialog.open() == ResourceSelectionDialog.OK) {
+ Object[] results = dialog.getResult();
+ if (results.length == 1) {
+ Object result = results[0];
+ if (result instanceof IResource) {
+ text.setText(((IResource) result).getName());
+ }
+ }
+ }
+ }
+
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfigurationTabGroup.java b/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfigurationTabGroup.java
new file mode 100644
index 0000000..58e2e8d
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/launch/LaunchConfigurationTabGroup.java
@@ -0,0 +1,20 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/launch/LisaacApplicationShortcut.java b/editor/eclipse/src/org/lisaac/ldt/launch/LisaacApplicationShortcut.java
new file mode 100644
index 0000000..1168a0f
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/launch/LisaacApplicationShortcut.java
@@ -0,0 +1,98 @@
+package org.lisaac.ldt.launch;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.ui.ILaunchShortcut;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * Handle the 'Lisaac Application' run shortcut.
+ */
+public class LisaacApplicationShortcut implements ILaunchShortcut {
+
+ public LisaacApplicationShortcut() {
+ }
+
+ public void launch(ISelection selection, String mode) {
+ if(selection instanceof IStructuredSelection) {
+ Object firstSelection = ((IStructuredSelection)selection).getFirstElement();
+ if (firstSelection instanceof IFile) {
+ ILaunchConfiguration config = findLaunchConfiguration((IFile)firstSelection, mode);
+ try {
+ if(config != null)
+ config.launch(mode, null);
+ }
+ catch(CoreException coreexception) { }
+ }
+ }
+ }
+
+ public void launch(IEditorPart editor, String mode)
+ {
+ // make sure the file is saved
+ editor.getEditorSite().getPage().saveEditor(editor,true);
+ org.eclipse.ui.IEditorInput input = editor.getEditorInput();
+ ISelection selection = new StructuredSelection(input.getAdapter(org.eclipse.core.resources.IFile.class));
+ launch(selection, mode);
+ }
+
+ protected ILaunchConfiguration findLaunchConfiguration(IFile file, String mode) {
+ ILaunchConfigurationType configType = getLaunchConfigType();
+ List<ILaunchConfiguration> candidateConfigs = null;
+ try {
+ ILaunchConfiguration configs[] = getLaunchManager().getLaunchConfigurations(configType);
+ candidateConfigs = new ArrayList<ILaunchConfiguration>(configs.length);
+ for(int i = 0; i < configs.length; i++) {
+ ILaunchConfiguration config = configs[i];
+
+ if(config.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_PROTOTYPE, "").equals(file.getFullPath().lastSegment()) &&
+ config.getAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_PROJECT, "").equals(file.getProject().getFullPath().lastSegment()))
+ candidateConfigs.add(config);
+ }
+ }
+ catch(CoreException coreexception) { }
+ switch(candidateConfigs.size())
+ {
+ case 0: // '\0'
+ return createConfiguration(file);
+
+ case 1: // '\001'
+ default:
+ return (ILaunchConfiguration)candidateConfigs.get(0);
+ }
+ }
+
+ protected ILaunchConfiguration createConfiguration(IFile file)
+ {
+ ILaunchConfiguration config = null;
+ try
+ {
+ ILaunchConfigurationType configType = getLaunchConfigType();
+ ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, getLaunchManager().generateUniqueLaunchConfigurationNameFrom(file.getName()));
+ wc.setAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_PROJECT, file.getProject().getName());
+ wc.setAttribute(LaunchConfigurationTab.LISAAC_LAUNCH_PROTOTYPE, file.getName());
+ config = wc.doSave();
+ }
+ catch(CoreException coreexception) { }
+ return config;
+ }
+
+ protected ILaunchConfigurationType getLaunchConfigType() {
+ return getLaunchManager().getLaunchConfigurationType(LaunchConfiguration.TYPE_ID);
+ }
+
+ protected ILaunchManager getLaunchManager() {
+ return DebugPlugin.getDefault().getLaunchManager();
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/launch/LisaacCompiler.java b/editor/eclipse/src/org/lisaac/ldt/launch/LisaacCompiler.java
new file mode 100644
index 0000000..4e2e470
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/launch/LisaacCompiler.java
@@ -0,0 +1,243 @@
+package org.lisaac.ldt.launch;
+
+import java.util.ArrayList;
+
+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.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.jface.text.IRegion;
+import org.lisaac.ldt.builder.LisaacBuilder;
+import org.lisaac.ldt.model.AbstractLisaacParser;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.items.Prototype;
+
+public class LisaacCompiler {
+
+ protected String inputFile;
+ protected String lipFile;
+
+ protected ArrayList<String> options;
+
+ protected LisaacModel model;
+
+ protected String outputName;
+
+ // for lisaac <input_file> <lip_file> [options]
+ public LisaacCompiler(LisaacModel model, String inputFile, String outputName, String lipFile) {
+ this.inputFile = inputFile;
+ this.lipFile = lipFile;
+ this.outputName = outputName;
+ this.model = model;
+ }
+
+ // for lisaac <lip_file> --p
+ public LisaacCompiler(String lipFile) {
+ this.lipFile = lipFile;
+ }
+
+ public IContainer launchInConsole(final ILaunch launch, IProject project, IProgressMonitor monitor) throws CoreException {
+ IContainer src = project.getFolder("src");
+
+ if (src != null) {
+ if (LisaacLauncher.executeCommandInConsole(launch, monitor, src, this.toCommandLineArray(),this)) {
+ return src;
+ }
+ }
+ else if (LisaacLauncher.executeCommandInConsole(launch, monitor, project, this.toCommandLineArray(),this)) {
+ return project;
+ }
+ return null;
+ }
+
+ public Process launch(IProject project, IProgressMonitor monitor) throws CoreException {
+ 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);
+ }
+ return cmd.toArray(new String[cmd.size()]);
+ }
+
+ public String toCommandLine() {
+ StringBuffer result = new StringBuffer();
+
+ result.append("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);
+ }
+
+ public void moveFiles(IContainer output) throws CoreException {
+ IProject project = model.getProject();
+
+ // refresh the generated files
+ output.refreshLocal(IResource.DEPTH_INFINITE, null);
+
+ // move the generated files to bin/
+ IContainer bin = project.getFolder("bin");
+ IPath generatedPath = new Path(outputName);
+ IFile executable = output.getFile(generatedPath);
+ if (! executable.exists()) {
+ generatedPath = new Path(outputName+".exe");// FIXME platform-dependant
+ executable = output.getFile(generatedPath);
+ }
+ if (executable.exists()) {
+ IFile destFile = bin.getFile(generatedPath);
+ if (destFile.exists()) {
+ destFile.delete(true, null);
+ }
+ executable.move(bin.getFullPath().append(generatedPath), true, null);
+ }
+ moveFile(outputName+".o", output, bin);// FIXME .java, etc..
+ moveFile(outputName+".c", output, bin);
+
+ //
+ project.refreshLocal(IResource.DEPTH_INFINITE, null); // TODO usefull? try to remove
+ //
+
+ model.setCompiled(true);
+ }
+
+ private void moveFile(String filename, IContainer origin, IContainer destination) throws CoreException {
+ IPath path = new Path(filename);
+ IFile originFile = origin.getFile(path);
+
+ if (originFile.exists()) {
+ IFile destFile = destination.getFile(path);
+ if (destFile.exists()) {
+ destFile.delete(true, null);
+ }
+ originFile.move(destination.getFullPath().append(path), true, null);
+ }
+ }
+
+ public void cleanFiles() throws CoreException {
+ IContainer bin = model.getProject().getFolder("bin");
+
+ IFile executable = bin.getFile(new Path(outputName));
+ if (executable.exists()) {
+ executable.delete(true, null);
+ }
+ executable = bin.getFile(new Path(outputName+".exe"));// FIXME platform-dependant
+ if (executable.exists()) {
+ executable.delete(true, null);
+ }
+ IFile file = bin.getFile(new Path(outputName+".o"));
+ if (file.exists()) {
+ file.delete(true, null);
+ }
+ file = bin.getFile(new Path(outputName+".c")); // FIXME .java, etc..
+ if (file.exists()) {
+ file.delete(true, null);
+ }
+ }
+
+ public void showErrors(String output) throws CoreException {
+ new CompilerOutputParser(output).run(model);
+ }
+}
+
+class CompilerOutputParser extends AbstractLisaacParser {
+ public CompilerOutputParser(String contents) {
+ super(contents);
+ }
+
+ public void run(LisaacModel model) throws CoreException {
+ int startOffset = source.indexOf("--");
+ while (startOffset != -1) {
+ setPosition(startOffset+2);
+
+ if (! readCapIdentifier()) {
+ break;
+ }
+ int line, column;
+ String prototypeName;
+ String msg;
+ int severity = 0;
+
+ if (lastString.compareTo("WARNING") == 0) {
+ readWord("----------");
+ severity = 1;
+ } else if (lastString.compareTo("SYNTAX") == 0) {
+ readWord("-----------");
+ severity = 2;
+ } else if (lastString.compareTo("SEMANTIC") == 0) {
+ readWord("---------");
+ severity = 2;
+ }
+ readLine();
+ msg = new String(lastString);
+ msg = msg.replace('\r', ' ');
+ readWord("Line");
+ readInteger();
+ line = (int) lastInteger;
+ readWord("column");
+ readInteger();
+ column = (int) lastInteger;
+ readWord("in");
+ readCapIdentifier();
+ prototypeName = new String(lastString);
+
+ // add marker to file
+ Prototype prototype = model.getPrototype(prototypeName);
+ if (prototype != null) {
+ IFile file = prototype.getFile();
+ IRegion region = prototype.getRegionAt(line, column);
+
+ Position position = new Position(line, column, region.getOffset(), region.getLength());
+ LisaacBuilder.addMarker(file, msg, position, severity);
+ }
+ startOffset = source.indexOf("--", position);
+ }
+ }
+ private void readLine() {
+ if (readSpace()) {
+ string_tmp = "";
+ while (lastCharacter() != 0 && lastCharacter() != '\n') {
+ string_tmp += lastCharacter();
+ if (lastCharacter() == '\\') {
+ position = position+1;
+ readEscapeCharacter();
+ } else {
+ position = position+1;
+ }
+ }
+ position = position+1;
+ lastString = string_tmp;
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/launch/LisaacLauncher.java b/editor/eclipse/src/org/lisaac/ldt/launch/LisaacLauncher.java
new file mode 100644
index 0000000..bb55953
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/launch/LisaacLauncher.java
@@ -0,0 +1,142 @@
+package org.lisaac.ldt.launch;
+
+import java.io.File;
+import java.io.IOException;
+
+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.debug.core.ILaunch;
+import org.eclipse.debug.core.IStreamListener;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IStreamMonitor;
+import org.eclipse.swt.widgets.Display;
+import org.lisaac.ldt.views.ConsoleFactory;
+import org.lisaac.ldt.views.LisaacConsole;
+
+
+public class LisaacLauncher {
+
+ public static boolean executeCommandInConsole(final ILaunch launch, final IProgressMonitor monitor,
+ final IContainer container, final String[] commandLine, final LisaacCompiler compiler) throws CoreException {
+ // get & clear lisaac console
+ final LisaacConsole console = ConsoleFactory.getConsole();
+ console.clearConsole();
+
+ if (compiler == null) {
+ console.activate();// show console
+ }
+ Runnable getStandardOutput = new Runnable() {
+ public void run() {
+ monitor.beginTask("Executing... ", 100);
+
+ // 1. Clean existing files
+ if (compiler != null) {
+ try {
+ compiler.cleanFiles();
+ } catch (CoreException e) {
+ }
+ monitor.worked(10);
+ }
+
+ // 2. Launch process
+ Process process = null;
+ try {
+ process = launchProcess(commandLine, container);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ monitor.worked(20);
+ if (monitor.isCanceled()) {
+ return;
+ }
+ if (process != null) {
+ monitor.setTaskName("Reading output...");
+ monitor.worked(20);
+
+ // attach process stream to Lisaac console
+ IProcess eclipseProcess = DebugPlugin.newProcess(launch,
+ process,"Lisaac Session");
+
+ // get the process output
+ final StringBuffer buffer = new StringBuffer();
+
+ IStreamListener listener = new IStreamListener() {
+ public void streamAppended(String text,
+ IStreamMonitor monitor) {
+ buffer.append(text);
+ }
+ };
+ eclipseProcess.getStreamsProxy().getOutputStreamMonitor().addListener(listener);
+ eclipseProcess.getStreamsProxy().getErrorStreamMonitor().addListener(listener);
+
+ // 3. clean files after process execution
+ if (compiler != null) {
+ try {
+ process.waitFor();
+ } catch (InterruptedException e) {
+ }
+ try {
+ compiler.moveFiles(container);
+
+ while (! eclipseProcess.isTerminated()) {}
+ compiler.showErrors(buffer.toString());
+
+ } catch (CoreException e) {
+ }
+ }
+ }
+ monitor.done();
+ }
+ };
+ // execute action in a new thread UI safe
+ Display.getDefault().asyncExec(getStandardOutput);
+ return true;
+ }
+
+ public static Process executeCommand(IProgressMonitor monitor, IContainer container, String[] commandLine) throws CoreException {
+ monitor.beginTask("Executing...", 100);
+
+ Process process = null;
+ try {
+ process = launchProcess(commandLine, container);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ monitor.worked(20);
+ if (monitor.isCanceled()) {
+ return null;
+ }
+ return process;
+ }
+
+ /**
+ * 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 directory) throws IOException {
+ File projectDirectory =
+ (directory != null) ? new File(directory.getLocationURI()) : null;
+
+ String cmd = concatCommandLine(commandLine);
+
+ Process process = Runtime.getRuntime().exec(cmd, null, projectDirectory);
+ return process;
+ }
+
+ private static String concatCommandLine(String[] commandLine) {
+ StringBuffer buf = new StringBuffer();
+ for (int i=0; i<commandLine.length; i++) {
+ buf.append(commandLine[i]);
+ buf.append(' ');
+ }
+ return buf.toString();
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/messages.properties b/editor/eclipse/src/org/lisaac/ldt/messages.properties
new file mode 100644
index 0000000..58c617b
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/messages.properties
@@ -0,0 +1,75 @@
+AbstractNewFileWizardPage_1=Source folder :
+AbstractNewFileWizardPage_2=Browse...
+AbstractNewFileWizardPage_3=File name :
+AbstractNewFileWizardPage_4=Select container.
+AbstractNewFileWizardPage_5=Source folder must be specified.
+AbstractNewFileWizardPage_6=File name must be specified.
+AbstractNewFileWizardPage_7=File already exists.
+LaunchConfigurationTab.10=Program Arguments
+LaunchConfigurationTab.12=Compiler Options
+LaunchConfigurationTab.13=Lisaac Path File (default : make.lip):
+LaunchConfigurationTab.14=Browse...
+LaunchConfigurationTab.15=Option
+LaunchConfigurationTab.16=Argument
+LaunchConfigurationTab.17=Description
+LaunchConfigurationTab.18=Main
+LaunchConfigurationTab.23=No comment
+LaunchConfigurationTab.6=Project Options
+LaunchConfigurationTab.7=Project:
+LaunchConfigurationTab.8=Main Prototype to run :
+LaunchConfigurationTab.9=Browse...
+LisaacBuilder.2=Build workpace...
+LisaacColoringPage.0=Lisaac Editor Syntax Coloring preferences :
+LisaacColoringPage.10=\ \ \ \ &Externals:
+LisaacColoringPage.11=\ \ \ \ &Slots:
+LisaacColoringPage.12=\ \ \ \ &Local variable:
+LisaacColoringPage.2=\ \ \ \ &Comments:
+LisaacColoringPage.3=\ \ \ \ &Prototype:
+LisaacColoringPage.4=\ \ \ \ &Slot style:
+LisaacColoringPage.5=\ \ \ \ &Keywords:
+LisaacColoringPage.6=\ \ \ \ &Characters:
+LisaacColoringPage.7=\ \ \ \ &Strings:
+LisaacColoringPage.8=\ \ \ \ &Numbers:
+LisaacColoringPage.9=\ \ \ \ &Operators:
+LisaacColoringPage.20=Bold
+LisaacColoringPage.21=Italics
+LisaacColoringPage.22=Normal
+LisaacColoringPage.23=Underline
+LisaacConfiguration_0=Lisaac Completion
+LisaacConsole.1=Lisaac Console
+LisaacEditorPage.0=&Enable Auto-Indentation
+LisaacEditorPage.1=&Enable Hovering
+LisaacEditorPage.2=Content Assist preferences
+LisaacEditorPage.3=&Enable Completion
+LisaacEditorPage.4=Auto-Activation Delay
+LisaacEditorPage.5=Enable folding
+LisaacPreferencePage.0=General settings for Lisaac Development
+LisaacPreferencePage.1=&Your name :
+LisaacPreferencePage.2=&Support for Lisaac 0.13
+LisaacProjectPropertyPage.0=Lisaac Environment Path
+LisaacProjectPropertyPage.1=Use default Lisaac Environment
+LisaacProjectPropertyPage.2=Use a project specific Lisaac Environment :
+LisaacProjectPropertyPage.3=Browse...
+LisaacProjectPropertyPage.8=Select Lisaac Environment Directory.
+NewProjectWizard_46=New Lisaac Project Wizard
+NewProjectWizard_47=New Lisaac Project
+NewProjectWizard_48=Create a lisaac project
+NewProjectWizard_49=Use default Lisaac Environment
+NewProjectWizard_50=Use a project specific Lisaac Environment :
+NewProjectWizard_51=Browse...
+NewPrototypeWizard_0=New Prototype
+NewPrototypeWizard_2=Prototype File
+NewPrototypeWizard_25=Prototype Style :
+NewPrototypeWizard_26=None
+NewPrototypeWizard_27=Expanded
+NewPrototypeWizard_28=Strict
+NewPrototypeWizard_29=Description :
+NewPrototypeWizard_3=Creates a new source file into a project
+NewPrototypeWizard_30=Inheritance :
+NewPrototypeWizard_32=Inheritance Type
+NewPrototypeWizard_34=Add...
+NewPrototypeWizard_35=Remove
+NewPrototypeWizard_36=Which slots would you like to create?
+NewPrototypeWizard_37=Main slot
+NewPrototypeWizard_38=Constructor slot
+RenamePrototype.0=Rename Prototype...
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/AbstractLisaacParser.java b/editor/eclipse/src/org/lisaac/ldt/model/AbstractLisaacParser.java
new file mode 100644
index 0000000..45af489
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/AbstractLisaacParser.java
@@ -0,0 +1,886 @@
+package org.lisaac.ldt.model;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+
+import org.lisaac.ldt.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 Position getLine() {
+ Position result=null;
+ int startLine = pos_cur;
+ int endLine = position+1;
+
+ while (pos_cur < position && !isEOF()) {
+ if (source.charAt(pos_cur) == '\n') {
+ pos_col = 0;
+ pos_line++;
+ startLine = pos_cur+1;
+ } 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);
+ };
+ while (endLine <= source.length()-1) {
+ if (source.charAt(endLine) == '\n') {
+ break;
+ }
+ endLine++;
+ }
+ result = new Position(pos_line, pos_col, endLine, endLine - startLine);
+ return result;
+ }
+
+ public void updateLine() {
+ while (pos_cur < position) {
+ if (source.charAt(pos_cur) == '\n') {
+ pos_col = 0;
+ pos_line++;
+ } else {
+ pos_col++;
+ }
+ pos_cur++;
+ }
+ }
+
+ public int getOffset() {
+ return position;
+ }
+
+ public String getSource() {
+ return source;
+ }
+
+ public boolean isEOF() {
+ return position > source.length()-1;
+ }
+
+ public void setPosition(int pos) {
+ initialize();
+ position = pos;
+ }
+
+ protected long lastInteger;
+ protected String lastReal;
+ protected String lastString;
+
+ protected static String lastComment;
+ protected boolean isCatchComment;
+
+ protected boolean isParameterType;
+
+ protected void setCatchComment() {
+ isCatchComment = true;
+ lastComment = "";
+ }
+ protected void setCatchCommentOff() {
+ isCatchComment = false;
+ }
+
+ public String getLastString() {
+ return lastString;
+ }
+
+ public char lastCharacter() {
+ if (position > source.length()-1) {
+ return 0;
+ }
+ return source.charAt(position);
+ }
+
+ //
+ // AMBIGU Manager.
+ //
+
+ protected int old_position;
+ protected int old_pos_cur;
+ protected int old_pos_line;
+ protected int old_pos_col;
+
+ protected void saveContext() {
+ old_position = position;
+ old_pos_cur = pos_cur;
+ old_pos_line = pos_line;
+ old_pos_col = pos_col;
+ }
+ protected void restoreContext() {
+ position = old_position;
+ pos_cur = old_pos_cur;
+ pos_line = old_pos_line;
+ pos_col = old_pos_col;
+ }
+
+ public AbstractLisaacParser(InputStream contents, ILisaacModel model) {
+ this.model = model;
+ this.reporter = model.getReporter();
+
+ // convert the input stream into string
+ try {
+ InputStreamReader reader = new InputStreamReader (contents);
+ BufferedReader buffer = new BufferedReader(reader);
+
+ StringWriter writer = new StringWriter();
+
+ String line="";
+ do {
+ line = buffer.readLine();
+ if (line != null) {
+ writer.write(line+"\n");
+ }
+ } while (line != null);
+ //
+ source = writer.toString();
+ //
+ } catch (IOException e) {
+ return; // ERROR
+ }
+ initialize();
+ }
+
+ public AbstractLisaacParser(String contents) {
+ // null reporter
+ this.reporter = new ILisaacErrorHandler() {
+ public void fatalError(String msg, Position position) {
+ }
+ public void semanticError(String msg, Position position) {
+ }
+ public void syntaxError(String msg, Position position) {
+ }
+ public void warning(String msg, Position position) {
+ }
+ };
+ source = contents;
+ initialize();
+ }
+
+ public void initialize() {
+ position = 0;
+ pos_cur = 0;
+ pos_line = 1;
+ pos_col = 0;
+ }
+
+ //
+ // Lisaac Parser
+ //
+
+ public boolean readSpace() {
+ int pos,posold;
+ int level_comment = 0;
+
+ pos = position;
+ posold = -1;
+ while (posold != position) {
+ posold = position;
+
+ // skip spaces
+ while ((lastCharacter() != 0) && (lastCharacter() <= ' ')) {
+ position++;
+ }
+ if (position < source.length()-1) {
+ // Skip C++ comment style :
+ if (lastCharacter() == '/' && source.charAt(position+1) == '/') {
+ position += 2;
+
+ if (isCatchComment)
+ lastComment += "\t";
+
+ while ((lastCharacter() != 0) && (lastCharacter() != '\n')) {
+ if (isCatchComment)
+ lastComment += lastCharacter();
+
+ lastCharacter();
+ position++;
+ }
+ if (isCatchComment)
+ lastComment += "\n";
+ }
+ }
+ if (position < source.length()-1) {
+ // Skip C comment style :
+ if (lastCharacter() == '/' && source.charAt(position+1) == '*') {
+ position += 2;
+ level_comment++;
+
+ while (lastCharacter() != 0 && level_comment != 0) {
+ if (lastCharacter() == '/' && source.charAt(position+1) == '*') {
+ position += 2;
+ level_comment++;
+ } else if (lastCharacter() == '*' && source.charAt(position+1) == '/') {
+ position += 2;
+ level_comment--;
+ } else {
+ position++;
+ }
+ }
+ if (level_comment != 0) {
+ reporter.syntaxError("End of comment not found !", getPosition());
+ }
+ }
+ }
+ }
+ // FALSE : Last character.
+ begin_position = position;
+ return (position != pos) || (lastCharacter() != 0);
+ }
+
+ public boolean readSymbol(String st) {
+ int posold,j;
+ boolean result=false;
+
+ if (! readSpace()) {
+ result = false;
+ } else {
+ posold = position;
+ j = 0;
+ while (lastCharacter() != 0 && (j <= st.length()-1 && lastCharacter() == st.charAt(j))) {
+ position++;
+ j++;
+ }
+ if (j > st.length()-1) {
+ result = true;
+ lastString = st;
+ } else {
+ position = posold;
+ result = false;
+ }
+ }
+ return result;
+ }
+
+ public boolean readCharacter (char ch) {
+ boolean result=false;
+
+ if (! readSpace()) {
+ result = false;
+ } else {
+ if (lastCharacter() == ch) {
+ position++;
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ //-- affect -> ":=" | "<-" | "?="
+ public boolean readAffect() {
+ return readSymbol(ILisaacModel.symbol_affect_immediate) ||
+ readSymbol(ILisaacModel.symbol_affect_cast) ||
+ readSymbol(ILisaacModel.symbol_affect_code);
+ }
+
+ //-- style -> '-' | '+'
+ public char readStyle() {
+ char result;
+
+ if (readCharacter('-')) {
+ result = '-';
+ } else if (readCharacter('+')) {
+ result = '+';
+ } else {
+ result = ' ';
+ }
+ return result;
+ }
+
+ //-- identifier -> 'a'-'z' {'a'-'z' | '0'-'9' | '_'}
+ public boolean readIdentifier() {
+ boolean result=false;
+ int posold,idx;
+
+ if (! readSpace() || !Character.isLowerCase(lastCharacter())) {
+ result = false;
+ } else {
+ posold = position;
+ string_tmp = "";
+
+ while (lastCharacter() != 0 &&
+ (Character.isLowerCase(lastCharacter()) ||
+ Character.isDigit(lastCharacter()) ||
+ lastCharacter() == '_')) {
+ string_tmp += lastCharacter();
+ position++;
+ }
+ if (string_tmp.length() > 0) {
+ idx = string_tmp.lastIndexOf("__");
+ if (idx != -1) {
+ position = posold+idx;
+ reporter.syntaxError("Identifier is incorrect.", getPosition());
+ }
+ lastString = getString(string_tmp);
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ public boolean readWord(String st) {
+ int posold,idx;
+ boolean result=false;
+
+ if (! readSpace()) {
+ result = false;
+ } else {
+ posold = position;
+ idx = 0;
+
+ while (idx <= st.length()-1 && lastCharacter() == st.charAt(idx)) {
+ position++;
+ idx++;
+ }
+ if (idx > st.length()-1) {
+ lastString = st;
+ result = true;
+ } else {
+ position = posold;
+ }
+ }
+ return result;
+ }
+
+ public boolean readThisKeyword(String st) {
+ return readWord(st);
+ }
+
+ //-- keyword -> 'A'-'Z' 'a'-'z' {'a'-'z' | '0'-'9' | '_'}
+ public boolean readKeyword() {
+ boolean result=false;
+
+ if (! readSpace() || ! Character.isUpperCase(lastCharacter())) {
+ result = false;
+ } else {
+ string_tmp = "";
+ string_tmp += lastCharacter();
+ position++;
+
+ if (Character.isLowerCase(lastCharacter())) {
+ string_tmp += lastCharacter();
+ position++;
+ while (lastCharacter() != 0 &&
+ (Character.isLowerCase(lastCharacter()) ||
+ Character.isDigit(lastCharacter()) ||
+ lastCharacter() == '_')) {
+ string_tmp += lastCharacter();
+ position++;
+ }
+ lastString = getString(string_tmp);
+ result = true;
+ } else {
+ position--;
+ result = false;
+ }
+ }
+ return result;
+ }
+
+ //-- cap_identifier -> 'A'-'Z' {'A'-'Z' | '0'-'9' | '_'}
+ public boolean readCapIdentifier() {
+ int posold,idx;
+ boolean result=false;
+ char car;
+
+ if (! readSpace() || ! Character.isUpperCase(lastCharacter())) {
+ result = false;
+ } else {
+ posold = position;
+ string_tmp = ""+lastCharacter();
+ position++;
+ isParameterType = true;
+ while (lastCharacter() != 0 &&
+ (Character.isUpperCase(lastCharacter()) ||
+ Character.isDigit(lastCharacter()) ||
+ lastCharacter() == '_')) {
+ car = lastCharacter();
+ isParameterType = isParameterType && (Character.isDigit(car));
+
+ string_tmp += car;
+ position++;
+ }
+ if (Character.isLetter(lastCharacter()) ||
+ Character.isDigit(lastCharacter()) ||
+ lastCharacter() == '_') {
+ reporter.syntaxError("Identifier is incorrect.", getPosition());
+ return false;
+ }
+ idx = string_tmp.lastIndexOf("__");
+ if (idx != -1) {
+ position = posold + idx;
+ reporter.syntaxError("Identifier is incorrect.", getPosition());
+ return false;
+ }
+ lastString = getString(string_tmp);
+ result = true;
+ }
+ return result;
+ }
+
+ //-- integer -> number
+ //-- number -> {'0'-'9'} ['d']
+ //-- | '0'-'9' {'0'-'9' | 'A'-'F' | 'a'-'f'} 'h'
+ //-- | {'0'-'7'} 'o'
+ //-- | {'0' | '1'} 'b'
+ public boolean readInteger() {
+ boolean result=false;
+ //int pos_old;
+
+ if (readSpace() && Character.isDigit(lastCharacter())) {
+ result = true;
+ string_tmp = ""+lastCharacter();
+ //pos_old = position;
+ position++;
+
+ while (isHexadecimalDigit(lastCharacter()) || lastCharacter() == '_') {
+ if (lastCharacter() != '_') {
+ string_tmp += lastCharacter();
+ }
+ position++;
+ }
+ if (lastCharacter() == 'h') {
+ try {
+ Integer integer = Integer.valueOf(string_tmp, 16);
+ lastInteger = integer.intValue();
+ } catch (Exception e) {
+ System.out.println("Warning readInteger : "+e);// FIXME hex string
+ lastInteger = 0;
+ }
+ position++;
+ } else {
+ if (string_tmp.charAt(string_tmp.length()-1) > '9') {
+ string_tmp = string_tmp.substring(0, string_tmp.length()-1);// remove last
+ position--;
+ }
+ if (lastCharacter() == 'o') {
+ if (!isOctal(string_tmp)) {
+ reporter.syntaxError("Incorrect octal number.", getPosition());
+ }
+ lastInteger = Integer.valueOf(string_tmp, 8).intValue();
+ position++;
+ } else if (lastCharacter() == 'b') {
+ if (!isBinary(string_tmp)) {
+ reporter.syntaxError("Incorrect binary number.", getPosition());
+ }
+ lastInteger = Integer.valueOf(string_tmp, 2).intValue();
+ position++;
+ } else {
+ if (lastCharacter() == 'd') {
+ position++;
+ }
+ if (! isInteger(string_tmp)) {
+ reporter.syntaxError("Incorrect decimal number.", getPosition());
+ }
+ lastInteger = Integer.valueOf(string_tmp);
+ }
+ }
+ }
+ return result;
+ }
+
+ private boolean isInteger(String s) {
+ try {
+ Integer.parseInt(s);
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ return true;
+ }
+
+ // True when the contents is a sequence of bits (i.e., mixed
+ // characters `0' and characters `1').
+ private boolean isBinary(String s) {
+ boolean result;
+ int i;
+
+ i = s.length()-1;
+ result = true;
+ while (result && i != 0) {
+ result = s.charAt(i) == '0' || s.charAt(i) == '1';
+ i--;
+ }
+ return result;
+ }
+
+ private boolean isOctal(String s) {
+ try {
+ Integer.parseInt(s, 8);
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isHexadecimalDigit(char c) {
+ boolean result=false;
+
+ if (Character.isDigit(c)) {
+ result = true;
+ } else if (c >= 'a') {
+ result = c <= 'f';
+ } else if (c >= 'A') {
+ result = c <= 'F';
+ }
+ return result;
+ }
+
+ //-- real -> '0'-'9' {'0'-'9'_} [ '.' {'0'-'9'} ] [ 'E' ['+'|'-'] '0'-'9' {'0'-'9'}
+ public boolean readReal() {
+ boolean result=false;
+ int pos_old;
+
+ if (readSpace() && Character.isDigit(lastCharacter())) {
+ string_tmp = ""+lastCharacter();
+ pos_old = position;
+ position++;
+
+ while (Character.isDigit(lastCharacter()) || lastCharacter() == '_') {
+ if (lastCharacter() != '_') {
+ string_tmp += lastCharacter();
+ }
+ position++;
+ }
+ if (lastCharacter() == '.') {
+ string_tmp += '.';
+ position++;
+
+ if (Character.isDigit(lastCharacter())) {
+ result = true;
+ string_tmp += lastCharacter();
+ position++;
+
+ while (Character.isDigit(lastCharacter())) {
+ string_tmp += lastCharacter();
+ position++;
+ }
+ }
+ if (lastCharacter() == 'E') {
+ result = true;
+ string_tmp += 'E';
+ position++;
+
+ if (lastCharacter() == '+' || lastCharacter() == '-') {
+ string_tmp += lastCharacter();
+ position++;
+ }
+ if (Character.isDigit(lastCharacter())) {
+ string_tmp += lastCharacter();
+ position++;
+ while (Character.isDigit(lastCharacter())) {
+ string_tmp += lastCharacter();
+ position++;
+ }
+ } else {
+ reporter.syntaxError("Incorrect real number.", getPosition());
+ }
+ }
+ }
+ if (result) {
+ lastReal = getString(string_tmp);
+ } else {
+ position = pos_old;
+ }
+ }
+ return result;
+ }
+
+ public void readEscapeCharacter() {
+ int val;
+
+ if (isSeparator(lastCharacter())) {
+ position++;
+ while (lastCharacter() != 0 && isSeparator(lastCharacter())) {
+ position++;
+ }
+ if (lastCharacter() == '\\') {
+ string_tmp.substring(0, string_tmp.length()-2); // remove last
+ position++;
+ } else if (lastCharacter() != 0) {
+ reporter.syntaxError("Unknown escape sequence.", getPosition());
+ }
+ } else if (lastCharacter() != 0) {
+ char c = lastCharacter();
+
+ if (c == 'a' ||
+ c == 'b' ||
+ c == 'f' ||
+ c == 'n' ||
+ c == 'r' ||
+ c == 't' ||
+ c == 'v' ||
+ c == '\\' ||
+ c == '?' ||
+ c == '\'' ||
+ c == '\"') {
+ string_tmp += c;
+ position++;
+ } else if (lastCharacter() >= '0' && lastCharacter() <= '9') {
+ if (lastCharacter() == '0' &&
+ position < source.length() &&
+ ! isHexadecimalDigit(source.charAt(position+1))) {
+
+ string_tmp += lastCharacter();
+ position++;
+ } else {
+ String string_tmp2 = new String(string_tmp);
+ readInteger(); // result is Always TRUE.
+ string_tmp = string_tmp2;
+
+ if (lastInteger > 255) {
+ reporter.syntaxError("Invalid range character number [0,255].", getPosition());
+ }
+ val = (int) lastInteger;
+ string_tmp += (val / 64);
+ string_tmp += ((val % 64) / 8);
+ string_tmp += (val % 8);
+ if (lastCharacter() == '\\') {
+ position++;
+ } else {
+ reporter.syntaxError("Character '\' is needed.", getPosition());
+ }
+ }
+ } else {
+ reporter.syntaxError("Unknown escape sequence.", getPosition());
+ }
+ }
+ }
+
+ //-- character -> '\'' ascii '\''
+ public boolean readCharacters() {
+ boolean result=false;
+ int count=0;
+
+ if (readSpace() && lastCharacter() == '\'') {
+ //old_pos = position;
+ position++;
+ string_tmp = "";
+ while (lastCharacter() != 0 && lastCharacter() != '\n' && lastCharacter() != '\'') {
+ string_tmp += lastCharacter();
+ if (lastCharacter() == '\\') {
+ position++;
+ readEscapeCharacter();
+ count++;
+ } else {
+ position++;
+ count++;
+ }
+ }
+ if (lastCharacter() == '\'') {
+ position++;
+ lastString = getString(string_tmp);
+ if (count != 1) {
+ position = begin_position;
+ reporter.syntaxError("Character constant too long.", getPosition());
+ }
+ result = true;
+ } else {
+ position = begin_position;
+ reporter.syntaxError("Unterminated character constant.", getPosition());
+ }
+ }
+ return result;
+ }
+
+ //-- string -> '\"' ascii_string '\"'
+ public boolean readString() {
+ boolean result=false;
+ // int old_pos;
+
+ if (readSpace() && lastCharacter() == '\"') {
+ // old_pos = position;
+ position = position+1;
+ string_tmp = "";
+ while (lastCharacter() != 0 && lastCharacter() != '\n' && lastCharacter() != '\"') {
+ string_tmp += lastCharacter();
+ if (lastCharacter() == '\\') {
+ position = position+1;
+ readEscapeCharacter();
+ } else {
+ position = position+1;
+ }
+ }
+ if (lastCharacter() == '\"') {
+ position = position+1;
+ lastString = getString(string_tmp);
+ result = true;
+ } else {
+ position = begin_position;
+ reporter.syntaxError("Unterminated string constant.", getPosition());
+ }
+ }
+ return result;
+ }
+
+ //-- external -> '`' ascii_c_code '`'
+ public boolean readExternal() {
+ boolean result=false;
+ // int pos_old;
+
+ if ((! readSpace()) || lastCharacter() != '`') {
+ result = false;
+ } else {
+ // pos_old=position;
+ position = position+1;
+ string_tmp = "";
+ while (lastCharacter() != 0 && lastCharacter() != '`') {
+ string_tmp += lastCharacter();
+ if (lastCharacter() == '\\') {
+ position = position+1;
+ string_tmp += lastCharacter();
+ if (lastCharacter() != 0) {
+ position = position+1;
+ }
+ } else {
+ position = position+1;
+ }
+ }
+ if (lastCharacter() != 0) {
+ position = position+1;
+ lastString = getString(string_tmp);
+ result = true;
+ } else {
+ result = false;
+ }
+ }
+ return result;
+ }
+
+ private final String operators = "!@#$%^&<|*-+=~/?\\>";
+
+ public boolean isOperatorSymbol(char c) {
+ return operators.indexOf(c) != -1;
+ }
+
+ //-- 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;
+ }
+
+ public void readTokenAt(int line, int column) {
+ // goto (line,column) position
+ while (! isEOF()) {
+ if (source.charAt(pos_cur) == '\n') {
+ pos_col = 0;
+ pos_line++;
+ } else {
+ pos_col++;
+ }
+ if (pos_line == line && pos_col == column) {
+ position = pos_cur;
+ break;
+ }
+ pos_cur++;
+ }
+ // goto token begining
+ while (position >= 0) {
+ char c = lastCharacter();
+ if (isSeparator(c)) {
+ break;
+ }
+ position--;
+ }
+ // read token
+ position++;
+ string_tmp = "";
+ while (! isEOF()) {
+ char c = lastCharacter();
+ if (isSeparator(c)) {
+ break;
+ }
+ string_tmp += c;
+ position++;
+ }
+ lastString = string_tmp;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/AliasString.java b/editor/eclipse/src/org/lisaac/ldt/model/AliasString.java
new file mode 100644
index 0000000..c3e214c
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/AliasString.java
@@ -0,0 +1,84 @@
+package org.lisaac.ldt.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.prototype_block);
+
+ list.add(ILisaacModel.variable_null);
+ list.add(ILisaacModel.variable_void);
+ list.add(ILisaacModel.variable_self);
+
+ // lip
+ list.add(ILisaacModel.slot_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/editor/eclipse/src/org/lisaac/ldt/model/ILisaacContext.java b/editor/eclipse/src/org/lisaac/ldt/model/ILisaacContext.java
new file mode 100644
index 0000000..168cb32
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/ILisaacContext.java
@@ -0,0 +1,20 @@
+package org.lisaac.ldt.model;
+
+import org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/ILisaacFileVisitor.java b/editor/eclipse/src/org/lisaac/ldt/model/ILisaacFileVisitor.java
new file mode 100644
index 0000000..9c16926
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/ILisaacFileVisitor.java
@@ -0,0 +1,8 @@
+package org.lisaac.ldt.model;
+
+import org.lisaac.ldt.model.items.Prototype;
+
+public interface ILisaacFileVisitor {
+
+ void visit(Prototype prototype);
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/ILisaacModel.java b/editor/eclipse/src/org/lisaac/ldt/model/ILisaacModel.java
new file mode 100644
index 0000000..6ce8e63
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/ILisaacModel.java
@@ -0,0 +1,96 @@
+package org.lisaac.ldt.model;
+
+import org.eclipse.core.resources.IProject;
+import org.lisaac.ldt.builder.ILisaacErrorHandler;
+import org.lisaac.ldt.model.lip.LIP;
+
+public interface ILisaacModel {
+
+ final String[] keywords = new String[] { "Section", "Public",
+ "Private", "Inherit", "Header", "Insert", "Mapping", "Interrupt",
+ "External", "Directory",
+ "Expanded", "Strict",
+ "Left", "Right",
+ "Self",};
+
+ 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 prototype_block = "BLOCK";
+
+ final String variable_null = "NULL";
+ final String variable_void = "VOID";
+ final String variable_self = "Self";
+
+ // lip
+ final String slot_lip = "lip";
+ final String slot_if = "if";
+ final String slot_else = "else";
+ final String slot_print = "print";
+
+ final String slot_debug_mode = "debug_mode";
+
+ ILisaacErrorHandler getReporter();
+ AliasString getAliasString();
+ LisaacParser getParser();
+ LIP getLipCode();
+ IProject getProject();
+ LisaacPath getPathManager();
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/LipParser.java b/editor/eclipse/src/org/lisaac/ldt/model/LipParser.java
new file mode 100644
index 0000000..fe22d7d
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/LipParser.java
@@ -0,0 +1,465 @@
+package org.lisaac.ldt.model;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+
+import org.lisaac.ldt.model.lip.*;
+
+
+public class LipParser extends AbstractLisaacParser {
+
+ public LIP lipFile;
+
+ public LipParser(InputStream contents, ILisaacModel model) {
+ super(contents, model);
+ this.lipFile = model.getLipCode();
+ }
+
+ public LipParser(String contents, int offset) {
+ super(contents);
+ setPosition(offset);
+ }
+
+ //
+ // 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.", getLine());
+ return false;
+ }
+ if (! readCharacter(':')) {
+ reporter.syntaxError("Added ':' is needed.", getLine());
+ return false;
+ }
+ if (! readWord(ILisaacModel.prototype_string)) {
+ reporter.warning("`STRING' type needed.", getLine());
+ }
+ if (readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ if (! readString()) {
+ reporter.syntaxError("String needed.", getLine());
+ 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.", getLine());
+ 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.", getLine());
+ return false;
+ }
+ result = true;
+ }
+ } else {
+ reporter.syntaxError("`Public' or `Private' or `Inherit' needed.", getLine());
+ return false;
+ }
+ }
+ if (position < source.length()-2) {
+ result = false;
+ }
+
+ // TODO recursive parsing !!!
+ 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(1));
+ }
+ if (! readIdentifier()) {
+ reporter.syntaxError("Identifier is incorrect.", getLine());
+ return false;
+ }
+ String n = new String(lastString);
+ if (! readCharacter(':')) {
+ reporter.syntaxError("Added ':' is needed.", getLine());
+ return false;
+ }
+ LIPConstant t = readType();
+ if (t == null) {
+ reporter.syntaxError("type is incorrect.", getLine());
+ 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.", getLine());
+ return false;
+ }
+ data.setValue(cst);
+ cst.free();
+ }
+ } else if (readCharacter('-')) {
+ // Function.
+ result = true;
+ if (! readIdentifier()) {
+ reporter.syntaxError("Identifier is incorrect.", getLine());
+ 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.", getLine());
+ return false;
+ }
+ LIPConstant t = readType();
+ if (t == null) {
+ reporter.syntaxError("Incorrect type.", getLine());
+ return false;
+ }
+ data = new LIPSlotData(na, t);// do not add argument do lipFile
+ }
+ //
+ if (! readSymbol(ILisaacModel.symbol_affect_code)) {
+ reporter.syntaxError("Added '<-' is needed.", getLine());
+ return false;
+ }
+ if (! readCharacter('(')) {
+ reporter.syntaxError("Added '(' is needed.", getLine());
+ 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.", getLine());
+ return false;
+ }
+ }
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')' is needed.", getLine());
+ 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.", getLine());
+ }
+ }
+ return result;
+ }
+
+ //// EXPR -> [ identifier !!AMBIGU!! ':=' ] EXPR_OPERATOR [ '.' FUNCTION ]
+ public 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.", getLine());
+ 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.", getLine());
+ 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.", getLine());
+ return null;
+ }
+ LIPCode val;
+ while ((val = readExpr()) != null) {
+ thenArray.add(val);
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';' is needed.", getLine());
+ return null;
+ }
+ }
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}' is needed.", getLine());
+ return null;
+ }
+ if (readWord(ILisaacModel.slot_else)) {
+ elseArray = new ArrayList<LIPCode>();
+ if (! readCharacter('{')) {
+ reporter.syntaxError("Added '{' is needed.", getLine());
+ return null;
+ }
+ while ((val = readExpr()) != null) {
+ elseArray.add(val);
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';' is needed.", getLine());
+ return null;
+ }
+ }
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}' is needed.", getLine());
+ 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.", getLine());
+ 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.", getLine());
+ 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.", getLine());
+ 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.", getLine());
+ 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.", getLine());
+ return null;
+ }
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')' is needed.", getLine());
+ 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.", getLine());
+ }
+ }
+ 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/editor/eclipse/src/org/lisaac/ldt/model/LisaacCompletionParser.java b/editor/eclipse/src/org/lisaac/ldt/model/LisaacCompletionParser.java
new file mode 100644
index 0000000..d539280
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/LisaacCompletionParser.java
@@ -0,0 +1,193 @@
+package org.lisaac.ldt.model;
+
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.editors.LisaacEditor;
+import org.lisaac.ldt.model.items.ICode;
+import org.lisaac.ldt.model.items.ITMRead;
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.model.items.Slot;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.TypeSelf;
+import org.lisaac.ldt.outline.OutlineImages;
+
+public class LisaacCompletionParser extends LisaacParser {
+ protected static LisaacModel model;
+
+ protected Prototype currentPrototype;
+ protected Slot currentSlot;
+
+ protected int endOffset;
+
+
+
+ public LisaacCompletionParser(String contents, LisaacModel model) {
+ super(null,contents);
+ LisaacCompletionParser.model = model;
+ }
+
+ /**
+ * 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<ICompletionProposal> proposals)
+ throws CoreException {
+ IType type;
+
+ currentPrototype = LisaacModel.getCurrentPrototype();
+ currentSlot = currentPrototype.getSlot(startOffset);
+ endOffset = -1;
+
+ // keyword match
+ while (readKeyword()) {
+ if (baseOffset != (startOffset+position)) {
+ continue;// not last keyword
+ }
+ String[] keywords = ILisaacModel.keywords;
+ for (int i = 0; i < keywords.length; i++) {
+ if (keywords[i].startsWith(lastString)) {// length(keyword[i]) >= length(lastString)
+ String keywordCompletion = keywords[i].substring(lastString.length());
+ proposals.add(new CompletionProposal(keywordCompletion,
+ baseOffset, 0, keywordCompletion.length(),
+ OutlineImages.KEYWORD, keywords[i], null, ""));
+ }
+ }
+ return;
+ }
+
+ // slot match
+ ICode code = readExpr();
+ if (code != null && currentPrototype != null) {
+ type = code.getType(currentSlot, currentPrototype);
+ if (type != null) {
+ //if (! type.equals(TypeSimple.getTypeSelf())) {
+ //if ("SELF".compareTo(type.toString()) != 0) {
+ if (type instanceof TypeSelf) {
+ currentPrototype = findPrototype(((TypeSelf) type).getStaticType());
+ } else {
+ currentPrototype = findPrototype(type.toString());
+ }
+ if (currentPrototype != null) {
+ currentPrototype.getSlotProposals(proposals, baseOffset, 0);
+ proposals.add(new CompletionProposal(""+type,baseOffset,0,0));
+ } else {
+ // partial prototype name
+ String prefix = type.toString();
+ model.getPathManager().getPathMatch(prefix, proposals, baseOffset);
+ }
+ } else {
+ // partial slot name (first keyword)
+ if (code instanceof ITMRead) {
+ String prefix = ((ITMRead) code).getName();
+ currentPrototype.lookupSlotMatch(prefix, proposals, baseOffset, 0);
+ }
+ }
+ }
+ }
+
+ //++ EXPR_MESSAGE -> EXPR_BASE { '.' SEND_MSG }
+ protected ICode readExprMessage() {
+
+ ICode result = readExprBase();
+ if (result != null) {
+ while (readCharacter('.')) {
+ if (endOffset != -1 && position == endOffset+1) {
+ break;
+ }
+ ICode lastResult = result;
+ result = readSendMsg(result);
+ if (result == null) {
+ return lastResult;
+ }
+ // update source of completion
+ IType type = lastResult.getType(currentSlot, currentPrototype);
+ //if (type != null && ! type.equals(TypeSimple.getTypeSelf())) {
+ if (type != null && "SELF".compareTo(type.toString()) != 0) {
+ try {
+ currentPrototype = findPrototype(type.toString());
+ } catch(CoreException e) {
+ return null;
+ }
+ if (currentPrototype == null) {
+ return null;
+ }
+ if (result instanceof ITMRead) {
+ currentSlot = currentPrototype.lookupSlot(((ITMRead) result).getName());
+ } else {
+ currentSlot = null;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+
+ public Prototype readReceiver(int startOffset, int endOffset, Prototype currentPrototype) throws CoreException {
+ Prototype result=null;
+ IType type;
+
+ this.currentPrototype = currentPrototype;//LisaacModel.getCurrentPrototype();
+ currentSlot = currentPrototype.getSlot(startOffset);
+ this.endOffset = endOffset;
+
+ setPosition(startOffset);
+ readSpace();
+
+ ICode code = readExpr();
+ if (code != null && currentPrototype != null) {
+ type = code.getType(currentSlot, currentPrototype);
+ if (type != null) {
+ //if (! type.equals(TypeSimple.getTypeSelf())) {
+ if (type.toString() != null && "SELF".compareTo(type.toString()) != 0) {
+ Prototype save = currentPrototype;
+ currentPrototype = findPrototype(type.toString());
+ if (currentPrototype == null) {
+ currentPrototype = save;
+ }
+ }
+ result = currentPrototype;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Find and parse a lisaac prototype according to its name.
+ */
+ public static Prototype findPrototype(String prototypeName) throws CoreException {
+ IProject project = null;
+
+ if (model == null) {
+ IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+ if (w == null) {
+ return null;
+ }
+ IWorkbenchPart part = w.getPartService().getActivePart();
+ if (part instanceof LisaacEditor) {
+ project = ((LisaacEditor)part).getProject();
+ }
+ if (project != null) {
+ model = LisaacModel.getModel(project);
+ }
+ }
+ if (model == null) {
+ return null;
+ }
+ if (project == null) {
+ project = model.getProject();
+ }
+ return model.getPrototype(prototypeName);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/LisaacModel.java b/editor/eclipse/src/org/lisaac/ldt/model/LisaacModel.java
new file mode 100644
index 0000000..e0913ae
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/LisaacModel.java
@@ -0,0 +1,309 @@
+package org.lisaac.ldt.model;
+
+import java.io.InputStream;
+import java.util.HashMap;
+
+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.resources.IResourceVisitor;
+import org.eclipse.core.resources.ResourceAttributes;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.builder.ILisaacErrorHandler;
+import org.lisaac.ldt.editors.AbstractLisaacEditor;
+import org.lisaac.ldt.editors.LisaacEditor;
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.model.lip.LIP;
+
+/**
+ * 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;
+
+ /** error handler */
+ private ILisaacErrorHandler reporter;
+
+ /** lisaac parser */
+ private LisaacParser parser;
+
+ /** string aliaser */
+ private AliasString aliasString;
+
+ /** modification flag */
+ private boolean isProjectCompiled;
+
+ public static AbstractLisaacEditor currentEditor = null;
+
+
+ public LisaacModel(IProject project) {
+ this.project = project;
+ prototypes = new HashMap<String,Prototype>();
+ aliasString = new AliasString();
+
+ // 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
+ isProjectCompiled = false;
+ }
+
+ public IProject getProject() {
+ return project;
+ }
+ public void setProject(IProject project) {
+ this.project = project;
+ }
+
+ 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) throws CoreException {
+ Prototype result=null;
+
+ if (prototypes != null) {
+ result = prototypes.get(name); // prototype is already cached
+
+ if (result == null) {
+ // cache new prototype
+ String prototypePath = modelPath.getFullPath(name);
+ if (prototypePath != null) {
+ IPath location = new Path(prototypePath);
+ IPath projectLocation = project.getLocation();
+ IFile file = null;
+
+ if (projectLocation.isPrefixOf(location)) {
+ // the file is inside the workspace
+ location = location.removeFirstSegments(projectLocation.segmentCount());
+ file = project.getFile(location);
+ } else {
+ // file is outside workspace : create link in /lib
+ IContainer lib = project.getFolder("lib");
+ if (lib == null) {
+ lib = project;
+ }
+ file = lib.getFile(new Path(location.lastSegment()));
+ if (! file.isAccessible() && ! file.exists()) {
+ file.createLink(location, IResource.NONE, null);
+ //
+ ResourceAttributes attrib = new ResourceAttributes();
+ attrib.setReadOnly(true);
+ file.setResourceAttributes(attrib);
+ //
+ }
+ }
+ result = parsePrototype(file, 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;
+ }
+
+ public void refreshPresentation() {
+ final IWorkbenchPart part = currentEditor;
+ Display display = PlatformUI.getWorkbench().getDisplay();
+
+ if (currentEditor != null) {
+ display.asyncExec(new Runnable() {
+ public void run() {
+ ((AbstractLisaacEditor)part).refreshPresentation();
+ }
+ });
+ }
+ }
+
+ public void accept(final ILisaacFileVisitor visitor) {
+ try {
+ project.accept(new IResourceVisitor() {
+ public boolean visit(IResource resource) throws CoreException {
+ if (resource instanceof IFile) {
+ if (resource.getName().endsWith(".li")) {
+ String name = extractPrototypeName(resource.getName());
+ visitor.visit(getPrototype(name));
+ }
+ }
+ return true;
+ }
+ });
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /** parse and create part of current model */
+ public Prototype parsePrototype(IFile file, InputStream contents, ILisaacErrorHandler reporter) {
+ this.reporter = reporter;
+
+ String name = file.getName();
+ String prototypeName = extractPrototypeName(name);
+
+ modelPath.addPath(prototypeName, file.getLocation());
+
+ parser = new LisaacParser(prototypeName, contents, this);
+ Prototype prototype = new Prototype(file, prototypeName, this);
+
+ ILisaacContext context = parser.readContext();
+ while (context != null) {
+ if (context.parseDefinition(prototype)) {
+ context = parser.readContext();
+ } else {
+ context = context.getNextContext();
+ }
+ }
+ parser.setLastSection(null);// close last section
+
+ // 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() throws CoreException {
+ IWorkbenchWindow w = LisaacPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+ if (w == null) {
+ return null;
+ }
+ IPartService service = w.getPartService();
+ if (service == null) {
+ return null;
+ }
+ IWorkbenchPart part = service.getActivePart();
+ if (part == null || !(part instanceof LisaacEditor)) {
+ part = currentEditor;
+ }
+ 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;
+ }
+
+ public void refreshPath() {
+ // create lisaac path
+ modelPath = new LisaacPath(project, "make.lip"); // TODO get lip from property page
+ }
+
+ public boolean needCompilation() {
+ return !isProjectCompiled;
+ }
+
+ public void setCompiled(boolean done) {
+ isProjectCompiled = done;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/LisaacParser.java b/editor/eclipse/src/org/lisaac/ldt/model/LisaacParser.java
new file mode 100644
index 0000000..994bd3f
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/LisaacParser.java
@@ -0,0 +1,1554 @@
+package org.lisaac.ldt.model;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.lisaac.ldt.model.items.IArgument;
+import org.lisaac.ldt.model.items.ICode;
+import org.lisaac.ldt.model.items.IConstant;
+import org.lisaac.ldt.model.items.ITMArgs;
+import org.lisaac.ldt.model.items.ITMArgument;
+import org.lisaac.ldt.model.items.ITMBlock;
+import org.lisaac.ldt.model.items.ITMCharacter;
+import org.lisaac.ldt.model.items.ITMExpression;
+import org.lisaac.ldt.model.items.ITMExternal;
+import org.lisaac.ldt.model.items.ITMExternalType;
+import org.lisaac.ldt.model.items.ITMLDots;
+import org.lisaac.ldt.model.items.ITMList;
+import org.lisaac.ldt.model.items.ITMListIdf;
+import org.lisaac.ldt.model.items.ITMLocal;
+import org.lisaac.ldt.model.items.ITMNumber;
+import org.lisaac.ldt.model.items.ITMOld;
+import org.lisaac.ldt.model.items.ITMOperator;
+import org.lisaac.ldt.model.items.ITMPrototype;
+import org.lisaac.ldt.model.items.ITMRead;
+import org.lisaac.ldt.model.items.ITMReadArg1;
+import org.lisaac.ldt.model.items.ITMReadArg2;
+import org.lisaac.ldt.model.items.ITMReadArgs;
+import org.lisaac.ldt.model.items.ITMReal;
+import org.lisaac.ldt.model.items.ITMResult;
+import org.lisaac.ldt.model.items.ITMString;
+import org.lisaac.ldt.model.items.ITMWrite;
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.model.items.Section;
+import org.lisaac.ldt.model.items.Slot;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.ITypeMono;
+import org.lisaac.ldt.model.types.TypeBlock;
+import org.lisaac.ldt.model.types.TypeGeneric;
+import org.lisaac.ldt.model.types.TypeMulti;
+import org.lisaac.ldt.model.types.TypeParameter;
+import org.lisaac.ldt.model.types.TypeSelf;
+import org.lisaac.ldt.model.types.TypeSimple;
+
+/**
+ * Lisaac Prototype Parser
+ */
+
+
+public class LisaacParser extends AbstractLisaacParser {
+
+ private String selfType;
+
+ private ILisaacContext sectionContext;
+ private ILisaacContext slotContext;
+
+ //
+ private Slot lastSlot;
+ private ITMList lastGroup;
+ private Section lastSection;
+ //
+
+ public LisaacParser(String selfType, InputStream contents, ILisaacModel model) {
+ super(contents, model);
+ this.model = model;
+ this.selfType = selfType;
+ sectionContext = new SectionContext(this);
+ slotContext = new SlotContext(this);
+
+ initialize();
+ }
+
+ public LisaacParser(String selfType, String contents) {
+ super(contents);
+ this.selfType = selfType;
+ initialize();
+ }
+
+ public void initialize() {
+ //
+ // initialisations
+ //
+ super.initialize();
+ TypeSimple.init();
+ }
+
+ public ILisaacContext getSectionContext() {
+ return sectionContext;
+ }
+
+ public Slot getLastSlot() {
+ return lastSlot;
+ }
+
+ public void setLastSection(Section section) {
+ if (lastSection != null) {
+ // update last section length
+ Position pos = lastSection.getPosition();
+ pos.setLength(position - pos.offset);
+
+ // update link
+ lastSection.setNext(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) && ! (t instanceof TypeSelf)) {
+ reporter.syntaxError("For a section, the prototype name only (without '('...')').", getLine());
+ return null;
+ }
+ }
+ lst = new ArrayList<ITypeMono>();
+ lst.add(t);
+ while (readCharacter(',')) {
+ t = readType(false);
+ if (t == null) {
+ reporter.syntaxError("Incorrect type list.", getLine());
+ return null;
+ }
+ if (isSection) {
+ if (! (t instanceof TypeSimple)) {
+ reporter.syntaxError("For a section, the prototype name only (without '('...')').", getLine());
+ 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.", getLine());
+ return null;
+ }
+ if (lst.length == 1) {
+ typ_arg = lst[0];
+ } else {
+ typ_arg = TypeMulti.get(lst);
+ }
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')'.", getLine());
+ return null;
+ }
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';'.", getLine());
+ }
+ // 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 '}'.", getLine());
+ 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))) {
+ int len = ILisaacModel.keyword_expanded.length();
+ reporter.syntaxError("`Expanded' is not possible.", getPosition(len));
+ }
+ }
+ // 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.", getLine());
+ 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 ')'.", getLine());
+ return result;
+ }
+ } else {
+ // Simple type.
+ if (isParameterType) {
+ if (style != null) {
+ reporter.warning("Style `"+style+"' for parameter type is ignored.", getPosition(name.length()));
+ }
+ result = TypeParameter.get(name);
+ } else if (style == null) {
+ if (name.equals(ILisaacModel.prototype_self)) {
+ result = TypeSelf.get(selfType);
+ } else {
+ result = TypeSimple.get(name);
+ }
+ } else {
+ if (name.equals(ILisaacModel.prototype_self)) {
+ reporter.warning("Style `"+style+"' ignored.", getPosition(name.length()));
+ result = TypeSelf.get(selfType);
+ } else {
+ if (name.equals(ILisaacModel.prototype_self)) {
+ result = TypeSelf.get(selfType);
+ } else {
+ result = TypeSimple.get(name);
+ }
+ }
+ }
+ }
+ }
+ 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.", getLine());
+ 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.", getLine());
+ return false;
+ }
+ if (! readCharacter(')')) {
+ reporter.warning("Added ')' is needed.", getLine());
+ }
+ t = TypeMulti.get(lt);
+ } else {
+ t = readType(false);
+ if (t == null) {
+ reporter.syntaxError("Incorrect result type.", getLine());
+ return false;
+ }
+ }
+ if (readAffect()) {
+ affect = lastString.charAt(0);
+ }
+ } else {
+ t = TypeSimple.getTypeVoid();
+ }
+ lastSlot.setResultType(t);
+ lastSlot.setAffect(affect);
+
+ setCatchComment();
+
+ if (affect != ' ') {
+ readSpace();
+
+ setCatchCommentOff();
+
+ //
+ readDefSlot();
+ //
+ }
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';'.", getLine());
+ return false;
+ }
+ // update slot body position
+ updateLine();
+ Position body = lastSlot.getPositionBody();
+ if (body.line != pos_line) {
+ body.setLength(position - body.offset);
+ } else {
+ // one line slot - delete position
+ lastSlot.setBody(null);
+ }
+
+ if (lastComment != null && lastComment.length() > 0) {
+ lastSlot.setComment(lastComment);
+ }
+ if (lastSection.isInheritOrInsert()) {
+ // Add parent slot
+ Slot s = prototype.getParentSlot(lastSlot.getName());
+ if (s != null) {
+ reporter.semanticError("Double slot declaration.", getPosition());
+ } else {
+ prototype.addParentSlot(lastSlot);
+ }
+ } else {
+ // Added slot in prototype :
+ Slot s = prototype.getSlot(lastSlot.getName());
+ if (s != null) {
+ reporter.semanticError("Double slot declaration.", getPosition());
+ } else {
+ prototype.addSlot(lastSlot);
+ lastSection.addSlot(lastSlot);
+ }
+ }
+ }
+ return result;
+ }
+
+ //++ DEF_SLOT -> [CONTRACT] EXPR [CONTRACT]
+ private void readDefSlot() {
+
+ readRequire();
+ ICode expr = readExpr();
+ if (expr == null) {
+ reporter.syntaxError("Incorrect expression.", getLine());
+ }
+ 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();
+ Position slotBody = 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.", getLine());
+ 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()]));
+ result.setBody(slotBody);
+ //
+ }
+ 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())) {
+
+ int startPos = position;
+
+ //Position pos = getPosition();
+ String n = new String(lastString);
+ if (readCharacter(':') && lastCharacter() != '=') {
+ ITypeMono t = readType(true);
+ if (t == null) {
+ reporter.syntaxError("Incorrect type.", getLine());
+ 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());
+ }*/
+ Position p = getPosition();
+ p.offset = startPos;
+ result = new ITMArgument(n, t, p);
+ } else {
+ if (! mute) {
+ reporter.warning("Added ':' is needed.", getLine());
+ }
+ }
+ } else if (readCharacter('(')) {
+ result = readLocalArg(mute, selfFirst);
+ if (result == null) {
+ if (! mute) {
+ reporter.syntaxError("Incorrect argument definition.", getLine());
+ return null;
+ }
+ } else {
+ if (! readCharacter(')')) {
+ reporter.warning("Added ')'.", getPosition());
+ }
+ }
+ }
+ return result;
+ }
+
+ private IArgument readLocalArg(boolean m, boolean s) {
+ IArgument result=null;
+ boolean mute = m;
+ int startPos;
+
+ int firstPos = position;
+
+ 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.", getLine());
+ return null;
+ }
+
+ startPos = position;
+
+ name.add(lastString);
+ if (readCharacter(':') && lastCharacter() != '=') {
+ mute = false;
+ ITypeMono t = readType(true);
+
+ if (t == null) {
+ reporter.syntaxError("Incorrect argument type.", getLine());
+ 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.", getLine());
+ 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.
+ Position p = new Position(0,0,startPos, 0);
+
+ result = new ITMArgument(name.get(0), type.get(0), p);
+
+ // 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, getPosition(position - firstPos));
+ }
+ }
+ }
+ return result;
+ }
+
+ private Slot readSlotOperator(ArrayList<IArgument> list_arg) {
+ Slot result=null;
+ String associativity=null;
+ int priority=0;
+ Position slotPosition = getPosition();
+ Position slotBody = getPosition();
+
+ if (! readOperator()) {
+ reporter.syntaxError("Operator is needed.", getLine());
+ return null;
+ }
+ if (lastString.equals(ILisaacModel.symbol_equal) ||
+ lastString.equals(ILisaacModel.symbol_not_equal)) {
+ reporter.syntaxError("Incorrect operator.", getLine());
+ return null;
+ }
+ String name = new String(lastString);
+ slotPosition.setLength(name.length());
+
+ if (! readCharacter('\'')) {
+ reporter.warning("Added `''.", getLine());
+ }
+ 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.", getLine());
+ return null;
+ }
+ if (arg != null) {
+ list_arg.add(arg);
+ }
+ name = getOperator("__prefix", name);
+ if (associativity != null) {
+ reporter.syntaxError("No associativity for postfix operator.", getLine());
+ }
+ } 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.", getLine());
+ }
+ }
+ }
+ result = new Slot(slotPosition, name, lastSection);
+ result.setAssociativity(associativity, priority);
+ result.setBody(slotBody);
+
+ 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 = new ITMListIdf(l_assignment);
+
+ char affect = lastString.charAt(0);
+ ICode value = readExpr();
+ if (value == null) {
+ reporter.syntaxError("Incorrect expression.", getLine());
+ return null;
+ }
+ if (affect == '<') {
+ reporter.syntaxError("Impossible '<-' style assignment with vector.", getPosition(lastString.length()));
+ return null;
+ }
+ result = new ITMWrite(result, value, affect);
+ } 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.", getLine());
+ return null;
+ }
+ result = new ITMWrite(result, value, affect);
+ }
+ }
+ 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.", getLine());
+ }
+ // 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.", getLine());
+ return null;
+ }
+ }
+ }
+ return result;
+ }
+
+ //++ EXPR_BASE -> "Old" EXPR
+ //++ | EXPR_PRIMARY
+ //++ | SEND_MSG
+ public ICode readExprBase() {
+ ICode result=null;
+
+ if (readThisKeyword(ILisaacModel.keyword_old)) {
+ ICode old_value = readExpr();
+ if (old_value == null) {
+ reporter.syntaxError("Incorrect `Old' expression.", getLine());
+ 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;
+
+ readSpace();
+ Position pos = getPosition();
+
+ 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.", getLine());
+ }
+ 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, pos);
+
+ } else if ((result = readConstant()) != null) {
+ } else if (readCharacter('(')) {
+ group_sav = lastGroup;
+ lastGroup = new ITMList(lastSlot, position);
+ result = lastGroup;
+
+ lastGroup.setCode(readGroup());
+ if (! readCharacter(')')) {
+ reporter.syntaxError("Added ')'.", getLine());
+ return null;
+ }
+ lastGroup.setEndOffset(position);
+ lastGroup = group_sav;
+ } else if (readCharacter('{')) {
+ group_sav = lastGroup;
+ lastGroup = new ITMList(lastSlot, position);
+
+ saveContext(); // !! SAVE CONTEXT !!
+
+ //
+ IArgument arg = readLocArg(true,false);
+ //
+ if (arg != null) {
+ if (! readCharacter(';')) {
+ reporter.syntaxError("Added ';'.", getLine());
+ return null;
+ }
+ } else {
+ restoreContext(); // !! RESTORE CONTEXT !!
+ }
+ result = new ITMBlock(lastGroup, arg, lastSlot);
+
+ lastGroup.setCode(readGroup());
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}'.", getLine());
+ return null;
+ }
+ lastGroup.setEndOffset(position);
+ 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.", getLine());
+ return null;
+ }
+ ext.setType(type);
+ if (readCharacter('{')) {
+ ITypeMono[] ltype = readTypeList(false);
+ if (ltype == null) {
+ reporter.syntaxError("Incorrect live type list.", getLine());
+ return null;
+ }
+ if (! readCharacter('}')) {
+ reporter.syntaxError("Added '}'.", getLine());
+ return null;
+ }
+ ext.setTypeList(ltype);
+ }
+ if (ext.isPersistant() && (! readCharacter(')'))) {
+ reporter.syntaxError("Added '}'.", getLine());
+ 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.", getLine());
+ 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 ';'.", getLine());
+ }
+ 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 } ]
+ public 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.", getLine());
+ 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.", getLine());
+ return null;
+ }
+ ITMLocal loc = new ITMLocal(new String(lastString), getPosition());
+ result.add(loc);
+ if (readCharacter(':') && lastCharacter() != '=') {
+ mute = false;
+ ITypeMono t = readType(false);
+ if (t == null) {
+ reporter.syntaxError("Incorrect local type.", getLine());
+ 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.", getLine());
+ 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(lastSlot, position);
+ 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 ';'.", getLine());
+ return null;
+ }
+ doContinue = true;
+ }
+ } while (doContinue);
+
+ if (! readCharacter(']')) {
+ reporter.syntaxError("Added ']'.", getLine());
+ return null;
+ }
+ // TODO lst add prototype void
+ result.setCode(lst.toArray(new ICode[lst.size()]));
+ result.setEndOffset(position);
+ }
+ 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, boolean modifyCurrentOffset) {
+ 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();
+ }
+ }
+ if (! modifyCurrentOffset) {
+ 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;
+ }
+
+ //++ SEND_MSG -> identifier [ ARGUMENT { identifier ARGUMENT } ]
+ public String readKeywordInSendMsg(String keyword, int keywordOffset) {
+ String result=null;
+ boolean keywordFound=false;
+
+ if (readIdentifier()) {
+ //
+ // Classic Message.
+ //
+ String n = getString(lastString);// create alias
+ if (n.compareTo(keyword) == 0 && position == keywordOffset+keyword.length()) {
+ keywordFound = true;
+ }
+ // Argument list.
+ ICode arg = readArgument();
+ if (arg != null) {
+ while (readIdentifier()) {
+ if (lastString.compareTo(keyword) == 0 && position == keywordOffset+keyword.length()) {
+ keywordFound = true;
+ }
+ n += "__" + lastString; // FIXME: alias pb
+ arg = readArgument();
+ if (arg == null) {
+ reporter.syntaxError("Incorrect argument.", getPosition());
+ return null;
+ }
+ }
+ }
+ // return slot full name
+ result = getString(n); // FIXME alias pb
+ }
+ if (! keywordFound) {
+ result = null;
+ }
+ return result;
+ }
+
+ /**
+ * Read the next context in lisaac code.
+ * @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", getLine());
+ return sectionContext.getNextContext(); // go to next section
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/LisaacPath.java b/editor/eclipse/src/org/lisaac/ldt/model/LisaacPath.java
new file mode 100644
index 0000000..0872307
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/LisaacPath.java
@@ -0,0 +1,124 @@
+package org.lisaac.ldt.model;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.lisaac.ldt.launch.LisaacCompiler;
+import org.lisaac.ldt.outline.OutlineImages;
+
+
+public class LisaacPath {
+
+ private HashMap<String,String> prototypesPath;
+
+ private LisaacCompiler compiler;
+
+ private String lipFile;
+
+
+ public LisaacPath(final IProject project, String lipFile) {
+ prototypesPath = new HashMap<String,String>();
+ this.lipFile = lipFile;
+
+ refreshPath(project);
+ }
+
+ public void refreshPath(final IProject project) {
+ try {
+ compiler = new LisaacCompiler(lipFile);
+ compiler.addOption("--p");
+
+ System.out.println("===> "+compiler.toCommandLine());
+
+ try {
+ final Process process = compiler.launch(project, new NullProgressMonitor());
+
+ if (process != null) {
+ try {
+ // wait for end of process
+ process.waitFor();
+ } catch(InterruptedException e) {
+ }
+ }
+ BufferedReader bufferIn = new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(project.getLocation()+"/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 (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } catch (CoreException e) {
+ //LisaacPlugin.log(status) // TODO log error
+ e.printStackTrace();
+ } catch (Exception e) {
+ 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);
+ }
+
+
+ public void getPathMatch(String prefix,
+ ArrayList<ICompletionProposal> proposals, int baseOffset) {
+
+ Collection<String> values = prototypesPath.keySet();
+ Iterator<String> it = values.iterator() ;
+ while (it.hasNext()) {
+ String name = it.next();
+ if (name.startsWith(prefix)) {
+ int lenPrefix = prefix.length();
+ int lenName = name.length();
+ proposals.add(new CompletionProposal(name, baseOffset-lenPrefix, lenPrefix, lenName,
+ OutlineImages.PROTOTYPE, name, null, null));
+ }
+ }
+ }
+
+ public void addPath(String prototypeName, IPath location) {
+ prototypesPath.put(prototypeName, location.toString());
+ }
+
+ public int getSize() {
+ return prototypesPath.size();
+ }
+
+ public Iterator<String> getPathIterator() {
+ return prototypesPath.values().iterator();
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/Position.java b/editor/eclipse/src/org/lisaac/ldt/model/Position.java
new file mode 100644
index 0000000..3c2b8fa
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/Position.java
@@ -0,0 +1,52 @@
+package org.lisaac.ldt.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 offset-length;
+ }
+ public int getCharEnd() {
+ return offset;
+ }
+
+ public int getStartOffset() {
+ return offset;
+ }
+
+ public int length() {
+ return length;
+ }
+ public void setLength(int l) {
+ length = l;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/SectionContext.java b/editor/eclipse/src/org/lisaac/ldt/model/SectionContext.java
new file mode 100644
index 0000000..3596bdf
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/SectionContext.java
@@ -0,0 +1,306 @@
+package org.lisaac.ldt.model;
+
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.model.items.Section;
+import org.lisaac.ldt.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) {
+ Position sectionPosition;
+
+ parser.readSpace();
+
+ // read Section
+ if (! parser.readThisKeyword (ILisaacModel.keyword_section)) {
+ parser.getReporter().syntaxError("`Section' is needed.", parser.getLine());
+ return false;
+ }
+ sectionPosition = parser.getPosition();
+
+ if (firstSection) {
+ //
+ // Read Section Header.
+ //
+ if (! parser.readThisKeyword (ILisaacModel.section_header)) {
+ parser.getReporter().syntaxError("Section `Header' is needed.", parser.getLine());
+ 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, sectionPosition);
+ parser.setLastSection(lastSection);
+
+ if (prototype.getFirstSection() == null) {// section list head
+ prototype.setFirstSection(lastSection);
+ }
+
+ if (lastSection.isInheritOrInsert() &&
+ parser.getLastSlot() != null &&
+ ! parser.getLastSlot().getSectionId().isInheritOrInsert()) {
+ parser.getReporter().syntaxError("`Section Inherit/Insert' must to be first section.", parser.getLine());
+ 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.getLine());
+ }
+ } else {
+ parser.getReporter().syntaxError("Incorrect type section.", parser.getLine());
+ return false;
+ }
+ } else {
+ // TYPE_LIST.
+ ITypeMono[] t = parser.readTypeList(true);
+ if (t == null) {
+ parser.getReporter().syntaxError("Incorrect type section.", parser.getLine());
+ return false;
+ }
+ parser.setLastSection(new Section(prototype, t, sectionPosition));
+ }
+ // 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(1));
+ }
+ 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.getLine());
+ return false;
+ }
+ if (parser.readThisKeyword(ILisaacModel.keyword_expanded) ||
+ parser.readThisKeyword(ILisaacModel.keyword_strict)) {
+ prototype.setTypeStyle(parser.getLastString());
+ }
+ prototype.setNameOffset(parser.getOffset());// for refactor
+
+ if (! parser.readCapIdentifier()) {
+ parser.getReporter().syntaxError("Prototype identifier is needed.", parser.getLine());
+ return false;
+ }
+ if (parser.getLastString().compareTo(prototype.getName()) != 0) {
+ int len = parser.getLastString().length();
+ parser.getReporter().syntaxError("Incorrect name (filename != name).", parser.getPosition(len));
+ }
+
+ 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.getLine());
+ return false;
+ }
+ }
+ if (! parser.readCharacter(')')) {
+ parser.getReporter().syntaxError("Added ')'.", parser.getLine());
+ return false;
+ }
+ } else {
+ parser.getReporter().syntaxError("Identifier parameter type is needed.", parser.getLine());
+ return false;
+ }
+ }
+ } else {
+ parser.getReporter().syntaxError("Slot `name' must to be first slot.", parser.getLine());
+ }
+ } 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.getLine());
+ return false;
+ }
+ if (parser.readTypeList(false) == null) {
+ parser.getReporter().syntaxError("Incorrect type list.", parser.getLine());
+ 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.getLine());
+ return false;
+ }
+ if (! parser.readExternal()) {
+ parser.getReporter().syntaxError("Incorrect external.", parser.getLine());
+ return false;
+ }
+ } else if (parser.readWord(ILisaacModel.slot_default)) {
+ // '-' "default" ':=' EXPR_PRIMARY
+
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getLine());
+ return false;
+ }
+ if (parser.readExprPrimary() == null) {
+ parser.getReporter().syntaxError("Incorrect expr.", parser.getLine());
+ 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.getLine());
+ return false;
+ }
+ if (! parser.readExternal()) {
+ parser.getReporter().syntaxError("Incorrect external.", parser.getLine());
+ 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.getLine());
+ return false;
+ }
+ if (! parser.readInteger()) {
+ parser.getReporter().syntaxError("Incorrect number.", parser.getLine());
+ return false;
+ }
+ } else if (parser.readWord(ILisaacModel.slot_lip)) {
+
+ // '-' lip <- ( { LIP_EXPR ';' } )
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_code)) {
+ parser.getReporter().warning("Added '<-' is needed.", parser.getLine());
+ }
+ if (! parser.readCharacter('(')) {
+ parser.getReporter().warning("Added '(' is needed.", parser.getLine());
+ }
+ //
+ // LIP interpreter
+ //
+ LipParser lipParser = new LipParser(parser.getSource(), parser.getOffset());
+
+ while (lipParser.readExpr() != null) {
+ // instr.run(); // TODO interpret lip code if needed
+ if (! lipParser.readCharacter(';')) {
+ parser.getReporter().warning("Added ';' is needed.", parser.getLine());
+ }
+ }
+ if (! lipParser.readCharacter(')')) {
+ parser.getReporter().warning("Added ')' is needed.", parser.getLine());
+ }
+ parser.setPosition(lipParser.getOffset());
+
+ } 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.
+ //
+
+ String headerSlot = new String(parser.getLastString());
+
+ // '-' ("date"|"comment"|"author"|"bibliography"|"language"|"copyright"|"bug_report")
+ // ':=' string
+ if (! parser.readSymbol(ILisaacModel.symbol_affect_immediate)) {
+ parser.getReporter().syntaxError("Added ':='.", parser.getLine());
+ return false;
+ }
+ parser.readSpace();
+ Position slotPosition = parser.getPosition();
+ if (! parser.readString()) {
+ parser.getReporter().syntaxError("Incorrect string.", parser.getLine());
+ return false;
+ }
+ if (headerSlot.equals(ILisaacModel.slot_comment)) {
+ prototype.setHeaderComment(new String(parser.getLastString()));
+ } else {
+ slotPosition.setLength(parser.getOffset() - slotPosition.offset);
+ prototype.addHeaderData(headerSlot,new String(parser.getLastString()), slotPosition);
+ }
+
+ } 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/editor/eclipse/src/org/lisaac/ldt/model/SlotContext.java b/editor/eclipse/src/org/lisaac/ldt/model/SlotContext.java
new file mode 100644
index 0000000..c58a267
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/SlotContext.java
@@ -0,0 +1,29 @@
+package org.lisaac.ldt.model;
+
+import org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/items/IArgument.java b/editor/eclipse/src/org/lisaac/ldt/model/items/IArgument.java
new file mode 100644
index 0000000..8a464f5
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/IArgument.java
@@ -0,0 +1,14 @@
+package org.lisaac.ldt.model.items;
+
+import org.lisaac.ldt.model.types.IType;
+
+public interface IArgument extends IVariable {
+
+ String getName();
+
+ IType getType();
+
+ boolean hasName(String word);
+
+ void printIn(StringBuffer buffer);
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ICode.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ICode.java
new file mode 100644
index 0000000..9ba6c20
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ICode.java
@@ -0,0 +1,13 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.types.IType;
+
+public interface ICode {
+
+ IType getType(Slot slot, Prototype prototype);
+
+ void refactorRenamePrototype(String oldName, String newName, List<TextEdit> edits);
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/IConstant.java b/editor/eclipse/src/org/lisaac/ldt/model/items/IConstant.java
new file mode 100644
index 0000000..797c218
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/IConstant.java
@@ -0,0 +1,5 @@
+package org.lisaac.ldt.model.items;
+
+public interface IConstant extends ICode {
+
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMArgs.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMArgs.java
new file mode 100644
index 0000000..d053c6e
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMArgs.java
@@ -0,0 +1,96 @@
+package org.lisaac.ldt.model.items;
+
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.TypeMulti;
+
+public class ITMArgs implements IArgument {
+
+ protected String[] name;
+ protected TypeMulti type;
+
+ protected Position position;
+
+ public ITMArgs(String[] name, TypeMulti type, Position position) {
+ this.name = name;
+ this.type = type;
+ this.position = position;
+ }
+
+ public String getName() {
+ StringBuffer buffer = new StringBuffer("(");
+ for (int i=0; i<name.length; i++) {
+ buffer.append(name[i]);
+
+ if (i != name.length-1) {
+ buffer.append(", ");
+ }
+ }
+ buffer.append(")");
+ return buffer.toString();
+ }
+
+ 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 hasName(String word) {
+ return lastIndexOf(word) != -1;
+ }
+
+ public IType getType() {
+ 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) {
+ buffer.append("(");
+ for (int i=0; i<name.length; i++) {
+ IType subType = type.getSubType(i);
+ buffer.append(name[i]);
+ buffer.append(" : ");
+ buffer.append(subType);
+
+ if (i != name.length-1) {
+ buffer.append(", ");
+ }
+ }
+ buffer.append(")");
+ }
+
+ public String getHoverInformation() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("<I>Arguments</I> : ");
+ buffer.append("(");
+ for (int i=0; i<name.length; i++) {
+ IType subType = type.getSubType(i);
+ buffer.append("<b>"+name[i]+"</b>");
+ buffer.append(" : ");
+ buffer.append("<g>"+subType+"</g>");
+
+ if (i != name.length-1) {
+ buffer.append(", ");
+ }
+ }
+ buffer.append(")");
+
+ return buffer.toString();
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+}
+
\ No newline at end of file
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMArgument.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMArgument.java
new file mode 100644
index 0000000..ae1abdc
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMArgument.java
@@ -0,0 +1,52 @@
+package org.lisaac.ldt.model.items;
+
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.ITypeMono;
+
+public class ITMArgument implements IArgument {
+
+ protected String name;
+ protected ITypeMono type;
+
+ protected Position position;
+
+ public ITMArgument(String name, ITypeMono type, Position position) {
+ this.name = name;
+ this.type = type;
+ this.position = position;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public IType getType() {
+ return type;
+ }
+
+ public boolean hasName(String word) {
+ return name.compareTo(word) == 0;
+ }
+
+ public void printIn(StringBuffer buffer) {
+ buffer.append(name);
+ buffer.append(':');
+ buffer.append(type);
+ }
+
+ public String getHoverInformation() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("<I>Argument</I> : <b>");
+ buffer.append(name);
+ buffer.append("</b> <g> : ");
+ buffer.append(type.toString());
+ buffer.append("</g>");
+
+ return buffer.toString();
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMBlock.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMBlock.java
new file mode 100644
index 0000000..831171c
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMBlock.java
@@ -0,0 +1,51 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.LisaacParser;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.TypeBlock;
+
+public class ITMBlock implements ICode {
+ protected ITMList list;
+ protected IArgument argument;
+
+ public ITMBlock(ITMList list, IArgument argument, Slot slot) {
+ this.list = list;
+ this.argument = argument;
+
+ if (slot != null) {
+ slot.addSubList(this);
+ }
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ return TypeBlock.get(null, null); // FIXME empty block
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName, List<TextEdit> edits) {
+ if (argument != null && list != null) {
+ IType type = argument.getType();
+ Position p = argument.getPosition();
+
+ if (p != null && type.toString().compareTo(oldName) == 0) {
+ LisaacParser parser = list.getOwner().getPrototype().openParser();
+ parser.setPosition(p.offset+p.length);
+ parser.readCharacter(':');
+ parser.readSpace();
+
+ int startOffset = parser.getOffset();
+
+ edits.add(new DeleteEdit(startOffset, oldName.length()));
+ edits.add(new InsertEdit(startOffset, newName));
+ }
+ }
+ if (list != null) {
+ list.refactorRenamePrototype(oldName, newName, edits);
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMCharacter.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMCharacter.java
new file mode 100644
index 0000000..0656c92
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMCharacter.java
@@ -0,0 +1,21 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.TypeSimple;
+
+public class ITMCharacter implements IConstant {
+
+ public ITMCharacter(String string) {
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ return TypeSimple.get(ILisaacModel.prototype_character);
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName, List<TextEdit> edits) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExpression.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExpression.java
new file mode 100644
index 0000000..06cf4ae
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExpression.java
@@ -0,0 +1,30 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.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, Prototype prototype) {
+ if (valueList != null && valueList.length > 0) {
+ return valueList[valueList.length-1].getType(slot, prototype); // FIXME expr type
+ }
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName, List<TextEdit> edits) {
+ for (int i=0; i<valueList.length; i++) {
+ valueList[i].refactorRenamePrototype(oldName, newName, edits);
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExternal.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExternal.java
new file mode 100644
index 0000000..dbbeed5
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExternal.java
@@ -0,0 +1,21 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.types.IType;
+
+public class ITMExternal implements ICode {
+ protected String extern;
+
+ public ITMExternal(String extern) {
+ this.extern = extern;
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName, List<TextEdit> edits) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExternalType.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExternalType.java
new file mode 100644
index 0000000..782e001
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMExternalType.java
@@ -0,0 +1,36 @@
+package org.lisaac.ldt.model.items;
+
+import org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/items/ITMLDots.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMLDots.java
new file mode 100644
index 0000000..5b39c71
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMLDots.java
@@ -0,0 +1,16 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.types.IType;
+
+public class ITMLDots implements ICode {
+
+ public IType getType(Slot slot, Prototype prototype) {
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName, List<TextEdit> edits) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMList.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMList.java
new file mode 100644
index 0000000..be09219
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMList.java
@@ -0,0 +1,116 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.LisaacParser;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.types.IType;
+
+public class ITMList implements ICode {
+ protected ICode[] code;
+ protected ITMLocal[] localList;
+ protected ITMLocal[] staticList;
+
+ protected int startOffset, endOffset;
+
+ private Slot owner;
+
+ public ITMList(Slot slot, int start) {
+ startOffset = start;
+ endOffset = startOffset;
+ owner = slot;
+ if (slot != null) {
+ slot.addSubList(this);
+ }
+ }
+
+ public Slot getOwner() {
+ return owner;
+ }
+
+ public void setEndOffset(int end) {
+ endOffset = end;
+ }
+
+ 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, Prototype prototype) {
+ if (code != null && code.length > 0) {
+ return code[code.length-1].getType(slot, prototype); // FIXME list type
+ }
+ return null;
+ }
+
+ public boolean isInside(int offset) {
+ return offset >= startOffset && offset <= endOffset;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName, List<TextEdit> edits) {
+ if (localList != null && owner != null) {
+ for (int i=0; i<localList.length; i++) {
+ createEdit(localList[i], oldName, newName, edits);
+ }
+ }
+ if (staticList != null && owner != null) {
+ for (int i=0; i<staticList.length; i++) {
+ createEdit(staticList[i], oldName, newName, edits);
+ }
+ }
+ if (code != null) {
+ for (int i=0; i<code.length; i++) {
+ code[i].refactorRenamePrototype(oldName, newName, edits);
+ }
+ }
+ }
+
+ private void createEdit(ITMLocal local, String oldName, String newName, List<TextEdit> edits) {
+ IType type = local.getType();
+ Position p = local.getPosition();
+
+ if (p != null && type.toString().compareTo(oldName) == 0) {
+ LisaacParser parser = owner.getPrototype().openParser();
+ parser.setPosition(p.offset+p.length);
+ parser.readCharacter(':');
+ parser.readSpace();
+
+ int startOffset = parser.getOffset();
+
+ edits.add(new DeleteEdit(startOffset, oldName.length()));
+ edits.add(new InsertEdit(startOffset, newName));
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMListIdf.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMListIdf.java
new file mode 100644
index 0000000..20ad159
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMListIdf.java
@@ -0,0 +1,28 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.types.IType;
+
+public class ITMListIdf implements ICode {
+
+ ArrayList<String> list;
+
+
+ public ITMListIdf(ArrayList<String> list) {
+ this.list = list;
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMLocal.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMLocal.java
new file mode 100644
index 0000000..626afe7
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMLocal.java
@@ -0,0 +1,48 @@
+package org.lisaac.ldt.model.items;
+
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.ITypeMono;
+
+/**
+ * Local declaration slot
+ */
+public class ITMLocal implements IVariable {
+ protected ITypeMono type;
+ protected String name;
+
+ protected Position position;
+
+ public ITMLocal(String name, Position position) {
+ this.position = position;
+ 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;
+ }
+
+ public String getHoverInformation() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("<I>Local</I> : <b>");
+ buffer.append(name);
+ buffer.append("</b> <g> : ");
+ buffer.append(type.toString());
+ buffer.append("</g>");
+
+ return buffer.toString();
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMNumber.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMNumber.java
new file mode 100644
index 0000000..9785e18
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMNumber.java
@@ -0,0 +1,22 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.TypeSimple;
+
+public class ITMNumber implements IConstant {
+
+ public ITMNumber(long lastInteger) {
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ return TypeSimple.get(ILisaacModel.prototype_integer);
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMOld.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMOld.java
new file mode 100644
index 0000000..0ea0cb6
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMOld.java
@@ -0,0 +1,25 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.types.IType;
+
+public class ITMOld implements ICode {
+ protected ICode value;
+
+ public ITMOld(ICode value) {
+ this.value = value;
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ if (value != null) {
+ return value.getType(slot, prototype);
+ }
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMOperator.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMOperator.java
new file mode 100644
index 0000000..c99d6ec
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMOperator.java
@@ -0,0 +1,27 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.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, Prototype prototype) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMPrototype.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMPrototype.java
new file mode 100644
index 0000000..7f0de2b
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMPrototype.java
@@ -0,0 +1,34 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.ITypeMono;
+
+public class ITMPrototype implements ICode {
+ protected ITypeMono type;
+
+ protected Position position;
+
+ public ITMPrototype(ITypeMono type, Position position) {
+ this.type = type;
+ this.position = position;
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ return type;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+
+ if (type.toString().compareTo(oldName) == 0) {
+ edits.add(new DeleteEdit(position.offset, oldName.length()));
+ edits.add(new InsertEdit(position.offset, newName));
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMRead.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMRead.java
new file mode 100644
index 0000000..a9898e6
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMRead.java
@@ -0,0 +1,55 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.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, Prototype prototype) {
+
+ 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();
+ }
+ }
+ }
+ if (prototype != null) {
+ Slot s = prototype.lookupSlot(name);
+ if (s != null) {
+ return s.getResultType();
+ }
+ }
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArg1.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArg1.java
new file mode 100644
index 0000000..6b08c01
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArg1.java
@@ -0,0 +1,20 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+
+public class ITMReadArg1 extends ITMRead {
+
+ protected ICode arg;
+
+ public ITMReadArg1(String name, ICode arg) {
+ super(name);
+ this.arg = arg;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ arg.refactorRenamePrototype(oldName, newName, edits);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArg2.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArg2.java
new file mode 100644
index 0000000..7b220ef
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArg2.java
@@ -0,0 +1,76 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.LisaacCompletionParser;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.TypeSimple;
+
+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;
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ //
+ // operator expression.
+ //
+ if (name.startsWith("__")) { // FIXME __infix __prefix __postfix??
+
+ // Get type of left part of operator.
+ IType type = argFirst.getType(slot, prototype);
+ if (type != null) {
+ try {
+ Prototype operatorPrototype = LisaacCompletionParser.findPrototype(""+type);
+ if (operatorPrototype != null) {
+ Slot operatorSlot = operatorPrototype.lookupSlot(name);
+ if (operatorSlot != null) {
+ // return result type of operator.
+ return operatorSlot.getResultType();
+ } else {
+ if (name.compareTo("__infix_equal") == 0) {
+ // special case for '=' operator (can't be a slot)
+ return TypeSimple.getTypeBoolean();
+ }
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+ // second chance with second argument FIXME use __postfix?
+ type = argSecond.getType(slot, prototype);
+ if (type != null) {
+ try {
+ Prototype operatorPrototype = LisaacCompletionParser.findPrototype(""+type);
+ if (operatorPrototype != null) {
+ Slot operatorSlot = operatorPrototype.lookupSlot(name);
+ if (operatorSlot != null) {
+ // return result type of operator.
+ return operatorSlot.getResultType();
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+ //
+ // classic slot
+ //
+ return super.getType(slot, prototype);
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+
+ argFirst.refactorRenamePrototype(oldName, newName, edits);
+ argSecond.refactorRenamePrototype(oldName, newName, edits);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArgs.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArgs.java
new file mode 100644
index 0000000..4d819c5
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReadArgs.java
@@ -0,0 +1,21 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+
+public class ITMReadArgs extends ITMRead {
+ protected ICode[] args;
+
+ public ITMReadArgs(String name, ICode[] args) {
+ super(name);
+ this.args = args;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ for (int i=0; i<args.length; i++) {
+ args[i].refactorRenamePrototype(oldName, newName, edits);
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReal.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReal.java
new file mode 100644
index 0000000..3aa345f
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMReal.java
@@ -0,0 +1,22 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.TypeSimple;
+
+public class ITMReal implements IConstant {
+
+ public ITMReal(String string) {
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ return TypeSimple.get(ILisaacModel.prototype_real);
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMResult.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMResult.java
new file mode 100644
index 0000000..7cfe175
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMResult.java
@@ -0,0 +1,26 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.types.IType;
+
+public class ITMResult implements ICode {
+ protected ICode value;
+
+ public ITMResult(ICode value) {
+ this.value = value;
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ if (value != null) {
+ return value.getType(slot, prototype);
+ }
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ value.refactorRenamePrototype(oldName, newName, edits);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMString.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMString.java
new file mode 100644
index 0000000..229c20f
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMString.java
@@ -0,0 +1,25 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.TypeSimple;
+
+public class ITMString implements IConstant {
+
+ protected String string;
+
+ public ITMString(String string) {
+ this.string = string;
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ return TypeSimple.get(ILisaacModel.prototype_string);
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/ITMWrite.java b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMWrite.java
new file mode 100644
index 0000000..8f8746f
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/ITMWrite.java
@@ -0,0 +1,33 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.List;
+
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.types.IType;
+
+public class ITMWrite implements ICode {
+
+ protected ICode assign;
+ protected ICode value;
+
+ protected char type;
+
+ public ITMWrite(ICode assign, ICode value, char type) {
+ super();
+ this.assign = assign;
+ this.value = value;
+ this.type = type;
+ }
+
+ public IType getType(Slot slot, Prototype prototype) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void refactorRenamePrototype(String oldName, String newName,
+ List<TextEdit> edits) {
+ assign.refactorRenamePrototype(oldName, newName, edits);
+ value.refactorRenamePrototype(oldName, newName, edits);
+ }
+
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/IVariable.java b/editor/eclipse/src/org/lisaac/ldt/model/items/IVariable.java
new file mode 100644
index 0000000..4060773
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/IVariable.java
@@ -0,0 +1,9 @@
+package org.lisaac.ldt.model.items;
+
+import org.lisaac.ldt.model.Position;
+
+public interface IVariable {
+ String getHoverInformation();
+
+ Position getPosition();
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/Prototype.java b/editor/eclipse/src/org/lisaac/ldt/model/items/Prototype.java
new file mode 100644
index 0000000..adc9b70
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/Prototype.java
@@ -0,0 +1,679 @@
+package org.lisaac.ldt.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.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.TextFileChange;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.LisaacCompletionParser;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.LisaacParser;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.model.types.ITypeMono;
+import org.lisaac.ldt.outline.OutlineItem;
+import org.lisaac.ldt.outline.OutlinePrototype;
+import org.lisaac.ldt.outline.OutlineSection;
+
+public class Prototype {
+ protected IFile file;
+
+ protected ILisaacModel parent;
+ protected LisaacParser parser;
+
+ protected String name;
+ protected String typeStyle;
+
+ protected HashMap<String, Slot> parentList;
+ protected HashMap<String, Slot> slotList;
+
+ // hover informations
+ protected String headerData;
+ protected String headerComment;
+
+ protected Section firstSection;
+
+ // refactor information
+ protected int nameOffset;
+ protected Position authorOffset;
+ protected Position bibliographyOffset;
+ protected Position copyrightOffset;
+
+ public Prototype(IFile file, String name, ILisaacModel model) {
+ this.file = file;
+ this.name = name;
+ this.parent = model;
+ this.parser = model.getParser();
+
+ slotList = new HashMap<String, Slot>();
+ parentList = 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 IFile getFile() {
+ return file;
+ }
+
+ public String getFileName() {
+ return file.getName();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setHeaderComment(String comment) {
+ this.headerComment = comment;
+ }
+
+ public void addHeaderData(String slotName, String data, Position position) {
+ String info = "\n<g>" + slotName + "</g> " + data;
+ if (headerData == null) {
+ headerData = info;
+ } else {
+ this.headerData += info;
+ }
+ if (slotName.equals(ILisaacModel.slot_author)) {
+ authorOffset = position;
+ } else if (slotName.equals(ILisaacModel.slot_bibliography)) {
+ bibliographyOffset = position;
+ } else if (slotName.equals(ILisaacModel.slot_copyright)) {
+ copyrightOffset = position;
+ }
+ }
+
+
+ public LisaacParser openParser() {
+ parser.initialize();
+ return parser;
+ }
+
+ public void setTypeStyle(String s) {
+ typeStyle = s;
+ }
+
+ public String getTypeStyle() {
+ return typeStyle;
+ }
+
+ public Section getFirstSection() {
+ return firstSection;
+ }
+
+ public void setFirstSection(Section s) {
+ firstSection = s;
+ }
+
+ 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 lookupSlot(String n) {
+ Slot result = null;
+
+ //
+ // Search in 'Self'.
+ //
+ result = getSlot(n);
+ if (result == null) {
+ result = getParentSlot(n);
+ }
+
+ if (result == null) {
+ //
+ // Search in parents.
+ //
+ Collection<Slot> values = parentList.values();
+ Iterator<Slot> it = values.iterator();
+ while (it.hasNext()) {
+ Slot slotParent = it.next();
+ IType typeParent = slotParent.getResultType();
+ try {
+ Prototype parent = LisaacCompletionParser
+ .findPrototype("" + typeParent);
+ if (parent != null) {
+ result = parent.lookupSlot(n);
+ if (result != null) {
+ return result;
+ }
+ }
+ } catch (CoreException e) {
+ return null;
+ }
+ }
+ }
+ return result;
+ }
+
+ public Slot getSlot(String n) {
+ //
+ // Search in 'Self' only.
+ //
+ if (slotList.containsKey(n)) {
+ return slotList.get(n);
+ }
+ return null;
+ }
+
+ public Slot getParentSlot(String n) {
+ // Search in 'Self' parent.
+ if (parentList.containsKey(n)) {
+ return parentList.get(n);
+ }
+ return null;
+ }
+
+ public Slot getSlot(int offset) {
+ return getSlot(openParser(), offset);
+ }
+
+ public Slot getSlot(String s, int offset) {
+ return getSlot(new LisaacParser(null, s), offset);
+ }
+
+ public Slot getSlot(LisaacParser parser, int offset) {
+ //
+ // Use indentation to get slot
+ //
+ String source = parser.getSource();
+ boolean again;
+
+ if (offset >= source.length() - 1) {
+ 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, false);
+ if (slotName != null) {
+ return getSlot(slotName);
+ }
+ } else {
+ again = true;
+ offset--;
+ }
+ }
+ } while (again);
+
+ return null;
+ }
+
+ public void lookupSlotMatch(String n,
+ ArrayList<ICompletionProposal> matchList, int offset, int length) {
+ //
+ // Search in 'Self'.
+ //
+ getSlotMatch(n, matchList, offset, length);
+ getParentSlotMatch(n, matchList, offset, length);
+
+ //
+ // Search in parents.
+ //
+ Collection<Slot> values = parentList.values();
+ Iterator<Slot> it = values.iterator();
+ while (it.hasNext()) {
+ Slot slotParent = it.next();
+ IType typeParent = slotParent.getResultType();
+ try {
+ Prototype parent = LisaacCompletionParser.findPrototype(""
+ + typeParent);
+ if (parent != null) {
+ parent.lookupSlotMatch(n, matchList, offset, length);
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+
+ public void getSlotMatch(String n,
+ ArrayList<ICompletionProposal> matchList, int offset, int length) {
+ //
+ // // Search in 'Self' only.
+ //
+ Collection<Slot> values = slotList.values();
+ Iterator<Slot> it = values.iterator();
+ while (it.hasNext()) {
+ Slot slot = it.next();
+ if (slot.match(n)) {
+ slot.getSlotMatchProposals(matchList, offset, length, n
+ .length());
+ }
+ }
+ }
+
+ public void getParentSlotMatch(String n,
+ ArrayList<ICompletionProposal> matchList, int offset, int length) {
+ // Search in 'Self' parent.
+ Collection<Slot> values = parentList.values();
+ Iterator<Slot> it = values.iterator();
+ while (it.hasNext()) {
+ Slot slot = it.next();
+ if (slot.match(n)) {
+ slot.getSlotMatchProposals(matchList, offset, length, n
+ .length());
+ }
+ }
+ }
+
+ public Slot getSlotFromKeyword(String keyword, LisaacParser parser,
+ int baseOffset) throws CoreException {
+ String source = parser.getSource();
+ int bracketLevel = 0, invBracketLevel = 0;
+ Prototype receiver = null;
+ Slot result = null;
+ char c = 0;
+
+ int offset = baseOffset;
+ if (offset >= source.length() - 1) {
+ return null;
+ }
+
+ while (offset > 0) {
+ //
+ // find beginning of SEND_MSG grammar rule
+ //
+
+ // Rewind to '(' '{' ';' '[' '.' '<-' 'operator'
+ c = source.charAt(offset);
+
+ if (c == '(' || c == '{' || c == '[') {
+ if (bracketLevel == 0) {
+ break;
+ }
+ bracketLevel--;
+ invBracketLevel++;
+ }
+ if (c == ')' || c == '}' || c == ']') {
+ bracketLevel++;
+ invBracketLevel--;
+ }
+
+ // ok, we're not in nested statements
+ if (bracketLevel == 0 && invBracketLevel == 0) {
+ if (c == ';' || c == '.') {
+ break;
+ }
+
+ // affectation
+ if (c == '=' && source.length() - offset > 2) {
+ if (source.charAt(offset - 1) == ':'
+ || source.charAt(offset - 1) == '?') {
+ break;
+ }
+ } else if (c == '-' && source.length() - offset > 2) {
+ if (source.charAt(offset - 1) == '<') {
+ break;
+ }
+ }
+ if (parser.isOperatorSymbol(c)) {
+ if (c == '+' || c == '-') {
+ // ambiguity with slot definition
+ if (offset - 3 > 0 && source.charAt(offset - 1) == ' ' &&
+ source.charAt(offset - 2) == ' ' &&
+ source.charAt(offset - 3) == '\n') {
+ offset = offset - 3;
+ continue;
+ }
+ }
+ break;
+ }
+ }
+
+ // look at indentation
+ if (c == '\n' && source.length() - offset > 4) {
+ if (source.charAt(offset + 1) == ' '
+ && source.charAt(offset + 2) == ' '
+ && (source.charAt(offset + 3) == '+' || source
+ .charAt(offset + 3) == '-')) {
+ String slotName = parser
+ .readSlotNameFromOffset(offset + 4, false);
+ if (slotName != null) {
+ result = lookupSlot(slotName);
+ if (result == null) {
+ return null;
+ }
+ if (result.keywordCount() == 1) {
+ if (result.getName().compareTo(keyword) == 0) {
+ return result;
+ }
+ } else {
+ // find keyword next token
+ offset = baseOffset;
+ while (offset < source.length() - 1
+ && Character
+ .isJavaIdentifierPart(source
+ .charAt(offset))) {
+ offset++;
+ }
+ // read space
+ while (offset < source.length() - 1
+ && Character.isWhitespace(source
+ .charAt(offset))) {
+ offset++;
+ }
+ if (source.charAt(offset) != ':') {
+ return result;// 'keyword' is a slot keyword
+ }
+ return null;
+ }
+ }
+ }
+ }
+ offset--;
+ }
+ if (result == null) {
+ // Slot Call.
+
+ if (c == '.') {
+ int pointOffset = offset;
+ offset--;
+ bracketLevel = 0;
+
+ // rewind until ';' '(' '{' '['
+ while (offset > 0) {
+ c = source.charAt(offset);
+ if (c == ';') {
+ break;
+ }
+ if (c == '(' || c == '{' || c == '[') {
+ if (bracketLevel == 0) {
+ break;
+ }
+ bracketLevel--;
+ }
+ if (c == ')' || c == '}' || c == ']') {
+ bracketLevel++;
+ }
+ offset--;
+ }
+ if (offset > 0) {
+ LisaacCompletionParser p = new LisaacCompletionParser(
+ source, (LisaacModel) getModel());
+ receiver = p
+ .readReceiver(offset + 1, pointOffset, this);
+
+ offset = pointOffset;
+ }
+ } else {
+ receiver = this;
+ }
+ parser.setPosition(offset + 1);
+ parser.readSpace();
+ String slotName = parser.readKeywordInSendMsg(keyword,
+ baseOffset);
+
+ if (slotName != null && receiver != null) {
+ result = receiver.lookupSlot(slotName);
+ }
+ }
+ return result;
+ }
+
+ public void addSlot(Slot s) {
+ slotList.put(s.getName(), s);
+ }
+
+ public void addParentSlot(Slot s) {
+ parentList.put(s.getName(), s);
+ }
+
+ public String getHoverInformation() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("<b>");
+ buffer.append(name);
+ buffer.append("</b>");
+ if (headerComment != null) {
+ buffer.append("\n" + headerComment);
+ }
+ if (headerData != null) {
+ buffer.append("\n\n" + headerData);
+ }
+ return buffer.toString();
+ }
+
+ public List<OutlineItem> getOutlineItems() {
+ List<OutlineItem> sections = new ArrayList<OutlineItem>();
+
+ Section current = firstSection;
+ while (current != null) {
+ sections.add(new OutlineSection(current));
+ current = current.getNext();
+ }
+
+ List<OutlineItem> result = new ArrayList<OutlineItem>();
+ result.add(new OutlinePrototype(this, sections));
+ return result;
+ }
+
+ public void getSlotProposals(ArrayList<ICompletionProposal> proposals,
+ int offset, int length) {
+ Collection<Slot> values = slotList.values();
+ Iterator<Slot> it = values.iterator();
+ while (it.hasNext()) {
+ Slot slot = it.next();
+ slot.getSlotProposals(proposals, offset, length);
+ }
+
+ values = parentList.values();
+ it = values.iterator();
+ while (it.hasNext()) {
+ Slot slotParent = it.next();
+ IType typeParent = slotParent.getResultType();
+ try {
+ Prototype parent = LisaacCompletionParser.findPrototype(""
+ + typeParent);
+ if (parent != null) {
+ parent.getSlotProposals(proposals, offset, length);
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+
+ public ArrayList<org.eclipse.jface.text.Position> getPositions() {
+ ArrayList<org.eclipse.jface.text.Position> result = new ArrayList<org.eclipse.jface.text.Position>();
+
+ // section positions
+ Section current = firstSection;
+ while (current != null) {
+ Position p = current.getPosition();
+ result.add(new org.eclipse.jface.text.Position(p.offset, p.length));
+
+ current = current.getNext();
+ }
+
+ // slot positions
+ Collection<Slot> values = slotList.values();
+ Iterator<Slot> it = values.iterator();
+ while (it.hasNext()) {
+ Slot slot = it.next();
+ Position p = slot.getPositionBody();
+ if (p != null) {
+ result.add(new org.eclipse.jface.text.Position(p.offset, p.length));
+ }
+ }
+ return result;
+ }
+
+ public IPath getWorkspacePath() {
+ return file.getFullPath();
+ }
+
+ public Change refactorRenameSelf(String newName) {
+ TextFileChange change = new TextFileChange("Change 'name' slot in section header", file);
+
+ // rename 'name' slot
+ MultiTextEdit edit= new MultiTextEdit();
+ edit.addChild(new DeleteEdit(nameOffset, name.length()));
+ edit.addChild(new InsertEdit(nameOffset, newName));
+
+ change.setEdit(edit);
+ return change;
+ }
+
+ public Change refactorRenamePrototype(String oldName, String newName) {
+ MultiTextEdit edit= new MultiTextEdit();
+
+ // 1. refactor sections
+ Section current = firstSection;
+ while (current != null) {
+ Position p = current.getPosition();
+ ITypeMono[] typeList = current.getTypeList();
+ if (typeList != null) {
+ for (int i=0; i<typeList.length; i++) {
+ if (typeList[i].toString().compareTo(oldName) == 0) {
+ typeList[i].rename(oldName, newName);
+
+ // rename section
+ edit.addChild(new DeleteEdit(p.offset+1, p.length-1));
+ edit.addChild(new InsertEdit(p.offset+1, current.getName()+"\n\n "));
+
+ // for model invariance (other changes in refactor)
+ typeList[i].rename(newName, oldName);
+ }
+ }
+ }
+ current = current.getNext();
+ }
+
+ // 2. refactor slots
+ Collection<Slot> values = slotList.values();
+ Iterator<Slot> it = values.iterator();
+ while (it.hasNext()) {
+ Slot slot = it.next();
+ TextEdit[] slotEdits = slot.refactorRenamePrototype(oldName, newName);
+ if (slotEdits != null) {
+ edit.addChildren(slotEdits);
+ }
+ }
+ // create change
+ if (edit.getChildrenSize() > 0) {
+ TextFileChange change = new TextFileChange("Rename prototype occurences", file);
+ change.setEdit(edit);
+ return change;
+ }
+ return null;
+ }
+
+ public Change refactorHeader(String author, String bibliography,
+ String copyright, String license) {
+ MultiTextEdit edit= new MultiTextEdit();
+
+ // update header slots.
+ refactorHeaderSlot(ILisaacModel.slot_author, authorOffset, author, edit);
+ refactorHeaderSlot(ILisaacModel.slot_bibliography, bibliographyOffset, bibliography, edit);
+ refactorHeaderSlot(ILisaacModel.slot_copyright, copyrightOffset, copyright, edit);
+
+ // update license.
+ if (license != null) {
+ int offset = getOffsetBeforeSection();
+ edit.addChild(new DeleteEdit(0, offset-1));
+ edit.addChild(new InsertEdit(0, license));
+ }
+
+ // create change
+ if (edit.getChildrenSize() > 0) {
+ TextFileChange change = new TextFileChange("Update Section Header", file);
+ change.setEdit(edit);
+ return change;
+ }
+ return null;
+ }
+
+ private void refactorHeaderSlot(String name, Position pos, String newValue, MultiTextEdit edit) {
+ if (newValue != null) {
+ if (pos != null) {
+ // slot already exist
+ edit.addChild(new DeleteEdit(pos.offset, pos.length));
+ edit.addChild(new InsertEdit(pos.offset, "\"" + newValue + "\""));
+ } else {
+ // create slot
+ String slot = "\n - " + name + " := \"" + newValue + "\";";
+ edit.addChild(new InsertEdit(getOffsetAfterName(), slot));
+ }
+ }
+ }
+
+ private int getOffsetAfterName() {
+ LisaacParser parser = openParser();
+ parser.setPosition(nameOffset);
+ parser.readCapIdentifier();
+ parser.readCharacter(';');
+
+ return parser.getOffset();
+ }
+
+ private int getOffsetBeforeSection() {
+ LisaacParser parser = openParser();
+ parser.setPosition(0);
+ if (parser.readThisKeyword (ILisaacModel.keyword_section)) {
+ return parser.getOffset() - 7;
+ }
+ return 0;
+ }
+
+ public void setNameOffset(int offset) {
+ nameOffset = offset;
+ }
+
+ public void setAuthorOffset(Position p) {
+ authorOffset = p;
+ }
+
+ public void setBibliographyOffset(Position p) {
+ bibliographyOffset = p;
+ }
+
+ public void setCopyrightOffset(Position p) {
+ copyrightOffset = p;
+ }
+
+ public IRegion getRegionAt(int line, int column) {
+ LisaacParser parser = openParser();
+ parser.readTokenAt(line, column);
+
+ return new Region(parser.getOffset(), parser.getLastString().length());
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/Section.java b/editor/eclipse/src/org/lisaac/ldt/model/items/Section.java
new file mode 100644
index 0000000..f08234e
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/Section.java
@@ -0,0 +1,166 @@
+package org.lisaac.ldt.model.items;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.types.ITypeMono;
+import org.lisaac.ldt.outline.OutlineItem;
+import org.lisaac.ldt.outline.OutlineSlot;
+
+public class Section {
+ protected Prototype prototype;
+
+ protected String name;
+ protected ITypeMono[] typeList;
+
+ protected Section next;
+
+ protected Position position;
+
+ protected LinkedList<Slot> slots;
+
+
+ public Section(Prototype prototype, String name, Position position) {
+ this.name = name;
+ this.prototype = prototype;
+ this.position = position;
+ this.next = null;
+ }
+
+ public Section(Prototype prototype, ITypeMono[] typeList, Position position) {
+ this.typeList = typeList;
+ this.prototype = prototype;
+ this.position = position;
+ this.next = null;
+ }
+
+ public String getName() {
+ if (name == null) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i=0; i<typeList.length; i++) {
+ buffer.append(typeList[i].toString());
+ if (i != typeList.length-1) {
+ buffer.append(", ");
+ }
+ }
+ return buffer.toString();
+ }
+ return name;
+ }
+
+ public ITypeMono[] getTypeList() {
+ return typeList;
+ }
+
+ public Section getNext() {
+ return next;
+ }
+
+ public void setNext(Section next) {
+ this.next = next;
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+
+ public void addSlot(Slot slot) {
+ if (slots == null) {
+ slots = new LinkedList<Slot>();
+ }
+ slots.add(slot);
+ }
+
+ //
+ // 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;
+ }
+
+ public List<OutlineItem> getOutlineItems() {
+ List<OutlineItem> items = new ArrayList<OutlineItem>();
+
+ if (slots != null) {
+ for (int i=0; i<slots.size(); i++) {
+ items.add(new OutlineSlot(slots.get(i)));
+ }
+ }
+ return items;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/items/Slot.java b/editor/eclipse/src/org/lisaac/ldt/model/items/Slot.java
new file mode 100644
index 0000000..90d2b16
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/items/Slot.java
@@ -0,0 +1,417 @@
+ package org.lisaac.ldt.model.items;
+
+ import java.util.ArrayList;
+ import org.eclipse.jface.text.contentassist.CompletionProposal;
+ import org.eclipse.jface.text.contentassist.ICompletionProposal;
+ import org.eclipse.swt.graphics.Image;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.TextEdit;
+ import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.model.LisaacParser;
+ import org.lisaac.ldt.model.Position;
+ import org.lisaac.ldt.model.types.IType;
+import org.lisaac.ldt.outline.OutlineSlot;
+
+ 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;
+
+ protected ICode value;
+
+ protected ArrayList<ICode> subLists;
+
+ protected String comment;
+
+ protected Position body;
+
+ 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 setComment(String comment) {
+ this.comment = comment;
+ }
+
+ public void setAffect(char affect) {
+ this.affect = affect;
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+
+ public Position getPositionBody() {
+ return body;
+ }
+
+ public void setBody(Position p) {
+ body = p;
+ }
+
+ public int keywordCount() {
+ if (keywordList == null) {
+ return 0;
+ }
+ return keywordList.length;
+ }
+
+ //
+ // Value.
+ //
+
+ public void setValue(ICode v) {
+ if (affect == '<') {
+ value = v;
+ } else {
+ // TODO not yet implemented
+ }
+ }
+
+ public ICode getValue() {
+ return value;
+ }
+
+ public void addSubList(ICode list) {
+ if (subLists == null) {
+ subLists = new ArrayList<ICode>();
+ }
+ subLists.add(list);
+ }
+
+ //
+ // 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].hasName(word)) {
+ return argumentList[i];
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean hasVariableDefinition(String word, int offset) {
+ return getVariableDefinition(word, offset) != null;
+ }
+
+ public IVariable getVariableDefinition(String word, int offset) {
+ ITMList list;
+
+ if (subLists != null) {
+ for (int i = 0; i < subLists.size(); i++) {
+ ICode c = subLists.get(i);
+
+ if (c instanceof ITMList) {
+ list = (ITMList) c;
+ if (list != null && list.isInside(offset)) {
+ // list variable
+ IVariable var = list.getLocal(word);
+ if (var != null) {
+ return var;
+ }
+ }
+ } else if (c instanceof ITMBlock) {
+ list = ((ITMBlock) c).list;
+ IArgument arg = ((ITMBlock) c).argument;
+
+ if (list != null && arg != null
+ && list.isInside(offset) && arg.hasName(word)) {
+ // block argument
+ return arg;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public IVariable getVariable(String word, int offset) {
+ IVariable result = getArgument(word);
+ if (result == null) {
+ result = getVariableDefinition(word, offset);
+ }
+ return result;
+ }
+
+ public Prototype getPrototype() {
+ return sectionId.getPrototype();
+ }
+
+ private String getOperatorName() {
+ String s = name.substring(2);
+ StringBuffer result = new StringBuffer("'");
+ int index;
+ do {
+ index = s.indexOf("_");
+ s = s.substring(index + 1);
+ if (index != -1) {
+ if (s.startsWith("add")) {
+ result.append('+');
+ } else if (s.startsWith("sub")) {
+ result.append('-');
+ } else if (s.startsWith("logicnot")) {
+ result.append('~');
+ } else if (s.startsWith("not")) {
+ result.append('!');
+ } else if (s.startsWith("div")) {
+ result.append('/');
+ } else if (s.startsWith("mul")) {
+ result.append('*');
+ } else if (s.startsWith("xor")) {
+ result.append('^');
+ } else if (s.startsWith("mod")) {
+ result.append('%');
+ } else if (s.startsWith("greater")) {
+ result.append('>');
+ } else if (s.startsWith("less")) {
+ result.append('<');
+ } else if (s.startsWith("equal")) {
+ result.append('=');
+ } else if (s.startsWith("notdiv")) {
+ result.append('\\');
+ } else if (s.startsWith("or")) {
+ result.append('|');
+ } else if (s.startsWith("and")) {
+ result.append('&');
+ } else if (s.startsWith("dollar")) {
+ result.append('$');
+ } else if (s.startsWith("diese")) {
+ result.append('#');
+ } else if (s.startsWith("at")) {
+ result.append('@');
+ } else if (s.startsWith("ask")) {
+ result.append('?');
+ }
+ }
+ } while (index != -1);
+
+ result.append('\'');
+ return result.toString();
+ }
+
+ public String getSignature(boolean isCall) {
+
+ if (name.startsWith("__")) {
+ return getOperatorName();
+ }
+
+ 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();
+ }
+
+ public void getSlotProposals(ArrayList<ICompletionProposal> proposals,
+ int offset, int length) {
+
+ Image image = new OutlineSlot(this).getImage();
+ String displayString = getSignature(true);
+
+
+
+ if (checkUnicity(proposals,displayString)) {
+ proposals.add(new CompletionProposal(displayString, offset, length,
+ displayString.length() - 1, image, getSignature(false),
+ null, null));
+ }
+ }
+
+ public void getSlotMatchProposals(
+ ArrayList<ICompletionProposal> proposals, int offset,
+ int length, int matchLength) {
+
+ Image image = new OutlineSlot(this).getImage();
+ String displayString = getSignature(true);
+
+ if (checkUnicity(proposals,displayString)) {
+ displayString = displayString.substring(matchLength);
+ proposals.add(new CompletionProposal(displayString, offset, length,
+ displayString.length(), image, getSignature(false), null,
+ null));
+ }
+ }
+
+ private boolean checkUnicity(ArrayList<ICompletionProposal> proposals, String str) {
+ for (int i=0; i<proposals.size(); i++) {
+ if (proposals.get(i).getDisplayString().compareTo(str) == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean match(String n) {
+ return name.startsWith(n);
+ }
+
+ public String getHoverInformation() {
+ StringBuffer buffer = new StringBuffer("<b>");
+ buffer.append(getSignature(false));
+ buffer.append("</b> <I>- ");
+ buffer.append(getPrototype().getName());
+ buffer.append("</I>");
+ if (comment != null) {
+ buffer.append("\n\n<g>");
+ buffer.append(comment);
+ buffer.append("</g>");
+ }
+ return buffer.toString();
+ }
+
+ public TextEdit[] refactorRenamePrototype(String oldName, String newName) {
+ ArrayList<TextEdit> result = new ArrayList<TextEdit>();
+
+ // 1. rename arguments
+ for (int i=0; i<argumentList.length; i++) {
+ IType type = argumentList[i].getType();
+ Position p = argumentList[i].getPosition();
+
+ if (p != null && type.toString().compareTo(oldName) == 0) {
+ LisaacParser parser = getPrototype().openParser();
+ parser.setPosition(p.offset+p.length);
+ parser.readCharacter(':');
+ parser.readSpace();
+
+ int startOffset = parser.getOffset();
+
+ result.add(new DeleteEdit(startOffset, oldName.length()));
+ result.add(new InsertEdit(startOffset, newName));
+ }
+ }
+
+ // 2. rename result type
+ if (resultType != null && resultType.toString() != null) {
+ if (resultType.toString().compareTo(oldName) == 0) {
+ LisaacParser parser = getPrototype().openParser();
+ parser.setPosition(position.offset);
+ parser.readSlotNameFromOffset(position.offset, true);
+ parser.readCharacter(':');
+ parser.readSpace();
+
+ int startOffset = parser.getOffset();
+
+ result.add(new DeleteEdit(startOffset, oldName.length()));
+ result.add(new InsertEdit(startOffset, newName));
+ }
+ }
+
+ // 3. rename code
+ if (value != null) {
+ value.refactorRenamePrototype(oldName, newName, result);
+ }
+
+ if (result.size() > 0) {
+ return result.toArray(new TextEdit[result.size()]);
+ }
+ return null;
+ }
+ }
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/lip/LIP.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIP.java
new file mode 100644
index 0000000..03971e9
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIP.java
@@ -0,0 +1,93 @@
+package org.lisaac.ldt.model.lip;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class LIP {
+
+ private static final String PROJECT_PATH_SLOT = "project_path";
+ private static final String LISAAC_PATH_SLOT = "path";
+
+ 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 ArrayList<String> getParentList() {
+ return listParent;
+ }
+
+ public void clearParents() {
+ listParent = null;
+ }
+
+ 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;
+ }
+
+ public void addProjectPath(String projectPath) {
+ for (int i=0; i<getMethodCount(); i++) {
+ LIPSlotCode method = getMethod(i);
+ if (method.getName().compareTo(PROJECT_PATH_SLOT) == 0) {
+
+ // lip code: path (projectPath);
+ method.addLastCode(new LIPCall(LISAAC_PATH_SLOT, new LIPValue(new LIPString(projectPath))));
+ break;
+ }
+ }
+ }
+
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPAffect.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPAffect.java
new file mode 100644
index 0000000..aa7ca69
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPAffect.java
@@ -0,0 +1,12 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPBinary.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPBinary.java
new file mode 100644
index 0000000..2c8b920
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPBinary.java
@@ -0,0 +1,13 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPBoolean.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPBoolean.java
new file mode 100644
index 0000000..9d07d51
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPBoolean.java
@@ -0,0 +1,28 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPCall.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPCall.java
new file mode 100644
index 0000000..2cd28f4
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPCall.java
@@ -0,0 +1,13 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPCode.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPCode.java
new file mode 100644
index 0000000..716d535
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPCode.java
@@ -0,0 +1,4 @@
+package org.lisaac.ldt.model.lip;
+
+public class LIPCode {
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPConstant.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPConstant.java
new file mode 100644
index 0000000..1e4a1f8
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPConstant.java
@@ -0,0 +1,8 @@
+package org.lisaac.ldt.model.lip;
+
+public abstract class LIPConstant {
+
+ public abstract String getName();
+
+ public abstract void free();
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPIf.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPIf.java
new file mode 100644
index 0000000..3b378af
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPIf.java
@@ -0,0 +1,15 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPInteger.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPInteger.java
new file mode 100644
index 0000000..a494883
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPInteger.java
@@ -0,0 +1,23 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPPrint.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPPrint.java
new file mode 100644
index 0000000..1ceab63
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPPrint.java
@@ -0,0 +1,10 @@
+package org.lisaac.ldt.model.lip;
+
+public class LIPPrint extends LIPCode {
+
+ protected LIPCode message;
+
+ public LIPPrint(LIPCode message) {
+ this.message = message;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPSlotCode.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPSlotCode.java
new file mode 100644
index 0000000..e3f5e6d
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPSlotCode.java
@@ -0,0 +1,62 @@
+package org.lisaac.ldt.model.lip;
+
+import org.lisaac.ldt.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();
+ }
+
+ public void addLastCode(LIPCode instr) { // TODO use array list
+
+ LIPCode[] newCode = new LIPCode[code.length + 1];
+ System.arraycopy(code, 0, newCode, 0, code.length);
+ newCode[newCode.length - 1] = instr;
+
+ code = newCode;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPSlotData.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPSlotData.java
new file mode 100644
index 0000000..1c845e7
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPSlotData.java
@@ -0,0 +1,29 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPString.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPString.java
new file mode 100644
index 0000000..63f710b
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPString.java
@@ -0,0 +1,23 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPUnary.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPUnary.java
new file mode 100644
index 0000000..30d5135
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPUnary.java
@@ -0,0 +1,13 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPValue.java b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPValue.java
new file mode 100644
index 0000000..33ad0a3
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/lip/LIPValue.java
@@ -0,0 +1,10 @@
+package org.lisaac.ldt.model.lip;
+
+public class LIPValue extends LIPCode {
+
+ protected LIPConstant value;
+
+ public LIPValue(LIPConstant value) {
+ this.value = value;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/types/IType.java b/editor/eclipse/src/org/lisaac/ldt/model/types/IType.java
new file mode 100644
index 0000000..6c4441f
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/IType.java
@@ -0,0 +1,8 @@
+package org.lisaac.ldt.model.types;
+
+public interface IType {
+
+ void rename(String oldName, String newName);
+
+ public String toString();
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/types/ITypeMono.java b/editor/eclipse/src/org/lisaac/ldt/model/types/ITypeMono.java
new file mode 100644
index 0000000..eeeed50
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/ITypeMono.java
@@ -0,0 +1,4 @@
+package org.lisaac.ldt.model.types;
+
+public interface ITypeMono extends IType {
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/types/TypeBlock.java b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeBlock.java
new file mode 100644
index 0000000..79ebf93
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeBlock.java
@@ -0,0 +1,57 @@
+package org.lisaac.ldt.model.types;
+
+import org.lisaac.ldt.model.ILisaacModel;
+
+/**
+ * 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 ILisaacModel.prototype_block;
+ }
+
+ public void rename(String oldName, String newName) {
+ // TODO emit error
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/types/TypeGeneric.java b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeGeneric.java
new file mode 100644
index 0000000..be734f1
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeGeneric.java
@@ -0,0 +1,11 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/model/types/TypeMulti.java b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeMulti.java
new file mode 100644
index 0000000..934e2f0
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeMulti.java
@@ -0,0 +1,54 @@
+package org.lisaac.ldt.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
+ }
+
+ public void rename(String oldName, String newName) {
+ for (int i=0; i<listType.length; i++) {
+ listType[i].rename(oldName, newName);
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/types/TypeParameter.java b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeParameter.java
new file mode 100644
index 0000000..9d2a1e1
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeParameter.java
@@ -0,0 +1,11 @@
+package org.lisaac.ldt.model.types;
+
+/**
+ * Parameter type for argument define.
+ */
+public class TypeParameter extends TypeSimple {
+
+ public TypeParameter(String name) {
+ super(name);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/types/TypeSelf.java b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeSelf.java
new file mode 100644
index 0000000..796e821
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeSelf.java
@@ -0,0 +1,39 @@
+package org.lisaac.ldt.model.types;
+
+import java.util.HashMap;
+
+public class TypeSelf implements ITypeMono {
+
+ private static HashMap<String,TypeSelf> dico;
+
+ protected String staticType;
+
+ TypeSelf(String staticType) {
+ this.staticType = staticType;
+ }
+
+ public static TypeSelf get(String n) {
+ TypeSelf result=null;
+
+ if (dico == null) {
+ dico = new HashMap<String,TypeSelf>();
+ }
+ result = dico.get(n == null ? "" : n);
+ if (result == null) {
+ result = new TypeSelf(n);
+ }
+ return result;
+ }
+
+ public String getStaticType() {
+ return staticType;
+ }
+
+ public String toString() {
+ return staticType;// ou SELF
+ }
+
+ public void rename(String oldName, String newName) {
+ // TODO emit error
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/types/TypeSimple.java b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeSimple.java
new file mode 100644
index 0000000..3c91bbc
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeSimple.java
@@ -0,0 +1,71 @@
+package org.lisaac.ldt.model.types;
+
+import java.util.HashMap;
+
+import org.lisaac.ldt.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 typeBoolean; // for '=' operator
+
+ public static void init() {
+ typeNull = new TypeSimple(ILisaacModel.variable_null);
+ typeVoid = new TypeSimple(ILisaacModel.variable_void);
+ typeBoolean = new TypeSimple(ILisaacModel.prototype_boolean);
+ }
+
+ 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 getTypeVoid() {
+ return typeVoid;
+ }
+ public static ITypeMono getTypeNull() {
+ return typeNull;
+ }
+ public static ITypeMono getTypeBoolean() {
+ return typeBoolean;
+ }
+
+ public String toString() { // FIXME VOID pb
+ if (this.equals(typeVoid) || name.compareTo("VOID") == 0) {
+ return null; // do not print void type
+ }
+ return name;
+ }
+ public void rename(String oldName, String newName) {
+ if (name.compareTo(oldName) == 0) {
+ dico.put(name, null);
+ name = newName;
+ dico.put(name, this);
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/model/types/TypeStyle.java b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeStyle.java
new file mode 100644
index 0000000..7fdc595
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/model/types/TypeStyle.java
@@ -0,0 +1,43 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/outline/OutlineContentProvider.java b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineContentProvider.java
new file mode 100644
index 0000000..fafbac2
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineContentProvider.java
@@ -0,0 +1,53 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/outline/OutlineImages.java b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineImages.java
new file mode 100644
index 0000000..a07b4b0
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineImages.java
@@ -0,0 +1,27 @@
+package org.lisaac.ldt.outline;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.lisaac.ldt.LisaacPlugin;
+
+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 KEYWORD = getImage("/icons/keyword.gif");
+
+ public static final Image BLANK = getImage("/icons/blank.gif");
+
+
+ public static final String SORT_ALPHA = "/icons/alphab_sort_co.gif";
+ public static final String SORT_SECTION = "/icons/sections_co.gif";
+
+ private static Image getImage(String path) {
+ ImageDescriptor descr = LisaacPlugin.getImageDescriptor(path);
+ return descr.createImage();
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/outline/OutlineItem.java b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineItem.java
new file mode 100644
index 0000000..bb520c2
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineItem.java
@@ -0,0 +1,39 @@
+package org.lisaac.ldt.outline;
+
+import java.util.List;
+import org.eclipse.swt.graphics.Image;
+
+public abstract class OutlineItem implements Comparable<Object> {
+
+ public static boolean showSections = true;
+
+ 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/editor/eclipse/src/org/lisaac/ldt/outline/OutlineLabelProvider.java b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineLabelProvider.java
new file mode 100644
index 0000000..51c96eb
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineLabelProvider.java
@@ -0,0 +1,41 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/outline/OutlinePrototype.java b/editor/eclipse/src/org/lisaac/ldt/outline/OutlinePrototype.java
new file mode 100644
index 0000000..d55daff
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/outline/OutlinePrototype.java
@@ -0,0 +1,57 @@
+package org.lisaac.ldt.outline;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.lisaac.ldt.model.items.Prototype;
+
+public class OutlinePrototype extends OutlineItem {
+ protected String name;
+
+ protected List<OutlineItem> sections;
+
+
+ public OutlinePrototype(Prototype prototype, List<OutlineItem> sections) {
+ name = prototype.getName();
+ this.sections = sections;
+ }
+
+ /**
+ * 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() {
+ List<OutlineItem> result;
+
+ if (showSections) {
+ result = sections;
+ } else {
+ result = new ArrayList<OutlineItem>();
+ for (int i=0; i<sections.size(); i++) {
+ result.addAll(((OutlineSection)sections.get(i)).slots);
+ }
+ }
+ return result;
+ }
+
+ public int compareTo(Object arg0) {
+ return 0;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/outline/OutlineSection.java b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineSection.java
new file mode 100644
index 0000000..d45a4e1
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineSection.java
@@ -0,0 +1,72 @@
+package org.lisaac.ldt.outline;
+
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.items.Section;
+import org.lisaac.ldt.model.types.ITypeMono;
+
+public class OutlineSection extends OutlineItem {
+
+ protected Section section;
+
+ protected List<OutlineItem> slots;
+
+ public OutlineSection(Section section) {
+ this.section = section;
+ this.slots = section.getOutlineItems();
+
+ Position position = section.getPosition();
+
+ fstartOffset = position.getStartOffset() - 7;
+ fLength = 7;
+ //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="";
+ if (section != null) {
+ if (section.getName() != null) {
+ result = section.getName();
+ } else {
+ ITypeMono[] types = section.getTypeList();
+ for (int i=0; i<types.length; i++) {
+ result += types[i];
+ if (i != types.length-1) {
+ result += ", ";
+ }
+ }
+ }
+ }
+ 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 (section != null) {
+ return OutlineImages.PRIVATE_NONSHARED;
+ }
+ return null;
+ }
+
+ public List<OutlineItem> getChildren() {
+ return slots;
+ }
+
+ public int compareTo(Object arg0) {
+ return 0;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/outline/OutlineSlot.java b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineSlot.java
new file mode 100644
index 0000000..62de449
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/outline/OutlineSlot.java
@@ -0,0 +1,75 @@
+package org.lisaac.ldt.outline;
+
+import java.util.List;
+
+import org.eclipse.swt.graphics.Image;
+import org.lisaac.ldt.model.Position;
+import org.lisaac.ldt.model.items.Slot;
+import org.lisaac.ldt.model.types.IType;
+
+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.getSignature(false);
+ }
+ 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;
+ }
+
+ public int compareTo(Object obj) {
+ if (obj instanceof OutlineSlot) {
+ OutlineSlot slot = (OutlineSlot) obj;
+ return getText().compareTo(slot.getText());
+ }
+ return 0;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/perspectives/LisaacPerspective.java b/editor/eclipse/src/org/lisaac/ldt/perspectives/LisaacPerspective.java
new file mode 100644
index 0000000..63cef86
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/perspectives/LisaacPerspective.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * 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.lisaac.ldt.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 topLeft =
+ factory.createFolder(
+ "topLeft", //NON-NLS-1
+ IPageLayout.LEFT,
+ 0.25f,
+ factory.getEditorArea());
+ topLeft.addView(IPageLayout.ID_RES_NAV);
+
+ 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 topRight =
+ factory.createFolder(
+ "topRight", //NON-NLS-1
+ IPageLayout.RIGHT,
+ 0.80f,
+ factory.getEditorArea());
+ topRight.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.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.lisaac.ldt.prototype");//NON-NLS-1
+ factory.addNewWizardShortcut("org.lisaac.ldt.wizard");//NON-NLS-1
+ 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/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacColoringPage.java b/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacColoringPage.java
new file mode 100644
index 0000000..c87cbd9
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacColoringPage.java
@@ -0,0 +1,110 @@
+package org.lisaac.ldt.preferences;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.jface.preference.*;
+import org.eclipse.ui.*;
+import org.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.editors.ILisaacColor;
+
+/**
+ * Lisaac Syntax coloring preference page.
+ */
+public class LisaacColoringPage extends FieldEditorPreferencePage
+implements IWorkbenchPreferencePage {
+
+ private Group colorGroup;
+
+ private String[][] comboValues;
+
+ public LisaacColoringPage() {
+ super(GRID);
+ setPreferenceStore(LisaacPlugin.getDefault().getPreferenceStore());
+ }
+
+ public void createFieldEditors() {
+ colorGroup = new Group(getFieldEditorParent(),SWT.SHADOW_ETCHED_IN);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 3;
+ colorGroup.setLayoutData(gd);
+ colorGroup.setLayout(new GridLayout(2, false));
+ colorGroup.setText(LisaacMessages.getString("LisaacColoringPage.0")); //$NON-NLS-1$
+
+ String bold = LisaacMessages.getString("LisaacColoringPage.20");
+ String italics = LisaacMessages.getString("LisaacColoringPage.21");
+ String normal = LisaacMessages.getString("LisaacColoringPage.22");
+ String underline = LisaacMessages.getString("LisaacColoringPage.23");
+ String[][] values = {
+ {normal, ILisaacColor.PREF_NORMAL},
+ {bold, ILisaacColor.PREF_BOLD},
+ {italics, ILisaacColor.PREF_ITALICS},
+ {underline, ILisaacColor.PREF_UNDERLINE}
+ };
+ this.comboValues = values;
+
+
+ addField(new ColorFieldEditor(
+ ILisaacColor.PREF_COMMENT,
+ LisaacMessages.getString("LisaacColoringPage.2"), colorGroup)); //$NON-NLS-1$
+
+
+ createColorField(ILisaacColor.PREF_PROTOTYPE, ILisaacColor.STYLE_PROTOTYPE,
+ LisaacMessages.getString("LisaacColoringPage.3")); //$NON-NLS-1$
+
+ createColorField(ILisaacColor.PREF_PROTOTYPE_STYLE, ILisaacColor.STYLE_PROTOTYPE_STYLE,
+ LisaacMessages.getString("LisaacColoringPage.4")); //$NON-NLS-1$
+
+ createColorField(ILisaacColor.PREF_KEYWORD, ILisaacColor.STYLE_KEYWORD,
+ LisaacMessages.getString("LisaacColoringPage.5")); //$NON-NLS-1$
+
+ createColorField(ILisaacColor.PREF_SLOT, ILisaacColor.STYLE_SLOT,
+ LisaacMessages.getString("LisaacColoringPage.11")); //$NON-NLS-1$
+
+ createColorField(ILisaacColor.PREF_LOCAL_SLOT, ILisaacColor.STYLE_LOCAL_SLOT,
+ LisaacMessages.getString("LisaacColoringPage.12")); //$NON-NLS-1$
+
+ createColorField(ILisaacColor.PREF_CHARACTER, ILisaacColor.STYLE_CHARACTER,
+ LisaacMessages.getString("LisaacColoringPage.6")); //$NON-NLS-1$
+
+ createColorField(ILisaacColor.PREF_STRING, ILisaacColor.STYLE_STRING,
+ LisaacMessages.getString("LisaacColoringPage.7")); //$NON-NLS-1$
+
+ createColorField(ILisaacColor.PREF_NUMBER, ILisaacColor.STYLE_NUMBER,
+ LisaacMessages.getString("LisaacColoringPage.8")); //$NON-NLS-1$
+
+ createColorField(ILisaacColor.PREF_OPERATOR, ILisaacColor.STYLE_OPERATOR,
+ LisaacMessages.getString("LisaacColoringPage.9")); //$NON-NLS-1$
+
+
+ addField(new ColorFieldEditor(
+ ILisaacColor.PREF_EXTERNAL,
+ LisaacMessages.getString("LisaacColoringPage.10"), colorGroup)); //$NON-NLS-1$
+ }
+
+ private void createColorField(String prefColor, String prefStyle, String tokenName) {
+ Composite c = new Composite(colorGroup, SWT.NONE);
+ c.setLayout(new GridLayout(3, false));
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ c.setLayoutData(gd);
+
+ Label label = new Label(c, SWT.NONE);
+ gd = new GridData(80, 15);
+ label.setLayoutData(gd);
+ label.setText(tokenName);
+
+ Composite c2 = new Composite(c, SWT.NONE);
+ addField(new ColorFieldEditor(prefColor, "", c2));
+
+ c2 = new Composite(c, SWT.NONE);
+ addField(new ComboFieldEditor(prefStyle, "", comboValues, c2)); //$NON-NLS-1$
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+}
\ No newline at end of file
diff --git a/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacEditorPage.java b/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacEditorPage.java
new file mode 100644
index 0000000..9c5bd51
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacEditorPage.java
@@ -0,0 +1,53 @@
+package org.lisaac.ldt.preferences;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.jface.preference.*;
+import org.eclipse.ui.*;
+import org.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.LisaacPlugin;
+
+/**
+ * Lisaac Syntax coloring preference page.
+ */
+public class LisaacEditorPage extends FieldEditorPreferencePage
+implements IWorkbenchPreferencePage {
+
+ public LisaacEditorPage() {
+ super(GRID);
+ setPreferenceStore(LisaacPlugin.getDefault().getPreferenceStore());
+ }
+
+ public void createFieldEditors() {
+ Composite g = getFieldEditorParent();
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 3;
+ g.setLayoutData(gd);
+
+
+ addField(new BooleanFieldEditor(PreferenceConstants.P_LISAAC_INDENT,
+ LisaacMessages.getString("LisaacEditorPage.0"), g)); //$NON-NLS-1$
+ addField(new BooleanFieldEditor(PreferenceConstants.P_LISAAC_HOVER,
+ LisaacMessages.getString("LisaacEditorPage.1"), g)); //$NON-NLS-1$
+ addField(new BooleanFieldEditor(PreferenceConstants.P_LISAAC_FOLD,
+ LisaacMessages.getString("LisaacEditorPage.5"), g)); //$NON-NLS-1$
+
+ Group completionGroup = new Group(g,SWT.SHADOW_ETCHED_IN);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 3;
+ gd.verticalSpan = 2;
+ completionGroup.setLayoutData(gd);
+ completionGroup.setText(LisaacMessages.getString("LisaacEditorPage.2")); //$NON-NLS-1$
+
+ addField(new BooleanFieldEditor(PreferenceConstants.P_LISAAC_COMPLETION,
+ LisaacMessages.getString("LisaacEditorPage.3"), completionGroup)); //$NON-NLS-1$
+
+ addField(new StringFieldEditor(PreferenceConstants.P_LISAAC_COMPLETION_DELAY,
+ LisaacMessages.getString("LisaacEditorPage.4"), completionGroup)); //$NON-NLS-1$
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+}
\ No newline at end of file
diff --git a/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacPreferencePage.java b/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacPreferencePage.java
new file mode 100644
index 0000000..c699394
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacPreferencePage.java
@@ -0,0 +1,69 @@
+package org.lisaac.ldt.preferences;
+
+import org.eclipse.jface.preference.*;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbench;
+import org.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.LisaacPlugin;
+
+/**
+ * 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(LisaacMessages.getString("LisaacPreferencePage.0")); //$NON-NLS-1$
+ }
+
+ /**
+ * 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 StringFieldEditor(PreferenceConstants.P_LISAAC_USER,
+ LisaacMessages.getString("LisaacPreferencePage.1"), getFieldEditorParent())); //$NON-NLS-1$
+
+ //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/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacTemplatePage.java b/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacTemplatePage.java
new file mode 100644
index 0000000..382a089
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/preferences/LisaacTemplatePage.java
@@ -0,0 +1,25 @@
+package org.lisaac.ldt.preferences;
+
+
+import org.eclipse.ui.texteditor.templates.TemplatePreferencePage;
+import org.lisaac.ldt.LisaacPlugin;
+
+
+public class LisaacTemplatePage extends TemplatePreferencePage {
+ public LisaacTemplatePage() {
+ setPreferenceStore(LisaacPlugin.getDefault().getPreferenceStore());
+ setTemplateStore(LisaacPlugin.getDefault().getTemplateStore());
+ setContextTypeRegistry(LisaacPlugin.getDefault().getContextTypeRegistry());
+ }
+
+ protected boolean isShowFormatterSetting() {
+ return true;
+ }
+
+ public boolean performOk() {
+ boolean ok = super.performOk();
+
+ LisaacPlugin.getDefault().savePluginPreferences();
+ return ok;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/preferences/PreferenceConstants.java b/editor/eclipse/src/org/lisaac/ldt/preferences/PreferenceConstants.java
new file mode 100644
index 0000000..0756575
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/preferences/PreferenceConstants.java
@@ -0,0 +1,16 @@
+package org.lisaac.ldt.preferences;
+
+/**
+ * Constant definitions for plug-in preferences
+ */
+public class PreferenceConstants {
+
+ public static final String P_LISAAC_PATH = "lisaac_path";
+ public static final String P_LISAAC_USER = "lisaac_user";
+
+ public static final String P_LISAAC_INDENT = "lisaac_indent";
+ public static final String P_LISAAC_HOVER = "lisaac_hover";
+ public static final String P_LISAAC_FOLD = "lisaac_fold";
+ public static final String P_LISAAC_COMPLETION = "lisaac_competion";
+ public static final String P_LISAAC_COMPLETION_DELAY = "lisaac_competion_delay";
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/preferences/PreferenceInitializer.java b/editor/eclipse/src/org/lisaac/ldt/preferences/PreferenceInitializer.java
new file mode 100644
index 0000000..7bca019
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/preferences/PreferenceInitializer.java
@@ -0,0 +1,77 @@
+package org.lisaac.ldt.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.StringConverter;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.editors.ILisaacColor;
+
+
+/**
+ * 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");
+
+ store.setDefault(PreferenceConstants.P_LISAAC_INDENT, true);
+ store.setDefault(PreferenceConstants.P_LISAAC_HOVER, true);
+ store.setDefault(PreferenceConstants.P_LISAAC_FOLD, true);
+ store.setDefault(PreferenceConstants.P_LISAAC_COMPLETION, true);
+ store.setDefault(PreferenceConstants.P_LISAAC_COMPLETION_DELAY, 200);
+
+ // Colors for syntax highlighting.
+ store.setDefault(
+ ILisaacColor.PREF_COMMENT,
+ StringConverter.asString(ILisaacColor.COMMENT));
+ store.setDefault(
+ ILisaacColor.PREF_PROTOTYPE,
+ StringConverter.asString(ILisaacColor.PROTOTYPE));
+ store.setDefault(
+ ILisaacColor.PREF_PROTOTYPE_STYLE,
+ StringConverter.asString(ILisaacColor.PROTOTYPE_STYLE));
+ store.setDefault(
+ ILisaacColor.PREF_KEYWORD,
+ StringConverter.asString(ILisaacColor.KEYWORD));
+ store.setDefault(
+ ILisaacColor.PREF_SLOT,
+ StringConverter.asString(ILisaacColor.UNDEFINED));
+ store.setDefault(
+ ILisaacColor.PREF_LOCAL_SLOT,
+ StringConverter.asString(ILisaacColor.DEFAULT));
+ store.setDefault(
+ ILisaacColor.PREF_CHARACTER,
+ StringConverter.asString(ILisaacColor.CHARACTER));
+ store.setDefault(
+ ILisaacColor.PREF_STRING,
+ StringConverter.asString(ILisaacColor.STRING));
+ store.setDefault(
+ ILisaacColor.PREF_NUMBER,
+ StringConverter.asString(ILisaacColor.NUMBER));
+ store.setDefault(
+ ILisaacColor.PREF_OPERATOR,
+ StringConverter.asString(ILisaacColor.OPERATOR));
+ store.setDefault(
+ ILisaacColor.PREF_EXTERNAL,
+ StringConverter.asString(ILisaacColor.EXTERNAL));
+
+ // styles
+ store.setDefault(ILisaacColor.STYLE_CHARACTER, ILisaacColor.PREF_NORMAL);
+ store.setDefault(ILisaacColor.STYLE_KEYWORD, ILisaacColor.PREF_NORMAL);
+ store.setDefault(ILisaacColor.STYLE_LOCAL_SLOT, ILisaacColor.PREF_NORMAL);
+ store.setDefault(ILisaacColor.STYLE_NUMBER, ILisaacColor.PREF_NORMAL);
+ store.setDefault(ILisaacColor.STYLE_OPERATOR, ILisaacColor.PREF_NORMAL);
+ store.setDefault(ILisaacColor.STYLE_PROTOTYPE, ILisaacColor.PREF_NORMAL);
+ store.setDefault(ILisaacColor.STYLE_PROTOTYPE_STYLE, ILisaacColor.PREF_NORMAL);
+ store.setDefault(ILisaacColor.STYLE_SLOT, ILisaacColor.PREF_NORMAL);
+ store.setDefault(ILisaacColor.STYLE_STRING, ILisaacColor.PREF_NORMAL);
+ }
+}
+
diff --git a/editor/eclipse/src/org/lisaac/ldt/properties/LisaacProjectPropertyPage.java b/editor/eclipse/src/org/lisaac/ldt/properties/LisaacProjectPropertyPage.java
new file mode 100644
index 0000000..9d3219c
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/properties/LisaacProjectPropertyPage.java
@@ -0,0 +1,101 @@
+package org.lisaac.ldt.properties;
+
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.preference.PreferencePage;
+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.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.lisaac.ldt.model.LisaacModel;
+
+public class LisaacProjectPropertyPage extends PropertyPage {
+
+ private List pathValueList;
+
+ /**
+ * Constructor for SamplePropertyPage.
+ */
+ public LisaacProjectPropertyPage() {
+ super();
+ }
+
+ private void addSection(Composite parent) {
+ Composite composite = createDefaultComposite(parent);
+ Label label = new Label(composite, SWT.NONE);
+ label.setText("Project Path");
+
+ pathValueList = new List(composite, SWT.SINGLE | SWT.BORDER);
+ GridData gd = new GridData();
+ pathValueList.setLayoutData(gd);
+
+ Button refreshPathButton = new Button(parent, SWT.PUSH);
+ refreshPathButton.setText("Refresh Lisaac Path");
+ refreshPathButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ refreshList();
+ }
+ });
+ refreshList();
+ }
+
+ /**
+ * @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);
+
+ addSection(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 void refreshList() {
+ pathValueList.removeAll();
+
+ // Populate list
+ IProject project = (IProject) getElement();
+ LisaacModel model = LisaacModel.getModel(project);
+ if (model != null) {
+ model.getPathManager().refreshPath(project);
+
+ Iterator<String> it = model.getPathManager().getPathIterator();
+ while (it.hasNext()) {
+ pathValueList.add(it.next());
+ }
+ }
+ }
+
+ protected void performDefaults() {
+ }
+
+ public boolean performOk() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/editor/eclipse/src/org/lisaac/ldt/refactor/ChangeHeaderRefactor.java b/editor/eclipse/src/org/lisaac/ldt/refactor/ChangeHeaderRefactor.java
new file mode 100644
index 0000000..dd7c1b3
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/refactor/ChangeHeaderRefactor.java
@@ -0,0 +1,94 @@
+package org.lisaac.ldt.refactor;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.Refactoring;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.lisaac.ldt.model.AbstractLisaacParser;
+import org.lisaac.ldt.model.ILisaacFileVisitor;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.items.Prototype;
+
+public class ChangeHeaderRefactor extends Refactoring {
+
+ private String author, bibliography, copyright, license;
+
+ private LisaacModel model;
+
+
+ public ChangeHeaderRefactor(LisaacModel model) {
+ this.model = model;
+ }
+
+ public RefactoringStatus setLicense(String license) {
+ this.license = license;
+ return isValidLicense(license);
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ public void setBibliography(String bibliography) {
+ this.bibliography = bibliography;
+ }
+
+ public void setCopyright(String copyright) {
+ this.copyright = copyright;
+ }
+
+ public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
+ throws CoreException, OperationCanceledException {
+ RefactoringStatus status = isValidLicense(license);
+ return status;
+ }
+
+ public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
+ throws CoreException, OperationCanceledException {
+ RefactoringStatus status = isValidLicense(license);
+ return status;
+ }
+
+ public Change createChange(final IProgressMonitor pm) throws CoreException,
+ OperationCanceledException {
+ final CompositeChange result = new CompositeChange(getName());
+
+ int work = model.getPathManager().getSize();
+ pm.beginTask("Updating headers...", work);
+
+ model.accept(new ILisaacFileVisitor() {
+ public void visit(Prototype prototype) {
+ if (prototype != null) {
+ Change change = prototype.refactorHeader(author, bibliography, copyright, license);
+ if (change != null) {
+ result.add(change);
+ }
+ }
+ pm.worked(1);
+ }
+ });
+ pm.done();
+ return result;
+ }
+
+ private RefactoringStatus isValidLicense(String source) {
+ RefactoringStatus status = new RefactoringStatus();
+ if (source != null) {
+ AbstractLisaacParser parser = new AbstractLisaacParser(source);
+ parser.readSpace();
+ int offset = parser.getOffset();
+
+ if (offset < source.length()) {
+ status.addFatalError("The license must be inside Lisaac comments");
+ }
+ }
+ return status;
+ }
+
+ public String getName() {
+ return "Change Project Headers...";
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/refactor/ChangeHeaderWizard.java b/editor/eclipse/src/org/lisaac/ldt/refactor/ChangeHeaderWizard.java
new file mode 100644
index 0000000..d8c2834
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/refactor/ChangeHeaderWizard.java
@@ -0,0 +1,128 @@
+package org.lisaac.ldt.refactor;
+
+import org.eclipse.ltk.core.refactoring.Refactoring;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+
+class ChangeHeaderInputPage extends UserInputWizardPage {
+
+ private Text authorField;
+ private Text bibliographyField;
+ private Text copyrightField;
+ private Text licenseField;
+
+ public ChangeHeaderInputPage() {
+ super("ChangeHeaderInputPage");
+ }
+
+ public void createControl(Composite parent) {
+ Composite result= new Composite(parent, SWT.NONE);
+ setControl(result);
+
+ GridLayout layout= new GridLayout();
+ layout.numColumns= 2;
+ result.setLayout(layout);
+
+ Label label= new Label(result, SWT.NONE);
+ label.setText("&Author :");
+ authorField = createNameField(result);
+
+ label= new Label(result, SWT.NONE);
+ label.setText("&Bibliography :");
+ bibliographyField = createNameField(result);
+
+ label= new Label(result, SWT.NONE);
+ label.setText("&Copyright :");
+ copyrightField = createNameField(result);
+
+ Group group = new Group(result, SWT.NONE);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = 2;
+ gd.heightHint = 100;
+ gd.verticalSpan = 2;
+ group.setLayoutData(gd);
+ group.setLayout(new GridLayout());
+ group.setText("&License :");
+
+ licenseField = new Text(group, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
+ licenseField.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ authorField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent event) {
+ handleInputChanged(authorField);
+ }
+ });
+ bibliographyField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent event) {
+ handleInputChanged(bibliographyField);
+ }
+ });
+ copyrightField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent event) {
+ handleInputChanged(copyrightField);
+ }
+ });
+ licenseField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent event) {
+ handleInputChanged(licenseField);
+ }
+ });
+ authorField.setFocus();
+ }
+
+ private Text createNameField(Composite result) {
+ Text field= new Text(result, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ field.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ return field;
+ }
+
+ void handleInputChanged(Text field) {
+ RefactoringStatus status= new RefactoringStatus();
+
+ ChangeHeaderRefactor refactoring = (ChangeHeaderRefactor) getRefactoring();
+ if (field == authorField) {
+ refactoring.setAuthor(field.getText());
+ } else if (field == bibliographyField) {
+ refactoring.setBibliography(field.getText());
+ } else if (field == copyrightField) {
+ refactoring.setCopyright(field.getText());
+ } else {
+ status.merge(refactoring.setLicense(field.getText()));
+ }
+ setPageComplete(!status.hasError());
+ int severity= status.getSeverity();
+ String message= status.getMessageMatchingSeverity(severity);
+ if (severity >= RefactoringStatus.INFO) {
+ setMessage(message, severity);
+ } else {
+ setMessage("", NONE); //$NON-NLS-1$
+ }
+ }
+}
+
+public class ChangeHeaderWizard extends RefactoringWizard {
+
+ ChangeHeaderInputPage page;
+
+ public ChangeHeaderWizard(Refactoring refactoring, String title) {
+ super(refactoring, DIALOG_BASED_USER_INTERFACE | PREVIEW_EXPAND_FIRST_NODE);
+ setDefaultPageTitle(title);
+
+ page = new ChangeHeaderInputPage();
+ }
+
+ protected void addUserInputPages() {
+ addPage(page);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/refactor/RenamePrototypeRefactor.java b/editor/eclipse/src/org/lisaac/ldt/refactor/RenamePrototypeRefactor.java
new file mode 100644
index 0000000..0a2800c
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/refactor/RenamePrototypeRefactor.java
@@ -0,0 +1,109 @@
+package org.lisaac.ldt.refactor;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.Refactoring;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.core.refactoring.resource.RenameResourceChange;
+import org.lisaac.ldt.editors.LisaacScanner;
+import org.lisaac.ldt.model.ILisaacFileVisitor;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.items.Prototype;
+
+public class RenamePrototypeRefactor extends Refactoring {
+
+ private String oldName, newName;
+
+ private LisaacModel model;
+ private IPath prototypePath;
+
+ private boolean updateReferences;
+
+ public RenamePrototypeRefactor(String oldName, LisaacModel model) {
+ this.oldName = oldName;
+ this.model = model;
+ updateReferences = true;
+ }
+
+ public RefactoringStatus setNewPrototypeName(String newName) {
+ this.newName = newName;
+
+ return isValidPrototypeName(newName);
+ }
+
+ public void setUpdateReferences(boolean update) {
+ updateReferences = update;
+ }
+
+ public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
+ throws CoreException, OperationCanceledException {
+
+ RefactoringStatus status = isValidPrototypeName(newName);
+ // ...
+ return status;
+ }
+
+ public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
+ throws CoreException, OperationCanceledException {
+ RefactoringStatus status = isValidPrototypeName(oldName);
+
+ Prototype prototype = model.getPrototype(oldName);
+ if (prototype != null) {
+ prototypePath = prototype.getWorkspacePath();
+ } else {
+ status.addFatalError("The prototype do not exist in project");
+ }
+ return status;
+ }
+
+ public Change createChange(final IProgressMonitor pm) throws CoreException,
+ OperationCanceledException {
+ final CompositeChange result = new CompositeChange(getName());
+
+ // 1. rename the prototype in section header
+ Prototype prototype = model.getPrototype(oldName);
+ result.add(prototype.refactorRenameSelf(newName));
+
+ // 2. rename occurences in the project program
+ if (updateReferences) {
+ int work = model.getPathManager().getSize();
+ pm.beginTask("Collecting occurences...", work);
+
+ model.accept(new ILisaacFileVisitor() {
+ public void visit(Prototype prototype) {
+ if (prototype != null) {
+ Change change = prototype.refactorRenamePrototype(oldName, newName);
+ if (change != null) {
+ result.add(change);
+ }
+ }
+ pm.worked(1);
+ }
+ });
+ }
+ // 3. rename the prototype file
+ result.add(new RenameResourceChange(prototypePath, newName.toLowerCase()+".li"));
+ pm.done();
+
+ return result;
+ }
+
+ private RefactoringStatus isValidPrototypeName(String name) {
+ RefactoringStatus status = new RefactoringStatus();
+
+ if (name.length() == 0) {
+ status.addError("Empty name");
+ } else if (! LisaacScanner.isPrototypeIdentifier(name)) {
+ status.addError("Invalid prototype name");
+ }
+ return status;
+ }
+
+ public String getName() {
+ return "Rename Prototype...";
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/refactor/RenamePrototypeWizard.java b/editor/eclipse/src/org/lisaac/ldt/refactor/RenamePrototypeWizard.java
new file mode 100644
index 0000000..fdb39be
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/refactor/RenamePrototypeWizard.java
@@ -0,0 +1,112 @@
+package org.lisaac.ldt.refactor;
+
+import org.eclipse.ltk.core.refactoring.Refactoring;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
+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;
+
+
+class RenamePrototypeInputPage extends UserInputWizardPage {
+
+ Text fNameField;
+
+ String prototypeToRename;
+
+ public RenamePrototypeInputPage(String prototypeToRename) {
+ super("RenamePrototypeInputPage");
+ this.prototypeToRename = prototypeToRename;
+ }
+
+ public void createControl(Composite parent) {
+ Composite result= new Composite(parent, SWT.NONE);
+ setControl(result);
+
+ GridLayout layout= new GridLayout();
+ layout.numColumns= 2;
+ result.setLayout(layout);
+
+ Label label= new Label(result, SWT.NONE);
+ label.setText("&New name:");
+
+ fNameField= createNameField(result);
+
+ final Button referenceButton= new Button(result, SWT.CHECK);
+ referenceButton.setText("&Update references");
+ GridData data= new GridData(GridData.FILL_HORIZONTAL);
+ data.horizontalSpan= 2;
+ data.verticalIndent= 2;
+ referenceButton.setLayoutData(data);
+
+ fNameField.setText(prototypeToRename);
+
+ fNameField.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent event) {
+ handleInputChanged();
+ }
+ });
+
+ referenceButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ RenamePrototypeRefactor refactoring = (RenamePrototypeRefactor) getRefactoring();
+ refactoring.setUpdateReferences(referenceButton.getSelection());
+ }
+ });
+
+ referenceButton.setSelection(true);
+
+ fNameField.setFocus();
+ fNameField.selectAll();
+ handleInputChanged();
+ }
+
+ private Text createNameField(Composite result) {
+ Text field= new Text(result, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ field.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ return field;
+ }
+
+ void handleInputChanged() {
+ RefactoringStatus status= new RefactoringStatus();
+
+ RenamePrototypeRefactor refactoring = (RenamePrototypeRefactor) getRefactoring();
+ status.merge(refactoring.setNewPrototypeName(fNameField.getText()));
+
+ setPageComplete(!status.hasError());
+ int severity= status.getSeverity();
+ String message= status.getMessageMatchingSeverity(severity);
+ if (severity >= RefactoringStatus.INFO) {
+ setMessage(message, severity);
+ } else {
+ setMessage("", NONE); //$NON-NLS-1$
+ }
+ }
+
+}
+
+public class RenamePrototypeWizard extends RefactoringWizard {
+
+ RenamePrototypeInputPage page;
+
+ public RenamePrototypeWizard(Refactoring refactoring, String prototypeToRename, String title) {
+ super(refactoring, DIALOG_BASED_USER_INTERFACE | PREVIEW_EXPAND_FIRST_NODE);
+ setDefaultPageTitle(title);
+
+ page = new RenamePrototypeInputPage(prototypeToRename);
+ }
+
+ protected void addUserInputPages() {
+ addPage(page);
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/templates/LisaacContextType.java b/editor/eclipse/src/org/lisaac/ldt/templates/LisaacContextType.java
new file mode 100644
index 0000000..8619a7f
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/templates/LisaacContextType.java
@@ -0,0 +1,28 @@
+package org.lisaac.ldt.templates;
+
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+public class LisaacContextType extends TemplateContextType {
+ /** This context's id */
+ public static final String ID_CONTEXT_TYPE= "org.lisaac.ldt.contexttype"; //$NON-NLS-1$
+
+ /**
+ * Creates a new Lisaac context type.
+ */
+ public LisaacContextType() {
+ addGlobalResolvers();
+ }
+
+ private void addGlobalResolvers() {
+ addResolver(new GlobalTemplateVariables.Cursor());
+ addResolver(new GlobalTemplateVariables.WordSelection());
+ addResolver(new GlobalTemplateVariables.LineSelection());
+ addResolver(new GlobalTemplateVariables.Dollar());
+ addResolver(new GlobalTemplateVariables.Date());
+ addResolver(new GlobalTemplateVariables.Year());
+ addResolver(new GlobalTemplateVariables.Time());
+ addResolver(new GlobalTemplateVariables.User());
+ }
+
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/templates/LisaacTemplateProcessor.java b/editor/eclipse/src/org/lisaac/ldt/templates/LisaacTemplateProcessor.java
new file mode 100644
index 0000000..1321bc6
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/templates/LisaacTemplateProcessor.java
@@ -0,0 +1,48 @@
+package org.lisaac.ldt.templates;
+
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.swt.graphics.Image;
+import org.lisaac.ldt.LisaacPlugin;
+
+public class LisaacTemplateProcessor extends TemplateCompletionProcessor {
+
+
+ /**
+ * Simply return all templates.
+ *
+ * @param contextTypeId the context type, ignored in this implementation
+ * @return all templates
+ */
+ protected Template[] getTemplates(String contextTypeId) {
+ return LisaacPlugin.getDefault().getTemplateStore().getTemplates();
+ }
+
+ /**
+ * Return the XML context type that is supported by this plug-in.
+ *
+ * @param viewer the viewer, ignored in this implementation
+ * @param region the region, ignored in this implementation
+ * @return the supported XML context type
+ */
+ protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) {
+ return LisaacPlugin.getDefault().getContextTypeRegistry().getContextType(LisaacContextType.ID_CONTEXT_TYPE);
+ }
+
+ /**
+ * Always return the default image.
+ *
+ * @param template the template, ignored in this implementation
+ * @return the default template image
+ */
+ protected Image getImage(Template template) {
+ ImageDescriptor descr = LisaacPlugin.getImageDescriptor("icons/template.gif");
+ return descr.createImage();
+ }
+
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/views/ConsoleFactory.java b/editor/eclipse/src/org/lisaac/ldt/views/ConsoleFactory.java
new file mode 100644
index 0000000..974b4bc
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/views/ConsoleFactory.java
@@ -0,0 +1,54 @@
+package org.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/views/LisaacConsole.java b/editor/eclipse/src/org/lisaac/ldt/views/LisaacConsole.java
new file mode 100644
index 0000000..628bffb
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/views/LisaacConsole.java
@@ -0,0 +1,27 @@
+package org.lisaac.ldt.views;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.ui.console.IOConsole;
+import org.lisaac.ldt.LisaacMessages;
+
+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"; //$NON-NLS-1$
+
+ public LisaacConsole() {
+ super(LisaacMessages.getString("LisaacConsole.1"), CONSOLE_TYPE, null, true); //$NON-NLS-1$
+
+ Font font = JFaceResources.getFont(CONSOLE_FONT);
+ setFont(font);
+ }
+
+ /**
+ * Set the document's initial contents.
+ * Called by ConsoleFactory.
+ */
+ void initializeDocument() {
+ getDocument().set(""); //$NON-NLS-1$
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/views/LisaacOutlineView.java b/editor/eclipse/src/org/lisaac/ldt/views/LisaacOutlineView.java
new file mode 100644
index 0000000..17f9dd8
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/views/LisaacOutlineView.java
@@ -0,0 +1,268 @@
+package org.lisaac.ldt.views;
+
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+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.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.editors.LisaacEditor;
+import org.lisaac.ldt.model.LisaacModel;
+import org.lisaac.ldt.model.items.Prototype;
+import org.lisaac.ldt.outline.OutlineContentProvider;
+import org.lisaac.ldt.outline.OutlineImages;
+import org.lisaac.ldt.outline.OutlineItem;
+import org.lisaac.ldt.outline.OutlineLabelProvider;
+
+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);
+ createActions();
+
+ document = getDocument();
+ if (document != null) {
+ document.addDocumentListener(this);
+ }
+ update();
+ }
+
+ private void createActions() {
+
+ //---- Sort by name
+ Action sortByName = new Action("Sort by name", IAction.AS_CHECK_BOX) {
+
+ ViewerSorter sortByNameSorter;
+
+ public void setAlphaSort(boolean doSort) {
+ if (sortByNameSorter == null) {
+ sortByNameSorter = new ViewerSorter() {
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ return ((Comparable) e1).compareTo(e2);
+ }
+ };
+ }
+ getTreeViewer().setSorter(doSort ? sortByNameSorter : null);
+ }
+
+ public void run() {
+ setAlphaSort(isChecked());
+ }
+ };
+ sortByName.run();
+
+ //---- Sort by name
+ Action sortBySection= new Action("Sort by Section", IAction.AS_CHECK_BOX) {
+ public void run() {
+ OutlineItem.showSections = isChecked();
+ getTreeViewer().refresh();
+ getTreeViewer().expandAll();
+ }
+ };
+ sortBySection.setChecked(true);
+
+ try {
+ sortByName.setImageDescriptor(LisaacPlugin.getImageDescriptor(OutlineImages.SORT_ALPHA));
+ sortBySection.setImageDescriptor(LisaacPlugin.getImageDescriptor(OutlineImages.SORT_SECTION));
+ } catch (Exception e) {
+ }
+
+ // Add actions to the toolbar
+ IActionBars actionBars = getSite().getActionBars();
+ IToolBarManager toolbarManager = actionBars.getToolBarManager();
+ toolbarManager.add(sortByName);
+ toolbarManager.add(sortBySection);
+
+ /* IMenuManager menuManager = actionBars.getMenuManager();
+ menuManager.add(new OutlineHideCommentsAction(this, imageCache));
+ menuManager.add(new OutlineHideImportsAction(this, imageCache));
+ menuManager.add(new OutlineHideMagicObjectsAction(this, imageCache));
+ menuManager.add(new OutlineHideFieldsAction(this, imageCache));
+ menuManager.add(new OutlineHideNonPublicMembersAction(this, imageCache));
+ menuManager.add(new OutlineHideStaticMethodsAction(this, imageCache));
+ */
+ }
+
+ /**
+ * 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().expandAll();
+ }
+ }
+
+ 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
+ * @throws CoreException
+ */
+ public List<OutlineItem> getSourceOutline(IProject project, String filename) throws CoreException {
+ 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.lisaac.ldt.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();
+
+ try {
+ final List<OutlineItem> items = getSourceOutline(project, filename);
+
+ display.asyncExec(new Runnable() {
+ public void run() {
+ if (items != null) {
+ setInput(items.toArray(new OutlineItem[items.size()]));
+ //
+ ((LisaacEditor) textEditor).refreshPresentation();
+ //
+ }
+ }
+ });
+ } catch (CoreException e) {
+ }
+ }
+ }
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/wizards/AbstractNewFileWizard.java b/editor/eclipse/src/org/lisaac/ldt/wizards/AbstractNewFileWizard.java
new file mode 100644
index 0000000..e371f07
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/wizards/AbstractNewFileWizard.java
@@ -0,0 +1,155 @@
+package org.lisaac.ldt.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.lisaac.ldt.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/editor/eclipse/src/org/lisaac/ldt/wizards/AbstractNewFileWizardPage.java b/editor/eclipse/src/org/lisaac/ldt/wizards/AbstractNewFileWizardPage.java
new file mode 100644
index 0000000..a53312e
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/wizards/AbstractNewFileWizardPage.java
@@ -0,0 +1,259 @@
+package org.lisaac.ldt.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;
+import org.lisaac.ldt.LisaacMessages;
+
+
+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 = ""; //$NON-NLS-1$
+
+
+ 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();
+ layout.numColumns = 3;
+ container.setLayout(layout);
+
+ Label label = new Label(container, SWT.NULL);
+ label.setText(LisaacMessages.getString("AbstractNewFileWizardPage_1"));
+
+ 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(LisaacMessages.getString("AbstractNewFileWizardPage_2"));
+ button.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+
+ label = new Label(container, SWT.NULL);
+ label.setText(LisaacMessages.getString("AbstractNewFileWizardPage_3"));
+
+ fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ fileText.setLayoutData(gd);
+ fileText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ });
+
+ label = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 3;
+ label.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,
+ LisaacMessages.getString("AbstractNewFileWizardPage_4"));
+ 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(LisaacMessages.getString("AbstractNewFileWizardPage_5"));
+ return;
+ }
+ if (fileName.length() == 0) {
+ updateStatus(LisaacMessages.getString("AbstractNewFileWizardPage_6"));
+ return;
+ }
+ // TODO check container -> source folder !
+ 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(LisaacMessages.getString("AbstractNewFileWizardPage_7"));
+ 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/editor/eclipse/src/org/lisaac/ldt/wizards/InputParentDialog.java b/editor/eclipse/src/org/lisaac/ldt/wizards/InputParentDialog.java
new file mode 100644
index 0000000..66afe2a
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/wizards/InputParentDialog.java
@@ -0,0 +1,72 @@
+package org.lisaac.ldt.wizards;
+
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.lisaac.ldt.model.ILisaacModel;
+
+public class InputParentDialog extends InputDialog {
+
+ private String parentType;
+
+ public InputParentDialog(Shell parentShell, String dialogTitle) {
+ super(parentShell, dialogTitle, "Parent prototype name", "", new IInputValidator() {
+ public String isValid(String newText) {
+ if (newText.length() == 0) {
+ return "Empty name";
+ }
+ String correct = newText.toUpperCase();
+ if (newText.compareTo(correct) != 0) {
+ return "Invalid prototype name";
+ }
+ return null;
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Dialog.
+ */
+ protected Control createDialogArea(Composite parent) {
+ Composite c = (Composite) super.createDialogArea(parent);
+
+ Label label = new Label(c, SWT.NONE);
+ label.setText("Choose Parent inheritance type");
+
+ String[] values = {
+ ILisaacModel.inherit_shared,
+ ILisaacModel.inherit_nonshared,
+ ILisaacModel.inherit_shared_expanded,
+ ILisaacModel.inherit_nonshared_expanded
+ };
+ parentType = values[0];
+
+ final Combo combo = new Combo(c, SWT.NONE);
+ combo.setItems(values);
+ combo.select(0);
+ combo.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ widgetSelected(e);
+ }
+ public void widgetSelected(SelectionEvent e) {
+ parentType = combo.getText();
+ }
+ });
+ return c;
+ }
+
+ public String getParentName() {
+ return getValue();
+ }
+
+ public String getParentType() {
+ return parentType;
+ }
+}
diff --git a/editor/eclipse/src/org/lisaac/ldt/wizards/NewProjectWizard.java b/editor/eclipse/src/org/lisaac/ldt/wizards/NewProjectWizard.java
new file mode 100644
index 0000000..0291659
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/wizards/NewProjectWizard.java
@@ -0,0 +1,248 @@
+package org.lisaac.ldt.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.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
+import org.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.builder.LisaacNature;
+import org.lisaac.ldt.editors.LisaacResourceDecorator;
+import org.lisaac.ldt.model.LisaacModel;
+
+
+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;
+ 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, monitor);
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ } catch (NullPointerException e1) {
+ e1.printStackTrace();
+ }
+
+ try {
+ getContainer().run(false, false, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ Throwable realException = e.getTargetException();
+ MessageDialog.openError(getShell(), "Error !", realException.getMessage()); //$NON-NLS-1$
+ return false;
+ }
+ return true;
+ }
+
+ private void doFinish(String projectName, IPath nomRep, IProgressMonitor monitor)
+ throws CoreException
+ {
+ monitor.beginTask("Project Creation " + projectName, 4); //$NON-NLS-1$
+
+ // get project root
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+
+ try {
+ IProject project = root.getProject(projectName);
+ if (project.exists() && !project.isOpen()) {
+ project.open(monitor);
+ } else {
+ project.create(monitor);
+ project.open(monitor);
+ }
+ 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, monitor);
+
+ } catch (CoreException e) {
+ // Something went wrong
+ }
+ monitor.worked(1);
+
+ //
+ new LisaacModel(project);
+ //
+
+ monitor.worked(1);
+
+ // create make file for project
+ IFile lipFile = project.getFile("make.lip"); //$NON-NLS-1$
+ if (! lipFile.exists()) {
+ lipFile.create(new ByteArrayInputStream(getLipStream(project)), false, monitor);
+ }
+
+ // create default folder & files in project
+ IFolder src = project.getFolder("src"); //$NON-NLS-1$
+ if (! src.exists()) {
+ src.create(false, true, monitor);
+ src.setPersistentProperty(
+ new QualifiedName("", LisaacResourceDecorator.SOURCE_FOLDER_PROPERTY),
+ "true");
+ }
+
+ monitor.worked(1);
+ IFile mainPrototype = src.getFile(projectName.toLowerCase()+".li"); //$NON-NLS-1$
+ if (! mainPrototype.exists()) {
+ mainPrototype.create(new ByteArrayInputStream(getMainPrototypeStream(projectName)), false, monitor);
+ }
+ IFolder bin = project.getFolder("bin"); //$NON-NLS-1$
+ if (! bin.exists()) {
+ bin.create(false,true,monitor);
+ }
+ monitor.worked(1);
+ IFolder lib = project.getFolder("lib"); //$NON-NLS-1$
+ if (! lib.exists()) {
+ // create link to lib
+ /*IPath location = new Path(lisaacPath+"/lib");// FIXME path delimiter
+ lib.createLink(location, IResource.NONE, monitor);*/
+ lib.create(false,true,monitor);
+ lib.setPersistentProperty(
+ new QualifiedName("", LisaacResourceDecorator.LIB_PROPERTY),
+ "true");
+ }
+ } catch (IOException e) {
+ MessageDialog.openError(getShell(), "Project creation Error !", e.getMessage()); //$NON-NLS-1$
+ } catch (CoreException e) {
+ MessageDialog.openError(getShell(), "Project settings Error !", e.getMessage()); //$NON-NLS-1$
+ }
+ monitor.done();
+ }
+
+
+ public byte[] getMainPrototypeStream(String projectName) throws IOException {
+ String contents = "\nSection Header\n\n"; //$NON-NLS-1$
+ contents += " + name := "+projectName.toUpperCase()+";\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ contents += " - comment := \"Main Prototype\";\n"; //$NON-NLS-1$
+ contents += "\nSection Inherit\n\n"; //$NON-NLS-1$
+ contents += " - parent_object:OBJECT := OBJECT;\n"; //$NON-NLS-1$
+ contents += "\nSection Public\n\n"; //$NON-NLS-1$
+ contents += " - main <- \n"; //$NON-NLS-1$
+ contents += " // Main entry point.\n"; //$NON-NLS-1$
+ contents += " (\n\n"; //$NON-NLS-1$
+ contents += " \n"; //$NON-NLS-1$
+ contents += " );\n"; //$NON-NLS-1$
+ return contents.getBytes();
+ }
+
+ public byte[] getLipStream(IProject project) throws IOException {
+ String contents = "//\n// `"+project.getName()+"` LIsaac Project file\n//"; //$NON-NLS-1$ //$NON-NLS-2$
+ contents += "\nSection Inherit\n\n"; //$NON-NLS-1$
+ contents += " + parent:STRING;\n"; //$NON-NLS-1$
+ contents += "\nSection Private\n\n"; //$NON-NLS-1$
+ contents += " + project_root:STRING := \""+project.getLocationURI().getPath()+"/\";\n\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ contents += " - project_src_path <- \n"; //$NON-NLS-1$
+ contents += " // Define the project path for source code.\n"; //$NON-NLS-1$
+ contents += " (\n"; //$NON-NLS-1$
+ contents += " path (project_root + \"src/\");\n"; //$NON-NLS-1$
+ contents += " );\n\n"; //$NON-NLS-1$
+ contents += " - front_end <- \n"; //$NON-NLS-1$
+ contents += " // Executed by compiler, before compilation step.\n"; //$NON-NLS-1$
+ contents += " (\n"; //$NON-NLS-1$
+ contents += " project_src_path;\n"; //$NON-NLS-1$
+ contents += " general_front_end;\n"; //$NON-NLS-1$
+ contents += " );\n"; //$NON-NLS-1$
+ contents += "\nSection Public\n\n"; //$NON-NLS-1$
+ contents += " - debug_mode <- \n"; //$NON-NLS-1$
+ contents += " // Run in Debug Mode.\n"; //$NON-NLS-1$
+ contents += " (\n"; //$NON-NLS-1$
+ contents += " debug 15; // default level [1-20]\n"; //$NON-NLS-1$
+ contents += " );\n\n"; //$NON-NLS-1$
+ contents += " - clean <- \n"; //$NON-NLS-1$
+ contents += " // Clean project.\n"; //$NON-NLS-1$
+ contents += " (\n"; //$NON-NLS-1$
+ contents += " );\n"; //$NON-NLS-1$
+ return contents.getBytes();
+ }
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ setWindowTitle(LisaacMessages.getString("NewProjectWizard_46"));
+ setNeedsProgressMonitor(true);
+ mainPage = new NewProjectWizardPage(LisaacMessages.getString("NewProjectWizard_47"));
+ }
+
+ public void addPages() {
+ super.addPages();
+ addPage(mainPage);
+ }
+}
+
+class NewProjectWizardPage extends WizardNewProjectCreationPage {
+
+ NewProjectWizardPage(String pageName) {
+ super(pageName);
+ setTitle(pageName);
+ setDescription(LisaacMessages.getString("NewProjectWizard_48"));
+ }
+}
+/*
+class LicenseWizardPage extends WizardPage {
+
+ private Text licenseText;
+
+ LicenseWizardPage(String pageName) {
+ super(pageName);
+ setTitle(pageName);
+ setDescription("Specify the project license");
+ }
+
+ public String getLicense() {
+ return licenseText.getText();
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ licenseText = new Text(composite, SWT.MULTI);
+ licenseText.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ setControl(composite);
+ }
+}*/
diff --git a/editor/eclipse/src/org/lisaac/ldt/wizards/NewPrototypeWizard.java b/editor/eclipse/src/org/lisaac/ldt/wizards/NewPrototypeWizard.java
new file mode 100644
index 0000000..5b3291c
--- /dev/null
+++ b/editor/eclipse/src/org/lisaac/ldt/wizards/NewPrototypeWizard.java
@@ -0,0 +1,288 @@
+package org.lisaac.ldt.wizards;
+
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.jface.viewers.IStructuredSelection;
+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;
+import org.lisaac.ldt.LisaacMessages;
+import org.lisaac.ldt.LisaacPlugin;
+import org.lisaac.ldt.actions.GenerateConstructor;
+import org.lisaac.ldt.model.ILisaacModel;
+import org.lisaac.ldt.preferences.PreferenceConstants;
+import org.eclipse.jface.dialogs.InputDialog;
+
+import java.io.*;
+
+/**
+ * Lisaac source file creator.
+ */
+public class NewPrototypeWizard extends AbstractNewFileWizard {
+
+ public NewPrototypeWizard() {
+ super();
+ setWindowTitle(LisaacMessages.getString("NewPrototypeWizard_0"));
+ }
+
+ /**
+ * 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"; //$NON-NLS-1$
+
+ protected Text commentField;
+
+ protected Button styleNone;
+ protected Button styleExpanded;
+ protected Button styleStrict;
+
+ protected Table tableInherit;
+
+ protected Button generateConstructor, generateMain;
+
+
+ protected NewPrototypeWizardPage(IStructuredSelection selection) {
+ super(NewPrototypeWizardPage.class.getName(), selection);
+
+ setTitle(LisaacMessages.getString("NewPrototypeWizard_2"));
+ setDescription(LisaacMessages.getString("NewPrototypeWizard_3"));
+ setFileExtension(".li"); //$NON-NLS-1$
+
+ }
+
+ 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();
+
+ /* //IProject project = (IProject) ();
+ try {
+ String license = project.getPersistentProperty(new QualifiedName("",LICENSE_PROPERTY));
+ licenseText.setText(license);
+ } catch (CoreException e) {
+ }*/
+
+ String contents = "\nSection Header\n\n"; //$NON-NLS-1$
+ contents += " + name := "; //$NON-NLS-1$
+ if (isExpanded) {
+ contents += "Expanded "; //$NON-NLS-1$
+ } else if (isStrict) {
+ contents += "Strict "; //$NON-NLS-1$
+ }
+ contents += filename.toUpperCase()+";\n"; //$NON-NLS-1$
+
+ String descr = getPrototypeDescription();
+ if (descr != null && descr.length() > 0) {
+ contents += " - comment := \""+descr+"\";\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ String username = LisaacPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.P_LISAAC_USER);
+ if (username != null && username.length() > 0) {
+ contents += "\n - author := \""+username+"\";\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (! isExpanded) {
+ contents += "\nSection Inherit\n\n"; //$NON-NLS-1$
+ } else {
+ contents += "\nSection Insert\n\n"; //$NON-NLS-1$
+ }
+ 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 += " - "; //$NON-NLS-1$
+ } else {
+ contents += " + "; //$NON-NLS-1$
+ }
+ contents += "parent_"; //$NON-NLS-1$
+ contents += item.getText(0).toLowerCase() + ":"; //$NON-NLS-1$
+ if (type.equals(ILisaacModel.inherit_shared_expanded) ||
+ type.equals(ILisaacModel.inherit_nonshared_expanded)) {
+ contents += "Expanded " + item.getText(0); //$NON-NLS-1$
+ } else {
+ contents += item.getText(0) + " := " + item.getText(0); //$NON-NLS-1$
+ }
+ contents += ";\n"; //$NON-NLS-1$
+ }
+ } else {
+ contents += " - parent_object:OBJECT := OBJECT;\n"; //$NON-NLS-1$
+ }
+ contents += "\nSection Public\n\n"; //$NON-NLS-1$
+
+ if (generateConstructor.getSelection()) {
+ contents += GenerateConstructor.getConstructor();
+ }
+ if (generateMain.getSelection()) {
+ contents += " - main <- \n"; //$NON-NLS-1$
+ contents += " // Main entry point.\n"; //$NON-NLS-1$
+ contents += " (\n\n"; //$NON-NLS-1$
+ contents += " \n"; //$NON-NLS-1$
+ contents += " );\n"; //$NON-NLS-1$
+ }
+ return contents.getBytes();
+ }
+
+ /**
+ * Additional wizard information
+ */
+ public void createAdvancedControls(Composite parent) {
+
+ // -- Style --
+ Label label = new Label(parent, SWT.NONE);
+ label.setText(LisaacMessages.getString("NewPrototypeWizard_25"));
+ 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.setSelection(true);
+ styleNone.setText(LisaacMessages.getString("NewPrototypeWizard_26"));
+ styleExpanded = new Button(radioGroup, SWT.RADIO);
+ styleExpanded.setFont(parent.getFont());
+ styleExpanded.setText(LisaacMessages.getString("NewPrototypeWizard_27"));
+ styleStrict = new Button(radioGroup, SWT.RADIO);
+ styleStrict.setFont(parent.getFont());
+ styleStrict.setText(LisaacMessages.getString("NewPrototypeWizard_28"));
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ radioGroup.setLayoutData(gridData);
+ //
+
+ // -- Description --
+ label = new Label(parent, SWT.NONE);
+ label.setText(LisaacMessages.getString("NewPrototypeWizard_29"));
+ 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(LisaacMessages.getString("NewPrototypeWizard_30"));
+ 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"); //$NON-NLS-1$
+ c1.setWidth(150);
+ final TableColumn c2 = new TableColumn(table, SWT.LEFT);
+ c2.setText(LisaacMessages.getString("NewPrototypeWizard_32"));
+ 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}); //$NON-NLS-1$
+
+ Composite buttonGroup = new Composite(tableGroup, SWT.NONE);
+ buttonGroup.setLayout(new GridLayout());
+ Button tableAdd = new Button(buttonGroup, SWT.PUSH);
+ tableAdd.setFont(parent.getFont());
+ tableAdd.setText(LisaacMessages.getString("NewPrototypeWizard_34"));
+ tableAdd.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ InputParentDialog input = new InputParentDialog(getShell(), "New Parent...");
+ if (input.open() == InputDialog.OK) {
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setText(new String[] {input.getParentName(), input.getParentType()});
+ }
+ }
+ });
+ Button tableRemove= new Button(buttonGroup, SWT.PUSH);
+ tableRemove.setFont(parent.getFont());
+ tableRemove.setText(LisaacMessages.getString("NewPrototypeWizard_35"));
+ 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;
+ //
+
+ label = new Label(parent, SWT.NONE);
+ label.setText(LisaacMessages.getString("NewPrototypeWizard_36"));
+ label.setFont(parent.getFont());
+ gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 3;
+ label.setLayoutData(gridData);
+
+ gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 3;
+ gridData.horizontalAlignment = SWT.CENTER;
+ generateMain = new Button(parent, SWT.CHECK);
+ generateMain.setText(LisaacMessages.getString("NewPrototypeWizard_37"));
+ generateMain.setLayoutData(gridData);
+ generateConstructor = new Button(parent, SWT.CHECK);
+ generateConstructor.setText(LisaacMessages.getString("NewPrototypeWizard_38"));
+ generateConstructor.setLayoutData(gridData);
+ }
+
+ protected String getInitialFileName() {
+ return INITIAL_PROTOTYPE_NAME;
+ }
+}
--
Lisaac compiler
More information about the Lisaac-commits
mailing list