Esprima/Espree Examples
Esprima/Espree Examples
En el Repo ULL-ESIT-GRADOII-PL/esprima-pegjs-jsconfeu-talk encontrará el material de esta lección. Clone este repo.
The examples in this repo use a couple of JavaScript compiler frameworks: Esprima and Espree.
Espree started out as a fork of Esprima v1.2.2, the last stable published released of Esprima before work on ECMAScript 6 began. Espree is now built on top of Acorn, which has a modular architecture that allows extension of core functionality. The goal of Espree is to produce output that is similar to Esprima with a similar API so that it can be used in place of Esprima.
REPL example
Una vez clonado el repo ULL-ESIT-GRADOII-PL/esprima-pegjs-jsconfeu-talk, instalamos las dependencias:
➜ esprima-pegjs-jsconfeu-talk git:(master) npm i
y arrancamos el bucle REPL de Node.JS:
➜ esprima-pegjs-jsconfeu-talk git:(master) node
Welcome to Node.js v14.4.0.
Type ".help" for more information.
Cargamos espree
:
> const espree = require('espree')
undefined
> espree.version
'7.3.1'
> espree.latestEcmaVersion
12
> espree.supportedEcmaVersions
[
3, 5, 6, 7, 8,
9, 10, 11, 12
]
Navegar en el árbol AST es complicado. El atributo espree.visitorKeys
nos proporciona la lista de nodos y los nombres de los atributos de sus hijos
Hagamos un análisis léxico:
> espree.tokenize('answer = /* comment*/ 42', { range: true })
[
Token {
type: 'Identifier',
value: 'answer',
start: 0,
end: 6,
range: [ 0, 6 ]
},
Token {
type: 'Punctuator',
value: '=',
start: 7,
end: 8,
range: [ 7, 8 ]
},
Token {
type: 'Numeric',
value: '42',
start: 22,
end: 24,
range: [ 22, 24 ]
}
]
Hagamos ahora un análisis sintáctico:
> espree.parse('const answer = 42', { tokens: true })
Uncaught [SyntaxError: The keyword 'const' is reserved
] {
index: 0,
lineNumber: 1,
column: 1
}
La versión ECMA de JS usada por defecto por espree
es la 5 y esta no admite const
Especifiquemos la versión ECMA que queremos:
> espree.parse('const answer = 42',
{ ecmaVersion: espree.latestEcmaVersion,
tokens: true }
)
Node {
type: 'Program',
start: 0,
end: 17,
body: [
Node {
type: 'VariableDeclaration',
start: 0,
end: 17,
declarations: [Array],
kind: 'const'
}
],
sourceType: 'script',
tokens: [
Token { type: 'Keyword', value: 'const', start: 0, end: 5 },
Token { type: 'Identifier', value: 'answer', start: 6, end: 12 },
Token { type: 'Punctuator', value: '=', start: 13, end: 14 },
Token { type: 'Numeric', value: '42', start: 15, end: 17 }
]
}
Observe que el Árbol no aparece completo. El log que usa el bucle REPL de Node lo trunca en el hijo declarations
(sólo nos muestra que es un array [Array]
sin expandirlo) para que la salida no sea excesivamente larga.
Para que nos muestre el árbol vamos a usar el método util.inspect
del módulo util
que convierte un objeto en una string:
> const util = require('util')
undefined
> console.log(
util.inspect(
espree.parse('const answer = 42',{ecmaVersion: 6}),
{depth: null}
)
)
Node {
type: 'Program',
start: 0,
end: 17,
body: [
Node {
type: 'VariableDeclaration',
start: 0,
end: 17,
declarations: [
Node {
type: 'VariableDeclarator',
start: 6,
end: 17,
id: Node {
type: 'Identifier',
start: 6,
end: 12,
name: 'answer'
},
init: Node {
type: 'Literal',
start: 15,
end: 17,
value: 42,
raw: '42'
}
}
],
kind: 'const'
}
],
sourceType: 'script'
}
undefined
Usando la herramienta web https://astexplorer.net podemos navegar el AST producido por varios compiladores JS:
Example: Searching for Specific Identifiers
The file idgrep.js is a very simple example of using Esprima to do static analysis on JavaScript code.
It provides a function idgrep
that finds the appearances of identifiers matching a search string inside the input code.
Given an input like this:
➜ esprima-pegjs-jsconfeu-talk git:(master) cat hacky.js
// This is a hack!
const hacky = () => {
let hack = 3;
return 'hacky string';
}
if we search for hack
it produces:
➜ esprima-pegjs-jsconfeu-talk git:(master) ./idgrep.js hacky.js
1:6: const hacky = () => {
2:8: let hack = 3;
Observe how the appearances of hack
inside the comment or the string aren’t shown
Práctica Espree Logging
ASTExplorer
Master the Art of the AST
Syntax Analysis: PEG.js Example
altjs.js is the code for the “AltJS language in 5 minutes” section presented in the second half of the talk Parsing, Compiling, and Static Metaprogramming by Patrick Dubroy