UNPKG

ink-docstrap

Version:

[![NPM](https://nodei.co/npm/ink-docstrap.png?downloads=true)](https://nodei.co/npm/ink-docstrap/)

414 lines (354 loc) 13.4 kB
(function(sunlight, undefined){ if (sunlight === undefined || sunlight["registerLanguage"] === undefined) { throw "Include sunlight.js before including language files"; } sunlight.registerLanguage("vb", { //http://msdn.microsoft.com/en-us/library/dd409611.aspx keywords: [ "AddHandler","AddressOf","Alias","AndAlso","And","As","Boolean","ByRef","Byte","ByVal","Call","Case","Catch", "CBool","CByte","CChar","CDate","CDbl","CDec","Char","CInt","Class","CLng","CObj","Const","Continue","CSByte", "CShort","CSng","CStr","CType","CUInt","CULng","CUShort","Date","Decimal","Declare","Default","Delegate","Dim", "DirectCast","Double","Do","Each","ElseIf","Else","EndStatement","EndIf","End","Enum","Erase","Error","Event", "Exit","False","Finally","ForEach","For","Friend","Function","GetType","GetXMLNamespace","Get","Global","GoSub", "GoTo","Handles","If","Implements","Imports","Inherits","Integer","Interface","In","IsNot","Is","Let","Lib", "Like","Long","Loop","Me","Module","Mod","MustInherit","MustOverride","MyBase","MyClass","Namespace","Narrowing", "New","Next","Nothing","NotInheritable","NotOverridable","Not","Object","Of","On","Operator","Option","Optional", "OrElse","Or","Out","Overloads","Overridable","Overrides","ParamArray","Partial","Private","Property","Protected", "Public","RaiseEvent","ReadOnly","ReDim","RemoveHandler","Resume","Return","SByte","Select","Set","Shadows", "Shared","Short","Single","Static","Step","Stop","String","Structure","Sub","SyncLock","Then","Throw","To","True", "TryCast","Try","TypeOf","UInteger","ULong","UShort","Using","Variant","Wend","When","While","Widening", "WithEvents","With","WriteOnly","Xor" ], customTokens: { reservedWord: { values: [ "Aggregate","Ansi","Assembly","Auto","Binary","Compare","Custom","Distinct","Equals","Explicit","From","Group By","Group Join", "Into","IsFalse","IsTrue","Join","Key","Mid","Off","Order By","Preserve","Skip","Skip While","Strict","Take While","Take","Text", "Unicode","Until","Where" ], boundary: "\\b" } }, scopes: { string: [ ["\"", "\"", sunlight.util.escapeSequences.concat(["\\\""])] ], comment: [ ["'", "\n", null, true], ["REM", "\n", null, true] ], compilerDirective: [ ["#", "\n", null, true] ] }, customParseRules: [ //xml doc comments (copypasted from c# file) function(context) { var metaName = "xmlDocCommentMeta", contentName = "xmlDocCommentContent", tokens, peek, current; if (context.reader.current() !== "'" || context.reader.peek(2) !== "''") { return null; } tokens = [context.createToken(metaName, "'''", context.reader.getLine(), context.reader.getColumn())]; current = { line: 0, column: 0, value: "", name: null }; context.reader.read(2); while ((peek = context.reader.peek()) !== context.reader.EOF) { if (peek === "<" && current.name !== metaName) { //push the current token if (current.value !== "") { tokens.push(context.createToken(current.name, current.value, current.line, current.column)); } //amd create a token for the tag current.line = context.reader.getLine(); current.column = context.reader.getColumn(); current.name = metaName; current.value = context.reader.read(); continue; } if (peek === ">" && current.name === metaName) { //close the tag current.value += context.reader.read(); tokens.push(context.createToken(current.name, current.value, current.line, current.column)); current.name = null; current.value = ""; continue; } if (peek === "\n") { break; } if (current.name === null) { current.name = contentName; current.line = context.reader.getLine(); current.column = context.reader.getColumn(); } current.value += context.reader.read(); } if (current.name === contentName) { tokens.push(context.createToken(current.name, current.value, current.line, current.column)); } return tokens.length > 0 ? tokens : null; }, //keyword escaping: e.g. "[In]" function(context) { var line = context.reader.getLine(), column = context.reader.getColumn(), next, value = "["; if (context.reader.current() !== "[") { return null; } //read until "]" next = context.reader.read(); while (next !== context.reader.EOF) { value += next; if (next === "]") { break; } next = context.reader.read(); } return context.createToken("escapedKeyword", value, line, column); }, //handles New/GetType contextual keywords //e.g. prevents "New" in "SomeClass.New()" from being a keyword function() { var hashmap = sunlight.util.createHashMap(["New", "GetType"], "\\b"); return function(context) { var token = sunlight.util.matchWord(context, hashmap, "keyword"), prevToken; if (!token) { return null; } //if the previous non-ws token is the "." operator then it's an ident, not a keyword //or if it's a subprocedure name prevToken = sunlight.util.getPreviousNonWsToken(context.getAllTokens(), context.count()); if (prevToken && ((prevToken.name === "operator" && prevToken.value === ".") || (prevToken.name === "keyword" && prevToken.value === "Sub"))) { token.name = "ident"; } return token; }; }() ], identFirstLetter: /[A-Za-z_]/, identAfterFirstLetter: /\w/, namedIdentRules: { custom: [ //attributes (copypasted (mostly) from c# file) function(context) { //if the next token is an equals sign, this is a named parameter (or something else not inside of an attribute) var token, nextToken = sunlight.util.getNextNonWsToken(context.tokens, context.index), index = context.index, bracketCount = [0, 0], indexOfLastBracket = -1; if (nextToken && nextToken.name === "operator" && (nextToken.value === "=" || nextToken.value === ".")) { return false; } //we need to verify that we're between <> //first, verify that we're inside an opening bracket while ((token = context.tokens[--index]) !== undefined) { if (token.name === "operator") { if (token.value === "<") { bracketCount[0]++; } else if (token.value === ">") { bracketCount[1]++; } } else if (token.name === "keyword" && sunlight.util.contains(["Public", "Class", "Protected", "Private", "Friend"], token.value)) { //early exits break; } } if (bracketCount[0] === 0 || bracketCount[0] === bracketCount[1]) { //if no brackets were found OR... //all the found brackets are closed, so this ident is actually outside of the brackets //duh. return false; } //next, verify we're inside a closing bracket index = context.index; while ((token = context.tokens[++index]) !== undefined) { if (token.name === "operator") { if (token.value === "<") { bracketCount[0]++; } else if (token.value === ">") { indexOfLastBracket = index; bracketCount[1]++; } } else if (token.name === "keyword" && sunlight.util.contains(["Public", "Class", "Protected", "Private", "Friend", "ByVal"], token.value)) { //early exits break; } } if (indexOfLastBracket < 0 || bracketCount[0] !== bracketCount[1]) { return false; } //next token after the last closing bracket should be either a keyword or an ident token = sunlight.util.getNextNonWsToken(context.tokens, indexOfLastBracket); if (token && (token.name === "keyword" || token.name === "ident")) { return true; } return false; }, //casts function(context) { var token, index = context.index, parenCount = 1; //look backward for CType, DirectCast or TryCast //could be goofy because of nesting, so we need to count parens //verify that this ident is the second argument to the function call if (!sunlight.util.createProceduralRule(context.index - 1, -1, [{ token: "punctuation", values: [","] }, sunlight.util.whitespace])(context.tokens)) { return false; } while (token = context.tokens[--index]) { if (token.name === "punctuation" && token.value === "(") { parenCount--; if (parenCount === 0) { //we found the opening paren, so if the previous token is one of the cast functions, this is a cast token = context.tokens[--index]; if (token && token.name === "keyword" && sunlight.util.contains(["CType", "DirectCast", "TryCast"], token.value)) { return true; } return false; } } else if (token.name === "punctuation" && token.value === ")") { parenCount++; } } return false; }, //implemented interfaces function(context) { var prevToken = sunlight.util.getPreviousNonWsToken(context.tokens, context.index), token, index = context.index; //if previous non-ws token was a "." then it's an implemented method if (prevToken && prevToken.name === "operator" && prevToken.value === ".") { return false; } //look backward for "Implements" while (token = context.tokens[--index]) { if (token.name === "keyword") { switch (token.value) { case "Class": case "New": break; case "Implements": return true; default: return false; } } else if (token.name === "default" && token.value.indexOf(sunlight.util.eol) >= 0) { //apparently they must be on the same line...? return false; } } return false; }, //type constraints: "As {ident, ident, ...}" function(context) { //look backward for "As {" var token, index = context.index, isValid = function() { while (token = context.tokens[--index]) { if (token.name === "punctuation") { switch (token.value) { case "(": case ")": return false; case "{": //previous non-ws token should be keyword "As" token = sunlight.util.getPreviousNonWsToken(context.tokens, index); if (!token || token.name !== "keyword" || token.value !== "As") { return false; } return true; } } else if (token.name === "keyword" && sunlight.util.contains(["Public", "Protected", "Friend", "Private", "End"], token.value)) { return false; } } return false; }(); if (!isValid) { return false; } //"}" before ) index = context.index; while (token = context.tokens[++index]) { if (token.name === "punctuation") { switch (token.value) { case "}": return true; case "(": case ")": case ";": return false; } } } return false; } ], follows: [ [{ token: "keyword", values: ["Of", "As", "Class", "Implements", "Inherits", "New", "AddressOf", "Interface", "Structure", "Event", "Module", "Enum"] }, { token: "default" }], [{ token: "keyword", values: ["GetType"] }, sunlight.util.whitespace, { token: "punctuation", values: ["("] }, sunlight.util.whitespace] ] }, numberParser: function(context) { var current = context.reader.current(), number, line = context.reader.getLine(), column = context.reader.getColumn(), allowDecimal = true, peek; if (current === "&" && /[Hh][A-Fa-f0-9]/.test(context.reader.peek(2))) { number = current + context.reader.read(2); allowDecimal = false; } else if (/\d/.test(current)) { number = current; } else { if (current !== "." || !/\d/.test(context.reader.peek())) { return null; } number = current + context.reader.read(); allowDecimal = false; } while ((peek = context.reader.peek()) !== context.reader.EOF) { if (!/[A-Za-z0-9]/.test(peek)) { if (peek === "." && allowDecimal && /\d$/.test(context.reader.peek(2))) { number += context.reader.read(); allowDecimal = false; continue; } break; } number += context.reader.read(); } return context.createToken("number", number, line, column); }, operators: [ ".", "<>", "=", "&=", "&", "*=", "*", "/=", "/", "\\=", "\\", "^=", "^", "+=", "+", "-=", "-", ">>=", ">>", "<<=", "<<", "<=", ">=", "<", ">" ] }); }(this["Sunlight"]));