blob: fbae06a80bd2e9c4952b83a037a9eb23620c911c [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Xtext - Scripting Language</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/202_scripting.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="scripting">Scripting Language</h1>
<p>The scripting language allows writing code without any preludes such as package, class or method declarations. Just open a file and start coding. It’s the simplest of the seven languages and is therefore a good starting point.</p>
<p><img src="images/scripting_screenshot.png" alt="" /></p>
<h2 id="scripting-solution">Overview</h2>
<p>As you can see the language is straightforward: All you can do is write expressions. The expressions you see are the same as in Xtend and they are defined in its own grammar (called Xbase). They are syntactically very close to Java, but feature advanced concepts like lambda expressions and operator overloading. They support local type inference so you do not have to write types everywhere like in Java, but the expressions are still statically typed. For a Java developer, the code should be self-explanatory. The Xbase expression language is exhaustively covered in the respective <a href="305_xbase.html">documentation section</a>.</p>
<p>A script is compiled to a Java class with one main method. That is the script</p>
<pre><code class="language-scripting">println('Hello World!')
</code></pre>
<p>is compiled to the following Java source code</p>
<pre><code class="language-java">package my.first;
public class Application {
public static void main(String... args) {
System.out.println("Hello World!");
}
}
</code></pre>
<p>Note that the core language infrastructure such as the parser, linker and compiler does not depend on Eclipse, but the compilation is integrated with Eclipse for convenience reasons. All 7 languages can be parsed, compiled and executed without Eclipse. We could also make use of the interpreter, which might make more sense for a scripting language. How to use and integrate the interpreter is explained in the section describing the <a href="208_tortoise.html">Tortoise</a> language.</p>
<h2 id="scripting-running">Running the Example</h2>
<p>Make sure you have the projects <em>org.xtext.scripting</em> and <em>org.xtext.scripting.ui</em> in your workspace. Then start a new Eclipse by choosing <em>Run → Run Configurations… → Eclipse Application → Run (org.xtext.scripting)</em>. Import the project <em>org.xtext.scripting.examples</em> into the newly spawned workspace using the <em>Import existing projects into workspace</em> wizard.</p>
<h2 id="scripting-grammar">Grammar</h2>
<p>To build a language with Xtext, you first have to define a grammar. As opposed to other parser generators, an Xtext grammar defines both, the lexical structure of the language and an object model (the AST or semantic model) that is build during parsing. For a more detailed description of the Xtext grammar language, please see the respective <a href="301_grammarlanguage.html">documentation section</a>.</p>
<p>The grammar for our DSL is rather simple. We inherit from <code>org.eclipse.xtext.xbase.Xbase</code> to get the syntax of the expressions. As we want to refer to the type <a href="https://github.com/eclipse/xtext-extras/blob/master/org.eclipse.xtext.xbase/emf-gen/org/eclipse/xtext/xbase/XBlockExpression.java">XBlockExpression</a>, we have to import Xbase’s Ecore model. The single type inferred from this grammar goes into the Ecore model <code>simpleExpressions</code>.</p>
<pre><code class="language-xtext">grammar org.xtext.scripting.Scripting with org.eclipse.xtext.xbase.Xbase
generate scripting "http://www.xtext.org/scripting/Scripting"
import "http://www.eclipse.org/xtext/xbase/Xbase"
Script returns XBlockExpression:
{Script}
(expressions+=XExpressionOrVarDeclaration ';'?)*;
</code></pre>
<p>The main rule <em>Script</em> is defined to produce an object of type <code>Script</code>, which is a subtype of <code>XBlockExpression</code>. A block expression simply contains any number of expressions. The rule <code>XExpressionOrVarDeclaration</code> is defined in the Xbase grammar. Usually block expressions are surrounded by curly braces, but of course we do not want to force anybody to write curly braces at the beginning and the end of a simple script.</p>
<h2 id="scripting-inferrer">Translation to Java</h2>
<p>To make our language executable, we have to define how its concepts relate to Java concepts. In Xtext, this is defined by the <a href="https://github.com/eclipse/xtext-extras/blob/master/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/jvmmodel/IJvmModelInferrer.java">IJvmModelInferrer</a>. The language generator automatically generates an Xtend stub for it. Nevertheless, it is up to the language developer to implement the <code>infer()</code> method.</p>
<p>This hook is not only used to explain how to generate Java code, but also to give expressions a proper scope and to make your DSL constructs visible by other JVM languages. The Java type system is used as a common hub to integrate arbitrary languages with each other.</p>
<p>The inferrer is written in Xtend, if you are not yet familiar with it, you should read at least the <a href="201_sevenlang_introduction.html#xtend-primer">Xtend Primer</a> first.</p>
<p>The JVM model inferrer code for the scripting language looks like this:</p>
<pre><code class="language-xtend">class ScriptingJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
def dispatch void infer(Script script,
IJvmDeclaredTypeAcceptor acceptor,
boolean isPreIndexingPhase) {
val className = script.eResource.URI.trimFileExtension.lastSegment
acceptor.accept(script.toClass(className))[
// the class gets one main method
members += script.toMethod('main', typeRef(Void.TYPE)) [
parameters += script.toParameter("args", typeRef(String).addArrayTypeDimension)
static = true
varArgs = true
// Associate the script as the body of the main method
body = script
]
]
}
}
</code></pre>
<p>It maps each script to one Java class with a main method. Note the use of <code>script</code> as a receiver for all the factory methods. When creating a Java element, you need to pass a context so Xtext knows what the origin of a Java element is. This is used throughout the workbench for features like find references, call hierarchies, rename refactoring and more.</p>
<p>As the whole script is an expression it is associated with the body of the main method. That association is important since it defines the scope of the expression. It includes the variables, fields and methods that are visible as well as which return type is expected.</p>
<p>In this case <code>void</code> is expected, so you would get an error when using a return expression. Also the parameter <code>args</code> defined in the main method is now on the scope. So you could write the following script:</p>
<pre><code class="language-scripting">for (arg : args)
println('-- '+arg)
</code></pre>
<p>As you can imagine, this is a fairly powerful way to put things on the scope implicitly.</p>
<hr />
<p><strong><a href="203_builddsl.html">Next Chapter: Build 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>