providing rapid feedback in generated modular language
play

Providing Rapid Feedback in Generated Modular Language Environments - PowerPoint PPT Presentation

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


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

  2. Domain-Specific Languages • Encapsulate domain knowledge • Eliminate boilerplate code • Domain-specific analysis / verification / optimization

  3. Integration and Composition of DSLs Data Access Data Workflow UI Actions models control validation HQL (www.webdsl.org)

  4. DSLs without IDE support are a nonstarter! Markus Voelter [Practical Product Lines 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

  6. Code Folding Outline Brace matching HQL Semantic errors References

  7. FOLDING/OUTLINE entity User { ... } entity BlogPost { poster : User REFERENCE body : String }

  8. What about incorrect and incomplete programs? entity User { NORMAL PARSING name : String password : String homepage } entity BlogPost { poster : User body : String } }

  9. What about incorrect and incomplete programs? entity User { name : String password : String NORMAL PARSING homepage ERROR } Parse failure: entity BlogPost { No abstract syntax tree poster : User body : String } NEVER PARSED

  10. Mini-Demo Error Recovery in a data modeling language

  11. Parsing with SDF and SGLR • Language composition without shift/reduce conflicts • Ambiguities can be inspected • Declarative disambiguation

  12. Normal LR Parser x token token token token token Recovery: Backtracking, skip/insert tokens, etc. (S)GLR Parser x token x token token token token token x token Recovery: ?

  13. Do we really need to dive into this intimidating algorithm?

  14. Island Grammars [Van Deursen & Kuipers, 1999] • Parse only interesting bits ( Islands ) • Skip the remaining characters ( Water ) IDENTIFICATION DIVISION. PROGRAM-ID. EXAMPLE. PROCEDURE DIVISION. WATER CALL X. CALL X. YADA. YADA YADA. WATER CALL Y. CALL Y. Grammar-based “error recovery”!

  15. Island Grammars [Van Deursen & Kuipers, 1999] ~[\ \t\n]+ → WATER {avoid}

  16. Running Example: Java

  17. Error Recovery Recipe 1. Take the entire Java grammar 2. Add water 3. Mix it together

  18. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); ERROR } return; } public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; } }

  19. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; NORMAL PARSING public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); ERROR } return; } public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; } }

  20. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); ERROR } } NORMAL PARSING return; } public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; } }

  21. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); ERROR } } NORMAL PARSING return; UNEXPECTED KEYWORD } public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; } }

  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: New production: WATER → MethodDec {cons(“WATER”)} WATER → MethodDec {cons(“WATER”),recover}

  23. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } return; } WATER public TemperatureMonitor(Fridge fridge) { this .fridge = fridge; } } New production: New production: WATER → MethodDec {cons(“WATER”),recover} WATER → Stm {cons(“WATER”),recover}

  24. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); } WATER return ; } public TemperatureMonitor(Fridge fridge) { this .fridge = fridge; } } New production: WATER → Stm {cons(“WATER”),recover}

  25. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); LAYOUT } WATER PROBLEMATIC TOKEN return ; } public TemperatureMonitor(Fridge fridge) { this .fridge = fridge; } }

  26. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); LAYOUT } WATER PROBLEMATIC TOKEN return ; } public TemperatureMonitor(Fridge fridge) { this .fridge = fridge; } } New production: WATER → LAYOUT {cons(“WATER”),recover}

  27. Mixing Java with Water public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); LAYOUT } WATER return ; } public TemperatureMonitor(Fridge fridge) { this .fridge = fridge; } } New production: WATER → LAYOUT {cons(“WATER”),recover}

  28. Reflection: Water-based Recovery Rules • • Works with any existing grammar • Can only remove fragments

  29. Danger of Floods public class Fridge { public void startCooling() { cooling.commence(); // missing } public void onResetButtonPress() { log.message(“Reset button pressed”); power.reboot(); } }

  30. Danger of Floods public class Fridge { public void startCooling() { cooling.commence(); // missing } public void onResetButtonPress() { WATER log.message(“Reset button pressed”); power.reboot(); } } So why not parse methods with missing closing brackets?

  31. Productions for Missing Literals why not add rules like this: “if” “(” Expr Stm → Stm {cons(“If”), recover} and this, and this, and this: “if” Expr “)” Stm → Stm {cons(“If”), recover} “if” Expr Stm → Stm {cons(“If”), recover} “while” “(“ Expr Stm → Stm {cons(“While”), ...} ... not going to scale.

  32. Productions for Missing Literals “if” “(” Expr “)” Stm → Stm {cons(“If”)} what it means internally: IF BOPEN … BCLOSE … → … [\i][\f] → IF [\(] → BOPEN [\)] → BCLOSE so, we can write (using the literal instead of BCLOSE): → BCLOSE {recover} “)” → “}” {recover}

  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}

  34. Applying Insertion Rules public class Fridge { public void startCooling() { cooling.commence(); // missing } INSERT } public void onResetButtonPress() { log.message(“Reset button pressed”); power.reboot(); } } New production: → “}” {recover}

  35. Recovery Rules • • Water So who's gonna • write all those • Closing brackets (“}”) recovery rules? • • Opening brackets (“{”) • • Separators (“,”) We derive • them from the • Comments grammar! • • String literals

  36. Customization of Recovery Rules → “class” {reject} “[|” → “|[“ {recover} “|]” → “]|” {recover}

  37. Putting Things Together • Water y = f ( x + 1 ; • Insertion: “)” y = f ( x + 1 ) ; y = f ( x ) + 1 ; y = x ; y = f + 1 ; f ( x + 1 ) ; y = f ( 1 ) ; f ( 1 ) ; y = ( x ) + 1 ; y ( x + 1 ) ; y = ( x + 1 ) ; y ( x ) ; y = x + 1 ; y () ; y = f ; y ( 1 ) ; y = ( x ) ; y = 1 ; y = f ( ) ; ;

  38. Putting Things Together For recovery, parallel parsing does not scale...

  39. Putting Things Together Why not do backtracking for recovery?

  40. Recovery Using Backtracking public class TemperatureMonitor { private Fridge fridge; public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); ERROR } return; } public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; } }

  41. Recovery Using Backtracking public class TemperatureMonitor { private Fridge fridge; 1. NORMAL PARSING public void trigger(Temperature temp) { if (temp.greaterThan(MAX)) // missing { fridge.startCooling(); ERROR } return; } public TemperatureMonitor(Fridge fridge) { this.fridge = fridge; } }

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend