├── .gitignore ├── LICENSE ├── README.md ├── dist ├── angulartemplate.js ├── c.js ├── clif.js ├── cpp.js ├── flatbuffers.js ├── go.js ├── html.js ├── java.js ├── javascript.js ├── kotlin.js ├── python.js └── typescript.js ├── index.html ├── package.json ├── rollup.config.js ├── src ├── angulartemplate.grammar ├── angulartemplate.js ├── c.grammar ├── c.js ├── c_indent.js ├── clif.grammar ├── clif.js ├── cpp.grammar ├── cpp.js ├── doxygen.grammar ├── flatbuffers.grammar ├── flatbuffers.js ├── go.grammar ├── go.js ├── html.grammar ├── html.js ├── html_util.js ├── java.grammar ├── java.js ├── javadoc.grammar ├── javascript.grammar ├── javascript.js ├── js_semi.js ├── jsdoc.grammar ├── kdoc.grammar ├── kotlin.grammar ├── kotlin.js ├── locals.js ├── python.grammar ├── python.js ├── template_string_inline_language.js ├── typescript.grammar └── typescript.js └── test ├── c ├── def.c ├── double_block.c ├── indent.c ├── indent_switch.c ├── lookahead_type.c ├── preprocessor.c └── tmp.c ├── clif ├── grammar.clif └── indent.clif ├── cpp ├── class.cpp ├── ctor_dtor.cpp ├── grammar.cpp ├── indent.cpp ├── lambda.cpp ├── literal.cpp ├── macro.cpp ├── main.cpp ├── syntax.cpp ├── template.cpp └── types.cpp ├── flatbuffers └── testbuffer.fbs ├── go ├── grammar.go └── indent.go ├── import-indent-test.js ├── import-style-test.js ├── java ├── grammar.java └── indent.java ├── js ├── anonymous_class_expression.js ├── async.js ├── async_arrow.js ├── async_assignment.js ├── async_jquery.js ├── async_object.js ├── async_object_function.js ├── async_object_properties.js ├── async_variable.js ├── class.js ├── class_async_method.js ├── class_body.js ├── comma-and-binop.js ├── const.js ├── destructure_trailing_comma.js ├── destructuring.js ├── fatArrow.js ├── for_of.js ├── generator.js ├── import.js ├── import_trailing_comma.js ├── indent.js ├── indent_below_if.js ├── indent_else.js ├── indent_for.js ├── indent_funarg.js ├── indent_if.js ├── indent_semicolonless_if.js ├── indent_semicolonless_if_with_statement.js ├── indent_statement.js ├── indent_strange_array.js ├── indent_switch.js ├── jsdoc.js ├── locals.js ├── multilinestring.js ├── named_class_expression.js ├── new_target.js ├── param_default.js ├── quasi.js ├── quasi_no_function.js ├── quotedFatArrow.js ├── quotedStringAddition.js ├── scary_regexp.js ├── spread.js └── tagged_template.js ├── kotlin ├── annotation.kt ├── expr.kt └── statement.kt ├── ng └── template.html ├── parse_spec.js ├── py ├── fstrings.py ├── grammar.py └── indent.py ├── run.js └── ts ├── grammar.ts └── tagged_template.ts /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .tern-* 3 | /src/*.mode.js 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2017 by Marijn Haverbeke and others 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Google mode pack 2 | 3 | This is a set of [CodeMirror](http://codemirror.net/) modes for **C**, 4 | **C++**, **Java**, **Kotlin**, **Go**, **JavaScript**, **TypeScript**, **Python**, 5 | **HTML**, and **Angular Templates**, providing a consistent 6 | highlighting style across these languages and an indentation style 7 | compatible with Google's style guides. 8 | 9 | The repository contains the sources needed to create the modes. To 10 | actually build them, run `npm install`. That will create files for the 11 | different modes under `dist/`. 12 | 13 | These modes are defined using the 14 | [codemirror-grammar-mode](https://github.com/codemirror/grammar-mode) 15 | tool, and have that tool's 16 | [runtime](https://github.com/codemirror/grammar-mode/blob/master/src/mode.js) 17 | as a client-side dependency. 18 | -------------------------------------------------------------------------------- /dist/html.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('codemirror'), require('codemirror-grammar-mode')) : 3 | typeof define === 'function' && define.amd ? define(['codemirror', 'codemirror-grammar-mode'], factory) : 4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CodeMirror)); 5 | })(this, (function (CodeMirror$1) { 'use strict'; 6 | 7 | function _interopNamespace(e) { 8 | if (e && e.__esModule) return e; 9 | var n = Object.create(null); 10 | if (e) { 11 | Object.keys(e).forEach(function (k) { 12 | if (k !== 'default') { 13 | var d = Object.getOwnPropertyDescriptor(e, k); 14 | Object.defineProperty(n, k, d.get ? d : { 15 | enumerable: true, 16 | get: function () { return e[k]; } 17 | }); 18 | } 19 | }); 20 | } 21 | n["default"] = e; 22 | return Object.freeze(n); 23 | } 24 | 25 | var CodeMirror__namespace = /*#__PURE__*/_interopNamespace(CodeMirror$1); 26 | 27 | var e = [[1, "\n", "\t", " "], /^[a-zA-Z\-\.0-9_]+/]; 28 | var nodes = [ 29 | [1, 3, 0, 30 | 0, 1], 31 | [/^[^]/, 0], 32 | [/^[^]/, -1], 33 | [2, 4, -1, {"name":"comment","token":"comment"}, 34 | 2, 6, -1, {"name":"doctype","token":"meta"}, 35 | 2, 8, -1, {"name":"tag"}, 36 | 3, "atom", /^\&(?:(?![\;\n\t ]).)*\;/, -1, 37 | [1, "\n", /^(?:(?![\&\<]).)+/], -1], 38 | ["", -1], 41 | [/^(?:\<\!doctype|\<\!DOCTYPE)(?![a-zA-Z\-\.0-9_])/, 7], 42 | [[0, /^(?!\>)/, /^[^]/], 7, 43 | ">", -1], 44 | [2, 14, 9, {"name":"openTag"}], 45 | [3, "tag", "/>", -1, 46 | [7, "selfClosing"], 10, 47 | 3, "tag", ">", 11], 48 | [3, "tag", ">", -1], 49 | [1, 3, 11, 50 | /^(?=\<\/)/, 12], 51 | [[7, "matchingTag"], 13, 52 | 0, -1], 53 | [2, 21, -1, {"name":"closeTag"}], 54 | [3, "tag", [0, "<", [6, 24]], 15], 55 | [e[0], 15, 56 | 3, "tag", e[1], 16], 57 | [e[0], 16, 58 | 0, 17], 59 | [3, "attribute", e[1], 18, 60 | 0, -1], 61 | [e[0], 18, 62 | "=", 19, 63 | 0, 20], 64 | [e[0], 19, 65 | 2, 25, 20, {"name":"attributeValue","token":"string"}], 66 | [e[0], 20, 67 | 0, 17], 68 | [3, "tag", "", -1], 72 | [e[0], 24, 73 | "/", -1], 74 | ["\"", 26, 75 | "'", 27, 76 | /^(?:(?![\n\t \>]).)*/, -1], 77 | [[0, /^(?!\")/, /^[^]/], 26, 78 | "\"", -1], 79 | [[0, /^(?!\')/, /^[^]/], 27, 80 | "'", -1] 81 | ]; 82 | var start = 0; 83 | var token = 2; 84 | 85 | var grammar = /*#__PURE__*/Object.freeze({ 86 | __proto__: null, 87 | nodes: nodes, 88 | start: start, 89 | token: token 90 | }); 91 | 92 | function tagName(str) { 93 | var m = /^\s*([\w_\.-]+)/.exec(str); 94 | return m ? m[1].toLowerCase() : "x" 95 | } 96 | 97 | function cxTagName(cx) { 98 | return tagName(cx.startLine.slice(cx.startPos + 1)) 99 | } 100 | 101 | var selfClosers = "area base br col command embed frame hr img input keygen link meta param source track wbr menuitem".split(" "); 102 | 103 | function selfClosing(_string, _pos, cx) { 104 | return selfClosers.indexOf(cxTagName(cx)) > -1 105 | } 106 | 107 | function matchingTag(string, pos, cx) { 108 | return tagName(string.slice(pos + 2)) == cxTagName(cx) 109 | } 110 | 111 | var predicates = {selfClosing: selfClosing, matchingTag: matchingTag}; 112 | 113 | function indent(state, textAfter, line, config) { 114 | var cx = state.contextAt(line, line.length - textAfter.length); 115 | var closing = /^\s*<\/\s*([\w_\.-]+)/.exec(textAfter); 116 | while (cx) { 117 | if (cx.name == "tag") { 118 | var base = CodeMirror.countColumn(cx.startLine, null, config.tabSize); 119 | if (closing && closing[1].toLowerCase() == cxTagName(cx)) { return base } 120 | else { return base + config.indentUnit } 121 | } else if (cx.name == "openTag") { 122 | return CodeMirror.countColumn(cx.startLine, null, config.tabSize) + 2 * config.indentUnit 123 | } 124 | cx = cx.parent; 125 | } 126 | return 0 127 | } 128 | 129 | function contextInfo(proto) { 130 | proto.xmlCurrentTag = function (state) { 131 | var cx = state.context; 132 | if (!cx || (cx.name != "openTag" && cx.name != "closeTag")) { return null } 133 | var match = /^<\/?\s*([\w\-\.]+)/.exec(cx.startLine.slice(cx.startPos)); 134 | return match ? {name: match[1], close: cx.name == "closeTag"} : null 135 | }; 136 | proto.xmlCurrentContext = function (state) { 137 | var context = []; 138 | for (var cx = state.context; cx; cx = cx.parent) { 139 | if (cx.name == "tag") { 140 | var match = /^<\s*([\w\-\.]+)/.exec(cx.startLine.slice(cx.startPos)); 141 | if (match) { context.push(match[1]); } 142 | } 143 | } 144 | return context.reverse() 145 | }; 146 | } 147 | 148 | var HTMLMode = /*@__PURE__*/(function (superclass) { 149 | function HTMLMode(conf, modeConf) { 150 | superclass.call(this, grammar, {predicates: predicates}); 151 | this.conf = conf; 152 | } 153 | 154 | if ( superclass ) HTMLMode.__proto__ = superclass; 155 | HTMLMode.prototype = Object.create( superclass && superclass.prototype ); 156 | HTMLMode.prototype.constructor = HTMLMode; 157 | 158 | HTMLMode.prototype.indent = function indent$1 (state, textAfter, line) { 159 | return indent(state, textAfter, line, this.conf) 160 | }; 161 | 162 | return HTMLMode; 163 | }(CodeMirror__namespace.GrammarMode)); 164 | 165 | var proto = HTMLMode.prototype; 166 | proto.electricInput = /^\s*<\/.*?>/; 167 | proto.blockCommentStart = ""; 169 | proto.fold = "xml"; 170 | contextInfo(proto); 171 | 172 | CodeMirror__namespace.defineMode("google-html", function (conf, modeConf) { return new HTMLMode(conf, modeConf); }); 173 | 174 | })); 175 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google_modes", 3 | "version": "1.0.0", 4 | "description": "Modes following Google's style", 5 | "main": "index.js", 6 | "scripts": { 7 | "build-cpp": "grammar-mode --es-module src/cpp.grammar --output src/cpp.mode.js && rollup -c rollup.config.js src/cpp.js -o dist/cpp.js", 8 | "build-clif": "grammar-mode --es-module src/clif.grammar --output src/clif.mode.js && rollup -c rollup.config.js src/clif.js -o dist/clif.js", 9 | "build-fbs": "grammar-mode --es-module src/flatbuffers.grammar --output src/flatbuffers.mode.js && rollup -c rollup.config.js src/flatbuffers.js -o dist/flatbuffers.js", 10 | "build-c": "grammar-mode --es-module src/c.grammar --output src/c.mode.js && rollup -c rollup.config.js src/c.js -o dist/c.js", 11 | "build-js": "grammar-mode --es-module src/javascript.grammar --output src/javascript.mode.js && rollup -c rollup.config.js src/javascript.js -o dist/javascript.js", 12 | "build-ts": "grammar-mode --es-module src/typescript.grammar --output src/typescript.mode.js && rollup -c rollup.config.js src/typescript.js -o dist/typescript.js", 13 | "build-py": "grammar-mode --es-module src/python.grammar --output src/python.mode.js && rollup -c rollup.config.js src/python.js -o dist/python.js", 14 | "build-go": "grammar-mode --es-module src/go.grammar --output src/go.mode.js && rollup -c rollup.config.js src/go.js -o dist/go.js", 15 | "build-java": "grammar-mode --es-module src/java.grammar --output src/java.mode.js && rollup -c rollup.config.js src/java.js -o dist/java.js", 16 | "build-kotlin": "grammar-mode --es-module src/kotlin.grammar --output src/kotlin.mode.js && rollup -c rollup.config.js src/kotlin.js -o dist/kotlin.js", 17 | "build-html": "grammar-mode --es-module src/html.grammar --output src/html.mode.js && rollup -c rollup.config.js src/html.js -o dist/html.js", 18 | "build-ng": "grammar-mode --es-module src/angulartemplate.grammar --output src/angulartemplate.mode.js && rollup -c rollup.config.js src/angulartemplate.js -o dist/angulartemplate.js", 19 | "build": "npm run build-js && npm run build-ts && npm run build-c && npm run build-cpp && npm run build-clif && npm run build-fbs && npm run build-py && npm run build-go && npm run build-java && npm run build-html && npm run build-ng && npm run build-kotlin", 20 | "test": "node test/run.js", 21 | "prepare": "npm run build && npm test" 22 | }, 23 | "dependencies": { 24 | "codemirror": "^5.42.2" 25 | }, 26 | "devDependencies": { 27 | "@rollup/plugin-buble": "^0.21.3", 28 | "codemirror-grammar-mode": "^0.1.10", 29 | "rollup": "^2.42.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import buble from "@rollup/plugin-buble" 2 | 3 | export default { 4 | external: ["codemirror", "codemirror-grammar-mode"], 5 | output: { 6 | globals: {"codemirror": "CodeMirror"}, 7 | format: "umd" 8 | }, 9 | plugins: [buble()] 10 | } 11 | -------------------------------------------------------------------------------- /src/angulartemplate.grammar: -------------------------------------------------------------------------------- 1 | extends "./html.grammar" 2 | 3 | element { 4 | "{{" ngExpression "}}" | super 5 | } 6 | 7 | attribute { 8 | (("*" | "#") spaceChar* attributeName | ("[" | "(")+ spaceChar* attributeName spaceChar* ("]" | ")")+ | bindOnAttributeName) spaceChar* 9 | ("=" spaceChar* ngAttributeValue spaceChar*)? | 10 | super 11 | } 12 | 13 | text { 14 | "\n" | (!("&" | "<" | "{{") .)+ 15 | } 16 | 17 | bindOnAttributeName="attribute" { 18 | ("bind" | "on")+ "-" wordChar+ 19 | } 20 | 21 | ngAttributeValue { 22 | quote ngExpression quote 23 | } 24 | 25 | skip (spaceChar | jsComment)* { 26 | ngExpression { ngBaseExpression ngExpressionSuffix* } 27 | 28 | ngBaseExpression { 29 | atom | 30 | kw("this") | 31 | kw("let" | "const" | "var") ngBaseExpression | 32 | (kw("typeof") | op("!" | "-")) ngBaseExpression | 33 | calleeName | 34 | variable | 35 | number | 36 | string | 37 | regexp | 38 | "[" CommaSep(ngExpression) "]" | 39 | "{" CommaSep(ngObjectMember) "}" | 40 | "(" ngExpression ")" 41 | } 42 | 43 | ngExpressionSuffix { 44 | (binOp | kw("in" | "instanceof" | "of" | "as" | "else")) ngExpression | 45 | "(" CommaSep(ngExpression) ")" | 46 | ("?." | ".") (calleeProp | propName) | 47 | "[" ngExpression "]" | 48 | op("?") ngExpression op(":") ngExpression | 49 | ";" (kw("else" | "then") ngExpression? | propName kw(":") ngExpression)? 50 | } 51 | 52 | ngObjectMember { 53 | (kw("get" | "set" | "async") !(" "* ("," | "}" | ":" | "(")))? 54 | ((propName | "[" ngExpression "]" | number | string) (":" ngExpression)? | 55 | op("...") ngExpression) 56 | } 57 | 58 | CommaSep(expr) { (expr ("," expr?)*)? } 59 | } 60 | 61 | quote="string" { "\"" } 62 | 63 | kw(value)="keyword" { value !identifierChar } 64 | op(value)="operator" { value } 65 | 66 | binOp { 67 | op("+" | "-" | "%" | "*" | slash | ">" ("=" | ">" ">"?)? | "<" ("=" | "<")? | "=" ("=" "="?)? | "&" "&"? | "|" "|"? | "^" | "!=" "="?) 68 | } 69 | 70 | jsComment="comment" { "/*" (!"*/" _)* "*/" | "//" .* } 71 | 72 | atom="atom" { ("true" | "false" | "null" | "undefined" | "NaN" | "Infinity") !identifierChar } 73 | 74 | letter { "a"-"z" | "A"-"Z" | "\u00a1"-"\uffff" | "_" } 75 | 76 | digit { "0"-"9" } 77 | 78 | identifierStart { letter | "_" | "$" } 79 | 80 | identifierChar { letter | digit | "_" | "$" } 81 | 82 | slash { "/" !("/" | "*") } 83 | 84 | identifier { identifierStart identifierChar* } 85 | 86 | propName="property" { identifier } 87 | variable="variable" { identifier } 88 | calleeName="variable callee" { identifier ~(" "* "(") } 89 | calleeProp="property callee" { identifier ~(" "* "(") } 90 | 91 | string="string" { "'" ("\\" _ | (!"'" .))* "'" } 92 | 93 | number="number" { 94 | "0x" (digit | "a"-"f" | "A"-"F")+ | 95 | "0o" "0"-"7"+ | 96 | "0b" ("0" | "1")+ | 97 | (digit+ ("." digit*)? | "." digit+) (("e" | "E") ("+" | "-")? digit+)? 98 | } 99 | 100 | regexp="string-2" { slash ("\\" . | .)+ "/" } 101 | -------------------------------------------------------------------------------- /src/angulartemplate.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./angulartemplate.mode" 4 | import {predicates, indent, contextInfo} from "./html_util" 5 | 6 | class AngularTemplateMode extends CodeMirror.GrammarMode { 7 | constructor(conf, modeConf) { 8 | super(grammar, {predicates}) 9 | this.conf = conf 10 | } 11 | 12 | indent(state, textAfter, line) { 13 | return indent(state, textAfter, line, this.conf) 14 | } 15 | } 16 | 17 | let proto = AngularTemplateMode.prototype 18 | proto.electricInput = /^\s*<\/.*?>/ 19 | proto.blockCommentStart = "" 21 | proto.fold = "xml" 22 | contextInfo(proto) 23 | 24 | CodeMirror.defineMode("google-angular-template", (conf, modeConf) => new AngularTemplateMode(conf, modeConf)) 25 | -------------------------------------------------------------------------------- /src/c.grammar: -------------------------------------------------------------------------------- 1 | include "./doxygen.grammar" as doccomment 2 | 3 | start top { 4 | preprocessorLine? (whitespace Statement)+ 5 | } 6 | 7 | skip whitespace { 8 | context Statement { 9 | Enum | 10 | Loop | 11 | Conditional | 12 | Switch | 13 | Block | 14 | breakCont ";" | 15 | goto identifier ";" | 16 | return Expressions? ";" | 17 | Struct | 18 | Label | 19 | Macro (Block | ExpressionSuffix*) | 20 | DeclType DeclRest | 21 | ";" | 22 | Expressions ";" 23 | } 24 | 25 | context DeclType { 26 | (modifier | qualifier)+ (auto TypeSuffixNoBrackets* | typeName TypeSuffix*) | 27 | typeModifier+ modifiableType? TypeSuffix* | 28 | MaybeType 29 | } 30 | 31 | DeclRest { 32 | Declarator Macro? 33 | (~("(" (")" | modifier | qualifier | typeModifier | auto | maybeTypeName)) FunctionDef | 34 | Initializer? ("," declName Initializer?)* ";") 35 | } 36 | 37 | Declarator { 38 | declOp* declName ("[" "]")* | "(" Declarator ")" 39 | } 40 | 41 | Loop { 42 | for "(" Statement Expressions? ";" Expressions? ")" Statement | 43 | while CondExpr Statement | 44 | do Statement while CondExpr ";" 45 | } 46 | 47 | Switch { 48 | switch CondExpr Block 49 | } 50 | 51 | Label { 52 | (default | case Expression | labelIdentifier) ":" 53 | } 54 | 55 | context Block { 56 | "{" Statement* "}" 57 | } 58 | 59 | context BlockOf(element, separator) { 60 | "{" (element (separator element?)*)? "}" 61 | } 62 | 63 | Enum { enum typeDeclName? BlockOf(propDeclName (op("=") Expression)?, ",")? } 64 | 65 | Initializer { op("=") Expression } 66 | 67 | context FunctionDef { ParamList (";" | Block) } 68 | 69 | context ParamList { "(" ListOf(Type (Declarator ParamList? (op("=") Expression)?)? "..."? | "...") ")" } 70 | 71 | Expression { 72 | ExpressionPrefix* BaseExpression ExpressionSuffix* 73 | } 74 | 75 | Expressions { 76 | Expression ("," Expression)* 77 | } 78 | 79 | ExpressionPrefix { 80 | prefixOp 81 | } 82 | 83 | BaseExpression { 84 | ParenExpr (!("[" | "(" | "-" | "+") Expression)? | 85 | atom | 86 | number | 87 | string string* | 88 | BlockOf(Expression, ",") | 89 | sizeof ("(" Type ")" | "..."? Expression) | 90 | Macro | 91 | variableName 92 | } 93 | 94 | context ParenExpr { "(" Expressions? ")" } 95 | context CondExpr { "(" Expressions? ")" } 96 | 97 | ExpressionSuffix { 98 | ArgList | 99 | "[" Expression "]" | 100 | suffixOp | 101 | ("->" | !".." ".") fieldName | 102 | binOp Expression? | 103 | "?" Expression ":" Expression 104 | } 105 | 106 | context ArgList { 107 | "(" ListOf(Expression) ")" 108 | } 109 | 110 | MaybeType { 111 | (auto TypeSuffixNoBrackets* | maybeTypeName TypeSuffix*) 112 | } 113 | 114 | Type { 115 | (modifier | qualifier)* structUnion? (auto | typeName) TypeSuffix* 116 | } 117 | 118 | Struct { 119 | structUnion declName? BlockOf(StructField, ";")? declName? ";" 120 | } 121 | 122 | StructField { 123 | Type fieldName? (":" number | "[" Expression? "]")? 124 | } 125 | 126 | TypeSuffixNoBrackets { 127 | ("*" | "&") | 128 | qualifier 129 | } 130 | 131 | TypeSuffix { 132 | "[" Expression? "]" | 133 | TypeSuffixNoBrackets 134 | } 135 | 136 | ListOf(expr) { 137 | (expr ("," expr)*)? 138 | } 139 | 140 | Macro { 141 | macroName ParenTokens? 142 | } 143 | 144 | context ParenTokens { "(" BalancedToken* ")" } 145 | context BracketTokens { "[" BalancedToken* "]" } 146 | context BraceTokens { "{" BalancedToken* "}" } 147 | 148 | BalancedToken { 149 | ParenTokens | BracketTokens | BraceTokens | 150 | keyword | atom | number | string | binOp | prefixOp | variableToken | 151 | !(")" | "]" | "}") . 152 | } 153 | } 154 | 155 | Conditional { 156 | if whitespace CondExpr whitespace Statement Alternative 157 | } 158 | 159 | context Alternative { 160 | whitespace (else whitespace Statement)? 161 | } 162 | 163 | tokens { 164 | enum { kw("enum") } 165 | return { kw("return") } 166 | if { kw("if") } 167 | else { kw("else") } 168 | for { kw("for") } 169 | while { kw("while") } 170 | do { kw("do") } 171 | breakCont { kw("break" | "continue") } 172 | goto { kw("goto") } 173 | default { kw("default") } 174 | case { kw("case") } 175 | switch { kw("switch") } 176 | structUnion { kw("struct" | "union") } 177 | sizeof { kw("sizeof" | "alignof") } 178 | auto { kw("auto") } 179 | modifier { kw("register" | "static" | "extern" | "typedef") } 180 | typeModifier="type" { ("unsigned" | "signed" | "long") !identifierChar } 181 | modifiableType="type" { ("int" | "float" | "double" | "char" | "short") !identifierChar } 182 | qualifier { kw("const" | "volatile" | "restrict") } 183 | 184 | atom="atom" { ("true" | "false" | "null") !identifierChar } 185 | 186 | macroName="meta" { 187 | "_" ("A"-"Z" | digit | "_")+ !identifierChar | 188 | "A"-"Z" ("A"-"Z" | digit | "_")+ !identifierChar 189 | } 190 | 191 | variableName { plainVariableName } 192 | 193 | number="number" { 194 | ("0x" (digit | "a"-"f" | "A"-"F")+ | 195 | (digit+ ("." digit*)? | "." digit+) (("e" | "E") "-"? digit+)?) 196 | ("L" | "l" | "U" | "u" | "F" | "f")? 197 | } 198 | 199 | string="string" { 200 | (("L" | "u" "8"? | "U") ~("'" | "\""))? 201 | ("'" ("\\" .)? (!"'" .)* "'" | 202 | "\"" ("\\" _ | (!"\"" _))* "\"") 203 | } 204 | 205 | prefixOp="operator" { 206 | "+" "+"? | "-" "-"? | "!" | "~" | "&" | "*" 207 | } 208 | 209 | suffixOp="operator" { 210 | "++" | "--" 211 | } 212 | 213 | binOp="operator" { 214 | ("!" | "+" | "-" | "/" | "*" | "%" | ">" ">"? | "<" "<"? | "=" | "|" "|"? | "&" "&"?) "="? 215 | } 216 | 217 | comment="comment" { doccomment.comment | "/*" (!"*/" _)* "*/" | "//" .* } 218 | } 219 | 220 | keyword { 221 | kw("auto" | "double" | "int" | "struct" | "break" | "else" | "long" | "switch" | "case" | "enum" | "register" | "typedef" | "char" | "extern" | "return" | "union" | "const" | "float" | "short" | "unsigned" | "continue" | "for" | "signed" | "void" | "default" | "goto" | "sizeof" | "volatile" | "do" | "if" | "static" | "while" | "asm" | "alignof") 222 | } 223 | 224 | variableToken { plainVariableName } 225 | 226 | declOp { "*" } 227 | 228 | maybeCallee { callee | identifier } 229 | callee="callee" { identifier ~(" "* "(") } 230 | 231 | plainVariableName="variable" { maybeCallee } 232 | 233 | identifier { identifierStart identifierChar* } 234 | 235 | whitespace { 236 | (" " | "\t" | 237 | "\n" (" " | "\t")* preprocessorLine? | 238 | comment)* 239 | } 240 | 241 | preprocessorLine="meta" { "#" (comment | "\\" _ | .)* } 242 | 243 | declName="def" { identifier } 244 | propDeclName="def property" { identifier } 245 | typeDeclName="type def" { identifier } 246 | 247 | fieldName="property" { maybeCallee } 248 | 249 | typeName { typeModifier+ (whitespace modifiableType)? | typeNameInner } 250 | 251 | typeNameInner="type" { identifier } 252 | 253 | maybeTypeName { 254 | // The lookahead tries to figure out whether this identifier is 255 | // followed by optionally some type suffix and then another identifier 256 | typeNameInner ~(!identifierChar whitespace (TypeSuffix whitespace)* 257 | (identifierStart | "(" whitespace "*" whitespace identifier whitespace ")" whitespace "(")) 258 | } 259 | 260 | kw(value)="keyword" { value !identifierChar } 261 | op(value)="operator" { value } 262 | 263 | letter { "a"-"z" | "A"-"Z" | "\u00a1"-"\uffff" | "_" } 264 | 265 | digit { "0"-"9" } 266 | 267 | identifierStart { letter } 268 | 269 | identifierChar { letter | digit } 270 | 271 | spaceChar { "\n" | "\t" | " " } 272 | 273 | labelIdentifier { identifier ~(spaceChar* ":" !":") } 274 | -------------------------------------------------------------------------------- /src/c.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./c.mode" 4 | import {markLocals} from "./locals" 5 | import {indent} from "./c_indent" 6 | 7 | const scopes = ["Block", "FunctionDef"] 8 | 9 | class CMode extends CodeMirror.GrammarMode { 10 | constructor(conf) { 11 | super(grammar) 12 | this.conf = conf 13 | } 14 | 15 | token(stream, state) { 16 | return markLocals(super.token(stream, state), scopes, stream, state) 17 | } 18 | 19 | indent(state, textAfter, line) { 20 | if (textAfter.charAt(0) == "#") return 0 21 | return indent(state, textAfter, line, this.conf) 22 | } 23 | } 24 | 25 | CMode.prototype.electricInput = /^\s*(?:case .*?:|default:|\{\}?|\})$/ 26 | CMode.prototype.blockCommentStart = "/*" 27 | CMode.prototype.blockCommentEnd = "*/" 28 | CMode.prototype.blockCommentContinue = " * " 29 | CMode.prototype.lineComment = "//" 30 | CMode.prototype.fold = "brace" 31 | 32 | CodeMirror.defineMode("google-c", conf => new CMode(conf)) 33 | -------------------------------------------------------------------------------- /src/c_indent.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | 3 | function hasSubStatement(context) { 4 | let m = /^(if|for|do|while|try)\b/.exec(context.startLine.slice(context.startPos)) 5 | return m && m[1] 6 | } 7 | 8 | function isSwitch(context) { 9 | return context && context.name == "Statement" && 10 | /^switch\b/.test(context.startLine.slice(context.startPos)) 11 | } 12 | 13 | function isLabel(text) { 14 | return text && /^\s*(case|default)\b/.test(text) 15 | } 16 | 17 | function aligned(cx) { 18 | return !/^\s*((\/\/.*)?$|.*=>)/.test(cx.startLine.slice(cx.startPos + 1)) 19 | } 20 | 21 | const bracketed = { 22 | Block: "}", BlockOf: "}", ClassBody: "}", AnnotationTypeBody: "}", ObjectLiteral: "}", 23 | ObjectPattern: "}", EnumBody: "}", LambdaBlock: "}", WhenBody: "}", 24 | ObjType: "}", ArrayInitializer: "}", NamespaceBlock: "}", BraceTokens: "}", 25 | ArrayLiteral: "]", BracketTokens: "]", TupleType: "]", 26 | ParamList: ")", SimpleParamList: ")", ArgList: ")", ParenExpr: ")", CondExpr: ")", ForSpec: ")", ParenTokens: ")", 27 | ParenthesizedExpression: ")", ConstructorParamList: ")", 28 | TypeParams: ">", TypeArgs: ">", TemplateArgs: ">", TemplateParams: ">" 29 | } 30 | 31 | const blockish = ["Block", "NamespaceBlock", "ClassBody", "AnnotationTypeBody", "BlockOf", "EnumBody"] 32 | 33 | const statementish = ["Statement", "ObjectMember", "ClassItem", "EnumConstant", "AnnotationTypeItem", "ArgExpr", "StatementMaybeOf", "NewExpr"] 34 | 35 | function baseIndent(cx, config) { 36 | for (let startLine = cx.startLine;; cx = cx.parent) { 37 | if (cx.name == "CondExpr") 38 | return CodeMirror.countColumn(cx.startLine, cx.startPos + 1, config.tabSize) 39 | if (statementish.indexOf(cx.name) > -1 && /(^\s*|[\(\{\[])$/.test(cx.startLine.slice(0, cx.startPos))) 40 | return CodeMirror.countColumn(cx.startLine, cx.startPos, config.tabSize) 41 | if (!cx.parent || cx.parent.startLine != startLine) 42 | return CodeMirror.countColumn(cx.startLine, null, config.tabSize) 43 | } 44 | } 45 | 46 | function findIndent(cx, textAfter, config) { 47 | if (!cx) return 0 48 | if (cx.name == "string" || cx.name == "comment") return CodeMirror.Pass 49 | 50 | let brack = bracketed[cx.name] 51 | let closed = textAfter && textAfter.charAt(0) == brack 52 | if (brack && config.align !== false && (!config.dontAlign || config.dontAlign.indexOf(cx.name) < 0) && aligned(cx)) 53 | return CodeMirror.countColumn(cx.startLine, cx.startPos, config.tabSize) + (closed ? 0 : 1) 54 | 55 | if (brack && blockish.indexOf(cx.name) > -1) { 56 | let parent = cx.parent 57 | if (parent && parent.name == "Statement" && parent.parent && 58 | parent.parent.name == "Statement" && hasSubStatement(parent.parent) && !hasSubStatement(parent)) 59 | parent = parent.parent 60 | let base = statementIndent(parent, config) 61 | 62 | if (closed || cx.name == "NamespaceBlock") return base 63 | if (/^(public|private|protected)\s*:/.test(textAfter)) return base + 1 64 | if (isSwitch(cx.parent) && !isLabel(textAfter)) return base + 2 * config.indentUnit 65 | return base + config.indentUnit 66 | } 67 | 68 | let base = baseIndent(cx, config) 69 | if (brack) { 70 | if (closed && (config.dontCloseBrackets || "").indexOf(brack) < 0) return base 71 | return base + config.indentUnit * ((config.doubleIndentBrackets || "").indexOf(brack) < 0 ? 1 : 2) 72 | } else if (statementish.indexOf(cx.name) > -1) { 73 | if (hasSubStatement(cx)) return base + config.indentUnit; 74 | return base + 2 * config.indentUnit 75 | } else if (cx.name == "Alternative" || cx.name == "CatchFinally") { 76 | base = baseIndent(cx.parent, config) 77 | if (!textAfter || /^((else|catch|finally)\b|\/[\/\*])/.test(textAfter)) return base 78 | return base + config.indentUnit 79 | } else if (cx.name == "ArrowRest") { 80 | return base + config.indentUnit 81 | } else if (cx.name == "NewExpression" && cx.startLine.length > cx.startPos + 5) { 82 | return CodeMirror.countColumn(cx.startLine, cx.startPos, config.tabSize) + 2 * config.indentUnit 83 | } else if (cx.name == "InitializerList") { 84 | return base + 2 85 | } else if (cx.name == "ThrowsClause" && !/throws\s*$/.test(cx.startLine.slice(cx.startPos))) { 86 | return base + 2 * config.indentUnit 87 | } else { 88 | return findIndent(cx.parent, textAfter, config) 89 | } 90 | } 91 | 92 | function statementIndent(cx, config) { 93 | for (;; cx = cx.parent) { 94 | if (!cx) return 0 95 | if (statementish.indexOf(cx.name) > -1 || (cx.parent && bracketed[cx.parent.name])) 96 | return CodeMirror.countColumn(cx.startLine, null, config.tabSize) 97 | } 98 | } 99 | 100 | export function indent(state, textAfter, line, config) { 101 | let top = state.context && state.context.name 102 | if (top == "DeclType" || top == "BeforeStatement" || top == "AnnotationHead" || top == "Template" || top == "str") 103 | return statementIndent(state.context, config) 104 | 105 | if ((top == "doccomment.braced" || top == "doccomment.tagGroup") && !/^[@*]/.test(textAfter)) 106 | return CodeMirror.countColumn(state.context.startLine, null, config.tabSize) + 2 * config.indentUnit 107 | 108 | let passLine = config.forceContent && /^\s*(\/\/.*)?$/.test(line) ? "x" : line 109 | return findIndent(state.contextAt(passLine, line.length - textAfter.length), textAfter, config) 110 | } 111 | -------------------------------------------------------------------------------- /src/clif.grammar: -------------------------------------------------------------------------------- 1 | skip whitespace { 2 | start top { whitespace ("\n" | Statement)* } 3 | 4 | context Statement { 5 | FromStatement | 6 | InterfaceStatement | 7 | FuncDef | 8 | ClassDef | 9 | EnumDef | 10 | InterfaceStatement | 11 | StaticMethodsStatement | 12 | NamespaceStatement | 13 | SimpleStatement "\n" 14 | } 15 | 16 | SimpleStatement { 17 | CapsuleDef | 18 | ImplementsDef | 19 | ImportStatement | 20 | IncludeStatement | 21 | UseStatement | 22 | TypeDefStatement | 23 | ConstDef | 24 | VarDef | 25 | Decorator | 26 | enumEntry | 27 | pass | 28 | qstring !(":" | import) | 29 | return name "(" op("...") ")" | 30 | name !":" 31 | } 32 | 33 | FromStatement { 34 | !(from (DottedName | qstring import)) from qstring ":" indentedBody 35 | } 36 | 37 | IncludeStatement { 38 | !(from (DottedName | qstring ":")) from qstring import "*" (as d(name))? 39 | } 40 | 41 | ImportStatement { !(from qstring) from DottedName import name } 42 | 43 | TypeDefStatement { type d(name) "=" Type } 44 | 45 | UseStatement { use rename DottedName } 46 | 47 | NamespaceStatement { namespace astring ":" indentedBody } 48 | 49 | InterfaceStatement { 50 | interface d(name) TypeParams ":" indentedBody 51 | } 52 | context TypeParams { "<" CommaSep(name) ">" } 53 | 54 | StaticMethodsStatement { 55 | staticmethods from astring ":" indentedBody 56 | } 57 | 58 | ConstDef { const d(cname) ":" Type } 59 | 60 | CapsuleDef { capsule cname } 61 | 62 | EnumDef { enum cname (with ":" indentedBody)? } 63 | enumEntry { rename DottedName } 64 | 65 | VarDef { ~(cname ":") cname ":" Type ("=" property "(" astring ("," astring)? ")")? } 66 | 67 | ClassDef { class cname Bases? ":" indentedBody } 68 | context Bases { "(" CommaSep(tname) ")" } 69 | 70 | ImplementsDef { implements name QualifiedTypes } 71 | context QualifiedTypes { "<" CommaSep(DottedName) ">" } 72 | 73 | FuncDef { def cname Params (Returns (":" indentedBody)?)? } 74 | 75 | Type { 76 | rename? (!(lambda | "(") DottedName Types? | lambda? Params Returns) 77 | } 78 | context Types { "<" CommaSep(Type) ">" } 79 | 80 | ParamDef { locald(name) (":" Type ("=" default)?)? } 81 | context Params { "(" CommaSep(receiver | ParamDef) ")" } 82 | Returns { "->" (None | Type | Params) } 83 | 84 | DottedName { name ("." name)* } 85 | 86 | Decorator="meta" { "@" DottedName } 87 | 88 | rename { astring as } 89 | cname { rename? d(name) } 90 | tname { rename? DottedName } 91 | CommaSep(expr) { (expr ("," expr?)* ","?)? } 92 | } 93 | 94 | tokens { 95 | as { kw("as") } 96 | capsule { kw("capsule") } 97 | class { kw("class") } 98 | const { kw("const") } 99 | def { kw("def") } 100 | default { kw("default") } 101 | enum { kw("enum") } 102 | from { kw("from") } 103 | implements { kw("implements") } 104 | import { kw("import") } 105 | interface { kw("interface") } 106 | lambda { kw("lambda") } 107 | namespace { kw("namespace") } 108 | pass { kw("pass") } 109 | property { kw("property") } 110 | return { kw("return") } 111 | staticmethods { kw("staticmethods") } 112 | type { kw("type") } 113 | use { kw("use") } 114 | with { kw("with") } 115 | 116 | None { atom("None") } 117 | receiver { atom("self" | "cls") } 118 | 119 | comment="comment" { "#" .* } 120 | } 121 | 122 | qstring="string" { 123 | "'''" ("\\" _ | !"'''" _)* "'''" | 124 | "\"\"\"" ("\\" _ | !"\"\"\"" _)* "\"\"\"" | 125 | "'" ("\\" _ | !"'" .)* "'" | 126 | "\"" ("\\" _ | !"\"" .)* "\"" 127 | } 128 | astring="string" { "`" (!"`" .)* "`" } 129 | 130 | atom(word)="atom" { word !nameChar } 131 | kw(word)="keyword" { word !nameChar } 132 | 133 | d(word)="def" { word } 134 | locald(word)="variable-2" { word } 135 | op(expr)="operator" { expr } 136 | 137 | context indentedBody { 138 | "\n" (whitespaceSimple | "\n")* (&stillIndented Statement (whitespaceSimple | "\n")*)+ 139 | } 140 | 141 | name { nameStart nameChar* } 142 | 143 | whitespaceSimple { (" " | "\t" | comment) } 144 | 145 | whitespace { (whitespaceSimple | ~"\n" &maySkipNewline "\n")* } 146 | 147 | nameStart { letter | "_" } 148 | nameChar { letter | digit | "_" } 149 | letter { "a"-"z" | "A"-"Z" } 150 | digit { "0"-"9" } 151 | -------------------------------------------------------------------------------- /src/clif.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./clif.mode" 4 | import {markLocals} from "./locals" 5 | 6 | const scopes = ["FuncDef", "ClassDef"] 7 | 8 | const allowNewline = [ 9 | "Bases", "Params", "Types", "QualifiedTypes", "TypeParams", 10 | ] 11 | 12 | function maySkipNewline(_line, _pos, cx) { 13 | return cx && allowNewline.indexOf(cx.name) > -1 14 | } 15 | 16 | function countIndent(line, pos) { 17 | let count = 0 18 | for (let i = pos - 1; i >= 0; i--) { 19 | let ch = line.charCodeAt(i) 20 | if (ch === 32) count++ 21 | else if (ch === 9) count += 4 22 | else break 23 | } 24 | return count 25 | } 26 | 27 | function stillIndented(line, pos, cx) { 28 | while (cx && cx.name != "Statement") cx = cx.parent 29 | return cx && countIndent(line, pos) > countIndent(cx.startLine, cx.startPos) 30 | } 31 | 32 | function aligned(cx) { 33 | return !/^\s*((#.*)?$)/.test(cx.startLine.slice(cx.startPos + 1)) 34 | } 35 | 36 | const bracketed = { 37 | Bases: ")", Params: ")", 38 | Types: ">", QualifiedTypes: ">", TypeParams: ">", 39 | } 40 | 41 | 42 | function findIndent(cx, textAfter, curLine, config) { 43 | if (!cx) return 0 44 | if (cx.name == "string") return CodeMirror.Pass 45 | 46 | let brack = bracketed[cx.name] 47 | if (brack) { 48 | if (curLine != cx.startLine && aligned(cx)) { 49 | return CodeMirror.countColumn(cx.startLine, cx.startPos, config.tabSize) + 1 50 | } 51 | 52 | let closed = textAfter && textAfter.charAt(0) == brack 53 | let flat = closed || curLine == cx.startLine 54 | return findIndent(cx.parent, closed ? null : textAfter, cx.startLine, config) + (flat ? 0 : 2 * config.indentUnit) 55 | } else if (cx.name == "indentedBody") { 56 | for (;; cx = cx.parent) { 57 | if (!cx) return config.indentUnit 58 | if (cx.name == "Statement") return CodeMirror.countColumn(cx.startLine, null, config.tabSize) + config.indentUnit 59 | } 60 | } else { 61 | return findIndent(cx.parent, textAfter, curLine, config) + 62 | (cx.name == "Statement" && curLine != cx.startLine ? 2 * config.indentUnit : 0) 63 | } 64 | } 65 | 66 | 67 | class ClifMode extends CodeMirror.GrammarMode { 68 | constructor(conf) { 69 | super(grammar, { 70 | predicates: {maySkipNewline, stillIndented}, 71 | }) 72 | this.conf = conf 73 | } 74 | 75 | token(stream, state) { 76 | return markLocals(super.token(stream, state), scopes, stream, state) 77 | } 78 | 79 | indent(state, textAfter, line) { 80 | return findIndent(state.contextAt(line, line.length - textAfter.length), textAfter, null, this.conf) 81 | } 82 | } 83 | 84 | ClifMode.prototype.electricInput = /^\s*\(\)<>$/ 85 | ClifMode.prototype.closeBrackets = {triples: "'\"", pairs: "()<>''\"\"``",} 86 | ClifMode.prototype.lineComment = "#" 87 | ClifMode.prototype.fold = "indent" 88 | 89 | CodeMirror.defineMode("google-clif", conf => new ClifMode(conf)) 90 | CodeMirror.defineMIME("text/x-clif", {name: "google-clif"}) 91 | -------------------------------------------------------------------------------- /src/cpp.grammar: -------------------------------------------------------------------------------- 1 | extends "./c.grammar" 2 | 3 | skip whitespace { 4 | context Statement { 5 | Attributes | 6 | Class declName? ";" | 7 | StaticAssert | 8 | namespace declName? (op("=") variableName ";" | NamespaceBlock) | 9 | throw Expression ";" | 10 | try Block Catch | 11 | asm "{" string "}" | 12 | Using | 13 | Template | 14 | &constructorAhead declName FunctionDef | 15 | super 16 | } 17 | 18 | TypeSuffix { 19 | TemplateArgs | 20 | "::" (operator overloadableOp | qualifiedTypeName) | 21 | Attributes | 22 | super 23 | } 24 | 25 | BaseExpression { 26 | this | 27 | Lambda | 28 | cast "<" Type ">" "(" Expression ")" | 29 | BlockOf(("." fieldName op("="))? Expression, ",") | 30 | super 31 | } 32 | 33 | ExpressionNoGt { 34 | ExpressionPrefix* BaseExpression (!">" ExpressionSuffix)* 35 | } 36 | 37 | ExpressionSuffix { 38 | BlockOf(("." fieldName op("="))? Expression, ",") | 39 | ArgList Block? | 40 | ("->" | !".." ".") "*"? fieldName TemplateArgs? | 41 | super 42 | } 43 | 44 | context Lambda { 45 | "[" !"[" ListOf("&"? variableName? | "=" | this) "]" (FunctionDef | Block) 46 | } 47 | 48 | context Catch { (catch "(" Type Declarator? ")" Block)* } 49 | 50 | context FunctionDef { 51 | ParamList 52 | qualifier* 53 | ("&&" | "&")? 54 | (noexcept ("(" Expression ")")? | throw "(" ListOf(Type) ")")? 55 | Attributes? 56 | ("->" Type)? 57 | virtSpec* 58 | InitializerList? 59 | (";" | Block | op("=") (default | delete) ";") 60 | } 61 | 62 | context Template { 63 | export? template TemplateParams? whitespace Statement 64 | } 65 | 66 | Using { 67 | using (typename Type | namespace? variableName) (op("=") Type Declarator?)? ";" 68 | } 69 | 70 | context InitializerList { (":" ListOf(CtorInitializer)) } 71 | 72 | CtorInitializer { 73 | NameQualifier(variableQualifier)* fieldName 74 | TemplateArgs? 75 | ("(" ListOf(Expression) ")" | "{" ListOf(Expression) "}") 76 | } 77 | 78 | ExpressionPrefix { 79 | delete ("[" "]")? | new ("[" "]")? ("(" Expression ")")? Attributes? | super 80 | } 81 | 82 | Type { 83 | typename Type | 84 | Class | 85 | super 86 | } 87 | 88 | Declarator { 89 | declOp* ("[" declName ("," declName)* "]" | declName ("[" "]")*) | "(" Declarator ")" 90 | } 91 | 92 | context TemplateParams { 93 | "<" ListOf(TypeParam | Type "..."* Declarator ParamList? (modifier | qualifier)* (op("=") ExpressionNoGt)?) ">" 94 | } 95 | 96 | TypeParam { 97 | template TemplateParams class "..."? typeDeclName? (op("=") (variableName | number))? | 98 | (class | typename) "..."? typeDeclName? (op("=") Type)? 99 | } 100 | 101 | context TemplateArgs { 102 | "<" ListOf(TypeArg | modifier* (~(number | string) ExpressionNoGt | Type (ParamList | Initializer | (!">" ExpressionSuffix)+)?) "..."?) ">" 103 | } 104 | 105 | TypeArg { 106 | (template TemplateArgs)? (class | typename) Type 107 | } 108 | 109 | Class { 110 | (class | structUnion) Attributes? (NameQualifier(typeQualifier)+ qualifiedTypeName | typeDeclName) classVirtSpec* 111 | (":" ListOf(virtual? access? Type))? ClassBody? 112 | } 113 | 114 | context ClassBody { 115 | "{" ClassItem* "}" 116 | } 117 | 118 | context ClassItem { 119 | access ":" | Template | Using | StaticAssert | Macro ";"? | modifier* (Enum ";"? | Class declName? ";"? | ObjectMember) 120 | } 121 | 122 | context ObjectMember { 123 | (modifier | qualifier)* 124 | (ctorDtorName | Type PropDeclarator ("," PropDeclarator)*) 125 | (FunctionDef | (Initializer | ":" number | "[" Expression? "]")? ";" | Macro ";"?) 126 | } 127 | 128 | PropDeclarator { 129 | declOp* propDeclName ("[" "]")* | "(" PropDeclarator ")" 130 | } 131 | 132 | Initializer { super | BlockOf(Expression, ",") | ArgList } 133 | 134 | context NamespaceBlock { "{" Statement* "}" } 135 | 136 | Attributes { 137 | (alignas "(" number ")" | Attribute)+ 138 | } 139 | Attribute { 140 | ~("[" " "* "[") "[" "[" ListOf(NameQualifier(attributeName)* attributeName ("(" BalancedAttributeToken* ")")? "..."?) "]" "]" 141 | } 142 | BalancedAttributeToken { 143 | number | string | identifier | binOp | "," | 144 | "(" BalancedAttributeToken* ")" | "[" BalancedAttributeToken* "]" | "{" BalancedAttributeToken* "}" 145 | } 146 | 147 | context ArgList { 148 | "(" ListOf(Expression "..."?) ")" 149 | } 150 | 151 | context CondExpr { 152 | "(" ( 153 | !(identifier "&&") DeclType Declarator Macro? Initializer? ("," declName Initializer?)* (";" Expression?)? | 154 | Expressions 155 | )? ")" 156 | } 157 | 158 | StaticAssert { 159 | staticAssert ArgList ";" 160 | } 161 | 162 | MatchingAngleBrackets { 163 | "<" (!">" (MatchingAngleBrackets | string | _))* ">" 164 | } 165 | 166 | Enum { enum (class | kw("struct"))? Attributes? typeDeclName? (":" Type)? BlockOf(propDeclName (op("=") Expression)?, ",")? } 167 | } 168 | 169 | NameQualifier(type) { 170 | ("::" | ~(type MatchingAngleBrackets? whitespace "::") type TemplateArgs? whitespace "::") 171 | whitespace "*"? 172 | } 173 | 174 | tokens { 175 | namespace { kw("namespace") } 176 | typename { kw("typename") } 177 | new { kw("new") } 178 | delete { kw("delete") } 179 | this { kw("this") } 180 | try { kw("try") } 181 | catch { kw("catch") } 182 | throw { kw("throw") } 183 | noexcept { kw("noexcept") } 184 | asm { kw("asm") } 185 | export { kw("export") } 186 | template { kw("template") } 187 | class { kw("class") } 188 | virtual { kw("virtual") } 189 | access { kw("private" | "public" | "protected") } 190 | operator { kw("operator") } 191 | using { kw("using") } 192 | alignas { kw("alignas") } 193 | staticAssert { kw("static_assert") } 194 | cast { kw(("dynamic" | "static" | "const" | "reinterpret") "_cast") } 195 | virtSpec { kw("override" | "final" | "new") } 196 | classVirtSpec { kw("final" | "explicit") } 197 | atom="atom" { "nullptr" !identifierChar | super } 198 | 199 | variableName { 200 | NameQualifier(variableQualifier)+ 201 | (operator overloadableOp | qualifiedInitializedName | qualifiedVariableName) (TemplateArgs (~"::" variableName)?)? | 202 | initializedName | 203 | unqualifiedVariableName TemplateArgs? 204 | } 205 | 206 | modifier { kw("inline" | "virtual" | "explicit" | "friend" | "constexpr" | "mutable" | "thread_local") | super } 207 | 208 | prefixOp="operator" { 209 | typename | super 210 | } 211 | 212 | number="number" { 213 | ("0x" (digit | "a"-"f" | "A"-"F" | "'")+ | 214 | "0b" ("0" | "1" | "'")+ | 215 | (digit digits ("." digits)? | "." digit digits) (("e" | "E") "-"? digits)?) 216 | (("L" | "l")+ | (("U" | "u") ("l" | "L")*) | "F" | "f")? 217 | } 218 | 219 | string="string" { 220 | "R\"" (!"(" .)* "(" (&rawStringContinues _)* "\"" | super 221 | } 222 | } 223 | 224 | keyword { 225 | super | kw("alignas" | "asm" | "bool" | "catch" | "class" | "compl" | "concept" | "constexpr" | "const_cast" | "decltype" | "delete" | "dynamic_cast" | "explicit" | "export" | "friend" | "import" | "module" | "mutable" | "namespace" | "new" | "noexcept" | "nullptr" | "operator" | "private" | "protected" | "public" | "reinterpret_cast" | "requires" | "static_assert" | "static_cast" | "synchronized" | "template" | "this" | "throw" | "try" | "typedef" | "typeid" | "using" | "virtual" | "wchar_t") 226 | } 227 | 228 | variableToken { 229 | ("::" | ~(identifier "::") variableQualifier "::")+ qualifiedVariableName | 230 | unqualifiedVariableName 231 | } 232 | 233 | digits { (digit | "'")* } 234 | 235 | variableQualifier="variable qualifier" { identifier } 236 | 237 | attributeName="meta" { identifier } 238 | 239 | rawPropDeclName="def property" { identifier } 240 | propDeclName { operator overloadableOp | rawPropDeclName } 241 | 242 | declName { 243 | operator overloadableOp | 244 | NameQualifier(declQualifier)+ (operator overloadableOp | qualifiedDeclName) | 245 | unqualifiedDeclName 246 | } 247 | 248 | overloadableOp { op("->*") | "," | op("==") | op("=") | binOp | prefixOp | "(" ")" | "[" "]" | (new | delete) ("[" "]")? } 249 | 250 | declOp { "*" | "&&" | "&" | "..." } 251 | 252 | unqualifiedDeclName="def" { "~"? identifier } 253 | qualifiedDeclName="qualified def" { "~"? identifier } 254 | declQualifier="qualifier def" { identifier } 255 | 256 | initializedName="type" { identifier ~"{" } 257 | qualifiedInitializedName="type qualified" { identifier ~"{" } 258 | 259 | unqualifiedVariableName="variable" { maybeCallee } 260 | 261 | qualifiedVariableName="qualified" { unqualifiedVariableName } 262 | 263 | typeNameInner { (typename whitespace)? (NameQualifier(typeQualifier)+ qualifiedTypeName | unqualifiedTypeName) } 264 | 265 | unqualifiedTypeName="type" { identifier } 266 | qualifiedTypeName="type qualified" { identifier } 267 | typeQualifier="type qualifier" { identifier } 268 | 269 | maybeTypeName { 270 | ~(!(("new" | "delete") !identifierChar) typeNameInner 271 | whitespace (TypeSuffix whitespace)* 272 | (identifierStart | "..." | "(" whitespace "*" whitespace identifier whitespace ")" whitespace "(")) 273 | typeNameInner 274 | } 275 | 276 | ctorDtorName="def" { &localConstructorAhead "~"? identifier } 277 | -------------------------------------------------------------------------------- /src/cpp.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as cpp from "./cpp.mode" 4 | import {markLocals, markTypeLocals} from "./locals" 5 | import {indent} from "./c_indent" 6 | 7 | function constructorAhead(line, pos, _cx, nextLines) { 8 | let m1 = /^(\w+)\s*(::\s*(?:~?(\w+)|$)|$)/.exec(line.slice(pos)) 9 | if (!m1) return false 10 | if (m1[3]) return m1[3] == m1[1] 11 | let m2 = (m1[2] ? /^\s*~?(\w+)/ : /^\s*::\s*~?(\w+)/).exec(nextLines && nextLines(1) || "") 12 | return m2 && m2[1] == m1[1] 13 | } 14 | 15 | function localConstructorAhead(line, pos, cx) { 16 | let ahead = /^~?(\w+)\s*\(/.exec(line.slice(pos)), skippedItem = false 17 | if (!ahead) return false 18 | while (!(cx.name == "Statement" || skippedItem && cx.name == "ClassItem")) { 19 | if (cx.name == "ClassItem") skippedItem = true 20 | cx = cx.parent 21 | } 22 | let className = /\b(?:class|struct)\s+(\w+)/.exec(cx.startLine.slice(cx.startPos)) 23 | return className ? className[1] == ahead[1] : false 24 | } 25 | 26 | const rawStringOpen = /R"(.*?)\(/g 27 | 28 | function rawStringContinues(line, pos, cx) { 29 | rawStringOpen.lastIndex = cx.startPos 30 | let open = rawStringOpen.exec(cx.startLine) 31 | if (!open) return false 32 | let closing = ")" + open[1] + '"' 33 | return pos < closing.length - 1 || line.slice(pos - closing.length + 1, pos + 1) != closing 34 | } 35 | 36 | const scopes = ["Block", "FunctionDef"], typeScopes = ["Template"] 37 | 38 | class CppMode extends CodeMirror.GrammarMode { 39 | constructor(conf) { 40 | super(cpp, { 41 | predicates: {constructorAhead, localConstructorAhead, rawStringContinues} 42 | }) 43 | this.indentConf = {doubleIndentBrackets: ">)", dontCloseBrackets: ")", tabSize: conf.tabSize, indentUnit: conf.indentUnit} 44 | } 45 | 46 | token(stream, state) { 47 | return markTypeLocals(markLocals(super.token(stream, state), scopes, stream, state), typeScopes, stream, state) 48 | } 49 | 50 | indent(state, textAfter, line) { 51 | if (textAfter.charAt(0) == "#") return 0 52 | return indent(state, textAfter, line, this.indentConf) 53 | } 54 | } 55 | 56 | CppMode.prototype.electricInput = /^\s*(?:case .*?:|(?:public|private|protected|default):|\{\}?|\})$/ 57 | CppMode.prototype.blockCommentStart = "/*" 58 | CppMode.prototype.blockCommentEnd = "*/" 59 | CppMode.prototype.blockCommentContinue = " * " 60 | CppMode.prototype.lineComment = "//" 61 | CppMode.prototype.fold = "brace" 62 | 63 | CodeMirror.defineMode("google-cpp", conf => new CppMode(conf)) 64 | -------------------------------------------------------------------------------- /src/doxygen.grammar: -------------------------------------------------------------------------------- 1 | // Extends Javadoc grammar to support Doxygen special commands. 2 | // Doxygen grammar only supports commands starting with an at-sign (@). 3 | extends "./javadoc.grammar" 4 | 5 | tag { 6 | formulaTag | 7 | super 8 | } 9 | 10 | defTag="tag" { "@param" ("[" ("in" | "out" | "in,out") "]")? !letter } 11 | 12 | formulaTag="tag" { "@f" ("$" | "[" | "]") } 13 | -------------------------------------------------------------------------------- /src/flatbuffers.grammar: -------------------------------------------------------------------------------- 1 | skip (" " | "\t" | "\n" | comment)* { 2 | start top { 3 | include_decl* ( namespace_decl | type_decl | enum_union_decl | root_decl | 4 | file_extension_decl | file_identifier_decl | attribute_decl | 5 | rpc_decl | object | comment)* 6 | } 7 | 8 | include_decl { include string_constant ";" } 9 | 10 | namespace_decl { namespace ident ( "." ident )* ";" } 11 | 12 | attribute_decl { attribute (attr | quoted_attribute) ";" } 13 | 14 | type_decl { (table_decl | struct_decl) } 15 | 16 | context table_decl { 17 | table customType metadata "{" table_field_decl+ "}" 18 | } 19 | table_field_decl { prop ":" typename ( "=" scalar )? metadata ";" } 20 | 21 | context struct_decl { 22 | struct customType metadata "{" struct_field_decl+ "}" 23 | } 24 | struct_field_decl { prop ":" typename metadata ";" } 25 | 26 | enum_union_decl { (enum_decl | union_decl) } 27 | context enum_decl { 28 | enum customType ( ":" typename )? metadata "{" 29 | enumval_decl ("," enumval_decl)* "}" 30 | } 31 | enumval_decl { enum_value_def ( "=" int_or_bool_constant )? } 32 | 33 | context union_decl { 34 | union customType metadata "{" 35 | unionval_decl ("," unionval_decl)* "}" 36 | } 37 | unionval_decl { customType } 38 | 39 | 40 | root_decl { root_type typename ";" } 41 | 42 | context rpc_decl { rpc_service def "{" rpc_method+ "}" } 43 | 44 | rpc_method { def "(" customType ")" ":" customType metadata ";" } 45 | 46 | metadata { 47 | ( "(" attr ( ":" single_value )? ("," attr ( ":" single_value )? )* ")" )? 48 | } 49 | 50 | scalar { float_constant | int_or_bool_constant | enum_value } 51 | 52 | context object { "{" prop ":" value ("," prop ":" value)* "}" } 53 | 54 | single_value { scalar | string_constant } 55 | 56 | value { single_value | object | list_literal } 57 | context list_literal { "[" value ( "," value )* "]" } 58 | 59 | file_extension_decl { file_extension string_constant ";" } 60 | 61 | file_identifier_decl { file_identifier string_constant ";" } 62 | } 63 | 64 | tokens { 65 | include { kw("include") } 66 | namespace { kw("namespace") } 67 | attribute { kw("attribute") } 68 | table { kw("table") } 69 | struct { kw("struct") } 70 | enum { kw("enum") } 71 | union { kw("union") } 72 | root_type { kw("root_type") } 73 | rpc_service { kw("rpc_service") } 74 | file_extension { kw("file_extension") } 75 | file_identifier { kw("file_identifier") } 76 | 77 | comment="comment" { 78 | single_line_comment | multiline_comment 79 | } 80 | single_line_comment { "//" .* "\n" } 81 | multiline_comment { "/*" (!"*/" _)* "*/" } 82 | 83 | int_or_bool_constant { integer_constant | bool_constant } 84 | integer_constant="number" { hex_constant | decimal_constant } 85 | 86 | hex_constant { "-"? "0x" hexdigit+ } 87 | decimal_constant { "-"? digit+ } 88 | bool_constant="builtin" { "true" | "false" } 89 | 90 | float_constant="number" { 91 | "-"? digit+ "." digit+ (("e"|"E")("+"|"-")? digit+)? 92 | } 93 | 94 | string_constant="string" { "\"" ("\\" _ | !"\"" .)* "\"" } 95 | ident { identifierStart identifierChar* } 96 | def="def" { ident } 97 | enum_value_def="def property" { ident } 98 | enum_value="property" { ident } 99 | prop="property" { ident } 100 | attr="attribute" { ident } 101 | quoted_attribute="attribute" { "\"" ident "\"" } 102 | 103 | builtin="builtin" { 104 | ("bool" | "byte" | "ubyte" | "short" | "ushort" | "int" | "uint" | "float" | 105 | "long" | "ulong" | "double" | "int8" | "uint8" | "int16" | "uint16" | 106 | "int32" | "uint32"| "int64" | "uint64" | "float32" | "float64" | "string") 107 | !identifierChar 108 | } 109 | 110 | customType="type" { ident } 111 | listType { "[" " "* ( builtin | customType ) " "* "]" } 112 | typename { listType | builtin | customType } 113 | 114 | } 115 | 116 | kw(word)="keyword" { word !identifierChar } 117 | op(expr)="operator" { expr } 118 | identifierStart { letter | "_" } 119 | identifierChar { letter | digit | "_" } 120 | letter { "a"-"z" | "A"-"Z" | "\u00a1"-"\uffff" | "_" } 121 | digit { "0"-"9" } 122 | hexdigit { "0"-"9" | "a"-"f" | "A"-"F" } 123 | -------------------------------------------------------------------------------- /src/flatbuffers.js: -------------------------------------------------------------------------------- 1 | import 'codemirror-grammar-mode'; 2 | 3 | import * as CodeMirror from 'codemirror'; 4 | 5 | import * as grammar from './flatbuffers.mode'; 6 | 7 | class FlatBuffersMode extends CodeMirror.GrammarMode { 8 | constructor(conf, modeConf) { 9 | super(grammar); 10 | this.conf = conf; 11 | 12 | this.electricChars = '[{}]'; 13 | this.blockCommentStart = '/*'; 14 | this.blockCommentEnd = ' */'; 15 | this.blockCommentLead = ' * '; 16 | this.lineComment = '//'; 17 | this.fold = ['brace']; 18 | } 19 | 20 | /** 21 | * Simple indent function: Indent 1 level for each open context (i.e. open 22 | * curly or square bracket) 23 | * 24 | * @param state the state object at the current cursor position, as defined by 25 | * grammar-mode.js 26 | * @param {string} textAfter the portion of the current line that is past the 27 | * cursor position 28 | * @param {string} line the (complete) line the cursor is on 29 | */ 30 | indent(state, textAfter, line) { 31 | var context = state.contextAt(line, line.length); 32 | 33 | var indentLevel = 0; 34 | while (context) { 35 | // Ignore brackets that were opened on this line 36 | if (context.startLine !== line && context.startLine !== '') { 37 | indentLevel = indentLevel + 1; 38 | } 39 | context = context.parent; 40 | } 41 | return indentLevel * this.conf.indentUnit; 42 | } 43 | } 44 | 45 | CodeMirror.defineMode( 46 | 'flatbuffers', (conf, modeConf) => new FlatBuffersMode(conf, modeConf)); 47 | CodeMirror.defineMIME('text/x-fbs', {name: 'flatbuffers'}); 48 | 49 | let keywords = ["include", "namespace", "attribute", "table", "struct", "enum", 50 | "union", "root_type", "rpc_service", "file_extension", 51 | "file_identifier"]; 52 | let builtins = ["bool", "byte", "ubyte", "short", "ushort", "int", "uint", 53 | "float", "long", "ulong", "double", "int8", "uint8", "int16", 54 | "uint16", "int32", "uint32", "int64", "uint64", "float32", 55 | "float64", "string", "true", "false"]; 56 | CodeMirror.registerHelper('hintWords', 'flatbuffers', 57 | keywords.concat(builtins)); 58 | -------------------------------------------------------------------------------- /src/go.grammar: -------------------------------------------------------------------------------- 1 | include "./javadoc.grammar" as doccomment 2 | 3 | start top { whitespace separated(Statement) } 4 | 5 | skip whitespace { 6 | context Statement { 7 | (const | var) MaybeSet(declName ("," declName)* Type? (op("=") CommaSep(Expr))?) | 8 | type MaybeSet(declName Type) | 9 | import MaybeSet(("." | declName)? string) | 10 | package variableName | 11 | IfStatement | 12 | SwitchStatement | 13 | ForStatement | 14 | func FunctionDecl | 15 | (go | defer) Expr | 16 | return CommaSep(Expr) | 17 | (break | continue) identifier? | 18 | (default | case CommaSep(Expr) | label) ":" | 19 | Block | 20 | select Block | 21 | goto identifier | 22 | fallthrough | 23 | case Statement ":" | 24 | Expr ("," Expr)* 25 | } 26 | 27 | context IfStatement { 28 | if ExprNoBrace (";" ExprNoBrace)? Block (else (if ExprNoBrace (";" ExprNoBrace)?)? Block)* 29 | } 30 | 31 | context ForStatement { 32 | for (ExprNoBrace (";" ExprNoBrace?)*)? Block 33 | } 34 | 35 | context SwitchStatement { 36 | switch (ExprNoBrace (";" ExprNoBrace?)?)? (&isTypeSwitch TypeSwitchBlock | Block) 37 | } 38 | 39 | MaybeSet(inner) { Set(inner) | inner } 40 | context Set(inner) { "(" separated(inner) ")" } 41 | 42 | Expr { 43 | AssignedNames Expr | 44 | ExprPrefix* (!func ~(Type "{") Type (LiteralBody | "(" Expr ")") | BaseExpr) ExprSuffix(Expr)* 45 | } 46 | 47 | ExprNoBrace { 48 | AssignedNames ExprNoBrace | 49 | ExprPrefix* BaseExpr ExprSuffix(ExprNoBrace)* 50 | } 51 | 52 | BaseExpr { 53 | number | 54 | string | 55 | atom | 56 | func FunctionExpr | 57 | make TypeList | 58 | ~(map | "[" "]" | struct | "*") Type (LiteralBody | "(" Expr ")") | 59 | builtin | 60 | calleeName | 61 | variableName | 62 | Bracketed Type? (LiteralBody | "(" Expr ")")? | 63 | "*" Type | 64 | ParenExpr 65 | } 66 | 67 | context FunctionDecl { ("(" declName Type ")")? funcName? ParamList TypeOrParamList? Block? } 68 | context FunctionExpr { ParamList TypeOrParamList? Block } 69 | context ParenExpr { "(" CommaSep(Expr) ")" } 70 | context LiteralBody { "{" CommaSep((propNameColon | LiteralBody | Expr) (":" (LiteralBody | Expr))?) "}" } 71 | context TypeList { "(" Type ("," CommaSep(Expr))? ")" } 72 | 73 | ExprPrefix { 74 | prefixOp | range 75 | } 76 | 77 | ExprSuffix(Expr) { 78 | ".(" Type ")" | 79 | "." (calleeProp | propName) | 80 | suffixOp | 81 | binOp Expr | 82 | ArgList | 83 | Bracketed 84 | } 85 | 86 | context Bracketed { "[" CommaSep(Expr | "...") (":" Expr?)* "]" } 87 | 88 | context ArgList { "(" CommaSep(Expr) "..."? ")" } 89 | 90 | CommaSep(expr) { (expr ("," expr?)*)? } 91 | 92 | context Block { "{" separated(Statement) "}" } 93 | 94 | context TypeSwitchBlock { "{" separated(case Type ":" | Statement) "}" } 95 | 96 | Type { 97 | "[" Expr? "]" Type | 98 | struct StructBody | 99 | interface InterfaceBody | 100 | "*" Type | 101 | func ParamList TypeOrParamList? | 102 | map "[" Type "]" Type | 103 | (op("<-") | chan op("<-")?) Type | 104 | "(" CommaSep(Type) ")" | 105 | typeQualifier* typeName 106 | } 107 | 108 | TypeOrParamList { 109 | ~("(" (identifier ("," identifier)* !(")" | "{" | "," | ".") | ")")) ParamList | Type 110 | } 111 | 112 | context StructBody { 113 | "{" separated((~(identifier (identifierStart | "[" | "," | "*" | "<" | "(")) propDeclName ("," propDeclName)* | "*")? Type string?) "}" 114 | } 115 | 116 | context InterfaceBody { 117 | "{" separated(propNameParen ParamList TypeOrParamList? | Type) "}" 118 | } 119 | 120 | context ParamList { 121 | "(" CommaSep((~(identifier ("," identifier)* ("..." | !(")" | ","))) CommaSep(declName))? "..."? Type) ")" 122 | } 123 | 124 | AssignedNames { 125 | ~(identifier ("," identifier)* ":=") 126 | declName ("," declName)* op(":=") 127 | } 128 | } 129 | 130 | tokens { 131 | break { kw("break") } 132 | default { kw("default") } 133 | func { kw("func") } 134 | interface { kw("interface") } 135 | select { kw("select") } 136 | case { kw("case") } 137 | defer { kw("defer") } 138 | go { kw("go") } 139 | map { kw("map") } 140 | struct { kw("struct") } 141 | chan { kw("chan") } 142 | else { kw("else") } 143 | goto { kw("goto") } 144 | package { kw("package") } 145 | switch { kw("switch") } 146 | const { kw("const") } 147 | fallthrough { kw("fallthrough") } 148 | if { kw("if") } 149 | range { kw("range") } 150 | type { kw("type") } 151 | continue { kw("continue") } 152 | for { kw("for") } 153 | import { kw("import") } 154 | return { kw("return") } 155 | var { kw("var") } 156 | make="builtin" { "make" !identifierChar } 157 | 158 | atom="atom" { ("true" | "false" | "nil" | "iota") !identifierChar } 159 | 160 | builtin="builtin" { 161 | ("append" | "cap" | "close" | "complex" | "copy" | "delete" | "imag" | 162 | "len" | "new" | "panic" | "print" | "println" | "real" | 163 | "recover") !(identifierChar | ".") 164 | } 165 | 166 | binOp="operator" { 167 | ("+" | "&" "^"? | "-" | "|" | "*" | "^" | "/" | "<" "<"? | ">" ">"? | "%" | "=") "="? | 168 | "<-" | "=" | ":=" | "!=" 169 | } 170 | prefixOp="operator" { "!" | "+" | "-" | "*" | "^" | "&" | "<-" } 171 | suffixOp="operator" { "++" | "--" } 172 | 173 | number="number" { 174 | ("0o" | "0O") "0"-"7"+ | 175 | ("0x" | "OX") (digit | "a"-"f" | "A"-"F")+ | 176 | (digit digit* ("." digit+)? | "." digit+) (("e" | "E") ("+" | "-")? digit+)? "i"? 177 | } 178 | 179 | string="string" { 180 | "'" ("\\" . (!"'" .)* | .) "'" | 181 | "\"" ("\\" . | (!"\"" .))* "\"" | 182 | "`" (!"`" _)* "`" 183 | } 184 | 185 | variableName="variable" { identifier } 186 | 187 | comment="comment" { doccomment.comment | "/*" (!"*/" _)* "*/" | "//" .* } 188 | } 189 | 190 | kw(word)="keyword" { word !identifierChar } 191 | op(expr)="operator" { expr } 192 | 193 | separated(expr) { 194 | (whitespaceSimple | "\n")* 195 | (expr (whitespaceSimple | ";" | "\n")*)* 196 | } 197 | 198 | identifier { identifierStart identifierChar* } 199 | 200 | declName="def" { identifier } 201 | context funcName { declName } 202 | propDeclName="def property" { identifier } 203 | calleeName="variable callee" { identifier ~"(" } 204 | calleeProp="property callee" { identifier ~"(" } 205 | propName="property" { identifier } 206 | propNameParen="property" { identifier ~(" "* "(") } 207 | propNameColon="property" { identifier ~(" "* ":") } 208 | typeName="type" { identifier } 209 | typeQualifier="meta" { identifier "." } 210 | label { identifier ~(" "* ":" !"=") } 211 | 212 | whitespaceSimple { (" " | "\t" | comment) } 213 | whitespace { (whitespaceSimple | ~"\n" &skippableNewline "\n")* } 214 | 215 | identifierStart { letter | "_" } 216 | identifierChar { letter | digit | "_" } 217 | letter { "a"-"z" | "A"-"Z" | "\u00a1"-"\uffff" | "_" } 218 | digit { "0"-"9" } 219 | -------------------------------------------------------------------------------- /src/go.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./go.mode" 4 | import {markLocals} from "./locals" 5 | 6 | const scopes = ["Block", "FunctionDecl", "FunctionExpr", "IfStatement", "ForStatement", "SwitchStatement", "InterfaceBody"] 7 | const allowNewline = ["LiteralBody", "Bracketed", "ArgList", "ParamList", "ParenExpr"] 8 | 9 | function skippableNewline(line, pos, cx) { 10 | if (cx && allowNewline.indexOf(cx.name) > -1) return true 11 | let match = /(?:(\w+)|[\d"'\)\]\}:]|\+\+|--)\s*(?:\/\/.*)?$/.exec(line.slice(0, pos)) 12 | return !match || 13 | (match[1] ? /^(?:func|interface|select|case|defer|go|map|struct|chan|else|goto|package|switch|const|if|range|type|for|import|var)$/.test(match[1]) : false) 14 | } 15 | 16 | function isTypeSwitch(line, pos) { 17 | return /\.\s*\(\s*type\s*\)\s*$/.test(line.slice(0, pos)) 18 | } 19 | 20 | const bracketed = { 21 | Block: "}", LiteralBody: "}", StructBody: "}", InterfaceBody: "}", 22 | Bracketed: "]", 23 | Set: ")", ParamList: ")", ArgList: ")", ParenExpr: ")" 24 | } 25 | 26 | function findIndent(cx, textAfter, config) { 27 | if (!cx) return 0 28 | if (cx.name == "string" || cx.name == "comment") return CodeMirror.Pass 29 | 30 | let brack = bracketed[cx.name] 31 | if (brack) { 32 | let closed = textAfter && textAfter.charAt(0) == brack 33 | let flat = closed || cx.name == "Block" && /^(case|default)\b/.test(textAfter) 34 | return CodeMirror.countColumn(cx.startLine, null, config.tabSize) + (flat ? 0 : config.tabSize) 35 | } else if (cx.name == "Statement") { 36 | return CodeMirror.countColumn(cx.startLine, null, config.tabSize) + config.tabSize 37 | } else { 38 | return findIndent(cx.parent, textAfter, config) 39 | } 40 | } 41 | 42 | class GoMode extends CodeMirror.GrammarMode { 43 | constructor(conf) { 44 | super(grammar, { 45 | predicates: {skippableNewline, isTypeSwitch} 46 | }) 47 | this.conf = conf 48 | } 49 | 50 | token(stream, state) { 51 | return markLocals(super.token(stream, state), scopes, stream, state) 52 | } 53 | 54 | indent(state, textAfter, line) { 55 | return findIndent(state.contextAt(line, line.length - textAfter.length), textAfter, this.conf) 56 | } 57 | } 58 | 59 | GoMode.prototype.electricInput = /^\s*(?:case .*?:|default:|\{\}?|\})$/ 60 | GoMode.prototype.closeBrackets = "()[]{}''\"\"``" 61 | GoMode.prototype.blockCommentStart = "/*" 62 | GoMode.prototype.blockCommentEnd = "*/" 63 | GoMode.prototype.blockCommentContinue = " * " 64 | GoMode.prototype.lineComment = "//" 65 | GoMode.prototype.fold = "brace" 66 | 67 | CodeMirror.defineMode("google-go", conf => new GoMode(conf)) 68 | -------------------------------------------------------------------------------- /src/html.grammar: -------------------------------------------------------------------------------- 1 | start top { element* } 2 | 3 | element { 4 | comment | doctype | tag | entity | text 5 | } 6 | 7 | comment="comment" { 8 | "" _)* "-->" 9 | } 10 | 11 | doctype="meta" { 12 | ("" _)* ">" 13 | } 14 | 15 | context tag { 16 | openTag 17 | (asTag("/>") | 18 | &selfClosing asTag(">") | 19 | asTag(">") element* (~"") 28 | } 29 | 30 | asTag(value)="tag" { value } 31 | 32 | attribute { 33 | attributeName spaceChar* ("=" spaceChar* attributeValue)? spaceChar* 34 | } 35 | 36 | attributeValue="string" { 37 | "\"" (!"\"" _)* "\"" | 38 | "'" (!"'" _)* "'" | 39 | (!(spaceChar | ">") .)* 40 | } 41 | 42 | entity="atom" { 43 | "&" (!(";" | spaceChar) .)* ";" 44 | } 45 | 46 | text { 47 | "\n" | (!("&" | "<") .)+ 48 | } 49 | 50 | tagName="tag" { wordChar+ } 51 | attributeName="attribute" { wordChar+ } 52 | 53 | wordChar { "a"-"z" | "A"-"Z" | "-" | "." | "0"-"9" | "_" } 54 | 55 | spaceChar { "\n" | "\t" | " " } 56 | -------------------------------------------------------------------------------- /src/html.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./html.mode" 4 | import {predicates, indent, contextInfo} from "./html_util" 5 | 6 | class HTMLMode extends CodeMirror.GrammarMode { 7 | constructor(conf, modeConf) { 8 | super(grammar, {predicates}) 9 | this.conf = conf 10 | } 11 | 12 | indent(state, textAfter, line) { 13 | return indent(state, textAfter, line, this.conf) 14 | } 15 | } 16 | 17 | let proto = HTMLMode.prototype 18 | proto.electricInput = /^\s*<\/.*?>/ 19 | proto.blockCommentStart = "" 21 | proto.fold = "xml" 22 | contextInfo(proto) 23 | 24 | CodeMirror.defineMode("google-html", (conf, modeConf) => new HTMLMode(conf, modeConf)) 25 | -------------------------------------------------------------------------------- /src/html_util.js: -------------------------------------------------------------------------------- 1 | function tagName(str) { 2 | let m = /^\s*([\w_\.-]+)/.exec(str) 3 | return m ? m[1].toLowerCase() : "x" 4 | } 5 | 6 | function cxTagName(cx) { 7 | return tagName(cx.startLine.slice(cx.startPos + 1)) 8 | } 9 | 10 | const selfClosers = "area base br col command embed frame hr img input keygen link meta param source track wbr menuitem".split(" ") 11 | 12 | function selfClosing(_string, _pos, cx) { 13 | return selfClosers.indexOf(cxTagName(cx)) > -1 14 | } 15 | 16 | function matchingTag(string, pos, cx) { 17 | return tagName(string.slice(pos + 2)) == cxTagName(cx) 18 | } 19 | 20 | export let predicates = {selfClosing, matchingTag} 21 | 22 | export function indent(state, textAfter, line, config) { 23 | let cx = state.contextAt(line, line.length - textAfter.length) 24 | let closing = /^\s*<\/\s*([\w_\.-]+)/.exec(textAfter) 25 | while (cx) { 26 | if (cx.name == "tag") { 27 | let base = CodeMirror.countColumn(cx.startLine, null, config.tabSize) 28 | if (closing && closing[1].toLowerCase() == cxTagName(cx)) return base 29 | else return base + config.indentUnit 30 | } else if (cx.name == "openTag") { 31 | return CodeMirror.countColumn(cx.startLine, null, config.tabSize) + 2 * config.indentUnit 32 | } 33 | cx = cx.parent 34 | } 35 | return 0 36 | } 37 | 38 | export function contextInfo(proto) { 39 | proto.xmlCurrentTag = state => { 40 | let cx = state.context 41 | if (!cx || (cx.name != "openTag" && cx.name != "closeTag")) return null 42 | let match = /^<\/?\s*([\w\-\.]+)/.exec(cx.startLine.slice(cx.startPos)) 43 | return match ? {name: match[1], close: cx.name == "closeTag"} : null 44 | } 45 | proto.xmlCurrentContext = state => { 46 | let context = [] 47 | for (let cx = state.context; cx; cx = cx.parent) { 48 | if (cx.name == "tag") { 49 | let match = /^<\s*([\w\-\.]+)/.exec(cx.startLine.slice(cx.startPos)) 50 | if (match) context.push(match[1]) 51 | } 52 | } 53 | return context.reverse() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/java.grammar: -------------------------------------------------------------------------------- 1 | include "./javadoc.grammar" as doccomment 2 | 3 | start top { 4 | (whitespace Statement)+ 5 | } 6 | 7 | skip whitespace { 8 | context Statement { 9 | for "(" Statement Expr? ";" Expr? ")" Statement | 10 | while CondExpr Statement | 11 | try Block CatchFinally | 12 | do Statement while CondExpr ";" | 13 | Conditional | 14 | switch CondExpr Block | 15 | breakCont identifier ? ";" | 16 | assert Expr (":" Expr)? ";" | 17 | return Expr? ";" | 18 | throw Expr ";" | 19 | (default | case Expr | labelIdentifier) ":" | 20 | import kw("static")? identifierDot* ("*" | identifier) ";" | 21 | kw("synchronized") CondExpr Block | 22 | ";" | 23 | BeforeStatement(Modifier*) Declaration(declName) | 24 | ExprComma ";" 25 | } 26 | 27 | context BeforeStatement(expr) { expr } 28 | 29 | context CatchFinally { 30 | (catch "(" Modifier* Type ("|" Type)* declName ")" Block)* 31 | (finally Block)? 32 | } 33 | 34 | Modifier { modifierKw | Annotation } 35 | 36 | context StatementModifiers { Modifier* } 37 | 38 | Annotation { 39 | annotationHead ("(" CommaSep(maybe(identifier "=")? (Annotation | ArrayInitializer | Expr)) ")")? 40 | } 41 | 42 | context EnumBody { 43 | "{" (EnumConstant ","?)+ (";" ClassItem*)? "}" 44 | } 45 | context EnumConstant { 46 | Annotation? propDeclName ArgList? ClassBody? 47 | } 48 | 49 | Declaration(name) { 50 | Block | 51 | enum typeDeclName (implements CommaSep(Type))? EnumBody | 52 | classInterface typeDeclName TypeParams? (extends Type)? (implements CommaSep(Type))? ClassBody | 53 | atInterface declName AnnotationTypeBody | 54 | package identifier ("." identifier)* ";" | 55 | ~(Annotation* TypeParams? (primType | var | (typeQualifier TypeArgs? ".")* className)) 56 | (Type | var) DeclExpr(name) (FunctionDef | (op("=") Expr)? ("," DeclExpr(name) (op("=") Expr)?)* ";") 57 | } 58 | 59 | context ClassItem { 60 | BeforeStatement(Modifier*) TypeParams? (propDeclNameParen FunctionDef | Declaration(propDeclName)) 61 | } 62 | 63 | context ClassBody { 64 | "{" ClassItem* "}" 65 | } 66 | 67 | context AnnotationTypeItem { 68 | BeforeStatement(Modifier*) 69 | (declNameParenBracketOrEquals (("[" "]")* op("=") Expr) | "(" ")" ("[" "]")* (default Expr)? | 70 | Declaration(declName)) 71 | } 72 | 73 | context AnnotationTypeBody { 74 | "{" AnnotationTypeItem* "}" 75 | } 76 | 77 | context Block { "{" Statement* "}" } 78 | 79 | context FunctionDef { ParamList ThrowsClause? (";" | Block) } 80 | 81 | context ThrowsClause { throws CommaSep(Type) } 82 | 83 | context ParamList { "(" CommaSep((Annotation | Modifier)* Type "..."? (this | DeclExpr(declName))) ")" } 84 | context SimpleParamList { "(" CommaSep(declName) ")" } 85 | 86 | context TypeParams { "<" CommaSep(Annotation* typeDeclName (extends Type)*) ">" } 87 | context TypeArgs { "<" CommaSep(Type | "?" ((extends | super_) Type)?) ">" } 88 | 89 | Expr { prefixOp* BaseExpr ExprSuffix* } 90 | 91 | ExprComma { Expr ("," Expr)* } 92 | 93 | BaseExpr { 94 | atom | this | super_ | 95 | number | 96 | string | 97 | NewExpr | 98 | Lambda | 99 | calleeName | 100 | plainVariableName | 101 | ArrayInitializer | 102 | ~("(" TypeID) "(" Type ")" Expr | 103 | ParenExpr 104 | } 105 | 106 | context NewExpr { 107 | new TypeArgs? TypeNoArray ("[" Expr? "]" ArrayInitializer? | ArgList? ClassBody?) 108 | } 109 | 110 | ExprSuffix { 111 | ArgList | 112 | "[" Expr? "]" | 113 | "." (kw("class") | NewExpr | TypeArgs | calleeField | fieldName) | 114 | "::" (kw("new") | calleeField | fieldName) | 115 | suffixOp | 116 | instanceof Type | 117 | binOp Expr | 118 | op("?") Expr op(":") Expr 119 | } 120 | 121 | context Lambda { 122 | (maybe((declName | ParamList) op("->")) | maybe(SimpleParamList op("->"))) (Block | Expr) 123 | } 124 | 125 | context ParenExpr { "(" Expr? ")" } 126 | context CondExpr { "(" Expr? ")" } 127 | context ArgList { "(" CommaSep(ArgExpr) ")" } 128 | context ArgExpr { Expr } 129 | context ArrayInitializer { "{" CommaSep(ArgExpr) "}" } 130 | 131 | Type { 132 | Annotation* TypeID ("[" Expr? "]" | TypeArgs)* 133 | } 134 | 135 | TypeID { 136 | primType | 137 | (typeQualifier TypeArgs? ".")+ qualifiedClassName | 138 | className 139 | } 140 | 141 | TypeNoArray { 142 | Annotation* TypeID TypeArgs* 143 | } 144 | 145 | DeclExpr(name) { name ("[" "]")? } 146 | 147 | CommaSep(expr) { (expr ("," expr?)*)? } 148 | } 149 | 150 | Conditional { 151 | if whitespace CondExpr whitespace Statement Alternative 152 | } 153 | context Alternative { 154 | whitespace (else whitespace Statement)? 155 | } 156 | 157 | tokens { 158 | enum { kw("enum") } 159 | return { kw("return") } 160 | if { kw("if") } 161 | else { kw("else") } 162 | for { kw("for") } 163 | while { kw("while") } 164 | do { kw("do") } 165 | breakCont { kw("break" | "continue") } 166 | default { kw("default") } 167 | case { kw("case") } 168 | switch { kw("switch") } 169 | modifierKw { kw("public" | "protected" | "private" | "abstract" | "static" | "final" | "transient" | 170 | "volatile" | "synchronized" | "native" | "strictfp" | "const") } 171 | extends { kw("extends") } 172 | implements { kw("implements") } 173 | this { kw("this") } 174 | new { kw("new") } 175 | super_ { kw("super") } 176 | assert { kw("assert") } 177 | throw { kw("throw") } 178 | throws { kw("throws") } 179 | try { kw("try") } 180 | catch { kw("catch") } 181 | finally { kw("finally") } 182 | package { kw("package") } 183 | import { kw("import") } 184 | classInterface { kw("class" | "interface") } 185 | atInterface { kw("@interface") } 186 | instanceof { kw("instanceof") } 187 | var { kw("var") } 188 | 189 | primType="type" { ("boolean" | "char" | "byte" | "short" | "int" | "long" | "float" | "double" | "void") !identifierChar } 190 | className="type" { "A"-"Z" identifierChar* } 191 | 192 | atom="atom" { ("true" | "false" | "null") !identifierChar } 193 | 194 | variableName { calleeName | plainVariableName } 195 | 196 | number="number" { 197 | (("0x" | "0X") (digit | "_" | "a"-"f" | "A"-"F")+ | 198 | ("0b" | "0B") ("0" | "1" | "_")+ | 199 | (digit (digit | "_")* ("." (digit | "_")*)? | "." (digit | "_")+) (("e" | "E") ("+" | "-")? (digit | "_")+)?) 200 | ("L" | "l" | "D" | "d" | "F" | "f")? 201 | } 202 | 203 | string="string" { 204 | ("'" ("\\" . (!"'" .)* | .) "'" | 205 | "\"" ("\\" _ | (!"\"" .))* "\"") 206 | } 207 | 208 | prefixOp="operator" { 209 | "++" | "--" | "!" | "~" | "&" | "*" | "-" | "+" 210 | } 211 | 212 | suffixOp="operator" { 213 | "++" | "--" 214 | } 215 | 216 | binOp="operator" { 217 | ("!" | "+" | "-" | "/" | "*" | "%" | ">" ">"? | "<" "<"? | "=" | "|" "|"? | "&" "&"?) "="? 218 | } 219 | 220 | comment="comment" { doccomment.comment | "/*" (!"*/" _)* "*/" | "//" .* } 221 | } 222 | 223 | calleeName="variable callee" { identifier ~"(" } 224 | plainVariableName="variable" { identifier } 225 | 226 | identifier { identifierStart identifierChar* } 227 | identifierDot { identifier " "* "." } 228 | 229 | annotationHead="meta" { 230 | !atInterface "@" identifier ("." identifier)* 231 | } 232 | 233 | whitespace { 234 | (" " | "\t" | "\n" | comment)* 235 | } 236 | 237 | declName="def" { identifier } 238 | propDeclName="def property" { identifier } 239 | propDeclNameParen="def property" { identifier ~(" "* "(") } 240 | declNameParenBracketOrEquals="def" { identifier ~(" "* ("(" | "[" | "=")) } 241 | 242 | typeDeclName="type def" { identifier } 243 | 244 | calleeField="property callee" { identifier ~(" "* "(") } 245 | fieldName="property" { identifier } 246 | 247 | typeQualifier="type qualifier" { identifier ~(" "* (TypeArgs " "*)? "." !".") } 248 | 249 | typeName="type" { identifier } 250 | 251 | qualifiedClassName="qualified" { className } 252 | 253 | kw(value)="keyword" { value !identifierChar } 254 | op(value)="operator" { value } 255 | 256 | maybe(value) { ~value value } 257 | 258 | letter { "a"-"z" | "A"-"Z" | "\u00a1"-"\uffff" | "_" } 259 | 260 | digit { "0"-"9" } 261 | 262 | identifierStart { letter } 263 | 264 | identifierChar { letter | digit } 265 | 266 | spaceChar { "\n" | "\t" | " " } 267 | 268 | labelIdentifier { identifier ~(spaceChar* ":" !":") } 269 | -------------------------------------------------------------------------------- /src/java.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./java.mode" 4 | import {markLocals, markTypeLocals} from "./locals" 5 | import {indent} from "./c_indent" 6 | 7 | const scopes = ["Block", "FunctionDef", "Lambda"] 8 | const typeScopes = ["ClassItem", "Statement", "AnnotationTypeItem"] 9 | 10 | class JavaMode extends CodeMirror.GrammarMode { 11 | constructor(conf) { 12 | super(grammar) 13 | this.indentConf = {doubleIndentBrackets: ">)", dontCloseBrackets: ")", align: false, 14 | tabSize: conf.tabSize, indentUnit: conf.indentUnit} 15 | } 16 | 17 | token(stream, state) { 18 | return markTypeLocals(markLocals(super.token(stream, state), scopes, stream, state), typeScopes, stream, state) 19 | } 20 | 21 | indent(state, textAfter, line) { 22 | if (!textAfter) textAfter = line = "x" // Force getContextAt to terminate the statement, if needed 23 | return indent(state, textAfter, line, this.indentConf) 24 | } 25 | } 26 | 27 | JavaMode.prototype.electricInput = /^\s*(?:case .*?:|default:|\{\}?|\})$/ 28 | JavaMode.prototype.blockCommentStart = "/*" 29 | JavaMode.prototype.blockCommentEnd = "*/" 30 | JavaMode.prototype.blockCommentContinue = " * " 31 | JavaMode.prototype.lineComment = "//" 32 | JavaMode.prototype.fold = "brace" 33 | 34 | CodeMirror.defineMode("google-java", conf => new JavaMode(conf)) 35 | -------------------------------------------------------------------------------- /src/javadoc.grammar: -------------------------------------------------------------------------------- 1 | comment { "/**" !"/" content* tagGroup* "*/" } 2 | 3 | content { (!("*/" | "{"? "@" letter) _)+ } 4 | 5 | context tagGroup { (tag | "{" otherTag spacing tagContent "}") content* } 6 | 7 | tag { 8 | defTag spaceChar* (def | typeDef)? | 9 | typeTag spaceChar* type? | 10 | otherTag 11 | } 12 | 13 | defTag="tag" { "@param" !letter } 14 | 15 | typeTag="tag" { "@" ("throws" | "exception") !letter } 16 | 17 | otherTag="tag" { "@" letter+ } 18 | 19 | tagContent { (attr("{") tagContent (~"*/" | attr("}")) | attr((!("{" | "}" | "*/") .)+) | "\n" spacing ("*" !"/" spacing)?)* } 20 | 21 | attr(expr)="attribute" { expr } 22 | 23 | def="def" { (letter | ".")+ } 24 | 25 | typeDef { "<" typeDefName ">" } 26 | 27 | typeDefName="type def" { letter+ } 28 | 29 | type="type" { (letter | ".")+ } 30 | 31 | spaceChar { "\n" | "\t" | " " } 32 | 33 | spacing { ("\t" | " ")* } 34 | 35 | letter { "a"-"z" | "A"-"Z" | "0"-"9" | "\u00a1"-"\uffff" | "_" } 36 | -------------------------------------------------------------------------------- /src/javascript.grammar: -------------------------------------------------------------------------------- 1 | include "./jsdoc.grammar" as doccomment 2 | 3 | skip whitespace { 4 | start top { whitespace Statement* } 5 | 6 | context Statement { 7 | var VariableDeclarator ("," VariableDeclarator)* semi | 8 | (while | with) CondExpr Statement | 9 | do Statement (while CondExpr semi)? | 10 | Block | 11 | ";" | 12 | debugger | 13 | Conditional | 14 | function asyncStar? declName FunctionDef | 15 | for ForStatement | 16 | Label | 17 | return (semi | Expression semi) | 18 | throw Expression semi | 19 | breakCont identifier? semi | 20 | switch CondExpr Block | 21 | try Block CatchFinally | 22 | class typeDeclName ClassDef | 23 | Export | 24 | Import | 25 | async Statement | 26 | Decorator | 27 | Expression semi 28 | } 29 | 30 | VariableDeclarator { Pattern (op("=") ExpressionNoComma)? } 31 | 32 | context Block { "{" Statement* "}" } 33 | 34 | Label { (default | labelName | case Expression) ":" } 35 | 36 | context ForStatement { ForSpec Statement } 37 | context ForSpec { 38 | "(" StatementMaybeOf (Expression? ";" Expression?)? ")" 39 | } 40 | 41 | context StatementMaybeOf { 42 | Statement (kw("of") Expression)? 43 | } 44 | 45 | context CatchFinally { 46 | (catch ("(" Pattern ")")? Block)? (finally Block)? 47 | } 48 | 49 | Export { 50 | export 51 | (("*" | default | "{" CommaSep(DeclMaybeAs) "}") (kw("from") string)? semi | 52 | Statement) 53 | } 54 | 55 | Import { 56 | import 57 | (string | 58 | ((asyncStar (kw("as") declName)? | DeclMaybeAs | "{" CommaSep(DeclMaybeAs) "}") 59 | (kw("from") string)?)) 60 | semi 61 | } 62 | 63 | DeclMaybeAs { 64 | variableAs kw("as") declName | declName 65 | } 66 | 67 | Expression { BaseExpression ("," ExpressionNoComma | ExpressionSuffix(Expression))* } 68 | 69 | ExpressionNoComma { BaseExpression ExpressionSuffix(ExpressionNoComma)* } 70 | 71 | context ParenExpr { "(" Expression ")" } 72 | context CondExpr { "(" Expression ")" } 73 | 74 | BaseExpression { 75 | atom | 76 | kwExpr | 77 | (kwPrefix | prefixOp | async) BaseExpression | 78 | NewExpression | 79 | function asyncStar? declName? FunctionDef | 80 | class (!kw("extends") typeDeclName)? ClassDef | 81 | ArrowFunc | 82 | Callee | 83 | variable | 84 | number | 85 | string | 86 | regexp | 87 | template | 88 | ArrayLiteral | 89 | ObjectLiteral | 90 | ParenExpr 91 | } 92 | 93 | Callee { calleeName } 94 | 95 | context NewExpression { new ("." kw("target") | BaseExpression (ArgList | "." (calleeProp | propName))*) } 96 | 97 | context ArrowFunc { (declNameAndArrow | ParamsAndArrow) ArrowRest } 98 | 99 | context ArrowRest { op("=>") (Block | ExpressionNoComma) } 100 | 101 | context ArrayLiteral { "[" CommaSep(ExpressionNoComma) "]" } 102 | 103 | context ObjectLiteral { "{" CommaSep(ObjectMember) "}" } 104 | 105 | context ObjectMember { 106 | propModifier? asyncStar? 107 | ((propDeclName | "[" Expression "]" | number | string) (FunctionDef | ":" ExpressionNoComma)? | 108 | op("...") ExpressionNoComma) 109 | } 110 | 111 | ExpressionSuffix(ContExpression) { 112 | suffixOp | 113 | (binOp | kwBinOp) ContExpression | 114 | ArgList | 115 | template | 116 | ("." | "?.") (calleeProp | propName) | 117 | "[" Expression "]" | 118 | op("?") Expression op(":") ContExpression 119 | } 120 | 121 | context ArgList { 122 | "(" CommaSep(ExpressionNoComma) ")" 123 | } 124 | 125 | context ParamList { 126 | "(" CommaSep(PatternDefault) ")" 127 | } 128 | 129 | context FunctionDef { 130 | ParamList Block 131 | } 132 | 133 | ClassDef { 134 | (extends Expression)? ClassBody 135 | } 136 | 137 | context ClassBody { 138 | "{" (kw("static")? ObjectMember | Decorator)* "}" 139 | } 140 | 141 | Decorator { "@" Expression } 142 | 143 | Pattern { 144 | op("...")? (declName | ArrayPattern | ObjectPattern) 145 | } 146 | 147 | PatternDefault { 148 | Pattern (op("=") ExpressionNoComma)? 149 | } 150 | 151 | context ArrayPattern { "[" CommaSep(PatternDefault?) "]" } 152 | 153 | context ObjectPattern { "{" CommaSep(PropPattern) "}" } 154 | 155 | PropPattern { 156 | declNameNoColon (op("=") ExpressionNoComma)? | 157 | (propName | number | string) ":" PatternDefault | 158 | op("...") PatternDefault 159 | } 160 | 161 | CommaSep(expr) { (expr ("," expr?)*)? } 162 | 163 | ParamsAndArrow { ~(ParamList "=>") ParamList } 164 | } 165 | 166 | Conditional { 167 | if whitespace CondExpr whitespace Statement Alternative 168 | } 169 | context Alternative { 170 | whitespace (else whitespace Statement)? 171 | } 172 | 173 | tokens { 174 | var { kw("var" | "let" | "const") } 175 | while { kw("while") } 176 | with { kw("with") } 177 | else { kw("else") } 178 | do { kw("do") } 179 | try { kw("try") } 180 | finally { kw("finally") } 181 | return { kw("return") } 182 | throw { kw("throw") } 183 | breakCont { kw("break" | "continue") } 184 | debugger { kw("debugger") } 185 | case { kw("case") } 186 | default { kw("default") } 187 | function { kw("function") } 188 | if { kw("if") } 189 | catch { kw("catch") } 190 | for { kw("for") } 191 | switch { kw("switch") } 192 | class { kw("class") } 193 | export { kw("export") } 194 | import { kw("import") } 195 | extends { kw("extends") } 196 | async { kw("async") ~(whitespace (function | identifier | "(")) } 197 | new { kw("new") } 198 | kwBinOp { kw("in" | "instanceof") } 199 | kwPrefix { kw("delete" | "typeof" | "yield" | "await" | "void") } 200 | kwExpr { kw("super" | "this") } 201 | 202 | atom="atom" { ("true" | "false" | "null" | "undefined" | "NaN" | "Infinity") !identifierChar } 203 | 204 | variable="variable" { identifier } 205 | 206 | prefixOp="operator" { "..." | "!" | "+" "+"? | "-" "-"? } 207 | binOp="operator" { 208 | ("+" | "-" | "%" | "*" | slash | ">" ">"? ">"? | "<" "<"? | "=" "="? | "&" "&"? | "|" "|"? | "^" | "!=") "="? | 209 | "??" 210 | } 211 | suffixOp="operator" { "++" | "--" } 212 | 213 | string="string" { 214 | "'" ("\\" _ | (!"'" .))* "'" | 215 | "\"" ("\\" _ | (!"\"" .))* "\"" 216 | } 217 | 218 | number="number" { 219 | "0x" (digit | "a"-"f" | "A"-"F" | "_")+ | 220 | "0o" ("0"-"7" | "_")+ | 221 | "0b" ("0" | "1" | "_")+ | 222 | (digit (digit | "_")* ("." (digit | "_")*)? | "." (digit | "_")+) (("e" | "E") ("+" | "-")? (digit | "_")+)? 223 | } 224 | 225 | comment="comment" { doccomment.comment | "/*" (!"*/" _)* "*/" | "//" .* } 226 | 227 | regexp="string-2" { slash ("\\" . | "[" (!"]" .)* "]" | !"/" .)+ "/" ("g" | "i" | "m" | "y" | "u" | "s")* } 228 | 229 | template { 230 | str2("`") 231 | (str2("${") Expression str2("}") | str2("\\" _ | "\n") | str2((!("`" | "${" | "\\") .)+))* 232 | str2("`") 233 | } 234 | } 235 | 236 | whitespace { (spaceChar | comment)* } 237 | 238 | kw(value)="keyword" { value !identifierChar } 239 | op(value)="operator" { value } 240 | str2(value)="string-2" { value } 241 | 242 | propName="property" { identifier } 243 | propDeclName="def property" { identifier } 244 | declName="def" { identifier } 245 | typeDeclName="type def" { identifier } 246 | calleeName="variable callee" { identifier ~(" "* "(") } 247 | calleeProp="property callee" { identifier ~(" "* "(") } 248 | labelName { identifier ~(" "* ":") } 249 | 250 | declNameNoColon { declName !(identifierChar | " "* ":") } 251 | 252 | declNameAndArrow { declName ~(whitespace "=>") } 253 | 254 | propModifier { kw("get" | "set" | "async") !(" "* ("," | "}" | ":" | "(")) } 255 | 256 | asyncStar="keyword" { "*" } 257 | 258 | variableAs { variable ~(" "+ "as") } 259 | 260 | identifier { identifierStart identifierChar* } 261 | 262 | semi { ";" | ~"}" | &canInsertSemi } 263 | 264 | letter { "a"-"z" | "A"-"Z" | "\u00a1"-"\uffff" | "_" } 265 | 266 | digit { "0"-"9" } 267 | 268 | identifierStart { letter | "_" | "$" } 269 | 270 | identifierChar { letter | digit | "_" | "$" } 271 | 272 | spaceChar { "\n" | "\t" | " " } 273 | 274 | slash { "/" !("/" | "*") } 275 | -------------------------------------------------------------------------------- /src/javascript.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./javascript.mode" 4 | import {markLocals} from "./locals" 5 | import {indent} from "./c_indent" 6 | import {canInsertSemi} from "./js_semi" 7 | import {TemplateTokenizer} from "./template_string_inline_language"; 8 | 9 | const scopes = ["Block", "FunctionDef", "ArrowFunc", "ForStatement"] 10 | 11 | class JSMode extends CodeMirror.GrammarMode { 12 | constructor(conf, modeConf) { 13 | super(grammar, { 14 | predicates: {canInsertSemi: modeConf.requireSemicolons === false ? canInsertSemi : () => false} 15 | }) 16 | this.embeddedParser = new TemplateTokenizer(conf); 17 | this.indentConf = {doubleIndentBrackets: ">)", dontCloseBrackets: ")", 18 | tabSize: conf.tabSize, indentUnit: conf.indentUnit, 19 | forceContent: true} 20 | } 21 | 22 | startState() { 23 | const state = super.startState(); 24 | state.embeddedParserState = this.embeddedParser.startState(); 25 | return state; 26 | } 27 | 28 | copyState(state) { 29 | const copy = super.copyState(state); 30 | copy.embeddedParserState = 31 | this.embeddedParser.copyState(state.embeddedParserState); 32 | return copy; 33 | } 34 | 35 | token(stream, state) { 36 | const embeddedParserState = state.embeddedParserState; 37 | if (this.embeddedParser.shouldInterceptTokenizing(embeddedParserState)) { 38 | const {handled, style} = this.embeddedParser.interceptTokenizing( 39 | stream, embeddedParserState); 40 | if (handled) { 41 | return style; 42 | } 43 | } 44 | const style = super.token(stream, state); 45 | this.embeddedParser.trackState( 46 | style, stream, embeddedParserState); 47 | return markLocals(style, scopes, stream, state) 48 | } 49 | 50 | indent(state, textAfter, line) { 51 | if (!textAfter) textAfter = line = "x" // Force getContextAt to terminate the statement, if needed 52 | return indent(state, textAfter, line, this.indentConf) 53 | } 54 | } 55 | 56 | let meta = { 57 | electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, 58 | blockCommentStart: "/*", 59 | blockCommentEnd: "*/", 60 | blockCommentContinue: " * ", 61 | lineComment: "//", 62 | fold: "brace", 63 | closeBrackets: "()[]{}''\"\"``" 64 | } 65 | for (let prop in meta) JSMode.prototype[prop] = meta[prop] 66 | 67 | CodeMirror.registerHelper("wordChars", "google-javascript", /[\w$]/) 68 | 69 | CodeMirror.defineMode("google-javascript", (conf, modeConf) => new JSMode(conf, modeConf)) 70 | -------------------------------------------------------------------------------- /src/js_semi.js: -------------------------------------------------------------------------------- 1 | export function canInsertSemi(string, pos) { 2 | for (let i = pos - 1; i >= 0; i--) { 3 | let ch = string.charCodeAt(i) 4 | if (ch === 10) break 5 | if (ch !== 32 && ch !== 9) return false 6 | } 7 | return true 8 | } 9 | -------------------------------------------------------------------------------- /src/jsdoc.grammar: -------------------------------------------------------------------------------- 1 | comment { "/**" !"/" content* tagGroup* "*/" } 2 | 3 | content { (!("*/" | "@" letter | "{") _)+ | braced } 4 | 5 | context braced { "{" (tag (!("}" | "*/") _)* | content) ("}" | ~"*/") } 6 | 7 | context tagGroup { tag content* } 8 | 9 | tag { 10 | defTag spaceChar* (("{" type "}" (spaceChar | "*" !"/")*)? def?)? | 11 | otherTag 12 | } 13 | 14 | defTag="tag" { "@" ("member" | "param" | "arg" "ument"? | "module" | "namespace" | "typedef") !letter } 15 | 16 | otherTag="tag" { "@" letter+ } 17 | 18 | context type { (tp("{") type (~"*/" | tp("}")) | tp((!("{" | "}" | "*/") .)+) | "\n" spacing ("*" !"/" spacing)?)* } 19 | 20 | tp(expr)="type" { expr } 21 | 22 | def="def" { letter+ } 23 | 24 | spaceChar { "\n" | "\t" | " " } 25 | 26 | spacing { ("\t" | " ")* } 27 | 28 | letter { "a"-"z" | "A"-"Z" | "\u00a1"-"\uffff" | "_" | "0"-"9" } 29 | -------------------------------------------------------------------------------- /src/kdoc.grammar: -------------------------------------------------------------------------------- 1 | comment { "/**" !"/" content* tagGroup* "*/" } 2 | 3 | content { "/*" (!"*/" _)* "*/" | (!("*/" | "{"? "@" letter | link) _)+ | link } 4 | 5 | link="link" { "[" (!"]" _)+ "]" } 6 | 7 | context tagGroup { (tag | "{" otherTag spacing tagContent "}") content* } 8 | 9 | tag { 10 | defTag spaceChar* (def | typeDef)? | 11 | typeTag spaceChar* type? | 12 | otherTag 13 | } 14 | 15 | defTag="tag" { "@param" !letter } 16 | 17 | typeTag="tag" { "@" ("throws" | "exception") !letter } 18 | 19 | otherTag="tag" { "@" letter+ } 20 | 21 | tagContent { (attr("{") tagContent (~"*/" | attr("}")) | attr((!("{" | "}" | "*/") .)+) | "\n" spacing ("*" !"/" spacing)?)* } 22 | 23 | attr(expr)="attribute" { expr } 24 | 25 | def="def" { (letter | ".")+ } 26 | 27 | typeDef { "<" typeDefName ">" } 28 | 29 | typeDefName="type def" { letter+ } 30 | 31 | type="type" { (letter | ".")+ } 32 | 33 | spaceChar { "\n" | "\t" | " " } 34 | 35 | spacing { ("\t" | " ")* } 36 | 37 | letter { "a"-"z" | "A"-"Z" | "0"-"9" | "\u00a1"-"\uffff" | "_" } 38 | -------------------------------------------------------------------------------- /src/kotlin.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./kotlin.mode" 4 | import {markLocals, markTypeLocals} from "./locals" 5 | import {indent} from "./c_indent" 6 | 7 | const scopes = ["Block", "FunctionSpec", "LambdaBlock", "ClassSpec", "TypeAliasSpec", "ForStatement", "CatchFinally"] 8 | const typeScopes = ["FunctionDeclaration", "ClassSpec", "TypeAliasSpec"] 9 | 10 | class KotlinMode extends CodeMirror.GrammarMode { 11 | constructor(conf, modeConf) { 12 | super(grammar) 13 | this.indentConf = {tabSize: conf.tabSize, indentUnit: conf.indentUnit, forceContent: true, dontAlign: ["LambdaBlock"]} 14 | } 15 | 16 | token(stream, state) { 17 | return markTypeLocals(markLocals(super.token(stream, state), scopes, stream, state), typeScopes, stream, state) 18 | } 19 | 20 | indent(state, textAfter, line) { 21 | return indent(state, textAfter, line, this.indentConf) 22 | } 23 | } 24 | 25 | let meta = { 26 | electricInput: /^\s*[{}]$/, 27 | blockCommentStart: "/*", 28 | blockCommentEnd: "*/", 29 | blockCommentContinue: " * ", 30 | lineComment: "//", 31 | fold: "brace", 32 | closeBrackets: "()[]{}''\"\"``" 33 | } 34 | for (let prop in meta) KotlinMode.prototype[prop] = meta[prop] 35 | 36 | CodeMirror.defineMode("google-kotlin", (conf, modeConf) => new KotlinMode(conf, modeConf)) 37 | -------------------------------------------------------------------------------- /src/locals.js: -------------------------------------------------------------------------------- 1 | function getScope(context, scopes) { 2 | for (let cx = context; cx; cx = cx.parent) 3 | if (scopes.indexOf(cx.name) > -1) return cx 4 | } 5 | function isLocal(context, name) { 6 | for (let cx = context; cx; cx = cx.parent) 7 | if (cx.locals && cx.locals.indexOf(name) > -1) return true 8 | return false 9 | } 10 | function isLocalType(context, name) { 11 | for (let cx = context; cx; cx = cx.parent) 12 | if (cx.localTypes && cx.localTypes.indexOf(name) > -1) return true 13 | return false 14 | } 15 | 16 | const varRE = /(^|\s)variable($|\s)/ 17 | 18 | export function markLocals(type, scopes, stream, state) { 19 | if (type == "def") { 20 | let scope = getScope(state.context, scopes), name = stream.current() 21 | if (scope) { 22 | if (!scope.locals) scope.locals = [] 23 | if (scope.locals.indexOf(name) == -1) scope.locals.push(name) 24 | if (state.context.name != "funcName") return "def local" 25 | } 26 | } else if (varRE.test(type) && !/qualified/.test(type) && 27 | isLocal(state.context, stream.current())) { 28 | type = type.replace(varRE, "$1variable-2$2") 29 | } 30 | return type 31 | } 32 | 33 | const typeRE = /(^|\s)type($|\s)/ 34 | 35 | export function markTypeLocals(type, scopes, stream, state) { 36 | if (type == "type def") { 37 | let scope = getScope(state.context, scopes) 38 | if (scope) { 39 | if (!scope.localTypes) scope.localTypes = [] 40 | scope.localTypes.push(stream.current()) 41 | } 42 | } else if (typeRE.test(type) && !/qualifie[rd]/.test(type) && 43 | isLocalType(state.context, stream.current())) { 44 | type += " local" 45 | } 46 | return type 47 | } 48 | -------------------------------------------------------------------------------- /src/python.grammar: -------------------------------------------------------------------------------- 1 | skip whitespace { 2 | start top { whitespace ("\n" | Statement)* } 3 | 4 | context Statement { 5 | (if | whileElif) Expr ":" Body | 6 | (else | tryFinally) ":" Body | 7 | for CommaSep(MaybePattern(in) | ExprNoIn) in Expr ":" Body | 8 | except (Expr (as declName)?)? ":" Body | 9 | async AsyncStatement | 10 | AsyncStatement | 11 | Annotation ArgList? "\n" | 12 | print (ArgList | Expr) | 13 | SimpleStatement 14 | } 15 | 16 | AsyncStatement { 17 | with CommaSep(ExprNoComma (as (declName | ParenPattern | BracketPattern))?) ":" Body | 18 | def declName FuncDef | 19 | class ClassDef 20 | } 21 | 22 | SimpleStatement { 23 | SmallStatement (";" SmallStatement?)* "\n" 24 | } 25 | 26 | SmallStatement { 27 | passBreakCont | 28 | del Expr | 29 | returnAssert Expr? | 30 | raise Expr? (from Expr)? | 31 | import CommaSep(ExprNoComma (as declName)?) | 32 | from "."* (!import Expr import | import) ("*" | FromImportList | CommaSep(identifier (as declName)?)) | 33 | globalNonlocal CommaSep(variableName) | 34 | MaybePattern(("=" | ":")) (":" Expr)? (op("=") Expr)? | 35 | Expr 36 | } 37 | 38 | context FromImportList { "(" CommaSep(identifier (as declName)?)? ","? ")" } 39 | 40 | Annotation="meta" { "@" identifier ("." identifier)* } 41 | 42 | context ArgList { "(" MaybeComp((op("**") | labelName "=")? ExprNoComma)? ")" } 43 | 44 | context ParamList { "(" CommaSep(op("*" "*"?)? (self | declName) (":" ExprNoComma)? (op("=") ExprNoComma)?)? ")" } 45 | 46 | Expr { 47 | ExprPrefix* BaseExpr (ExprSuffix(Expr) | (in | ",") ExprNoComma)* 48 | } 49 | 50 | ExprNoComma { 51 | ExprPrefix* BaseExpr (ExprSuffix(ExprNoComma) | in Expr)* 52 | } 53 | 54 | ExprNoIn { 55 | ExprPrefix* BaseExpr ExprSuffix(ExprNoIn)* 56 | } 57 | 58 | ExprPrefix { 59 | prefixOp | 60 | prefixKw 61 | } 62 | 63 | BaseExpr { 64 | ParenExpr | 65 | ArrayLiteral | 66 | ObjectLiteral | 67 | number | 68 | (string | fstring)+ | 69 | op("...") | 70 | atom | 71 | self | 72 | yield (from Expr | Expr)? | 73 | lambda LambdaDef | 74 | builtin | 75 | calleeName | 76 | variableName 77 | } 78 | 79 | ExprSuffix(Expr) { 80 | !replacementFieldSuffix (binop | binopKw) Expr | 81 | ArgList | 82 | Subscript | 83 | "." (calleeProp | propName) | 84 | if Expr (else Expr)? 85 | } 86 | 87 | context LambdaDef { CommaSep(op("*" | "**")? declName (op("=") ExprNoComma)?)? ":" ExprNoComma } 88 | context ClassDef { typeDeclName ArgList? ":" Body } 89 | context FuncDef { ParamList ("->" Expr)? ":" Body } 90 | 91 | MaybeComp(E) { (compLocalName ExprSuffix(ExprNoComma)* | E) ("," CommaSep(E)? | CompFor)? } 92 | CompFor { async? for (MaybePattern("\n"* in) | ExprNoIn) in Expr (CompFor | CompIf)? } 93 | CompIf { if Expr (CompFor | CompIf)? } 94 | 95 | context ParenExpr { "(" MaybeComp(ExprNoComma)? ")" } 96 | 97 | context ArrayLiteral { "[" MaybeComp(ExprNoComma)? "]" } 98 | 99 | context ObjectLiteral { 100 | "{" (CommaSep(DictProp) CompFor?)? "}" 101 | } 102 | 103 | context DictProp { 104 | op("**") ExprNoComma | ExprNoComma (":" ExprNoComma)? 105 | } 106 | 107 | context Subscript { 108 | "[" CommaSep(ExprNoComma (":" ExprNoComma? (":" ExprNoComma?)?)? | ":" ExprNoComma? (":" ExprNoComma?)?) "]" 109 | } 110 | 111 | CommaSep(expr) { expr ("," expr?)* } 112 | 113 | Body { SimpleStatement | indentedBody } 114 | 115 | context ParenPattern { "(" Pattern ")" } 116 | context BracketPattern { "[" Pattern "]" } 117 | Pattern { CommaSep(!in declName | ParenPattern | BracketPattern) } 118 | 119 | MaybePattern(after) { ~(Pattern after) Pattern } 120 | } 121 | 122 | tokens { 123 | if { kw("if") } 124 | whileElif { kw("while" | "elif") } 125 | else { kw("else") } 126 | tryFinally { kw("try" | "finally") } 127 | for { kw("for") } 128 | in { kw("in") } 129 | as { kw("as") } 130 | async { kw("async") } 131 | def { kw("def") } 132 | except { kw("except") } 133 | class { kw("class") } 134 | with { kw("with") } 135 | lambda { kw("lambda") } 136 | del { kw("del") } 137 | yield { kw("yield") } 138 | raise { kw("raise") } 139 | from { kw("from") } 140 | import { kw("import") } 141 | passBreakCont { kw("pass" | "break" | "continue") } 142 | globalNonlocal { kw("global" | "nonlocal") } 143 | returnAssert { kw("return" | "assert") } 144 | prefixKw { kw("not" | "await") } 145 | atom="atom" { ("None" | "True" | "False") !identifierChar } 146 | self="atom" { "self" !identifierChar } 147 | binopKw { kw("or" | "and" | "in" | "is" (" "+ "not")? | "not" (" "+ "in")?) } 148 | 149 | builtin="builtin" { 150 | ("abs" | "all" | "any" | "bin" | "bool" | "bytearray" | "callable" | "chr" | 151 | "classmethod" | "compile" | "complex" | "delattr" | "dict" | "dir" | "divmod" | 152 | "enumerate" | "eval" | "filter" | "float" | "format" | "frozenset" | 153 | "getattr" | "globals" | "hasattr" | "hash" | "help" | "hex" | "id" | 154 | "input" | "int" | "isinstance" | "issubclass" | "iter" | "len" | 155 | "list" | "locals" | "map" | "max" | "memoryview" | "min" | "next" | 156 | "object" | "oct" | "open" | "ord" | "pow" | "property" | "range" | 157 | "repr" | "reversed" | "round" | "set" | "setattr" | "slice" | 158 | "sorted" | "staticmethod" | "str" | "sum" | "super" | "tuple" | 159 | "type" | "vars" | "zip" | "__import__" | "NotImplemented" | 160 | "Ellipsis" | "__debug__" | "ascii" | "bytes" | "exec" | "print") !identifierChar 161 | } 162 | 163 | print="builtin" { "print" !identifierChar } 164 | 165 | binop { 166 | op(("^" | "&" | "|" | "<<" | ">>" | "+" | "-" | "*" "*"? | "@" | "/" | "%" | "/") "="? | 167 | "=" | "<" | ">" | "==" | ">=" | "<=" | "<>" | "!=" | ":=") 168 | } 169 | prefixOp { op("*" | "+" | "-" | "~") } 170 | 171 | number="number" { 172 | ("0b" | "OB") ("0" | "1" | "_")+ | 173 | ("0o" | "0O") ("0"-"7" | "_")+ | 174 | ("0x" | "OX") (digit | "a"-"f" | "A"-"F" | "_")+ | 175 | (digit (digit | "_")* (("l" | "L") | ("." (digit | "_")+))? | "." (digit | "_")+) 176 | (("e" | "E") ("+" | "-")? (digit | "_")+)? ("j" | "J")? 177 | } 178 | 179 | string="string" { 180 | ("u" | "U" | "r" | "R" | "b" | "B")+ ~("'" | "\"") stringQuoted | 181 | stringQuoted 182 | } 183 | 184 | fstring { fstringPrefix ~("'" | "\"") fstringQuoted } 185 | 186 | variableName="variable" { identifier } 187 | 188 | comment="comment" { "#" .* } 189 | } 190 | 191 | stringQuoted { 192 | "'''" ("\\" _ | !"'''" _)* "'''" | 193 | "\"\"\"" ("\\" _ | !"\"\"\"" _)* "\"\"\"" | 194 | "'" ("\\" _ | !"'" .)* "'" | 195 | "\"" ("\\" _ | !"\"" .)* "\"" 196 | } 197 | 198 | fstringPrefix="string" { 199 | ("u" | "U" | "r" | "R")* ("f" | "F") ("u" | "U" | "r" | "R")* 200 | } 201 | fstringQuoted { 202 | str("'''") (!"'''" fstringU | fstringItem)* str("'''") | 203 | str("\"\"\"") (!"\"\"\"" fstringU | fstringItem)* str("\"\"\"") | 204 | str("'") (str("\\") fstringU | !"'" fstringD | fstringItem)* str("'") | 205 | str("\"") (str("\\") fstringU | !"\"" fstringD | fstringItem)* str("\"") 206 | } 207 | fstringItem { str("{{") | str("}}") | replacementField } 208 | replacementField { op("{") Expr? op("=")? (op("!") conversion)? (op(":") formatSpec)? op("}") } 209 | replacementFieldSuffix { ("=" ("!" | ":" | "}")) } 210 | conversion="keyword" { (!(":" | "}" | " " | "\t") .)* } 211 | formatSpec { (fstringD | replacementField)* } 212 | fstringD="string" { !("{" | "}") . } 213 | fstringU="string" { !("{" | "}") _ } 214 | 215 | kw(word)="keyword" { word !identifierChar } 216 | op(expr)="operator" { expr } 217 | str(expr)="string" { expr } 218 | 219 | context indentedBody { 220 | "\n" (whitespaceSimple | "\n")* 221 | (&stillIndented (!kw("return" | "pass") Statement) (whitespaceSimple | "\n")*)* 222 | (&stillIndented ~("return" | "pass") Statement)? 223 | } 224 | 225 | identifier { identifierStart identifierChar* } 226 | 227 | declName="def" { identifier } 228 | typeDeclName="type def" { identifier } 229 | labelName="meta" { identifier ~(" "* "=" !"=") } 230 | calleeName="variable callee" { identifier ~"(" } 231 | calleeProp="property callee" { identifier ~"(" } 232 | propName="property" { identifier } 233 | compLocalName="variable-2" { identifier &isCompLocal } 234 | 235 | whitespaceSimple { (" " | "\t" | comment) } 236 | 237 | whitespace { (whitespaceSimple | "\\\n" | ~"\n" &maySkipNewline "\n")* } 238 | 239 | identifierStart { letter | "_" } 240 | identifierChar { letter | digit | "_" } 241 | letter { "a"-"z" | "A"-"Z" | "\u00a1"-"\uffff" | "_" } 242 | digit { "0"-"9" } 243 | -------------------------------------------------------------------------------- /src/python.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./python.mode" 4 | import {markLocals} from "./locals" 5 | 6 | const scopes = ["LambdaDef", "FuncDef", "ClassDef"] 7 | const allowNewline = ["ArgList", "ParamList", "FromImportList", "ParenExpr", "ArrayLiteral", "ObjectLiteral", "Subscript", "DictProp", "ParenPattern", "BracketPattern"] 8 | 9 | function maySkipNewline(_line, _pos, cx) { 10 | return cx && allowNewline.indexOf(cx.name) > -1 11 | } 12 | 13 | function countIndent(line, pos) { 14 | let count = 0 15 | for (let i = pos - 1; i >= 0; i--) { 16 | let ch = line.charCodeAt(i) 17 | if (ch === 32) count++ 18 | else if (ch === 9) count += 4 19 | else break 20 | } 21 | return count 22 | } 23 | 24 | function stillIndented(line, pos, cx) { 25 | while (cx && cx.name != "Statement") cx = cx.parent 26 | return cx && countIndent(line, pos) > countIndent(cx.startLine, cx.startPos) 27 | } 28 | 29 | function isCompLocal(line, pos) { 30 | let id = /\w*$/.exec(line.slice(0, pos))[0] 31 | let forDecl = /\s+for\s+(\w+)/.exec(line.slice(pos)) 32 | return forDecl ? forDecl[1] == id : false 33 | } 34 | 35 | function aligned(cx) { 36 | return !/^\s*((#.*)?$)/.test(cx.startLine.slice(cx.startPos + 1)) 37 | } 38 | 39 | const bracketed = { 40 | ObjectLiteral: "}", 41 | ArrayLiteral: "]", SubScript: "]", BracketPattern: "]", 42 | ParamList: ")", ArgList: ")", ParenExpr: ")", ParenPattern: ")" 43 | } 44 | 45 | function findIndent(cx, textAfter, curLine, config) { 46 | if (!cx) return 0 47 | if (cx.name == "string") return CodeMirror.Pass 48 | 49 | let brack = bracketed[cx.name] 50 | if (brack) { 51 | if (curLine != cx.startLine && aligned(cx)) 52 | return CodeMirror.countColumn(cx.startLine, cx.startPos, config.tabSize) + 1 53 | 54 | let closed = textAfter && textAfter.charAt(0) == brack 55 | let flat = closed && brack != ")" || curLine == cx.startLine 56 | return findIndent(cx.parent, closed ? null : textAfter, cx.startLine, config) + (flat ? 0 : 2 * config.indentUnit) 57 | } else if (cx.name == "indentedBody") { 58 | for (;; cx = cx.parent) { 59 | if (!cx) return config.indentUnit 60 | if (cx.name == "Statement") return CodeMirror.countColumn(cx.startLine, null, config.tabSize) + config.indentUnit 61 | } 62 | } else { 63 | return findIndent(cx.parent, textAfter, curLine, config) + 64 | ((cx.name == "DictProp" || cx.name == "Statement") && cx.startLine != curLine ? 2 * config.indentUnit : 0) 65 | } 66 | } 67 | 68 | function pythonMarkLocals(token, stream, state) { 69 | let marked = markLocals(token, scopes, stream, state) 70 | if (token == "def") { 71 | let cx = state.context 72 | while (cx && scopes.indexOf(cx.name) == -1) cx = cx.parent 73 | if (cx && cx.name == "ClassDef") marked = "def property" 74 | else if (marked == "def local") marked = "variable-2" 75 | } 76 | return marked 77 | } 78 | 79 | class PythonMode extends CodeMirror.GrammarMode { 80 | constructor(conf) { 81 | super(grammar, { 82 | predicates: {maySkipNewline, stillIndented, isCompLocal} 83 | }) 84 | this.conf = conf 85 | } 86 | 87 | token(stream, state) { 88 | return pythonMarkLocals(super.token(stream, state), stream, state) 89 | } 90 | 91 | indent(state, textAfter, line) { 92 | return findIndent(state.contextAt(line, line.length - textAfter.length), textAfter, null, this.conf) 93 | } 94 | } 95 | 96 | PythonMode.prototype.electricInput = /^\s*[\}\]\)]$/ 97 | // ` also gets autoclosed since it's often used in comments/docstrings. 98 | PythonMode.prototype.closeBrackets = {triples: "'\"", pairs: "()[]{}''\"\"``",} 99 | PythonMode.prototype.lineComment = "#" 100 | PythonMode.prototype.fold = "indent" 101 | 102 | CodeMirror.defineMode("google-python", conf => new PythonMode(conf)) 103 | -------------------------------------------------------------------------------- /src/typescript.grammar: -------------------------------------------------------------------------------- 1 | extends "./javascript.grammar" 2 | 3 | skip whitespace { 4 | context Statement { 5 | type typeDeclName TypeParams? op("=") Type semi | 6 | namespace (~(identifier ".") variable ".")* declName Block | 7 | interface typeDeclName TypeParams? (extends CommaSep(Type))? ObjType | 8 | (~(kw("const") enum) kw("const") enum | enum) typeDeclName EnumBody | 9 | (declare | kw("abstract")) Statement | 10 | super 11 | } 12 | 13 | context TypeParams { "<" CommaSep(typeDeclName (extends Type)? (op("=") Type)?) ">" } 14 | 15 | context TypeArgs { "<" CommaSep(Type) ">" } 16 | 17 | Type { TypeAtom TypeSuffix* } 18 | 19 | TypeAtom { 20 | kw("this") | 21 | atom | 22 | kw("typeof") variable ("." propName | "[" Expression "]")* | 23 | kw("keyof" | "readonly" | "unique") Type | 24 | ~("(" !(")" | "..." | identifier ("?" | ":"))) "(" Type ")" | 25 | new? TypeParams? ParamListSpec op("=>") RetType | 26 | (~(identifier ".") variable ".")* typeName TypeArgs? | 27 | TupleType | 28 | ObjType | 29 | string | 30 | number 31 | } 32 | 33 | TypeSuffix { 34 | (op("&" | "|") | kw("extends")) Type | 35 | "[" Type? "]" | 36 | op("?") Type op(":") Type 37 | } 38 | 39 | TypeAnn { 40 | ":" Type 41 | } 42 | 43 | RetType { 44 | (~(identifier kw("is")) variable kw("is"))? Type 45 | } 46 | 47 | context ParamListSpec { ParamList } 48 | 49 | context ParamList { // FIXME typing comes before default values 50 | "(" CommaSep(Decorator* modifier* "..."? Pattern "?"? TypeAnn? (op("=") ExpressionNoComma)?) ")" 51 | } 52 | 53 | context ObjType { "{" ObjTypeField? (("," | ";") ObjTypeField?)* "}" } 54 | 55 | context TupleType { "[" CommaSep((labelName ":")? Type) "]" } 56 | 57 | ObjTypeField { 58 | new? TypeParams? ParamList (":" RetType)? | 59 | modifier* ("[" (~(identifier (":" | "in")) identifier (":" | kw("in")) Type | Expression) "]" TypeAnn | 60 | (propDeclName | string | number) "?"? (TypeParams? ParamList)? (":" RetType)?) 61 | } 62 | 63 | Callee { calleeName TypeArgs? } 64 | 65 | NewExpression { new ("." kw("target") | calleeName TypeArgs? | BaseExpression) } 66 | 67 | context ArrowRest { op("=>") TypeParams? (Block | ExpressionNoComma) } 68 | 69 | ExpressionSuffix(ContExpression) { 70 | kw("as") Type | 71 | op("!") | 72 | suffixOp | 73 | (binOp | kwBinOp) ContExpression | 74 | ArgList | 75 | template | 76 | ("." | "?.") (calleeProp TypeArgs? | propName) | 77 | "[" Expression "]" | 78 | op("?") Expression op(":") ContExpression 79 | } 80 | 81 | BaseExpression { 82 | "<" Type ">" BaseExpression | 83 | super 84 | } 85 | 86 | context FunctionDef { 87 | TypeParams? ParamList (":" RetType)? (Block | semi) 88 | } 89 | 90 | ClassDef { 91 | TypeParams? (extends Type)? (kw("implements") CommaSep(Type))? ClassBody 92 | } 93 | 94 | context ClassBody { 95 | "{" ((modifier | override)* ClassItem | Decorator)* "}" 96 | } 97 | 98 | context ClassItem { 99 | propModifier? 100 | (propDeclName | "[" Expression "]" | number | string) 101 | (asyncStar? FunctionDef | ("!" | "?")? TypeAnn? (op("=") Expression)? semi) 102 | } 103 | 104 | VariableDeclarator { Pattern op("!")? TypeAnn? (op("=") ExpressionNoComma)? } 105 | 106 | context EnumBody { "{" CommaSep(propDeclName (op("=") ExpressionNoComma)?) "}" } 107 | 108 | ParamsAndArrow { ~(ParamList (":" RetType)? "=>") ParamList (":" RetType)? } 109 | } 110 | 111 | modifier { kw("public" | "private" | "protected" | "readonly" | "abstract" | "static") } 112 | enum { kw("enum") } 113 | 114 | propModifier { kw("get" | "set" | "async") !(" "* ("," | "}" | ":" | "(" | "<")) } 115 | 116 | typeDeclName="def type" { identifier } 117 | typeName="type" { identifier } 118 | 119 | calleeName="variable callee" { identifier ~("<" !" " | " "* (typeArgStructure " "*)? "(") } 120 | calleeProp="property callee" { identifier ~(" "* (typeArgStructure " "*)? "(") } 121 | 122 | typeArgStructure { "<" (typeArgStructure | "=>" | !">" _)* ">" } 123 | 124 | declNameAndArrow { declName ~(whitespace (":" whitespace Type whitespace)? "=>") } 125 | 126 | type { kw("type") ~(spaceChar* identifierStart) } 127 | namespace { kw("namespace") ~(spaceChar* identifierStart) } 128 | interface { kw("interface") ~(spaceChar* identifierStart) } 129 | declare { kw("declare") ~(spaceChar* identifierStart) } 130 | override { kw("override") ~(spaceChar* identifierStart) } 131 | -------------------------------------------------------------------------------- /src/typescript.js: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from "codemirror" 2 | import "codemirror-grammar-mode" 3 | import * as grammar from "./typescript.mode" 4 | import {markLocals} from "./locals" 5 | import {indent} from "./c_indent" 6 | import {canInsertSemi} from "./js_semi" 7 | import {TemplateTokenizer} from "./template_string_inline_language"; 8 | 9 | const scopes = ["Block", "FunctionDef", "ArrowFunc", "ForStatement", "ParamListSpec"] 10 | 11 | class TSMode extends CodeMirror.GrammarMode { 12 | constructor(conf, modeConf) { 13 | super(grammar, { 14 | predicates: {canInsertSemi: modeConf.requireSemicolons === false ? canInsertSemi : () => false} 15 | }) 16 | this.templateTokenizer = new TemplateTokenizer(conf); 17 | this.indentConf = {doubleIndentBrackets: ">)", dontCloseBrackets: ")", 18 | tabSize: conf.tabSize, indentUnit: conf.indentUnit, 19 | forceContent: true} 20 | } 21 | 22 | startState() { 23 | const state = super.startState(); 24 | state.embeddedParserState = this.templateTokenizer.startState(); 25 | return state; 26 | } 27 | 28 | copyState(state) { 29 | const copy = super.copyState(state); 30 | copy.embeddedParserState = 31 | this.templateTokenizer.copyState(state.embeddedParserState); 32 | return copy; 33 | } 34 | 35 | token(stream, state) { 36 | const templateTokenizerState = state.embeddedParserState; 37 | if (this.templateTokenizer 38 | .shouldInterceptTokenizing(templateTokenizerState)) { 39 | const {handled, style} = this.templateTokenizer 40 | .interceptTokenizing(stream, templateTokenizerState); 41 | if (handled) { 42 | return style; 43 | } 44 | } 45 | const style = super.token(stream, state); 46 | this.templateTokenizer.trackState(style, stream, templateTokenizerState); 47 | return markLocals(style, scopes, stream, state) 48 | } 49 | 50 | indent(state, textAfter, line) { 51 | if (!textAfter) textAfter = line = "x" // Force getContextAt to terminate the statement, if needed 52 | return indent(state, textAfter, line, this.indentConf) 53 | } 54 | } 55 | 56 | let meta = { 57 | electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, 58 | blockCommentStart: "/*", 59 | blockCommentEnd: "*/", 60 | blockCommentContinue: " * ", 61 | lineComment: "//", 62 | fold: "brace", 63 | closeBrackets: "()[]{}''\"\"``" 64 | } 65 | for (let prop in meta) TSMode.prototype[prop] = meta[prop] 66 | 67 | CodeMirror.registerHelper("wordChars", "google-typescript", /[\w$]/) 68 | 69 | CodeMirror.defineMode("google-typescript", (conf, modeConf) => new TSMode(conf, modeConf)) 70 | -------------------------------------------------------------------------------- /test/c/def.c: -------------------------------------------------------------------------------- 1 | [type void] [def foo]() {} 2 | [keyword struct] [def bar]{}; 3 | [type int] *[def baz]() {} 4 | -------------------------------------------------------------------------------- /test/c/double_block.c: -------------------------------------------------------------------------------- 1 | [variable x]; 2 | [keyword for] (;;) 3 | [keyword for] (;;) 4 | [variable x][operator ++]; 5 | [keyword return]; 6 | -------------------------------------------------------------------------------- /test/c/indent.c: -------------------------------------------------------------------------------- 1 | [type void] [def foo]([type void]* [def&local a], [type int] [def&local b]) { 2 | [type int] [def&local c] [operator =] [variable-2 b] [operator +] 3 | [number 1]; 4 | [keyword return] [operator *][variable-2 a]; 5 | 6 | [keyword if] ([number 1]) 7 | [number 2]; 8 | [keyword else] 9 | [number 3]; 10 | } 11 | -------------------------------------------------------------------------------- /test/c/indent_switch.c: -------------------------------------------------------------------------------- 1 | [keyword switch] ([variable x]) { 2 | [keyword case] [number 10]: { 3 | [keyword return] [number 20]; 4 | } 5 | [keyword default]: { 6 | [variable&callee printf]([string "foo %c"], [variable x]); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/c/lookahead_type.c: -------------------------------------------------------------------------------- 1 | [type int] 2 | [def foo] [operator =] [number 2] 3 | -------------------------------------------------------------------------------- /test/c/preprocessor.c: -------------------------------------------------------------------------------- 1 | [meta #define FOO 3] 2 | [type int] [def foo]; 3 | [meta #define BAR\] 4 | [meta 4] 5 | [type unsigned] [type int] [def bar] [operator =] [number 8]; 6 | [meta #include ][comment&meta // comment] 7 | 8 | [meta #define FOO(][comment&meta /* some comment */][meta ...) \] 9 | [comment&meta /* another comment */][meta \] 10 | [meta MyMacroIsGreat(__VA_ARGS__);] 11 | 12 | [meta MY_MACRO]([variable foo] [operator +] [variable&callee bar]([number 10])); 13 | -------------------------------------------------------------------------------- /test/c/tmp.c: -------------------------------------------------------------------------------- 1 | foo: [variable x]; 2 | -------------------------------------------------------------------------------- /test/clif/grammar.clif: -------------------------------------------------------------------------------- 1 | [comment # This is a comment] 2 | 3 | [comment # Unhighlighted variable] 4 | foo 5 | xdef 6 | defx 7 | 8 | [keyword from] [string "foo.h"] [keyword import] * 9 | [keyword from] [string "bar.h"] [keyword import] * [keyword as] [def bar] 10 | 11 | [keyword from] foo.bar [keyword import] baz 12 | 13 | [comment # Variable definition] 14 | [def x]: int 15 | 16 | [keyword capsule] [def Foo] 17 | 18 | [meta @deco] 19 | [keyword def] [def f]([variable-2 x]: int) -> [atom None] 20 | 21 | [comment # Parameter with default value] 22 | [keyword def] [def f]([variable-2 x]: int = [keyword default]) 23 | 24 | [comment # No parameters] 25 | [keyword def] [def f]() 26 | 27 | [comment # Named return type] 28 | [keyword def] [def f]() -> [string `foobar`] [keyword as] foo.bar 29 | [keyword def] [def f]() -> foo.bar 30 | [keyword def] [def f]() -> foo.bar 31 | 32 | [comment # Callable return type] 33 | [keyword def] [def f]() -> [string `foobar`] [keyword as] ([variable-2 x]: int) -> foo.bar 34 | [keyword def] [def f]() -> [string `foobar`] [keyword as] [keyword lambda] ([variable-2 x]: int) -> Boo 35 | 36 | [comment # Function/method body] 37 | [keyword return] foo([operator ...]) 38 | 39 | [comment # Type alias] 40 | [keyword type] [def A] = int 41 | [keyword use] [string `std::string_view`] [keyword as] bytes 42 | 43 | [comment # Compound statements] 44 | [keyword from] [string "baz.h"]: 45 | [keyword namespace] [string `std::boo`]: 46 | [keyword def] [def f]() 47 | [keyword interface] [def A] : 48 | [def x]: int 49 | -------------------------------------------------------------------------------- /test/clif/indent.clif: -------------------------------------------------------------------------------- 1 | # test: indent_only 2 | 3 | def f( 4 | x: int) 5 | 6 | def f(x: int, 7 | y: int) 8 | 9 | def f(x: int, 10 | y: int) -> (x: int, 11 | ) -> int 12 | 13 | interface Foo: 15 | x: int 16 | 17 | class C: 18 | def f(self) -> C 19 | 20 | # Comment directly after DEDENT. 21 | # TODO(slebedev): This is a known bug which also affects google-python mode. 22 | # Shift to the toplevel and the test will fail. 23 | def f() -> C 24 | 25 | from "foo.h": 26 | x: int 27 | 28 | namespace `std::foo`: 29 | x: int 30 | 31 | interface Foo: 32 | def bar(self) -> T 33 | 34 | def bar(self) -> Foo 35 | def boo(self) 36 | -------------------------------------------------------------------------------- /test/cpp/class.cpp: -------------------------------------------------------------------------------- 1 | [keyword class] [type&def BitcodeReaderValueList] { 2 | [type&qualifier std]::[type&qualified vector]<[type WeakVH]> [def&property ValuePtrs]; 3 | 4 | [keyword typedef] [type&qualifier std]::[type&qualified vector]<[type&qualifier std]::[type&qualified pair]<[type Constant]*, [type unsigned]> > [def&property ResolveConstantsTy]; 5 | [type ResolveConstantsTy] [def&property ResolveConstants]; 6 | [type LLVMContext] &[def&property Context]; 7 | [keyword public]: 8 | [def BitcodeReaderValueList]([type LLVMContext] &[def&local C]) : [callee&property Context]([variable-2 C]) {} 9 | [def ~BitcodeReaderValueList]() { 10 | [variable&callee assert]([variable ResolveConstants].[property&callee empty]() [operator &&] [string "Constants not resolved?"]); 11 | } 12 | 13 | [comment // vector compatibility methods] 14 | [type unsigned] [def&property size]() [keyword const] { [keyword return] [variable ValuePtrs].[property&callee size](); } 15 | [type void] [def&property resize]([type unsigned] [def&local N]) { [variable ValuePtrs].[property&callee resize]([variable-2 N]); } 16 | [type void] [def&property push_back]([type Value] *[def&local V]) { [variable ValuePtrs].[property&callee emplace_back]([variable-2 V]); } 17 | 18 | [type Foo] [keyword operator][operator +]([keyword const] [type Box]& [def&local b]) {} 19 | }; 20 | 21 | [type BitcodeReaderValueList] [def a]([variable cx]); 22 | 23 | [keyword template] <[keyword class] [type&def T], [keyword class] [type&def V]> 24 | [keyword class] [type&def Class] : [keyword public] [type BaseClass] { 25 | [keyword const] [type MyType]<[type&local T], [type&local V]> [def&property member_]; 26 | }; 27 | -------------------------------------------------------------------------------- /test/cpp/ctor_dtor.cpp: -------------------------------------------------------------------------------- 1 | [def&qualifier Foo]::[qualified&def Foo]([type int] [def&local y]) 2 | : [callee&property x]([variable-2 y]), [callee&property Foo]() { 3 | } 4 | [def&qualifier Foo]::[qualified&def ~Foo]() {} 5 | 6 | [keyword template] <[keyword class] [type&def A1]> 7 | [keyword class] [type&def Foo] { 8 | [keyword public]: 9 | [keyword virtual] [def ~Foo]() { } 10 | [keyword protected]: 11 | [def Foo]() 12 | : [callee&property t_](::[variable&qualifier bar]::[variable&qualifier Baz]::[qualified&variable VALUE]) { } 13 | [keyword explicit] [def Foo](::[type&qualifier bar]::[type&qualifier Baz]::[qualified&type Type] [def&local t]) 14 | : [callee&property t_]([variable-2 t]) { } 15 | ::[type&qualifier bar]::[type&qualified Baz] [def&property t_]; 16 | }; 17 | -------------------------------------------------------------------------------- /test/cpp/grammar.cpp: -------------------------------------------------------------------------------- 1 | [keyword using] [variable Foo] [operator =] ::[qualified&type Foo]; 2 | 3 | [[[[ [meta foo]::[meta target](gpu, [[cpu]]) ]]]] 4 | [keyword class] [type&def Foo]; 5 | 6 | [type void] [def foo]([type Bar]& [def&local x], [type Bar]& [def&local y]) [keyword noexcept]; 7 | 8 | [type void] [def Foo]([keyword const] [type unsigned] [type char]* [def&local in_bytes], [type char]* [def&local out]); 9 | 10 | [variable&qualifier foo]::[qualified&callee&variable bar](); 11 | 12 | [type void] [def&qualifier X]::[qualified&def Y]() { 13 | [variable x_]->[callee&property Y]([variable&callee A]([keyword this], [operator &][variable&qualifier B]::[qualified&variable C]<[type D], [number 2]>)); 14 | [keyword delete] [[]] [variable baz]; 15 | [variable baz].[property foo]<[type quux]>(); 16 | } 17 | 18 | [type void] [def foo](::[qualified&type y] [def&local data], [type void]* [def&local arg], [type void] (*[def&local r])([type void]*)); 19 | 20 | [keyword class] [type&def Z] { 21 | [keyword typedef] [type void] (*[def&property Bar])([type&qualifier x]::[qualified&type Y] [def&local z], [type void]* [def&local arg]); 22 | 23 | [keyword public]: 24 | [type Z]& [keyword operator][operator =]([keyword const] [type Z]& [def&local x]); 25 | [type Z]& [keyword operator][operator =]([type Z]&& [def&local x]); 26 | 27 | [type int] [def&property num_to_block_] [meta GUARDED_BY]([string "foo"] [operator ++] [variable lock_]); 28 | 29 | [meta MOCK_METHOD3]([variable DoFoo], [keyword bool]([keyword const] [variable&qualifier ns]::[qualified&variable Something][operator &], 30 | [keyword const] [variable&qualifier std]::[qualified&variable vector][operator <][keyword int][operator >][operator &], [keyword const] [variable string])); 31 | 32 | [keyword static_assert]([variable compliant] [operator ||] [operator !][variable&qualifier std]::[qualifier&variable is_trivially_destructible]<[type T]>::[qualified&variable value], 33 | [string "Not compliant with std::is_trivially_destructible; "] 34 | [string "Standard: true, Implementation: false"]); 35 | }; 36 | 37 | [keyword template] <[type size_t] [def max_size], 38 | [keyword class] [def&type ExpectedExternalId] [operator =] 39 | [keyword typename] [type&qualifier std]::[type&qualifier conditional]<[type true], [type int], [type bool]>::[type&qualified type]> 40 | [keyword struct] [type&def Foo] { 41 | [type&qualifier std]::[type&qualified array]<[type char], [type max_size]> [def&property data]; 42 | [type size_t] [def&property size]; 43 | [type bool] [keyword operator]()([keyword const] [type&qualifier std]::[type&qualified pair]<[type int32], [type double]> & [def&local a]) [keyword override]; 44 | [type void] [def&property foo]() [operator =] [keyword delete]; 45 | }; 46 | 47 | [type int] [def emit]([type int]... [def&local s]) { 48 | } 49 | 50 | [keyword class] [def&type Foo] : [keyword public] [type Bar] { 51 | [meta SOME_MACRO]([variable SomethingCapitalized], [variable SomethingCapitalized1]); 52 | [meta SOME_MACRO]([variable SomethingCapitalized], [variable SomethingCapitalized1]); 53 | [keyword class] [def&type Baz] { 54 | [keyword public]: 55 | [type void] [def&property abc](); 56 | }; 57 | [keyword enum] [keyword class] [def&type MyEnum] : [type uint8] {[def&property kValue0], [def&property kValue1]}; 58 | }; 59 | [meta SOME_OTHER_MACRO]([variable SomethingThatLooksLikeAType]); 60 | 61 | [keyword template] <[keyword typename] [type&def X]> 62 | [keyword inline] [type void] [def Foo]([type&local X]* [def&local x]) { 63 | [keyword for] ([keyword typename] [type&qualifier X]::[type&qualified iterator] [def&local it] [operator =] [variable-2 x]->[callee&property begin](); 64 | [variable-2 it] [operator !=] [variable-2 x]->[callee&property end](); [operator ++][variable-2 it]) 65 | [variable&callee Bar]([operator &]([operator *][variable-2 it])); 66 | } 67 | 68 | [keyword template] <[keyword typename] [type&def T]> 69 | [keyword inline] [keyword typename] [type&qualifier std]::[type&qualifier enable_if]<[type&qualifier std]::[type&qualifier is_same]<[type&local T], [type int]>::[type&qualified value], [type void]>::[type&qualified type] 70 | [def Foo]() { 71 | [keyword return] [type Foo]{[number 0]} [operator ||] [variable&qualifier std]::[type&qualified Foo]{[number 1]}; 72 | } 73 | } 74 | 75 | [keyword namespace] [def ns] { 76 | [type int] [def x]; 77 | [type int] [def y] [operator =] [variable x]; 78 | [type void] [def&qualifier A]::[qualified&def B]() { 79 | [keyword return] [string R"(foo " ) bar)"] [string "ok"]; 80 | } 81 | [type void] [def&qualifier X]::[qualified&def Y]() { 82 | [callee&variable B](); 83 | } 84 | } 85 | 86 | [keyword if] ([variable foo]) [keyword return] [variable bar]; 87 | 88 | [keyword const] [type char]* [def s1][[]] [operator =] [string R"foo(] 89 | [string Hello can have "quotes"] 90 | [string World] 91 | [string )foo"]; 92 | 93 | [keyword using] [variable FooOrder] [operator =] [type&qualifier std]::[type&qualified function]<[type bool]([keyword const] [type Foo]&, [keyword const] [type Foo]&)>; 94 | 95 | [variable&qualifier std]::[qualified&variable xyz]<[keyword class] [type foo]>; 96 | 97 | [type string] [def xyzzy]([type Bar] [def&local s]) { 98 | [keyword switch] ([variable-2 s]) { 99 | [keyword case] [variable&qualifier Bar]::[qualified&variable OK]: 100 | [keyword return] [string "OK"]; 101 | [keyword case] [variable&qualifier Bar]::[qualified&variable NotOK]: 102 | [keyword return] [string "NOT OK"]; 103 | } 104 | [keyword if] ([variable foo] [operator &&] 105 | [variable foo]) { 106 | [number 2u] [operator +] [number 2ul] [operator +] [number 2uLl]; 107 | } 108 | 109 | [keyword return] [variable&callee Foo]([[ [variable a], 110 | [variable b] ]]() { 111 | [number 3]; 112 | }); 113 | } 114 | 115 | [keyword struct] [def&type Extend] { 116 | [keyword using] [variable Bar] [operator =] [keyword struct] {}; 117 | [keyword using] [variable type] [operator =] [type integer_sequence]<[type Ints]..., ([type Ints] [operator +] [variable SeqSize])...>; 118 | }; 119 | 120 | [[[[ [meta noreturn] ]]]] 121 | [type int] [def sizeofint]() { 122 | ([variable u])[[ [number 1] ]]; 123 | [variable&callee foo]([[ [variable argv] ]] { 124 | [variable&callee bar]([variable argv]); 125 | }); 126 | [keyword return] [keyword sizeof]([type int]); 127 | } 128 | 129 | [def&qualifier DerivedClass]::[def&qualified DerivedClass]([type int] [def&local i]) 130 | : [variable&qualifier foo]::[variable&qualifier bar]::[property ParentClass]<[type SomeTemplateParameter]>([variable-2 i]) {} 131 | 132 | [keyword template] <[keyword const] [type int] &([def&qualifier Base]::*[def&qualified BaseValueProvider])() [keyword const]> 133 | [keyword class] [def&type Foo] { 134 | [keyword public]: 135 | [def Foo]() {} 136 | [keyword const] [type int] [def&property Val]([type Base] &[def&local base]) { 137 | [keyword if] ([keyword const] [keyword auto]* [def&local foo] [operator =] [variable&callee bar]()) { 138 | [keyword return] [number 1]; 139 | } 140 | [keyword if] ([keyword auto] [def&local foo] [operator =] [number 3]; [variable-2 foo] [operator >] [number 1]) { 141 | [keyword return] [number 2]; 142 | } 143 | [keyword return] ([variable-2 base].*[property BaseValueProvider])(); 144 | } 145 | [keyword friend] [keyword class] [def&type X]; 146 | [keyword struct] [def&type Baz] { 147 | [type int] [def&property x]; 148 | } [def a]; 149 | }; 150 | 151 | [type int] [def z] [meta MACRO]() [operator =] [number 0]; 152 | 153 | [callee&variable Bar]({ 154 | .[property a] [operator =] [variable a], 155 | .[property b] [operator =] [variable b].[property&callee Bar](), 156 | .[property c] [operator =] [variable c]->[property Baz] 157 | }); 158 | 159 | [keyword auto] [[ [def a], [def b] ]] [operator =] [variable x]; 160 | 161 | [type void] [def abc]([keyword const] [type char]* [local&def msg]...) { 162 | [keyword for] ([type int] [def&local x] [operator =] [number 1]; [variable-2 x] [operator <] [number 5]; [variable-2 x][operator ++], [variable y][operator ++]) { 163 | } 164 | [type int]* [keyword restrict] [def&local baz]; 165 | } 166 | [type void] [def def]([keyword const] [type char]* [local&def msg], ...); 167 | 168 | [qualifier&def ClassName]:: 169 | [qualified&def ClassName]([type T] [def&local a]) {} 170 | 171 | [qualifier&def ClassName2] 172 | ::[qualified&def ClassName2]([type T] [def&local a]) {} 173 | -------------------------------------------------------------------------------- /test/cpp/indent.cpp: -------------------------------------------------------------------------------- 1 | // test: indent_only 2 | if (foo) 3 | return; 4 | 5 | if (foo + 6 | bar) 7 | return; 8 | 9 | 10 | if (foo) { 11 | #if DIRECTIVES_IGNORED 12 | DropEverything(); 13 | } 14 | 15 | if (a->ba( 16 | baz)) {} 17 | 18 | 19 | LOG(FOO) << "foo" 20 | << "bar"; 21 | 22 | while (foo + 23 | bar) { 24 | 25 | } // aligning to parens 26 | 27 | namespace mynamespace { 28 | } 29 | 30 | const Foo& foo = 31 | bar.baz().quux(X); 32 | 33 | const Foo& foo = 34 | bar.baz().quux( 35 | X); 36 | 37 | ReturnType 38 | LongClassName::Meth( 39 | Type1 par1) { 40 | 41 | } 42 | 43 | ReturnType LongClassName::Meth( 44 | Type1 par1) { 45 | 46 | } 47 | 48 | method([&](int a, int b) { 49 | 50 | }); 51 | 52 | O C::M(T a, 53 | T b) { 54 | 55 | } 56 | 57 | O C::M(T a, 58 | T b) { 59 | 60 | } 61 | 62 | void foo(int my_arg) { 63 | int abc = 64 | MyFunction( 65 | my_arg); 66 | } 67 | 68 | class A 69 | : 70 | public B { 71 | 72 | }; 73 | 74 | class A 75 | : public B { 76 | 77 | }; 78 | 79 | class A 80 | : public B< 81 | X, Y> { 82 | 83 | }; 84 | 85 | class Foo { 86 | public: 87 | 88 | }; 89 | 90 | Type m{a, 91 | b}; 92 | 93 | Type m( 94 | a, 95 | b); 96 | 97 | Type m = { 98 | 99 | }; 100 | 101 | Type m = ( 102 | ); 103 | 104 | Type m = 105 | (); 106 | 107 | MyClass::MyClass( 108 | int var) 109 | : some_var_(var) { 110 | 111 | } 112 | 113 | MyClass::MyClass( 114 | int var) 115 | : some_var_(var) { 116 | 117 | } 118 | 119 | MyClass::MyClass( 120 | int var) 121 | : some_var_(var), 122 | some_other_var_(var + 1) { 123 | 124 | } 125 | 126 | auto something = MakeSomething( 127 | // Some comment comes here 128 | +[](Bar* bar) { 129 | // Another comment 130 | return bar->get(1); 131 | }); 132 | -------------------------------------------------------------------------------- /test/cpp/lambda.cpp: -------------------------------------------------------------------------------- 1 | [keyword auto] [def glambda] [operator =] [[]]([keyword auto] [def&local a], [keyword auto]&& [def&local b]) { 2 | [keyword return] [variable-2 a] [operator <] [variable-2 b]; 3 | }; 4 | -------------------------------------------------------------------------------- /test/cpp/literal.cpp: -------------------------------------------------------------------------------- 1 | [number 10'000]; 2 | [number 0b10'000]; 3 | [number 0x10'000]; 4 | [string "100000"]; 5 | 6 | [type string] [def raw_string] [operator =] [string R"delim(anything] 7 | [string you] 8 | [string want)delim"]; 9 | [atom nullptr]; 10 | -------------------------------------------------------------------------------- /test/cpp/macro.cpp: -------------------------------------------------------------------------------- 1 | [meta TEST]([variable ATest], [variable Move]) { 2 | [type int] [def&local foo]; 3 | [keyword break]; 4 | }; 5 | [keyword return]; 6 | -------------------------------------------------------------------------------- /test/cpp/main.cpp: -------------------------------------------------------------------------------- 1 | [meta #include ] 2 | [meta #include ] 3 | [keyword using] [keyword namespace] [variable std]; 4 | 5 | [type int] [def main]() { 6 | [comment // create a vector to store int] 7 | [type vector]<[type int]> [def&local vec]; 8 | [type int] [def&local i]; 9 | 10 | [comment // display the original size of vec] 11 | [variable cout] [operator <<] [string "vector size = "] [operator <<] [variable-2 vec].[property&callee size]() [operator <<] [variable endl]; 12 | 13 | [comment // push 5 values into the vector] 14 | [keyword for] ([variable-2 i] [operator =] [number 0]; [variable-2 i] [operator <] [number 5]; [variable-2 i][operator ++]) { 15 | [variable-2 vec].[property&callee push_back]([variable-2 i]); 16 | } 17 | 18 | [comment // display extended size of vec] 19 | [variable cout] [operator <<] [string "extended vector size = "] [operator <<] [variable-2 vec].[property&callee size]() [operator <<] [variable endl]; 20 | 21 | [comment // access 5 values from the vector] 22 | [keyword for] ([variable-2 i] [operator =] [number 0]; [variable-2 i] [operator <] [number 5]; [variable-2 i][operator ++]) { 23 | [variable cout] [operator <<] [string "value of vec [["] [operator <<] [variable-2 i] [operator <<] [string "]] = "] [operator <<] [variable-2 vec][[ [variable-2 i] ]] [operator <<] [variable endl]; 24 | } 25 | 26 | [comment // use iterator to access the values] 27 | [qualifier&type vector]<[type int]>::[type&qualified iterator] [def&local v] [operator =] [variable-2 vec].[property&callee begin](); 28 | [keyword while] ([variable-2 v] [operator !=] [variable-2 vec].[property&callee end]()) { 29 | [variable cout] [operator <<] [string "value of v = "] [operator <<] [operator *][variable-2 v] [operator <<] [variable endl]; 30 | [variable-2 v][operator ++]; 31 | } 32 | 33 | [keyword return] [number 0]; 34 | } 35 | -------------------------------------------------------------------------------- /test/cpp/syntax.cpp: -------------------------------------------------------------------------------- 1 | // test: open 2 | 3 | void foo() { 4 | Type [def&local usertype_plain]; 5 | Type* [def&local usertype_lstar]; 6 | Type *[def&local usertype_rstar]; 7 | const Type& [def&local usertype_lref]; 8 | const Type &[def&local usertype_rref]; 9 | int [def&local basictype_plain]; 10 | int* [def&local basictype_lstar]; 11 | int *[def&local basictype_rstar]; 12 | const int& [def&local basictype_lref]; 13 | const int &[def&local basictype_rref]; 14 | Type [def&local equals_usertype_plain] = 1; 15 | Type* [def&local equals_usertype_lstar] = 1; 16 | Type *[def&local equals_usertype_rstar] = 1; 17 | const Type& [def&local equals_usertype_lref] = 1; 18 | const Type &[def&local equals_usertype_rref] = 1; 19 | int [def&local equals_basictype_plain] = 1; 20 | int* [def&local equals_basictype_lstar] = 1; 21 | int *[def&local equals_basictype_rstar] = 1; 22 | const int& [def&local equals_basictype_lref] = 1; 23 | const int &[def&local equals_basictype_rref] = 1; 24 | Type [def&local constructor_usertype_plain](1); 25 | Type* [def&local constructor_usertype_lstar](1); 26 | Type *[def&local constructor_usertype_rstar](1); 27 | const Type& [def&local constructor_usertype_lref](1); 28 | const Type &[def&local constructor_usertype_rref](1); 29 | int [def&local constructor_basictype_plain](1); 30 | int* [def&local constructor_basictype_lstar](1); 31 | int *[def&local constructor_basictype_rstar](1); 32 | const int& [def&local constructor_basictype_lref](1); 33 | const int &[def&local constructor_basictype_rref](1); 34 | Type [def&local initializer_usertype_plain]{1}; 35 | Type* [def&local initializer_usertype_lstar]{1}; 36 | Type *[def&local initializer_usertype_rstar]{1}; 37 | const Type& [def&local initializer_usertype_lref]{1}; 38 | const Type &[def&local initializer_usertype_rref]{1}; 39 | int [def&local initializer_basictype_plain]{1}; 40 | int* [def&local initializer_basictype_lstar]{1}; 41 | int *[def&local initializer_basictype_rstar]{1}; 42 | const int& [def&local initializer_basictype_lref]{1}; 43 | const int &[def&local initializer_basictype_rref]{1}; 44 | LOG << [variable-2 equals_basictype_rstar] << 45 | [variable-2 equals_basictype_lref] << 46 | [variable-2 equals_basictype_rref] << 47 | [variable-2 constructor_usertype_plain] << 48 | [variable-2 constructor_usertype_lstar] << 49 | [variable-2 constructor_usertype_rstar] << 50 | [variable-2 constructor_usertype_lref] << 51 | [variable-2 constructor_usertype_rref] << 52 | [variable-2 constructor_basictype_plain] << 53 | [variable-2 constructor_basictype_lstar] << 54 | [variable-2 constructor_basictype_rstar] << 55 | [variable-2 constructor_basictype_lref] << 56 | [variable-2 constructor_basictype_rref] << 57 | [variable-2 initializer_usertype_plain] << 58 | [variable-2 initializer_usertype_lstar] << 59 | [variable-2 initializer_usertype_rstar] << 60 | [variable-2 initializer_usertype_lref] << 61 | [variable-2 initializer_usertype_rref] << 62 | [variable-2 initializer_basictype_plain] << 63 | [variable-2 initializer_basictype_lstar] << 64 | [variable-2 initializer_basictype_rstar] << 65 | [variable-2 initializer_basictype_lref] << 66 | [variable-2 initializer_basictype_rref]; 67 | } 68 | 69 | void foo() { 70 | [type Type] usertype_plain; 71 | [type Type]* usertype_lstar; 72 | [type Type] *usertype_rstar; 73 | const [type Type]& usertype_lref; 74 | const [type Type] &usertype_rref; 75 | int basictype_plain; 76 | int* basictype_lstar; 77 | int *basictype_rstar; 78 | const int& basictype_lref; 79 | const int &basictype_rref; 80 | [type Type] equals_usertype_plain = 1; 81 | [type Type]* equals_usertype_lstar = 1; 82 | [type Type] *equals_usertype_rstar = 1; 83 | const [type Type]& equals_usertype_lref = 1; 84 | const [type Type] &equals_usertype_rref = 1; 85 | int equals_basictype_plain = 1; 86 | int* equals_basictype_lstar = 1; 87 | int *equals_basictype_rstar = 1; 88 | const int& equals_basictype_lref = 1; 89 | const int &equals_basictype_rref = 1; 90 | [type Type] constructor_usertype_plain(1); 91 | [type Type]* constructor_usertype_lstar(1); 92 | [type Type] *constructor_usertype_rstar(1); 93 | const [type Type]& constructor_usertype_lref(1); 94 | const [type Type] &constructor_usertype_rref(1); 95 | int constructor_basictype_plain(1); 96 | int* constructor_basictype_lstar(1); 97 | int *constructor_basictype_rstar(1); 98 | const int& constructor_basictype_lref(1); 99 | const int &constructor_basictype_rref(1); 100 | [type Type] initializer_usertype_plain{1}; 101 | [type Type]* initializer_usertype_lstar{1}; 102 | [type Type] *initializer_usertype_rstar{1}; 103 | const [type Type]& initializer_usertype_lref{1}; 104 | const [type Type] &initializer_usertype_rref{1}; 105 | int initializer_basictype_plain{1}; 106 | int* initializer_basictype_lstar{1}; 107 | int *initializer_basictype_rstar{1}; 108 | const int& initializer_basictype_lref{1}; 109 | const int &initializer_basictype_rref{1}; 110 | } 111 | -------------------------------------------------------------------------------- /test/cpp/template.cpp: -------------------------------------------------------------------------------- 1 | [keyword template] <[keyword typename] [type&def T], [type size_t] [def inlined] [operator =] [variable kFixedArrayUseDefault]> 2 | [keyword class] [type&def FixedArray] { 3 | [keyword static] [keyword constexpr] [type size_t] [def&property kInlineBytesDefault] [operator =] [number 256]; 4 | 5 | [comment // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,] 6 | [comment // but this seems to be mostly pedantic.] 7 | [keyword template] <[keyword typename] [type&def Iter]> 8 | [keyword using] [variable EnableIfForwardIterator] [operator =] [keyword typename] [type&qualifier std]::[type&qualified enable_if]< 9 | [type&qualifier std]::[type&qualifier is_convertible]< 10 | [keyword typename] [type&qualifier std]::[type&qualifier iterator_traits]<[local&type Iter]>::[type&qualified iterator_category], 11 | [type&qualifier std]::[type&qualified forward_iterator_tag]>::[type&qualified value], 12 | [type int]>::[type&qualified type]; 13 | }; 14 | 15 | [keyword template] <[keyword typename] [def&type Alpha], [keyword typename] [def&type Beta], 16 | [keyword typename] [def&type Gamma]> 17 | [type Fooooooooooooooooooo] [def&qualifier Bar]::[def&qualifier MyNiceClass]<[local&type Alpha], [local&type Beta], 18 | [local&type Gamma]>::[def&qualified Func]() [keyword const] { 19 | [comment // Any comment.] 20 | [type Foo] [def&local foo]; 21 | } 22 | -------------------------------------------------------------------------------- /test/cpp/types.cpp: -------------------------------------------------------------------------------- 1 | ::[variable&qualifier x]::[qualified&variable bar]; 2 | [type foo] [def x]; 3 | 4 | [type unsigned] [type int] [def foo] [operator =] [number 2], [def x], [def bar] [operator =] [string "hi"]; 5 | 6 | [type void] [def f]([type void]* [def&local a], 7 | [type int][[]] [keyword const] [def&local b]) [keyword noexcept] { 8 | [type&qualifier std]::[type&qualified vector]<[type bool]> [def&local quux]; 9 | [variable&callee something]( 10 | [variable-2 a], [variable-2 quux], 11 | ::[variable&qualifier something]::[qualified&variable a]); 12 | } 13 | -------------------------------------------------------------------------------- /test/flatbuffers/testbuffer.fbs: -------------------------------------------------------------------------------- 1 | [comment // example IDL file] 2 | 3 | [keyword namespace] MyGame.Actors; 4 | 5 | [keyword attribute] [attribute "priority"]; 6 | [keyword attribute] [attribute Florb]; 7 | 8 | 9 | [keyword enum] [type Color] : [builtin byte] { 10 | [def&property Red] = [number 1], 11 | [def&property Green] = [number 0x2fF], 12 | [def&property Blue] 13 | } 14 | 15 | [keyword union] [type Any] { [type Monster], [type Weapon], [type Pickup] } 16 | 17 | [keyword struct] [type Vec3] { 18 | [comment // this is a comment inside a struct] 19 | [property x]:[builtin float]; [comment // this is a comment on a struct member] 20 | [property y]:[builtin float]; 21 | [property z]:[builtin float]; 22 | } 23 | 24 | [comment // /** multiline comments work, but] 25 | [comment // * testing infrastructure doesn't allow us to verify that :(] 26 | [comment // */] 27 | [keyword table] [type Monster] { 28 | [property pos]:[type Vec3]; 29 | [property mana]:[builtin short] = [number 150]; 30 | [property hp]:[builtin short] = [number 100]; 31 | [property name]:[builtin string]; 32 | [property friendly]:[builtin bool] = [builtin false] ([attribute deprecated], [attribute priority]: [number 1]); 33 | [property inventory]:[[ [builtin ubyte] ]]; 34 | [property color]:[type Color] = [property Blue]; 35 | [property test]:[type Any]; 36 | [property float_member]:[builtin float] = [number 0.01]; 37 | [property small_float]:[builtin float] = [number 0.01E-9]; 38 | } 39 | 40 | [keyword struct] [type Weapon] { [property foo]:[builtin int]; } 41 | [keyword struct] [type Pickup] { [property bar]:[builtin int]; } 42 | 43 | 44 | [keyword root_type] [type Monster]; 45 | -------------------------------------------------------------------------------- /test/go/grammar.go: -------------------------------------------------------------------------------- 1 | [keyword package] [variable hello] [comment /**/] 2 | 3 | [keyword import] [def m] [string "lib/math"] 4 | 5 | [keyword func] [def generate]([def&local ch] [keyword chan][operator <-] [type int]) { 6 | [keyword for] [def&local i] [operator :=] [number 2]; ; [variable-2 i][operator ++] { 7 | [variable-2 ch] [operator <-] [variable-2 i] [comment // Send 'i' to channel 'ch'.] 8 | } 9 | } 10 | 11 | [keyword const] ( 12 | [def x], [def y] [type int] 13 | [def p] [[]][type Something]; [def u] [operator =] [string '\n'] 14 | ) 15 | 16 | [keyword for] [def&local a] [operator :=] [keyword range] [keyword map][[ *[meta baz.][type Banana] ]] [[]][meta baz.][type Apple]{ 17 | { 18 | [property Fish]: [number 1], 19 | [property Gorilla]: [[]][type string]{}, 20 | }: [atom nil], 21 | } { 22 | [variable t].[property&callee Run]() 23 | } 24 | 25 | [keyword type] [def j] [keyword struct] { 26 | [def&property x], [def&property y] [type int] 27 | [def&property u] [type float32] 28 | [def&property _] [type float32] [comment // padding] 29 | [def&property A] *[[]][type int] 30 | [def&property F] [keyword func]() 31 | [def&property dial] [keyword func]([def network], [def address] [type string]) ([meta net.][type Conn], [type error]) 32 | } 33 | 34 | [keyword if] [variable x] [operator +] [variable y] { 35 | [variable x][operator ++] 36 | [variable y] [operator -=] [variable x]; [variable&callee foo]([number 0xaffe]) 37 | } [keyword else] [keyword if] [atom true] { 38 | [keyword return] [string `plain] 39 | [string stringthing`] 40 | } [keyword else] { 41 | [keyword switch] [def&local r] [operator :=] [variable tag] { 42 | [keyword default]: [variable&callee s3]() 43 | [keyword case] [number 0], [number 1], [number 2], [number 3]: [variable&callee s1]() 44 | [keyword case] [number 4]: [keyword go] [variable&callee s2]() 45 | } 46 | } 47 | 48 | [def r], [def w] [operator :=] [variable os].[property&callee Pipe]([variable fd]) 49 | [def _], [def y], [def _] [operator :=] [type T]{[number 1], [number 3.44e+2]} 50 | 51 | [keyword select] { 52 | [keyword case] [variable i1] [operator =] [operator <-][variable c1]: 53 | [builtin print]([string "received "], [variable i1], [string " from c1\n"]) 54 | [keyword case] [variable c2] [operator <-] [variable i2]: 55 | [builtin print]([string "sent "], [variable i2], [string " to c2\n"]) 56 | [keyword case] [def&local i3], [def&local ok] [operator :=] ([operator <-][variable c3]): [comment // same as: i3, ok := <-c3] 57 | [keyword if] [variable-2 ok] { 58 | [builtin print]([string "received "], [variable-2 i3], [string " from c3\n"]) 59 | } [keyword else] { 60 | [builtin print]([string "c3 is closed\n"]) 61 | } 62 | [keyword case] [variable a][[[variable&callee f]()]] [operator =] [operator <-][variable c4]: 63 | [comment // same as:] 64 | [comment // case t := <-c4] 65 | [keyword default]: 66 | [builtin print]([string "no communication\n"]) 67 | } 68 | 69 | [comment /* this is a comment] 70 | [comment more comment] 71 | [comment */] 72 | 73 | [def x] [operator :=] [type Foo]{ 74 | [number 1], [variable&callee bar]([variable&callee foo]([variable a], 75 | [variable b])), 76 | [number 3], [number 4], 77 | } 78 | 79 | [keyword func] [def sieve]() { 80 | { 81 | [def&local m] [operator :=] [number 1]; 82 | } 83 | } 84 | 85 | [keyword func] [def main]() { 86 | [keyword if] [def&local z] [operator :=] [number 1]; [variable-2 z] [operator %] [number 2] [operator ==] [number 1] { 87 | [def&local i] [operator :=] [number 2]; 88 | } [keyword else] { 89 | [variable-2 z] [operator =] [number 2]; 90 | } 91 | [variable fmt].[callee&property Println]([variable z]) 92 | } 93 | 94 | [keyword func] ([def&local r] [type X]) [def y]() { 95 | [callee&variable bar]([variable-2 r], [builtin make]([type Bar])); 96 | } 97 | 98 | [keyword type] [def Message] [keyword struct] { 99 | [def&property Foo] [meta foo.][type string] 100 | } 101 | 102 | [keyword func] [def foo]() { 103 | [keyword var] [def&local wg] [meta sync.][type WaitGroup] 104 | [variable-2 wg].[property&callee Add]([number 1]) 105 | [variable&callee f]([keyword func]() { [variable-2 wg].[property&callee Done]() }) 106 | [variable-2 wg].[property&callee Wait]() 107 | } 108 | 109 | [keyword var] [def imported] [operator =] [keyword map][[ [type string] ]][type bool]{} 110 | 111 | [keyword for] { 112 | [def&local x] [operator :=] [operator <-][variable ch] 113 | } 114 | 115 | [keyword type] [def A] [keyword interface] { 116 | [property Load]() ([keyword interface]{}) 117 | [property Foo]([def&local f] [meta foo.][type Bar]) [keyword map][[ [type string] ]][type string] 118 | [property a]([def&local f] [meta foo.][type Bar]) 119 | [type u] 120 | } 121 | 122 | [keyword type] [def Span] [keyword struct] { 123 | [type Range] 124 | } 125 | 126 | [callee&variable something]([keyword func]() { [keyword return] [number 22] }) 127 | 128 | [def abcd] [operator :=] [[]][meta bar.][type Baz]{ 129 | {}, 130 | } 131 | [keyword var] [def hashes] [operator =] [number 123] 132 | 133 | [def abs] [operator :=] [[]][keyword struct] { 134 | [def&property a] [type string] 135 | [def&property b] [type int] 136 | }{ 137 | [builtin make]([[]][type byte], [number 128]) 138 | [number 22] 139 | } 140 | 141 | [keyword for] [def&local _], [def&local x] [operator :=] [[]][type int]{ 142 | { 143 | [property foo]: [string "bar"], 144 | [property baz]: [number 2] 145 | }, 146 | } { 147 | [number 1] 148 | } 149 | 150 | [keyword func] [def foo]([def&local x], [def&local y] ... [type z]) ([type int], [type error]) {} 151 | 152 | [keyword func] [def x] () ([def&local foo] [[ ]][type byte], [def&local bar] [type myType]) {} 153 | -------------------------------------------------------------------------------- /test/go/indent.go: -------------------------------------------------------------------------------- 1 | // test: indent_only 2 | 3 | // source: gofmt.go 4 | 5 | // Copyright 2009 The Go Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style 7 | // license that can be found in the LICENSE file. 8 | 9 | package main 10 | 11 | import ( 12 | "bytes" 13 | "flag" 14 | "fmt" 15 | "go/ast" 16 | "go/parser" 17 | "go/printer" 18 | "go/scanner" 19 | "go/token" 20 | "io" 21 | "io/ioutil" 22 | "os" 23 | "os/exec" 24 | "path/filepath" 25 | "runtime" 26 | "runtime/pprof" 27 | "strings" 28 | ) 29 | 30 | var ( 31 | // main operation modes 32 | list = flag.Bool("l", false, "list files whose formatting differs from gofmt's") 33 | write = flag.Bool("w", false, "write result to (source) file instead of stdout") 34 | rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')") 35 | simplifyAST = flag.Bool("s", false, "simplify code") 36 | doDiff = flag.Bool("d", false, "display diffs instead of rewriting files") 37 | allErrors = flag.Bool("e", false, "report all errors (not just the first 10 on different lines)") 38 | 39 | // debugging 40 | cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file") 41 | ) 42 | 43 | const ( 44 | tabWidth = 8 45 | printerMode = printer.UseSpaces | printer.TabIndent 46 | ) 47 | 48 | var ( 49 | fileSet = token.NewFileSet() // per process FileSet 50 | exitCode = 0 51 | rewrite func(*ast.File) *ast.File 52 | parserMode parser.Mode 53 | ) 54 | 55 | func report(err error) { 56 | scanner.PrintError(os.Stderr, err) 57 | exitCode = 2 58 | } 59 | 60 | func usage() { 61 | fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n") 62 | flag.PrintDefaults() 63 | } 64 | 65 | func initParserMode() { 66 | parserMode = parser.ParseComments 67 | if *allErrors { 68 | parserMode |= parser.AllErrors 69 | } 70 | } 71 | 72 | func isGoFile(f os.FileInfo) bool { 73 | // ignore non-Go files 74 | name := f.Name() 75 | return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") 76 | } 77 | 78 | // If in == nil, the source is the contents of the file with the given filename. 79 | func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error { 80 | var perm os.FileMode = 0644 81 | if in == nil { 82 | f, err := os.Open(filename) 83 | if err != nil { 84 | return err 85 | } 86 | defer f.Close() 87 | fi, err := f.Stat() 88 | if err != nil { 89 | return err 90 | } 91 | in = f 92 | perm = fi.Mode().Perm() 93 | } 94 | 95 | src, err := ioutil.ReadAll(in) 96 | if err != nil { 97 | return err 98 | } 99 | 100 | file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, stdin) 101 | if err != nil { 102 | return err 103 | } 104 | 105 | if rewrite != nil { 106 | if sourceAdj == nil { 107 | file = rewrite(file) 108 | } else { 109 | fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n") 110 | } 111 | } 112 | 113 | ast.SortImports(fileSet, file) 114 | 115 | if *simplifyAST { 116 | simplify(file) 117 | } 118 | 119 | res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth}) 120 | if err != nil { 121 | return err 122 | } 123 | 124 | if !bytes.Equal(src, res) { 125 | // formatting has changed 126 | if *list { 127 | fmt.Fprintln(out, filename) 128 | } 129 | if *write { 130 | // make a temporary backup before overwriting original 131 | bakname, err := backupFile(filename+".", src, perm) 132 | if err != nil { 133 | return err 134 | } 135 | err = ioutil.WriteFile(filename, res, perm) 136 | if err != nil { 137 | os.Rename(bakname, filename) 138 | return err 139 | } 140 | err = os.Remove(bakname) 141 | if err != nil { 142 | return err 143 | } 144 | } 145 | if *doDiff { 146 | data, err := diff(src, res, filename) 147 | if err != nil { 148 | return fmt.Errorf("computing diff: %s", err) 149 | } 150 | fmt.Printf("diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename)) 151 | out.Write(data) 152 | } 153 | } 154 | 155 | if !*list && !*write && !*doDiff { 156 | _, err = out.Write(res) 157 | } 158 | 159 | return err 160 | } 161 | 162 | func visitFile(path string, f os.FileInfo, err error) error { 163 | if err == nil && isGoFile(f) { 164 | err = processFile(path, nil, os.Stdout, false) 165 | } 166 | // Don't complain if a file was deleted in the meantime (i.e. 167 | // the directory changed concurrently while running gofmt). 168 | if err != nil && !os.IsNotExist(err) { 169 | report(err) 170 | } 171 | return nil 172 | } 173 | 174 | func walkDir(path string) { 175 | filepath.Walk(path, visitFile) 176 | } 177 | 178 | func main() { 179 | // call gofmtMain in a separate function 180 | // so that it can use defer and have them 181 | // run before the exit. 182 | gofmtMain() 183 | os.Exit(exitCode) 184 | } 185 | 186 | func gofmtMain() { 187 | flag.Usage = usage 188 | flag.Parse() 189 | 190 | if *cpuprofile != "" { 191 | f, err := os.Create(*cpuprofile) 192 | if err != nil { 193 | fmt.Fprintf(os.Stderr, "creating cpu profile: %s\n", err) 194 | exitCode = 2 195 | return 196 | } 197 | defer f.Close() 198 | pprof.StartCPUProfile(f) 199 | defer pprof.StopCPUProfile() 200 | } 201 | 202 | initParserMode() 203 | initRewrite() 204 | 205 | if flag.NArg() == 0 { 206 | if *write { 207 | fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input") 208 | exitCode = 2 209 | return 210 | } 211 | if err := processFile("", os.Stdin, os.Stdout, true); err != nil { 212 | report(err) 213 | } 214 | return 215 | } 216 | 217 | for i := 0; i < flag.NArg(); i++ { 218 | path := flag.Arg(i) 219 | switch dir, err := os.Stat(path); { 220 | case err != nil: 221 | report(err) 222 | case dir.IsDir(): 223 | walkDir(path) 224 | default: 225 | if err := processFile(path, nil, os.Stdout, false); err != nil { 226 | report(err) 227 | } 228 | } 229 | } 230 | } 231 | 232 | func writeTempFile(dir, prefix string, data []byte) (string, error) { 233 | file, err := ioutil.TempFile(dir, prefix) 234 | if err != nil { 235 | return "", err 236 | } 237 | _, err = file.Write(data) 238 | if err1 := file.Close(); err == nil { 239 | err = err1 240 | } 241 | if err != nil { 242 | os.Remove(file.Name()) 243 | return "", err 244 | } 245 | return file.Name(), nil 246 | } 247 | 248 | func diff(b1, b2 []byte, filename string) (data []byte, err error) { 249 | f1, err := writeTempFile("", "gofmt", b1) 250 | if err != nil { 251 | return 252 | } 253 | defer os.Remove(f1) 254 | 255 | f2, err := writeTempFile("", "gofmt", b2) 256 | if err != nil { 257 | return 258 | } 259 | defer os.Remove(f2) 260 | 261 | cmd := "diff" 262 | if runtime.GOOS == "plan9" { 263 | cmd = "/bin/ape/diff" 264 | } 265 | 266 | data, err = exec.Command(cmd, "-u", f1, f2).CombinedOutput() 267 | if len(data) > 0 { 268 | // diff exits with a non-zero status when the files don't match. 269 | // Ignore that failure as long as we get output. 270 | return replaceTempFilename(data, filename) 271 | } 272 | return 273 | } 274 | 275 | // replaceTempFilename replaces temporary filenames in diff with actual one. 276 | // 277 | // --- /tmp/gofmt316145376 2017-02-03 19:13:00.280468375 -0500 278 | // +++ /tmp/gofmt617882815 2017-02-03 19:13:00.280468375 -0500 279 | // ... 280 | // -> 281 | // --- path/to/file.go.orig 2017-02-03 19:13:00.280468375 -0500 282 | // +++ path/to/file.go 2017-02-03 19:13:00.280468375 -0500 283 | // ... 284 | func replaceTempFilename(diff []byte, filename string) ([]byte, error) { 285 | bs := bytes.SplitN(diff, []byte{'\n'}, 3) 286 | if len(bs) < 3 { 287 | return nil, fmt.Errorf("got unexpected diff for %s", filename) 288 | } 289 | // Preserve timestamps. 290 | var t0, t1 []byte 291 | if i := bytes.LastIndexByte(bs[0], '\t'); i != -1 { 292 | t0 = bs[0][i:] 293 | } 294 | if i := bytes.LastIndexByte(bs[1], '\t'); i != -1 { 295 | t1 = bs[1][i:] 296 | } 297 | // Always print filepath with slash separator. 298 | f := filepath.ToSlash(filename) 299 | bs[0] = []byte(fmt.Sprintf("--- %s%s", f+".orig", t0)) 300 | bs[1] = []byte(fmt.Sprintf("+++ %s%s", f, t1)) 301 | return bytes.Join(bs, []byte{'\n'}), nil 302 | } 303 | 304 | const chmodSupported = runtime.GOOS != "windows" 305 | 306 | // backupFile writes data to a new file named filename with permissions perm, 307 | // with N] 8 | [comment * line] 9 | [comment * {][comment&tag @code][comment ][comment&attribute some @code{with braces}] 10 | [comment * ][comment&attribute continued code][comment }] 11 | [comment * comment ][comment&tag @tag][comment */] 12 | 13 | [meta @Foo](x = [string "something"]) 14 | [meta @Bar] 15 | [meta @baz.argh]([variable Something].[property OK]) 16 | [keyword public] [keyword class] [type&def FontChoice] [keyword extends] [type Choice]<[type Param][[]]> { 17 | [comment // line comment] 18 | [keyword private] [keyword final] [keyword volatile] [type&qualifier java].[type&qualifier blah].[qualified&type Font] [def&property fonts][[]]; 19 | [keyword public] [def&property FontChoice]([type String] [def&local in], [type Globals] [def&local g]) { 20 | [keyword super]([variable-2 g]); 21 | 22 | [variable totalwidth] [operator =] [number 30]; 23 | [type int] [def&local i], [def&local last] [operator =] [number 0b0_1], [def&local j] [operator =] [number 0.33e+3f]; 24 | 25 | [keyword for] ([variable-2 i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 in].[property&callee length](); [variable-2 i][operator ++]) 26 | [keyword if] ([variable-2 in].[property&callee charAt]([variable-2 i]) [operator ==] [string ' ']) 27 | [variable numofstyles][operator ++]; 28 | [keyword else] 29 | [keyword throw] [keyword new]<[type Ugh], ?> [type Error]([string "double \" quoted"]); 30 | [keyword if] ([variable numofstyles] [operator ==] [variable foo][[ [number 0] ]]) 31 | [keyword return]; 32 | 33 | [variable&callee foo]( 34 | [number 1] [operator +] [number 2] [operator +] 35 | [number 3] [operator +] [number 4]); 36 | 37 | [variable names] [operator =] [keyword new] [type String][[ [variable numofstyles] ]]; 38 | [keyword return] ([type Bar]<[type K], [type V]>) [variable&callee baz](); 39 | } 40 | 41 | [type void] [def&property foo]() { 42 | [keyword return] [keyword new] [type Foo]( 43 | [keyword new] [type Bar](). 44 | [property Abc]); 45 | } 46 | 47 | [comment /** ][comment&tag @throws][comment ][comment&type FooError][comment */] 48 | [keyword protected] [type void] [def&property setX]([type int] [def&local x]) { 49 | [variable g] [operator ||] [variable-2 x]; 50 | [keyword super].[property&callee setX]([variable-2 x]); 51 | [type FontMetrics]<[type Param]> [def&local fm] [operator =] [variable parent].[property&callee getFontMetrics]([variable fonts][[ [variable i] ]]); 52 | [keyword var] [def&local z] [operator =] [number 2]; 53 | 54 | label: [keyword try] { 55 | [keyword continue] label; 56 | } [keyword catch] ([type RuntimeException] [def&local e]) { 57 | [variable system].[property&callee println]([variable-2 e].[property message]); 58 | } [keyword catch] ([keyword final] [type Exception] | [type InterruptedException] [def&local e]) { 59 | } [keyword finally] { 60 | [keyword return] [number 00l]; 61 | } 62 | 63 | [variable foo].[property&callee addListeners]( 64 | ([def&local x], [def&local y]) [operator ->] [atom true], 65 | [def&local z] [operator ->] [atom false] [operator ?] [variable-2 z] [operator :] [atom null] 66 | ); 67 | } 68 | 69 | [def&property join]([type Bar]... [def&local bars]) { 70 | } 71 | 72 | [keyword public] [type&qualifier Foo]<[type Integer]>.[type&qualified Buar] [def&property bad]() {} 73 | 74 | [keyword enum] [type&def TrafficLight] { 75 | [def&property RED]([number 30]), [def&property AMBER]([number 10]),; 76 | 77 | [keyword private] [keyword final] [type int] [def&property seconds]; 78 | 79 | [def&property TrafficLight]([type int] [def&local seconds]) { 80 | [keyword this].[property seconds] [operator =] [variable-2 seconds]; 81 | } 82 | 83 | [type int] [def&property getSeconds]() { 84 | [keyword return] [variable seconds]; 85 | } 86 | } 87 | } 88 | 89 | [keyword class] [type&def Foo] { 90 | [comment /** ][comment&tag @param][comment <][comment&type&def X][comment > Doc comment! */] 91 | <[type&def X]> [type void] [def&property foo]([type&local X] [def&local x], [type Y] [def&local y]) { 92 | } 93 | } 94 | 95 | [meta @BindingAnnotation] 96 | [keyword @interface] [def SomeInterface] { } 97 | [keyword public] [type void] [def run]() { 98 | [keyword if] ([variable x]) 99 | [keyword try] { 100 | } [keyword catch] ([type Exception] [def&local e]) { 101 | } 102 | [keyword return] [variable Foo].[keyword class]; 103 | } 104 | -------------------------------------------------------------------------------- /test/java/indent.java: -------------------------------------------------------------------------------- 1 | // test: indent_only 2 | 3 | class Foo { 4 | 5 | } 6 | 7 | class Foo { 8 | void bar( 9 | ) { 10 | 11 | } 12 | } 13 | 14 | Foo foo = 15 | Foo.newBuilder() 16 | .setBar(Bar.newBuilder()).build(); 17 | 18 | Foo foo = Foo.newBuilder() 19 | .setBar( 20 | Bar 21 | .newBuilder() 22 | ) 23 | .build() 24 | ; 25 | 26 | Foo foo = a. 27 | bar(); 28 | 29 | Foo foo = a. 30 | bar( 31 | ); 32 | 33 | return ( 34 | ) -> { 35 | 36 | }; 37 | 38 | return ( 39 | ) -> 40 | 1 41 | ; 42 | 43 | MyLambda lambda = 44 | (label, value, obj) -> {obj}; 45 | 46 | MyLambda lambda = (label, 47 | value, obj) -> {obj}; 48 | 49 | MyLambda lambda = (label, value, obj) -> { 50 | obj}; 51 | 52 | MyLambda lambda = 53 | (label, 54 | value, obj) -> {obj}; 55 | 56 | MyLambda lambda = 57 | (label, value, obj) -> { 58 | obj}; 59 | 60 | new int[] { 61 | 0, 1, 2, 3}; 62 | 63 | new int[] 64 | {0, 1, 2, 3}; 65 | 66 | new int[] { 67 | 0, 68 | 1, 2, 3}; 69 | 70 | new int[] { 71 | 0, 1, 2, 3 72 | 73 | }; 74 | switch (foo) { 75 | case 1: return b;} 76 | 77 | switch (foo) { 78 | case 1: 79 | return b;} 80 | 81 | public class Foo { 82 | @Override 83 | public Bar bar() 84 | throws RpcException, 85 | FooException { 86 | 87 | } 88 | 89 | void bar() throws 90 | Ex { 91 | } 92 | } 93 | 94 | public class Foo { 95 | @Override 96 | public Bar bar( 97 | ) 98 | throws RpcException, 99 | FooException { 100 | 101 | } 102 | } 103 | 104 | public class Foo { 105 | @Override 106 | public Bar bar( 107 | Baz baz) 108 | throws RpcException, FooException { 109 | 110 | } 111 | } 112 | 113 | public class Foo { 114 | @Override 115 | public Bar bar( 116 | Baz baz) 117 | throws RpcException, 118 | FooException { 119 | 120 | } 121 | } 122 | 123 | public class Foo { 124 | @Override 125 | public Bar bar() 126 | throws RpcException, 127 | FooException { 128 | 129 | } 130 | } 131 | 132 | class Foo { 133 | public void 134 | method() { 135 | 136 | } 137 | } 138 | 139 | class Foo { 140 | public void 141 | method() { 142 | 143 | } 144 | } 145 | 146 | public class Foo 147 | extends Bar { 148 | 149 | } 150 | 151 | public class Foo 152 | extends Bar< 153 | Baz, Quux> { 154 | 155 | } 156 | 157 | public class Foo 158 | extends Bar< 159 | Baz, 160 | Quux> { 161 | 162 | } 163 | 164 | foo = 165 | new Foo() { 166 | public void bar() { 167 | 168 | } 169 | }; 170 | 171 | foo = 172 | new Foo() { 173 | 174 | public void bar() { 175 | } 176 | 177 | }; 178 | -------------------------------------------------------------------------------- /test/js/anonymous_class_expression.js: -------------------------------------------------------------------------------- 1 | [keyword const] [def Adder] [operator =] [keyword class] [keyword extends] [variable Arithmetic] { 2 | [def&property add]([def&local a], [def&local b]) {} 3 | }; 4 | -------------------------------------------------------------------------------- /test/js/async.js: -------------------------------------------------------------------------------- 1 | [keyword async] [keyword function] [def foo]([def&local args]) { [keyword return] [atom true]; } 2 | -------------------------------------------------------------------------------- /test/js/async_arrow.js: -------------------------------------------------------------------------------- 1 | [keyword const] [def foo] [operator =] [keyword async] ([def&local args]) [operator =>] { [keyword return] [atom true]; }; 2 | -------------------------------------------------------------------------------- /test/js/async_assignment.js: -------------------------------------------------------------------------------- 1 | [keyword const] [def foo] [operator =] [keyword async] [keyword function] ([def&local args]) { [keyword return] [atom true]; }; 2 | -------------------------------------------------------------------------------- /test/js/async_jquery.js: -------------------------------------------------------------------------------- 1 | [variable $].[property&callee ajax]({ 2 | [def&property url]: [variable url], 3 | [def&property async]: [atom true], 4 | [def&property method]: [string 'GET'] 5 | }); 6 | -------------------------------------------------------------------------------- /test/js/async_object.js: -------------------------------------------------------------------------------- 1 | [keyword let] [def obj] [operator =] { [def&property async]: [atom false] }; 2 | -------------------------------------------------------------------------------- /test/js/async_object_function.js: -------------------------------------------------------------------------------- 1 | [keyword let] [def obj] [operator =] { [keyword async] [def&property foo]([def&local args]) { [keyword return] [atom true]; } }; 2 | -------------------------------------------------------------------------------- /test/js/async_object_properties.js: -------------------------------------------------------------------------------- 1 | [keyword let] [def obj] [operator =] { 2 | [def&property prop1]: [keyword async] [keyword function] ([def&local args]) { [keyword return] [atom true]; }, 3 | [def&property prop2]: [keyword async] [keyword function] ([def&local args]) { [keyword return] [atom true]; }, 4 | [def&property prop3]: [keyword async] [keyword function] [def prop3]([def&local args]) { [keyword return] [atom true]; }, 5 | }; 6 | -------------------------------------------------------------------------------- /test/js/async_variable.js: -------------------------------------------------------------------------------- 1 | [keyword const] [def async] [operator =] {[def&property a]: [number 1]}; 2 | [keyword const] [def foo] [operator =] [string-2 `bar ${][variable async].[property a][string-2 }`]; 3 | -------------------------------------------------------------------------------- /test/js/class.js: -------------------------------------------------------------------------------- 1 | [keyword class] [type&def Point] [keyword extends] [variable SuperThing] { 2 | [keyword get] [def&property prop]() { [keyword return] [number 24]; } 3 | [def&property constructor]([def&local x], [def&local y]) { 4 | [keyword super]([string 'something']); 5 | [keyword this].[property x] [operator =] [variable-2 x]; 6 | } 7 | [def&property set]([def&local x]) {} 8 | } 9 | -------------------------------------------------------------------------------- /test/js/class_async_method.js: -------------------------------------------------------------------------------- 1 | [keyword class] [type&def Foo] { 2 | [def&property sayName1]() {} 3 | [keyword async] [def&property sayName2]() {} 4 | } 5 | -------------------------------------------------------------------------------- /test/js/class_body.js: -------------------------------------------------------------------------------- 1 | [keyword class] [type&def Foo] { 2 | [def&property constructor]() {} 3 | [def&property sayName]() { 4 | [keyword return] [string-2 `foo${][variable foo][string-2 }oo`]; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/js/comma-and-binop.js: -------------------------------------------------------------------------------- 1 | [comment /* foo */] 2 | 3 | [keyword function](){ [keyword var] [def&local x] [operator =] [number 1] [operator +] [number 2], [def&local y]; } 4 | -------------------------------------------------------------------------------- /test/js/const.js: -------------------------------------------------------------------------------- 1 | [keyword function] [def f]() { 2 | [keyword const] [[ [def&local a], [def&local b] ]] [operator =] [[ [number 1], [number 2] ]]; 3 | } 4 | -------------------------------------------------------------------------------- /test/js/destructure_trailing_comma.js: -------------------------------------------------------------------------------- 1 | [keyword let] {[def a], [def b],} [operator =] [variable foo]; 2 | [keyword let] [def c]; 3 | -------------------------------------------------------------------------------- /test/js/destructuring.js: -------------------------------------------------------------------------------- 1 | ([keyword function]([def&local a], [[[def&local b], [def&local c] ]]) { 2 | [keyword let] {[def&local d], [property foo]: [def&local c][operator =][number 10], [def&local x]} [operator =] [variable&callee foo]([variable-2 a]); 3 | [[[variable-2 c], [variable y] ]] [operator =] [variable-2&callee d](); 4 | })(); 5 | 6 | [keyword let] {[def a] [operator =] [number 3]}, [def b] [operator =] [number 20]; 7 | -------------------------------------------------------------------------------- /test/js/fatArrow.js: -------------------------------------------------------------------------------- 1 | [variable array].[property&callee filter]([def&local a] [operator =>] [variable-2 a] [operator +] [number 1]); 2 | [variable a]; 3 | [keyword let] [def f] [operator =] ([[ [def&local a], [def&local b] ]], [def&local c]) [operator =>] [variable-2 a] [operator +] [variable-2 c]; 4 | [variable c]; 5 | -------------------------------------------------------------------------------- /test/js/for_of.js: -------------------------------------------------------------------------------- 1 | [keyword for]([keyword let] [def&local of] [keyword of] [variable something]) {} 2 | -------------------------------------------------------------------------------- /test/js/generator.js: -------------------------------------------------------------------------------- 1 | [keyword function*] [def repeat]([def&local n]) { 2 | [keyword for]([keyword var] [def&local i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i]) 3 | [keyword yield] [variable-2 i]; 4 | } 5 | -------------------------------------------------------------------------------- /test/js/import.js: -------------------------------------------------------------------------------- 1 | [keyword function] [def foo]() { 2 | [keyword import] [def&local $] [keyword from] [string 'jquery']; 3 | [keyword import] { [def&local encrypt], [def&local decrypt] } [keyword from] [string 'crypto']; 4 | } 5 | -------------------------------------------------------------------------------- /test/js/import_trailing_comma.js: -------------------------------------------------------------------------------- 1 | [keyword import] {[def foo], [def bar],} [keyword from] [string 'baz'] -------------------------------------------------------------------------------- /test/js/indent.js: -------------------------------------------------------------------------------- 1 | // test: indent_only 2 | 3 | const 4 | foo 5 | = 6 | 1 7 | + 8 | 2 9 | ; 10 | 11 | 12 | const foo = 13 | [1, 2]; 14 | 15 | const foo = [ 16 | 1, 2]; 17 | 18 | const foo = 19 | {a, b}; 20 | 21 | const foo = { 22 | a, b}; 23 | 24 | someMethod(foo, [ 25 | 0, 1, 2,], bar); 26 | 27 | someMethod( 28 | foo, 29 | [0, 1, 2,], 30 | bar); 31 | 32 | someMethod(foo, [ 33 | 0, 1, 34 | 2, 35 | ], bar); 36 | 37 | someMethod( 38 | foo, 39 | [ 40 | 1, 2],); 41 | 42 | someMethod( 43 | foo, 44 | [1, 2], 45 | ); 46 | 47 | someMethod(foo, { 48 | a: 1, b: 2,}, bar); 49 | 50 | someMethod( 51 | foo, 52 | {a: 1, b: 2,}, 53 | bar); 54 | 55 | someMethod(foo, { 56 | a: 1, b: 2 57 | 58 | }, bar); 59 | 60 | someMethod( 61 | foo, 62 | { 63 | a: 1, b: 2},); 64 | 65 | someMethod( 66 | foo, 67 | {a: 1, b: 2}, 68 | ); 69 | 70 | someMethod(a => 71 | a*2 72 | ); 73 | 74 | someMethod(a => { 75 | a*2} 76 | ); 77 | 78 | foo() 79 | .bar(a => a*2); 80 | 81 | foo().bar(a => 82 | a*2); 83 | 84 | foo = 85 | function() { 86 | 87 | }; 88 | 89 | foo = 90 | function() { 91 | 92 | }; 93 | 94 | switch (foo) { 95 | case 1: return b;} 96 | 97 | switch (foo) { 98 | case 1: 99 | return b;} 100 | 101 | class Foo { 102 | 103 | } 104 | 105 | class Foo { 106 | bar( 107 | ) {} 108 | } 109 | 110 | class Foo { 111 | bar() { 112 | 113 | } 114 | } 115 | 116 | if (x) { 117 | statement; 118 | 119 | more; 120 | } 121 | -------------------------------------------------------------------------------- /test/js/indent_below_if.js: -------------------------------------------------------------------------------- 1 | [keyword for] (;;) 2 | [keyword if] ([variable foo]) 3 | [number 1]; 4 | [number 2]; -------------------------------------------------------------------------------- /test/js/indent_else.js: -------------------------------------------------------------------------------- 1 | [keyword for] (;;) 2 | [keyword if] ([variable foo]) 3 | [keyword if] ([variable bar]) 4 | [number 1]; 5 | [keyword else] 6 | [number 2]; 7 | [keyword else] 8 | [number 3]; -------------------------------------------------------------------------------- /test/js/indent_for.js: -------------------------------------------------------------------------------- 1 | [keyword for] ([keyword var] [def&local i] [operator =] [number 0]; 2 | [variable-2 i] [operator <] [number 100]; 3 | [variable-2 i][operator ++]) 4 | [variable&callee doSomething]([variable-2 i]); 5 | [keyword debugger]; 6 | 7 | [keyword for] ([keyword const] [def&local name] [keyword of] [variable Object].[callee&property getOwnPropertyNames]( 8 | [variable Object].[callee&property getPrototypeOf]([variable instance]))) {} 9 | 10 | [keyword for] ([keyword let] [def&local x] [keyword of] [number 1] [operator +] 11 | [number 1]) {} 12 | -------------------------------------------------------------------------------- /test/js/indent_funarg.js: -------------------------------------------------------------------------------- 1 | [variable&callee foo]([number 10000], 2 | [keyword function]([def&local a]) { 3 | [keyword debugger]; 4 | }; 5 | -------------------------------------------------------------------------------- /test/js/indent_if.js: -------------------------------------------------------------------------------- 1 | [keyword if] ([number 1]) 2 | [keyword break]; 3 | [keyword else] [keyword if] ([number 2]) 4 | [keyword continue]; 5 | [keyword else] 6 | [number 10]; 7 | [keyword if] ([number 1]) { 8 | [keyword break]; 9 | } [keyword else] [keyword if] ([number 2]) { 10 | [keyword continue]; 11 | } [keyword else] { 12 | [number 10]; 13 | } -------------------------------------------------------------------------------- /test/js/indent_semicolonless_if.js: -------------------------------------------------------------------------------- 1 | [keyword function] [def foo]() { 2 | [keyword if] ([variable x]) 3 | [variable&callee foo]() 4 | } 5 | -------------------------------------------------------------------------------- /test/js/indent_semicolonless_if_with_statement.js: -------------------------------------------------------------------------------- 1 | // test: {"requireSemicolons": false} 2 | 3 | [keyword function] [def foo]() { 4 | [keyword if] ([variable x]) 5 | [variable&callee foo]() 6 | [variable&callee bar]() 7 | } 8 | -------------------------------------------------------------------------------- /test/js/indent_statement.js: -------------------------------------------------------------------------------- 1 | // test: {"requireSemicolons": false} 2 | 3 | [keyword var] [def x] [operator =] [number 10] 4 | [variable x] [operator +=] [variable y] [operator +] 5 | [atom Infinity] 6 | [keyword debugger]; 7 | -------------------------------------------------------------------------------- /test/js/indent_strange_array.js: -------------------------------------------------------------------------------- 1 | [keyword var] [def x] [operator =] [[ 2 | [number 1],, 3 | [number 2], 4 | ]]; 5 | [number 10]; 6 | -------------------------------------------------------------------------------- /test/js/indent_switch.js: -------------------------------------------------------------------------------- 1 | [keyword switch] ([variable x]) { 2 | [keyword default]: 3 | [keyword return] [number 2]; 4 | } 5 | -------------------------------------------------------------------------------- /test/js/jsdoc.js: -------------------------------------------------------------------------------- 1 | [comment /**] 2 | [comment Plain text doesn't have any special ] 3 | [comment indentation. {][comment&tag @link][comment foo}] 4 | 5 | [comment&tag @fileoverview][comment Doesn't have any special] 6 | [comment indentation.] 7 | 8 | [comment&tag @see][comment https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler] 9 | 10 | [comment&tag @constructor] 11 | [comment&tag @foo] 12 | 13 | [comment&tag @param][comment {] 14 | [comment * ][comment&type !Foo][comment } ] 15 | [comment * ][comment&def param][comment Some ] 16 | [comment description.] 17 | 18 | [comment&tag @param][comment {][comment&type {] 19 | [comment ][comment&type foo: objectRulesApplyAndParamNameIsRequired}][comment }] 20 | [comment ][comment&def Desc] 21 | [comment */] 22 | 23 | [string "use strict"] 24 | -------------------------------------------------------------------------------- /test/js/locals.js: -------------------------------------------------------------------------------- 1 | [keyword function] [def foo]([def&local a], [def&local b]) { 2 | [keyword var] [def&local c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; 3 | 4 | [keyword if] ([number 1] [operator !=] [number 2]) 5 | [keyword return] [atom false]; 6 | 7 | [variable-2 c][operator ++]; 8 | } 9 | -------------------------------------------------------------------------------- /test/js/multilinestring.js: -------------------------------------------------------------------------------- 1 | [keyword var] [def x] [operator =] [string 'foo\] 2 | [string bar']; 3 | -------------------------------------------------------------------------------- /test/js/named_class_expression.js: -------------------------------------------------------------------------------- 1 | [keyword const] [def Subber] [operator =] [keyword class] [type&def Subtract] { 2 | [def&property sub]([def&local a], [def&local b]) {} 3 | }; 4 | -------------------------------------------------------------------------------- /test/js/new_target.js: -------------------------------------------------------------------------------- 1 | [keyword function] [def F]([def&local target]) { 2 | [keyword if] ([variable-2 target] [operator &&] [keyword new].[keyword target].[property name]) { 3 | [keyword return] [keyword new] 4 | .[keyword target]; 5 | } 6 | } 7 | 8 | [keyword const] [def foo] [operator =] [keyword new] [callee&variable Bar]() 9 | .[property&callee baz]() 10 | .[property&callee quux](); 11 | 12 | [keyword const] [def foo] [operator =] 13 | [keyword new] [callee&variable Bar]() 14 | .[property&callee baz]() 15 | .[property&callee quux](); 16 | -------------------------------------------------------------------------------- /test/js/param_default.js: -------------------------------------------------------------------------------- 1 | [keyword function] [def foo]([def&local x] [operator =] [string-2 `foo${][number 10][string-2 }bar`]) { 2 | [keyword return] [variable-2 x]; 3 | } 4 | -------------------------------------------------------------------------------- /test/js/quasi.js: -------------------------------------------------------------------------------- 1 | [variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2] -------------------------------------------------------------------------------- /test/js/quasi_no_function.js: -------------------------------------------------------------------------------- 1 | [variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2] -------------------------------------------------------------------------------- /test/js/quotedFatArrow.js: -------------------------------------------------------------------------------- 1 | [keyword let] [def f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c]; -------------------------------------------------------------------------------- /test/js/quotedStringAddition.js: -------------------------------------------------------------------------------- 1 | [keyword let] [def f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c]; -------------------------------------------------------------------------------- /test/js/scary_regexp.js: -------------------------------------------------------------------------------- 1 | [string-2 /foo[[/]]bar/]; -------------------------------------------------------------------------------- /test/js/spread.js: -------------------------------------------------------------------------------- 1 | [keyword function] [def f]([def&local a], [operator ...][def&local b]) { 2 | [variable&callee something]([variable-2 a], [operator ...][variable-2 b]); 3 | } 4 | -------------------------------------------------------------------------------- /test/js/tagged_template.js: -------------------------------------------------------------------------------- 1 | [comment // normal template] 2 | [string-2 `hello`]; 3 | 4 | [comment // inline html] 5 | [variable html][string-2 `][tag
][string-2 `]; 6 | 7 | [comment // expression inside inline html] 8 | [variable html][string-2 `][tag
][string-2 ${][number 10] 9 | [string-2 }][string-2 `]; 10 | 11 | [comment // normal template inside inline html] 12 | [variable html][string-2 `][tag
][string-2 ${] 13 | [variable foo][string-2 `][string-2 ][string-2 `] 14 | [string-2 }][tag
][string-2 `]; 15 | 16 | [comment // inline html inside of inline html] 17 | [variable html][string-2 `][tag
][string-2 ${] 18 | [variable html][string-2 `][tag ][string-2 `] 19 | [string-2 }][tag
][string-2 `]; 20 | 21 | 22 | 23 | [comment // tricky escape sequences] 24 | 25 | [comment // escaped backticks] 26 | 27 | [variable html][string-2 ``]; 28 | [variable html][string-2 `]\`; 29 | [string-2 `]; [comment // close the unclosed from prev line] 30 | [variable html][string-2 `]\`[string-2 `]; 31 | 32 | [comment // escaped backticks are matched by inner language] 33 | [variable html][string-2 `] 34 | [tag ] 35 | [tag
][string-2 `]; 36 | 37 | [comment // any odd number of backslashes is fine] 38 | [variable html][string-2 `] 39 | [tag ] 40 | [tag
][string-2 `]; 41 | [variable html][string-2 `] 42 | [tag ] 43 | [tag ][string-2 `]; 44 | 45 | [comment // an even number of backslashes do not escape, the template ends.] 46 | [variable html][string-2 `] 47 | [tag "]; 48 | [variable html][string-2 `] 49 | [tag "]; 50 | [variable html][string-2 `] 51 | [tag "]; 52 | 53 | [comment // escaped inner expressions] 54 | 55 | [variable html][string-2 `${][number 10][string-2 }`]; 56 | [variable html][string-2 `]\\[string-2 ${][number 10][string-2 }`]; 57 | [variable html][string-2 `]\\\\[string-2 ${][number 10][string-2 }`]; 58 | [variable html][string-2 `]\${10}[string-2 `]; 59 | -------------------------------------------------------------------------------- /test/kotlin/annotation.kt: -------------------------------------------------------------------------------- 1 | [meta @file:foo] 2 | 3 | [meta @dontIndent]([number 2])] 4 | [keyword class] [def&type Foo]([meta @`anno`] [meta @anno] [keyword private] [keyword val] [def&property field]: [type Int]) {} 5 | 6 | [keyword class] [def&type Foo] { 7 | [meta @][[ [meta ann] ]][meta @`anno`] [keyword var] [def&property field]: [type Int] [operator =] [number 10] 8 | } 9 | 10 | [keyword class] [def&type Foo]([meta @`anno`] [meta @][[ [meta ann] [meta anno] ]] [keyword protected] [keyword val] [def&property field]: [type Int]) {} 11 | 12 | [keyword fun] [def case_1]([def&local x]: [type Int]?, [def&local y]: [type Int]) { 13 | [keyword if] ([meta @Anno] [operator !]([variable-2 x] [operator ==] [variable-2 y])) { 14 | [variable-2 x].[property&callee inv]() 15 | } 16 | } 17 | 18 | [keyword val] [def x] [operator =] [meta @Anno] [operator !][variable y] 19 | -------------------------------------------------------------------------------- /test/kotlin/expr.kt: -------------------------------------------------------------------------------- 1 | [keyword val] [def bar]: ([type Any]) [operator ->] ([type Any]) [operator ->] [type Unit] [operator =] 2 | [keyword fun] ([def&local a]) [operator =] [keyword fun] ([meta @Anno] [def&local b]) [operator =] [atom null] 3 | 4 | [keyword val] [def bar]: ([type Any]) [operator ->] [type Unit] [operator =] [keyword fun] ([keyword vararg] [def&local a]) {} 5 | 6 | [keyword val] [def q] [operator =] [string "hi"] 7 | .[property length] 8 | 9 | [keyword if] ([atom true]) { 10 | [variable&callee call]([number 1] [variable&callee xor] [number 0xff_ffff]) 11 | } [keyword else] [keyword if] ([atom false]) { 12 | [keyword return] [number 55_000.32e-3] 13 | } [keyword else] { 14 | [keyword continue] 15 | } 16 | 17 | [keyword if] ([variable x] [operator <] [number 10]) [atom null] [keyword else] [string "foo"] 18 | 19 | [keyword if] ([variable y]) { 20 | [number 1] 21 | } 22 | 23 | [keyword if] ([number 2]) [number 3] 24 | 25 | [keyword if] ([variable x] [operator !==] [number 0b1010]) 26 | [keyword break] @foo 27 | [keyword else] 28 | [variable abc] 29 | 30 | [keyword var] [def enum] [operator =] [string """hello${][number 80] [operator %] [number 2][string }more] 31 | [string text"""] 32 | 33 | [keyword try] { 34 | [variable&callee print]([string "hello world"]); [keyword throw] [type&callee Error]() 35 | } [keyword catch] ([def&local e]: [type Error]) { 36 | [keyword return] 37 | } 38 | 39 | [variable a].[property b]?. 40 | [property c]::[property&callee d](foo [operator =] [number 1], bar [operator =] [number 2]) 41 | 42 | [string "foo $][variable bar][string and ${][variable baz][string }"]; 43 | 44 | [keyword val] [def lambda] [operator =] {[def&local a], [def&local b]: [type Int] [operator ->] [variable-2 a] [operator /=] [variable-2 b]} 45 | 46 | [keyword var] [def simpleLambda] [operator =] {[variable-2 it].[property x]} 47 | 48 | [keyword when] ([number 10]) { 49 | [type Foo].[property&callee bar]() 50 | ([number 4]) 51 | } 52 | 53 | [variable&callee bar]().[property&callee forEach] { 54 | [comment // ...] 55 | } 56 | 57 | [variable&callee somefunction] { [def&local foo] [operator ->] 58 | [variable&callee bar]() 59 | } 60 | -------------------------------------------------------------------------------- /test/kotlin/statement.kt: -------------------------------------------------------------------------------- 1 | [meta #!/usr/bin/env node] 2 | 3 | [keyword external] [keyword fun] [def hello]([def&local name]: [type String]): [type String] 4 | 5 | [keyword package] [variable&package foo].[variable&package bar] 6 | 7 | [keyword import] [variable&package Kotlin].*; 8 | 9 | [comment // An enum] 10 | [meta @foo]([number 3]) 11 | [keyword enum] [keyword class] [type&def Color]([keyword val] [def&property rgb]: [type Int]) { 12 | [keyword public] [def&property RED]([number 0xFF0000]), 13 | [def&property GREEN]([number 0x00FF00]), 14 | [def&property BLUE]([number 0x0000FF]); 15 | 16 | [keyword fun] [def&property containsRed]() [operator =] 17 | ([keyword this].[property rgb] [variable&callee and] [number 0xFF0000] [operator !=] [number 0]) 18 | } 19 | 20 | [keyword fun] [def main]() { 21 | [keyword val] [def&local red] [operator =] [type Color].[property RED] 22 | [variable&callee println]([variable-2 red]) 23 | } 24 | 25 | [keyword value] [keyword class] [type&def Abc]([keyword var] [def&property x]: [type A], [def&local b]: [type X]?) { 26 | [keyword private] [keyword var] [def&property value]: [type Q] [operator =] [variable-2 b] [operator -] [number 1] 27 | } 28 | 29 | [keyword typealias] [type&def Array]<[type&def V]> [operator =] [type Something]<[type&local V]>; 30 | 31 | [keyword fun]<[type&def X]> [def id]([def&local x]: [type&local X]) { 32 | [keyword return] [variable-2 x] 33 | } 34 | 35 | [keyword class] [def&type C]<[def&type T]> { 36 | [keyword val] [def&property t]: [type&local T] [operator =] [atom null] 37 | } 38 | 39 | [keyword fun] [def f]( 40 | [def&local a]: [type Int], 41 | [def&local b]: [type Int] 42 | ) { 43 | [keyword return] [variable-2 a] 44 | } 45 | 46 | [keyword class] [def&type ParamList]( 47 | [def&local a]: [type Int], 48 | [keyword var] [def&property b]: [type Bool] 49 | ) { 50 | [keyword var] [def&property stringRepresentation]: [type String] 51 | [keyword get]() [operator =] [keyword this].[property&callee toString]() 52 | [keyword set]([def&local value]) { 53 | [variable&callee setDataFromString]([variable-2 value]) [comment // parses the string and assigns values to other properties] 54 | } 55 | } 56 | 57 | [keyword class] [def&type A] { 58 | [keyword val] [def&property a]: [type String] 59 | [keyword private] [keyword val] [def&property b]: [type String] 60 | } 61 | 62 | [keyword class] [def&type ClassBody] { 63 | [meta @Ann] 64 | [keyword private] [keyword companion] [keyword object] { 65 | [keyword val] [def&property a]: [type String] 66 | } 67 | 68 | [keyword init] { 69 | [keyword val] [def&local x] [operator =] [number 1] 70 | } 71 | 72 | [keyword internal] [meta @Ann] [keyword class] [def&type InnerClass] {} 73 | 74 | [keyword public] [keyword constructor]() 75 | 76 | [keyword val] [def&property beforeSemi]: [type String]; [keyword val] [def&property afterSemi]: [type String]; 77 | } 78 | 79 | [comment /* block comment] 80 | [comment */] 81 | 82 | [comment /** doc comment ][comment&link [[with]]][comment a link and a ][comment&tag @tag][comment */] 83 | 84 | [comment /* nested /* comment */ here */] 85 | 86 | [keyword var] [def a] [operator =] [number 1] 87 | [comment // Not indented] 88 | 89 | [comment // This works incorrectly because of greedy expression matching: class WithDelegation: I by b {}] 90 | -------------------------------------------------------------------------------- /test/ng/template.html: -------------------------------------------------------------------------------- 1 | [comment ] 2 | [tag ] 4 | [tag ] 5 | [tag ]Name[atom &] 6 | [tag ] 8 | [tag ] 9 | [tag ] 10 | [tag ]Submit[tag ] 11 | [tag ] 12 | [tag ] 13 | {{[variable submitMessage]}} 14 | [tag ] 15 | 16 | 17 | [tag ] 18 | 19 | [tag ]On Save[tag ] 20 | -------------------------------------------------------------------------------- /test/parse_spec.js: -------------------------------------------------------------------------------- 1 | function findSingle(str, pos, ch) { 2 | for (;;) { 3 | var found = str.indexOf(ch, pos); 4 | if (found == -1) return null; 5 | if (str.charAt(found + 1) != ch) return found; 6 | pos = found + 2; 7 | } 8 | } 9 | 10 | exports.tokenType = function(str) { 11 | return str ? str.split(" ").sort().join(" ") : null 12 | } 13 | 14 | const typeName = /[\w&-_]+/g; 15 | 16 | exports.parseSpec = function(str, filename) { 17 | let tokens = [], plain = "", pos = 0 18 | while (pos < str.length) { 19 | let type = null, text 20 | if (str.charAt(pos) == "[" && str.charAt(pos+1) != "[") { 21 | typeName.lastIndex = pos + 1 22 | let m = typeName.exec(str) 23 | type = exports.tokenType(m[0].replace(/&/g, " ")) 24 | let textStart = pos + type.length + 2 25 | let end = findSingle(str, textStart, "]") 26 | if (end == null) throw new Error("Unterminated token at " + pos + " in " + filename) 27 | text = str.slice(textStart, end) 28 | pos = end + 1 29 | } else { 30 | let end = findSingle(str, pos, "[") 31 | if (end == null) end = str.length 32 | text = str.slice(pos, end) 33 | pos = end 34 | } 35 | text = text.replace(/\[\[|\]\]/g, s => s.charAt(0)) 36 | tokens.push({type, text}) 37 | plain += text 38 | } 39 | return {tokens, plain} 40 | } 41 | -------------------------------------------------------------------------------- /test/py/fstrings.py: -------------------------------------------------------------------------------- 1 | [comment # no replacements] 2 | [string f'foo bar'] 3 | [string f"foo bar"] 4 | [string f'''foo bar'''] 5 | [string f"""foo bar"""] 6 | [comment # TODO(slebedev): Multi-line strings don't work.] 7 | 8 | [comment # f- with other prefixes] 9 | [string fr'foo bar'] 10 | [string rfu'foo bar'] 11 | 12 | [comment # escaped replacement] 13 | [string f'foo {{ bar {{}} boo }}'] 14 | 15 | [comment # replacement] 16 | [string f'foo ][operator {][variable bar][operator }][string '] 17 | 18 | [comment # replacement with a =] 19 | [string f'foo ][operator {][variable bar][operator =][operator }][string '] 20 | 21 | [comment # replacement with a conversion] 22 | [string f'foo ][operator {][variable bar][operator !][keyword s][operator }][string '] 23 | 24 | [comment # replacement with an invalid conversion] 25 | [string f'foo ][operator {][variable bar][operator !][keyword boo][operator }][string '] 26 | [string f'foo ][operator {][variable bar][operator !][operator }][string '] 27 | 28 | [comment # replacement with a format spec] 29 | [string f'foo ][operator {][variable bar][operator :][string 42d][operator }][string '] 30 | 31 | [comment # replacement with a nested format spec] 32 | [string f'foo ][operator {][variable bar][operator :][operator {][variable boo][operator }][string d][operator }][string '] 33 | 34 | [comment # replacement with both a conversion and a format spec] 35 | [string f'foo ][operator {][variable bar][operator !][keyword s][operator :][string 42d][operator }][string '] 36 | 37 | [comment # replacement with a misplaced format spec] 38 | [string f'foo ][operator {][variable bar][operator :][string 42d!s][operator }][string '] 39 | 40 | [comment # replacement with a walrus operator] 41 | [string f'foo ][operator {][variable bar][operator :=][number 42][operator :][string 42d][operator }][string '] 42 | -------------------------------------------------------------------------------- /test/py/grammar.py: -------------------------------------------------------------------------------- 1 | [comment # this is a comment] 2 | 3 | [keyword import] [variable foo].[property bar] [keyword as] [def foobar] 4 | [keyword from] [variable foo] [keyword import] * 5 | [keyword from] [variable foo] [keyword import] bar 6 | [keyword from] [variable foo] [keyword import] bar [keyword as] [def foobar] 7 | [keyword from] [variable foo] [keyword import] (bar) 8 | [keyword from] [variable foo] [keyword import] (bar [keyword as] [def foobar]) 9 | [keyword from] [variable foo] [keyword import] (bar,) 10 | [keyword from] .. [keyword import] bar 11 | [keyword from] .. [variable foo] [keyword import] bar 12 | 13 | [def foo] [operator =] [string "bar"]; [variable abc_cde].[property&callee prop]([operator **][variable baz]); [keyword del] [variable foo], [variable bar] 14 | [def bar]: [builtin str] [operator =] [string "q"] 15 | [def bar]: [builtin str] 16 | [def bar]: [builtin list] [[ [builtin int] ]] 17 | [def bar]: [variable x][operator +][variable y] 18 | 19 | [keyword for] [def y] [keyword in] [variable x]: [keyword pass] 20 | 21 | [meta @foo.bar] 22 | [keyword async] [keyword def] [def f]([variable-2 v]: [variable myType] [operator =] [number 0xffff], [operator **][variable-2 blah]): 23 | [builtin print]([variable-2 v] [operator +] [string 'hi\''] [keyword if] [atom False] [keyword else] [string '''blah''']) 24 | [keyword yield] [keyword from] [variable ugh] 25 | 26 | [keyword class] [type&def C]([variable hi]): 27 | [string """my docstring"""] 28 | [def&property x] [operator =] [number 100_000.0] 29 | 30 | [keyword def] [def&property method]([atom self], [variable-2 u]) -> [variable t]: 31 | [atom self].[property&callee map]([keyword lambda] [variable-2 a]: [variable-2 x] [keyword not in] [variable-2 a]) 32 | [keyword return] [variable-2 u][[ : [number 1] : [number 2], [variable a] ]] 33 | 34 | [keyword if] [atom None]: 35 | [keyword for] [def i] [keyword in] [[ [variable-2 k] [keyword for] [def k] [keyword in] [variable p] ]]: 36 | [keyword global] [variable m] 37 | [keyword break] 38 | 39 | [keyword while] [atom False]: [string fr"single line"] 40 | [keyword raise] [number 0e+20] [keyword from] [variable huh] 41 | [keyword elif] [string """ok"""]: 42 | [keyword pass] 43 | [keyword else]: 44 | [keyword assert] [atom False] 45 | 46 | [def empty] [operator =] {} 47 | 48 | [keyword if] [variable pfile] [keyword is] [atom None] [keyword or] [variable pfile].[property project].[property disabled]: [keyword return] 49 | 50 | [comment # with statement with a non-trivial target] 51 | [keyword with] [variable cm] [keyword as] ([def x], [def y]): [operator ...] 52 | 53 | [keyword class] [type&def B]: 54 | [keyword def] [def&property __init__]([atom self]): 55 | [keyword try]: 56 | [keyword with] [string U"x"] [keyword as] [variable-2 ay]: [variable-2 ay] 57 | [keyword except] [variable Except] [keyword as] [variable-2 e]: 58 | [variable&callee report]([variable-2 e]) 59 | [keyword finally]: 60 | [variable-2 hey] [operator =] [atom True] [keyword or] [atom False] 61 | [variable-2 hey] [operator =] [string "again"] 62 | [variable-2 hey] [operator <<=] [number 0b10] [operator @] [operator ~][number 0O7] [operator **] [variable n] 63 | 64 | [def&property dict1] [operator =] { 65 | [string "x"]: ([number 22]), 66 | [string "y"]: [operator ...], 67 | [number 3]: [string "str"] [string "more str"] 68 | } 69 | 70 | [variable hey] [operator |=] [variable dict1] 71 | 72 | [keyword def] [def foo](): 73 | [keyword try]: 74 | [keyword yield] 75 | [keyword finally]: 76 | [keyword return] 77 | 78 | [keyword def] [def abc](): 79 | [variable-2 x], [variable-2 y] [operator =] [number 1], [number 2] 80 | 81 | [keyword for] [def a], [def b] [keyword in] [builtin enumerate]([string 'xyz']): 82 | [keyword pass] 83 | 84 | [callee&variable foo]([meta dir]=[string "a"], [meta file]=[string "b"]) 85 | [callee&variable foo]([variable x] [operator ==] [variable y]) 86 | [callee&variable foo]([meta p]=[variable x] [operator ==] [variable y]) 87 | 88 | [keyword def] [def testRaise](): 89 | [variable-2 bar] [operator =] [number 1] 90 | [keyword raise] [variable Exception], [string 'blah'] 91 | [variable-2 bar] [operator =] [builtin map]([keyword lambda] [variable-2 x]: [number 1], [variable-2 bar]) 92 | 93 | [keyword import] [variable typing] 94 | 95 | [keyword class] [type&def Example]([builtin object]): 96 | [keyword def] [def&property method]([atom self], [variable-2 x]: [variable typing].[property List]): 97 | [atom self].[property x] [operator =] [variable-2 x] 98 | 99 | [def x] [operator =] [[ [variable k] [keyword for] ([def k], [def v]) [keyword in] [variable w].[property&callee items]() [keyword if] [variable v] [operator ==] [number 3] ]] 100 | 101 | [variable&callee main]([[ 102 | [number 1], 103 | [number 2], 104 | ]]) 105 | 106 | \ 107 | [string """] 108 | [string x] 109 | [string """] 110 | 111 | [def foo] [operator =] [builtin tuple]([variable-2 bar] [keyword for] [def bar] [keyword in] [variable baz]) 112 | 113 | [variable x][[[variable a] 114 | .[property x] ]] 115 | 116 | ([def a], 117 | [def b]) [operator =] [variable c] 118 | 119 | [comment # subscript] 120 | [variable xs][[ [variable i] ]] 121 | 122 | [comment # simple slices] 123 | [variable xs][[ [variable i] : [variable j] ]] 124 | [variable xs][[ [variable i] : ]] 125 | [variable xs][[ : [variable j] ]] 126 | [variable xs][[ : ]] 127 | 128 | [comment # slices with step] 129 | [variable xs][[ [variable i] : [variable j] : [variable s] ]] 130 | [variable xs][[ : [variable j] : [variable s] ]] 131 | [variable xs][[ [variable i] : : [variable s] ]] 132 | [variable xs][[ : : [variable s] ]] 133 | [variable xs][[ [variable i] : : ]] 134 | [variable xs][[ : [variable j] : ]] 135 | [variable xs][[ : : ]] 136 | -------------------------------------------------------------------------------- /test/py/indent.py: -------------------------------------------------------------------------------- 1 | # test: indent_only 2 | 3 | quux( 4 | var_one, var_two, var_three, var_four) 5 | 6 | quux(var_one, var_two, 7 | var_three, var_four) 8 | 9 | quux(var_one, 10 | var_two, 11 | ) 12 | 13 | quux(var_one, 14 | var_two 15 | ) 16 | 17 | meal = ( 18 | spam, beans) 19 | 20 | meal = (spam, 21 | beans) 22 | 23 | meal = [ 24 | spam, beans] 25 | 26 | meal = [spam, 27 | beans] 28 | 29 | meal = [ 30 | spam, 31 | beans, 32 | ] 33 | 34 | foo = { 35 | "x": x} 36 | 37 | foo = { 38 | 39 | "x": x + 40 | y} 41 | 42 | foo = { 43 | "a": a, 44 | "b": b, 45 | } 46 | 47 | var = ( 48 | 3) or ( 49 | 4) 50 | 51 | return int(str( 52 | 3)) 53 | 54 | class Foo(object): 55 | pass 56 | 57 | def foo( 58 | a: int, 59 | b: int) -> int: 60 | pass 61 | 62 | def foo(a: int, 63 | b: int) -> int: 64 | pass 65 | 66 | def foo( 67 | a: int, 68 | b: int) -> int: 69 | pass 70 | 71 | if (True): 72 | pass 73 | 74 | return ("implicit line " 75 | "joining") 76 | 77 | return ('fmt') % dict( 78 | a=b) 79 | 80 | a = ('afmt' 81 | 'bfmt') % dict( 82 | x=y) 83 | -------------------------------------------------------------------------------- /test/run.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const {runMode, getMode} = require("codemirror/addon/runmode/runmode.node") 3 | global.CodeMirror = require("codemirror") // FIXME make the modes properly require CodeMirror 4 | global.CodeMirror.Pass = {} 5 | require("codemirror-grammar-mode") 6 | 7 | const {parseSpec, tokenType} = require("./parse_spec") 8 | 9 | require("../dist/cpp") 10 | require("../dist/clif") 11 | require("../dist/c") 12 | require("../dist/flatbuffers") 13 | require("../dist/javascript") 14 | require("../dist/typescript") 15 | require("../dist/python") 16 | require("../dist/go") 17 | require("../dist/java") 18 | require("../dist/kotlin") 19 | require("../dist/angulartemplate") 20 | require("../dist/html") 21 | 22 | let filter = process.argv[2] 23 | 24 | ;[{dir: "c", mode: "google-c"}, 25 | {dir: "clif", mode: "google-clif"}, 26 | {dir: "cpp", mode: "google-cpp"}, 27 | {dir: "flatbuffers", mode: "flatbuffers"}, 28 | {dir: "js", mode: "google-javascript"}, 29 | {dir: "ts", mode: "google-typescript"}, 30 | {dir: "py", mode: "google-python"}, 31 | {dir: "go", mode: "google-go"}, 32 | {dir: "java", mode: "google-java"}, 33 | {dir: "kotlin", mode: "google-kotlin"}, 34 | {dir: "ng", mode: "google-angular-template"} 35 | ].forEach(lang => { 36 | let base = __dirname + "/" + lang.dir + "/" 37 | fs.readdirSync(base).forEach(file => { 38 | if (file[0] == "." || (filter && filter != file)) return 39 | let {tokens, plain, open, conf = {}} = parseTestSpec(fs.readFileSync(base + file, "utf8"), base + file) 40 | conf.name = lang.mode 41 | try { 42 | compare(plain, tokens, conf, open) 43 | } catch(e) { 44 | console.log(`${file}: ${e.stack || e.message}`) 45 | } 46 | }); 47 | }); 48 | 49 | function parseTestSpec(file, fileName) { 50 | let directive = /(?:\/\/|#)\s*test:\s*(.*)/.exec(file) 51 | if (directive) file = file.slice(0, directive.index) + file.slice(directive.index + directive[0].length) 52 | if (directive && /\bindent_only\b/.test(directive[1])) 53 | return {tokens: [{text: file, type: null}], plain: file, open: true} 54 | let result = parseSpec(file, fileName) 55 | result.open = directive && /\bopen\b/.test(directive[1]) 56 | result.conf = directive && /^\s*\{.*?\}\s*$/.test(directive[1]) && JSON.parse(directive[1]) || undefined 57 | return result 58 | } 59 | 60 | function compare(text, tokens, mode, open) { 61 | let index = 0, off = 0, line = 1, ch = 0 62 | let conf = {indentUnit: 2, tabSize: 4} 63 | let lines = text.split("\n"), modeObj = CodeMirror.getMode(conf, mode), curState = null 64 | 65 | runMode(text, mode, (text, style, _i, _s, state) => { 66 | if (!text) return 67 | if (state) curState = state 68 | let token = tokens[index], type = tokenType(style) 69 | if (token.type != type && !(open && token.type == null)) { 70 | let shortText = token.text.length < text.length ? token.text : text 71 | let underlined = ` ${lines[line - 1]}\n ${' '.repeat(ch)}^`; 72 | throw new Error(`Unexpected token ${JSON.stringify(type)} for ${JSON.stringify(shortText)} at ${line}:${ch}. Expected ${JSON.stringify(token.type)}\n${underlined}`) 73 | } 74 | 75 | if (text == "\n") { 76 | line++ 77 | ch = 0 78 | if (modeObj.indent && curState) { 79 | let str = lines[line - 1], ws = str.match(/^(\s*)(.*)/) 80 | if (str) { 81 | let indent = modeObj.indent(curState, ws[2], str) 82 | let expected = CodeMirror.countColumn(str, ws[1].length, conf.tabSize) 83 | if (indent != CodeMirror.Pass && indent != expected) 84 | throw new Error("Indentation of line " + line + " is " + indent + " (expected " + expected + ")") 85 | } 86 | } 87 | } else { 88 | ch += text.length 89 | } 90 | if (text.length == token.text.length - off) { 91 | off = 0 92 | index++ 93 | } else { 94 | off += text.length 95 | } 96 | }) 97 | } 98 | -------------------------------------------------------------------------------- /test/ts/grammar.ts: -------------------------------------------------------------------------------- 1 | [keyword let] [def x]: ([def&local arg]: [type Type]) [operator =>] [type ReturnType]; 2 | 3 | [keyword class] [type&def Foo] [keyword extends] [type Some]<[type Type]> {} 4 | 5 | [keyword class] [def&type Foo] { 6 | [keyword public] [keyword static] [def&property main]() {} 7 | [keyword private] [def&property _foo]: [type string]; 8 | } 9 | 10 | [keyword import] [keyword *] [keyword as] [def Sequelize] [keyword from] [string 'sequelize']; 11 | [keyword interface] [def&type MyAttributes] { 12 | [def&property truthy]: [string 'true'] [operator |] [number 1] [operator |] [atom true]; 13 | [def&property falsy]: [string 'false'] [operator |] [number 0] [operator |] [atom false]; 14 | [[ [variable NAME] ]]: [type Something]; 15 | } 16 | [keyword interface] [def&type MyInstance] [keyword extends] [variable Sequelize].[type Instance] < [type MyAttributes] > { 17 | [def&property rawAttributes]: [type MyAttributes]; 18 | [def&property truthy]: [string 'true'] [operator |] [number 1] [operator |] [atom true]; 19 | [def&property falsy]: [string 'false'] [operator |] [number 0] [operator |] [atom false]; 20 | } 21 | 22 | [keyword export] [keyword interface] [def&type UserModel] [keyword extends] 23 | [variable Sequelize].[type Model]<[type UserInstance], [type UserAttributes]> { 24 | [def&property findById]: ( 25 | [def&local userId]: [type number] 26 | ) [operator =>] [type Promise]<[type Array]<{ [def&property id], [def&property name] }>>; 27 | [def&property updateById]: ( 28 | [def&local userId]: [type number], 29 | [def&local isActive]: [type boolean] 30 | ) [operator =>] [type Promise]<[type AccountHolderNotificationPreferenceInstance]>; 31 | [keyword readonly] [def&property bar]: [type string]; 32 | } 33 | 34 | [keyword const] [def hello]: { 35 | [def&property prop1]?: [type string]; 36 | [def&property prop2]?: [type string]; 37 | } [operator =] {}; 38 | 39 | [keyword export] [keyword interface] [def&type UserAttributes] { 40 | [def&property id]?: [type number]; 41 | [def&property createdAt]?: [type Date]; 42 | } 43 | [keyword export] [keyword interface] [def&type UserInstance] [keyword extends] [variable Sequelize].[type Instance]<[type UserAttributes]>, [type UserAttributes] { 44 | [def&property id]: [type number]; 45 | [def&property createdAt]: [type Date]; 46 | } 47 | 48 | [keyword interface] [def&type A] { 49 | [[ prop: [type string] ]]: [type any]; 50 | [def&property prop1]: [type any]; 51 | } 52 | 53 | [keyword class] [def&type Foo]<[def&type T]> { 54 | [def&property bar]() {} 55 | [def&property foo](@[variable ann] [def&local x]: [type number]): [type Foo] {} 56 | } 57 | 58 | [keyword export] [keyword type] [def&type AB] [operator =] [type A] [operator |] [type B]; 59 | [keyword type] [type&def Flags] [operator =] { 60 | [def&property p1]: [type string]; 61 | [def&property p2]: [type boolean]; 62 | }; 63 | 64 | [keyword class] [def&type HasType] { 65 | [def&property type]: [type string]; 66 | [def&property constructor]([def&local type]: [type string]) { 67 | [keyword this].[property type] [operator =] [variable-2 type]; 68 | } 69 | [def&property setType]({ [def&local type] }: { [def&property type]: [type string]; }) { 70 | [keyword this].[property type] [operator =] [variable-2 type]; 71 | } 72 | } 73 | 74 | [keyword function] [def a]() {} 75 | [keyword function] [def b]<[type&def IA] [keyword extends] [type object], [type&def IB] [keyword extends] [type object]>() {} 76 | [keyword function] [def c]() {} 77 | 78 | [keyword function] [def A]() { 79 | [keyword return] [keyword this].[property property]; 80 | } 81 | [keyword function] [def B](): [type Promise]<{ [[ key: [type string] ]]: [type any] } [operator |] [atom null]> { 82 | [keyword return] [keyword this].[property property]; 83 | } 84 | 85 | [keyword const] [def giftpay] [operator =] [variable config].[property&callee get]([string 'giftpay']) [keyword as] { [[ platformUuid: [type string] ]]: { [def&property version]: [type number]; [def&property apiCode]: [type string]; } }; 86 | 87 | [keyword function] [def x]<[type&def T] [keyword extends] [keyword keyof] [type X]>([def&local a]: [type T]) { 88 | [keyword return]; 89 | } 90 | 91 | [keyword let] [def x] [operator =] [keyword new] [callee&variable Map]<[type string], [type Date]>([string-2 `foo${][variable bar][string-2 }`]); 92 | 93 | [keyword class] [def&type Foo] { 94 | [keyword public] [keyword abstract] [def&property bar]() {} 95 | [def&property constructor]([keyword readonly] [keyword private] [def&local x]) {} 96 | } 97 | 98 | ({[def&property a]: [def&local p] [operator =>] [variable-2 p]}); 99 | 100 | [keyword this].[callee&property a]<[type Type]>([variable foo], [keyword function]([def&local a]) { [keyword return] [variable-2 a] [operator +] [number 200_000]; }); 101 | [keyword this].[property a][operator <][variable Type][operator >][variable foo]; 102 | 103 | [keyword class] [def&type Appler] { 104 | [keyword static] [def&property assertApple]([def&local fruit]: [type Fruit]): [variable-2 fruit] [keyword is] [type Apple] { 105 | [keyword if] ([operator !]([variable-2 fruit] [keyword instanceof] [variable Apple])) 106 | [keyword throw] [keyword new] [variable&callee Error](); 107 | } 108 | } 109 | 110 | [variable type] [operator =] <[type number]>[variable x] [keyword as] [type Bar]; 111 | 112 | [keyword export] [keyword const] [keyword enum] [def&type CodeInspectionResultType] { 113 | [def&property ERROR] [operator =] [string 'problem_type_error'], 114 | [def&property WARNING] [operator =] [string 'problem_type_warning'], 115 | [def&property META], 116 | } 117 | 118 | [keyword class] [def&type Foo] { 119 | [def&property x] [operator =] [keyword new] [variable&callee A]<[type B], [type string] [operator |] (() [operator =>] [type void])>(); 120 | [keyword private] [def&property bar](); 121 | } 122 | 123 | [keyword export] [keyword abstract] [keyword class] [def&type Foo] {} 124 | 125 | [keyword namespace] [def n] { 126 | [variable console].[callee&property log]([string "abc"]); 127 | } 128 | 129 | [keyword function] [def foo]() { 130 | [keyword const] [def&local x] [operator =] [number 2][operator !]; 131 | [keyword const] [def&local y] [operator =] [number 3]; 132 | } 133 | 134 | [keyword const] [def foo] [operator =] [keyword async] () [operator =>] {[keyword const] [def&local y] [operator =] [keyword await] [variable bar];}; 135 | 136 | [keyword export] [keyword abstract] [keyword class] [def&type A]<[type&def T]> [keyword extends] [type B] {} 137 | 138 | [keyword export] [keyword type] [type&def Filter]<[type&def T] [operator =] [type X], [type&def U]> [operator =] [type T] [keyword extends] [type U] [operator ?] [type T] [operator :] [type never]; 139 | 140 | [keyword let] [def f]: ([def&local x]: [type any]) [operator =>] [variable m] [keyword is] [type string]; 141 | 142 | [keyword const] [def x]: [type Array]<[keyword typeof] [variable a].[property b]>; 143 | 144 | [callee&variable describe]([string 'Foo'], () [operator =>] { 145 | [keyword const] [def&local foo] [operator =] [callee&variable fooFunc]<{ 146 | [def&property spy]: [variable jasmine].[type SpyObj]<[type Bar]>, 147 | [def&property bar]: [type Bar], 148 | }>(); 149 | }); 150 | -------------------------------------------------------------------------------- /test/ts/tagged_template.ts: -------------------------------------------------------------------------------- 1 | [comment // normal template] 2 | [string-2 `hello`]; 3 | 4 | [comment // inline html] 5 | [variable html][string-2 `][tag
][string-2 `]; 6 | 7 | [comment // expression inside inline html] 8 | [variable html][string-2 `][tag
][string-2 ${][number 10] 9 | [string-2 }][string-2 `]; 10 | 11 | [comment // normal template inside inline html] 12 | [variable html][string-2 `][tag
][string-2 ${] 13 | [variable foo][string-2 `][string-2 ][string-2 `] 14 | [string-2 }][tag
][string-2 `]; 15 | 16 | [comment // inline html inside of inline html] 17 | [variable html][string-2 `][tag
][string-2 ${] 18 | [variable html][string-2 `][tag ][string-2 `] 19 | [string-2 }][tag
][string-2 `]; 20 | 21 | 22 | 23 | [comment // tricky escape sequences] 24 | 25 | [comment // escaped backticks] 26 | 27 | [variable html][string-2 ``]; 28 | [variable html][string-2 `]\`; 29 | [string-2 `]; [comment // close the unclosed from prev line] 30 | [variable html][string-2 `]\`[string-2 `]; 31 | 32 | [comment // escaped backticks are matched by inner language] 33 | [variable html][string-2 `] 34 | [tag ] 35 | [tag
][string-2 `]; 36 | 37 | [comment // any odd number of backslashes is fine] 38 | [variable html][string-2 `] 39 | [tag ] 40 | [tag
][string-2 `]; 41 | [variable html][string-2 `] 42 | [tag ] 43 | [tag ][string-2 `]; 44 | 45 | [comment // an even number of backslashes do not escape, the template ends.] 46 | [variable html][string-2 `] 47 | [tag "]; 48 | [variable html][string-2 `] 49 | [tag "]; 50 | [variable html][string-2 `] 51 | [tag "]; 52 | 53 | [comment // escaped inner expressions] 54 | 55 | [variable html][string-2 `${][number 10][string-2 }`]; 56 | [variable html][string-2 `]\\[string-2 ${][number 10][string-2 }`]; 57 | [variable html][string-2 `]\\\\[string-2 ${][number 10][string-2 }`]; 58 | [variable html][string-2 `]\${10}[string-2 `]; 59 | --------------------------------------------------------------------------------