diff --git a/Ocaml/icons/markOccurrence.gif b/Ocaml/icons/markOccurrence.gif old mode 100755 new mode 100644 diff --git a/Ocaml/icons/shiftLeft.png b/Ocaml/icons/shiftLeft.png old mode 100755 new mode 100644 diff --git a/Ocaml/icons/shiftRight.png b/Ocaml/icons/shiftRight.png old mode 100755 new mode 100644 diff --git a/Ocaml/lib/beaver-cc.jar b/Ocaml/lib/beaver-cc.jar new file mode 100644 index 0000000..fab999e Binary files /dev/null and b/Ocaml/lib/beaver-cc.jar differ diff --git a/Ocaml/plugin.xml b/Ocaml/plugin.xml index 0b50421..982b8ed 100644 --- a/Ocaml/plugin.xml +++ b/Ocaml/plugin.xml @@ -70,30 +70,30 @@ point="org.eclipse.ui.editors"> @@ -739,21 +739,53 @@ + + + + + + + + + + + id="Ocaml_sourceActions_markOccurrences" label="Mark Occurrences" style="push"/> + id="Ocaml_sourceActions_shiftLeft" label="Shift Left" style="push"/> + id="Ocaml_sourceActions_shiftRight" label="Shift Right" style="push"/> + + + + + + + + + + + + + + + + + + + + + + @@ -890,6 +999,81 @@ id="Ocaml.shiftLeftCommand" name="Shift Left"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -978,7 +1159,97 @@ + sequence="M1+M3+N"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1099,22 +1381,50 @@ colorPreferenceValue="255,140,0" contributesToHeader="true" highlightPreferenceKey="syntaxerror.highlight" - highlightPreferenceValue="false" + highlightPreferenceValue="true" includeOnPreferencePage="true" - isGoToNextNavigationTarget="false" - isGoToPreviousNavigationTarget="false" + isGoToNextNavigationTarget="true" + isGoToNextNavigationTargetKey="true" + isGoToPreviousNavigationTarget="true" + isGoToPreviousNavigationTargetKey="true" label="Ocaml Syntax Error" overviewRulerPreferenceKey="syntaxerror.rulers.overview" overviewRulerPreferenceValue="true" presentationLayer="1" - showInNextPrevDropdownToolbarAction="false" + showInNextPrevDropdownToolbarAction="true" + showInNextPrevDropdownToolbarActionKey="true" symbolicIcon="error" textPreferenceKey="syntaxerror.text" textPreferenceValue="true" textStylePreferenceKey="syntaxerror.textstyle" textStylePreferenceValue="SQUIGGLES" verticalRulerPreferenceKey="syntaxerror.rulers.vertical" - verticalRulerPreferenceValue="false"> + verticalRulerPreferenceValue="true"> + + - - - - - - - - diff --git a/Ocaml/src/ocaml/FolderChangeListener.java b/Ocaml/src/ocaml/FolderChangeListener.java index 0ed759e..923b77e 100644 --- a/Ocaml/src/ocaml/FolderChangeListener.java +++ b/Ocaml/src/ocaml/FolderChangeListener.java @@ -43,10 +43,11 @@ public boolean visit(IResourceDelta delta) throws CoreException { switch (delta.getKind()) { case IResourceDelta.ADDED: { - // ignore special directories (.settings, .git, .cvsignore, etc.) + // ignore special directories (.settings, .git, .cvsignore, etc.) but not "." IResource r = res; while (r != null) { - if (r.getName().startsWith(".")) + String rName = r.getName(); + if (rName.startsWith(".")) return false; r = r.getParent(); } @@ -55,12 +56,24 @@ public boolean visit(IResourceDelta delta) throws CoreException { if(res.getName().equals("_build")) return false; - // add this path to the project paths + // add this path to the project paths when necessary OcamlPaths paths = new OcamlPaths(project); String[] strPaths = paths.getPaths(); - String[] newPaths = new String[strPaths.length + 1]; - System.arraycopy(strPaths, 0, newPaths, 0, strPaths.length); - newPaths[strPaths.length] = res.getProjectRelativePath().toPortableString(); + String resPath = res.getProjectRelativePath().toPortableString(); + + boolean needAdd = true; + for (String s: strPaths) { + if (s.compareTo(resPath) == 0) { + needAdd = false; + break; + } + } + String[] newPaths = strPaths; + if (needAdd) { + newPaths = new String[strPaths.length + 1]; + System.arraycopy(strPaths, 0, newPaths, 0, strPaths.length); + newPaths[strPaths.length] = resPath; + } paths.setPaths(newPaths); break; diff --git a/Ocaml/src/ocaml/OcamlPlugin.java b/Ocaml/src/ocaml/OcamlPlugin.java index 4f2e2d2..15fa911 100644 --- a/Ocaml/src/ocaml/OcamlPlugin.java +++ b/Ocaml/src/ocaml/OcamlPlugin.java @@ -37,6 +37,7 @@ import java.io.File; import java.net.URL; +import java.util.HashMap; import ocaml.debugging.OcamlDebugger; import ocaml.editor.syntaxcoloring.OcamlPartitionScanner; @@ -51,6 +52,7 @@ import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; @@ -72,6 +74,8 @@ public class OcamlPlugin extends AbstractUIPlugin { /** The singleton instance of the plug-in. */ private static OcamlPlugin instance = null; + + public static HashMap ActiveBuildJobs = new HashMap<>(); /** The directory in which the plug-in was started. */ private final String pluginDirectory; @@ -396,6 +400,11 @@ public static boolean getCommentIsBold() { return instance.getPreferenceStore().getBoolean(PreferenceConstants.P_BOLD_COMMENTS); } + /** Returns whether comments should appear in bold (from the user preferences) */ + public static boolean getDocsCommentIsBold() { + return instance.getPreferenceStore().getBoolean(PreferenceConstants.P_BOLD_DOCS_COMMENTS); + } + /** Returns whether constants should appear in bold (from the user preferences) */ public static boolean getConstantIsBold() { return instance.getPreferenceStore().getBoolean(PreferenceConstants.P_BOLD_CONSTANTS); diff --git a/Ocaml/src/ocaml/build/graph/CompilerVisitor.java b/Ocaml/src/ocaml/build/graph/CompilerVisitor.java index 9a3d187..79bfadb 100644 --- a/Ocaml/src/ocaml/build/graph/CompilerVisitor.java +++ b/Ocaml/src/ocaml/build/graph/CompilerVisitor.java @@ -22,13 +22,6 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorReference; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.part.FileEditorInput; /** * Visit a graph layer by layer, to compile all vertices in the right order.
diff --git a/Ocaml/src/ocaml/build/makefile/OcamlMakefileBuilder.java b/Ocaml/src/ocaml/build/makefile/OcamlMakefileBuilder.java index a9de21c..27a570f 100644 --- a/Ocaml/src/ocaml/build/makefile/OcamlMakefileBuilder.java +++ b/Ocaml/src/ocaml/build/makefile/OcamlMakefileBuilder.java @@ -258,8 +258,8 @@ protected IStatus run(IProgressMonitor monitor) { public void run() { try { project.refreshLocal(IProject.DEPTH_INFINITE, null); - } catch (CoreException e1) { - OcamlPlugin.logError("ocaml plugin error", e1); + } catch (Exception e) { +// OcamlPlugin.logError("ocaml plugin error", e); } } }); diff --git a/Ocaml/src/ocaml/debugging/OcamlDebugger.java b/Ocaml/src/ocaml/debugging/OcamlDebugger.java index 146d985..0b565ec 100644 --- a/Ocaml/src/ocaml/debugging/OcamlDebugger.java +++ b/Ocaml/src/ocaml/debugging/OcamlDebugger.java @@ -76,7 +76,7 @@ public enum State { /** The project containing the debugged executable */ private IProject project; - + /** list of paths of project */ private String[] projectPaths; @@ -240,7 +240,7 @@ public synchronized void start( pathStr = pathStr.trim(); if (!".".equals(pathStr)) { commandLineArgs.add("-I"); - + //These paths are either absolute or relative to the project //directory. We must convert them to absolute paths in case //we are running a bytecode within a nested directory. @@ -248,12 +248,14 @@ public synchronized void start( if (!path.isAbsolute()) { path = Paths.get(projectLocation.append(pathStr).toOSString()); } - commandLineArgs.add(path.toString()); + commandLineArgs.add(path.toString()); } } // add the _build folder (for the cases making project by using Ocamlbuild) String buildpath = projectLocation.append("_build").toOSString(); + commandLineArgs.add("-I"); + commandLineArgs.add(buildpath); ArrayList buildFolders = FileUtil.findSubdirectories(buildpath); for (String path: buildFolders) { commandLineArgs.add("-I"); @@ -429,7 +431,7 @@ public synchronized void backstepReturn() { send("start"); } } - + public synchronized void setFrame(int frame) { if (!checkStarted()) return; @@ -831,7 +833,6 @@ public void run() { refreshEditor(); state = State.Idle; } - else if (state.equals(State.Frame)) { processFrame(output); debuggerOutput.setLength(0); @@ -903,7 +904,7 @@ else if (state.equals(State.Quitting)) { } } - + private void getFrame() { state = State.Frame; send("frame"); @@ -1091,7 +1092,7 @@ private void processFrame(String output) { public static final Pattern patternCallstack = Pattern .compile("\\A#(\\d+)\\s+Pc\\s*:\\s+(\\d+)\\s+(\\w+)\\s+char\\s+(\\d+)"); - + private void processCallStack(final String output) { Display.getDefault().asyncExec(new Runnable() { public void run() { @@ -1138,7 +1139,7 @@ public void run() { // prettier stackview String newOutput = "#" + s1 + " - " + module + "." + functionName - + " - (" + line + ": " + column + ")"; + + " - (" + line + ": " + column + ")"; backtrace[i] = newOutput; } else { OcamlPlugin.logError("ocamldebugger: couldn't parse call stack"); @@ -1156,7 +1157,7 @@ public void run() { } }); } - + // get function that contains line private synchronized String findFunctionContainingLine(String filepath, int line) { String functionName = ""; @@ -1167,20 +1168,20 @@ private synchronized String findFunctionContainingLine(String filepath, int line int i = 0; for (i = 0; i < childs.size(); i++) { Def def = childs.get(i); - int l = Symbol.getLine(def.posStart); - if (l >= line ) + int l = Symbol.getLine(def.posStart); + if (l >= line ) break; } if (i > 0) { Def child = childs.get(i-1); if (child.type == Def.Type.Let) functionName = child.name; - else if (child.type == Def.Type.Module) { + else if (child.type == Def.Type.Module) { List grandChilds = child.children; int j = 0; for (j = 0; j < grandChilds.size(); j++) { Def def = grandChilds.get(j); - int l = Symbol.getLine(def.posStart); + int l = Symbol.getLine(def.posStart); if (l > line) break; } @@ -1192,7 +1193,7 @@ else if (child.type == Def.Type.Module) { } return functionName; } - + private void indicateRunningState(final String message) { Display.getDefault().asyncExec(new Runnable() { public void run() { @@ -1213,7 +1214,7 @@ public void run() { DebugMarkers.getInstance().clearCurrentPosition(); refreshEditor(); } - + private synchronized IEditorInput getEditorInput(final String filename) { String ufilename = filename.substring(0, 1).toUpperCase() + filename.substring(1); @@ -1277,6 +1278,7 @@ private synchronized String getFilePath(final String filename) return null; } + public void highlight(final String filename, final int offset) { final IEditorInput editorInput = getEditorInput(filename); if (editorInput != null) { @@ -1446,7 +1448,7 @@ public void run() { } }); } - + public void printMessage(final String message) { final IOConsoleOutputStream console = this.console; diff --git a/Ocaml/src/ocaml/debugging/views/OcamlCallStackView.java b/Ocaml/src/ocaml/debugging/views/OcamlCallStackView.java index 850f42b..1de777b 100644 --- a/Ocaml/src/ocaml/debugging/views/OcamlCallStackView.java +++ b/Ocaml/src/ocaml/debugging/views/OcamlCallStackView.java @@ -6,8 +6,6 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Rectangle; @@ -30,10 +28,10 @@ public void setCallStack(String elements[]){ list.removeAll(); for(String e : elements) list.add(e); + list.setRedraw(true); if (selectionIndex >= 0 && selectionIndex < elements.length) { list.setSelection(selectionIndex); } - list.setRedraw(true); } public void empty(){ diff --git a/Ocaml/src/ocaml/editor/actions/CancelCompileAllProjectsAction.java b/Ocaml/src/ocaml/editor/actions/CancelCompileAllProjectsAction.java new file mode 100644 index 0000000..9f28683 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/CancelCompileAllProjectsAction.java @@ -0,0 +1,91 @@ +package ocaml.editor.actions; + +import java.util.Collection; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; +import ocaml.editors.lex.OcamllexEditor; +import ocaml.editors.yacc.OcamlyaccEditor; +import ocaml.util.Misc; +import ocaml.views.OcamlCompilerOutput; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.part.FileEditorInput; + +/** This action activates completion in the OCaml editor. */ +public class CancelCompileAllProjectsAction implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + IWorkbenchPage page = window.getActivePage(); + if (page != null) { + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart != null) { + IProject project = null; + FileEditorInput editorInput = (FileEditorInput) editorPart.getEditorInput(); + if (editorInput != null && editorInput.getFile() != null) { + project = editorInput.getFile().getProject(); + } + + if (project == null) + return; + + // show compiler output + Misc.showView(OcamlCompilerOutput.ID); + // then activate current editor (to resolve shortcut-key issues) + page.activate(editorPart); + + final String jobName = "Cancelling compiling jobs"; + + Job job = new Job(jobName) { + @Override + protected IStatus run(IProgressMonitor monitor) { + if (!OcamlPlugin.ActiveBuildJobs.isEmpty()) { + // cancel all jobs + Collection monitors = OcamlPlugin.ActiveBuildJobs.values(); + for (IProgressMonitor m: monitors) { + m.setCanceled(true); + } + // clear them from store + OcamlPlugin.ActiveBuildJobs.clear(); + } + return Status.OK_STATUS; + } + }; + + job.setPriority(Job.BUILD); + job.setUser(action != null); + job.schedule(50); + }else + OcamlPlugin.logError("ContentAssistAction: editorPart is null"); + } else + OcamlPlugin.logError("ContentAssistAction: page is null"); + + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/CleanProjectAction.java b/Ocaml/src/ocaml/editor/actions/CleanProjectAction.java new file mode 100644 index 0000000..09fb562 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/CleanProjectAction.java @@ -0,0 +1,155 @@ +package ocaml.editor.actions; + +import java.util.concurrent.TimeUnit; + +import ocaml.OcamlPlugin; +import ocaml.build.makefile.OcamlMakefileBuilder; +import ocaml.editors.OcamlEditor; +import ocaml.editors.lex.OcamllexEditor; +import ocaml.editors.yacc.OcamlyaccEditor; +import ocaml.util.Misc; +import ocaml.views.OcamlCompilerOutput; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.part.FileEditorInput; + +/** This action activates completion in the OCaml editor. */ +public class CleanProjectAction implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + IWorkbenchPage page = window.getActivePage(); + if (page != null) { + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart != null) { + IProject project = null; + FileEditorInput editorInput = (FileEditorInput) editorPart.getEditorInput(); + if (editorInput != null && editorInput.getFile() != null) { + project = editorInput.getFile().getProject(); + } + + if (project == null) + return; + + final IProject buildProject = project; + final String jobName = "Cleaning project " + project.getName(); + + final long[] executedTime = new long[1]; + executedTime[0] = -1; + + // show compiler output + Misc.showView(OcamlCompilerOutput.ID); + // then activate current editor (to resolve shortcut-key issues) + page.activate(editorPart); + + Job job = new Job(jobName) { + @Override + protected IStatus run(IProgressMonitor monitor) { + // save progress monitor for later use + OcamlPlugin.ActiveBuildJobs.put(jobName, monitor); + + // cleaning + executedTime[0] = System.currentTimeMillis(); + OcamlMakefileBuilder builder = new OcamlMakefileBuilder(); + builder.clean(buildProject, monitor); + return Status.OK_STATUS; + } + }; + + job.setPriority(Job.BUILD); + /* + * If the action is directly called by the user, then we display a dialog box. Else, the launch is silent. + */ + job.setUser(action != null); + job.schedule(500); + job.addJobChangeListener(new IJobChangeListener() { + @Override + public void sleeping(IJobChangeEvent event) { + } + + @Override + public void scheduled(IJobChangeEvent event) { + } + + @Override + public void running(IJobChangeEvent event) { + } + + @Override + public void done(IJobChangeEvent event) { + // cleaning job was cancelled + if (!OcamlPlugin.ActiveBuildJobs.containsKey(jobName)) { + Misc.appendToOcamlConsole("Cleaning was cancelled!"); + } + // cleaning job terminates normally + else { + OcamlPlugin.ActiveBuildJobs.remove(jobName); + } + + // time + long cleaningTime = -1; + if (executedTime[0] > 0) + cleaningTime = System.currentTimeMillis() - executedTime[0]; + if (cleaningTime >= 0) { + long minutes = TimeUnit.MILLISECONDS.toMinutes(cleaningTime); + long seconds = TimeUnit.MILLISECONDS.toSeconds(cleaningTime) - + TimeUnit.MINUTES.toSeconds(minutes); + String time = ""; + if (minutes > 1) + time = time + String.valueOf(minutes) + " mins"; + else + time = time + String.valueOf(minutes) + " min"; + if (seconds > 1) + time = time + ", " + String.valueOf(seconds) + " secs"; + else + time = time + ", " + String.valueOf(seconds) + " sec"; + Misc.appendToOcamlConsole("Time: " + time); + } + else + Misc.appendToOcamlConsole("Time: unknown"); + + Misc.appendToOcamlConsole(""); + } + + @Override + public void awake(IJobChangeEvent event) { + } + + @Override + public void aboutToRun(IJobChangeEvent event) { + } + }); + + }else + OcamlPlugin.logError("ContentAssistAction: editorPart is null"); + } else + OcamlPlugin.logError("ContentAssistAction: page is null"); + + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/CommentSelectionAction.java b/Ocaml/src/ocaml/editor/actions/CommentSelectionAction.java index 16d831f..fef7ec7 100644 --- a/Ocaml/src/ocaml/editor/actions/CommentSelectionAction.java +++ b/Ocaml/src/ocaml/editor/actions/CommentSelectionAction.java @@ -39,7 +39,7 @@ public void run(IAction action) { int selEnd = selStart + selection.getLength(); // the last selected character can be a newline - if (selEnd > 1) + if (selEnd - selStart > 1) selEnd--; IEditorInput input = editor.getEditorInput(); @@ -67,7 +67,7 @@ public void run(IAction action) { editor.getSelectionProvider().setSelection(sel); } catch (BadLocationException e) { - OcamlPlugin.logError("Wrong offset", e); +// OcamlPlugin.logError("Wrong offset", e); return; } @@ -86,7 +86,7 @@ private String switchComment(String input) { final int tabSize = OcamlEditor.getTabSize(); // split the string into lines - String[] lines = input.split("\\r?\\n"); + String[] lines = input.split("\\r?\\n", -1); // uncomment if (isCommented(lines)) { @@ -163,8 +163,8 @@ else if (line.charAt(i) == ' ') // comment character should be inserted at the shortest indentation position // and at the end of longest line. private String comment(String line, int indent, int length, int tabSize) { - - if (line.trim().equals("")) + + if (line.trim().equals("")) return line; StringBuilder builder = new StringBuilder(); diff --git a/Ocaml/src/ocaml/editor/actions/CompileProjectAction.java b/Ocaml/src/ocaml/editor/actions/CompileProjectAction.java new file mode 100644 index 0000000..3d3cec3 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/CompileProjectAction.java @@ -0,0 +1,181 @@ +package ocaml.editor.actions; + +import java.util.concurrent.TimeUnit; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; +import ocaml.editors.lex.OcamllexEditor; +import ocaml.editors.yacc.OcamlyaccEditor; +import ocaml.util.Misc; +import ocaml.views.OcamlCompilerOutput; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.part.FileEditorInput; + +/** This action activates completion in the OCaml editor. */ +public class CompileProjectAction implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + final IWorkbenchPage page = window.getActivePage(); + if (page != null) { + /* + * Save all source code file before compiling + */ + IEditorReference[] editorReferences = page.getEditorReferences(); + NullProgressMonitor monitor = new NullProgressMonitor(); + if ( editorReferences != null ){ + for (IEditorReference iEditorReference : editorReferences) { + IEditorPart editor = iEditorReference.getEditor(false); + if (editor != null && editor.isDirty() + && ((editor instanceof OcamlEditor) + || (editor instanceof OcamllexEditor) + || (editor instanceof OcamlyaccEditor))) { + editor.doSave(monitor); + } + } + } + + /* + * Now build the project of current opened file + */ + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart != null) { + IProject project = null; + FileEditorInput editorInput = (FileEditorInput) editorPart.getEditorInput(); + if (editorInput != null && editorInput.getFile() != null) { + project = editorInput.getFile().getProject(); + } + + if (project == null) + return; + + final IProject buildProject = project; + + final String jobName = "Compiling project " + project.getName(); + + final long[] executedTime = new long[1]; + executedTime[0] = -1; + + Job job = new Job(jobName) { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + // save progress monitor for later use + OcamlPlugin.ActiveBuildJobs.put(jobName, monitor); + + // compile + executedTime[0] = System.currentTimeMillis(); + buildProject.build(IncrementalProjectBuilder.FULL_BUILD, monitor); + + } catch (CoreException e) { + OcamlPlugin.logError("ocaml plugin error", e); + } + return Status.OK_STATUS; + } + }; + + // show compiler output + Misc.showView(OcamlCompilerOutput.ID); + // then activate current editor (to resolve shortcut-key issues) + page.activate(editorPart); + + job.setPriority(Job.BUILD); + /* + * If the action is directly called by the user, then we display a dialog box. Else, the launch is silent. + */ + job.setUser(action != null); + job.schedule(500); + job.addJobChangeListener(new IJobChangeListener() { + @Override + public void sleeping(IJobChangeEvent event) { + } + + @Override + public void scheduled(IJobChangeEvent event) { + } + + @Override + public void running(IJobChangeEvent event) { + } + + @Override + public void done(IJobChangeEvent event) { + // compiling job was cancelled + if (!OcamlPlugin.ActiveBuildJobs.containsKey(jobName)) { + Misc.appendToOcamlConsole("Compilation was cancelled!"); + } + // compiling job terminates normally + else { + OcamlPlugin.ActiveBuildJobs.remove(jobName); + } + + // time + long compilingTime = -1; + if (executedTime[0] > 0) + compilingTime = System.currentTimeMillis() - executedTime[0]; + if (compilingTime >= 0) { + long minutes = TimeUnit.MILLISECONDS.toMinutes(compilingTime); + long seconds = TimeUnit.MILLISECONDS.toSeconds(compilingTime) - + TimeUnit.MINUTES.toSeconds(minutes); + String time = ""; + if (minutes > 1) + time = time + String.valueOf(minutes) + " mins"; + else + time = time + String.valueOf(minutes) + " min"; + if (seconds > 1) + time = time + ", " + String.valueOf(seconds) + " secs"; + else + time = time + ", " + String.valueOf(seconds) + " sec"; + Misc.appendToOcamlConsole("Time: " + time); + } + else + Misc.appendToOcamlConsole("Time: unknown"); + + Misc.appendToOcamlConsole(""); + } + + @Override + public void awake(IJobChangeEvent event) { + } + + @Override + public void aboutToRun(IJobChangeEvent event) { + } + }); + + }else + OcamlPlugin.logError("ContentAssistAction: editorPart is null"); + } else + OcamlPlugin.logError("ContentAssistAction: page is null"); + + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/DeleteTrailingWhitespaces.java b/Ocaml/src/ocaml/editor/actions/DeleteTrailingWhitespaces.java new file mode 100644 index 0000000..5c1e047 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/DeleteTrailingWhitespaces.java @@ -0,0 +1,120 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class DeleteTrailingWhitespaces implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + + TextSelection selection = (TextSelection) editor.getSelectionProvider().getSelection(); + + try { + int startLine = 0; + int endLine = 0; + if (selection.getLength() > 0) { + startLine = doc.getLineOfOffset(selection.getOffset()); + endLine = doc.getLineOfOffset(selection.getOffset() + selection.getLength()); + } + else { + startLine = 0; + endLine = doc.getNumberOfLines() - 1; + } + String newContent = removeTrailingWhitespaces(doc, startLine, endLine); + int startOffset = doc.getLineOffset(startLine); + int length = 0; + if (endLine < doc.getNumberOfLines() - 1) + length = doc.getLineOffset(endLine + 1) - doc.getLineDelimiter(endLine).length() - startOffset + 1; + else + length = doc.getLength() - startOffset; + doc.replace(startOffset, length, newContent); + editor.selectAndReveal(startOffset, newContent.length() - 1); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + private String removeTrailingWhitespaces(IDocument doc, int startLine, int endLine) throws Exception { + int line = startLine; + String newContent = ""; + while (line <= endLine) { + + int offset1 = doc.getLineOffset(line); + + if (line < doc.getNumberOfLines() - 1) { + String lineDelimiter = doc.getLineDelimiter(line); + int offset2 = doc.getLineOffset(line+1) - lineDelimiter.length(); + + String lineContent = doc.get(offset1, offset2 - offset1 + 1); + lineContent = "L" + lineContent; + lineContent = lineContent.trim(); + lineContent = lineContent.substring(1); + newContent = newContent + lineContent + lineDelimiter; + } + else { + String lineContent = doc.get(offset1, doc.getLength() - offset1); + lineContent = "L" + lineContent; + lineContent = lineContent.trim(); + lineContent = lineContent.substring(1); + newContent = newContent + lineContent; + } + + line++; + } + + return newContent; + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/GotoDefinition.java b/Ocaml/src/ocaml/editor/actions/GotoDefinition.java new file mode 100644 index 0000000..1ccccab --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/GotoDefinition.java @@ -0,0 +1,68 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; +import ocaml.editors.OcamlHyperlinkDetector; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class GotoDefinition implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + if (editorPart instanceof OcamlEditor) { + OcamlEditor editor = (OcamlEditor) editorPart; + TextSelection selection = + (TextSelection) editor.getSelectionProvider().getSelection(); + int offset = selection.getOffset(); + OcamlHyperlinkDetector hyperlinkdetector = new OcamlHyperlinkDetector(editor); + ITextViewer textViewer = editor.getTextViewer(); + IHyperlink hyperlink = hyperlinkdetector.makeHyperlink(textViewer, offset); + if (hyperlink != null) + hyperlink.open(); + } + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/MarkOccurrencesAction.java b/Ocaml/src/ocaml/editor/actions/MarkOccurrencesAction.java index 317ee48..5fefa8d 100644 --- a/Ocaml/src/ocaml/editor/actions/MarkOccurrencesAction.java +++ b/Ocaml/src/ocaml/editor/actions/MarkOccurrencesAction.java @@ -55,19 +55,22 @@ public void run(IAction action) { int endOffset = region.getOffset() + region.getLength(); marker.setAttribute(IMarker.CHAR_START, startOffset); marker.setAttribute(IMarker.CHAR_END, endOffset); + marker.setAttribute(IMarker.MESSAGE, ""); region = docFind.find(endOffset + 1, text, true, true, false, false); } } } catch (Exception e) { - OcamlPlugin.logError(e); +// OcamlPlugin.logError(e); } - } else - OcamlPlugin.logError(MarkOccurrencesAction.class.getSimpleName() + ": only works on ml and mli files"); - - } else - OcamlPlugin.logError(MarkOccurrencesAction.class.getSimpleName() + ": editorPart is null"); - } else - OcamlPlugin.logError(MarkOccurrencesAction.class.getSimpleName() + ": page is null"); + } +// else +// OcamlPlugin.logError(MarkOccurrencesAction.class.getSimpleName() + ": only works on ml and mli files"); + } +// else +// OcamlPlugin.logError(MarkOccurrencesAction.class.getSimpleName() + ": editorPart is null"); + } +// else +// OcamlPlugin.logError(MarkOccurrencesAction.class.getSimpleName() + ": page is null"); } public void dispose() { diff --git a/Ocaml/src/ocaml/editor/actions/MoveCursorDownwardByIndent.java b/Ocaml/src/ocaml/editor/actions/MoveCursorDownwardByIndent.java new file mode 100644 index 0000000..93c7de9 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/MoveCursorDownwardByIndent.java @@ -0,0 +1,174 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; + +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.swt.custom.StyledText; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class MoveCursorDownwardByIndent implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int cursorOffset = styledText.getCaretOffset(); + + try { + int lineNum= doc.getLineOfOffset(cursorOffset); + int numOfLine = doc.getNumberOfLines(); + int docLen = doc.getLength(); + + if (lineNum == (numOfLine - 2)) { + int lastLineOffset = doc.getLineOffset(lineNum+1); + editor.selectAndReveal(lastLineOffset, 0); + return; + } + + if (lineNum >= (numOfLine - 1)) { + editor.selectAndReveal(doc.getLength(), 0); + return; + } + + // ignore empty lines while going down, go to the first non empty line + int beginOffset = doc.getLineOffset(lineNum); + int endOffset = doc.getLineOffset(lineNum+1) - 1; + String currentLine = doc.get(beginOffset, endOffset - beginOffset + 1); + + if (currentLine.trim().isEmpty()) { + lineNum++; + while (lineNum < numOfLine) { + beginOffset = doc.getLineOffset(lineNum); + endOffset = (lineNum < numOfLine - 1) ? doc.getLineOffset(lineNum+1) - 1 : docLen - 1; + currentLine = doc.get(beginOffset, endOffset - beginOffset + 1); + if (currentLine.trim().isEmpty()) + lineNum++; + else + break; + } + if (lineNum >= numOfLine) + lineNum = numOfLine - 1; + int newOffset = doc.getLineOffset(lineNum); + while (newOffset < docLen) { + Character ch = doc.getChar(newOffset); + if (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r') + break; + else + newOffset++; + } + if (newOffset >= docLen) + newOffset = beginOffset; + editor.selectAndReveal(newOffset, 0); + return; + } + + // find next line which has different identation + int currentIndent = computeIndent(currentLine); + lineNum++; + while (lineNum < numOfLine - 1) { + beginOffset = doc.getLineOffset(lineNum); + endOffset = (lineNum < numOfLine - 1) ? doc.getLineOffset(lineNum+1) - 1 : docLen - 1; + String nextLine = doc.get(beginOffset, endOffset - beginOffset + 1); + int nextIndent = computeIndent(nextLine); + if (currentIndent != nextIndent) { + break; + } + else if (nextLine.trim().isEmpty()) { + currentIndent = -1; + lineNum++; + } + else { + lineNum++; + currentLine = nextLine; + currentIndent = nextIndent; + } + } + + // find location to jump to + int newLineOffset = doc.getLineOffset(lineNum); + int newOffset = newLineOffset; + while (newOffset < docLen) { + Character ch = doc.getChar(newOffset); + if (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r') + break; + else + newOffset++; + } + if (newOffset >= docLen) + newOffset = newLineOffset; + + editor.selectAndReveal(newOffset, 0); + } catch (BadLocationException e) { + e.printStackTrace(); + return; + } + } + + private int computeIndent(String line) { + if (line.trim().isEmpty()) + return 0; + + if (line.charAt(0) == ' ') + return 1 + computeIndent(line.substring(1)); + + if (line.charAt(0) == '\t') + return OcamlEditor.getTabSize() + computeIndent(line.substring(1)); + + return 0; + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/MoveCursorDownwardOneBlock.java b/Ocaml/src/ocaml/editor/actions/MoveCursorDownwardOneBlock.java new file mode 100644 index 0000000..3d82fd2 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/MoveCursorDownwardOneBlock.java @@ -0,0 +1,113 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; + +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.swt.custom.StyledText; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class MoveCursorDownwardOneBlock implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int cursorOffset = styledText.getCaretOffset(); + + try { + int lineNum= doc.getLineOfOffset(cursorOffset); + int numOfLine = doc.getNumberOfLines(); + + if (lineNum == (numOfLine - 2)) { + int lastLineOffset = doc.getLineOffset(lineNum+1); + editor.selectAndReveal(lastLineOffset, 0); + return; + } + + if (lineNum >= (numOfLine - 1)) { + editor.selectAndReveal(doc.getLength(), 0); + return; + } + + int beginOffset = doc.getLineOffset(lineNum); + int endOffset = doc.getLineOffset(lineNum+1) - 1; + String currentLine = doc.get(beginOffset, endOffset - beginOffset + 1); + boolean isCurrentLineEmpty = currentLine.trim().isEmpty(); + + // find next non-empty line which follows an empty line + lineNum++; + while (lineNum < numOfLine - 1) { + beginOffset = doc.getLineOffset(lineNum); + endOffset = doc.getLineOffset(lineNum+1) - 1; + String nextLine = doc.get(beginOffset, endOffset - beginOffset + 1); + if (nextLine.trim().isEmpty()) { + isCurrentLineEmpty = true; + lineNum++; + } + else if (!isCurrentLineEmpty) + lineNum++; + else + break; + } + int newOffset = doc.getLineOffset(lineNum); + editor.selectAndReveal(newOffset, 0); + } catch (BadLocationException e) { + e.printStackTrace(); + return; + } + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/MoveCursorUpwardByIndent.java b/Ocaml/src/ocaml/editor/actions/MoveCursorUpwardByIndent.java new file mode 100644 index 0000000..9373c72 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/MoveCursorUpwardByIndent.java @@ -0,0 +1,196 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; + +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.swt.custom.StyledText; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class MoveCursorUpwardByIndent implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int cursorOffset = styledText.getCaretOffset(); + + try { + int lineNum = doc.getLineOfOffset(cursorOffset); + int numOfLine = doc.getNumberOfLines(); + int docLen = doc.getLength(); + + if (lineNum <= 0) { + editor.selectAndReveal(0, 0); + return; + } + + // ignore empty lines when going back; + int beginOffsetCurrentLine = 0; + int endOffsetCurrentLine = 0; + String currentLine = ""; + while (lineNum > 0) { + beginOffsetCurrentLine = doc.getLineOffset(lineNum); + endOffsetCurrentLine = (lineNum < numOfLine-1) ? doc.getLineOffset(lineNum+1) - 1 : docLen - 1; + currentLine = doc.get(beginOffsetCurrentLine, endOffsetCurrentLine - beginOffsetCurrentLine + 1); + if (currentLine.trim().isEmpty()) { + lineNum--; + } + else + break; + } + if (lineNum == 0) { + editor.selectAndReveal(0, 0); + return; + } + + + // if previous line has different indentation and cursor is not + // in the beginning of current block, then go to the beginning. + beginOffsetCurrentLine = doc.getLineOffset(lineNum); + int cursorColumn = cursorOffset - beginOffsetCurrentLine; + int newOffset = beginOffsetCurrentLine; + while (newOffset < docLen) { + Character ch = doc.getChar(newOffset); + if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n') + break; + else + newOffset++; + } + int currentIndent = newOffset - beginOffsetCurrentLine; + + + int beginOffsetPrevLine = doc.getLineOffset(lineNum-1); + int endOffsetPrevLine = doc.getLineOffset(lineNum) - 1; + String prevLine = doc.get(beginOffsetPrevLine, endOffsetPrevLine - beginOffsetPrevLine + 1); + int prevIndent = computeIndent(prevLine); + if (prevLine.trim().isEmpty() && cursorColumn > currentIndent) { + newOffset = beginOffsetCurrentLine + currentIndent; + editor.selectAndReveal(newOffset, 0); + return; + } + else if ((prevIndent != currentIndent) && (cursorColumn > currentIndent)) { + newOffset = beginOffsetCurrentLine + currentIndent; + editor.selectAndReveal(newOffset, 0); + return; + } + + // ignore empty lines when going back; + lineNum--; + endOffsetCurrentLine = 0; + currentLine = ""; + while (lineNum > 0) { + beginOffsetCurrentLine = doc.getLineOffset(lineNum); + endOffsetCurrentLine = (lineNum < numOfLine-1) ? doc.getLineOffset(lineNum+1) - 1 : docLen; + currentLine = doc.get(beginOffsetCurrentLine, endOffsetCurrentLine - beginOffsetCurrentLine + 1); + if (currentLine.trim().isEmpty()) { + lineNum--; + } + else + break; + } + if (lineNum == 0) { + editor.selectAndReveal(0, 0); + return; + } + + + // search back to find the last line has different indentation + currentIndent = computeIndent(currentLine); + while (lineNum > 0) { + beginOffsetPrevLine = doc.getLineOffset(lineNum-1); + endOffsetPrevLine = doc.getLineOffset(lineNum) - 1; + prevLine = doc.get(beginOffsetPrevLine, endOffsetPrevLine - beginOffsetPrevLine + 1); + prevIndent = computeIndent(prevLine); + + if (prevLine.trim().isEmpty()) { + break; + } + else if (prevIndent == currentIndent) { + lineNum--; + currentLine = prevLine; + } + else + break; + } + newOffset = doc.getLineOffset(lineNum); + while (newOffset < docLen) { + Character ch = doc.getChar(newOffset); + if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n') + break; + else + newOffset++; + } + editor.selectAndReveal(newOffset, 0); + } catch (BadLocationException e) { + return; + } + } + + private int computeIndent(String line) { + if (line.trim().isEmpty()) + return 0; + + if (line.charAt(0) == ' ') + return 1 + computeIndent(line.substring(1)); + + if (line.charAt(0) == '\t') + return OcamlEditor.getTabSize() + computeIndent(line.substring(1)); + + return 0; + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/MoveCursorUpwardOneBlock.java b/Ocaml/src/ocaml/editor/actions/MoveCursorUpwardOneBlock.java new file mode 100644 index 0000000..5e47909 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/MoveCursorUpwardOneBlock.java @@ -0,0 +1,115 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; + +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.swt.custom.StyledText; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class MoveCursorUpwardOneBlock implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int cursorOffset = styledText.getCaretOffset(); + + try { + int lineNum= doc.getLineOfOffset(cursorOffset); + int numOfLine = doc.getNumberOfLines(); + + if (lineNum <= 0) { + editor.selectAndReveal(0, 0); + return; + } + + int currentLineOffset = doc.getLineOffset(lineNum); + + // if previous line is empty and cursor is not in beginning of + // current block, then go to the beginning. + int beginOffset = doc.getLineOffset(lineNum-1); + int endOffset = doc.getLineOffset(lineNum) - 1; + String prevLine= doc.get(beginOffset, endOffset - beginOffset + 1); + boolean isPrevLineEmpty = prevLine.trim().isEmpty(); + if (isPrevLineEmpty && (cursorOffset != currentLineOffset)) { + editor.selectAndReveal(currentLineOffset, 0); + return; + } + + // find previous non-empty line which follows an empty line + lineNum--; + while (lineNum > 0) { + beginOffset = doc.getLineOffset(lineNum-1); + endOffset = doc.getLineOffset(lineNum) - 1; + prevLine = doc.get(beginOffset, endOffset - beginOffset + 1); + if (!prevLine.trim().isEmpty()) { + isPrevLineEmpty = false; + lineNum--; + } + else if (isPrevLineEmpty) + lineNum--; + else { + break; // stop at this non-empty line + } + } + int newOffset = doc.getLineOffset(lineNum); + editor.selectAndReveal(newOffset, 0); + } catch (BadLocationException e) { + return; + } + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/SelectDownwardByIndent.java b/Ocaml/src/ocaml/editor/actions/SelectDownwardByIndent.java new file mode 100644 index 0000000..2c7ddd0 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/SelectDownwardByIndent.java @@ -0,0 +1,182 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; + +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.swt.custom.StyledText; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class SelectDownwardByIndent implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int cursorOffset = styledText.getCaretOffset(); + + Point selection = styledText.getSelection(); + int startOffset = (selection.x < cursorOffset) ? selection.x : selection.y; + + try { + int lineNum= doc.getLineOfOffset(cursorOffset); + int numOfLine = doc.getNumberOfLines(); + int docLen = doc.getLength(); + + if (lineNum == (numOfLine - 2)) { + int lastLineOffset = doc.getLineOffset(lineNum+1); + styledText.setSelection(startOffset, lastLineOffset); + return; + } + + if (lineNum >= (numOfLine - 1)) { + styledText.setSelection(startOffset, doc.getLength()); + return; + } + + // ignore empty lines while going down, go to the first non empty line + int beginOffset = doc.getLineOffset(lineNum); + int endOffset = doc.getLineOffset(lineNum+1) - 1; + String currentLine = doc.get(beginOffset, endOffset - beginOffset + 1); + + if (currentLine.trim().isEmpty()) { + lineNum++; + while (lineNum < numOfLine) { + beginOffset = doc.getLineOffset(lineNum); + endOffset = (lineNum < numOfLine - 1) ? doc.getLineOffset(lineNum+1) - 1 : docLen - 1; + currentLine = doc.get(beginOffset, endOffset - beginOffset + 1); + if (currentLine.trim().isEmpty()) + lineNum++; + else + break; + } + if (lineNum >= numOfLine) + lineNum = numOfLine - 1; + int newOffset = doc.getLineOffset(lineNum); + int k = newOffset; + while (k < docLen) { + Character ch = doc.getChar(k); + if (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r') + break; + else { + if (ch == '\n' || ch == '\r') + newOffset = k + 1; + k++; + } + } + + styledText.setSelection(startOffset, newOffset); + return; + } + + // find next line which has different identation + int currentIndent = computeIndent(currentLine); + lineNum++; + while (lineNum < numOfLine - 1) { + beginOffset = doc.getLineOffset(lineNum); + endOffset = (lineNum < numOfLine - 1) ? doc.getLineOffset(lineNum+1) - 1 : docLen - 1; + String nextLine = doc.get(beginOffset, endOffset - beginOffset + 1); + int nextIndent = computeIndent(nextLine); + if (currentIndent != nextIndent) { + break; + } + else if (nextLine.trim().isEmpty()) { + currentIndent = -1; + lineNum++; + } + else { + lineNum++; + currentLine = nextLine; + currentIndent = nextIndent; + } + } + + // find location to jump to + int newOffset = doc.getLineOffset(lineNum); + int k = newOffset; + while (k < docLen) { + Character ch = doc.getChar(k); + if (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r') + break; + else { + if (ch == '\n' || ch == '\r') + newOffset = k + 1; + k++; + } + } + + styledText.setSelection(startOffset, newOffset); + } catch (BadLocationException e) { + e.printStackTrace(); + return; + } + } + + private int computeIndent(String line) { + if (line.trim().isEmpty()) + return 0; + + if (line.charAt(0) == ' ') + return 1 + computeIndent(line.substring(1)); + + if (line.charAt(0) == '\t') + return OcamlEditor.getTabSize() + computeIndent(line.substring(1)); + + return 0; + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/SelectDownwardOneBlock.java b/Ocaml/src/ocaml/editor/actions/SelectDownwardOneBlock.java new file mode 100644 index 0000000..c2a77aa --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/SelectDownwardOneBlock.java @@ -0,0 +1,116 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; + +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.swt.custom.StyledText; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class SelectDownwardOneBlock implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int cursorOffset = styledText.getCaretOffset(); + + Point selection = styledText.getSelection(); + int startOffset = (selection.x < cursorOffset) ? selection.x : selection.y; + + try { + int lineNum= doc.getLineOfOffset(cursorOffset); + int numOfLine = doc.getNumberOfLines(); + + if (lineNum == (numOfLine - 2)) { + int lastLineOffset = doc.getLineOffset(lineNum+1); + styledText.setSelection(startOffset, lastLineOffset); + return; + } + + if (lineNum >= (numOfLine - 1)) { + styledText.setSelection(startOffset, doc.getLength()); + return; + } + + int beginOffset = doc.getLineOffset(lineNum); + int endOffset = doc.getLineOffset(lineNum+1) - 1; + String currentLine = doc.get(beginOffset, endOffset - beginOffset + 1); + boolean isCurrentLineEmpty = currentLine.trim().isEmpty(); + + // find next non-empty line which follows an empty line + lineNum++; + while (lineNum < numOfLine - 1) { + beginOffset = doc.getLineOffset(lineNum); + endOffset = doc.getLineOffset(lineNum+1) - 1; + String nextLine = doc.get(beginOffset, endOffset - beginOffset + 1); + if (nextLine.trim().isEmpty()) { + isCurrentLineEmpty = true; + lineNum++; + } + else if (!isCurrentLineEmpty) + lineNum++; + else + break; + } + int newOffset = doc.getLineOffset(lineNum); + styledText.setSelection(startOffset, newOffset); + } catch (BadLocationException e) { + return; + } + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/SelectUpwardByIndent.java b/Ocaml/src/ocaml/editor/actions/SelectUpwardByIndent.java new file mode 100644 index 0000000..3a9c351 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/SelectUpwardByIndent.java @@ -0,0 +1,200 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; + +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.swt.custom.StyledText; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class SelectUpwardByIndent implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int cursorOffset = styledText.getCaretOffset(); + + Point selection = styledText.getSelection(); + int startOffset = (selection.x < cursorOffset) ? selection.x : selection.y; + + try { + int lineNum = doc.getLineOfOffset(cursorOffset); + int numOfLine = doc.getNumberOfLines(); + int docLen = doc.getLength(); + + if (lineNum <= 0) { + styledText.setSelection(startOffset, 0); + return; + } + + // ignore empty lines when going back; + int beginOffsetCurrentLine = 0; + int endOffsetCurrentLine = 0; + String currentLine = ""; + while (lineNum > 0) { + beginOffsetCurrentLine = doc.getLineOffset(lineNum); + endOffsetCurrentLine = (lineNum < numOfLine-1) ? doc.getLineOffset(lineNum+1) - 1 : docLen - 1; + currentLine = doc.get(beginOffsetCurrentLine, endOffsetCurrentLine - beginOffsetCurrentLine + 1); + if (currentLine.trim().isEmpty()) { + lineNum--; + } + else + break; + } + if (lineNum == 0) { + styledText.setSelection(startOffset, 0); + return; + } + + + // if previous line has different indentation and cursor is not + // in the beginning of current block, then go to the beginning. + beginOffsetCurrentLine = doc.getLineOffset(lineNum); + int cursorColumn = cursorOffset - beginOffsetCurrentLine; + int newOffset = beginOffsetCurrentLine; + while (newOffset < docLen) { + Character ch = doc.getChar(newOffset); + if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n') + break; + else + newOffset++; + } + int currentIndent = newOffset - beginOffsetCurrentLine; + + + int beginOffsetPrevLine = doc.getLineOffset(lineNum-1); + int endOffsetPrevLine = doc.getLineOffset(lineNum) - 1; + String prevLine = doc.get(beginOffsetPrevLine, endOffsetPrevLine - beginOffsetPrevLine + 1); + int prevIndent = computeIndent(prevLine); + if (prevLine.trim().isEmpty() && cursorColumn > currentIndent) { + newOffset = beginOffsetCurrentLine;// + currentIndent; + styledText.setSelection(startOffset, newOffset); + return; + } + else if ((prevIndent != currentIndent) && (cursorColumn > currentIndent)) { + newOffset = beginOffsetCurrentLine;// + currentIndent; + styledText.setSelection(startOffset, newOffset); + return; + } + + // ignore empty lines when going back; + lineNum--; + endOffsetCurrentLine = 0; + currentLine = ""; + while (lineNum > 0) { + beginOffsetCurrentLine = doc.getLineOffset(lineNum); + endOffsetCurrentLine = (lineNum < numOfLine-1) ? doc.getLineOffset(lineNum+1) - 1 : docLen; + currentLine = doc.get(beginOffsetCurrentLine, endOffsetCurrentLine - beginOffsetCurrentLine + 1); + if (currentLine.trim().isEmpty()) { + lineNum--; + } + else + break; + } + if (lineNum == 0) { + styledText.setSelection(startOffset, 0); + return; + } + + + // search back to find the last line has different indentation + currentIndent = computeIndent(currentLine); + while (lineNum > 0) { + beginOffsetPrevLine = doc.getLineOffset(lineNum-1); + endOffsetPrevLine = doc.getLineOffset(lineNum) - 1; + prevLine = doc.get(beginOffsetPrevLine, endOffsetPrevLine - beginOffsetPrevLine + 1); + prevIndent = computeIndent(prevLine); + + if (prevLine.trim().isEmpty()) { + break; + } + else if (prevIndent == currentIndent) { + lineNum--; + currentLine = prevLine; + } + else + break; + } + newOffset = doc.getLineOffset(lineNum); +// while (newOffset < docLen) { +// Character ch = doc.getChar(newOffset); +// if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n') +// break; +// else +// newOffset++; +// } + styledText.setSelection(startOffset, newOffset); + } catch (BadLocationException e) { + return; + } + } + + private int computeIndent(String line) { + if (line.trim().isEmpty()) + return 0; + + if (line.charAt(0) == ' ') + return 1 + computeIndent(line.substring(1)); + + if (line.charAt(0) == '\t') + return OcamlEditor.getTabSize() + computeIndent(line.substring(1)); + + return 0; + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/SelectUpwardOneBlock.java b/Ocaml/src/ocaml/editor/actions/SelectUpwardOneBlock.java new file mode 100644 index 0000000..37b7a56 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/SelectUpwardOneBlock.java @@ -0,0 +1,118 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; + +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.swt.custom.StyledText; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class SelectUpwardOneBlock implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + TextEditor editor = (TextEditor) editorPart; + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int cursorOffset = styledText.getCaretOffset(); + + Point selection = styledText.getSelection(); + int startOffset = (selection.x < cursorOffset) ? selection.x : selection.y; + + try { + int lineNum= doc.getLineOfOffset(cursorOffset); + int numOfLine = doc.getNumberOfLines(); + + if (lineNum <= 0) { + styledText.setSelection(startOffset, 0); + return; + } + + int currentLineOffset = doc.getLineOffset(lineNum); + + // if previous line is empty and cursor is not in beginning of + // current block, then go to the beginning. + int beginOffset = doc.getLineOffset(lineNum-1); + int endOffset = doc.getLineOffset(lineNum) - 1; + String prevLine= doc.get(beginOffset, endOffset - beginOffset + 1); + boolean isPrevLineEmpty = prevLine.trim().isEmpty(); + if (isPrevLineEmpty && (cursorOffset != currentLineOffset)) { + styledText.setSelection(startOffset, currentLineOffset); + return; + } + + // find previous non-empty line which follows an empty line + lineNum--; + while (lineNum > 0) { + beginOffset = doc.getLineOffset(lineNum-1); + endOffset = doc.getLineOffset(lineNum) - 1; + prevLine = doc.get(beginOffset, endOffset - beginOffset + 1); + if (!prevLine.trim().isEmpty()) { + isPrevLineEmpty = false; + lineNum--; + } + else if (isPrevLineEmpty) + lineNum--; + else { + break; // stop at this non-empty line + } + } + int newOffset = doc.getLineOffset(lineNum); + styledText.setSelection(startOffset, newOffset); + } catch (BadLocationException e) { + return; + } + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } +} diff --git a/Ocaml/src/ocaml/editor/actions/ShiftLeftAction.java b/Ocaml/src/ocaml/editor/actions/ShiftLeftAction.java index cb7f626..38f9041 100644 --- a/Ocaml/src/ocaml/editor/actions/ShiftLeftAction.java +++ b/Ocaml/src/ocaml/editor/actions/ShiftLeftAction.java @@ -85,39 +85,38 @@ private String decreaseIndentation(String input) { String[] lines = input.split("\\r?\\n"); if (lines.length > 0) { - // find the shortest indentation - int shortest = lines[0].length(); + // compute decrease size + int decrease = tabSize; for (String line : lines) { - int indent = calculateIndent(line, tabSize); - if (indent < shortest) - shortest = indent; + if (!line.trim().isEmpty()) { + int indent = calculateIndent(line, tabSize); + if (indent < decrease) + decrease = indent; + } } - if (shortest == 0) // nothing left to decrease + if (decrease == 0) // nothing left to decrease return input; - // the size of indentation will be decreased - int decrease = tabSize; - if (shortest < tabSize) - decrease = shortest; - // subtract 1 indentation from each lines for (int i = 0; i < lines.length; i++) { String line = lines[i]; - int d = 0; - int u = 0; - for (u = 0; u < line.length(); u++) { - if (line.charAt(u) == ' ') - d++; - else if (line.charAt(u) == '\t') - d = d + tabSize; - if (d >= decrease) - break; + if (line.length() >= decrease) { + int d = 0; + int u = 0; + for (u = 0; u < line.length(); u++) { + if (line.charAt(u) == ' ') + d++; + else if (line.charAt(u) == '\t') + d = d + tabSize; + if (d >= decrease) + break; + } + String newline = ""; + for (int j = 0; j < d - decrease; j++) + newline = newline + ' '; + newline = newline + line.substring(u + 1); + lines[i] = newline; } - String newline = ""; - for (int j = 0; j < d - decrease; j++) - newline = newline + ' '; - newline = newline + line.substring(u + 1); - lines[i] = newline; } // rebuild a string from the lines diff --git a/Ocaml/src/ocaml/editor/actions/ShowTextHover.java b/Ocaml/src/ocaml/editor/actions/ShowTextHover.java new file mode 100644 index 0000000..58d5c1b --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/ShowTextHover.java @@ -0,0 +1,89 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; +import ocaml.editors.OcamlTextHover; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +public class ShowTextHover implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(GotoDefinition.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof OcamlEditor)) { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + final OcamlEditor editor = (OcamlEditor) editorPart; + ITextViewer viewer = editor.getTextViewer(); + IEditorInput editorInput = editor.getEditorInput(); + IDocument doc = editor.getDocumentProvider().getDocument(editorInput); + Control control = (Control)editor.getAdapter(Control.class); + + if (!(control instanceof StyledText)) + { + OcamlPlugin.logError(GotoDefinition.class.getSimpleName() + + ": Cannot get caret position"); + return; + } + + final StyledText styledText = (StyledText) control; + int offset = styledText.getCaretOffset(); + + OcamlTextHover hover = new OcamlTextHover(editor); + IRegion region = hover.getHoverRegion(viewer, offset); + final String hoverInfo = hover.getHoverInfoOneLine(viewer, region); + + Display.getCurrent().asyncExec(new Runnable() { + public void run() { + if (!hoverInfo.equals("")) + editor.setStatusLineMessage(hoverInfo); + else + editor.setStatusLineMessage(""); + } + }); + + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/actions/SynchronizeAndGotoOutline.java b/Ocaml/src/ocaml/editor/actions/SynchronizeAndGotoOutline.java new file mode 100644 index 0000000..01e3936 --- /dev/null +++ b/Ocaml/src/ocaml/editor/actions/SynchronizeAndGotoOutline.java @@ -0,0 +1,66 @@ +package ocaml.editor.actions; + +import ocaml.OcamlPlugin; +import ocaml.editors.OcamlEditor; +import ocaml.editors.OcamlHyperlinkDetector; +import ocaml.util.Misc; +import ocaml.views.OcamlCompilerOutput; +import ocaml.views.outline.OcamlOutlineControl; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.editors.text.TextEditor; + +public class SynchronizeAndGotoOutline implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void run(IAction action) { + + IWorkbenchPage page = window.getActivePage(); + + if (page == null) { + OcamlPlugin.logWarning(SynchronizeAndGotoOutline.class.getSimpleName() + + ": page is null"); + return; + } + + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart == null) { + OcamlPlugin.logError(SynchronizeAndGotoOutline.class.getSimpleName() + + ": editorPart is null"); + return; + } + + if (!(editorPart instanceof TextEditor)) { + OcamlPlugin.logError(SynchronizeAndGotoOutline.class.getSimpleName() + + ": only works on ml and mli files"); + return; + } + + if (editorPart instanceof OcamlEditor) { + OcamlEditor editor = (OcamlEditor) editorPart; + editor.synchronizeOutline(); + // show compiler output + editor.getOutline().setFocus(); + } + } + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void selectionChanged(IAction action, ISelection selection) { + } + +} diff --git a/Ocaml/src/ocaml/editor/completion/CompletionJob.java b/Ocaml/src/ocaml/editor/completion/CompletionJob.java index e85c2db..1be467f 100644 --- a/Ocaml/src/ocaml/editor/completion/CompletionJob.java +++ b/Ocaml/src/ocaml/editor/completion/CompletionJob.java @@ -140,19 +140,22 @@ public static Def buildDefinitionsTree(IProject project, boolean bUsingEditor) { } if (!(dir.exists() && dir.isDirectory())) { - OcamlPlugin.logError("Wrong path:" + dir.toString() + " (in project:" - + project.getName() + ")"); continue; } // get all the ml and mli files from the directory String[] mlmliFiles = dir.list(mlmliFilter); + /* * keep all the mli files, and discard the ml files when there is a mli file with * the same name */ - String[] files = Misc.filterInterfaces(mlmliFiles); + // String[] files = Misc.filterInterfaces(mlmliFiles); + + // Trung: use both ml & mli files + String[] files = mlmliFiles; + // for each file for (String mlmlifile : files) { diff --git a/Ocaml/src/ocaml/editor/completion/OcamlCompletionProcessor.java b/Ocaml/src/ocaml/editor/completion/OcamlCompletionProcessor.java index e0db003..dbbd5c6 100644 --- a/Ocaml/src/ocaml/editor/completion/OcamlCompletionProcessor.java +++ b/Ocaml/src/ocaml/editor/completion/OcamlCompletionProcessor.java @@ -1,6 +1,9 @@ package ocaml.editor.completion; +import java.io.File; +import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.HashSet; import ocaml.OcamlPlugin; import ocaml.editor.syntaxcoloring.OcamlPartitionScanner; @@ -9,16 +12,26 @@ import ocaml.editors.yacc.OcamlyaccEditor; import ocaml.parser.Def; import ocaml.util.Misc; +import ocaml.typeHovers.OcamlAnnotParser; +import ocaml.typeHovers.TypeAnnotation; +import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; 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.contentassist.ContextInformation; 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.ui.dialogs.NewFolderDialog; +import org.eclipse.ui.editors.text.TextEditor; +import org.eclipse.ui.editors.text.TextFileDocumentProvider; +import org.eclipse.ui.texteditor.IDocumentProvider; /** * This class is responsible for managing completion in the OCaml editor. @@ -28,29 +41,35 @@ */ public class OcamlCompletionProcessor implements IContentAssistProcessor { - // private final OcamlEditor ocamlEditor; + private final TextEditor editor; private final IProject project; + // cache last parsed annotation file for speed up + private TypeAnnotation[] lastUsedAnnotations = new TypeAnnotation[0]; + private String lastParsedFileName = ""; + private long lastParsedTime = 0; + private static int cacheTime = 2000; + /** The partition type in which completion was triggered. */ private final String partitionType; public OcamlCompletionProcessor(OcamlEditor edit, String regionType) { - // this.ocamlEditor = edit; - this.partitionType = regionType; + this.editor = (TextEditor)edit; this.project = edit.getProject(); + this.partitionType = regionType; } public OcamlCompletionProcessor(OcamllexEditor edit, String regionType) { - // this.ocamlEditor = null; - this.partitionType = regionType; + this.editor = (TextEditor)edit; this.project = edit.getProject(); + this.partitionType = regionType; } public OcamlCompletionProcessor(OcamlyaccEditor edit, String regionType) { - // this.ocamlEditor = null; - this.partitionType = regionType; + this.editor = (TextEditor)edit; this.project = edit.getProject(); + this.partitionType = regionType; } /** @@ -99,20 +118,27 @@ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int String completion = completionExpression(viewer, documentOffset); - OcamlCompletionProposal[] proposals; - /* - * If the interfaces parsing Job isn't done, we return an empty list to avoid blocking the graphical - * interface by doing a potentially long search (should be quick normally, but not on a network file - * system for example). - */ + OcamlCompletionProposal[] proposals = new OcamlCompletionProposal[0]; + + IDocument document = viewer.getDocument(); + + // must wait parsing job finish first. if (CompletionJob.isParsingFinished()) { - Def definitionsRoot = CompletionJob.buildDefinitionsTree(this.project, true); - proposals = findCompletionProposals(completion, definitionsRoot, documentOffset); + Def interfacesDefinitionsRoot = null; + if (project != null) + interfacesDefinitionsRoot = CompletionJob.buildDefinitionsTree(project, false); + + Def outlineDefinitionsRoot = null; // definitions of current editting file + if (editor instanceof OcamlEditor) { + outlineDefinitionsRoot = ((OcamlEditor) editor).getOutlineDefinitionsTree(); + } + + proposals = findCompletionProposals(completion, interfacesDefinitionsRoot, outlineDefinitionsRoot, document, documentOffset); } else { proposals = new OcamlCompletionProposal[0]; OcamlPlugin.logInfo("Completion proposals skipped (background job not done yet)"); } - + ICompletionProposal[] templateCompletionProposals; OcamlTemplateCompletionProcessor tcp = new OcamlTemplateCompletionProcessor(); @@ -137,7 +163,7 @@ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int * ocamlEditor.getOutlineDefinitionsTree(); if (def != null) { ICompletionProposal[] * moduleCompletionProposals = findModuleCompletionProposals( def, documentOffset, lastWord.length(), * lastWord); - * + * * for (int j = 0; j < moduleCompletionProposals.length; j++) * allProposals.add(moduleCompletionProposals[j]); } else OcamlPlugin * .logError("OcamlCompletionProcessor:computeCompletionProposals : module definitions=null"); } @@ -150,7 +176,7 @@ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int /* * if (allProposals.size() == 2) { ICompletionProposal prop1 = allProposals.get(0); * ICompletionProposal prop2 = allProposals.get(1); - * + * * if (prop1 instanceof OcamlCompletionProposal && prop2 instanceof SimpleCompletionProposal && * prop1.getDisplayString().equals(prop2.getDisplayString())) allProposals.remove(1); } */ @@ -186,53 +212,549 @@ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int /** * Find the completions matching the argument completion from all the definitions found in * the definitionsRoot tree. - * + * * @return the completions found */ - private OcamlCompletionProposal[] findCompletionProposals(String completion, Def definitionsRoot, + private OcamlCompletionProposal[] findCompletionProposals(String completion, + Def interfacesDefsRoot, + Def outlineDefsRoot, + IDocument doc, int offset) { - ArrayList definitions = definitionsRoot.children; + ArrayList proposals; + + String fileName = editor.getEditorInput().getName(); + String moduleName = editor.getEditorInput().getName(); + if (moduleName.endsWith(".ml")) + moduleName = moduleName.substring(0, moduleName.length() - 3); + else if (moduleName.endsWith(".mli")) + moduleName = moduleName.substring(0, moduleName.length() - 4); + if (moduleName.length() > 0) + moduleName = Character.toUpperCase(moduleName.charAt(0)) + + moduleName.substring(1); + + if (completion.contains(".")) + proposals = processDottedCompletion(completion, interfacesDefsRoot, + outlineDefsRoot, moduleName, fileName, doc, offset, completion.length()); + else + proposals = processNondottedCompletion(completion, interfacesDefsRoot, + outlineDefsRoot, moduleName, fileName, doc, offset, completion.length()); + + proposals = removeDuplicatedCompletionProposal(proposals); + + return proposals.toArray(new OcamlCompletionProposal[0]); + } + + // completion string must contained dots + private ArrayList processDottedCompletion(String completion, + Def interfacesDefsRoot, + Def outlineDefsRoot, + String moduleName, + String fileName, + IDocument document, + int offset, + int length) { ArrayList proposals = new ArrayList(); + if (interfacesDefsRoot == null) + return proposals; + // look in the module before the dot what's after the dot + // The module can be like "A.B." or "c.D.E." if (completion.contains(".")) { - int index = completion.indexOf('.'); - String prefix = completion.substring(0, index); - String suffix = completion.substring(index + 1); + // find the first module in completion string + int index = completion.lastIndexOf('.'); + String[] parts = completion.substring(0,index).split("\\."); + String prefix = parts[parts.length - 1]; + String suffix = completion.substring(index+1); + int i = parts.length - 2; + while (i >= 0) { + if (parts[i].isEmpty()) + break; + if (!Character.isUpperCase(parts[i].charAt(0))) + break; + suffix = prefix + "." + suffix; + prefix = parts[i]; + i--; + } - for (Def def : definitions) { + boolean isLowerCasePrefix= false; + if (prefix.length() > 0 && Character.isLowerCase(prefix.charAt(0))) + isLowerCasePrefix = true; + + Def currentDef = null; + ArrayList searchDefs = interfacesDefsRoot.children; + if (outlineDefsRoot != null) + searchDefs.addAll(outlineDefsRoot.children); + for (Def def: searchDefs) { + if (def.name.equals(moduleName) && def.getFileName().endsWith(fileName)) { + currentDef = def; + break; + } + } + + /* + * prefix is a lower-case identifier, hence look for suffix completion + * in the current module, sub-modules, included modules or opened modules + */ + if (isLowerCasePrefix) { + + // find in current def + for (Def def : currentDef.children) { + // look for completion of suffix in the current module + if (checkCompletion(def, suffix) && isCompletionDef(def)) { + Def proposedDef = createProposalDef(project, def); + proposals.add(new OcamlCompletionProposal(proposedDef, + offset, suffix.length())); + } + + // look for completion in opened or included module of current module + // by attach the involved module name to suffix and find new completion + if (def.type == Def.Type.Open || def.type == Def.Type.Include) { + String newCompletion = def.name + "." + suffix; + proposals.addAll(processDottedCompletion(newCompletion, + interfacesDefsRoot, outlineDefsRoot, + moduleName, fileName, document, + offset, suffix.length())); + } + } + + // completion maybe modules's name + searchDefs = interfacesDefsRoot.children; + if (outlineDefsRoot != null) + searchDefs.addAll(outlineDefsRoot.children); + for (Def def : searchDefs) { + if (checkCompletion(def, suffix) && isCompletionDef(def)) { + Def proposedDef = createProposalDef(project, def); + proposals.add(new OcamlCompletionProposal(proposedDef, + offset, suffix.length())); + } + } + } + /* + * prefix is upper-case identifier, hence look for a module which has + * name is or aliased by 'prefix' + */ + else { + // bottom-up search to look for prefix in sub-module + // or aliased module of current modules + final Def nearestDef = findSmallestDefAtOffset(currentDef, offset, document); + String newPrefix = bottomUpFindAliasedModule(prefix, "", nearestDef); + String newSuffix = suffix; + + // compute prefix, suffix + if (newPrefix.contains(".")) { + index = newPrefix.indexOf('.'); + newSuffix = newPrefix.substring(index+1); + newSuffix = combineModuleNameParts(newSuffix, suffix); + newPrefix = newPrefix.substring(0,index); + } + + // find in other modules + searchDefs = interfacesDefsRoot.children; + if (outlineDefsRoot != null) + searchDefs.addAll(outlineDefsRoot.children); + for (Def def: searchDefs) { + if (def.name.equals(newPrefix)) + proposals.addAll(lookupProposalsCompletionInDef( + newSuffix, def, interfacesDefsRoot, + outlineDefsRoot, document, + offset, length)); + } + } + + } + // find elements starting by in the list of elements + else { + ArrayList searchDefs = interfacesDefsRoot.children; + if (outlineDefsRoot != null) + searchDefs.addAll(outlineDefsRoot.children); + for (Def def : searchDefs) { + if (checkCompletion(def, completion) && isCompletionDef(def)) { + Def proposedDef = createProposalDef(project, def); + proposals.add(new OcamlCompletionProposal(proposedDef, offset, completion.length())); + } + } + } + + return proposals; + } + + + private ArrayList processNondottedCompletion(String completion, + Def interfacesDefsRoot, + Def outlineDefsRoot, + String moduleName, + String fileName, + IDocument document, + int offset, + int length) { + + ArrayList proposals = new ArrayList(); + + if (interfacesDefsRoot == null) + return proposals; + + /* + * look in def root + */ + for (Def def: interfacesDefsRoot.children) { + if (checkCompletion(def, completion)) { + Def proposedDef = createProposalDef(project, def); + proposals.add(new OcamlCompletionProposal(proposedDef, offset, length)); + } + } + + /* + * looked in current module + */ + Def currentDef = null; + for (Def def: interfacesDefsRoot.children) { + if (def.name.equals(moduleName) && def.getFileName().endsWith(fileName)) { + currentDef = def; + break; + } + } + + if (currentDef != null) { + // search defns from current def to its parents (bottom-up search) + final Def nearestDef = findSmallestDefAtOffset(currentDef, offset, document); + proposals.addAll(bottomUpFindProposals(completion, nearestDef, offset)); + + // looking in children of current module + for (Def def: currentDef.children) { + if (checkCompletion(def, completion)) { + Def proposedDef = createProposalDef(project, def); + proposals.add(new OcamlCompletionProposal(proposedDef, offset, length)); + } + } + + /* + * look in opened module of current module + */ + for (Def def : currentDef.children) { + if (def.type != Def.Type.Open && def.type != Def.Type.Include) + continue; + + String newCompletion = def.name + "." + completion; + proposals.addAll(processDottedCompletion(newCompletion, + interfacesDefsRoot, outlineDefsRoot, + moduleName, fileName, document, offset, length)); + } + } + + /* + * look in Pervasives module, which is always opended + */ + for (Def def: interfacesDefsRoot.children) { + if (!def.name.equals("Pervasives")) + continue; + + for (Def d: def.children) { + if (d == null || d.name == null) + break; + + if (checkCompletion(d, completion) && isCompletionDef(d)) { + Def proposedDef = createProposalDef(project, d); + proposals.add(new OcamlCompletionProposal(proposedDef, offset, completion.length())); + } + } + } + + return proposals; + } + + private ArrayList lookupProposalsCompletionInDef(String completion, + Def defsRoot, + Def interfacesDefRoot, + Def outlineDefRoot, + IDocument document, + int offset, + int length) { + + ArrayList proposals = new ArrayList(); + + if (defsRoot == null) + return proposals; + + if (completion.contains(".")) { + // find the first module in completion string + int index = completion.lastIndexOf('.'); + String[] parts = completion.substring(0,index).split("\\."); + String prefix = parts[parts.length - 1]; + String suffix = completion.substring(index+1); + int i = parts.length - 2; + while (i >= 0) { + if (parts[i].isEmpty()) + break; + if (!Character.isUpperCase(parts[i].charAt(0))) + break; + suffix = prefix + "." + suffix; + prefix = parts[i]; + i--; + } + + // look inside def roots first + for (Def def: defsRoot.children) { if (def.name.equals(prefix)) - return findCompletionProposals(suffix, def, offset); + proposals.addAll(lookupProposalsCompletionInDef(suffix, def, + interfacesDefRoot, outlineDefRoot, + document, offset, length)); + } + + // look inside included module + for (Def def1: defsRoot.children) { + if (def1.type == Def.Type.Include) { + Def includedDef = def1; + // look for included def in current defs + for (Def def2: defsRoot.children) { + if (def2.name.equals(includedDef.name)) { + Def includedDefRoot = def2; + proposals.addAll(lookupProposalsCompletionInDef( + completion, includedDefRoot, + interfacesDefRoot, outlineDefRoot, + document, offset, length)); + } + + } + // look for included def in interfaces root defs + for (Def def2: interfacesDefRoot.children) { + if (def2.name.equals(includedDef.name)) { + Def includedDefRoot = def2; + proposals.addAll(lookupProposalsCompletionInDef( + completion, includedDefRoot, + interfacesDefRoot, outlineDefRoot, + document, offset, length)); + } + + } + } } } // find elements starting by in the list of elements else { + // look inside def roots first + for (Def def : defsRoot.children) { + if (checkCompletion(def, completion) && isCompletionDef(def)) { + Def proposedDef = createProposalDef(project, def); + proposals.add(new OcamlCompletionProposal(proposedDef, + offset, completion.length())); + } + } + // look inside included module + for (Def def1: defsRoot.children) { + if (def1.type == Def.Type.Include) { + Def includedDef = def1; + // look for included def in current defs + for (Def def2: defsRoot.children) { + if (def2.name.equals(includedDef.name)) { + Def includedDefRoot = def2; + proposals.addAll(lookupProposalsCompletionInDef( + completion, includedDefRoot, + interfacesDefRoot, outlineDefRoot, + document, offset, length)); + } - for (Def def : definitions) { - if (def.name.startsWith(completion) && isCompletionDef(def)) - proposals.add(new OcamlCompletionProposal(def, offset, completion.length())); + } + // look for included def in interfaces root defs + for (Def def2: interfacesDefRoot.children) { + if (def2.name.equals(includedDef.name)) { + Def includedDefRoot = def2; + proposals.addAll(lookupProposalsCompletionInDef( + completion, includedDefRoot, + interfacesDefRoot, outlineDefRoot, + document, offset, length)); + } + } + } } + } - return proposals.toArray(new OcamlCompletionProposal[0]); + return proposals; + } + + private ArrayList bottomUpFindProposals(String completion, Def node, int offset) { + ArrayList proposals = new ArrayList(); + + if (node == null) + return proposals; + + Def travelNode = node.parent; + while (true) { + if (travelNode == null || travelNode.name == null) + break; + + if (checkCompletion(travelNode, completion) && isCompletionDef(travelNode)) { + Def proposedDef = createProposalDef(project, travelNode); + proposals.add(new OcamlCompletionProposal(proposedDef, offset, completion.length())); + } + + for (Def def : travelNode.children) { + if (def == null || def.name == null) + continue; + if (checkCompletion(def, completion)) { +// && (def.type == Def.Type.Let +// || def.type == Def.Type.LetIn +// || def.type == Def.Type.Parameter)) { + Def proposedDef = createProposalDef(project, def); + proposals.add(new OcamlCompletionProposal(proposedDef, offset, completion.length())); + } + } + + if (travelNode.type == Def.Type.Root) + break; + + travelNode = travelNode.parent; + } + + return proposals; + } + + private String combineModuleNameParts(String prefix, String suffix) { + if (suffix.isEmpty()) + return prefix; + else + return prefix + "." + suffix; + } + + private String bottomUpFindAliasedModule(String prefixAlias, String suffixAlias, Def node) { + if (node == null) + return combineModuleNameParts(prefixAlias, suffixAlias); + + // search for aliasedModuel from current def, and go upper until meeting root + Def currentNode = node; + String newPrefixAlias = prefixAlias; + while (true) { + if (currentNode == null || currentNode.name == null) + break; + + if (currentNode.type == Def.Type.ModuleAlias + && (currentNode.name.compareTo(newPrefixAlias) == 0)) { + if (currentNode.children.size() > 0) { + newPrefixAlias = currentNode.children.get(0).name; + if (newPrefixAlias.contains(".")) // stop when name has "." + break; + } + } + + if (currentNode.type == Def.Type.Root) + break; + + if (currentNode.parent == null) + break; + + ArrayList currentSiblings = currentNode.parent.children; + int currentIndex = -1; + for (int i = 0; i < currentSiblings.size(); i++) + if (currentSiblings.get(i).equals(currentNode)) { + currentIndex = i; + break; + } + // if current node has a prior sibling, go to that node + if (currentIndex > 0) + currentNode = currentSiblings.get(currentIndex-1); + // otherwise, go to its parent + else + currentNode = currentNode.parent; + } + + // if aliased module is a sub-module (containing "."), then find + // the first part. Otherwise, continue to search aliased module + if (newPrefixAlias.contains(".")) { + String[] parts = newPrefixAlias.split("\\."); + String newSuffixAlias = ""; + for (int i = parts.length-1; i > 0; i--) + newSuffixAlias = parts[i] + "." + newSuffixAlias ; + if (newSuffixAlias.length() > 0) { + newSuffixAlias = newSuffixAlias + suffixAlias; + } else + newSuffixAlias = suffixAlias; + newPrefixAlias = parts[0]; + return bottomUpFindAliasedModule(newPrefixAlias, newSuffixAlias, currentNode); + } + else + return combineModuleNameParts(newPrefixAlias, suffixAlias); + } + + private ArrayList removeDuplicatedCompletionProposal(ArrayList proposals) { + + ArrayList newProposals = new ArrayList(); + HashSet proposalHashSet = new HashSet<>(); + for (OcamlCompletionProposal p: proposals) { + String hashStr = p.getDisplayString() + p.getAdditionalProposalInfo(null); + if (!proposalHashSet.contains(hashStr)) { + newProposals.add(p); + proposalHashSet.add(hashStr); + } + } + + return newProposals; + } + + /** Find an identifier (or an open directive) at a position in the document */ + private Def findSmallestDefAtOffset(Def def, int offset, IDocument doc) { + + if (def == null || doc == null) + return null; + + if (def.children.size() == 0) + return def; + + Def firstChild = def.children.get(0); + IRegion region = firstChild.getNameRegion(doc); + if (region != null) { + if (region.getOffset() > offset) + return def; + } + else return null; + + + Def nearestChild = null; + for (Def d : def.children) { + region = d.getNameRegion(doc); + if (region != null) { + if (region.getOffset() < offset) + nearestChild = d; + } + } + + return findSmallestDefAtOffset(nearestChild, offset, doc); + } + + private boolean checkCompletion(Def def, String completion) { + if (def == null) + return false; + + if (def.name == null) + return false; + + if (def.name.startsWith(completion)){ +// if (def.type != Def.Type.Identifier) +// return true; +// else if (def.name.length() > completion.length()) +// return true; + return true; + } + + return false; } private boolean isCompletionDef(Def def) { switch (def.type) { - case Parameter: - case Object: - case LetIn: +// case Parameter: +// case Object: +// case LetIn: case Open: case Include: case In: - case Identifier: +// case Identifier: case Dummy: case Root: - case Sig: - case Struct: +// case Sig: +// case Struct: return false; default: return true; @@ -370,10 +892,14 @@ private String expressionAtOffset(ITextViewer viewer, int documentOffset) { /** Return context informations available at a given position in the editor (at documentOffset) */ public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { + IProject project = null; + if (editor instanceof OcamlEditor) { + project = ((OcamlEditor) editor).getProject(); + } IContextInformation[] infos; if (CompletionJob.isParsingFinished()) { - Def definitionsRoot = CompletionJob.buildDefinitionsTree(this.project, true); + Def definitionsRoot = CompletionJob.buildDefinitionsTree(project, true); String expression = expressionAtOffset(viewer, documentOffset); @@ -397,17 +923,48 @@ private IContextInformation[] findContextInformation(String expression, Def defi // search in the module before the dot the element after the dot if (expression.contains(".")) { - int index = expression.indexOf('.'); - String prefix = expression.substring(0, index); - String suffix = expression.substring(index + 1); + int index = expression.lastIndexOf('.'); + String[] parts = expression.substring(0,index).split("\\."); + String prefix = parts[parts.length - 1]; + String suffix = expression.substring(index+1); + int i = parts.length - 2; + while (i >= 0) { + if (parts[i].isEmpty()) + break; + if (!Character.isUpperCase(parts[i].charAt(0))) + break; + suffix = prefix + "." + suffix; + prefix = parts[i]; + i--; + } - for (Def def : definitions) { - if (def.name.equals(prefix)) { - IContextInformation[] informations = findContextInformation(suffix, def); - for (IContextInformation i : informations) - infos.add(i); + String moduleName = prefix; + boolean stop = false; + while (!stop) { + stop = true; + for (Def def : definitions) { + if (def.name.equals(moduleName)) { + if (def.type == Def.Type.Module) { + IContextInformation[] informations = findContextInformation(suffix, def); + for (IContextInformation d : informations) + infos.add(d); + stop = true; + break; + } + else if (def.type == Def.Type.ModuleAlias) { + String aliasedName = def.children.get(0).name; + if (moduleName.equals(aliasedName)) + stop = true; + else { + moduleName = aliasedName; + stop = false; + } + break; + } + } } } + return infos.toArray(new IContextInformation[0]); } @@ -421,7 +978,7 @@ private IContextInformation[] findContextInformation(String expression, Def defi */ if (def.name.equals(expression)) { - String body = def.body; + String body = def.getBody(); // if (!def.getParentName().equals("")) // body = body + " (constructor of type " + def.getParentName() + ")"; @@ -435,12 +992,12 @@ private IContextInformation[] findContextInformation(String expression, Def defi else message = message + "\u00A0"; - String filename = def.filename; + String filename = def.getFileName(); message = message + "\u00A0\n\n" + filename; message = message.trim(); if (!message.equals("")) { - String context = def.filename + " : " + def.body; + String context = def.getFileName() + " : " + body; infos.add(new ContextInformation(context, message)); } } @@ -454,4 +1011,186 @@ private IContextInformation[] findContextInformation(String expression, Def defi public String getErrorMessage() { return null; } + + private Def createProposalDef(IProject project, Def def) { + Def newDef = new Def(def); + if (newDef.type == Def.Type.Let + || newDef.type == Def.Type.LetIn + || newDef.type == Def.Type.External) { + + String typeInfo = ""; + + // look for type infor in body first + String body = newDef.getBody(); + int index = body.indexOf(newDef.name); + if (index >= 0 && body.length() > newDef.name.length()) { + typeInfo = body.substring(index); + newDef.setOcamlType(typeInfo); + } + + // not found type in body + if (typeInfo.isEmpty()) { + String filename = newDef.getFileName(); + + // store last used annotation for caching + TypeAnnotation[] annotations; + long currentTime = System.currentTimeMillis(); + if (filename.equals(lastParsedFileName) + && (currentTime - lastParsedTime < cacheTime)) { + annotations = lastUsedAnnotations; + } + else { + annotations = parseModuleAnnotation(project, filename); + lastUsedAnnotations = annotations; + lastParsedFileName = filename; + lastParsedTime = System.currentTimeMillis(); + } + + IDocument document = getDocument(project, filename); + typeInfo = computeTypeInfo(newDef, annotations, document); + if (!typeInfo.isEmpty()) { + newDef.setOcamlType(typeInfo); + newDef.setBody("val " + typeInfo); + } + } + } + else if (def.type == Def.Type.Type) { + String typeInfo = newDef.name + " 't"; + newDef.setOcamlType(typeInfo); + } + + return newDef; + } + + private IDocument getDocument(IProject project, String filename) { + if (project == null) + return null; + + if (filename.isEmpty()) + return null; + + try { + IFile[] files = project.getWorkspace().getRoot().findFilesForLocationURI(URIUtil.toURI(filename)); + if (files.length == 0) + return null; + + IFile file = files[0]; + IDocumentProvider provider = new TextFileDocumentProvider(); + provider.connect(file); + IDocument document = provider.getDocument(file); + + return document; + } catch (Exception e) { + return null; + } + } + + + private TypeAnnotation[] parseModuleAnnotation(IProject project, String filename) { + if (project == null) + return new TypeAnnotation[0]; + + if (filename.isEmpty()) + return new TypeAnnotation[0]; + + try { + IFile[] files = project.getWorkspace().getRoot().findFilesForLocationURI(URIUtil.toURI(filename)); + if (files.length == 0) + return new TypeAnnotation[0]; + + IFile file = files[0]; + IPath relativeProjectPath = file.getFullPath(); + IDocumentProvider provider = new TextFileDocumentProvider(); + provider.connect(file); + IDocument document = provider.getDocument(file); + + File annotFile = null; + + annotFile = Misc.getOtherFileFor(file.getProject(), relativeProjectPath, ".annot"); + + if (annotFile != null && annotFile.exists()) { + TypeAnnotation[] annotations = OcamlAnnotParser.parseFile(annotFile, document); + + return annotations; + } + } catch (Exception e) { +// e.printStackTrace(); + return new TypeAnnotation[0]; + } + + return new TypeAnnotation[0]; + + } + + private String computeTypeInfo(Def def, TypeAnnotation[] annotations, IDocument document) { + try { + String typeInfo = ""; + IRegion region = def.getNameRegion(document); + int offset = region.getOffset(); + + ArrayList found = new ArrayList(); + + if (annotations != null) { + for (TypeAnnotation annot : annotations) + if (annot.getBegin() <= offset && offset < annot.getEnd()) + found.add(annot); + + /* + * Search for the smallest hovered type annotation + */ + TypeAnnotation annot = null; + int minSize = Integer.MAX_VALUE; + + for (TypeAnnotation a : found) { + int size = a.getEnd() - a.getBegin(); + if (size < minSize) { + annot = a; + minSize = size; + } + } + + String docContent = document.get(); + if (annot != null) { + String expr = docContent.substring(annot.getBegin(), annot.getEnd()); + String[] lines = expr.split("\\n"); + if (expr.length() < 50 && lines.length <= 6) + typeInfo = expr + ": " + annot.getType(); + else if (lines.length > 6) { + int l = lines.length; + typeInfo = lines[0] + "\n" + lines[1] + "\n" + lines[2] + + "\n" + "..." + (l - 6) + " more lines...\n" + lines[l - 3] + + "\n" + lines[l - 2] + "\n" + lines[l - 1] + "\n:" + annot + .getType(); + } else + typeInfo = expr + "\n:" + annot.getType(); + } + } + return typeInfo.trim(); + } catch (Exception e) { + return ""; + } + + } + + ArrayList lineOffsets = null; + + private void computeLinesStartOffset(String doc) { + lineOffsets = new ArrayList(); + lineOffsets.add(0); + for (int i = 0; i < doc.length(); i++) { + /* + * if(doc.charAt(i) == '\r') System.err.print("\n"); + * if(doc.charAt(i) == '\n') System.err.print("\n"); else + * System.err.print(doc.charAt(i)); + */ + + if (doc.charAt(i) == '\n') { + lineOffsets.add(i + 1); + // System.err.println(i); + } + + } + } + + } diff --git a/Ocaml/src/ocaml/editor/completion/OcamlCompletionProposal.java b/Ocaml/src/ocaml/editor/completion/OcamlCompletionProposal.java index 0442fe5..2166f7b 100644 --- a/Ocaml/src/ocaml/editor/completion/OcamlCompletionProposal.java +++ b/Ocaml/src/ocaml/editor/completion/OcamlCompletionProposal.java @@ -1,7 +1,10 @@ package ocaml.editor.completion; +import java.io.File; + import ocaml.OcamlPlugin; import ocaml.parser.Def; +import ocaml.util.Misc; import ocaml.views.outline.OcamlOutlineLabelProvider; import org.eclipse.core.runtime.IProgressMonitor; @@ -43,7 +46,7 @@ public OcamlCompletionProposal(Def definition, int replacementOffset, int typedW this.typedLength = typedWordLength; } - + public void apply(IDocument document) { String name = this.definition.name; @@ -64,17 +67,17 @@ public IContextInformation getContextInformation() { * We display context information only for functions (to help the user with the types of the expected * arguments), an exception with arguments, or a constructor with arguments. */ - boolean bArrow = definition.body.contains("->") || definition.body.contains("\u2192"); + final String body = definition.getBody(); + boolean bArrow = body.contains("->") || body.contains("\u2192"); boolean bFun = type.equals(Def.Type.Let) && bArrow; boolean bExtFun = type.equals(Def.Type.External) && bArrow; boolean bExceptionArgs = type.equals(Def.Type.Exception) - && definition.body.contains(" of "); + && body.contains(" of "); boolean bConstructorArgs = type.equals(Def.Type.TypeConstructor) - && definition.body.contains(" of "); + && body.contains(" of "); if (!(bFun || bExtFun || bExceptionArgs || bConstructorArgs)) return null; - final String body = definition.body; if (body.trim().equals("")) return null; @@ -107,7 +110,18 @@ public Image getImage() { } public String getDisplayString() { - return definition.name; + String displayString = definition.name; + + String typeInfo = Misc.beautify(Def.cleanString(definition.getOcamlType())); + + if (!typeInfo.isEmpty()) { + if (typeInfo.startsWith(definition.name)) + displayString = typeInfo; + else + displayString = displayString + " - " + typeInfo; + } + + return displayString; } /** @deprecated replaced by the same name function in ICompletionProposalExtension5 */ @@ -121,9 +135,11 @@ public String getAdditionalProposalInfo(IProgressMonitor monitor) { * encodes as a string the informations that will be read back by OcamlInformationPresenter to format * them */ - return definition.parentName + " $@| " + definition.body + " $@| " + + return definition.parentName + " $@| " + definition.getBody() + " $@| " + + definition.getOcamlType() + " $@| " + definition.sectionComment + " $@| " + definition.comment + " $@| " - + definition.filename; + + definition.getFileName(); } } \ No newline at end of file diff --git a/Ocaml/src/ocaml/editor/completion/OcamlInformationPresenter.java b/Ocaml/src/ocaml/editor/completion/OcamlInformationPresenter.java index 87eac47..a1a46d6 100644 --- a/Ocaml/src/ocaml/editor/completion/OcamlInformationPresenter.java +++ b/Ocaml/src/ocaml/editor/completion/OcamlInformationPresenter.java @@ -1,5 +1,6 @@ package ocaml.editor.completion; +import java.io.File; import java.util.ArrayList; import ocaml.OcamlPlugin; @@ -26,13 +27,14 @@ public String updatePresentation(Display display, String infoText, final Color colorSection = new Color(display, 150, 50, 191); final Color colorParent = new Color(display, 191, 100, 50); final Color colorCode = new Color(display, 0, 0, 255); + final Color colorModuleName = new Color(display, 119, 131, 112); final Color colorFilename = new Color(display, 64, 64, 64); String[] infos = infoText.split("\\$\\@\\|"); // templates don't respect the same format - if (infos.length != 5) - infos = new String[] { "", "", "", infoText, "" }; + if (infos.length != 6) + infos = new String[] { "", "", "", "", infoText, "" }; // the offset in the generated text, in number of characters int offset = 0; @@ -40,19 +42,25 @@ public String updatePresentation(Display display, String infoText, // the result string StringBuilder result = new StringBuilder(); - String text; + String text = ""; String parentName = infos[0].trim(); String body = infos[1].trim(); - String sectionComment = infos[2].trim(); - String comment = infos[3].trim(); - String filename = infos[4].trim(); + String ocamlType = infos[2].trim(); + String sectionComment = infos[3].trim(); + String comment = infos[4].trim(); + String filename = infos[5].trim(); - if (!body.equals("")) { + // if there is type info, then no need to print body + if (!ocamlType.equals("")) { + text = body + "\n"; + result.append(text); + presentation.addStyleRange(new StyleRange(offset, text.length(), null, null, SWT.BOLD)); + offset += text.length(); + } + else if (!body.equals("")) { text = body + "\n"; result.append(text); - - // Color colorBody = new Color(display, 50, 150, 200); presentation.addStyleRange(new StyleRange(offset, text.length(), null, null, SWT.BOLD)); offset += text.length(); } @@ -251,16 +259,28 @@ else if (bAnnotation) } if (!filename.equals("")) { + // attach module name + String[] parts = filename.split(File.separator); + String moduleName = ""; + if (parts.length > 1) { + moduleName = "Module: " + parts[parts.length - 1]; + } String strResult = result.toString(); if (strResult.endsWith("\n\n")) - text = filename; + text = moduleName; else if (strResult.endsWith("\n")) - text = "\n" + filename; + text = "\n" + moduleName; else - text = "\n\n" + filename; + text = "\n\n" + moduleName; result.append(text); + presentation.addStyleRange(new StyleRange(offset, text.length(), colorModuleName, null, + SWT.ITALIC)); + offset += text.length(); + // attach file name + text = "\n" + filename; + result.append(text); presentation.addStyleRange(new StyleRange(offset, text.length(), colorFilename, null, SWT.ITALIC)); offset += text.length(); diff --git a/Ocaml/src/ocaml/editor/syntaxcoloring/OcamlCommentRule.java b/Ocaml/src/ocaml/editor/syntaxcoloring/OcamlCommentRule.java index a6ecc04..83912a5 100644 --- a/Ocaml/src/ocaml/editor/syntaxcoloring/OcamlCommentRule.java +++ b/Ocaml/src/ocaml/editor/syntaxcoloring/OcamlCommentRule.java @@ -40,10 +40,13 @@ public IToken evaluate(ICharacterScanner scanner, boolean resume) { ch = scanner.read(); nRead++; + /* //Commented out by Trung if (ch == -1) return token; - else if (ch == ')') { + else + */ + if (ch == ')') { if (bStar) { nestingLevel--; if (nestingLevel <= 0) diff --git a/Ocaml/src/ocaml/editors/OcamlAutoEditStrategy.java b/Ocaml/src/ocaml/editors/OcamlAutoEditStrategy.java index 360c4f9..76138cf 100644 --- a/Ocaml/src/ocaml/editors/OcamlAutoEditStrategy.java +++ b/Ocaml/src/ocaml/editors/OcamlAutoEditStrategy.java @@ -9,9 +9,11 @@ import ocaml.preferences.PreferenceConstants; import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPartitioningException; import org.eclipse.jface.text.DocumentCommand; import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentExtension3; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.TextUtilities; @@ -34,6 +36,8 @@ public class OcamlAutoEditStrategy implements IAutoEditStrategy { /** A comment opened at the beginning of the line */ private Pattern patternCommentOpen = Pattern.compile("^\\(\\*"); + + private Pattern patternCommentMultipleLines = Pattern.compile("^\\*"); /** A "no-format" comment opened at the beginning of the line */ private Pattern patternCommentOpenNoFormat = Pattern.compile("^\\(\\*\\|"); @@ -88,8 +92,8 @@ public void customizeDocumentCommand(IDocument document, DocumentCommand command int offsetInLine = command.offset - lineRegion.getOffset(); - String beforeCursor = line.substring(0, offsetInLine).trim(); - String afterCursor = line.substring(offsetInLine, line.length()).trim(); + String beforeCursor = line.substring(0, offsetInLine); + String afterCursor = line.substring(offsetInLine, line.length()); try { ITypedRegion region = document.getPartition(offsetInLine); @@ -164,7 +168,7 @@ else if (command.text.equals(eol)) { PreferenceConstants.P_EDITOR_CONTINUE_COMMENTS)) { Matcher matcher = patternCommentOpenNoFormat.matcher(beforeCursor); if (matcher.find() && !beforeCursor.contains("*)")) { - command.text = "*)" + eol + makeIndent(indent) + "(*| "; + command.text = " *)" + eol + makeIndent(indent) + "(*| "; return; } @@ -173,9 +177,50 @@ else if (command.text.equals(eol)) { if (matcher.find()) return; + // support multiple-lines comment like Ecipse for Java matcher = patternCommentOpen.matcher(beforeCursor); - if (matcher.find() && !beforeCursor.contains("*)")) { - command.text = "*)" + eol + makeIndent(indent) + "(* "; + if (matcher.find()) { + try { + IDocumentExtension3 extension = (IDocumentExtension3) document; + ITypedRegion partition; + partition = extension.getPartition(OcamlPartitionScanner.OCAML_PARTITIONING, + command.offset, false); + if(OcamlPartitionScanner.OCAML_DOCUMENTATION_COMMENT.equals(partition.getType())|| + OcamlPartitionScanner.OCAML_MULTILINE_COMMENT.equals(partition.getType())) { + command.text = eol + makeIndent(indent) + " * "; + } + else if (partition.getOffset() <= matcher.end() + lineRegion.getOffset()) { + String strIndent = makeIndent(indent); + command.text = eol + makeIndent(indent) + " * " + eol + makeIndent(indent) + " *)"; + command.shiftsCaret = false; + command.caretOffset = command.offset + eol.length() + strIndent.length() + 3; + } + } catch (BadLocationException e) { + OcamlPlugin.logError("bad location in OcamlAutoEditStrategy", e); + } catch (BadPartitioningException e) { + OcamlPlugin.logError("bad partitioning in OcamlAutoEditStrategy", e); + } + return; + } + + // support multiple-lines comment like Eclipse for Java + matcher = patternCommentMultipleLines.matcher(trimmed); + if (matcher.find()) { + try { + IDocumentExtension3 extension = (IDocumentExtension3) document; + ITypedRegion partition = extension.getPartition(OcamlPartitionScanner.OCAML_PARTITIONING, + command.offset, false); + if(OcamlPartitionScanner.OCAML_DOCUMENTATION_COMMENT.equals(partition.getType())|| + OcamlPartitionScanner.OCAML_MULTILINE_COMMENT.equals(partition.getType())) { + if (trimmed.startsWith("*") && !trimmed.startsWith("*)")) { + command.text = eol + makeIndent(indent) + " * "; + } + } + } catch (BadLocationException e) { + OcamlPlugin.logError("bad location in OcamlAutoEditStrategy", e); + } catch (BadPartitioningException e) { + OcamlPlugin.logError("bad partitioning in OcamlAutoEditStrategy", e); + } return; } } @@ -246,8 +291,45 @@ else if (trimmed.startsWith("|") && trimmed.equals(beforeCursor)) { } else if (OcamlPlugin.getInstance().getPreferenceStore().getBoolean( - PreferenceConstants.P_EDITOR_KEEP_INDENT)) - command.text = eol + makeIndent(indent); + PreferenceConstants.P_EDITOR_KEEP_INDENT)) { + // if current line contains only whitespace, then + // then trim it and indent next line by indentation + // of nearest non-whitespace line + try { + int lineNum = document.getLineOfOffset(command.offset); + int startLineFindIndent = lineNum - 1; + String firstPartCurrentLine = + document.get(lineRegion.getOffset(), + command.offset - lineRegion.getOffset()); + // if enter is pressed at beginning of line, just start a new line + if (firstPartCurrentLine.isEmpty()) { + command.text = eol; + } + // if enter is pressed at middle or end of line, + // then new-line-and-indent + else { + if (firstPartCurrentLine.trim().isEmpty()) { + startLineFindIndent = lineNum - 1; + command.length = command.offset - lineRegion.getOffset(); + command.offset = lineRegion.getOffset(); + } + else + startLineFindIndent = lineNum; + int priorIndent = 0; + for (int l = startLineFindIndent; l >= 0; l--) { + int x = document.getLineOffset(l); + int y = document.getLineOffset(l+1); + String priorLine = document.get(x, y - x + 1); + if (!priorLine.trim().isEmpty()) { + priorIndent = OcamlFormatter.getLineIndent(priorLine); + break; + } + } + command.text = eol + makeIndent(priorIndent); + } + } catch (BadLocationException e) { + } + } } } else if (command.text.equals("\t")) { diff --git a/Ocaml/src/ocaml/editors/OcamlEditor.java b/Ocaml/src/ocaml/editors/OcamlEditor.java index df94793..13937ef 100644 --- a/Ocaml/src/ocaml/editors/OcamlEditor.java +++ b/Ocaml/src/ocaml/editors/OcamlEditor.java @@ -2,15 +2,17 @@ import java.io.File; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import ocaml.OcamlPlugin; import ocaml.debugging.DebugVisuals; import ocaml.editor.completion.CompletionJob; +import ocaml.editor.syntaxcoloring.OcamlEditorColors; import ocaml.editors.util.OcamlCharacterPairMatcher; import ocaml.natures.OcamlNatureMakefile; import ocaml.parser.Def; -import ocaml.popup.actions.CompileProjectAction; +import ocaml.popup.actions.CompileProjectPopupAction; import ocaml.preferences.PreferenceConstants; import ocaml.views.outline.OcamlOutlineControl; import ocaml.views.outline.OutlineJob; @@ -26,7 +28,9 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; +import org.eclipse.jface.preference.IPreferenceStore; 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.ITextListener; @@ -34,10 +38,16 @@ import org.eclipse.jface.text.PaintManager; import org.eclipse.jface.text.TextEvent; import org.eclipse.jface.text.TextSelection; -import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.MatchingCharacterPainter; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; @@ -49,6 +59,8 @@ import org.eclipse.ui.ide.FileStoreEditorInput; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; +import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; /** @@ -98,6 +110,12 @@ public ITextViewer getTextViewer() { protected void createActions() { super.createActions(); + final ISourceViewer sourceViewer = this.getSourceViewer(); + final StyledText textWidget = sourceViewer.getTextWidget(); + final OcamlSourceViewerConfig sourceViewerConfig = + (OcamlSourceViewerConfig) this.getSourceViewerConfiguration(); + + try { paintManager = new PaintManager(getSourceViewer()); matchingCharacterPainter = new MatchingCharacterPainter(getSourceViewer(), @@ -111,7 +129,7 @@ protected void createActions() { * AnnotationPainter(getSourceViewer(), null); * annotationPainter.addAnnotationType * ("Ocaml.ocamlSyntaxErrorMarker"); - * + * * paintManager.addPainter(annotationPainter); */ @@ -120,9 +138,8 @@ protected void createActions() { } try { - StyledText text = this.getSourceViewer().getTextWidget(); - caret = new DebugVisuals(text); - text.addPaintListener(caret); + caret = new DebugVisuals(textWidget); + textWidget.addPaintListener(caret); IPath file = getPathOfFileBeingEdited(); if (file != null) @@ -134,7 +151,7 @@ protected void createActions() { // parse the OCaml libraries in a background thread try { CompletionJob job = new CompletionJob("Parsing ocaml library mli files", null); - job.setPriority(CompletionJob.DECORATE); + job.setPriority(CompletionJob.INTERACTIVE); // Trung changes priority job.schedule(); } catch (Exception e) { OcamlPlugin.logError("ocaml plugin error", e); @@ -146,13 +163,49 @@ protected void createActions() { OcamlPlugin.logError("ocaml plugin error", e); } - this.getSourceViewer().addTextListener(new ITextListener() { + // synchronize with outline when double-click mouse + textWidget.addMouseListener(new MouseListener() { + @Override + public void mouseUp(MouseEvent e) { + } + + @Override + public void mouseDown(MouseEvent e) { + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + if (sourceViewerConfig.isContentAssistantActive() || e == null) + return; + + synchronizeOutline(); + } + }); + + + // Trung: don't rebuild outline when text is changed because it + // slow down the system + /* + final ISourceViewer viewer = this.getSourceViewer(); + final OcamlSourceViewerConfig viewerConfig = (OcamlSourceViewerConfig) this.getSourceViewerConfiguration(); + viewer.addTextListener(new ITextListener() { public void textChanged(TextEvent event) { - if (event.getDocumentEvent() != null) - rebuildOutline(500); + // Trung: rebuild only when content assistant is inactive + if (viewerConfig.isContentAssistantActive() || event == null) + return; + + DocumentEvent docEvent = event.getDocumentEvent(); + if (docEvent == null) + return; + + String text = docEvent.getText().trim(); + if (!text.isEmpty()) + rebuildOutline(50, false); // don't sync outline with editor } }); + */ + } @Override @@ -167,7 +220,7 @@ public void doSetInput(IEditorInput input) throws CoreException { super.doSetInput(input); if (this.outline != null) { - rebuildOutline(100); + rebuildOutline(50, false); } IProject project = this.getProject(); @@ -176,7 +229,7 @@ public void doSetInput(IEditorInput input) throws CoreException { // parse the project interfaces in a background thread CompletionJob job = new CompletionJob("Parsing ocaml project mli files", project); - job.setPriority(CompletionJob.DECORATE); + job.setPriority(CompletionJob.INTERACTIVE); // Trung changes priority job.schedule(); if (input instanceof IFileEditorInput) { @@ -191,6 +244,8 @@ public void doSetInput(IEditorInput input) throws CoreException { */ } + + /** * We give the outline to Eclipse when it asks for an adapter with the * outline class. @@ -205,7 +260,7 @@ public Object getAdapter(@SuppressWarnings("unchecked") Class required) { if (this.outline == null) this.outline = new OcamlOutlineControl(this); - rebuildOutline(100); + rebuildOutline(50, false); return this.outline; } return super.getAdapter(required); @@ -223,6 +278,8 @@ public void createPartControl(Composite parent) { styledText.setTabs(getTabSize()); } + + public static int getTabSize() { return OcamlPlugin.getInstance().getPreferenceStore().getInt( PreferenceConstants.P_EDITOR_TABS); @@ -264,7 +321,7 @@ public int getCaretOffset() { OcamlPlugin.logError("selection is not instanceof TextSelection"); return -1; } - + public static class LineColumn { private final int line; private final int column; @@ -282,7 +339,7 @@ public int getColumn() { return column; } } - + /** @return the current selection offset in the editor, as a (line,column) position. */ public LineColumn getSelectionLineColumn() { ISelection sel = getSelectionProvider().getSelection(); @@ -298,7 +355,7 @@ public LineColumn getSelectionLineColumn() { OcamlPlugin.logError(e); return null; } - + } OcamlPlugin.logError("selection is not instanceof TextSelection"); return null; @@ -407,6 +464,9 @@ public IProgressMonitor getMonitor() { public void doSave(IProgressMonitor monitor) { super.doSave(monitor); + // rebuild Outline when file is saved + rebuildOutline(50, false); + boolean bMakefileNature = false; try { IProject project = this.getProject(); @@ -425,7 +485,7 @@ public void doSave(IProgressMonitor monitor) { IWorkspace ws = ResourcesPlugin.getWorkspace(); IWorkspaceDescription desc = ws.getDescription(); if (desc.isAutoBuilding()) - CompileProjectAction.compileProject(this.getProject()); + CompileProjectPopupAction.compileProject(this.getProject()); } } @@ -433,7 +493,7 @@ public void doSave(IProgressMonitor monitor) { * @Override protected void editorContextMenuAboutToShow(IMenuManager menu) * { IFile file = this.getFileBeingEdited(); * super.editorContextMenuAboutToShow(menu); - * + * * MenuManager ocamlGroup = new MenuManager("OCaml"); menu.add(new * Separator()); menu.add(ocamlGroup); ocamlGroup.add(new * GenDocAction("GenDoc", file)); } @@ -446,7 +506,7 @@ public void doSave(IProgressMonitor monitor) { * this.fOutlinePage; } */ - public void rebuildOutline(int delay) { + public void rebuildOutline(int delay, boolean syncWithEditor) { // invalidate previous definitions this.codeDefinitionsTree = null; @@ -457,14 +517,14 @@ public void rebuildOutline(int delay) { // String doc = document.get(); if (outlineJob == null) - outlineJob = new OutlineJob("Rebuilding outline"); + outlineJob = new OutlineJob("Rebuilding outline", syncWithEditor); // else if (outlineJob.getState() == OutlineJob.RUNNING) // return; // only one Job at a time else outlineJob.cancel(); - outlineJob.setPriority(CompletionJob.DECORATE); + outlineJob.setPriority(CompletionJob.SHORT); outlineJob.setOutline(this.outline); outlineJob.setDoc(document); outlineJob.setEditor(this); @@ -479,26 +539,42 @@ public void rebuildOutline(int delay) { @Override public void handleCursorPositionChanged() { super.handleCursorPositionChanged(); - synchronizeOutline(); + fireCursorPositionChanged(getTextViewer().getSelectedRange()); + final OcamlEditor editor = this; + OcamlTextHover hover = new OcamlTextHover(editor); + ITextViewer viewer = this.getTextViewer(); + int offset = this.getCaretOffset(); + IRegion region = hover.getHoverRegion(viewer, offset); + + String message = ""; + if (OcamlPlugin.getInstance().getPreferenceStore().getBoolean( - PreferenceConstants.P_SHOW_TYPES_IN_STATUS_BAR)) { - final String annot = OcamlTextHover.getAnnotAt(this, - (TextViewer) this.getSourceViewer(), this.getCaretOffset()).trim(); - final OcamlEditor editor = this; - Display.getCurrent().asyncExec(new Runnable() { - - public void run() { - if (editor == null) - return; - if (!annot.equals("")) - editor.setStatusLineMessage(annot); - else - editor.setStatusLineMessage(null); // clear - } - }); + PreferenceConstants.P_SHOW_MARKERS_IN_STATUS_BAR)) { + message = hover.getMarkerInfoOneLine(viewer, region); } + + // only display type info when there isn't any markers + if (message.isEmpty() + && OcamlPlugin.getInstance().getPreferenceStore().getBoolean( + PreferenceConstants.P_SHOW_TYPES_IN_STATUS_BAR)) { + message = hover.getTypeInfoOneLine(viewer, region); + if (message.contains("more lines...")) + message = ""; + } + + final String statusMessage = message; + Display.getCurrent().asyncExec(new Runnable() { + public void run() { + editor.setStatusLineMessage(statusMessage); + } + }); + } + + @Override + public void setStatusLineMessage(String message) { + super.setStatusLineMessage(message); } private Def codeDefinitionsTree = null; diff --git a/Ocaml/src/ocaml/editors/OcamlEditorActionContributor.java b/Ocaml/src/ocaml/editors/OcamlEditorActionContributor.java new file mode 100644 index 0000000..2023258 --- /dev/null +++ b/Ocaml/src/ocaml/editors/OcamlEditorActionContributor.java @@ -0,0 +1,10 @@ +package ocaml.editors; + +import org.eclipse.ui.editors.text.TextEditorActionContributor; + +/* + * Trung: add code here to support editor action + */ +public class OcamlEditorActionContributor extends TextEditorActionContributor { + +} diff --git a/Ocaml/src/ocaml/editors/OcamlHyperlinkDetector.java b/Ocaml/src/ocaml/editors/OcamlHyperlinkDetector.java index a7316a8..de60514 100644 --- a/Ocaml/src/ocaml/editors/OcamlHyperlinkDetector.java +++ b/Ocaml/src/ocaml/editors/OcamlHyperlinkDetector.java @@ -8,6 +8,7 @@ import ocaml.OcamlPlugin; import ocaml.editor.completion.CompletionJob; import ocaml.parser.Def; +import ocaml.parser.Def.Type; import ocaml.parsers.OcamlNewInterfaceParser; import ocaml.util.Misc; import ocaml.util.OcamlPaths; @@ -16,9 +17,12 @@ import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; +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.TextSelection; import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.ui.IEditorPart; @@ -47,32 +51,31 @@ public OcamlHyperlinkDetector(OcamlEditor editor) { public IHyperlink[] detectHyperlinks(final ITextViewer textViewer, final IRegion region, boolean canShowMultipleHyperlinks) { + IHyperlink hyperlink = makeHyperlink(textViewer, region.getOffset()); + if (hyperlink != null) + return new IHyperlink[] {hyperlink}; + else + return null; + } + public IHyperlink makeHyperlink (final ITextViewer textViewer, int offset) { IProject project = editor.getProject(); // get the definitions from the current module final Def modulesDefinitionsRoot = editor.getDefinitionsTree(); - /* - * get the definitions from all the mli files in the project paths (which should include the - * ocaml standard library) - */ - // long before = System.currentTimeMillis(); - - // long after = System.currentTimeMillis(); - // System.err.println("parsing for hyperlinks: " + (after - before) + " ms"); - + final Def interfacesDefinitionsRoot; - + if(project != null) interfacesDefinitionsRoot = CompletionJob.buildDefinitionsTree(project, false); - /* If the project is null, that means the file is external (not in a project). In this case, + /* If the project is null, that means the file is external (not in a project). In this case, * parse only the file to be able to show hyperlinks for this file. - */ - /* TODO: Provide hyperlinks to other modules referenced by this file */ + */ + /* TODO: Provide hyperlinks to other modules referenced by this file */ else { interfacesDefinitionsRoot = new Def("", Def.Type.Root, 0, 0); OcamlNewInterfaceParser parser = OcamlNewInterfaceParser.getInstance(); - + File file = editor.getPathOfFileBeingEdited().toFile(); Def def = parser.parseFile(file, false); if (def != null) @@ -80,17 +83,17 @@ public IHyperlink[] detectHyperlinks(final ITextViewer textViewer, final IRegion else return null; } - + long time = System.currentTimeMillis(); /* Find which definition in the tree is at the hovered offset */ - final Def searchedDef = (time - lastTime < 1000 && lastOffset == region.getOffset() && lastDef != null) ? lastDef - : findIdentAt(modulesDefinitionsRoot, region.getOffset(), textViewer.getDocument()); + final Def searchedDef = (time - lastTime < 1000 && lastOffset == offset && lastDef != null) ? lastDef + : findIdentAt(modulesDefinitionsRoot, offset, textViewer.getDocument()); lastTime = time; - lastOffset = region.getOffset(); + lastOffset = offset; lastDef = searchedDef; if (searchedDef != null) { @@ -103,48 +106,100 @@ public IHyperlink[] detectHyperlinks(final ITextViewer textViewer, final IRegion return makeOpenHyperlink(textViewer, searchedDef, interfacesDefinitionsRoot); } - return new IHyperlink[] { + if (searchedDef.type == Def.Type.Identifier) + return makeDefinitionHyperlink(textViewer, searchedDef, + modulesDefinitionsRoot, interfacesDefinitionsRoot); - new IHyperlink() { + return null; - public void open() { + } + // find definition by text its self + else { + time = System.currentTimeMillis(); - Def target = findDefinitionOf(searchedDef, modulesDefinitionsRoot, - interfacesDefinitionsRoot); + // TODO Trung: currently, this create a hyperlink for even Ocaml's + // keywords or text occurring inside comment. + // Need to fix this! - if (target == null) - return; + IDocument doc = textViewer.getDocument(); + TextSelection ident = findIdentAt(doc, offset); + String hoveredText = ident.getText(); + int beginOffset = ident.getOffset(); - IRegion region = target.getRegion(textViewer.getDocument()); - editor.selectAndReveal(region.getOffset(), region.getLength()); - } + if (hoveredText.isEmpty() || Character.isDigit(hoveredText.charAt(0))) + return null; - public String getTypeLabel() { - return null; - } + return makeDefinitionHyperlink(textViewer, hoveredText, beginOffset, + modulesDefinitionsRoot, interfacesDefinitionsRoot); + } + } - public String getHyperlinkText() { - return searchedDef.name; - } + private IHyperlink makeDefinitionHyperlink(final ITextViewer textViewer, + final Def def, + final Def moudulesRoot, + final Def interfacesRoot) { + IHyperlink hyperlink = new IHyperlink() { + public void open() { + Def target = findDefinitionOf(def, moudulesRoot, interfacesRoot); + if (target == null) + return; + IRegion region = target.getNameRegion(textViewer.getDocument()); + editor.selectAndReveal(region.getOffset(), region.getLength()); + } - public IRegion getHyperlinkRegion() { - return searchedDef.getRegion(textViewer.getDocument()); - } + public String getTypeLabel() { + return null; + } + public String getHyperlinkText() { + return def.name; } - }; + public IRegion getHyperlinkRegion() { + return def.getNameRegion(textViewer.getDocument()); + } + }; - } + return hyperlink; + + } + + private IHyperlink makeDefinitionHyperlink(final ITextViewer textViewer, + final String strDef, final int offset, + final Def moudulesRoot, + final Def interfacesRoot) { + IHyperlink hyperlink = new IHyperlink() { + public void open() { + Def target = findDefinitionOf(strDef, moudulesRoot, interfacesRoot); + if (target == null) + return; + IRegion region = target.getNameRegion(textViewer.getDocument()); + editor.selectAndReveal(region.getOffset(), region.getLength()); + } + + public String getTypeLabel() { + return null; + } + + public String getHyperlinkText() { + return strDef; + } + + public IRegion getHyperlinkRegion() { + return new Region(offset, strDef.length()); + } + }; + + return hyperlink; - return null; } /** * Find the definition of searchedDef in modulesDefinitionsRoot, * and in interfacesDefinitionsRoot */ - private Def findDefinitionOf(final Def searchedDef, final Def modulesDefinitionsRoot, + private Def findDefinitionOf(final Def searchedDef, + final Def modulesDefinitionsRoot, final Def interfacesDefinitionsRoot) { Def def = null; @@ -153,11 +208,14 @@ private Def findDefinitionOf(final Def searchedDef, final Def modulesDefinitions * if this is a compound name "A.B.c", then we extract the first component to know what * module to look for, and then we get the definition by entering the module */ + StringBuilder fullDefName = new StringBuilder(searchedDef.name); if (searchedDef.name.indexOf('.') != -1) { String[] parts = searchedDef.name.split("\\."); if (parts.length > 1) { - Def firstPart = lookForDefinitionUp(null, parts[0], searchedDef, interfacesDefinitionsRoot, parts, true); - // don't find it in the current module, look in the other ones + Def firstPart = lookForDefinitionUp(null, parts[0], searchedDef, interfacesDefinitionsRoot, fullDefName, true); + // since fullDefName is updated, we need to updata parts variable + parts = fullDefName.toString().split("\\."); + // don't find it in the current module, look in the other ones if (firstPart == null) { if (openDefInInterfaces(0, parts, interfacesDefinitionsRoot)) return null; @@ -173,17 +231,17 @@ private Def findDefinitionOf(final Def searchedDef, final Def modulesDefinitions Def searchedDef2 = new Def(searchedDef); searchedDef2.name = parts[0]; for (int i = 1; i < parts.length; i++) - searchedDef2.name = "." + searchedDef2.name; - firstPart = lookForDefinitionUp(null, parts[0], searchedDef2, interfacesDefinitionsRoot, parts, true); - } else + searchedDef2.name = "." + searchedDef2.name; + firstPart = lookForDefinitionUp(null, parts[0], searchedDef2, interfacesDefinitionsRoot, fullDefName, true); + } else break; } // if the original definition of firstPart is not in current module, look in the other ones if (firstPart == null) { if (openDefInInterfaces(0, parts, interfacesDefinitionsRoot)) return null; - - } + + } // look for the whole parts in current module. else { Def defFromPath = findDefFromPath(1, parts, firstPart, null); @@ -197,7 +255,7 @@ private Def findDefinitionOf(final Def searchedDef, final Def modulesDefinitions } else { def = lookForDefinitionUp(searchedDef, searchedDef.name, searchedDef, - interfacesDefinitionsRoot, new String[] { searchedDef.name }, true); + interfacesDefinitionsRoot, fullDefName, true); // if we didn't find it, look in Pervasives (which is always opened by default) if (def == null) { @@ -209,16 +267,101 @@ private Def findDefinitionOf(final Def searchedDef, final Def modulesDefinitions // if it still wasn't found, try to open it as a module if (def == null && searchedDef.name.length() > 0 && Character.isUpperCase(searchedDef.name.charAt(0))) { - IHyperlink[] hyperlinks = makeOpenHyperlink(null, searchedDef, + IHyperlink hyperlink = makeOpenHyperlink(null, searchedDef, interfacesDefinitionsRoot); - if (hyperlinks.length > 0) - hyperlinks[0].open(); + hyperlink.open(); } } return def; } + /** + * Find the definition of searchedDef in modulesDefinitionsRoot, + * and in interfacesDefinitionsRoot + */ + private Def findDefinitionOf(final String strDef, + final Def modulesDefinitionsRoot, + final Def interfacesDefinitionsRoot) { + /* + * use direct name + */ + String[] directPath = strDef.split("\\."); + if (openDefInInterfaces(0, directPath, interfacesDefinitionsRoot)) + return null; + + /* + * look in current module + */ + Def def = modulesDefinitionsRoot; + for (int index = 0; index < directPath.length; index++) { + boolean stop = true; + for (Def d : def.children) { + if (d.name.equals(directPath[index])) { + def = d; + if (index == directPath.length - 1) + return def; + else { + stop = false; + break; + } + } + } + if (stop) + break; + } + + /* + * lookup in opened module + */ + for (Def d : modulesDefinitionsRoot.children) { + if (d.type == Def.Type.Open) { + String fullStrDef = d.name + "." + strDef; + String[] openedPath = fullStrDef.split("\\."); + if (openDefInInterfaces(0, openedPath, interfacesDefinitionsRoot)) + return null; + } + } + + /* + * lookup in module nam or possible aliased module + */ + String[] path = strDef.split("\\."); + String moduleName = path[0]; + boolean stop = false; + while (!stop) { + stop = true; + for (Def d : modulesDefinitionsRoot.children) { + if (d.name.equals(moduleName) && (d.type == Def.Type.ModuleAlias)) { + String aliasedName = d.children.get(0).name; + if (moduleName.equals(aliasedName)) + stop = true; + else { + moduleName = aliasedName; + stop = false; + } + break; + } + } + } + if (!moduleName.equals(path[0])) { + String newFullDefName = moduleName; + for (int i = 1; i < path.length; i++) + newFullDefName = newFullDefName + "." + path[i]; + String[] aliasedPath = newFullDefName.split("\\."); + + if (openDefInInterfaces(0, aliasedPath, interfacesDefinitionsRoot)) + return null; + } + + /* + * finally, look in Pervasives (which is always opened by default) + */ + String[] pervasivesPath = ("Pervasives" + strDef).split("\\."); + openDefInInterfaces(0, pervasivesPath, interfacesDefinitionsRoot); + return null; + } + /** Find the definition whose complete path is given, starting at index */ private Def findDefFromPath(int index, String[] path, Def def, Def lastPartFound) { if (index == path.length) @@ -245,7 +388,7 @@ private Def findDefFromPath(int index, String[] path, Def def, Def lastPartFound /** * Look for a definition in the node node, its previous siblings, its associated * nodes ("and"), and recurse on its parent - * + * * @param searchedNode * the node we are looking for * @param name @@ -254,20 +397,27 @@ private Def findDefFromPath(int index, String[] path, Def def, Def lastPartFound * the node from which to start * @param interfacesDefinitionsRoot * the root of the interfaces definitions tree - * @param fullpath + * @param fullDefName * the full path of the searched definition (used to look for it in other modules) * @param otherBranch * are we in another branch relative to the definition from which we started? (this * is used to manage the non-rec definitions) */ private Def lookForDefinitionUp(Def searchedNode, String name, Def node, - Def interfacesDefinitionsRoot, String[] fullpath, boolean otherBranch) { + Def interfacesDefinitionsRoot, StringBuilder fullDefName, boolean otherBranch) { Def test = null; + + // extract first part and search again + if (name.indexOf('.') > -1) { + String[] parts = name.split("\\."); + return lookForDefinitionUp(searchedNode, parts[0], node, interfacesDefinitionsRoot, + fullDefName, otherBranch); + } if (node.type == Def.Type.In) { /* If this is an 'in' node (in a 'let in'), go directly to the parent */ return lookForDefinitionUp(searchedNode, name, node.parent, interfacesDefinitionsRoot, - fullpath, false); + fullDefName, false); } // is it this node? @@ -277,19 +427,34 @@ private Def lookForDefinitionUp(Def searchedNode, String name, Def node, // if it is an "open" node, look inside the interface of this module if (node.type == Def.Type.Open || node.type == Def.Type.Include) { - String[] path = new String[fullpath.length + 1]; - System.arraycopy(fullpath, 0, path, 1, fullpath.length); - path[0] = node.name; + String newFullDefName = node.name + "." + fullDefName.toString(); + String[] path = newFullDefName.split("\\."); if (openDefInInterfaces(0, path, interfacesDefinitionsRoot)) return null; } + // if it is an ModuleAlias, then using the aliased module to find def + if (node.type == Def.Type.ModuleAlias) { + if (node.children.size() > 0) { + String aliasModule = node.name; + String aliasedModule = node.children.get(0).name; + if (fullDefName.length() > aliasModule.length()) { + String str = fullDefName.substring(0, aliasModule.length()+1); + if (str.compareTo(aliasModule+".") == 0) { + fullDefName.delete(0, aliasModule.length()); + fullDefName.insert(0, aliasedModule); + } + } + return lookForDefinitionUp(searchedNode, aliasedModule, + node, interfacesDefinitionsRoot, + fullDefName, false); + } + } + /* if we are at root, we cannot go further up in this module. */ - if (node.type == Def.Type.Root) { - // openDefInInterfaces(0, new String[] { name }, interfacesDefinitionsRoot); + if (node.type == Def.Type.Root) return null; - } // look in the associated "and" nodes after it for (int i = node.getSiblingsOffset() + 1; i < node.parent.children.size(); i++) { @@ -298,8 +463,26 @@ private Def lookForDefinitionUp(Def searchedNode, String name, Def node, break; test = isDef(searchedNode, name, after, true, false); - if (test != null) - return test; + if (test != null) { + if (test.type == Type.ModuleAlias) { + if (test.children.size() > 0) { + String aliasModule = test.name; + String aliasedModule = test.children.get(0).name; + if (fullDefName.length() > aliasModule.length()) { + String str = fullDefName.substring(0, aliasModule.length()+1); + if (str.compareTo(aliasModule+".") == 0) { + fullDefName.delete(0, aliasModule.length()); + fullDefName.insert(0, aliasedModule); + } + } + return lookForDefinitionUp(searchedNode, aliasedModule, + node, interfacesDefinitionsRoot, + fullDefName, false); + } + } + else + return test; + } } /* look in the associated "and" nodes that precede it and also in the other (not "and") */ @@ -316,22 +499,39 @@ private Def lookForDefinitionUp(Def searchedNode, String name, Def node, // if it is an "open" node, look inside the interface of this module if (before.type == Def.Type.Open || before.type == Def.Type.Include) { - String[] path = new String[fullpath.length + 1]; - System.arraycopy(fullpath, 0, path, 1, fullpath.length); - path[0] = before.name; + String newFullDefName = before.name + "." + fullDefName.toString(); + String[] path = newFullDefName.split("\\."); if (openDefInInterfaces(0, path, interfacesDefinitionsRoot)) return null; } test = isDef(searchedNode, name, before, bAnd, !bAnd); - if (test != null) - return test; + if (test != null) { + if (test.type == Type.ModuleAlias) { + if (test.children.size() > 0) { + String aliasModule = test.name; + String aliasedModule = test.children.get(0).name; + if (fullDefName.length() > aliasModule.length()) { + String str = fullDefName.substring(0, aliasModule.length()+1); + if (str.compareTo(aliasModule+".") == 0) { + fullDefName.delete(0, aliasModule.length()); + fullDefName.insert(0, aliasedModule); + } + } + return lookForDefinitionUp(searchedNode, aliasedModule, + node, interfacesDefinitionsRoot, + fullDefName, false); + } + } + else + return test; + } } /* Now, go one step up */ return lookForDefinitionUp(searchedNode, name, node.parent, interfacesDefinitionsRoot, - fullpath, false); + fullDefName, false); } /** @@ -342,7 +542,7 @@ private boolean openDefInInterfaces(int index, final String[] path, Def interfac if (index == path.length) { try { - String filename = interfaceDef.filename; + String filename = interfaceDef.getFileName(); // open the file containing the definition IProject project = editor.getProject(); @@ -353,9 +553,9 @@ private boolean openDefInInterfaces(int index, final String[] path, Def interfac .getActivePage(); if (page != null) { - + File file = new File(filename); - + final IFileStore fileStore; try { URI uri = file.toURI(); @@ -366,14 +566,14 @@ private boolean openDefInInterfaces(int index, final String[] path, Def interfac } IEditorPart part = IDE.openEditorOnFileStore(page, fileStore); - + if (part instanceof OcamlEditor) { final OcamlEditor editor = (OcamlEditor) part; ITextViewer textViewer = editor.getTextViewer(); if (interfaceDef != null) { - IRegion region = interfaceDef.getRegion(textViewer.getDocument()); + IRegion region = interfaceDef.getNameRegion(textViewer.getDocument()); editor.selectAndReveal(region.getOffset(), region.getLength()); } } else @@ -394,21 +594,13 @@ private boolean openDefInInterfaces(int index, final String[] path, Def interfac return true; } - /* - * if we couldn't go all the way down to the definition, but we could find the beginning of - * the path, open it - */ - if (index > 1) - if (openDefInInterfaces(path.length, path, interfaceDef)) - return true; - return false; } /** * Is node the definition of name? If true, returns the node (or * the constructor in a type). If false, returns null. - * + * * @param bIn * whether to accept "let in" (or parameter) nodes * @param otherBranch @@ -466,6 +658,8 @@ else if (!searchedNode.bInIn) { return node; case ModuleType: return node; + case ModuleAlias: + return node; case External: return node; case Class: @@ -501,17 +695,15 @@ private Def findIdentAt(Def def, int offset, IDocument doc) { if (def == null || doc == null) return null; - IRegion region = def.getRegion(doc); + IRegion region = def.getNameRegion(doc); if (region == null) return null; int startOffset = region.getOffset(); - int endOffset = startOffset + region.getLength() - 1; + int endOffset = startOffset + region.getLength(); - if (startOffset <= offset - && endOffset >= offset - && (def.type == Def.Type.Identifier || def.type == Def.Type.Open || def.type == Def.Type.Include)) + if (startOffset <= offset && endOffset >= offset) return def; for (Def d : def.children) { @@ -523,20 +715,69 @@ private Def findIdentAt(Def def, int offset, IDocument doc) { return null; } + /** Find a smallest def at a position in the document */ + private TextSelection findIdentAt(IDocument doc, int offset) { + int docLen = doc.getLength(); + String text = ""; + int i = offset; + while (i < docLen) { + char ch; + try { + ch = doc.getChar(i); + if (ch == '.' || ch == '_' || Character.isLetterOrDigit(ch)) { + text = text + ch; + i++; + } + else break; + } catch (BadLocationException e) { + break; + } + } + + i = offset - 1; + while (i >= 0) { + char ch; + try { + ch = doc.getChar(i); + if (ch == '.' || ch == '_' || Character.isLetterOrDigit(ch)) { + text = ch + text; + i--; + } + else break; + } catch (BadLocationException e) { + break; + } + } + int beginOffset = (i >= 0) ? i + 1 : 0; + + + String[] parts = text.split("\\."); + String hoveredText = parts[parts.length - 1]; + i = parts.length - 2; + while (i >= 0) { + if (parts[i].isEmpty()) + break; + if (!Character.isUpperCase(parts[i].charAt(0))) + break; + hoveredText = parts[i] + "." + hoveredText; + i--; + } + beginOffset = beginOffset + (text.length() - hoveredText.length()); + + return new TextSelection(doc, beginOffset, hoveredText.length()); + } + + + /** * make an hyperlink for an open directive (to open the interface in an editor) */ - private IHyperlink[] makeOpenHyperlink(final ITextViewer textViewer, final Def searchedDef, + private IHyperlink makeOpenHyperlink(final ITextViewer textViewer, final Def searchedDef, final Def interfacesDefinitionsRoot) { - return new IHyperlink[] { - - new IHyperlink() { - + return new IHyperlink() { public void open() { - try { - // extract the first part of a multipart name (A.B.C) String[] fragments = searchedDef.name.split("\\."); @@ -634,13 +875,9 @@ public String getHyperlinkText() { } public IRegion getHyperlinkRegion() { - return searchedDef.getRegion(textViewer.getDocument()); + return searchedDef.getNameRegion(textViewer.getDocument()); } - - } - }; - } } diff --git a/Ocaml/src/ocaml/editors/OcamlSourceViewerConfig.java b/Ocaml/src/ocaml/editors/OcamlSourceViewerConfig.java index 889f476..79d1f81 100644 --- a/Ocaml/src/ocaml/editors/OcamlSourceViewerConfig.java +++ b/Ocaml/src/ocaml/editors/OcamlSourceViewerConfig.java @@ -13,16 +13,26 @@ import ocaml.preferences.PreferenceConstants; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.JFacePreferences; +import org.eclipse.jface.resource.ColorRegistry; 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.ContentAssistEvent; import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.ICompletionListener; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.ICompletionProposalSorter; import org.eclipse.jface.text.contentassist.IContentAssistant; import org.eclipse.jface.text.formatter.IContentFormatter; import org.eclipse.jface.text.formatter.MultiPassContentFormatter; +import org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; +import org.eclipse.jface.text.hyperlink.IHyperlinkPresenter; import org.eclipse.jface.text.presentation.IPresentationReconciler; import org.eclipse.jface.text.presentation.PresentationReconciler; import org.eclipse.jface.text.reconciler.IReconciler; @@ -42,9 +52,15 @@ import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; import org.eclipse.ui.editors.text.EditorsUI; +import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; import org.eclipse.ui.texteditor.spelling.SpellingService; +import org.eclipse.ui.themes.ITheme; +import org.eclipse.ui.themes.IThemeManager; /** * Configures the OCaml code editor: auto edit strategies, formatter, partitioning, completion assistant, @@ -52,9 +68,11 @@ */ public class OcamlSourceViewerConfig extends SourceViewerConfiguration { private OcamlEditor ocamlEditor; + private boolean isContentAssistantActive; public OcamlSourceViewerConfig(OcamlEditor ocamlEditor) { this.ocamlEditor = ocamlEditor; + this.isContentAssistantActive = false; } /** @@ -107,6 +125,7 @@ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { int styleComment = ocaml.OcamlPlugin.getCommentIsBold() ? SWT.BOLD : SWT.NONE; + int styleDocsComment = ocaml.OcamlPlugin.getDocsCommentIsBold() ? SWT.BOLD : SWT.NONE; int styleString = ocaml.OcamlPlugin.getStringIsBold() ? SWT.BOLD : SWT.NONE; PresentationReconciler reconciler = new PresentationReconciler(); @@ -121,10 +140,10 @@ public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceVie // a damager-repairer for doc comments and doc annotations RuleBasedScanner scannerAnnot = new RuleBasedScanner(); IToken tokenAnnot = new Token(new TextAttribute(OcamlEditorColors.getDocAnnotationColor(), null, - styleComment)); + styleDocsComment)); IToken tokenDocComment = new Token(new TextAttribute(OcamlEditorColors.getDocCommentColor(), null, - styleComment)); + styleDocsComment)); scannerAnnot.setRules(new IRule[] { new DocumentAnnotationRule(tokenAnnot, tokenDocComment) }); dr = new DefaultDamagerRepairer(scannerAnnot); @@ -149,21 +168,40 @@ public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceVie public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { ContentAssistant assistant = new ContentAssistant(); assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); - + assistant.enablePrefixCompletion(true); assistant.setContentAssistProcessor(new OcamlCompletionProcessor(this.ocamlEditor, OcamlPartitionScanner.OCAML_DOCUMENTATION_COMMENT), OcamlPartitionScanner.OCAML_DOCUMENTATION_COMMENT); assistant.setContentAssistProcessor(new OcamlCompletionProcessor(this.ocamlEditor, IDocument.DEFAULT_CONTENT_TYPE), IDocument.DEFAULT_CONTENT_TYPE); - assistant.enableAutoInsert(true); + assistant.addCompletionListener(new ICompletionListener() { + @Override + public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) { + isContentAssistantActive = true; + } + @Override + public void assistSessionStarted(ContentAssistEvent event) { + isContentAssistantActive = true; + } + @Override + public void assistSessionEnded(ContentAssistEvent event) { + isContentAssistantActive = false; + } + }); + + assistant.setSorter(new ICompletionProposalSorter() { + @Override + public int compare(ICompletionProposal p1, ICompletionProposal p2) { + return p1.getDisplayString().compareTo(p2.getDisplayString()); + } + }); boolean autoActivation = OcamlPlugin.getInstance().getPreferenceStore().getBoolean( PreferenceConstants.P_EDITOR_AUTOCOMPLETION); - assistant.enableAutoActivation(autoActivation); - assistant.setAutoActivationDelay(100); + assistant.enableAutoInsert(true); assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_STACKED); assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE); assistant.setInformationControlCreator(new OcamlInformationControlCreator()); @@ -179,11 +217,23 @@ public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { return new OcamlAnnotationHover(); } + @Override public IHyperlinkDetector[] getHyperlinkDetectors(ISourceViewer sourceViewer) { return new IHyperlinkDetector[] { new OcamlHyperlinkDetector(this.ocamlEditor) }; } + + @Override + public IHyperlinkPresenter getHyperlinkPresenter(ISourceViewer sourceViewer) { + IThemeManager themeManager = WorkbenchPlugin.getDefault().getWorkbench().getThemeManager(); + ITheme currentTheme = themeManager.getCurrentTheme(); + ColorRegistry colorRegistry = currentTheme.getColorRegistry(); + // use hyperlink color from current preference of Eclipse + Color color = colorRegistry.get(JFacePreferences.HYPERLINK_COLOR); + DefaultHyperlinkPresenter hyperlinkPresenter = new DefaultHyperlinkPresenter(color); + return hyperlinkPresenter; + } @Override public IReconciler getReconciler(final ISourceViewer sourceViewer) { @@ -207,7 +257,7 @@ public IReconciler getReconciler(final ISourceViewer sourceViewer) { reconciler.setIsIncrementalReconciler(false); reconciler.setProgressMonitor(new NullProgressMonitor()); reconciler.setDelay(500); - + OcamlPlugin.getInstance().getPreferenceStore().addPropertyChangeListener( new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { @@ -245,6 +295,14 @@ public void propertyChange(PropertyChangeEvent event) { else return null; } + + + + public boolean isContentAssistantActive() { + return isContentAssistantActive; + } + + } diff --git a/Ocaml/src/ocaml/editors/OcamlTextHover.java b/Ocaml/src/ocaml/editors/OcamlTextHover.java index 90f32e7..0d86d02 100644 --- a/Ocaml/src/ocaml/editors/OcamlTextHover.java +++ b/Ocaml/src/ocaml/editors/OcamlTextHover.java @@ -5,7 +5,6 @@ import ocaml.OcamlPlugin; import ocaml.debugging.OcamlDebugger; -import ocaml.preferences.PreferenceConstants; import ocaml.typeHovers.OcamlAnnotParser; import ocaml.typeHovers.TypeAnnotation; import ocaml.util.Misc; @@ -28,35 +27,85 @@ */ public class OcamlTextHover implements ITextHover { private OcamlEditor ocamlEditor; + public OcamlTextHover(OcamlEditor ocamlEditor) { this.ocamlEditor = ocamlEditor; } /** - * Returns the string to display in a pop-up which gives informations about the element currently under - * the mouse cursor in the editor + * Returns the string to display in a pop-up which gives informations + * about the element currently under the mouse cursor in the editor */ + @Override public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { - // the file in the workspace. null if the file is external - IFile file = ocamlEditor.getFileBeingEdited(); + String markersInfo = getMarkerInfo(textViewer, hoverRegion); + String valueInfo = getExpressionValue(textViewer, hoverRegion); + String typeInfo = getTypeInfo(textViewer, hoverRegion); + + String hoverInfo = ""; + + if (!markersInfo.isEmpty()) { + hoverInfo = markersInfo; + } + + if (!valueInfo.isEmpty()) { + if (hoverInfo.isEmpty()) + hoverInfo = valueInfo; + else + hoverInfo = hoverInfo + "\n\n" + "Value info: " + "\n" + valueInfo; + } + + if (!typeInfo.isEmpty()) { + if (hoverInfo.isEmpty()) + hoverInfo = typeInfo; + else + hoverInfo = hoverInfo + "\n\n" + "Type info: " + "\n" + typeInfo; + } + + return hoverInfo; + } + + // get HoverInfo in 1 line format + public String getHoverInfoOneLine(ITextViewer textViewer, IRegion hoverRegion) { + // display only marker info, value info, or type info + String hoverInfo = getMarkerInfo(textViewer, hoverRegion); + + if (hoverInfo.isEmpty()) + hoverInfo = getExpressionValue(textViewer, hoverRegion); + + if (hoverInfo.isEmpty()) + hoverInfo = getTypeInfo(textViewer, hoverRegion); + + String[] lines = hoverInfo.split(System.lineSeparator()); + String hoverInfoOneLine = ""; + for (String line: lines) + hoverInfoOneLine = hoverInfoOneLine + " " + line.trim(); + return hoverInfoOneLine.trim(); + } - // the full system path of the file + + /** + * Returns the string to display in a pop-up which gives marker informations + * about the element currently under the mouse cursor in the editor + */ + public String getMarkerInfo(ITextViewer textViewer, IRegion region) { + IFile file = ocamlEditor.getFileBeingEdited(); IPath filePath = ocamlEditor.getPathOfFileBeingEdited(); if (filePath == null) - return ""; + return ""; - if (hoverRegion == null) { + if (region == null) { ocaml.OcamlPlugin.logError("OcamlTextHover:getHoverInfo null region"); return ""; } try { // error message string, if we found one in the hovered region - String hoverMessage = ""; + String markerInfo = ""; - int hoverOffset = hoverRegion.getOffset(); + int hoverOffset = region.getOffset(); if (file != null) { IMarker[] markers = file.findMarkers(null, true, 1); @@ -66,102 +115,180 @@ public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { if (hoverOffset >= markerStart && hoverOffset <= markerEnd) { String message = marker.getAttribute(IMarker.MESSAGE, ""); - hoverMessage = hoverMessage + message.trim() + "\n"; + markerInfo = markerInfo + message.trim() + "\n\n"; } } + return markerInfo.trim(); } + } catch (Throwable e) { + // ocaml.OcamlPlugin.logError("Erreur dans OcamlTextHover:getHoverInfo", e); + } - // if the debugger is started, we ask it for the value of the variable under the cursor - if (OcamlDebugger.getInstance().isStarted()) { - String text = textViewer.getDocument().get(); - String expression = expressionAtOffset(text, hoverOffset).trim(); + return ""; + } + + // get markerInfo in 1 line format + public String getMarkerInfoOneLine(ITextViewer textViewer, IRegion region) { + String markerInfo = getMarkerInfo(textViewer, region); + String[] lines = markerInfo.split(System.lineSeparator()); + String markerInfoOneLine = ""; + for (String line: lines) + markerInfoOneLine = markerInfoOneLine + " " + line.trim(); + return markerInfoOneLine.trim(); + } + + /** + * Returns the string to display in a pop-up which gives type informations + * about the element currently under the mouse cursor in the editor + */ + public String getTypeInfo(ITextViewer textViewer, IRegion region) { + IFile file = ocamlEditor.getFileBeingEdited(); + IPath filePath = ocamlEditor.getPathOfFileBeingEdited(); - if (!expression.equals("")) { - String value = OcamlDebugger.getInstance().display(expression).trim(); + if (filePath == null) + return ""; - if (!value.equals("")) - return (hoverMessage + Misc.beautify(value)).trim(); - } - } + if (region == null) { + ocaml.OcamlPlugin.logError("OcamlTextHover:getHoverInfo null region"); + return ""; + } - if (OcamlPlugin.getInstance().getPreferenceStore().getBoolean( - PreferenceConstants.P_SHOW_TYPES_IN_POPUPS)) { + try { + String typeInfo = ""; + int offset = region.getOffset(); + + File annotFile = null; + + // workspace file + if (file != null) + annotFile = Misc.getOtherFileFor(file.getProject(), file.getFullPath(), ".annot"); + else + annotFile = Misc.getOtherFileFor(filePath, ".annot"); - File annotFile = null; + if (annotFile != null && annotFile.exists()) { + boolean bUpToDate = false; - // workspace file if (file != null) - annotFile = Misc.getOtherFileFor(file.getProject(), file.getFullPath(), ".annot"); + bUpToDate = file.getLocation().toFile().lastModified() <= annotFile.lastModified(); else - annotFile = Misc.getOtherFileFor(filePath, ".annot"); - - if (annotFile != null && annotFile.exists()) { - boolean bUpToDate = false; - - if (file != null) - bUpToDate = file.getLocation().toFile().lastModified() <= annotFile.lastModified(); - else - bUpToDate = filePath.toFile().lastModified() <= annotFile.lastModified(); - - if (!ocamlEditor.isDirty() && bUpToDate) { - ArrayList found = new ArrayList(); - - TypeAnnotation[] annotations = OcamlAnnotParser.parseFile(annotFile, textViewer - .getDocument()); - if (annotations != null) { - for (TypeAnnotation annot : annotations) - if (annot.getBegin() <= hoverOffset && hoverOffset < annot.getEnd()) - found.add(annot); - - /* - * Search for the smallest hovered type annotation - */ - TypeAnnotation annot = null; - int minSize = Integer.MAX_VALUE; - - for (TypeAnnotation a : found) { - int size = a.getEnd() - a.getBegin(); - if (size < minSize) { - annot = a; - minSize = size; - } - } + bUpToDate = filePath.toFile().lastModified() <= annotFile.lastModified(); + + if (!ocamlEditor.isDirty() /*&& bUpToDate*/) { + ArrayList found = new ArrayList(); + + TypeAnnotation[] annotations = OcamlAnnotParser.parseFile(annotFile, textViewer + .getDocument()); + if (annotations != null) { + for (TypeAnnotation annot : annotations) + if (annot.getBegin() <= offset && offset < annot.getEnd()) + found.add(annot); - if (annot != null) { - - String doc = ocamlEditor.getDocumentProvider().getDocument( - ocamlEditor.getEditorInput()).get(); - String expr = doc.substring(annot.getBegin(), annot.getEnd()); - String[] lines = expr.split("\\n"); - if (expr.length() < 50 && lines.length <= 6) - return (hoverMessage + expr + ": " + annot.getType()).trim(); - else if (lines.length > 6) { - int l = lines.length; - - return (hoverMessage + lines[0] + "\n" + lines[1] + "\n" + lines[2] - + "\n" + "..." + (l - 6) + " more lines...\n" + lines[l - 3] - + "\n" + lines[l - 2] + "\n" + lines[l - 1] + "\n:" + annot - .getType()).trim(); - } else - return (hoverMessage + expr + "\n:" + annot.getType()).trim(); + /* + * Search for the smallest hovered type annotation + */ + TypeAnnotation annot = null; + int minSize = Integer.MAX_VALUE; + + for (TypeAnnotation a : found) { + int size = a.getEnd() - a.getBegin(); + if (size < minSize) { + annot = a; + minSize = size; } } + + if (annot != null) { + String doc = ocamlEditor.getDocumentProvider().getDocument( + ocamlEditor.getEditorInput()).get(); + String expr = doc.substring(annot.getBegin(), annot.getEnd()); + String[] lines = expr.split("\\n"); + if (expr.length() < 50 && lines.length <= 6) + return (typeInfo + expr + ": " + annot.getType()).trim(); + else if (lines.length > 6) { + int l = lines.length; + + return (typeInfo + lines[0] + "\n" + lines[1] + "\n" + lines[2] + + "\n" + "..." + (l - 6) + " more lines...\n" + lines[l - 3] + + "\n" + lines[l - 2] + "\n" + lines[l - 1] + "\n:" + annot + .getType()).trim(); + } else + return (typeInfo + expr + "\n:" + annot.getType()).trim(); + } } } } - return hoverMessage.trim(); + return typeInfo.trim(); /* * if (!this.ocamlEditor.isDirty()) return this.ocamlEditor.getTypeInfoAt(hoverOffset).trim(); */ } catch (Throwable e) { - ocaml.OcamlPlugin.logError("Erreur dans OcamlTextHover:getHoverInfo", e); + // ocaml.OcamlPlugin.logError("Erreur dans OcamlTextHover:getHoverInfo", e); } return ""; } + + // get HoverInfo in 1 line format + public String getTypeInfoOneLine(ITextViewer textViewer, IRegion region) { + String typeInfo = getTypeInfo(textViewer, region); + String[] lines = typeInfo.split(System.lineSeparator()); + String typeInfoOneLine = ""; + for (String line: lines) + typeInfoOneLine = typeInfoOneLine + " " + line.trim(); + return typeInfoOneLine.trim(); + } + + /** + * Returns the string to display in a pop-up which gives value of expression + * currently under the mouse cursor in the editor in debug mode + */ + public String getExpressionValue(ITextViewer textViewer, IRegion region) { + IPath filePath = ocamlEditor.getPathOfFileBeingEdited(); + + if (filePath == null) + return ""; + + if (region == null) { + ocaml.OcamlPlugin.logError("OcamlTextHover:getHoverInfo null region"); + return ""; + } + + String value = ""; + + try { + int offset = region.getOffset(); + + // if the debugger is started, we ask it for the value of the variable under the cursor + if (OcamlDebugger.getInstance().isStarted()) { + String text = textViewer.getDocument().get(); + String expression = expressionAtOffset(text, offset).trim(); + + if (!expression.equals("")) { + value = OcamlDebugger.getInstance().display(expression).trim(); + if (!value.equals("")) + value = Misc.beautify(value).trim(); + } + } + } catch (Throwable e) { + // ocaml.OcamlPlugin.logInfo("Erreur dans OcamlTextHover:getHoverInfo", e); + } + + return value; + } + + // get expression value in 1 line format + public String getExpressionValueOneLine(ITextViewer textViewer, IRegion region) { + String value = getExpressionValue(textViewer, region); + String[] lines = value.split(System.lineSeparator()); + String valueOneLine = ""; + for (String line: lines) + valueOneLine = valueOneLine + " " + line.trim(); + return valueOneLine.trim(); + } + @Override public IRegion getHoverRegion(ITextViewer textViewer, int offset) { return new Region(offset, 0); } diff --git a/Ocaml/src/ocaml/editors/lex/OcamllexEditor.java b/Ocaml/src/ocaml/editors/lex/OcamllexEditor.java index 9781bcd..d7b3e53 100644 --- a/Ocaml/src/ocaml/editors/lex/OcamllexEditor.java +++ b/Ocaml/src/ocaml/editors/lex/OcamllexEditor.java @@ -2,9 +2,10 @@ import ocaml.OcamlPlugin; import ocaml.editor.completion.CompletionJob; +import ocaml.editor.syntaxcoloring.OcamlEditorColors; import ocaml.editors.util.OcamlCharacterPairMatcher; import ocaml.natures.OcamlNatureMakefile; -import ocaml.popup.actions.CompileProjectAction; +import ocaml.popup.actions.CompileProjectPopupAction; import ocaml.preferences.PreferenceConstants; import org.eclipse.core.resources.IProject; @@ -13,8 +14,12 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.PaintManager; +import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.MatchingCharacterPainter; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; @@ -39,9 +44,11 @@ public OcamllexEditor() { protected void createActions() { super.createActions(); - paintManager = new PaintManager(getSourceViewer()); + final ISourceViewer viewer = getSourceViewer(); + + paintManager = new PaintManager(viewer); matchingCharacterPainter = - new MatchingCharacterPainter(getSourceViewer(), new OcamlCharacterPairMatcher()); + new MatchingCharacterPainter(viewer, new OcamlCharacterPairMatcher()); matchingCharacterPainter.setColor(new Color(Display.getCurrent(), new RGB(160, 160, 160))); paintManager.addPainter(matchingCharacterPainter); @@ -49,7 +56,7 @@ protected void createActions() { // effectue le parsing des bibliothèques ocaml en arrière plan CompletionJob job = new CompletionJob("Parsing ocaml library mli files", null); - job.setPriority(CompletionJob.DECORATE); + job.setPriority(CompletionJob.INTERACTIVE); // Trung changes priority job.schedule(); } @@ -97,7 +104,7 @@ public void doSave(IProgressMonitor monitor) { IWorkspace ws = ResourcesPlugin.getWorkspace(); IWorkspaceDescription desc = ws.getDescription(); if (desc.isAutoBuilding()) - CompileProjectAction.compileProject(this.getProject()); + CompileProjectPopupAction.compileProject(this.getProject()); } } diff --git a/Ocaml/src/ocaml/editors/yacc/OcamlyaccEditor.java b/Ocaml/src/ocaml/editors/yacc/OcamlyaccEditor.java index 67b774c..6e96bd1 100644 --- a/Ocaml/src/ocaml/editors/yacc/OcamlyaccEditor.java +++ b/Ocaml/src/ocaml/editors/yacc/OcamlyaccEditor.java @@ -2,11 +2,12 @@ import ocaml.OcamlPlugin; import ocaml.editor.completion.CompletionJob; +import ocaml.editor.syntaxcoloring.OcamlEditorColors; import ocaml.editors.util.OcamlCharacterPairMatcher; import ocaml.editors.yacc.outline.OcamlYaccOutlineControl; import ocaml.editors.yacc.outline.YaccOutlineJob; import ocaml.natures.OcamlNatureMakefile; -import ocaml.popup.actions.CompileProjectAction; +import ocaml.popup.actions.CompileProjectPopupAction; import ocaml.preferences.PreferenceConstants; import org.eclipse.core.resources.IProject; @@ -15,11 +16,15 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.PaintManager; import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.MatchingCharacterPainter; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; @@ -45,9 +50,11 @@ public OcamlyaccEditor() { protected void createActions() { super.createActions(); - paintManager = new PaintManager(getSourceViewer()); + final ISourceViewer viewer = getSourceViewer(); + + paintManager = new PaintManager(viewer); matchingCharacterPainter = - new MatchingCharacterPainter(getSourceViewer(), new OcamlCharacterPairMatcher()); + new MatchingCharacterPainter(viewer, new OcamlCharacterPairMatcher()); matchingCharacterPainter.setColor(new Color(Display.getCurrent(), new RGB(160, 160, 160))); paintManager.addPainter(matchingCharacterPainter); @@ -55,17 +62,18 @@ protected void createActions() { // effectue le parsing des bibliothèques ocaml en arrière plan CompletionJob job = new CompletionJob("Parsing ocaml library mli files", null); - job.setPriority(CompletionJob.DECORATE); + job.setPriority(CompletionJob.INTERACTIVE); // Trung changes priority job.schedule(); - - - this.getSourceViewer().addTextListener(new ITextListener() { + + + viewer.addTextListener(new ITextListener() { public void textChanged(TextEvent event) { if (event.getDocumentEvent() != null) rebuildOutline(500); } }); + } @Override @@ -112,14 +120,14 @@ public void doSave(IProgressMonitor monitor) { IWorkspace ws = ResourcesPlugin.getWorkspace(); IWorkspaceDescription desc = ws.getDescription(); if (desc.isAutoBuilding()) - CompileProjectAction.compileProject(this.getProject()); + CompileProjectPopupAction.compileProject(this.getProject()); } } - - + + private OcamlYaccOutlineControl outline; private YaccOutlineJob outlineJob = null; - + /** * We give the outline to Eclipse when it asks for an adapter with the outline class. */ @@ -133,8 +141,12 @@ public Object getAdapter(@SuppressWarnings("unchecked") Class required) { } return super.getAdapter(required); } - + public void rebuildOutline(int delay) { + /* + * Trung: rebuilding outline will dispose all completion proposal + * pop-up windows if existing. + */ IEditorInput input = this.getEditorInput(); IDocument document = this.getDocumentProvider().getDocument(input); @@ -154,6 +166,6 @@ public void rebuildOutline(int delay) { outlineJob.schedule(delay); } - - + + } diff --git a/Ocaml/src/ocaml/parser/Def.java b/Ocaml/src/ocaml/parser/Def.java index 3099d46..3bcc5ac 100644 --- a/Ocaml/src/ocaml/parser/Def.java +++ b/Ocaml/src/ocaml/parser/Def.java @@ -24,7 +24,7 @@ public enum Type { /** the root of the definitions tree (module implementation) */ Root, /** a variable name, with its position */ - Identifier, Let, LetIn, Type, Module, ModuleType, Exception, External, Class, Sig, + Identifier, Let, LetIn, Type, Module, ModuleAlias, ModuleType, Exception, External, Class, Sig, Open, Object, Method, Struct, Functor, Include, Val, Constraint, Initializer, @@ -72,7 +72,17 @@ public enum Type { * The type inferred by the OCaml compiler for this definition (this is retrieved and displayed * in the outline when a ".annot" file is present and up-to-date) */ - public String ocamlType; + private String ocamlType; + + public String getOcamlType() { + return ocamlType; + } + + public void setOcamlType(String type) { + if (type == null) + this.ocamlType = ""; + else this.ocamlType = type; + } /** The parent of this node. This is required by the outline's ContentProvider */ public Def parent; @@ -111,6 +121,7 @@ public Def() { this.posStart = 0; this.posEnd = 0; this.defPosStart = 0; + this.ocamlType = ""; // this.defPosEnd = 0; } @@ -118,14 +129,18 @@ public Def() { public Def(String name, Type type, int start, int end) { super(); children = new ArrayList(); - this.name = name; + if (name != null) + this.name = name; + else + this.name = ""; this.type = type; this.posStart = start; this.posEnd = end; this.defPosStart = 0; + this.ocamlType = ""; // this.defPosEnd = 0; } - + /** copy constructor */ public Def(Def def) { this.bAlt = def.bAlt; @@ -156,15 +171,26 @@ public Def(Def def) { void add(Symbol s) { assert s instanceof Def; - children.add((Def) s); + + Def def = (Def) s; + children.add(def); + + // update location + this.defOffsetEnd = def.defOffsetEnd; } /** Creates a new dummy node as root of a and b, and return this node */ public static Def root(Symbol a) { assert a instanceof Def; + Def def = new Def(); Def defa = (Def) a; def.children.add(defa); + + // update location + def.defOffsetStart = defa.defOffsetStart; + def.defOffsetEnd = defa.defOffsetEnd; + return def; } @@ -181,6 +207,10 @@ public static Def root(Symbol a, Symbol b) { def.children.add(defa); def.children.add(defb); + // update location + def.defOffsetStart = defa.defOffsetStart; + def.defOffsetEnd = defb.defOffsetEnd; + return def; } @@ -200,6 +230,10 @@ public static Def root(Symbol a, Symbol b, Symbol c) { def.children.add(defb); def.children.add(defc); + // update location + def.defOffsetStart = defa.defOffsetStart; + def.defOffsetEnd = defc.defOffsetEnd; + return def; } @@ -222,6 +256,10 @@ public static Def root(Symbol a, Symbol b, Symbol c, Symbol d) { def.children.add(defc); def.children.add(defd); + // update location + def.defOffsetStart = defa.defOffsetStart; + def.defOffsetEnd = defd.defOffsetEnd; + return def; } @@ -251,7 +289,7 @@ private void collapseAux(Def node, ArrayList nodes, boolean bClean) { flatList.add(node); while(!flatList.isEmpty()) { Def def = flatList.removeFirst(); - + if (def.type == Type.Dummy || bClean && def.type == Type.Identifier) { for (int i = def.children.size() - 1; i>=0; i--) { Def child = def.children.get(i); @@ -263,8 +301,8 @@ private void collapseAux(Def node, ArrayList nodes, boolean bClean) { def.clean(); } } - - + + } /** @@ -287,6 +325,13 @@ void findIdents(ArrayList idents) { child.findIdents(idents); } + void findDefNames(ArrayList defNames) { + if (this.name != null && !this.name.isEmpty()) + defNames.add(this.name); + for (Def child: children) + child.findDefNames(defNames); + } + /** Find all the "lets" in the tree rooted at this definition (and do not go further down) */ void findLets(ArrayList idents) { if (this.type == Type.Let) { @@ -337,16 +382,17 @@ public void buildSiblingOffsets() { } } - public Def cleanCopy() { + public Def cleanCopy(boolean parserError) { + this.buildParents(); Def def = new Def("", Def.Type.Root, 0, 0); - cleanCopyAux(this, def); - def.buildParents(); + cleanCopyAux(this, def, parserError); +// def.buildParents(); return def; } - private void cleanCopyAux(Def node, Def newNode) { + private void cleanCopyAux(Def node, Def newNode, boolean parserError) { ArrayList realNodes = new ArrayList(); - findRealChildren(node, realNodes, true); + findRealChildren(node, realNodes, true, parserError); for (Def d : realNodes) { Def def = new Def(d.name, d.type, d.posStart, d.posEnd); @@ -362,22 +408,60 @@ private void cleanCopyAux(Def node, Def newNode) { def.sectionComment = d.sectionComment; def.filename = d.filename; def.body = d.body; + def.parent = newNode; newNode.add(def); } for (int i = 0; i < realNodes.size(); i++) - cleanCopyAux(realNodes.get(i), newNode.children.get(i)); + cleanCopyAux(realNodes.get(i), newNode.children.get(i), parserError); } - private void findRealChildren(Def node, ArrayList nodes, boolean root) { - if (node.type == Type.Dummy || node.type == Type.Identifier || node.type == Type.Parameter - || node.type == Type.Functor || node.type == Type.Sig || node.type == Type.Object - || node.type == Type.Struct || node.type == Type.In || root - || "_".equals(node.name) || "()".equals(node.name)) { + private void findRealChildren(Def node, ArrayList nodes, boolean root, boolean parserError) { + // always go down when is in root + if (root) { for (Def d : node.children) - findRealChildren(d, nodes, false); - } else { + findRealChildren(d, nodes, false, parserError); + } + // find parameter + else if (node.type == Type.Parameter) { + // created a cloned node without children to add into nodes + Def simpleNode = new Def(node); + simpleNode.children = new ArrayList(); + nodes.add(simpleNode); + + // find children + for (Def d : node.children) + findRealChildren(d, nodes, false, parserError); + } + // find aliased module + else if (node.type == Type.Identifier) { + // add all identifiers when parser error + if (parserError) { + nodes.add(node); + } + // if no parser error, add selected identifiers + else { + Def parent = node.parent; + if (parent != null) { + if (parent.type == Type.ModuleAlias) + nodes.add(node); + } + } + + } + // go down to find real children + else if (node.type == Type.Dummy + || node.type == Type.Functor + || node.type == Type.Sig + || node.type == Type.Object + || node.type == Type.Struct + || node.type == Type.In + || "()".equals(node.name)) { + for (Def d : node.children) + findRealChildren(d, nodes, false, parserError); + } + else { nodes.add(node); } } @@ -385,17 +469,17 @@ private void findRealChildren(Def node, ArrayList nodes, boolean root) { /** completely unnest the 'in' definitions */ /* * public void completelyUnnestIn(Def parent, int index) { - * + * * for(int i = 0; i < children.size(); i++){ Def child = children.get(i); * child.completelyUnnestIn(this, i); } - * + * * ArrayList newChildren = new ArrayList(); - * + * * int j = 1; for(int i = 0; i < children.size(); i++){ Def child = children.get(i); - * + * * if(type == Type.LetIn && child.type == Type.LetIn){ parent.children.add(index + j++, child); * }else newChildren.add(child); } - * + * * children = newChildren; } */ @@ -470,12 +554,12 @@ public void unnestTypes(Def parent, int index) { } /** Returns the region in the document covered by the name of the definition */ - public IRegion getRegion(IDocument doc) { + public IRegion getNameRegion(IDocument doc) { int lineOffset = 0; try { lineOffset = doc.getLineOffset(getLine(posStart)); } catch (BadLocationException e) { - OcamlPlugin.logError("offset error", e); +// OcamlPlugin.logError("offset error", e); return null; } @@ -486,6 +570,28 @@ public IRegion getRegion(IDocument doc) { } + /** Returns the region in the document covered by this definition and its body */ + public Region getFullRegion() { + // startOffset is computed by def name + int startOffset = posStart; + + // endOffset is computed by def's full definition + Def lastDescendant = this; + while (lastDescendant.children != null & lastDescendant.children.size() > 0) { + ArrayList children = lastDescendant.children; + for (int i = children.size() - 1; i >= 0; i--) { + if (children.get(i) != null) { + lastDescendant = children.get(i); + break; + } + } + } + int endOffset = lastDescendant.posEnd; + + return new Region(startOffset, endOffset - startOffset + 1); + } + + /** The ocamldoc comment associated with this definition */ public String comment = ""; @@ -500,30 +606,27 @@ public void appendToComment(String comment) { this.comment = this.comment + "\n________________________________________\n\n" + comment; - this.comment = clean(this.comment); + this.comment = cleanString(this.comment); } public String sectionComment = ""; public void setSectionComment(String text) { - this.sectionComment = clean(text); + this.sectionComment = cleanString(text); } public void setComment(String text) { if (text.equals("/*")) return; - this.comment = clean(text); + this.comment = cleanString(text); } - public void setBody(String text) { - this.body = Misc.beautify(clean(text)); - } - private static String clean(String str) { + public static String cleanString(String str) { if (str == null) return ""; - + // remove all redundant spaces String[] lines = str.split("\\n"); StringBuilder stringBuilder = new StringBuilder(); @@ -537,9 +640,91 @@ private static String clean(String str) { return stringBuilder.toString().trim(); } - public String body = ""; + private String body = ""; + + private String filename = ""; + + public void setBody(String body) { +// this.body = Misc.beautify(clean(body)); + this.body = Misc.beautify(body); + } + + public String getBody() { + return this.body; + } + + + public void setFileName(String filename) { + this.filename = filename; + } + + public String getFileName() { + return filename; + } + + public String getTypeName() { + + + if (type == Type.Dummy) + return "Dummy"; + else if (type == Type.In) + return "In"; + else if (type == Type.Root) + return "Root"; + else if (type == Type.Identifier) + return "Identifier"; + else if (type == Type.Let) + return "Let"; + else if (type == Type.LetIn) + return "LetIn"; + else if (type == Type.Type) + return "Type"; + else if (type == Type.Module) + return "Module"; + else if (type == Type.ModuleAlias) + return "ModuleAlias"; + else if (type == Type.ModuleType) + return "ModuleType"; + else if (type == Type.Exception) + return "Exception"; + else if (type == Type.External) + return "External"; + else if (type == Type.Class) + return "Class"; + else if (type == Type.Sig) + return "Sig"; + else if (type == Type.Open) + return "Open"; + else if (type == Type.Object) + return "Object"; + else if (type == Type.Method) + return "Method"; + else if (type == Type.Struct) + return "Struct"; + else if (type == Type.Functor) + return "Functor"; + else if (type == Type.Include) + return "Include"; + else if (type == Type.Val) + return "Val"; + else if (type == Type.Constraint) + return "Constraint"; + else if (type == Type.Initializer) + return "Initializer"; + else if (type == Type.ClassType) + return "ClassType"; + else if (type == Type.TypeConstructor) + return "TypeConstructor"; + else if (type == Type.RecordTypeConstructor) + return "RecordTypeConstructor"; + else if (type == Type.Parameter) + return "Parameter"; + else if (type == Type.ParserError) + return "ParserError"; + else + return "Unknown"; + } - public String filename = ""; public String parentName = ""; @@ -549,10 +734,10 @@ private static String clean(String str) { * 0; try { firstLineOffset = doc.getLineOffset(getLine(defPosStart)); lastLineOffset = * doc.getLineOffset(getLine(defPosEnd)); } catch (BadLocationException e) { * OcamlPlugin.logError("offset error", e); return null; } - * + * * int startOffset = firstLineOffset + getColumn(defPosStart); int endOffset = lastLineOffset + * getColumn(defPosEnd); - * + * * return new Region(startOffset, endOffset - startOffset + 1); } */ } diff --git a/Ocaml/src/ocaml/parser/OcamlParser.g b/Ocaml/src/ocaml/parser/OcamlParser.g index fa3a102..a08b9be 100644 --- a/Ocaml/src/ocaml/parser/OcamlParser.g +++ b/Ocaml/src/ocaml/parser/OcamlParser.g @@ -4,6 +4,7 @@ %package "ocaml.parser"; %import "java.util.ArrayList"; +%import "org.eclipse.jface.text.Region"; %embed {: public ErrorReporting errorReporting; @@ -16,12 +17,29 @@ we use the "bTop" boolean to know if this definition should be added to the outline */ public ArrayList recoverDefs = new ArrayList(); + public ArrayList recoverIdents = new ArrayList(); + /** backup a node, so as to be able to later recover from a parsing error */ - private void backup(Def def){ + private void backupDef(Def def){ recoverDefs.add(def); for(Def child: def.children) //child.bTop = false; unsetTop(child); + + // remove all identifiers that is used to build this def + Region region = def.getFullRegion(); + ArrayList usedIdents = new ArrayList(); + for (Def ident: recoverIdents) + if (ident.posStart >= region.getOffset() + && (ident.posEnd <= region.getOffset() + region.getLength())) + usedIdents.add(ident); + recoverIdents.removeAll(usedIdents); + } + + // backup identifiers for later recovering from a parsing error, + // some will be removed when they are used to build a Def sucessfully + private void backupIdent(Def def) { + recoverIdents.add(def); } private void unsetTop(Def def){ @@ -285,7 +303,7 @@ module_expr= Def def = new Def("", Def.Type.Struct, s.getStart(), s.getEnd()); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} | STRUCT.a structure.s error @@ -293,7 +311,7 @@ module_expr= Def def = new Def("", Def.Type.Struct, a.getStart(), a.getEnd()); def.add(s); def.collapse(); - backup(def); + backupDef(def); return def; :} | FUNCTOR LPAREN UIDENT.i COLON module_type.a RPAREN MINUSGREATER module_expr.b @@ -302,7 +320,7 @@ module_expr= def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} | module_expr.a LPAREN module_expr.b RPAREN @@ -341,6 +359,10 @@ structure_tail= {: return Def.root(a,b); :} | structure_item.a structure_tail.b {: return Def.root(a,b); :} + | SEMISEMI cppo_directive.a structure_tail.b + {: return Def.root(a,b); :} + | cppo_directive.a structure_tail.b + {: return Def.root(a,b); :} | error {: return new Def(); :} ; @@ -366,7 +388,7 @@ structure_item= def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} | TYPE type_declarations.t @@ -376,7 +398,7 @@ structure_item= Def def = new Def((String)id.value, Def.Type.Exception, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | EXCEPTION UIDENT.id EQUAL constr_longident.a @@ -384,15 +406,19 @@ structure_item= Def def = new Def((String)id.value, Def.Type.Exception, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | MODULE UIDENT.id module_binding.a {: - Def def = new Def((String)id.value, Def.Type.Module, id.getStart(), id.getEnd()); + Def.Type type = Def.Type.Module; + assert a instanceof Def; + Def.Type aType = ((Def)a).type; + type = (aType == Def.Type.Identifier) ? Def.Type.ModuleAlias : type; + Def def = new Def((String)id.value, type, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | MODULE REC module_rec_bindings.a @@ -403,14 +429,14 @@ structure_item= Def def = new Def(ident.name, Def.Type.ModuleType, ident.posStart, ident.posEnd); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | OPEN mod_longident.id {: Def ident = (Def)id; Def def = new Def(ident.name, Def.Type.Open, ident.posStart, ident.posEnd); - backup(def); + backupDef(def); return def; :} | CLASS class_declarations.a @@ -422,7 +448,7 @@ structure_item= Def ident = (Def)id; if(ident.type == Def.Type.Identifier){ Def def = new Def(ident.name, Def.Type.Include, ident.posStart, ident.posEnd); - backup(def); + backupDef(def); return def; } return new Def(); @@ -456,7 +482,7 @@ module_rec_binding= def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -471,7 +497,7 @@ module_type= Def def = new Def("", Def.Type.Sig, s.getStart(), s.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | SIG signature error @@ -483,7 +509,7 @@ module_type= def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} | module_type.a WITH with_constraints.b @@ -514,7 +540,7 @@ signature_item= // add the start position of the definition def.defPosStart = v.getStart(); - backup(def); + backupDef(def); return def; :} | EXTERNAL.e val_ident.id COLON core_type.a EQUAL primitive_declaration.b @@ -525,7 +551,7 @@ signature_item= def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} | TYPE.t type_declarations.a @@ -542,7 +568,7 @@ signature_item= def.defPosStart = e.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | MODULE.m UIDENT.id module_declaration.a @@ -551,7 +577,7 @@ signature_item= def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | MODULE.m REC module_rec_declarations.a @@ -567,7 +593,7 @@ signature_item= Def ident = (Def)id; Def def = new Def(ident.name, Def.Type.ModuleType, ident.posStart, ident.posEnd); def.defPosStart = m.getStart(); - backup(def); + backupDef(def); return def; :} | MODULE.m TYPE ident.id EQUAL module_type.a @@ -577,7 +603,7 @@ signature_item= def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | OPEN.o mod_longident.id @@ -585,7 +611,7 @@ signature_item= Def ident = (Def)id; Def def = new Def(ident.name, Def.Type.Open, ident.posStart, ident.posEnd); def.defPosStart = o.getStart(); - backup(def); + backupDef(def); return def; :} | INCLUDE.i module_type.id @@ -594,7 +620,7 @@ signature_item= if(ident.type == Def.Type.Identifier){ Def def = new Def(ident.name, Def.Type.Include, ident.posStart, ident.posEnd); def.defPosStart = i.getStart(); - backup(def); + backupDef(def); return def; } return new Def(); @@ -642,7 +668,7 @@ module_rec_declaration= Def def = new Def((String)id.value, Def.Type.Module, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -666,7 +692,7 @@ class_declaration= def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -718,7 +744,7 @@ class_expr= in.collapse(); last.children.add(in); last.collapse(); - backup(last); + backupDef(last); return a; } @@ -735,7 +761,7 @@ class_simple_expr= Def def = new Def("", Def.Type.Object, o.getStart(), o.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} @@ -773,7 +799,7 @@ class_fields= if(ident.type == Def.Type.Identifier){ Def def = new Def(ident.name, Def.Type.Val, ident.posStart, ident.posEnd); def.defPosStart = v.getStart(); - backup(def); + backupDef(def); return Def.root(a, def); } return Def.root(a,id); @@ -784,7 +810,7 @@ class_fields= if(ident.type == Def.Type.Identifier){ Def def = new Def(ident.name, Def.Type.Val, ident.posStart, ident.posEnd); def.defPosStart = v.getStart(); - backup(def); + backupDef(def); return Def.root(a, def); } return Def.root(a,id); @@ -798,7 +824,7 @@ class_fields= Def def = new Def("", Def.Type.Constraint, c.getStart(), c.getEnd()); def.add(b); def.collapse(); - backup(def); + backupDef(def); return Def.root(a, def); :} | class_fields.a INITIALIZER.i seq_expr.b @@ -807,7 +833,7 @@ class_fields= def.defPosStart = i.getStart(); def.add(b); def.collapse(); - backup(def); + backupDef(def); return Def.root(a, def); :} ; @@ -830,7 +856,7 @@ virtual_value= def.add(a); def.collapse(); def.bAlt = true; - backup(def); + backupDef(def); return def; :} | VIRTUAL.v mutable_flag.m label.id COLON core_type.a @@ -842,7 +868,7 @@ virtual_value= def.add(a); def.collapse(); def.bAlt = ((Def)m).bAlt; - backup(def); + backupDef(def); return def; :} ; @@ -858,7 +884,7 @@ value= def.add(a); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)m).bAlt; - backup(def); + backupDef(def); return def; :} | override_flag.o mutable_flag.m label.id type_constraint.a EQUAL seq_expr.b @@ -873,7 +899,7 @@ value= def.add(b); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)m).bAlt; - backup(def); + backupDef(def); return def; :} ; @@ -887,7 +913,7 @@ virtual_method= def.add(a); def.collapse(); def.bAlt = true; - backup(def); + backupDef(def); return def; :} | METHOD.m override_flag.o VIRTUAL private_flag.p label.id COLON poly_type.a @@ -899,7 +925,7 @@ virtual_method= def.add(a); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)p).bAlt; - backup(def); + backupDef(def); return def; :} ; @@ -913,7 +939,7 @@ concrete_method = def.add(a); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)p).bAlt; - backup(def); + backupDef(def); return def; :} | METHOD.m override_flag.o private_flag.p label.id COLON poly_type.a EQUAL seq_expr.b @@ -926,7 +952,7 @@ concrete_method = def.add(b); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)p).bAlt; - backup(def); + backupDef(def); return def; :} ; @@ -956,7 +982,7 @@ class_signature= Def def = new Def("", Def.Type.Object, o.getStart(), o.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | OBJECT class_sig_body error @@ -999,7 +1025,7 @@ value_type= def.add(a); def.collapse(); def.bAlt = ((Def)m).bAlt; - backup(def); + backupDef(def); return def; :} | MUTABLE virtual_flag label.id COLON core_type.a @@ -1010,7 +1036,7 @@ value_type= def.add(a); def.collapse(); def.bAlt = true; - backup(def); + backupDef(def); return def; :} | label.id COLON core_type.a @@ -1020,7 +1046,7 @@ value_type= Def def = new Def(ident.name, Def.Type.Val, ident.posStart, ident.posEnd); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -1033,7 +1059,7 @@ method_type= def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -1046,7 +1072,7 @@ virtual_method_type= def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | METHOD.m VIRTUAL private_flag label.id COLON poly_type.a @@ -1057,7 +1083,7 @@ virtual_method_type= def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -1082,7 +1108,7 @@ class_description= Def def = new Def((String)id.value, Def.Type.Class, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -1103,7 +1129,7 @@ class_type_declaration= Def def = new Def((String)id.value, Def.Type.ClassType, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -1208,7 +1234,7 @@ expr= in.collapse(); last.children.add(in); last.collapse(); - backup(last); + backupDef(last); return a; } @@ -1216,11 +1242,11 @@ expr= :} | LET MODULE UIDENT.id module_binding.a IN seq_expr.b {: - Def def = new Def((String)id.value, Def.Type.Module, id.getStart(), id.getEnd()); + Def def = new Def((String)id.value, Def.Type.ModuleAlias, id.getStart(), id.getEnd()); def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} | LET OPEN mod_longident.id IN seq_expr.a @@ -1232,7 +1258,7 @@ expr= in.collapse(); def.children.add(in); def.collapse(); - backup(def); + backupDef(def); return def; :} | FUNCTION opt_bar.a match_cases.b @@ -1372,7 +1398,7 @@ expr= Def def = new Def("", Def.Type.Object, o.getStart(), o.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} | OBJECT class_structure error @@ -1495,7 +1521,7 @@ let_binding= Def def = new Def(ident.name, Def.Type.Let, ident.posStart, ident.posEnd); def.add(f); def.collapse(); - backup(def); + backupDef(def); return def; :} | val_ident.i COLON typevar_list DOT core_type EQUAL seq_expr.b @@ -1504,7 +1530,7 @@ let_binding= Def def = new Def(ident.name, Def.Type.Let, ident.posStart, ident.posEnd); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; :} | pattern.p EQUAL seq_expr.b @@ -1519,6 +1545,12 @@ let_binding= Def root = new Def(); + // update root position + int identsSize = idents.size(); + if (identsSize > 1) + root.posStart = idents.get(0).posStart; + root.posEnd = idents.get(identsSize - 1).posEnd; + Def last = null; for(int i = 0; i < idents.size(); i++){ Def ident = idents.get(i); @@ -1534,7 +1566,8 @@ let_binding= if(last != null){ last.add(b); last.collapse(); - backup(root); + backupDef(root); + return root; } @@ -1559,6 +1592,12 @@ strict_binding= Def root = new Def(); + // update root position + int identsSize = idents.size(); + if (identsSize > 1) + root.posStart = idents.get(0).posStart; + root.posEnd = idents.get(identsSize - 1).posEnd; + Def last = null; boolean bFirst = true; for(int i = 0; i < idents.size(); i++){ @@ -1579,7 +1618,7 @@ strict_binding= if(last != null){ last.add(b); last.collapse(); - backup(root); + backupDef(root); return root; } @@ -1893,7 +1932,7 @@ type_declaration= Def def = new Def((String)id.value, Def.Type.Type, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; :} ; @@ -2233,13 +2272,25 @@ signed_constant= ident= UIDENT.id /*{ $1 }*/ - {: return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); :} + {: + Def def = new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + backupIdent(def); + return def; + :} | LIDENT.id /*{ $1 }*/ - {: return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); :} + {: + Def def = new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + backupIdent(def); + return def; + :} ; val_ident= LIDENT.id /*{ $1 }*/ - {: return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); :} + {: + Def def = new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + backupIdent(def); + return def; + :} | LPAREN operator.o RPAREN /*{ $2 }*/ {: Def op = (Def)o; @@ -2419,6 +2470,21 @@ toplevel_directive= {: return new Def(); :} ; +/* CPPO directives: http://mjambon.com/cppo.html*/ +// This is temporarily. Should support more CPPO's syntax. +cppo_directive= + SHARP ident + {: return new Def(); :} + | SHARP INCLUDE STRING + {: return new Def(); :} + | SHARP ident STRING + {: return new Def(); :} +// | SHARP ident ident STRING +// {: return new Def(); :} + | SHARP ident ident seq_expr + {: return new Def(); :} +; + /* Miscellaneous */ name_tag= diff --git a/Ocaml/src/ocaml/parser/OcamlParser.java b/Ocaml/src/ocaml/parser/OcamlParser.java index 0887530..c8d005e 100644 --- a/Ocaml/src/ocaml/parser/OcamlParser.java +++ b/Ocaml/src/ocaml/parser/OcamlParser.java @@ -1,7 +1,8 @@ package ocaml.parser; -import java.util.ArrayList; +import org.eclipse.jface.text.Region; import beaver.*; +import java.util.ArrayList; /** * This class is a LALR parser generated by @@ -12,22 +13,22 @@ public class OcamlParser extends Parser { static public class Terminals { static public final short EOF = 0; static public final short LIDENT = 1; - static public final short UIDENT = 2; - static public final short SHARP = 3; + static public final short SHARP = 2; + static public final short UIDENT = 3; static public final short LPAREN = 4; static public final short LET = 5; static public final short END = 6; static public final short LBRACKET = 7; - static public final short RPAREN = 8; - static public final short MODULE = 9; + static public final short MODULE = 8; + static public final short RPAREN = 9; static public final short TYPE = 10; static public final short OPEN = 11; - static public final short EXTERNAL = 12; - static public final short EXCEPTION = 13; - static public final short CLASS = 14; - static public final short INCLUDE = 15; - static public final short EQUAL = 16; - static public final short SEMISEMI = 17; + static public final short INCLUDE = 12; + static public final short EXTERNAL = 13; + static public final short EXCEPTION = 14; + static public final short CLASS = 15; + static public final short SEMISEMI = 16; + static public final short EQUAL = 17; static public final short MINUS = 18; static public final short PLUS = 19; static public final short VAL = 20; @@ -36,12 +37,12 @@ static public class Terminals { static public final short FALSE = 23; static public final short TRUE = 24; static public final short LBRACE = 25; - static public final short INT = 26; - static public final short FLOAT = 27; - static public final short INT32 = 28; - static public final short INT64 = 29; - static public final short NATIVEINT = 30; - static public final short STRING = 31; + static public final short STRING = 26; + static public final short INT = 27; + static public final short FLOAT = 28; + static public final short INT32 = 29; + static public final short INT64 = 30; + static public final short NATIVEINT = 31; static public final short CHAR = 32; static public final short LBRACKETBAR = 33; static public final short BAR = 34; @@ -68,8 +69,8 @@ static public class Terminals { static public final short BANG = 55; static public final short BARRBRACKET = 56; static public final short STAR = 57; - static public final short UNDERSCORE = 58; - static public final short PREFIXOP = 59; + static public final short PREFIXOP = 58; + static public final short UNDERSCORE = 59; static public final short BEGIN = 60; static public final short LBRACELESS = 61; static public final short NEW = 62; @@ -90,10 +91,10 @@ static public class Terminals { static public final short DO = 77; static public final short DONE = 78; static public final short THEN = 79; - static public final short TO = 80; - static public final short DOWNTO = 81; - static public final short ELSE = 82; - static public final short LAZY = 83; + static public final short LAZY = 80; + static public final short TO = 81; + static public final short DOWNTO = 82; + static public final short ELSE = 83; static public final short OBJECT = 84; static public final short DOT = 85; static public final short FUN = 86; @@ -122,22 +123,22 @@ static public class Terminals { static public final String[] NAMES = { "EOF", "LIDENT", - "UIDENT", "SHARP", + "UIDENT", "LPAREN", "LET", "END", "LBRACKET", - "RPAREN", "MODULE", + "RPAREN", "TYPE", "OPEN", + "INCLUDE", "EXTERNAL", "EXCEPTION", "CLASS", - "INCLUDE", - "EQUAL", "SEMISEMI", + "EQUAL", "MINUS", "PLUS", "VAL", @@ -146,12 +147,12 @@ static public class Terminals { "FALSE", "TRUE", "LBRACE", + "STRING", "INT", "FLOAT", "INT32", "INT64", "NATIVEINT", - "STRING", "CHAR", "LBRACKETBAR", "BAR", @@ -178,8 +179,8 @@ static public class Terminals { "BANG", "BARRBRACKET", "STAR", - "UNDERSCORE", "PREFIXOP", + "UNDERSCORE", "BEGIN", "LBRACELESS", "NEW", @@ -200,10 +201,10 @@ static public class Terminals { "DO", "DONE", "THEN", + "LAZY", "TO", "DOWNTO", "ELSE", - "LAZY", "OBJECT", "DOT", "FUN", @@ -237,501 +238,507 @@ static public class AltGoals { } static final ParsingTables PARSING_TABLES = new ParsingTables( - "U9piVGUS54NsVtNt26j614GbRa8HYRBWWYuW1XGHYMPG512H922YWdZeOGvWEi#SSpenufc" + - "pdbdlr3FdVEVfUJfT$#zxLTLTtTCzExF0hllxxxnFLtplrRTUlQgkxkdf4UB4Tdxtna5YFx" + - "#xSnNYyTcltLFT7kxVtExkjjcl$UvkDtVhxAVWsRPnaEZjR#lrH3nEZ0vxubpXRukUJ12eo" + - "VwdSP1SXKFALJQ9QyMWx7$4TKZjXDe3tHT5DS9Zd5a8Lye3SybzrdsUOj7RkTUvpptNUSfv" + - "nddMUSvvtddQVSczF8V$1VUvU9a$n1cBcbMKTaQx3xeJtKVSl$f3ajhpznUnSlTIzpfdB#S" + - "3SP8xoptCFSBvtldPcUSkyzTf72HzVvtGayGducruqYdYBTGrQnmaSEJqu1pnA#esQ1paRE" + - "9lOArBtsVsHGyk4#kYRlt6GM8zV$sm1vczlI4q1juEgDkeSL2cnDyeCWQjq8E71DLjs3X8R" + - "EnlQ8t1Uju5wC4RthcewzOOo1adslZTnC1CSy$FjFN#cn6PBJBzHLVv7zHkqnX8x2SsyxUn" + - "rg9DH0kCmRjYSzGEQWma#efgVv3LWt5Y7vu7xL6xOsCWCL2K#Ziw3pghd8USlpeFYxt5rg9" + - "Sj1ARedQ7na3emRR#3iwZpcFEuyuJpfD13zgYTc1Z8FIWDy81OgWOHdCWwC4Mg1tG60Wzw8" + - "NmMj5V7EoUBYO4FMY7skh6GEX17x$Qkmyzg7PFTuS7FUZWLsSRu2E#BbfY4t5XDkkESeUAx" + - "T6BViuWyOCpJ7o6gj$gdqHLqH83dVxPt$pZd9x#SQ8RvWAFWEUYR71Z8B6Zg46yNlrJPjEY" + - "PQxozz7XLVvLcVN5G8f34hjHdHZCkVNyTUkVOCjYPQxsn#lmQlzgFZDVRPFOW#h4TfnRr$#" + - "HoEsguleXiLVH4Zt466UQtBZ#ILnTj0JEN8Wtg7$oTovMWh5k8DUlV$9tAbQ2F1bolzG$YV" + - "sBbi0voFz5Rbx$92OMBV47iHHns$edzvLY9SJ9mDfMRbR$90uhMc8xzr74RUgVn9nY9J8xY" + - "RCHjwv$oWmfLW9pwtp4hUgVnD55Iz3wsagsg7yI9nGjyG$njcpX$xV#IVonM8dif#9Bn3yt" + - "01rOjCGVGJ$BJUkVn1#BbV1Fzaz6l4dzaxzVqHBB$6M8MzO$YMN5If2$ofR#nlLFufIYPSx" + - "pptDFanlLFudJYvNmL$Wh46zO$oHw5olXD7FMaHlwilv9z2fQ0kSjNyfczK$YWc8bd2xEve" + - "ZNgNyIbnOhmLZNaPdw9t5biH9E6QwtCjAhV$A75YlXL8h#Y9tw9t5zqH83n534elv9t52i1" + - "Fk0y1lYqxLOWUodpZKKDG1jNQm4iBw4#BS6eAsAbU1x6R$vlpO0TIbMWh7#sY3VG#zcKju$" + - "2fEGnplR#jsSeP3S3UbTvF6vX3t3#XJxW$rDwfySjrW9xs7l4SGr3K2LnKhGseRuVmr05SL" + - "AP3zr$uJuNqHkLnNN4vKNA#5UxzxaJFE$8mBMx#gHoegLy4xrJdEcIRV#oIyjLeBlVxj#Ym" + - "QWpiLAk5#9uNuBkLxzaz#fM0cswtfotVedlsEn4kvtxas8I#gV$0x5IdYRYk68czS$#UsBb" + - "V1QOq$Ul26#NtJ61gdH1SeSv#yBxWd#lcA2FCuP9O$B9NzVlnt5tcSDyJqa#cHIemkKELPC" + - "1$UjuamnI1xhZ977vf8uA$ifnTxN3RAk30lMYnqAb5deRmcvuVumo2xCVYiNvX9gjw3O#w5" + - "1vlIPGMhp0cMEaU$94l6zVoPaANrCBl6U5R7taznTN2kgtQvkJxcxtDrTIM4QfJw9dqV6aF" + - "iFzns4goYTsSOyYGzFIk9zqtqzMkAr5JNU9$v$wf$4USLAoCt8ed8pM7GpX2lpVl#OPj62l" + - "y64HH7wRIsB5YJdjVCwqZUVZBKDiBP1k3BlDvPfM0l#1XDO4NgRMLWBalEsy$hADlw$wv#y" + - "FOgM#Q41QBEY9RwjVn9$BLhc#$edyN3HCZ$LFub7YvMGmtYc3yDC7uPm9OLfb3hJyyWOudL" + - "#66OwwNdSpFJirucyjCv7IloIDK$EKFSQYjrnyHhvhegpdphZaDxJBud#Fi4$m1dfZc3Ev$" + - "mzlPxoEMUeV4u#9nxp3w0u97yyIgyIKy7RVCsJynjQG2oguZL0pR6OJZqGH$ZDeprm$kUCb" + - "3iIXzjLx2vtb3jclwGmZRnAwCArbhUD#r$tO#SwzmlnXFE6roQVZ27$1ly6kQDuZjBEOkSj" + - "RmjlhhF4AqtYTOuNlMDbEuZddMbkL#TOkGFIvr2OHjal$RFSRxDVkkyHLl42ONL$TB$89sF" + - "8Fyi$2$e7KjfPxFudqq6yx2mHNPDuWVADM5bxKQLHjfVjdLSeJ2F6zYPZ#zRzmdtFlyc$IH" + - "oQwPTF9f0TAF#9y5fENoV$oSyNNvFPCeaNUpaHAsi7Vm1ASOniX$Ip5AQH#wtuJTdHsO2mU" + - "jCmvl$p3iadOqWC54zHI6cditX7eHIx9V9MYgzZPGTbzd2coOEy8#H1yY3tpnJQvBR1qSBT" + - "WDB#Sd#vqn5OVm3MB7Al#wyxcueF0jvAUP1pAEADt9QSRwlBXRi5K7xjTXAx8jUAzEXdjPi" + - "XN#wwRiPjvfQuwxdjt0vkgVYd#3o6um1nFAwH3n1VoGCGhg0mZTYAvMH5iTpzmkdXj1B3dN" + - "F55$ba3F6tE0U8goZjtqPZwjtft#RTaSXxlBD5h6mt$qt$JOItoTtaRjbFA4mZUEEJQiJT2" + - "ndhT8puD#BoV3A6OCjgkLkc6QKpwsG$rRPSFucNpY6nifsz1M8TkJFyUcU4rr6OHc8WNU#x" + - "tsPckE#vV$FAkAMjCaSu2$99QTbCffVS6LTpI3kBlVdUqU8gvspnRH8lR5aUBV4$v3kv7ph" + - "7#X$w7sQgA4obbxmjiz$mhs6s4MCTpt$9UJdJtMkJLqOJ$G85uNMS6#Tal2tySMx$JDz4tk" + - "$zSR6oVufzdQ7#F$qo7FyKAoXC8#ltHikTo#6N$RpXeiOTb4$648q2z0$aT1b6t8SjRtKkJ" + - "Mm7NXijaKD5bP1ogDzP3aNwMGhJAFnTbxD1zXDdDt6jqznz65wIHyQGjwM7LfonbCRPlCGP" + - "xLw3LNgdn7PelOoK#1#8VM713p83$0#GVfR2DCBClW0M70XypuWgRm9eJs#STsG#6KFyRSO" + - "7$ZcKTl$dVktix4ppDtRw9FAkvwmRAtlVUmaetuTtlU#$d$s4mZGIow6tXrFZl2ZVTllGao" + - "9UAwUrV3kVJ23RJFuTyTyuTpRIvthtkDlfV8mOPRJiFUSUe7mla$7Vyz#ZL3e1vK5E3tSt#" + - "PPOZj7kuUw5qNuh#sq#6KEPm$mN$FUy4oZjT7Ssyi$rNn0dEXidyRfLJfjOsRjEIs1xrntW" + - "l#k$Y$t4k#aabcTw0Tlex5UPJPpTCjsSZBClqfFpoGIotsVsGFmYfPtMeYfJvSrrQrG#Jiv" + - "HtYlH4Zd4sJGpJ0xndfT3v13t6mhJo3l9Un7ddjkoNpgx0MK7zouQzUotM2$pI2dodtVQeg" + - "rsb7OwO9VvlBk7kwUpPH8lZNXC#YEd8jFU$mZs$CZ$oFs6mZHoTd3ACOC#SdfuVyliu$Lox" + - "tBs5TKOyJmoXhnZdAtGob1APqO1vRbEQ#S8SLKIh$kPKnujaOEThautEHXdyC5oC6mvE9tS" + - "OUv8eFmSA5yNGvtTWF9QiYPicKTAaVXUz8U6bodjzCBgTnLGjlPUIEBrAjmniR91s47qHRX" + - "23fA3W79GEk6yTHLG$kBqoBJ0Y7S5ojREzavrFXb3M5y7e9M1h6V7x7VPRzoBlPUn2qvgPx" + - "3tIgoinjaL26lWbpMoXbBf99R3BtjaDYEiyCmUcH7Ea4nNPmzJx$XvfFUM8pWalk5ORVUJ8" + - "p8j4IRmUZjw2wCb$ZlEUETW$ntuvJl#E$3BTwBaji61$IMblGFa7fZdPS0t7YXdk7V9FPoP" + - "pkmS6UmlEMwhyzXVodyuyzrEyYhaMib$0ENuJDVCziv2he$jBxq3l3UY6cL$vpZd3DaVLkm" + - "l#sF4##SIxu8HE#MPlO2o2r0Uu9pfpU0HlzBvKmu$xOBjl93z$UkTgw7X9kHQEJSxjsI$yp" + - "w5z9q13wDKwSm2Z7XKPrLceNENhCA8Lo4zby8uCKggxOKH$ulSo$cRywP$7Jpj7yxRpXToh" + - "nn#Gcdd1VGVw7mfgvnlaMlb$2lJq$ctyvFp2tR5YaFRKkM0SdbCPz$CGdSRsJVxlUoBzD4K" + - "nebHKjpN7UBkxExYxkhkxevtztR7keUu1xYJSlW9fPqNEAQuHoASYQELEzkTuyvrvxl7kWi" + - "qXq79kSm2zxYOpks0ycIv7L1kX$Gn5AQH#9TthtkcUvQxmZtFlSZ$XtkbUvLxjNj3FXb3xe" + - "tkpGXlnT7AlTszqxtNlS#ztttCuY2Kd0BAnsFoVO3o2Td7VKhsGVfO2jD8$CjzsdtL$Rlx5" + - "ewttK$S7zpllH5kDf#C8VTdzpVPnnEKzXpFyvfx6tWRU#qZFEkf62FU8IRVExFGwoHxUrra" + - "RwIFfp2Dn5NULjxMNZV4sthTlTxUzaXLUmFooLYoDMXb4AMzdP0Rwkti3VCcsZn0oJ5GJeZ" + - "9zmBAVMGlRr$P2#d55ARIIEzmxr3lC6yMTfOplKLewrZlECo0V3AQlCNUYGZ$87kvhRoJ8V" + - "b7xnnlcVVda8D7d5EeNH6Jx#cTvrqeUwAjdaXVH64QUN#2$2NU5TuDtYtUhTxT$j#zUxt7l" + - "IVooGIoJtlF87nLzWJAPxtNl3T5jVTtxxsGWr4gtdzw7yVaUtXVEJCHlYTx8Fo5mZJollV#" + - "v$qc7lUo6IVZEYyuxsJMpMoKsIYVZA7CXfcD4RQMFTnMcJQYEhDvfcEcKwOov62KAdrbfdT" + - "CldjckqmVX3l8xWY7KfX6cPqpksI6PqPczioC1Ot9ZCli9xEPYVba0lflvX24FylkG7ce$4" + - "d#c9cQcUdT6t8mIfN#JVux9hsj$9Vy7k4tEBQLNtEOHj$9R#MlcINoVoBooIkZIV4ftZHPe" + - "BHu8zIDoxhHOS8uyQhUJN4cVNBuQLMtyy9knMsLAnkiwjrCEp6Tst3PDdIOC4wCSXl5cOWo" + - "payexRomMucXL1m6vJQcdPZEhbpMbGuJnebHTbMSYIZZ$8JIpWkxbHXAnM5GTZNjn7HkpML" + - "Rqs52czmsE0Zbreep4MLSXb1It5RdwSuWFcuduesXfFhudS5SdLjnsLPqcD0ceDoAKMwbE1" + - "DHncK89SLjTTv6kLKC9TKdeOpgxC9bNUWmeKr0sOLHTb6SYIZZCeIIuhOwRwFi4aD9zG5Ap" + - "fKcwApaiaewJ6WJK5Oooah5cOWoBaCeAMwhypRAoXXAgWzHKguqGMS5brNGOKARWBA2KLOe" + - "paIKXhTInuIIuhOwRwEiYA6iIBXZBU8u$BUfZ4B$RHFQXEkUj$cwvst5cVJ9aQ7h7ehRwho" + - "54hbMSTaab56DSW0Z7q272Ms2BGUmBGSepaHR6jvA7PCjAMwhyxOj1yHiEI35bZQ6m#L0BX" + - "j8Xmbj0ig1Z7AWuan4QNWhTKmeAMwhypRAWJ6K0rDGHd5KSrar7IPCerIKUMHisR2L$B89v" + - "TjpsVPqc32DKb7caR5bmrRoooQKz#EoVdIOC8rIKUQHiMN3LlBB9fINSrav7IPCerIKUMHi" + - "sR2L$B89vMLSLaQ72TCe5MKU6LisR2M$R49v1oxhG8S9RS8Sxy1pl8FYJ4HfU2jrJ7ESuhO" + - "wRy$n3h4vtY5bZaTnRCbbMz9XmZHAHPb7nfODMyalcr3ElQHGRc72D4f5cKV6bWrRoI#RKB" + - "uJb#r4XmdJA1Lb7XbRDcmblsn2#QvSjYiT9aoZL9HvP6pPi9NyiWdbkt3PBdIOC8rIKUQHi" + - "MN3LlBB9fIh6LLAXmbjmXmlvJbUgZWJKHhUIXtJ7AUuhSxRSxmqDiTBK#Pu54TdBkjCXmbj" + - "0ihEZBApuan4QNWhTKmeAMwhypRApZ6KdLDGHd5quZAIxsH2cu2o4wFif3WJKHhUIXqJIeh" + - "RwhoDibCCPQTSb9cTij$6S7HatevqcD0ceEp8A3igJhGLlY7u4#IwEOS7l9Kw9fGKjzLveC" + - "pixcpDA3l6K7PCiMKKnOi2EoLw2tfcaBlIUSVTqVsdUxVudZYptukLsU#zXxm77RgIJtacJ" + - "t4I2U5iwqpnLdb$PG3tP5cBkr3So$a7l0VGrjtkSFTi$KmUrQyIDucRnItYLd6Rk4$SBnwq" + - "tWyhb1NeBUZG$G5oaRUWC$Q1X1qrZ1q2vasKdSLA8GWxolwL3xi$LipYK8Y18NQsmjvY9c5" + - "77M6V2#n33NRW6PQBtTZU$Gj7buWfQTWBVZC78SnR7wQTUvm$E#Sv5pltKwctgx#ndCFbzA" + - "t$nivqulRUyOvoBa1gXPp3JurC4iS2smTYij94DlNUvxVYpt5NWc#viwrO8dh3R#P0OgL$F" + - "lk3WveKczBtis8KR4f#DJomQJLiEboCD3PL$k3k8#uMYqERkk#dsdI4ZeyKCzYcys7Jqw8s" + - "bUyQRyuC98$mpuszxLau8#cT$gmdZqVeCHoAepUzqv$6sXsQ$Jhxeo9d6ANTLTvJiETRmRF" + - "aD0zG2wagmnad5rUInYFagYXwM7XLvFyAM1#L2YzpO6QMl8oVdxtCxIalGxYIGfkodzEH$P" + - "7IQRtpUYhExEVYK$zyZELens5##fohOdf#5Y7Qfv4qlIEfX9b9pyzUmhWk0QvB4Awaq2Rqu" + - "19UToYTvZEzgTPf8PvqjXCFEHjcQfmg9OjFYRp4FpV4vKp5p1G1haliTJE2w#By14GNCwvQ" + - "U1IN#ZYBLOcpnB$Hlp6Kfv1mESU7ijalirzY17Ne71kqzQVy1Au$CMyjFF9FuNptvgeIyPv" + - "$ldWVDOxE8wJvRclZKVr0V2G#PWzZT5npKNw2Zel4XnIcK$PhnScQlwOZiwqfeJeXChi5kW" + - "RwvtfZBFrcvTv0l1ISmwZcmlm4hWkPjnOU2kqLKfKeIR52$CtmUJt9Og6irnC#jLD6tK5TZ" + - "cE9Rkk2$0Ik2rXxBJmKXhZSmLIImUxA7ucQ5HGQNOpBalL7kWTcjl97MhYevlpy1Axp6LS#" + - "hjaKsjPozwUI3DqBdqto$jwKfr3xboMB$dn877pksXlyh4sUbv#Wupp6LGiFXP5nF4$9sVA" + - "S7kYiWBr2sS2$NBwVuLRhjbRa9t2jOBsryCWLDYfLmXOOGp65Yi#R0rGFMD8F#6DG$a24KC" + - "x$J$C0dSjmNiDUflXp6V2S0Zn$19xPt6C#b#63zTgvn7cDPgXpW$C7vm9tLVPhvnXdgLbLd" + - "GUSHqBDpcMsPkT2vtQIP8qubq4oPtSZtmdFn4YlTCwFeqTThMTY$rIstwbq#ASIUef3odZ#" + - "gJmxLsaqmPdOPtmK#b#Rj4sKzteIUZy1FM7FJ36xY5pBP#RLXjt$MjYVT#EMf$E8SmEE9S1" + - "UxRo7FN74ylJhX6JBg$D8k8l8iVmFKVIvbdU#hjtoyadsu2UTeV99#IJ$hz6JDXaETnLgXu" + - "QMTuRvNz5AJw7$bKdRHEKAlVzLyPQltMj8EpqZpdjFu$FXcUL0inCZx1JQNYCEulCKrHxWz" + - "KpTmwLONe$jQMfidNUmHxZPlrbKGsAuU0zN8#yx$tJUhNLiSLw6n53kuvtYBtoTSOyQS#Tq" + - "itCMjoEyspbVt8YpmcYaiTucxfmr9fOcJCkTpv7SHE1CvuwYAoJ2v0nAd#dkK9$F5hIZ01A" + - "D2Pzx0k##btVy5YPh7So3YSuR2fDtin1gn9nF3APygmyuo8y$Tdfg104csYTgJ1z5xLGqfi" + - "TCzmh3XEk3Bx9VE1zpE2pxHSnEinZJf$3CoDZnrP187BlOo25SpfpluNW$GBHGp4YrajxXu" + - "JCjj1AGtPFzGivLLefx4se$zCgf3xc8p1jnl2hCOSG6aTVVezrAZIbLSHhPjNn#sf$FJrhU" + - "wF2xcJnQmVc9Kjv8PwbyrbyNQy#pM9UUHHgy58T4TOpWKKtqfdl4IfUpdzzDrIeEb5mKS2Q" + - "GfUTHbkjcj7DDDrKktqMy7ckZNy2X9lTChJKzeed#Km2n$jM6O5JL$YFkS2uL5cS2eJxCZM" + - "CyS$mvN3e7HpV5Gtbrg0$dveGM9mcjwM55dEUOBCuZ2ujJNfM6d4c4TI98EyFC2kFjfUITG" + - "Lo#ZxDOvvVmoBwdMWtd9jP6ZSB$goBE8tQELVjCtPk$gbBlcf0pYHIN8aUVaxthZRntNTW2" + - "7nervNY56UJqT0u8smGzf8ZpEWu$b5Ub8MSIAIwJflC5Icx1#U8X$vPGXz6dRA9pjzXpXiu" + - "Nh6ML8a9DCL3R8uXoLHjo9f7YCcdpmGXoZQfrvfXqqETLUWG3LAeKzA0YpdCSGVMWAGqvaq" + - "Xn1Pf2l#8Q#1NAtKyfhGxT$eDHlpAbe0SKSPxZY5yze4hXLm5d4YckK5FWLrm3lmfQuCFur" + - "GEXNtdNXcs2xbV4UHrRVdM$AGqvaqXncRJsgrlXL$VxjuOwZBx0h#vdBijMx5UavJv5x5U8" + - "dPuHMzr7XtyVR1Lm9f7YCcdBLbm3M#bobGziTPyQRMSGHlis9ONH9YttAc8P7LkskjUKXfn" + - "9fBX2JL5vemDhkyxhjVtUnBMTjDoZY6s5MErD7DwpEZsfNDM6d4cak4pQGdMFELIvoOUr2N" + - "EGjDojYFCSH#RWtQOqv4mYnHLgqcEubwfHjPaTJJf0TRV6T5w8IMjQgOZpY0qcvp$EKYfHf" + - "SoxCfqKLwWfQ66bhSEai$$3tkT$pj6Ko$xF9igpbkqLiOoEBQtRczAGCuaKboAxzwecrApp" + - "0$N#1Zbd9NflNQbeJVqLiOoEXRvIeHBndIeDEPD8oIgAeEfl3fJV6EGDglw9g4XBFqMCGSS" + - "MgdxUG5KQSYQHaWqr1RRc6ZcBofqxJDwkbRDordRIKgM8wbLirYivYqh0XLBdav0pYHIN8k" + - "TZ2rMLEIYasFbAfKnjWhUJbhwAE8yuvkrzLIdpzaqdnHLg2bheQ#i8yzp2ZvHAG4LQjbF4U" + - "SGnLDkfKkRTBfqKLwWfQ64xMqUOvnP#LQauBjRIHn7dEGxMgybOh$gOqf0pYHHNg2b0nJLo" + - "PjY2Ei9QEJF7hqXBRqLKh#B0hsPI2RXG2hyAE9D8SIcA#5LlS$YzlKaKUq$wlRE$O5twHTL" + - "aVx69ygobboBMeMDBQozJ6d8caU8ADKNbGyqgdVqlMl#locN$QnFbMKjFHIoZOqjhJrCQSY" + - "QHuWerHUL3pIgT$Hcj$wnosPzjeZnhwQ68PNHiQUrXIaFE959SeQQeVAXPfRC$eVMVL2xxa" + - "qsKPor$KSGoEhQq$iMKXfn9fBX2JL7vKBDAPwRGNaRbSkzhifQx5B6CZYsjTvdIa3E955Ue" + - "AIeVQbRf0DLTYQX8ovsAM4R7bjOxJMd8cKIAAzGKbGyrgtI0wiv4LAJb3aKiesDBwnscDEH" + - "C8iKLQehAXvfDNWoa#wJ#7UR91#kRZO74w#vGoDrrqaNFcQYFkKDDtmtpzyESvffLYYjuar" + - "9Gcqn2tuEh$QaDzr2wnylQmXt6HRLZL#s7dm2xkRUxY$hct7lANUMz5S7#exhdctPlDz1Oq" + - "1CdgfKYiV#OZ3suttUS#cQ0xExTJlTs2$rEHkbpNYWKktD#1FlwjMDNz$kS5tAms$Y9uuRS" + - "RsHGMW3#DEpP3xCVmjewzCkSkpN#uAFgL9n4Z61vU7OF#8tNql$1VkwE8Wry5tXG8Cl#xbr" + - "JcxyRT3aOFiX#u5rA8Me#y4j96psH0vrVa9pthQgZsXJwtFjtfA#6Fp9NwLep#u6wxWmb2v" + - "kh1bqEXe#p7uk178hintxd#5przbPrL9j2dwlx4FHTb#4p$e9HxYbsSOvtL$fTgKPZqPBgF" + - "aIwDvex1GOTHYpQyaVPZr2E42lOHtwdg3ToIyoXuYIAxr03VckroFv8ErGgTnOvImFPWjOP" + - "fp#tqjFW36djhZDaT$TBVaAgN7rxQgypWKWjTZTprHcKiCxm4uNkAdTbV1NWVE7VM#TWjxu" + - "JuU#jaJgXyE#jZTq9kzEpw3Mo0BlhRsaIxSxVCBKCrtVDKIZsGkoUZdtFrSVEz#Dke3LIOG" + - "U2#h7x8Mi0k$AP$lm4MSzwjFkyDOMzJZwpUdO$jU6n5xuNYs5$f15ZVwNnOdVQDsBidHenz" + - "ecD6FlV6ozsT$j6ZFsdnelTwzg8iVTOFUnytIIKvbpiWKWjlt38YtsjxD#z#stimVxzn73$" + - "$ll57hLxWFtaHenzMIF6VceZndvM8yP#JcF1dd2VuFfYxnFKUNtlquZFJRlL7NlstufKEWb" + - "xM9jCnM9dYH3xGRLZpqRkfFwEx3wr4VlCyOLWbszIDONoJVac$wRWJPjK7M5tzhMn2#5$IN" + - "aA$IzDsYPLnxyf#B9sxFm9iPzIEtR$I$awOt#T3lawOt$T9bN7Td$QnkwUwXxa$itTojqM2" + - "4vokpcJdKbErbtY$i52yAl2xlRAY$tw7Epy9f42VilnCcD$cGxvCcD$sIR3uQxAR922NSIm" + - "Hxqm7tOHmnwLh1txKupzAJhaKupzAPiCXxjAntN1ViPQmiwUGA5yMZxDs9#soN00UyHduCt" + - "Vi8z$GuT9swJgsD#$oOizz7VrI##TEJsvLd$$Hl8lC2cKBycN6FjBDgawzlTHCUpydHR2aV" + - "uN9cqJvPtMZFsB5EmZOjZdupYjKBlxNyWN6VkBTCWN6VkBDgawzlTsKUpH5KgbSrSelfUwR" + - "u5sByfddACahzuKoXla3Opz1fjK7VlC3L7iiEirg3sBGlyQ2bKS4jMntQz9nYxFYcANPycp" + - "JAeWVx#EUQ#ZGrx7sA#poN00#tKszcBcgdF8sh0xaF7Js1JAQ#MrZFrQcmm7i5zRP#o7hIN" + - "iFDOKoclaDOpz6fiC1x1VKsViHwubx5Spzglfa5SpzgjjCXp0VdMTiSzTIzZvEGWAvGlo1S" + - "R#Was60#jCZpfZVtyjOR#UiLzFXxoUiLzla#60tQ#lC$QrScu2CgwNppj3vVFoUSR#l4s68" + - "tvkih2Fh1NxTslZt0HaRp3sD#YGRp3sDsmo7F7zUr5s$s4jsVqrnluQ7V8rnlwQJOPZjUp#" + - "tuHdV#ZvZX7cAOyakzVs30gGlShONwL3lafb58TaEEBFe1HgT#OzM25CVWQ5mYIxr$OC2f2" + - "zmjXVeKE#GcKKXsGum3lArbIetPbtSkupAFmyquZmgQO4kzVsp1NzwfMEWUem$FohrxszpS" + - "EdAen#8rcBtUbNhvU8AOhVdPxzq6kP#yoLM10#rPHWzrgUkJ9zDC#0KbdkCw1AWxQxbYpOx" + - "iGx8$UPgpMnpaInqrnDnhuwwunxrDfPPuh0NkTrnfstTjPtpCLVh9RKkwCYRpNIDQj4IGhs" + - "rFi4z5OSndxqMjaJpDACUgugx5u$DLVjDwUugzpgPEpEGGgx#q1ihWPsJxstTCRgxMSKPhd" + - "SidliRK8UFOTpHRg$UwT7iNjdkxSeNk$CMh0dsDqxeqvs3tn6X6y6C7hkANAkHkpkZKh1Vj" + - "bgNQ#ctN#FV8BxxxU5zz#BMMUy$TVAjNPns5#j8$Ob3O$T$NSTiIzTEzSUuFaNvkhPwTXLN" + - "Rg$oxEZsENPHXl5ZFsiX7talx9eruH9s5MTYfCeZjsKvM8tvKQoKEp4wrrfS5hqG$O7bEam" + - "4ViFgfpY90hmdHdbZs0$KzM474GMzZDZsCyqsYWcNkzgWpEaDUCptCeVDN#Ipt1T7f$vOmp" + - "x7uqsYjbdRbnR$Xvy1iQmX#UeYrTlB#Ozr$3hZFEwzTtmKV8PjkqpT22yNiKXgRfYpwk5Or" + - "VjenNpQwGad#6wF3vpRindpZNQA6QxlxqsVKQUamVxERLWFoU6$HoZZMB6$kvQnNv67kndr" + - "8BzZ1ZsCumsYXbxslTyQmRxwNcmdruBzjDZs4ytsYXcx6dtbXfehig$CRg$oPDmKFfwYaDI" + - "TVddgZmfn2w7upY995ZlIN9uxNPt5djJ6D#IPEpgNINEjeHTtXZQNTv8ln6IDzgaE5HfOBs" + - "2rncdTN5spncdHBjp3M6$ryBExnsHzzgaE3XykdZiEItM0Nlksm8CTexDymJm8tcdyYF6Uw" + - "SARO8VtKdOvPq9RxykKIH46CQ9D9euwOEQJidyeMvv18NEjimj$16QIYYKHmHvYrWBnoHhV" + - "#GHh6s4fIV2R$AcB0mrNal6baXhF#VJtMXijEtF2TvufjvODYUNc5F7YUt7v49#a$Vdo6cA" + - "JtCVgMaEXN9QaBU8UJcMqsAZFesr7MdfYV2RF3GVhlWqzrHDHr8e3m$o5Z4lnoGRQVLmrZR" + - "LqXFXDtbedg7uDFTUcgPIA6S4UOkObsCv8zRg3DQsbwKdmc$oq7oaujFSitbSXw5sjZzR7a" + - "bXd9YNOtbahDKZMTjiLP$BR$BGF5tnQUxfccPJAAVx2SIy7ClfiLQdixRfbfu8lyb3yrJ5f" + - "xcdQ9fEePmQv2rYNexbr5YhKrdR54jFXD$aeNcAujFSipHDeL1E2V8MCI$7SagiLQLjbgKd" + - "mc$oq3nPyMdkcPfcKIWd1tcBc9TZaesqEfcrpRJqHFXD7fgFKdoQUuQccHJAeuAyHSpBCSb" + - "6MZsAjSsmz4JuJTwKcT0$GjCC2gsyHSohuwHFN2xaDtbJ5d1FqtG4XLRU8kRLSMAhCRcGt#" + - "HDMS1zkAPf55fvYvXNnucjnkH2VfCtPG7tP4s7KsZbBM9U7IUs6fCB#KtUb0NSXscQJA6Lj" + - "uXvTPpOQamkv3TvKnPmJz9q68LMtYBcrN5Ygp6vaD$aJLd0FK7J90gjl4NCg#F4LcDo8R$9" + - "cxA0#s1D4oYqyXOnhuuJMut9XVmcRye2xecQ3gRGobl4l3fER3Kc5$ARl2aBk0$HD952Asy" + - "Hy#euiTMONCXlygOiu3vKqo4KMdcBwDwIgjMVyDuIlmaWBgVAmbB5OON1CyN#eSuDrfjEFn" + - "7qZvuFYV$KzannxfjEeyyfsszFvVUWdc$U4O9StkUKpLjhdEKnZQjiVTbF$5NE#RMYfBUT3" + - "WpVVChFM8UsUyr#5og$OPNVEkBlGJaEzp1XdCGlgjnwQfjjXyz$bGxIOF6Bg3RLYcvhTr71" + - "8GxG7Xp6Y7brdEXtHZg7t#HD6OvTH1SESO1svp16pAlZnFQCT0w$oPio7Bkga5D8SnWZvjL" + - "nOdj6EeVVv4qPZcDKo2caEOmHy#euiJqZhRXRXln6tkZ0mRiK2lsZ46v8OPmKXtzKQdjQMd" + - "Et3FcDlDNAqPmwcWxGKHp6I76eEB4z8vt3R$9MA$CvDPyEqD4SnaXng3YnFIEjk5k6$4RUQ" + - "eMV0A3GdmUQps6C58UAhLP6AUAwKHPtov3Vo5kjyFlIAVJdWkPn6ATHgjQq8lviMjInaMRI" + - "xSqDIwrMU5NpRY99#Zs7AbUQ$57ULRM$Iyb$r3cG9HxDjJFz1nMLUsEzu7mSlal9VrJkgOX" + - "o9lQcUxDLFUNjsYHINEPZfqtEzuZFznI5APiK7sW1yov0Re49uyIy79D#9HiPzOYSAGjB5G" + - "U5Sdz5Z7N$k2ug2MkJYMh2ksYArvOtiaA$snBShpjBvNwAk7O$I#HwrheVbPhQPEAQeBM8Z" + - "Y1dT8HbSbz5AXsL0UshE6pEE75Dg3MgOryJX#LQspwAL3eg0zf7STYSSUAQK6jKnpuc3ikr" + - "jj6AL3eg0ngjE6pEE75Dg3MgOxI9mtAjRPGYbOxAW4Of3fipJbmJQetg66NYi5nh6wz8fQC" + - "oeF6Am#QC4zU4MgCwnfiuBDVQnYbIwQWCQ9pYi3dZn3MXrgYESIOEoxMsiOfKEYe36giuRC" + - "uuSKseDQfZh8d3SgrjZ2ALZig0nYWEcpDEN1DgZUeOO#AmNAVqkOAIwhT$ORqSKyYv0cU4g" + - "ZHTTAwW3vqhZ2u#L#JHHUUAx6UAI5Q5KLrKIkNE#OOpJfgNpZjgZ$#PGcLgJCobGCNvMdxT" + - "gBdVYsfGSNWsp7v6gAAjHZMeis5jTfNShlhN2NaxjIfljudorAgyFJEOES$FrwPgjTRp$XL" + - "KwL$XVErVWV0z2kD4RLAisqmSTrMhsWnz2AMf5lOkuvxcinfRMF#$rVcfLhirjB2ybQrsgq" + - "sKPwlTgaVJwe7pMcwxf2bJ6hJREhq7cNBz3o7fkj2kqPL$5cJABSzDq5IeDTG$e2bh#AUwz" + - "AzwaNz0epoFvwc1DTHOFbft7mgOLnjzsARW$qvos#1euMwGgoaoblZuBxkL589$8vTtocvR" + - "fSd#NsPmjOhgJFx7Owtp5TRvIbGdnxRELuhHYTfA$mt$ZJITRXkN$uaw#i$CoJePtQjhHfF" + - "$glzQ$dv2NwleM2Jta$LK#c$vR#NNXx1MP9BlZr8e3pDXd1I7F2pXwITfddwImPrQURBXv$" + - "0hZh$IT7AGieZv4RjjvCdKVs#b#UzOy9$iTdFF9ycW3$kfCLPIr7$tZcZ$tHF2$ikll3kWz" + - "m$AhadsbFhPBOV$gTP$M#i9xAhgGxlAFq0RsvLgFFKUxxTpx7efSrnAXmbjKdMcrdpynOfK" + - "EbhhBW$vvHMSel0A4qQ8wqojqMQtOchjya3Rdpb5uPzD626kynUhsb2htOfJ6grbxKhRvPo" + - "Yy78JHWXryaHJcxj2KLrOQsb7YLlfVIXFH6pD2kHFLAE7k1EuQk0LDR8cb4nVJHnVyHb#8w" + - "NoyAiQ$hVuckWJ6bGR9V9Nxp$yf0#GyPC#qVcw4lvwbxW3VdMztQUywrpmRtRUklhN7FV27" + - "pSn$ns7uqQBE#U$uoJl2EHdYiAKJVHh3bKBBD9RXoK#HJ1IVghfio1b4Kjn77wyBJdIJn#G" + - "92Vcoo$frnpoIqsV1YcBMCB4MglyGeMQlWnI5h4KujoLotNqis1VAAtW$5o5pb3vEUWB3cE" + - "aE7JyXPRxH8MQFWzI5h4KuWGSdiRnYTHlK9SVgr3J9q7A8iCHje$u8nLg#ZX8MSHIY1DmhA" + - "DnV2Jrx#taXohKz56GiiXmXEqZ$a25cZuCKXQn5E847CqrZW#a$lsPV5#5cZu8KXOPZh1zi" + - "shubrFElro#xrzkqZPHkRj8bIQVI#Nxl0UvlFPpQLQ6Jprb9HsvfEgoClr9Oc#zi0tIvOnr" + - "z9nnHgF4vN9NKqcGiiXm8Cn0Qay$euZokSJS9dOJHcHTXIjp0khLypxTVGz7TqXrpoNDqHq" + - "8J3gZolDoPunsuPhUPz#tdue8hI8FrLApLDgV9G#rYKhf7g5A2n4#Ls4$OI629osKdVmsND" + - "86QDi4QOiK1uKgjZ$#yVfeuozXpYLY459BA9LBA3s1KoU0wmJ$1Cxd4ElLiLoWGd#9N80mG" + - "s6S50Tgsq2ce$txFl61MAGjjy02FIGhYTzuQeg$3Z6r#cFVusejjZI#BaO6e#QpfCyf7SP9" + - "yt6CCq8KxNoWFOtgRGlBeubV7aqf4yP9yKdxsvCSjBfMevNpMN8#ftGO9yrdlYE9FuN7lqO" + - "CQfNMUImvZrCwZ9FccvSmtzOFzjJpZ4NzvaJ4dsvH$rEAVVhVnKzzFaTI79AtkrNQNEXlLB" + - "sDa8hO7roBk9u$tXR4xvB#JrZt9#wlIF4vXsABFWrB8$Otsid#zFJ79xQtXFp#vnJxdykbI" + - "7skIspwXEh425EhjPjVWwhHfV$9#ZpKBfSQROW$ezZ$Z0wVznuKM$GvIaU4jU7eKY8S9$yp" + - "FKuRgd4Aj7tCkZ$crCUwnARFmbBMtL7y1BlyhAnkwVzOwzzOwoT##WVgxtth7whOBxwtS$x" + - "7qlmgrdZzXyekTDwJfo4SgSw1qJEWFW#Ufie3ovrcj76idXmDQaEx#7z0wR$zFt1AXt7IVB" + - "7VoCY7LOZzriD8lqXXd23bSEn0WsF2EB5#4ojRGA$FQJ#1#8uDfKw5rAdc7#tZzt1CQO3tL" + - "ACTyIbSTmeVfr0TnI4f3WfLB0CjHXTBjF5FGTmcFAVaEUDqqPAdM2FUMhoBkjPyjAOwYaDY" + - "3kPJiIshyYpHoc#D6BiRf7YFGt58b3Ub8k7ZRuhsMo6aOrDTOX7bJIdQN9QWeJNgMlgRocK" + - "#zbz8gUzXMzf4UPBbj9uvSXbA#Aaohccbk6BAQUPyfvBX7Cj#f#VO9k6ljnXbC7Fa8pHp40" + - "hv2CAH5CQ9Mtx4sIooEhJKcZVLcdFE5$vId2yUyMcbMch2EA7qH4wTo2aTnebHc$Wa5KBc9" + - "4fJ62UWVO9YX2VA9#GJbCybxfM97rSXP1wdD8LnGkbZd7eCKe$9npYVGwp7n8#g43AFKfh2" + - "E6aEgdsiq5$TgRsoqrhIVqMFfb3#rOHnOlsKuYUUA9GFoOUSFIcCa#AG#jaeMS2l01tzn8z" + - "yAAFlf6RK$R5hHNNsLt4T3YgRbFtL9gpeluPzoKpF78amUCOqStX1RoGuK7FhPrOoUiUNKK" + - "yN7kHVXlH2$p9li7yPf#TG799urRzCqd#QSIrwS8SARQ8yrQew$r8J#fTIc3c8uf34wuP3n" + - "URNFFw59lGlvF1IYaEYSdc8gKLhXwZG9l5tUGZgJwUqVtfcjd#wpx$ieZWaoflIkCTm#MbS" + - "TneVwgnscasAGvKcof$1TMVmSOOgiKbngD94#Okvxc8#BbObDYaELPeeJ$VP$kx$6VL$vhI" + - "WE2JD8KnjZloVMFvFgFyJfmN58MaEOMfpvAza#IjHVoMd1SKXQGvXQWEv2qpeNy3f5oaEAU" + - "JmBuZ8NM92$n8EBw0uf913nO7SHIRqB#Bm4ef32ZdyY$BDSSM5#5eLPkRxrr8wSnp58N7T8" + - "iEdFfRUnsDwWrsuF9ZEQl9WPszvCD8YKqrnIAAtv5L5rIAUeCF3vGIJjacC2alvh3QHSnDn" + - "LfjeqZPndV2VLMdplsJ#iq84$$ANU1L4FCH5eIAspvFw7yt8Zvx5LSYJsdhFXlzSvcsaUDK" + - "7UfuaBWeLUUhUErs5y1d9ETxBQ2sFX$hysqZI6k$Rg0MKFKvI$kFE4aef3I6FVvjpF8MQeC" + - "z$BliTxHcotq66hkgVCxmudWabOQSb$ZF42yxdY8j2HTdlv1A5ZsH0p$dFE2TnYjAtKxtF$" + - "w5EDJvzyxo4991#Mabo7LhpzQyE$Tk9Yq95LX#Uyv$sdqOldWxeTlyfIyFjA7dAt2L6#Wbl" + - "aq0MslqdTFefag9GaTN2xVuJeASuV4Ad7miqZE8QpjDTOgDFNOTHBcZxCVynRnCA5LajS6k" + - "e3UuIXxNGC1#vq#G9mPrkmNUwwMEUiZb1jHrmZ0muTBtIP#hb2T2sYP5KUgXjkLYCYEcP3p" + - "vQzqV9uDiDSoyyxALTxst9zIFaOYuPoLh3QwPHuRrmvkiOjeHvVvhIeAqGlpEYD0Ib7bzHw" + - "zaOyXez2LVV0UBakb6eIouL6f6#vwDBxQll4J7jgYvPGfN6UvxMttHRZD1liZes9f7Rkr6Y" + - "Tp1M8I8gEJoFBSBF20ljA6xfYl2#0t$ceoP46tvYjl17Aw9U8rHeHmJ$$WWEX8f$PApF$45" + - "jydYVwuVFlOtW5ZG$Kf5tPYbKq9FFD$W3oSWu8J$P7wtF0a7xo4zcL26YKTPOn7r3YCXSy1" + - "SfOjii2YmV7xqHiT5Biz0LOHTPcxOyjw1xZjHyw4iUlMWVp4VpiOwHyhQm1NaRogwGjzaav" + - "kEWxxHkozZ$IJtAyef87nBk0RPMUuA4cisiAut4it22pEQfshPChMcVMjCnjQPpQarPQar5" + - "QasN#Bv8c3bGIqc2hdtrTolHNsACikw1gX4PPNbfK8BTnqZUVGJUufNOQuFLtWZTtbIDtVY" + - "PFKQv9ScZDYtLCiUdrYnEhJanjMPfQiqVKsikIQsvDhNccTIQr#ewqWMNv7vh4OoqN9G#zd" + - "9HhZVe4bxBfLbJHgfnbOjCYLnKuDYFYAqwvjnT3pslOyc8sFapgLTN55poVwtdQtNCiNwPa" + - "e5SejSlbDjtW6Bh6jQlKRn#KHyEuf8DnIXlbzYwHYjT2ohnZutra$OJQeSbT9mwdghUFnOn" + - "bt3AICx7aR3IUNUbhGpU1zv7AJMVfyfyarhphzIQ7rFR#JcwDib9mTW8JYECqDrMwTsSkji" + - "coglIZDcjcIkOcmAFK#cHyYQRg5JUp24$5Knf2ctIfICuzvTmR92c$SXVRChiZ$0kAjNjtw" + - "N223reId4yoAa7RK91SrNAeVL#6aexhUNzDXaEXD5TUxuSxTh3ajue6HWqqjjVA4J4ytjZT" + - "xTG#zj2OQy18#7vEkUTprxEzVv2nEewTQ4bETAaHNoNDI9sLHBTMUkvBU#pR7#VAedGFOg3" + - "GdaFf#w9q4fJYeFV8uGIcsunfJZudQWeiKWCDAL2lSNKjb7aNd5iHtHGiA9SB0uoTTxbkZP" + - "OLSBxCUQJgJ2fX3hwZQSZNE69Z5X7D8FFb8XrnNfYVM3OK6maDXOjn2QYfTWKg5gBDc8pqL" + - "PiBhR0N6WdseiEc7kTH6THAig0kq9KYYvYAo3fAhOHtSIsehle8NgANXZxFc8xqLTKYNwYl" + - "zXULCDl1eeTn8wYHWmIWyKGiHFyQ6UnYzXLx2Q6YTt57cAus1CZjXSyO6zunsWnJumLPuZn" + - "qE#8cMAMc2tcYAE0To96zcZeFxJHzAGDUZ89FVcdUC$goQ#w9nMDg2VD1Fq29uhD0Ug9E5e" + - "1TVtrP2knDEZ9AK5F#YJsf0IeupqP8wuMuu1X7x6ls4$iBmx033oeqOo3G8z2JxfUtC2UT3" + - "F6eR7quFb6tmCtqWC76Aa7injH3yeYFPY6DOfwCBaHzI1v3COteXuiQ#HZi0vGZXLpOzYE0" + - "xR6qeDviNb0c6aCjcuqFN1Yyu3s6Osh1tEXTQpLxd7YUB58B1OdDA8UtDleUq3xL8MKmiRO" + - "Wrcw1sE1T7oZxC4otGCNI3CDteDBwxWMPSGXEhMkU5XC5O#A2Gs2VsOTHk0Ge1uh3eF$d6d" + - "DWeR1NzTpGKDWVRPeh09jZ0NA2aRvPU8keWzA2UNX3T8dTpNxH8YZAE$bFirgm3ujAxfFJq" + - "53m$ZK6Ot8$$iqOLqhMCiQ4TRYvzRRufq6mZgl4M6zjsYiiyGd3OJrywAnNe0Ljc6mljQ8v" + - "jOLZGXhIT5OwGvems1ThsYifBUnsBNXi3RPTUrWTHeHrXQDQCrgJEjhcwAn$abSt41OPpKY" + - "knQ$VoLC3OErj15XBTwkJTU6XM1TqOYm5d#ERKnOc$OkJJxmUy0wgE3xj6FvUmfgendaar3" + - "Idg7XxjF#lMZxKzZGzczCll9$SRruHRpQQB1#BtveD5WRax#IxiQ2jJ7PjJ7DhIOVA0JhqW" + - "3hAKLzlpiMROm7ogiJKVP1QSFj6#hQfwtGHYPFd$etO9z2dnfRS9$egUysUd$d9AAiQD1n2" + - "ljKKd2VQDSwHVUfsUzwpvhvtS$ziNLujgCXlQHGY$vB$Bl1BLeerf$4pmsEjN6C$kyPvUn6" + - "WRBuvqWQnpT63O6oOu3IQK2K6OI4iYG7fT1FJ$Rdrjh0bj7MIj1Q6QCKq3Sfm7KtMezobeB" + - "J0S$QUVvsAQn7FPYPseDIRgqYfmTN27fZ4lN04sVgPmtp8Pg47X3#AOo$1V3V3Vwv1OqyrL" + - "H1MdthKYREWXTKYdCJHxut#XuV#S$uYSWQtPFyA4l4635PZ6EiZp3M4c0j12NLLg571kK5q" + - "5mfZaj1ULaEofaMoXPvKHAsAnZR660RnvZE57yh22NzLwMn9UssrVF5toIYfBrSlgTBRyoB" + - "SWpyJzdn8SRgi1qp1Q9yAx1b2$5NZJBPbk#AItDGPXXbTO6s70oi3mFhe#0aJ6M82qDvAL2" + - "MCCeA7clrh7OooZCIhX0gWV9XHZctLfGpsOhBOCLJnMcG9Ao5e2JPSFRGc99Vdf$YbpVce2" + - "JDnY#xr3BYM#aHVuAnbWBhFA0hp9Q4CiCecmD3FblIsXP7#HVn7FzkX51cygASomZ7m9xZi" + - "7DehbkQNn3AB6PrQCjlnNT8Lq8ksPOpyzhomRmeQHroz8fFr$CjC6Al5xXUEfOjIy5v5lXx" + - "fgoNKy0VHta4P3sqMRjVXkUNPU9Jzajgkwm8b7FrY5TWVZZWJPxZIIlHJEWsAFElH27AXz3" + - "kJBH3lwqeR2KQmolHKZt7bubJU0JFAHZb4UYX9wuk0EKoj4eMd0cKCtdiI$WtE8NRShpUPv" + - "u9VBJ#BKr4IUt5KRPWb7CBcEC6PJMabdAxPw6aMK4ed#TpZrelwUxLUA2y5jeBHJcJKSufm" + - "2#NeVPKVXV7Cc2aL8PtA8MWF0MoLT16AF#1$er7kWVEGKaeoyHNEIXVO9Gz2zWJBSDgekPC" + - "2$IDKBN6J7Yc89IqZpAsx07f1x4dEYV5beF06qTPXjN40p#XFBEMFL4Pz5#E5cU2BX3NyAW" + - "NPiiIMB1AVCWe7u5q2s0y9#NSapJYOx6hCNwP7sK9j2y3IhBdYpZhN8EoGb5Ipwh0JIY$Hd" + - "eywivFkR8ObB2gpxLcJsqeImAKT4Q$Xjjn2qH9StmuetoELuWUeEILw3ze9uwIsYiC9UasA" + - "6V28wz1Eva2KGu7ZrdLj#PLx7nWJ5xLrqlmowLionO5pV4oFNkM0IMb3WNMmbQY4fxZ9Vf#" + - "DVbbYzJPCmaKHtaBU0kpvUtMYCz4#XhKBeLy8IZf3PPcjz4Cqc#WV#U8AnDHtfumuhDHLkY" + - "8XoWpQ8T6l0kk60kxEgCtePoXpv1BUSHx89#4yfI44LyEIJFY5#L5UG7GB0N76GYxy7bgAQ" + - "#TXQ0iun7VMg#N3yAoLo9EdkEd98puSgmfPd#P7sK9dxTf5qJNrqJD66aXAFT2grLeLztLQ" + - "Y4#GBu4#S9jUNY1A2UpTopbqJi38OtVqW9dprBn4L3#XL5#ZDREu75F6$7X2IYN0kMyWb3I" + - "p7J4#tpSmWYN5cXBDSSTlIVQMbEp59HB4r3#29IN5e3IuNSuNA3ZCbpRgrHXExTvG5d6A8r" + - "S2MPpCaed0UMRmIwu5hzq17X9D#rABjLj5NQ6d8TzcjaJASc$S3#JK59jxcxZii0lv#L5MS" + - "RoQjHBs3DdSweGbAwuFpYF3mB$$NpEIzu5LoICU0dxvL96EJiloWfeRo4wYhlHmb$vdjBz$" + - "9lvGb0#osV8PVhU1Y5SoQjOiYrN9kpL7Q2yXL6khCKlow3$1GvTx8hA1FtZpYO5ddis2Uu2" + - "Ri8vUZF0x4IKzCdzfb00fM2K8YzAzLagX8ny2a79V5KuW38Ycu2IosCekSp30PG8yw2KAPy" + - "cb4qecr0seMn2sOIo2MKJoYQKJIYRK3QXR4BPXB89PUD7oNVrLXEbzMRKBiZHcr4BkGFp6Z" + - "JLtPQES556Js7yLpyhTgUuIqnXJXUQCunnC78fpuen9zSW7YjU9enSrbsKSXnOKlI3HdgQo" + - "3oJrnkbkPOChC1IP8NHOWnIut14tu9EtuZD9UoeOUo8mpTHja0Es15EpekzLCn2M85ZheMT" + - "h42wW1qs9knLm7w8mOxIgSdsPVcNEVopk2GLUu5FwR6UF4$f4VB0EopBmJioi7mpVahFuNk" + - "T6L7DTZfH$47KyDiADGAKdYwQ8wIdzAXiSqPL3bxrtkTJHHlKaj$HFKNo1tgJVXeggkyE9C" + - "glj4sXjJiXC3RL$j0ADhtFikbBQJOLutMiRIecY77Yu2IRAc$cdewFsXHbjThKcZ#7y9nLw" + - "AVoUqBDY4s5xkP0J$wsVeW#yBUoLDlqHAts2A2De4TP32rAQCHQYUdYI36ZLeznqRiCjETx" + - "hdCIhoUgZhHDWmJ6LS#3NXp3On3sKxsndlBjdJ0prPEfUN6HrPa$7wvcZ2lQ7uEh5TQvyI4" + - "kcfc80rpskhccSV5Objjd3JqFr8oBs8jNZDwMlQA#MCEyQnINTRxeft7HammPs2jZuS9yj#" + - "t5etewwULMb2yMY8jNx7pZw8JsuXM5tdHlnh4vsGjvWsikvkTB5gvmvLuIs7iDZsDaXTIua" + - "Ee5B0y4k2Rn2XdYceJIfU9qvbo6uzIrYGkh8OtZOse#0bU5DHyZkFYy15nyxb$3kFHyjAqL" + - "uch5urZAPvQA1F#Y$fnEwFGgJtBrD8wH#JWtDeun$n9BrzvyPFx8kXgE8wCI5gvclCU8hdt" + - "cJDpAeCezEnImFmYzwb3cCxiRqryds0$qGtoo#6E0gZRDZhRuQFLaUVBkHgr#RDFgX7DRhM" + - "VYw0wQzxwvUwH9QcumPxYFYEsz4wqtYT6tJjbNUcRbhfFb1qdh8mxDiNofrbp9U#AjhJsns" + - "a7qJjLS4rfUrhAlvD7DiJnsRWLRNezVZkM3ET4FzZl4clrJIPA#TpQM1u84oRfQldQl8SlJ" + - "C#BaUyRdxPblxNdxKGiHhpdRj23EWtUajP3lQYGOMtvcd$O8BaOW4rv9rJQsN3EQR6hcAsp" + - "QNO#vTIM5aD#wZdWQrSY4AwdGt$JvjmIQrrEbF3Vr5HBlOzCm7QBcEbjighM6T0#ykm$hi3" + - "1PwquUJBpkX9WKejF3gxQy$aa#TwKuJ2C8hzh61vZkYDgfBfYqhe8mwVyHk99d35qVHEp4L" + - "vZ01C#CZXqya#kJdkY8Z1pD6Kv7HuwkXj8GwHqUE6#pl6aCh3HEhuavtWIlxurppcGn9HqH" + - "dtzjH7oUAyX6UQzNjHUhiwGd#ak##f5grqCpWyvFWjinwnAT9PFN9OELsb5O9#AuJlJWsl3" + - "Em165OjNh8Q$h2YkkYnLMUlQb1L#fgHMl9d75CsTq2vNAeww7b94L8ltQEcv1TOS5UKA5V8" + - "0A#S22dAlXCGvd0Pz7R5IMf$6EJbiyj5LULF3$4DNKO8MvJjjgNTujtWfEHaLu4M#jKOIeU" + - "gUXWbKrAdi4CJSBjzL4BNjjC88tHMqLeAxHAyowuZ2nAcWpqLRsfr1RHVqg74ECu5RX70XG" + - "zRP6i7zapjJ4KM4Ko5Q7rMK4uzwkMxtEdfdYrYI$ah4hy3NfLp5RfVZLca1LLxyAPFy$ygj" + - "wiXMrloxIsbP8hoLRMVBHyv0mVbNesXxQYhMfVTnXQnPLmyx1eDK2LeOufcHKDgOrFOA1Nw" + - "ahadiOLUxrt5hng$JzJO1ghepkRoBtAD9HgIiLGeKhbJM4IZpPaAXoHr1$Tn6WYlXLg$pUp" + - "jzTsDxEtrqKlrw9A$Fv5VRplrDlrtNt$7vHrVzw5VMhEAhVXr#9NunVgVLAewgdzQhs4Mn2" + - "rOIg2LN3ef9IlvcY9hZ7Qz$V95HBPG7tq1XLHT1Mx0wrwX67$QXTAGl#Rg1KQwprgGtzlGR" + - "rABh3gAs5qJ4xn##kNoNDtUD#OlrYi0SQ2thYP6rYLtRdUxj5OOSdhMNikJwJwpUvtyWKw9" + - "5viClmk$IIw9cx2EtXdQQSxy8GDzVV2z3UTztODpAdhvQ$tsHXhvR1VGnjhLhjJizMfVkCr" + - "d88OpzixSnL2xkzshGe0BjfepAEdKVqAkp8r9ugzrkychoQZGRpFCswQJx3tswMHBsn49$9" + - "sGicsvs$FvMocEzFjRv3#7kmm#fxdL5sDsSinZujmJfhnExnLU3$Pxl7r$UelzV#dNljTb$" + - "BsAqrailNRJnsrpvJbpMomUskiDV5PtulTgyxzaBFJKtOcx0tOM$2teIz2Vl$TUnIviCUIA" + - "m6ThdMzkyXzgJzUnFs9knDs9kmhpxsDN6VeEdSr8Iz2VkQmbxRhpcazPi26xiiwDSSClzl2" + - "YpiB5ySza5rnMvztp1NpEDV9YuGnuY5ujWO0i9#KjxlobRaOkVSQl#AfdRiA8jWZtbX7knw" + - "VG#mnoIRiAybVvSovk$HC#AQzFVkoTZLVseaOnSzyixLyJ7i4t0SNAZTwpvNruRTY$EPrS6" + - "kq4Cc5Rre1SiJzbOfTY#FsJtokyh6C5VhQlScx4tOcx0t5FRYpasocD#cTa$6ZdDJ7R6lth" + - "cf6BjhZRz3knVWCqrsRx8xxMVeLwzqpDM7kLwbAvZezKzHTkTVlU88iOkh4h3VjdfsrrBc6" + - "T16PFTYiF$#$Brnszr#Ext#nNNEEmmOUwiKx7M#Jn2tUwpN1SnLhe$CLV50qbobvuiJiP#T" + - "F5T3kykqUqkthTv#HcDk5jezvsqliBTuFDtVSVKJjNlqwgUWvr8jn0$KnUwXpyZWpG21dZp" + - "OqzR8qEwf$hvQTa#x$nxJadJ$lS7tm4tO6#hQGwftYLXpDKU7MXjNOwusOKyzhpPXRn3ip3" + - "CtYdrrzi2Mrj$ZElD5xAfbXKozbrhCURK8xFeDN8tPPvgmDs4l5Fjgp5LpFwsPViV5YeHlR" + - "5hbdwlsTmVycnBxtPgr$aP8IlKhI1dxZP25MxqNQ2nZ5vRTcoN$DbEDLFZsxyBN6VM6gE9z" + - "9k1Fj3lNv63dqZM8FQV5Ec3FVLk0mSwnmSxli9JwRG5cniI#RrgHv$ic$PP2cUVTw74xvA2" + - "DlHkTozIxoFZTw9BUk4QwgyHOXDkJzVMz2FM$wgtojsg$zzVIJM$tgwLLBglYq7eZErfThL" + - "xJlOYczWjfNuswQR##HhsfrQPMcrfjFAroMKghnQvDkkscLfjQRMgrgTK6Q9NlBTbN3V7lF" + - "ufiDVpM3grQRxOHruiR9BtXxURQtosHzFPEwvl0tfPDp9jjrBisQcfxnucEHySqXYZfRR$y" + - "Ljv2KFA$B9WtSusEsYu9fLJNSJMr$BVJPMf4mgUsbUqGtwn6H4miT4JW0UG7vcvQpThskwR" + - "srdHxd6fghy7RizQrKgmOQx0zUXh1jCVlyglIBPht7XRSFuEH$$M8xgZLQ0qJS1nS#9lMfR" + - "wV5hD0xArYDaPUrHBML7ghcAulxFtyPLPxEUyqu$b75ZBFy5Nd6p$mqZlD2hnhm2j$x1vUt" + - "FQwBA$jLUznZ8teAR3trltWXDuRs#j$pgdckx4vl#7Hd2kuzuMsEp6VrPF6FArTDUPDxJQr" + - "szJk$o$j9loEq6etUCzjTIswSjwBcTG7lTElhcMdd$kEpU2$SAoUreegOXTjMRClL$yP4rf" + - "MJ02gWzFjAlNPiDPpiDepACisu#kVtE$LoAvcpr2ThqrjYyBQz71bGUVLhHFtAP4sKyQzt6" + - "epV8jfZzfyAA$L2XfttGDbuRnMqrgBcWMrzo2lhZKm2zQsDLRVXmBUrKPljQd#VyvQZQAQx" + - "B7abFf76#pKxFzHOasn$sMEwap$HzuqdHpNMQUKPaUPh9F#cPcz9VBFpCawywChJfCONci$" + - "Mw2VaR58#xVeslee4xxhIzPNo3zYCmVj#lCy$HJUyzVVEvkTlE2TlBcgoFlD0TBbRCzmfqx" + - "lSgTsojJ$I3Ad$LH23$v#l2RQVtxQmTmp6oJEXzvcUbuaZOoPfsD3lRPTLS#i$taZJ6nNxj" + - "aJTREhJ7Yg87T#s$zqA$vdsPNkTVNACserSUtXVyE5yvk$gu##iRS8xM9y3Fi4QJ#NFpdwB" + - "xt5QUToSpwChL3wQPz4xJmhog7TNg6eNCtNNXYzca9dcV86#jVtskT$x5z6a#T$5tv2W$oL" + - "hYtJDAs8z2dVsXbwgBatGPgQc$#Emp4WdwReR$QIPtxy$Wd7D7xLmOmkIvxHc9cn#ppqn8m" + - "C$pEyJFzlsmIi40TRAqIFskuR1KyHHdzpc1T7#ifbSEJeQyBHg744Uq8ZNPRo2$mUyF9AVV" + - "v9dkM3#DnSNiYvr3nB8sNTpwNn#tHYgJX9vqx9iSRsjTnvexbwTVuv7h5TZpoudYvkBCJOG" + - "bQOa5lgUuJYDzDxnudQCx2Aq5XRQ3ktIjY1ZxLwfSxWiJkyKePt6PcRRBMzXJRnVyLaulro" + - "bgSxmwNmWVBQ#mmkwdFXus8isOFjFZQl9Gy5L#n#CVsRR6W9WnaewDoO$nkpiT4U9#uZgCV" + - "XTK81MYDz6nz3Em7y1ylOKoJ5Qar3gtsXkgvQpVahq3f1qlt$EcCjP4yTVDTCMclrATDgpa" + - "etrsgLrXNzZQgCVmTS3hbWhHDdSQldidwraxymHV#WXETakuVQ#PguUTnRhDbez3TBrm$Tr" + - "gwJjRFzxT6rzxICNUqwUndzgVOX$UDZ#BLsAMj$chmG$RPzObRFgrzVomVNG1fTQIGtA7X6" + - "theVnrONt6hm$f$4ULuUwtdq6NbrFowy5Wdj8h3QJAxBywEnSqbv8geUSQykRgMiTVtjaU#" + - "jGZ6BaBOU8NQizHvGhvDs1egWIhfMuNE5VIMK3uMPaT7p8DRwUaKX4pvn5FdbRVo1XaCrYb" + - "RvKHWV3LOKmg$kZVPIMXBwo3D7fyCvLfhmwzn3xPbZlWrLUF9$6nhHV6XizkQSB#Xw1tvNY" + - "qVNZz$$dhK6jisp9ytn9EoLQSr0wfG2px$HfmYkBc07K00UsYjhNcll7gxvzFiGv9OdpvJG" + - "Sn5k4UGx5lf60kQEj8lu6GxFPjii1uRpj6qkIbXrXJLMUUUYFPg1jVtQhZ4qehXSUK8hjI3" + - "1F0QImF$gl895L$Cc#VgHByG36agki7svqeSrH#ax9S63bvjvecN2ETmnDeV3fw04xvDJzO" + - "esAUjfQShEixlLBxqVbBMy3v9NJRN#cZMBhhRDzyR9Lq5jaluv4NhqlvvBEg$E9JsSxy$xT" + - "xDorLZQgdF#c$KiBgUh4FNiKszneUPjeVu9KT8$9vRWwi3MqqBZolT$ZlIiQM#hfVwin$oE" + - "huRtq05YqpxdQcXDGXjgRnv7NAfNnuc9RPGWNww$sqGRR5jrdK9rlI9jj0YH9lS2Y1DQC7M" + - "cXM0SgONcQx85#9VkWrJN6sP4geCMJDkafNbo2tfSWxl4HWktC04j70nhvtuhRdPihNJRfg" + - "Lg6NrcgppwJN9qxwZqy6ywcy678dhGTdE#mkmUpkEaRqZDDqMaXpMCroDQhTe8hbHrIzJBv" + - "9Qi#jYT4QqXN2d6y4entkuPjMGGovohRuCukGvzg4ukrPBZhMSoYDSWulx6j7DTiaHopzFw" + - "cswBL0lbz0vjjmayCZ9wyCbKMrZ#Czv2svtlKeqFxpim1p#ZOhWjoPWj4ZrhV0ojuazySW2" + - "hRE9ugtxa7oSRLT98XwDdwyaTfyJshR5G5ahs3MMhj75AnaOMYevUceNoMTwsHzheHViGQ3" + - "9tEXb5#3unI3LZxT7pxGISzqbNx5vaY2tMX$HxxldV9vLy5gw3jjzrJUwQNqj97brpOtCWl" + - "0UgHgHxwALXYJYBPyMvbhTS65aRmZtT#5Xxsi$iCSej#JyvQlKoqWMNv7uF48mqPd3gsFEk" + - "eZfHIgsCveolLvJ8EpOA6dkz3kMUk#kXvtKhiTVIiEU5zREfvwlNS$qlytHUdCihdRbwcXl" + - "vVLniNSFwrPtNB#h3sLno8NZEYwvhp7EXFIDCFxddvXgXLIsz2hzhJPeHVHhjIcViBcIu4q" + - "kwrXRMjNP1zqA2AnWXmtr6C$Qlek#7AUtgExBuBYK7QN2dhv3Uv6jFHku4Xjf4ZzI#Hy$N#" + - "N9j8ZEb3Kg2SpXor8hj#MtWrvQdMZlPQdY#iVHvxDDq1xCxUwgQxRQdLgkd$JWNsMN1jXEa" + - "VLLYvQnPK9ljQx7hQjVFjUhdncmKVSDTT4TqTb1x7jBc$QVdwJXSLOBxCO7aXK4geKw8p8a" + - "d2Fhqsbm8fnFYMOW$56BS$aASy5yXjfk1V1SXN9GT1PubwEDXtONmje3iMK9CoGZrEKo8XJ" + - "SWcepZKjH19eFqmdiG7u7uKPI$WVW5v9z7$9OGapSIui1laVvKY7LA4V#0ibs4E7I447jTW" + - "$Xa8KRz6$53GXpqXH0JoY7xET9R8pq1CZ#ZtQkG$fCGRISAqGppHZmhHBj9IB#3umCXclS1" + - "$ZCH3qJy7Ue6W7SzvD5kkp#ZFSJDLw2kGeWInBCUmG5iSxeAqG4w9xmknCGMgBiRxHwEz1v" + - "275ifnAQ72B4kR3CH62T2Pk9lGdH4Vqi#4#BWVZZc04jF8Jfj0BvZSFnDYFNwGhO7sWA6nT" + - "y0NtkKFuxsTq0vZYL3m0Ex7WGx7dmBodO3ndb8eyyzRqSQ60uf0n#E4jYY1FtgU1x627AJW" + - "VVOiU1hYNYw47qE4cB1B#15UVjLa4D#iqNervVer$5e6xPV3sEzmOsekqY8pjiWxGknuJZW" + - "cuqOvHkvE63dZQw5JiYqMuZuPkZi1Lt0TCXhGcmy7Fg1UHByul1tXPYxlH2ReuyRT11Oi97" + - "V6$5ciFaeyEmENDIlAuHe0SnBSCNMuLMKdmJ#kU23tPfZJ5f0pw4$mSUWVmRoc$m5umxRjS" + - "IujSIOj5m9#yEkhU0phHRWU568rh17Q#1h$P8GRJ0#ROx3yGfmReK3VMaBcxH5$zjYh3R7M" + - "6m1cVP8RxalyC17j$mh#kS14tnWmH#568cvqHE#TE0q8Nh3lqfs1l#MGio7Jys2p8Br8VU4" + - "4DDGrnw#VonyU3fyz2ZuxT70sGFwUfqFMUWv6dYg3aKCtvbBCUR3wDkGNehZEjW0Tfdx50w" + - "CpJp8pjiMFAS1A$ncW$#X7hWNO3xr68zn6Ody$HXtp9DZKRSXngOZC6y8$plcACZ2hWjsWl" + - "nDi2VySpRiU$Hpm8ZvqEyKfBy2Fsou4SQZ8yPx0OqlRD7fLkJFnNZ2ZfqTjFqWyk3T6FRiW" + - "BOwmIywOUpRxmfR07jd#DeH9y9ULsDjk18yM1EMO9oQ8vxsAyOGupyFlji2upeFzRqWqmBZ" + - "qQ54YEFMWPtUHd$NHHf#E0z#VIJgZyEyRlulwCQuR89nApb0Y5BCtnxmZrBOQFOvYD7cRBH" + - "PUZ7ai9RCUn$#sXRwlqSQwzLyZ4ifx7CWS5S1xtoi7wLlulW73l3tXs#LOlwKOWtQlZ$gAG" + - "syfSzWJhmCJ1Yh7l3jJT7E38pfJCo18x7kRRTOY3BWcudvD1FsQFjF#0lcUFk7KKTfsBdJn" + - "z0$1Z7ishaAxODtAFgx9$GDnThG5pQP3B$iYxuVjntySa$4cEDbeuNO2VDh1EpI0NFBmVpf" + - "0Dze#oFy4hARe#ybJy8VqUzrsu4NycNpaKRxwpwDlaF7KAmZdU4lGp7$Eg2$Ws23dJ4$EWB" + - "3pbZY#sAUTaGR7U5R2x3cxGpCns2js0NhuZ6GsGL#V0p6zXZuvZ7GimjiUGpctYIilSTW$X" + - "oAjVKOsAyAFbW6Noc3$NQ5JtI4l#sASUy0tcE0QplO$1Zqlp$MjlvJSTm5luDlbs6C#wDy#" + - "s4uuA#RmAUtVmynvdXBd4FAi2vK0siPnhuQVjC9Qs0x#C9kmDWRlZ0O$Us8yIZ3E5N3vWCm" + - "pfDWc#tXnuDnNjaCjY$3#0q0fW5ONmPy3JwqqNCc$1Dpnhr3Y85ONzQ1Fmt4s0v4NtQ0t#o" + - "0SyKEwCywmBG3riiTX#B0UMr7#4iDpWaPpE4CpZFhx8FZFlW8rhfcns9j0gwM#w5DpBkoBF" + - "m0EdV3Ubg5DQqVscs7iXhaQnx062CkXpq6DSE1zT33FEq8#tNgYF6w06duwX6m$pIiFvtWZ" + - "vtGrsax8aPVgz2NSlXaEVnb6jQwpXZ$eVz17ll8dU4tdT6$dT6tSk0PqXiOC9SxurpR7tvH" + - "2fvTi2wNjq7TsK8CwuOoZ4afC9LXtkro9EA34MDzACCOxWh$Bc#E6EjVEVgswoU8CIwxOJs" + - "1ASHkm5A1DdV3Fge2wywm0n73PiEWhnB#jJlcIULbY8z6ZB7R7UVEBbWtzu3Dks0Tt0Fpjm" + - "lMb3rm7juA$HiE$zyAPSEnLcs5yTiJwy7M6ACzfo0#5J7MrwqnNpU$1FOaBD2r7kRGUbXJr" + - "iFQl3xsA#l3LZrnVku5kwyFcsu0doz77pU0hOw7NtV4EdeyVBGJ$BapVEzuhC6TiJ$fZ3dG" + - "4pexmbujuJ$bEBTlWFI6MF$AiMwMu#HLZh6g1gPIj56E$lN5V9k9kfuqts6tQgpbfUZhJ62" + - "TUIVoM8zBqPVviD5yw9i9VJDn7Xk1CJqIOxqfx5yE7RCmLhE0TtEiJUsn1Ws2JShX4nlY$B" + - "KXV64ZZFU89IYhGOmvqXNxYBsmF#Zw1yHOzyhHdxrWztACIrTWxpG8QQoH8p4tDuMjHcAkb" + - "MFDs7jJnEZlDXZN7i1N3XyennZkZRxDWYttnddmIAh7cZGAwy8so8#2lRgH3R76ZSBvh1lc" + - "uZ3qhptADm9VC$XRJwmjvTXJR8JrV6FCpI6mvSRm#M6OZ#MN8uqvtG9pkHFs7As0jHNwN8v" + - "zMWUSPpk0VpJMcUbeRtUqqHws78nnQGT$ACSSR86rgWNwDEWCp8c$2x4FC9J3bxlXs1Rdtv" + - "7W6Oz#zSPvgntctf7O1#oBSsuvzbtxOVxqMeO3xMy1dODnRkq4#vR3ZpQ1xJV179qEdjsnZ" + - "kw1TNqJxFDQOzwrn3ch56FM0MjiETQlbbXxMzBv0fWhC1z6G$zqh3DZ83i6upu6v$QncC#R" + - "ObmsXVocEFUqGbygiDQFnTem7Jwn1ywnhR0cLc2DsGBn5l3v2gmTMy8UUs1DRONviINsRaT" + - "0rv4KWxyzsZWIw$XEyBNXcEUby9dsiEUHy9D5mDWQ$jq6xVI6t$V6VcPVsB42SwxtlTXNOG" + - "qT3lzfZxLkVs1RX7bKWJxl3ppjuOETOCyPc3CLi7iVyFG1fatXJnKuJrLWVpO6wtu5$F8Op" + - "BVDC8V7OhzH0JilXCtROWxCmfeuzYEKjK8P$B8j$BK2wyj2w6eBcGLO9zh0tpV3kMWszWwp" + - "CHwRmxwR0#ySwEsFDN0EVBWdsGJpSWxcw9pbm07i$Qx7F8GF3yJyMOIu7TQA7J47EkFSL06" + - "#2kXSXF4y23PfX$8AzBq2Dbe4Uqq0ziuOymgi9OimzoPG6Vew0Vwo26lQH8oPY$DN1No#0l" + - "Dv4Vns8doj56je1VRk5LXh5c7S9#ASLqxh6MGhi2ukmboO2Fd5yDSAx9icOlosm1XqXA$Fm" + - "NhN1xw#7TRalN1E7OBrTYnyTI#S$uQZppCmVpfXBrM1kLY6ULw1$SyKnEDeJA2p73wn6EVv" + - "Cbm7J8QkALXVscCFiYV6eWmsgi0ycOBvUW3yU37aoc2xAMXtAkRKLEmZEi5k5JW7Lc0UJeN" + - "kgPX3VR7U70x$EXpdltvO1pfZtkuFJ0UWpSwuTYk53rGyXWC#lHZhnW7GNu5#TqPw7FplIC" + - "XLu9mu3husW#O3zjiLs5jLu7oy6BO#2hvq5Cv7Sx6kBiPyc0lSus7FUV2FTbY$F8n96Vau7" + - "TX$BCOvzHZCjt9SjrHWdbRWVBmO$Lg8iQ$4EMaQxB0GFhSO$QZ4N1oF$TyYhAVxR0ZxmeyE" + - "X$tcOBzm5B1KOWpt0UzHM4#gq5Ob$B8IV8V3Tux2DL1h#4S7d0Ft0RxfyDsEw7y5vcGdb3N" + - "3UjeQwtq$sBS$V74d#C8GxBE6uBm$17tR2NDiN$ZwlbW$#w7FbHYRIlZhDDXkMwprbRWkwe" + - "phZGhOPL$u$xQGgI8$n3aImoSwOGogi2Rqnxwzah1YdpI4nX5hJ1dwjH$MxqhuoQROq#qtM" + - "8Zkc3$x0MCbpcEjiRzhWtLwF#mLPc1iss2kpu3$ji5O3O4FRWQxxu$hyExmqVsnzwZ4chqP" + - "i1m0d##ETW$065V2NzfYFJW0#yyUiCc1yAiPM7$QOiq#47Es1zQLpl21Iioh4x1#Ls9$MWa" + - "xZCPrJHNyOGJIbRX#wOiz$sZCcOxennZCiKhiWofnZUjXJCfWkp5O4oiXCmBzgiHOx8M#LM" + - "8yTi9OTiQwKuNvr1VhsbvehnFEgvNmwPsmhzWBPPMmxG4OxzwmwKZOJc0lDH8ofTYlLM9k7" + - "O5rP2JcJGTSX#uDsos4ZagiMntWItjZlJy2XjwRhWkmFdI6BIhXhxsmzet2shCT$6i1zfXb" + - "6CDAsAyIvxXEy9S5Q7i1nciK$B0$x3GQvua1M7lB83iOOxmdz8w4B$R6zTmqjBSTV7ysva8" + - "PzcELm5g9EROG#uoZSVxeYskdux1Mde1pSYNEhPNO4mx5#9V1VftHvXAisPNmnHEmbwd4E9" + - "s0DYjnNXWAUnw8Ta#0ZtV6N3e1vxMTqSO9M3lwulnTYRM$4dvVYR6hXAvAr5T2fXBddWpMa" + - "4girwLePpxyPI3s9JjY$7R4Nhe6$bc3jQeIwrv7zBylribAd2ShSVrOWxMq4hxQ5$k46iIL" + - "yB51MEyguLDZuGELQ7SivaCNEbTXNdR1sju5Ozvb0tKVQ5QLYZiSh6BdQ8fLsjrHnOEhJ9d" + - "AUpNHVEODEw$Arkcdumjr$8kAc#qNylIuJCKZMeHbxVVGU9xNRQrKSNESbpC$gdG9vimwVY" + - "ZJRDTu#uKSqFbnRjcWXRhkxofkX$bOqbobXrRgzXVOCbBAzw8wIh0kPJQDblMz8PfVJ#iQk" + - "bJt6#VmzQvKwHvFX7nLFuNfdZF3TBjVjHxupxx$qRe#LF7wMAl7p8xrwotT3lQ3FGT4wzRz" + - "si8r95gtyo0LRuGrODokOVdwc7CRxsRpglADJuwNvVACzy9qYzx9F2rUgKrFNG#Sr#$LVRj" + - "KnLkQiTvBnUq7gBZZgw5CE$XSknKgtVkui7pdtrGywH7DX#kQzbWhdS4glq6PrhcVZY#j7L" + - "ypd7FRVnVcsp#juWxwtkq0FrTcKbaqFsHac7QqNz6UlkFYA5$BNyFqHX#4wOuvSpgiw$HdA" + - "tsLnhQPpX#duixjTJak93l3TphZ7BOBhZ4xQzlkScz#6tH#MyVQjpl$bC23VKUdNc6#T8J6" + - "FYa1SyPAZu$MTNnPbtU6ZjEYTVEm1ozzF5ectbVn0bn$R#Qgz6RJBHnqxqFtivyUi$udgtZ" + - "SC1NlsaR58qyAvKP#fE8UM9zxMUjavrKgtXlxYTAirGwkjxTlf#lqMahxt057gVHsm5Vggt" + - "JPK1KFUKN5Evsfuc4pedqRfjVTtRlgU9cAzniLykp#gOht61gMzRdCrfDsmDRBTKpVbZmJb" + - "fSTfllwWzQjVNO0zW5bs7UK7H7oZZz4nGEn5oh3$hZiuaBQNbC7sbiHpOz$MCK7uDgXxDAm" + - "V5Vi9ygkJDQnTrR5VR2kLCq8owlqsdJWyB1iuEKg7hM$ZkzJyMWzvyfmJJ3mIvFMTVDKt0v" + - "xe1twHjkUVhQAPtoZufczTAnbPchzixJlpgbMyL4RwLZl2#P#h#9vUguVDr37siUFcwJZMJ" + - "e#NiUdwlW27L#jupjq$135y8#lT9y#i$67$TWJ#vrE1#UMzxbPnRk#4fODsZnCTzPpflUZI" + - "NfLNQSRBVuPEfu9BF37JjZ3bVtRuiL#lkp7N1t7VQpnR1Gj$t#jd7bi5KKSn#VjljTM$KSZ" + - "9X2XvpuIDGX2$0EYVtZ4r016GjiKDD6$m3zK506hy7Yj25WW862a8BUK2dB8BI9odoae88S" + - "SAeWYLmLHG53nCpE$rvqb5KsKvCldTytCxlRjpimMddhIiZlhmA9BqLo9$2nISemfkTObOu" + - "Hdmzf0vfRIplPzQ#aSwvTbXpLFT0ljbAojKkLEJEwxL5ydbhQCzNV6wavV2$Mxg30MssVv$" + - "4RYZqRF8xSDCVay5ChzcXfbwSdQi8nzIA3V0ptkZ3tHibahlJyFuqNNY9KIQwVd4DYuXh3v" + - "jkpZxvij$RAs3fv6lQCrNWsITMZUCikRsJC5pw31phdAjKxDTjlVIDGkiVHbdWywEVt9TOY" + - "t36FjvFdQddL$WJoB0$Rz7NjRk#2evIEoJiyl2jlUmLudc1JwvRcXNTmkj0lPXmQJkN$Pnm" + - "LJcZxkx3ijA#PRjfBdxo1dJPWhzsdQUIQboorBPAx9xz5q$uM3BPkpjm#sEDU4FNGBzdCjn" + - "ybvRWtdkO0zLI3pVd7csZ3N1VApAsuyDkjtFXprosIz7kn6Clyzu7p6ahTR3f3xC6ZGx#ha" + - "lBfPTcdy#Tr8FFiBedwWtxsmPmjsEJNfqEvISrtzQfxF#jtlYMYyInFhdUIj#dTNqLY7Kr4" + - "$rzc$9PD2ES#k9U9ptoNlvxYEXBNbibv9FgpVXqdzucZVPRBMAvTxDDaMFIQshFigTuhF$P" + - "SSQUsgPoN6P$6XLHBh9NrTiknHQjdnkZ5xo7tLoraFTogErgIb9bdjd7jTj2QUSlrexiLMe" + - "VrWlTD7FykUjraMofgje5RyvwBz55oMTWE5icxlkSFogNlq#q3dkDSwOwsrB98vFfrfKqrk" + - "kyGEIkm4CLcdfKy86#SV$ev9dx8Vx7f1V9bVyogTSMNEo5$WdakqFbkUtydbOQvGvfB2LKw" + - "zx4aB9rksRc7PyeXbGR7KxR5iBv#5GZclAbb$5BMnx23tSVFIS8nSkQP5ifvEkdkMkwF7No" + - "JhbJoPfv8NMK$UPUrxvNhVqbvovy9sLKCiyni$Syvvpv1wMPiKo1edsU3Kd0$jrl9#9RF#7" + - "j3i#ZwZ$UTlaNObdElUlwzh$KBc#INzoxMhoCAMQnJ8ipsGzKiWUzHaC#bZkAN#u#NfRtb1" + - "NaRgTnL3dle3$WapseQ$3Uf$3tODJeGJbU$8CnfBV2o#LGwAYnAYJ2xB#5kftqgxMHpEB6p" + - "zVJbMdl6hiQkfhSQtTboebP1u9kUfJupYA4kTelqfujkf6uaz4jigHnXlZ36x8W$vgfvuFU" + - "thyUkDxoeXSQynlmFkeFuCOvp1tudE6iNKv$IrWVm6uNB6MKxk2oDFJQTckg5MGjLILqkib" + - "hnLGcJztTJjWNk8iP9Ktnaba2$oHDO$ZdsScWQEhu6wduoor3cLRNGU$ppNeuOnQuZNCBx#" + - "Zf4Qsex37aTydB5zzJDzNO2imDKlHhx84$dgLzfQ#UeIl4YVMglmBnl5r9V4zsBlnVuKUoW" + - "SIlkXn4RXZy8E6HTgyH6rKliPVp#nVTZxQFSH$Ct8LnMmWbm5VLGmjgKlolXQSQVMarnSSZ" + - "T9VOxJzhygCuxkFzkHcxErht9SKVcEF65ScFW7#KvzNDgxjjT4JDTdcVQx67yNiSLGQmcsg" + - "s#9BJ3oLHr#7UTKXxsQs6hu8J6hX5e1Lp368dABi1SHcmbd4dkDMgqhs5U8RSBUHDqcQhJz" + - "lL52RIIs4NisDREfjRGQHcuOEKjFfFqSeQVU81VATsoTYpUXJDmN9Oo6Osjjfkrc#8DH32M" + - "CVHNxAbm6bz770NW0$pFwMWVNyHa#OUGXts4SPObor5ngvj9sBhdtq2JyIVXQNndvQXwS1p" + - "#WZpNary3rnDOJMqj$fx5FOn#apuCStq5YMiU87wFsRIFzpGGnvAigM4M#4bRIfjBO2UIhm" + - "SG6mnHjKjXMsewZJDmNFykn4qBFoSNLIjglfEOmzY7iGzWBuK8u6MfD8JS5$cYar4bualp7" + - "HafjmTz2lscO9lO#V1yUWKVWDqOUYgcliVl3LswW8KRUlz9Rr6gzREIhT#3$gJb6dj1gW96" + - "l#iA#vAnYHkyQ#MeG70Jxm3vG$$#5VePnDG9x1FOOE0QEXgFXUFePRnZLIyJdSvtdKtTKD0" + - "r$6fmAfy89S09S2fV26N06P9UEOkfrqK3Hcty14LzYs0=="); + "U9piVGUS54NsVtNt4DR84WM96m6H9KYGjAYeO414SCqO41IGe820A20evXmm1nHpJfZ0T6P" + + "FpxlppeGYvdoUuT9q$R#lGdTrckb5O9RVV#TzgkfLrQjNtwfw5RgdfuUnqvzokstEnBdRZG" + + "ra8zWmn7ROd8cjWEjlNy1TTuVi3vi7yIV9MRtvapwneQmu#mDh0cutv1vglyKFPGFiKwmJm" + + "Q$aXqR9Vjt#8uMib$M4zQHzcVMgzOhrclMwzORrH$jj##Q8$9ls6#4qzYrhY9pL8dyLQsWV" + + "RJzlF#iU75SVsvMTuUcwKOLti7zOwzWNzedsHFi4woVhtzR9zZckitcGTP3hi3wP8ZOWmp9" + + "jCWES$sJiJ5l#2$8ocmUn8ZTZdsVtjFzazx2hs6ViVRkxlGFxE$Ass3o8mKLQS1JxB$AADW" + + "zYsxX5VWkoNxCLQC6vx3RaRRLv4DlMtSfiWJCCBRZKgKRUbfi7iPRkbeOLjNAkGWjkSYv3N" + + "jUwJMoG39qdmMCVO$kpBgoCDMTRiItPOhO4ULtgDg45CYo6Qy9Q6otObxNBx8Ay8NMRq08P" + + "he3hpsupMd0qEnDZCCGTLBU9QMuiyUmuemMpM5Us4t86rcrY2Y4hWQj26$mMdCDsPCEHDw1" + + "k4reWmsAu9e4MFCjwiQx8sxbk4reWGtBz0oruc$N46Epizg$RX1R8S0XSDUljjy1gPpMqjd" + + "JxP$zR2BBij99ia0hxeTGMLf7HWevi67B#KmXoBqeh2Vmox0CtWErYu3#QLKDJTTqcjhSCC" + + "oFXDou4PVPDAybFaI7hHJpRZvyI9NO8wo53OV#DtKQ5eCoEQINvF1coASIpoNnUbDY1x00L" + + "7iJ6GFedzoUx6$cRagnRqqgoMnItcpM5Rrq8SZv8AsdjgCBbyBSe1Bcxf9NCJ9SXEnH#KI4" + + "eCoEj93jIXSVo8lUtGX0xCRNaoIfSwFx6MnM2sDAqakwXHecMXI3teBIIx2mLdWs$HI68dP" + + "TQifSAUy9lNWXYLwQMl5w5DyDlLWXoTqqhoMvNuHtmcnQ2tCwf9IjLM05$cqAGMvvQiao5f" + + "N2$5eHAKajsKc57k5yAGXrIIxPNOJlt5rvS27BRffRSNeLju6zR279RfvRSJeMju3Sf1Baj" + + "Kqksa25R3NxhGX1x9hNaSofymJwVRrK8Oi#dblo32b#3lsKXYBsUMl8D5Vw9R#bc2q7idTI" + + "IVrFX1swMPmf1R6rgoIzL#1Lyfn34bgUM$4w5tyEt2q7PBz9ACbU57BvL2B8QfvPi94FtGZ" + + "XU4BeWhQIrZGgtXL#GZzKqjUHsAcmBxt#58AjzQibo6R81yFzR2B8wfvLamrI9hl3$KmW2W" + + "fIILZTLeZ$yVnU2h9vf9J7siaGV#1lvU#TuidPMuO1yadokulOI$DvyRfJOJkvU5Bfxi$VO" + + "#swrksqXo1gOLf9Tf4eCWJ#u46JjabfoLnNk2VzVXI1hxzII#wZmOFW$kZ$QtSZVb6GTarf" + + "okWfdM5FSxzplWFMxJKlMIQabvwXmlZM5iqAGTLfgoGjLU15dxZQ58ElQr9AtA6w5kmrlN0" + + "YoLgIMl4U5zy9lL0Yoxaij#R0A7u7Vi11aFPfQyayoT6#5tw0GbFqehQJrhWe$W5#GxnUj3" + + "rLObbTsZWnPB#9P3U8HodxCBgQG5LlRioRELuNv7jBwHeNVvfKzMNqFEOLuDXVn2B41zaWA" + + "qRQlCoETxmkphcJ6gjMYUzvrfQKCxR$mnkvPzXxkMLP3Yxbd8HpXdfNPcpYVCWsiDiu$2pE" + + "dtJracFqodoJxK9LOJixT0xJSNMw$u2vdWuZpIJorqjbTxloB3sShx6uOlLvyE1zkhoG$YH" + + "AVnCzHHfFzWRq6$ch1hs8$oYVnhHzZPT#r$wPvwsSL$k9yuVwp46JzAxNaVsN8Mx0LSDIdB" + + "NWBz6dExo4J#ZJrTvxeK$9NiUMoJ#qTyvRefy9XzDqdi3ONM9lpvi2Qwtl89Aofl$C4Ll9N" + + "sNighCFpbXYXmdruS$SVXI3xuDII1oZkXqAGNPDQyWZ5VLi8iiUdbZnMSTyNWkpZKqjEKzp" + + "FXI1xHch9asJ8zyIStrFC#JtvdfZpUoPJufpFKKQJMFFtn9mdVfKzKyvvDZHMbjPypS#MeT" + + "jmmvCznpr4S9qYUIATJO4Rp6wqvxaDhHUiFrWlMYzPBxCLsN#p0UosxBz91loWxBzDCfual" + + "YPpScOEMvwPcPa5sGORdjXbR4yHZWtdsAUAz45mHx5BsJYtWLLbDVUmDUE3s3wuteSC7yG7" + + "MLt8Jo9wDjT5FTbFsKdPJudOmTbFhR$dAgC9vVQ4XXs4daNMU$PfEEakParYwrbWxQXvPxR" + + "Y1bfJx6xMgVPPV20Vw5v4VX9PfUnKDW3e#i0DiFzZVyw6sj$Ol#OgeudjOvN27o3qBB9$ot" + + "wKwGYS3MBhMO2pl#RVKjps4YUxZ6$FjyVrpFR9v5xCBdKljdzaY#orx7AMSI#s$cmTcjavL" + + "nbDR13h0t#0r0DDDAAtPjh5oYwmPdbr3bLS6yBfdcSvl0rlWzGsoUJ$oiYwsTcEVYVbdeUI" + + "cLnbDB51pZpUncbBl5DcBP8uhKjYPIki1Pftdb3SOTOKVfXxldKgFumVvkn7Vf3ixUoczZQ" + + "2yt0wSvovmFcCUxvxllq$Jx8pj4r0sCHkBk9jLBfjjsNVklFi4dSUOYsjLTPgwndhMUiv#o" + + "B4A#oCtT1kR6zXRsMtjplQPMmDnbtfP7qLTmZx1rmMg#WX26yZFucCNsrrOzy2vz#j4rXVw" + + "x9SPRoo5pkje7yOyUuzJZdhoxvnxs5xnSbQ2pAzDSy6AMuF8Dx3lSUwaU$1zx1$83#9V9ps" + + "0vd#mFcH$GWRpvRdAgF9QPVfWNhU8DvVCsKyJE8wKV7MCCNjPi6vPxXdyDtuRlOXv2SHpGN" + + "xptAcmpw$aQkRax7cvIgbo$AF#6wmJ$2PVlmZLRPnh2pXLBnzXGpTZt6T#B6x1FIn#p6k4p" + + "zE9ipqFfZf4kVRzZVE5FTCzqndVAuocZ2FMi4V9cffWN6NEBUEbGLEhyuh5VS1S7vWN#ESu" + + "7xWVW2S7oIJYTCQXlvSJbVmza6vocZ2kC#5XZyHd#beZyhCPiLiA5iM9ojmAZxxaGpvhlOU" + + "V5TSTpVWko8SGNuIsJ#wVxJN#bQQwO0uPdskCfhOmQmO$XM2BtPQioPsDtj0zkjOMHftnMD" + + "6YT3z2FtvKVPZwpRt8$SZzET7oMHVnVguVrSxqGhx6#iETblcm4p$N6KykWtqaLLCV6QCUw" + + "arnRqqCzvg5YSh#bFpFobk3N2k0SwttJNk6k1Saqo1SNU1yo$k9LOdzv9SPJow0xJ6laNm1" + + "rh$otxi7fZzqhe$JZPpc7kWvgqEYliGE3zqddEUTpzqFmJE3vC9EFy7d0FP3coOtSVTshuU" + + "DlOVrYHN6O$#3FemiuNWnzYtihxkc4nBks#ixDRk6Csp7nNtlbK9rzhjuBxllc$$G7uI6Vl" + + "8PyxZrd3dOViH#qxxdbnbFFehw7qsLF1ZsGhW7CjkitQBayrivOxrOg$9a0$5IZgKNUQ#ne" + + "VoeLZdXoOJJY67MODnBkndVsrLMiEjri2vgxq2wsUEKfASVN5U6efp2FZin$Qrs8zEjrfOk" + + "yVMG$D8yPX78dJNmbBMiiliszorxbhqvzfaOfVoDUxhm3d8$gzLmTUm$lOZxkkPNhdAQB9V" + + "vkyZV5N4QlZxrb5k3Kx3hyR9PZztQmnUXBmQwr8rkopxCQ$crLYNgfC9ED$5VbvbLVE$MSF" + + "13yoqm8xzD$HdZbAIxBluE$2V4tgcy7VGdnVOksIsZfFDViukz7d53R7lvaFOPKulFWJy3#" + + "Gd4RlKAhFtjghilJBbLgbzByRd4USyv$nSPJHbFyFwEOGjqpnmBiEutnvR3usxuj4VaXkCS" + + "yXWWNCm7moSWvE9NMgFXbLMsVjdkjZVuNfbNzZdzpY7g7oR9PUrxuTz3ePz4h#V$I3hOxLW" + + "0vpUSR9qVUFLEKY6xdjObzx3zLLNzpttFQnBxuL9dZ#90yu3iny1vrYiem#ZrV#mxt5Qi7q" + + "Y9N3#564R5SVvqtx2QMMNO7z$psxfRETUvBG1pchxAP4VEdzcFyUwgdJ1FaN8#pejUL$Ceo" + + "TvNzuNLjetIkASZ936tQcqgfm$EUsTJavVfvypCjECLKVawPninctKSfHp1Fo346lf76NVP" + + "l$1cMQriA$pP0HEoMS$zt70FYMta$qYtqcC#qvy9#TWyiCaS2B4FDgFnjtv6wqicMFO2kSm" + + "wr2ShSFoXDECst0l0UTEV1zmBPqtCuS3orVPBoak95H$obZsS$ihNHOu9TVRVeNt5ZXxyzx" + + "ETFB3970Y99nyX5MLQMezdZdG6fvfw1p6HzYlHkG9fnctuT#4UTGRry6zxPQPRbQpx1U4q$" + + "cpaj0uHSpfvGpLPTcFYkjb$vNt4ZX1EB$qIYPsgVDtwizCwqntAsCDnwmjParGTuuockpt#" + + "KtmtuDhcMcUwMQ$RxN8VfaPQ4WGJi4vyvtBTQfpYk9wylTuJzZdX#04dqnad#mdu3oO$zt#" + + "mlx9$gVzRsSK$tkkCXxTb3c4zxHTue6IExRZE0sSBqqPu1IXK#HiuzNve#9wE1ru3$HdCU$" + + "1UrWjo4yYz6T7fmGuZtQwiELELwUximF2gbnbD3azd9tW3nHwbZk3dC7mTt5sDMM0KyhkZh" + + "LEbzj3SLNEdhmAEFVcLU2F9Z#9n7m$2ZWdEeSuX$AHpcHdWdEYCp5N6KsOxpFWB#HLTaiWF" + + "DKv3VuYvo5VGeoxb5tYdE6bxwl2xivPl3lmxykxWp#R$2HonZddE9SwrzjNeuuhd2iT2gzn" + + "hirLHXCaRu26vRmxvljTpdtEOyxzxj#S9tm9WLFMywBp5w$ELnMte$CIt6lE7$cE25ydFuc" + + "Sjvo$Ekywxs0VUT$vs5dhVEvyPyrmVifLnYkxrlalV9VlYFvymVcVmpDE9cEzwKi8d8AprW" + + "2dIirigRXkcIPmsm9dDyada$DMfZZJAhCT6v3PFjCfKvBfp6$Cx9JfawkCfapVp63urRmRv" + + "llmpAwP$JAZCljd3lKb14ufUn1mwd8rYjiXSoJSEE3SGVB919n7POxbsSna$g$C2Votp3J#" + + "A$yvSrAkCfeoyp36E$3$YTW$#K$yH$uT$vR$OCe0f#I#v$$rofsdkAxyFxmhmmTSL#c7IQp" + + "pNQLKt2SYJ#ky6RTr3UGmxf6otZhVLTUZotfS5t1TH4uNoKT9uEmYfM9nXkK9fnctTGtaGZ" + + "YbXCRPHTUZotfSPt2THKvdoKT9uEmifM9nXkK9fnctTGtaGZYbXCRPMTUZotfS9RXAaLCf#" + + "J2f#ugLKYeMPxW4uQImZOhJVKLySAw3R0WdvOVlAnewFQu2N8N8gP1yc1JE2YaLYpDSWd1I" + + "s4R5JPmL8PoK7uTJwVAuSd3b8gTSyc5IECkbL2pES0d2IM4R5JTnbeTmKhw7KyJAJ9qUXrG" + + "kSyea7oQ5iqnAnU8Cbo2S5BPHSHDdMGWdvViuALPcwlIuKd2b8gTKyc5IE4kbL2nEBTbPXO" + + "IJmZOgRk8i3U4iZRdlRUZKdFikO#J8btoOrFNHkr8gxXCfGTT75BPHSGCdOYt3PUDmQbsQu" + + "pi3ySwY1JjBFaogFtUMKh7zgIKxgv3way8sAcxsvywX$jmveJ#LJidPa$a0S0D4pW39XqdX" + + "722bOd5goSug99mKjb5n4#U04Cu12JYLJe$h3ww$oEal#MHAn9cZZ5bMwyzNraptk7xW#ec" + + "SVf9FfaISESgOPRN#V6NDT8$h0wwFoEaZ#MHAn9cZZ5bMwyzNraptEBAP4f5J8lbaIiIPeu" + + "nPLklFLzPCzxXEu3g9d4wIJwP4d3dAc6Mr$dnbpNIFmqpaOZRojf8FavhlRQLKB4ujsLc5D" + + "DyfRAFYvdnl6vhlRHFckzBfSQt1jHOvhIMVJ8auSvGnoshz#SgQwHwt7RZjHCvsaa#cH9mv" + + "ofXbjVvyPSrqZzi5t2uYPnV99rCYpXnbpB9QVxwoPhh7xGvkTv6pk#IJAH5dZZ9cMQq$Nra" + + "ptUE6WHicSeP9FfaISUOeOvRL#lELDTCzhYEuZYAde#J3fEPxHoaLYrDBTbOXpNSAswYuET" + + "yxXkPxnuJvhdHwN0Tm7KHE1yc7IU7i8ALYSMh9pYead1IsKN4JPuSGpWu9E9LEZsiFhht8Q" + + "I$vC2cSxQLKB4ujsLc5X9F2DYfkucmVmja#0QVIwN7jmBKJEUqa7oQ5ivsKGct#Ko8KwsvD" + + "zYGxgv1mKjX6nKsSxIHEUe9TrXgByrMjKoEotsBJvJlOsI1xfJtKMcD$R3zcRGNP$TaqvtJ" + + "sgFECiqgeJ7WAqCRPopq0#I#HRntlh7QU5IWUimUpwzX4UpvRAIIUT9vcCzaZzYNiLVKK87" + + "sUPdUnkzazx5vs7tkSFS6UClhX5Vj6wWUqy0veNeSmy0vsO1#ai3E9tNW6xotepeiTMalTa" + + "Mo0DHK#SzOGThOSyeyXPv8DNs0VITZX0xlpIIxix4rdfVSCpOqqYlQoUEnft$NXF8JwSxqB" + + "nCYr7hUkjwwqhhEUSZhB76T7aRue#oN2kwp5v3kphAierrg45Z#ASB6rmBdDMgiqtKKDoq3" + + "IMe2yK#sth1rb7sVEi5TINlOZwrIIpInmxjHzxDoHeuyl4pPwkNM4j7DX7z$BFXOvkrCViq" + + "k5VImIzi5ozl6FndDADygP4j$7$4FxhOomaCoUP26P8dityoturYYalcx$CPU5e4$FHP#UR" + + "JsbqBvfly5MW1bWzwAPGdtYThREiAwoLmF3R$Ogwqm3VQBTGTEZXDxTZwpRtI#AFlkfa5ej" + + "95Qv#scjrbpcP8xBdEAt3Ur4sp1gwzqsPxQzaseRVLPODs1El4EpsBfBjyqvpc#RzRJrF6P" + + "nVwdPkidKR5rjFMWFfhQXp5Bx3cihQrtsqz38V62W$u3GMyjCz1ahFtgHzn7x62lPuzx825" + + "uwdu1#7VlKNWLE$kBWFFj8s4zNMcdjfR2VuwnZBMuljiyGc8z5ga3FFW7wyJ5sTHrR0KVFJ" + + "b$7hxDNaXyajLSGbuYUSlqPwychag957zXho0AiAp02g$IiG8sHdG8#FJjz3N1T8t1Tmwy1" + + "hcl2bFqa#mcqWyk1Iyjzxkrv94#VIsJeuS8A2Lo35AvhIBVOD$JRSDzNkAxAHwgUd1Ba#$s" + + "L$LocY1NfSmepLLgELZXmWqpjzZeVbprGrRKi7obSEIN83usZB0dRH3WWqvZYcKPycS2rpF" + + "v4btLw2LomJSngZ8PNrvNvY6mJiZabo0$XaYK9rvKwdbdChnIuhdGEr6Kpc0UPhXANs0rEL" + + "tLTaOyKhfmIv8Tm8IKZxtrUeUFa2rnNO1nzxOJB7yT$gRekpqVPhxDVGpQ7XCmbEPBCB1Ou" + + "a9BP0VRrDULdpj1oo1g4d2M#TWEJk9je3n8vb#KZPLyv9QHlrK3m9vAs3Z1BwlBMMF23YBV" + + "syyhwg8O8LDMghalpaTAUKuByq3YAT9SmNsfPEiul5UDuAVfCbQNdRgnFVNHEDrNN9Vb8uS" + + "efuSjvwvTAiKeH3d2#eRZp8$X1xaMwX93nJuy$YvtW5vc7lUf4ynGHt6ap2rFiLP#nzqN#B" + + "yA65qTssaMPCwoxw2mcJX5hxLKPSwTbE8ibxBGueSczAk6CpFyHHX$SQL7c#$mxhPmFMPfl" + + "vsV$HUYp$ygSaVsNIPcp#Fc4dauhvWdEtssH7zXj#Vb84UWH2lHsx$09FzJpjmUnkwC9kpi" + + "w6Rl8OxwTgfvV0Il5FabMAavm9RIVEJFDVLQycJxt2Kxs$8pudbTZA$h4kWjdfpN6kP0#Zr" + + "eVMn$v$HuTMzNlnUv5R9az1jo3x65hA5PdTNAsBc0hdNqovx0dsVs8FiBkj9QfvyIRiBYJi" + + "xQtyvssrkNMNGwprbXOxR9VaSj#PMVpOo8vaXUVwH8J6uIKnxnshQGhHnEJrPzAM3tYC65T" + + "KvYi0mWJvDOuzqBo13PLj76in9Jzr1gTt4#X3s6YZu79sGT#odvoPaVxoVc3hzvfc6RiefZ" + + "4YVwnxAVhWobkx4prpXOfC1KZJreIzUnGlv$eDELsbPZ00rFcW20cjr4S9lsc7i847t5I9z" + + "vjJvZq6uQw#f9nPEQAQvB3vVMMohbCf5l4M$tThl1xq3K9vJgOtTQPD5Eplz5fAliRoMP$8" + + "yuaWUePIP8NSO7MsL$sXyor3h6kqP9nvEk1h75jg78kCciG$Y215J7hRuJLl4CXjAoMn6w7" + + "z6hfp8$APRva76aveW2grTf9lUvgPsUH8b7HohGoWegqh98aogoIBe1AvVgISQJbY0AeLcb" + + "7ldMtkygvKAH8LAkYg9oUGilJaWI2fwKBe5AvlcGSQJcY0AgdjIFVUiYhHw9wEZg2JX#XvI" + + "b9OWIVaYw0IkOoNpAEj9pYBoCdRFufPuJx59ykqxLszocvEr6CJm#UmfIc9oLHFldkatGAe" + + "rm#dK#dE97rXIyPHrfEycYzkYQKENoQoBb8ngtFf8oCyMaHL2JxX2JA9zzzmaCrZK#ZE15G" + + "UP9nfEKaRw1wGZkPJhxrfUHbJ9m40lTpX9R79Oduu#Hen8NqRpJYEjUNZ2CgfobWLuzhvzS" + + "WV6bNZrk$HkngBw5bfIHXLokb2zYLp6M#P1nfEScRfRMJwS8lXY$s1ufPGoCZI5eUaoJYZv" + + "7J8wXaH2v6q9EC8osdDNaZ#9XsVWtMT#vZVcxC29AMHoLPT2$wKQi7N704HQwGVJIPgAodo" + + "Hp1HxKZN$B2boFug9MDZE2HGiiZaiG8FY9TO0naBlCbuqZBITuiJSvQ97BkjXQJh#l8hdCV" + + "oQuZiXParp5rjUZUBMGVaYJkujBTvOViSI9RNlKjahcYreUIYSfvcio#UaWxyYKlVT5N3zc" + + "7ew#AqLUmCo03KckeqFAm9D5N3vEZNCgNeSfblcGSQJd96ttri7OoNVZ5yAMrFnnhxQIbdo" + + "GHxqTEMhibdZs1dObSMBid6KTKpjJaMNi$xRmQ1Zalk$tyN6DVFbodWlfA4jRU5oZwiYECn" + + "XucSuLitsIYiZvlz9N8uIVgTFAplqgVOjbVdOhihoOfJNqauKJLdtpNUzx46U2KKbpc#f9n" + + "fEKaRw0IENogJYS$#ulqAPRzXK$D$cAIqhIJ9EmmKyad9pzyAfzASPdhIyQHbfEyWKhay1D" + + "qEldPdwLFiUpF$8JipoOfJRqb0SK9v9DJg4xW9r1SvlgISQJb96#W4ZdyU9rEVkP4ygs3A9" + + "OfuiU7xs08BRqa0SNnv9DJg8xdnrDSvlgISQJb96#W4ZdyE9rEFb3rKgXw0TLn4LIafQSae" + + "3YEV78ArN7yE8hBN5yoZhISv0rK8eTFrEda0rLFXQedK4sCe28jFIG1nKJooIbK4$b4YijS" + + "NpAEj9pa3LGYXq$HwUG3LG#5gWTGJOcW8YrLae1Y2lbkbOTg2fz2SPdhIyQHbfEyWKhayCa" + + "wdNoWgbAege1gSWGLQUak2IWcaqzEePhC9rDSvlgISQJb96#W4Zbyaaud7wYwArJTWMfI11" + + "LfsL4IK4mYdvn2DObFehZCzINZICiftllDWDOeqmK$o6siwn1XT6qdBGyged#zUn1f3ygrN" + + "Md#GUOAsGUJYShvlD5NCgUhJeS$IARgtEYTRA7b0Kb2wW5orf41lIhNbumZBKSKE3Cye9rV" + + "W$3b#GenwvJG#MgIq7A$925zltG1L2hNbumZBKSKG7M$TduDmfUe4BCMXb0j45hkaoIaxvC" + + "kW4hb#f9nfEK4NymdwFisxdquBwbS6KUUgiD#2w7tF8JylJoiUOAMbVUf#GIKIBohIPBPZr" + + "2Ahl36qDrITxexdUBkTFwaJ$Pgah9NWLDtDTtf$frUy84xlNHIiMyKTm1PqfrU$Io7FK4yP" + + "t2xqQ$dQkoY4JdkoF9$#$rCs2swb$QYjPFLbwsojixifN9MiyR9TwcZtmdRRzatAcnts2kj" + + "TTR4q9tU$DX2TzxaNMYBzhuGGdkryw30rdWziKshDJRw3BBUvCVw$MRqVLRqwx5Y15VJ2Fh" + + "zPjpPFrRYifzMT$QF9MtP3#mRinyGsNTaFx3MkPt2s2YFz4kfA1dpSP2MKyEh4Mx7fjDyHF" + + "eWwtIKE5EM51BJV8JsyY32xFkGUbyGXH#u7OCreoxaiNbigfAAaEmtk4cI4saQLHkFQqkQq" + + "8EFaYzByaSfJiuaMzmNGFhBsJMGMYE8mlVT3k6QAK$qnvfuyh0nXOtIDABs7jU9DA3E#ycN" + + "9Vdz52TdabH3OVP3I7qeYC8rRljmpPGdi7qOJv4nLVB6c9RAgqLAjvQWn9co968xvfuBa15" + + "p8VkXlHBbPWThNi#dVI8VxscViu9F#zHgddvIstbQIspd$0viFsnaREVz3cp$sCZOBluTsF" + + "wvaR5T#Zkm$MSZOxjp$R7PnsnaR0$y3cp7RMHiV$qTsAPkN6psBxy3s$JQdqEi6hrdMGU4p" + + "o5qZMIDLQXNMsD2vxSZV6pEaBpOPcrKR0VcmBPRNcmdRqnicM4vi0tFYstkHiMsHmvio$9X" + + "SyQitxdNj$eeDYyd#bIBYUswlDWENuzvQjoBjXQfwuN5xktkxJukkXSjrf05FZRdDdEUMgV" + + "cnROuYCsvSPFrsyrviPsv7lQsI5dROlTEzyxe#aPFjSTZGr$LOdrpBjumru1ndznFKQN0Ti" + + "l6mHPt3LXhR2lgCBQxwp2sD#emjW$hCBQFwZ2sRzThpp8#6n5RhQ#pqc4JERzpVSiCNMziW" + + "qBO$7thgdXiKLosvVzM98gDxL5GR4vERFCBYgr17UwtHhcmsUi$JpS4jg9Ss9pcwukDZmzX" + + "CpuoBnaR7w#mRQdkzuwd4f4n3JyHdHxRZ1pOPkJ1DaDXsrfXcq4bDXms$Kc$liMCwROvvq9" + + "XiHNNOMpDwZ2s5dKOMwiwZArr7SQsVHt6rguEO#jGXx5rgiFOIkimjd8JMtQDVQFyni##8x" + + "ic3bkgxoYDJroQpj6#gZ6AhJA0BVGTPHX3$kye8mXYqdIEzcN966nT0jW#W9JyZfd23yCOy" + + "dyd7a4GawPpjA##XOzYEpI0BVITU1Y3#awSwU#n4xuJDn74fEaSxSkICTWc1US2PELtk#$R" + + "A$roVisRT2vCgSFpT44TnhQe3cDRKeUndLc7iPrTXx7TK8UntLw7iRrMXx6z4zYpliKvv5i" + + "Yd4E#ZJs784zAnbCOGLoQpj6#gZ62pNaaWEqRI7qZYC9lmnY4n3TACfOY26BIT8xsPSaORE" + + "kSpmBxwJTgF$q6##atOGoRTaoTh#kklJa$r65iFzTXRBy6xQrEOVjtxVlDEI0VDl#xvuJlP" + + "HP8RFnUusrEzrBSEfNVQvAKv$TczjdK$SQFDh0TJN5o9Ybiu3OvjYCDR4TId9n92XkuJOxj" + + "7WFRFHGdPvB2Ta#cvoR7TfI1xIYAapD9OGEtYR1DLzW6cVEKYMUsuNTWnx1XJBuNTW8xZQr" + + "Lcj9XcyUc9c8RhUgV0zU2RMzW6nNJRmyP$VOGnScP1C6Hb9OvWkctmSosxs3dnhplKVt3D6" + + "E#7oOghiEu3t8wnilxkfMSyjrz53KatuWR96HL65jhg9mdFrt51#aqvSinP6OfNKFg#kU9j" + + "xzqprd$#RxkGFq6ylMkNtvorv#c$TFrht3ahsZ83vEGL65i#qFbFFaRT5odUTAJ5KqdtuWR" + + "96HL63lgeNA#l8xhD4zwWgB9v1jnWuIi2cDh3PNpvNLSftdI#ogQGBuHDqZ8gZ2srb0vNrx" + + "7TPedFGtZEe8DG#uqbzvRCIrAGbQ5iRM6oldoEgxJFEb9YgQHRyGD4h8gZAqrLCwNrt6Tva" + + "aVgsWI#KRS826hmjXQG#LyUHtNQPxqL4N7ac$43HAoAeojDLJEbzTndUP9dw1eAlb6t20Xg" + + "yBOMaFbV7aTrscUz1H59v1ln0qIiYgChJLKpfVNSPtcIH#lQ0hvHjmW8Ql2s5f3vNnv7TTf" + + "dlHnYeudtuWR96HL65jhg9mlh#CwpPEUgEWuyesuGK9MXR6rXihvyZgkqppfyOecac$43HA" + + "oAeojDLJEbzTndUP97wDeFFb6t20XgyBOMaFbV7aTrscUz56AZY7VY1iaP5KOMsked2#lup" + + "hDapvSqL7a6t63XAmAOsiDbVFbTLodUTBZ51rElX4tICYgCBRMK3bVNiTrcYTzXA9nv1jnW" + + "uIi2cDh3PNpvNLSftdIHoewWdmZRf2GLM5ihQ5olhoEwpHF#cX5Hv9ln0qIiYgChJLKpfVN" + + "SPscVFL#FUBfFOJHztZ9Tt6onFVhHT$Z5TOWGtw7vgrbnFCxtAVu7IPfEN3wxOYNqria6TF" + + "lsF9qFYbHGLyIgfZtU0KrgF0ipLlB17yMfCyoIKYD03T2SIEioyaFaywDebKrZP3vCV8ZTE" + + "Z93MVbS1GR3XeX$13fNAK#yaqjvSJBwxXEWnl6AbtnJnxkCD1muOT8vvhl5GtKDqoLLYJUk" + + "3$CJwMGVgSXkDsH8gvqmGa#IZgNCV76VV5nxZ3gsrsL3iaxj#kuJeCx6IadYzZ9ae#Ipari" + + "tycgj9HkAjftifzAeMWVSJEa8n$XrkI7oSjDQjyCcQ#acsfvvm5TNkk0coKT#Q0PmW#Hpes" + + "pJPcdIaVaTLodmSsKZdpGBE67IEScrZTJbPRIJNrvNLxhW3j9El91CuKV8fqRgcMK994tof" + + "1kwilhybe7t8dIaGywIVXX6YLpTItiMhzEMLAL5gJgEz5FzMkGgvrp3vKJgzs9lXvopgrvr" + + "#1dBBbZFXDiFRrhrHuiqvqQvnZ$NQkMUikx#mpVMnB5oETxEssTgSv9ZjAXSvscMZ9CiXpp" + + "v4q48lTkgKN4YRyRiRjDKh9tkxE1Q3R9khCb7oM1MeMarseH6l50EPtcfqe9KS$1aeIUWmt" + + "CweqPEfVlfIN3fCjPYvpZYRSM#szorHf9pbh03r94PGxIx#bpHbkdMcSAAPKBEYYUICR0U9" + + "3MRntcvoYv6aM2Pv6FpWNLn5EmdDJantmjy0zK9FYOkbGkwC1u2fQJcloOhmN#$ee47rENo" + + "WNj7q$1SbAJ7$Erm1#bIF0nTQbSqAXu2fQJcloOhmN#M4M2ZwbBvOB6nbEmdDJantmjyCSe" + + "4dnCNIeND2QUWkMa9Z$cQu5$W2B1nzIbSa47n5EmdDJantmjy4Sh4ZoI1mRkfkjyqZewdbG" + + "vhNrqeERHNkfeDbglrvHgtMKqIFMwNA#5RE9xictpVpv7cZLZlQRrwLonNZDT5wtNWRgOMH" + + "Ujr$dhogwL97bLbzGYws8orrgc9SCaPAckq2UxDXXYTRr1kknQzmR9HqdAoL2LbUT#UZFxM" + + "jbQCrTWa#V#6nBVrFvFLWo77Ixxp#m$hRNW1UUJrrfLbxKiCoJOi$8$ocHTUNgsi$iNzoy8" + + "czZDhRNMztORfS7xZpAgosxfroNUYX$p7sNvwp8$L9Tw9#pX$diDuYt6tsl4UxjIMOnpKw2" + + "sxprhyzOmgikQ6MpNUlVXE#uxkWyHvkx3TvBwC5EMlwvCuD$3y$MXhYlQXxMgI#aIDTuLxa" + + "FxIstJg2j15t$GdtNyGVjJYlC7JSfC85tymUptaWXtzdld5L7BUsQRAPTqQSam6QBIZbxGk" + + "ACVYHjb4lk0logTDOo$ob$DVY$Z9iNtj$znnlfrfPiVPak2VU2jSY8NgroEFb3zxTqTMVy#" + + "43L#vAFpvuRNndrCAUFV1zwqEsEjUzCPItE3yiovGVy#WBc1VBkbhp5JYTpO$sgaZ$kMqFY" + + "Md6rXZI8i4L8jWxqOfz7FpMT9zBzQyZ#uY6UHlLbA24sVn1ExHDwR4Mquopqh#xswLnEwJy" + + "D6QmvbWcCtoXdhwmYCtISvnswazMR03cP3rxb9Tf0yXpr1TP$6kZpIAxuk#SRlPNvkKg$ar" + + "wKjG$LmWYRI9IpZJzeoif$4MGRybbgdh2VUraYFo2MTRqDN3ckJEWEOutM#7RJ9w1ZajqcE" + + "#S$56i2FaNoK$5nT3tz5EgnYhqWU#Qy42FAadNz33XBV4EamI4A$2lNg5hHL7dhQKTHD9qf" + + "ApsbVGYBLccNjcCDMGq#YM9VdqsajotU7GWcEDdIrODiRkemhbjHpYJuZoVxppS$K#5Z#jg" + + "R0Lzz$lwl$t5CbaIpv6wx$t5DzNLI3hqlMLll#2#CZdRukgwGG$HUHZ#eCxS1fyCbLdxwHI" + + "NvhXNqOFMj6gpxff5K$CqMk#fdfR5HurSzCzV2nk5NVFbraZzJjK7kPk3hE$M#cxhkgXDXt" + + "hFq5WacPtHI25K10$sHBUzdAZFTFxEwxaNqd#Ma$sOEdo1vqwEe16aMTApF6amFsQjOhyBH" + + "VhdVKoUiGUIzWXQbHAHlb$IljQECTTVanZXIZx6kS3Otd#jSXX34p8Zz6mwHoO5GQMPfM6n" + + "f7XZGAZ85#hAr6beYnrXhvjSfTpA#LV9Wm9YVRguaBlk75$pWNI3alVebzdoXxWtCHlq5el" + + "O7V8FqGNSjlrxa8RzSkGBBixTnxKvgM9ovvJI4PkeEUR$xpgo5xjIXnjUJ3XBJxT2xnrZ8H" + + "loz0dfnNFrBa$4TECighqw7qIsI$aoJvY5Ke2N7A$YwUWjByUkjoVhtaA2G$IEujsU$SMoJ" + + "dteBLH3YJP2aAFUqlI6rIRuxsNwzMtnJjjpixyZ#qyvov#M0Y$JrGyZKZyXWVJAiqoGiqwg" + + "vXCCu71wzhfNwJ38sTdT$IO0psID9zirmzadEVU9Gzn1wGDJlxM3MMM8Em5zATN$zV2TL7l" + + "BDH$7UWjQ$yZqNhSgSj$OkxO$oV8QLdzDtSo7y7yY$GBy8HwJ18A7#k38tn$rmxGL#eC412" + + "6yBa5bD9Kokw#qAfFHkuHoJIlXRkTlwreCzL620f9qElt5VQ2VfQXK6wKwOB#Jkr2z1Nedx" + + "YlaJufRZs#XBqbV139FJeKFrB9$zCEq5VgZ183yXq8V#0TW7wJDHFwPzg9#Wp5GP8wD7XP$" + + "9xIRvEEq6VgZ18JyXq8V#4TZwnHbHIfN#YdQ1rAWoGqAF3TQe$rcedw1CL1ccbJ1VoAxKBq" + + "5fHDwL$h9sWjIeCaD2ZmxNgha7MVue$c#KVPsC#zaAPdhmwE5lnZ$LT0$tBWUZguD8$2Lge" + + "pI8IV8I41k8e5CurmY0ndMuZj5769X9yX8GiSTqGTdEfZcwAZn1JkIfVbCeXosGeQkXcFkD" + + "hpaFt9dBGD1N#JSBl9ZYFj9oGd2emH9ulDfyNLl8odLhT7BdDHIkRYr0uarG9cNkAT06C2v" + + "07nuR2No3Y4L9o2zpJ4C91zZJ9Hqd8gf1AmNrDJg3zMlAIyudFTfl3dKOSnvK5#M5Yqzck8" + + "XpaREbVDpdDsFxEzlgzPdosrwnTXRr37hR#TJOhBPt2E5jdrx698XHxXYFwpB6SHaOtZP8w" + + "X9x$aHC5$wVu2A5yEn6E3A4Lrqs#7ldXiyYHF9yb#IX9EMu#EMHyNodHUhcZ#4p4PegICnK" + + "V8Q5HXKuxKMua2tvc8rUXvIUH4oLFKdoK7fFfGlunxKnIUXwZrhiDY4W#kHTbkejrbnm$p$" + + "rKyyJvn1z1NWEPon$HBa0Ydtl$OyZFazhSTGZN2Otht7NaIywWpo7rkUBetug5CqbO#ZhDA" + + "SiNsYIdGYDNna6VGUupeV4pzpFo9MVG9v3wH75OzwKpIUZwJ7DAjz0cEHL#8kw8$SfmvkCF" + + "imbAssVyOVSJn95c4bl7Fir#ZRph8IVEnk2kptvDVfZ84bL825gmxONy8k7ewQb5eEk57wR" + + "hPIwBVdnBbB$uC#ODFlzq5t5SuP73cMILvACanXbXxliKvaUVF$agA#PP2Jf$PZbiajFvCy" + + "ib7oMI51osgwpOihAkvAFavyfIQhIMMdkvIoL7eNG1QfvriN8BBdxbLsMyFI3ySPiXhvaer" + + "ynjnYhX16TGKwGqbPpaHTmaMKRaUdgBfICVr5GvWxISaDGxL1Ffo0SLAsUGbjESjcV28B$1" + + "ydM4MjfKs3ETY5TBHpvVdVsA$30XSpHVRRK2EjEUlnAExFahnGlE9waP#BwA8WYkhExfR3R" + + "SkSGX57wOf1ne8SA5egw5ae#Ia2LkCSB5GkDYnKT8o2Bak6BZprDP$hpaeoJwYRZd43v7PV" + + "bpae#Ia2NkMOJF2etFAZv2GfQuPn0#8pG#e$W82LdYdaRujD3ujE8Z96I9e$#cVehE$lmfo" + + "KT9oAgGIgLV8$XJ6NMwoIoEMDfrcJFSwoH78UAd4kSJ#xEVwvMwLZho9O$yQqrYV$LplL9N" + + "I4U#v95$HO3EGUevafEyY1l4tXNbH6xy1tbdaqDhvuD3A5s0o9BFbPpaHTmaMKRaUfglaev" + + "yqBdAcNGrygwMdEH5t221N#LwUfT9Hpx2T#5VJPn1rulzJ72Ib$kRiQUzAqhBNKthlL4wVe" + + "Pxe#IHVsE0BaVUvP9pBuU4S2PnigO$obnXIsUWn3MGkePot6iaZ$nh0dGbKg#KdEH5t221J" + + "#JcicCf9sJf$$Pkpj0UVJF2fJ9kKkPiAGV2rRShhklTBpLFd4$wkpOX5Vg5hVkDTEGZx2NZ" + + "9WcnuxLKw3DQrytKIkn#8HqRvNwXUU9yycgcUpilkz$mbyKfuMKAuKOIvnFEk2#mS#58vWK" + + "AfJD9ZTKuyEE4rd5y7FcIC#Xmf1mkESM$J9n1Ho3r2Cb9NiHDmapdVvMSv4NS8FsqW7Le#3" + + "a3BIqvaeoMTj4BzCm2IjDTu3VSb$aR$2BY#1kGVyEQHPn15xalkozdFo5VKgX6od$1w$EN#" + + "KL8UK7dXF79vnyWzmBeEU4B4cMVy#NqVsLGRJBNedyqVKwKUSvQB3WbxzuJB2NZCjSLJnxP" + + "FxlFyGjq71hk8Hdo9SayfUqLznLh0VcAxd5Vedobxnwa8Awr1Kjwt4lkI#HRIuaJ$BrUtZq" + + "Y$rv3zaMZxfVuXJBktaiov4iIFNgXadlHVH4ON$JeNlSFEfzq8qN5jJQ$f5VN7qY6V4dWd$" + + "VoxXKvpnkotlSeKhUCky#J3FcIcF5ndmKzBtn9HYxf9WtwsbZmpVoIeMjcvakY9IyvpJZrw" + + "FFy9GgbCqcWYrmRktD5PBJ$7Jsb8tMqoXiLlUPNSkr4$aXtBeL2Ft6pSSryBiAHIZDJLz6p" + + "STOpTZd#PwmmVwOK$cU4JBe0lOaKUhxfPVwcveap23rEBhCD$uFcYJC8uoeSE8z$CK2uZX8" + + "EdCV$CK2l8#LrWVbrpHFdasvJfZroRfEEV7wRrKB60tGhKcuLgRTw$Aq1eczZRX6fjtZyBI" + + "RfSGU$7EE#NDItd4Bf0eGzJ3Xm7d#pITwOtCpYxfwy9XqRnL$JF74#QJIPdgQz#dTF#0gKM" + + "25gM85mDjovnFcaTqeXPUwKX4Rb2JH#tYYlp990cS3pBSZpsWCqj5EED3ICHhw#WXQxA5yY" + + "j64sY90nxpf7OI7R7sa$PAIIPO$oB7jawFaQhJq#FKawfYN1aGdKRypT6BH#gjQ7Tgl#6Xd" + + "If5jIMxIZZJpIv#Tf1FuJ2QEDiOf3sqkDKX3jR9o4pcL1jBB4Q7PJ0jhWBsC2QDtz9P4##4" + + "6q8uqd5aV33rY8WGjrgNtSw1be8mINYAjOgi7x40$vX5v4JlpuZaQvm3YI7g5Nf6O$CVIDb" + + "eYo#lfyP11jld5qvqlYX7s#6jSWejd8apqrcfyJoXDeaK#$53f7f$9pbRPH5BARP2rUsTd8" + + "eJtW7AJ8Eqo#Leqs#55eeUD3hBZYtpoiW$Y7xlnC4Ppnh$BMgA04#2Au3IuHcQVHcPik9Vg" + + "9MeH8iNz6RrvWfZ1f3If5dRv6kNCYDdiJc#3E4UUsEQetiIlhSnjw$mAzJyjyTmv2aI8u9j" + + "CmQdEykSH2CvzvUDQl5ypn7ksFTvuLp#i5lZYnNnZoHeQGpKQjv#fQkN$VGlRBOfs2K9zVe" + + "cNDJuh#u8jO$7w5sSlrFL#$jIEPlugEHdvmlreaIj1#5IqvMg#1VA6UlKolSxhMaSWphI#o" + + "No7VNoDk8bqYHMhrrzH0Aq9Z4ro3ebRjbnqLCnFCzJsyjsXDDx7uVIn#D08zoe8M5hzY#f#" + + "HePP6hTFKRlOeZTxfYRR1a9Tp5$NBShe3CO6VZfIH$2oH8xKlnUfyjc4RPx6RFErBPKj3#O" + + "oVZHHQovU2EujIA0$SKfIWqgFuKZNQVq7fluYr#Yy8ANuJSJu5#ceaVnioRukIRoES3NSkS" + + "GRz2NdYMNp#9yqJPz1RI7bBIBobUU9yolu3kzq$I2Bx3yqJPz2FIFbHIFoeUU8C#WafFmc9" + + "dpHFd4yRP9S8F9EPCzOBhJpJimrwEd2G6KEU$vzLVs71#KHsSARt1AquE$4pbRPHXbPje$z" + + "MCLtYC$O#48na$z9YV05YmPEUYl6x#09jt$mkQBzBf9cqGE2vIsld2v0oGMabF7I$MAttN3" + + "#NhBMBUybyVY1FsPP8EutFLssVZVnp4LTtdy6TYfHHb6#MvFEbDgqruPDmtc0Mivc3GMt06" + + "h96h34hObkmBJ42MxDjsBQi2IjcJLapZ4aBrfArOjknrgmDPbbRrewrnypjo3gn4bQAKIjd" + + "5QoITSO8TcKxi6viHzQTLR4Uh2V6jZVRYVLXVLa$rf$jp0QWtmQnmMm8gsP3sIviLxQR6AC" + + "zs9viE1l1zc9xittOla2y7qPpV$J50MmC6yiEP3Ni87OmEuGToWvZXpDwSz2H2l$upRmb5b" + + "f2sDbcr9A6Q4bZjYI0BQDQqXoODrrBRcHl62rvGxMaABObOr5NT4oUnPWy7x6kpMCS6g1D5" + + "j0v8NH7RZOjc84MJ6FJ4Px8Jc9ti3knEftCxjcCMb2wsRUW9j022qGjo6n6BLWQQi4neWKJ" + + "DgCMM84Mb6v6BPXfj81GpcUdijFO0hQGBM8Vi0ytknPq2RIW2r1kRYtOdCUW12sOYJhC5ip" + + "7lDXyMj05BNWPCRC5ZoEs#RH0Mb6m1Iqt#nPCtmnRi3JGWclPTGLhmNkrRi5O4E4mM#2mSG" + + "N2NxD1RAXm#DDRqECA$p8sja1O$veQArDOMm9hGrXx7BvPg9lmpHBsVtoTjtzcx6GDKKSSl" + + "e$Onm8VXRqBrgRpKxVfVDMctWMpgQ6fiOvLMFzNCAozKsCzsxY6B0pMLrDZNQgmFbumh5#b" + + "nhfSOIqg6DOjKcCjKbYtA1ZMejHOBOMrk61ObwV6sb9XdLumh4jJOoqnxcFKzJNhyeBFhVJ" + + "sMbIFjHvhFTPwhCQt3ON1MfeQQx72sgPWM1zDZVLHurgvC5Y$J8trkOAVNMwgzVdrcSrWRk" + + "bhmyg2ORLIOvrLyEkjz5WBtw$fpwyrnZU9TVt#dbFmkVN7r5ZVLrZN5GphSxM#x#8K3EkqM" + + "jl0p89XTMfzFxfm$VfwhVjrMi6mPXHMfvRtdbl6ufkkxZsNY#Sw2dMVDltPyMNZEyYwVjzh" + + "lCAwf61O6wR6kaHXlRTWM8jhVQrJk7wzjzRdt5iAXdL6hVirKp2i7LDZhIpusN59hS#vvPi" + + "HrlwR4TR2sK1bhTVNmjrBqlqwhPRdXiwn#7ghSuF5haHB2dLkqDUQyKz3r$OxQq9F#AZsPG" + + "LhatwsuFsyRVfMjMcMiAcZWPMU7o2inm7hloDOxofOc$Iz5YlrcOcXJRQeWt1#3fmpGpZbK" + + "olD2zQcYQfDNVAsgKgrQNd1vlujgTUfAg$$2pcVPsq6z#RJNuUL5loQ9VsUkgIWuvyUPr51" + + "STR#kgemEFTBZNFVWk8ScHhdZ8BYrDUecRmuFzc8EFU53i9P5C7PGk0iOGEnqfG3HxMXoST" + + "1E9FsK$aKAE6m18wDypJkJDM2tf4M58aMp1GjMCfgq89psBa6DWOTjcW1eIdEYOR28l4hog" + + "yL$id0NvHgt2ctByPOzcUf#ErVHS9QtmjOzRZt2vnVgd4w8PmrEN5Qo7FO68G7AfoPr3WhK" + + "AelIccSbJYvLh3N4t1Eyt0E3E6SAN1Mvi6vLE0y1pZ7CXUILoBrhLGuPneuILAEwFUnE9z0" + + "giRPEO2p24GuU#V4wV$Aw0lKIxyoeXehKk9y13Wl53WlGGc9io8MvngKYAvB4cUrm5cK4kS" + + "Fx4SFPsdANuME1SuQWTEVQ$7NGMkCSP$cuNmME9$7g13EJ4gS5w1UmdabqjBPvvA0VJP2kM" + + "SXVq62VIwBV2V0K8BiSxx0UK5Ad3UpfmNE5IXXfS8vXhtZhJv#VnR7ugGvgd5cF9n5m4dw2" + + "MVpd3XfBkoZPlfCz8bUtTBP9pFiiw5NDX$EIW$dqGREutBYD5UaOk2qHBbChUTxbT76V3YN" + + "172UZtMgTZWp7ivqzZa6LjCNLaCubq5#Dafd4jPv4sVl04xpkZiNpYBWzAtqBUIHbQR1ETd" + + "eJ$cx3HjvyTVJ9ivbwp7kLQ87PNzQwCzYUYq6PbGQd9IZSRwZa6w1SlbmJlYTzhb4uBJ4NP" + + "pqECzNwz9oI9UZTETOd9CWht7k4i19V1gShO5JdgAMm2yMQr9jSEhrip#ifnprt1QBiyh0E" + + "T73sHWrRg7spTphfx$ktIn#grkCzVFFx2#rm9bHE2s1CyCkpjkV$dLS1ZXdeixyE9UASm2T" + + "2s#6t3J8hG329QbmZZNc4KbDGrvL0ixuULGkS7PEXPDvE2r8Ey1Pd78UTHRhV97gpuRYF5#" + + "Ji1zPHdys2jZdJAJdjy#bOfSzHxmnPHgaBVOQi3PCXREXm7c1XvF6$MBsJIrmBX4uZqdLdz" + + "EC$lnKzES$s4#fS5h6k3SIzkaWzygyupujS0v9YxD8zUVD0jN5jJY7F6BWl9XzXbWLOl7tm" + + "wY#w7b9ZllyLEDUXFA4ath74NEzFEKv#Nm3vqnOfiIv967SEyUC#uK2Pxd0sJ$lkFygSFwJ" + + "$Sn#O$#gnJfliGUyTObmd0y#QTmjI4LnxcEC#zzIZZlXULEWR97olBH4u2nIu$wT614hSRu" + + "FZS4vgrOuvJoQ1dJJS1Of5bJxULIgSCQldyU0eljHiO7JIjcVX6cQijAququurwh#R2Jiit" + + "OucS2vLk1icDS#9wZryrx8Be7iafJh9rtxwt5l9AwMIY4PRvzTG56S3GNEBW9dLHwSIzWl0" + + "kUDg6UMEEzIc0PdAQWlkqdDercgPFovxYPnVHDy7fL1rXRtVGZd0tdxqn8u$qwMQba87qXv" + + "dfVzUMC8Ptn$teOwe#UG6u7JKkUGMJbnKfyyWjQ#g6gwIONfSCu2pcA1ayw3vwEUIbmNnCz" + + "tVpzo0jURJogSG$FWT219FktEIvHzbgTSbsPuEDj0$b5eUGPbud0M6JYVz73IbSfh2gUJjp" + + "#NYfLz6djCZ84bmZGuYr6oBnpXl1T87nCpwO#nE4jZ#vDmlbaBd8mr2RYbAS#Vr9zCu3G$S" + + "JYPs7t2ryLObpW#X1D#3fmyuPC6fv3h2mUSWR8nE4MwmWbEuGHNZxCUPptEUfprEEjnrkEi" + + "nrcFinvdFSvwdFKuwt7Mu$m$XjF$Nbl4Kdwl7SP9twGdusHtHN1QgDL$ae9GFiGUPgkHJqy" + + "S54kKGcFIiscbrADmxx9o#6yBbFHzVdTWl9xT856otk8fmBxYAS2xv5E0Gclqhet$$VvgDe" + + "hw0L9Zu0w42xyNVwR4ZXo9tNW63sbviID7VfES4TWR2UmMkEvmw0V27SBUEYVsfmpqezGen" + + "cDF#rJWbJbwlaJqlMyVVjt7i1x8wSKcYgS2IyGtCoGt47AdiyMiMetPYt0La3kFTG57JmNs" + + "5osZ$qVfXR2QwVS5Ds2NiaOYhrAKFf9TmsxJVSpkpe5ofYZrNxPAsJdryP6oZqLyYUZZfQA" + + "Fpw4#HYnN7qzSdpvM5l94i8#Hci#w0xDIeISB8QqqKz0d63dgqtxWpeI5d6MWJxGxCLD6gL" + + "4OWx69iMuXrK$qpW3qZjBALh8fx0GsDMm$o5dljg6M8jas8Qyrqonk5DSsCUPtONLAqjo3s" + + "eOonw1jgzc16BDyrZymWFxT$EX57ZJ0Ptfau8krDjGN$OI60LXhzI#ul35biuJzp65psJns" + + "Yj3p7pY9lXVGdx4#SrVPIeudUf5BQtjmpSVQhahs53xchh006W5lLc1EHdOADNVphocol$B" + + "Z4ddUdgTmOHq9uYBx7u0rMEFg9NA3Qt0gNBNlBp47DQv6X0iQ0$tbun8ovsqQN7v$2RqzXK" + + "zhS2CFrv#y$Zf6u89UXC9FZqkiphy3bnv7hFHHN9Vwk8JSDHiV5tiXoUutn3ZMrkxPsIOkQ" + + "VVO$nGkk9d0TOrlzq5COa$ReFP56k4cgBqvPfrWbw6$PegTuYeFLmJL9h5xcfazHNydZAFO" + + "FJRgVEI1ZxTEMA7vIC$TcEjgkBzQAroXKyHwxBHti3j5$Zrg1CCxROayNU4iHjRLnR0keHa" + + "MbgIvMkvLFEcC73q31NPQJYUv$ATaEHzisbynDdG6QWp4mJbs3SQbdv0Bdk3yDRiikDkA#I" + + "LtsfuIFNRRy0a$YFto4FOIOKlbENg#TmY3F2N89s4omah52IvcdvKzd#lq8R6FJxmwaTZx2" + + "UpURtWzgqnpTNAsm5gZrY$Tx$haB9yJluPEpeZ9Ty0h6#On9sV3tYx4#RuHkuJcbvgnb7fr" + + "YgizusJ0fYjCCp4EtRrszHOOJ4n7YrtXs3XCueaTYOckEUHfcZ3Xob5ekqnTOLXOrtACHM2" + + "#wzbbOgArCMK$mH9Y#ydJbgAVuZ29$RwxNCLhYobkx0BwquoT6cTLeh7VJoB7bfYWcwx4jW" + + "XYWlRKcEXgrCJ4gd9WIho6HQgyXhN4Uatstn#MD1QOZlMkOS#4EqlKOOlULR$DYwxGFbR1I" + + "pixKl2tc$EHtSSc$mwiDNBF8wp27uZ#368rVoLexYsN#ojHO5pLg6ALNczKUYSMFVXKRL3v" + + "VRNnKB6NwYggGesWlo8JAcZkXLqtR5TI9w5g7hb74UWhxBhUFGgHAqzfnUeKLWjKYDsYQf3" + + "MBb2n6ecAFSW6gjo2eZAjFOoAyzoel9L1ev8Zle7dOD2ksCfDPrT6wRY#ie1AZawrs1zgrL" + + "ScgaAD83kQK65$#Fzc1251Sv0a#jEkA$iADLUhwwXUw8#PgaJ$0AfgRmINYDobmZzdu$GLd" + + "Eoh9zYPG72MG23F$8tZ#uhsSuGJsCIwP#raP$2FtT3M3eiAhgAXAz94Qx$8QEiL6yIk0ZiE" + + "wgCHfAkmQlHKyyZrR#pQxcaqrlPwLFMewb7Le$g$YKf#u##Zui6rlRWMQpjfb3kEMDlf6ff" + + "lgBLzh8cAyroer9tiw3vuKK3lHZrVyJfmFLXGLFAtpr9Z3zXpqAwQyyYfZsgME8Hr0vMgcq" + + "uhTDSr#OuZVJDFzrFf#PKISTSAE3YTZxg4lbEbUUPzfyhf7fP$bxKwTAUNJYgZw0uWvubtU" + + "cVwT$uXSNd44jDy7yoCVXPtIpaFtZ4MEVr4doNSfUQHxuI1RPJ2DWRz6i6U7rlydRU4xwf3" + + "$RgniOay#XrnGwFVmdtVN8nWFt4Frxz3dlFEVWosebhtcr$3J8rDeVGHJfTFAA0DWQSlX8H" + + "V$WyXXAcmYUUNSlORtFsg1uFzvd5SVcF8Z7wB6$Scx0#gfrly$dxJs5HV$MviIa$pJJMcdC" + + "S$KIFUgh4nvsdCqpuyyabysgSUMpssUcprsEgnhTSv1DSQ#axbsN7d47QPokt7hkA1ynkxo" + + "DXLhgZ7Leyj3JPkd97Yi7avaQTQDZQsq7DL9UfweK9$inwQfxsCyzjvvZmDNuVbnyRktfpx" + + "ZOldgOM4l7QEh6$o6TLORDKRUUrDUFeY#idz55NXiCLT0zPZgyTMZsrJtgi9eDZii8cSJRw" + + "#UJNhiuX#yYrw3pw4BVTlHMAmtLgFhHxRPe6jOH2R#Q4xVRcmfRlVo$d$HMmUZjJhMst7j1" + + "vRFRPwRFNOwh7LOwl7Le#j7bizjdfizTZgiTLZgyTMZwqUMpssUcoR6XihpeVD#Euv$dkPN" + + "ZpXUKjMdVYUaqtSR#cV1Qt7LezjVR7HcqC8ctnZaSR6nVSZFFIc1deBa2gLRfxcU6RRUtFA" + + "$Lo#DSb$zdZW#lMR#FMxU8UdUXlCE60xAlazF3p7#q3r6CIF98#yjrIaoMytnFj0EVVV1mf" + + "$Pz42sPVLlwTMpkDgnPegtq8wCrYh74F1Lwzlg#NRNzYudFNVdzHgJyjwrw$Avww$phP$Ou" + + "vwOMojljRwMkjhhQ#rljRwMkjhhQzrOzHgl0#WEjVljddgTzb54Ebdp#ctrVhNvFcl$#Nx0" + + "EXTuHly7KArHuMHQUx$hm6kntAEZ7p3tkyP6TItir5VTNvBOECtNNtXtrF5roT#fn6gJ$nE" + + "e$RrtURLSNV#zh5LTQ5zd6$QzjMcllXFxUnbSwdFMDzAMACDMP$ujmnLdxYhqjUhSs3jskU" + + "jTZLgjQjMUiR17PL#3KP#HQZrTAV9UAE7yQvLx#qdCMyvkL2yqUCI9Q7NsgjplNtQg3FwxX" + + "N6$JTto3LsOCBAB$fTr9vo1yGEK9NBhbHQpdxNBVSqw3jlkkN5#LgkTfikul$6zHEvFPGMw" + + "lTUtXZJ6teQ#U$fG$#VvTSbMfwob$KkGszoDUloRLxMnIEVzQzBZsXzNVLrrUsw8glQ1gkB" + + "tXiTtovlJQrjNJN1kkIwl#7xCBhU1VkGgsyvi3hd#XMizrub0uNtRdOlHUsWq9Ls9Hzb8aI" + + "VI8JgNmsylL0Yh4hS2GFtdZ6ASTzUX7eMEW8zwwtx#NjMxJ7Yry2m6FCTzIBiAoncvz3g7$" + + "TEyRnr1H0Awuoyro1#9WJU2Ljxw#J6zOn#QxYQ2VSbM#Vwzg5fIxNhm$LhryRlmyXA5Eh3$" + + "BDEp2Krw#9j6dX8L$DG7pKM9ROCj3crdIMTZeAwSgyMtYgGqTVD4UHvLZaswVVXDlkWzglS" + + "XkW38LNkoO$YndbUfNblAXQ#$#y3yXrqdTcay7yxYF$0e7yVwCikeVz0DAuGhkQn$wEWSKY" + + "DFF9l4U5$LGprOiAA9N9hRKan#r2#6L0IkYABiIJP6k#AR62e1GFHYoN#VcBKEYgd7TI8zm" + + "Bw#z8uw3fgVUs0U$TfK6kYRGNVTf$SmzwJDxbq6UjmdXuEM0PqnbW6b$SfvUedht8J$XTKb" + + "PNsEogNjN4U$A$HP9rfPsEE7aln$wGYrp#L30olOg9KMQYK#4yVd4eOwncIpAdVMzs2jbeQ" + + "QjLGjVxb#4SHGp9LBub$54by5q3eIPGSzgLxATrgWFdfwPB$H#Lh28zY$haaP6k2zXy$FzF" + + "YopsNqkAhxxyDsNzfTDRL$lF#zMYJzbz4Fg8p4a#1JwtwT7v9VBAKbOgxeXMgpNIYFqEk#k" + + "nin4EhFltZeiGd$EY9laZti9AJ2CPnkZhE$M#cwZwesilE40XU1GRvhymMpara0JkB#NcPf" + + "p#A8BatWdFSU7iAOcRVzsCjkVbKRlxtWuezCgZHiwAuVwNDYr7ULpR#NKVOg74T0eoubikB" + + "qMXL3enIe$1hex4cg36y3jLUeoeNWx7s6hqJGCEaVPtJdjvFV7SPUCEBKLzPy3yQnPc1d3W" + + "pYFlIIMU6Qb6$FZF4lqTN$b#cyVs7#N#PESw7rLoyPVttdvnKBtaeOQs9A4EzC6f3eJJ7VS" + + "EkeXYbKNbEZWowR6413HAVcwKdMPlh5GzXcxIZfDQ#D6#fgs2L8inpvZPFyN5hdr6xq9Z$5" + + "1#yhislCGN6ttqLclCDImPUDfCjeRrAM0Iziz7xfip3V9ctdrobrhzHk0Qd$UGI$$yCHVhL" + + "IJqGSoKHStt0Neay6HkyZrAQKAvAM5#ktNbeG6jMjRZAiddeexw9krpLE3JrCxmfa6AcLEL" + + "TpOPAtI5zLNclg8Pk31mHVIbmgF#kA3YEEjCVShtnxi#BFI8UHuMovCJLWN3ekmRw##QasO" + + "PPcU9gFDtCD6M1SOF9ucgybhAgpLLcRyRCtx7eJHgVvj1LbVIq5HTtnI0RUaw1S$FxSYKlU" + + "fsDfHgmAmLwB6mjWHgeH0qFVA2X11ZBDlJuwBxnUu7p98p0C5xqUOjalLXFvVZC3Er7vd#W" + + "U2Sxgats87GFpNUtIVnkXtJB7ULMuQlxr4hVG4EtR0$fpcKXOuJ6cX3QSPph4tLjDORNUVy" + + "$XZLQxtkwWRNLIF#C4cCRus0N6cqAZVbFoChAnTgbUeOqfhMxXZaig3dhegmyNg8CQr2PV#" + + "fDFld7w1wQxqn9xGgDZd6c38#tWK3gtYIr6$T762nHFeqp57tQCwPMUOvh7fmzM2dYRLtTy" + + "G$yEv2qbu6gP5cilLI5RTh3xzzlA9EMwCyRJl$CM5MhlIBFht2DUlNviqh#xtma$pAltglI" + + "hvUvrXujg$IhvwZGxwy4IyROHLLkkr3FO2K#$QTNVZL2EyVL8SQmbdM4lYKgYTwfLtBIPiQ" + + "lJod1wJihuxd#1YlqtPA7QBoqvzXQ4kqPfHBjEM5jgn9rvRHdrVFZeEkeD7RXsTlGzEUSz7" + + "hhPVMygyKQKINN2CwZQmH6zjBGZBycnKuUNIV2tssjNwdrch#X5fMWJMLKZyMIrwADiqxKJ" + + "Rt6$SU8Nlg5GawzPK6zyWmWq9Zt7ckDL#WgoxVNHKwSPwW#EZi6wQN1sMJQMKHMhyGjUEG#" + + "NsWqMYPWf$wEMpVfEmDzzIpFk95dskBq2VaMOZuE3PqIQaBOnq7cg5JNK0nzOOjhxzJp0BN" + + "NrlBoI$oktgRlSsHlo$zQn2dC5lMGVFSOnCt5R$y79lsA1rRNo$Z$qlx2ekLgrHFNff4h2Y" + + "wV82ITHQ7dyeiDEVtB87ewJ3w9CLQLgWuZCMhlvUjHfUItLncKQgZps96HVxaqxuLJ7RsCl" + + "Fx0MSRLytVGqmizfg$C##lJjSmpTV3WlxFw6Ab5lVosadu$Zt0g$77$tjqy6QCS2wL3wHTZ" + + "8Vj1NmLi48nU7#VwlzS8HYDFOEJ#2Qw$QSdHNqDm7hfsiOMEv7FOaJ7NndByk$lVCOlldjK" + + "lIBXynYHqpQ$2CQ9VQzGJaaDLlygtRVH4kdTdHlo$w3YacD#PHSvwyJDUpCWw8P6Cr6jJYy" + + "XAKxMHC7bhdHxttzEF0VnH2ycxioIjlFhkIQXFnc4rFIgbXkx6R0Wz4#6bDmpCak1zfUP#U" + + "s2NfA76qD0Tg$GuBbTUsLPvzO$PuAqCdkqBB0D5UwhD6O7s3FJk1YNSrufFptKNBDoIk97H" + + "k89pDuZM64V$cVBkQlMe2MbIBQajMkYh2OwIrswDm5#dkXjZ5OCMUxCOfI1Q82lnHyaVmM3" + + "T8RI1zmUbHslgatK7B2Ju57FB#1ArHIkjCMvyHOdWEAP6Q$PYgd4CpIYgEuW8BMkkqVhtz0" + + "DeoqHTpUDdbBOu$vSJok9evv1FMNWd1usM1px6ZCg$gkG$eMy8YHoxScrIef#OjLZUYQTPq" + + "T1CuSO#JNTfP8eduy#b6entiV#SWzoL0z$pgtrQtL#aCqgSJ6yzbtZUzRcM$MACjz2knpld" + + "YkVtGdA$K9k5$Hd8z9CyolRywy3aVidvDEBlsQ$4xDKdMNz6rN1$5QtbVgLN3gzFT5aVImt" + + "wnDnljOI$SfIPAmSFFhapBhnoy9ZrFV9xbP1L6sK7HcT2hjNQ6#EaVInsD88z6hIm#1NJG9" + + "DpRmXhDtjKo3TCVhwJJYgvzYN$UmffFtB557nFJxjUdMM$DrTMhRHpxtih$rineKMUWtegM" + + "wAQU#hrsB2hwBtPo1q3lw$gqEfSLoH2psJcYD4pcVxUIh6PWLZpqF#r6lD9hH71ivE#AXyO" + + "k2gNAyDDAgPBtC7kH8aQTeydrn0nquQz6DtLq$QTy4HT6PVV6MZjP5Lo3lRa#fqcDRgUu7n" + + "H#vEyEZNkGt1lhHQrUrOTM9UaLPTn7cXnvBk$k4$yUOEnpFaB6Nrw7Ybc0Xlg8doPiLqEPc" + + "p6pepr6iEOinLZzYB6vaz6sgcC7VarulSoPdLcxEXLJ7wEHVvSneugWJi4PLw4kmjfPw2EO" + + "n1UXFHB4Bw5#2I47o3#AcC7hm3$1MCD5YFy1VfiwD#2iV6V8DoLiUFkHpYFiKDkWaCPQntA" + + "h6Niq5QCDRGOQzm3$6Z6car573WPT3QR0Hwo3T#7Em5bBi35v224Fp3M5ZhRTa7w7n4kHti" + + "#Gru$v9KXl1Bn$p9sOZ5Zaz0jRVy0tUV3eJyQNOZwEp5scCFOgUqOs#ufnbezWFWGEBJxi8" + + "SXVptmN0mUzHpU5VcdCDO1#XgZVKLeGn7gExKtO#sUOEoKKiYV0xw2iVPja0uz2r1lE$JR8" + + "HYNmz6VfnwAVW7Mmszax8Icq8Ds78usdJ2UiOu$CTRfQhWz6EjRXRxy7FBxC5RrJuGp6Ukn" + + "FsDpWNqH#g7LbumTqPAn4hHzSaVK0Jc6yUw8UhSu7dcGxVGf#5lXdaHVeEujCAvR$8#nBLl" + + "3RGsTmDeMzPxw87HY34gkGBdpa8UnReMy8rw22KnXRDQ#q0$RwJW1$LY9ECR#nC4e#s#O5y" + + "Qs9#pWLFJ3bhT03#oeBSgFGtv7sDQ91wAVhqNUNm0FzJW8fm7NLXZhJ1#4iCMjW7ShZEbMT" + + "yAjXdkUOLh2jO03rgsXOslesdeQtDrmpy9X7BT1tTj0ppRRmnq41ntjCLRRN0Oypo14kxTv" + + "bB6JqB$Jsc9yrp3M1$spA#opBsHFH3ksBMVivCCOcuF#dhCNohs6DgCjswA#Ks6Jnt$FsCm" + + "x87CoOpiTZRc3CUar4d7OVM#qwsJ87eSo9sECfy16Py76PW53auO8qTvPQCiir3iBVNNotu" + + "01TjSASw89x7mERA47#g83xA09ng49ugSL8Ov#RW9xwd0wS6BiPyE6vin6UTZ7YMZRmGCHX" + + "yrswWOCi8CvxS6Z7pgyWtBt8BuKVO$sDoAxG1iw$WjZWdQq#nZvRq8MjjBkDl1$PgmO#q7x" + + "dL06Sx8ODZ$kDxHtEvH1$Hrl1dyVC3o7EOm#w0JRduqwEs6CPsCiTiPyAS6yxlWLSAF#cI$" + + "0eRxJi5xCnXen6HXEwmuSm5sCkafsXxsZhvl2$ji2IrFeE$4HXD1p8lgmwLzHxXeup44B67" + + "Q1FSo63Sx#4FCVThVhpuprmxoRUXtY4#5WcytGnmE0kHFcV3FOnA0T88y#QuvvtGppP3lOq" + + "2pqNmUiSHs0PJevZFCaz5bFh1VDWM4wrgdfDo0VOtxQcS2v2yPuH$1OEqgmVfvsEyBB4JwE" + + "y2guXp3c69j9M4ldmWOcGUP4sCNH$L7t2CYz0XdKUThRq0#xs0qdZ3a8smz0ks1dxJ7djqD" + + "RjiUOj0QMniZh0TifWetkXldQ77Enw4GusCh4mw7$R8mNshmRsjKUQ#Xnm3C9uzAXBy9tKV" + + "ODy9Yl7R6UpiKSd8JzRYxQDXdzF1TZCta$nkPXGit3F9c7UJaPupmFcCV1fkPX7ep3V9g7j" + + "R0lrheM25iiWmpwentqJ4PRscE#pCEOzCIwDm$pip$iip$Y$R6Mz8Vzj42$xBmd7ER4pXYh" + + "4epX0EmZ9Ty14#PC2upXW9CGOem7O0rgTm3IBuLkhAbxmiQEGtix$eEnbbW$1yB#1s9DEAu" + + "1sWMxEnxnKhIz9UeS24m3ONk3i6uCXBtsm7vbZu83ba6OT#snHWr27OEnBWx6UZiOQyLWs4" + + "O7pBKXM2U7OEqSydV6gb5FDVQM3DQx3F8ROEreW3OqnDhG4FRWO3vsnBhH4ltQYkmRDZS5w" + + "z1mZ6y$Z5Kxh3lLa1#QmHXZRMa5UncAFXwAjTj1Ezl2DZl1teOXlGFc$aJOrx5FGqylEDZN" + + "iHZ7Zk#Xlp5tM$q8zorZ4p1MdM2Rmz3$hL7dCFHZ9zZOxh3drh3Xux77JAb66kPu7$HT2VQ" + + "YtJ6EhM6pnwFTKx26bfm61vihnVwpE$gy5FlJ7YXR2blO0sjT6URb7kYhCepx7XZRCkohUs" + + "9jByTSs1DZLWwRsnFsKeus3iV#MO7#68vvN86#6exvMu7n685vLOd#7O7vNuazVmJQLOant" + + "MjBnZgZt$O2biuOgxsmldJ66h8Nrheksp2szsu8OGjxOstiWhxT#oF6kgAThM5pRJ6chJ4k" + + "Mm375jZdjW2kBR5sRGcSFT2lFM57MxwEVG7uMsEURpK7$Ovri#DGxA$0s04ss0bskW1phmH" + + "piWJZsU5FI0FcKgp3hT6chT07M#Cyq0RzsGRdYpPeno2qgmJhLPiEq8LzO3hwh0F6eSEl64" + + "kiswLO5wV3DcUWRRjWNfMUXJKOzdWov6TWFPe1RFjWdPW2cod5EQKDiCsWynJ6fpNcTpli$" + + "xl0LhU7xDOOYwrnJje6OxCFvBU7BUm3p5sFO6nVh9rTiOxjYprwUxHXNwmlssCDtm7OEs5j" + + "R8krS2Hik2FMp96eiotg7uavqHOwTi1UMuMvqnRjROV#6VaDwiTOxeT#c8AoEs2Ex0TTtM2" + + "p#s5zxOQzj2tMZ56O0zsmlaw1$RN3lDrcFZPSjBadwca$7N7OqRQOmptFHGYxEW7stm5hnh" + + "ROlvl0zZfYtIX5tPtGjnsnDxQ3xNJ2lZGAwzYnq7a2vbixh8cxmFPBqSUTUg8SvcWJsEzGx" + + "8F7ONpd0KC9vcWtd4ztn7clB#RJrCOeXxsj7TRC#Kkmds0TACNQEsSurcISJNh1JjfWpTm5" + + "xIr1$vHYlol6dbICkN8S#ku4zFy9s2EB8LUADQ0fvbG7jBq4QsKfwcqAdKqnzqfnnYh3N1o" + + "5zUnuzCd#M1$tn$wxF$Qv$R4cD8EDDCDyReQsD2TPsF9ex5$7emqdmEQROzqlom8BxBSDzh" + + "TouDmUSYUWpSqHtnvb9sADc0eRduZnxu0zTohMZ#DXnrCnLyjWDnrm1foA$bqm5dXm$Ym5x" + + "jwmqTxe$zCmFyjXExqnXZkXJwOYR0USSp5$5y1coc6Ryz3l7M1dxQ7t9E0lHnqxOUtS2NeR" + + "e$$BCHVBaNSwvcKvre#JSCPeZFu#7NEW76l9FE1iXlRCm5voEiQo7FDf7iQY5TfMZdNXb4R" + + "Ofz37Sp1cfRFWO4ideczEmbpf29iinTvz4iv2Gx76dGGiEwClos4N9w7#as3R0z3sGJXxjC" + + "UwCHZpVm7MnHwO1uEn$vN1bign7fTZ3Yx07Z0ODbc6lQuSwqCvR6O1pWv3q1UbwDToZDa2Z" + + "FSGh3b3C0xLI5k0zR4QQx#3kLcEQv9owaUifqE1eOpw1rZBKSz2sDWkc1yTqQVbwCDopEE5" + + "wBjzOBSBzqOSUz##MEiweIsbM8TFWknE2FkWt#PWFjTW3HgD#JmN$JiLU#yqr5U6ELAE#ij" + + "W8#N0VJJ6O3Hil1nsLG6vXUZtCc0x6dro3EPA1wo5qt2jKePsbAElZi4v$MZqoqAo0wolns" + + "0VEWPsCHvsMeO#ByTPiHnZCnuOngD$#c2l6m$Suw5$8CuqFR7UdaRd4unN6TQACjX4ETaBr" + + "jI5wDy5w8iAwAg2xHw0yyO2bC6ommx0dhGG#q4vwgZ0MQC2w$92xFKBqOQ5sCiNeSn2rBK8" + + "zdO0zj55E9$qWyqxE6ULONsgGBzLD8SCnkPqs5CPrhCAOAo0BIn4tQTZlbN0RYPWR4$7M2$" + + "4$bu1Z6EmTfoEzM4CqcQYxcEnNi#4RS$4VAc0NOn1ty$4kjyFwra5xBS2DdKiycQYRrfWtd" + + "V2dZWMQy84h5Dbs7igi9PqmbpFO5wrmFphXpsc6cUrli2vAzR6NM63k#BilnlMwh6u3XgBS" + + "qC$h6yLs0Chi3TDm7go8yuq5S1JGPY1PIpsc1t$0pl1dZe9vOOZlmFaEk8CC1TsM87rfGBp" + + "PpZ6kWnhImKmduAnhW368gpV1sBjwmxS1#AiLe5rl0NaMcATEX1hpZIS#rfYJan3$Isnj$H" + + "1lQqmLsimZxh3zcjmPgY0RRJ2lbW3U#mEcOEsHHhsr#smJXw4UL45NGV1pgTX3TmEPxs3O2" + + "DLQ7iPvd45rh65M8igi7vKmEONuOpN7$F$5E2em5bnEzZm8gmnlT4FYz3#2knZ5PZpdR0VL" + + "wAjYs2d5HZJKo1NWRt$5EmN5S0o0ZfAwJo7jMakrizJO2jbs3Cgi3#Fm3NVALWhAs0xSt6T" + + "t9lM2ypD4hJb5CpLCig3hK#07Ps2UTCHQyefEFVCnpXMu1ga8snpFkgUYBaq7tjuAUPi6J1" + + "KO8yhmJuy7trMYlreBjfTXZMf0ZegC1yxmFRdOfsUYx6UZx0KjZKHOvL1cuw53Iv2U33Eee" + + "jmJg$0thq8U1V15ifX5uimnygnBqw4t3HSAyp5VEY7SQh1cbY6CQp1#9V3NYgeFhHxFlKvx" + + "AyCUyf1cAC7uSnHIUE2jMC4sbPEsD3VfyDMAp4l3iPQMecsZ8E#IgnzUs5VcWgPwNJcmXbo" + + "8cnsBypFwR3NlfWNbPYRbHZVIjXp9VRkIiofIjXQ9UpHGlsLcBHbMDFQOdpxOXtkZxan6Fq" + + "t67OscDe7FHbWwOFriXBzNuarPp1XH1lweB#6a7xigqDGPoNEt4FGvahegCRyguGzLAF$Ah" + + "4MLM8EL4wMzuocpP5XsmTaoAwaKFBMsp9qxjTfCcv$58otFTwCoxHTLDbTswcmH8MJVPbTf" + + "wlmAJ#jtMWPRdUI33Floh0zhcKoMPM6FRTXOxzCmxt3zQTnk4xj44tRwnSPDXYewiLyQzHR" + + "rLkioZqNqXFgZyPO4ngj2wODsZqOBxfOwJnHrOFriEWOoLSjzkLsMUVpVM$q#GRNAZtOvzf" + + "khtJzMQLX3XxqTB2#lNTJvR9qRWpcEGVwV6QxO5w3dMIunKhO#mr#UZFOxvOPKrQcRzard1" + + "QLEQI38RzRlCoMI$FfML#7iswHQjlbAbwZmYaoh1gYmaL6cLFetf9A$z1FR$2h31SjbU6ss" + + "1ktnNdBkad6ctwlqflAiDsA$FZeNBwjCG$RRo739WraMDqxMcQd$mNZUr$iyxQjwiOrKPFT" + + "Wd8D1$jyXwjyliavoVYQF6FmFyYmxS4oRBL4fV#cubZNMk7iqGHxGKESyOltL$MkpDq7nV#" + + "HOTDjL7XaLAOfrbTsdH5VBSDEnqPbEptkyoLRX$9wg709xFgPODvCs7tpfi6qdNQLuPJnc9" + + "F$hvKp3uwYYC9uxynk4ie$$4CE3P1ZTsSjImj38428fI0a754YfvQbLUAD9KOHCI1ogA0eW" + + "iO322Y29A388Q3YXSeH2WmeY8Y2AE09UA7YWTVN$RwaUoGYLMhLLx$NxxtkdfsTxNuz6XUB" + + "NRn2MEBPl9DGLtPyK#pBbmhpXWZF6IDCFrdOzdVRhskwy4piHMVMMNzMSyQnbZUztlgRZiL" + + "U#9dOv#wa3tj$svCu5shafdF5RiRdi0kVgOPrkc4DbdOtnhjTHDO8E#KwEJy8kvzhVVaDzh" + + "64ptATi3NspupXrjzieJ0#YcC$m7cn$pTx0VLKnEPstysOzgCsQtxXySpzVmdpNH5k5vyXB" + + "4HTtNorzUVZksZXDpv6jzE4xL4N5bvb$OLyNZgtiRxEt3EwtKgkuttWztnoDVeTeRs7iS72" + + "7DJZdNU5vovblrBcb2uXkS#ULqhE83yNdbz0tabk4VR99eUIBmlBkDwMSPqjgoQ$5rxGbPn" + + "AVYZiUxemibruohNkzTlFKO1wDAVsQ7$xKuJv1npVbTQES$oy9OsDovp1ZhsSH3sRYJesZZ" + + "D1PdCRJw2#pHnuz1XzHmgBRWpxlOx2xgZDCrU5Oztv7VHTB#pNJ5ZCxwJOMQjRSlnYr9mjB" + + "y4QnE#dnAaZkZnbxNwiC$ezw$Z#5FO$t$hwp#HrJhU#rgWfot5cpZhR#Ho$2FEmxsKtr1BY" + + "q#Vzx06yFoCuxfT2$s9Xrpdu$h3svjvi#mtWlSd1lOwNMNySv$6ullTurhDGpyP7X#VBmtw" + + "JVod7nPawaGiLX7DQtw$$FGd7ErNO0kVf1Cu7YQqsBybzSy04j$#nX5pMO5dy3f8vpdXyph" + + "CcML$#1y9sgFrp#DjDuintzJrYvvO9Ip$YzQwqVUFuBf9EktYKjTkzPUtS9#LzLWTzvdgty" + + "UlEsY7iS8XjrZKTpx8vsRtfcsXzWva$Z6j4ealZuoTuB#E7zRipvvxWp1tNxqwdI5k$Nur$" + + "onZEw46csEtvsql#hDzVYzrfRNYEmXF3xKvjX466VY$6UxJEnWFM#2LS1uEM#ZqOVLmJEnS" + + "rzdcE$dmbMyBj03LF0cUne8drzN3gtg9MuVmapgvjnoF$RxN9ENLkcsFZl9Ye2ViA3eVRhQ" + + "zsylbx22OBkxHWUoeq1DSrrBb6hja1wjtW6UQl2O$TYUjDJwxh0NutGINjDtW$k9S4qo3kK" + + "oLSq$HxinvzE1#VcvxS6tfoRxZiRsUKdjmhYawqliigmpa3Spd#1kUpVn7EoGxjWU5OKRMr" + + "ptBEbm7h$bxy$IPOqoLuNvF9y3W9dgK3vgNu3FVY$jOBQrGgtRdkSckdCZXcBMEl2djZRKs" + + "n9Xjq0dqZuUDlOH3hxq7pxLY3U9PDvGkxZkTriMvhUwNp6Gzotj1zPtzVcCjQCVZLnf8yao" + + "ITjJlLdpvUK#e6OQjzmknnz7FjRSSpS9nxspLyNkAp6LybJ6yuqs9zudUHotKZTReJsns#$" + + "YJVSQHmLavnhjxhmpab5v2FCxSFwliwiLjCvFoiXLCzRBzodlkozxlZSTv5pEVxWmJVTwHw" + + "svp0gMTJy#aRABp#gEyYF7wJGlPRYldd$NDU2h#t4HjjEs#uiA8DxYtF8#tuJ1GaoD723bm" + + "tKtk5#XylY7Wg0ddrKh#h2EIfFq3zjt3rseZsHkIWY8CyDHFjcSftv1az2F#3Q8ioe2WLe#" + + "fZQQQz0VaRq6y6BcS6x1c8YJo74JK9zYJprv8UxIYf5QE$FkQfbusYK9ewWFu7u7yJUVV1l" + + "W#sA8ECDlZgS1rrw5i7UnFycz1$4zgRJDjLZ7wl8RuPt8pyhp37LsY$1Nrj555lOworYAyb" + + "STA1VBN5o5DpaJFNK2kcQf1N0ryDug8O9UrtaBSDt0RVDeprYL4CyYcFalQdi3z5pZUulc#" + + "GzwrHclfEfHiTGliGxaSLvgo2lmhpLy5NXRwLi2lXhpIshxx7M3#0sEtLZqO#vL6#Eeo#8b" + + "$z3Fw4CRLUGViNeuXw5$xjiBV3VXNs1722$ijO#2QZFHcsPPJKYk0XD58xCFyE#Dw3$HxwF" + + "Gl#QkIh2h02iGgCKO6vXJvLtzQAEhaUOr76cZ0$m#dxNrK$Znu$tP4RaznRSLrX#OuyCah6" + + "$aM#anzbVzVs6l7f$3JJVolctmhVSb1h1MnNU#1ROkIh1MWlm6TQ07iLVAl0P#0JnTHAS2N" + + "cM8ROCjZBu9i7peDl97ArZi0#0byjx5harI97svyPnTGw#DR1de#S#SWLYYOYDX4neKVfTW" + + "RfgJiGi$8TMyUYZQZUxrCnetjWQwr7t$NWvqOHA6Rits3$1ZuFFeyntWVVH$irZBKQN8rd#" + + "0iZ3$8THg4qAaCjHCv2z5s8s6FGBBHdeQtrWP6l5e6BmASmnkk8lmwkWMyDV6zWl8Em3yBU" + + "YJ5tulfsmgUr3$vzo7t0o5UFelqeE1uSZ$WuS1pwZ3Ds3FBL6FZ6WBUZp#smHTgEGlL#d#q" + + "qnuwHdXEBgfVG$oNaV0Xx5#nTi9U2Iy77GQtPYCq6lpHIQZ#u7$4NZVH$BHk1F3KM70jVDL" + + "WDxWPtWnyRUL14VGJx5l3cO#XE8##uT3TojMuoyjKZuF#ffuqyKZJ2o5V3m668YI96qunyD" + + "HeS3PQ3vQ3#ltWDDuogUs7V2tigE1MS0au17y8u3nc6zJ3y3njgHTMDQ2$6VL#CVdkfEMZF" + + "0Py0dm2dWzF1vy3dG9nYeOZ2wHsAg57KRTHTVm5CyM3z"); static final Action RETURN2 = new Action() { public Symbol reduce(Symbol[] _symbols, int offset) { @@ -749,12 +756,29 @@ the root node (typically, when the user is changing code). In this case, we use we use the "bTop" boolean to know if this definition should be added to the outline */ public ArrayList recoverDefs = new ArrayList(); + public ArrayList recoverIdents = new ArrayList(); + /** backup a node, so as to be able to later recover from a parsing error */ - private void backup(Def def){ + private void backupDef(Def def){ recoverDefs.add(def); for(Def child: def.children) //child.bTop = false; unsetTop(child); + + // remove all identifiers that is used to build this def + Region region = def.getFullRegion(); + ArrayList usedIdents = new ArrayList(); + for (Def ident: recoverIdents) + if (ident.posStart >= region.getOffset() + && (ident.posEnd <= region.getOffset() + region.getLength())) + usedIdents.add(ident); + recoverIdents.removeAll(usedIdents); + } + + // backup identifiers for later recovering from a parsing error, + // some will be removed when they are used to build a Def sucessfully + private void backupIdent(Def def) { + recoverIdents.add(def); } private void unsetTop(Def def){ @@ -905,7 +929,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def("", Def.Type.Struct, s.getStart(), s.getEnd()); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, @@ -917,7 +941,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def("", Def.Type.Struct, a.getStart(), a.getEnd()); def.add(s); def.collapse(); - backup(def); + backupDef(def); return def; } }, @@ -931,7 +955,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, @@ -1026,12 +1050,26 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b); } }, - new Action() { // [39] structure_tail = error + new Action() { // [39] structure_tail = SEMISEMI cppo_directive.a structure_tail.b + public Symbol reduce(Symbol[] _symbols, int offset) { + final Symbol a = _symbols[offset + 2]; + final Symbol b = _symbols[offset + 3]; + return Def.root(a,b); + } + }, + new Action() { // [40] structure_tail = cppo_directive.a structure_tail.b + public Symbol reduce(Symbol[] _symbols, int offset) { + final Symbol a = _symbols[offset + 1]; + final Symbol b = _symbols[offset + 2]; + return Def.root(a,b); + } + }, + new Action() { // [41] structure_tail = error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [40] structure_item = LET.l rec_flag.r let_bindings.a + new Action() { // [42] structure_item = LET.l rec_flag.r let_bindings.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol l = _symbols[offset + 1]; final Symbol r = _symbols[offset + 2]; @@ -1049,7 +1087,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return a; } }, - new Action() { // [41] structure_item = EXTERNAL val_ident.i COLON core_type.a EQUAL primitive_declaration.b + new Action() { // [43] structure_item = EXTERNAL val_ident.i COLON core_type.a EQUAL primitive_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol i = _symbols[offset + 2]; final Symbol a = _symbols[offset + 4]; @@ -1060,17 +1098,17 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [42] structure_item = TYPE type_declarations.t + new Action() { // [44] structure_item = TYPE type_declarations.t public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol t = _symbols[offset + 2]; return t; } }, - new Action() { // [43] structure_item = EXCEPTION UIDENT.id constructor_arguments.a + new Action() { // [45] structure_item = EXCEPTION UIDENT.id constructor_arguments.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 2]; final Symbol a = _symbols[offset + 3]; @@ -1078,11 +1116,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def((String)id.value, Def.Type.Exception, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [44] structure_item = EXCEPTION UIDENT.id EQUAL constr_longident.a + new Action() { // [46] structure_item = EXCEPTION UIDENT.id EQUAL constr_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 2]; final Symbol a = _symbols[offset + 4]; @@ -1090,29 +1128,33 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def((String)id.value, Def.Type.Exception, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [45] structure_item = MODULE UIDENT.id module_binding.a + new Action() { // [47] structure_item = MODULE UIDENT.id module_binding.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 2]; final Symbol a = _symbols[offset + 3]; - Def def = new Def((String)id.value, Def.Type.Module, id.getStart(), id.getEnd()); + Def.Type type = Def.Type.Module; + assert a instanceof Def; + Def.Type aType = ((Def)a).type; + type = (aType == Def.Type.Identifier) ? Def.Type.ModuleAlias : type; + Def def = new Def((String)id.value, type, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [46] structure_item = MODULE REC module_rec_bindings.a + new Action() { // [48] structure_item = MODULE REC module_rec_bindings.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 3]; return a; } }, - new Action() { // [47] structure_item = MODULE TYPE ident.id EQUAL module_type.a + new Action() { // [49] structure_item = MODULE TYPE ident.id EQUAL module_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 5]; @@ -1121,72 +1163,72 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def(ident.name, Def.Type.ModuleType, ident.posStart, ident.posEnd); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [48] structure_item = OPEN mod_longident.id + new Action() { // [50] structure_item = OPEN mod_longident.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 2]; Def ident = (Def)id; Def def = new Def(ident.name, Def.Type.Open, ident.posStart, ident.posEnd); - backup(def); + backupDef(def); return def; } }, - new Action() { // [49] structure_item = CLASS class_declarations.a + new Action() { // [51] structure_item = CLASS class_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [50] structure_item = CLASS TYPE class_type_declarations.a + new Action() { // [52] structure_item = CLASS TYPE class_type_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 3]; return a; } }, - new Action() { // [51] structure_item = INCLUDE module_expr.id + new Action() { // [53] structure_item = INCLUDE module_expr.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 2]; Def ident = (Def)id; if(ident.type == Def.Type.Identifier){ Def def = new Def(ident.name, Def.Type.Include, ident.posStart, ident.posEnd); - backup(def); + backupDef(def); return def; } return new Def(); } }, - new Action() { // [52] module_binding = EQUAL module_expr.a + new Action() { // [54] module_binding = EQUAL module_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [53] module_binding = COLON module_type.a EQUAL module_expr.b + new Action() { // [55] module_binding = COLON module_type.a EQUAL module_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [54] module_binding = LPAREN UIDENT COLON module_type.a RPAREN module_binding.b + new Action() { // [56] module_binding = LPAREN UIDENT COLON module_type.a RPAREN module_binding.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 4]; final Symbol b = _symbols[offset + 6]; return Def.root(a,b); } }, - new Action() { // [55] module_rec_bindings = module_rec_binding.a + new Action() { // [57] module_rec_bindings = module_rec_binding.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [56] module_rec_bindings = module_rec_bindings.a AND module_rec_binding.b + new Action() { // [58] module_rec_bindings = module_rec_bindings.a AND module_rec_binding.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -1196,7 +1238,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b); } }, - new Action() { // [57] module_rec_binding = UIDENT.id COLON module_type.a EQUAL module_expr.b + new Action() { // [59] module_rec_binding = UIDENT.id COLON module_type.a EQUAL module_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; final Symbol a = _symbols[offset + 3]; @@ -1206,17 +1248,17 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [58] module_type = mty_longident.id + new Action() { // [60] module_type = mty_longident.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return id; } }, - new Action() { // [59] module_type = SIG.s signature.a END + new Action() { // [61] module_type = SIG.s signature.a END public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol s = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -1224,16 +1266,16 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def("", Def.Type.Sig, s.getStart(), s.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [60] module_type = SIG signature error + new Action() { // [62] module_type = SIG signature error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [61] module_type = FUNCTOR LPAREN UIDENT.id COLON module_type.a RPAREN MINUSGREATER module_type.b + new Action() { // [63] module_type = FUNCTOR LPAREN UIDENT.id COLON module_type.a RPAREN MINUSGREATER module_type.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 5]; @@ -1243,54 +1285,54 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [62] module_type = module_type.a WITH with_constraints.b + new Action() { // [64] module_type = module_type.a WITH with_constraints.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [63] module_type = MODULE TYPE OF module_expr.a + new Action() { // [65] module_type = MODULE TYPE OF module_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 4]; return a; } }, - new Action() { // [64] module_type = LPAREN module_type.a RPAREN + new Action() { // [66] module_type = LPAREN module_type.a RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [65] module_type = LPAREN module_type error + new Action() { // [67] module_type = LPAREN module_type error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [66] signature = + new Action() { // [68] signature = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [67] signature = signature.a signature_item.b + new Action() { // [69] signature = signature.a signature_item.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [68] signature = signature.a signature_item.b SEMISEMI + new Action() { // [70] signature = signature.a signature_item.b SEMISEMI public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [69] signature_item = VAL.v val_ident.id COLON core_type.a + new Action() { // [71] signature_item = VAL.v val_ident.id COLON core_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol v = _symbols[offset + 1]; final Symbol id = _symbols[offset + 2]; @@ -1304,11 +1346,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { // add the start position of the definition def.defPosStart = v.getStart(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [70] signature_item = EXTERNAL.e val_ident.id COLON core_type.a EQUAL primitive_declaration.b + new Action() { // [72] signature_item = EXTERNAL.e val_ident.id COLON core_type.a EQUAL primitive_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol e = _symbols[offset + 1]; final Symbol id = _symbols[offset + 2]; @@ -1321,11 +1363,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [71] signature_item = TYPE.t type_declarations.a + new Action() { // [73] signature_item = TYPE.t type_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol t = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -1337,7 +1379,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return a; } }, - new Action() { // [72] signature_item = EXCEPTION.e UIDENT.id constructor_arguments.a + new Action() { // [74] signature_item = EXCEPTION.e UIDENT.id constructor_arguments.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol e = _symbols[offset + 1]; final Symbol id = _symbols[offset + 2]; @@ -1347,11 +1389,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.defPosStart = e.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [73] signature_item = MODULE.m UIDENT.id module_declaration.a + new Action() { // [75] signature_item = MODULE.m UIDENT.id module_declaration.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol id = _symbols[offset + 2]; @@ -1361,11 +1403,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [74] signature_item = MODULE.m REC module_rec_declarations.a + new Action() { // [76] signature_item = MODULE.m REC module_rec_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol a = _symbols[offset + 3]; @@ -1377,7 +1419,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return a; } }, - new Action() { // [75] signature_item = MODULE.m TYPE ident.id + new Action() { // [77] signature_item = MODULE.m TYPE ident.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -1385,11 +1427,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def ident = (Def)id; Def def = new Def(ident.name, Def.Type.ModuleType, ident.posStart, ident.posEnd); def.defPosStart = m.getStart(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [76] signature_item = MODULE.m TYPE ident.id EQUAL module_type.a + new Action() { // [78] signature_item = MODULE.m TYPE ident.id EQUAL module_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -1400,11 +1442,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [77] signature_item = OPEN.o mod_longident.id + new Action() { // [79] signature_item = OPEN.o mod_longident.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol o = _symbols[offset + 1]; final Symbol id = _symbols[offset + 2]; @@ -1412,11 +1454,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def ident = (Def)id; Def def = new Def(ident.name, Def.Type.Open, ident.posStart, ident.posEnd); def.defPosStart = o.getStart(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [78] signature_item = INCLUDE.i module_type.id + new Action() { // [80] signature_item = INCLUDE.i module_type.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol i = _symbols[offset + 1]; final Symbol id = _symbols[offset + 2]; @@ -1425,13 +1467,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { if(ident.type == Def.Type.Identifier){ Def def = new Def(ident.name, Def.Type.Include, ident.posStart, ident.posEnd); def.defPosStart = i.getStart(); - backup(def); + backupDef(def); return def; } return new Def(); } }, - new Action() { // [79] signature_item = CLASS.c class_descriptions.a + new Action() { // [81] signature_item = CLASS.c class_descriptions.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol c = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -1443,7 +1485,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return a; } }, - new Action() { // [80] signature_item = CLASS.c TYPE class_type_declarations.a + new Action() { // [82] signature_item = CLASS.c TYPE class_type_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol c = _symbols[offset + 1]; final Symbol a = _symbols[offset + 3]; @@ -1455,26 +1497,26 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return a; } }, - new Action() { // [81] module_declaration = COLON module_type.a + new Action() { // [83] module_declaration = COLON module_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [82] module_declaration = LPAREN UIDENT COLON module_type.a RPAREN module_declaration.b + new Action() { // [84] module_declaration = LPAREN UIDENT COLON module_type.a RPAREN module_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 4]; final Symbol b = _symbols[offset + 6]; return Def.root(a,b); } }, - new Action() { // [83] module_rec_declarations = module_rec_declaration.a + new Action() { // [85] module_rec_declarations = module_rec_declaration.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [84] module_rec_declarations = module_rec_declarations.a AND.n module_rec_declaration.b + new Action() { // [86] module_rec_declarations = module_rec_declarations.a AND.n module_rec_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol n = _symbols[offset + 2]; @@ -1486,7 +1528,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b); } }, - new Action() { // [85] module_rec_declaration = UIDENT.id COLON module_type.a + new Action() { // [87] module_rec_declaration = UIDENT.id COLON module_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; final Symbol a = _symbols[offset + 3]; @@ -1494,11 +1536,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def((String)id.value, Def.Type.Module, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [86] class_declarations = class_declarations.a AND class_declaration.b + new Action() { // [88] class_declarations = class_declarations.a AND class_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -1508,13 +1550,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b); } }, - new Action() { // [87] class_declarations = class_declaration.a + new Action() { // [89] class_declarations = class_declaration.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [88] class_declaration = virtual_flag class_type_parameters.a LIDENT.id class_fun_binding.b + new Action() { // [90] class_declaration = virtual_flag class_type_parameters.a LIDENT.id class_fun_binding.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol id = _symbols[offset + 3]; @@ -1524,75 +1566,75 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [89] class_fun_binding = EQUAL class_expr.a + new Action() { // [91] class_fun_binding = EQUAL class_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [90] class_fun_binding = COLON class_type.a EQUAL class_expr.b + new Action() { // [92] class_fun_binding = COLON class_type.a EQUAL class_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [91] class_fun_binding = labeled_simple_pattern.a class_fun_binding.b + new Action() { // [93] class_fun_binding = labeled_simple_pattern.a class_fun_binding.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [92] class_type_parameters = + new Action() { // [94] class_type_parameters = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [93] class_type_parameters = LBRACKET type_parameter_list.a RBRACKET + new Action() { // [95] class_type_parameters = LBRACKET type_parameter_list.a RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [94] class_fun_def = labeled_simple_pattern.a MINUSGREATER class_expr.b + new Action() { // [96] class_fun_def = labeled_simple_pattern.a MINUSGREATER class_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [95] class_fun_def = labeled_simple_pattern.a class_fun_def.b + new Action() { // [97] class_fun_def = labeled_simple_pattern.a class_fun_def.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [96] class_expr = class_simple_expr.a + new Action() { // [98] class_expr = class_simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [97] class_expr = FUN class_fun_def.a + new Action() { // [99] class_expr = FUN class_fun_def.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [98] class_expr = class_simple_expr.a simple_labeled_expr_list.b + new Action() { // [100] class_expr = class_simple_expr.a simple_labeled_expr_list.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [99] class_expr = LET rec_flag.r let_bindings.a IN class_expr.b + new Action() { // [101] class_expr = LET rec_flag.r let_bindings.a IN class_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol r = _symbols[offset + 2]; final Symbol a = _symbols[offset + 3]; @@ -1617,27 +1659,27 @@ public Symbol reduce(Symbol[] _symbols, int offset) { in.collapse(); last.children.add(in); last.collapse(); - backup(last); + backupDef(last); return a; } return Def.root(a,b); } }, - new Action() { // [100] class_simple_expr = LBRACKET core_type_comma_list.a RBRACKET class_longident.b + new Action() { // [102] class_simple_expr = LBRACKET core_type_comma_list.a RBRACKET class_longident.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [101] class_simple_expr = class_longident.a + new Action() { // [103] class_simple_expr = class_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [102] class_simple_expr = OBJECT.o class_structure.a END + new Action() { // [104] class_simple_expr = OBJECT.o class_structure.a END public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol o = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -1645,69 +1687,69 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def("", Def.Type.Object, o.getStart(), o.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [103] class_simple_expr = OBJECT class_structure error + new Action() { // [105] class_simple_expr = OBJECT class_structure error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [104] class_simple_expr = LPAREN class_expr.a COLON class_type.b RPAREN + new Action() { // [106] class_simple_expr = LPAREN class_expr.a COLON class_type.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [105] class_simple_expr = LPAREN class_expr COLON class_type error + new Action() { // [107] class_simple_expr = LPAREN class_expr COLON class_type error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [106] class_simple_expr = LPAREN class_expr.a RPAREN + new Action() { // [108] class_simple_expr = LPAREN class_expr.a RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [107] class_simple_expr = LPAREN class_expr error + new Action() { // [109] class_simple_expr = LPAREN class_expr error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [108] class_structure = class_self_pattern.a class_fields.b + new Action() { // [110] class_structure = class_self_pattern.a class_fields.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [109] class_self_pattern = LPAREN pattern.a RPAREN + new Action() { // [111] class_self_pattern = LPAREN pattern.a RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [110] class_self_pattern = LPAREN pattern.a COLON core_type.b RPAREN + new Action() { // [112] class_self_pattern = LPAREN pattern.a COLON core_type.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [111] class_self_pattern = + new Action() { // [113] class_self_pattern = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [112] class_fields = + new Action() { // [114] class_fields = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [113] class_fields = class_fields.a INHERIT override_flag.b class_expr.c parent_binder.d + new Action() { // [115] class_fields = class_fields.a INHERIT override_flag.b class_expr.c parent_binder.d public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -1716,7 +1758,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c,d); } }, - new Action() { // [114] class_fields = class_fields.a VAL.v virtual_value.id + new Action() { // [116] class_fields = class_fields.a VAL.v virtual_value.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol v = _symbols[offset + 2]; @@ -1726,13 +1768,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { if(ident.type == Def.Type.Identifier){ Def def = new Def(ident.name, Def.Type.Val, ident.posStart, ident.posEnd); def.defPosStart = v.getStart(); - backup(def); + backupDef(def); return Def.root(a, def); } return Def.root(a,id); } }, - new Action() { // [115] class_fields = class_fields.a VAL.v value.id + new Action() { // [117] class_fields = class_fields.a VAL.v value.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol v = _symbols[offset + 2]; @@ -1742,27 +1784,27 @@ public Symbol reduce(Symbol[] _symbols, int offset) { if(ident.type == Def.Type.Identifier){ Def def = new Def(ident.name, Def.Type.Val, ident.posStart, ident.posEnd); def.defPosStart = v.getStart(); - backup(def); + backupDef(def); return Def.root(a, def); } return Def.root(a,id); } }, - new Action() { // [116] class_fields = class_fields.a virtual_method.b + new Action() { // [118] class_fields = class_fields.a virtual_method.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [117] class_fields = class_fields.a concrete_method.b + new Action() { // [119] class_fields = class_fields.a concrete_method.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [118] class_fields = class_fields.a CONSTRAINT.c constrain.b + new Action() { // [120] class_fields = class_fields.a CONSTRAINT.c constrain.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol c = _symbols[offset + 2]; @@ -1771,11 +1813,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def("", Def.Type.Constraint, c.getStart(), c.getEnd()); def.add(b); def.collapse(); - backup(def); + backupDef(def); return Def.root(a, def); } }, - new Action() { // [119] class_fields = class_fields.a INITIALIZER.i seq_expr.b + new Action() { // [121] class_fields = class_fields.a INITIALIZER.i seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol i = _symbols[offset + 2]; @@ -1785,23 +1827,23 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.defPosStart = i.getStart(); def.add(b); def.collapse(); - backup(def); + backupDef(def); return Def.root(a, def); } }, - new Action() { // [120] parent_binder = AS LIDENT.id + new Action() { // [122] parent_binder = AS LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 2]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [121] parent_binder = + new Action() { // [123] parent_binder = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [122] virtual_value = override_flag.o MUTABLE.m VIRTUAL label.id COLON core_type.a + new Action() { // [124] virtual_value = override_flag.o MUTABLE.m VIRTUAL label.id COLON core_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol o = _symbols[offset + 1]; final Symbol m = _symbols[offset + 2]; @@ -1816,11 +1858,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.collapse(); def.bAlt = true; - backup(def); + backupDef(def); return def; } }, - new Action() { // [123] virtual_value = VIRTUAL.v mutable_flag.m label.id COLON core_type.a + new Action() { // [125] virtual_value = VIRTUAL.v mutable_flag.m label.id COLON core_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol v = _symbols[offset + 1]; final Symbol m = _symbols[offset + 2]; @@ -1834,11 +1876,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.collapse(); def.bAlt = ((Def)m).bAlt; - backup(def); + backupDef(def); return def; } }, - new Action() { // [124] value = override_flag.o mutable_flag.m label.id EQUAL seq_expr.a + new Action() { // [126] value = override_flag.o mutable_flag.m label.id EQUAL seq_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol o = _symbols[offset + 1]; final Symbol m = _symbols[offset + 2]; @@ -1854,11 +1896,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)m).bAlt; - backup(def); + backupDef(def); return def; } }, - new Action() { // [125] value = override_flag.o mutable_flag.m label.id type_constraint.a EQUAL seq_expr.b + new Action() { // [127] value = override_flag.o mutable_flag.m label.id type_constraint.a EQUAL seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol o = _symbols[offset + 1]; final Symbol m = _symbols[offset + 2]; @@ -1876,11 +1918,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(b); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)m).bAlt; - backup(def); + backupDef(def); return def; } }, - new Action() { // [126] virtual_method = METHOD.m override_flag.o PRIVATE VIRTUAL label.id COLON poly_type.a + new Action() { // [128] virtual_method = METHOD.m override_flag.o PRIVATE VIRTUAL label.id COLON poly_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol o = _symbols[offset + 2]; @@ -1894,11 +1936,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.collapse(); def.bAlt = true; - backup(def); + backupDef(def); return def; } }, - new Action() { // [127] virtual_method = METHOD.m override_flag.o VIRTUAL private_flag.p label.id COLON poly_type.a + new Action() { // [129] virtual_method = METHOD.m override_flag.o VIRTUAL private_flag.p label.id COLON poly_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol o = _symbols[offset + 2]; @@ -1913,11 +1955,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)p).bAlt; - backup(def); + backupDef(def); return def; } }, - new Action() { // [128] concrete_method = METHOD.m override_flag.o private_flag.p label.id strict_binding.a + new Action() { // [130] concrete_method = METHOD.m override_flag.o private_flag.p label.id strict_binding.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol o = _symbols[offset + 2]; @@ -1932,11 +1974,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)p).bAlt; - backup(def); + backupDef(def); return def; } }, - new Action() { // [129] concrete_method = METHOD.m override_flag.o private_flag.p label.id COLON poly_type.a EQUAL seq_expr.b + new Action() { // [131] concrete_method = METHOD.m override_flag.o private_flag.p label.id COLON poly_type.a EQUAL seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol o = _symbols[offset + 2]; @@ -1953,51 +1995,51 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(b); def.collapse(); def.bAlt = ((Def)o).bAlt || ((Def)p).bAlt; - backup(def); + backupDef(def); return def; } }, - new Action() { // [130] class_type = class_signature.s + new Action() { // [132] class_type = class_signature.s public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol s = _symbols[offset + 1]; return s; } }, - new Action() { // [131] class_type = QUESTION LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type.c + new Action() { // [133] class_type = QUESTION LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol c = _symbols[offset + 6]; return c; } }, - new Action() { // [132] class_type = OPTLABEL simple_core_type_or_tuple MINUSGREATER class_type.c + new Action() { // [134] class_type = OPTLABEL simple_core_type_or_tuple MINUSGREATER class_type.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol c = _symbols[offset + 4]; return c; } }, - new Action() { // [133] class_type = LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type.c + new Action() { // [135] class_type = LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol c = _symbols[offset + 5]; return c; } }, - new Action() { // [134] class_type = simple_core_type_or_tuple MINUSGREATER class_type.c + new Action() { // [136] class_type = simple_core_type_or_tuple MINUSGREATER class_type.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol c = _symbols[offset + 3]; return c; } }, - new Action() { // [135] class_signature = LBRACKET core_type_comma_list RBRACKET clty_longident + new Action() { // [137] class_signature = LBRACKET core_type_comma_list RBRACKET clty_longident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [136] class_signature = clty_longident + new Action() { // [138] class_signature = clty_longident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [137] class_signature = OBJECT.o class_sig_body.a END + new Action() { // [139] class_signature = OBJECT.o class_sig_body.a END public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol o = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -2005,46 +2047,46 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def("", Def.Type.Object, o.getStart(), o.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [138] class_signature = OBJECT class_sig_body error + new Action() { // [140] class_signature = OBJECT class_sig_body error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [139] class_sig_body = class_self_type.a class_sig_fields.b + new Action() { // [141] class_sig_body = class_self_type.a class_sig_fields.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [140] class_self_type = LPAREN core_type.a RPAREN + new Action() { // [142] class_self_type = LPAREN core_type.a RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return Def.root(a); } }, - new Action() { // [141] class_self_type = + new Action() { // [143] class_self_type = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [142] class_sig_fields = + new Action() { // [144] class_sig_fields = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [143] class_sig_fields = class_sig_fields.s INHERIT class_signature.a + new Action() { // [145] class_sig_fields = class_sig_fields.s INHERIT class_signature.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol s = _symbols[offset + 1]; final Symbol a = _symbols[offset + 3]; return Def.root(s,a); } }, - new Action() { // [144] class_sig_fields = class_sig_fields.s VAL.v value_type.a + new Action() { // [146] class_sig_fields = class_sig_fields.s VAL.v value_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol s = _symbols[offset + 1]; final Symbol v = _symbols[offset + 2]; @@ -2055,28 +2097,28 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(s,a); } }, - new Action() { // [145] class_sig_fields = class_sig_fields.s virtual_method_type.a + new Action() { // [147] class_sig_fields = class_sig_fields.s virtual_method_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol s = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; return Def.root(s,a); } }, - new Action() { // [146] class_sig_fields = class_sig_fields.s method_type.a + new Action() { // [148] class_sig_fields = class_sig_fields.s method_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol s = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; return Def.root(s,a); } }, - new Action() { // [147] class_sig_fields = class_sig_fields.s CONSTRAINT constrain.a + new Action() { // [149] class_sig_fields = class_sig_fields.s CONSTRAINT constrain.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol s = _symbols[offset + 1]; final Symbol a = _symbols[offset + 3]; return Def.root(s,a); } }, - new Action() { // [148] value_type = VIRTUAL mutable_flag.m label.id COLON core_type.a + new Action() { // [150] value_type = VIRTUAL mutable_flag.m label.id COLON core_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 2]; final Symbol id = _symbols[offset + 3]; @@ -2088,11 +2130,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.collapse(); def.bAlt = ((Def)m).bAlt; - backup(def); + backupDef(def); return def; } }, - new Action() { // [149] value_type = MUTABLE virtual_flag label.id COLON core_type.a + new Action() { // [151] value_type = MUTABLE virtual_flag label.id COLON core_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 5]; @@ -2103,11 +2145,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.add(a); def.collapse(); def.bAlt = true; - backup(def); + backupDef(def); return def; } }, - new Action() { // [150] value_type = label.id COLON core_type.a + new Action() { // [152] value_type = label.id COLON core_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; final Symbol a = _symbols[offset + 3]; @@ -2117,11 +2159,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def(ident.name, Def.Type.Val, ident.posStart, ident.posEnd); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [151] method_type = METHOD.m private_flag label.id COLON poly_type.a + new Action() { // [153] method_type = METHOD.m private_flag label.id COLON poly_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -2133,11 +2175,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [152] virtual_method_type = METHOD.m PRIVATE VIRTUAL label.id COLON poly_type.a + new Action() { // [154] virtual_method_type = METHOD.m PRIVATE VIRTUAL label.id COLON poly_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol id = _symbols[offset + 4]; @@ -2149,11 +2191,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [153] virtual_method_type = METHOD.m VIRTUAL private_flag label.id COLON poly_type.a + new Action() { // [155] virtual_method_type = METHOD.m VIRTUAL private_flag label.id COLON poly_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol id = _symbols[offset + 4]; @@ -2165,18 +2207,18 @@ public Symbol reduce(Symbol[] _symbols, int offset) { def.defPosStart = m.getStart(); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [154] constrain = core_type.a EQUAL core_type.b + new Action() { // [156] constrain = core_type.a EQUAL core_type.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [155] class_descriptions = class_descriptions.a AND.n class_description.b + new Action() { // [157] class_descriptions = class_descriptions.a AND.n class_description.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol n = _symbols[offset + 2]; @@ -2188,13 +2230,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b); } }, - new Action() { // [156] class_descriptions = class_description.a + new Action() { // [158] class_descriptions = class_description.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [157] class_description = virtual_flag class_type_parameters LIDENT.id COLON class_type.a + new Action() { // [159] class_description = virtual_flag class_type_parameters LIDENT.id COLON class_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 5]; @@ -2202,11 +2244,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def((String)id.value, Def.Type.Class, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [158] class_type_declarations = class_type_declarations.a AND.n class_type_declaration.b + new Action() { // [160] class_type_declarations = class_type_declarations.a AND.n class_type_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol n = _symbols[offset + 2]; @@ -2218,13 +2260,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b); } }, - new Action() { // [159] class_type_declarations = class_type_declaration.a + new Action() { // [161] class_type_declarations = class_type_declaration.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [160] class_type_declaration = virtual_flag class_type_parameters LIDENT.id EQUAL class_signature.a + new Action() { // [162] class_type_declaration = virtual_flag class_type_parameters LIDENT.id EQUAL class_signature.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 5]; @@ -2232,43 +2274,43 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def((String)id.value, Def.Type.ClassType, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [161] seq_expr = expr.a + new Action() { // [163] seq_expr = expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [162] seq_expr = expr.a SEMI + new Action() { // [164] seq_expr = expr.a SEMI public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [163] seq_expr = expr.a SEMI seq_expr.b + new Action() { // [165] seq_expr = expr.a SEMI seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [164] labeled_simple_pattern = QUESTION LPAREN label_let_pattern.a opt_default.b RPAREN + new Action() { // [166] labeled_simple_pattern = QUESTION LPAREN label_let_pattern.a opt_default.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 3]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [165] labeled_simple_pattern = QUESTION label_var.a + new Action() { // [167] labeled_simple_pattern = QUESTION label_var.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [166] labeled_simple_pattern = OPTLABEL.id LPAREN let_pattern.a opt_default.b RPAREN + new Action() { // [168] labeled_simple_pattern = OPTLABEL.id LPAREN let_pattern.a opt_default.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; final Symbol a = _symbols[offset + 3]; @@ -2278,7 +2320,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(ident,a,b); } }, - new Action() { // [167] labeled_simple_pattern = OPTLABEL.id pattern_var.a + new Action() { // [169] labeled_simple_pattern = OPTLABEL.id pattern_var.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -2287,19 +2329,19 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(ident,a); } }, - new Action() { // [168] labeled_simple_pattern = TILDE LPAREN label_let_pattern.a RPAREN + new Action() { // [170] labeled_simple_pattern = TILDE LPAREN label_let_pattern.a RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 3]; return a; } }, - new Action() { // [169] labeled_simple_pattern = TILDE label_var.a + new Action() { // [171] labeled_simple_pattern = TILDE label_var.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [170] labeled_simple_pattern = LABEL.id simple_pattern.a + new Action() { // [172] labeled_simple_pattern = LABEL.id simple_pattern.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -2308,84 +2350,84 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(ident,a); } }, - new Action() { // [171] labeled_simple_pattern = simple_pattern.a + new Action() { // [173] labeled_simple_pattern = simple_pattern.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [172] pattern_var = LIDENT.id + new Action() { // [174] pattern_var = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [173] pattern_var = UNDERSCORE.id + new Action() { // [175] pattern_var = UNDERSCORE.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def("_", Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [174] opt_default = + new Action() { // [176] opt_default = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [175] opt_default = EQUAL seq_expr.a + new Action() { // [177] opt_default = EQUAL seq_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [176] label_let_pattern = label_var.a + new Action() { // [178] label_let_pattern = label_var.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [177] label_let_pattern = label_var.a COLON core_type.b + new Action() { // [179] label_let_pattern = label_var.a COLON core_type.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [178] label_var = LIDENT.id + new Action() { // [180] label_var = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [179] let_pattern = pattern.a + new Action() { // [181] let_pattern = pattern.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [180] let_pattern = pattern.a COLON core_type.b + new Action() { // [182] let_pattern = pattern.a COLON core_type.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [181] expr = simple_expr.a + new Action() { // [183] expr = simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [182] expr = simple_expr.a simple_labeled_expr_list.b + new Action() { // [184] expr = simple_expr.a simple_labeled_expr_list.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [183] expr = LET rec_flag.r let_bindings.a IN seq_expr.b + new Action() { // [185] expr = LET rec_flag.r let_bindings.a IN seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol r = _symbols[offset + 2]; final Symbol a = _symbols[offset + 3]; @@ -2410,28 +2452,28 @@ public Symbol reduce(Symbol[] _symbols, int offset) { in.collapse(); last.children.add(in); last.collapse(); - backup(last); + backupDef(last); return a; } return Def.root(a,b); } }, - new Action() { // [184] expr = LET MODULE UIDENT.id module_binding.a IN seq_expr.b + new Action() { // [186] expr = LET MODULE UIDENT.id module_binding.a IN seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 4]; final Symbol b = _symbols[offset + 6]; - Def def = new Def((String)id.value, Def.Type.Module, id.getStart(), id.getEnd()); + Def def = new Def((String)id.value, Def.Type.ModuleAlias, id.getStart(), id.getEnd()); def.add(a); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [185] expr = LET OPEN mod_longident.id IN seq_expr.a + new Action() { // [187] expr = LET OPEN mod_longident.id IN seq_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 5]; @@ -2443,18 +2485,18 @@ public Symbol reduce(Symbol[] _symbols, int offset) { in.collapse(); def.children.add(in); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [186] expr = FUNCTION opt_bar.a match_cases.b + new Action() { // [188] expr = FUNCTION opt_bar.a match_cases.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [187] expr = FUN labeled_simple_pattern.a fun_def.b + new Action() { // [189] expr = FUN labeled_simple_pattern.a fun_def.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; @@ -2493,7 +2535,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { } } }, - new Action() { // [188] expr = FUN LPAREN TYPE LIDENT.id RPAREN fun_def.a + new Action() { // [190] expr = FUN LPAREN TYPE LIDENT.id RPAREN fun_def.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 4]; final Symbol a = _symbols[offset + 6]; @@ -2506,7 +2548,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return root; } }, - new Action() { // [189] expr = MATCH seq_expr.a WITH opt_bar.b match_cases.c + new Action() { // [191] expr = MATCH seq_expr.a WITH opt_bar.b match_cases.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; @@ -2514,7 +2556,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [190] expr = TRY seq_expr.a WITH opt_bar.b match_cases.c + new Action() { // [192] expr = TRY seq_expr.a WITH opt_bar.b match_cases.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; @@ -2522,32 +2564,32 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [191] expr = TRY seq_expr WITH error + new Action() { // [193] expr = TRY seq_expr WITH error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [192] expr = expr_comma_list.a + new Action() { // [194] expr = expr_comma_list.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [193] expr = constr_longident.a simple_expr.b + new Action() { // [195] expr = constr_longident.a simple_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [194] expr = name_tag.a simple_expr.b + new Action() { // [196] expr = name_tag.a simple_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [195] expr = IF seq_expr.a THEN expr.b ELSE expr.c + new Action() { // [197] expr = IF seq_expr.a THEN expr.b ELSE expr.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; @@ -2555,21 +2597,21 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [196] expr = IF seq_expr.a THEN expr.b + new Action() { // [198] expr = IF seq_expr.a THEN expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [197] expr = WHILE seq_expr.a DO seq_expr.b DONE + new Action() { // [199] expr = WHILE seq_expr.a DO seq_expr.b DONE public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [198] expr = FOR val_ident.ident EQUAL seq_expr.b direction_flag seq_expr.c DO seq_expr.d DONE + new Action() { // [200] expr = FOR val_ident.ident EQUAL seq_expr.b direction_flag seq_expr.c DO seq_expr.d DONE public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol ident = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; @@ -2585,159 +2627,159 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return def; } }, - new Action() { // [199] expr = expr.a COLONCOLON expr.b + new Action() { // [201] expr = expr.a COLONCOLON expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [200] expr = LPAREN COLONCOLON RPAREN LPAREN expr.a COMMA expr.b RPAREN + new Action() { // [202] expr = LPAREN COLONCOLON RPAREN LPAREN expr.a COMMA expr.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 5]; final Symbol b = _symbols[offset + 7]; return Def.root(a,b); } }, - new Action() { // [201] expr = expr.a INFIXOP0 expr.b + new Action() { // [203] expr = expr.a INFIXOP0 expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [202] expr = expr.a INFIXOP1 expr.b + new Action() { // [204] expr = expr.a INFIXOP1 expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [203] expr = expr.a INFIXOP2 expr.b + new Action() { // [205] expr = expr.a INFIXOP2 expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [204] expr = expr.a INFIXOP3 expr.b + new Action() { // [206] expr = expr.a INFIXOP3 expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [205] expr = expr.a INFIXOP4 expr.b + new Action() { // [207] expr = expr.a INFIXOP4 expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [206] expr = expr.a PLUS expr.b + new Action() { // [208] expr = expr.a PLUS expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [207] expr = expr.a PLUSDOT expr.b + new Action() { // [209] expr = expr.a PLUSDOT expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [208] expr = expr.a MINUS expr.b + new Action() { // [210] expr = expr.a MINUS expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [209] expr = expr.a MINUSDOT expr.b + new Action() { // [211] expr = expr.a MINUSDOT expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [210] expr = expr.a STAR expr.b + new Action() { // [212] expr = expr.a STAR expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [211] expr = expr.a EQUAL expr.b + new Action() { // [213] expr = expr.a EQUAL expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [212] expr = expr.a LESS expr.b + new Action() { // [214] expr = expr.a LESS expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [213] expr = expr.a GREATER expr.b + new Action() { // [215] expr = expr.a GREATER expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [214] expr = expr.a OR expr.b + new Action() { // [216] expr = expr.a OR expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [215] expr = expr.a BARBAR expr.b + new Action() { // [217] expr = expr.a BARBAR expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [216] expr = expr.a AMPERSAND expr.b + new Action() { // [218] expr = expr.a AMPERSAND expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [217] expr = expr.a AMPERAMPER expr.b + new Action() { // [219] expr = expr.a AMPERAMPER expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [218] expr = expr.a COLONEQUAL expr.b + new Action() { // [220] expr = expr.a COLONEQUAL expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [219] expr = subtractive expr.a + new Action() { // [221] expr = subtractive expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [220] expr = additive expr.a + new Action() { // [222] expr = additive expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [221] expr = simple_expr.a DOT label_longident.b LESSMINUS expr.c + new Action() { // [223] expr = simple_expr.a DOT label_longident.b LESSMINUS expr.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -2745,7 +2787,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [222] expr = simple_expr.a DOT LPAREN seq_expr.b RPAREN LESSMINUS expr.c + new Action() { // [224] expr = simple_expr.a DOT LPAREN seq_expr.b RPAREN LESSMINUS expr.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; @@ -2753,7 +2795,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [223] expr = simple_expr.a DOT LBRACKET seq_expr.b RBRACKET LESSMINUS expr.c + new Action() { // [225] expr = simple_expr.a DOT LBRACKET seq_expr.b RBRACKET LESSMINUS expr.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; @@ -2761,7 +2803,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [224] expr = simple_expr.a DOT LBRACE expr.b RBRACE LESSMINUS expr.c + new Action() { // [226] expr = simple_expr.a DOT LBRACE expr.b RBRACE LESSMINUS expr.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; @@ -2769,26 +2811,26 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [225] expr = label.a LESSMINUS expr.b + new Action() { // [227] expr = label.a LESSMINUS expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [226] expr = ASSERT simple_expr.a + new Action() { // [228] expr = ASSERT simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [227] expr = LAZY simple_expr.a + new Action() { // [229] expr = LAZY simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [228] expr = OBJECT.o class_structure.a END + new Action() { // [230] expr = OBJECT.o class_structure.a END public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol o = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -2796,303 +2838,303 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def("", Def.Type.Object, o.getStart(), o.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [229] expr = OBJECT class_structure error + new Action() { // [231] expr = OBJECT class_structure error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [230] simple_expr = val_longident.a + new Action() { // [232] simple_expr = val_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [231] simple_expr = constant.a + new Action() { // [233] simple_expr = constant.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [232] simple_expr = constr_longident.a + new Action() { // [234] simple_expr = constr_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [233] simple_expr = name_tag.a + new Action() { // [235] simple_expr = name_tag.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [234] simple_expr = LPAREN seq_expr.a RPAREN + new Action() { // [236] simple_expr = LPAREN seq_expr.a RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [235] simple_expr = LPAREN seq_expr.a error + new Action() { // [237] simple_expr = LPAREN seq_expr.a error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [236] simple_expr = BEGIN seq_expr.a END + new Action() { // [238] simple_expr = BEGIN seq_expr.a END public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [237] simple_expr = BEGIN END + new Action() { // [239] simple_expr = BEGIN END public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [238] simple_expr = BEGIN seq_expr.a error + new Action() { // [240] simple_expr = BEGIN seq_expr.a error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [239] simple_expr = LPAREN seq_expr.a type_constraint.b RPAREN + new Action() { // [241] simple_expr = LPAREN seq_expr.a type_constraint.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [240] simple_expr = simple_expr.a DOT label_longident.b + new Action() { // [242] simple_expr = simple_expr.a DOT label_longident.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [241] simple_expr = mod_longident.a DOT LPAREN seq_expr.b RPAREN + new Action() { // [243] simple_expr = mod_longident.a DOT LPAREN seq_expr.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [242] simple_expr = mod_longident.a DOT LPAREN seq_expr.b error + new Action() { // [244] simple_expr = mod_longident.a DOT LPAREN seq_expr.b error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [243] simple_expr = simple_expr.a DOT LPAREN seq_expr.b RPAREN + new Action() { // [245] simple_expr = simple_expr.a DOT LPAREN seq_expr.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [244] simple_expr = simple_expr.a DOT LPAREN seq_expr.b error + new Action() { // [246] simple_expr = simple_expr.a DOT LPAREN seq_expr.b error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [245] simple_expr = simple_expr.a DOT LBRACKET seq_expr.b RBRACKET + new Action() { // [247] simple_expr = simple_expr.a DOT LBRACKET seq_expr.b RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [246] simple_expr = simple_expr.a DOT LBRACKET seq_expr.b error + new Action() { // [248] simple_expr = simple_expr.a DOT LBRACKET seq_expr.b error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [247] simple_expr = simple_expr.a DOT LBRACE expr.b RBRACE + new Action() { // [249] simple_expr = simple_expr.a DOT LBRACE expr.b RBRACE public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [248] simple_expr = simple_expr.a DOT LBRACE expr_comma_list.b error + new Action() { // [250] simple_expr = simple_expr.a DOT LBRACE expr_comma_list.b error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [249] simple_expr = LBRACE record_expr.a RBRACE + new Action() { // [251] simple_expr = LBRACE record_expr.a RBRACE public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [250] simple_expr = LBRACE record_expr.a error + new Action() { // [252] simple_expr = LBRACE record_expr.a error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [251] simple_expr = LBRACKETBAR expr_semi_list.a opt_semi.b BARRBRACKET + new Action() { // [253] simple_expr = LBRACKETBAR expr_semi_list.a opt_semi.b BARRBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [252] simple_expr = LBRACKETBAR expr_semi_list.a opt_semi.b error + new Action() { // [254] simple_expr = LBRACKETBAR expr_semi_list.a opt_semi.b error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [253] simple_expr = LBRACKETBAR BARRBRACKET + new Action() { // [255] simple_expr = LBRACKETBAR BARRBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [254] simple_expr = LBRACKET expr_semi_list.a opt_semi.b RBRACKET + new Action() { // [256] simple_expr = LBRACKET expr_semi_list.a opt_semi.b RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [255] simple_expr = LBRACKET expr_semi_list.a opt_semi.b error + new Action() { // [257] simple_expr = LBRACKET expr_semi_list.a opt_semi.b error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [256] simple_expr = PREFIXOP simple_expr.a + new Action() { // [258] simple_expr = PREFIXOP simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [257] simple_expr = BANG simple_expr.a + new Action() { // [259] simple_expr = BANG simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [258] simple_expr = NEW class_longident.a + new Action() { // [260] simple_expr = NEW class_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [259] simple_expr = LBRACELESS field_expr_list.a opt_semi.b GREATERRBRACE + new Action() { // [261] simple_expr = LBRACELESS field_expr_list.a opt_semi.b GREATERRBRACE public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [260] simple_expr = LBRACELESS field_expr_list.a opt_semi.b error + new Action() { // [262] simple_expr = LBRACELESS field_expr_list.a opt_semi.b error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [261] simple_expr = LBRACELESS GREATERRBRACE + new Action() { // [263] simple_expr = LBRACELESS GREATERRBRACE public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [262] simple_expr = simple_expr.a SHARP label.b + new Action() { // [264] simple_expr = simple_expr.a SHARP label.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [263] simple_expr = LPAREN MODULE module_expr.a COLON package_type.b RPAREN + new Action() { // [265] simple_expr = LPAREN MODULE module_expr.a COLON package_type.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 3]; final Symbol b = _symbols[offset + 5]; return Def.root(a,b); } }, - new Action() { // [264] simple_expr = LPAREN MODULE module_expr.a COLON error + new Action() { // [266] simple_expr = LPAREN MODULE module_expr.a COLON error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 3]; return a; } }, - new Action() { // [265] simple_labeled_expr_list = labeled_simple_expr.a + new Action() { // [267] simple_labeled_expr_list = labeled_simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [266] simple_labeled_expr_list = simple_labeled_expr_list.a labeled_simple_expr.b + new Action() { // [268] simple_labeled_expr_list = simple_labeled_expr_list.a labeled_simple_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [267] labeled_simple_expr = simple_expr.a + new Action() { // [269] labeled_simple_expr = simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [268] labeled_simple_expr = label_expr.a + new Action() { // [270] labeled_simple_expr = label_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [269] label_expr = LABEL simple_expr.a + new Action() { // [271] label_expr = LABEL simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [270] label_expr = TILDE label_ident.a + new Action() { // [272] label_expr = TILDE label_ident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [271] label_expr = QUESTION label_ident.a + new Action() { // [273] label_expr = QUESTION label_ident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [272] label_expr = OPTLABEL simple_expr.a + new Action() { // [274] label_expr = OPTLABEL simple_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [273] label_ident = LIDENT.id + new Action() { // [275] label_ident = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [274] let_bindings = let_binding.b + new Action() { // [276] let_bindings = let_binding.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol b = _symbols[offset + 1]; return b; } }, - new Action() { // [275] let_bindings = let_bindings.a AND let_binding.b + new Action() { // [277] let_bindings = let_bindings.a AND let_binding.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -3102,7 +3144,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b); } }, - new Action() { // [276] let_binding = val_ident.i fun_binding.f + new Action() { // [278] let_binding = val_ident.i fun_binding.f public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol i = _symbols[offset + 1]; final Symbol f = _symbols[offset + 2]; @@ -3111,11 +3153,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def(ident.name, Def.Type.Let, ident.posStart, ident.posEnd); def.add(f); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [277] let_binding = val_ident.i COLON typevar_list DOT core_type EQUAL seq_expr.b + new Action() { // [279] let_binding = val_ident.i COLON typevar_list DOT core_type EQUAL seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol i = _symbols[offset + 1]; final Symbol b = _symbols[offset + 7]; @@ -3124,11 +3166,11 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def(ident.name, Def.Type.Let, ident.posStart, ident.posEnd); def.add(b); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [278] let_binding = pattern.p EQUAL seq_expr.b + new Action() { // [280] let_binding = pattern.p EQUAL seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol p = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -3143,6 +3185,12 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def root = new Def(); + // update root position + int identsSize = idents.size(); + if (identsSize > 1) + root.posStart = idents.get(0).posStart; + root.posEnd = idents.get(identsSize - 1).posEnd; + Def last = null; for(int i = 0; i < idents.size(); i++){ Def ident = idents.get(i); @@ -3158,33 +3206,34 @@ public Symbol reduce(Symbol[] _symbols, int offset) { if(last != null){ last.add(b); last.collapse(); - backup(root); + backupDef(root); + return root; } return Def.root(p, b); } }, - new Action() { // [279] fun_binding = strict_binding.a + new Action() { // [281] fun_binding = strict_binding.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [280] fun_binding = type_constraint.a EQUAL seq_expr.b + new Action() { // [282] fun_binding = type_constraint.a EQUAL seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [281] strict_binding = EQUAL seq_expr.a + new Action() { // [283] strict_binding = EQUAL seq_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [282] strict_binding = labeled_simple_pattern.p fun_binding.b + new Action() { // [284] strict_binding = labeled_simple_pattern.p fun_binding.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol p = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; @@ -3196,6 +3245,12 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def root = new Def(); + // update root position + int identsSize = idents.size(); + if (identsSize > 1) + root.posStart = idents.get(0).posStart; + root.posEnd = idents.get(identsSize - 1).posEnd; + Def last = null; boolean bFirst = true; for(int i = 0; i < idents.size(); i++){ @@ -3216,14 +3271,14 @@ public Symbol reduce(Symbol[] _symbols, int offset) { if(last != null){ last.add(b); last.collapse(); - backup(root); + backupDef(root); return root; } return Def.root(p, b); } }, - new Action() { // [283] strict_binding = LPAREN TYPE LIDENT.id RPAREN fun_binding.a + new Action() { // [285] strict_binding = LPAREN TYPE LIDENT.id RPAREN fun_binding.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 5]; @@ -3236,7 +3291,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return root; } }, - new Action() { // [284] match_cases = pattern.p match_action.b + new Action() { // [286] match_cases = pattern.p match_action.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol p = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; @@ -3277,7 +3332,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(p, b); } }, - new Action() { // [285] match_cases = match_cases.a BAR pattern.b match_action.c + new Action() { // [287] match_cases = match_cases.a BAR pattern.b match_action.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -3319,13 +3374,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a, b, c); } }, - new Action() { // [286] fun_def = match_action.a + new Action() { // [288] fun_def = match_action.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [287] fun_def = labeled_simple_pattern.p fun_def.b + new Action() { // [289] fun_def = labeled_simple_pattern.p fun_def.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol p = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; @@ -3366,7 +3421,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(root, b); } }, - new Action() { // [288] fun_def = LPAREN TYPE LIDENT.id RPAREN fun_def.a + new Action() { // [290] fun_def = LPAREN TYPE LIDENT.id RPAREN fun_def.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 3]; final Symbol a = _symbols[offset + 5]; @@ -3379,34 +3434,34 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return root; } }, - new Action() { // [289] match_action = MINUSGREATER seq_expr.a + new Action() { // [291] match_action = MINUSGREATER seq_expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [290] match_action = WHEN seq_expr.a MINUSGREATER seq_expr.b + new Action() { // [292] match_action = WHEN seq_expr.a MINUSGREATER seq_expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [291] expr_comma_list = expr_comma_list.a COMMA expr.b + new Action() { // [293] expr_comma_list = expr_comma_list.a COMMA expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [292] expr_comma_list = expr.a COMMA expr.b + new Action() { // [294] expr_comma_list = expr.a COMMA expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [293] record_expr = simple_expr.a WITH lbl_expr_list.b opt_semi.c + new Action() { // [295] record_expr = simple_expr.a WITH lbl_expr_list.b opt_semi.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -3414,27 +3469,27 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [294] record_expr = lbl_expr_list.a opt_semi.b + new Action() { // [296] record_expr = lbl_expr_list.a opt_semi.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [295] lbl_expr_list = label_longident.a EQUAL expr.b + new Action() { // [297] lbl_expr_list = label_longident.a EQUAL expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [296] lbl_expr_list = label_longident.a + new Action() { // [298] lbl_expr_list = label_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [297] lbl_expr_list = lbl_expr_list.a SEMI label_longident.b EQUAL expr.c + new Action() { // [299] lbl_expr_list = lbl_expr_list.a SEMI label_longident.b EQUAL expr.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -3442,21 +3497,21 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [298] lbl_expr_list = lbl_expr_list.a SEMI label_longident.b + new Action() { // [300] lbl_expr_list = lbl_expr_list.a SEMI label_longident.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [299] field_expr_list = label.a EQUAL expr.b + new Action() { // [301] field_expr_list = label.a EQUAL expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [300] field_expr_list = field_expr_list.a SEMI label.b EQUAL expr.c + new Action() { // [302] field_expr_list = field_expr_list.a SEMI label.b EQUAL expr.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -3464,257 +3519,257 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [301] expr_semi_list = expr.a + new Action() { // [303] expr_semi_list = expr.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [302] expr_semi_list = expr_semi_list.a SEMI expr.b + new Action() { // [304] expr_semi_list = expr_semi_list.a SEMI expr.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [303] type_constraint = COLON core_type.a + new Action() { // [305] type_constraint = COLON core_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [304] type_constraint = COLON core_type.a COLONGREATER core_type.b + new Action() { // [306] type_constraint = COLON core_type.a COLONGREATER core_type.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [305] type_constraint = COLONGREATER core_type.a + new Action() { // [307] type_constraint = COLONGREATER core_type.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [306] type_constraint = COLON error + new Action() { // [308] type_constraint = COLON error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [307] type_constraint = COLONGREATER error + new Action() { // [309] type_constraint = COLONGREATER error public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [308] pattern = simple_pattern.a + new Action() { // [310] pattern = simple_pattern.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [309] pattern = pattern.a AS val_ident.b + new Action() { // [311] pattern = pattern.a AS val_ident.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [310] pattern = pattern_comma_list.a + new Action() { // [312] pattern = pattern_comma_list.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [311] pattern = constr_longident.a pattern.b + new Action() { // [313] pattern = constr_longident.a pattern.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [312] pattern = name_tag.a pattern.b + new Action() { // [314] pattern = name_tag.a pattern.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return Def.root(a,b); } }, - new Action() { // [313] pattern = pattern.a COLONCOLON pattern.b + new Action() { // [315] pattern = pattern.a COLONCOLON pattern.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [314] pattern = LPAREN COLONCOLON RPAREN LPAREN pattern.a COMMA pattern.b RPAREN + new Action() { // [316] pattern = LPAREN COLONCOLON RPAREN LPAREN pattern.a COMMA pattern.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 5]; final Symbol b = _symbols[offset + 7]; return Def.root(a,b); } }, - new Action() { // [315] pattern = pattern.a BAR pattern.b + new Action() { // [317] pattern = pattern.a BAR pattern.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [316] pattern = LAZY simple_pattern.a + new Action() { // [318] pattern = LAZY simple_pattern.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [317] simple_pattern = val_ident.a + new Action() { // [319] simple_pattern = val_ident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [318] simple_pattern = UNDERSCORE.id + new Action() { // [320] simple_pattern = UNDERSCORE.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def("_", Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [319] simple_pattern = signed_constant.a + new Action() { // [321] simple_pattern = signed_constant.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [320] simple_pattern = CHAR DOTDOT CHAR + new Action() { // [322] simple_pattern = CHAR DOTDOT CHAR public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [321] simple_pattern = constr_longident.a + new Action() { // [323] simple_pattern = constr_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [322] simple_pattern = name_tag.a + new Action() { // [324] simple_pattern = name_tag.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [323] simple_pattern = SHARP type_longident.a + new Action() { // [325] simple_pattern = SHARP type_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [324] simple_pattern = LBRACE lbl_pattern_list.a record_pattern_end RBRACE + new Action() { // [326] simple_pattern = LBRACE lbl_pattern_list.a record_pattern_end RBRACE public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [325] simple_pattern = LBRACE lbl_pattern_list.a opt_semi error + new Action() { // [327] simple_pattern = LBRACE lbl_pattern_list.a opt_semi error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [326] simple_pattern = LBRACKET pattern_semi_list.a opt_semi RBRACKET + new Action() { // [328] simple_pattern = LBRACKET pattern_semi_list.a opt_semi RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [327] simple_pattern = LBRACKET pattern_semi_list.a opt_semi error + new Action() { // [329] simple_pattern = LBRACKET pattern_semi_list.a opt_semi error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [328] simple_pattern = LBRACKETBAR pattern_semi_list.a opt_semi BARRBRACKET + new Action() { // [330] simple_pattern = LBRACKETBAR pattern_semi_list.a opt_semi BARRBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [329] simple_pattern = LBRACKETBAR BARRBRACKET + new Action() { // [331] simple_pattern = LBRACKETBAR BARRBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [330] simple_pattern = LBRACKETBAR pattern_semi_list.a opt_semi error + new Action() { // [332] simple_pattern = LBRACKETBAR pattern_semi_list.a opt_semi error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [331] simple_pattern = LPAREN pattern.a RPAREN + new Action() { // [333] simple_pattern = LPAREN pattern.a RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [332] simple_pattern = LPAREN pattern.a error + new Action() { // [334] simple_pattern = LPAREN pattern.a error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [333] simple_pattern = LPAREN pattern.a COLON core_type.b RPAREN + new Action() { // [335] simple_pattern = LPAREN pattern.a COLON core_type.b RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [334] simple_pattern = LPAREN pattern.a COLON core_type.b error + new Action() { // [336] simple_pattern = LPAREN pattern.a COLON core_type.b error public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; final Symbol b = _symbols[offset + 4]; return Def.root(a,b); } }, - new Action() { // [335] pattern_comma_list = pattern_comma_list.a COMMA pattern.b + new Action() { // [337] pattern_comma_list = pattern_comma_list.a COMMA pattern.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [336] pattern_comma_list = pattern.a COMMA pattern.b + new Action() { // [338] pattern_comma_list = pattern.a COMMA pattern.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [337] pattern_semi_list = pattern.a + new Action() { // [339] pattern_semi_list = pattern.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [338] pattern_semi_list = pattern_semi_list.a SEMI pattern.b + new Action() { // [340] pattern_semi_list = pattern_semi_list.a SEMI pattern.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [339] lbl_pattern_list = label_longident.a EQUAL pattern.b + new Action() { // [341] lbl_pattern_list = label_longident.a EQUAL pattern.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [340] lbl_pattern_list = label_longident.a + new Action() { // [342] lbl_pattern_list = label_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [341] lbl_pattern_list = lbl_pattern_list.a SEMI label_longident.b EQUAL pattern.c + new Action() { // [343] lbl_pattern_list = lbl_pattern_list.a SEMI label_longident.b EQUAL pattern.c public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -3722,43 +3777,43 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b,c); } }, - new Action() { // [342] lbl_pattern_list = lbl_pattern_list.a SEMI label_longident.b + new Action() { // [344] lbl_pattern_list = lbl_pattern_list.a SEMI label_longident.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [343] record_pattern_end = opt_semi.a + new Action() { // [345] record_pattern_end = opt_semi.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [344] record_pattern_end = SEMI UNDERSCORE opt_semi.a + new Action() { // [346] record_pattern_end = SEMI UNDERSCORE opt_semi.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 3]; return a; } }, - new Action() { // [345] primitive_declaration = STRING + new Action() { // [347] primitive_declaration = STRING public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [346] primitive_declaration = STRING primitive_declaration.a + new Action() { // [348] primitive_declaration = STRING primitive_declaration.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [347] type_declarations = type_declaration.a + new Action() { // [349] type_declarations = type_declaration.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [348] type_declarations = type_declarations.a AND.n type_declaration.b + new Action() { // [350] type_declarations = type_declarations.a AND.n type_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol n = _symbols[offset + 2]; @@ -3770,7 +3825,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return Def.root(a,b); } }, - new Action() { // [349] type_declaration = type_parameters LIDENT.id type_kind.a constraints + new Action() { // [351] type_declaration = type_parameters LIDENT.id type_kind.a constraints public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 2]; final Symbol a = _symbols[offset + 3]; @@ -3778,159 +3833,159 @@ public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def((String)id.value, Def.Type.Type, id.getStart(), id.getEnd()); def.add(a); def.collapse(); - backup(def); + backupDef(def); return def; } }, - new Action() { // [350] constraints = constraints CONSTRAINT constrain + new Action() { // [352] constraints = constraints CONSTRAINT constrain public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [351] constraints = + new Action() { // [353] constraints = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [352] type_kind = + new Action() { // [354] type_kind = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [353] type_kind = EQUAL core_type + new Action() { // [355] type_kind = EQUAL core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [354] type_kind = EQUAL PRIVATE core_type + new Action() { // [356] type_kind = EQUAL PRIVATE core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [355] type_kind = EQUAL constructor_declarations.a + new Action() { // [357] type_kind = EQUAL constructor_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [356] type_kind = EQUAL PRIVATE constructor_declarations.a + new Action() { // [358] type_kind = EQUAL PRIVATE constructor_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 3]; return a; } }, - new Action() { // [357] type_kind = EQUAL private_flag BAR constructor_declarations.a + new Action() { // [359] type_kind = EQUAL private_flag BAR constructor_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 4]; return a; } }, - new Action() { // [358] type_kind = EQUAL private_flag LBRACE label_declarations.a opt_semi RBRACE + new Action() { // [360] type_kind = EQUAL private_flag LBRACE label_declarations.a opt_semi RBRACE public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 4]; return a; } }, - new Action() { // [359] type_kind = EQUAL core_type EQUAL private_flag opt_bar constructor_declarations.a + new Action() { // [361] type_kind = EQUAL core_type EQUAL private_flag opt_bar constructor_declarations.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 6]; return a; } }, - new Action() { // [360] type_kind = EQUAL core_type EQUAL private_flag LBRACE label_declarations.a opt_semi RBRACE + new Action() { // [362] type_kind = EQUAL core_type EQUAL private_flag LBRACE label_declarations.a opt_semi RBRACE public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 6]; return a; } }, - new Action() { // [361] type_parameters = + new Action() { // [363] type_parameters = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [362] type_parameters = type_parameter + new Action() { // [364] type_parameters = type_parameter public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [363] type_parameters = LPAREN type_parameter_list RPAREN + new Action() { // [365] type_parameters = LPAREN type_parameter_list RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [364] type_parameter = type_variance QUOTE ident + new Action() { // [366] type_parameter = type_variance QUOTE ident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [365] type_variance = + new Action() { // [367] type_variance = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [366] type_variance = PLUS + new Action() { // [368] type_variance = PLUS public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [367] type_variance = MINUS + new Action() { // [369] type_variance = MINUS public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [368] type_parameter_list = type_parameter + new Action() { // [370] type_parameter_list = type_parameter public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [369] type_parameter_list = type_parameter_list COMMA type_parameter + new Action() { // [371] type_parameter_list = type_parameter_list COMMA type_parameter public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [370] constructor_declarations = constructor_declaration.a + new Action() { // [372] constructor_declarations = constructor_declaration.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [371] constructor_declarations = constructor_declarations.a BAR constructor_declaration.b + new Action() { // [373] constructor_declarations = constructor_declarations.a BAR constructor_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [372] constructor_declaration = constr_ident.a constructor_arguments + new Action() { // [374] constructor_declaration = constr_ident.a constructor_arguments public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [373] constructor_arguments = + new Action() { // [375] constructor_arguments = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [374] constructor_arguments = OF core_type_list + new Action() { // [376] constructor_arguments = OF core_type_list public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [375] label_declarations = label_declaration.a + new Action() { // [377] label_declarations = label_declaration.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [376] label_declarations = label_declarations.a SEMI label_declaration.b + new Action() { // [378] label_declarations = label_declarations.a SEMI label_declaration.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; return Def.root(a,b); } }, - new Action() { // [377] label_declaration = mutable_flag.m label.a COLON poly_type + new Action() { // [379] label_declaration = mutable_flag.m label.a COLON poly_type public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; final Symbol a = _symbols[offset + 2]; @@ -3943,461 +3998,470 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return da; } }, - new Action() { // [378] with_constraints = with_constraint + new Action() { // [380] with_constraints = with_constraint public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [379] with_constraints = with_constraints AND with_constraint + new Action() { // [381] with_constraints = with_constraints AND with_constraint public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [380] with_constraint = TYPE type_parameters label_longident with_type_binder core_type constraints + new Action() { // [382] with_constraint = TYPE type_parameters label_longident with_type_binder core_type constraints public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [381] with_constraint = TYPE type_parameters label_longident COLONEQUAL core_type + new Action() { // [383] with_constraint = TYPE type_parameters label_longident COLONEQUAL core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [382] with_constraint = MODULE mod_longident EQUAL mod_ext_longident + new Action() { // [384] with_constraint = MODULE mod_longident EQUAL mod_ext_longident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [383] with_constraint = MODULE mod_longident COLONEQUAL mod_ext_longident + new Action() { // [385] with_constraint = MODULE mod_longident COLONEQUAL mod_ext_longident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [384] with_type_binder = EQUAL + new Action() { // [386] with_type_binder = EQUAL public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [385] with_type_binder = EQUAL PRIVATE + new Action() { // [387] with_type_binder = EQUAL PRIVATE public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [386] typevar_list = QUOTE ident + new Action() { // [388] typevar_list = QUOTE ident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [387] typevar_list = typevar_list QUOTE ident + new Action() { // [389] typevar_list = typevar_list QUOTE ident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [388] poly_type = core_type + new Action() { // [390] poly_type = core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [389] poly_type = typevar_list DOT core_type + new Action() { // [391] poly_type = typevar_list DOT core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [390] core_type = core_type2 + new Action() { // [392] core_type = core_type2 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [391] core_type = core_type2 AS QUOTE ident + new Action() { // [393] core_type = core_type2 AS QUOTE ident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [392] core_type2 = simple_core_type_or_tuple + new Action() { // [394] core_type2 = simple_core_type_or_tuple public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [393] core_type2 = QUESTION LIDENT COLON core_type2 MINUSGREATER core_type2 + new Action() { // [395] core_type2 = QUESTION LIDENT COLON core_type2 MINUSGREATER core_type2 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [394] core_type2 = OPTLABEL core_type2 MINUSGREATER core_type2 + new Action() { // [396] core_type2 = OPTLABEL core_type2 MINUSGREATER core_type2 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [395] core_type2 = LIDENT COLON core_type2 MINUSGREATER core_type2 + new Action() { // [397] core_type2 = LIDENT COLON core_type2 MINUSGREATER core_type2 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [396] core_type2 = core_type2 MINUSGREATER core_type2 + new Action() { // [398] core_type2 = core_type2 MINUSGREATER core_type2 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [397] simple_core_type = simple_core_type2 + new Action() { // [399] simple_core_type = simple_core_type2 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [398] simple_core_type = LPAREN core_type_comma_list RPAREN + new Action() { // [400] simple_core_type = LPAREN core_type_comma_list RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [399] simple_core_type2 = QUOTE ident + new Action() { // [401] simple_core_type2 = QUOTE ident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [400] simple_core_type2 = UNDERSCORE + new Action() { // [402] simple_core_type2 = UNDERSCORE public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [401] simple_core_type2 = type_longident + new Action() { // [403] simple_core_type2 = type_longident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [402] simple_core_type2 = simple_core_type2 type_longident + new Action() { // [404] simple_core_type2 = simple_core_type2 type_longident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [403] simple_core_type2 = LPAREN core_type_comma_list RPAREN type_longident + new Action() { // [405] simple_core_type2 = LPAREN core_type_comma_list RPAREN type_longident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [404] simple_core_type2 = LESS meth_list GREATER + new Action() { // [406] simple_core_type2 = LESS meth_list GREATER public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [405] simple_core_type2 = LESS GREATER + new Action() { // [407] simple_core_type2 = LESS GREATER public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [406] simple_core_type2 = SHARP class_longident opt_present + new Action() { // [408] simple_core_type2 = SHARP class_longident opt_present public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [407] simple_core_type2 = simple_core_type2 SHARP class_longident opt_present + new Action() { // [409] simple_core_type2 = simple_core_type2 SHARP class_longident opt_present public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [408] simple_core_type2 = LPAREN core_type_comma_list RPAREN SHARP class_longident opt_present + new Action() { // [410] simple_core_type2 = LPAREN core_type_comma_list RPAREN SHARP class_longident opt_present public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [409] simple_core_type2 = LBRACKET tag_field RBRACKET + new Action() { // [411] simple_core_type2 = LBRACKET tag_field RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [410] simple_core_type2 = LBRACKET BAR row_field_list RBRACKET + new Action() { // [412] simple_core_type2 = LBRACKET BAR row_field_list RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [411] simple_core_type2 = LBRACKET row_field BAR row_field_list RBRACKET + new Action() { // [413] simple_core_type2 = LBRACKET row_field BAR row_field_list RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [412] simple_core_type2 = LBRACKETGREATER opt_bar row_field_list RBRACKET + new Action() { // [414] simple_core_type2 = LBRACKETGREATER opt_bar row_field_list RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [413] simple_core_type2 = LBRACKETGREATER RBRACKET + new Action() { // [415] simple_core_type2 = LBRACKETGREATER RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [414] simple_core_type2 = LBRACKETLESS opt_bar row_field_list RBRACKET + new Action() { // [416] simple_core_type2 = LBRACKETLESS opt_bar row_field_list RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [415] simple_core_type2 = LBRACKETLESS opt_bar row_field_list GREATER name_tag_list RBRACKET + new Action() { // [417] simple_core_type2 = LBRACKETLESS opt_bar row_field_list GREATER name_tag_list RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [416] simple_core_type2 = LPAREN MODULE package_type RPAREN + new Action() { // [418] simple_core_type2 = LPAREN MODULE package_type RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [417] package_type = mty_longident + new Action() { // [419] package_type = mty_longident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [418] package_type = mty_longident WITH package_type_cstrs + new Action() { // [420] package_type = mty_longident WITH package_type_cstrs public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [419] package_type_cstr = TYPE LIDENT EQUAL core_type + new Action() { // [421] package_type_cstr = TYPE LIDENT EQUAL core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [420] package_type_cstrs = package_type_cstr + new Action() { // [422] package_type_cstrs = package_type_cstr public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [421] package_type_cstrs = package_type_cstr AND package_type_cstrs + new Action() { // [423] package_type_cstrs = package_type_cstr AND package_type_cstrs public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [422] row_field_list = row_field + new Action() { // [424] row_field_list = row_field public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [423] row_field_list = row_field_list BAR row_field + new Action() { // [425] row_field_list = row_field_list BAR row_field public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [424] row_field = tag_field + new Action() { // [426] row_field = tag_field public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [425] row_field = simple_core_type2 + new Action() { // [427] row_field = simple_core_type2 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [426] tag_field = name_tag OF opt_ampersand amper_type_list + new Action() { // [428] tag_field = name_tag OF opt_ampersand amper_type_list public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [427] tag_field = name_tag + new Action() { // [429] tag_field = name_tag public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [428] opt_ampersand = AMPERSAND + new Action() { // [430] opt_ampersand = AMPERSAND public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [429] opt_ampersand = + new Action() { // [431] opt_ampersand = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [430] amper_type_list = core_type + new Action() { // [432] amper_type_list = core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [431] amper_type_list = amper_type_list AMPERSAND core_type + new Action() { // [433] amper_type_list = amper_type_list AMPERSAND core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [432] opt_present = LBRACKETGREATER name_tag_list RBRACKET + new Action() { // [434] opt_present = LBRACKETGREATER name_tag_list RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [433] opt_present = + new Action() { // [435] opt_present = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [434] name_tag_list = name_tag + new Action() { // [436] name_tag_list = name_tag public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [435] name_tag_list = name_tag_list name_tag + new Action() { // [437] name_tag_list = name_tag_list name_tag public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [436] simple_core_type_or_tuple = simple_core_type + new Action() { // [438] simple_core_type_or_tuple = simple_core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [437] simple_core_type_or_tuple = simple_core_type STAR core_type_list + new Action() { // [439] simple_core_type_or_tuple = simple_core_type STAR core_type_list public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [438] core_type_comma_list = core_type + new Action() { // [440] core_type_comma_list = core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [439] core_type_comma_list = core_type_comma_list COMMA core_type + new Action() { // [441] core_type_comma_list = core_type_comma_list COMMA core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [440] core_type_list = simple_core_type + new Action() { // [442] core_type_list = simple_core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [441] core_type_list = core_type_list STAR simple_core_type + new Action() { // [443] core_type_list = core_type_list STAR simple_core_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [442] meth_list = field SEMI meth_list + new Action() { // [444] meth_list = field SEMI meth_list public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [443] meth_list = field opt_semi + new Action() { // [445] meth_list = field opt_semi public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [444] meth_list = DOTDOT + new Action() { // [446] meth_list = DOTDOT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [445] field = label COLON poly_type + new Action() { // [447] field = label COLON poly_type public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [446] label = LIDENT.id + new Action() { // [448] label = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [447] constant = INT + new Action() { // [449] constant = INT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [448] constant = CHAR + new Action() { // [450] constant = CHAR public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [449] constant = STRING + new Action() { // [451] constant = STRING public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [450] constant = FLOAT + new Action() { // [452] constant = FLOAT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [451] constant = INT32 + new Action() { // [453] constant = INT32 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [452] constant = INT64 + new Action() { // [454] constant = INT64 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [453] constant = NATIVEINT + new Action() { // [455] constant = NATIVEINT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [454] signed_constant = constant + new Action() { // [456] signed_constant = constant public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [455] signed_constant = MINUS INT + new Action() { // [457] signed_constant = MINUS INT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [456] signed_constant = MINUS FLOAT + new Action() { // [458] signed_constant = MINUS FLOAT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [457] signed_constant = MINUS INT32 + new Action() { // [459] signed_constant = MINUS INT32 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [458] signed_constant = MINUS INT64 + new Action() { // [460] signed_constant = MINUS INT64 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [459] signed_constant = MINUS NATIVEINT + new Action() { // [461] signed_constant = MINUS NATIVEINT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [460] signed_constant = PLUS INT + new Action() { // [462] signed_constant = PLUS INT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [461] signed_constant = PLUS FLOAT + new Action() { // [463] signed_constant = PLUS FLOAT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [462] signed_constant = PLUS INT32 + new Action() { // [464] signed_constant = PLUS INT32 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [463] signed_constant = PLUS INT64 + new Action() { // [465] signed_constant = PLUS INT64 public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [464] signed_constant = PLUS NATIVEINT + new Action() { // [466] signed_constant = PLUS NATIVEINT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [465] ident = UIDENT.id + new Action() { // [467] ident = UIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; - return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + + Def def = new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + backupIdent(def); + return def; } }, - new Action() { // [466] ident = LIDENT.id + new Action() { // [468] ident = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; - return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + + Def def = new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + backupIdent(def); + return def; } }, - new Action() { // [467] val_ident = LIDENT.id + new Action() { // [469] val_ident = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; - return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + + Def def = new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); + backupIdent(def); + return def; } }, - new Action() { // [468] val_ident = LPAREN operator.o RPAREN + new Action() { // [470] val_ident = LPAREN operator.o RPAREN public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol o = _symbols[offset + 2]; @@ -4405,127 +4469,127 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(op.name, Def.Type.Identifier, op.posStart, op.posEnd); } }, - new Action() { // [469] operator = PREFIXOP.id + new Action() { // [471] operator = PREFIXOP.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [470] operator = INFIXOP0.id + new Action() { // [472] operator = INFIXOP0.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [471] operator = INFIXOP1.id + new Action() { // [473] operator = INFIXOP1.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [472] operator = INFIXOP2.id + new Action() { // [474] operator = INFIXOP2.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [473] operator = INFIXOP3.id + new Action() { // [475] operator = INFIXOP3.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [474] operator = INFIXOP4.id + new Action() { // [476] operator = INFIXOP4.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [475] operator = BANG.id + new Action() { // [477] operator = BANG.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [476] operator = PLUS.id + new Action() { // [478] operator = PLUS.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [477] operator = PLUSDOT.id + new Action() { // [479] operator = PLUSDOT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [478] operator = MINUS.id + new Action() { // [480] operator = MINUS.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [479] operator = MINUSDOT.id + new Action() { // [481] operator = MINUSDOT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [480] operator = STAR.id + new Action() { // [482] operator = STAR.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [481] operator = EQUAL.id + new Action() { // [483] operator = EQUAL.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [482] operator = LESS.id + new Action() { // [484] operator = LESS.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [483] operator = GREATER.id + new Action() { // [485] operator = GREATER.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [484] operator = OR.id + new Action() { // [486] operator = OR.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [485] operator = BARBAR.id + new Action() { // [487] operator = BARBAR.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [486] operator = AMPERSAND.id + new Action() { // [488] operator = AMPERSAND.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [487] operator = AMPERAMPER.id + new Action() { // [489] operator = AMPERAMPER.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [488] operator = COLONEQUAL.id + new Action() { // [490] operator = COLONEQUAL.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [489] constr_ident = UIDENT.id + new Action() { // [491] constr_ident = UIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; @@ -4534,38 +4598,38 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return def; } }, - new Action() { // [490] constr_ident = LPAREN.a RPAREN.b + new Action() { // [492] constr_ident = LPAREN.a RPAREN.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return new Def("()", Def.Type.TypeConstructor, a.getStart(), b.getEnd()); } }, - new Action() { // [491] constr_ident = COLONCOLON.a + new Action() { // [493] constr_ident = COLONCOLON.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return new Def("::", Def.Type.TypeConstructor, a.getStart(), a.getEnd()); } }, - new Action() { // [492] constr_ident = FALSE.id + new Action() { // [494] constr_ident = FALSE.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def("false", Def.Type.TypeConstructor, id.getStart(), id.getEnd()); } }, - new Action() { // [493] constr_ident = TRUE.id + new Action() { // [495] constr_ident = TRUE.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def("true", Def.Type.TypeConstructor, id.getStart(), id.getEnd()); } }, - new Action() { // [494] val_longident = val_ident.a + new Action() { // [496] val_longident = val_ident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [495] val_longident = mod_longident.a DOT val_ident.b + new Action() { // [497] val_longident = mod_longident.a DOT val_ident.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -4575,41 +4639,41 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "." + db.name, Def.Type.Identifier, da.posStart, db.posEnd); } }, - new Action() { // [496] constr_longident = mod_longident.a + new Action() { // [498] constr_longident = mod_longident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [497] constr_longident = LBRACKET RBRACKET + new Action() { // [499] constr_longident = LBRACKET RBRACKET public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [498] constr_longident = LPAREN.a RPAREN.b + new Action() { // [500] constr_longident = LPAREN.a RPAREN.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 2]; return new Def("()", Def.Type.Identifier, a.getStart(), b.getEnd()); } }, - new Action() { // [499] constr_longident = FALSE + new Action() { // [501] constr_longident = FALSE public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [500] constr_longident = TRUE + new Action() { // [502] constr_longident = TRUE public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [501] label_longident = LIDENT.id + new Action() { // [503] label_longident = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [502] label_longident = mod_longident.a DOT LIDENT.id + new Action() { // [504] label_longident = mod_longident.a DOT LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -4618,13 +4682,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "." + (String)id.value, Def.Type.Identifier, da.posStart, id.getEnd()); } }, - new Action() { // [503] type_longident = LIDENT.id + new Action() { // [505] type_longident = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [504] type_longident = mod_ext_longident.a DOT LIDENT.id + new Action() { // [506] type_longident = mod_ext_longident.a DOT LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -4633,13 +4697,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "." + (String)id.value, Def.Type.Identifier, da.posStart, id.getEnd()); } }, - new Action() { // [505] mod_longident = UIDENT.id + new Action() { // [507] mod_longident = UIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [506] mod_longident = mod_longident.a DOT UIDENT.id + new Action() { // [508] mod_longident = mod_longident.a DOT UIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -4648,13 +4712,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "." + (String)id.value, Def.Type.Identifier, da.posStart, id.getEnd()); } }, - new Action() { // [507] mod_ext_longident = UIDENT.id + new Action() { // [509] mod_ext_longident = UIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [508] mod_ext_longident = mod_ext_longident.a DOT UIDENT.id + new Action() { // [510] mod_ext_longident = mod_ext_longident.a DOT UIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -4663,7 +4727,7 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "." + (String)id.value, Def.Type.Identifier, da.posStart, id.getEnd()); } }, - new Action() { // [509] mod_ext_longident = mod_ext_longident.a LPAREN mod_ext_longident.b RPAREN.par + new Action() { // [511] mod_ext_longident = mod_ext_longident.a LPAREN mod_ext_longident.b RPAREN.par public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -4674,13 +4738,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "(" + db.name + ")", Def.Type.Identifier, da.posStart, par.getEnd()); } }, - new Action() { // [510] mty_longident = ident.a + new Action() { // [512] mty_longident = ident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; return a; } }, - new Action() { // [511] mty_longident = mod_ext_longident.a DOT ident.b + new Action() { // [513] mty_longident = mod_ext_longident.a DOT ident.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol b = _symbols[offset + 3]; @@ -4690,13 +4754,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "." + db.name, Def.Type.Identifier, da.posStart, db.posEnd); } }, - new Action() { // [512] clty_longident = LIDENT.id + new Action() { // [514] clty_longident = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [513] clty_longident = mod_ext_longident.a DOT LIDENT.id + new Action() { // [515] clty_longident = mod_ext_longident.a DOT LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -4705,13 +4769,13 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "." + (String)id.value, Def.Type.Identifier, da.posStart, id.getEnd()); } }, - new Action() { // [514] class_longident = LIDENT.id + new Action() { // [516] class_longident = LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol id = _symbols[offset + 1]; return new Def((String)id.value, Def.Type.Identifier, id.getStart(), id.getEnd()); } }, - new Action() { // [515] class_longident = mod_longident.a DOT LIDENT.id + new Action() { // [517] class_longident = mod_longident.a DOT LIDENT.id public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 1]; final Symbol id = _symbols[offset + 3]; @@ -4720,142 +4784,162 @@ public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(da.name + "." + (String)id.value, Def.Type.Identifier, da.posStart, id.getEnd()); } }, - new Action() { // [516] toplevel_directive = SHARP ident + new Action() { // [518] toplevel_directive = SHARP ident + public Symbol reduce(Symbol[] _symbols, int offset) { + return new Def(); + } + }, + new Action() { // [519] toplevel_directive = SHARP ident STRING + public Symbol reduce(Symbol[] _symbols, int offset) { + return new Def(); + } + }, + new Action() { // [520] toplevel_directive = SHARP ident INT + public Symbol reduce(Symbol[] _symbols, int offset) { + return new Def(); + } + }, + new Action() { // [521] toplevel_directive = SHARP ident val_longident + public Symbol reduce(Symbol[] _symbols, int offset) { + return new Def(); + } + }, + new Action() { // [522] toplevel_directive = SHARP ident FALSE public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [517] toplevel_directive = SHARP ident STRING + new Action() { // [523] toplevel_directive = SHARP ident TRUE public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [518] toplevel_directive = SHARP ident INT + new Action() { // [524] cppo_directive = SHARP ident public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [519] toplevel_directive = SHARP ident val_longident + new Action() { // [525] cppo_directive = SHARP INCLUDE STRING public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [520] toplevel_directive = SHARP ident FALSE + new Action() { // [526] cppo_directive = SHARP ident STRING public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [521] toplevel_directive = SHARP ident TRUE + new Action() { // [527] cppo_directive = SHARP ident ident seq_expr public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [522] name_tag = BACKQUOTE ident.a + new Action() { // [528] name_tag = BACKQUOTE ident.a public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol a = _symbols[offset + 2]; return a; } }, - new Action() { // [523] rec_flag = + new Action() { // [529] rec_flag = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [524] rec_flag = REC + new Action() { // [530] rec_flag = REC public Symbol reduce(Symbol[] _symbols, int offset) { Def def = new Def(); def.bRec = true; return def; } }, - new Action() { // [525] direction_flag = TO + new Action() { // [531] direction_flag = TO public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [526] direction_flag = DOWNTO + new Action() { // [532] direction_flag = DOWNTO public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [527] private_flag = + new Action() { // [533] private_flag = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [528] private_flag = PRIVATE.p + new Action() { // [534] private_flag = PRIVATE.p public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol p = _symbols[offset + 1]; Def def = new Def(); def.bAlt=true; def.posStart = p.getStart(); return def; } }, - new Action() { // [529] mutable_flag = + new Action() { // [535] mutable_flag = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [530] mutable_flag = MUTABLE.m + new Action() { // [536] mutable_flag = MUTABLE.m public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol m = _symbols[offset + 1]; Def def = new Def(); def.bAlt=true; def.posStart = m.getStart(); return def; } }, - new Action() { // [531] virtual_flag = + new Action() { // [537] virtual_flag = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [532] virtual_flag = VIRTUAL.v + new Action() { // [538] virtual_flag = VIRTUAL.v public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol v = _symbols[offset + 1]; Def def = new Def(); def.bAlt=true; def.posStart = v.getStart(); return def; } }, - new Action() { // [533] override_flag = + new Action() { // [539] override_flag = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [534] override_flag = BANG.b + new Action() { // [540] override_flag = BANG.b public Symbol reduce(Symbol[] _symbols, int offset) { final Symbol b = _symbols[offset + 1]; Def def = new Def(); def.bAlt=true; def.posStart = b.getStart(); return def; } }, - new Action() { // [535] opt_bar = + new Action() { // [541] opt_bar = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [536] opt_bar = BAR + new Action() { // [542] opt_bar = BAR public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [537] opt_semi = + new Action() { // [543] opt_semi = public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [538] opt_semi = SEMI + new Action() { // [544] opt_semi = SEMI public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [539] subtractive = MINUS + new Action() { // [545] subtractive = MINUS public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [540] subtractive = MINUSDOT + new Action() { // [546] subtractive = MINUSDOT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [541] additive = PLUS + new Action() { // [547] additive = PLUS public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } }, - new Action() { // [542] additive = PLUSDOT + new Action() { // [548] additive = PLUSDOT public Symbol reduce(Symbol[] _symbols, int offset) { return new Def(); } diff --git a/Ocaml/src/ocaml/parsers/Camlp4Preprocessor.java b/Ocaml/src/ocaml/parsers/Camlp4Preprocessor.java index 6150015..636f8dd 100644 --- a/Ocaml/src/ocaml/parsers/Camlp4Preprocessor.java +++ b/Ocaml/src/ocaml/parsers/Camlp4Preprocessor.java @@ -196,7 +196,7 @@ public void associateCamlp4Locations(IDocument oldDocument, String strOldDocumen if (def.type != Def.Type.Root) { - IRegion region = def.getRegion(newDocument); + IRegion region = def.getNameRegion(newDocument); // String doc = newDocument.get(); int pos = region.getOffset() - 1; diff --git a/Ocaml/src/ocaml/parsers/OcamlNewInterfaceParser.java b/Ocaml/src/ocaml/parsers/OcamlNewInterfaceParser.java index 6b716b7..88d23d2 100644 --- a/Ocaml/src/ocaml/parsers/OcamlNewInterfaceParser.java +++ b/Ocaml/src/ocaml/parsers/OcamlNewInterfaceParser.java @@ -64,7 +64,8 @@ public static OcamlNewInterfaceParser getInstance() { * interpreting a keyword inside a comment, and to attach comments to * definitions. */ - private LinkedList comments; + private LinkedList comments = new LinkedList(); + /** Section comments */ private LinkedList sectionComments; @@ -198,12 +199,9 @@ protected IStatus run(IProgressMonitor monitor) { String errors = preprocessor.getErrorOutput().trim(); if (!"".equals(errors)) { Def def = new Def(moduleName, Def.Type.ParserError, 0, 0); - def.filename = filename; - - def - .setComment("ERROR: The camlp4 preprocessor encountered an error " + def.setFileName(filename); + def.setComment("ERROR: The camlp4 preprocessor encountered an error " + "while parsing this file:\n" + errors); - cache.addFirst(new CachedDef(file, def)); return def; } @@ -216,20 +214,14 @@ protected IStatus run(IProgressMonitor monitor) { // parse the .mli interface file or the .ml module file try { // System.err.println("parsing:" + filename); - definition = parseModule(lines, moduleName, bInterface); + definition = parseModule(lines, filename, moduleName, bInterface); } catch (Throwable e) { - // if there was a parsing error, we log it and we continue on to the - // next file - // OcamlPlugin.logError("Error parsing '" + moduleName + "'", e); + // if there was a parsing error, we log it and we continue on to the next file + e.printStackTrace(); Def def = new Def(moduleName, Def.Type.ParserError, 0, 0); - def.filename = filename; - - def - .setComment("ERROR: The parser encountered an error while parsing this file.\n\n" + def.setFileName(filename); + def.setComment("ERROR 2: The parser encountered an error while parsing this file.\n\n" + "Please make sure that it is syntactically correct.\n\n"); - - // System.err.println("ERROR:" + filename); - cache.addFirst(new CachedDef(file, def)); return def; } @@ -268,14 +260,13 @@ protected IStatus run(IProgressMonitor monitor) { } private void setFilenames(Def definition, String filename) { - definition.filename = filename; + definition.setFileName(filename); for (Def child : definition.children) setFilenames(child, filename); } - private Def parseModule(String doc, String moduleName, + private Def parseModule(String doc, String filename, String moduleName, boolean parseInterface) throws Throwable { - /* * "Sanitize" the document by replacing extended characters, which * otherwise would crash the parser @@ -296,19 +287,38 @@ private Def parseModule(String doc, String moduleName, Def root = null; - if (parseInterface) - root = (Def) parser.parse(scanner, OcamlParser.AltGoals.interfaces); - else - root = (Def) parser.parse(scanner); - - root = root.cleanCopy(); + try { + if (parseInterface) + root = (Def) parser.parse(scanner, OcamlParser.AltGoals.interfaces); + else + root = (Def) parser.parse(scanner); + root = root.cleanCopy(false); + } catch (Exception e) { + // recover pieces from the AST (which couldn't be built completely + // because of an unrecoverable error) + if (root == null || !parser.errorReporting.errors.isEmpty()) { + root = new Def(moduleName, Def.Type.Module, 0, 0); + for (Def def : parser.recoverDefs) + if (def.bTop && def.name != null && !"".equals(def.name.trim())) { + def.bTop = false; + root.children.add(def); + } + for (Def def : parser.recoverIdents) + if (def.bTop && def.name != null && !"".equals(def.name.trim())) { + def.bTop = false; + root.children.add(def); + } + root = root.cleanCopy(true); + } + } + root.name = moduleName; // set the start offset from the packed (line, column) positions computeLinesStartOffset(doc); computeDefinitionsStartOffset(root); - + // parse the comments and remove them from the text if (parseInterface) { doc = parseComments(doc); @@ -328,8 +338,7 @@ private Def parseModule(String doc, String moduleName, if (parser.errorReporting.errors.size() != 0) { root.type = Def.Type.ParserError; - root - .setComment("ERROR: The parser encountered an error while parsing this file.\n\n" + root.setComment("ERROR 1: The parser encountered an error while parsing this file.\n\n" + "Please make sure that it is syntactically correct.\n\n"); } else root.type = Def.Type.Module; @@ -390,7 +399,7 @@ private void computeDefinitionsStartOffset(Def def) { for (Def child : def.children) computeDefinitionsStartOffset(child); } - + /** * Find the end of each definition, knowing the start of the next * definition. @@ -419,9 +428,7 @@ private void findDefinitionsEnd(Def def, String doc, int index, Def parent) { boolean skip = false; if (def.defOffsetStart > def.defOffsetEnd || def.defOffsetStart < 0) { - OcamlPlugin - .logError("OcamlNewParser: findDefinitionsEnd: wrong offset (" - + def.name + ")"); + OcamlPlugin.logWarning("OcamlNewParser: findDefinitionsEnd: wrong offset (" + def.name + ")"); skip = true; } @@ -496,7 +503,6 @@ public Comment(int begin, int end, String text) { private String parseComments(String lines) { StringBuilder result = new StringBuilder(lines); - comments = new LinkedList(); sectionComments = new LinkedList(); boolean bParL = false; @@ -685,17 +691,21 @@ private boolean nextTo(String text, int offset1, int offset2, boolean bNewline = false; for (int i = offset1; i < offset2; i++) { - if (text.charAt(i) == '\n') { - if (bNewline) - return false; - else { - if (noNewLines) + try { + if (text.charAt(i) == '\n') { + if (bNewline) return false; - bNewline = true; - } - } else if (!Character.isWhitespace(text.charAt(i)) - && text.charAt(i) != ';') + else { + if (noNewLines) + return false; + bNewline = true; + } + } else if (!Character.isWhitespace(text.charAt(i)) + && text.charAt(i) != ';') + return false; + } catch (Exception e) { return false; + } } return true; diff --git a/Ocaml/src/ocaml/popup/actions/CancelCompileProjectPopupAction.java b/Ocaml/src/ocaml/popup/actions/CancelCompileProjectPopupAction.java new file mode 100644 index 0000000..3c1306a --- /dev/null +++ b/Ocaml/src/ocaml/popup/actions/CancelCompileProjectPopupAction.java @@ -0,0 +1,71 @@ +package ocaml.popup.actions; + +import java.util.Collection; + +import ocaml.OcamlPlugin; +import ocaml.util.Misc; +import ocaml.views.OcamlCompilerOutput; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +/** + * This action is called when the user clicks on the "make project" menu item in the contextual menu for + * OCaml makefile projects. Calls the Builder to build the project. + */ +public class CancelCompileProjectPopupAction implements IObjectActionDelegate { + + public CancelCompileProjectPopupAction() { + } + + /** This method is used to call the action directly, without having to instantiate it */ + public static void cancelCompileProject(IProject project) { + CancelCompileProjectPopupAction action = new CancelCompileProjectPopupAction(); + action.run(null); + } + + @Override + public void run(IAction action) { + final String jobName = "Cancelling compiling jobs"; + + // show compiler output + Misc.showView(OcamlCompilerOutput.ID); + + Job job = new Job(jobName) { + @Override + protected IStatus run(IProgressMonitor monitor) { + if (!OcamlPlugin.ActiveBuildJobs.isEmpty()) { + // cancel all jobs + Collection monitors = OcamlPlugin.ActiveBuildJobs.values(); + for (IProgressMonitor m: monitors) { + m.setCanceled(true); + } + // clear them from store + OcamlPlugin.ActiveBuildJobs.clear(); + } + return Status.OK_STATUS; + } + }; + + job.setPriority(Job.BUILD); + job.setUser(action != null); + job.schedule(50); + } + + @Override + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + } +} diff --git a/Ocaml/src/ocaml/popup/actions/CleanProjectAction.java b/Ocaml/src/ocaml/popup/actions/CleanProjectAction.java deleted file mode 100644 index f5e7f8e..0000000 --- a/Ocaml/src/ocaml/popup/actions/CleanProjectAction.java +++ /dev/null @@ -1,59 +0,0 @@ -package ocaml.popup.actions; - -import ocaml.build.makefile.OcamlMakefileBuilder; -import ocaml.util.Misc; -import ocaml.views.OcamlCompilerOutput; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.IObjectActionDelegate; -import org.eclipse.ui.IWorkbenchPart; - -/** This action is called when the user clicks on the "Clean Project" contextual pop-up menu item on OCaml makefile projects */ -public class CleanProjectAction implements IObjectActionDelegate { - - private IProject project = null; - - public CleanProjectAction() { - } - - public void run(IAction action) { - if (project != null) { - Job job = new Job("Cleaning Project") { - @Override - protected IStatus run(IProgressMonitor monitor) { - OcamlMakefileBuilder builder = new OcamlMakefileBuilder(); - builder.clean(project, monitor); - return Status.OK_STATUS; - } - }; - - // open the "OCaml compiler output" view to show the output of the make - Misc.showView(OcamlCompilerOutput.ID); - - job.setPriority(Job.BUILD); - job.setUser(true); - job.schedule(500); - } - } - - public void selectionChanged(IAction action, ISelection selection) { - this.project = null; - if (selection instanceof IStructuredSelection) { - IStructuredSelection sel = (IStructuredSelection) selection; - Object o = sel.getFirstElement(); - if (o instanceof IProject) - this.project = (IProject) o; - } - } - - public void setActivePart(IAction action, IWorkbenchPart targetPart) { - } - -} diff --git a/Ocaml/src/ocaml/popup/actions/CleanProjectPopupAction.java b/Ocaml/src/ocaml/popup/actions/CleanProjectPopupAction.java new file mode 100644 index 0000000..b8cad5a --- /dev/null +++ b/Ocaml/src/ocaml/popup/actions/CleanProjectPopupAction.java @@ -0,0 +1,134 @@ +package ocaml.popup.actions; + +import java.util.concurrent.TimeUnit; + +import ocaml.OcamlPlugin; +import ocaml.build.makefile.OcamlMakefileBuilder; +import ocaml.util.Misc; +import ocaml.views.OcamlCompilerOutput; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +/** This action is called when the user clicks on the "Clean Project" contextual pop-up menu item on OCaml makefile projects */ +public class CleanProjectPopupAction implements IObjectActionDelegate { + + private IProject project = null; + + public CleanProjectPopupAction() { + } + + public void run(IAction action) { + if (project != null) { + final String jobName = "Cleaning project " + project.getName(); + + final long[] executedTime = new long[1]; + executedTime[0] = -1; + + // show compiler output + Misc.showView(OcamlCompilerOutput.ID); + + Job job = new Job(jobName) { + @Override + protected IStatus run(IProgressMonitor monitor) { + // save progress monitor for later use + OcamlPlugin.ActiveBuildJobs.put(jobName, monitor); + + // cleaning + executedTime[0] = System.currentTimeMillis(); + OcamlMakefileBuilder builder = new OcamlMakefileBuilder(); + builder.clean(project, monitor); + return Status.OK_STATUS; + } + }; + + job.setPriority(Job.BUILD); + /* + * If the action is directly called by the user, then we display a dialog box. Else, the launch is silent. + */ + job.setUser(action != null); + job.schedule(500); + job.addJobChangeListener(new IJobChangeListener() { + @Override + public void sleeping(IJobChangeEvent event) { + } + + @Override + public void scheduled(IJobChangeEvent event) { + } + + @Override + public void running(IJobChangeEvent event) { + } + + @Override + public void done(IJobChangeEvent event) { + // cleaning job was cancelled + if (!OcamlPlugin.ActiveBuildJobs.containsKey(jobName)) { + Misc.appendToOcamlConsole("Cleaning was cancelled!"); + } + // cleaning job terminates normally + else { + OcamlPlugin.ActiveBuildJobs.remove(jobName); + } + + // time + long cleaningTime = -1; + if (executedTime[0] > 0) + cleaningTime = System.currentTimeMillis() - executedTime[0]; + if (cleaningTime >= 0) { + long minutes = TimeUnit.MILLISECONDS.toMinutes(cleaningTime); + long seconds = TimeUnit.MILLISECONDS.toSeconds(cleaningTime) - + TimeUnit.MINUTES.toSeconds(minutes); + String time = ""; + if (minutes > 1) + time = time + String.valueOf(minutes) + " mins"; + else + time = time + String.valueOf(minutes) + " min"; + if (seconds > 1) + time = time + ", " + String.valueOf(seconds) + " secs"; + else + time = time + ", " + String.valueOf(seconds) + " sec"; + Misc.appendToOcamlConsole("Time: " + time); + } + else + Misc.appendToOcamlConsole("Time: unknown"); + + Misc.appendToOcamlConsole(""); + } + + @Override + public void awake(IJobChangeEvent event) { + } + + @Override + public void aboutToRun(IJobChangeEvent event) { + } + }); + } + } + + public void selectionChanged(IAction action, ISelection selection) { + this.project = null; + if (selection instanceof IStructuredSelection) { + IStructuredSelection sel = (IStructuredSelection) selection; + Object o = sel.getFirstElement(); + if (o instanceof IProject) + this.project = (IProject) o; + } + } + + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + } + +} diff --git a/Ocaml/src/ocaml/popup/actions/CompileProjectAction.java b/Ocaml/src/ocaml/popup/actions/CompileProjectAction.java deleted file mode 100644 index f95e5ec..0000000 --- a/Ocaml/src/ocaml/popup/actions/CompileProjectAction.java +++ /dev/null @@ -1,75 +0,0 @@ -package ocaml.popup.actions; - -import ocaml.OcamlPlugin; -import ocaml.util.Misc; -import ocaml.views.OcamlCompilerOutput; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IncrementalProjectBuilder; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.IObjectActionDelegate; -import org.eclipse.ui.IWorkbenchPart; - -/** - * This action is called when the user clicks on the "make project" menu item in the contextual menu for - * OCaml makefile projects. Calls the Builder to build the project. - */ -public class CompileProjectAction implements IObjectActionDelegate { - private IProject project = null; - - public CompileProjectAction() { - } - - /** This method is used to call the action directly, without having to instantiate it */ - public static void compileProject(IProject project) { - CompileProjectAction compileProjectAction = new CompileProjectAction(); - compileProjectAction.project = project; - compileProjectAction.run(null); - } - - public void run(IAction action) { - if (project != null) { - Job job = new Job("Building Project") { - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - project.build(IncrementalProjectBuilder.FULL_BUILD, monitor); - } catch (CoreException e) { - OcamlPlugin.logError("ocaml plugin error", e); - } - return Status.OK_STATUS; - } - }; - - // open the "OCaml compiler output" view to show the output of the make - Misc.showView(OcamlCompilerOutput.ID); - - job.setPriority(Job.BUILD); - /* - * If the action is directly called by the user, then we display a dialog box. Else, the launch is silent. - */ - job.setUser(action != null); - job.schedule(500); - } - } - - public void selectionChanged(IAction action, ISelection selection) { - this.project = null; - if (selection instanceof IStructuredSelection) { - IStructuredSelection sel = (IStructuredSelection) selection; - Object o = sel.getFirstElement(); - if (o instanceof IProject) - this.project = (IProject) o; - } - } - - public void setActivePart(IAction action, IWorkbenchPart targetPart) { - } -} diff --git a/Ocaml/src/ocaml/popup/actions/CompileProjectPopupAction.java b/Ocaml/src/ocaml/popup/actions/CompileProjectPopupAction.java new file mode 100644 index 0000000..04052c3 --- /dev/null +++ b/Ocaml/src/ocaml/popup/actions/CompileProjectPopupAction.java @@ -0,0 +1,146 @@ +package ocaml.popup.actions; + +import java.util.concurrent.TimeUnit; + +import ocaml.OcamlPlugin; +import ocaml.util.Misc; +import ocaml.views.OcamlCompilerOutput; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +/** + * This action is called when the user clicks on the "make project" menu item in the contextual menu for + * OCaml makefile projects. Calls the Builder to build the project. + */ +public class CompileProjectPopupAction implements IObjectActionDelegate { + private IProject project = null; + + public CompileProjectPopupAction() { + } + + /** This method is used to call the action directly, without having to instantiate it */ + public static void compileProject(IProject project) { + CompileProjectPopupAction compileProjectAction = new CompileProjectPopupAction(); + compileProjectAction.project = project; + compileProjectAction.run(null); + } + + public void run(IAction action) { + if (project != null) { + final long[] executedTime = new long[1]; + executedTime[0] = -1; + + final String jobName = "Compiling project " + project.getName(); + + // show compiler output + Misc.showView(OcamlCompilerOutput.ID); + + Job job = new Job(jobName) { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + // save progress monitor for later use + OcamlPlugin.ActiveBuildJobs.put(jobName, monitor); + + // compile + executedTime[0] = System.currentTimeMillis(); + project.build(IncrementalProjectBuilder.FULL_BUILD, monitor); + } catch (CoreException e) { + OcamlPlugin.logError("ocaml plugin error", e); + } + return Status.OK_STATUS; + } + }; + + job.setPriority(Job.BUILD); + /* + * If the action is directly called by the user, then we display a dialog box. Else, the launch is silent. + */ + job.setUser(action != null); + job.schedule(500); + job.addJobChangeListener(new IJobChangeListener() { + @Override + public void sleeping(IJobChangeEvent event) { + } + + @Override + public void scheduled(IJobChangeEvent event) { + } + + @Override + public void running(IJobChangeEvent event) { + } + + @Override + public void done(IJobChangeEvent event) { + // compiling job was cancelled + if (!OcamlPlugin.ActiveBuildJobs.containsKey(jobName)) { + Misc.appendToOcamlConsole("Compilation was cancelled!"); + } + // compiling job terminates normally + else { + OcamlPlugin.ActiveBuildJobs.remove(jobName); + } + + // time + long compilingTime = -1; + if (executedTime[0] > 0) + compilingTime = System.currentTimeMillis() - executedTime[0]; + if (compilingTime >= 0) { + long minutes = TimeUnit.MILLISECONDS.toMinutes(compilingTime); + long seconds = TimeUnit.MILLISECONDS.toSeconds(compilingTime) - + TimeUnit.MINUTES.toSeconds(minutes); + String time = ""; + if (minutes > 1) + time = time + String.valueOf(minutes) + " mins"; + else + time = time + String.valueOf(minutes) + " min"; + if (seconds > 1) + time = time + ", " + String.valueOf(seconds) + " secs"; + else + time = time + ", " + String.valueOf(seconds) + " sec"; + Misc.appendToOcamlConsole("Time: " + time); + } + else + Misc.appendToOcamlConsole("Time: unknown"); + + Misc.appendToOcamlConsole(""); + } + + @Override + public void awake(IJobChangeEvent event) { + } + + @Override + public void aboutToRun(IJobChangeEvent event) { + } + }); + } + } + + public void selectionChanged(IAction action, ISelection selection) { + this.project = null; + if (selection instanceof IStructuredSelection) { + IStructuredSelection sel = (IStructuredSelection) selection; + Object o = sel.getFirstElement(); + if (o instanceof IProject) + this.project = (IProject) o; + } + } + + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + } +} diff --git a/Ocaml/src/ocaml/popup/actions/GenDocAction.java b/Ocaml/src/ocaml/popup/actions/GenDocAction.java index 035702a..b3169f9 100644 --- a/Ocaml/src/ocaml/popup/actions/GenDocAction.java +++ b/Ocaml/src/ocaml/popup/actions/GenDocAction.java @@ -73,9 +73,6 @@ public void run() { } }; - // open the "OCaml compiler output" view to show the output of the make command - Misc.showView(OcamlCompilerOutput.ID); - job.setPriority(Job.BUILD); job.setUser(true); job.schedule(500); diff --git a/Ocaml/src/ocaml/preferences/PathsPreferencePage.java b/Ocaml/src/ocaml/preferences/PathsPreferencePage.java index 9adcd08..03fd043 100644 --- a/Ocaml/src/ocaml/preferences/PathsPreferencePage.java +++ b/Ocaml/src/ocaml/preferences/PathsPreferencePage.java @@ -4,6 +4,7 @@ import ocaml.OcamlPlugin; +import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; diff --git a/Ocaml/src/ocaml/preferences/PreferenceConstants.java b/Ocaml/src/ocaml/preferences/PreferenceConstants.java index b49b140..dce9844 100644 --- a/Ocaml/src/ocaml/preferences/PreferenceConstants.java +++ b/Ocaml/src/ocaml/preferences/PreferenceConstants.java @@ -36,6 +36,7 @@ public class PreferenceConstants public static final String P_BOLD_KEYWORDS = "boldKeywords"; public static final String P_BOLD_COMMENTS = "boldComments"; + public static final String P_BOLD_DOCS_COMMENTS = "boldDocumentationComments"; public static final String P_BOLD_CONSTANTS = "boldConstants"; public static final String P_BOLD_STRINGS = "boldStrings"; public static final String P_BOLD_NUMBERS = "boldNumbers"; @@ -65,6 +66,7 @@ public class PreferenceConstants public static final String P_DISABLE_UNICODE_CHARS = "DisableUnicodeChars"; public static final String P_SHOW_TYPES_IN_OUTLINE = "ShowTypesInOutline"; public static final String P_SHOW_TYPES_IN_STATUS_BAR = "ShowTypesInStatusBar"; + public static final String P_SHOW_MARKERS_IN_STATUS_BAR = "ShowMarkersInStatusBar"; public static final String P_SHOW_TYPES_IN_POPUPS = "ShowTypesInPopups"; public static final String P_FORMATTER_INDENT_IN = "FormatterIndentIn"; diff --git a/Ocaml/src/ocaml/preferences/PreferenceInitializer.java b/Ocaml/src/ocaml/preferences/PreferenceInitializer.java index cd374f4..a7a27db 100644 --- a/Ocaml/src/ocaml/preferences/PreferenceInitializer.java +++ b/Ocaml/src/ocaml/preferences/PreferenceInitializer.java @@ -41,6 +41,7 @@ public void initializeDefaultPreferences() { // set the default syntax coloring bold attributes store.setDefault(PreferenceConstants.P_BOLD_CHARACTERS, false); store.setDefault(PreferenceConstants.P_BOLD_COMMENTS, false); + store.setDefault(PreferenceConstants.P_BOLD_DOCS_COMMENTS, false); store.setDefault(PreferenceConstants.P_BOLD_CONSTANTS, false); store.setDefault(PreferenceConstants.P_BOLD_KEYWORDS, true); store.setDefault(PreferenceConstants.P_BOLD_NUMBERS, false); @@ -74,7 +75,8 @@ public void initializeDefaultPreferences() { store.setDefault(PreferenceConstants.P_SHOW_TYPES_IN_OUTLINE, true); store.setDefault(PreferenceConstants.P_SHOW_TYPES_IN_POPUPS, true); - store.setDefault(PreferenceConstants.P_SHOW_TYPES_IN_STATUS_BAR, true); + store.setDefault(PreferenceConstants.P_SHOW_TYPES_IN_STATUS_BAR, false); + store.setDefault(PreferenceConstants.P_SHOW_MARKERS_IN_STATUS_BAR, true); // set the defaults for the formatter store.setDefault(PreferenceConstants.P_FORMATTER_INDENT_IN, false); diff --git a/Ocaml/src/ocaml/preferences/RootPreferencePage.java b/Ocaml/src/ocaml/preferences/RootPreferencePage.java index cbc27d0..c670bec 100644 --- a/Ocaml/src/ocaml/preferences/RootPreferencePage.java +++ b/Ocaml/src/ocaml/preferences/RootPreferencePage.java @@ -43,6 +43,11 @@ public void createFieldEditors() { PreferenceConstants.P_SHOW_TYPES_IN_POPUPS, "Show the types in popups when hovering over the editor", this .getFieldEditorParent())); + + this.addField(new BooleanFieldEditor( + PreferenceConstants.P_SHOW_MARKERS_IN_STATUS_BAR, + "Show markers' information in the editor's status bar", this + .getFieldEditorParent())); } @Override diff --git a/Ocaml/src/ocaml/preferences/SyntaxColoringPreferencePage.java b/Ocaml/src/ocaml/preferences/SyntaxColoringPreferencePage.java index 4804434..679e2fb 100644 --- a/Ocaml/src/ocaml/preferences/SyntaxColoringPreferencePage.java +++ b/Ocaml/src/ocaml/preferences/SyntaxColoringPreferencePage.java @@ -104,11 +104,12 @@ public void createFieldEditors() { this.addField(colorFieldUppercase); this.addField(colorFieldPointedUppercase); - this.addField(new BooleanFieldEditor(PreferenceConstants.P_BOLD_KEYWORDS, "Bold k&eywords", this .getFieldEditorParent())); this.addField(new BooleanFieldEditor(PreferenceConstants.P_BOLD_COMMENTS, "Bold co&mments", this .getFieldEditorParent())); + this.addField(new BooleanFieldEditor(PreferenceConstants.P_BOLD_DOCS_COMMENTS, "Bold documentation comments", this + .getFieldEditorParent())); this.addField(new BooleanFieldEditor(PreferenceConstants.P_BOLD_STRINGS, "Bold stri&ngs", this .getFieldEditorParent())); this.addField(new BooleanFieldEditor(PreferenceConstants.P_BOLD_CONSTANTS, "Bold con&stants", this diff --git a/Ocaml/src/ocaml/typeHovers/OcamlAnnotParser.java b/Ocaml/src/ocaml/typeHovers/OcamlAnnotParser.java index df2228a..c24ec52 100644 --- a/Ocaml/src/ocaml/typeHovers/OcamlAnnotParser.java +++ b/Ocaml/src/ocaml/typeHovers/OcamlAnnotParser.java @@ -92,8 +92,8 @@ public static TypeAnnotation[] parseFile(File file, IDocument document) try { while ((line = inputStream.readLine()) != null) text.append(line + "\n"); - } catch (IOException e) { - OcamlPlugin.logError("ocaml plugin error", e); + } catch (Exception e) { +// OcamlPlugin.logError("ocaml plugin error", e); return null; } @@ -116,8 +116,11 @@ public static TypeAnnotation[] parseFile(File file, IDocument document) int endLineOffset = Integer.parseInt(matcher.group(5)); int endOffset = Integer.parseInt(matcher.group(6)); - beginOffset += document.getLineOffset(beginLine - 1) - beginLineOffset; - endOffset += document.getLineOffset(endLine - 1) - endLineOffset; + if ((beginLine >= 1) && (beginLine <= document.getNumberOfLines())) + beginOffset += document.getLineOffset(beginLine - 1) - beginLineOffset; + + if ((endLine >= 1) && (endLine <= document.getNumberOfLines())) + endOffset += document.getLineOffset(endLine - 1) - endLineOffset; String type = matcher.group(7); diff --git a/Ocaml/src/ocaml/util/FileUtil.java b/Ocaml/src/ocaml/util/FileUtil.java index 4332a35..f0baaa3 100644 --- a/Ocaml/src/ocaml/util/FileUtil.java +++ b/Ocaml/src/ocaml/util/FileUtil.java @@ -53,7 +53,6 @@ public static int refineOffset(String filepath, int offset) { if ((ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r')) { // meets separation character pos--; - continue; } else if (ch == ')') { raf.seek(pos - 2); int ch2 = raf.read(); @@ -61,7 +60,6 @@ public static int refineOffset(String filepath, int offset) { // meets end comment block symbols commentBlocks++; pos = pos - 2; - continue; } else if (commentBlocks > 0) pos--; else @@ -73,7 +71,6 @@ public static int refineOffset(String filepath, int offset) { // meets begin comments block symbols commentBlocks--; pos = pos - 2; - continue; } else if (commentBlocks > 0) pos--; else diff --git a/Ocaml/src/ocaml/util/Misc.java b/Ocaml/src/ocaml/util/Misc.java index bb26d5f..05ebb95 100644 --- a/Ocaml/src/ocaml/util/Misc.java +++ b/Ocaml/src/ocaml/util/Misc.java @@ -13,6 +13,7 @@ import ocaml.preferences.PreferenceConstants; import ocaml.views.OcamlCompilerOutput; +import org.eclipse.core.internal.resources.ResourceException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -219,7 +220,7 @@ public static IFile[] getMliFiles(final IProject project) { /** * Keep all the mli files in the list and the ml files when there is no corresponding mli - * + * * @return the mli files and the ml files which don't have a corresponding mli file */ public static String[] filterInterfaces(String[] mlmliFiles) { @@ -302,7 +303,7 @@ public static boolean isGeneratedFile(IFile file) { /** * Return a persistent property associated with the project. The qualified name uses the "ocaml" * qualifier. - * + * * @return the value of the property, or an empty string if it couldn't be retrieved */ public static String getProjectProperty(IProject project, String propertyName) { @@ -320,7 +321,7 @@ public static String getProjectProperty(IProject project, String propertyName) { /** * Return a file persistent property - * + * * @see getProjectProperty */ public static String getFileProperty(IFile file, String propertyName) { @@ -338,7 +339,7 @@ public static String getFileProperty(IFile file, String propertyName) { /** * Return a folder persistent property - * + * * @see getProjectProperty */ public static String getFolderProperty(IFolder folder, String propertyName) { @@ -372,7 +373,7 @@ public static String getResourceProperty(IResource resource, String propertyName /** * set a project persistent property - * + * * @see getProjectProperty */ public static void setProjectProperty(IProject project, String propertyName, String value) { @@ -386,7 +387,7 @@ public static void setProjectProperty(IProject project, String propertyName, Str /** * set a file persistent property - * + * * @see getProjectProperty */ public static void setFileProperty(IFile file, String propertyName, String value) { @@ -400,7 +401,7 @@ public static void setFileProperty(IFile file, String propertyName, String value /** * set a folder persistent property - * + * * @see getProjectProperty */ public static void setFolderProperty(IFolder folder, String propertyName, String value) { @@ -416,9 +417,7 @@ public static void setFolderProperty(IFolder folder, String propertyName, String * Append text to the OCaml compiler output (in a UI-Thread) */ public static void appendToOcamlConsole(final String msg) { - Display.getDefault().syncExec(new Runnable() { - public void run() { try { final IWorkbenchPage activePage = PlatformUI.getWorkbench() @@ -427,7 +426,6 @@ public void run() { .findView(OcamlCompilerOutput.ID); if (console == null) { console = (OcamlCompilerOutput) activePage.showView(OcamlCompilerOutput.ID); - } console.appendln(msg); } catch (PartInitException pe) { @@ -480,7 +478,7 @@ public static void refreshFileSystem(IProject proj, IProgressMonitor monitor) { /** * Create an icon from a filename - * + * * @return an image, or null if there was an error */ public static Image createIcon(String name) { @@ -498,7 +496,7 @@ public static Image createIcon(String name) { /** * Get the file with the given extension corresponding to the given ml file. - * + * * @param project * the project in which the ml file resides * @param mlPath @@ -536,10 +534,10 @@ public static File getOtherFileFor(IProject project, IPath mlPath, String extens return null; } - + /** * Get the file with the given extension corresponding to the given ml file. - * + * * @param mlPath * the full absolute filesystem path of the ml file * @param extension @@ -565,14 +563,14 @@ public static File getOtherFileFor(IPath mlPath, String extension) { return null; } - + /** Remove carriage returns */ public static String CRLFtoLF(String str){ return str.replace("\r", ""); } - + private static HashSet keywordsHashset; - + /** Can this character be part of an OCaml identifier */ public static boolean isOcamlIdentifierChar(char c) { return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_' || c == '\''); @@ -585,13 +583,13 @@ public static boolean isOcamlIdentifierFirstChar(char c) { /** Test whether this string is a valid OCaml identifier (lowercase) */ public static boolean isValidOcamlIdentifier(String str) { - + if(str.length() < 1) return false; - + char[] chars = new char[str.length()]; str.getChars(0, str.length(), chars, 0); - + if(!isOcamlIdentifierFirstChar(chars[0])) return false; @@ -604,10 +602,10 @@ public static boolean isValidOcamlIdentifier(String str) { for(String word : ILanguageWords.keywords) keywordsHashset.add(word); } - + if(keywordsHashset.contains(str)) return false; - + return true; } @@ -619,10 +617,10 @@ public static boolean isValidOcamlIdentifier(String str) { public static void setShareableProperty(IResource resource, String name, String value) { setShareableProperty(resource, new QualifiedName(OcamlPlugin.QUALIFIER, name), value); } - + public static void setShareableProperty(IResource resource, QualifiedName name, String value) { String preferenceName = name.getLocalName(); - IPath resourcePath = resource.getFullPath(); + IPath resourcePath = resource.getFullPath(); try { // 1. save in /.settings/ocaml.pref Preferences settings = getPreferences(resource.getProject(), preferenceName, true); @@ -632,18 +630,20 @@ public static void setShareableProperty(IResource resource, QualifiedName name, settings.put(getKeyFor(resourcePath), value); // TODO disable the listener (if any) so we don't react to changes made by ourselves settings.flush(); - - // 2. also save in /.medatada to decorate icons (see plugin.xml) + + // 2. also save in /.medatada to decorate icons (see plugin.xml) resource.setPersistentProperty(name, value); - + } catch (BackingStoreException e) { - OcamlPlugin.logError("error in OcamlPlugin.setPersistentProperty", e); - } catch (CoreException e) { - + // OcamlPlugin.logError("error in OcamlPlugin.setPersistentProperty", e); + } catch (ResourceException e) { + + } catch (Exception e) { + } } - /** Load a property from /.settings/. + /** Load a property from /.settings/. * If it does not exist, fallback to see /.metadata/ */ public static String getShareableProperty(IResource resource, String name) { return getShareableProperty(resource, new QualifiedName(OcamlPlugin.QUALIFIER, name)); @@ -664,7 +664,7 @@ public static String getShareablePropertyNull(IResource resource, QualifiedName if (prefs == null) { return migrateOldSettingIfAny(resource, name); } - + String value = prefs.get(getKeyFor(resource.getFullPath()), null); if(value!=null) { return value; @@ -672,7 +672,7 @@ public static String getShareablePropertyNull(IResource resource, QualifiedName return migrateOldSettingIfAny(resource, name); } } - + // for backward compatibility static String migrateOldSettingIfAny(IResource resource, QualifiedName name) { String oldVerSetting = null; @@ -705,7 +705,7 @@ private static Preferences getPreferences(IProject project, String preferenceNam } return null; } - + private static String getKeyFor(IPath resourcePath) { return resourcePath.segmentCount() > 1 ? resourcePath.removeFirstSegments(1).toString() : ""; } diff --git a/Ocaml/src/ocaml/util/OcamlPaths.java b/Ocaml/src/ocaml/util/OcamlPaths.java index 8dbf09c..2d74141 100644 --- a/Ocaml/src/ocaml/util/OcamlPaths.java +++ b/Ocaml/src/ocaml/util/OcamlPaths.java @@ -3,10 +3,12 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; +import java.io.FileFilter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import ocaml.OcamlPlugin; @@ -35,14 +37,15 @@ public class OcamlPaths { public OcamlPaths(IProject project) { this.project = project; +// restoreDefaults(); } - + public void setPaths(String[] paths) { IPath pathsPath = project.getLocation().append(PATHS_FILE); File file = pathsPath.toFile(); try { - BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + BufferedWriter writer = new BufferedWriter(new FileWriter(file, false)); for (String path : paths) if (path != null && path.trim().length() > 0) @@ -54,6 +57,22 @@ public void setPaths(String[] paths) { return; } } + + List getSubdirs(File file) { + List subdirs = Arrays.asList(file.listFiles(new FileFilter() { + public boolean accept(File f) { + return f.isDirectory(); + } + })); + subdirs = new ArrayList(subdirs); + + List deepSubdirs = new ArrayList(); + for(File subdir : subdirs) { + deepSubdirs.addAll(getSubdirs(subdir)); + } + subdirs.addAll(deepSubdirs); + return subdirs; + } public void restoreDefaults() { ArrayList paths = new ArrayList(); @@ -69,7 +88,9 @@ public void restoreDefaults() { IPath path = folder.getFullPath(); for (String segment : path.segments()) { - if ("_build".equals(segment)) + if (segment.equals("_build") + || segment.equals(".hg") + || segment.equals(".git")) continue mainLoop; } @@ -81,7 +102,14 @@ public void restoreDefaults() { } } - paths.add(OcamlPlugin.getLibFullPath()); + // add lib path and its sub-folder + String libPath = OcamlPlugin.getLibFullPath(); + paths.add(libPath); + List subpaths = getSubdirs(new File(libPath)); + for (File file : subpaths) + paths.add(file.toPath().toString()); + + this.setPaths(paths.toArray(new String[paths.size()])); } @@ -108,7 +136,7 @@ public String[] getPaths() { OcamlPlugin.logError("ocaml plugin error", e); return new String[0]; } - + addReferencedProjectsPaths(paths); return paths.toArray(new String[paths.size()]); @@ -186,9 +214,9 @@ public static boolean isRelativePath(IProject project, String strPath) { * relative to the project. * * @param paths - * the list of paths to add + * the list of paths to add * @param project - * the project to add them to + * the project to add them to */ public static void addToPaths(final List paths, final IProject project) { final OcamlPaths oPaths = new OcamlPaths(project); diff --git a/Ocaml/src/ocaml/views/OcamlBrowserView.java b/Ocaml/src/ocaml/views/OcamlBrowserView.java index 999fcfd..e30cc54 100644 --- a/Ocaml/src/ocaml/views/OcamlBrowserView.java +++ b/Ocaml/src/ocaml/views/OcamlBrowserView.java @@ -445,9 +445,9 @@ protected void treeItemSelected() { } private void addFormatedText(StyledText text, Def def) { - String body = def.body; + String body = def.getBody(); String comment = def.comment; - String filename = def.filename; + String filename = def.getFileName(); // String name = def.getName(); String parentName = def.parentName; String sectionComment = def.sectionComment; diff --git a/Ocaml/src/ocaml/views/ast/Indexer.java b/Ocaml/src/ocaml/views/ast/Indexer.java index 5acfbc4..4477052 100644 --- a/Ocaml/src/ocaml/views/ast/Indexer.java +++ b/Ocaml/src/ocaml/views/ast/Indexer.java @@ -3,11 +3,7 @@ import static org.eclipse.core.runtime.Status.OK_STATUS; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.net.URL; import ocaml.OcamlPlugin; diff --git a/Ocaml/src/ocaml/views/outline/OcamlOutlineControl.java b/Ocaml/src/ocaml/views/outline/OcamlOutlineControl.java index ae8047c..6b30187 100644 --- a/Ocaml/src/ocaml/views/outline/OcamlOutlineControl.java +++ b/Ocaml/src/ocaml/views/outline/OcamlOutlineControl.java @@ -101,7 +101,7 @@ public void run() { public void run() { OcamlOutlineControl.bDebug = this.isChecked(); super.run(); - editor.rebuildOutline(0); + editor.rebuildOutline(0, false); outline.update(); } }; @@ -141,7 +141,7 @@ public void selectionChanged(SelectionChangedEvent event) { IDocument document = editor.getDocumentProvider().getDocument( editor.getEditorInput()); - IRegion region = def.getRegion(document); + IRegion region = def.getNameRegion(document); if (region != null) { ISelection editorSel = editor.getSelectionProvider().getSelection(); diff --git a/Ocaml/src/ocaml/views/outline/OcamlOutlineLabelProvider.java b/Ocaml/src/ocaml/views/outline/OcamlOutlineLabelProvider.java index 14be1a7..6dc849b 100644 --- a/Ocaml/src/ocaml/views/outline/OcamlOutlineLabelProvider.java +++ b/Ocaml/src/ocaml/views/outline/OcamlOutlineLabelProvider.java @@ -41,6 +41,8 @@ public static Image retrieveImage(Object element) { return ImageRepository.getImage(ImageRepository.ICON_EXTERNAL); if (type.equals(Def.Type.Module)) return ImageRepository.getImage(ImageRepository.ICON_OCAML_MODULE); + if (type.equals(Def.Type.ModuleAlias)) + return ImageRepository.getImage(ImageRepository.ICON_OCAML_MODULE); if (type.equals(Def.Type.ModuleType)) return ImageRepository.getImage(ImageRepository.ICON_OCAML_MODULE_TYPE); if (type.equals(Def.Type.Open)) @@ -89,8 +91,8 @@ public String getText(Object element) { if (OcamlOutlineControl.bOutlineDebugButton && OcamlOutlineControl.bDebug) return def.name + " (" + def.type + ")"; - if (def.ocamlType != null && !"".equals(def.ocamlType)) - return def.name + " : " + def.ocamlType; + if (!def.getOcamlType().isEmpty()) + return def.name + " : " + def.getOcamlType(); else return def.name; } diff --git a/Ocaml/src/ocaml/views/outline/OutlineBuildListener.java b/Ocaml/src/ocaml/views/outline/OutlineBuildListener.java index bd13ee0..3a3e806 100644 --- a/Ocaml/src/ocaml/views/outline/OutlineBuildListener.java +++ b/Ocaml/src/ocaml/views/outline/OutlineBuildListener.java @@ -95,7 +95,7 @@ public void run() { return; IEditorPart editorPart = workbenchPage.getActiveEditor(); if (editorPart instanceof OcamlEditor) - ((OcamlEditor) editorPart).rebuildOutline(500); + ((OcamlEditor) editorPart).rebuildOutline(500,false); } catch (Throwable e) { OcamlPlugin.logError("rebuilding outline after build", e); } diff --git a/Ocaml/src/ocaml/views/outline/OutlineJob.java b/Ocaml/src/ocaml/views/outline/OutlineJob.java index 8573290..b8b0d26 100644 --- a/Ocaml/src/ocaml/views/outline/OutlineJob.java +++ b/Ocaml/src/ocaml/views/outline/OutlineJob.java @@ -49,8 +49,9 @@ public class OutlineJob extends Job { - public OutlineJob(String name) { + public OutlineJob(String name, boolean syncWithEditor) { super(name); + this.syncWithEditor = syncWithEditor; } /** The outline. Can be null if the outline view is closed */ @@ -59,6 +60,8 @@ public OutlineJob(String name) { private IDocument doc; private OcamlEditor editor; + + private boolean syncWithEditor; public void setDoc(IDocument doc) { this.doc = doc; @@ -282,6 +285,7 @@ else if (!("ml4".equals(extension) || "mlp".equals(extension))) * recover pieces from the AST (which couldn't be built completely because of an * unrecoverable error) */ + boolean parserError = false; if (root == null || !parser.errorReporting.errors.isEmpty()) { // System.err.println("recovering"); // System.err.println("recovering AST"); @@ -292,6 +296,13 @@ else if (!("ml4".equals(extension) || "mlp".equals(extension))) def.bTop = false; root.children.add(def); } + for (Def def : parser.recoverIdents) + if (def.bTop && def.name != null && !"".equals(def.name.trim())) { + def.bTop = false; + root.children.add(def); + } + + parserError = true; } /* @@ -321,7 +332,7 @@ else if (!("ml4".equals(extension) || "mlp".equals(extension))) definitions.setInInAttribute(); - Def outlineDefinitions = definitions.cleanCopy(); + Def outlineDefinitions = definitions.cleanCopy(parserError); // remove the definitions the user has chosen not to display initPreferences(); cleanOutline(outlineDefinitions); @@ -435,7 +446,9 @@ public void run() { } else outline.setInput(fOutlineDefinitions); - editor.synchronizeOutline(); + // synchronize outline with editor + if (syncWithEditor) + editor.synchronizeOutline(); } } @@ -483,7 +496,7 @@ private void addTypes(IFile file, Def root) { private void addTypeRec(TypeAnnotation[] annotations, Def def, boolean root) { if (!root) { - IRegion region = def.getRegion(doc); + IRegion region = def.getNameRegion(doc); int startOffset = region.getOffset(); int endOffset = startOffset + region.getLength() - 1; @@ -494,7 +507,7 @@ private void addTypeRec(TypeAnnotation[] annotations, Def def, boolean root) { if (index >= 0) { TypeAnnotation annot = annotations[index]; String type = annot.getType().replaceAll("\r?\n", " "); - def.ocamlType = type; + def.setOcamlType(type); } } diff --git a/Ocaml/src/ocaml/views/outline/QuickOutline.java b/Ocaml/src/ocaml/views/outline/QuickOutline.java index 89999cc..1b65c58 100644 --- a/Ocaml/src/ocaml/views/outline/QuickOutline.java +++ b/Ocaml/src/ocaml/views/outline/QuickOutline.java @@ -3,6 +3,7 @@ import ocaml.OcamlPlugin; import ocaml.editors.OcamlEditor; import ocaml.parser.Def; +import ocaml.util.Misc; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogSettings; @@ -185,7 +186,7 @@ protected void gotoSelectedElement() { IDocument document = editor.getDocumentProvider().getDocument( editor.getEditorInput()); - IRegion region = def.getRegion(document); + IRegion region = def.getNameRegion(document); if (region != null) { editor.selectAndReveal(region.getOffset(), region.getLength()); @@ -325,14 +326,59 @@ private boolean matchesFilter(Object element) { if (element instanceof Def) { Def def = (Def) element; - String matchName = ((ILabelProvider) fTreeViewer.getLabelProvider()).getText(def); - String filterText = getFilterText().getText(); - - if(matchName != null) { - if(filterText.startsWith("*")) { - return matchName.contains(filterText.substring(1)); - } else { - return matchName.startsWith(filterText); + // don't show identifier and parameter in quick outline + if (def.type != Def.Type.Parameter && def.type != Def.Type.Identifier) { + String matchName = ((ILabelProvider) fTreeViewer.getLabelProvider()).getText(def); + String filterText = getFilterText().getText(); + /* + * allow to search special characters in type information: + * In raw text: + * use "a -> b" for function type "a → b" + * use "a x b" to search a tuple type (a * b) + * use 'a, 'b, 'c,... for α, β, γ,... + */ + filterText = filterText.replaceAll("->", "\u2192"); + filterText = filterText.replaceAll(" x ", " \u00d7 "); + filterText = filterText.replaceAll("\\B'a\\b", "\u03b1"); + filterText = filterText.replaceAll("\\B'b\\b", "\u03b2"); + filterText = filterText.replaceAll("\\B'c\\b", "\u03b3"); + filterText = filterText.replaceAll("\\B'd\\b", "\u03b4"); + filterText = filterText.replaceAll("\\B'e\\b", "\u03b5"); + filterText = filterText.replaceAll("\\B'f\\b", "\u03b6"); + filterText = filterText.replaceAll("\\B'g\\b", "\u03b7"); + filterText = filterText.replaceAll("\\B'h\\b", "\u03b8"); + filterText = filterText.replaceAll("\\B'i\\b", "\u03b9"); + filterText = filterText.replaceAll("\\B'j\\b", "\u03ba"); + filterText = filterText.replaceAll("\\B'k\\b", "\u03bb"); + filterText = filterText.replaceAll("\\B'l\\b", "\u03bc"); + + try { + // use regex when filterText start with "^" (regex is slow) + if (filterText.startsWith("^")) + return matchName.matches(filterText); + // search for substring when filterText start with "*" + // or by converting to regex + if (filterText.startsWith("*")) { + if (filterText.lastIndexOf("*") == 0) + return matchName.contains(filterText.substring(1)); + else { + // convert to regex + String newText = filterText.replaceAll("\\*", ".*"); + newText = "^" + newText + ".*"; + return matchName.matches(newText); + } + } + // otherwise, search for static string or by converting to reged + if (filterText.lastIndexOf("*") < 0) + return matchName.startsWith(filterText); + else { + // convert to regex + String newText = filterText.replaceAll("\\*", ".*"); + newText = "^" + newText + ".*"; + return matchName.matches(newText); + } + } catch (Exception e) { + return false; } } } diff --git a/Ocaml/src/ocaml/wizards/OcamlNewMakeProjectWizard.java b/Ocaml/src/ocaml/wizards/OcamlNewMakeProjectWizard.java index 43a88ed..f40c4e6 100644 --- a/Ocaml/src/ocaml/wizards/OcamlNewMakeProjectWizard.java +++ b/Ocaml/src/ocaml/wizards/OcamlNewMakeProjectWizard.java @@ -53,6 +53,9 @@ public boolean performFinish() { project.setDefaultCharset("ISO-8859-1", null); + OcamlPaths opaths = new OcamlPaths(project); + opaths.restoreDefaults(); + URL url = OcamlPlugin.getInstance().getBundle().getEntry("/resources/OCamlMakefile"); IFile file = project.getFile("OCamlMakefile"); @@ -63,8 +66,6 @@ public boolean performFinish() { file = project.getFile("Makefile"); file.create(url.openStream(), true, null); - OcamlPaths opaths = new OcamlPaths(project); - opaths.restoreDefaults(); } catch (Exception e) { OcamlPlugin.logError("Error in OcamlNewMakeProjectWizard:performFinish()", e); diff --git a/plugins-install.sh b/plugins-install.sh new file mode 100755 index 0000000..afc607e --- /dev/null +++ b/plugins-install.sh @@ -0,0 +1,4 @@ +#!/bin/sh +rm ~/Programs/OcaIDE/dropins/Ocaml* +cp ~/Desktop/plugins/Ocaml* ~/Programs/OcaIDE/dropins/ + diff --git a/plugins-prepare.sh b/plugins-prepare.sh new file mode 100755 index 0000000..bbec19b --- /dev/null +++ b/plugins-prepare.sh @@ -0,0 +1,3 @@ +#!/bin/sh +rm -rf ~/Desktop/plugins/ +