960 likes | 1.13k Views
Embedding DSLs in Newspeak: NewShell, EBNF and Hopscotch. Gilad Bracha Ministry of Truth. Three DSLs. Shell Scripting Parsing UI. Newspeak Syntax for Java Programmers. Newspeak Syntax for Java Programmers. Newspeak Syntax for C# Programmers. Syntax: Unary Expressions. x foo means
E N D
Embedding DSLs in Newspeak:NewShell, EBNF and Hopscotch Gilad Bracha Ministry of Truth
Three DSLs • Shell Scripting • Parsing • UI
Syntax: Unary Expressions x foo means x.foo()
Syntax: Unary Expressions x foo means x.foo()
Binary Expressions 6 + 3 factorial evaluates to 12. In javanese, we’d write 6.+(3.factorial()) or, really 6.plus(3.factorial())
Keyword Expressions Windows version: 7 + 0i . is equivalent to all these: Windows version: (7 + 0i). Windows version: (7 + (0 i)). Windows.version(7 + 0.i()) ;
Keyword Expressions add: 1 to: Cobol in javanese would be add(1, Cobol); Big advantage - no arity errors
Three DSLs • Shell Scripting • Parsing • UI
NewShell class NewShell = ( ls value: ‘-l’. ls - ‘lt’. echo value: ‘Hello World’. svn value: ‘ls’ value: ‘svn://myDir’. (ls value findTokens: {Character cr}) collect: ls. )()
Three DSLs • Shell Scripting • Parsing • UI
Parser Combinators BNF id = letter (letter | digit) *
Parser Combinators BNF id = letter (letter | digit) * Newspeak id = letter, (letter | digit) star.
Parser Combinators BNF id = letter (letter | digit) * Newspeak id = letter, (letter | digit) star. Javanese id = letter().seq(letter().or(digit()).star());
How it Works id = letter, (letter | digit) star.
How it Works id = letter, (letter | digit) star.
How it Works id = letter, (letter | digit) star.
How it Works id = letter, (letter | digit) star.
How it Works id = letter, (letter | digit) star. letter
How it Works id = letter, (letter | digit) star. letter
How it Works id = letter, (letter | digit) star. letter
How it Works id = letter, (letter | digit) star. letter
How it Works id = letter, (letter | digit)star. letter
How it Works id = letter, (letter | digit) star. letter
How it Works id = letter, (letter | digit) star. letter letter
How it Works id = letter, (letter| digit) star. letter letter
How it Works id = letter, (letter | digit) star. letter letter digit
How it Works id = letter, (letter | digit) star. letter | letter digit
How it Works id = letter, (letter | digit) star. letter star | letter digit
How it Works , id = letter, (letter | digit) star. letter star | letter digit
Why is this Pretty? id = letter, (letter | digit) star.
Why is this Ugly? id = letter().seq(letter().or(digit()).star());
Why is this Ugly? id = letter().seq(letter().or(digit()).star()); vs. id = letter (letter | digit) * vs. id = letter, (letter | digit) star.
Why is this Ugly? id = letter().seq(letter().or(digit()).star()); vs. id = letter (letter | digit) * vs. id = letter, (letter | digit) star.
Why is it Ugly? A programming language is low level when its programs require attention to the irrelevant - Alan Perlis
A Complete Grammar class ExampleGrammar1 = ExecutableGrammar ( | digit = charBetween: ‘0’ and: ‘9’. letter = (charBetween: ‘a’ and:’z’) | (charBetween: ‘A’ and:’Z’). id = letter, (letter | digit) star. identifier = tokenFor: id. hat = tokenFromChar: ‘ˆ’. expression = identifier. returnStatement = hat, expression. | )()
Building an AST returnStatement = hat, expression wrapper:[:r : e | ReturnStatAST on: e ]
Building an AST returnStatement = hat, expression wrapper:[:r : e | ReturnStatAST on: e ] ^ wrapper: , expression
Grammar returnStatement = hat, expression wrapper:[:r : e | ReturnStatAST on: e ]
Semantic Action returnStatement = hat, expression wrapper:[:r : e | ReturnStatAST on: e ]
Factor out Grammar Superclass (pure grammar specification): returnStatement = hat, expression Subclass (AST builder): returnStatement = ( super returnStatement wrapper:[:r : e | ReturnStatAST on: e] )
Modular Parser class ExampleParser1= ExampleGrammar1 () ( id = ( ˆsuper id wrapper:[:fst :snd | fst asString, (String withAll: snd)] ) identifier = ( ˆsuper identifier wrapper:[:v | VariableAST new name: v token; start: v start; end: v end]. ) r
Modular Parser … returnStatement = ( ˆsuper returnStatement wrapper:[:r :e | ReturnStatAST new expr:e; start: r start; end: e end]. ) )
Extending a Grammar class ExampleGrammar2 = ExampleGrammar1 ( | if = tokenFromSymbol:#if. then = tokenFromSymbol:#then. else = tokenFromSymbol:#else. ifStatement = if, expression, then, statement, else, statement. statement = ifStatement | returnStatement. | )()
Mutual Recursion returnStat IfStmt if then else | stmt
Mutual Recursion digit nil letter nil nil id identifier nil hat nil expression nil returnStatement nil if nil then nil else nil ifStatement nil statement nil
Mutual Recursion digit a parser letter nil nil id identifier nil hat nil expression nil returnStatement nil if nil then nil else nil ifStatement nil statement nil
Mutual Recursion digit a parser letter a parser nil id identifier nil hat nil expression nil returnStatement nil if nil then nil else nil ifStatement nil statement nil