blob: 38b4b39dc5e4bb41c4961539a9d4b94a8a3ace9c [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Xtext - Introduction to the Seven Languages</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description"
content="The website of Eclipse Xtext, an open-source framework for development of programming languages and domain-specific languages">
<meta name="author" content="Sven Efftinge">
<meta name="author" content="Miro Spoenemann">
<!-- styles -->
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- Le fav and touch icons -->
<link rel="shortcut icon" href="/Xtext/images/favicon.png">
<link href="/Xtext/css/bootstrap.css" rel="stylesheet" type='text/css'>
<link href="/Xtext/css/bootstrap-responsive.css" rel="stylesheet" type='text/css'>
<link href="/Xtext/css/shield-responsive.css" rel="stylesheet" type='text/css'>
<link href='/Xtext/css/fonts.css' rel='stylesheet' type='text/css'>
<link href="/Xtext/css/prettyPhoto.css" rel="stylesheet" media="screen" type='text/css'>
<link href="/Xtext/css/prettify.css" type="text/css" rel="stylesheet"/>
<link href="/Xtext/css/style.css" rel="stylesheet" type='text/css'>
<!-- cover flow -->
<link href="/Xtext/css/coverflow.css" rel="stylesheet" type='text/css'>
<!--[if lt IE 9]>
<link href="/css/iebugs.css" rel="stylesheet" type='text/css'>
<![endif]-->
</head>
<body>
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-TGDS5S"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-TGDS5S');</script>
<!-- End Google Tag Manager -->
<header class="site-header">
<!-- Navbar -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse"> <span class="icon-bar"></span> <span
class="icon-bar"></span> <span class="icon-bar"></span>
</a> <a class="brand" href="/Xtext/index.html"></a>
<div class="nav-collapse collapse" style="height: 0px;">
<ul class="nav">
<!--li ><a href="/Xtext/news.html">News</a></li-->
<li ><a href="/Xtext/download.html">Download</a></li>
<li ><a href="/Xtext/documentation/index.html">Documentation</a></li>
<li ><a href="/Xtext/community.html">Community</a></li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Support &amp; Trainings<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="https://www.itemis.com/en/xtext/support-and-team/" target="_blank">itemis</a></li>
<li><a href="https://typefox.io/trainings-2" target="_blank">TypeFox</a></li>
</ul>
</li>
<li ><a href="http://xtend-lang.org">Xtend</a></li>
</ul>
<!--div class="nav pull-right">
<li ><a><iframe src="https://ghbtns.com/github-btn.html?user=eclipse&repo=xtext&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe></a></li>
</div-->
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Navbar End -->
</header>
<div class="page-content">
<script>
function startSearch(event) {
if (event.keyCode == 13) {
var q = 'site:eclipse.org/Xtext/documentation+' + event.target.value;
window.open('https://www.google.com/search?q=' + q, "_self");
}
}
</script>
<div class="wrapper">
<div id="page">
<div class="inner">
<div id="maincontainer" class="container">
<span class="edit-on-github pull-right">
<a href="https://github.com/eclipse/xtext/edit/website-published/xtext-website/documentation/201_sevenlang_introduction.md">Edit on Github</a>
</span>
<div class="span3" style="margin-left: 0px;">
<div class="search-bar">
<img src="/Xtext/images/search-gray.png"/>
<input type="search" id="google-search" onkeyup="startSearch(event);"/>
</div>
<ul id="nav-outline" style="margin-left: 0px;">
<li class="nav-part">Getting Started</li>
<li><a href="102_domainmodelwalkthrough.html">15 Minutes Tutorial</a></li>
<li><a href="103_domainmodelnextsteps.html">15 Minutes Tutorial - Extended</a></li>
<li><a href="104_jvmdomainmodel.html">Five simple steps to your JVM language</a></li>
<!--li class="nav-part">Seven JVM Languages Built With Xbase</li>
<li><a href="201_sevenlang_introduction.html">Introduction</a></li>
<li><a href="202_scripting.html">Scripting Language</a></li>
<li><a href="203_builddsl.html">Build Language</a></li>
<li><a href="204_mongodb.html">DSL for MongoDB</a></li>
<li><a href="205_guice.html">DSL for Guice</a></li>
<li><a href="206_httprouting.html">Http Routing Language</a></li>
<li><a href="207_template.html">Template Language</a></li>
<li><a href="208_tortoise.html">Little Tortoise</a></li-->
<li class="nav-part">Reference Documentation</li>
<li><a href="301_grammarlanguage.html">The Grammar Language</a></li>
<li><a href="302_configuration.html">Configuration</a></li>
<li><a href="303_runtime_concepts.html">Language Implementation</a></li>
<li><a href="305_xbase.html">Integration with Java</a></li>
<!--li><a href="306_mwe2.html">MWE2</a></li-->
<!--li><a href="307_special_languages.html">Typical Language Configurations</a></li-->
<li><a href="308_emf_integration.html">Integration with EMF</a></li>
<li><a href="310_eclipse_support.html">Eclipse Support</a></li>
<!--li><a href="320_idea_support.html">IntelliJ IDEA Support</a></li-->
<li><a href="330_web_support.html">Web Editor Support</a></li>
<li><a href="350_continuous_integration.html">Continuous Integration</a></li>
<!--li class="nav-part">Appendix</li>
<li><a href="401_migrating_from_1_0_x.html">Migrating from Xtext 1.0.x to 2.0</a></li>
<li><a href="402_migrating_from_0_7.html">Migrating from Xtext 0.7.x to 1.0</a></li-->
</ul>
</div>
<div class="span8 doc-contents">
<h1 id="sevenlang-introduction">Introduction</h1>
<p>Building a domain-specific language (DSL) for structural parts of an application has always been rather easy with Xtext. But structure alone is not sufficient in many cases. When it comes to the behavioral aspects users often fall back to implementing them in Java. The reasons are obvious: expressions and statements are hard to get right and extremely complex and therefore costly to implement.</p>
<p>This document introduces and explains a new API, which allows reusing predefined language constructs such as type references, annotations and fully featured expressions anywhere in your languages. You not only reuse the grammar but the complete implementation including a compiler, interpreter, the whole Java type system and a tight IDE integration. And the best part is, that it is relatively easy to do so. It is actually just two steps:</p>
<h2 id="write-the-grammar">Write the Grammar</h2>
<p>Using the traditional Xtext grammar language you freely describe the syntax of your language. The specialty for JVM languages is, that you inherit from an abstract grammar org.eclipse.xtext.xbase.Xbase, which predefines the syntax for the reusable parts. You do not need to use all of them directly and you can of course change the syntax or add new concepts, as it seems fit.</p>
<h2 id="map-to-java">Map to Java</h2>
<p>Having the grammar defined, you now need to tell Xtext what your language concepts mean in terms of Java constructs. For that purpose you use a so-called <em>model inferrer</em>, a special API that allows you to create any number of Java classes, interfaces or members from your DSL. This hook not only defines how your language is translated to Java, but also defines the scope of the embedded expressions. The expressions from your language ‘live’ in the context you give them. If you want an expression to have access to certain local variables, just put it into a method with appropriate parameters or use instance fields if they work better.</p>
<p>While in plain Xtext you would usually customize a bunch of further services to fit your needs, Xbase already has JVM model aware implementations almost all of them. For example, a generic code generator generates the Java code directly from the inferred model. The same way, Xbase already integrates your language with JDT to an extend that customizations beyond the JVM model inferrer will only be necessary for very special cases. You can naturally mix Java and DSL code in the same application without any barriers.</p>
<p>The inferred model also reveals your DSL constructs to other JVM languages. The Java type system is used as a common hub to integrate arbitrary languages with each other. You can for instance call <a href="207_template.html">templates</a> directly from a <a href="202_scripting.html">script</a> and vice versa. You do not even need to generate the equivalent Java code; everything is based on the Java types you create in the model inferrer.</p>
<p>To illustrate the power and flexibility of these two abstractions, we have built seven example languages using them:</p>
<ul>
<li><a href="202_scripting.html">A simple scripting language</a></li>
<li><a href="203_builddsl.html">A Grade-like build DSL</a></li>
<li><a href="204_mongodb.html">A DSL for statically-typed MongoDB documents</a></li>
<li><a href="205_guice.html">A Guice modules DSL</a></li>
<li><a href="206_httprouting.html">A Playframework-like HTTP routing language</a></li>
<li><a href="207_template.html">A template language</a></li>
<li><a href="208_tortoise.html">A Logo-like programming environment for educational purposes</a></li>
</ul>
<p>Each language is very simple and focuses on the value a DSL can add to the respective viewpoint. It is meant to give you an idea of what is possible without being a complete practical solution. Yet the languages are flexible and come with powerful core abstractions. We also covered different technical aspects of customizing to the language infrastructure. Some languages have special syntax coloring, others provide customized outline views or content assist. All aspects of a language are still fully customizable when using Xbase.</p>
<h2 id="provisional-API">CAUTION: This is Provisional API</h2>
<p><strong>Please be aware that some of the new API covered in this document is not yet finalized and will likely be improved in future releases in incompatible ways. Usages of such API are marked with a warning.</strong></p>
<h2 id="common-requirements">Common Requirements</h2>
<p>To run any of the examples, you will need <a href="http://www.eclipse.org/downloads/">Eclipse 3.6 or better</a> for your platform. In addition, you have to install <a href="http://www.eclipse.org/xtend/download.html">Xtend</a> and of course <a href="http://www.eclipse.org/Xtext/download.html">Xtext 2.7</a>.</p>
<p>If you prefer a simple all-inclusive installation, consider downloading the latest <a href="http://www.eclipse.org/Xtext/download.html">Xtext distribution</a>.</p>
<p>Additional requirements are mentioned in the <em>Running the Example</em> section of each chapter.</p>
<h2 id="installation">Getting the Code</h2>
<p>You can get the source code for all languages from the github repository at <a href="https://github.com/xtext-dev/seven-languages-xtext.git">github.com/xtext-dev/seven-languages-xtext</a>. The repository contains two folders <em>languages</em> and <em>examples</em>. Download the plug-ins from <em>languages</em> into the root workspace and the <em>examples</em> into the runtime workspace spawned from the root one using <em>Run → Run Configurations… → Eclipse Application → Run (&lt;language&gt;)</em>.</p>
<p>Each language consists of several Eclipse projects</p>
<table>
<tbody>
<tr>
<td><em>org.xtext.&lt;language&gt;</em></td>
<td>The base infrastructure</td>
</tr>
<tr>
<td><em>org.xtext.&lt;language&gt;.ui</em></td>
<td>The editor based on Eclipse</td>
</tr>
<tr>
<td><em>org.xtext.&lt;language&gt;.tests</em></td>
<td>Tests for the language</td>
</tr>
<tr>
<td><em>org.xtext.&lt;language&gt;.lib</em></td>
<td>Runtime library</td>
</tr>
<tr>
<td><em>org.xtext.&lt;language&gt;.example</em></td>
<td>Examples for using the language</td>
</tr>
</tbody>
</table>
<p>Some of the languages do not include all of these plug-ins but the general structure is always the same.</p>
<h2 id="xtend-primer">A Short Xtend Primer</h2>
<p>Any general code in the examples is implemented in <a href="http://www.xtend-lang.org">Xtend</a>. Xtend is a more expressive and less verbose way to implement Java applications. It is 100% interoperable with Java APIs and compiles to readable Java code. In addition, it uses the same expressions that we use in our example languages. In fact it is built with the very same API that is described in this document. This should give you a taste of how powerful JVM-languages built with Xtext can actually be.</p>
<p>Xtend is designed to be easy to learn for Java developers. In this section we will shortly describe the most important language features that were used in our examples. For a full description of the Xtend language, please refer to the <a href="http://www.xtend-lang.org/documentation">Xtend documentation</a>.</p>
<p>Just like a Java file, an Xtend file starts with a <code>package</code> declaration and an <code>import</code> section followed by one or more class declarations. Semicolons are optional. All types are <code>public</code> by default. Xtend classes can extend other classes and implement interfaces just like in Java. It does not make any difference whether they were originally declared in Xtend or in Java.</p>
<p><a name="xtend_property"></a> JavaBean properties can be accessed directly by their name. The access will be automatically mapped to the appropriate accessor method. That means you can write</p>
<pre><code class="language-xtend">println(foo.bar) // instead of println(foo.getBar())
foo.bar = baz // instead of foo.setBar(baz)
foo.fooBars += foobar // instead of foo.getFooBars().add(foobar)
</code></pre>
<p>Empty parentheses on method or constructor calls can be skipped.</p>
<p><a name="xtend_methods"></a></p>
<p>Methods are introduced with the keyword <code>def</code> or <code>override</code> if they override/implement a super type’s method. Methods are public if not specified otherwise. The value of the last expression is returned if no explicit return expression is used and the method’s return type is not <code>void</code>.</p>
<p><a name="xtend_variables"></a></p>
<p>Variables are declared with the keywords <code>val</code> (final) or <code>var</code> (non-final). Field declarations can use the same syntax as in Java.</p>
<p><a name="xtend_typeinferrence"></a></p>
<p>Xtend is statically typed, but you do not have to specify the type in a declaration if it can be inferred from the context:</p>
<pre><code class="language-xtend">val x = newArrayList('foo', 'bar', 'baz') // x is of type List&lt;String&gt;
def foo() { // equivalent to def int foo()...
1
}
</code></pre>
<p><a name="xtend_extension"></a> The methods of fields marked as <code>extension</code> are callable in extension syntax. That means, you can put the first argument in front as if it were the receiver of the call, e.g.</p>
<pre><code class="language-xtend">// assume the class Foo defines a method foo(Baz)
extension Foo theFoo
def bar(Baz baz) {
baz.foo // calls theFoo.foo(baz)
}
</code></pre>
<p>Static methods can be put on the extension scope with a <code>static extension</code> import, e.g.</p>
<pre><code class="language-xtend">import static extension java.util.Collections.*
...
val foo = singleton('foo') // calls Collections.&lt;String&gt;singleton('foo')
</code></pre>
<p><a name="xtend_it"></a> In addition to Java’s <code>this</code>, you can define another implicit receiver variable named <code>it</code>. As with <code>this</code>, you can omit <code>it</code> in feature calls, i.e.</p>
<pre><code class="language-xtend">class Foo {
def foo(Bar it) {
foo // will call it.foo() or if that doesn't exist this.foo()
}
}
</code></pre>
<p><a name="xtend_lambda"></a> Xtend provides lambda expressions. These are anonymous functions in square brackets.</p>
<pre><code class="language-xtend">[String foo, String bar | foo + bar]
// a function (String foo, String bar) { foo + bar }
</code></pre>
<p><a name="xtend_lambda_coercion"></a> As this is a bit bulky, there are more rules to make working with lambdas more attractive:</p>
<ol>
<li>When a lambda expression is the last argument in a method call, it can be put behind the closing parentheses.</li>
<li>Lambdas are automatically coerced to interfaces with a single function. Parameter types will be inferred.</li>
<li>If you skip the declaration of the only parameter, it will be implicitly called <code>it</code>.</li>
</ol>
<pre><code class="language-xtend">new Thread [ println("Hello concurrent world") ]
// lambda will be coerced to a java.lang.Runnable
val list = #['fooooo', 'fo', 'foo'] // #[] delimits a list literal
list.sortBy[ length ]
// lambda is coerced to a function (String)=&gt;Comparable
// equivalent to list.sortBy[String it | it.length]
</code></pre>
<p><a name="xtend_templates"></a> Also noteworthy is the template expression, which allows defining interpolated multi-line string literals. In addition, the template expressions has intelligent whitespace handling and supports a special <code>FOR</code> and <code>IF</code> construct, which is far better readable in this context. In model inferrers, the template expressions are enhanced further to support type literals, automatically adding an import to the generated Java file.</p>
<p>We most often use this expression in the examples to generate some synthetic Java boilerplate code. Here is an example from the <a href="206_httprouting.html">http routing language</a>:</p>
<pre><code class="language-xtend">'''
String url = request.getRequestURL().toString();
«FOR route : routes»
{
//java.util.regex.Matcher will be imported in the generated Java file
«Matcher» _matcher = _pattern«route.index».matcher(url);
if (_matcher.find()) {
«FOR variable : route.url.variables»
String «variable.name» = _matcher.group(«variable.index + 1»);
«ENDFOR»
«IF route.condition != null»
if («route.nameOfRouteMethod»Condition(request, response
«FOR v : route.url.variables
BEFORE ", "
SEPARATOR ", "»«v.name»«ENDFOR»))
«ENDIF»
«route.nameOfRouteMethod»(request, response
«FOR v : route.url.variables», «v.name»«ENDFOR»);
}
}
«ENDFOR»
'''
</code></pre>
<hr />
<p><strong><a href="202_scripting.html">Next Chapter: Scripting Language</a></strong></p>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="site-footer">
<div id="extra">
<div class="inner">
<div class="container">
<div class="row">
<div class="span6">
<h3 class="footer-links-header">Quick Links</h3>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a></li>
<li><a href="http://www.eclipse.org/legal/termsofuse.php">Terms of Use</a></li>
<li><a href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a></li>
<li><a href="http://www.eclipse.org/legal/">Legal</a></li>
</ul>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org">Eclipse Home</a></li>
<li><a href="http://marketplace.eclipse.org/">Market Place</a></li>
<li><a href="http://live.eclipse.org/">Eclipse Live</a></li>
<li><a href="http://www.planeteclipse.org/">Eclipse Planet</a></li>
</ul>
</div>
<div class="span6">
<h3 class="footer-links-header"><a href="https://twitter.com/xtext" style="color: white;">@Xtext</a> on Twitter</h3>
<a class="twitter-timeline" href="https://twitter.com/xtext" data-widget-id="346625441290928128"
data-chrome="noheader nofooter transparent"
data-theme="dark">Tweets by @xtext</a>
<script>
!function(d,s,id) {
var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';
if(!d.getElementById(id)) {
js=d.createElement(s);
js.id=id;
js.src=p+"://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js,fjs);
}
}(document,"script","twitter-wjs");
</script>
</div>
</div>
</div>
</div>
</div>
<a href="#" class="scrollup fadeOutRight animated" style="display: none;">ScrollUp</a>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/Xtext/js/jquery-1.11.3.min.js"></script>
<script src="/Xtext/js/bootstrap.min.js"></script>
<script src="/Xtext/js/jquery.easing.1.3.js" type="text/javascript"></script>
<script src="/Xtext/js/jquery.prettyPhoto.js" type="text/javascript"></script>
<script src="/Xtext/js/twitter.js" type="text/javascript"></script>
<script src="/Xtext/js/prettify.js" type="text/javascript"></script>
<script src="/Xtext/js/lang-xtend.js" type="text/javascript"></script>
<script src="/Xtext/js/lang-common.js" type="text/javascript"></script>
<script src="/Xtext/js/custom.js" type="text/javascript"></script>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<!--script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push([ '_setAccount', 'UA-2429174-3' ]);
_gaq.push([ '_trackPageview' ]);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl'
: 'http://www')
+ '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script-->
<script src="/Xtext/js/coverflow.min.js" type="text/javascript"></script>
<script>
$(function() {
$('#coverflow').coverflow({
active : 1,
visibleAside: 2,
overlap : 0.5,
scale : 0.9,
angle : 20,
trigger : {
"itemfocus" : true,
"swipe" : true,
"mousewheel" : false
}
});
$('#coverflow :hidden').toggle();
$(window).resize(function() {
$('#coverflow').coverflow();
});
});
</script>
</footer>
</body>
</html>