├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── dist ├── index.d.cts └── index.d.ts ├── package.json ├── rollup.config.js ├── src ├── highlight.js ├── rust.grammar └── tokens.js └── test ├── async.txt ├── comments.txt ├── declarations.txt ├── expressions.txt ├── literals.txt ├── macros.txt ├── patterns.txt ├── test-rust.js └── types.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /src/parser.* 3 | .tern-* 4 | /dist 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.2 (2023-12-28) 2 | 3 | ### Bug fixes 4 | 5 | Tag comments and strings as isolating for the purpose of bidirectional text. 6 | 7 | ## 1.0.1 (2023-07-03) 8 | 9 | ### Bug fixes 10 | 11 | Make the package work with new TS resolution styles. 12 | 13 | ## 1.0.0 (2022-06-06) 14 | 15 | ### New features 16 | 17 | First stable version. 18 | 19 | ## 0.16.1 (2022-04-26) 20 | 21 | ### Bug fixes 22 | 23 | Allow arbitrary bracketed token trees to appear after attribute names 24 | 25 | ## 0.16.0 (2022-04-20) 26 | 27 | ### Breaking changes 28 | 29 | Move to 0.16 serialized parser format. 30 | 31 | ### New features 32 | 33 | The parser now includes syntax highlighting information in its node types. 34 | 35 | ## 0.15.1 (2022-03-21) 36 | 37 | ### Bug fixes 38 | 39 | Allow arbitrary token trees after `=` in attributes. 40 | 41 | ## 0.15.0 (2021-08-11) 42 | 43 | ### Breaking changes 44 | 45 | The module's name changed from `lezer-rust` to `@lezer/rust`. 46 | 47 | Upgrade to the 0.15.0 lezer interfaces. 48 | 49 | ## 0.13.1 (2020-12-04) 50 | 51 | ### Bug fixes 52 | 53 | Fix versions of lezer packages depended on. 54 | 55 | ## 0.13.0 (2020-12-04) 56 | 57 | ## 0.12.0 (2020-10-23) 58 | 59 | ### Breaking changes 60 | 61 | Adjust to changed serialized parser format. 62 | 63 | ## 0.11.1 (2020-10-01) 64 | 65 | ### New features 66 | 67 | Expression statements are now wrapped in an `ExpressionStatement` node. 68 | 69 | The package now provides TypeScript type definitions. 70 | 71 | ## 0.11.0 (2020-09-29) 72 | 73 | ### Breaking changes 74 | 75 | First numbered release. 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2018 by Marijn Haverbeke and others 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @lezer/rust 2 | 3 | This is a Rust grammar for the 4 | [Lezer](https://lezer.codemirror.net/) parser system. 5 | 6 | The grammar used is based in part on the corresponding 7 | [tree-sitter grammar](https://github.com/tree-sitter/tree-sitter-rust). 8 | 9 | The code is licensed under an MIT license. 10 | -------------------------------------------------------------------------------- /dist/index.d.cts: -------------------------------------------------------------------------------- 1 | import {LRParser} from "@lezer/lr" 2 | 3 | export const parser: LRParser 4 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import {LRParser} from "@lezer/lr" 2 | 3 | export const parser: LRParser 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lezer/rust", 3 | "version": "1.0.2", 4 | "description": "Lezer-based Rust grammar", 5 | "main": "dist/index.cjs", 6 | "type": "module", 7 | "exports": { 8 | "import": "./dist/index.js", 9 | "require": "./dist/index.cjs" 10 | }, 11 | "module": "dist/index.js", 12 | "types": "dist/index.d.ts", 13 | "author": "Marijn Haverbeke ", 14 | "license": "MIT", 15 | "devDependencies": { 16 | "@lezer/generator": "^1.0.0", 17 | "mocha": "^10.2.0", 18 | "rollup": "^2.52.2", 19 | "@rollup/plugin-node-resolve": "^9.0.0" 20 | }, 21 | "dependencies": { 22 | "@lezer/common": "^1.2.0", 23 | "@lezer/lr": "^1.0.0", 24 | "@lezer/highlight": "^1.0.0" 25 | }, 26 | "repository": { 27 | "type" : "git", 28 | "url" : "https://github.com/lezer-parser/rust.git" 29 | }, 30 | "scripts": { 31 | "build": "lezer-generator src/rust.grammar -o src/parser && rollup -c", 32 | "build-debug": "lezer-generator src/rust.grammar --names -o src/parser && rollup -c", 33 | "prepare": "npm run build", 34 | "test": "mocha test/test-*.js" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import {nodeResolve} from "@rollup/plugin-node-resolve" 2 | 3 | export default { 4 | input: "./src/parser.js", 5 | output: [{ 6 | format: "cjs", 7 | file: "./dist/index.cjs" 8 | }, { 9 | format: "es", 10 | file: "./dist/index.js" 11 | }], 12 | external(id) { return !/^[\.\/]/.test(id) }, 13 | plugins: [ 14 | nodeResolve() 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/highlight.js: -------------------------------------------------------------------------------- 1 | import {styleTags, tags as t} from "@lezer/highlight" 2 | 3 | export const rustHighlighting = styleTags({ 4 | "const macro_rules struct union enum type fn impl trait let static": t.definitionKeyword, 5 | "mod use crate": t.moduleKeyword, 6 | "pub unsafe async mut extern default move": t.modifier, 7 | "for if else loop while match continue break return await": t.controlKeyword, 8 | "as in ref": t.operatorKeyword, 9 | "where _ crate super dyn": t.keyword, 10 | "self": t.self, 11 | String: t.string, 12 | Char: t.character, 13 | RawString: t.special(t.string), 14 | Boolean: t.bool, 15 | Identifier: t.variableName, 16 | "CallExpression/Identifier": t.function(t.variableName), 17 | BoundIdentifier: t.definition(t.variableName), 18 | "FunctionItem/BoundIdentifier": t.function(t.definition(t.variableName)), 19 | LoopLabel: t.labelName, 20 | FieldIdentifier: t.propertyName, 21 | "CallExpression/FieldExpression/FieldIdentifier": t.function(t.propertyName), 22 | Lifetime: t.special(t.variableName), 23 | ScopeIdentifier: t.namespace, 24 | TypeIdentifier: t.typeName, 25 | "MacroInvocation/Identifier MacroInvocation/ScopedIdentifier/Identifier": t.macroName, 26 | "MacroInvocation/TypeIdentifier MacroInvocation/ScopedIdentifier/TypeIdentifier": t.macroName, 27 | "\"!\"": t.macroName, 28 | UpdateOp: t.updateOperator, 29 | LineComment: t.lineComment, 30 | BlockComment: t.blockComment, 31 | Integer: t.integer, 32 | Float: t.float, 33 | ArithOp: t.arithmeticOperator, 34 | LogicOp: t.logicOperator, 35 | BitOp: t.bitwiseOperator, 36 | CompareOp: t.compareOperator, 37 | "=": t.definitionOperator, 38 | ".. ... => ->": t.punctuation, 39 | "( )": t.paren, 40 | "[ ]": t.squareBracket, 41 | "{ }": t.brace, 42 | ". DerefOp": t.derefOperator, 43 | "&": t.operator, 44 | ", ; ::": t.separator, 45 | "Attribute/...": t.meta, 46 | }) 47 | -------------------------------------------------------------------------------- /src/rust.grammar: -------------------------------------------------------------------------------- 1 | @precedence { 2 | preferGenerics 3 | try 4 | implFor 5 | implBang 6 | deref 7 | call 8 | params 9 | macroRules 10 | macroSemi 11 | macro 12 | unary 13 | mult @left 14 | add @left 15 | shift @left 16 | bitAnd @left 17 | bitXor @left 18 | bitOr @left 19 | compare @left 20 | and @left 21 | or @left 22 | assign @right 23 | else @right 24 | range @left 25 | cast 26 | return 27 | typeArgs 28 | block 29 | bind 30 | plusSep 31 | bound @left 32 | scope 33 | crateVis 34 | selfParam 35 | mut @cut 36 | statement 37 | } 38 | 39 | @skip { whitespace | LineComment | BlockComment } 40 | 41 | @top SourceFile { 42 | InnerAttribute* 43 | statement* 44 | } 45 | 46 | statement[@isGroup=Statement] { 47 | declarationStatement | 48 | AttributeItem | 49 | ExpressionStatement { 50 | blockExpression !statement | 51 | nonBlockExpression ";" 52 | } 53 | } 54 | 55 | AttributeItem { Attribute+ declarationStatement } 56 | 57 | declarationStatement { 58 | ConstItem { 59 | Vis? kw<"const"> BoundIdentifier ":" type ("=" expression)? ";" 60 | } | 61 | MacroInvocationSemi | 62 | MacroDefinition { 63 | ckw<"macro_rules"> !macroRules "!" Identifier ( 64 | "(" (MacroRule ";")* MacroRule? ")" ";" | 65 | "{" (MacroRule ";")* MacroRule? "}" 66 | ) 67 | } | 68 | EmptyStatement { ";" } | 69 | ModItem { 70 | Vis? kw<"mod"> BoundIdentifier (";" | DeclarationList) 71 | } | 72 | ForeignModItem { 73 | Vis? externModifier (";" | DeclarationList) 74 | } | 75 | StructItem { 76 | Vis? kw<"struct"> 77 | TypeIdentifier TypeParamList? 78 | (WhereClause? FieldDeclarationList | OrderedFieldDeclarationList WhereClause? ";" | ";") 79 | } | 80 | UnionItem { 81 | Vis? ckw<"union"> 82 | TypeIdentifier TypeParamList? WhereClause? FieldDeclarationList 83 | } | 84 | EnumItem { 85 | Vis? kw<"enum"> TypeIdentifier TypeParamList? WhereClause? 86 | EnumVariantList { "{" commaSep "}" } 87 | } | 88 | TypeItem { 89 | Vis? kw<"type"> TypeIdentifier TypeParamList? "=" type ";" 90 | } | 91 | FunctionItem { 92 | Vis? functionModifier* kw<"fn"> 93 | functionName TypeParamList? ParamList ("->" type)? 94 | WhereClause? 95 | (Block | ";") 96 | } | 97 | ImplItem { 98 | kw<"unsafe">? kw<"impl"> TypeParamList? 99 | ((!implBang "!")? type !implFor kw<"for">)? type 100 | WhereClause? DeclarationList 101 | } | 102 | TraitItem { 103 | Vis? kw<"unsafe">? kw<"trait"> TypeIdentifier TypeParamList? TraitBounds? WhereClause? DeclarationList 104 | } | 105 | AssociatedType { 106 | kw<"type"> TypeIdentifier TraitBounds? ";" 107 | } | 108 | LetDeclaration { 109 | kw<"let"> (!mut kw<"mut">)? pattern (":" type)? ("=" expression)? ";" 110 | } | 111 | UseDeclaration { 112 | Vis? kw<"use"> useClause ";" 113 | } | 114 | ExternCrateDeclaration { 115 | Vis? kw<"extern"> kw<"crate"> (BoundIdentifier | Identifier kw<"as"> BoundIdentifier) ";" 116 | } | 117 | StaticItem { 118 | Vis? kw<"static"> kw<"ref">? kw<"mut">? BoundIdentifier ":" type ("=" expression)? ";" 119 | } 120 | } 121 | 122 | functionName { BoundIdentifier | Metavariable } 123 | 124 | delimitedTokenTree { ParenthesizedTokens | BracketedTokens | BracedTokens } 125 | 126 | MacroRule { tokenTree "=>" delimitedTokenTree } 127 | 128 | tokenTree { 129 | delimitedTokenTree | 130 | TokenBinding { 131 | Metavariable !bind ":" tokenIdentifier 132 | } | 133 | TokenRepetition { 134 | "$" "(" tokenTree* ")" separatorToken? ("+" | "*" | "?") 135 | } | 136 | ArithOp { "*" | "+" } | 137 | "?" | 138 | separatorToken 139 | } 140 | 141 | separatorToken { 142 | String | 143 | RawString | 144 | Char | 145 | Integer | 146 | Float | 147 | tokenIdentifier | 148 | Lifetime | 149 | Metavariable | 150 | ArithOp { "-" | "/" } | 151 | BitOp { "<<" | ">>" | "&" | "|" | "^" } | 152 | LogicOp { "||" | "&&" } | 153 | UpdateOp | CompareOp | 154 | "." | "," | ";" | ":" | "=" | "->" | "=>" | ".." | "..." | "::" | "#" | "!" 155 | } 156 | 157 | ParenthesizedTokens { "(" tokenTree* ")" } 158 | BracketedTokens { "[" tokenTree* "]" } 159 | BracedTokens { "{" tokenTree* "}" } 160 | 161 | Attribute { 162 | "#" "[" MetaItem "]" 163 | } 164 | 165 | InnerAttribute { 166 | "#" "!" "[" MetaItem "]" 167 | } 168 | 169 | MetaItem { 170 | path ("=" tokenTree | delimitedTokenTree)? 171 | } 172 | 173 | DeclarationList { 174 | "{" InnerAttribute* (declarationStatement | AttributeItem)* "}" 175 | } 176 | 177 | EnumVariant { 178 | Vis? Identifier (FieldDeclarationList | OrderedFieldDeclarationList)? ("=" expression)? 179 | } 180 | 181 | FieldDeclarationList { 182 | "{" commaSep "}" 183 | } 184 | 185 | FieldDeclaration { 186 | Vis? FieldIdentifier ":" type 187 | } 188 | 189 | OrderedFieldDeclarationList { 190 | "(" commaSep ")" 191 | } 192 | 193 | functionModifier { 194 | kw<"async"> | ckw<"default"> | kw<"const"> | kw<"unsafe"> | externModifier 195 | } 196 | 197 | WhereClause { 198 | kw<"where"> commaSep 199 | } 200 | 201 | LifetimeClause { Lifetime ":" plusSep } 202 | 203 | TypeBoundClause { (HigherRankedTraitBound | type) TraitBounds } 204 | 205 | TraitBounds { 206 | ":" plusSep 207 | } 208 | 209 | HigherRankedTraitBound { 210 | kw<"for"> TypeParamList type 211 | } 212 | 213 | RemovedTraitBound { 214 | "?" type 215 | } 216 | 217 | typeParam[@inline] { 218 | Lifetime | 219 | Metavariable | 220 | TypeIdentifier | 221 | ConstrainedTypeParameter | 222 | OptionalTypeParameter | 223 | ConstParameter 224 | } 225 | 226 | TypeParamList { 227 | tpOpen !preferGenerics (typeParam !preferGenerics ("," typeParam? !preferGenerics)*)? tpClose 228 | } 229 | 230 | ConstParameter { 231 | kw<"const"> BoundIdentifier ":" type 232 | } 233 | 234 | ConstrainedTypeParameter { 235 | (Lifetime | TypeIdentifier) TraitBounds 236 | } 237 | 238 | OptionalTypeParameter { 239 | (TypeIdentifier | ConstrainedTypeParameter) "=" type 240 | } 241 | 242 | useClause { 243 | pathIdent | 244 | ScopedIdentifier { simplePathPrefix BoundIdentifier } | 245 | UseAsClause { simplePath kw<"as"> BoundIdentifier } | 246 | UseList | 247 | ScopedUseList { simplePathPrefix UseList } | 248 | UseWildcard { simplePathPrefix? "*" } 249 | } 250 | 251 | UseList { 252 | "{" commaSep "}" 253 | } 254 | 255 | ParamList { 256 | "(" commaSep)> ")" 257 | } 258 | 259 | SelfParameter { 260 | "&"? Lifetime? (!mut kw<"mut">)? !selfParam kw<"self"> 261 | } 262 | 263 | Parameter { 264 | (!mut kw<"mut">)? pattern ":" type 265 | } 266 | 267 | externModifier { 268 | kw<"extern"> String? 269 | } 270 | 271 | Vis { 272 | kw<"pub"> (!call "(" (kw<"self"> | kw<"super"> | kw<"crate"> | kw<"in"> path) ")")? | 273 | kw<"crate"> !crateVis 274 | } 275 | 276 | type[@isGroup=Type] { 277 | AbstractType { kw<"impl"> (typePath | GenericType | FunctionType) } | 278 | ReferenceType { "&" Lifetime? kw<"mut">? type } | 279 | PointerType { "*" (kw<"const"> | kw<"mut">) type } | 280 | typePath | 281 | GenericType | 282 | TupleType { "(" commaSep1 ")" } | 283 | UnitType { "(" ")" } | 284 | ArrayType { "[" type (";" expression)? "]" } | 285 | FunctionType | 286 | MacroInvocation { typePath !macro "!" delimitedTokenTree } | 287 | EmptyType { "!" } | 288 | DynamicType { kw<"dyn"> (typePath | GenericType | FunctionType) } | 289 | BoundedType { Lifetime !bound "+" type | type !bound "+" type | type !bound "+" Lifetime } 290 | } 291 | 292 | FunctionType { 293 | ForLifetimes { kw<"for"> tpOpen commaSep tpClose }? 294 | (typePath | functionModifier* kw<"fn">) 295 | !params ParamList { 296 | "(" commaSep | Parameter { type }> ")" 297 | } 298 | ("->" type)? 299 | } 300 | 301 | GenericType { 302 | typePath !typeArgs TypeArgList 303 | } 304 | 305 | TypeArgList { 306 | tpOpen commaSep1 tpClose 307 | } 308 | 309 | TypeBinding { 310 | TypeIdentifier "=" type 311 | } 312 | 313 | expression[@isGroup=Expression] { blockExpression | nonBlockExpression } 314 | 315 | nonBlockExpression { 316 | UnaryExpression { (ArithOp { "-" } | DerefOp { "*" } | LogicOp { "!" }) !unary expression } | 317 | ReferenceExpression { "&" kw<"mut">? expression } | 318 | TryExpression { expression !try "?" } | 319 | BinaryExpression | 320 | AssignmentExpression { expression !assign ("=" | UpdateOp) expression } | 321 | TypeCastExpression { expression !cast kw<"as"> type } | 322 | ReturnExpression { kw<"return"> (!return expression)? } | 323 | RangeExpression { expression? !range (".." | "..." | "..=") expression? } | 324 | CallExpression { expression !call ArgList } | 325 | literal | 326 | path | 327 | AwaitExpression { expression !deref "." kw<"await"> } | 328 | FieldExpression | 329 | GenericFunction { (path | FieldExpression) !scope "::" TypeArgList } | 330 | BreakExpression { kw<"break"> LoopLabel? (!return expression)? } | 331 | ContinueExpression { kw<"continue"> LoopLabel? } | 332 | IndexExpression { expression !deref "[" expression "]" } | 333 | ArrayExpression { "[" InnerAttribute* (expression ";" expression | commaSep1)? "]" } | 334 | TupleExpression { "(" InnerAttribute* expression ("," expression?)+ ")" } | 335 | MacroInvocation { macroInvocation } | 336 | UnitExpression { "(" ")" } | 337 | ClosureExpression { kw<"move">? ClosureParamList (("->" type)? !statement Block | expression) } | 338 | ParenthesizedExpression { "(" InnerAttribute* expression ")" } | 339 | StructExpression { structName FieldInitializerList } 340 | } 341 | 342 | FieldExpression { expression !deref "." (FieldIdentifier | Integer) } 343 | 344 | blockExpression { 345 | UnsafeBlock { kw<"unsafe"> Block } | 346 | AsyncBlock { kw<"async"> kw<"move">? Block } | 347 | Block | 348 | IfExpression | 349 | MatchExpression { 350 | kw<"match"> expression MatchBlock { "{" InnerAttribute* (MatchArm<",">* MatchArm<","?>)? "}" } 351 | } | 352 | WhileExpression { 353 | (LoopLabel ":")? kw<"while"> cond Block 354 | } | 355 | LoopExpression { 356 | (LoopLabel ":")? kw<"loop"> Block 357 | } | 358 | ForExpression { 359 | (LoopLabel ":")? kw<"for"> pattern kw<"in"> expression Block 360 | } 361 | } 362 | 363 | macroInvocation { 364 | path !macro "!" delimitedTokenTree 365 | } 366 | 367 | MacroInvocationSemi[@name=MacroInvocation] { 368 | path !macro "!" ((ParenthesizedTokens | BracketedTokens) !macroSemi ";" | BracedTokens !macroSemi) 369 | } 370 | 371 | QualifiedScope { tpOpen type (kw<"as"> type)? tpClose } 372 | 373 | pathIdent { 374 | kw<"self"> | 375 | Metavariable | 376 | kw<"super"> | 377 | kw<"crate"> | 378 | and 379 | } 380 | 381 | pathSegment { 382 | pathIdent ~path !scope "::" (TypeArgList "::")? 383 | } 384 | 385 | path { 386 | pathIdent ~path | 387 | ScopedIdentifier { 388 | (("::" | QualifiedScope !scope "::") pathSegment* | pathSegment+) pathIdent ~path 389 | } 390 | } 391 | 392 | typePathSegment { 393 | pathIdent ~path ((!scope "::")? TypeArgList)? !scope "::" 394 | } 395 | 396 | typePath { 397 | SelfType { kw<"self"> } ~path | 398 | MetaType { Metavariable } ~path | 399 | TypeIdentifier ~path | 400 | ScopedTypeIdentifier { 401 | (("::" | QualifiedScope !scope "::") typePathSegment* | typePathSegment+) pathIdent ~path 402 | } 403 | } 404 | 405 | simplePathPrefix[@inline] { 406 | "::" (pathIdent ~path !scope "::")* | 407 | (pathIdent ~path !scope "::")+ 408 | } 409 | 410 | simplePath { 411 | pathIdent ~path | 412 | ScopedIdentifier { simplePathPrefix pathIdent ~path } 413 | } 414 | 415 | structName { 416 | pathIdent ~path | 417 | ScopedTypeIdentifier { 418 | (("::" | QualifiedScope !scope "::") pathSegment* | pathSegment+) pathIdent ~path 419 | } 420 | } 421 | 422 | patternPath { 423 | MetaPattern { Metavariable ~path } | 424 | BoundIdentifier ~path | 425 | SelfPattern { kw<"self"> ~path } | 426 | ScopedIdentifier { 427 | (("::" | QualifiedScope !scope "::") pathSegment* | pathSegment+) pathIdent ~path 428 | } 429 | } 430 | 431 | BinaryExpression { 432 | expression !add ArithOp { "+" | "-" } expression | 433 | expression !mult ArithOp { "*" | "/" | "%" } expression | 434 | expression !shift BitOp { "<<" | ">>" } expression | 435 | expression !bitAnd BitOp { "&" } expression | 436 | expression !bitXor BitOp { "^" } expression | 437 | expression !bitOr BitOp { "|" } expression | 438 | expression !compare CompareOp expression | 439 | expression !and LogicOp { "&&" } expression | 440 | expression !or LogicOp { "||" } expression 441 | } 442 | 443 | ArgList { 444 | "(" commaSep ")" 445 | } 446 | 447 | FieldInitializerList { 448 | "{" commaSep "}" 449 | } 450 | 451 | fieldInitializer { 452 | ShorthandFieldInitializer { Attribute* Identifier } | 453 | FieldInitializer { Attribute* FieldIdentifier ":" expression } | 454 | BaseFieldInitializer { ".." expression } 455 | } 456 | 457 | IfExpression { 458 | kw<"if"> cond Block (!else kw<"else"> (Block | IfExpression))? 459 | } 460 | 461 | cond { 462 | expression | 463 | LetDeclaration { kw<"let"> pattern "=" expression } 464 | } 465 | 466 | Guard { kw<"if"> expression } 467 | 468 | MatchArm { 469 | Attribute* pattern Guard? 470 | "=>" (nonBlockExpression after | !block blockExpression) 471 | } 472 | 473 | ClosureParamList[@name=ParamList] { 474 | closureParamDelim commaSep)? pattern (":" type)?}> closureParamDelim 475 | } 476 | 477 | Block { 478 | "{" 479 | InnerAttribute* 480 | statement* 481 | ExpressionStatement { expression }? 482 | "}" 483 | } 484 | 485 | pattern[@isGroup=Pattern] { 486 | LiteralPattern { literalPattern } | 487 | patternPath | 488 | TuplePattern { structName? "(" commaSep ")" } | 489 | StructPattern { 490 | structName 491 | FieldPatternList { "{" commaSep "}" } 492 | } | 493 | RefPattern { kw<"ref"> !unary pattern } | 494 | SlicePattern { "[" commaSep "]" } | 495 | CapturedPattern { BoundIdentifier "@" pattern } | 496 | ReferencePattern { "&" !unary (!mut kw<"mut">)? pattern } | 497 | ".." | 498 | MutPattern { kw<"mut"> !unary pattern } | 499 | RangePattern { (literalPattern | path) ("..." | "..=") (literalPattern | path) } | 500 | OrPattern { pattern !or "|" pattern } | 501 | MacroPattern { macroInvocation } | 502 | kw<"_"> 503 | } 504 | 505 | FieldPattern { 506 | kw<"ref">? (!mut kw<"mut">)? (BoundIdentifier | FieldIdentifier ":" pattern) 507 | } 508 | 509 | literal { 510 | String | 511 | RawString | 512 | Char | 513 | boolean | 514 | Integer | 515 | Float 516 | } 517 | 518 | literalPattern { 519 | literal | 520 | ArithOp { "-" } (Integer | Float) 521 | } 522 | 523 | boolean { @specialize[@name=Boolean] } 524 | 525 | @skip {} { 526 | BlockComment[isolate] { "/*" (BlockComment | blockCommentContent)* blockCommentEnd } 527 | 528 | String[isolate] { stringStart (Escape | stringContent)* stringEnd } 529 | } 530 | 531 | Identifier { identifier } 532 | 533 | TypeIdentifier { identifier } 534 | 535 | FieldIdentifier { identifier } 536 | 537 | ScopeIdentifier { identifier } 538 | 539 | BoundIdentifier { identifier } 540 | 541 | LoopLabel { quoteIdentifier } 542 | 543 | Lifetime { quoteIdentifier } 544 | 545 | kw { @specialize[@name={term}] } 546 | 547 | ckw { @extend[@name={term}] } 548 | 549 | commaSep { commaSep1? } 550 | 551 | commaSep1 { expr ("," expr?)* } 552 | 553 | plusSep { expr (!plusSep "+" expr)* } 554 | 555 | @external tokens closureParam from "./tokens" { closureParamDelim[@name="|"] } 556 | 557 | @external tokens tpDelim from "./tokens" { tpOpen[@name="<"], tpClose[@name=">"] } 558 | 559 | @external tokens literalTokens from "./tokens" { RawString[isolate], Float } 560 | 561 | @tokens { 562 | whitespace { $[ \t\r\n] } 563 | 564 | UpdateOp { ($[+\-*/%^&|] | "<<" | ">>") "=" } 565 | 566 | CompareOp { $[<>] "="? | $[!=] "=" } 567 | 568 | Integer { 569 | ($[0-9] $[0-9_]* | 570 | "0x" $[0-9a-fA-F_]+ | 571 | "0b" $[01_]+ | 572 | "0o" $[0-7_]+) 573 | (("u" | "i") ("8" | "16" | "32" | "64" | "128" | "size"))? 574 | } 575 | 576 | hex { $[0-9a-fA-F] } 577 | Escape { "\\" (![xu] | "u" hex hex hex hex | "u{" hex+ "}" | "x" hex hex) } 578 | 579 | Char { "b"? "'" (Escape | ![\\'])? "'" } 580 | 581 | LineComment[isolate] { "//" ![\n]* } 582 | 583 | @precedence { LineComment, "/" } 584 | 585 | blockCommentContent { ![*/] blockCommentContent? | "*" blockCommentStar | "/" blockCommentSlash } 586 | blockCommentStar { ![/*] blockCommentContent | "*" blockCommentStar } 587 | blockCommentSlash { ![/*] blockCommentContent | "/" blockCommentSlash } 588 | 589 | blockCommentEnd { ![*/] blockCommentEnd | "*" blockCommentEndStar | "/" blockCommentEndSlash } 590 | blockCommentEndStar { "/" | ![/*] blockCommentEnd | "*" blockCommentEndStar } 591 | blockCommentEndSlash { ![/*] blockCommentEnd | "/" blockCommentSlash } 592 | 593 | @precedence { blockCommentEnd, blockCommentContent } 594 | 595 | stringStart { "b"? '"' } 596 | stringContent { !["\\\n]* "\n" | !["\\\n]+ } 597 | stringEnd { '"' } 598 | 599 | identBase { $[a-zA-Zα-ωΑ-Ωµ_] $[a-zA-Zα-ωΑ-Ωµ0-9_]* } 600 | identifier { ("r#")? identBase } 601 | tokenIdentifier[@name=Identifier] { identBase } 602 | quoteIdentifier { "'" identBase } 603 | Metavariable { "$" identBase } 604 | 605 | @precedence { stringStart, Char, identifier } 606 | @precedence { stringStart, Char, tokenIdentifier } 607 | @precedence { Char, quoteIdentifier } 608 | @precedence { Metavariable, "$" } 609 | 610 | "[" "]" "{" "}" "(" ")" 611 | ";" ":" "::" "," 612 | "=" "->" "=>" ".." "..." 613 | "&" "!" 614 | } 615 | 616 | @external propSource rustHighlighting from "./highlight" 617 | 618 | @detectDelim 619 | -------------------------------------------------------------------------------- /src/tokens.js: -------------------------------------------------------------------------------- 1 | import {ExternalTokenizer} from "@lezer/lr" 2 | import {Float, RawString, closureParamDelim, tpOpen, tpClose} from "./parser.terms" 3 | 4 | const _b = 98, _e = 101, _f = 102, _r = 114, _E = 69, Zero = 48, 5 | Dot = 46, Plus = 43, Minus = 45, Hash = 35, Quote = 34, Pipe = 124, LessThan = 60, GreaterThan = 62 6 | 7 | function isNum(ch) { return ch >= 48 && ch <= 57 } 8 | function isNum_(ch) { return isNum(ch) || ch == 95 } 9 | 10 | export const literalTokens = new ExternalTokenizer((input, stack) => { 11 | if (isNum(input.next)) { 12 | let isFloat = false 13 | do { input.advance() } while (isNum_(input.next)) 14 | if (input.next == Dot) { 15 | isFloat = true 16 | input.advance() 17 | if (isNum(input.next)) { 18 | do { input.advance() } while (isNum_(input.next)) 19 | } else if (input.next == Dot || input.next > 0x7f || /\w/.test(String.fromCharCode(input.next))) { 20 | return 21 | } 22 | } 23 | if (input.next == _e || input.next == _E) { 24 | isFloat = true 25 | input.advance() 26 | if (input.next == Plus || input.next == Minus) input.advance() 27 | if (!isNum_(input.next)) return 28 | do { input.advance() } while (isNum_(input.next)) 29 | } 30 | if (input.next == _f) { 31 | let after = input.peek(1) 32 | if (after == Zero + 3 && input.peek(2) == Zero + 2 || 33 | after == Zero + 6 && input.peek(2) == Zero + 4) { 34 | input.advance(3) 35 | isFloat = true 36 | } else { 37 | return 38 | } 39 | } 40 | if (isFloat) input.acceptToken(Float) 41 | } else if (input.next == _b || input.next == _r) { 42 | if (input.next == _b) input.advance() 43 | if (input.next != _r) return 44 | input.advance() 45 | let count = 0 46 | while (input.next == Hash) { count++; input.advance() } 47 | if (input.next != Quote) return 48 | input.advance() 49 | content: for (;;) { 50 | if (input.next < 0) return 51 | let isQuote = input.next == Quote 52 | input.advance() 53 | if (isQuote) { 54 | for (let i = 0; i < count; i++) { 55 | if (input.next != Hash) continue content 56 | input.advance() 57 | } 58 | input.acceptToken(RawString) 59 | return 60 | } 61 | } 62 | } 63 | }) 64 | 65 | export const closureParam = new ExternalTokenizer(input => { 66 | if (input.next == Pipe) input.acceptToken(closureParamDelim, 1) 67 | }) 68 | 69 | export const tpDelim = new ExternalTokenizer(input => { 70 | if (input.next == LessThan) input.acceptToken(tpOpen, 1) 71 | else if (input.next == GreaterThan) input.acceptToken(tpClose, 1) 72 | }) 73 | -------------------------------------------------------------------------------- /test/async.txt: -------------------------------------------------------------------------------- 1 | # Async function 2 | 3 | async fn abc() {} 4 | 5 | async fn main() { 6 | let x = futures.await?; 7 | } 8 | 9 | ==> 10 | 11 | SourceFile( 12 | FunctionItem(async, fn, 13 | BoundIdentifier, 14 | ParamList, 15 | Block), 16 | FunctionItem(async, fn, BoundIdentifier, ParamList, 17 | Block( 18 | LetDeclaration(let,BoundIdentifier, TryExpression( 19 | AwaitExpression(Identifier, await)))))) 20 | 21 | # Await expression 22 | 23 | futures.await; 24 | futures.await?; 25 | futures.await?.await?; 26 | futures.await?.function().await?; 27 | 28 | ==> 29 | 30 | SourceFile( 31 | ExpressionStatement(AwaitExpression(Identifier, await)), 32 | ExpressionStatement(TryExpression( 33 | AwaitExpression(Identifier, await))), 34 | ExpressionStatement(TryExpression( 35 | AwaitExpression( 36 | TryExpression( 37 | AwaitExpression(Identifier, await)), await))), 38 | ExpressionStatement(TryExpression( 39 | AwaitExpression( 40 | CallExpression( 41 | FieldExpression( 42 | TryExpression( 43 | AwaitExpression(Identifier, await)), 44 | FieldIdentifier), 45 | ArgList), await)))) 46 | 47 | 48 | # Async Block 49 | 50 | async {} 51 | async { let x = 10; } 52 | async move {} 53 | 54 | ==> 55 | 56 | SourceFile( 57 | ExpressionStatement(AsyncBlock(async, Block)), 58 | ExpressionStatement(AsyncBlock(async, Block(LetDeclaration(let, BoundIdentifier, Integer)))), 59 | ExpressionStatement(AsyncBlock(async, move, Block))) 60 | -------------------------------------------------------------------------------- /test/comments.txt: -------------------------------------------------------------------------------- 1 | # Block comments 2 | 3 | /* 4 | * Block comments 5 | */ 6 | 7 | /* Comment with asterisks **/ 8 | 9 | ==> 10 | 11 | SourceFile( 12 | BlockComment, 13 | BlockComment) 14 | 15 | 16 | # Nested block comments 17 | 18 | /* /* double nested */ */ 19 | 20 | // --- 21 | 22 | /*/*/* triple nested */*/*/ 23 | 24 | // --- 25 | 26 | /**** 27 | /**** 28 | nested with extra stars 29 | ****/ 30 | ****/ 31 | 32 | // --- 33 | 34 | ==> 35 | 36 | SourceFile( 37 | BlockComment(BlockComment), 38 | LineComment, 39 | BlockComment(BlockComment(BlockComment)), 40 | LineComment, 41 | BlockComment(BlockComment), 42 | LineComment) 43 | 44 | 45 | # Line comments 46 | 47 | // Comment 48 | 49 | ==> 50 | 51 | SourceFile( 52 | LineComment) 53 | -------------------------------------------------------------------------------- /test/declarations.txt: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | mod english; 4 | 5 | mod english {} 6 | 7 | mod english { 8 | mod greetings {} 9 | mod farewells {} 10 | } 11 | 12 | pub mod english; 13 | 14 | ==> 15 | 16 | SourceFile( 17 | ModItem(mod,BoundIdentifier), 18 | ModItem(mod,BoundIdentifier, DeclarationList), 19 | ModItem(mod,BoundIdentifier, DeclarationList( 20 | ModItem(mod,BoundIdentifier, DeclarationList), 21 | ModItem(mod,BoundIdentifier, DeclarationList))), 22 | ModItem(Vis(pub),mod, BoundIdentifier)) 23 | 24 | 25 | # Extern crate declarations 26 | 27 | extern crate std; 28 | extern crate std as ruststd; 29 | pub extern crate futures; 30 | 31 | ==> 32 | 33 | SourceFile( 34 | ExternCrateDeclaration(extern,crate, BoundIdentifier), 35 | ExternCrateDeclaration(extern,crate, Identifier, as, BoundIdentifier), 36 | ExternCrateDeclaration(Vis(pub),extern, crate, BoundIdentifier)) 37 | 38 | 39 | # Function declarations 40 | 41 | fn main() {} 42 | 43 | fn add(x: i32, y: i32) -> i32 { 44 | return x + y; 45 | } 46 | 47 | fn takes_slice(slice: &str) { 48 | println!("Got: {}", slice); 49 | } 50 | 51 | fn foo() -> [u32; 2] { 52 | return [1, 2]; 53 | } 54 | 55 | fn foo() -> (u32, u16) { 56 | return (1, 2); 57 | } 58 | 59 | fn foo() { 60 | return 61 | } 62 | 63 | fn foo(x: impl FnOnce() -> result::Result) {} 64 | 65 | fn foo(#[attr] x: i32, #[attr] x: i64) {} 66 | 67 | fn accumulate(self) -> Machine<{State::Accumulate}> {} 68 | 69 | ==> 70 | 71 | SourceFile( 72 | FunctionItem(fn, 73 | BoundIdentifier, 74 | ParamList, 75 | Block), 76 | FunctionItem(fn, 77 | BoundIdentifier, 78 | ParamList( 79 | Parameter( 80 | BoundIdentifier, 81 | TypeIdentifier), 82 | Parameter( 83 | BoundIdentifier, 84 | TypeIdentifier)), 85 | TypeIdentifier, 86 | Block( 87 | ExpressionStatement(ReturnExpression(return, 88 | BinaryExpression( 89 | Identifier, 90 | ArithOp, 91 | Identifier))))), 92 | FunctionItem(fn, 93 | BoundIdentifier, 94 | ParamList( 95 | Parameter( 96 | BoundIdentifier, 97 | ReferenceType( 98 | TypeIdentifier))), 99 | Block( 100 | MacroInvocation( 101 | Identifier, 102 | ParenthesizedTokens( 103 | String, 104 | Identifier)))), 105 | FunctionItem(fn, 106 | BoundIdentifier, 107 | ParamList, 108 | ArrayType( 109 | TypeIdentifier, 110 | Integer), 111 | Block( 112 | ExpressionStatement(ReturnExpression(return, 113 | ArrayExpression( 114 | Integer, 115 | Integer))))), 116 | FunctionItem(fn, 117 | BoundIdentifier, 118 | ParamList, 119 | TupleType( 120 | TypeIdentifier, 121 | TypeIdentifier), 122 | Block( 123 | ExpressionStatement(ReturnExpression(return, 124 | TupleExpression( 125 | Integer, 126 | Integer))))), 127 | FunctionItem(fn, 128 | BoundIdentifier, 129 | ParamList, 130 | Block( 131 | ExpressionStatement(ReturnExpression(return)))), 132 | FunctionItem(fn, 133 | BoundIdentifier, 134 | ParamList( 135 | Parameter( 136 | BoundIdentifier, 137 | AbstractType( 138 | impl, 139 | FunctionType( 140 | TypeIdentifier, 141 | ParamList, 142 | GenericType( 143 | ScopedTypeIdentifier( 144 | ScopeIdentifier, 145 | TypeIdentifier), 146 | TypeArgList( 147 | TypeIdentifier, 148 | TypeIdentifier)))))), 149 | Block), 150 | FunctionItem(fn, 151 | BoundIdentifier, 152 | ParamList( 153 | Attribute( 154 | MetaItem( 155 | Identifier)), 156 | Parameter( 157 | BoundIdentifier, 158 | TypeIdentifier), 159 | Attribute( 160 | MetaItem( 161 | Identifier)), 162 | Parameter( 163 | BoundIdentifier, 164 | TypeIdentifier)), 165 | Block), 166 | FunctionItem(fn, 167 | BoundIdentifier, 168 | ParamList( 169 | SelfParameter( 170 | self)), 171 | GenericType( 172 | TypeIdentifier, 173 | TypeArgList( 174 | Block( 175 | ExpressionStatement(ScopedIdentifier( 176 | ScopeIdentifier, 177 | Identifier))))), 178 | Block)) 179 | 180 | 181 | # Const function declarations 182 | 183 | const fn main() {} 184 | 185 | ==> 186 | 187 | SourceFile( 188 | FunctionItem(const, fn, BoundIdentifier, ParamList, Block)) 189 | 190 | 191 | # Functions with abstract return types 192 | 193 | fn triples(a: impl B) -> impl Iterator { 194 | } 195 | 196 | ==> 197 | 198 | SourceFile( 199 | FunctionItem(fn, 200 | BoundIdentifier, 201 | ParamList( 202 | Parameter( 203 | BoundIdentifier, 204 | AbstractType(impl, TypeIdentifier))), 205 | AbstractType(impl, GenericType( 206 | TypeIdentifier, 207 | TypeArgList(TypeBinding(TypeIdentifier, TupleType(TypeIdentifier))))), 208 | Block)) 209 | 210 | 211 | # Diverging functions 212 | 213 | fn aborts() -> ! { 214 | } 215 | 216 | ==> 217 | 218 | SourceFile( 219 | FunctionItem(fn, 220 | BoundIdentifier, 221 | ParamList, 222 | EmptyType, 223 | Block)) 224 | 225 | 226 | # Extern function declarations 227 | 228 | extern "C" fn foo() {} 229 | extern "C" fn printf( 230 | c: *const c_char, 231 | ..., 232 | ) {} 233 | 234 | ==> 235 | 236 | SourceFile( 237 | FunctionItem(extern, String, fn, 238 | BoundIdentifier, 239 | ParamList, 240 | Block), 241 | FunctionItem(extern, String, fn, 242 | BoundIdentifier, 243 | ParamList(Parameter(BoundIdentifier, PointerType(const, TypeIdentifier)), VariadicParameter), 244 | Block)) 245 | 246 | 247 | # Use declarations 248 | 249 | use abc; 250 | use phrases::japanese; 251 | use sayings::english::greetings; 252 | use sayings::english::greetings as en_greetings ; 253 | use phrases::english::{greetings,farewells}; 254 | use sayings::japanese::farewells::*; 255 | pub use self::greetings::hello; 256 | use sayings::english::{self, greetings as en_greetings, farewells as en_farewells}; 257 | use three::{ dot::{one, four} }; 258 | use my::{ some::* }; 259 | use my::{*}; 260 | 261 | ==> 262 | 263 | SourceFile( 264 | UseDeclaration(use, 265 | BoundIdentifier), 266 | UseDeclaration(use, 267 | ScopedIdentifier( 268 | ScopeIdentifier, 269 | BoundIdentifier)), 270 | UseDeclaration(use, 271 | ScopedIdentifier( 272 | ScopeIdentifier, 273 | ScopeIdentifier, 274 | BoundIdentifier)), 275 | UseDeclaration(use, 276 | UseAsClause( 277 | ScopedIdentifier( 278 | ScopeIdentifier, 279 | ScopeIdentifier, 280 | Identifier), 281 | as, 282 | BoundIdentifier)), 283 | UseDeclaration(use, 284 | ScopedUseList( 285 | ScopeIdentifier, 286 | ScopeIdentifier, 287 | UseList( 288 | BoundIdentifier, 289 | BoundIdentifier))), 290 | UseDeclaration(use, 291 | UseWildcard( 292 | ScopeIdentifier, 293 | ScopeIdentifier, 294 | ScopeIdentifier)), 295 | UseDeclaration(Vis(pub), use, 296 | ScopedIdentifier( 297 | self, 298 | ScopeIdentifier, 299 | BoundIdentifier)), 300 | UseDeclaration(use, 301 | ScopedUseList( 302 | ScopeIdentifier, 303 | ScopeIdentifier, 304 | UseList( 305 | self, 306 | UseAsClause( 307 | Identifier, 308 | as, 309 | BoundIdentifier), 310 | UseAsClause( 311 | Identifier, 312 | as, 313 | BoundIdentifier)))), 314 | UseDeclaration(use, 315 | ScopedUseList( 316 | ScopeIdentifier, 317 | UseList( 318 | ScopedUseList( 319 | ScopeIdentifier, 320 | UseList( 321 | BoundIdentifier, 322 | BoundIdentifier))))), 323 | UseDeclaration(use, 324 | ScopedUseList( 325 | ScopeIdentifier, 326 | UseList( 327 | UseWildcard( 328 | ScopeIdentifier)))), 329 | UseDeclaration(use, 330 | ScopedUseList( 331 | ScopeIdentifier, 332 | UseList( 333 | UseWildcard)))) 334 | 335 | 336 | # Variable bindings 337 | 338 | let x; 339 | let x = 42; 340 | let x: i32; 341 | let x: i8 = 42; 342 | let mut x = 5; 343 | let y: bool = false; 344 | let bool: bool = false; 345 | let u32: str = ""; 346 | 347 | ==> 348 | 349 | SourceFile( 350 | LetDeclaration(let,BoundIdentifier), 351 | LetDeclaration(let,BoundIdentifier, Integer), 352 | LetDeclaration(let,BoundIdentifier, TypeIdentifier), 353 | LetDeclaration(let,BoundIdentifier, TypeIdentifier, Integer), 354 | LetDeclaration(let,mut, BoundIdentifier, Integer), 355 | LetDeclaration(let,BoundIdentifier, TypeIdentifier, Boolean), 356 | LetDeclaration(let,BoundIdentifier, TypeIdentifier, Boolean), 357 | LetDeclaration(let,BoundIdentifier, TypeIdentifier, String)) 358 | 359 | 360 | # Structs 361 | 362 | struct Proton; 363 | struct Electron {} 364 | struct Person {pub name: String, pub age: u32} 365 | struct Point { 366 | x: i32, 367 | 368 | #[attribute1] 369 | y: i32, 370 | } 371 | struct Color(pub i32, i32, i32); 372 | struct Inches(i32); 373 | 374 | ==> 375 | 376 | SourceFile( 377 | StructItem(struct,TypeIdentifier), 378 | StructItem(struct,TypeIdentifier, FieldDeclarationList), 379 | StructItem(struct,TypeIdentifier, FieldDeclarationList( 380 | FieldDeclaration(Vis(pub), FieldIdentifier, TypeIdentifier), 381 | FieldDeclaration(Vis(pub), FieldIdentifier, TypeIdentifier))), 382 | StructItem(struct,TypeIdentifier, FieldDeclarationList( 383 | FieldDeclaration(FieldIdentifier, TypeIdentifier), 384 | Attribute(MetaItem(Identifier)), 385 | FieldDeclaration(FieldIdentifier, TypeIdentifier))), 386 | StructItem(struct,TypeIdentifier, OrderedFieldDeclarationList( 387 | Vis(pub), TypeIdentifier, TypeIdentifier, TypeIdentifier)), 388 | StructItem(struct,TypeIdentifier, OrderedFieldDeclarationList( 389 | TypeIdentifier))) 390 | 391 | 392 | # Unions 393 | 394 | pub union in6_addr__bindgen_ty_1 { 395 | pub __u6_addr8: [__uint8_t; 16usize], 396 | pub __u6_addr16: [__uint16_t; 8usize], 397 | pub __u6_addr32: [__uint32_t; 4usize], 398 | _bindgen_union_align: [u32; 4usize], 399 | } 400 | 401 | ==> 402 | 403 | SourceFile( 404 | UnionItem(Vis(pub), union, TypeIdentifier, FieldDeclarationList( 405 | FieldDeclaration(Vis(pub), FieldIdentifier, ArrayType(TypeIdentifier, Integer)), 406 | FieldDeclaration(Vis(pub), FieldIdentifier, ArrayType(TypeIdentifier, Integer)), 407 | FieldDeclaration(Vis(pub), FieldIdentifier, ArrayType(TypeIdentifier, Integer)), 408 | FieldDeclaration(FieldIdentifier, ArrayType(TypeIdentifier, Integer))))) 409 | 410 | 411 | # Generic structs 412 | 413 | struct A {} 414 | struct C<'a, 'b> {} 415 | struct C<'a,> {} 416 | struct D {} 417 | 418 | ==> 419 | 420 | SourceFile( 421 | StructItem(struct, 422 | TypeIdentifier, 423 | TypeParamList( 424 | TypeIdentifier), 425 | FieldDeclarationList), 426 | StructItem(struct, 427 | TypeIdentifier, 428 | TypeParamList( 429 | Lifetime, 430 | Lifetime), 431 | FieldDeclarationList), 432 | StructItem(struct, 433 | TypeIdentifier, 434 | TypeParamList( 435 | Lifetime), 436 | FieldDeclarationList), 437 | StructItem(struct, 438 | TypeIdentifier, 439 | TypeParamList( 440 | ConstParameter(const, 441 | BoundIdentifier, 442 | TypeIdentifier)), 443 | FieldDeclarationList)) 444 | 445 | 446 | # Enums 447 | 448 | pub enum Option { 449 | None, 450 | Some(T), 451 | } 452 | 453 | pub enum Node { 454 | Internal { 455 | children: Vec>, 456 | height: u16 457 | }, 458 | #[attribute1] 459 | #[attribute2] 460 | Leaf { 461 | value: T 462 | } 463 | } 464 | 465 | ==> 466 | 467 | SourceFile( 468 | EnumItem(Vis(pub), enum, 469 | TypeIdentifier, 470 | TypeParamList(TypeIdentifier), 471 | EnumVariantList( 472 | EnumVariant(Identifier), 473 | EnumVariant(Identifier, OrderedFieldDeclarationList(TypeIdentifier)))), 474 | EnumItem(Vis(pub), enum, 475 | TypeIdentifier, 476 | TypeParamList(ConstrainedTypeParameter( 477 | TypeIdentifier, 478 | TraitBounds(TypeIdentifier))), 479 | EnumVariantList( 480 | EnumVariant( 481 | Identifier, 482 | FieldDeclarationList( 483 | FieldDeclaration(FieldIdentifier, GenericType( 484 | TypeIdentifier, 485 | TypeArgList( 486 | GenericType(TypeIdentifier, TypeArgList(TypeIdentifier))))), 487 | FieldDeclaration(FieldIdentifier, TypeIdentifier))), 488 | Attribute(MetaItem(Identifier)), 489 | Attribute(MetaItem(Identifier)), 490 | EnumVariant( 491 | Identifier, 492 | FieldDeclarationList( 493 | FieldDeclaration(FieldIdentifier, TypeIdentifier)))))) 494 | 495 | 496 | # Enums with values specified 497 | 498 | pub enum c_style_enum { 499 | val1 = 1, 500 | val2 = 2 501 | } 502 | 503 | ==> 504 | 505 | SourceFile( 506 | EnumItem(Vis(pub), enum, 507 | TypeIdentifier, 508 | EnumVariantList( 509 | EnumVariant(Identifier, Integer), 510 | EnumVariant(Identifier, Integer)))) 511 | 512 | 513 | # Generic functions 514 | 515 | pub fn splice>(&mut self, old_range: Range, new_text: T) { 516 | } 517 | pub fn uninit_array() -> [Self; LEN] {} 518 | 519 | ==> 520 | 521 | SourceFile( 522 | FunctionItem(Vis(pub), fn, 523 | BoundIdentifier, 524 | TypeParamList( 525 | ConstrainedTypeParameter( 526 | TypeIdentifier, 527 | TraitBounds( 528 | GenericType( 529 | TypeIdentifier, 530 | TypeArgList( 531 | TypeIdentifier))))), 532 | ParamList( 533 | SelfParameter( 534 | mut, 535 | self), 536 | Parameter( 537 | BoundIdentifier, 538 | GenericType( 539 | TypeIdentifier, 540 | TypeArgList( 541 | TypeIdentifier))), 542 | Parameter( 543 | BoundIdentifier, 544 | TypeIdentifier)), 545 | Block), 546 | FunctionItem(Vis(pub), fn, 547 | BoundIdentifier, 548 | TypeParamList( 549 | ConstParameter(const, 550 | BoundIdentifier, 551 | TypeIdentifier)), 552 | ParamList, 553 | ArrayType( 554 | TypeIdentifier, 555 | Identifier), 556 | Block)) 557 | 558 | 559 | # Functions with mutable parameters 560 | 561 | fn foo(mut x : u32) { 562 | } 563 | 564 | ==> 565 | 566 | SourceFile( 567 | FunctionItem(fn, 568 | BoundIdentifier, 569 | ParamList(Parameter(mut, BoundIdentifier, TypeIdentifier)), 570 | Block)) 571 | 572 | 573 | # Functions with destructured parameters 574 | 575 | fn f1([x, y]: [u32; 2]) {} 576 | fn f2(&x: &Y) {} 577 | fn f3((x, y): (T, U)) {} 578 | 579 | ==> 580 | 581 | SourceFile( 582 | FunctionItem(fn, 583 | BoundIdentifier, 584 | ParamList( 585 | Parameter( 586 | SlicePattern(BoundIdentifier, BoundIdentifier), 587 | ArrayType(TypeIdentifier, Integer))), 588 | Block), 589 | FunctionItem(fn, 590 | BoundIdentifier, 591 | ParamList( 592 | Parameter( 593 | ReferencePattern(BoundIdentifier), 594 | ReferenceType(TypeIdentifier))), 595 | Block), 596 | FunctionItem(fn, 597 | BoundIdentifier, 598 | ParamList( 599 | Parameter( 600 | TuplePattern(BoundIdentifier, BoundIdentifier), 601 | TupleType(TypeIdentifier, TypeIdentifier))), 602 | Block)) 603 | 604 | 605 | # Functions with custom types for self 606 | 607 | trait Callback { 608 | fn call(self: Box); 609 | } 610 | 611 | ==> 612 | 613 | SourceFile( 614 | TraitItem(trait, 615 | TypeIdentifier, 616 | DeclarationList( 617 | FunctionItem(fn, 618 | BoundIdentifier, 619 | ParamList( 620 | Parameter( 621 | SelfPattern(self), 622 | GenericType(TypeIdentifier, TypeArgList(TypeIdentifier)))))))) 623 | 624 | 625 | # Constant items 626 | 627 | const N: i32 = 5; 628 | 629 | trait Foo { 630 | const X: u8; 631 | } 632 | 633 | ==> 634 | 635 | SourceFile( 636 | ConstItem(const,BoundIdentifier, TypeIdentifier, Integer), 637 | TraitItem(trait, 638 | TypeIdentifier, 639 | DeclarationList(ConstItem(const,BoundIdentifier, TypeIdentifier)))) 640 | 641 | 642 | # Static items 643 | 644 | static N: i32 = 5; 645 | static mut __progname: *mut ::c_char; 646 | 647 | ==> 648 | 649 | SourceFile( 650 | StaticItem(static, 651 | BoundIdentifier, 652 | TypeIdentifier, 653 | Integer), 654 | StaticItem(static, 655 | mut, 656 | BoundIdentifier, 657 | PointerType(mut, ScopedTypeIdentifier(TypeIdentifier)))) 658 | 659 | 660 | # Static 'ref' items using lazy_static 661 | 662 | static ref ONE: usize = 0; 663 | 664 | ==> 665 | 666 | SourceFile( 667 | StaticItem(static,ref,BoundIdentifier, TypeIdentifier, Integer)) 668 | 669 | 670 | # Type aliases 671 | 672 | type Inch = u64; 673 | type Name = Vec; 674 | 675 | ==> 676 | 677 | SourceFile( 678 | TypeItem(type,TypeIdentifier, TypeIdentifier), 679 | TypeItem(type,TypeIdentifier, TypeParamList(TypeIdentifier), GenericType(TypeIdentifier, TypeArgList(TypeIdentifier)))) 680 | 681 | 682 | # Empty statements 683 | 684 | fn main() { 685 | ; 686 | } 687 | 688 | ==> 689 | 690 | SourceFile( 691 | FunctionItem(fn,BoundIdentifier, ParamList, Block( 692 | EmptyStatement))) 693 | 694 | 695 | # Attributes 696 | 697 | #![allow(clippy::useless_transmute)] 698 | 699 | #[test] 700 | fn test_foo() {} 701 | 702 | #[derive(Debug)] 703 | struct Baz; 704 | 705 | #[derive(Debug, Eq,)] 706 | struct Foo; 707 | 708 | #[cfg(target_os = "macos")] 709 | #[clippy::cyclomatic_complexity = "100"] 710 | #[a = b] 711 | mod macos_only {} 712 | 713 | ==> 714 | 715 | SourceFile( 716 | InnerAttribute(MetaItem( 717 | Identifier, 718 | ParenthesizedTokens(Identifier,Identifier))), 719 | 720 | AttributeItem( 721 | Attribute(MetaItem(Identifier)), 722 | FunctionItem(fn, 723 | BoundIdentifier, 724 | ParamList, 725 | Block)), 726 | 727 | AttributeItem( 728 | Attribute(MetaItem( 729 | Identifier, 730 | ParenthesizedTokens(Identifier))), 731 | StructItem(struct,TypeIdentifier)), 732 | 733 | AttributeItem( 734 | Attribute(MetaItem( 735 | Identifier, 736 | ParenthesizedTokens(Identifier, Identifier))), 737 | StructItem(struct,TypeIdentifier)), 738 | 739 | AttributeItem( 740 | Attribute(MetaItem( 741 | Identifier, 742 | ParenthesizedTokens(Identifier, String))), 743 | Attribute(MetaItem( 744 | ScopedIdentifier(ScopeIdentifier, Identifier), 745 | String)), 746 | Attribute(MetaItem(Identifier, Identifier)), 747 | ModItem(mod, 748 | BoundIdentifier, 749 | DeclarationList))) 750 | 751 | # Inner attributes 752 | 753 | mod macos_only { 754 | #![cfg(target_os = "macos")] 755 | } 756 | 757 | ==> 758 | 759 | SourceFile( 760 | ModItem(mod, 761 | BoundIdentifier, 762 | DeclarationList( 763 | InnerAttribute(MetaItem( 764 | Identifier, 765 | ParenthesizedTokens( 766 | Identifier, 767 | String)))))) 768 | 769 | # Attributes and Expressions 770 | 771 | fn foo() { 772 | bar(x, 773 | #[cfg(foo = "bar")] 774 | y); 775 | let z = [#![hello] 2, 7, 8]; 776 | let t = (#![hello] 2, 7, 8); 777 | } 778 | 779 | ==> 780 | 781 | SourceFile( 782 | FunctionItem(fn, 783 | BoundIdentifier, 784 | ParamList, 785 | Block( 786 | ExpressionStatement(CallExpression( 787 | Identifier, 788 | ArgList( 789 | Identifier, 790 | Attribute(MetaItem( 791 | Identifier, 792 | ParenthesizedTokens(Identifier, String))), 793 | Identifier))), 794 | LetDeclaration(let, 795 | BoundIdentifier, 796 | ArrayExpression( 797 | InnerAttribute(MetaItem(Identifier)), 798 | Integer, 799 | Integer, 800 | Integer)), 801 | LetDeclaration(let, 802 | BoundIdentifier, 803 | TupleExpression( 804 | InnerAttribute(MetaItem(Identifier)), 805 | Integer, 806 | Integer, 807 | Integer))))) 808 | 809 | 810 | # Inherent Impls 811 | 812 | impl Person { 813 | const leg_count : u32 = 2; 814 | 815 | fn walk(self) {} 816 | fn walk_mut(mut self) {} 817 | fn talk(& self) {} 818 | fn talk_mut(&'a mut self) {} 819 | } 820 | 821 | impl Machine<{State::Init}> {} 822 | 823 | ==> 824 | 825 | SourceFile( 826 | ImplItem(impl, 827 | TypeIdentifier, 828 | DeclarationList( 829 | ConstItem(const, 830 | BoundIdentifier, 831 | TypeIdentifier, 832 | Integer), 833 | FunctionItem(fn, 834 | BoundIdentifier, 835 | ParamList( 836 | SelfParameter( 837 | self)), 838 | Block), 839 | FunctionItem(fn, 840 | BoundIdentifier, 841 | ParamList( 842 | SelfParameter( 843 | mut, 844 | self)), 845 | Block), 846 | FunctionItem(fn, 847 | BoundIdentifier, 848 | ParamList( 849 | SelfParameter( 850 | self)), 851 | Block), 852 | FunctionItem(fn, 853 | BoundIdentifier, 854 | ParamList( 855 | SelfParameter( 856 | Lifetime, 857 | mut, 858 | self)), 859 | Block))), 860 | ImplItem(impl, 861 | GenericType( 862 | TypeIdentifier, 863 | TypeArgList( 864 | Block( 865 | ExpressionStatement(ScopedIdentifier( 866 | ScopeIdentifier, 867 | Identifier))))), 868 | DeclarationList)) 869 | 870 | 871 | # Trait impls 872 | 873 | impl<'a> iter::Iterator for Self::Iter<'a> { 874 | } 875 | 876 | impl ConvertTo for i32 { 877 | fn convert(&self) -> i64 { *self as i64 } 878 | } 879 | 880 | ==> 881 | 882 | SourceFile( 883 | ImplItem(impl, 884 | TypeParamList(Lifetime), 885 | ScopedTypeIdentifier( 886 | ScopeIdentifier, 887 | TypeIdentifier), 888 | for, 889 | GenericType( 890 | ScopedTypeIdentifier( 891 | ScopeIdentifier, 892 | TypeIdentifier), 893 | TypeArgList(Lifetime)), 894 | DeclarationList), 895 | ImplItem(impl, 896 | GenericType( 897 | TypeIdentifier, 898 | TypeArgList(TypeIdentifier)), 899 | for, 900 | TypeIdentifier, 901 | DeclarationList( 902 | FunctionItem(fn, 903 | BoundIdentifier, 904 | ParamList(SelfParameter(self)), 905 | TypeIdentifier, 906 | Block( 907 | ExpressionStatement(TypeCastExpression( 908 | UnaryExpression(DerefOp, self), 909 | as, 910 | TypeIdentifier))))))) 911 | 912 | 913 | # Unsafe impls 914 | 915 | unsafe impl Foo { 916 | } 917 | 918 | ==> 919 | 920 | SourceFile(ImplItem(unsafe, impl,TypeIdentifier, DeclarationList)) 921 | 922 | 923 | # Impls with default functions 924 | 925 | impl Foo { 926 | const default fn bar() -> i32 { 927 | // Make 'default' still works as an identifier 928 | default.bar(); 929 | } 930 | } 931 | 932 | ==> 933 | 934 | SourceFile( 935 | ImplItem(impl,TypeIdentifier, DeclarationList( 936 | FunctionItem(const, default, fn, 937 | BoundIdentifier, 938 | ParamList, 939 | TypeIdentifier, 940 | Block( 941 | LineComment, 942 | ExpressionStatement(CallExpression( 943 | FieldExpression(Identifier, FieldIdentifier), 944 | ArgList))))))) 945 | 946 | 947 | # Trait declarations 948 | 949 | pub trait Item: Clone + Eq + fmt::Debug { 950 | fn summarize(&self) -> Self::Summary; 951 | } 952 | 953 | unsafe trait Foo { } 954 | 955 | ==> 956 | 957 | SourceFile( 958 | TraitItem(Vis(pub), trait, 959 | TypeIdentifier, 960 | TraitBounds( 961 | TypeIdentifier, 962 | TypeIdentifier, 963 | ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier)), 964 | DeclarationList( 965 | FunctionItem(fn, 966 | BoundIdentifier, 967 | ParamList(SelfParameter(self)), 968 | ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier)))), 969 | TraitItem(unsafe, trait,TypeIdentifier, DeclarationList)) 970 | 971 | 972 | # Trait declarations with optional type parameters 973 | 974 | trait Add { 975 | type Output; 976 | fn add(self, rhs: RHS) -> Self::Output; 977 | } 978 | 979 | ==> 980 | 981 | SourceFile( 982 | TraitItem(trait, 983 | TypeIdentifier, 984 | TypeParamList(OptionalTypeParameter(TypeIdentifier, TypeIdentifier)), 985 | DeclarationList( 986 | AssociatedType(type,TypeIdentifier), 987 | FunctionItem( 988 | fn, 989 | BoundIdentifier, 990 | ParamList(SelfParameter(self), Parameter(BoundIdentifier, TypeIdentifier)), 991 | ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier))))) 992 | 993 | 994 | # Unsized types in trait bounds 995 | 996 | trait Foo { 997 | } 998 | 999 | ==> 1000 | 1001 | SourceFile( 1002 | TraitItem(trait, 1003 | TypeIdentifier, 1004 | TypeParamList( 1005 | ConstrainedTypeParameter( 1006 | TypeIdentifier, 1007 | TraitBounds(RemovedTraitBound(TypeIdentifier)))), 1008 | DeclarationList)) 1009 | 1010 | 1011 | # Macro invocations inside trait declarations 1012 | 1013 | pub trait A: B + C + D { 1014 | private_decl!{} 1015 | fn f(&self); 1016 | } 1017 | 1018 | ==> 1019 | 1020 | SourceFile( 1021 | TraitItem(Vis(pub), trait, 1022 | TypeIdentifier, 1023 | TraitBounds(TypeIdentifier, TypeIdentifier, TypeIdentifier), 1024 | DeclarationList( 1025 | MacroInvocation(Identifier, BracedTokens), 1026 | FunctionItem(fn, BoundIdentifier, ParamList(SelfParameter(self)))))) 1027 | 1028 | 1029 | # Associated Types 1030 | 1031 | pub trait Graph { 1032 | type N: fmt::Display; 1033 | type E; 1034 | } 1035 | 1036 | ==> 1037 | 1038 | SourceFile( 1039 | TraitItem(Vis(pub), trait, 1040 | TypeIdentifier, 1041 | DeclarationList( 1042 | AssociatedType(type,TypeIdentifier, TraitBounds(ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier))), 1043 | AssociatedType(type,TypeIdentifier)))) 1044 | 1045 | 1046 | # Higher-ranked types 1047 | 1048 | trait T: for<'a> AddAssign<&'a usize> { 1049 | } 1050 | 1051 | ==> 1052 | 1053 | SourceFile( 1054 | TraitItem(trait, 1055 | TypeIdentifier, 1056 | TraitBounds( 1057 | HigherRankedTraitBound(for, 1058 | TypeParamList(Lifetime), 1059 | GenericType(TypeIdentifier, TypeArgList(ReferenceType(Lifetime, TypeIdentifier))))), 1060 | DeclarationList)) 1061 | 1062 | 1063 | # Visibility modifiers 1064 | 1065 | pub fn a() {} 1066 | pub(super) fn b() {} 1067 | pub(self) fn c() {} 1068 | pub(crate) fn c() {} 1069 | pub(in crate::d) fn e() {} 1070 | 1071 | ==> 1072 | 1073 | SourceFile( 1074 | FunctionItem(Vis(pub), fn, BoundIdentifier, ParamList, Block), 1075 | FunctionItem(Vis(pub, super), fn, BoundIdentifier, ParamList, Block), 1076 | FunctionItem(Vis(pub, self), fn, BoundIdentifier, ParamList, Block), 1077 | FunctionItem(Vis(pub, crate), fn, BoundIdentifier, ParamList, Block), 1078 | FunctionItem(Vis(pub, in, ScopedIdentifier(crate, Identifier)), fn, 1079 | BoundIdentifier, 1080 | ParamList, 1081 | Block)) 1082 | 1083 | 1084 | # Function parameter names that match built-in type names 1085 | 1086 | fn foo(str: *const c_char) {} 1087 | fn bar(bool: bool) {} 1088 | 1089 | ==> 1090 | 1091 | SourceFile( 1092 | FunctionItem(fn,BoundIdentifier, ParamList(Parameter(BoundIdentifier, PointerType(const, TypeIdentifier))), Block), 1093 | FunctionItem(fn,BoundIdentifier, ParamList(Parameter(BoundIdentifier, TypeIdentifier)), Block)) 1094 | 1095 | # Where clauses 1096 | 1097 | fn walk(&self, it: &mut F) -> bool 1098 | where F: FnMut(&Pat) -> bool 1099 | { 1100 | return false 1101 | } 1102 | 1103 | impl<'a, T: 'a + Item> Iterator for Iter<'a, T> where Self: 'a { 1104 | } 1105 | 1106 | impl A for B 1107 | where C: D, 1108 | T: 'c, 1109 | 'c: 'b, 1110 | { 1111 | } 1112 | 1113 | impl<'a, E> Read 1114 | where &'a E: Read, 1115 | { 1116 | } 1117 | 1118 | impl A for B where (T, T, T): C, {} 1119 | 1120 | impl A for B 1121 | where for<'a> D: E<'a>, 1122 | { 1123 | } 1124 | 1125 | pub trait A where B: C, 1126 | { 1127 | } 1128 | 1129 | fn foo() where A: B + As, f64: As {} 1130 | 1131 | impl Default for B where *mut A: C + D {} 1132 | 1133 | ==> 1134 | 1135 | SourceFile( 1136 | FunctionItem(fn, 1137 | BoundIdentifier, 1138 | TypeParamList(TypeIdentifier), 1139 | ParamList( 1140 | SelfParameter(self), 1141 | Parameter( 1142 | BoundIdentifier, 1143 | ReferenceType( 1144 | mut, 1145 | TypeIdentifier))), 1146 | TypeIdentifier, 1147 | WhereClause(where, TypeBoundClause( 1148 | TypeIdentifier, 1149 | TraitBounds(FunctionType(TypeIdentifier,ParamList( 1150 | Parameter(ReferenceType(TypeIdentifier))),TypeIdentifier)))), 1151 | Block(ExpressionStatement(ReturnExpression(return,Boolean)))), 1152 | 1153 | ImplItem(impl, 1154 | TypeParamList( 1155 | Lifetime, 1156 | ConstrainedTypeParameter( 1157 | TypeIdentifier, 1158 | TraitBounds(Lifetime, TypeIdentifier))), 1159 | TypeIdentifier, 1160 | for, 1161 | GenericType( 1162 | TypeIdentifier, 1163 | TypeArgList( 1164 | Lifetime, 1165 | TypeIdentifier)), 1166 | WhereClause(where,TypeBoundClause(TypeIdentifier,TraitBounds(Lifetime))), 1167 | DeclarationList), 1168 | 1169 | ImplItem(impl, 1170 | TypeParamList(TypeIdentifier), 1171 | TypeIdentifier, 1172 | for, 1173 | GenericType( 1174 | TypeIdentifier, 1175 | TypeArgList(TypeIdentifier)), 1176 | WhereClause(where, 1177 | TypeBoundClause(GenericType(TypeIdentifier,TypeArgList(TypeIdentifier)),TraitBounds(TypeIdentifier)), 1178 | TypeBoundClause(TypeIdentifier,TraitBounds(Lifetime)), 1179 | LifetimeClause(Lifetime,Lifetime)), 1180 | DeclarationList), 1181 | 1182 | ImplItem(impl, 1183 | TypeParamList( 1184 | Lifetime, 1185 | TypeIdentifier), 1186 | TypeIdentifier, 1187 | WhereClause(where,TypeBoundClause(ReferenceType(Lifetime,TypeIdentifier),TraitBounds(TypeIdentifier))), 1188 | DeclarationList), 1189 | 1190 | ImplItem(impl, 1191 | TypeParamList(TypeIdentifier), 1192 | TypeIdentifier, 1193 | for, 1194 | GenericType( 1195 | TypeIdentifier, 1196 | TypeArgList(TypeIdentifier)), 1197 | WhereClause(where, 1198 | TypeBoundClause(TupleType(TypeIdentifier,TypeIdentifier,TypeIdentifier),TraitBounds(TypeIdentifier))), 1199 | DeclarationList), 1200 | 1201 | ImplItem(impl, 1202 | TypeParamList(TypeIdentifier), 1203 | TypeIdentifier, 1204 | for, 1205 | GenericType( 1206 | TypeIdentifier, 1207 | TypeArgList(TypeIdentifier)), 1208 | WhereClause(where, 1209 | TypeBoundClause(HigherRankedTraitBound(for, 1210 | TypeParamList(Lifetime), 1211 | GenericType(TypeIdentifier,TypeArgList(TypeIdentifier))), 1212 | TraitBounds(GenericType(TypeIdentifier,TypeArgList(Lifetime))))), 1213 | DeclarationList), 1214 | 1215 | TraitItem(Vis(pub), trait, 1216 | TypeIdentifier, 1217 | TypeParamList(TypeIdentifier), 1218 | WhereClause(where,TypeBoundClause(TypeIdentifier,TraitBounds(TypeIdentifier))), 1219 | DeclarationList), 1220 | 1221 | FunctionItem(fn, 1222 | BoundIdentifier, 1223 | TypeParamList(TypeIdentifier), 1224 | ParamList, 1225 | WhereClause(where, 1226 | TypeBoundClause(TypeIdentifier,TraitBounds( 1227 | TypeIdentifier,GenericType(TypeIdentifier,TypeArgList(TypeIdentifier)))), 1228 | TypeBoundClause(TypeIdentifier,TraitBounds(GenericType(TypeIdentifier,TypeArgList(TypeIdentifier))))), 1229 | Block), 1230 | 1231 | ImplItem(impl, 1232 | TypeParamList(TypeIdentifier), 1233 | TypeIdentifier, 1234 | for, 1235 | GenericType( 1236 | TypeIdentifier, 1237 | TypeArgList(TypeIdentifier)), 1238 | WhereClause(where,TypeBoundClause(PointerType(mut,TypeIdentifier),TraitBounds(TypeIdentifier,TypeIdentifier))), 1239 | DeclarationList)) 1240 | 1241 | # External Modules 1242 | 1243 | pub extern { 1244 | pub fn napi_module_register(mod_: *mut napi_module); 1245 | } 1246 | 1247 | extern "C" {} 1248 | 1249 | ==> 1250 | 1251 | SourceFile( 1252 | ForeignModItem(Vis(pub), extern, DeclarationList( 1253 | FunctionItem(Vis(pub), fn, BoundIdentifier, ParamList(Parameter(BoundIdentifier, PointerType(mut, TypeIdentifier)))))), 1254 | ForeignModItem(extern, String, DeclarationList)) 1255 | 1256 | 1257 | # Crate visibility 1258 | 1259 | crate mod foo; 1260 | crate struct Foo(crate crate::Bar); 1261 | crate fn foo() { } 1262 | crate const X: u32 = 0; 1263 | 1264 | ==> 1265 | 1266 | SourceFile( 1267 | ModItem(Vis(crate), mod, BoundIdentifier), 1268 | StructItem(Vis(crate), struct, 1269 | TypeIdentifier, 1270 | OrderedFieldDeclarationList(Vis(crate), ScopedTypeIdentifier(crate, TypeIdentifier))), 1271 | FunctionItem(Vis(crate), fn, BoundIdentifier, ParamList, Block), 1272 | ConstItem(Vis(crate), const, 1273 | BoundIdentifier, TypeIdentifier, Integer)) 1274 | 1275 | # Greek letters in identifiers 1276 | 1277 | const σ1 : Σ = 0; 1278 | const ψ_2 : Ψ = 1; 1279 | 1280 | ==> 1281 | 1282 | SourceFile( 1283 | ConstItem(const,BoundIdentifier, TypeIdentifier, Integer), 1284 | ConstItem(const,BoundIdentifier, TypeIdentifier, Integer)) 1285 | 1286 | # Allows keywords in attributes 1287 | 1288 | #[foo(mut)] 1289 | const a: i32 = 5; 1290 | 1291 | ==> 1292 | 1293 | SourceFile(AttributeItem( 1294 | Attribute(MetaItem(Identifier,ParenthesizedTokens(Identifier))), 1295 | ConstItem(const,BoundIdentifier,TypeIdentifier,Integer))) 1296 | -------------------------------------------------------------------------------- /test/expressions.txt: -------------------------------------------------------------------------------- 1 | # Identifiers 2 | 3 | fn main() { 4 | abc; 5 | } 6 | 7 | ==> 8 | 9 | SourceFile( 10 | FunctionItem(fn,BoundIdentifier, ParamList, Block( 11 | ExpressionStatement(Identifier)))) 12 | 13 | 14 | # Raw identifiers 15 | 16 | fn main() { 17 | (r#abc as r#Def).r#ghi; 18 | } 19 | 20 | ==> 21 | 22 | SourceFile( 23 | FunctionItem(fn, 24 | BoundIdentifier, 25 | ParamList, 26 | Block( 27 | ExpressionStatement(FieldExpression( 28 | ParenthesizedExpression( 29 | TypeCastExpression(Identifier, as, TypeIdentifier)), 30 | FieldIdentifier))))) 31 | 32 | 33 | # Unary operator expressions 34 | 35 | -num; 36 | !bits; 37 | *boxed_thing; 38 | 39 | ==> 40 | 41 | SourceFile( 42 | ExpressionStatement(UnaryExpression(ArithOp, Identifier)), 43 | ExpressionStatement(UnaryExpression(LogicOp, Identifier)), 44 | ExpressionStatement(UnaryExpression(DerefOp, Identifier))) 45 | 46 | 47 | # Reference expressions 48 | 49 | &a; 50 | &mut self.name; 51 | 52 | ==> 53 | 54 | SourceFile( 55 | ExpressionStatement(ReferenceExpression(Identifier)), 56 | ExpressionStatement(ReferenceExpression(mut, FieldExpression(self, FieldIdentifier)))) 57 | 58 | # Try expressions 59 | 60 | a.unwrap()?; 61 | 62 | ==> 63 | 64 | SourceFile( 65 | ExpressionStatement(TryExpression(CallExpression(FieldExpression(Identifier, FieldIdentifier), ArgList)))) 66 | 67 | # Binary operator expressions 68 | 69 | a * b; 70 | a / b; 71 | a % b; 72 | a + b; 73 | a - b; 74 | a >> b; 75 | a << b; 76 | a == b; 77 | a && b; 78 | a || b; 79 | 80 | ==> 81 | 82 | SourceFile( 83 | ExpressionStatement(BinaryExpression(Identifier, ArithOp, Identifier)), 84 | ExpressionStatement(BinaryExpression(Identifier, ArithOp, Identifier)), 85 | ExpressionStatement(BinaryExpression(Identifier, ArithOp, Identifier)), 86 | ExpressionStatement(BinaryExpression(Identifier, ArithOp, Identifier)), 87 | ExpressionStatement(BinaryExpression(Identifier, ArithOp, Identifier)), 88 | ExpressionStatement(BinaryExpression(Identifier, BitOp, Identifier)), 89 | ExpressionStatement(BinaryExpression(Identifier, BitOp, Identifier)), 90 | ExpressionStatement(BinaryExpression(Identifier, CompareOp, Identifier)), 91 | ExpressionStatement(BinaryExpression(Identifier, LogicOp, Identifier)), 92 | ExpressionStatement(BinaryExpression(Identifier, LogicOp, Identifier))) 93 | 94 | # Grouped expressions 95 | 96 | (0); 97 | (2 * (3 + 4)); 98 | 99 | ==> 100 | 101 | SourceFile( 102 | ExpressionStatement(ParenthesizedExpression(Integer)), 103 | ExpressionStatement(ParenthesizedExpression(BinaryExpression( 104 | Integer, 105 | ArithOp, 106 | ParenthesizedExpression(BinaryExpression(Integer, ArithOp, Integer)))))) 107 | 108 | 109 | # Range expressions 110 | 111 | 1..2; 112 | 3..; 113 | ..4; 114 | ..; 115 | 1..b; 116 | a..b; 117 | 118 | ==> 119 | 120 | SourceFile( 121 | ExpressionStatement(RangeExpression(Integer, Integer)), 122 | ExpressionStatement(RangeExpression(Integer)), 123 | ExpressionStatement(RangeExpression(Integer)), 124 | ExpressionStatement(RangeExpression), 125 | ExpressionStatement(RangeExpression(Integer, Identifier)), 126 | ExpressionStatement(RangeExpression(Identifier, Identifier))) 127 | 128 | 129 | # Assignment expressions 130 | 131 | x = y; 132 | 133 | ==> 134 | 135 | SourceFile( 136 | ExpressionStatement(AssignmentExpression( 137 | Identifier, 138 | Identifier))) 139 | 140 | 141 | # Compound assignment expressions 142 | 143 | x += 1; 144 | x += y; 145 | 146 | ==> 147 | 148 | SourceFile( 149 | ExpressionStatement(AssignmentExpression(Identifier, UpdateOp, Integer)), 150 | ExpressionStatement(AssignmentExpression(Identifier, UpdateOp, Identifier))) 151 | 152 | 153 | # Type cast expressions 154 | 155 | 1000 as u8; 156 | let character = integer as char; 157 | let size: f64 = len(values) as f64; 158 | 159 | ==> 160 | 161 | SourceFile( 162 | ExpressionStatement(TypeCastExpression( 163 | Integer, 164 | as, 165 | TypeIdentifier)), 166 | LetDeclaration(let, 167 | BoundIdentifier, 168 | TypeCastExpression( 169 | Identifier, 170 | as, 171 | TypeIdentifier)), 172 | LetDeclaration(let, 173 | BoundIdentifier, 174 | TypeIdentifier, 175 | TypeCastExpression( 176 | CallExpression( 177 | Identifier, 178 | ArgList(Identifier)), 179 | as, 180 | TypeIdentifier))) 181 | 182 | 183 | # Call expressions 184 | 185 | foo(); 186 | add(1i32, 2i32); 187 | add( 188 | 1i32, 189 | 2i32, 190 | ); 191 | 192 | ==> 193 | 194 | SourceFile( 195 | ExpressionStatement(CallExpression( 196 | Identifier, 197 | ArgList)), 198 | ExpressionStatement(CallExpression( 199 | Identifier, 200 | ArgList(Integer, Integer))), 201 | ExpressionStatement(CallExpression( 202 | Identifier, 203 | ArgList(Integer, Integer)))) 204 | 205 | 206 | # Array expressions 207 | 208 | []; 209 | [1, 2, 3]; 210 | ["a", "b", "c"]; 211 | [0; 128]; 212 | 213 | ==> 214 | 215 | SourceFile( 216 | ExpressionStatement(ArrayExpression), 217 | ExpressionStatement(ArrayExpression( 218 | Integer, 219 | Integer, 220 | Integer)), 221 | ExpressionStatement(ArrayExpression( 222 | String, 223 | String, 224 | String)), 225 | ExpressionStatement(ArrayExpression( 226 | Integer, 227 | Integer))) 228 | 229 | 230 | # Tuple expressions 231 | 232 | (); 233 | (0,); 234 | let (x, y, z) = (1, 2, 3); 235 | 236 | ==> 237 | 238 | SourceFile( 239 | ExpressionStatement(UnitExpression), 240 | ExpressionStatement(TupleExpression(Integer)), 241 | LetDeclaration(let, 242 | TuplePattern(BoundIdentifier, BoundIdentifier, BoundIdentifier), 243 | TupleExpression(Integer, Integer, Integer))) 244 | 245 | 246 | # Struct expressions 247 | 248 | NothingInMe {}; 249 | Point {x: 10.0, y: 20.0}; 250 | let a = SomeStruct { field1, field2: expression, field3, }; 251 | let u = game::User {name: "Joe", age: 35, score: 100_000}; 252 | 253 | ==> 254 | 255 | SourceFile( 256 | ExpressionStatement(StructExpression(TypeIdentifier, 257 | FieldInitializerList)), 258 | ExpressionStatement(StructExpression(TypeIdentifier, 259 | FieldInitializerList( 260 | FieldInitializer(FieldIdentifier, Float), 261 | FieldInitializer(FieldIdentifier, Float)))), 262 | LetDeclaration(let, 263 | BoundIdentifier, 264 | StructExpression( 265 | TypeIdentifier, 266 | FieldInitializerList( 267 | ShorthandFieldInitializer( 268 | Identifier), 269 | FieldInitializer(FieldIdentifier, Identifier), 270 | ShorthandFieldInitializer( 271 | Identifier)))), 272 | LetDeclaration(let, 273 | BoundIdentifier, 274 | StructExpression( 275 | ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier), 276 | FieldInitializerList( 277 | FieldInitializer(FieldIdentifier, String), 278 | FieldInitializer(FieldIdentifier, Integer), 279 | FieldInitializer(FieldIdentifier, Integer))))) 280 | 281 | 282 | # Struct expressions with update initializers 283 | 284 | let u = User{name, ..current_user()}; 285 | 286 | ==> 287 | 288 | SourceFile( 289 | LetDeclaration(let, 290 | BoundIdentifier, 291 | StructExpression( 292 | TypeIdentifier, 293 | FieldInitializerList( 294 | ShorthandFieldInitializer( 295 | Identifier), 296 | BaseFieldInitializer(CallExpression(Identifier, ArgList)))))) 297 | 298 | 299 | # If expressions 300 | 301 | fn main() { 302 | if n == 1 { 303 | } else if n == 2 { 304 | } else { 305 | } 306 | } 307 | 308 | let y = if x == 5 { 10 } else { 15 }; 309 | 310 | ==> 311 | 312 | SourceFile( 313 | FunctionItem(fn, 314 | BoundIdentifier, 315 | ParamList, 316 | Block( 317 | ExpressionStatement(IfExpression(if, 318 | BinaryExpression( 319 | Identifier, 320 | CompareOp, 321 | Integer), 322 | Block, 323 | else, 324 | IfExpression(if, 325 | BinaryExpression( 326 | Identifier, 327 | CompareOp, 328 | Integer), 329 | Block, 330 | else, 331 | Block))))), 332 | LetDeclaration(let, 333 | BoundIdentifier, 334 | IfExpression(if, 335 | BinaryExpression( 336 | Identifier, 337 | CompareOp, 338 | Integer), 339 | Block(ExpressionStatement(Integer)), 340 | else, 341 | Block(ExpressionStatement(Integer))))) 342 | 343 | 344 | # If let expressions 345 | 346 | if let ("Bacon", b) = dish { 347 | } 348 | 349 | ==> 350 | 351 | SourceFile( 352 | ExpressionStatement(IfExpression(if, LetDeclaration(let, TuplePattern(LiteralPattern(String), BoundIdentifier), Identifier), 353 | Block))) 354 | 355 | 356 | # While let expressions 357 | 358 | while let ("Bacon", b) = dish { 359 | } 360 | 361 | ==> 362 | 363 | SourceFile( 364 | ExpressionStatement(WhileExpression(while, 365 | LetDeclaration(let, TuplePattern(LiteralPattern(String), BoundIdentifier), Identifier), 366 | Block))) 367 | 368 | 369 | # Match expressions 370 | 371 | match x { 372 | 1 => { "one" } 373 | 2 => "two", 374 | -1 => 1, 375 | -3.14 => 3, 376 | 377 | #[attr1] 378 | 3 => "three", 379 | macro!(4) => "four", 380 | _ => "something else", 381 | } 382 | 383 | let msg = match x { 384 | 0 | 1 | 10 => "one of zero, one, or ten", 385 | y if y < 20 => "less than 20, but not zero, one, or ten", 386 | y if y == 200 => 387 | if a { 388 | "200 (but this is not very stylish)" 389 | } 390 | _ => "something else", 391 | }; 392 | 393 | ==> 394 | 395 | SourceFile( 396 | ExpressionStatement(MatchExpression(match, 397 | Identifier, 398 | MatchBlock( 399 | MatchArm( 400 | LiteralPattern(Integer), 401 | Block( 402 | ExpressionStatement(String))), 403 | MatchArm( 404 | LiteralPattern(Integer), 405 | String), 406 | MatchArm( 407 | LiteralPattern(ArithOp, Integer), 408 | Integer), 409 | MatchArm( 410 | LiteralPattern(ArithOp, Float), 411 | Integer), 412 | MatchArm( 413 | Attribute( 414 | MetaItem( 415 | Identifier)), 416 | LiteralPattern(Integer), 417 | String), 418 | MatchArm( 419 | MacroPattern( 420 | Identifier, 421 | ParenthesizedTokens( 422 | Integer)), 423 | String), 424 | MatchArm(_, String)))), 425 | LetDeclaration(let, 426 | BoundIdentifier, 427 | MatchExpression(match, 428 | Identifier, 429 | MatchBlock( 430 | MatchArm( 431 | OrPattern(OrPattern(LiteralPattern(Integer), LiteralPattern(Integer)), LiteralPattern(Integer)), 432 | String), 433 | MatchArm( 434 | BoundIdentifier, 435 | Guard(if, 436 | BinaryExpression( 437 | Identifier, 438 | CompareOp, 439 | Integer)), 440 | String), 441 | MatchArm( 442 | BoundIdentifier, 443 | Guard(if, 444 | BinaryExpression( 445 | Identifier, 446 | CompareOp, 447 | Integer)), 448 | IfExpression(if, 449 | Identifier, 450 | Block( 451 | ExpressionStatement(String)))), 452 | MatchArm( 453 | _, 454 | String))))) 455 | 456 | 457 | # While expressions 458 | 459 | while !done { 460 | done = true; 461 | } 462 | 463 | ==> 464 | 465 | SourceFile( 466 | ExpressionStatement(WhileExpression(while, 467 | UnaryExpression(LogicOp, Identifier), 468 | Block( 469 | ExpressionStatement(AssignmentExpression( 470 | Identifier, 471 | Boolean)))))) 472 | 473 | # Loop expressions 474 | 475 | 'outer: loop { 476 | 'inner: loop { 477 | break 'outer; 478 | break true; 479 | } 480 | } 481 | 482 | ==> 483 | 484 | SourceFile( 485 | ExpressionStatement(LoopExpression(LoopLabel, loop, Block( 486 | ExpressionStatement(LoopExpression(LoopLabel, loop, Block( 487 | ExpressionStatement(BreakExpression(break,LoopLabel)), 488 | ExpressionStatement(BreakExpression(break,Boolean))))))))) 489 | 490 | # For expressions 491 | 492 | for e in v { 493 | bar(e); 494 | } 495 | 496 | for i in 0..256 { 497 | bar(i); 498 | } 499 | 500 | 'outer: for x in 0..10 { 501 | 'inner: for y in 0..10 { 502 | if x % 2 == 0 { continue 'outer; } 503 | if y % 2 == 0 { continue 'inner; } 504 | } 505 | } 506 | 507 | ==> 508 | 509 | SourceFile( 510 | ExpressionStatement(ForExpression(for,BoundIdentifier, in, Identifier, Block( 511 | ExpressionStatement(CallExpression(Identifier, ArgList(Identifier)))))), 512 | ExpressionStatement(ForExpression(for,BoundIdentifier, in, RangeExpression(Integer, Integer), Block( 513 | ExpressionStatement(CallExpression(Identifier, ArgList(Identifier)))))), 514 | ExpressionStatement(ForExpression(LoopLabel, for, BoundIdentifier, in, RangeExpression(Integer, Integer), Block( 515 | ExpressionStatement(ForExpression(LoopLabel, for, BoundIdentifier, in, RangeExpression(Integer, Integer), Block( 516 | ExpressionStatement(IfExpression(if,BinaryExpression(BinaryExpression(Identifier, ArithOp, Integer), CompareOp, Integer), 517 | Block(ExpressionStatement(ContinueExpression(continue,LoopLabel))))), 518 | ExpressionStatement(IfExpression(if,BinaryExpression(BinaryExpression(Identifier, ArithOp, Integer), CompareOp, Integer), 519 | Block(ExpressionStatement(ContinueExpression(continue,LoopLabel)))))))))))) 520 | 521 | 522 | # Field expressions 523 | 524 | mystruct.myfield; 525 | foo().x; 526 | value.0.1.iter(); 527 | 1.max(2); 528 | 529 | ==> 530 | 531 | SourceFile( 532 | ExpressionStatement(FieldExpression(Identifier, FieldIdentifier)), 533 | ExpressionStatement(FieldExpression(CallExpression(Identifier, ArgList), FieldIdentifier)), 534 | ExpressionStatement(CallExpression( 535 | FieldExpression( 536 | FieldExpression(FieldExpression(Identifier, Integer), Integer), 537 | FieldIdentifier), 538 | ArgList)), 539 | ExpressionStatement(CallExpression( 540 | FieldExpression(Integer, FieldIdentifier), ArgList(Integer)))) 541 | 542 | 543 | # Method call expressions 544 | 545 | mystruct.foo(); 546 | 547 | ==> 548 | 549 | SourceFile(ExpressionStatement(CallExpression(FieldExpression(Identifier, FieldIdentifier), ArgList))) 550 | 551 | 552 | # Index expressions 553 | 554 | ([1, 2, 3, 4])[0]; 555 | arr[10]; 556 | arr[n]; 557 | 558 | ==> 559 | 560 | SourceFile( 561 | ExpressionStatement(IndexExpression( 562 | ParenthesizedExpression( 563 | ArrayExpression(Integer, Integer, Integer, Integer)), 564 | Integer)), 565 | ExpressionStatement(IndexExpression(Identifier, Integer)), 566 | ExpressionStatement(IndexExpression(Identifier, Identifier))) 567 | 568 | 569 | # Scoped functions 570 | 571 | a::b(); 572 | C::::e(); 573 | ::f(); 574 | ::g::h(); 575 | 576 | ==> 577 | 578 | SourceFile( 579 | ExpressionStatement(CallExpression( 580 | ScopedIdentifier(ScopeIdentifier, Identifier), 581 | ArgList)), 582 | ExpressionStatement(CallExpression( 583 | ScopedIdentifier( 584 | ScopeIdentifier, TypeArgList(TypeIdentifier), 585 | Identifier), 586 | ArgList)), 587 | ExpressionStatement(CallExpression(ScopedIdentifier(Identifier), ArgList)), 588 | ExpressionStatement(CallExpression(ScopedIdentifier(ScopeIdentifier, Identifier), ArgList))) 589 | 590 | 591 | # Scoped functions with fully qualified syntax 592 | 593 | ::eat(d); 594 | 595 | ==> 596 | 597 | SourceFile( 598 | ExpressionStatement(CallExpression( 599 | ScopedIdentifier( 600 | QualifiedScope(TypeIdentifier, as, TypeIdentifier), 601 | Identifier), 602 | ArgList(Identifier)))) 603 | 604 | 605 | # Scoped functions with macros as types 606 | 607 | ::foo(); 608 | 609 | ==> 610 | 611 | SourceFile( 612 | ExpressionStatement(CallExpression( 613 | ScopedIdentifier( 614 | QualifiedScope(MacroInvocation(TypeIdentifier, BracketedTokens)), 615 | Identifier), 616 | ArgList))) 617 | 618 | 619 | # Generic functions 620 | 621 | std::sizeof::(); 622 | foo::<8>(); 623 | 624 | ==> 625 | 626 | SourceFile( 627 | ExpressionStatement(CallExpression( 628 | GenericFunction( 629 | ScopedIdentifier( 630 | ScopeIdentifier, 631 | Identifier), 632 | TypeArgList( 633 | TypeIdentifier)), 634 | ArgList)), 635 | ExpressionStatement(CallExpression( 636 | GenericFunction( 637 | Identifier, 638 | TypeArgList( 639 | Integer)), 640 | ArgList))) 641 | 642 | 643 | # Closures 644 | 645 | a.map(|(b, c)| b.push(c)); 646 | d.map(move |mut e| { 647 | f(e); 648 | g(e) 649 | }); 650 | h(|| -> i { j }); 651 | 652 | ==> 653 | 654 | SourceFile( 655 | ExpressionStatement(CallExpression( 656 | FieldExpression(Identifier, FieldIdentifier), 657 | ArgList( 658 | ClosureExpression( 659 | ParamList(Parameter(TuplePattern(BoundIdentifier, BoundIdentifier))), 660 | CallExpression( 661 | FieldExpression(Identifier, FieldIdentifier), 662 | ArgList(Identifier)))))), 663 | ExpressionStatement(CallExpression( 664 | FieldExpression(Identifier, FieldIdentifier), 665 | ArgList( 666 | ClosureExpression(move, 667 | ParamList(Parameter(mut, BoundIdentifier)), 668 | Block( 669 | ExpressionStatement(CallExpression(Identifier, ArgList(Identifier))), 670 | ExpressionStatement(CallExpression(Identifier, ArgList(Identifier)))))))), 671 | ExpressionStatement(CallExpression( 672 | Identifier, 673 | ArgList( 674 | ClosureExpression( 675 | ParamList, 676 | TypeIdentifier, 677 | Block(ExpressionStatement(Identifier))))))) 678 | 679 | 680 | # Closures with typed parameteres 681 | 682 | a.map(|b: usize| b.push(c)); 683 | 684 | ==> 685 | 686 | SourceFile( 687 | ExpressionStatement(CallExpression( 688 | FieldExpression(Identifier, FieldIdentifier), 689 | ArgList(ClosureExpression( 690 | ParamList(Parameter(BoundIdentifier, TypeIdentifier)), 691 | CallExpression(FieldExpression(Identifier, FieldIdentifier), ArgList(Identifier))))))) 692 | 693 | 694 | # Unsafe blocks 695 | 696 | const a : A = unsafe { foo() }; 697 | 698 | ==> 699 | 700 | SourceFile( 701 | ConstItem(const, 702 | BoundIdentifier, 703 | TypeIdentifier, 704 | UnsafeBlock(unsafe, Block(ExpressionStatement(CallExpression(Identifier, ArgList)))))) 705 | -------------------------------------------------------------------------------- /test/literals.txt: -------------------------------------------------------------------------------- 1 | # Integer literals 2 | 3 | 0; 4 | 0___0; 5 | 123; 6 | 0usize; 7 | 123i32; 8 | 123u32; 9 | 123_u32; 10 | 0xff_u8; 11 | 0o70_i16; 12 | 0b1111_1111_1001_0000_i32; 13 | 1u128; 14 | 15 | ==> 16 | 17 | SourceFile( 18 | ExpressionStatement(Integer), 19 | ExpressionStatement(Integer), 20 | ExpressionStatement(Integer), 21 | ExpressionStatement(Integer), 22 | ExpressionStatement(Integer), 23 | ExpressionStatement(Integer), 24 | ExpressionStatement(Integer), 25 | ExpressionStatement(Integer), 26 | ExpressionStatement(Integer), 27 | ExpressionStatement(Integer), 28 | ExpressionStatement(Integer)) 29 | 30 | 31 | # Floating-point literals 32 | 33 | 123.123; 34 | 2.; 35 | 123.0f64; 36 | 0.1f64; 37 | 0.1f32; 38 | 12E+99_f64; 39 | 40 | ==> 41 | 42 | SourceFile( 43 | ExpressionStatement(Float), 44 | ExpressionStatement(Float), 45 | ExpressionStatement(Float), 46 | ExpressionStatement(Float), 47 | ExpressionStatement(Float), 48 | ExpressionStatement(Float)) 49 | 50 | 51 | # String literals 52 | 53 | ""; 54 | "abc"; 55 | b"foo\nbar"; 56 | "foo\ 57 | bar"; 58 | "\"foo\""; 59 | "/* foo bar */ foo bar"; 60 | "foo\x42\x43bar"; 61 | "foo \x42 \x43 bar"; 62 | 63 | ==> 64 | 65 | SourceFile( 66 | ExpressionStatement(String), 67 | ExpressionStatement(String), 68 | ExpressionStatement(String(Escape)), 69 | ExpressionStatement(String(Escape)), 70 | ExpressionStatement(String(Escape, Escape)), 71 | ExpressionStatement(String), 72 | ExpressionStatement(String(Escape, Escape)), 73 | ExpressionStatement(String(Escape, Escape))) 74 | 75 | 76 | # Raw string literals 77 | 78 | r#"abc"#; r##"ok"##; 79 | r##"foo #"# bar"##; 80 | r###"foo ##"## bar"###; 81 | r######"foo ##### bar"######; 82 | 83 | ==> 84 | 85 | SourceFile( 86 | ExpressionStatement(RawString), 87 | ExpressionStatement(RawString), 88 | ExpressionStatement(RawString), 89 | ExpressionStatement(RawString), 90 | ExpressionStatement(RawString)) 91 | 92 | 93 | # Raw byte string literals 94 | 95 | br#"abc"#; 96 | br##"abc"##; 97 | 98 | ==> 99 | 100 | SourceFile( 101 | ExpressionStatement(RawString), 102 | ExpressionStatement(RawString)) 103 | 104 | 105 | # Character literals 106 | 107 | 'a'; 108 | '\''; 109 | '\0'; 110 | b'x'; 111 | '\t'; 112 | '\xff'; 113 | '\\'; 114 | 115 | ==> 116 | 117 | SourceFile( 118 | ExpressionStatement(Char), 119 | ExpressionStatement(Char), 120 | ExpressionStatement(Char), 121 | ExpressionStatement(Char), 122 | ExpressionStatement(Char), 123 | ExpressionStatement(Char), 124 | ExpressionStatement(Char)) 125 | 126 | 127 | # Boolean literals 128 | 129 | true; 130 | false; 131 | 132 | ==> 133 | 134 | SourceFile(ExpressionStatement(Boolean), ExpressionStatement(Boolean)) 135 | 136 | -------------------------------------------------------------------------------- /test/macros.txt: -------------------------------------------------------------------------------- 1 | # Macro invocation - no arguments 2 | 3 | a!(); 4 | b![]; 5 | c!{} 6 | d::e!(); 7 | f::g::h!{} 8 | 9 | ==> 10 | 11 | SourceFile( 12 | MacroInvocation(Identifier, ParenthesizedTokens), 13 | MacroInvocation(Identifier, BracketedTokens), 14 | MacroInvocation(Identifier, BracedTokens), 15 | MacroInvocation(ScopedIdentifier(ScopeIdentifier, Identifier), ParenthesizedTokens), 16 | MacroInvocation(ScopedIdentifier(ScopeIdentifier, ScopeIdentifier, Identifier), BracedTokens)) 17 | 18 | 19 | # Macro invocation - arbitrary tokens 20 | 21 | a!(* a *); 22 | a!(& a &); 23 | a!(- a -); 24 | a!(b + c + +); 25 | a!('a'..='z'); 26 | a!('\u{0}'..='\u{2}'); 27 | a!('lifetime); 28 | 29 | ==> 30 | 31 | SourceFile( 32 | MacroInvocation( 33 | Identifier, 34 | ParenthesizedTokens(ArithOp, Identifier, ArithOp)), 35 | MacroInvocation( 36 | Identifier, 37 | ParenthesizedTokens(BitOp, Identifier, BitOp)), 38 | MacroInvocation( 39 | Identifier, 40 | ParenthesizedTokens(ArithOp, Identifier, ArithOp)), 41 | MacroInvocation( 42 | Identifier, 43 | ParenthesizedTokens(Identifier, ArithOp, Identifier, ArithOp, ArithOp)), 44 | MacroInvocation( 45 | Identifier, 46 | ParenthesizedTokens(Char, Char)), 47 | MacroInvocation( 48 | Identifier, 49 | ParenthesizedTokens(Char, Char)), 50 | MacroInvocation( 51 | Identifier, 52 | ParenthesizedTokens(Lifetime))) 53 | 54 | 55 | # Macro definition 56 | 57 | macro_rules! say_hello { 58 | () => ( 59 | println!("Hello!"); 60 | ) 61 | } 62 | 63 | macro_rules! four { 64 | () => {1 + 3}; 65 | } 66 | 67 | macro_rules! foo { 68 | (x => $e:expr) => (println!("mode X: {}", $e)); 69 | (y => $e:expr) => (println!("mode Y: {}", $e)) 70 | } 71 | 72 | macro_rules! o_O { 73 | ( 74 | $($x:expr; [ $( $y:expr ),* ]);* 75 | ) => { 76 | $($($x + $e),*),* 77 | } 78 | } 79 | 80 | macro_rules! zero_or_one { 81 | ($($e:expr),?) => { 82 | $($e),? 83 | }; 84 | } 85 | 86 | ==> 87 | 88 | SourceFile( 89 | MacroDefinition(macro_rules, 90 | Identifier, 91 | MacroRule( 92 | ParenthesizedTokens, 93 | ParenthesizedTokens( 94 | Identifier, 95 | ParenthesizedTokens(String)))), 96 | MacroDefinition(macro_rules, 97 | Identifier, 98 | MacroRule( 99 | ParenthesizedTokens, 100 | BracedTokens(Integer, ArithOp, Integer))), 101 | MacroDefinition(macro_rules, 102 | Identifier, 103 | MacroRule( 104 | ParenthesizedTokens( 105 | Identifier, 106 | TokenBinding( 107 | Metavariable, 108 | Identifier)), 109 | ParenthesizedTokens( 110 | Identifier, 111 | ParenthesizedTokens( 112 | String, 113 | Metavariable))), 114 | MacroRule( 115 | ParenthesizedTokens( 116 | Identifier, 117 | TokenBinding( 118 | Metavariable, 119 | Identifier)), 120 | ParenthesizedTokens( 121 | Identifier, 122 | ParenthesizedTokens( 123 | String, 124 | Metavariable)))), 125 | MacroDefinition(macro_rules, 126 | Identifier, 127 | MacroRule( 128 | ParenthesizedTokens( 129 | TokenRepetition( 130 | TokenBinding( 131 | Metavariable, 132 | Identifier), 133 | BracketedTokens( 134 | TokenRepetition( 135 | TokenBinding( 136 | Metavariable, 137 | Identifier))))), 138 | BracedTokens( 139 | TokenRepetition( 140 | TokenRepetition(Metavariable, ArithOp, Metavariable))))), 141 | MacroDefinition(macro_rules, 142 | Identifier, 143 | MacroRule( 144 | ParenthesizedTokens( 145 | TokenRepetition( 146 | TokenBinding(Metavariable, Identifier))), 147 | BracedTokens( 148 | TokenRepetition(Metavariable))))) 149 | -------------------------------------------------------------------------------- /test/patterns.txt: -------------------------------------------------------------------------------- 1 | # Tuple struct patterns 2 | 3 | match x { 4 | Some(x) => "some", 5 | std::None() => "none" 6 | } 7 | 8 | ==> 9 | 10 | SourceFile( 11 | ExpressionStatement(MatchExpression(match,Identifier, MatchBlock( 12 | MatchArm( 13 | TuplePattern(TypeIdentifier, BoundIdentifier), 14 | String), 15 | MatchArm( 16 | TuplePattern(ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier)), 17 | String))))) 18 | 19 | 20 | # Reference patterns 21 | 22 | match x { 23 | A(ref x) => x.0, 24 | ref mut y => y, 25 | & mut z => z, 26 | } 27 | 28 | ==> 29 | 30 | SourceFile( 31 | ExpressionStatement(MatchExpression(match,Identifier, MatchBlock( 32 | MatchArm( 33 | TuplePattern(TypeIdentifier, RefPattern(ref, BoundIdentifier)), 34 | FieldExpression(Identifier, Integer)), 35 | MatchArm( 36 | RefPattern(ref, MutPattern(mut, BoundIdentifier)), 37 | Identifier), 38 | MatchArm( 39 | ReferencePattern(mut, BoundIdentifier), 40 | Identifier))))) 41 | 42 | # Struct patterns 43 | 44 | match x { 45 | Person{name, age} if age < 5 => ("toddler", name), 46 | Person{name: adult_name, age: _} => ("adult", adult_name), 47 | } 48 | 49 | ==> 50 | 51 | SourceFile( 52 | ExpressionStatement(MatchExpression(match,Identifier, MatchBlock( 53 | MatchArm( 54 | StructPattern( 55 | TypeIdentifier, 56 | FieldPatternList(FieldPattern(BoundIdentifier), FieldPattern(BoundIdentifier))), 57 | Guard(if, BinaryExpression(Identifier, CompareOp, Integer)), 58 | TupleExpression(String, Identifier)), 59 | MatchArm( 60 | StructPattern( 61 | TypeIdentifier, 62 | FieldPatternList( 63 | FieldPattern(FieldIdentifier, BoundIdentifier), 64 | FieldPattern(FieldIdentifier, _))), 65 | TupleExpression(String, Identifier)))))) 66 | 67 | # Ignored patterns 68 | 69 | match x { 70 | (a, ..) => a, 71 | B(..) => c, 72 | D::E{f: g, ..} => g 73 | } 74 | 75 | ==> 76 | 77 | SourceFile( 78 | ExpressionStatement(MatchExpression(match,Identifier, MatchBlock( 79 | MatchArm( 80 | TuplePattern(BoundIdentifier), 81 | Identifier), 82 | MatchArm( 83 | TuplePattern(TypeIdentifier), 84 | Identifier), 85 | MatchArm( 86 | StructPattern( 87 | ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier), 88 | FieldPatternList(FieldPattern(FieldIdentifier, BoundIdentifier))), 89 | Identifier))))) 90 | 91 | # Captured patterns 92 | 93 | match x { 94 | a @ A(_) | b @ B(..) => a, 95 | a @ 1 ... 5 => a, 96 | Some(1 ... 5) => a, 97 | a @ b...c => a, 98 | a @ b..=c => a, 99 | } 100 | 101 | ==> 102 | 103 | SourceFile( 104 | ExpressionStatement(MatchExpression(match, 105 | Identifier, 106 | MatchBlock( 107 | MatchArm( 108 | OrPattern( 109 | CapturedPattern( 110 | BoundIdentifier, 111 | TuplePattern(TypeIdentifier, _)), 112 | CapturedPattern( 113 | BoundIdentifier, 114 | TuplePattern(TypeIdentifier))), 115 | Identifier), 116 | MatchArm( 117 | CapturedPattern( 118 | BoundIdentifier, 119 | RangePattern(Integer, Integer)), 120 | Identifier), 121 | MatchArm( 122 | TuplePattern( 123 | TypeIdentifier, 124 | RangePattern(Integer, Integer)), 125 | Identifier), 126 | MatchArm( 127 | CapturedPattern( 128 | BoundIdentifier, 129 | RangePattern(Identifier, Identifier)), 130 | Identifier), 131 | MatchArm( 132 | CapturedPattern( 133 | BoundIdentifier, 134 | RangePattern(Identifier, Identifier)), 135 | Identifier))))) 136 | 137 | 138 | # Or patterns 139 | 140 | if let A(x) | B(x) = expr { 141 | do_stuff_with(x); 142 | } 143 | 144 | while let A(x) | B(x) = expr { 145 | do_stuff_with(x); 146 | } 147 | 148 | let Ok(index) | Err(index) = slice.binary_search(&x); 149 | 150 | for ref a | b in c {} 151 | 152 | let Ok(x) | Err(x) = binary_search(x); 153 | 154 | for A | B | C in c {} 155 | 156 | |(Ok(x) | Err(x))| expr(); 157 | 158 | let ref mut x @ (A | B | C); 159 | 160 | fn foo((1 | 2 | 3): u8) {} 161 | 162 | ==> 163 | 164 | SourceFile( 165 | ExpressionStatement(IfExpression(if, 166 | LetDeclaration(let, 167 | OrPattern( 168 | TuplePattern(TypeIdentifier, BoundIdentifier), 169 | TuplePattern(TypeIdentifier, BoundIdentifier)), 170 | Identifier), 171 | Block( 172 | ExpressionStatement(CallExpression(Identifier, ArgList(Identifier)))))), 173 | ExpressionStatement(WhileExpression(while, 174 | LetDeclaration(let, 175 | OrPattern( 176 | TuplePattern(TypeIdentifier, BoundIdentifier), 177 | TuplePattern(TypeIdentifier, BoundIdentifier)), 178 | Identifier), 179 | Block( 180 | ExpressionStatement(CallExpression(Identifier,ArgList(Identifier)))))), 181 | LetDeclaration(let, 182 | OrPattern( 183 | TuplePattern(TypeIdentifier, BoundIdentifier), 184 | TuplePattern(TypeIdentifier, BoundIdentifier)), 185 | CallExpression(FieldExpression(Identifier, FieldIdentifier), 186 | ArgList(ReferenceExpression(Identifier)))), 187 | ExpressionStatement(ForExpression(for, 188 | OrPattern(RefPattern(ref, BoundIdentifier), BoundIdentifier), 189 | in, Identifier, 190 | Block)), 191 | LetDeclaration(let, 192 | OrPattern( 193 | TuplePattern(TypeIdentifier, BoundIdentifier), 194 | TuplePattern(TypeIdentifier, BoundIdentifier)), 195 | CallExpression(Identifier, ArgList(Identifier))), 196 | ExpressionStatement(ForExpression(for, 197 | OrPattern(OrPattern(BoundIdentifier, BoundIdentifier), BoundIdentifier), 198 | in, Identifier, 199 | Block)), 200 | ExpressionStatement(ClosureExpression( 201 | ParamList(Parameter(TuplePattern( 202 | OrPattern( 203 | TuplePattern(TypeIdentifier, BoundIdentifier), 204 | TuplePattern(TypeIdentifier, BoundIdentifier))))), 205 | CallExpression(Identifier, ArgList))), 206 | LetDeclaration(let, 207 | RefPattern(ref, 208 | MutPattern( 209 | mut, 210 | CapturedPattern( 211 | BoundIdentifier, 212 | TuplePattern( 213 | OrPattern(OrPattern(BoundIdentifier, BoundIdentifier), BoundIdentifier)))))), 214 | FunctionItem(fn, 215 | BoundIdentifier, 216 | ParamList( 217 | Parameter( 218 | TuplePattern( 219 | OrPattern(OrPattern(LiteralPattern(Integer), LiteralPattern(Integer)), LiteralPattern(Integer))), 220 | TypeIdentifier)), 221 | Block)) 222 | -------------------------------------------------------------------------------- /test/test-rust.js: -------------------------------------------------------------------------------- 1 | import {parser} from "../dist/index.js" 2 | import {fileTests} from "@lezer/generator/dist/test" 3 | 4 | import * as fs from "fs" 5 | import * as path from "path" 6 | import {fileURLToPath} from "url" 7 | let caseDir = path.dirname(fileURLToPath(import.meta.url)) 8 | 9 | for (let file of fs.readdirSync(caseDir)) { 10 | if (!/\.txt$/.test(file)) continue 11 | let name = /^[^\.]*/.exec(file)[0] 12 | describe(name, () => { 13 | for (let {name, run} of fileTests(fs.readFileSync(path.join(caseDir, file), "utf8"), file)) 14 | it(name, () => run(parser)) 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /test/types.txt: -------------------------------------------------------------------------------- 1 | # The unit type 2 | 3 | type A = (); 4 | 5 | ==> 6 | 7 | SourceFile( 8 | TypeItem(type,TypeIdentifier, UnitType)) 9 | 10 | 11 | # Tuple types 12 | 13 | type A = (i32, String); 14 | 15 | ==> 16 | 17 | SourceFile( 18 | TypeItem(type,TypeIdentifier, TupleType(TypeIdentifier, TypeIdentifier))) 19 | 20 | 21 | # Reference types 22 | 23 | type A = &B; 24 | type C = &'a str; 25 | type D = &'a mut str; 26 | 27 | ==> 28 | 29 | SourceFile( 30 | TypeItem(type,TypeIdentifier, ReferenceType(TypeIdentifier)), 31 | TypeItem(type,TypeIdentifier, ReferenceType(Lifetime, TypeIdentifier)), 32 | TypeItem(type,TypeIdentifier, ReferenceType(Lifetime, mut, TypeIdentifier))) 33 | 34 | 35 | # Raw pointer types 36 | 37 | type A = *mut B; 38 | type C = *const str; 39 | 40 | ==> 41 | 42 | SourceFile( 43 | TypeItem(type,TypeIdentifier, PointerType(mut, TypeIdentifier)), 44 | TypeItem(type,TypeIdentifier, PointerType(const, TypeIdentifier))) 45 | 46 | 47 | # Generic types 48 | 49 | type A = B; 50 | type D = E; 51 | type G = H<'a, I>; 52 | type J = H; 53 | 54 | ==> 55 | 56 | SourceFile( 57 | TypeItem(type, 58 | TypeIdentifier, 59 | GenericType(TypeIdentifier, TypeArgList(TypeIdentifier))), 60 | TypeItem(type, 61 | TypeIdentifier, 62 | GenericType(TypeIdentifier, TypeArgList(TypeIdentifier, TypeIdentifier))), 63 | TypeItem(type, 64 | TypeIdentifier, 65 | GenericType(TypeIdentifier, TypeArgList(Lifetime, TypeIdentifier))), 66 | TypeItem(type, 67 | TypeIdentifier, 68 | GenericType(TypeIdentifier, TypeArgList(TypeBinding(TypeIdentifier, TypeIdentifier))))) 69 | 70 | 71 | # Scoped types 72 | 73 | type A = B::C; 74 | type D = E::F::G; 75 | type H = I::J; 76 | type L = M::O; 77 | 78 | ==> 79 | 80 | SourceFile( 81 | TypeItem(type, 82 | TypeIdentifier, 83 | ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier)), 84 | TypeItem(type, 85 | TypeIdentifier, 86 | ScopedTypeIdentifier(ScopeIdentifier, ScopeIdentifier, TypeIdentifier)), 87 | TypeItem(type, 88 | TypeIdentifier, 89 | GenericType( 90 | ScopedTypeIdentifier(ScopeIdentifier, TypeIdentifier), 91 | TypeArgList(TypeIdentifier))), 92 | TypeItem(type, 93 | TypeIdentifier, 94 | ScopedTypeIdentifier( 95 | ScopeIdentifier, 96 | TypeArgList(TypeIdentifier), 97 | TypeIdentifier))) 98 | 99 | 100 | # Array types 101 | 102 | type A = [B; 4]; 103 | type C = &[D]; 104 | 105 | ==> 106 | 107 | SourceFile( 108 | TypeItem(type,TypeIdentifier, ArrayType(TypeIdentifier, Integer)), 109 | TypeItem(type,TypeIdentifier, ReferenceType(ArrayType(TypeIdentifier)))) 110 | 111 | 112 | # Function types 113 | 114 | fn high_order1(value: i32, f: fn(i32)) -> i32 {} 115 | 116 | fn high_order2(value: i32, f: fn(i32) -> i32) -> i32 { 117 | f(value) 118 | } 119 | 120 | fn high_order3(value: i32, f: &FnOnce(i32) -> i32) -> i32 { 121 | f(value) 122 | } 123 | 124 | type F = for<'a, 'b> fn(&'a A, &'a B<'i, 't>,) -> C; 125 | 126 | ==> 127 | 128 | SourceFile( 129 | FunctionItem(fn, 130 | BoundIdentifier, 131 | ParamList( 132 | Parameter(BoundIdentifier, TypeIdentifier), 133 | Parameter(BoundIdentifier, FunctionType(fn, ParamList(Parameter(TypeIdentifier))))), 134 | TypeIdentifier, 135 | Block), 136 | FunctionItem(fn, 137 | BoundIdentifier, 138 | ParamList( 139 | Parameter(BoundIdentifier, TypeIdentifier), 140 | Parameter(BoundIdentifier, FunctionType(fn, ParamList(Parameter(TypeIdentifier)), TypeIdentifier))), 141 | TypeIdentifier, 142 | Block(ExpressionStatement(CallExpression(Identifier, ArgList(Identifier))))), 143 | FunctionItem(fn, 144 | BoundIdentifier, 145 | ParamList( 146 | Parameter(BoundIdentifier, TypeIdentifier), 147 | Parameter(BoundIdentifier, 148 | ReferenceType(FunctionType(TypeIdentifier, ParamList(Parameter(TypeIdentifier)), TypeIdentifier)))), 149 | TypeIdentifier, Block(ExpressionStatement(CallExpression(Identifier, ArgList(Identifier))))), 150 | TypeItem(type, 151 | TypeIdentifier, 152 | FunctionType( 153 | ForLifetimes(for, Lifetime, Lifetime), 154 | fn, 155 | ParamList( 156 | Parameter(ReferenceType(Lifetime, TypeIdentifier)), 157 | Parameter(ReferenceType(Lifetime, GenericType(TypeIdentifier, TypeArgList(Lifetime, Lifetime))))), 158 | TypeIdentifier))) 159 | 160 | 161 | # Unsafe and extern function types 162 | 163 | type a = extern "C" fn(*mut c_void); 164 | type b = unsafe extern "C" fn() -> *mut c_void; 165 | 166 | ==> 167 | 168 | SourceFile( 169 | TypeItem(type, 170 | TypeIdentifier, 171 | FunctionType( 172 | extern, String, fn, 173 | ParamList(Parameter(PointerType(mut, TypeIdentifier))))), 174 | TypeItem(type, 175 | TypeIdentifier, 176 | FunctionType( 177 | unsafe, extern, String, fn, 178 | ParamList, 179 | PointerType(mut, TypeIdentifier)))) 180 | 181 | 182 | # Trait objects 183 | 184 | type a = Box; 185 | type b = Rc; 186 | type c = A<&dyn Fn(&B) -> C>; 187 | 188 | ==> 189 | 190 | SourceFile( 191 | TypeItem(type, 192 | TypeIdentifier, 193 | GenericType( 194 | TypeIdentifier, 195 | TypeArgList(BoundedType(TypeIdentifier, Lifetime)))), 196 | TypeItem(type, 197 | TypeIdentifier, 198 | GenericType( 199 | TypeIdentifier, 200 | TypeArgList(DynamicType(dyn, TypeIdentifier)))), 201 | TypeItem(type, 202 | TypeIdentifier, 203 | GenericType( 204 | TypeIdentifier, 205 | TypeArgList( 206 | ReferenceType( 207 | DynamicType(dyn, FunctionType(TypeIdentifier, ParamList(Parameter(ReferenceType(TypeIdentifier))), TypeIdentifier))))))) 208 | 209 | 210 | # Type cast expressions with generics 211 | 212 | a as B; 213 | d as *mut E<::G>; 214 | 215 | ==> 216 | 217 | SourceFile( 218 | ExpressionStatement(TypeCastExpression( 219 | Identifier, 220 | as, 221 | GenericType(TypeIdentifier, TypeArgList(TypeIdentifier)))), 222 | ExpressionStatement(TypeCastExpression( 223 | Identifier, 224 | as, 225 | PointerType( 226 | mut, 227 | GenericType( 228 | TypeIdentifier, 229 | TypeArgList( 230 | ScopedTypeIdentifier( 231 | QualifiedScope(TypeIdentifier,as,TypeIdentifier), TypeIdentifier))))))) 232 | --------------------------------------------------------------------------------