Procesadores de Lenguajes

3º. 2º cuatrimestre. Itinerario de Computación. Grado en Ingeniería Informática. ULL


Organization ULL-ESIT-PL-1920   Github Classroom ULL-ESIT-PL-1920   Campus Virtual PL   Chat Chat   Profesor Casiano

Table of Contents

Clase del Miércoles 04/03/2020

Promises

Promises chaining fetch (continuation)

Error handling with promises

[~/.../exception-inside-promise(master)]$ pwd -P
/Users/casiano/campus-virtual/1920/pl1920/apuntes/tema1-introduccion-a-javascript/event-loop/exercises/promises/exception-inside-promise

Exercises: Exceptions and Promises

Promise API

Práctica p2-t1-testing

Repo ULL-ESIT-GRADOII-PL/esprima-pegjs-jsconfeu-talk

En el Repo ULL-ESIT-GRADOII-PL/esprima-pegjs-jsconfeu-talk encontrará el material de varias charlas.

  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

Esprima/Espree Example: checkstyle.js

The problem to solve: to write a program that forces camelCase instead of snake_case for identifiers in JS. See the blog Case Styles: Camel, Pascal, Snake, and Kebab Case

See the AST for the example:

var foo = bar;
var this_is_bad = 3;
function blah() {
  return function x() {
    var oops_another_one;
  }
}

Solution:

[~/javascript-learning/esprima-pegjs-jsconfeu-talk(private)]$ cat checkstyle.js 
var _ = require('underscore');
var esprima = require('espree');
var estraverse = require('estraverse');

function checkStyle(code, filename) {
    var ast = esprima.parse(code, parseOptions);
    var errors = [];
    estraverse.traverse(ast, {
        enter: function(node, parent) {
            if (node.type === 'VariableDeclaration')
                checkVariableNames(node, errors);
        }
    });
    return formatErrors(code, errors, filename);
}

function checkVariableNames(node, errors) {
    _.each(node.declarations, function(decl) {
        if (decl.id.name.indexOf('_') >= 0) {
            return errors.push({
                location: decl.loc,
                message: 'Use camelCase for variable names, not hacker_style.'
            });
        }
    });
}

// Takes a list of errors found by `checkStyle`, and returns a list of
// human-readable error messages.
function formatErrors(code, errors, filename) {
    return _.map(errors, function(e) {
        var loc = e.location.start;
        var prefix = (typeof filename === "function" ?
                filename("" + filename + ":" + loc.line + ":" + loc.column) : void 0) ? void 0 :
            "Line " + loc.line + ", column " + loc.column;
        return "" + prefix + ": " + e.message;
    });
}

var parseOptions = {
    loc: true,
    range: true
};

console.log(checkStyle(`
var foo = bar;
var this_is_bad = 3;
function blah() {
  return function x() {
    var oops_another_one;
  }
}`));

Ejecución:

[~/javascript-learning/esprima-pegjs-jsconfeu-talk(private)]$  node checkstyle.js 
[
  'Line 3, column 4: Use camelCase for variable names, not hacker_style.',
  'Line 6
]

Esprima/Espree Example: syntax-highlight.js

[~/javascript-learning/esprima-pegjs-jsconfeu-talk(private)]$ cat syntax-highlight.js 

The readline module provides an interface for reading data from a Readable stream (such as process.stdin) one line at a time.

// http://esprima.readthedocs.io/en/latest/lexical-analysis.html
// Chapter 3. Lexical Analysis (Tokenization)
// Example: Syntax Highlighting
const esprima = require('espree');
const readline = require('readline');

const CYAN = '\x1b[36m';
const RESET = '\x1b[0m'
let source = '';

readline.createInterface({ input: process.stdin, terminal: false })
    .on('line', line => { source += line + '\n' })
    .on('close', () => {
        const tokens = esprima.tokenize(source, { range: true });
        const ids = tokens.filter(x => x.type === 'Identifier');
        debugger;
        const markers = ids.sort((a, b) => { return b.range[0] - a.range[0] });
        markers.forEach(t => {
            const id = CYAN + t.value + RESET;
            const start = t.range[0];
            const end = t.range[1];
            source = source.slice(0, start) + id + source.slice(end);
        });
        console.log(source);
    });

Acorn Examples

Getting the AST of a ECMA6 JSX source

~/.../learning/esprima-pegjs-jsconfeu-talk(develop)]$ node
Welcome to Node.js v12.10.0.
Type ".help" for more information.
> const {Parser} = require("acorn")
undefined
> const MyParser = Parser.extend(
...   require("acorn-jsx")())
undefined
> MyParser.parse("() => (<h1>Hello</h1>)")
Node {
  type: 'Program',
  start: 0,
  end: 22,
  body: [
    Node {
      type: 'ExpressionStatement',
      start: 0,
      end: 22,
      expression: [Node]
    }
  ],
  sourceType: 'script'
}

See astexplorer.net to see the full ESTree for () => (<h1>Hello</h1>)

acorn-walk

Let us continue with an example showing how to traverse the ESTree.

> const walk = require("acorn-walk")
undefined
> walk.simple(MyParser.parse("let x = 10"), {
...   Literal(node) {
.....     console.log(`Found a literal: ${node.value}`)
.....   }
... })
Found a literal: 10

See the ESTree for let x = 10

What is a Compiler?

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

En el Repo ULL-ESIT-GRADOII-PL/esprima-pegjs-jsconfeu-talk encontrará el material de esta charla.

ASTExplorer

ESLint Piggyback example

Babel remove “debugger” example

jscodeshift example

Repositorios interesantes de cowchimp

Your Comments

Comment with Disqus