Last active
January 16, 2017 18:26
-
-
Save tlrobinson/b63ab1efe5b79aba14c65e6495d3ba1d to your computer and use it in GitHub Desktop.
Chevrotain + Webpack 2 mangling issue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
{ | |
"presets": [ | |
["es2015", { "modules": false }] | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import calculator from "./calculator"; | |
console.log(calculator("1 + 1")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Parser, Lexer } from "chevrotain"; | |
import { | |
allTokens, | |
WhiteSpace, | |
Plus, Minus, Multi, Div, | |
LParen, RParen, | |
NumberLiteral, | |
AdditionOperator, MultiplicationOperator | |
} from "./tokens"; | |
const CalculatorLexer = new Lexer(allTokens); | |
// ----------------- parser ----------------- | |
function Calculator(input) { | |
Parser.call(this, input, allTokens); | |
var $ = this; | |
$.RULE("expression", function() { | |
return $.SUBRULE($.additionExpression) | |
}); | |
// lowest precedence thus it is first in the rule chain | |
// The precedence of binary expressions is determined by how far down the Parse Tree | |
// The binary expression appears. | |
$.RULE("additionExpression", function() { | |
var value, op, rhsVal; | |
// parsing part | |
value = $.SUBRULE($.multiplicationExpression); | |
$.MANY(function() { | |
// consuming 'AdditionOperator' will consume either Plus or Minus as they are subclasses of AdditionOperator | |
op = $.CONSUME(AdditionOperator); | |
// the index "2" in SUBRULE2 is needed to identify the unique position in the grammar during runtime | |
rhsVal = $.SUBRULE2($.multiplicationExpression); | |
// interpreter part | |
if (op instanceof Plus) { | |
value += rhsVal | |
} else { // op instanceof Minus | |
value -= rhsVal | |
} | |
}); | |
return value | |
}); | |
$.RULE("multiplicationExpression", function() { | |
var value, op, rhsVal; | |
// parsing part | |
value = $.SUBRULE($.atomicExpression); | |
$.MANY(function() { | |
op = $.CONSUME(MultiplicationOperator); | |
// the index "2" in SUBRULE2 is needed to identify the unique position in the grammar during runtime | |
rhsVal = $.SUBRULE2($.atomicExpression); | |
// interpreter part | |
if (op instanceof Multi) { | |
value *= rhsVal | |
} else { // op instanceof Div | |
value /= rhsVal | |
} | |
}); | |
return value | |
}); | |
$.RULE("atomicExpression", function() { | |
// @formatter:off | |
return $.OR([ | |
// parenthesisExpression has the highest precedence and thus it appears | |
// in the "lowest" leaf in the expression ParseTree. | |
{ALT: function(){ return $.SUBRULE($.parenthesisExpression)}}, | |
{ALT: function(){ return parseInt($.CONSUME(NumberLiteral).image, 10)}} | |
], "a number or parenthesis expression"); | |
// @formatter:on | |
}); | |
$.RULE("parenthesisExpression", function() { | |
var expValue; | |
$.CONSUME(LParen); | |
expValue = $.SUBRULE($.expression); | |
$.CONSUME(RParen); | |
return expValue | |
}); | |
// very important to call this after all the rules have been defined. | |
// otherwise the parser may not work correctly as it will lack information | |
// derived during the self analysis phase. | |
Parser.performSelfAnalysis(this); | |
} | |
// avoids inserting number literals as these can have multiple(and infinite) semantic values, thus it is unlikely | |
// we can choose the correct number value to insert. | |
Calculator.prototype.canTokenTypeBeInsertedInRecovery = function(tokClass) { | |
return tokClass !== NumberLiteral | |
}; | |
Calculator.prototype = Object.create(Parser.prototype); | |
Calculator.prototype.constructor = Calculator; | |
// wrapping it all togater | |
// reuse the same parser instance. | |
var parser = new Calculator([]); | |
export default function(text) { | |
var lexResult = CalculatorLexer.tokenize(text); | |
// setting a new input will RESET the parser instance's state. | |
parser.input = lexResult.tokens; | |
// any top level rule may be used as an entry point | |
var value = parser.expression(); | |
return { | |
value: value, | |
lexResult: lexResult, | |
parseErrors: parser.errors | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title></title> | |
<script src="app.bundle.js" charset="utf-8"></script> | |
</head> | |
<body> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "webpack2-chevrotain-test", | |
"version": "1.0.0", | |
"main": "index.js", | |
"devDependencies": { | |
"babel-core": "^6.21.0", | |
"babel-loader": "^6.2.10", | |
"babel-preset-es2015": "^6.18.0", | |
"webpack": "2.2.0-rc.7" | |
}, | |
"dependencies": { | |
"chevrotain": "^0.21.0" | |
}, | |
"scripts": { | |
"install": "./node_modules/.bin/webpack" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createToken, Lexer } from "chevrotain"; | |
// using the NA pattern marks this Token class as 'irrelevant' for the Lexer. | |
// AdditionOperator defines a Tokens hierarchy but only the leafs in this hierarchy define | |
// actual Tokens that can appear in the text | |
export const AdditionOperator = createToken({name: "AdditionOperator", pattern: Lexer.NA}); | |
export const Plus = createToken({name: "Plus", pattern: /\+/, parent: AdditionOperator}); | |
export const Minus = createToken({name: "Minus", pattern: /-/, parent: AdditionOperator}); | |
export const MultiplicationOperator = createToken({name: "MultiplicationOperator", pattern: Lexer.NA}); | |
export const Multi = createToken({name: "Multi", pattern: /\*/, parent: MultiplicationOperator}); | |
export const Div = createToken({name: "Div", pattern: /\//, parent: MultiplicationOperator}); | |
export const LParen = createToken({name: "LParen", pattern: /\(/}); | |
export const RParen = createToken({name: "RParen", pattern: /\)/}); | |
export const NumberLiteral = createToken({name: "NumberLiteral", pattern: /[1-9]\d*/}); | |
// marking WhiteSpace as 'SKIPPED' makes the lexer skip it. | |
export const WhiteSpace = createToken({name: "WhiteSpace", pattern: /\s+/, group: Lexer.SKIPPED}); | |
export const allTokens = [WhiteSpace, // whitespace is normally very common so it should be placed first to speed up the lexer's performance | |
Plus, Minus, Multi, Div, LParen, RParen, NumberLiteral, AdditionOperator, MultiplicationOperator]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var config = module.exports = { | |
entry: { | |
app: './app.js' | |
}, | |
output: { | |
filename: '[name].bundle.js?[hash]', | |
}, | |
module: { | |
loaders: [ | |
{ | |
test: /\.js$/, | |
exclude: /node_modules/, | |
loader: "babel-loader" | |
}, | |
], | |
}, | |
devtool: "sourcemap" | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment