UNPKG

2.34 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6/*
7
8states = {
9 state1: {
10 "aa(\d)": function(match) {
11 match == ["aa4", "4"];
12 return "state2"
13 },
14 "a": "state2",
15 "b": true
16 }
17}
18*/
19
20function Parser(states, options) {
21 this.options = options || {};
22 this.states = this.compileStates(states);
23};
24
25Parser.prototype.compileStates = function(states) {
26 var result = {};
27 Object.keys(states).forEach(function(name) {
28 result[name] = this.compileState(states[name]);
29 }, this);
30 return result;
31};
32
33Parser.prototype.compileState = function(state) {
34 var regExps = Object.keys(state).map(function(str) {
35 return {
36 groups: Parser.getGroupCount(str),
37 regExp: str,
38 value: state[str]
39 };
40 });
41 var total = regExps.map(function(r) {
42 return "(" + r.regExp + ")";
43 }).join("|");
44 var actions = [];
45 var pos = 1;
46 regExps.forEach(function(r) {
47 var fn;
48 if(typeof r.value === "function") {
49 fn = r.value;
50 } else if(typeof r.value === "string") {
51 fn = createReturningFunction(r.value);
52 } else {
53 fn = ignoreFunction;
54 }
55 actions.push({
56 name: r.regExp,
57 fn: fn,
58 pos: pos,
59 pos2: pos + r.groups + 1
60 });
61 pos += r.groups + 1;
62 });
63 return {
64 regExp: new RegExp(total, "g"),
65 actions: actions
66 }
67};
68
69Parser.getGroupCount = function(regExpStr) {
70 return new RegExp("(" + regExpStr + ")|^$").exec("").length - 2;
71};
72
73Parser.prototype.parse = function(initialState, string, context) {
74 var currentState = initialState;
75 var currentIndex = 0;
76 for(;;) {
77 var state = this.states[currentState];
78 var regExp = state.regExp;
79 regExp.lastIndex = currentIndex;
80 var match = regExp.exec(string);
81 if(!match) return context;
82 var actions = state.actions;
83 currentIndex = state.regExp.lastIndex;
84 for(var i = 0; i < actions.length; i++) {
85 var action = actions[i];
86 if(match[action.pos]) {
87 var ret = action.fn.apply(context, Array.prototype.slice.call(match, action.pos, action.pos2).concat([state.regExp.lastIndex - match[0].length, match[0].length]));
88 if(ret) currentState = ret;
89 break;
90 }
91 }
92 }
93};
94
95module.exports = Parser;
96
97function ignoreFunction() {}
98
99function createReturningFunction(value) {
100 return function() {
101 return value;
102 };
103}
\No newline at end of file