/* Simple parser for Survex files (based on the CSS example) */ // The tokenizer breaks up the text into convincing chunks (I think the white-space is parser automatically) var SVXParser = Editor.Parser = (function() { var tokenizeSVX = (function() { function normal(source, setState) { var ch = source.next(); if (ch == ";") { source.nextWhile(matcher(/[^\n]/)); return "svx-comment"; } else if (ch == "*") { source.nextWhile(matcher(/\w/)); return "svx-command"; } else if (ch == "\"" || ch == "'") { var escaped = false; while (!source.endOfLine()) { var nch = source.next(); if (nch == ch && !escaped) break; escaped = !escaped && nch == "\\"; } return "svx-string"; } else if (/[\d\-+.]/.test(ch)) { source.nextWhile(matcher(/[\d.]/)); return "svx-measure"; } else { source.nextWhile(matcher(/\S/)); return "svx-word"; } } return function(source, startState) { return tokenizer(source, startState || normal); }; })(); // survex doesn't have indentation; but you get double linefeeds if you leave this out. function indentSVX() { return function(nextChars) { return 0; }; } // Then this simple parser fixes up the obvious errors made by the tokenizer (which could only operate on characters) // A very fancy upgrade could make it capable of handling the *data commands which make it accept different orderings of // the parameters -- though this may be a challenge because the whole file needs reparsing when that happens -- don't // know how optimized the basic code is to be able to call for such to happen when a formatting command like this changes. function parseSVX(source, basecolumn) { basecolumn = basecolumn || 0; var tokens = tokenizeSVX(source); var inCommand = false; var ntokeninline = -1; var iter = { next: function() { var token = tokens.next(), style = token.style, content = token.content; if (content == "\n") { ntokeninline = -1; inCommand = false; token.indentation = indentSVX(); } else if (style != "whitespace") ntokeninline += 1; if (style == "svx-command") { inCommand = (ntokeninline == 0); if (!inCommand) token.style = "svx-word"; else if (content == "*begin") token.style = "svx-begin"; else if (content == "*end") token.style = "svx-end"; } if (!inCommand && style == "svx-measure") { if (ntokeninline < 2) token.style = "svx-word"; } if (!inCommand && style == "svx-word" && (ntokeninline == 4)) { if (content == "down" || content == "up") token.style = "svx-measure"; } return token; }, copy: function() { var _inCommand = inCommand, _tokenState = tokens.state, _ntokeninline = ntokeninline; return function(source) { tokens = tokenizeSVX(source, _tokenState); inCommand = _inCommand; ntokeninline = _ntokeninline; return iter; }; } }; return iter; } return {make: parseSVX}; })();