50
Providing Rapid Feedback in Generated Modular Language Environments Lennart Kats (me) Maartje de Jonge Emma Nilsson-Nyman Eelco Visser Software Engineering Research Group OOPSLA 2009 October 29, 2009

Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

Embed Size (px)

DESCRIPTION

Integrated development environments (IDEs) increase programmer productivity, providing rapid, interactive feedback based on the syntax and semantics of a language. A heavy burden lies on developers of new languages to provide adequate IDE support. Code generation techniques provide a viable, efficient approach to semi-automatically produce IDE plugins. Key components for the realization of plugins are the language's grammar and parser. For embedded languages and language extensions, constituent IDE plugin modules and their grammars can be combined. Unlike conventional parsing algorithms, scannerless generalized-LR parsing supports the full set of context-free grammars, which is closed under composition, and hence can parse language embeddings and extensions composed from separate grammar modules. To apply this algorithm in an interactive environment, this paper introduces a novel error recovery mechanism, which allows it to be used with files with syntax errors -- common in interactive editing. Error recovery is vital for providing rapid feedback in case of syntax errors, as most IDE services depend on the parser -- from syntax highlighting to semantic analysis and cross-referencing. We base our approach on the principles of island grammars, and derive permissive grammars with error recovery productions from normal SDF grammars. To cope with the added complexity of these grammars, we adapt the parser to support backtracking. We evaluate the recovery quality and performance of our approach using a set of composed languages, based on Java and Stratego.

Citation preview

Page 1: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

Providing Rapid Feedback inGenerated Modular Language

Environments

Lennart Kats (me)Maartje de JongeEmma Nilsson-NymanEelco Visser

Software Engineering Research Group

OOPSLA 2009 October 29, 2009

Page 2: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

2

Domain-Specific Languages

• Encapsulate domain knowledge

• Eliminate boilerplate code

• Domain-specific analysis / verification / optimization

Page 3: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

3

UIData

models

Integration and Composition of DSLs

HQL

WorkflowAccesscontrol

Datavalidation

Actions

(www.webdsl.org)

Page 4: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

4Markus Voelter [Practical Product Lines 2009]

DSLs without IDE supportare a nonstarter!

Page 5: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

5

Spoofax/IMP:Efficient Editor Development

• Existing platform: Eclipse with IMP

• DSLs to define editor components

• Grammar and a parser generator: SDF, (J)SGLR

Page 6: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

6

Code Folding

Semantic errors

Outline

References

HQL                                                                                                             Brace matching

Page 7: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

7

                                                 FOLDING/OUTLINE

entity User { ...}

entity BlogPost { poster : User body : String}

    REFERENCE

Page 8: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

8

entity User { name : String password : String homepage}

entity BlogPost { poster : User body : String}

What aboutincorrect and incomplete programs?

                                                   NORMAL PARSING

}

Page 9: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

9

entity User { name : String password : String homepage}

entity BlogPost { poster : User body : String}

What aboutincorrect and incomplete programs?

                                                   NORMAL PARSING                                                                          ERROR

                                                           NEVER PARSED

Parse failure:No abstract syntax tree

Page 10: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

10

Mini-Demo

Error Recovery ina data modeling language

Page 11: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

11

Parsing with SDF and SGLR

• Language composition withoutshift/reduce conflicts

• Ambiguities can be inspected

• Declarative disambiguation

Page 12: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

12

token token token token token

token token token token token

token x

x

x

token x

Recovery:Backtracking,

skip/insert tokens, etc.

Normal LR Parser

(S)GLR Parser

Recovery: ?

Page 13: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

13

Do we really need to dive into thisintimidating algorithm?

Page 14: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

14

Island Grammars

IDENTIFICATION DIVISION.PROGRAM-ID. EXAMPLE.PROCEDURE DIVISION. CALL X. YADA. YADA YADA. CALL Y.

CALL X.

CALL Y.

                                                                                         WATER

                                                                                         WATER

• Parse only interesting bits (Islands)• Skip the remaining characters (Water)

 [Van Deursen & Kuipers, 1999]

Grammar-based“error recovery”!

Page 15: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

15

Island Grammars

~[\ \t\n]+ → WATER {avoid}

 [Van Deursen & Kuipers, 1999]

Page 16: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

16

Running Example: Java

Page 17: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

17

1. Take the entire Java grammar2. Add water3. Mix it together

Error Recovery Recipe

Page 18: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

18

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                  ERROR

Page 19: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

19

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                                                                        NORMAL PARSING

                  ERROR

Page 20: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

20

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

}                                                                          NORMAL PARSING                  ERROR

Page 21: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

21

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

}                                                                          NORMAL PARSING                  ERROR

                                                            UNEXPECTED KEYWORD

Page 22: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

22

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }} New production:

WATER → MethodDec {cons(“WATER”)}New production: WATER → MethodDec {cons(“WATER”),recover}

Page 23: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

23

New production: WATER → MethodDec {cons(“WATER”),recover}New production: WATER → Stm {cons(“WATER”),recover}

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                                                                                         WATER

Page 24: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

24

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }} New production:

WATER → Stm {cons(“WATER”),recover}

                                                                                    WATER

Page 25: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

25

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                                                                                    WATER                 LAYOUT

    PROBLEMATIC TOKEN

Page 26: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

26

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }} New production:

WATER → LAYOUT {cons(“WATER”),recover}

                                                                                    WATER                 LAYOUT

    PROBLEMATIC TOKEN

