Skip to content

Instantly share code, notes, and snippets.

@andywer
Created March 4, 2017 16:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andywer/a19b67fca9bea66ca71fce14a909800f to your computer and use it in GitHub Desktop.
Save andywer/a19b67fca9bea66ca71fce14a909800f to your computer and use it in GitHub Desktop.
Babylon plugin for elm/haskell-ish type declarations
// src/plugins/dctypes.js
import { types as tt } from "../tokenizer/types";
import { types as ct } from "../tokenizer/context";
import Parser from "../parser";
import "./flow";
const pp = Parser.prototype;
export default function (instance) {
instance.extend("parseStatement", function (inner) {
return function (declaration, topLevel) {
const lookahead = this.lookahead();
if (this.match(tt.name) && lookahead.type === tt.doubleColon) {
const declarationNode = this.startNode();
const identifierNode = this.parseIdentifier();
this.expect(tt.doubleColon);
return this.dctypesParseTypeDefinition(declarationNode, identifierNode);
} else {
return inner.call(this, declaration, topLevel);
}
};
});
// Slightly hacky solution to parse type declarations in class body:
// Make isClassProperty() return true on them, patch parseClassProperty()
instance.extend("isClassProperty", function (inner) {
return function () {
return inner.call(this) || this.match(tt.doubleColon);
};
});
instance.extend("parseClassProperty", function (inner) {
return function (node) {
if (this.match(tt.doubleColon)) {
const identifierNode = node.key;
delete node.key;
this.expect(tt.doubleColon);
return this.dctypesParseTypeDefinition(node, identifierNode);
} else {
return inner.call(this, node);
}
};
});
}
pp.dctypesParseTypeDefinition = function dctypesParseTypeDefinition (declarationNode, identifierNode) {
declarationNode.id = identifierNode;
declarationNode.typeAnnotation = this.flowParseType();
this.semicolon();
return this.finishNode(declarationNode, "TypeDeclaration");
};
--- a/src/index.js
+++ b/src/index.js
@@ -14,9 +14,11 @@ import "./tokenizer/context";
import estreePlugin from "./plugins/estree";
import flowPlugin from "./plugins/flow";
import jsxPlugin from "./plugins/jsx";
+import dctypesPlugin from "./plugins/dctypes";
plugins.estree = estreePlugin;
plugins.flow = flowPlugin;
plugins.jsx = jsxPlugin;
+plugins.dctypes = dctypesPlugin;
export function parse(input, options) {
return new Parser(options, input).parse();
// test.js
const babylon = require('./lib')
const code = `
add :: (number, number) => number
class Foo {
print :: string => undefined
print (string) {
console.log(string)
}
}
`
const parserOptions = {
plugins: ['dctypes']
}
parse()
function parse () {
const ast = babylon.parse(code, parserOptions)
console.log(
JSON.stringify(ast.program, null, 2)
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment