Skip to content

Commit 28b667d

Browse files
author
calibr
committed
add multiline processing closes #1
1 parent 0f246c9 commit 28b667d

File tree

1 file changed

+149
-17
lines changed

1 file changed

+149
-17
lines changed

index.js

Lines changed: 149 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,156 @@
1-
exports.parse = function(string) {
2-
var object = {};
3-
string.split(/(\n|\r\n)/).forEach(function(s) {
4-
s = s.trim();
5-
if(!s) {
6-
return;
1+
var EventEmitter = require("events");
2+
var util = require("util");
3+
4+
function SimpleApiParser() {
5+
EventEmitter.call(this);
6+
7+
this.inValue = false;
8+
this.inEntity = false;
9+
this.index = 0;
10+
this.string = null;
11+
this.end = false;
12+
this._space = /\s/;
13+
}
14+
util.inherits(SimpleApiParser, EventEmitter);
15+
16+
SimpleApiParser.prototype._checkUnexpectedDocEnd = function() {
17+
if(this.index >= this.length) {
18+
throw new Error("Unexpected document end");
19+
}
20+
}
21+
22+
SimpleApiParser.prototype._skipSpaces = function() {
23+
for(;;) {
24+
this.index++;
25+
this._checkUnexpectedDocEnd();
26+
if(!this._space.test(this.string[this.index])) {
27+
break;
728
}
8-
var m = s.match(/<!entity\s+(.+?)\s+(.+?)>$/i);
9-
if(!m) {
10-
return;
29+
}
30+
}
31+
32+
SimpleApiParser.prototype._readUntil = function(char) {
33+
for(;;) {
34+
this.index++;
35+
this._checkUnexpectedDocEnd();
36+
if(this.string[this.index] === char) {
37+
break;
1138
}
12-
var key = m[1];
13-
var value = m[2];
14-
if(value[0] === "\"" || value[0] === "'") {
15-
var quote = value[0];
16-
value = value.substr(1, value.length - 2);
17-
value = value.replace(new RegExp("\\\\" + quote, "g"), quote);
39+
}
40+
this.index--;
41+
}
42+
43+
SimpleApiParser.prototype._getNext = function(n) {
44+
if(n <= 0) {
45+
return "";
46+
}
47+
var res = "";
48+
while(n--) {
49+
res += this.string[this.index];
50+
this.index++;
51+
}
52+
return res;
53+
}
54+
55+
SimpleApiParser.prototype._next = function () {
56+
var char;
57+
if (this.index === 0) {
58+
this.emit("document_start");
59+
}
60+
if (this.index >= this.string.length) {
61+
this.end = true;
62+
return this.emit("document_end");
63+
}
64+
var symbol = this.string[this.index];
65+
if (symbol === "<") {
66+
this.index++;
67+
var next7Symbols = this._getNext(7);
68+
if(next7Symbols.toLowerCase() !== "!entity") {
69+
throw new Error("Expected !entity, got \"" + next7Symbols + "(" + next7Symbols.toLowerCase() + ")\"");
70+
}
71+
// reading entity name
72+
// first of skip space chars
73+
this._skipSpaces();
74+
// reading entity name until space
75+
var entityName = "";
76+
for (;;) {
77+
this._checkUnexpectedDocEnd();
78+
char = this.string[this.index];
79+
if(this._space.test(char)) {
80+
break;
81+
}
82+
this.index++;
83+
entityName += char;
84+
}
85+
this.inEntity = true;
86+
this.entityValueQuote = false;
87+
this.emit("entity_name", entityName);
88+
this._skipSpaces();
89+
char = this.string[this.index];
90+
var entityValueQuote = null;
91+
if (char === '"' || char === "'") {
92+
entityValueQuote = char;
93+
}
94+
var value = "";
95+
var symbolEscaped = false;
96+
var addChar;
97+
for (;;) {
98+
addChar = true;
99+
this.index++;
100+
this._checkUnexpectedDocEnd();
101+
char = this.string[this.index];
102+
if(entityValueQuote) {
103+
if (!symbolEscaped && char === entityValueQuote) {
104+
break;
105+
}
106+
} else if (this._space.test(char)) {
107+
this._readUntil(">");
108+
break;
109+
} else if (char === ">") {
110+
break;
111+
}
112+
if (symbolEscaped) {
113+
symbolEscaped = false;
114+
} else if (entityValueQuote && char === '\\') {
115+
var nextSymbol = this.string[this.index + 1];
116+
if(nextSymbol === entityValueQuote) {
117+
symbolEscaped = true;
118+
addChar = false;
119+
}
120+
}
121+
if(addChar) {
122+
value += char;
123+
}
18124
}
19-
object[key] = value;
125+
this.emit("entity_value", value);
126+
}
127+
this.index++;
128+
};
129+
130+
SimpleApiParser.prototype.parse = function(str) {
131+
this.string = str;
132+
var i = 0;
133+
while (!this._end) {
134+
i++;
135+
if(i > this.string.length) {
136+
break;
137+
}
138+
this._next();
139+
}
140+
};
141+
142+
exports.parse = function(string) {
143+
var parser = new SimpleApiParser();
144+
var res = {};
145+
var currentName;
146+
parser.on("entity_name", function(name) {
147+
currentName = name;
148+
});
149+
parser.on("entity_value", function(value) {
150+
res[currentName] = value;
20151
});
21-
return object;
152+
parser.parse(string);
153+
return res;
22154
};
23155

24156
exports.stringify = function(object) {

0 commit comments

Comments
 (0)