program = statement+
statement = expression | if_statement
if_statement = 'if' '(' expression ')' { statement+ }
expression = number (+ expression)*
Program based on our grammar
if (1) {
if (0) {
42 + 12 + 2
}
2 + 3
}
2 + 1
[
{
lexeme: 'if',
type: 'keyword',
position: {
line: 0,
char: 0
}
},
{
lexeme: '(',
type: 'open_bracket'
position: {
line: 0,
char: 3
}
},
{
lexeme: 1,
type: 'number',
position: {
line: 0,
char: 4
}
},
{
lexeme: ')',
type: 'close_bracket',
position: {
line: 0,
char: 5
}
},
...
]
AST (Abstract-Syntax Tree)
PROGRAM
/ \
if ...
/ \
cond body
| / \
1 if ...
/ \
cond body
| | \
0 +
/ \
42 +
/ \
12 2
class InterpretationVisitor {
execute ( ast ) {
ast . statements . forEach ( this . visitNode . bind ( this ) ) ;
}
visitNode ( node ) {
switch ( node . type ) {
case 'if_statement' :
return this . visitIfStatement ( node ) ;
break ;
case 'expression' :
return this . visitExpression ( node ) ;
break ;
default :
throw new Error ( 'Unrecognized node' ) ;
}
}
visitIfStatement ( node ) {
if ( this . visitNode ( node . condition ) ) {
node . statements . forEach ( this . visitNode . bind ( this ) ) ;
}
}
visitExpression ( node ) {
if ( node . operator ) {
return this . visitNode ( node . left ) + this . visitNode ( node . right ) ;
}
return node . value ;
}
}
@Directive ( {
selector : '[foo-bar]'
} )
class Foo { ...}
class DirectiveVisitor {
// ...
visitClassDeclaration ( node ) {
( node . decorator || [ ] ) . forEach ( this . visitDecorator . bind ( this ) ) ;
}
visitDecorator ( decorator ) {
//...
}
// ...
}