28
Creating own language made easy Ingvar Stepanyan @RReverser

Creating own language made easy

Embed Size (px)

DESCRIPTION

Slides from my talk from #jQueryBulgaria 2013

Citation preview

Page 1: Creating own language made easy

Creating own language made easy

Ingvar Stepanyan

@RReverser

Page 2: Creating own language made easy

Everything sucks

Page 3: Creating own language made easy

Everything sucks – human version

Page 4: Creating own language made easy

Everything sucks – developer version

Page 5: Creating own language made easy

Scary magic

?

?????

Page 6: Creating own language made easy
Page 7: Creating own language made easy

Not so scary magic

JS

JS

JS

ParserGenerator

Page 8: Creating own language made easy

Parsers

Page 9: Creating own language made easy

Parser generators

jison Bison in javascript, used by Coffeescript PEG.js parser generator for JavaScript based on the parsing expression grammar formalism OMeta/JS (source) metacompiler for many languages to many targets, including js.

languagejs - PEG parser written in JavaScript with first class errors Canopy Self-hosting PEG parser compiler for JavaScript, influenced by Ruby parser generators such as Treetop and Citrus JS/CC LALR(1) parser generator

jsparse PEG by Grandmaster Chris Double ReParse parser combinator library for Javascript like Haskell's Parsec p4js Monadic parser library for JavaScript JSGLR Scannerless, Generalized Left-to-right Rightmost (SGLR) derivation parser for JavaScript

antlr has a javascript target Cruiser.Parse LL(k) parser

Page 10: Creating own language made easy

Parser generators

Bottom-up (PEG.js)start = additive

additive = left:multiplicative "+" right:additive { return left + right; } / multiplicative

multiplicative = left:primary "*" right:multiplicative { return left * right; } / primary

primary = integer / "(" additive:additive ")" { return additive; }

integer "integer" = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

Top-down (Jison)%left "+"%left "*"

%start program;

%%

program : expression { return $$ } ;

expression : expression "+" expression -> $1 + $3 | expression "*" expression -> $1 * $3 | "(" expression ")" -> $2 | NUMBER -> $1 ;

Page 11: Creating own language made easy

Choice ordering

Bottom-up (PEG.js)start = additive

additive = left:multiplicative "+" right:additive { return left + right; } / multiplicative

multiplicative = left:primary "*" right:multiplicative { return left * right; } / primary

primary = integer / "(" additive:additive ")" { return additive; }

integer "integer" = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

Top-down (Jison)%left "+"%left "*"

%start program;

%%

program : expression { return $$ } ;

expression : expression "+" expression -> $1 + $3 | expression "*" expression -> $1 * $3 | "(" expression ")" -> $2 | NUMBER -> $1 ;

Page 12: Creating own language made easy

Ambiguity

Bottom-up (PEG.js)start = additive

additive = left:multiplicative "+" right:additive { return left + right; } / multiplicative

multiplicative = left:primary "*" right:multiplicative { return left * right; } / primary

primary = integer / "(" additive:additive ")" { return additive; }

integer "integer" = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

Top-down (Jison)%left "+"%left "*"

%start program;

%%

program : expression { return $$ } ;

expression : expression "+" expression -> $1 + $3 | expression "*" expression -> $1 * $3 | "(" expression ")" -> $2 | NUMBER -> $1 ;

if a then (if b then s) else s2 orif a then (if b then s else s2)

if a then if b then s else s2:

Page 13: Creating own language made easy

Left recursion

Bottom-up (PEG.js)start = additive

additive = left:multiplicative "+" right:additive { return left + right; } / multiplicative

multiplicative = left:primary "*" right:multiplicative { return left * right; } / primary

primary = integer / "(" additive:additive ")" { return additive; }

integer "integer" = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

Top-down (Jison)%left "+"%left "*"

%start program;

%%

program : expression { return $$ } ;

expression : expression "+" expression -> $1 + $3 | expression "*" expression -> $1 * $3 | "(" expression ")" -> $2 | NUMBER -> $1 ;

x = 1 - 2 - 3

Page 14: Creating own language made easy

Left recursion

Bottom-up (PEG.js)[ "x", "=", [ "1", "-", [ "2", "-", "3" ] ]]

Top-down (Jison)[ "x", "=", [ [ "1", "-", "2" ], "-", "3" ]]

x = 1 - 2 - 3

Page 15: Creating own language made easy

Summary choice

Bottom-up (PEG.js)start = additive

additive = left:multiplicative "+" right:additive { return left + right; } / multiplicative

multiplicative = left:primary "*" right:multiplicative { return left * right; } / primary

primary = integer / "(" additive:additive ")" { return additive; }

integer "integer" = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

Top-down (Jison)%left "+"%left "*"

%start program;

%%

program : expression { return $$ } ;

expression : expression "+" expression -> $1 + $3 | expression "*" expression -> $1 * $3 | "(" expression ")" -> $2 | NUMBER -> $1 ;

Page 16: Creating own language made easy

Jison syntax: helpers

%{

var scope = {};

%}

Page 17: Creating own language made easy

Jison syntax: lexer

%lex

%%

\s+ /* skip whitespace */

[A-Za-z_]\w+ return 'ID';

\d+ return ‘NUMBER’;

[+*;=] return yytext;

<<EOF>> return 'EOF';

/lex

Page 18: Creating own language made easy

Jison syntax: operator precedence

%left ';‘

%right ‘=‘

%left ‘+’

%left ‘*’

/*

“x=a*b+c”

-> assign(“x”, “a*b+c”)

-> assign(“x”, add(“a*b”, “c”))

-> assign(“x”, add(mul(“a”, “b”), “c”))

*/

Page 19: Creating own language made easy

Jison syntax: rules

%start program

program

: stmt* EOF { return $1 }

;

stmt

: expr ‘;’ -> $1

;

expr

: expression "+" expression -> $1 + $3

| expression "*" expression -> $1 * $3

| NUMBER -> $1

;

Page 20: Creating own language made easy

Code generation

Page 21: Creating own language made easy

Methods

string concatenation

building AST object + escodegen (http://github.com/Constellation/escodegen)

using SourceNode from source-map (https://github.com/mozilla/source-map)

Page 22: Creating own language made easy

Debugging: source maps

Page 23: Creating own language made easy

Methods

string concatenation

building AST object + escodegen (http://github.com/Constellation/escodegen)

using SourceNode from source-map (https://github.com/mozilla/source-map)

Page 24: Creating own language made easy

AST way

Page 25: Creating own language made easy

Methods

string concatenation

building AST object + escodegen (http://github.com/Constellation/escodegen)

using SourceNode from source-map (https://github.com/mozilla/source-map)

Page 26: Creating own language made easy

SourceNode

new SourceNode(line, column, filename, jsChunk)

line, column – position in original file

filename – name of original file

jsChunk – JavaScript code string, another SourceNode instance or array of those

Page 27: Creating own language made easy

Resulting stack

JS

JS

JS

Jisonsource-map

Page 28: Creating own language made easy

Live demo