How to find the matching token for Outlining

SyntaxEditor for Windows Forms Forum

Posted 7 years ago by Mike Dempsey - Sr. Developer, Teradata Corp
Version: 12.1.0300

I have iplemented a 'code behind' Dynamic language to support automatic Outlining.
The simple matches are working fine but I have one case that is condfitional. 

I want to outline a block that starts with an open paren, but only if it is immediately followed by the word 'Select'.
That part works fine. The problem is determining which close paren represents the end of the outline block since there can be many sets of parens within the block.

I thought that the MatchingTokenId property could somehow be used, but when I debug the app I'm not seing this value set, and I dont know what I would be comparing it to anyway.

My language defines:

   <ExplicitPatternGroup Key="OpenParen" TokenKey="OpenParen" PatternValue="(" EndBracket="CloseParen" />
   <ExplicitPatternGroup Key="CloseParen" TokenKey="CloseParen" PatternValue=")" StartBracket="OpenParen" />

And the rellevant section of my override function is:

   Case "OpenParen"  'set as Start if followed by 'Select'
      Dim streamCopy As TokenStream = tokenStream.Clone()
      streamCopy.FindNonWhitespace(True)   'Move to next token
      token = streamCopy.Peek()
      If token.AutoCaseCorrectText = "SELECT" Then
         outliningKey = "DerivedTable"
         tokenAction = OutliningNodeAction.Start
   Case "CloseParen"  'set as End if the token is paired with my start token
      If token.IsPaired Then '<<< this is where the decision needs to be made
         outliningKey = "DerivedTable"
         tokenAction = OutliningNodeAction.End

I'm new to the product so there may be a faster way to check the next token than cloning the stream ... but that part works.

The question is how do I determine that the current ')' token is the correct one that matches the '(' that started the outline?


Comments (2)

Answer - Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA

Hi Mike,

The IsPaired properties on a token only fill in if you are using a custom token type.  They will be false for dynamic languages.

That being said, if you use a TextStream instead of a TokenStream (you can do more with a TextStream anyhow), then you can call its GoToNextMatchingToken/GoToPreviousMatchingToken method as appropriate where you pass the token you're on and a target token ID.  If your open and close parens both have distinct token IDs assigned then that will work for your needs.

Actipro Software Support

Posted 7 years ago by Mike Dempsey - Sr. Developer, Teradata Corp

Thanks. That gave me enough info to get it working. I did have to add TokenIDs to the language file, but it seems to be happy with IDs only on some patterngroups. (I'll use IDs if I write a code language anyway.) 

The following code works:

  Case "CloseParen"             'set End if the token is paired with my start token
      Dim text As TextStream = tokenStream.Document.GetTextStream(token.StartOffset)
      If text.GoToPreviousMatchingToken(token, 5) Then    'Goto previous '('
         If text.PeekToken.AutoCaseCorrectText = "SELECT" Then
            outliningKey = "DerivedTable"
            tokenAction = OutliningNodeAction.End
         End If
      End If

The latest build of this product (v2018.1 build 0341) was released 3 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.