Skip to content

ULL-ESIT-PL-1819/p0-t0-esprima-logging-Alien-97

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Explicación código práctica esprima, fichero logging.js, se encuentra abajo

About

This repository contains code samples from the talks:

  1. Parsing, Compiling, and Static Metaprogramming at JSConfEU 2013 by Patrick Dubroy.
  2. Master the Art of the AST and Take Control of Your JS by Yonatan Mevorach.
  3. Talk on the same topic at Javascript Israel by Yonatan Mevorach

Talk Master the Art of the AST and Take Control of Your JS by Yonatan Mevorach

ASTExplorer

ESLint Piggyback example

Babel remove "debugger" example

jscodeshift example

Repositorios interesantes de cowchimp

Talk Parsing, Compiling, and Static Metaprogramming at JSConfEU 2013 by Patrick Dubroy.

Esprima Examples

  • checkstyle.coffee and logging.coffee contain the original source code for the style checker and logging examples presented in the talk.
  • checkstyle.js and logging.js are the slightly simplified JS versions that were shown in the talk.
  • syntax-highlight.js is taken from the Esprima tutorial Chapter 3. Lexical Analysis (Tokenization)¶

PEG.js Example

altjs.coffee is the code for the "AltJS language in 5 minutes" section presented in the second half of the talk.

Extra Special Bonus!

idgrep.coffee (and idgrep.js) is another example of using Esprima to do static analysis on JavaScript code.

REPL example

> esprima = require('esprima')
{ parse: [Function: parse],
  parseModule: [Function: parseModule],
  parseScript: [Function: parseScript],
  tokenize: [Function: tokenize],
  Syntax: 
   { ... },
  version: '4.0.1' }

> esprima.tokenize('answer = 42', { range: true })
[ { type: 'Identifier', value: 'answer', range: [ 0, 6 ] },
  { type: 'Punctuator', value: '=', range: [ 7, 8 ] },
  { type: 'Numeric', value: '42', range: [ 9, 11 ] } ]

> esprima.parseScript('const answer = 42', { tokens: true })
Script {
  type: 'Program',
  body: 
   [ VariableDeclaration {
       type: 'VariableDeclaration',
       declarations: [Array],
       kind: 'const' } ],
  sourceType: 'script',
  tokens: 
   [ { type: 'Keyword', value: 'const' },
     { type: 'Identifier', value: 'answer' },
     { type: 'Punctuator', value: '=' },
     { type: 'Numeric', value: '42' } ] }

> inspect = require('util')
{ ... }

> console.log(util.inspect(esprima.parseScript('answer = 42'), {depth: null}))
Script {
  type: 'Program',
  body: 
   [ ExpressionStatement {
       type: 'ExpressionStatement',
       expression: 
        AssignmentExpression {
          type: 'AssignmentExpression',
          operator: '=',
          left: Identifier { type: 'Identifier', name: 'answer' },
          right: Literal { type: 'Literal', value: 42, raw: '42' } } } ],
  sourceType: 'script' }
undefined
> 

Explicación código logging.js

  • Este fichero contiene el código para el análisis de una cadena que recibe como entrada, esta cadena consiste en una función no anónima que contiene llamadas a funciones anónimas, el código en Javascript identifica dichas funciones y las muestra por pantalla.
  • A continuación se explica el cometido de las funciones implementadas:

  • let escodegen = require('escodegen'); Herramienta que genera el output

  • let esprima = require('esprima'); Parseador, genera los tokens a partir del input, y a partir de estos construye el Abstract Syntax Tree (AST)

  • let estraverse = require('estraverse'); Herramienta para recorrer un Abstract Syntax Tree, un árbol de


addLogging(code)

  • Función que analiza el AST en busca de funciones anónimas y no anónimas function addLogging(code) {
    • let ast = esprima.parse(code); Parsea el código de entrada generando el Abstract Syntax Tree
    • estraverse.traverse(ast, { Se realiza el recorrido del árbol de sintaxis abstracto para clasificar los tokens, en este
      • enter: function(node, parent) { Funcion anónima, recibe como parámetros el nodo que se analiza actualmente y su nodo padre
        • if (node.type === 'FunctionDeclaration' || Se comprueba si el nodo contiene una función no anónima (FunctionDeclaration) o una función anónima (FuntionExpression), si se cumple cualquiera de los dos casos, se invoca el método addBeforeCode, que muestra por pantalla el tipo de función node.type === 'FunctionExpression') { addBeforeCode(node); } } });
    • return escodegen.generate(ast); //Genera el código a partir del análisis del AST }

addBeforeCode(node)

  • Función que agrega los comentarios al input function addBeforeCode(node) {

    • let name = node.id ? node.id.name : ''; El identificador del nodo o token indica su nombre, si la función no tiene nombre, es decir, su id está a NULL, eso significa que es anónima, de lo contrario, se considera no anónima.

    • let beforeCode = console.log('Entering ${name}()');; let es un tipo de variable que existe dentro del contexto léxico en el que se ha definido, en este caso, la función, se le podría llamar variable local, en este caso estamos mostrando el mensaje que indica si es una variable anónima o tiene un nombre, de acuerdo a lo especificado en la línea 153

    • let beforeNodes = esprima.parse(beforeCode).body; node.body.body = beforeNodes.concat(node.body.body); }

  • const input = function foo(a, b) { var x = 'blah'; var y = (function () { return 3; })(); } foo(1, 'wut', 3);;

  • const output = addLogging(input); El output es el resultado de la ejecución de addLogging, que a su vez invoca a addBeforeCode como hemos explicado

  • console.log(input:\n${input}\n---); // Se imprime por pantalla la cadena de entrada

  • console.log(output:\n${output}\n---);// Se imprime por pantalla la salida, que incluye las cadenas que indican el tipo de función.

About

p0-t0-esprima-logging-Alien-97 created by GitHub Classroom

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published