Xtext: referencing existing java packages and methods - xtext

I developed a DSL which I use together with standard java code.
In my DSL I can write things like this:
package: packagename;
method: void testMethod (int, double);
What I want to do, is that the user of the DSL can only write package names and method signatures which already exist in the Java project.
Example:
When my project only consists of one package e.g. “TestPackage”, the user of the DSL should only be able to write:
package: TestPackage
the name “TestPackage” should also be suggested by the code completor. The same shall also work with the methods.
Is it possible? And how can I do this with Xtext?

I've not used it (yet), but take a look at the relevant Xtext documentation on this. Also, I'd look through the "7 Languages", find one that does what you want (which I think you'll find), and study the source.

Related

Generated files in xtext with xbase

I followed this tutorial: https://www.eclipse.org/Xtext/documentation/104_jvmdomainmodel.html, but the generated files are .java, I want to change the file extension as well as the grammar, but I want to keep some java features. Also the class DomainmodelGenerator extends AbstractGenerator does not get generated when I use grammar org.example.domainmodel.Domainmodel with org.eclipse.xtext.xbase.Xbase, only if I use terminals. How can I achieve that?
If you use Xbase then, JvmModelGenerator will be used as IGenerator(2). So you have to customize that one and override org.eclipse.xtext.xbase.DefaultXbaseRuntimeModule.bindIGenerator() for binding.
But also triple check if you really want to customize the generator and not enhance the inferrer

working with xtext not as plugin

In general I have my dsl as plugin and I want to create a new app that use my dsl
so i tried to write this code:
JsonParser p = new JsonParser();
IParseResult r = p.parse(new StringReader("{}"));
//once that work it will be the file data instead of {}
but when i do the parse the node model builder is null and the following line has exception:
return doParse(ruleName, in, nodeModelBuilder.get(), 0);
and i'm not sure how to init nodeModelBuilder
i'm sure i missing some steps but i'm not quite familiar with the xtext process.
thanks!
You already read the following answer on Eclipse Forum. You need to create an IParser instance by injecting it. All dependencies gets also injected. The necessary bindings are described in your JsonRuntimeModule. Xtext uses Guice and theses Modules to glue everything together. This pattern is called Dependency Injection.
... I want to create a new app that use my dsl
So you want to use your Json DSL in standalone mode.
My suggestion:
Create a minimum Eclipse IApplication with CLI that reads and parses an input file. The advantage of an Eclipse IApplication is that you can easily deploy an headless version of your DSL runtime. [1]
Have a look at your JsonInjectorProvider and the ParseHelper [2] from Xtext's JUnit support for examples how to use your DSL and Xtext runtime in standalone mode.
[1] http://www.eclipsezone.com/eclipse/forums/t99762.html
[2] org.eclipse.xtext.junit.util.ParseHelper
You are not supposed to call parser directly. See:
http://wiki.eclipse.org/Xtext/FAQ#How_do_I_load_my_model_in_a_standalone_Java_application.C2.A0.3F
The code should look like:
Injector injector = new MyDslStandaloneSetup().createInjectorAndDoEMFRegistration();
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
Resource resource = resourceSet.getResource(new File("/../../some.json").toURI(), true);
Model modelRootElement = (Model) resource.getContents().get(0);
Replace MyDsl with 'JsonParser' or 'Json' or whatever is your DSL name. Look for class JsonStandaloneSetup or JsonParserStandaloneSetup in your DSL source code. This class is generated when you start the Xtext project (or when you run workflow for the first time, not sure now). Replace Model with whatever is your root element type. It must be EObject subclass.
The parsing/validation/buidling AST is done resource.getContents() command. Not very intuitive, I know. It is because you have to initialize context, all sorts of contexts i fact, Guice context, EMF context, and perhaps other, all encapsulated in the StandaloneSetup (and RuntimeModule). The context is similar to Spring Application Context.
You need to use StandaloneSetup to run in standalone mode.
See this tutorial for help

Creating macros using DWScript

I read this paragraph from the Delphi Tools Site
Changes since the last SVN update are:
Added support for FreePascal-like compile-time $INCLUDE “macros”:
%FILE% and %LINE% insert the current filename and line number into the source
%FUNCTION% inserts the current function name, or class.method name into the source
%DATE% and %TIME% allow inserting the compile date/time
Is there a way we can define macros in DWScript (other than these functions) just like people define macors in excel (using VBscript) in a simple way, where the name of the script will be the name of the function that will be used later, without adding {$Include XXX} in the executed script?
N.B.: I konw this can be done by managing the written script to be saved in a certain file called functions for ex. then save the added function with its name to be used (Add), then the user will write Add(1,2) to get the result; but my boss at work wants it to be something that looks like vbscript in excel.
I'm not sure to understand the question, so I'll list various answers to various possible interpretations...
If you want to declare functions that are implicitly supported by the scripting engine without having to "{$include}" or "uses" them, you can declare them via a TdwsUnit component, and attach it to the script component. If you don't have the "coExplicitUses" option set, they'll be available automatically, and you get design-time support in the IDE.
If you want to add internal functions (that are always there), use one of the RegisterInternalFunction overloads, you can check any of the "dwsXxxxFunctions.pas" units for examples. That's potentially more efficient, but also more cumbersome.
If you want to pre-process custom source-level macros in the source code (ala C's macros), you can use the filters functionality (check the HTML or JS filters as example of how a filter can be implemented).
If you want to react dynamically to "unknown" names, so you can declare them on the spot or bind them to something dynamically, you can use TdwsLanguageExtension.FindUnknownName, that's how the RTTI environment works f.i. (see TRTTIEnvironment in dwsRTTIConnector).
If you want to parse completely custom areas of code in a completely custom way, you can use language extensions too, override ReadInstr and check how asmLib & the JSLibModule do it to support "asm".

Erlang: "extending" an existing module with new functions

I'm currently writing some functions that are related to lists that I could possibly be reused.
My question is:
Are there any conventions or best practices for organizing such functions?
To frame this question, I would ideally like to "extend" the existing lists module such that I'm calling my new function the following way: lists:my_funcion(). At the moment I have lists_extensions:my_function(). Is there anyway to do this?
I read about erlang packages and that they are essentially namespaces in Erlang. Is it possible to define a new namespace for Lists with new Lists functions?
Note that I'm not looking to fork and change the standard lists module, but to find a way to define new functions in a new module also called Lists, but avoid the consequent naming collisions by using some kind namespacing scheme.
Any advice or references would be appreciated.
Cheers.
To frame this question, I would ideally like to "extend" the existing lists module such that I'm calling my new function the following way: lists:my_funcion(). At the moment I have lists_extensions:my_function(). Is there anyway to do this?
No, so far as I know.
I read about erlang packages and that they are essentially namespaces in Erlang. Is it possible to define a new namespace for Lists with new Lists functions?
They are experimental and not generally used. You could have a module called lists in a different namespace, but you would have trouble calling functions from the standard module in this namespace.
I give you reasons why not to use lists:your_function() and instead use lists_extension:your_function():
Generally, the Erlang/OTP Design Guidelines state that each "Application" -- libraries are also an application -- contains modules. Now you can ask the system what application did introduce a specific module? This system would break when modules are fragmented.
However, I do understand why you would want a lists:your_function/N:
It's easier to use for the author of your_function, because he needs the your_function(...) a lot when working with []. When another Erlang programmer -- who knows the stdlb -- reads this code, he will not know what it does. This is confusing.
It looks more concise than lists_extension:your_function/N. That's a matter of taste.
I think this method would work on any distro:
You can make an application that automatically rewrites the core erlang modules of whichever distribution is running. Append your custom functions to the core modules and recompile them before compiling and running your own application that calls the custom functions. This doesn't require a custom distribution. Just some careful planning and use of the file tools and BIFs for compiling and loading.
* You want to make sure you don't append your functions every time. Once you rewrite the file, it will be permanent unless the user replaces the file later. Could use a check with module_info to confirm of your custom functions exist to decide if you need to run the extension writer.
Pseudo Example:
lists_funs() -> ["myFun() -> <<"things to do">>."].
extend_lists() ->
{ok, Io} = file:open(?LISTS_MODULE_PATH, [append]),
lists:foreach(fun(Fun) -> io:format(Io,"~s~n",[Fun]) end, lists_funs()),
file:close(Io),
c(?LISTS_MODULE_PATH).
* You may want to keep copies of the original modules to restore if the compiler fails that way you don't have to do anything heavy if you make a mistake in your list of functions and also use as source anytime you want to rewrite the module to extend it with more functions.
* You could use a list_extension module to keep all of the logic for your functions and just pass the functions to list in this function using funName(Args) -> lists_extension:funName(Args).
* You could also make an override system that searches for existing functions and rewrites them in a similar way but it is more complicated.
I'm sure there are plenty of ways to improve and optimize this method. I use something similar to update some of my own modules at runtime, so I don't see any reason it wouldn't work on core modules also.
i guess what you want to do is to have some of your functions accessible from the lists module. It is good that you would want to convert commonly used code into a library.
one way to do this is to test your functions well, and if their are fine, you copy the functions, paste them in the lists.erl module (WARNING: Ensure you do not overwrite existing functions, just paste at the end of the file). this file can be found in the path $ERLANG_INSTALLATION_FOLDER/lib/stdlib-{$VERSION}/src/lists.erl. Make sure that you add your functions among those exported in the lists module (in the -export([your_function/1,.....])), to make them accessible from other modules. Save the file.
Once you have done this, we need to recompile the lists module. You could use an EmakeFile. The contents of this file would be as follows:
{"src/*", [verbose,report,strict_record_tests,warn_obsolete_guard,{outdir, "ebin"}]}.
Copy that text into a file called EmakeFile. Put this file in the path: $ERLANG_INSTALLATION_FOLDER/lib/stdlib-{$VERSION}/EmakeFile.
Once this is done, go and open an erlang shell and let its pwd(), the current working directory be the path in which the EmakeFile is, i.e. $ERLANG_INSTALLATION_FOLDER/lib/stdlib-{$VERSION}/.
Call the function: make:all() in the shell and you will see that the module lists is recompiled. Close the shell.
Once you open a new erlang shell, and assuming you exported you functions in the lists module, they will be running the way you want, right in the lists module.
Erlang being open source allows us to add functionality, recompile and reload the libraries. This should do what you want, success.

Template class using Gold Parser and the Klimstra engine

I'm using Klimstra's VB.NET template from the "Create skeleton program" of the GOLD parser but the resulting template has methods with the overrides keyword and inherits from TemplateParser..
Am I supposed to create the TemplateParser class or is there a tool to create it? I thought that the "create skeleton" function created a template that I was supposed to inherit and provide implementation to the "MustOverride" methods but now I don't know.
I'm following a tutorial that makes it look like we have to create it using a tool but I'm not sure. I don't know if the tutorial is very outdated (it's dated 2005) and the GOLD parser changed this mechanism. This is the tutorial I'm following: http://www.codeproject.com/KB/recipes/IntrotoGoldParser.aspx
I were just looking into this topic a your link to the article really helped me.
I figured out that in the source files provided with the artictle there are two file with extension .pgt. These are templates for GOLD Code generator. Yout have to copy them into your GOLD installation folder -> Templates and to use them both when you are creating the skeleton program.
I hope this is helpful.

Resources