Page 27: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

27

Mixing Java with Water

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

     WATER

New production: WATER → LAYOUT {cons(“WATER”),recover}

                 LAYOUT

Page 28: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

28

Reflection:Water-based Recovery Rules

•• Works with any existing grammar

• Can only remove fragments

Page 29: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

29

Danger of Floods

public class Fridge { public void startCooling() { cooling.commence(); // missing }

public void onResetButtonPress() { log.message(“Reset button pressed”); power.reboot(); }}

Page 30: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

30

Danger of Floods

public class Fridge { public void startCooling() { cooling.commence(); // missing }

public void onResetButtonPress() { log.message(“Reset button pressed”); power.reboot(); }}

                                                                                            WATER

So why not parse methodswith missing closing brackets?

Page 31: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

31

“if” “(” Expr Stm → Stm {cons(“If”), recover}

Productions for Missing Literals

“if” Expr “)” Stm → Stm {cons(“If”), recover}“if” Expr Stm → Stm {cons(“If”), recover}“while” “(“ Expr Stm → Stm {cons(“While”), ...}...

and this, and this, and this:

why not add rules like this:

not going to scale.

Page 32: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

32

IF BOPEN … BCLOSE … → …[\i][\f] → IF[\(] → BOPEN[\)] → BCLOSE

Productions for Missing Literals

→ BCLOSE {recover} → “}” {recover}

“)”

so, we can write (using the literal instead of BCLOSE):

what it means internally:

“if” “(” Expr “)” Stm → Stm {cons(“If”)}

Page 33: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

33

Applying Insertion Rules

public class Fridge { public void startCooling() { cooling.commence(); // missing }

public void onResetButtonPress() { log.message(“Reset button pressed”); power.reboot(); }}

New production: → “}” {recover}

Page 34: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

34

Applying Insertion Rules

public class Fridge { public void startCooling() { cooling.commence(); // missing }

public void onResetButtonPress() { log.message(“Reset button pressed”); power.reboot(); }}

                                                                   INSERT }

New production: → “}” {recover}

Page 35: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

35

So who's gonnawrite all thoserecovery rules?

•• Water•• Closing brackets (“}”)•• Opening brackets (“{”)•• Separators (“,”)•• Comments•• String literals

Recovery Rules

We derivethem from the

grammar!

Page 36: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

36

Customization of Recovery Rules

→ “class” {reject}

“[|” → “|[“ {recover}

“|]” → “]|” {recover}

Page 37: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

37

Putting Things Together

y = f ( x   + 1   ;y = f ( x   + 1 ) ;y = f ( x ) + 1   ;y = f       + 1   ;y = f (       1 ) ;y =   ( x ) + 1   ;y =   ( x   + 1 ) ;y =     x   + 1   ;y = f             ;y =   ( x )       ;y = f ( )         ;

• Water• Insertion: “)”

y =     x         ;    f ( x   + 1 ) ;    f (       1 ) ;y     ( x   + 1 ) ;y     ( x )       ;y     ()          ;y     (       1 ) ;y =           1   ;                  ;

Page 38: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

38

Putting Things Together

For recovery, parallel parsing does not scale...

Page 39: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

39

Putting Things Together

Why not do backtracking for recovery?

Page 40: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

40

Recovery Using Backtracking

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                  ERROR

Page 41: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

41

Recovery Using Backtracking

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                                                                   1. NORMAL PARSING

                  ERROR

Page 42: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

42

Recovery Using Backtracking

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                                                                    1. NORMAL PARSING                  ERROR

                                                                  POINT OF DETECTION

Page 43: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

43

Recovery Using Backtracking

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                                                                       2. BACKTRACKING                                                                    1. NORMAL PARSING

Page 44: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

44

Recovery Using Backtracking

public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; }

public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; }}

                                                                                                                                                                                                                                                                   

1 RULE1 RULE

2 RULES

1 RULE2 RULES3 RULES

1 RULE2 RULES3 RULES4 RULES

{

Page 45: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

45

Evaluation

Implementation:• JSGLR• Spoofax/IMP (WebDSL, Stratego, PIL, ...)

Test grammars:• Java• Java-SQL• Stratego• Stratego-Java

Page 46: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

46

Evaluation

Measurements:

• qualitative [Penello & DeRemer '78]:excellent / good / poor

• tree alignment distance [Jian et al '94]

• textual 'diffs'

Page 47: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

47

Recovery Quality (Stratego-Java)

Page 48: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

48

Continued Work

“Natural and Flexible Error Recovery for Generated Parsers” [SLE 2009]

• indentation-based region selection• fall-back mechanism• bridge parsing [Nilsson-Nyman et al, 2008]

(www.strategoxt.org/Stratego/PermissiveGrammars)

Page 49: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

49

Continued Work

“Natural and Flexible Error Recovery for Generated Parsers” [SLE 2009]

• comparison with JDT• performance, quality• synergy between recovery techniques

(www.strategoxt.org/Stratego/PermissiveGrammars)

Page 50: Providing Rapid Feedback in Generated Modular Language Environments (OOPSLA 2009)

www.strategoxt.org/Stratego/PermissiveGrammarswww.strategoxt.org/Stratego/Spoofax­IMPwww.lennartkats.net

Software Engineering Research Group

Conclusion

SGLR/SDF• modular specifications• composable languages

Recovery production rules• transparent• flexible• language-independent