Skip to content

Commit

Permalink
MACRO: Advanced macro expansion
Browse files Browse the repository at this point in the history
  • Loading branch information
vlad20012 committed Apr 5, 2018
1 parent c830220 commit 15ed9c7
Show file tree
Hide file tree
Showing 23 changed files with 4,628 additions and 2,439 deletions.
32 changes: 21 additions & 11 deletions src/main/grammars/RustParser.bnf
Expand Up @@ -1117,35 +1117,39 @@ MacroDefinition ::= AttrsAndVis "macro_rules" '!' identifier MacroDefinitionBody

MacroDefinitionBody ::= <<any_braces (MacroDefinitionCase ';'?)*>>

MacroDefinitionCase ::= MacroPattern '=>' MacroExpansion
MacroDefinitionCase ::= MacroPattern '=>' MacroExpansion { pin = 1 }

MacroPattern ::= <<any_braces MacroPatternContents >>
private MacroPatternContents ::=
MacroPatternContents ::=
(MacroPattern | MacroBinding | MacroBindingGroup | <<unpairedToken>>)*

MacroBinding ::= '$' <<macroIdentifier>> ':' identifier {
MacroBinding ::= '$' MetaVarIdentifier ':' identifier {
pin = 2
implements = [ "org.rust.lang.core.psi.ext.RsNameIdentifierOwner" ]
mixin = "org.rust.lang.core.psi.ext.RsMacroBindingImplMixin"
}
MacroBindingGroup ::= '$' '(' MacroPatternContents ')'

MetaVarIdentifier ::= <<macroIdentifier>>
MacroBindingGroup ::= '$' '(' MacroPatternContents ')' MacroBindingGroupSeparator? ('*' | '+' | '?') { pin = 2 }
MacroBindingGroupSeparator ::= <<macroBindingGroupSeparatorToken>>

MacroExpansion ::= <<any_braces MacroExpansionContents>>

private MacroExpansionContents ::=
MacroExpansionContents ::=
(MacroExpansion | MacroReference | MacroExpansionReferenceGroup | <<unpairedToken>>)*

MacroReference ::= '$' <<macroIdentifier>> {
MacroReference ::= '$' MetaVarIdentifier {
implements = [ "org.rust.lang.core.psi.ext.RsReferenceElement" ]
mixin = "org.rust.lang.core.psi.ext.RsMacroReferenceImplMixin"
}
MacroExpansionReferenceGroup ::= '$' '(' MacroExpansionContents ')'
MacroExpansionReferenceGroup ::= '$' '(' MacroExpansionContents ')' MacroExpansionGroupSeparator? ('*' | '+' | '?') { pin = 2 }
MacroExpansionGroupSeparator ::= <<macroBindingGroupSeparatorToken>>



MacroCall ::= MacroHead <<macroSemicolon>> {
implements = [ "org.rust.lang.core.psi.ext.RsReferenceElement"
"org.rust.lang.core.psi.ext.RsOuterAttributeOwner"]
"org.rust.lang.core.psi.ext.RsOuterAttributeOwner"
"org.rust.lang.core.macros.ExpansionResult" ]
pin = 2
hooks = [ leftBinder = "ADJACENT_LINE_COMMENTS" ]
mixin = "org.rust.lang.core.psi.ext.RsMacroCallImplMixin"
Expand All @@ -1161,8 +1165,13 @@ MacroCallNoSemicolons ::= MacroHead {

private MacroHead ::= AttrsAndVis &(identifier '!') (SpecialMacro | identifier '!' identifier? MacroArgument)

MacroArgument ::= <<any_braces TT>>
TT ::= (<<any_braces TT>> | <<unpairedToken>>)*
MacroArgument ::= <<any_braces CompactTT>>
// `CompactTT` differs from `TT` in that it does not create an additional `TT` nodes for each unpaired token
CompactTT ::= (<<any_braces CompactTT>> | <<unpairedToken>>)*

// Used only manually in (external) macro matching code
//noinspection BnfUnusedRule
TT ::= <<any_braces TT*>> | <<unpairedToken>>


private SpecialMacro ::= TryMacro | FormatLikeMacro | AssertMacro | VecMacro | LogMacro
Expand Down Expand Up @@ -1260,6 +1269,7 @@ EmptyStmt ::= ';' { extends = Stmt }
// Utils
///////////////////////////////////////////////////////////////////////////////////////////////////

// Keep in sync with `collapsedTokenType`
private gtgteq ::= <<gtgteqImpl>> | never GTGTEQ { name = ">>=" }
private gtgt ::= <<gtgtImpl>> | never GTGT { name = ">>" }
private gteq ::= <<gteqImpl>> | never GTEQ { name = ">=" }
Expand Down
Expand Up @@ -14,8 +14,6 @@ import org.rust.ide.highlight.RsHighlighter
import org.rust.lang.core.psi.*
import org.rust.lang.core.psi.ext.*
import org.rust.lang.core.types.ty.TyPrimitive
import org.rust.lang.core.types.ty.TyReference
import org.rust.lang.core.types.type

// Highlighting logic here should be kept in sync with tags in RustColorSettingsPage
class RsHighlightingAnnotator : Annotator {
Expand Down Expand Up @@ -145,7 +143,7 @@ private fun partToHighlight(element: RsElement): TextRange? {
is RsTraitItem -> element.identifier
is RsTypeAlias -> element.identifier
is RsTypeParameter -> element.identifier
is RsMacroBinding -> element.nameElement
is RsMacroBinding -> element.metaVarIdentifier
else -> null
}
return name?.textRange
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/org/rust/lang/core/macros/LazyStatic.kt
Expand Up @@ -12,7 +12,7 @@ import org.rust.lang.core.psi.ext.descendantOfTypeStrict
import org.rust.lang.core.psi.ext.elementType

fun expandLazyStatic(call: RsMacroCall): ExpansionResult? {
val arg = call.macroArgument?.tt ?: return null
val arg = call.macroArgument?.compactTT ?: return null
val lazyStaticCall = parseLazyStaticCall(arg) ?: return null
val text = "${if (lazyStaticCall.pub) "pub " else ""}static ${lazyStaticCall.identifier}: ${lazyStaticCall.type} = &${lazyStaticCall.expr};"
return RsPsiFactory(call.project)
Expand All @@ -27,7 +27,7 @@ private data class LazyStaticCall(
val expr: String
)

private fun parseLazyStaticCall(tt: RsTt): LazyStaticCall? {
private fun parseLazyStaticCall(tt: RsCompactTT): LazyStaticCall? {
// static ref FOO: Foo = Foo::new();
val pub = tt.firstToken(RsElementTypes.PUB) != null
val ident = tt.firstToken(RsElementTypes.IDENTIFIER) ?: return null
Expand All @@ -48,7 +48,7 @@ private fun parseLazyStaticCall(tt: RsTt): LazyStaticCall? {
return LazyStaticCall(pub, ident.text, typeText, exprText)
}

private fun RsTt.firstToken(type: IElementType): PsiElement? {
private fun RsCompactTT.firstToken(type: IElementType): PsiElement? {
var child = firstChild
while (child != null) {
if (child.elementType == type) return child
Expand Down

0 comments on commit 15ed9c7

Please sign in to comment.