XText DSL with lookbehind - eclipse-rcp

I am stuck in writing a DSL using XText. Let us assume that I want to parse something like this:
A {
B, //this comma is needed
C,
D {E}, //comma is optional after a closing curly brace
F {G}
H
}
I,
J
It should be represented by the types Model and Class, where Model contains a list of classes.
What I do have currently is:
Model: (classes += Class)*
Class: name = ID ('{' (subclasses += Class) (',' subclasses += Class)* '}')?
This would work if classes must be delimited by a comma, independent from them having subclasses or not. However, since a Class can have subclasses bracketed by curly braces, a comma is not a must after a closing curly brace.
This means I need a grammar expressing the following:
Class: ID (',' Class | '{' subclasses += Class '}' ','? Class)?
Since I am not able to reference the containing rule, the Class rule reference inside Class will not work. I believe that there is a simple solution for this issue which I just can not see.
Edit: I belive a lookbehind would be a solution. However, it seems to me like this is not suppoerted in XText.

you can try something like the following (+ a validation for the very last comma)
Model:
((classes+=ClassWithBraces|classes+=ClassWithComma)* classes+=ClassAtEnd?);
ClassWithComma returns Class:
name=ID ","
;
ClassWithBraces returns Class:
name=ID =>("{" ((classes+=ClassWithBraces|classes+=ClassWithComma)* classes+=ClassAtEnd?) "}") ","?
;
ClassAtEnd returns Class:
name=ID
;

Related

Assign single element to an IntArray value attribute in Kotlin annotations

I have a custom annotation declared as
#Target(AnnotationTarget.FUNCTION)
annotation class Anno(val value: IntArray, val attr2: Int = 0)
For a single element declaration, I'm able to use the above annotation in a Java class as
#Anno(1)
but while writing the same in a Kotlin class, I have to put enclosing brackets
#Anno([1])
Aren't the brackets unnecessary in this case or am I declaring the annotation wrong? I am using Kotlin version 1.2.0-rc-39
Yes, square brackets (Kotlin 1.2+) or arrayOf (Kotlin 1.2-) are required.
But as long as this is your annotation, written in Kotlin, you can do fancy things with it, like taking lambdas or varargs, so you can try to tune the resulting syntax for your need. For example, this will be valid syntax, even in Kotlin 1.2-:
#Target(AnnotationTarget.FUNCTION)
annotation class Anno(
val attribute: String,
vararg val value: Int
)
#Anno("test", 1, 2, 3)
fun test() = 42
You'll need to put vararg parameter at the end.

Underscore in method names

Hello fellow Scalaists,
I recently took another look at setters in Scala and found out that _ in a method name seems to translate to "There might be a space or not and oh also treat the next special character as part of the method name".
So first of all, is this correct?
Secondly, can someone please explain why the second to last line doesnt work?
class Person() {
private var _name: String = "Hans"
def name = _name
def name_=(aName: String) = _name = aName.toUpperCase
}
val myP = new Person()
myP.name = "test"
myP.name= "test"
myP.name_= "test" //Bad doesnt work
myP.name_=("test")//Now It works
Lastly, removing the getter breaks the above example
class Person() {
private var _name: String = "Hans"
def name_=(aName: String) = _name = aName.toUpperCase
}
val myP = new Person()
myP.name = "test" //Doesnt work anymore
myP.name= "test" //Doesnt work anymore
myP.name_= "test" //Still doesnt work
myP.name_=("test")//Still works
Edit:
Here is a quote(seemingly false) from the source which I originally read, and which spawned this question:
This line is a bit more tricky but I'll explain. First, the method
name is "age_=". The underscore is a special character in Scala and in
this case, allows for a space in the method name which essentially
makes the name "age ="
http://dustinmartin.net/getters-and-setters-in-scala/
So first of all, is this correct?
No, underscores in method names do not work exactly like what you described. It doesn't mean "there might be a space and the character after the space is also part of the method name".
Section 4.2 of the Scala Language Specification explains what a method that has a name that ends with _= means.
A variable declaration var x: T is equivalent to the declarations of both a getter function x and a setter function x_=:
def x: T
def x_= (y: T): Unit
An implementation of a class may define a declared variable using a variable definition, or by defining the corresponding setter and getter methods.
Note that if you only define the setter method and not the getter method, then the magic of the setter method disappears - it's treated as just another method that has a name that happens to end with _=, but this has no special meaning in this case.
Only if there are a getter and setter, the method with _= acts as the setter and can be used as such - that's why myP.name = "test" doesn't work anymore if you remove the getter.
The rules are given in http://www.scala-lang.org/files/archive/spec/2.11/01-lexical-syntax.html#identifiers:
First, an identifier can start with a letter which can be followed by an arbitrary sequence of letters and digits. This may be followed by underscore _ characters and another string composed of either letters and digits or of operator characters.
So space isn't allowed after _. (It is actually allowed in identifiers between backquotes.) There are additional special rules for the case where the "string composed of either letters and digits or of operator characters" is precisely =, already described in Jesper's answer.
Secondly, can someone please explain why the second to last line doesnt work?
There are simply no special rules for this case. name_= works here as any other foo method would and you can't write myP.foo "test". But you can write myP foo "test" or myP name_= "test".

