blob: aa2383aeafed5f65597d915545a6b83cc25cd8bc [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Xtext - Typical Language Configurations</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]-->
<!-- BEGIN Cookie Consent
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.js"></script>
<script>
window.addEventListener("load", function(){
window.cookieconsent.initialise({
"palette": {
"popup": {
"background": "#000"
},
"button": {
"background": "#f1d600"
}
},
"theme": "edgeless",
"type": "opt-in",
onInitialise: function (status) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onStatusChange: function(status, chosenBefore) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onRevokeChoice: function() {
var type = this.options.type;
if (type == 'opt-in') {
// TODO: disable cookies
}
if (type == 'opt-out') {
// TODO: enable cookies
}
},
"content": {
"href": "http://www.eclipse.org/legal/privacy.php"
}
})});
</script>
END Cookie Consent -->
</head>
<body>
<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://www.typefox.io/language-engineering/" 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/307_special_languages.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">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="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="330_web_support.html">Web Editor Support</a></li>
<li><a href="340_lsp_support.html">LSP Support</a></li>
<li><a href="350_continuous_integration.html">Continuous Integration</a></li>
</ul>
</div>
<div class="span8 doc-contents">
<h1 id="special-languages">Typical Language Configurations</h1>
<h2 id="case-insensitive-languages">Case Insensitive Languages</h2>
<p>In some cases, e.g. if your <em>SHIFT</em> key is broken, you might want to design a case insensitive language. Xtext offers options on some of its <a href="302_configuration.html#generator-fragment">generator fragments</a> for this purpose.</p>
<p>For case insensitive keywords, open your MWE workflow and enable the ignoreCase property:</p>
<pre><code class="language-mwe2"> ... StandardLanguage {
... other config
parserGenerator = {
options = {
ignoreCase = true
}
}
}
</code></pre>
<p>For case insensitive element names, use the <em>ignoreCase</em> option in the scoping, too :</p>
<pre><code class="language-mwe2"> scopeProvider = {
ignoreCase = true
}
</code></pre>
<h2 id="whitespace-aware-languages">Whitespace-Aware Languages</h2>
<p>Some language designers prefer to use indentation to structure code blocks instead of surrounding them with braces <code>{ ... }</code>, which are really hard to type with certain kinds of keyboards. A well-known example of such a language is <a href="https://www.python.org">Python</a>. Another well-known example is the <em>Home Automation</em> language shipped with Xtext, available through <em>File → New → Example → Xtext Examples → Xtext Home Automation Example</em>.</p>
<pre><code class="language-ruleengine">Device Window can be open, closed
Device Heater can be on, off, error
Rule 'Save energy' when Window.open then
fire(Heater.off)
println('Another penny to the piggy bank!')
</code></pre>
<p>The <code>'Save energy'</code> rule contains a code block with two operations, which is indicated by the equal indentation of these operations. Nested blocks are also possible:</p>
<pre><code class="language-ruleengine">Rule 'Report error' when Heater.error then
var String report
do
Thread.sleep(500)
report = HeaterDiagnostic.readError
while (report == null)
println(report)
</code></pre>
<p>The first step for including whitespace-aware blocks in your language is to use <em>synthetic tokens</em> in the grammar by writing terminals of the form <code>'synthetic:&lt;terminal name&gt;'</code>:</p>
<pre><code class="language-xtext">terminal BEGIN: 'synthetic:BEGIN';
terminal END: 'synthetic:END';
</code></pre>
<p>These terminals can be used to mark the boundaries of code blocks. The Xtext Home Automation example inherits expressions from <a href="305_xbase.html">Xbase</a> and redefines the syntax of block expressions:</p>
<pre><code class="language-xtext">@Override
XBlockExpression returns xbase::XExpression:
{xbase::XBlockExpression}
BEGIN
(expressions+=XExpressionOrVarDeclaration ';'?)*
END;
</code></pre>
<p>After running the workflow, a stub implementation of <code>AbstractIndentationTokenSource</code> is generated in the <code>parser.antlr</code> subpackage, e.g. <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.xtext.ui.examples/projects/homeautomation/org.eclipse.xtext.example.homeautomation/src/org/eclipse/xtext/example/homeautomation/parser/antlr/RuleEngineTokenSource.java">RuleEngineTokenSource</a>. Here you can specify which terminal rule should be applied to your synthetic tokens. For the Xtext Home Automation language the <code>WS</code> (whitespace) rule is selected, which brings the indentation awareness as seen above.</p>
<p>In case of a whitespace-aware language, the <a href="303_runtime_concepts.html#formatting">formatter</a> must be either adapted to produce whitespace that correctly reflects the document structure, or it must be deactivated. Otherwise automatic formatting might produce code with different semantics or even syntax errors. See how we <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.xtext.ui.examples/projects/homeautomation/org.eclipse.xtext.example.homeautomation/src/org/eclipse/xtext/example/homeautomation/formatting2/RuleEngineFormatter.xtend">customized the formatter</a> in the Xtext Home Automation example.</p>
<h2 id="java-independent-languages">Languages Independent of JDT</h2>
<p>The following section describes how you make your language independent of Eclipse’s Java Development Toolkit (JDT).</p>
<p>In the <em>UIModule</em> of your language you have to overwrite two bindings. First, remove the bindings to components with support for the <em>‘classpath:’</em> URI protocol, i.e.</p>
<pre><code class="language-java">@Override
public Class&lt;? extends IResourceForEditorInputFactory&gt;
bindIResourceForEditorInputFactory() {
return ResourceForIEditorInputFactory.class;
}
@Override
public Class&lt;? extends IResourceSetProvider&gt; bindIResourceSetProvider() {
return SimpleResourceSetProvider.class;
}
</code></pre>
<p>Second, configure the global scope provider to scan project root folders instead of the class path of Java projects.</p>
<pre><code class="language-java">@Override
public Provider&lt;IAllContainersState&gt; provideIAllContainersState() {
return org.eclipse.xtext.ui.shared.Access.getWorkspaceProjectsState();
}
</code></pre>
<p>The remaining steps show you how to adapt the project wizard for your language, if you have generated one. The best way to do this is to create a new subclass of the generated <em>IProjectCreator</em> in the <em>src/</em> folder of the <em>ui</em> project and apply the necessary changes there. First, remove the JDT project configuration by overriding <em>configureProject</em> with an empty body.</p>
<p>The next thing is to redefine the project natures and builders that should be applied to your language projects.</p>
<p>In in this case just remove the JDT stuff in this way:</p>
<pre><code class="language-java">protected String[] getProjectNatures() {
return new String[] {
"org.eclipse.pde.PluginNature",
"org.eclipse.xtext.ui.shared.xtextNature"
};
}
protected String[] getBuilders() {
return new String[] {
"org.eclipse.pde.ManifestBuilder",
"org.eclipse.pde.SchemaBuilder"
};
}
</code></pre>
<p>After that you have to bind the new <em>IProjectCreator</em></p>
<pre><code class="language-java">@Override
public Class&lt;? extends IProjectCreator&gt; bindIProjectCreator() {
return JDTFreeMyDslProjectCreator.class;
}
</code></pre>
<p>Now your language and its IDE should now no longer depend on JDT.</p>
<h2 id="expressions">Parsing Expressions with Xtext</h2>
<p>Parsing simple XML-like, structural languages with Xtext is a no-brainer. However, parsing nested expressions is often considered complicated. This is the perception due to their recursive nature and the properties of the parser technology used by Xtext. You have to avoid left recursive parser rules. As the underlying Antlr parser uses a top-down approach it would recurse endlessly if you had a left recursive grammar.</p>
<p>Let’s have a look at parsing a simple arithmetic expression:</p>
<p><code>2 + 20 * 2</code></p>
<p>If you know EBNF a bit and wouldn’t think about avoiding left recursion, operator precedence or associativity, you’ld probably write a grammar like this:</p>
<pre><code class="language-xtext">Expression :
Expression '+' Expression |
Expression '*' Expression |
INT;
</code></pre>
<p>This grammar would be left recursive because the parser reads the grammar top down and left to right and would endlessly call the <em>Expression</em> rule without consuming any characters, i.e. altering the underlying state of the parser. While this kind of grammar can be written for bottom-up parsers, you would still have to deal with operator precedence in addition. That is define that a multiplication has higher precedence than an addition for example.</p>
<p>In Xtext you define the precedence implicitly when left-factoring such a grammar. Left-factoring means you get rid of left recursion by applying a certain idiom, which is described in the following.</p>
<p>Here is a left-factored grammar (not yet working with Xtext) for the expression language above:</p>
<pre><code class="language-xtext">Addition :
Multiplication ('+' Multiplication)*;
Multiplication:
NumberLiteral ('*' NumberLiteral)*;
NumberLiteral:
INT;
</code></pre>
<p>As you can see the main difference is that it uses three rules instead of one, and if you look a bit closer you see that there’s a certain delegation pattern involved. The rule <em>Addition</em> doesn’t call itself but calls <em>Multiplication</em> instead. The operator precedence is defined by the order of delegation. The later the rule is called the higher is its precedence. This is at least the case for the first two rules which are of a left recursive nature (but we’ve left-factored them now). The last rule is not left recursive which is why you can implement it without applying this pattern.</p>
<p>The next task is to allow users to explicitly adjust precedence by adding parentheses, e.g. write something like <code>(2 + 20) * 2</code>. So let’s add support for that (note that the grammar is still not yet working with Xtext):</p>
<pre><code class="language-xtext">Addition :
Multiplication ('+' Multiplication)*;
Multiplication:
Primary ('*' Primary)*;
Primary :
NumberLiteral |
'(' Addition ')';
NumberLiteral:
INT;
</code></pre>
<p>Once again: if you have some construct that recurses on the left hand side, you need to put it into the delegation chain according to the operator precedence. The pattern is always the same: the thing that recurses delegates to the rule with the next higher precedence.</p>
<h3 id="construction-of-an-ast">Construction of an AST</h3>
<p>Now that left recursion is avoided, the parser should produce a proper syntax tree. In Xtext each rule returns a value. Production rules return AST nodes (i.e. instances of EObject), enum rules return enum literals and data type rules as well as terminal rules return simple values like strings. Xtext can automatically infer whether some rule is a production rule, i.e. constructs and returns an AST node, or if it is a data type rule that returns a value. The grammar above only consists of data type rules all of them returning plain strings. In order to construct an AST we need to add assignments and actions to the grammar.</p>
<p>The return type of a rule can be specified explicitly using the <code>returns</code> keyword but can be inferred if the type’s name is the same as the rule’s name. That is</p>
<pre><code class="language-xtext">NumberLiteral : ... ;
</code></pre>
<p>is a short form of</p>
<pre><code class="language-xtext">NumberLiteral returns NumberLiteral : ... ;
</code></pre>
<p>However in the case of the expression grammar above, all rules need to return the same type since they are recursive. In order to make the grammar valid, a common return type has to be added explicitly (but the grammar is still missing some bits):</p>
<pre><code class="language-xtext">Addition returns Expression:
Multiplication ('+' Multiplication)*;
Multiplication returns Expression:
Primary ('*' Primary)*;
Primary returns Expression:
NumberLiteral |
'(' Addition ')';
NumberLiteral:
INT;
</code></pre>
<p>The AST type inference mechanism of Xtext will infer two types: <em>Expression</em> and <em>NumberLiteral</em>. Assignments and actions have to be added to store all the important information in the AST and to create reasonable subtypes for the additive and multiplicative expressions. The fully working Xtext grammar is:</p>
<pre><code class="language-xtext">Addition returns Expression:
Multiplication ({Addition.left=current} '+' right=Multiplication)*;
Multiplication returns Expression:
Primary ({Multiplication.left=current} '*' right=Primary)*;
Primary returns Expression:
NumberLiteral |
'(' Addition ')';
NumberLiteral:
value=INT;
</code></pre>
<p>This is how the parser processes the following expression:</p>
<pre><code class="language-java">(1 + 20) * 2
</code></pre>
<p>It always starts with the first rule <em>Addition</em>. Therein the first element is an unassigned rule call to <em>Multiplication</em> which in turn calls <em>Primary</em>. <em>Primary</em> now has two alternatives. The first one is calling <em>NumberLiteral</em> which consists only of one assignment to a feature called ‘value’. The type of ‘value’ has to be compatible to the return type of the <em>INT</em> rule.</p>
<p>But as the first token in the sample expression is an opening parenthesis ‘(‘, the parser will take the second alternative in <em>Primary</em>: it consumes the ‘(‘ and calls the rule <em>Addition</em>. Now the value ‘1’ is the lookahead token and again <em>Addition</em> calls <em>Multiplication</em> and <em>Multiplication</em> calls <em>Primary</em>. This time the parser takes the first alternative because ‘1’ was consumed by the <em>INT</em> rule.</p>
<p>As soon as the parser hits an assignment it checks whether an AST node for the current rule was already created. Otherwise it will create one based on the return type of the current rule, which is <em>NumberLiteral</em>. The Xtext generator created the EClass ‘NumberLiteral’ before which can now be instantiated. That type will also have a property called value of type int, which will get the value ‘1’ set. This is what the Java equivalent looks like:</p>
<pre><code class="language-java">// value=INT
if (current == null)
current = new NumberLiteral();
current.setValue(ruleINT());
...
</code></pre>
<p>Now that the rule has been completed the produced EObject is returned to the calling rule <em>Primary</em>, which in turn returns the object unchanged to its own caller. Within <em>Multiplication</em> the rule <em>Primary</em> has been successfully parsed and returned an instance of <em>NumberLiteral</em>. The remainder of the rule (everything within the parentheses) is a so called group. The asterisk behind the closing parenthesis states that this part can be consumed zero or more times. The first token to consume in this group is the multiplication operator ‘*’. Unfortunately in the current input the next token to accept is the plus sign ‘+’, so the group is not consumed at all and the rule returns the <em>NumberLiteral</em> that was returned from the previous unassigned rule call.</p>
<p>In rule <em>Addition</em> there is a similar group but this time it expects the correct operator. The parser steps into the group. The first element in the group is an assigned action. It will create a new instance of type <em>Addition</em> and assigns what was the to-be-returned object to the feature ‘left’. In Java this would have been something like:</p>
<pre><code class="language-java">// Multiplication rule call
current = ruleMultiplication();
// {Addition.left=current}
Addition temp = new Addition();
temp.setLeft(current);
current = temp;
...
</code></pre>
<p>As a result the rule would now return an instance of <em>Addition</em> which has a <em>NumberLiteral</em> set to its property left. Next up the parser consumes the ‘+’ operator. The operator itself is not stored in the AST because there is an explicit Addition type. It implicitly contains this information. The assignment <code>right=Multiplication</code> calls the rule <em>Multiplication</em> another time and assigns its result object (a NumberLiteral of value=20) to the property <code>right</code>. The closing parenthesis is matched afterwards, consumed and the parser stack is reduced once more.</p>
<p>The parser is now in the rule <em>Multiplication</em> and has the multiplication operator ‘*’ on the lookahead. It steps into the group and applies the action. Finally it calls the <em>Primary</em> rule, produces another instance of <em>NumberLiteral</em> (value=2), assigns it as the ‘right’ operand of the <em>Multiplication</em> and returns the <em>Multiplication</em> to the rule <em>Addition</em> which in turn returns the very same object as there’s nothing left to parse.</p>
<p>The resulting AST looks like this:</p>
<p><img src="images/expression-ast.png" alt="" /></p>
<h3 id="associativity">Associativity</h3>
<p>There is still one topic worth to mention, which is associativity. There is left and right associativity as well as non-associativity. The example above implements left associativity. Associativity tells the parser how to construct the AST when there are two infix operations with the same precedence. The following example is taken from the corresponding wikipedia entry:</p>
<p>Consider the expression a ~ b ~ c. If the operator ~ has left associativity, this expression would be interpreted as (a ~ b) ~ c and evaluated left-to-right. If the operator has right associativity, the expression would be interpreted as a ~ (b ~ c) and evaluated right-to-left. If the operator is non-associative, the expression might be a syntax error, or it might have some special meaning. The most common variant is left associativity:</p>
<pre><code class="language-xtext">Addition returns Expression:
Multiplication ({Addition.left=current} '+' right=Multiplication)*;
</code></pre>
<p>Right associativity is done using a slightly modified pattern. Note the quantity operator and the call to the rule itself in the group:</p>
<pre><code class="language-xtext">Addition returns Expression:
Multiplication ({Addition.left=current} '+' right=Addition)?;
</code></pre>
<p>Non-associativity can be implemented in a similar way, but this time the final rule call is not immediately recursive but delegates to the next precedence level:</p>
<pre><code class="language-xtext">Addition returns Expression:
Multiplication ({Addition.left=current} '+' right=Multiplication)?;
</code></pre>
<p>Sometimes it’s more convenient to allow associativity on parser level, but forbid it later using validation. This allows more descriptive diagnostics. Also the whole parsing process won’t rely on error recovery but the editor will generally be more forgiving.</p>
<hr />
<p><strong><a href="308_emf_integration.html">Next Chapter: Integration with EMF and Other EMF Editors</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://www.planeteclipse.org/">Eclipse Planet</a></li>
<li><a href="https://www.eclipse.org/forums/index.php/f/27/">Xtext Forum</a></li>
</ul>
</div>
<div class="span6">
<!-- Social Media Links -->
<h3 class="footer-links-header"">Social Media</h3>
<ul class="footer-links clearfix">
<li>
<a href="https://twitter.com/xtext"><img src="/Xtext/images/Twitter-bird-darkgray.png" class="img-responsive" style="margin-right: 5px;height: 1em;" alt="Twitter icon">@xtext on Twitter</a>
</li>
</ul>
</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/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>