Formatting Expressions [message #1756122] |
Sun, 12 March 2017 09:30 |
Yves LEDUC Messages: 56 Registered: May 2015 |
Member |
|
|
Deciding to format my DSL is a problem. The API is complex and not easy to understand how it works and how to use it,
Especially for a non-specialist like me DSL and Java (my specialty is embedded computing in general in C).
My current problem is the formatting of the expressions of which here is the grammar (largely inspired by DSL LUA):
/* ****************************************************************************
* EXPRESSIONs
* ****************************************************************************
*/
// Chainage des expressions pour définir les priotités des opérateurs
Expression hidden (WS, SL_COMMENT, ML_COMMENT):
ExpressionOr;
// Or: left associative, priority 0
ExpressionOr returns Expression:
ExpressionAnd ('OU' {Expression_Or.left=current} right=ExpressionAnd)*;
// And: left associative, priority 1
ExpressionAnd returns Expression:
ExpressionCompare ('ET' {Expression_And.left=current} right=ExpressionCompare)*;
// Comparisons: left associative, priority 2
ExpressionCompare returns Expression:
ExpressionConcatenation (
('>' {Expression_Larger.left=current} right=ExpressionConcatenation) |
('>=' {Expression_Larger_Equal.left=current} right=ExpressionConcatenation) |
('<' {Expression_Smaller.left=current} right=ExpressionConcatenation) |
('<=' {Expression_Smaller_Equal.left=current} right=ExpressionConcatenation) |
('==' {Expression_Equal.left=current} right=ExpressionConcatenation) |
('~=' {Expression_Not_Equal.left=current} right=ExpressionConcatenation)
)*;
// Concatenation: right associative, priority 3
ExpressionConcatenation returns Expression:
ExpressionPlusMinus ('..' {Expression_Concatenation.left=current} right=ExpressionConcatenation)?;
// addition/subtraction: left associative, priority 4
ExpressionPlusMinus returns Expression:
ExpressionMultiplicationDivisionModulo
(
=>( ('+' {Expression_Plus.left=current} right=ExpressionMultiplicationDivisionModulo) |
('-' {Expression_Minus.left=current} right=ExpressionMultiplicationDivisionModulo) )
)*
;
// multiplication/division, left associative, priority 5
ExpressionMultiplicationDivisionModulo returns Expression:
ExpressionUnary (
('*' {Expression_Multiplication.left=current} right=ExpressionUnary) |
('/' {Expression_Division.left=current} right=ExpressionUnary) |
('%' {Expression_Modulo.left=current} right=ExpressionUnary)
)*;
// Unary operators: right associative, priority 6
ExpressionUnary returns Expression:
ExpressionExponentiation |
('NON' {Expression_Negate} exp=ExpressionUnary) |
// ('#' {Expression_Length} exp=ExpressionUnary) | // Définit une couleur dans lua ou gaml
('-' {Expression_Invert} exp=ExpressionUnary);
// exponentiation: right associative, priority 7
ExpressionExponentiation returns Expression:
ExpressionTerminal
( '^' {Expression_Exponentiation.left=current} right=ExpressionExponentiation )?;
ExpressionTerminal returns Expression :
('(' Expression ')')
| ExpressionLiteral // Un litéral: Value : INT | FLOAT | BOOL | CHAR | STRING
| ExpressionDataOrCall // Une variable, constante, paramètre (simple, tableau, structure, membre ) ou une fonction
;
ExpressionLiteral returns Expression:
LiteralNumber
| LiteralBoolean
| LiteralHex
| LiteralBin
| LiteralString
| LiteralChar
| LiteralExit
| LiteralFileType
| LiteralFileMode
| LiteralFilePorts
// | LiteralNull
;
ExpressionDataOrCall:
ref=DataRef // ExpressionData: Litéraux, Constantes, Variables, Tableaux, Structures
| call=Call
;
Call:
(ref=ModuleRef args=CallArgs) // Appel d'un module avec passage d'arguments
| (lib=LibraryName args=CallArgs) // Appel d'un élément de la librairie avec passage d'arguments
;
I would especially like to frame all the operators with a space.
I have already done this for my statements but because of the priority, the structure is more complex and I can not.
Example:
Abs (varInt + 123-CTE_INT * 2/3)
Should give me
Abs (varInt + 123 - CTE_INT * 2/3)
Same for boolean data and the ET, OU, NON, ...
Thank you in advance for your assistance.
The following code does not work :
def dispatch void format(Expression expr, extension IFormattableDocument document) {
// var ops = newArrayList(":","<-","+","-","*","/","ET","OU")
switch ( expr ) {
Expression_Invert :
expr.exp.prepend[oneSpace]
Expression_Plus : {
expr.right.prepend[oneSpace]
expr.left.append[oneSpace]
}
Expression_Minus : {
expr.right.prepend[oneSpace]
expr.left.append[oneSpace]
}
Expression_Multiplication : {
expr.right.prepend[oneSpace] // OK
expr.left.append[oneSpace] // NOK
}
Expression_Division : {
expr.right.prepend[oneSpace]
expr.left.append[oneSpace]
}
Expression_Negate : {
expr.exp.prepend[oneSpace]
expr.exp.append[oneSpace] // OK
}
Expression_And : {
expr.right.prepend[oneSpace]
expr.left.append[oneSpace]
}
ExpressionDataOrCall: {
if ( expr.call == null){
println("DataOrCall name: " + expr.ref.ref.name)
expr.call.prepend[oneSpace]
expr.call.append[oneSpace]
}
else if ( expr.call.lib == null)
println("DataOrCall call: " + expr.call.ref.ref.name)
else
println("DataOrCall lib: " + expr.call.lib.name)
}
}
}
}
Only spaces after the '-' and 'NO' operators are added. Why?
Yves LEDUC
|
|
|
|
|
Re: Formatting Expressions [message #1756127 is a reply to message #1756125] |
Sun, 12 March 2017 15:31 |
|
well this is not helpful since your example model does not work since it is incomplete as well.
and you dont go into all branches in your formatter as well.
and it is the opposite of small.
then i cannot find any recusions in your code.
Expression_Multiplication : {
expr.right.prepend[oneSpace] // OK
expr.left.append[oneSpace] // NOK
expr.left.format
expr.right.format
}
you can reproduce the problem with this very very simply grammar
Model:
(elements+=Element ";")*;
Element returns Expression:
NumberLiteral
('*' {Element.left=current} right=NumberLiteral)*;
NumberLiteral:
value=INT;
i can reproduce the problem with this one as well
obviously it has to do with the left recursion
and it seems to be a bug imho => can you file a ticket at eclipse/xtext-core on github
as a workaround you may try something like
def dispatch void format(Element element, extension IFormattableDocument document) {
element.allRegionsFor.keywords("*").forEach [
surround[oneSpace]
]
element.right.format;
element.left.format;
}
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Day Job: https://www.everest-systems.com
|
|
|
|
Powered by
FUDForum. Page generated in 0.03452 seconds