Scala - method call syntax

I am a beginning practitioner in Scala and I saw a few different syntax for calling a method. Some are nice, as ignoring parenthesis for a parameterless method, or ignoring the dot as in
1 to 10
but some really puzzle me. for instance:
breakable { ... }
this is simply a method call right? Can I also do that for more than one parameter or a parameter which is not a parameterless function?
Thanks
There are two standard ways of calling methods:
obj.method(params) // dot notation
obj method (params) // operator notation
The above can be modified in the following ways:
If params is a single parameter, you can replace () with {}.
If params is a single parameter and you are using operator notation, you can drop the parenthesis.
If method doesn't take parameters, you can drop (params) (that is, drop the empty ()).
If method ends with :, then it actually binds to the right in operator notation. That is, (params) method_: obj is equivalent to obj.method_:(params).
Either way, spaces are optional as long as identifiers can be told apart. So one can add spaces to the dot notation, like obj . method ( params ) or write .method(params) on the next line -- as often happens with call chaining --, as well as remove spaces from the operator notation, as in a+b.
There's also some stuff with tuple inference, but I try to avoid it, so I'm not sure of the exact rules.
None of these will explain the example you are confused about, however. Before I explain it, however, I'd like to show some syntactic sugars that can also be used to call methods:
obj(params) // equivalent to obj.apply(params)
obj.x = y // equivalent to obj.x_=(y), if obj.x also exists
obj(x) = y // equivalent to obj.update(x, y)
obj op= y // equivalent to obj = obj op y, if op is symbolic
~obj // equivalent to obj.unary_~; also for !, + and -, but no other symbol
Ok, now to the example you gave. One can import members of stable values. Java can do it for static methods with its static import, but Scala has a more general mechanism: importing from packages, objects or common instances is no different: it brings both type members and value members. Methods fall in the latter category.
So, imagine you have val a = 2, and you do import a._. That will bring into scope all of Int methods, so you can call them directly. You can't do +(2), because that would be interpreted as a call to unary_+, but you could call *(4), for example:
scala> val a = 2
a: Int = 2
scala> import a._
import a._
scala> *(4)
res16: Int = 8
Now, here's the rule. You can call
method(params)
If:
method was imported into scope.
You keep the parenthesis (even if there's only one parameter)
Note that there's a precedence issue as well. If you write obj method(params), Scala will presume method belongs to obj, even if it was imported into scope.
If we desugar this we will have:
breakable({ ... })
this matches signature
breakable: (op: ⇒ Unit): Unit
and uses so named call-by-name arguments (you may think of this as pass a block of code as argument)
More over scala allows you to write this:
scala> def foo (op1: => Unit)(op2: => Unit) = {op1;op2;}
foo: (op1: => Unit)(op2: => Unit)Unit
scala> foo { println(1) } { println(2) }
1
2
Above is the example of curried function

Scala DSL: method chaining with parameterless methods

i am creating a small scala DSL and running into the following problem to which i dont really have a solution. A small conceptual example of what i want to achieve:
(Compute
write "hello"
read 'name
calc()
calc()
write "hello" + 'name
)
the code defining this dsl is roughly this:
Object Compute extends Compute{
...
implicit def str2Message:Message = ...
}
class Compute{
def write(msg:Message):Compute = ...
def read(s:Symbol):Compute = ...
def calc():Compute = { ... }
}
Now the question: how can i get rid of these parenthesis after calc? is it possible? if so, how? just omitting them in the definition does not help because of compilation errors.
ok, i think, i found an acceptable solution... i now achieved this possible syntax
| write "hello"
| read 'name
| calc
| calc
| write "hello " + 'name
using an object named "|", i am able to write nearly the dsl i wanted. normaly, a ";" is needed after calc if its parameterless. The trick here is to accept the DSL-object itself (here, its the "|" on the next line). making this parameter implicit also allows calc as a last statement in this code.
well, looks like it is definitly not possible to have it the way i want, but this is ok too
It's not possible to get rid of the parenthesis, but you can replace it. For example:
object it
class Compute {
def calc(x: it.type):Compute = { ... }
(Compute
write "hello"
read 'name
calc it
calc it
write "hello" + 'name
)
To expand a bit, whenever Scala sees something like this:
object method
non-reserved-word
It assumes it means object.method(non-reserved-word). Conversely, whenever it sees something like this:
object method object
method2 object2
It assumes these are two independent statements, as in object.method(object); method2.object, expecting method2 to be a new object, and object2 a method.
These assumptions are part of Scala grammar: it is meant to be this way on purpose.
First try to remove the parentheses from the definition of calc. Second try to use curly braces around the whole instead of parentheses. Curly braces and parentheses doesn't mean the same and I find that parenthesis works best in single line code (unless using semi-colons). See also What is the formal difference in Scala between braces and parentheses, and when should they be used?

Groovy 'def' keyword and scope problem in Eclipse

I'm following a groovy tutorial and there is a code like this:
def fruit = ["apple", "orange" , "pear"] //list
def likeIt = { String fruit -> println "I like " + fruit + "s" } //closure
fruit.each(likeIt)
Eclipse reports an error at closure definition line:
Line breakpoint:SimpleClosuresTest
[line: 27] The current scope already
contains a variable of the name fruit
# line 27, column 14.
If i omit 'def' from 'def fruit' Eclipse doesn't complaint and code runs fine.
Could someone explain what is going on with the scopes in both cases?
Thanks.
first a general review of a groovy script:
// file: SomeScript.groovy
x = 1
def x = 2
println x
println this.x
is roughly compiled as:
class SomeScript extends groovy.lang.Script {
def x
def run() {
x = 1
def x = 2
println x // 2
println this.x // 1
}
}
in a groovy script (roughly speaking, a file without the class declaration), assigning a value to an undefined variable is interpreted as a field assignment.
your example tries to defines a closure with a parameter named fruit.
if you defined fruit with the def keyword you get an error message because the name is already taken as a local variable, and you can't duplicate a local variable name.
when you leave the def keyword out, you are actually assigning the value to a field of the class generated for the script, and thus the name fruit can be redefined as a local variable.
regarding scopes, it's pretty much like java...
in the example, you can see x is defined first as a field and then as a variable local to the run() method. there's nothing wrong with that and you can access both the variable and the field.
but once you define a local variable, you cannot create duplicates.
edit --
had to add this before anyone gets me wrong: the translation is not exactly like this (thus the "roughly"). Instead of a field you add a value to the binding of the script, quite like args for commandline scripts or request, session or response for groovlets.
but that is much a longer story...
ok if you really want to know just ask again and i'll explain it better
edit 2 --
i just can't leave it like this, if you ever need more info...
every groovy script has a field named binding, an instance of groovy.lang.Binding or one of its a subclasses.
this binding is basically a map, with methods setVariable and setVariable.
when you omit the def keyword when assigning a value in a script you are actually calling the method setVariable, and when you do something like this.x you are calling the getVariable method.
this is actually because class groovy.lang.Script overrides the methods getProperty and setProperty to call those methods first. that's the reason they behave like fields.
you might have also noticed that there is no type associated to those variables... that's because we are dealing with just a Map inside the binding.
standard groovy scrips are created with an instance of a binding with the args set to the array of parameters.
others, like groovy.servlet.ServletBinding define more variables and behavior, like block the assignment of certain variables, or adding a lazy initialization capabilities...
then the real reason behind the error is... if the def keyword is not used, fruits is not a real variable. still, i believe the behavior is somewhat analog to a field.
sorry about all that.
i was not satisfied with my own oversimplification :S
That String fruit shouldn't be having the same name as your def fruit. (you are defining first a list and then a string with the same name)
def likeIt = { String fruit -> println "I like " + fruit + "s" }
In the second case you are defining the type of the variable with def a posteriori, so it works but it is not a good practice as far as I know.
I think that you don't even need to write ->. The groovy manual says that "The -> token is optional and may be omitted if your Closure definition takes fewer than two parameters", which is the case here.
Second line
String fruit
the same variable name 'fruit' is being used again