├── .npmignore ├── spec ├── csharp │ ├── Usings.cs │ ├── Struct.cs │ ├── NamespacesNested.cs │ ├── UsingsAndNamespaces.cs │ ├── InheritedClass.cs │ ├── ImplementedInterface.cs │ ├── Generics.cs │ ├── InterfaceInsideNamespace.cs │ ├── Static.cs │ ├── ClassInsideNamespace.cs │ ├── Comments.cs │ ├── Enum.cs │ ├── MethodInsideClass.cs │ └── PropertyInsideClass.cs ├── support │ └── jasmine.json ├── ScopeHelperSpec.ts ├── RegExHelperSpec.ts └── FileParserSpec.ts ├── README.md ├── tsconfig.json ├── .vscode └── launch.json ├── .github └── FUNDING.yml ├── package.json ├── src ├── LiteralParser.ts ├── Index.ts ├── UsingsParser.ts ├── FieldParser.ts ├── AttributeParser.ts ├── FileParser.ts ├── InterfaceParser.ts ├── EnumParser.ts ├── StructParser.ts ├── PropertyParser.ts ├── TypeParser.ts ├── MethodParser.ts ├── NamespaceParser.ts ├── ClassParser.ts ├── ScopeHelper.ts ├── Models.ts ├── nearley │ ├── grammar.ne │ └── grammar.js └── RegExHelper.ts ├── LICENSE └── .gitignore /.npmignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/csharp/Usings.cs: -------------------------------------------------------------------------------- 1 | using foo = buz.bar; 2 | using blah.lol.omg; -------------------------------------------------------------------------------- /spec/csharp/Struct.cs: -------------------------------------------------------------------------------- 1 | [SomeAttribute] 2 | struct MyStruct 3 | { 4 | 5 | } -------------------------------------------------------------------------------- /spec/csharp/NamespacesNested.cs: -------------------------------------------------------------------------------- 1 | namespace my.stuff { 2 | namespace blah { 3 | } 4 | } 5 | namespace omg { 6 | } -------------------------------------------------------------------------------- /spec/csharp/UsingsAndNamespaces.cs: -------------------------------------------------------------------------------- 1 | using foo = buz.bar; 2 | using blah; 3 | namespace mynamespace { 4 | using blah.lol.omg; 5 | } 6 | 7 | namespace blah.foo { 8 | 9 | } -------------------------------------------------------------------------------- /spec/csharp/InheritedClass.cs: -------------------------------------------------------------------------------- 1 | class MyClass : IMyInterface1, IMyInterface2 where Foo : class 2 | { 3 | void Bar() 4 | { 5 | 6 | } 7 | 8 | public void Foo() 9 | { 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Parses C# code as well as possible into JavaScript objects. 2 | 3 | Are you looking for a flexible C# to TypeScript generator? See: https://github.com/ffMathy/FluffySpoon.JavaScript.CSharpToTypeScriptGenerator 4 | -------------------------------------------------------------------------------- /spec/csharp/ImplementedInterface.cs: -------------------------------------------------------------------------------- 1 | interface MyInterface : IMyInterface1, IMyInterface2 where Foo : class 2 | { 3 | void Bar() 4 | { 5 | 6 | } 7 | 8 | public void Foo() 9 | { 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /spec/csharp/Generics.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | class MyPoco 4 | { 5 | public SomeFoo Name { get; set; } 6 | public SomeFoo, SomeThing> Foo { get; set; } 7 | public SomeFoo Bar() { } 8 | } -------------------------------------------------------------------------------- /spec/csharp/InterfaceInsideNamespace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MyNamespace 4 | { 5 | [SomeAttribute] 6 | public interface MyPoco 7 | { 8 | string[] Name { get; set; } 9 | 10 | System.Int32 SomeMethod(); 11 | } 12 | } -------------------------------------------------------------------------------- /spec/support/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "spec_dir": ".", 3 | "spec_files": [ 4 | "./dist/spec/*[sS]pec.js", 5 | "./spec/legacy/*.js" 6 | ], 7 | "helpers": [], 8 | "stopSpecOnExpectationFailure": false, 9 | "random": false 10 | } 11 | -------------------------------------------------------------------------------- /spec/csharp/Static.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public static class MyPoco 4 | { 5 | public static string SomeProperty { get; set; } 6 | 7 | private static string someField; 8 | public string someField2; 9 | 10 | public static string someMethod() 11 | { 12 | 13 | } 14 | 15 | public static MyPoco(string str) 16 | { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spec/csharp/ClassInsideNamespace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MyNamespace 4 | { 5 | [SomeAttribute] 6 | [SomeAttributeWithParameters(MyName = "Foo", 28, Framework.Blah, typeof(BlahBlah))] 7 | abstract class MyPoco where WithGenerics : new() 8 | { 9 | public string[] Name { get; set; } 10 | 11 | public int? someField; 12 | 13 | public List someField2 = new List(); 14 | 15 | public MyPoco() 16 | { 17 | 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /spec/csharp/Comments.cs: -------------------------------------------------------------------------------- 1 | class Foobar 2 | { 3 | string myField; 4 | bool SomeOtherStuff { get; set; } 5 | 6 | virtual /*string*/ void MyFunction() 7 | { 8 | //some region that is commented 9 | } 10 | 11 | void SomeOtherFunction(/*string parameter1, */bool parameter2 = false, List> foo = "bar") 12 | { 13 | 14 | } 15 | 16 | //List> Stuff() { } 17 | List> OtherStuff() { } 18 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": true, 3 | "exclude": [ 4 | "./spec/**/*.d.ts" 5 | ], 6 | "include": [ 7 | "./src/**/*.ts", 8 | "./spec/**/*.ts" 9 | ], 10 | "compilerOptions": { 11 | "target": "es5", 12 | "module": "commonjs", 13 | "moduleResolution": "node", 14 | "lib": [ "es2015", "es2017", "dom" ], 15 | "outDir": "./dist", 16 | "sourceMap": true, 17 | "declaration": true, 18 | "emitDecoratorMetadata": true, 19 | "experimentalDecorators": true, 20 | "removeComments": false, 21 | "noImplicitAny": true, 22 | "suppressImplicitAnyIndexErrors": true 23 | } 24 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "stopOnEntry": false, 11 | "sourceMaps": true, 12 | "name": "Run tests", 13 | "program": "${workspaceFolder}\\node_modules\\jasmine\\bin\\jasmine.js", 14 | "env": { 15 | "NODE_PATH": ".", 16 | "NODE_ENV": "development" 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /spec/csharp/Enum.cs: -------------------------------------------------------------------------------- 1 | [SomeAttribute] 2 | enum MyEnum: int 3 | { 4 | FirstValue, 5 | [SomeStuff] 6 | [SomeAttribute("qwdqkwd, lol hehe")] 7 | SecondValue = -4, 8 | [SomeAttribute(DisplayName = "foobar, lol")] 9 | ThirdValue, 10 | [SomeAttribute, FooAttribute("lol"), BlahAttribute(DisplayName = "qwdkqwd, test")] 11 | FourthValue = 6, 12 | FifthValue 13 | } 14 | 15 | namespace Blah { 16 | public enum BlahEnum 17 | { 18 | Hello, 19 | World 20 | } 21 | } 22 | 23 | class Foo 24 | { 25 | enum StuffEnum : System.Int32 26 | { 27 | Lol, 28 | Bar 29 | } 30 | 31 | enum OtherEnumStuff 32 | { 33 | Hello, 34 | World 35 | } 36 | } -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ffMathy # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /spec/csharp/MethodInsideClass.cs: -------------------------------------------------------------------------------- 1 | class Foobar 2 | { 3 | string myField; 4 | bool SomeOtherStuff { get; set; } 5 | 6 | virtual string MyFunction() 7 | { 8 | 9 | } 10 | 11 | [SomeAttribute] 12 | void SomeOtherFunction( 13 | string parameter1, 14 | bool parameter2 = false, 15 | List> foo = "bar", 16 | [Hello] [Blah] [Foo, Bar] string foo2 = "bar", 17 | [Blah] params string[] someArray) 18 | { 19 | 20 | } 21 | 22 | public string MethodWithMultipleParametersAnnotated([Annotation1]string baz, [Annotation2]int buz) { 23 | } 24 | 25 | List> Stuff() { } 26 | 27 | public Task GetAllUsers(string username, string email) { 28 | return new [] { 29 | "foo", 30 | "bar" 31 | }; 32 | } 33 | 34 | public void MyNullParameterMethod(string foo = null) { } 35 | } -------------------------------------------------------------------------------- /spec/csharp/PropertyInsideClass.cs: -------------------------------------------------------------------------------- 1 | class Foobar 2 | { 3 | string MyProperty { get; set; } 4 | 5 | string ReadOnlyProperty 6 | { 7 | get 8 | { 9 | return "lol"; 10 | } 11 | } 12 | 13 | [SomeAttribute] 14 | string GetSetProperty 15 | { 16 | get 17 | { 18 | return "lol"; 19 | } 20 | set 21 | { 22 | //do stuff 23 | } 24 | } 25 | 26 | enum Foobar 27 | { 28 | Stuff 29 | } 30 | 31 | public virtual string MyPublicVirtualProperty { get; set; } = "barfoo"; 32 | 33 | string ReadOnlyShortProperty => "foobar"; 34 | 35 | (string, Func) TupleReturningProperty => ("foobar", 1337); 36 | (string a, Func b) NamedTupleReturningProperty => ("foobar", 1337); 37 | 38 | private IList _list; 39 | public IList List 40 | { 41 | get => _list; 42 | set => value == null ? _list = new List() : value; 43 | } 44 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@fluffy-spoon/csharp-parser", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "./dist/src/Index", 6 | "typings": "./dist/src/Index.d.ts", 7 | "scripts": { 8 | "test": "jasmine", 9 | "build": "tsc", 10 | "nearley:build": "nearleyc src/nearley/grammar.ne -o src/nearley/grammar.js", 11 | "nearley:unparse": "nearley-unparse -n 3 src/nearley/grammar.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/ffMathy/FluffySpoon.JavaScript.CSharpParser.git" 16 | }, 17 | "author": "", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/ffMathy/FluffySpoon.JavaScript.CSharpParser/issues" 21 | }, 22 | "homepage": "https://github.com/ffMathy/FluffySpoon.JavaScript.CSharpParser#readme", 23 | "devDependencies": { 24 | "@types/jasmine": "^3.6.2", 25 | "@types/node": "^16.0.0", 26 | "@types/safe-regex": "^1.1.1", 27 | "jasmine": "^3.6.3", 28 | "safe-regex": "^2.1.1" 29 | }, 30 | "dependencies": { 31 | "nearley": "^2.16.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/LiteralParser.ts: -------------------------------------------------------------------------------- 1 | import { ScopeHelper } from './ScopeHelper'; 2 | import { RegExHelper } from './RegExHelper'; 3 | import { CSharpToken, CSharpNamedToken } from './Models'; 4 | 5 | export class LiteralParser { 6 | private scopeHelper = new ScopeHelper(); 7 | private regexHelper = new RegExHelper(); 8 | 9 | constructor() { 10 | 11 | } 12 | 13 | parseLiteral(valueInput: string) { 14 | if(!valueInput) 15 | return null; 16 | 17 | valueInput = valueInput.trim(); 18 | 19 | var valueOutput = null; 20 | if ((valueInput.charAt(0) === "\"" || valueInput.charAt(0) === "'") && valueInput.charAt(valueInput.length - 1) === valueInput.charAt(0)) { 21 | valueOutput = valueInput.substr(1, valueInput.length - 2); 22 | } else if (!isNaN(parseFloat(valueInput))) { 23 | valueOutput = parseFloat(valueInput); 24 | } else if (valueInput === "false" || valueInput === "true") { 25 | valueOutput = valueInput === "true"; 26 | } else { 27 | var token = new CSharpNamedToken(); 28 | token.name = valueInput.trim(); 29 | 30 | valueOutput = token; 31 | } 32 | 33 | return valueOutput; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Mathias Lykkegaard Lorenzen 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Index.ts: -------------------------------------------------------------------------------- 1 | export { ClassParser } from './ClassParser'; 2 | export { EnumParser } from './EnumParser'; 3 | export { FileParser } from './FileParser'; 4 | export { TypeParser } from './TypeParser'; 5 | export { MethodParser } from './MethodParser'; 6 | export { NamespaceParser } from './NamespaceParser'; 7 | export { UsingsParser } from './UsingsParser'; 8 | export { AttributeParser } from './AttributeParser'; 9 | export { FieldParser } from './FieldParser'; 10 | export { StructParser } from './StructParser'; 11 | export { InterfaceParser } from './InterfaceParser'; 12 | export { ScopeHelper } from './ScopeHelper'; 13 | export { LiteralParser } from './LiteralParser'; 14 | 15 | export { 16 | CSharpType, 17 | CSharpUsing, 18 | CSharpImplementationTypeDeclarationScope, 19 | CSharpInterfaceTypeDeclarationScope, 20 | CSharpScope, 21 | CSharpNamespace, 22 | CSharpFile, 23 | CSharpMethod, 24 | CSharpToken, 25 | CSharpNamedToken, 26 | CSharpMethodParameter, 27 | CSharpClass, 28 | CSharpInterface, 29 | CSharpEnum, 30 | CSharpEnumOption, 31 | CSharpAttribute, 32 | CSharpAttributeParameter, 33 | CSharpProperty, 34 | CSharpPropertyComponent, 35 | CSharpField, 36 | CSharpStruct, 37 | CSharpGenericParameterContainer 38 | } from './Models'; 39 | -------------------------------------------------------------------------------- /src/UsingsParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpUsing, 3 | CSharpNamespace 4 | } from './Models'; 5 | 6 | import { ScopeHelper } from './ScopeHelper'; 7 | import { RegExHelper } from './RegExHelper'; 8 | 9 | export class UsingsParser { 10 | private scopeHelper = new ScopeHelper(); 11 | private regexHelper = new RegExHelper(); 12 | 13 | constructor() { 14 | 15 | } 16 | 17 | parseUsings(content: string) { 18 | var usings = new Array(); 19 | var scopes = this.scopeHelper.getCurlyScopes(content); 20 | var scope = scopes[0]; 21 | if (!scope) 22 | return usings; 23 | 24 | var statements = this.scopeHelper.getStatements(scope.prefix); 25 | for(var statement of statements) { 26 | var matches = this.regexHelper.getMatches( 27 | statement, 28 | new RegExp("^" + this.regexHelper.getUsingRegex(false, true, true) + "$", "g")); 29 | for (var match of matches) { 30 | try { 31 | var using = { 32 | alias: match[0] || null, 33 | namespace: new CSharpNamespace(match[1]) 34 | }; 35 | 36 | usings.push(using); 37 | } catch(ex) { 38 | console.error("Skipping using due to parsing error.", statement, ex); 39 | debugger; 40 | } 41 | } 42 | } 43 | 44 | return usings; 45 | } 46 | } -------------------------------------------------------------------------------- /spec/ScopeHelperSpec.ts: -------------------------------------------------------------------------------- 1 | import { ScopeHelper } from '../src/ScopeHelper'; 2 | 3 | describe("ScopeHelper", function () { 4 | 5 | var scopeHelper = new ScopeHelper(); 6 | 7 | it("should be able to handle curly scopes with content", () => { 8 | var content = "foo { bar { sub bar } other bar } other foo { } hello"; 9 | var scopes = scopeHelper.getCurlyScopes(content); 10 | 11 | expect(scopes.length).toEqual(3); 12 | 13 | expect(scopes[0].prefix).toEqual("foo {"); 14 | expect(scopes[0].content).toEqual("bar { sub bar } other bar"); 15 | expect(scopes[0].suffix).toEqual("} other foo"); 16 | 17 | expect(scopes[0].offset).toEqual(4); 18 | expect(scopes[0].length).toEqual(29); 19 | 20 | expect(scopes[1].prefix).toEqual("other foo {"); 21 | expect(scopes[1].content).toEqual(""); 22 | expect(scopes[1].suffix).toEqual("} hello"); 23 | }); 24 | 25 | it("should be able to handle nested single line comment scopes with newlines around", () => { 26 | var content = "\n\t} //other foo\n bar baz"; 27 | var trimmed = scopeHelper.enumerateRelevantCodeCharacterRegions(content); 28 | 29 | expect(trimmed).toEqual("\n\t} \n bar baz"); 30 | }); 31 | 32 | it("should be able to handle lists", () => { 33 | var content = "foo { bar { sub bar } other bar>, lol> }, other, foo"; 34 | var scopes = scopeHelper.getScopedList(",", content); 35 | 36 | expect(scopes.length).toEqual(3); 37 | 38 | expect(scopes[0]).toEqual("foo { bar { sub bar } other bar>, lol> }"); 39 | expect(scopes[1]).toEqual("other"); 40 | expect(scopes[2]).toEqual("foo"); 41 | }); 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /spec/RegExHelperSpec.ts: -------------------------------------------------------------------------------- 1 | import { RegExHelper } from '../src/RegExHelper'; 2 | import isSafeRegEx = require('safe-regex'); 3 | 4 | describe("RegExHelper", function () { 5 | 6 | var regexHelper = new RegExHelper(); 7 | 8 | var assertIsSafe = (name: keyof RegExHelper) => { 9 | it("should never time out for the regular expression " + name, () => { 10 | var regex = regexHelper[name].call(regexHelper); 11 | expect(isSafeRegEx(regex)).toBe(true, regex); 12 | }); 13 | }; 14 | 15 | assertIsSafe('getAttributeParameterRegex'); 16 | assertIsSafe('getAttributeParametersRegex'); 17 | assertIsSafe('getAttributeRegex'); 18 | assertIsSafe('getAttributesRegex'); 19 | assertIsSafe('getClassRegex'); 20 | assertIsSafe('getEnumOptionRegex'); 21 | assertIsSafe('getEnumRegex'); 22 | assertIsSafe('getGenericNameRegex'); 23 | assertIsSafe('getGenericTypeNameRegex'); 24 | assertIsSafe('getGenericTypeWrapperRegex'); 25 | assertIsSafe('getInterfaceRegex'); 26 | assertIsSafe('getKeywordRegex'); 27 | assertIsSafe('getLiteralCharacterRegex'); 28 | assertIsSafe('getLiteralNumberDecimalRegex'); 29 | assertIsSafe('getLiteralNumberHexadecimalRegex'); 30 | assertIsSafe('getLiteralNumberIntegerRegex'); 31 | assertIsSafe('getLiteralNumberRegex'); 32 | assertIsSafe('getLiteralRegex'); 33 | assertIsSafe('getLiteralStringRegex'); 34 | assertIsSafe('getMethodParameterRegex'); 35 | assertIsSafe('getMethodParametersWrapperRegex'); 36 | assertIsSafe('getMethodRegex'); 37 | assertIsSafe('getModifierRegex'); 38 | assertIsSafe('getModifiersRegex'); 39 | assertIsSafe('getNameRegex'); 40 | assertIsSafe('getPropertyRegex'); 41 | assertIsSafe('getSignRegex'); 42 | assertIsSafe('getTypeConstraintRegex'); 43 | assertIsSafe('getUsingRegex'); 44 | assertIsSafe('getFieldRegex'); 45 | assertIsSafe('getNamespaceRegex'); 46 | assertIsSafe('getStructRegex'); 47 | 48 | }); 49 | -------------------------------------------------------------------------------- /src/FieldParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpField, 3 | CSharpType 4 | } from './Models'; 5 | 6 | import { ScopeHelper } from './ScopeHelper'; 7 | import { RegExHelper } from './RegExHelper'; 8 | import { TypeParser } from './TypeParser'; 9 | import { AttributeParser } from './AttributeParser'; 10 | 11 | export class FieldParser { 12 | private scopeHelper = new ScopeHelper(); 13 | private regexHelper = new RegExHelper(); 14 | 15 | private attributeParser = new AttributeParser(); 16 | 17 | constructor( 18 | private typeParser: TypeParser) { 19 | 20 | } 21 | 22 | parseFields(content: string) { 23 | var fields = new Array(); 24 | var scopes = this.scopeHelper.getCurlyScopes(content); 25 | 26 | for (var scope of scopes) { 27 | var statements = this.scopeHelper.getStatements(scope.prefix); 28 | for(var statement of statements) { 29 | var matches = this.regexHelper.getMatches( 30 | statement, 31 | new RegExp("^" + this.regexHelper.getFieldRegex(false, true, true, true, true, true) + "$", "g")); 32 | for (var match of matches) { 33 | try { 34 | var attributes = match[0]; 35 | var modifiers = match[1] || ""; 36 | var returnType = match[2]; 37 | var name = match[3]; 38 | var initialValue = match[4]; 39 | 40 | var field = new CSharpField(name); 41 | field.attributes = this.attributeParser.parseAttributes(attributes); 42 | field.type = this.typeParser.parseType(returnType); 43 | field.initialValue = initialValue; 44 | 45 | field.isPublic = modifiers.indexOf("public") > -1; 46 | field.isStatic = modifiers.indexOf("static") > -1; 47 | field.isReadOnly = modifiers.indexOf("readonly") > -1; 48 | 49 | fields.push(field); 50 | } catch(ex) { 51 | console.error("Skipping field due to parsing error.", statement, ex); 52 | debugger; 53 | } 54 | } 55 | } 56 | 57 | } 58 | 59 | return fields; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/AttributeParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpAttribute, CSharpAttributeParameter 3 | } from './Models'; 4 | 5 | import { RegExHelper } from './RegExHelper'; 6 | import { LiteralParser } from './LiteralParser'; 7 | import { ScopeHelper } from './Index'; 8 | 9 | export class AttributeParser { 10 | private regexHelper = new RegExHelper(); 11 | private scopeHelper = new ScopeHelper(); 12 | 13 | private literalParser = new LiteralParser(); 14 | 15 | constructor() { 16 | 17 | } 18 | 19 | parseAttributes(content: string) { 20 | var attributes = new Array(); 21 | if(!content) 22 | return attributes; 23 | 24 | var attributeSplits = this.scopeHelper.getScopedList("", content); 25 | for(var attributeSplit of attributeSplits) { 26 | var attributeSplitContents = attributeSplit.substr(1, attributeSplit.length-2); 27 | var innerAttributeSplits = this.scopeHelper.getScopedList(",", attributeSplitContents); 28 | for(var innerAttributeSplit of innerAttributeSplits) { 29 | var matches = this.regexHelper.getMatches( 30 | innerAttributeSplit, 31 | new RegExp("^" + this.regexHelper.getAttributeRegex(false, true, true) + "$", "g")); 32 | for (var match of matches) { 33 | try { 34 | var name = match[0]; 35 | var parameters = match[1]; 36 | 37 | var attribute = new CSharpAttribute(name); 38 | attribute.parameters = this.parseAttributeParameters(parameters); 39 | 40 | attributes.push(attribute); 41 | } catch(ex) { 42 | console.error("Skipping attribute due to parsing error.", innerAttributeSplit, ex); 43 | debugger; 44 | } 45 | } 46 | } 47 | } 48 | 49 | return attributes; 50 | } 51 | 52 | parseAttributeParameters(content: string) { 53 | var result = new Array(); 54 | 55 | var splits = this.scopeHelper.getScopedList(",", content); 56 | for(var split of splits) { 57 | var matches = this.regexHelper.getMatches( 58 | split, 59 | new RegExp("^" + this.regexHelper.getAttributeParameterRegex(false, true, true) + "$", "g")); 60 | for (var match of matches) { 61 | var parameter = new CSharpAttributeParameter(); 62 | parameter.name = match[0] || null; 63 | parameter.value = this.literalParser.parseLiteral(match[1]); 64 | 65 | result.push(parameter); 66 | } 67 | } 68 | 69 | return result; 70 | } 71 | } -------------------------------------------------------------------------------- /src/FileParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpFile 3 | } from './Models'; 4 | 5 | import { NamespaceParser } from './NamespaceParser'; 6 | import { ScopeHelper } from './ScopeHelper'; 7 | import { UsingsParser } from './UsingsParser'; 8 | import { ClassParser } from './ClassParser'; 9 | import { InterfaceParser } from './InterfaceParser'; 10 | import { EnumParser } from './EnumParser'; 11 | import { StructParser } from './StructParser'; 12 | import { TypeParser } from './TypeParser'; 13 | import { FieldParser } from './FieldParser'; 14 | 15 | export class FileParser { 16 | private namespaceParser: NamespaceParser; 17 | private usingsParser: UsingsParser; 18 | private classParser: ClassParser; 19 | private interfaceParser: InterfaceParser; 20 | private enumParser: EnumParser; 21 | private structParser: StructParser; 22 | private fieldParser: FieldParser; 23 | 24 | private scopeHelper: ScopeHelper; 25 | 26 | constructor(private contents: string) { 27 | this.contents = contents.replace(/\r\n/gi, '\n').replace(/\r/gi, '\n'); 28 | 29 | this.scopeHelper = new ScopeHelper(); 30 | 31 | var typeParser = new TypeParser(); 32 | 33 | this.usingsParser = new UsingsParser(); 34 | this.enumParser = new EnumParser(typeParser); 35 | this.fieldParser = new FieldParser(typeParser); 36 | this.classParser = new ClassParser(typeParser, this.enumParser, this.fieldParser); 37 | this.interfaceParser = new InterfaceParser(typeParser); 38 | this.structParser = new StructParser(typeParser); 39 | this.namespaceParser = new NamespaceParser(this.classParser, this.interfaceParser, this.enumParser, this.structParser); 40 | } 41 | 42 | parseFile(): CSharpFile { 43 | var file = new CSharpFile(); 44 | 45 | file.innerScopeText = this.contents; 46 | 47 | file.usings = this.usingsParser.parseUsings(file.innerScopeText); 48 | for(var using of file.usings) 49 | using.parent = file; 50 | 51 | file.namespaces = this.namespaceParser.parseNamespacesFromCode(file.innerScopeText); 52 | for(var namespace of file.namespaces) 53 | namespace.parent = file; 54 | 55 | file.classes = this.classParser.parseClasses(file.innerScopeText); 56 | for(var classObject of file.classes) 57 | classObject.parent = file; 58 | 59 | file.enums = this.enumParser.parseEnums(file.innerScopeText); 60 | for(var enumObject of file.enums) 61 | enumObject.parent = file; 62 | 63 | file.structs = this.structParser.parseStructs(file.innerScopeText); 64 | for(var struct of file.structs) 65 | struct.parent = file; 66 | 67 | file.interfaces = this.interfaceParser.parseInterfaces(file.innerScopeText); 68 | for(var interfaceObject of file.interfaces) 69 | interfaceObject.parent = file; 70 | 71 | return file; 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /src/InterfaceParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpInterface, 3 | CSharpType 4 | } from './Models'; 5 | 6 | import { ScopeHelper } from './ScopeHelper'; 7 | import { RegExHelper } from './RegExHelper'; 8 | import { MethodParser } from './MethodParser'; 9 | import { PropertyParser } from './PropertyParser'; 10 | import { TypeParser } from './TypeParser'; 11 | import { AttributeParser } from './AttributeParser'; 12 | 13 | export class InterfaceParser { 14 | private scopeHelper = new ScopeHelper(); 15 | private regexHelper = new RegExHelper(); 16 | 17 | private propertyParser = new PropertyParser(); 18 | private attributeParser = new AttributeParser(); 19 | 20 | private methodParser: MethodParser; 21 | 22 | constructor( 23 | private typeParser: TypeParser) { 24 | 25 | this.methodParser = new MethodParser(typeParser); 26 | } 27 | 28 | parseInterfaces(content: string) { 29 | var interfaces = new Array(); 30 | var scopes = this.scopeHelper.getCurlyScopes(content); 31 | for (var scope of scopes) { 32 | var statements = this.scopeHelper.getStatements(scope.prefix); 33 | for(var statement of statements) { 34 | var matches = this.regexHelper.getMatches( 35 | statement, 36 | new RegExp("^" + this.regexHelper.getInterfaceRegex() + "$", "g")) 37 | for (var match of matches) { 38 | try { 39 | var interfaceObject = new CSharpInterface(match[2]); 40 | interfaceObject.innerScopeText = scope.content; 41 | interfaceObject.genericParameters = this.typeParser.parseTypesFromGenericParameters(match[3]); 42 | interfaceObject.isPublic = (match[1] || "").indexOf("public") > -1; 43 | interfaceObject.attributes = this.attributeParser.parseAttributes(match[0]); 44 | interfaceObject.implements = this.typeParser.parseTypesFromGenericParameters(match[4]); 45 | 46 | var properties = this.propertyParser.parseProperties(scope.content); 47 | for (var property of properties) { 48 | property.parent = interfaceObject; 49 | interfaceObject.properties.push(property); 50 | } 51 | 52 | var methods = this.methodParser.parseMethods(scope.content, interfaceObject); 53 | for (var method of methods) { 54 | method.parent = interfaceObject; 55 | interfaceObject.methods.push(method); 56 | } 57 | 58 | interfaces.push(interfaceObject); 59 | } catch(ex) { 60 | console.error("Skipping interface due to parsing error.", statement, ex); 61 | debugger; 62 | } 63 | } 64 | } 65 | } 66 | 67 | return interfaces; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/EnumParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpEnum, 3 | CSharpEnumOption 4 | } from './Models'; 5 | 6 | import { ScopeHelper } from './ScopeHelper'; 7 | import { RegExHelper } from './RegExHelper'; 8 | import { AttributeParser } from './AttributeParser'; 9 | import { TypeParser } from './TypeParser'; 10 | 11 | export class EnumParser { 12 | private scopeHelper = new ScopeHelper(); 13 | private regexHelper = new RegExHelper(); 14 | private attributeParser = new AttributeParser(); 15 | 16 | constructor( 17 | private typeParser: TypeParser) { 18 | 19 | } 20 | 21 | parseEnums(content: string) { 22 | var enums = new Array(); 23 | var scopes = this.scopeHelper.getCurlyScopes(content); 24 | for (var scope of scopes) { 25 | var statements = this.scopeHelper.getStatements(scope.prefix); 26 | for(var statement of statements) { 27 | var matches = this.regexHelper.getMatches( 28 | statement, 29 | new RegExp("^" + this.regexHelper.getEnumRegex(false, true, true, true, true) + "$", "g")); 30 | for (var match of matches) { 31 | try { 32 | var attributes = match[0]; 33 | var modifiers = match[1] || ""; 34 | var name = match[2]; 35 | var inheritance = match[3]; 36 | 37 | var enumObject = new CSharpEnum(name); 38 | enumObject.isPublic = modifiers.indexOf("public") > -1; 39 | enumObject.attributes = this.attributeParser.parseAttributes(attributes); 40 | enumObject.options = this.parseEnumOptions(scope.content); 41 | enumObject.inheritsFrom = this.typeParser.parseType(inheritance); 42 | 43 | enums.push(enumObject); 44 | } catch(ex) { 45 | console.error("Skipping enum due to parsing error.", statement, ex); 46 | debugger; 47 | } 48 | } 49 | } 50 | } 51 | 52 | return enums; 53 | } 54 | 55 | parseEnumOptions(content: string) { 56 | var result = new Array(); 57 | 58 | var nextValue = 0; 59 | var optionSplits = this.scopeHelper.getScopedList(",", content); 60 | for(var optionSplit of optionSplits) { 61 | var matches = this.regexHelper.getMatches( 62 | optionSplit, 63 | new RegExp("^" + this.regexHelper.getEnumOptionRegex(false, true, true, true) + "$", "g")); 64 | 65 | for (var match of matches) { 66 | var attributes = match[0]; 67 | var name = match[1]; 68 | var value = match[2]; 69 | 70 | var option = new CSharpEnumOption(name); 71 | option.attributes = this.attributeParser.parseAttributes(attributes); 72 | 73 | if (value) { 74 | option.value = parseInt(value); 75 | nextValue = option.value + 1; 76 | } else { 77 | option.value = nextValue; 78 | nextValue++; 79 | } 80 | 81 | result.push(option); 82 | } 83 | } 84 | 85 | return result; 86 | } 87 | } -------------------------------------------------------------------------------- /src/StructParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpNamespace, 3 | CSharpClass, 4 | CSharpType, 5 | CSharpStruct 6 | } from './Models'; 7 | 8 | import { ScopeHelper } from './ScopeHelper'; 9 | import { RegExHelper } from './RegExHelper'; 10 | import { MethodParser } from './MethodParser'; 11 | import { EnumParser } from './EnumParser'; 12 | import { PropertyParser } from './PropertyParser'; 13 | import { FieldParser } from './FieldParser'; 14 | import { TypeParser } from './TypeParser'; 15 | import { AttributeParser } from './AttributeParser'; 16 | 17 | export class StructParser { 18 | private scopeHelper = new ScopeHelper(); 19 | private regexHelper = new RegExHelper(); 20 | 21 | private propertyParser = new PropertyParser(); 22 | private attributeParser = new AttributeParser(); 23 | 24 | private methodParser: MethodParser; 25 | private fieldParser: FieldParser; 26 | 27 | constructor( 28 | private typeParser: TypeParser) { 29 | 30 | this.methodParser = new MethodParser(typeParser); 31 | this.fieldParser = new FieldParser(typeParser); 32 | } 33 | 34 | parseStructs(content: string) { 35 | var structs = new Array(); 36 | var scopes = this.scopeHelper.getCurlyScopes(content); 37 | for (var scope of scopes) { 38 | var statements = this.scopeHelper.getStatements(scope.prefix); 39 | for(var statement of statements) { 40 | var matches = this.regexHelper.getMatches( 41 | statement, 42 | new RegExp("^" + this.regexHelper.getStructRegex() + "$", "g")); 43 | for (var match of matches) { 44 | try { 45 | var attributes = match[0]; 46 | var modifiers = match[1] || ""; 47 | var name = match[2]; 48 | var genericParameters = match[3]; 49 | 50 | var struct = new CSharpStruct(name); 51 | struct.attributes = this.attributeParser.parseAttributes(attributes); 52 | struct.genericParameters = this.typeParser.parseTypesFromGenericParameters(genericParameters); 53 | struct.innerScopeText = scope.content; 54 | struct.isPublic = modifiers.indexOf("public") > -1; 55 | 56 | var fields = this.fieldParser.parseFields(scope.content); 57 | for (var field of fields) { 58 | field.parent = struct; 59 | struct.fields.push(field); 60 | } 61 | 62 | var properties = this.propertyParser.parseProperties(scope.content); 63 | for (var property of properties) { 64 | property.parent = struct; 65 | struct.properties.push(property); 66 | } 67 | 68 | var methods = this.methodParser.parseMethods(scope.content, struct); 69 | for (var method of methods) { 70 | method.parent = struct; 71 | struct.methods.push(method); 72 | } 73 | 74 | structs.push(struct); 75 | } catch(ex) { 76 | console.error("Skipping struct due to parsing error.", statement, ex); 77 | debugger; 78 | } 79 | } 80 | } 81 | } 82 | 83 | return structs; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/PropertyParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpProperty, 3 | CSharpPropertyComponent, 4 | CSharpType 5 | } from './Models'; 6 | 7 | import { ScopeHelper } from './ScopeHelper'; 8 | import { RegExHelper } from './RegExHelper'; 9 | import { TypeParser } from './TypeParser'; 10 | import { AttributeParser } from './AttributeParser'; 11 | 12 | export class PropertyParser { 13 | private scopeHelper = new ScopeHelper(); 14 | private regexHelper = new RegExHelper(); 15 | 16 | private typeParser = new TypeParser(); 17 | private attributeParser = new AttributeParser(); 18 | 19 | constructor() { 20 | 21 | } 22 | 23 | parseProperties(content: string) { 24 | var properties = new Array(); 25 | var scopes = this.scopeHelper.getCurlyScopes(content); 26 | 27 | for (var scope of scopes) { 28 | var statements = this.scopeHelper.getStatements(scope.prefix); 29 | for(var statement of statements) { 30 | if(statement.indexOf('=>') > -1) 31 | statement = statement.substr(0, statement.indexOf('=>') + 2); 32 | 33 | var matches = this.regexHelper.getMatches( 34 | statement, 35 | new RegExp("^" + this.regexHelper.getPropertyRegex(false, true, true, true, true, true) + "$", "g")); 36 | for (var match of matches) { 37 | try { 38 | var attributes = match[0]; 39 | var modifiers = match[1] || ""; 40 | var type = match[2]; 41 | var name = match[3]; 42 | var openingType = match[4]; 43 | 44 | var property = new CSharpProperty(name); 45 | property.attributes = this.attributeParser.parseAttributes(attributes); 46 | property.type = this.typeParser.parseType(type); 47 | 48 | property.isVirtual = modifiers.indexOf("virtual") > -1; 49 | property.isPublic = modifiers.indexOf("public") > -1; 50 | property.isStatic = modifiers.indexOf("static") > -1; 51 | 52 | if(openingType === "{") { 53 | var initialValueMatches = this.regexHelper.getMatches( 54 | scope.suffix, 55 | new RegExp("^" + this.regexHelper.getPropertyInitialValueRegex(true), "g")); 56 | if(initialValueMatches.length > 0) { 57 | property.initialValue = initialValueMatches[0][0]; 58 | } 59 | 60 | var subScopes = this.scopeHelper.getCurlyScopes(scope.content); 61 | for (var subScope of subScopes) { 62 | var subStatements = this.scopeHelper.getStatements(subScope.prefix); 63 | for(var subStatement of subStatements) { 64 | var componentTypeMatches = this.regexHelper.getMatches( 65 | subStatement, 66 | /^(get|set)\s*[{;]$/g); 67 | 68 | //Added case for properties with lambda like get => some methods.. 69 | if (componentTypeMatches.length === 0){ 70 | componentTypeMatches = this.regexHelper.getMatches( 71 | subStatement, 72 | /^(get|set)\s*[=>]+/g); 73 | } 74 | for (var componentTypeMatch of componentTypeMatches) { 75 | var component = new CSharpPropertyComponent(); 76 | component.type = <"get"|"set">componentTypeMatch[0]; 77 | 78 | property.components.push(component); 79 | } 80 | } 81 | } 82 | } else if(openingType === "=>") { 83 | var component = new CSharpPropertyComponent(); 84 | component.type = "get"; 85 | 86 | property.components.push(component); 87 | } 88 | 89 | if(property.components.length === 0 || property.components.length > 2) 90 | continue; 91 | 92 | properties.push(property); 93 | } catch(ex) { 94 | console.error("Skipping property due to parsing error.", statement, ex); 95 | debugger; 96 | } 97 | } 98 | } 99 | } 100 | 101 | return properties; 102 | } 103 | } -------------------------------------------------------------------------------- /src/TypeParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpType 3 | } from './Models'; 4 | 5 | import { ScopeHelper } from './ScopeHelper'; 6 | import { RegExHelper } from './RegExHelper'; 7 | import { NamespaceParser } from './NamespaceParser'; 8 | 9 | export class TypeParser { 10 | private scopeHelper = new ScopeHelper(); 11 | private regexHelper = new RegExHelper(); 12 | 13 | constructor() { 14 | 15 | } 16 | 17 | private getTypeNameFromGenericScopePrefix(prefix: string) { 18 | if (!prefix) 19 | return null; 20 | 21 | var result = prefix.trim(); 22 | if (result.lastIndexOf("<") > -1) { 23 | result = result.substr(0, result.length - 1); 24 | } 25 | 26 | result = result.trim(); 27 | if (result.indexOf(",") == 0) { 28 | result = result 29 | .substr(1) 30 | .trim(); 31 | } 32 | 33 | return result; 34 | } 35 | 36 | private prepareTypeForGenericParameters(type: CSharpType, content: string) { 37 | if (!content) 38 | return; 39 | 40 | type.genericParameters = this.parseTypesFromGenericParameters(content); 41 | if (type.isGeneric) { 42 | type.name += "<"; 43 | for (var i = 1; i < type.genericParameters.length; i++) { 44 | type.name += ","; 45 | } 46 | type.name += ">"; 47 | } 48 | } 49 | 50 | parseTypesFromGenericParameters(content: string): CSharpType[] { 51 | var result = new Array(); 52 | if (!content) 53 | return result; 54 | 55 | var typeRegions = this.scopeHelper.getScopedList(",", content); 56 | for (var typeRegion of typeRegions) { 57 | var scope = this.scopeHelper.getGenericTypeScopes(typeRegion).pop(); 58 | 59 | var type = new CSharpType(this.getTypeNameFromGenericScopePrefix(scope.prefix)); 60 | var arrowTrimmedName = type.name 61 | .replace(//g, "") 63 | .trim(); 64 | if (!arrowTrimmedName) 65 | continue; 66 | 67 | if(scope.content) { 68 | this.prepareTypeForGenericParameters( 69 | type, 70 | scope.content); 71 | } 72 | 73 | result.push(type); 74 | } 75 | 76 | return result; 77 | } 78 | 79 | parseType(typeString: string): CSharpType { 80 | if(!typeString) 81 | return null; 82 | 83 | const regex = this.regexHelper.getGenericTypeNameRegex(false, true, true, true, true); 84 | var matches = this.regexHelper.getMatches( 85 | typeString, 86 | new RegExp("^" + regex + "$", "g")); 87 | 88 | var match = matches[0]; 89 | if (!match) 90 | return null; 91 | 92 | var name = match[0]; 93 | var genericParameters = match[1]; 94 | var tupleContent = match[2]; 95 | var suffix = match[3]; 96 | 97 | if(tupleContent) { 98 | name = "System.ValueTuple"; 99 | genericParameters = this.prepareGenericParametersStringFromTupleContent(tupleContent); 100 | } 101 | 102 | var isNullable = suffix === "?"; 103 | var isArray = suffix === "[]"; 104 | 105 | if(isArray) { 106 | genericParameters = name + (genericParameters ? "<" + genericParameters + ">" : ""); 107 | name = "System.Array"; 108 | } 109 | 110 | var subNames = name.split("."); 111 | 112 | var type = new CSharpType(subNames[subNames.length-1]); 113 | type.isNullable = isNullable; 114 | type.namespace = NamespaceParser 115 | .parseNamespaceFromName(subNames 116 | .slice(0, subNames.length-1) 117 | .join(".")); 118 | 119 | this.prepareTypeForGenericParameters( 120 | type, 121 | genericParameters); 122 | 123 | return type; 124 | } 125 | 126 | private prepareGenericParametersStringFromTupleContent(content: string) { 127 | var scopes = this.scopeHelper.getScopedList(",", content); 128 | return scopes 129 | .map(x => { 130 | var regions = this.scopeHelper 131 | .getScopedList(" ", x) 132 | .filter(x => !!x); 133 | return regions[0]; 134 | }) 135 | .join(", "); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/MethodParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpMethod, 3 | CSharpClass, 4 | CSharpType, 5 | CSharpMethodParameter, 6 | CSharpToken, 7 | CSharpNamedToken, 8 | CSharpStruct, 9 | CSharpInterface 10 | } from './Models'; 11 | 12 | import { ScopeHelper } from './ScopeHelper'; 13 | import { RegExHelper } from './RegExHelper'; 14 | import { TypeParser } from './TypeParser'; 15 | import { AttributeParser } from './AttributeParser'; 16 | import { LiteralParser } from './LiteralParser'; 17 | 18 | export class MethodParser { 19 | private scopeHelper = new ScopeHelper(); 20 | private regexHelper = new RegExHelper(); 21 | 22 | private attributeParser = new AttributeParser(); 23 | private literalParser = new LiteralParser(); 24 | 25 | constructor( 26 | private typeParser: TypeParser) { 27 | 28 | } 29 | 30 | parseMethods(content: string, parent: CSharpClass | CSharpInterface | CSharpMethod | CSharpStruct) { 31 | var methods = new Array(); 32 | var scopes = this.scopeHelper.getCurlyScopes(content); 33 | for (var scope of scopes) { 34 | var statements = this.scopeHelper.getStatements(scope.prefix); 35 | for(var statement of statements) { 36 | var matches = this.regexHelper.getMatches( 37 | statement, 38 | new RegExp("^" + this.regexHelper.getMethodRegex(false, true, true, true, true, true, true, true) + "$", "g")); 39 | for (var match of matches) { 40 | try { 41 | var attributes = match[0]; 42 | var modifiers = match[1] || ""; 43 | var returnType = match[2]; 44 | var name = match[3]; 45 | var genericParameters = match[4]; 46 | var parameters = match[5]; 47 | var openingType = match[6]; 48 | 49 | var catchNoReturnType = this.regexHelper.getMatches(returnType, new RegExp("^" + this.regexHelper.getModifierRegex(true) + "$", "g")); 50 | if (catchNoReturnType.length > 0 && catchNoReturnType[0].length > 0) { 51 | modifiers += (modifiers ? " " : "") + catchNoReturnType[0][0] 52 | returnType = ""; 53 | } 54 | 55 | var method = new CSharpMethod(name); 56 | method.attributes = this.attributeParser.parseAttributes(attributes); 57 | method.genericParameters = this.typeParser.parseTypesFromGenericParameters(genericParameters); 58 | method.returnType = this.typeParser.parseType(returnType); 59 | method.parameters = this.parseMethodParameters(parameters); 60 | 61 | method.innerScopeText = scope.content; 62 | method.parent = parent; 63 | 64 | if (parent instanceof CSharpClass && parent.name === method.name) { 65 | method.isConstructor = true; 66 | method.isVirtual = false; 67 | } else { 68 | method.isVirtual = modifiers.indexOf("virtual") > -1; 69 | method.isConstructor = false; 70 | } 71 | 72 | method.isPublic = modifiers.indexOf("public") > -1; 73 | method.isStatic = modifiers.indexOf("static") > -1; 74 | method.isBodyless = openingType === ";"; 75 | 76 | methods.push(method); 77 | } catch(ex) { 78 | console.error("Skipping method due to parsing error.", statement, ex); 79 | debugger; 80 | } 81 | } 82 | } 83 | } 84 | 85 | return methods; 86 | } 87 | 88 | parseMethodParameters(content: string): CSharpMethodParameter[] { 89 | var result = new Array(); 90 | 91 | var attributeSplits = this.scopeHelper.getScopedList(",", content); 92 | for(var attributeSplit of attributeSplits) { 93 | var matches = this.regexHelper.getMatches( 94 | attributeSplit, 95 | new RegExp("^" + this.regexHelper.getMethodParameterRegex(false, true, true, true, true, true) + "$", "g")); 96 | if(matches.length > 1) { 97 | throw new Error("Method parameter split failed."); 98 | } 99 | 100 | try { 101 | result.push(this.parseMethodParameter(matches[0])); 102 | } catch(ex) { 103 | console.error("Skipping method parameter due to parsing error.", matches[0], ex); 104 | debugger; 105 | } 106 | } 107 | 108 | return result; 109 | } 110 | 111 | private parseMethodParameter(match: string[]) { 112 | return { 113 | type: this.typeParser.parseType(match[2]), 114 | name: match[3], 115 | isVariadicContainer: !!match[1], 116 | attributes: this.attributeParser.parseAttributes(match[0]), 117 | defaultValue: this.literalParser.parseLiteral(match[4]) 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/NamespaceParser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CSharpNamespace 3 | } from './Models'; 4 | 5 | import { ScopeHelper } from './ScopeHelper'; 6 | import { RegExHelper } from './RegExHelper'; 7 | import { UsingsParser } from './UsingsParser'; 8 | import { ClassParser } from './ClassParser'; 9 | import { InterfaceParser } from './InterfaceParser'; 10 | import { EnumParser } from './EnumParser'; 11 | import { StructParser } from './StructParser'; 12 | 13 | export class NamespaceParser { 14 | private scopeHelper = new ScopeHelper(); 15 | private regexHelper = new RegExHelper(); 16 | private usingsParser = new UsingsParser(); 17 | 18 | constructor( 19 | private classParser: ClassParser, 20 | private interfaceParser: InterfaceParser, 21 | private enumParser: EnumParser, 22 | private structParser: StructParser) { 23 | 24 | } 25 | 26 | parseNamespacesFromCode(content: string) { 27 | var namespaces = new Array(); 28 | var scopes = this.scopeHelper.getCurlyScopes(content); 29 | for (var scope of scopes) { 30 | var statements = this.scopeHelper.getStatements(scope.prefix); 31 | for(var statement of statements) { 32 | var matches = this.regexHelper.getMatches( 33 | statement, 34 | new RegExp(this.regexHelper.getNamespaceRegex(false, true), "g")); 35 | for (var match of matches) { 36 | try { 37 | var name = match[0]; 38 | var namespacesFromName = NamespaceParser.parseNamespacesFromName(name); 39 | 40 | var namespace = namespacesFromName[namespacesFromName.length-1]; 41 | namespace.innerScopeText = scope.content; 42 | 43 | var enums = this.enumParser.parseEnums(scope.content); 44 | for (var enumObject of enums) { 45 | enumObject.parent = namespace; 46 | namespace.enums.push(enumObject); 47 | } 48 | 49 | var classes = this.classParser.parseClasses(scope.content); 50 | for (var classObject of classes) { 51 | classObject.parent = namespace; 52 | namespace.classes.push(classObject); 53 | } 54 | 55 | var structs = this.structParser.parseStructs(scope.content); 56 | for (var struct of structs) { 57 | struct.parent = namespace; 58 | namespace.structs.push(struct); 59 | } 60 | 61 | var usings = this.usingsParser.parseUsings(scope.content); 62 | for (var using of usings) { 63 | using.parent = namespace; 64 | namespace.usings.push(using); 65 | } 66 | 67 | var subNamespaces = this.parseNamespacesFromCode(scope.content); 68 | for (let subNamespace of subNamespaces) { 69 | subNamespace.parent = namespace; 70 | namespace.namespaces.push(subNamespace); 71 | } 72 | 73 | var interfaces = this.interfaceParser.parseInterfaces(scope.content); 74 | for (var interfaceObject of interfaces) { 75 | namespace.interfaces.push(interfaceObject); 76 | } 77 | 78 | namespaces.push(namespacesFromName[0]); 79 | } catch(ex) { 80 | console.error("Skipping namespace due to parsing error.", statement, ex); 81 | debugger; 82 | } 83 | } 84 | } 85 | } 86 | 87 | return namespaces; 88 | } 89 | 90 | static parseNamespaceFromName(name: string) { 91 | return name ? this.parseNamespacesFromName(name)[0] : null; 92 | } 93 | 94 | static parseNamespacesFromName(name: string) { 95 | var namespaces = new Array(); 96 | 97 | var previousNamespace: CSharpNamespace = null; 98 | var subNames = name.split("."); 99 | 100 | for(var i=0;i(); 38 | var scopes = this.scopeHelper.getCurlyScopes(content); 39 | for (var scope of scopes) { 40 | var statements = this.scopeHelper.getStatements(scope.prefix); 41 | for(var statement of statements) { 42 | var matches = this.regexHelper.getMatches( 43 | statement, 44 | new RegExp("^" + this.regexHelper.getClassRegex() + "$", "g")); 45 | 46 | for (var match of matches) { 47 | try { 48 | var attributes = match[0]; 49 | var modifiers = match[1] || ""; 50 | var name = match[2]; 51 | var genericParameters = match[3]; 52 | var inheritance = match[4]; 53 | 54 | var classObject = new CSharpClass(name); 55 | classObject.isPublic = modifiers.indexOf("public") > -1; 56 | classObject.isStatic = modifiers.indexOf("static") > -1; 57 | classObject.attributes = this.attributeParser.parseAttributes(attributes); 58 | classObject.innerScopeText = scope.content; 59 | classObject.genericParameters = this.typeParser.parseTypesFromGenericParameters(genericParameters); 60 | classObject.inheritsFrom = this.typeParser.parseTypesFromGenericParameters(inheritance); 61 | 62 | var fields = this.fieldParser.parseFields(scope.content); 63 | for (var field of fields) { 64 | field.parent = classObject; 65 | classObject.fields.push(field); 66 | } 67 | 68 | var properties = this.propertyParser.parseProperties(scope.content); 69 | for (var property of properties) { 70 | property.parent = classObject; 71 | classObject.properties.push(property); 72 | } 73 | 74 | var enums = this.enumParser.parseEnums(scope.content); 75 | for (var enumObject of enums) { 76 | enumObject.parent = classObject; 77 | classObject.enums.push(enumObject); 78 | } 79 | 80 | var methods = this.methodParser.parseMethods(scope.content, classObject); 81 | for (var method of methods) { 82 | method.parent = classObject; 83 | classObject.methods.push(method); 84 | } 85 | 86 | var subClasses = this.parseClasses(scope.content); 87 | for (var subClass of subClasses) { 88 | subClass.parent = classObject; 89 | classObject.classes.push(subClass); 90 | } 91 | 92 | var interfaces = this.interfaceParser.parseInterfaces(scope.content); 93 | for (var interfaceObject of interfaces) { 94 | classObject.interfaces.push(interfaceObject); 95 | } 96 | 97 | classObject.constructors = classObject 98 | .methods 99 | .filter(x => x.isConstructor); 100 | 101 | classObject.methods = classObject 102 | .methods 103 | .filter(x => !x.isConstructor); 104 | 105 | classes.push(classObject); 106 | } catch(ex) { 107 | console.error("Skipping class due to parsing error.", statement, ex); 108 | debugger; 109 | } 110 | } 111 | } 112 | } 113 | 114 | return classes; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | 254 | dist/ -------------------------------------------------------------------------------- /src/ScopeHelper.ts: -------------------------------------------------------------------------------- 1 | export interface Scope { 2 | prefix: string; 3 | content: string; 4 | suffix: string; 5 | offset: number; 6 | length: number; 7 | } 8 | 9 | export class ScopeHelper { 10 | getStatements(content: string) { 11 | return this.getScopedList(";", content, true); 12 | } 13 | 14 | getScopedList(separator: string, content: string, includeSeparatorInSplits: boolean = false) { 15 | var scopes = [ 16 | ["<", ">"], 17 | ["[", "]"], 18 | ["(", ")"], 19 | ["{", "}"] 20 | ]; 21 | 22 | var isEntryScope = (item: string) => !!scopes.filter(x => x[0] === item)[0]; 23 | var isExitScope = (item: string) => !!scopes.filter(x => x[1] === item)[0]; 24 | 25 | var scope = 0; 26 | var totalStringSoFar = ""; 27 | var deepScopeStringSoFar = ""; 28 | var splits = new Array(); 29 | 30 | var pushNewSplit = () => { 31 | totalStringSoFar = totalStringSoFar.trim(); 32 | if(!totalStringSoFar) 33 | return; 34 | 35 | splits.push(totalStringSoFar); 36 | totalStringSoFar = ""; 37 | }; 38 | 39 | this.enumerateRelevantCodeCharacterRegions(content, (stringSoFar, character) => { 40 | if(isEntryScope(character)) { 41 | scope++; 42 | } else if(isExitScope(character) && scope > 0) { 43 | scope--; 44 | } 45 | 46 | if(scope === 0 && (character === separator || separator === "")) { 47 | if(separator === "" || includeSeparatorInSplits) 48 | totalStringSoFar += character; 49 | 50 | pushNewSplit(); 51 | } else { 52 | totalStringSoFar += character; 53 | } 54 | }); 55 | 56 | if(totalStringSoFar) 57 | pushNewSplit(); 58 | 59 | return splits; 60 | } 61 | 62 | getCurlyScopes(content: string) { 63 | return this.getScopes(content, "{", "}"); 64 | } 65 | 66 | getGenericTypeScopes(content: string) { 67 | var scopes = this.getScopes(content, "<", ">"); 68 | return scopes; 69 | } 70 | 71 | enumerateRelevantCodeCharacterRegions(content: string, enumerator?: (stringSoFar: string, character: string) => void) { 72 | var insideString = false; 73 | var stringEntry = ""; 74 | var insideStringEscapeCharacter = false; 75 | 76 | var insideSingleLineComment = false; 77 | var multiLineCommentScope = 0; 78 | var isEnteringCommentScope = false; 79 | 80 | var totalStringSoFar = ""; 81 | var stringSoFar = ""; 82 | 83 | for (var character of content) { 84 | totalStringSoFar += character; 85 | 86 | var insideComment = () => insideSingleLineComment || multiLineCommentScope > 0; 87 | if (insideComment()) { 88 | if (insideSingleLineComment && character === "\n") { 89 | insideSingleLineComment = false; 90 | } else if (multiLineCommentScope > 0 && this.stringEndsWith(totalStringSoFar, "*/")) { 91 | multiLineCommentScope--; 92 | } 93 | } 94 | 95 | if (!insideString) { 96 | if (this.stringEndsWith(totalStringSoFar, "//")) { 97 | insideSingleLineComment = true; 98 | } else if (this.stringEndsWith(totalStringSoFar, "/*")) { 99 | multiLineCommentScope++; 100 | } 101 | } 102 | 103 | if (insideComment()) { 104 | isEnteringCommentScope = false; 105 | continue; 106 | } 107 | 108 | if (!insideString && character === "/") { 109 | isEnteringCommentScope = true; 110 | continue; 111 | } 112 | 113 | stringSoFar += character; 114 | 115 | if (insideString && character === '\\') { 116 | insideStringEscapeCharacter = true; 117 | } else if (insideString) 118 | insideStringEscapeCharacter = false; 119 | 120 | var isEnteringString = (character === '"' || character === "'") && !insideString; 121 | var isExitingString = insideString && character === stringEntry; 122 | if (!insideStringEscapeCharacter && (isEnteringString || isExitingString)) { 123 | insideString = !insideString; 124 | stringEntry = character; 125 | } 126 | 127 | if (enumerator) { 128 | enumerator(stringSoFar, character); 129 | } 130 | 131 | isEnteringCommentScope = false; 132 | } 133 | 134 | return stringSoFar; 135 | } 136 | 137 | private getScopes(content: string, entry: string, exit: string): Scope[] { 138 | var scopes = new Array(); 139 | if (!content) 140 | return scopes; 141 | 142 | var results = ['', '', '']; 143 | 144 | var scope = 0; 145 | var area = 0; 146 | 147 | var pushScope = () => { 148 | var lastScope = scopes[scopes.length - 1]; 149 | var lastOffset = lastScope ? lastScope.offset : 0; 150 | var offset = content.indexOf(entry, lastOffset); 151 | 152 | var scopeObject = { 153 | prefix: results[0].substring(0, results[0].length - (results[1] === "" ? 0 : (entry.length - 1))), 154 | content: results[1], 155 | suffix: results[2], 156 | offset: offset, 157 | length: entry.length + results[1].length + exit.length 158 | }; 159 | 160 | scopeObject.prefix = scopeObject.prefix.trim(); 161 | scopeObject.content = scopeObject.content.trim(); 162 | scopeObject.suffix = scopeObject.suffix.trim(); 163 | 164 | if(scopeObject.prefix.startsWith(exit)) 165 | scopeObject.prefix = scopeObject.prefix.substr(exit.length).trim(); 166 | 167 | if(scopeObject.suffix.endsWith(entry)) 168 | scopeObject.suffix = scopeObject.suffix.substr(0, scopeObject.suffix.length - entry.length).trim(); 169 | 170 | if(scopeObject.suffix || scopeObject.content || scopeObject.prefix) 171 | scopes.push(scopeObject); 172 | 173 | results[0] = results[2] || ''; 174 | results[1] = ''; 175 | results[2] = ''; 176 | }; 177 | 178 | var popCharacters = (count: number) => { 179 | for (var i = 0; i < count; i++) { 180 | results[area] = results[area].substr(0, results[area].length - 1); 181 | } 182 | }; 183 | 184 | var pushCharacter = (character: string) => { 185 | results[area] += character; 186 | }; 187 | 188 | this.enumerateRelevantCodeCharacterRegions(content, (stringSoFar, character) => { 189 | if (this.stringEndsWith(stringSoFar, exit)) { 190 | scope--; 191 | if (scope === 0) 192 | area = 2; 193 | } 194 | 195 | pushCharacter(character); 196 | 197 | if (this.stringEndsWith(stringSoFar, entry)) { 198 | scope++; 199 | if (scope === 1 && area === 2) { 200 | pushScope(); 201 | } 202 | if (scope === 1) { 203 | popCharacters(entry.length - 1); 204 | area = 1; 205 | } 206 | } 207 | }); 208 | 209 | pushScope(); 210 | if (results[0]) 211 | pushScope(); 212 | 213 | return scopes; 214 | } 215 | 216 | private stringEndsWith(content: string, search: string) { 217 | return content.substr(content.length - search.length) === search; 218 | } 219 | } -------------------------------------------------------------------------------- /src/Models.ts: -------------------------------------------------------------------------------- 1 | export class CSharpType implements CSharpGenericParameterContainer { 2 | name: string; 3 | namespace: CSharpNamespace; 4 | isNullable: boolean; 5 | 6 | genericParameters: CSharpType[]; 7 | 8 | constructor(name: string) { 9 | this.name = name; 10 | this.genericParameters = []; 11 | } 12 | 13 | get isGeneric() { 14 | return this.genericParameters.length > 0; 15 | } 16 | 17 | get fullName() { 18 | var name = this.name; 19 | if (this.namespace && this.namespace.fullName) { 20 | name = this.namespace.fullName + "." + name; 21 | } 22 | return name; 23 | } 24 | } 25 | 26 | export interface CSharpUsing { 27 | alias: string; 28 | namespace: CSharpNamespace; 29 | parent?: CSharpNamespace | CSharpFile; 30 | } 31 | 32 | export interface CSharpInterfaceTypeDeclarationScope extends CSharpScope { 33 | name: string; 34 | properties: CSharpProperty[]; 35 | methods: CSharpMethod[]; 36 | } 37 | 38 | export interface CSharpImplementationTypeDeclarationScope extends CSharpScope { 39 | classes: CSharpClass[]; 40 | interfaces: CSharpInterface[]; 41 | enums: CSharpEnum[]; 42 | name: string; 43 | } 44 | 45 | export interface CSharpScope { 46 | innerScopeText: string; 47 | } 48 | 49 | export interface CSharpGenericParameterContainer { 50 | genericParameters: CSharpType[]; 51 | 52 | isGeneric: boolean; 53 | } 54 | 55 | export class CSharpNamespace implements CSharpImplementationTypeDeclarationScope { 56 | name: string; 57 | innerScopeText: string; 58 | 59 | parent: CSharpNamespace | CSharpFile; 60 | 61 | classes: CSharpClass[]; 62 | interfaces: CSharpInterface[]; 63 | structs: CSharpStruct[]; 64 | enums: CSharpEnum[]; 65 | 66 | usings: CSharpUsing[]; 67 | namespaces: CSharpNamespace[]; 68 | 69 | constructor(name: string) { 70 | this.name = name; 71 | 72 | this.classes = []; 73 | this.enums = []; 74 | this.usings = []; 75 | this.namespaces = []; 76 | this.structs = []; 77 | this.interfaces = []; 78 | } 79 | 80 | get fullName() { 81 | var name = this.name; 82 | if (this.parent && this.parent.fullName) { 83 | name = this.parent.fullName + "." + name; 84 | } 85 | return name; 86 | } 87 | 88 | getAllClassesRecursively() { 89 | var classes = new Array(); 90 | for(var classObject of this.classes) { 91 | classes.push(classObject); 92 | classes = classes.concat(...classObject.getAllClassesRecursively()); 93 | } 94 | for(var namespace of this.namespaces) { 95 | classes = classes.concat(...namespace.getAllClassesRecursively()); 96 | } 97 | return classes; 98 | } 99 | } 100 | 101 | export class CSharpFile implements CSharpImplementationTypeDeclarationScope { 102 | innerScopeText: string; 103 | name: string; 104 | fullName: string; 105 | 106 | classes: CSharpClass[]; 107 | interfaces: CSharpInterface[]; 108 | structs: CSharpStruct[]; 109 | enums: CSharpEnum[]; 110 | 111 | usings: CSharpUsing[]; 112 | namespaces: CSharpNamespace[]; 113 | parent: CSharpNamespace; 114 | 115 | constructor() { 116 | this.usings = []; 117 | this.namespaces = []; 118 | this.classes = []; 119 | this.enums = []; 120 | this.structs = []; 121 | this.interfaces = []; 122 | } 123 | 124 | getAllClassesRecursively() { 125 | var classes = new Array(); 126 | for(var classObject of this.classes) { 127 | classes.push(classObject); 128 | classes = classes.concat(...classObject.getAllClassesRecursively()); 129 | } 130 | for(var namespace of this.namespaces) { 131 | classes = classes.concat(...namespace.getAllClassesRecursively()); 132 | } 133 | return classes; 134 | } 135 | } 136 | 137 | export class CSharpMethod implements CSharpScope, CSharpGenericParameterContainer { 138 | name: string; 139 | innerScopeText: string; 140 | 141 | isConstructor: boolean; 142 | isStatic: boolean; 143 | isVirtual: boolean; 144 | isBodyless: boolean; 145 | 146 | parent: CSharpClass | CSharpInterface | CSharpMethod | CSharpStruct; 147 | returnType: CSharpType; 148 | 149 | genericParameters: CSharpType[]; 150 | parameters: CSharpMethodParameter[]; 151 | attributes: CSharpAttribute[]; 152 | 153 | private _isPublic: boolean; 154 | 155 | constructor(name: string) { 156 | this.name = name; 157 | 158 | this.parameters = []; 159 | this.attributes = []; 160 | this.genericParameters = []; 161 | } 162 | 163 | get isGeneric() { 164 | return this.genericParameters.length > 0; 165 | } 166 | 167 | public get isPublic() { 168 | return this._isPublic || this.parent instanceof CSharpInterface; 169 | } 170 | 171 | public set isPublic(isPublic: boolean) { 172 | this._isPublic = isPublic; 173 | } 174 | } 175 | 176 | export type CSharpToken = boolean | number | string | CSharpNamedToken; 177 | 178 | export class CSharpNamedToken { 179 | name: string; 180 | } 181 | 182 | export class CSharpMethodParameter { 183 | name: string; 184 | type: CSharpType; 185 | defaultValue: CSharpToken; 186 | 187 | isVariadicContainer: boolean; 188 | 189 | attributes: CSharpAttribute[]; 190 | 191 | constructor(name: string) { 192 | this.name = name; 193 | 194 | this.attributes = []; 195 | } 196 | } 197 | 198 | export class CSharpStruct implements CSharpScope, CSharpGenericParameterContainer { 199 | properties: CSharpProperty[]; 200 | methods: CSharpMethod[]; 201 | fields: CSharpField[]; 202 | 203 | parent: CSharpClass | CSharpNamespace | CSharpFile; 204 | 205 | innerScopeText: string; 206 | name: string; 207 | 208 | attributes: CSharpAttribute[]; 209 | genericParameters: CSharpType[]; 210 | 211 | private _isPublic: boolean; 212 | 213 | constructor(name: string) { 214 | this.name = name; 215 | 216 | this.methods = []; 217 | this.properties = []; 218 | this.fields = []; 219 | this.attributes = []; 220 | this.genericParameters = []; 221 | } 222 | 223 | get isGeneric() { 224 | return this.genericParameters.length > 0; 225 | } 226 | 227 | get isPublic() { 228 | if(this.parent instanceof CSharpClass) { 229 | return this._isPublic && this.parent.isPublic; 230 | } 231 | 232 | return true; 233 | } 234 | 235 | set isPublic(isPublic: boolean) { 236 | this._isPublic = isPublic; 237 | } 238 | 239 | get fullName() { 240 | var name = this.name; 241 | if (this.parent && this.parent.fullName) { 242 | name = this.parent.fullName + "." + name; 243 | } 244 | return name; 245 | } 246 | } 247 | 248 | export class CSharpInterface implements CSharpInterfaceTypeDeclarationScope, CSharpGenericParameterContainer { 249 | methods: CSharpMethod[]; 250 | properties: CSharpProperty[]; 251 | 252 | implements: CSharpType[]; 253 | parent: CSharpClass | CSharpNamespace | CSharpFile; 254 | 255 | innerScopeText: string; 256 | name: string; 257 | 258 | genericParameters: CSharpType[]; 259 | attributes: CSharpAttribute[]; 260 | 261 | private _isPublic: boolean; 262 | 263 | constructor(name: string) { 264 | this.name = name; 265 | 266 | this.methods = []; 267 | this.properties = []; 268 | this.attributes = []; 269 | this.implements = []; 270 | this.genericParameters = []; 271 | } 272 | 273 | get isGeneric() { 274 | return this.genericParameters.length > 0; 275 | } 276 | 277 | get isPublic() { 278 | if(this.parent instanceof CSharpClass) { 279 | return this._isPublic && this.parent.isPublic; 280 | } 281 | 282 | return true; 283 | } 284 | 285 | set isPublic(isPublic: boolean) { 286 | this._isPublic = isPublic; 287 | } 288 | 289 | get fullName() { 290 | var name = this.name; 291 | if (this.parent && this.parent.fullName) { 292 | name = this.parent.fullName + "." + name; 293 | } 294 | return name; 295 | } 296 | } 297 | 298 | export class CSharpClass implements CSharpImplementationTypeDeclarationScope, CSharpGenericParameterContainer { 299 | constructors: CSharpMethod[]; 300 | interfaces: CSharpInterface[]; 301 | methods: CSharpMethod[]; 302 | classes: CSharpClass[]; 303 | enums: CSharpEnum[]; 304 | properties: CSharpProperty[]; 305 | fields: CSharpField[]; 306 | structs: CSharpStruct[]; 307 | 308 | inheritsFrom: CSharpType[]; 309 | parent: CSharpClass | CSharpNamespace | CSharpFile; 310 | 311 | isStatic: boolean; 312 | 313 | innerScopeText: string; 314 | name: string; 315 | 316 | genericParameters: CSharpType[]; 317 | attributes: CSharpAttribute[]; 318 | 319 | private _isPublic: boolean; 320 | 321 | constructor(name: string) { 322 | this.name = name; 323 | 324 | this.constructors = []; 325 | this.methods = []; 326 | this.classes = []; 327 | this.enums = []; 328 | this.properties = []; 329 | this.fields = []; 330 | this.structs = []; 331 | this.interfaces = []; 332 | this.attributes = []; 333 | this.inheritsFrom = []; 334 | this.genericParameters = []; 335 | } 336 | 337 | get isGeneric() { 338 | return this.genericParameters.length > 0; 339 | } 340 | 341 | get isPublic() { 342 | if(this.parent instanceof CSharpClass) { 343 | return this._isPublic && this.parent.isPublic; 344 | } 345 | 346 | return true; 347 | } 348 | 349 | set isPublic(isPublic: boolean) { 350 | this._isPublic = isPublic; 351 | } 352 | 353 | get fullName() { 354 | var name = this.name; 355 | if (this.parent && this.parent.fullName) { 356 | name = this.parent.fullName + "." + name; 357 | } 358 | return name; 359 | } 360 | 361 | getAllClassesRecursively() { 362 | var classes = new Array(); 363 | for(var classObject of this.classes) { 364 | classes.push(classObject); 365 | classes = classes.concat(...classObject.getAllClassesRecursively()); 366 | } 367 | return classes; 368 | } 369 | } 370 | 371 | export class CSharpEnum implements CSharpScope { 372 | options: CSharpEnumOption[]; 373 | 374 | parent: CSharpNamespace | CSharpFile | CSharpClass; 375 | 376 | inheritsFrom: CSharpType; 377 | 378 | name: string; 379 | innerScopeText: string; 380 | 381 | attributes: CSharpAttribute[]; 382 | 383 | private _isPublic: boolean; 384 | 385 | constructor(name: string) { 386 | this.name = name; 387 | 388 | this.attributes = []; 389 | } 390 | 391 | get isPublic() { 392 | if(this.parent instanceof CSharpClass) { 393 | return this._isPublic && this.parent.isPublic; 394 | } 395 | 396 | return true; 397 | } 398 | 399 | set isPublic(isPublic: boolean) { 400 | this._isPublic = isPublic; 401 | } 402 | 403 | get fullName() { 404 | var name = this.name; 405 | if (this.parent && this.parent.fullName) { 406 | name = this.parent.fullName + "." + name; 407 | } 408 | return name; 409 | } 410 | } 411 | 412 | export class CSharpField { 413 | name: string; 414 | 415 | type: CSharpType; 416 | parent: CSharpClass | CSharpStruct; 417 | 418 | isPublic: boolean; 419 | isStatic: boolean; 420 | isReadOnly: boolean; 421 | 422 | attributes: CSharpAttribute[]; 423 | initialValue?: string; 424 | 425 | constructor(name: string) { 426 | this.name = name; 427 | 428 | this.attributes = []; 429 | } 430 | } 431 | 432 | export class CSharpPropertyComponent { 433 | type: 'set' | 'get'; 434 | } 435 | 436 | export class CSharpProperty { 437 | name: string; 438 | 439 | type: CSharpType; 440 | parent: CSharpClass | CSharpStruct | CSharpInterface; 441 | 442 | components: CSharpPropertyComponent[]; 443 | attributes: CSharpAttribute[]; 444 | 445 | isStatic: boolean; 446 | isVirtual: boolean; 447 | 448 | initialValue?: string; 449 | 450 | private _isPublic: boolean; 451 | 452 | constructor(name: string) { 453 | this.name = name; 454 | 455 | this.components = []; 456 | this.attributes = []; 457 | } 458 | 459 | get isReadOnly() { 460 | return !this.components.filter(c => c.type === 'set')[0]; 461 | } 462 | 463 | public get isPublic() { 464 | return this._isPublic || this.parent instanceof CSharpInterface; 465 | } 466 | 467 | public set isPublic(isPublic: boolean) { 468 | this._isPublic = isPublic; 469 | } 470 | } 471 | 472 | export class CSharpAttribute { 473 | name: string; 474 | parameters: CSharpAttributeParameter[]; 475 | 476 | constructor(name: string) { 477 | this.name = name; 478 | this.parameters = []; 479 | } 480 | } 481 | 482 | export class CSharpAttributeParameter { 483 | name?: string; 484 | value: CSharpToken; 485 | } 486 | 487 | export class CSharpEnumOption { 488 | name: string; 489 | value: number; 490 | 491 | attributes: CSharpAttribute[]; 492 | 493 | constructor(name: string) { 494 | this.name = name 495 | 496 | this.attributes = []; 497 | } 498 | } -------------------------------------------------------------------------------- /src/nearley/grammar.ne: -------------------------------------------------------------------------------- 1 | # based on https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-334.pdf 2 | 3 | # TODO: use underscore to match spaces in grammar 4 | 5 | @{% function rejecter(d, l, reject) { return reject; } %} 6 | @{% function joiner(d) { return d.join(''); } %} 7 | 8 | main -> 9 | input 10 | 11 | input -> 12 | input_section:? 13 | 14 | input_section -> 15 | input_section_part | 16 | input_section input_section_part 17 | 18 | input_section_part -> 19 | input_elements:? new_line 20 | pp_directive 21 | 22 | input_elements -> 23 | input_element 24 | input_elements input_element 25 | 26 | input_element -> 27 | whitespace 28 | comment 29 | token 30 | 31 | charriage_return_character -> 32 | "\u000D" 33 | 34 | line_feed_character -> 35 | "\u000A" 36 | 37 | next_line_character -> 38 | "\u0085" 39 | 40 | line_separator_character -> 41 | "\\u2028" 42 | # TODO: removing the double-slash here causes the unparser to crash. 43 | 44 | paragraph_separator_character -> 45 | "\\u2029" 46 | # TODO: removing the double-slash here causes the unparser to crash. 47 | 48 | new_line -> 49 | charriage_return_character | 50 | line_feed_character | 51 | charriage_return_character line_feed_character | 52 | next_line_character | 53 | line_separator_character | 54 | paragraph_separator_character 55 | 56 | comment -> 57 | single_line_comment | 58 | delimited_comment 59 | 60 | single_line_comment -> 61 | "//" input_characters:? 62 | 63 | input_characters -> 64 | input_character | 65 | input_characters input_character 66 | 67 | input_character -> 68 | new_line {% rejecter %} | 69 | unicode_character 70 | 71 | unicode_character -> 72 | [\u0000-\uFFFF] 73 | 74 | new_line_character -> 75 | charriage_return_character | 76 | line_feed_character | 77 | next_line_character | 78 | line_separator_character | 79 | paragraph_separator_character 80 | 81 | delimited_comment -> 82 | "/*" delimited_comment_text:? asterisks "/" 83 | 84 | delimited_comment_text -> 85 | delimited_comment_section | 86 | delimited_comment_text delimited_comment_section 87 | 88 | delimited_comment_section -> 89 | "/" | 90 | asterisks:? not_slash_or_asterisk 91 | 92 | asterisks -> 93 | "*" | 94 | asterisks "*" 95 | 96 | not_slash_or_asterisk -> 97 | "/" {% rejecter %} | 98 | "*" {% rejecter %} | 99 | unicode_character 100 | 101 | whitespace -> 102 | whitespace_character | 103 | whitespace whitespace_character 104 | 105 | whitespace_character -> 106 | [\p{Z}] | 107 | horizontal_tab_character | 108 | vertical_tab_character | 109 | form_feed_character 110 | 111 | horizontal_tab_character -> 112 | "\u0009" 113 | 114 | vertical_tab_character -> 115 | "\u000B" 116 | 117 | form_feed_character -> 118 | "\u000C" 119 | 120 | token -> 121 | identifier | 122 | keyword | 123 | integer_literal | 124 | real_literal | 125 | character_literal | 126 | string_literal | 127 | operator_or_punctuator 128 | 129 | unicode_escape_sequence -> 130 | "\\u" hex_digit hex_digit hex_digit hex_digit 131 | "\\U" hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit 132 | 133 | identifier -> 134 | available_identifier | 135 | "@" identifier_or_keyword 136 | 137 | available_identifier -> 138 | keyword {% rejecter %} | 139 | identifier_or_keyword 140 | 141 | identifier_or_keyword -> 142 | identifier_start_character identifier_part_characters:? 143 | 144 | identifier_start_character -> 145 | letter_character | 146 | underscore_character 147 | 148 | underscore_character -> 149 | "\u005F" 150 | # TODO: "A unicode-escape-sequence representing the character U+005F" 151 | 152 | identifier_part_characters -> 153 | identifier_part_character | 154 | identifier_part_characters identifier_part_character 155 | 156 | identifier_part_character -> 157 | letter_character | 158 | decimal_digit_character | 159 | connecting_character | 160 | combining_character | 161 | formatting_character 162 | 163 | letter_character -> 164 | [\p{Lu}] | 165 | [\p{Ll}] | 166 | [\p{Lt}] | 167 | [\p{Lm}] | 168 | [\p{Lo}] | 169 | [\p{Nl}] 170 | # TODO: "A unicode-escape-sequence representing a character of classes Lu, Ll, Lt, Lm, Lo, or Nl" 171 | 172 | combining_character -> 173 | [\p{Mn}] | 174 | [\p{Mc}] 175 | # TODO: "A unicode-escape-sequence representing a character of classes Mn or Mc" 176 | 177 | decimal_digit_character -> 178 | [\p{Nd}] 179 | # TODO: "A unicode-escape-sequence representing a character of the class Nd" 180 | 181 | connecting_character -> 182 | [\p{Pc}] 183 | # TODO: "A unicode-escape-sequence representing a character of the class Pc" 184 | 185 | formatting_character -> 186 | [\p{Cf}] 187 | # TODO: "A unicode-escape-sequence representing a character of the class Cf" 188 | 189 | keyword -> 190 | "abstract" | 191 | "as" | 192 | "base" | 193 | "bool" | 194 | "break" | 195 | "byte" | 196 | "case" | 197 | "catch" | 198 | "char" | 199 | "checked" | 200 | "class" | 201 | "const" | 202 | "continue" | 203 | "decimal" | 204 | "default" | 205 | "delegate" | 206 | "do" | 207 | "double" | 208 | "else" | 209 | "enum" | 210 | "event" | 211 | "explicit" | 212 | "extern" | 213 | "false" | 214 | "finally" | 215 | "fixed" | 216 | "float" | 217 | "for" | 218 | "foreach" | 219 | "goto" | 220 | "if" | 221 | "implicit" | 222 | "in" | 223 | "int" | 224 | "interface" | 225 | "internal" | 226 | "is" | 227 | "lock" | 228 | "long" | 229 | "namespace" | 230 | "new" | 231 | "null" | 232 | "object" | 233 | "operator" | 234 | "out" | 235 | "override" | 236 | "params" | 237 | "private" | 238 | "protected" | 239 | "public" | 240 | "readonly" | 241 | "ref" | 242 | "return" | 243 | "sbyte" | 244 | "sealed" | 245 | "short" | 246 | "sizeof" | 247 | "stackalloc" | 248 | "static" | 249 | "string" | 250 | "struct" | 251 | "switch" | 252 | "this" | 253 | "throw" | 254 | "true" | 255 | "try" | 256 | "typeof" | 257 | "uint" | 258 | "ulong" | 259 | "unchecked" | 260 | "unsafe" | 261 | "ushort" | 262 | "using" | 263 | "virtual" | 264 | "void" | 265 | "volatile" | 266 | "while" 267 | 268 | contextual_keyword -> 269 | "add" | 270 | "alias" | 271 | "ascending" | 272 | "async" | 273 | "await" | 274 | "by" | 275 | "descending" | 276 | "dynamic" | 277 | "equals" | 278 | "from" | 279 | "get" | 280 | "global" | 281 | "group" | 282 | "into" | 283 | "join" | 284 | "let" | 285 | "orderby" | 286 | "partial" | 287 | "remove" | 288 | "select" | 289 | "set" | 290 | "value" | 291 | "var" | 292 | "where" | 293 | "yield" 294 | 295 | literal -> 296 | boolean_literal | 297 | integer_literal | 298 | real_literal | 299 | character_literal | 300 | string_literal | 301 | null_literal 302 | 303 | boolean_literal -> 304 | "true" | 305 | "false" 306 | 307 | integer_literal -> 308 | decimal_integer_literal | 309 | hexadecimal_integer_literal 310 | 311 | decimal_integer_literal -> 312 | decimal_digits integer_type_suffix:? 313 | 314 | decimal_digits -> 315 | decimal_digit | 316 | decimal_digits decimal_digit 317 | 318 | decimal_digit -> 319 | "0" | 320 | "1" | 321 | "2" | 322 | "3" | 323 | "4" | 324 | "5" | 325 | "6" | 326 | "7" | 327 | "8" | 328 | "9" 329 | 330 | integer_type_suffix -> 331 | "U" | 332 | "u" | 333 | "L" | 334 | "l" | 335 | "UL" | 336 | "Ul" | 337 | "uL" | 338 | "ul" | 339 | "LU" | 340 | "Lu" | 341 | "lU" | 342 | "lu" 343 | 344 | hexadecimal_integer_literal -> 345 | "0x" hex_digits integer_type_suffix:? | 346 | "0X" hex_digits integer_type_suffix:? 347 | 348 | hex_digits -> 349 | hex_digit | 350 | hex_digits hex_digit 351 | 352 | hex_digit -> 353 | "0" | 354 | "1" | 355 | "2" | 356 | "3" | 357 | "4" | 358 | "5" | 359 | "6" | 360 | "7" | 361 | "8" | 362 | "9" | 363 | "A" | 364 | "B" | 365 | "C" | 366 | "D" | 367 | "E" | 368 | "F" | 369 | "a" | 370 | "b" | 371 | "c" | 372 | "d" | 373 | "e" | 374 | "f" 375 | 376 | real_literal -> 377 | decimal_digits "." decimal_digits exponent_part:? real_type_suffix:? | 378 | "." decimal_digits exponent_part:? real_type_suffix:? | 379 | decimal_digits exponent_part real_type_suffix:? | 380 | decimal_digits real_type_suffix 381 | 382 | exponent_part -> 383 | "e" sign:? decimal_digits | 384 | "E" sign:? decimal_digits 385 | 386 | sign -> 387 | "+" | 388 | "-" 389 | 390 | real_type_suffix -> 391 | "F" | 392 | "f" | 393 | "D" | 394 | "d" | 395 | "M" | 396 | "m" 397 | 398 | character_literal -> 399 | "'" character "'" 400 | 401 | character -> 402 | single_character | 403 | simple_escape_sequence | 404 | hexadecimal_escape_sequence | 405 | unicode_escape_sequence 406 | 407 | single_character -> 408 | "\u0027" {% rejecter %} | 409 | "\u005C" {% rejecter %} | 410 | new_line_character {% rejecter %} | 411 | character 412 | 413 | simple_escape_sequence -> 414 | "\\'" | 415 | "\\\"" | 416 | "\\\\" | 417 | "\\0" | 418 | "\\a" | 419 | "\\b" | 420 | "\\f" | 421 | "\\n" | 422 | "\\r" | 423 | "\\t" | 424 | "\\v" 425 | 426 | hexadecimal_escape_sequence -> 427 | "\\x" hex_digit hex_digit:? hex_digit:? hex_digit:? 428 | 429 | string_literal -> 430 | regular_string_literal | 431 | verbatim_string_literal 432 | 433 | regular_string_literal -> 434 | "\"" regular_string_literal_characters:? "\"" 435 | 436 | regular_string_literal_characters -> 437 | regular_string_literal_character | 438 | regular_string_literal_characters regular_string_literal_character 439 | 440 | regular_string_literal_character -> 441 | single_regular_string_literal_character | 442 | simple_escape_sequence | 443 | hexadecimal_escape_sequence | 444 | unicode_escape_sequence 445 | 446 | single_regular_string_literal_character -> 447 | "\u0022" {% rejecter %} | 448 | "\u005C" {% rejecter %} | 449 | new_line_character {% rejecter %} | 450 | character 451 | 452 | verbatim_string_literal -> 453 | "@\"" verbatim_string_literal_characters:? "\"" 454 | 455 | verbatim_string_literal_characters -> 456 | verbatim_string_literal_character | 457 | verbatim_string_literal_characters verbatim_string_literal_character 458 | 459 | verbatim_string_literal_character -> 460 | single_verbatim_string_literal_character | 461 | quote_escape_sequence 462 | 463 | single_verbatim_string_literal_character -> 464 | "\"" {% rejecter %} | 465 | character 466 | 467 | quote_escape_sequence -> 468 | "\"\"" 469 | 470 | null_literal -> 471 | "null" 472 | 473 | operator_or_punctuator -> 474 | "{" | 475 | "}" | 476 | "[" | 477 | "]" | 478 | "(" | 479 | ")" | 480 | "." | 481 | "," | 482 | ":" | 483 | ";" | 484 | "+" | 485 | "-" | 486 | "*" | 487 | "/" | 488 | "%" | 489 | "&" | 490 | "|" | 491 | "^" | 492 | "!" | 493 | "~" | 494 | "=" | 495 | "<" | 496 | ">" | 497 | "?" | 498 | "??" | 499 | "::" | 500 | "++" | 501 | "--" | 502 | "&&" | 503 | "||" | 504 | "->" | 505 | "==" | 506 | "!=" | 507 | "<=" | 508 | ">=" | 509 | "+=" | 510 | "-=" | 511 | "*=" | 512 | "/=" | 513 | "%=" | 514 | "&=" | 515 | "|=" | 516 | "^=" | 517 | "<<" | 518 | "<<=" 519 | 520 | right_shift -> 521 | ">>" 522 | 523 | right_shift_assignment -> 524 | ">>=" 525 | 526 | pp_directive -> 527 | pp_declaration | 528 | pp_conditional | 529 | pp_line | 530 | pp_diagnostic | 531 | pp_region | 532 | pp_pragma 533 | 534 | conditional_symbol -> 535 | "true" {% rejecter %} | 536 | "false" {% rejecter %} | 537 | identifier_or_keyword 538 | 539 | pp_expression -> 540 | whitespace:? pp_or_expression whitespace:? 541 | 542 | pp_or_expression -> 543 | pp_and_expression | 544 | pp_or_expression whitespace:? "||" whitespace:? pp_and_expression 545 | 546 | pp_and_expression -> 547 | pp_equality_expression | 548 | pp_and_expression whitespace:? "&&" whitespace:? pp_equality_expression 549 | 550 | pp_equality_expression -> 551 | pp_unary_expression | 552 | pp_equality_expression whitespace:? "==" whitespace:? pp_unary_expression | 553 | pp_equality_expression whitespace:? "!=" whitespace:? pp_unary_expression 554 | 555 | pp_unary_expression -> 556 | pp_primary_expression | 557 | "!" whitespace:? pp_unary_expression 558 | 559 | pp_primary_expression -> 560 | "true" | 561 | "false" | 562 | conditional_symbol | 563 | "(" whitespace:? pp_expression whitespace:? ")" 564 | 565 | pp_declaration -> 566 | whitespace:? "#" whitespace:? "define" whitespace conditional_symbol pp_new_line | 567 | whitespace:? "#" whitespace:? "undef" whitespace conditional_symbol pp_new_line 568 | 569 | pp_new_line -> 570 | whitespace:? single_line_comment:? new_line 571 | 572 | pp_conditional -> 573 | pp_if_section pp_elif_sections:? pp_else_section:? pp_endif 574 | 575 | pp_if_section -> 576 | whitespace:? "#" whitespace:? "if" whitespace pp_expression pp_new_line conditional_section:? 577 | 578 | pp_elif_sections -> 579 | pp_elif_section | 580 | pp_elif_sections pp_elif_section 581 | 582 | pp_elif_section -> 583 | whitespace:? "#" whitespace:? "elif" whitespace pp_expression pp_new_line conditional_section:? 584 | 585 | pp_else_section -> 586 | whitespace:? "#" whitespace:? "else" pp_new_line conditional_section:? 587 | 588 | pp_endif -> 589 | whitespace:? "#" whitespace:? "endif" pp_new_line 590 | 591 | conditional_section -> 592 | input_section | 593 | skipped_section 594 | 595 | skipped_section -> 596 | skipped_section_part | 597 | skipped_section skipped_section_part 598 | 599 | skipped_section_part -> 600 | skipped_characters:? new_line | 601 | pp_directive 602 | 603 | skipped_characters -> 604 | whitespace:? not_number_sign input_characters:? 605 | 606 | not_number_sign -> 607 | "#" {% rejecter %} | 608 | input_character 609 | 610 | pp_diagnostic -> 611 | whitespace:? "#" whitespace:? "error" pp_message | 612 | whitespace:? "#" whitespace:? "warning" pp_message 613 | 614 | pp_message -> 615 | new_line | 616 | whitespace input_characters:? new_line 617 | 618 | pp_region -> 619 | pp_start_region conditional_section:? pp_end_region 620 | 621 | pp_start_region -> 622 | whitespace:? "#" whitespace:? "region" pp_message 623 | 624 | pp_end_region -> 625 | whitespace:? "#" whitespace:? "endregion" pp_message 626 | 627 | pp_line -> 628 | whitespace:? "#" whitespace:? "line" whitespace line_indicator pp_new_line 629 | 630 | line_indicator -> 631 | decimal_digits whitespace file_name | 632 | decimal_digits | 633 | "default" | 634 | "hidden" 635 | 636 | file_name -> 637 | "\"" file_name_characters "\"" 638 | 639 | file_name_characters -> 640 | file_name_character | 641 | file_name_characters file_name_character 642 | 643 | file_name_character -> 644 | "\u0022" {% rejecter %} | 645 | new_line_character {% rejecter %} | 646 | input_character 647 | 648 | pp_pragma -> 649 | whitespace:? "#" whitespace:? "pragma" pp_pragma_text 650 | 651 | pp_pragma_text -> 652 | new_line | 653 | whitespace input_characters:? new_line -------------------------------------------------------------------------------- /src/RegExHelper.ts: -------------------------------------------------------------------------------- 1 | export class RegExHelper { 2 | //many of the rules here come from the C# standard: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf 3 | 4 | public getLiteralNumberHexadecimalRegex(capture: boolean) { 5 | return this.wrapInGroup(false, true, "0x" + this.wrapInGroup(capture, false, "[\\dA-F]+")); 6 | } 7 | 8 | public getSignRegex(capture: boolean) { 9 | return this.wrapInGroup(capture, true, "[\\+\\-]"); 10 | } 11 | 12 | public getLiteralNumberIntegerRegex(capture: boolean) { 13 | var integerRegex = this.wrapInGroup(capture, false, 14 | this.getSignRegex(false) + "??" + 15 | this.wrapInGroup(false, true, "\\d+?")) + 16 | "[uUlL]*?"; 17 | return this.wrapInGroup(false, true, integerRegex + "|" + this.getLiteralNumberHexadecimalRegex(false)); 18 | } 19 | 20 | public getLiteralNumberDecimalRegex(capture: boolean) { 21 | var decimalDigits = "\\d+?"; 22 | var exponentPart = this.wrapInGroup(false, false, "[eE]" + (this.getSignRegex(false) + "??") + decimalDigits); 23 | var realTypeSuffix = this.wrapInGroup(false, false, "[fFdDmM]"); 24 | 25 | var realLiteral = 26 | this.wrapInGroup(false, false, decimalDigits + "\\." + decimalDigits + (exponentPart + "??") + (realTypeSuffix + "??")) + "|" + 27 | this.wrapInGroup(false, false, "\\." + decimalDigits + (exponentPart + "??") + (realTypeSuffix + "??")) + "|" + 28 | this.wrapInGroup(false, false, decimalDigits + exponentPart + (realTypeSuffix + "??")) + "|" + 29 | this.wrapInGroup(false, false, decimalDigits + realTypeSuffix); 30 | 31 | return this.wrapInGroup(false, true, 32 | this.getSignRegex(false) + "??" + 33 | this.wrapInGroup(false, true, realLiteral)); 34 | } 35 | 36 | public getLiteralNumberRegex(capture: boolean) { 37 | return this.wrapInGroup(capture, true, 38 | this.getLiteralNumberDecimalRegex(false) + "|" + 39 | this.getLiteralNumberIntegerRegex(false) + "{1}?"); 40 | } 41 | 42 | public getLiteralStringRegex(capture: boolean) { 43 | return this.wrapInGroup(capture, false, "\".+\""); 44 | } 45 | 46 | public getLiteralCharacterRegex(capture: boolean) { 47 | return this.wrapInGroup(capture, false, "'" + this.wrapInGroup(false, false, "\\\\?.") + "'"); 48 | } 49 | 50 | public getTypeOfRegex(capture: boolean) { 51 | return this.wrapInGroup(capture, false, "typeof" + this.wrapInGroup(false, true, this.getMethodParametersWrapperRegex(false, false))); 52 | } 53 | 54 | public getLiteralRegex(capture: boolean) { 55 | return this.wrapInGroup(capture, true, 56 | this.getLiteralNumberRegex(false) + "{1}?|" + 57 | this.getLiteralStringRegex(false) + "|" + 58 | this.getLiteralCharacterRegex(false) + "|" + 59 | this.getNameRegex(false)); 60 | } 61 | 62 | public getMethodParameterRegex( 63 | capture: boolean, 64 | captureAttributes: boolean, 65 | captureModifiers: boolean, 66 | captureType: boolean, 67 | captureName: boolean, 68 | captureDefaultValue: boolean) 69 | { 70 | var result = ""; 71 | 72 | result += this.getAttributesRegex(captureAttributes); 73 | result += this.getModifierRegex(captureModifiers) + "??"; 74 | result += this.getGenericTypeNameRegex(captureType, false, false, false, false); 75 | result += this.getNameRegex(captureName); 76 | result += this.wrapInGroup(false, true, 77 | this.wrapInGroup(false, true, "=") + 78 | this.getLiteralRegex(captureDefaultValue)) + 79 | "??"; 80 | 81 | return this.wrapInGroup(capture, true, result); 82 | } 83 | 84 | public getMethodParametersWrapperRegex(capture: boolean, captureContents: boolean) { 85 | return this.wrapInGroup(capture, true, 86 | "\\(" + this.getWildcardGroup(captureContents) + "\\)"); 87 | } 88 | 89 | public getEnumOptionRegex(capture: boolean, captureAttributes: boolean, captureName: boolean, captureValue: boolean) { 90 | var result = ""; 91 | 92 | result += this.getAttributesRegex(captureAttributes); 93 | result += this.getNameRegex(captureName); 94 | result += this.wrapInGroup(false, true, 95 | this.wrapInGroup(false, true, "=") + 96 | this.getLiteralNumberIntegerRegex(captureValue)) + 97 | "??"; 98 | 99 | return this.wrapInGroup(capture, true, result); 100 | } 101 | 102 | public getEnumRegex(capture: boolean, captureAttributes: boolean, captureModifiers: boolean, captureName: boolean, captureInheritance: boolean) { 103 | var result = ""; 104 | 105 | result += this.getAttributesRegex(captureAttributes); 106 | result += this.getModifiersRegex(captureModifiers); 107 | result += this.wrapInGroup(false, true, "enum"); 108 | result += this.getNameRegex(captureName); 109 | result += this.wrapInGroup(false, true, 110 | this.wrapInGroup(false, true, ":") + 111 | this.getNameRegex(captureInheritance)) + 112 | "??"; 113 | 114 | result += this.wrapInGroup(false, true, "{"); 115 | 116 | return result; 117 | } 118 | 119 | public getMethodRegex( 120 | capture: boolean, 121 | captureAttributes: boolean, 122 | captureModifiers: boolean, 123 | captureReturnType: boolean, 124 | captureName: boolean, 125 | captureGenericParameters: boolean, 126 | captureParameters: boolean, 127 | captureOpeningMethod: boolean) 128 | { 129 | var result = ""; 130 | 131 | result += this.getAttributesRegex(captureAttributes); 132 | result += this.getModifiersRegex(captureModifiers); 133 | result += this.getGenericTypeNameRegex(captureReturnType, false, false, false, false) + "??"; 134 | result += this.getGenericNameRegex(false, captureName, captureGenericParameters); 135 | result += this.getMethodParametersWrapperRegex(false, captureParameters); 136 | result += this.wrapInGroup(false, false, 137 | this.wrapInGroup(false, true, "where") + 138 | this.getGenericNameRegex(false, false, false) + 139 | this.wrapInGroup(false, true, ":")) + 140 | "*?"; 141 | result += this.wrapInGroup(captureOpeningMethod, true, 142 | this.wrapInGroup(false, false, "{") + "|" + 143 | this.wrapInGroup(false, false, ";") + "|" + 144 | this.wrapInGroup(false, false, this.wrapInGroup(false, false, "=>"))); 145 | 146 | return this.wrapInGroup(capture, false, result); 147 | } 148 | 149 | private getWildcardGroup(capture: boolean) { 150 | return this.wrapInGroup(capture, false, "(?:\\s|.)*"); 151 | } 152 | 153 | public getNamespaceRegex(capture: boolean, captureFullName: boolean) { 154 | return this.wrapInGroup(capture, true, 155 | this.wrapInGroup(false, true, "namespace") + 156 | this.getNameRegex(captureFullName)) 157 | } 158 | 159 | public getFieldRegex( 160 | capture: boolean, 161 | captureAttributes: boolean, 162 | captureModifiers: boolean, 163 | captureReturnType: boolean, 164 | captureName: boolean, 165 | captureInitialValue: boolean) 166 | { 167 | var result = ""; 168 | 169 | result += this.getAttributesRegex(captureAttributes); 170 | result += this.getModifiersRegex(captureModifiers); 171 | result += this.getGenericTypeNameRegex(captureReturnType, false, false, false, false); 172 | result += this.getNameRegex(captureName); 173 | result += this.getInitialValueRegex(captureInitialValue); 174 | result += this.wrapInGroup(false, true, ";"); 175 | 176 | return this.wrapInGroup(capture, false, result); 177 | } 178 | 179 | public getPropertyRegex( 180 | capture: boolean, 181 | captureAttributes: boolean, 182 | captureModifiers: boolean, 183 | captureReturnType: boolean, 184 | captureName: boolean, 185 | captureOpeningMethod: boolean) 186 | { 187 | var result = ""; 188 | 189 | result += this.getAttributesRegex(captureAttributes); 190 | result += this.getModifiersRegex(captureModifiers); 191 | result += this.getGenericTypeNameRegex(captureReturnType, false, false, false, false); 192 | result += this.getNameRegex(captureName); 193 | result += this.wrapInGroup(captureOpeningMethod, true, 194 | this.wrapInGroup(false, false, "{") + "|" + 195 | this.wrapInGroup(false, false, this.wrapInGroup(false, false, "=>"))); 196 | 197 | return this.wrapInGroup(capture, false, result); 198 | } 199 | 200 | public getPropertyInitialValueRegex(capture: boolean) { 201 | var result = ""; 202 | 203 | result += this.wrapInGroup(false, true, "}"); 204 | result += this.wrapInGroup(false, false, "="); 205 | result += this.wrapInGroup(capture, true, "[^;]+?"); 206 | result += this.wrapInGroup(false, false, ";"); 207 | 208 | return this.wrapInGroup(false, false, result); 209 | } 210 | 211 | public getKeywordRegex(capture: boolean) { 212 | var validKeywords = [ 213 | this.getModifierRegex(false), 214 | "as", 215 | "base", 216 | "break", 217 | "case", 218 | "catch", 219 | "checked", 220 | "class", 221 | "const", 222 | "continue", 223 | "default", 224 | "delegate", 225 | "do", 226 | "else", 227 | "enum", 228 | "explicit", 229 | "finally", 230 | "fixed", 231 | "for", 232 | "foreach", 233 | "goto", 234 | "if", 235 | "implicit", 236 | "in", 237 | "interface", 238 | "is", 239 | "lock", 240 | "namespace", 241 | "new", 242 | "operator", 243 | "out", 244 | "override", 245 | "return", 246 | "sealed", 247 | "sizeof", 248 | "stackalloc", 249 | "switch", 250 | "this", 251 | "throw", 252 | "try", 253 | "typeof", 254 | "unchecked", 255 | "unsafe", 256 | "using", 257 | "while" 258 | ]; 259 | return this.wrapInGroup(capture, false, validKeywords.join('|')); 260 | } 261 | 262 | public getModifierRegex(capture: boolean) { 263 | var validModifiers = [ 264 | "public", 265 | "private", 266 | "internal", 267 | "protected", 268 | "abstract", 269 | "async", 270 | "const", 271 | "event", 272 | "extern", 273 | "new", 274 | "override", 275 | "partial", 276 | "readonly", 277 | "sealed", 278 | "static", 279 | "unsafe", 280 | "virtual", 281 | "volatile", 282 | "ref", 283 | "params" 284 | ]; 285 | return this.wrapInGroup(capture, false, validModifiers.join('|')); 286 | } 287 | 288 | public getModifiersRegex(capture: boolean) { 289 | return this.wrapInGroup(capture, false, this.repeatGroups("\\s*", () => this.getModifierRegex(false)) + "*?"); 290 | } 291 | 292 | public getAttributeParameterRegex(capture: boolean, captureName: boolean, captureValue: boolean) { 293 | var result = ""; 294 | 295 | result += this.wrapInGroup(false, true, this.getNameRegex(captureName) + "=") + "??"; 296 | result += this.getLiteralRegex(captureValue) + "|"; 297 | result += this.getTypeOfRegex(captureValue); 298 | 299 | return this.wrapInGroup(capture, true, result); 300 | } 301 | 302 | public getAttributeParametersRegex(capture: boolean, captureContents: boolean) { 303 | return this.wrapInGroup(capture, true, "\\(" + this.wrapInGroup(captureContents, true, this.repeatGroups(",", () => this.getAttributeParameterRegex(false, false, false))) + "\\)"); 304 | } 305 | 306 | public getAttributeRegex(capture: boolean, captureAttributeName: boolean, captureParameters: boolean) { 307 | return this.wrapInGroup(capture, true, this.getNameRegex(captureAttributeName) + this.getAttributeParametersRegex(false, captureParameters) + "??"); 308 | } 309 | 310 | public getAttributesRegex(capture: boolean) { 311 | return this.wrapInGroup(capture, false, this.wrapInGroup(false, true, "\\[" + this.repeatGroups(",", () => this.getAttributeRegex(false, false, false)) + "\\]") + "*?"); 312 | } 313 | 314 | public getNameRegex(capture: boolean) { 315 | return this.wrapInGroup(capture, true, "[\\w.]+"); 316 | } 317 | 318 | public getGenericTypeWrapperRegex(capture: boolean, captureContents: boolean) { 319 | return this.wrapInGroup(capture, true, "<" + this.wrapInGroup(captureContents, true, "[^=]+") + ">") + "??"; 320 | } 321 | 322 | public getTypeConstraintRegex(capture: boolean) { 323 | return this.wrapInGroup(capture, true, this.getGenericNameRegex(false, false, false) + "|new\\s*\\(\\s*\\)|class|struct"); 324 | } 325 | 326 | public getGenericNameRegex(capture: boolean, captureTypeName: boolean, captureGenericsContent: boolean) { 327 | return this.wrapInGroup(capture, true, 328 | this.getNameRegex(captureTypeName) + 329 | this.getGenericTypeWrapperRegex(false, captureGenericsContent)); 330 | } 331 | 332 | public getUsingRegex(capture: boolean, captureAlias: boolean, captureNamespace: boolean) { 333 | var result = ""; 334 | 335 | result += this.wrapInGroup(false, true, "using"); 336 | result += this.wrapInGroup(false, true, 337 | this.getNameRegex(captureAlias) + 338 | this.wrapInGroup(false, true, "=")) + 339 | "??"; 340 | result += this.getNameRegex(captureNamespace); 341 | result += this.wrapInGroup(false, true, ";"); 342 | 343 | return result; 344 | } 345 | 346 | public getGenericTypeNameRegex(capture: boolean, captureTypeName: boolean, captureGenericsContent: boolean, captureTupleContent: boolean, captureSuffix: boolean) { 347 | return this.wrapInGroup(capture, true, 348 | this.wrapInGroup(false, false, 349 | this.getGenericNameRegex(false, captureTypeName, captureGenericsContent) + "|" + 350 | this.wrapInGroup(false, false, "\\(" + this.wrapInGroup(captureTupleContent, true, ".+?") + "\\)")) + 351 | this.wrapInGroup(captureSuffix, true, "\\?|" + this.wrapInGroup(false, true, "\\[\\s*\\]") + "+") + "??"); 352 | } 353 | 354 | private wrapInGroup(capture: boolean, wrapInSpaces: boolean, input: string) { 355 | input = (capture ? "(" : "(?:") + input + ")"; 356 | if(wrapInSpaces) 357 | input = "(?:\\s*?" + input + "\\s*?)"; 358 | 359 | return input; 360 | } 361 | 362 | private wrapInNegatedGroup(capture: boolean, wrapInSpaces: boolean, input: string) { 363 | return this.wrapInGroup(capture, wrapInSpaces, "(?!" + input + ")"); 364 | } 365 | 366 | private repeatGroups(separator: string, groupRegexFunction: () => string) { 367 | return this.wrapInGroup(false, false, groupRegexFunction() + separator) + "*?" + groupRegexFunction(); 368 | } 369 | 370 | public getStructRegex() 371 | { 372 | var result = ""; 373 | 374 | result += this.getAttributesRegex(true); 375 | result += this.getModifiersRegex(true); 376 | result += this.wrapInGroup(false, true, "struct"); 377 | 378 | //struct name 379 | result += this.getGenericNameRegex(false, true, true); 380 | 381 | //inheritance. 382 | var whereSection = ""; 383 | whereSection += this.wrapInGroup(false, true, "where"); 384 | whereSection += this.getNameRegex(false); 385 | whereSection += this.wrapInGroup(false, true, ":"); 386 | whereSection += this.getTypeConstraintRegex(false); 387 | 388 | result += this.wrapInGroup(false, true, whereSection) + "*?"; 389 | 390 | result += "{"; 391 | 392 | return this.wrapInGroup(false, false, result); 393 | } 394 | 395 | private getClassOrInterfaceRegex(keyword: "class" | "interface") { 396 | var result = ""; 397 | 398 | result += this.getAttributesRegex(true); 399 | result += this.getModifiersRegex(true); 400 | result += this.wrapInGroup(false, true, keyword); 401 | 402 | //class name. 403 | result += this.getGenericNameRegex(false, true, true); 404 | 405 | //inheritance. 406 | var whereSection = ""; 407 | whereSection += this.wrapInGroup(false, true, "where"); 408 | whereSection += this.getNameRegex(false); 409 | whereSection += this.wrapInGroup(false, true, ":"); 410 | whereSection += this.getTypeConstraintRegex(false); 411 | 412 | var inheritanceSection = ""; 413 | inheritanceSection += this.wrapInGroup(false, true, ":"); 414 | inheritanceSection += this.wrapInGroup(true, true, this.repeatGroups(",", () => this.getGenericNameRegex(false, false, false))); 415 | 416 | result += this.wrapInGroup(false, true, inheritanceSection) + "??"; 417 | result += this.wrapInGroup(false, true, whereSection) + "*?"; 418 | 419 | result += "{"; 420 | 421 | return this.wrapInGroup(false, false, result); 422 | } 423 | 424 | public getClassRegex() { 425 | return this.getClassOrInterfaceRegex("class"); 426 | } 427 | 428 | public getInterfaceRegex() { 429 | return this.getClassOrInterfaceRegex("interface"); 430 | } 431 | 432 | public getInitialValueRegex(capture: boolean) { 433 | var result = this.wrapInGroup(false, true, "="); 434 | result += this.wrapInGroup(capture, true, "[^;]+?"); 435 | 436 | return this.wrapInGroup(false, false, result) + "??"; 437 | } 438 | 439 | public getMatches(input: string, regex: RegExp) { 440 | if(!input) 441 | return []; 442 | 443 | var final = []; 444 | 445 | var groups; 446 | while (groups = regex.exec(input)) { 447 | if(!groups[0]) 448 | continue; 449 | 450 | final.push(groups 451 | .slice(1) 452 | .map(x => x || "") 453 | .map(x => x.trim())); 454 | } 455 | 456 | return final; 457 | } 458 | } -------------------------------------------------------------------------------- /spec/FileParserSpec.ts: -------------------------------------------------------------------------------- 1 | import { FileParser } from '../src/FileParser'; 2 | import { CSharpNamedToken } from '../src/Index'; 3 | 4 | var fs = require('fs'); 5 | 6 | function useCSharp(file: string, callback: (parser: FileParser) => void) { 7 | return (done: Function) => { 8 | fs.readFile('./spec/csharp/' + file, 'utf8', function (err: any, data: any) { 9 | console.log("\n\n" + file); 10 | callback(new FileParser(data)); 11 | done(); 12 | }); 13 | }; 14 | } 15 | 16 | describe("FileParser", function () { 17 | 18 | it("should be able to fetch properties inside classes", useCSharp('PropertyInsideClass.cs', (parser) => { 19 | var file = parser.parseFile(); 20 | 21 | expect(file.classes.length).toBe(1, "classes length"); 22 | expect(file.classes[0].properties.length).toBe(8, "class properties length"); 23 | expect(file.classes[0].properties[0].components.length).toBe(2, "class property 0 components length"); 24 | expect(file.classes[0].properties[1].components.length).toBe(1, "class property 1 components length"); 25 | expect(file.classes[0].properties[1].attributes.length).toBe(0, "class property 1 attributes length"); 26 | expect(file.classes[0].properties[2].components.length).toBe(2, "class property 2 components length"); 27 | expect(file.classes[0].properties[2].attributes.length).toBe(1, "class property 2 attributes length"); 28 | expect(file.classes[0].properties[4].components.length).toBe(1, "class property 3 components length"); 29 | 30 | expect(file.classes[0].properties[0].name).toBe("MyProperty"); 31 | expect(file.classes[0].properties[0].isReadOnly).toBe(false); 32 | expect(file.classes[0].properties[0].isVirtual).toBe(false); 33 | expect(file.classes[0].properties[0].type.name).toBe("string"); 34 | expect(file.classes[0].properties[0].initialValue).toBe(undefined); 35 | 36 | expect(file.classes[0].properties[1].name).toBe("ReadOnlyProperty"); 37 | expect(file.classes[0].properties[1].isReadOnly).toBe(true); 38 | expect(file.classes[0].properties[1].components[0].type).toBe("get"); 39 | expect(file.classes[0].properties[1].type.name).toBe("string"); 40 | expect(file.classes[0].properties[1].initialValue).toBe(undefined); 41 | 42 | expect(file.classes[0].properties[2].name).toBe("GetSetProperty"); 43 | expect(file.classes[0].properties[2].isReadOnly).toBe(false); 44 | expect(file.classes[0].properties[2].type.name).toBe("string"); 45 | expect(file.classes[0].properties[2].initialValue).toBe(undefined); 46 | 47 | expect(file.classes[0].properties[3].name).toBe("MyPublicVirtualProperty"); 48 | expect(file.classes[0].properties[3].isReadOnly).toBe(false); 49 | expect(file.classes[0].properties[3].isVirtual).toBe(true); 50 | expect(file.classes[0].properties[3].type.name).toBe("string"); 51 | expect(file.classes[0].properties[3].initialValue).toBe('"barfoo"'); 52 | 53 | expect(file.classes[0].properties[4].name).toBe("ReadOnlyShortProperty"); 54 | expect(file.classes[0].properties[4].isReadOnly).toBe(true); 55 | expect(file.classes[0].properties[4].components[0].type).toBe("get"); 56 | expect(file.classes[0].properties[4].type.name).toBe("string"); 57 | expect(file.classes[0].properties[4].initialValue).toBe(undefined); 58 | 59 | expect(file.classes[0].properties[5].name).toBe("TupleReturningProperty"); 60 | expect(file.classes[0].properties[5].type.name).toBe("ValueTuple<,>"); 61 | expect(file.classes[0].properties[5].initialValue).toBe(undefined); 62 | 63 | expect(file.classes[0].properties[5].type.genericParameters[1].name).toBe("Func<,>"); 64 | expect(file.classes[0].properties[5].type.genericParameters[1].genericParameters[0].name).toBe("int"); 65 | expect(file.classes[0].properties[5].type.genericParameters[1].genericParameters[1].name).toBe("string"); 66 | 67 | expect(file.classes[0].properties[6].name).toBe("NamedTupleReturningProperty"); 68 | expect(file.classes[0].properties[6].type.name).toBe("ValueTuple<,>"); 69 | expect(file.classes[0].properties[6].type.genericParameters[1].name).toBe("Func<,>"); 70 | expect(file.classes[0].properties[6].type.genericParameters[1].genericParameters[0].name).toBe("int"); 71 | expect(file.classes[0].properties[6].type.genericParameters[1].genericParameters[1].name).toBe("string"); 72 | expect(file.classes[0].properties[6].initialValue).toBe(undefined); 73 | 74 | expect(file.classes[0].properties[7].name).toBe("List"); 75 | expect(file.classes[0].properties[7].type.name).toBe("IList<>"); 76 | expect(file.classes[0].properties[7].type.genericParameters[0].name).toBe("string"); 77 | expect(file.classes[0].properties[7].initialValue).toBe(undefined); 78 | })); 79 | 80 | describe("comments:", function () { 81 | 82 | it("should be able to remove comments from output", useCSharp('Comments.cs', (parser) => { 83 | var file = parser.parseFile(); 84 | 85 | expect(file.classes.length).toBe(1, "classes length"); 86 | expect(file.classes[0].fields.length).toBe(1, "class fields length"); 87 | expect(file.classes[0].properties.length).toBe(1, "class properties length"); 88 | expect(file.classes[0].methods.length).toBe(3, "class methods length"); 89 | 90 | expect(file.classes[0].methods[0].returnType.name).toBe("void"); 91 | 92 | expect(file.classes[0].methods[1].parameters[0].defaultValue).toBe(false); 93 | expect(file.classes[0].methods[1].parameters[0].type.name).toBe("bool"); 94 | expect(file.classes[0].methods[1].parameters[0].name).toBe("parameter2"); 95 | })); 96 | 97 | }); 98 | 99 | describe("usings:", function () { 100 | 101 | it("should be able to fetch file containing only usings and no scopes", useCSharp('Usings.cs', (parser) => { 102 | var file = parser.parseFile(); 103 | expect(file.usings.length).toBe(2); 104 | 105 | expect(file.usings[0].alias).toBe('foo'); 106 | expect(file.usings[0].namespace.fullName).toBe('buz.bar'); 107 | 108 | expect(file.usings[1].alias).toBeNull(); 109 | expect(file.usings[1].namespace.fullName).toBe('blah.lol.omg'); 110 | })); 111 | 112 | it("should be able to fetch file containing scoped usings", useCSharp('UsingsAndNamespaces.cs', (parser) => { 113 | var file = parser.parseFile(); 114 | 115 | expect(file.usings.length).toBe(2); 116 | 117 | expect(file.usings[0].alias).toBe('foo'); 118 | expect(file.usings[0].namespace.fullName).toBe('buz.bar'); 119 | 120 | expect(file.usings[1].alias).toBeNull(); 121 | expect(file.usings[1].namespace.fullName).toBe('blah'); 122 | 123 | expect(file.namespaces[0].usings[0].namespace.name).toBe('blah.lol.omg'); 124 | expect(file.namespaces[0].usings[0].parent.name).toBe('mynamespace'); 125 | 126 | expect(file.namespaces[1].name).toBe('blah'); 127 | expect(file.namespaces[1].fullName).toBe('blah'); 128 | 129 | expect(file.namespaces[1].namespaces[0].name).toBe('foo'); 130 | expect(file.namespaces[1].namespaces[0].fullName).toBe('blah.foo'); 131 | })); 132 | 133 | }); 134 | 135 | describe("classes:", function () { 136 | 137 | it("should be able to fetch classes inside namespaces", useCSharp('ClassInsideNamespace.cs', (parser) => { 138 | var file = parser.parseFile(); 139 | 140 | expect(file.namespaces.length).toBe(1, "namespaces length"); 141 | expect(file.namespaces[0].classes.length).toBe(1, "namespace classes length"); 142 | expect(file.namespaces[0].classes[0].properties.length).toBe(1, "namespace class properties length"); 143 | expect(file.namespaces[0].classes[0].attributes.length).toBe(2, "namespace class attributes length"); 144 | expect(file.namespaces[0].classes[0].fields.length).toBe(2, "namespace class fields length"); 145 | expect(file.namespaces[0].classes[0].methods.length).toBe(0, "namespace class methods length"); 146 | expect(file.namespaces[0].classes[0].constructors.length).toBe(1, "namespace class constructors length"); 147 | expect(file.namespaces[0].classes[0].genericParameters.length).toBe(1, "namespace class generic parameters length"); 148 | 149 | expect(file.namespaces[0].classes[0].name).toBe("MyPoco", "namespace class name"); 150 | 151 | expect(file.namespaces[0].classes[0].genericParameters[0].name).toBe("WithGenerics", "namespace class generic parameter name"); 152 | 153 | expect(file.namespaces[0].classes[0].properties[0].name).toBe("Name", "namespace class property name"); 154 | expect(file.namespaces[0].classes[0].properties[0].type.name).toBe("Array<>", "namespace class property type name"); 155 | expect(file.namespaces[0].classes[0].properties[0].type.genericParameters[0].name).toBe("string", "namespace class property type generic parameter name"); 156 | 157 | expect(file.namespaces[0].classes[0].fields[0].name).toBe("someField", "namespace class field name"); 158 | expect(file.namespaces[0].classes[0].fields[0].isPublic).toBe(true, "namespace class field public"); 159 | expect(file.namespaces[0].classes[0].fields[0].type.name).toBe("int", "namespace class field type name"); 160 | expect(file.namespaces[0].classes[0].fields[0].type.isNullable).toBe(true, "namespace class field type nullable"); 161 | 162 | expect(file.namespaces[0].classes[0].fields[1].type.genericParameters[0].name).toBe("string", "namespace class field generic parameter name"); 163 | expect(file.namespaces[0].classes[0].fields[1].initialValue).toBe("new List()", "namespace class field initial value"); 164 | 165 | expect(file.namespaces[0].classes[0].constructors[0].name).toBe("MyPoco", "namespace class constructor name"); 166 | expect(file.namespaces[0].classes[0].constructors[0].isConstructor).toBe(true, "namespace class constructor is constructor"); 167 | expect(file.namespaces[0].classes[0].constructors[0].isPublic).toBe(true, "namespace class constructor is public"); 168 | 169 | expect(file.namespaces[0].classes[0].attributes[1].name).toBe("SomeAttributeWithParameters", "namespace class attribute name"); 170 | expect(file.namespaces[0].classes[0].attributes[1].parameters[0].name).toBe("MyName", "namespace class attribute parameter 0 name"); 171 | expect(file.namespaces[0].classes[0].attributes[1].parameters[0].value).toBe("Foo", "namespace class attribute parameter 0 value"); 172 | expect(file.namespaces[0].classes[0].attributes[1].parameters[1].name).toBe(null, "namespace class attribute parameter 1 name"); 173 | expect(file.namespaces[0].classes[0].attributes[1].parameters[1].value).toBe(28, "namespace class attribute parameter 1 value"); 174 | expect(file.namespaces[0].classes[0].attributes[1].parameters[2].name).toBe(null, "namespace class attribute parameter 2 name"); 175 | expect((file.namespaces[0].classes[0].attributes[1].parameters[2].value as CSharpNamedToken).name).toBe("Framework.Blah", "namespace class attribute parameter 2 value"); 176 | })); 177 | 178 | it("should be able to fetch interfaces that implement something", useCSharp('ImplementedInterface.cs', (parser) => { 179 | var file = parser.parseFile(); 180 | 181 | expect(file.interfaces.length).toBe(1); 182 | expect(file.interfaces[0].implements.length).toBe(2); 183 | 184 | expect(file.interfaces[0].implements[0]).not.toBeUndefined(); 185 | expect(file.interfaces[0].implements[0].name).toBe("IMyInterface1<>"); 186 | 187 | expect(file.interfaces[0].implements[1]).not.toBeUndefined(); 188 | expect(file.interfaces[0].implements[1].name).toBe("IMyInterface2<,>"); 189 | })); 190 | 191 | it("should be able to fetch classes that inherit from something", useCSharp('InheritedClass.cs', (parser) => { 192 | var file = parser.parseFile(); 193 | 194 | expect(file.classes.length).toBe(1); 195 | expect(file.classes[0].inheritsFrom.length).toBe(2); 196 | 197 | expect(file.classes[0].inheritsFrom[0]).not.toBeUndefined(); 198 | expect(file.classes[0].inheritsFrom[0].name).toBe("IMyInterface1<>"); 199 | 200 | expect(file.classes[0].inheritsFrom[1]).not.toBeUndefined(); 201 | expect(file.classes[0].inheritsFrom[1].name).toBe("IMyInterface2<,>"); 202 | })); 203 | 204 | }); 205 | 206 | describe("generics:", function () { 207 | 208 | it("should be able to handle generics", useCSharp('Generics.cs', (parser) => { 209 | var file = parser.parseFile(); 210 | 211 | expect(file.classes.length).toBe(1, "classes length"); 212 | expect(file.classes[0].properties.length).toBe(2, "class properties length"); 213 | expect(file.classes[0].methods.length).toBe(1, "class methods length"); 214 | 215 | expect(file.classes[0].properties[0].name).toBe('Name', "class property 0 name"); 216 | expect(file.classes[0].properties[0].type.name).toBe('SomeFoo<,>', "class property 0 type name"); 217 | expect(file.classes[0].properties[0].type.genericParameters[0].name).toBe('SomeBar'); 218 | expect(file.classes[0].properties[0].type.genericParameters[1].name).toBe('SomeThing'); 219 | 220 | expect(file.classes[0].properties[1].name).toBe('Foo'); 221 | expect(file.classes[0].properties[1].type.name).toBe('SomeFoo<,>', "class property 1 type name"); 222 | expect(file.classes[0].properties[1].type.genericParameters[0].name).toBe('SomeBar<>'); 223 | expect(file.classes[0].properties[1].type.genericParameters[1].name).toBe('SomeThing<>'); 224 | 225 | expect(file.classes[0].methods[0].name).toBe('Bar'); 226 | expect(file.classes[0].methods[0].returnType.name).toBe('SomeFoo<>', "class method 0 type name"); 227 | expect(file.classes[0].methods[0].returnType.genericParameters[0].name).toBe('SomeBar'); 228 | })); 229 | 230 | }); 231 | 232 | describe("enums:", function () { 233 | 234 | it("should be able to fetch enums and the appropriate values", useCSharp('Enum.cs', (parser) => { 235 | var file = parser.parseFile(); 236 | 237 | expect(file.enums.length).toBe(1, "enums length"); 238 | expect(file.enums[0].options.length).toBe(5, "enum options length"); 239 | expect(file.enums[0].attributes.length).toBe(1, "enum attributes length"); 240 | 241 | expect(file.classes.length).toBe(1, "classes length"); 242 | expect(file.classes[0].enums.length).toBe(2, "classes enums length"); 243 | expect(file.namespaces[0].enums.length).toBe(1, "namespace enums length"); 244 | 245 | expect(file.enums[0].options[1].attributes.length).toBe(2, "enum option 1 attributes length"); 246 | expect(file.enums[0].options[2].attributes.length).toBe(1, "enum option 2 attributes length"); 247 | expect(file.enums[0].options[3].attributes.length).toBe(3, "enum option 3 attributes length"); 248 | 249 | expect(file.enums[0].options[0].name).toBe('FirstValue'); 250 | expect(file.enums[0].options[0].value).toBe(0); 251 | 252 | expect(file.enums[0].options[1].name).toBe('SecondValue'); 253 | expect(file.enums[0].options[1].value).toBe(-4); 254 | expect(file.enums[0].options[1].attributes[0].name).toBe('SomeStuff'); 255 | expect(file.enums[0].options[1].attributes[1].name).toBe('SomeAttribute'); 256 | 257 | expect(file.enums[0].options[2].name).toBe('ThirdValue'); 258 | expect(file.enums[0].options[2].value).toBe(-3); 259 | expect(file.enums[0].options[2].attributes[0].name).toBe('SomeAttribute'); 260 | 261 | expect(file.enums[0].options[3].name).toBe('FourthValue'); 262 | expect(file.enums[0].options[3].value).toBe(6); 263 | expect(file.enums[0].options[3].attributes[0].name).toBe('SomeAttribute'); 264 | expect(file.enums[0].options[3].attributes[1].name).toBe('FooAttribute'); 265 | expect(file.enums[0].options[3].attributes[2].name).toBe('BlahAttribute'); 266 | 267 | expect(file.enums[0].options[4].name).toBe('FifthValue'); 268 | expect(file.enums[0].options[4].value).toBe(7); 269 | })); 270 | 271 | }); 272 | 273 | describe("methods:", function () { 274 | 275 | it("should be able to fetch methods inside classes and their parameters", useCSharp('MethodInsideClass.cs', (parser) => { 276 | var file = parser.parseFile(); 277 | 278 | expect(file.classes.length).toBe(1); 279 | expect(file.classes[0].methods.length).toBe(6); 280 | 281 | expect(file.classes[0].methods[0].attributes.length).toBe(0); 282 | expect(file.classes[0].methods[0].parameters.length).toBe(0); 283 | expect(file.classes[0].methods[1].attributes.length).toBe(1); 284 | expect(file.classes[0].methods[1].parameters.length).toBe(5, "class methods 1 parameters length"); 285 | expect(file.classes[0].methods[1].parameters[2].type.genericParameters.length).toBe(1); 286 | expect(file.classes[0].methods[1].parameters[2].type.genericParameters[0].genericParameters.length).toBe(2); 287 | expect(file.classes[0].methods[1].parameters[3].attributes.length).toBe(4); 288 | expect(file.classes[0].methods[2].parameters.length).toBe(2); 289 | expect(file.classes[0].methods[2].parameters[0].attributes.length).toBe(1); 290 | expect(file.classes[0].methods[2].parameters[1].attributes.length).toBe(1); 291 | 292 | expect(file.classes[0].methods[0].returnType.name).toBe('string'); 293 | expect(file.classes[0].methods[0].isVirtual).toBe(true); 294 | expect(file.classes[0].methods[0].name).toBe('MyFunction'); 295 | 296 | expect(file.classes[0].methods[1].returnType.name).toBe('void'); 297 | expect(file.classes[0].methods[1].isVirtual).toBe(false); 298 | expect(file.classes[0].methods[1].name).toBe('SomeOtherFunction'); 299 | 300 | expect(file.classes[0].methods[1].parameters[0].name).toBe('parameter1'); 301 | expect(file.classes[0].methods[1].parameters[0].type.name).toBe('string'); 302 | expect(file.classes[0].methods[1].parameters[0].isVariadicContainer).toBe(false); 303 | 304 | expect(file.classes[0].methods[1].parameters[1].name).toBe('parameter2'); 305 | expect(file.classes[0].methods[1].parameters[1].type.name).toBe('bool'); 306 | expect(file.classes[0].methods[1].parameters[1].defaultValue).toBe(false); 307 | 308 | expect(file.classes[0].methods[1].parameters[2].name).toBe('foo'); 309 | expect(file.classes[0].methods[1].parameters[2].type.name).toBe('List<>'); 310 | expect(file.classes[0].methods[1].parameters[2].type.genericParameters[0].name).toBe('Dictionary<,>'); 311 | expect(file.classes[0].methods[1].parameters[2].type.genericParameters[0].genericParameters[0].name).toBe('string'); 312 | expect(file.classes[0].methods[1].parameters[2].type.genericParameters[0].genericParameters[1].name).toBe('int'); 313 | expect(file.classes[0].methods[1].parameters[2].defaultValue).toBe('bar'); 314 | 315 | expect(file.classes[0].methods[1].parameters[3].name).toBe('foo2'); 316 | expect(file.classes[0].methods[1].parameters[3].type.name).toBe('string'); 317 | expect(file.classes[0].methods[1].parameters[3].attributes[0].name).toBe('Hello'); 318 | expect(file.classes[0].methods[1].parameters[3].attributes[1].name).toBe('Blah'); 319 | expect(file.classes[0].methods[1].parameters[3].attributes[2].name).toBe('Foo'); 320 | expect(file.classes[0].methods[1].parameters[3].attributes[3].name).toBe('Bar'); 321 | 322 | expect(file.classes[0].methods[1].parameters[4].name).toBe('someArray'); 323 | expect(file.classes[0].methods[1].parameters[4].type.name).toBe('Array<>'); 324 | expect(file.classes[0].methods[1].parameters[4].isVariadicContainer).toBe(true); 325 | 326 | expect(file.classes[0].methods[2].parameters[0].name).toBe('baz'); 327 | expect(file.classes[0].methods[2].parameters[0].type.name).toBe('string'); 328 | expect(file.classes[0].methods[2].parameters[0].attributes[0].name).toBe('Annotation1'); 329 | 330 | expect(file.classes[0].methods[2].parameters[1].name).toBe('buz'); 331 | expect(file.classes[0].methods[2].parameters[1].type.name).toBe('int'); 332 | expect(file.classes[0].methods[2].parameters[1].attributes[0].name).toBe('Annotation2'); 333 | 334 | var defaultValue = file.classes[0].methods[5].parameters[0].defaultValue as CSharpNamedToken; 335 | expect(file.classes[0].methods[5].parameters[0].name).toBe('foo'); 336 | expect(file.classes[0].methods[5].parameters[0].type.name).toBe('string'); 337 | expect(defaultValue.name).toBe('null'); 338 | })); 339 | 340 | }); 341 | 342 | describe("namespaces:", function () { 343 | 344 | it("should be able to fetch file containing scoped namespaces", useCSharp('NamespacesNested.cs', (parser) => { 345 | var file = parser.parseFile(); 346 | 347 | expect(file.namespaces.length).toBe(2); 348 | expect(file.namespaces[0].namespaces.length).toBe(1); 349 | expect(file.namespaces[0].namespaces[0].namespaces.length).toBe(1); 350 | 351 | expect(file.namespaces[0].name).toBe('my'); 352 | 353 | expect(file.namespaces[0].namespaces[0].name).toBe('stuff'); 354 | expect(file.namespaces[0].namespaces[0].fullName).toBe('my.stuff'); 355 | 356 | expect(file.namespaces[0].namespaces[0].namespaces[0].name).toBe('blah'); 357 | expect(file.namespaces[0].namespaces[0].namespaces[0].fullName).toBe('my.stuff.blah'); 358 | 359 | expect(file.namespaces[1].name).toBe('omg'); 360 | })); 361 | 362 | }); 363 | 364 | describe("interfaces:", function() { 365 | 366 | it("should be able to fetch interfaces inside namespaces", useCSharp('InterfaceInsideNamespace.cs', (parser) => { 367 | var file = parser.parseFile(); 368 | 369 | expect(file.namespaces.length).toBe(1); 370 | expect(file.namespaces[0].interfaces.length).toBe(1); 371 | expect(file.namespaces[0].interfaces[0].properties.length).toBe(1); 372 | expect(file.namespaces[0].interfaces[0].methods.length).toBe(1); 373 | expect(file.namespaces[0].interfaces[0].attributes.length).toBe(1); 374 | 375 | expect(file.namespaces[0].interfaces[0].name).toBe("MyPoco"); 376 | 377 | expect(file.namespaces[0].interfaces[0].properties[0].name).toBe("Name"); 378 | expect(file.namespaces[0].interfaces[0].properties[0].type.name).toBe("Array<>"); 379 | expect(file.namespaces[0].interfaces[0].properties[0].type.genericParameters[0].name).toBe("string"); 380 | 381 | expect(file.namespaces[0].interfaces[0].methods[0].name).toBe("SomeMethod"); 382 | expect(file.namespaces[0].interfaces[0].methods[0].returnType.name).toBe("Int32"); 383 | expect(file.namespaces[0].interfaces[0].methods[0].returnType.fullName).toBe("System.Int32"); 384 | })); 385 | 386 | }); 387 | 388 | describe("structs:", function () { 389 | 390 | it("should be able to detect structs", useCSharp('Struct.cs', (parser) => { 391 | var file = parser.parseFile(); 392 | 393 | expect(file.structs.length).toBe(1); 394 | expect(file.structs[0].attributes.length).toBe(1); 395 | 396 | expect(file.structs[0].isPublic).toBe(true); 397 | expect(file.structs[0].name).toBe("MyStruct"); 398 | })); 399 | 400 | }); 401 | 402 | describe("statics:", function () { 403 | 404 | it("should be able to detect statics", useCSharp('Static.cs', (parser) => { 405 | var file = parser.parseFile(); 406 | 407 | expect(file.classes[0].isPublic).toBe(true); 408 | expect(file.classes[0].isStatic).toBe(true); 409 | expect(file.classes[0].properties[0].isStatic).toBe(true); 410 | expect(file.classes[0].fields[0].isPublic).toBe(false); 411 | expect(file.classes[0].fields[0].isStatic).toBe(true); 412 | expect(file.classes[0].fields[1].isPublic).toBe(true); 413 | expect(file.classes[0].fields[1].isStatic).toBe(false); 414 | expect(file.classes[0].methods[0].isStatic).toBe(true); 415 | expect(file.classes[0].constructors[0].isPublic).toBe(true); 416 | expect(file.classes[0].constructors[0].isStatic).toBe(true); 417 | expect(file.classes[0].constructors[0].parameters[0].name).toBe("str"); 418 | expect(file.classes[0].constructors[0].parameters[0].type.name).toBe("string"); 419 | })); 420 | 421 | }); 422 | 423 | }); 424 | -------------------------------------------------------------------------------- /src/nearley/grammar.js: -------------------------------------------------------------------------------- 1 | // Generated automatically by nearley, version 2.16.0 2 | // http://github.com/Hardmath123/nearley 3 | (function () { 4 | function id(x) { return x[0]; } 5 | function rejecter(d, l, reject) { return reject; } 6 | function joiner(d) { return d.join(''); } var grammar = { 7 | Lexer: undefined, 8 | ParserRules: [ 9 | {"name": "main", "symbols": ["input"]}, 10 | {"name": "input$ebnf$1", "symbols": ["input_section"], "postprocess": id}, 11 | {"name": "input$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 12 | {"name": "input", "symbols": ["input$ebnf$1"]}, 13 | {"name": "input_section", "symbols": ["input_section_part"]}, 14 | {"name": "input_section", "symbols": ["input_section", "input_section_part"]}, 15 | {"name": "input_section_part$ebnf$1", "symbols": ["input_elements"], "postprocess": id}, 16 | {"name": "input_section_part$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 17 | {"name": "input_section_part", "symbols": ["input_section_part$ebnf$1", "new_line", "pp_directive"]}, 18 | {"name": "input_elements", "symbols": ["input_element", "input_elements", "input_element"]}, 19 | {"name": "input_element", "symbols": ["whitespace", "comment", "token"]}, 20 | {"name": "charriage_return_character", "symbols": [{"literal":"\r"}]}, 21 | {"name": "line_feed_character", "symbols": [{"literal":"\n"}]}, 22 | {"name": "next_line_character", "symbols": [{"literal":"…"}]}, 23 | {"name": "line_separator_character$string$1", "symbols": [{"literal":"\\"}, {"literal":"u"}, {"literal":"2"}, {"literal":"0"}, {"literal":"2"}, {"literal":"8"}], "postprocess": function joiner(d) {return d.join('');}}, 24 | {"name": "line_separator_character", "symbols": ["line_separator_character$string$1"]}, 25 | {"name": "paragraph_separator_character$string$1", "symbols": [{"literal":"\\"}, {"literal":"u"}, {"literal":"2"}, {"literal":"0"}, {"literal":"2"}, {"literal":"9"}], "postprocess": function joiner(d) {return d.join('');}}, 26 | {"name": "paragraph_separator_character", "symbols": ["paragraph_separator_character$string$1"]}, 27 | {"name": "new_line", "symbols": ["charriage_return_character"]}, 28 | {"name": "new_line", "symbols": ["line_feed_character"]}, 29 | {"name": "new_line", "symbols": ["charriage_return_character", "line_feed_character"]}, 30 | {"name": "new_line", "symbols": ["next_line_character"]}, 31 | {"name": "new_line", "symbols": ["line_separator_character"]}, 32 | {"name": "new_line", "symbols": ["paragraph_separator_character"]}, 33 | {"name": "comment", "symbols": ["single_line_comment"]}, 34 | {"name": "comment", "symbols": ["delimited_comment"]}, 35 | {"name": "single_line_comment$string$1", "symbols": [{"literal":"/"}, {"literal":"/"}], "postprocess": function joiner(d) {return d.join('');}}, 36 | {"name": "single_line_comment$ebnf$1", "symbols": ["input_characters"], "postprocess": id}, 37 | {"name": "single_line_comment$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 38 | {"name": "single_line_comment", "symbols": ["single_line_comment$string$1", "single_line_comment$ebnf$1"]}, 39 | {"name": "input_characters", "symbols": ["input_character"]}, 40 | {"name": "input_characters", "symbols": ["input_characters", "input_character"]}, 41 | {"name": "input_character", "symbols": ["new_line"], "postprocess": rejecter}, 42 | {"name": "input_character", "symbols": ["unicode_character"]}, 43 | {"name": "unicode_character", "symbols": [/[\u0000-\uFFFF]/]}, 44 | {"name": "new_line_character", "symbols": ["charriage_return_character"]}, 45 | {"name": "new_line_character", "symbols": ["line_feed_character"]}, 46 | {"name": "new_line_character", "symbols": ["next_line_character"]}, 47 | {"name": "new_line_character", "symbols": ["line_separator_character"]}, 48 | {"name": "new_line_character", "symbols": ["paragraph_separator_character"]}, 49 | {"name": "delimited_comment$string$1", "symbols": [{"literal":"/"}, {"literal":"*"}], "postprocess": function joiner(d) {return d.join('');}}, 50 | {"name": "delimited_comment$ebnf$1", "symbols": ["delimited_comment_text"], "postprocess": id}, 51 | {"name": "delimited_comment$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 52 | {"name": "delimited_comment", "symbols": ["delimited_comment$string$1", "delimited_comment$ebnf$1", "asterisks", {"literal":"/"}]}, 53 | {"name": "delimited_comment_text", "symbols": ["delimited_comment_section"]}, 54 | {"name": "delimited_comment_text", "symbols": ["delimited_comment_text", "delimited_comment_section"]}, 55 | {"name": "delimited_comment_section", "symbols": [{"literal":"/"}]}, 56 | {"name": "delimited_comment_section$ebnf$1", "symbols": ["asterisks"], "postprocess": id}, 57 | {"name": "delimited_comment_section$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 58 | {"name": "delimited_comment_section", "symbols": ["delimited_comment_section$ebnf$1", "not_slash_or_asterisk"]}, 59 | {"name": "asterisks", "symbols": [{"literal":"*"}]}, 60 | {"name": "asterisks", "symbols": ["asterisks", {"literal":"*"}]}, 61 | {"name": "not_slash_or_asterisk", "symbols": [{"literal":"/"}], "postprocess": rejecter}, 62 | {"name": "not_slash_or_asterisk", "symbols": [{"literal":"*"}], "postprocess": rejecter}, 63 | {"name": "not_slash_or_asterisk", "symbols": ["unicode_character"]}, 64 | {"name": "whitespace", "symbols": ["whitespace_character"]}, 65 | {"name": "whitespace", "symbols": ["whitespace", "whitespace_character"]}, 66 | {"name": "whitespace_character", "symbols": [/[\p{Z}]/]}, 67 | {"name": "whitespace_character", "symbols": ["horizontal_tab_character"]}, 68 | {"name": "whitespace_character", "symbols": ["vertical_tab_character"]}, 69 | {"name": "whitespace_character", "symbols": ["form_feed_character"]}, 70 | {"name": "horizontal_tab_character", "symbols": [{"literal":"\t"}]}, 71 | {"name": "vertical_tab_character", "symbols": [{"literal":"\u000b"}]}, 72 | {"name": "form_feed_character", "symbols": [{"literal":"\f"}]}, 73 | {"name": "token", "symbols": ["identifier"]}, 74 | {"name": "token", "symbols": ["keyword"]}, 75 | {"name": "token", "symbols": ["integer_literal"]}, 76 | {"name": "token", "symbols": ["real_literal"]}, 77 | {"name": "token", "symbols": ["character_literal"]}, 78 | {"name": "token", "symbols": ["string_literal"]}, 79 | {"name": "token", "symbols": ["operator_or_punctuator"]}, 80 | {"name": "unicode_escape_sequence$string$1", "symbols": [{"literal":"\\"}, {"literal":"u"}], "postprocess": function joiner(d) {return d.join('');}}, 81 | {"name": "unicode_escape_sequence$string$2", "symbols": [{"literal":"\\"}, {"literal":"U"}], "postprocess": function joiner(d) {return d.join('');}}, 82 | {"name": "unicode_escape_sequence", "symbols": ["unicode_escape_sequence$string$1", "hex_digit", "hex_digit", "hex_digit", "hex_digit", "unicode_escape_sequence$string$2", "hex_digit", "hex_digit", "hex_digit", "hex_digit", "hex_digit", "hex_digit", "hex_digit", "hex_digit"]}, 83 | {"name": "identifier", "symbols": ["available_identifier"]}, 84 | {"name": "identifier", "symbols": [{"literal":"@"}, "identifier_or_keyword"]}, 85 | {"name": "available_identifier", "symbols": ["keyword"], "postprocess": rejecter}, 86 | {"name": "available_identifier", "symbols": ["identifier_or_keyword"]}, 87 | {"name": "identifier_or_keyword$ebnf$1", "symbols": ["identifier_part_characters"], "postprocess": id}, 88 | {"name": "identifier_or_keyword$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 89 | {"name": "identifier_or_keyword", "symbols": ["identifier_start_character", "identifier_or_keyword$ebnf$1"]}, 90 | {"name": "identifier_start_character", "symbols": ["letter_character"]}, 91 | {"name": "identifier_start_character", "symbols": ["underscore_character"]}, 92 | {"name": "underscore_character", "symbols": [{"literal":"_"}]}, 93 | {"name": "identifier_part_characters", "symbols": ["identifier_part_character"]}, 94 | {"name": "identifier_part_characters", "symbols": ["identifier_part_characters", "identifier_part_character"]}, 95 | {"name": "identifier_part_character", "symbols": ["letter_character"]}, 96 | {"name": "identifier_part_character", "symbols": ["decimal_digit_character"]}, 97 | {"name": "identifier_part_character", "symbols": ["connecting_character"]}, 98 | {"name": "identifier_part_character", "symbols": ["combining_character"]}, 99 | {"name": "identifier_part_character", "symbols": ["formatting_character"]}, 100 | {"name": "letter_character", "symbols": [/[\p{Lu}]/]}, 101 | {"name": "letter_character", "symbols": [/[\p{Ll}]/]}, 102 | {"name": "letter_character", "symbols": [/[\p{Lt}]/]}, 103 | {"name": "letter_character", "symbols": [/[\p{Lm}]/]}, 104 | {"name": "letter_character", "symbols": [/[\p{Lo}]/]}, 105 | {"name": "letter_character", "symbols": [/[\p{Nl}]/]}, 106 | {"name": "combining_character", "symbols": [/[\p{Mn}]/]}, 107 | {"name": "combining_character", "symbols": [/[\p{Mc}]/]}, 108 | {"name": "decimal_digit_character", "symbols": [/[\p{Nd}]/]}, 109 | {"name": "connecting_character", "symbols": [/[\p{Pc}]/]}, 110 | {"name": "formatting_character", "symbols": [/[\p{Cf}]/]}, 111 | {"name": "keyword$string$1", "symbols": [{"literal":"a"}, {"literal":"b"}, {"literal":"s"}, {"literal":"t"}, {"literal":"r"}, {"literal":"a"}, {"literal":"c"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 112 | {"name": "keyword", "symbols": ["keyword$string$1"]}, 113 | {"name": "keyword$string$2", "symbols": [{"literal":"a"}, {"literal":"s"}], "postprocess": function joiner(d) {return d.join('');}}, 114 | {"name": "keyword", "symbols": ["keyword$string$2"]}, 115 | {"name": "keyword$string$3", "symbols": [{"literal":"b"}, {"literal":"a"}, {"literal":"s"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 116 | {"name": "keyword", "symbols": ["keyword$string$3"]}, 117 | {"name": "keyword$string$4", "symbols": [{"literal":"b"}, {"literal":"o"}, {"literal":"o"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 118 | {"name": "keyword", "symbols": ["keyword$string$4"]}, 119 | {"name": "keyword$string$5", "symbols": [{"literal":"b"}, {"literal":"r"}, {"literal":"e"}, {"literal":"a"}, {"literal":"k"}], "postprocess": function joiner(d) {return d.join('');}}, 120 | {"name": "keyword", "symbols": ["keyword$string$5"]}, 121 | {"name": "keyword$string$6", "symbols": [{"literal":"b"}, {"literal":"y"}, {"literal":"t"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 122 | {"name": "keyword", "symbols": ["keyword$string$6"]}, 123 | {"name": "keyword$string$7", "symbols": [{"literal":"c"}, {"literal":"a"}, {"literal":"s"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 124 | {"name": "keyword", "symbols": ["keyword$string$7"]}, 125 | {"name": "keyword$string$8", "symbols": [{"literal":"c"}, {"literal":"a"}, {"literal":"t"}, {"literal":"c"}, {"literal":"h"}], "postprocess": function joiner(d) {return d.join('');}}, 126 | {"name": "keyword", "symbols": ["keyword$string$8"]}, 127 | {"name": "keyword$string$9", "symbols": [{"literal":"c"}, {"literal":"h"}, {"literal":"a"}, {"literal":"r"}], "postprocess": function joiner(d) {return d.join('');}}, 128 | {"name": "keyword", "symbols": ["keyword$string$9"]}, 129 | {"name": "keyword$string$10", "symbols": [{"literal":"c"}, {"literal":"h"}, {"literal":"e"}, {"literal":"c"}, {"literal":"k"}, {"literal":"e"}, {"literal":"d"}], "postprocess": function joiner(d) {return d.join('');}}, 130 | {"name": "keyword", "symbols": ["keyword$string$10"]}, 131 | {"name": "keyword$string$11", "symbols": [{"literal":"c"}, {"literal":"l"}, {"literal":"a"}, {"literal":"s"}, {"literal":"s"}], "postprocess": function joiner(d) {return d.join('');}}, 132 | {"name": "keyword", "symbols": ["keyword$string$11"]}, 133 | {"name": "keyword$string$12", "symbols": [{"literal":"c"}, {"literal":"o"}, {"literal":"n"}, {"literal":"s"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 134 | {"name": "keyword", "symbols": ["keyword$string$12"]}, 135 | {"name": "keyword$string$13", "symbols": [{"literal":"c"}, {"literal":"o"}, {"literal":"n"}, {"literal":"t"}, {"literal":"i"}, {"literal":"n"}, {"literal":"u"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 136 | {"name": "keyword", "symbols": ["keyword$string$13"]}, 137 | {"name": "keyword$string$14", "symbols": [{"literal":"d"}, {"literal":"e"}, {"literal":"c"}, {"literal":"i"}, {"literal":"m"}, {"literal":"a"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 138 | {"name": "keyword", "symbols": ["keyword$string$14"]}, 139 | {"name": "keyword$string$15", "symbols": [{"literal":"d"}, {"literal":"e"}, {"literal":"f"}, {"literal":"a"}, {"literal":"u"}, {"literal":"l"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 140 | {"name": "keyword", "symbols": ["keyword$string$15"]}, 141 | {"name": "keyword$string$16", "symbols": [{"literal":"d"}, {"literal":"e"}, {"literal":"l"}, {"literal":"e"}, {"literal":"g"}, {"literal":"a"}, {"literal":"t"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 142 | {"name": "keyword", "symbols": ["keyword$string$16"]}, 143 | {"name": "keyword$string$17", "symbols": [{"literal":"d"}, {"literal":"o"}], "postprocess": function joiner(d) {return d.join('');}}, 144 | {"name": "keyword", "symbols": ["keyword$string$17"]}, 145 | {"name": "keyword$string$18", "symbols": [{"literal":"d"}, {"literal":"o"}, {"literal":"u"}, {"literal":"b"}, {"literal":"l"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 146 | {"name": "keyword", "symbols": ["keyword$string$18"]}, 147 | {"name": "keyword$string$19", "symbols": [{"literal":"e"}, {"literal":"l"}, {"literal":"s"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 148 | {"name": "keyword", "symbols": ["keyword$string$19"]}, 149 | {"name": "keyword$string$20", "symbols": [{"literal":"e"}, {"literal":"n"}, {"literal":"u"}, {"literal":"m"}], "postprocess": function joiner(d) {return d.join('');}}, 150 | {"name": "keyword", "symbols": ["keyword$string$20"]}, 151 | {"name": "keyword$string$21", "symbols": [{"literal":"e"}, {"literal":"v"}, {"literal":"e"}, {"literal":"n"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 152 | {"name": "keyword", "symbols": ["keyword$string$21"]}, 153 | {"name": "keyword$string$22", "symbols": [{"literal":"e"}, {"literal":"x"}, {"literal":"p"}, {"literal":"l"}, {"literal":"i"}, {"literal":"c"}, {"literal":"i"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 154 | {"name": "keyword", "symbols": ["keyword$string$22"]}, 155 | {"name": "keyword$string$23", "symbols": [{"literal":"e"}, {"literal":"x"}, {"literal":"t"}, {"literal":"e"}, {"literal":"r"}, {"literal":"n"}], "postprocess": function joiner(d) {return d.join('');}}, 156 | {"name": "keyword", "symbols": ["keyword$string$23"]}, 157 | {"name": "keyword$string$24", "symbols": [{"literal":"f"}, {"literal":"a"}, {"literal":"l"}, {"literal":"s"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 158 | {"name": "keyword", "symbols": ["keyword$string$24"]}, 159 | {"name": "keyword$string$25", "symbols": [{"literal":"f"}, {"literal":"i"}, {"literal":"n"}, {"literal":"a"}, {"literal":"l"}, {"literal":"l"}, {"literal":"y"}], "postprocess": function joiner(d) {return d.join('');}}, 160 | {"name": "keyword", "symbols": ["keyword$string$25"]}, 161 | {"name": "keyword$string$26", "symbols": [{"literal":"f"}, {"literal":"i"}, {"literal":"x"}, {"literal":"e"}, {"literal":"d"}], "postprocess": function joiner(d) {return d.join('');}}, 162 | {"name": "keyword", "symbols": ["keyword$string$26"]}, 163 | {"name": "keyword$string$27", "symbols": [{"literal":"f"}, {"literal":"l"}, {"literal":"o"}, {"literal":"a"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 164 | {"name": "keyword", "symbols": ["keyword$string$27"]}, 165 | {"name": "keyword$string$28", "symbols": [{"literal":"f"}, {"literal":"o"}, {"literal":"r"}], "postprocess": function joiner(d) {return d.join('');}}, 166 | {"name": "keyword", "symbols": ["keyword$string$28"]}, 167 | {"name": "keyword$string$29", "symbols": [{"literal":"f"}, {"literal":"o"}, {"literal":"r"}, {"literal":"e"}, {"literal":"a"}, {"literal":"c"}, {"literal":"h"}], "postprocess": function joiner(d) {return d.join('');}}, 168 | {"name": "keyword", "symbols": ["keyword$string$29"]}, 169 | {"name": "keyword$string$30", "symbols": [{"literal":"g"}, {"literal":"o"}, {"literal":"t"}, {"literal":"o"}], "postprocess": function joiner(d) {return d.join('');}}, 170 | {"name": "keyword", "symbols": ["keyword$string$30"]}, 171 | {"name": "keyword$string$31", "symbols": [{"literal":"i"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 172 | {"name": "keyword", "symbols": ["keyword$string$31"]}, 173 | {"name": "keyword$string$32", "symbols": [{"literal":"i"}, {"literal":"m"}, {"literal":"p"}, {"literal":"l"}, {"literal":"i"}, {"literal":"c"}, {"literal":"i"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 174 | {"name": "keyword", "symbols": ["keyword$string$32"]}, 175 | {"name": "keyword$string$33", "symbols": [{"literal":"i"}, {"literal":"n"}], "postprocess": function joiner(d) {return d.join('');}}, 176 | {"name": "keyword", "symbols": ["keyword$string$33"]}, 177 | {"name": "keyword$string$34", "symbols": [{"literal":"i"}, {"literal":"n"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 178 | {"name": "keyword", "symbols": ["keyword$string$34"]}, 179 | {"name": "keyword$string$35", "symbols": [{"literal":"i"}, {"literal":"n"}, {"literal":"t"}, {"literal":"e"}, {"literal":"r"}, {"literal":"f"}, {"literal":"a"}, {"literal":"c"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 180 | {"name": "keyword", "symbols": ["keyword$string$35"]}, 181 | {"name": "keyword$string$36", "symbols": [{"literal":"i"}, {"literal":"n"}, {"literal":"t"}, {"literal":"e"}, {"literal":"r"}, {"literal":"n"}, {"literal":"a"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 182 | {"name": "keyword", "symbols": ["keyword$string$36"]}, 183 | {"name": "keyword$string$37", "symbols": [{"literal":"i"}, {"literal":"s"}], "postprocess": function joiner(d) {return d.join('');}}, 184 | {"name": "keyword", "symbols": ["keyword$string$37"]}, 185 | {"name": "keyword$string$38", "symbols": [{"literal":"l"}, {"literal":"o"}, {"literal":"c"}, {"literal":"k"}], "postprocess": function joiner(d) {return d.join('');}}, 186 | {"name": "keyword", "symbols": ["keyword$string$38"]}, 187 | {"name": "keyword$string$39", "symbols": [{"literal":"l"}, {"literal":"o"}, {"literal":"n"}, {"literal":"g"}], "postprocess": function joiner(d) {return d.join('');}}, 188 | {"name": "keyword", "symbols": ["keyword$string$39"]}, 189 | {"name": "keyword$string$40", "symbols": [{"literal":"n"}, {"literal":"a"}, {"literal":"m"}, {"literal":"e"}, {"literal":"s"}, {"literal":"p"}, {"literal":"a"}, {"literal":"c"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 190 | {"name": "keyword", "symbols": ["keyword$string$40"]}, 191 | {"name": "keyword$string$41", "symbols": [{"literal":"n"}, {"literal":"e"}, {"literal":"w"}], "postprocess": function joiner(d) {return d.join('');}}, 192 | {"name": "keyword", "symbols": ["keyword$string$41"]}, 193 | {"name": "keyword$string$42", "symbols": [{"literal":"n"}, {"literal":"u"}, {"literal":"l"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 194 | {"name": "keyword", "symbols": ["keyword$string$42"]}, 195 | {"name": "keyword$string$43", "symbols": [{"literal":"o"}, {"literal":"b"}, {"literal":"j"}, {"literal":"e"}, {"literal":"c"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 196 | {"name": "keyword", "symbols": ["keyword$string$43"]}, 197 | {"name": "keyword$string$44", "symbols": [{"literal":"o"}, {"literal":"p"}, {"literal":"e"}, {"literal":"r"}, {"literal":"a"}, {"literal":"t"}, {"literal":"o"}, {"literal":"r"}], "postprocess": function joiner(d) {return d.join('');}}, 198 | {"name": "keyword", "symbols": ["keyword$string$44"]}, 199 | {"name": "keyword$string$45", "symbols": [{"literal":"o"}, {"literal":"u"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 200 | {"name": "keyword", "symbols": ["keyword$string$45"]}, 201 | {"name": "keyword$string$46", "symbols": [{"literal":"o"}, {"literal":"v"}, {"literal":"e"}, {"literal":"r"}, {"literal":"r"}, {"literal":"i"}, {"literal":"d"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 202 | {"name": "keyword", "symbols": ["keyword$string$46"]}, 203 | {"name": "keyword$string$47", "symbols": [{"literal":"p"}, {"literal":"a"}, {"literal":"r"}, {"literal":"a"}, {"literal":"m"}, {"literal":"s"}], "postprocess": function joiner(d) {return d.join('');}}, 204 | {"name": "keyword", "symbols": ["keyword$string$47"]}, 205 | {"name": "keyword$string$48", "symbols": [{"literal":"p"}, {"literal":"r"}, {"literal":"i"}, {"literal":"v"}, {"literal":"a"}, {"literal":"t"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 206 | {"name": "keyword", "symbols": ["keyword$string$48"]}, 207 | {"name": "keyword$string$49", "symbols": [{"literal":"p"}, {"literal":"r"}, {"literal":"o"}, {"literal":"t"}, {"literal":"e"}, {"literal":"c"}, {"literal":"t"}, {"literal":"e"}, {"literal":"d"}], "postprocess": function joiner(d) {return d.join('');}}, 208 | {"name": "keyword", "symbols": ["keyword$string$49"]}, 209 | {"name": "keyword$string$50", "symbols": [{"literal":"p"}, {"literal":"u"}, {"literal":"b"}, {"literal":"l"}, {"literal":"i"}, {"literal":"c"}], "postprocess": function joiner(d) {return d.join('');}}, 210 | {"name": "keyword", "symbols": ["keyword$string$50"]}, 211 | {"name": "keyword$string$51", "symbols": [{"literal":"r"}, {"literal":"e"}, {"literal":"a"}, {"literal":"d"}, {"literal":"o"}, {"literal":"n"}, {"literal":"l"}, {"literal":"y"}], "postprocess": function joiner(d) {return d.join('');}}, 212 | {"name": "keyword", "symbols": ["keyword$string$51"]}, 213 | {"name": "keyword$string$52", "symbols": [{"literal":"r"}, {"literal":"e"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 214 | {"name": "keyword", "symbols": ["keyword$string$52"]}, 215 | {"name": "keyword$string$53", "symbols": [{"literal":"r"}, {"literal":"e"}, {"literal":"t"}, {"literal":"u"}, {"literal":"r"}, {"literal":"n"}], "postprocess": function joiner(d) {return d.join('');}}, 216 | {"name": "keyword", "symbols": ["keyword$string$53"]}, 217 | {"name": "keyword$string$54", "symbols": [{"literal":"s"}, {"literal":"b"}, {"literal":"y"}, {"literal":"t"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 218 | {"name": "keyword", "symbols": ["keyword$string$54"]}, 219 | {"name": "keyword$string$55", "symbols": [{"literal":"s"}, {"literal":"e"}, {"literal":"a"}, {"literal":"l"}, {"literal":"e"}, {"literal":"d"}], "postprocess": function joiner(d) {return d.join('');}}, 220 | {"name": "keyword", "symbols": ["keyword$string$55"]}, 221 | {"name": "keyword$string$56", "symbols": [{"literal":"s"}, {"literal":"h"}, {"literal":"o"}, {"literal":"r"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 222 | {"name": "keyword", "symbols": ["keyword$string$56"]}, 223 | {"name": "keyword$string$57", "symbols": [{"literal":"s"}, {"literal":"i"}, {"literal":"z"}, {"literal":"e"}, {"literal":"o"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 224 | {"name": "keyword", "symbols": ["keyword$string$57"]}, 225 | {"name": "keyword$string$58", "symbols": [{"literal":"s"}, {"literal":"t"}, {"literal":"a"}, {"literal":"c"}, {"literal":"k"}, {"literal":"a"}, {"literal":"l"}, {"literal":"l"}, {"literal":"o"}, {"literal":"c"}], "postprocess": function joiner(d) {return d.join('');}}, 226 | {"name": "keyword", "symbols": ["keyword$string$58"]}, 227 | {"name": "keyword$string$59", "symbols": [{"literal":"s"}, {"literal":"t"}, {"literal":"a"}, {"literal":"t"}, {"literal":"i"}, {"literal":"c"}], "postprocess": function joiner(d) {return d.join('');}}, 228 | {"name": "keyword", "symbols": ["keyword$string$59"]}, 229 | {"name": "keyword$string$60", "symbols": [{"literal":"s"}, {"literal":"t"}, {"literal":"r"}, {"literal":"i"}, {"literal":"n"}, {"literal":"g"}], "postprocess": function joiner(d) {return d.join('');}}, 230 | {"name": "keyword", "symbols": ["keyword$string$60"]}, 231 | {"name": "keyword$string$61", "symbols": [{"literal":"s"}, {"literal":"t"}, {"literal":"r"}, {"literal":"u"}, {"literal":"c"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 232 | {"name": "keyword", "symbols": ["keyword$string$61"]}, 233 | {"name": "keyword$string$62", "symbols": [{"literal":"s"}, {"literal":"w"}, {"literal":"i"}, {"literal":"t"}, {"literal":"c"}, {"literal":"h"}], "postprocess": function joiner(d) {return d.join('');}}, 234 | {"name": "keyword", "symbols": ["keyword$string$62"]}, 235 | {"name": "keyword$string$63", "symbols": [{"literal":"t"}, {"literal":"h"}, {"literal":"i"}, {"literal":"s"}], "postprocess": function joiner(d) {return d.join('');}}, 236 | {"name": "keyword", "symbols": ["keyword$string$63"]}, 237 | {"name": "keyword$string$64", "symbols": [{"literal":"t"}, {"literal":"h"}, {"literal":"r"}, {"literal":"o"}, {"literal":"w"}], "postprocess": function joiner(d) {return d.join('');}}, 238 | {"name": "keyword", "symbols": ["keyword$string$64"]}, 239 | {"name": "keyword$string$65", "symbols": [{"literal":"t"}, {"literal":"r"}, {"literal":"u"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 240 | {"name": "keyword", "symbols": ["keyword$string$65"]}, 241 | {"name": "keyword$string$66", "symbols": [{"literal":"t"}, {"literal":"r"}, {"literal":"y"}], "postprocess": function joiner(d) {return d.join('');}}, 242 | {"name": "keyword", "symbols": ["keyword$string$66"]}, 243 | {"name": "keyword$string$67", "symbols": [{"literal":"t"}, {"literal":"y"}, {"literal":"p"}, {"literal":"e"}, {"literal":"o"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 244 | {"name": "keyword", "symbols": ["keyword$string$67"]}, 245 | {"name": "keyword$string$68", "symbols": [{"literal":"u"}, {"literal":"i"}, {"literal":"n"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 246 | {"name": "keyword", "symbols": ["keyword$string$68"]}, 247 | {"name": "keyword$string$69", "symbols": [{"literal":"u"}, {"literal":"l"}, {"literal":"o"}, {"literal":"n"}, {"literal":"g"}], "postprocess": function joiner(d) {return d.join('');}}, 248 | {"name": "keyword", "symbols": ["keyword$string$69"]}, 249 | {"name": "keyword$string$70", "symbols": [{"literal":"u"}, {"literal":"n"}, {"literal":"c"}, {"literal":"h"}, {"literal":"e"}, {"literal":"c"}, {"literal":"k"}, {"literal":"e"}, {"literal":"d"}], "postprocess": function joiner(d) {return d.join('');}}, 250 | {"name": "keyword", "symbols": ["keyword$string$70"]}, 251 | {"name": "keyword$string$71", "symbols": [{"literal":"u"}, {"literal":"n"}, {"literal":"s"}, {"literal":"a"}, {"literal":"f"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 252 | {"name": "keyword", "symbols": ["keyword$string$71"]}, 253 | {"name": "keyword$string$72", "symbols": [{"literal":"u"}, {"literal":"s"}, {"literal":"h"}, {"literal":"o"}, {"literal":"r"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 254 | {"name": "keyword", "symbols": ["keyword$string$72"]}, 255 | {"name": "keyword$string$73", "symbols": [{"literal":"u"}, {"literal":"s"}, {"literal":"i"}, {"literal":"n"}, {"literal":"g"}], "postprocess": function joiner(d) {return d.join('');}}, 256 | {"name": "keyword", "symbols": ["keyword$string$73"]}, 257 | {"name": "keyword$string$74", "symbols": [{"literal":"v"}, {"literal":"i"}, {"literal":"r"}, {"literal":"t"}, {"literal":"u"}, {"literal":"a"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 258 | {"name": "keyword", "symbols": ["keyword$string$74"]}, 259 | {"name": "keyword$string$75", "symbols": [{"literal":"v"}, {"literal":"o"}, {"literal":"i"}, {"literal":"d"}], "postprocess": function joiner(d) {return d.join('');}}, 260 | {"name": "keyword", "symbols": ["keyword$string$75"]}, 261 | {"name": "keyword$string$76", "symbols": [{"literal":"v"}, {"literal":"o"}, {"literal":"l"}, {"literal":"a"}, {"literal":"t"}, {"literal":"i"}, {"literal":"l"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 262 | {"name": "keyword", "symbols": ["keyword$string$76"]}, 263 | {"name": "keyword$string$77", "symbols": [{"literal":"w"}, {"literal":"h"}, {"literal":"i"}, {"literal":"l"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 264 | {"name": "keyword", "symbols": ["keyword$string$77"]}, 265 | {"name": "contextual_keyword$string$1", "symbols": [{"literal":"a"}, {"literal":"d"}, {"literal":"d"}], "postprocess": function joiner(d) {return d.join('');}}, 266 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$1"]}, 267 | {"name": "contextual_keyword$string$2", "symbols": [{"literal":"a"}, {"literal":"l"}, {"literal":"i"}, {"literal":"a"}, {"literal":"s"}], "postprocess": function joiner(d) {return d.join('');}}, 268 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$2"]}, 269 | {"name": "contextual_keyword$string$3", "symbols": [{"literal":"a"}, {"literal":"s"}, {"literal":"c"}, {"literal":"e"}, {"literal":"n"}, {"literal":"d"}, {"literal":"i"}, {"literal":"n"}, {"literal":"g"}], "postprocess": function joiner(d) {return d.join('');}}, 270 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$3"]}, 271 | {"name": "contextual_keyword$string$4", "symbols": [{"literal":"a"}, {"literal":"s"}, {"literal":"y"}, {"literal":"n"}, {"literal":"c"}], "postprocess": function joiner(d) {return d.join('');}}, 272 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$4"]}, 273 | {"name": "contextual_keyword$string$5", "symbols": [{"literal":"a"}, {"literal":"w"}, {"literal":"a"}, {"literal":"i"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 274 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$5"]}, 275 | {"name": "contextual_keyword$string$6", "symbols": [{"literal":"b"}, {"literal":"y"}], "postprocess": function joiner(d) {return d.join('');}}, 276 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$6"]}, 277 | {"name": "contextual_keyword$string$7", "symbols": [{"literal":"d"}, {"literal":"e"}, {"literal":"s"}, {"literal":"c"}, {"literal":"e"}, {"literal":"n"}, {"literal":"d"}, {"literal":"i"}, {"literal":"n"}, {"literal":"g"}], "postprocess": function joiner(d) {return d.join('');}}, 278 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$7"]}, 279 | {"name": "contextual_keyword$string$8", "symbols": [{"literal":"d"}, {"literal":"y"}, {"literal":"n"}, {"literal":"a"}, {"literal":"m"}, {"literal":"i"}, {"literal":"c"}], "postprocess": function joiner(d) {return d.join('');}}, 280 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$8"]}, 281 | {"name": "contextual_keyword$string$9", "symbols": [{"literal":"e"}, {"literal":"q"}, {"literal":"u"}, {"literal":"a"}, {"literal":"l"}, {"literal":"s"}], "postprocess": function joiner(d) {return d.join('');}}, 282 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$9"]}, 283 | {"name": "contextual_keyword$string$10", "symbols": [{"literal":"f"}, {"literal":"r"}, {"literal":"o"}, {"literal":"m"}], "postprocess": function joiner(d) {return d.join('');}}, 284 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$10"]}, 285 | {"name": "contextual_keyword$string$11", "symbols": [{"literal":"g"}, {"literal":"e"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 286 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$11"]}, 287 | {"name": "contextual_keyword$string$12", "symbols": [{"literal":"g"}, {"literal":"l"}, {"literal":"o"}, {"literal":"b"}, {"literal":"a"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 288 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$12"]}, 289 | {"name": "contextual_keyword$string$13", "symbols": [{"literal":"g"}, {"literal":"r"}, {"literal":"o"}, {"literal":"u"}, {"literal":"p"}], "postprocess": function joiner(d) {return d.join('');}}, 290 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$13"]}, 291 | {"name": "contextual_keyword$string$14", "symbols": [{"literal":"i"}, {"literal":"n"}, {"literal":"t"}, {"literal":"o"}], "postprocess": function joiner(d) {return d.join('');}}, 292 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$14"]}, 293 | {"name": "contextual_keyword$string$15", "symbols": [{"literal":"j"}, {"literal":"o"}, {"literal":"i"}, {"literal":"n"}], "postprocess": function joiner(d) {return d.join('');}}, 294 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$15"]}, 295 | {"name": "contextual_keyword$string$16", "symbols": [{"literal":"l"}, {"literal":"e"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 296 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$16"]}, 297 | {"name": "contextual_keyword$string$17", "symbols": [{"literal":"o"}, {"literal":"r"}, {"literal":"d"}, {"literal":"e"}, {"literal":"r"}, {"literal":"b"}, {"literal":"y"}], "postprocess": function joiner(d) {return d.join('');}}, 298 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$17"]}, 299 | {"name": "contextual_keyword$string$18", "symbols": [{"literal":"p"}, {"literal":"a"}, {"literal":"r"}, {"literal":"t"}, {"literal":"i"}, {"literal":"a"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 300 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$18"]}, 301 | {"name": "contextual_keyword$string$19", "symbols": [{"literal":"r"}, {"literal":"e"}, {"literal":"m"}, {"literal":"o"}, {"literal":"v"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 302 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$19"]}, 303 | {"name": "contextual_keyword$string$20", "symbols": [{"literal":"s"}, {"literal":"e"}, {"literal":"l"}, {"literal":"e"}, {"literal":"c"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 304 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$20"]}, 305 | {"name": "contextual_keyword$string$21", "symbols": [{"literal":"s"}, {"literal":"e"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 306 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$21"]}, 307 | {"name": "contextual_keyword$string$22", "symbols": [{"literal":"v"}, {"literal":"a"}, {"literal":"l"}, {"literal":"u"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 308 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$22"]}, 309 | {"name": "contextual_keyword$string$23", "symbols": [{"literal":"v"}, {"literal":"a"}, {"literal":"r"}], "postprocess": function joiner(d) {return d.join('');}}, 310 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$23"]}, 311 | {"name": "contextual_keyword$string$24", "symbols": [{"literal":"w"}, {"literal":"h"}, {"literal":"e"}, {"literal":"r"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 312 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$24"]}, 313 | {"name": "contextual_keyword$string$25", "symbols": [{"literal":"y"}, {"literal":"i"}, {"literal":"e"}, {"literal":"l"}, {"literal":"d"}], "postprocess": function joiner(d) {return d.join('');}}, 314 | {"name": "contextual_keyword", "symbols": ["contextual_keyword$string$25"]}, 315 | {"name": "literal", "symbols": ["boolean_literal"]}, 316 | {"name": "literal", "symbols": ["integer_literal"]}, 317 | {"name": "literal", "symbols": ["real_literal"]}, 318 | {"name": "literal", "symbols": ["character_literal"]}, 319 | {"name": "literal", "symbols": ["string_literal"]}, 320 | {"name": "literal", "symbols": ["null_literal"]}, 321 | {"name": "boolean_literal$string$1", "symbols": [{"literal":"t"}, {"literal":"r"}, {"literal":"u"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 322 | {"name": "boolean_literal", "symbols": ["boolean_literal$string$1"]}, 323 | {"name": "boolean_literal$string$2", "symbols": [{"literal":"f"}, {"literal":"a"}, {"literal":"l"}, {"literal":"s"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 324 | {"name": "boolean_literal", "symbols": ["boolean_literal$string$2"]}, 325 | {"name": "integer_literal", "symbols": ["decimal_integer_literal"]}, 326 | {"name": "integer_literal", "symbols": ["hexadecimal_integer_literal"]}, 327 | {"name": "decimal_integer_literal$ebnf$1", "symbols": ["integer_type_suffix"], "postprocess": id}, 328 | {"name": "decimal_integer_literal$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 329 | {"name": "decimal_integer_literal", "symbols": ["decimal_digits", "decimal_integer_literal$ebnf$1"]}, 330 | {"name": "decimal_digits", "symbols": ["decimal_digit"]}, 331 | {"name": "decimal_digits", "symbols": ["decimal_digits", "decimal_digit"]}, 332 | {"name": "decimal_digit", "symbols": [{"literal":"0"}]}, 333 | {"name": "decimal_digit", "symbols": [{"literal":"1"}]}, 334 | {"name": "decimal_digit", "symbols": [{"literal":"2"}]}, 335 | {"name": "decimal_digit", "symbols": [{"literal":"3"}]}, 336 | {"name": "decimal_digit", "symbols": [{"literal":"4"}]}, 337 | {"name": "decimal_digit", "symbols": [{"literal":"5"}]}, 338 | {"name": "decimal_digit", "symbols": [{"literal":"6"}]}, 339 | {"name": "decimal_digit", "symbols": [{"literal":"7"}]}, 340 | {"name": "decimal_digit", "symbols": [{"literal":"8"}]}, 341 | {"name": "decimal_digit", "symbols": [{"literal":"9"}]}, 342 | {"name": "integer_type_suffix", "symbols": [{"literal":"U"}]}, 343 | {"name": "integer_type_suffix", "symbols": [{"literal":"u"}]}, 344 | {"name": "integer_type_suffix", "symbols": [{"literal":"L"}]}, 345 | {"name": "integer_type_suffix", "symbols": [{"literal":"l"}]}, 346 | {"name": "integer_type_suffix$string$1", "symbols": [{"literal":"U"}, {"literal":"L"}], "postprocess": function joiner(d) {return d.join('');}}, 347 | {"name": "integer_type_suffix", "symbols": ["integer_type_suffix$string$1"]}, 348 | {"name": "integer_type_suffix$string$2", "symbols": [{"literal":"U"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 349 | {"name": "integer_type_suffix", "symbols": ["integer_type_suffix$string$2"]}, 350 | {"name": "integer_type_suffix$string$3", "symbols": [{"literal":"u"}, {"literal":"L"}], "postprocess": function joiner(d) {return d.join('');}}, 351 | {"name": "integer_type_suffix", "symbols": ["integer_type_suffix$string$3"]}, 352 | {"name": "integer_type_suffix$string$4", "symbols": [{"literal":"u"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 353 | {"name": "integer_type_suffix", "symbols": ["integer_type_suffix$string$4"]}, 354 | {"name": "integer_type_suffix$string$5", "symbols": [{"literal":"L"}, {"literal":"U"}], "postprocess": function joiner(d) {return d.join('');}}, 355 | {"name": "integer_type_suffix", "symbols": ["integer_type_suffix$string$5"]}, 356 | {"name": "integer_type_suffix$string$6", "symbols": [{"literal":"L"}, {"literal":"u"}], "postprocess": function joiner(d) {return d.join('');}}, 357 | {"name": "integer_type_suffix", "symbols": ["integer_type_suffix$string$6"]}, 358 | {"name": "integer_type_suffix$string$7", "symbols": [{"literal":"l"}, {"literal":"U"}], "postprocess": function joiner(d) {return d.join('');}}, 359 | {"name": "integer_type_suffix", "symbols": ["integer_type_suffix$string$7"]}, 360 | {"name": "integer_type_suffix$string$8", "symbols": [{"literal":"l"}, {"literal":"u"}], "postprocess": function joiner(d) {return d.join('');}}, 361 | {"name": "integer_type_suffix", "symbols": ["integer_type_suffix$string$8"]}, 362 | {"name": "hexadecimal_integer_literal$string$1", "symbols": [{"literal":"0"}, {"literal":"x"}], "postprocess": function joiner(d) {return d.join('');}}, 363 | {"name": "hexadecimal_integer_literal$ebnf$1", "symbols": ["integer_type_suffix"], "postprocess": id}, 364 | {"name": "hexadecimal_integer_literal$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 365 | {"name": "hexadecimal_integer_literal", "symbols": ["hexadecimal_integer_literal$string$1", "hex_digits", "hexadecimal_integer_literal$ebnf$1"]}, 366 | {"name": "hexadecimal_integer_literal$string$2", "symbols": [{"literal":"0"}, {"literal":"X"}], "postprocess": function joiner(d) {return d.join('');}}, 367 | {"name": "hexadecimal_integer_literal$ebnf$2", "symbols": ["integer_type_suffix"], "postprocess": id}, 368 | {"name": "hexadecimal_integer_literal$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 369 | {"name": "hexadecimal_integer_literal", "symbols": ["hexadecimal_integer_literal$string$2", "hex_digits", "hexadecimal_integer_literal$ebnf$2"]}, 370 | {"name": "hex_digits", "symbols": ["hex_digit"]}, 371 | {"name": "hex_digits", "symbols": ["hex_digits", "hex_digit"]}, 372 | {"name": "hex_digit", "symbols": [{"literal":"0"}]}, 373 | {"name": "hex_digit", "symbols": [{"literal":"1"}]}, 374 | {"name": "hex_digit", "symbols": [{"literal":"2"}]}, 375 | {"name": "hex_digit", "symbols": [{"literal":"3"}]}, 376 | {"name": "hex_digit", "symbols": [{"literal":"4"}]}, 377 | {"name": "hex_digit", "symbols": [{"literal":"5"}]}, 378 | {"name": "hex_digit", "symbols": [{"literal":"6"}]}, 379 | {"name": "hex_digit", "symbols": [{"literal":"7"}]}, 380 | {"name": "hex_digit", "symbols": [{"literal":"8"}]}, 381 | {"name": "hex_digit", "symbols": [{"literal":"9"}]}, 382 | {"name": "hex_digit", "symbols": [{"literal":"A"}]}, 383 | {"name": "hex_digit", "symbols": [{"literal":"B"}]}, 384 | {"name": "hex_digit", "symbols": [{"literal":"C"}]}, 385 | {"name": "hex_digit", "symbols": [{"literal":"D"}]}, 386 | {"name": "hex_digit", "symbols": [{"literal":"E"}]}, 387 | {"name": "hex_digit", "symbols": [{"literal":"F"}]}, 388 | {"name": "hex_digit", "symbols": [{"literal":"a"}]}, 389 | {"name": "hex_digit", "symbols": [{"literal":"b"}]}, 390 | {"name": "hex_digit", "symbols": [{"literal":"c"}]}, 391 | {"name": "hex_digit", "symbols": [{"literal":"d"}]}, 392 | {"name": "hex_digit", "symbols": [{"literal":"e"}]}, 393 | {"name": "hex_digit", "symbols": [{"literal":"f"}]}, 394 | {"name": "real_literal$ebnf$1", "symbols": ["exponent_part"], "postprocess": id}, 395 | {"name": "real_literal$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 396 | {"name": "real_literal$ebnf$2", "symbols": ["real_type_suffix"], "postprocess": id}, 397 | {"name": "real_literal$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 398 | {"name": "real_literal", "symbols": ["decimal_digits", {"literal":"."}, "decimal_digits", "real_literal$ebnf$1", "real_literal$ebnf$2"]}, 399 | {"name": "real_literal$ebnf$3", "symbols": ["exponent_part"], "postprocess": id}, 400 | {"name": "real_literal$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}}, 401 | {"name": "real_literal$ebnf$4", "symbols": ["real_type_suffix"], "postprocess": id}, 402 | {"name": "real_literal$ebnf$4", "symbols": [], "postprocess": function(d) {return null;}}, 403 | {"name": "real_literal", "symbols": [{"literal":"."}, "decimal_digits", "real_literal$ebnf$3", "real_literal$ebnf$4"]}, 404 | {"name": "real_literal$ebnf$5", "symbols": ["real_type_suffix"], "postprocess": id}, 405 | {"name": "real_literal$ebnf$5", "symbols": [], "postprocess": function(d) {return null;}}, 406 | {"name": "real_literal", "symbols": ["decimal_digits", "exponent_part", "real_literal$ebnf$5"]}, 407 | {"name": "real_literal", "symbols": ["decimal_digits", "real_type_suffix"]}, 408 | {"name": "exponent_part$ebnf$1", "symbols": ["sign"], "postprocess": id}, 409 | {"name": "exponent_part$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 410 | {"name": "exponent_part", "symbols": [{"literal":"e"}, "exponent_part$ebnf$1", "decimal_digits"]}, 411 | {"name": "exponent_part$ebnf$2", "symbols": ["sign"], "postprocess": id}, 412 | {"name": "exponent_part$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 413 | {"name": "exponent_part", "symbols": [{"literal":"E"}, "exponent_part$ebnf$2", "decimal_digits"]}, 414 | {"name": "sign", "symbols": [{"literal":"+"}]}, 415 | {"name": "sign", "symbols": [{"literal":"-"}]}, 416 | {"name": "real_type_suffix", "symbols": [{"literal":"F"}]}, 417 | {"name": "real_type_suffix", "symbols": [{"literal":"f"}]}, 418 | {"name": "real_type_suffix", "symbols": [{"literal":"D"}]}, 419 | {"name": "real_type_suffix", "symbols": [{"literal":"d"}]}, 420 | {"name": "real_type_suffix", "symbols": [{"literal":"M"}]}, 421 | {"name": "real_type_suffix", "symbols": [{"literal":"m"}]}, 422 | {"name": "character_literal", "symbols": [{"literal":"'"}, "character", {"literal":"'"}]}, 423 | {"name": "character", "symbols": ["single_character"]}, 424 | {"name": "character", "symbols": ["simple_escape_sequence"]}, 425 | {"name": "character", "symbols": ["hexadecimal_escape_sequence"]}, 426 | {"name": "character", "symbols": ["unicode_escape_sequence"]}, 427 | {"name": "single_character", "symbols": [{"literal":"'"}], "postprocess": rejecter}, 428 | {"name": "single_character", "symbols": [{"literal":"\\"}], "postprocess": rejecter}, 429 | {"name": "single_character", "symbols": ["new_line_character"], "postprocess": rejecter}, 430 | {"name": "single_character", "symbols": ["character"]}, 431 | {"name": "simple_escape_sequence$string$1", "symbols": [{"literal":"\\"}, {"literal":"'"}], "postprocess": function joiner(d) {return d.join('');}}, 432 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$1"]}, 433 | {"name": "simple_escape_sequence$string$2", "symbols": [{"literal":"\\"}, {"literal":"\""}], "postprocess": function joiner(d) {return d.join('');}}, 434 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$2"]}, 435 | {"name": "simple_escape_sequence$string$3", "symbols": [{"literal":"\\"}, {"literal":"\\"}], "postprocess": function joiner(d) {return d.join('');}}, 436 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$3"]}, 437 | {"name": "simple_escape_sequence$string$4", "symbols": [{"literal":"\\"}, {"literal":"0"}], "postprocess": function joiner(d) {return d.join('');}}, 438 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$4"]}, 439 | {"name": "simple_escape_sequence$string$5", "symbols": [{"literal":"\\"}, {"literal":"a"}], "postprocess": function joiner(d) {return d.join('');}}, 440 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$5"]}, 441 | {"name": "simple_escape_sequence$string$6", "symbols": [{"literal":"\\"}, {"literal":"b"}], "postprocess": function joiner(d) {return d.join('');}}, 442 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$6"]}, 443 | {"name": "simple_escape_sequence$string$7", "symbols": [{"literal":"\\"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 444 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$7"]}, 445 | {"name": "simple_escape_sequence$string$8", "symbols": [{"literal":"\\"}, {"literal":"n"}], "postprocess": function joiner(d) {return d.join('');}}, 446 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$8"]}, 447 | {"name": "simple_escape_sequence$string$9", "symbols": [{"literal":"\\"}, {"literal":"r"}], "postprocess": function joiner(d) {return d.join('');}}, 448 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$9"]}, 449 | {"name": "simple_escape_sequence$string$10", "symbols": [{"literal":"\\"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 450 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$10"]}, 451 | {"name": "simple_escape_sequence$string$11", "symbols": [{"literal":"\\"}, {"literal":"v"}], "postprocess": function joiner(d) {return d.join('');}}, 452 | {"name": "simple_escape_sequence", "symbols": ["simple_escape_sequence$string$11"]}, 453 | {"name": "hexadecimal_escape_sequence$string$1", "symbols": [{"literal":"\\"}, {"literal":"x"}], "postprocess": function joiner(d) {return d.join('');}}, 454 | {"name": "hexadecimal_escape_sequence$ebnf$1", "symbols": ["hex_digit"], "postprocess": id}, 455 | {"name": "hexadecimal_escape_sequence$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 456 | {"name": "hexadecimal_escape_sequence$ebnf$2", "symbols": ["hex_digit"], "postprocess": id}, 457 | {"name": "hexadecimal_escape_sequence$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 458 | {"name": "hexadecimal_escape_sequence$ebnf$3", "symbols": ["hex_digit"], "postprocess": id}, 459 | {"name": "hexadecimal_escape_sequence$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}}, 460 | {"name": "hexadecimal_escape_sequence", "symbols": ["hexadecimal_escape_sequence$string$1", "hex_digit", "hexadecimal_escape_sequence$ebnf$1", "hexadecimal_escape_sequence$ebnf$2", "hexadecimal_escape_sequence$ebnf$3"]}, 461 | {"name": "string_literal", "symbols": ["regular_string_literal"]}, 462 | {"name": "string_literal", "symbols": ["verbatim_string_literal"]}, 463 | {"name": "regular_string_literal$ebnf$1", "symbols": ["regular_string_literal_characters"], "postprocess": id}, 464 | {"name": "regular_string_literal$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 465 | {"name": "regular_string_literal", "symbols": [{"literal":"\""}, "regular_string_literal$ebnf$1", {"literal":"\""}]}, 466 | {"name": "regular_string_literal_characters", "symbols": ["regular_string_literal_character"]}, 467 | {"name": "regular_string_literal_characters", "symbols": ["regular_string_literal_characters", "regular_string_literal_character"]}, 468 | {"name": "regular_string_literal_character", "symbols": ["single_regular_string_literal_character"]}, 469 | {"name": "regular_string_literal_character", "symbols": ["simple_escape_sequence"]}, 470 | {"name": "regular_string_literal_character", "symbols": ["hexadecimal_escape_sequence"]}, 471 | {"name": "regular_string_literal_character", "symbols": ["unicode_escape_sequence"]}, 472 | {"name": "single_regular_string_literal_character", "symbols": [{"literal":"\""}], "postprocess": rejecter}, 473 | {"name": "single_regular_string_literal_character", "symbols": [{"literal":"\\"}], "postprocess": rejecter}, 474 | {"name": "single_regular_string_literal_character", "symbols": ["new_line_character"], "postprocess": rejecter}, 475 | {"name": "single_regular_string_literal_character", "symbols": ["character"]}, 476 | {"name": "verbatim_string_literal$string$1", "symbols": [{"literal":"@"}, {"literal":"\""}], "postprocess": function joiner(d) {return d.join('');}}, 477 | {"name": "verbatim_string_literal$ebnf$1", "symbols": ["verbatim_string_literal_characters"], "postprocess": id}, 478 | {"name": "verbatim_string_literal$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 479 | {"name": "verbatim_string_literal", "symbols": ["verbatim_string_literal$string$1", "verbatim_string_literal$ebnf$1", {"literal":"\""}]}, 480 | {"name": "verbatim_string_literal_characters", "symbols": ["verbatim_string_literal_character"]}, 481 | {"name": "verbatim_string_literal_characters", "symbols": ["verbatim_string_literal_characters", "verbatim_string_literal_character"]}, 482 | {"name": "verbatim_string_literal_character", "symbols": ["single_verbatim_string_literal_character"]}, 483 | {"name": "verbatim_string_literal_character", "symbols": ["quote_escape_sequence"]}, 484 | {"name": "single_verbatim_string_literal_character", "symbols": [{"literal":"\""}], "postprocess": rejecter}, 485 | {"name": "single_verbatim_string_literal_character", "symbols": ["character"]}, 486 | {"name": "quote_escape_sequence$string$1", "symbols": [{"literal":"\""}, {"literal":"\""}], "postprocess": function joiner(d) {return d.join('');}}, 487 | {"name": "quote_escape_sequence", "symbols": ["quote_escape_sequence$string$1"]}, 488 | {"name": "null_literal$string$1", "symbols": [{"literal":"n"}, {"literal":"u"}, {"literal":"l"}, {"literal":"l"}], "postprocess": function joiner(d) {return d.join('');}}, 489 | {"name": "null_literal", "symbols": ["null_literal$string$1"]}, 490 | {"name": "operator_or_punctuator", "symbols": [{"literal":"{"}]}, 491 | {"name": "operator_or_punctuator", "symbols": [{"literal":"}"}]}, 492 | {"name": "operator_or_punctuator", "symbols": [{"literal":"["}]}, 493 | {"name": "operator_or_punctuator", "symbols": [{"literal":"]"}]}, 494 | {"name": "operator_or_punctuator", "symbols": [{"literal":"("}]}, 495 | {"name": "operator_or_punctuator", "symbols": [{"literal":")"}]}, 496 | {"name": "operator_or_punctuator", "symbols": [{"literal":"."}]}, 497 | {"name": "operator_or_punctuator", "symbols": [{"literal":","}]}, 498 | {"name": "operator_or_punctuator", "symbols": [{"literal":":"}]}, 499 | {"name": "operator_or_punctuator", "symbols": [{"literal":";"}]}, 500 | {"name": "operator_or_punctuator", "symbols": [{"literal":"+"}]}, 501 | {"name": "operator_or_punctuator", "symbols": [{"literal":"-"}]}, 502 | {"name": "operator_or_punctuator", "symbols": [{"literal":"*"}]}, 503 | {"name": "operator_or_punctuator", "symbols": [{"literal":"/"}]}, 504 | {"name": "operator_or_punctuator", "symbols": [{"literal":"%"}]}, 505 | {"name": "operator_or_punctuator", "symbols": [{"literal":"&"}]}, 506 | {"name": "operator_or_punctuator", "symbols": [{"literal":"|"}]}, 507 | {"name": "operator_or_punctuator", "symbols": [{"literal":"^"}]}, 508 | {"name": "operator_or_punctuator", "symbols": [{"literal":"!"}]}, 509 | {"name": "operator_or_punctuator", "symbols": [{"literal":"~"}]}, 510 | {"name": "operator_or_punctuator", "symbols": [{"literal":"="}]}, 511 | {"name": "operator_or_punctuator", "symbols": [{"literal":"<"}]}, 512 | {"name": "operator_or_punctuator", "symbols": [{"literal":">"}]}, 513 | {"name": "operator_or_punctuator", "symbols": [{"literal":"?"}]}, 514 | {"name": "operator_or_punctuator$string$1", "symbols": [{"literal":"?"}, {"literal":"?"}], "postprocess": function joiner(d) {return d.join('');}}, 515 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$1"]}, 516 | {"name": "operator_or_punctuator$string$2", "symbols": [{"literal":":"}, {"literal":":"}], "postprocess": function joiner(d) {return d.join('');}}, 517 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$2"]}, 518 | {"name": "operator_or_punctuator$string$3", "symbols": [{"literal":"+"}, {"literal":"+"}], "postprocess": function joiner(d) {return d.join('');}}, 519 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$3"]}, 520 | {"name": "operator_or_punctuator$string$4", "symbols": [{"literal":"-"}, {"literal":"-"}], "postprocess": function joiner(d) {return d.join('');}}, 521 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$4"]}, 522 | {"name": "operator_or_punctuator$string$5", "symbols": [{"literal":"&"}, {"literal":"&"}], "postprocess": function joiner(d) {return d.join('');}}, 523 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$5"]}, 524 | {"name": "operator_or_punctuator$string$6", "symbols": [{"literal":"|"}, {"literal":"|"}], "postprocess": function joiner(d) {return d.join('');}}, 525 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$6"]}, 526 | {"name": "operator_or_punctuator$string$7", "symbols": [{"literal":"-"}, {"literal":">"}], "postprocess": function joiner(d) {return d.join('');}}, 527 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$7"]}, 528 | {"name": "operator_or_punctuator$string$8", "symbols": [{"literal":"="}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 529 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$8"]}, 530 | {"name": "operator_or_punctuator$string$9", "symbols": [{"literal":"!"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 531 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$9"]}, 532 | {"name": "operator_or_punctuator$string$10", "symbols": [{"literal":"<"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 533 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$10"]}, 534 | {"name": "operator_or_punctuator$string$11", "symbols": [{"literal":">"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 535 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$11"]}, 536 | {"name": "operator_or_punctuator$string$12", "symbols": [{"literal":"+"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 537 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$12"]}, 538 | {"name": "operator_or_punctuator$string$13", "symbols": [{"literal":"-"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 539 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$13"]}, 540 | {"name": "operator_or_punctuator$string$14", "symbols": [{"literal":"*"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 541 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$14"]}, 542 | {"name": "operator_or_punctuator$string$15", "symbols": [{"literal":"/"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 543 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$15"]}, 544 | {"name": "operator_or_punctuator$string$16", "symbols": [{"literal":"%"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 545 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$16"]}, 546 | {"name": "operator_or_punctuator$string$17", "symbols": [{"literal":"&"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 547 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$17"]}, 548 | {"name": "operator_or_punctuator$string$18", "symbols": [{"literal":"|"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 549 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$18"]}, 550 | {"name": "operator_or_punctuator$string$19", "symbols": [{"literal":"^"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 551 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$19"]}, 552 | {"name": "operator_or_punctuator$string$20", "symbols": [{"literal":"<"}, {"literal":"<"}], "postprocess": function joiner(d) {return d.join('');}}, 553 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$20"]}, 554 | {"name": "operator_or_punctuator$string$21", "symbols": [{"literal":"<"}, {"literal":"<"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 555 | {"name": "operator_or_punctuator", "symbols": ["operator_or_punctuator$string$21"]}, 556 | {"name": "right_shift$string$1", "symbols": [{"literal":">"}, {"literal":">"}], "postprocess": function joiner(d) {return d.join('');}}, 557 | {"name": "right_shift", "symbols": ["right_shift$string$1"]}, 558 | {"name": "right_shift_assignment$string$1", "symbols": [{"literal":">"}, {"literal":">"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 559 | {"name": "right_shift_assignment", "symbols": ["right_shift_assignment$string$1"]}, 560 | {"name": "pp_directive", "symbols": ["pp_declaration"]}, 561 | {"name": "pp_directive", "symbols": ["pp_conditional"]}, 562 | {"name": "pp_directive", "symbols": ["pp_line"]}, 563 | {"name": "pp_directive", "symbols": ["pp_diagnostic"]}, 564 | {"name": "pp_directive", "symbols": ["pp_region"]}, 565 | {"name": "pp_directive", "symbols": ["pp_pragma"]}, 566 | {"name": "conditional_symbol$string$1", "symbols": [{"literal":"t"}, {"literal":"r"}, {"literal":"u"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 567 | {"name": "conditional_symbol", "symbols": ["conditional_symbol$string$1"], "postprocess": rejecter}, 568 | {"name": "conditional_symbol$string$2", "symbols": [{"literal":"f"}, {"literal":"a"}, {"literal":"l"}, {"literal":"s"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 569 | {"name": "conditional_symbol", "symbols": ["conditional_symbol$string$2"], "postprocess": rejecter}, 570 | {"name": "conditional_symbol", "symbols": ["identifier_or_keyword"]}, 571 | {"name": "pp_expression$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 572 | {"name": "pp_expression$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 573 | {"name": "pp_expression$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 574 | {"name": "pp_expression$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 575 | {"name": "pp_expression", "symbols": ["pp_expression$ebnf$1", "pp_or_expression", "pp_expression$ebnf$2"]}, 576 | {"name": "pp_or_expression", "symbols": ["pp_and_expression"]}, 577 | {"name": "pp_or_expression$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 578 | {"name": "pp_or_expression$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 579 | {"name": "pp_or_expression$string$1", "symbols": [{"literal":"|"}, {"literal":"|"}], "postprocess": function joiner(d) {return d.join('');}}, 580 | {"name": "pp_or_expression$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 581 | {"name": "pp_or_expression$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 582 | {"name": "pp_or_expression", "symbols": ["pp_or_expression", "pp_or_expression$ebnf$1", "pp_or_expression$string$1", "pp_or_expression$ebnf$2", "pp_and_expression"]}, 583 | {"name": "pp_and_expression", "symbols": ["pp_equality_expression"]}, 584 | {"name": "pp_and_expression$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 585 | {"name": "pp_and_expression$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 586 | {"name": "pp_and_expression$string$1", "symbols": [{"literal":"&"}, {"literal":"&"}], "postprocess": function joiner(d) {return d.join('');}}, 587 | {"name": "pp_and_expression$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 588 | {"name": "pp_and_expression$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 589 | {"name": "pp_and_expression", "symbols": ["pp_and_expression", "pp_and_expression$ebnf$1", "pp_and_expression$string$1", "pp_and_expression$ebnf$2", "pp_equality_expression"]}, 590 | {"name": "pp_equality_expression", "symbols": ["pp_unary_expression"]}, 591 | {"name": "pp_equality_expression$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 592 | {"name": "pp_equality_expression$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 593 | {"name": "pp_equality_expression$string$1", "symbols": [{"literal":"="}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 594 | {"name": "pp_equality_expression$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 595 | {"name": "pp_equality_expression$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 596 | {"name": "pp_equality_expression", "symbols": ["pp_equality_expression", "pp_equality_expression$ebnf$1", "pp_equality_expression$string$1", "pp_equality_expression$ebnf$2", "pp_unary_expression"]}, 597 | {"name": "pp_equality_expression$ebnf$3", "symbols": ["whitespace"], "postprocess": id}, 598 | {"name": "pp_equality_expression$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}}, 599 | {"name": "pp_equality_expression$string$2", "symbols": [{"literal":"!"}, {"literal":"="}], "postprocess": function joiner(d) {return d.join('');}}, 600 | {"name": "pp_equality_expression$ebnf$4", "symbols": ["whitespace"], "postprocess": id}, 601 | {"name": "pp_equality_expression$ebnf$4", "symbols": [], "postprocess": function(d) {return null;}}, 602 | {"name": "pp_equality_expression", "symbols": ["pp_equality_expression", "pp_equality_expression$ebnf$3", "pp_equality_expression$string$2", "pp_equality_expression$ebnf$4", "pp_unary_expression"]}, 603 | {"name": "pp_unary_expression", "symbols": ["pp_primary_expression"]}, 604 | {"name": "pp_unary_expression$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 605 | {"name": "pp_unary_expression$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 606 | {"name": "pp_unary_expression", "symbols": [{"literal":"!"}, "pp_unary_expression$ebnf$1", "pp_unary_expression"]}, 607 | {"name": "pp_primary_expression$string$1", "symbols": [{"literal":"t"}, {"literal":"r"}, {"literal":"u"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 608 | {"name": "pp_primary_expression", "symbols": ["pp_primary_expression$string$1"]}, 609 | {"name": "pp_primary_expression$string$2", "symbols": [{"literal":"f"}, {"literal":"a"}, {"literal":"l"}, {"literal":"s"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 610 | {"name": "pp_primary_expression", "symbols": ["pp_primary_expression$string$2"]}, 611 | {"name": "pp_primary_expression", "symbols": ["conditional_symbol"]}, 612 | {"name": "pp_primary_expression$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 613 | {"name": "pp_primary_expression$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 614 | {"name": "pp_primary_expression$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 615 | {"name": "pp_primary_expression$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 616 | {"name": "pp_primary_expression", "symbols": [{"literal":"("}, "pp_primary_expression$ebnf$1", "pp_expression", "pp_primary_expression$ebnf$2", {"literal":")"}]}, 617 | {"name": "pp_declaration$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 618 | {"name": "pp_declaration$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 619 | {"name": "pp_declaration$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 620 | {"name": "pp_declaration$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 621 | {"name": "pp_declaration$string$1", "symbols": [{"literal":"d"}, {"literal":"e"}, {"literal":"f"}, {"literal":"i"}, {"literal":"n"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 622 | {"name": "pp_declaration", "symbols": ["pp_declaration$ebnf$1", {"literal":"#"}, "pp_declaration$ebnf$2", "pp_declaration$string$1", "whitespace", "conditional_symbol", "pp_new_line"]}, 623 | {"name": "pp_declaration$ebnf$3", "symbols": ["whitespace"], "postprocess": id}, 624 | {"name": "pp_declaration$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}}, 625 | {"name": "pp_declaration$ebnf$4", "symbols": ["whitespace"], "postprocess": id}, 626 | {"name": "pp_declaration$ebnf$4", "symbols": [], "postprocess": function(d) {return null;}}, 627 | {"name": "pp_declaration$string$2", "symbols": [{"literal":"u"}, {"literal":"n"}, {"literal":"d"}, {"literal":"e"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 628 | {"name": "pp_declaration", "symbols": ["pp_declaration$ebnf$3", {"literal":"#"}, "pp_declaration$ebnf$4", "pp_declaration$string$2", "whitespace", "conditional_symbol", "pp_new_line"]}, 629 | {"name": "pp_new_line$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 630 | {"name": "pp_new_line$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 631 | {"name": "pp_new_line$ebnf$2", "symbols": ["single_line_comment"], "postprocess": id}, 632 | {"name": "pp_new_line$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 633 | {"name": "pp_new_line", "symbols": ["pp_new_line$ebnf$1", "pp_new_line$ebnf$2", "new_line"]}, 634 | {"name": "pp_conditional$ebnf$1", "symbols": ["pp_elif_sections"], "postprocess": id}, 635 | {"name": "pp_conditional$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 636 | {"name": "pp_conditional$ebnf$2", "symbols": ["pp_else_section"], "postprocess": id}, 637 | {"name": "pp_conditional$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 638 | {"name": "pp_conditional", "symbols": ["pp_if_section", "pp_conditional$ebnf$1", "pp_conditional$ebnf$2", "pp_endif"]}, 639 | {"name": "pp_if_section$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 640 | {"name": "pp_if_section$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 641 | {"name": "pp_if_section$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 642 | {"name": "pp_if_section$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 643 | {"name": "pp_if_section$string$1", "symbols": [{"literal":"i"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 644 | {"name": "pp_if_section$ebnf$3", "symbols": ["conditional_section"], "postprocess": id}, 645 | {"name": "pp_if_section$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}}, 646 | {"name": "pp_if_section", "symbols": ["pp_if_section$ebnf$1", {"literal":"#"}, "pp_if_section$ebnf$2", "pp_if_section$string$1", "whitespace", "pp_expression", "pp_new_line", "pp_if_section$ebnf$3"]}, 647 | {"name": "pp_elif_sections", "symbols": ["pp_elif_section"]}, 648 | {"name": "pp_elif_sections", "symbols": ["pp_elif_sections", "pp_elif_section"]}, 649 | {"name": "pp_elif_section$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 650 | {"name": "pp_elif_section$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 651 | {"name": "pp_elif_section$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 652 | {"name": "pp_elif_section$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 653 | {"name": "pp_elif_section$string$1", "symbols": [{"literal":"e"}, {"literal":"l"}, {"literal":"i"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 654 | {"name": "pp_elif_section$ebnf$3", "symbols": ["conditional_section"], "postprocess": id}, 655 | {"name": "pp_elif_section$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}}, 656 | {"name": "pp_elif_section", "symbols": ["pp_elif_section$ebnf$1", {"literal":"#"}, "pp_elif_section$ebnf$2", "pp_elif_section$string$1", "whitespace", "pp_expression", "pp_new_line", "pp_elif_section$ebnf$3"]}, 657 | {"name": "pp_else_section$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 658 | {"name": "pp_else_section$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 659 | {"name": "pp_else_section$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 660 | {"name": "pp_else_section$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 661 | {"name": "pp_else_section$string$1", "symbols": [{"literal":"e"}, {"literal":"l"}, {"literal":"s"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 662 | {"name": "pp_else_section$ebnf$3", "symbols": ["conditional_section"], "postprocess": id}, 663 | {"name": "pp_else_section$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}}, 664 | {"name": "pp_else_section", "symbols": ["pp_else_section$ebnf$1", {"literal":"#"}, "pp_else_section$ebnf$2", "pp_else_section$string$1", "pp_new_line", "pp_else_section$ebnf$3"]}, 665 | {"name": "pp_endif$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 666 | {"name": "pp_endif$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 667 | {"name": "pp_endif$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 668 | {"name": "pp_endif$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 669 | {"name": "pp_endif$string$1", "symbols": [{"literal":"e"}, {"literal":"n"}, {"literal":"d"}, {"literal":"i"}, {"literal":"f"}], "postprocess": function joiner(d) {return d.join('');}}, 670 | {"name": "pp_endif", "symbols": ["pp_endif$ebnf$1", {"literal":"#"}, "pp_endif$ebnf$2", "pp_endif$string$1", "pp_new_line"]}, 671 | {"name": "conditional_section", "symbols": ["input_section"]}, 672 | {"name": "conditional_section", "symbols": ["skipped_section"]}, 673 | {"name": "skipped_section", "symbols": ["skipped_section_part"]}, 674 | {"name": "skipped_section", "symbols": ["skipped_section", "skipped_section_part"]}, 675 | {"name": "skipped_section_part$ebnf$1", "symbols": ["skipped_characters"], "postprocess": id}, 676 | {"name": "skipped_section_part$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 677 | {"name": "skipped_section_part", "symbols": ["skipped_section_part$ebnf$1", "new_line"]}, 678 | {"name": "skipped_section_part", "symbols": ["pp_directive"]}, 679 | {"name": "skipped_characters$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 680 | {"name": "skipped_characters$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 681 | {"name": "skipped_characters$ebnf$2", "symbols": ["input_characters"], "postprocess": id}, 682 | {"name": "skipped_characters$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 683 | {"name": "skipped_characters", "symbols": ["skipped_characters$ebnf$1", "not_number_sign", "skipped_characters$ebnf$2"]}, 684 | {"name": "not_number_sign", "symbols": [{"literal":"#"}], "postprocess": rejecter}, 685 | {"name": "not_number_sign", "symbols": ["input_character"]}, 686 | {"name": "pp_diagnostic$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 687 | {"name": "pp_diagnostic$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 688 | {"name": "pp_diagnostic$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 689 | {"name": "pp_diagnostic$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 690 | {"name": "pp_diagnostic$string$1", "symbols": [{"literal":"e"}, {"literal":"r"}, {"literal":"r"}, {"literal":"o"}, {"literal":"r"}], "postprocess": function joiner(d) {return d.join('');}}, 691 | {"name": "pp_diagnostic", "symbols": ["pp_diagnostic$ebnf$1", {"literal":"#"}, "pp_diagnostic$ebnf$2", "pp_diagnostic$string$1", "pp_message"]}, 692 | {"name": "pp_diagnostic$ebnf$3", "symbols": ["whitespace"], "postprocess": id}, 693 | {"name": "pp_diagnostic$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}}, 694 | {"name": "pp_diagnostic$ebnf$4", "symbols": ["whitespace"], "postprocess": id}, 695 | {"name": "pp_diagnostic$ebnf$4", "symbols": [], "postprocess": function(d) {return null;}}, 696 | {"name": "pp_diagnostic$string$2", "symbols": [{"literal":"w"}, {"literal":"a"}, {"literal":"r"}, {"literal":"n"}, {"literal":"i"}, {"literal":"n"}, {"literal":"g"}], "postprocess": function joiner(d) {return d.join('');}}, 697 | {"name": "pp_diagnostic", "symbols": ["pp_diagnostic$ebnf$3", {"literal":"#"}, "pp_diagnostic$ebnf$4", "pp_diagnostic$string$2", "pp_message"]}, 698 | {"name": "pp_message", "symbols": ["new_line"]}, 699 | {"name": "pp_message$ebnf$1", "symbols": ["input_characters"], "postprocess": id}, 700 | {"name": "pp_message$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 701 | {"name": "pp_message", "symbols": ["whitespace", "pp_message$ebnf$1", "new_line"]}, 702 | {"name": "pp_region$ebnf$1", "symbols": ["conditional_section"], "postprocess": id}, 703 | {"name": "pp_region$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 704 | {"name": "pp_region", "symbols": ["pp_start_region", "pp_region$ebnf$1", "pp_end_region"]}, 705 | {"name": "pp_start_region$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 706 | {"name": "pp_start_region$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 707 | {"name": "pp_start_region$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 708 | {"name": "pp_start_region$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 709 | {"name": "pp_start_region$string$1", "symbols": [{"literal":"r"}, {"literal":"e"}, {"literal":"g"}, {"literal":"i"}, {"literal":"o"}, {"literal":"n"}], "postprocess": function joiner(d) {return d.join('');}}, 710 | {"name": "pp_start_region", "symbols": ["pp_start_region$ebnf$1", {"literal":"#"}, "pp_start_region$ebnf$2", "pp_start_region$string$1", "pp_message"]}, 711 | {"name": "pp_end_region$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 712 | {"name": "pp_end_region$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 713 | {"name": "pp_end_region$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 714 | {"name": "pp_end_region$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 715 | {"name": "pp_end_region$string$1", "symbols": [{"literal":"e"}, {"literal":"n"}, {"literal":"d"}, {"literal":"r"}, {"literal":"e"}, {"literal":"g"}, {"literal":"i"}, {"literal":"o"}, {"literal":"n"}], "postprocess": function joiner(d) {return d.join('');}}, 716 | {"name": "pp_end_region", "symbols": ["pp_end_region$ebnf$1", {"literal":"#"}, "pp_end_region$ebnf$2", "pp_end_region$string$1", "pp_message"]}, 717 | {"name": "pp_line$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 718 | {"name": "pp_line$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 719 | {"name": "pp_line$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 720 | {"name": "pp_line$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 721 | {"name": "pp_line$string$1", "symbols": [{"literal":"l"}, {"literal":"i"}, {"literal":"n"}, {"literal":"e"}], "postprocess": function joiner(d) {return d.join('');}}, 722 | {"name": "pp_line", "symbols": ["pp_line$ebnf$1", {"literal":"#"}, "pp_line$ebnf$2", "pp_line$string$1", "whitespace", "line_indicator", "pp_new_line"]}, 723 | {"name": "line_indicator", "symbols": ["decimal_digits", "whitespace", "file_name"]}, 724 | {"name": "line_indicator", "symbols": ["decimal_digits"]}, 725 | {"name": "line_indicator$string$1", "symbols": [{"literal":"d"}, {"literal":"e"}, {"literal":"f"}, {"literal":"a"}, {"literal":"u"}, {"literal":"l"}, {"literal":"t"}], "postprocess": function joiner(d) {return d.join('');}}, 726 | {"name": "line_indicator", "symbols": ["line_indicator$string$1"]}, 727 | {"name": "line_indicator$string$2", "symbols": [{"literal":"h"}, {"literal":"i"}, {"literal":"d"}, {"literal":"d"}, {"literal":"e"}, {"literal":"n"}], "postprocess": function joiner(d) {return d.join('');}}, 728 | {"name": "line_indicator", "symbols": ["line_indicator$string$2"]}, 729 | {"name": "file_name", "symbols": [{"literal":"\""}, "file_name_characters", {"literal":"\""}]}, 730 | {"name": "file_name_characters", "symbols": ["file_name_character"]}, 731 | {"name": "file_name_characters", "symbols": ["file_name_characters", "file_name_character"]}, 732 | {"name": "file_name_character", "symbols": [{"literal":"\""}], "postprocess": rejecter}, 733 | {"name": "file_name_character", "symbols": ["new_line_character"], "postprocess": rejecter}, 734 | {"name": "file_name_character", "symbols": ["input_character"]}, 735 | {"name": "pp_pragma$ebnf$1", "symbols": ["whitespace"], "postprocess": id}, 736 | {"name": "pp_pragma$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 737 | {"name": "pp_pragma$ebnf$2", "symbols": ["whitespace"], "postprocess": id}, 738 | {"name": "pp_pragma$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}}, 739 | {"name": "pp_pragma$string$1", "symbols": [{"literal":"p"}, {"literal":"r"}, {"literal":"a"}, {"literal":"g"}, {"literal":"m"}, {"literal":"a"}], "postprocess": function joiner(d) {return d.join('');}}, 740 | {"name": "pp_pragma", "symbols": ["pp_pragma$ebnf$1", {"literal":"#"}, "pp_pragma$ebnf$2", "pp_pragma$string$1", "pp_pragma_text"]}, 741 | {"name": "pp_pragma_text", "symbols": ["new_line"]}, 742 | {"name": "pp_pragma_text$ebnf$1", "symbols": ["input_characters"], "postprocess": id}, 743 | {"name": "pp_pragma_text$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}}, 744 | {"name": "pp_pragma_text", "symbols": ["whitespace", "pp_pragma_text$ebnf$1", "new_line"]} 745 | ] 746 | , ParserStart: "main" 747 | } 748 | if (typeof module !== 'undefined'&& typeof module.exports !== 'undefined') { 749 | module.exports = grammar; 750 | } else { 751 | window.grammar = grammar; 752 | } 753 | })(); 754 | --------------------------------------------------------------------------------