3º. 2º cuatrimestre. Itinerario de Computación. Grado en Ingeniería Informática. ULL
En las clases del 27 y 28 aprenderemos algo mas sobre programación asíncrona en JS mediante retos y aprovecharemos para seguir con la corrección de las prácticas anteriores
Lunes 9, Martes 10 y Miércoles 11 de Marzo
The tutorial in this repo:
loadScript
that mimicks the <script>
tag to load scripts on the browser,async-es
(A pure ESM version of Async) andEn el Repo ULL-ESIT-GRADOII-PL/esprima-pegjs-jsconfeu-talk encontrará el material de varias charlas.
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
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.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
]
syntax-highlight.js
is taken from the Esprima tutorial Chapter 3. Lexical Analysis (Tokenization)[~/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);
});
~/.../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>)
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
En el Repo ULL-ESIT-GRADOII-PL/esprima-pegjs-jsconfeu-talk encontrará el material de esta charla.
debugger;
statements