Outlining without braces

SyntaxEditor for Windows Forms Forum

Posted 15 years ago by NSXDavid
Avatar
I'm attempting to get outlining to work with a language that doesn't have braces. Given the following code snipet (as before):

if (something = somethingelse)
  dosomething()
  dosomethingelse()
else
  dosomethingmore()
  domorethingsthanbefore()
  stopdoingthings()
.
How would I setup the parsing so that I can outline the IF construct properly:

if (something = somethingelse) [...]
I don't have braces to collapse on and if I collapse on the IF (which is what starts the block), I get...

[....]
Which isn't what I'm after. Is there a way to do this?

-- David

Comments (20)

Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
What exactly do you want to collapse on... like from the first newline through a line that starts with a period?


Actipro Software Support

Posted 15 years ago by NSXDavid
Avatar
Yeah, I think that's what's needed... right? There didn't seem to be anything substantive to collapse on (like braces are).

-- David
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
This will be really tricky. <IMG SRC="smile.gif" border="0"> Somehow you need to identify the first newline character as a token with its own token key. Then you also need to identify the period character as a token with its own token key. Once you are able to do that lexically then you can perform outlining like you would with a {...} except use the above two tokens as your start and end tokens instead of { and }.

Now, the hard part of all this is identifying the two tokens. You have to do some creative stuff in your language definition so the lexical parser knows how to find them. The period isn't too hard to find but the newline will be.

You know that in the worst case scenario, you can't find the newline propertly and fall back to collapsing "if" through the period. And maybe in the collapsed text, you indicate the "if (something = somethingelse)" text. Although it isn't exactly how you wanted, it will work fine and not be too difficult to implement.

I'm not really sure how to assign the first newline a specific token key. What you really need is to be able to do a regular expression look-behind for the "if" but our engine doesn't support look-behinds yet.


Actipro Software Support

Posted 15 years ago by NSXDavid
Avatar
I guess this is the same problem as outling Visual Basic, right? It has the same sort of structure. Seems so common, shouldn't there be a way to do this?

-- David
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Yes... outlining is an extremely complex operation, even doing the "simpler" cases like C# braces/comments. I have a feeling that getting it to work for things like IF statements in VB would require an even more complex automatic outlining procedure that is possibly created specifically for VB. We do plan on making some enhanced language-specific add-ons to SyntaxEditor in the future that would possibly help with this sort of thing as well as provide language-specific data to the IntelliPrompt UI.


Actipro Software Support

Posted 15 years ago by Boyd - Automated Software Testing Consultant / Developer, Patterson Consulting, LLC
Avatar
I have a suggestion for a technique that might help with some of the outlining challenges without the need for the user to create their own semantic parser.

Currently, an OutliningNode has a StartOffset and EndOffset to indicate the area that should be outlined. As is often the case, the tokens used to identify on outlining region should not get collapsed. At the same time, these tokens need to be included within the region to make sure that any changes to those tokens result in a re-parse of then tokens within the node.

My suggesting is to have add a StartCollapseOffset and EndCollapseOffset properties. The StartOffset and EndOffset would still be the bounding region for the node, but the StartCollapseOffset and EndCollapseOffset properties would indicate which text actually gets collapsed (and they can default to the StartOffset and EndOffset respectively for backwards compatibility).

This technique, for example, would allow you to use function declaration tokens to identify an outlining node, but adjust the starting offset of the collapsed text to only include the body of the function.

What are your thoughts? Think it could work?
Posted 15 years ago by NSXDavid
Avatar
Dude.... excellent, simple approach that would definitely solve my issue without any undo complexity. What firm must I hire you away from? <IMG SRC="smile.gif" border="0">

-- David
Posted 15 years ago by NSXDavid
Avatar
.... though.... one thought.... I'm not sure what the endcollapseoffset would be useful for. Trying to think of an example that it would be... can't at the moment. If it existed, it would probably have to support negative values, right?

-- David
Posted 15 years ago by Boyd - Automated Software Testing Consultant / Developer, Patterson Consulting, LLC
Avatar
Hi David,

The 'EndCollapsedOffset' could be useful if you were working with a Visual Basic language using the Do-Until structure. For instance:
Do
  // some commands
  // go here
Loop Until True
You could place the 'StartCollapsedOffset' just after the 'Do' and the 'EndCollapsedOffset' at the last position in the line just before 'Loop'. This would result in the following effect:
[+] Do [...] Loop Until True
instead of
[+] Do [...]
In this case, you care more about the Loop Until condition than the Do statement.

[ 01-12-2005: Message edited by: Boyd ]
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
I like the idea of having a separate collapsible range for the node. The problem I still see here is that how do you know where the collapsible range starts and stops. It has to be assigned somewhere.


Actipro Software Support

Posted 15 years ago by NSXDavid
Avatar
Can't we do it in the same place we set the outlining start/end for automatic outlining?

-- David
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
But right now automatic outlining is performed by SemanticDefaultParser (if you're using it). Is that what you're using? SemanticDefaultParser has to have a way to know what offset range to set for the collapsible region. So it still comes back to the same issue where you need a unique token key assigned to the start and end tokens of the region to collapse.


Actipro Software Support

Posted 15 years ago by NSXDavid
Avatar
Well I think all you have to do is have so when you set the outlining mode (open or close indention) you specify an offset with it. It applies to whichever you are doing. Doesn't that work?

-- David
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
You have to remember that when you use SemanticDefaultParser, you are overriding GetTokenOutliningAction to determine the outlining action to take for that specific Token. That is fired for each Token as it is scanned. So there is no real spot where you can simply set an offset range. Know what I mean?


Actipro Software Support

Posted 15 years ago by painetraine
Avatar
What I do in my outlining parser is I actually examine the token and then look forwards or backwards to manually decide if this token is the start or end of an outlining region.

For example, if I see the token "select", I will look at lines above and see if they are comment lines, if so, then this token is not the start of an outlining region. If there is empty space or other tokens above, then this is the start of an outlining region.

I think the outlining you want can only be achieved by doing something similar where you basically parse every token to find the proper outlining you want.

You probably need to start an outlining action on "if" and then end on "." or whatever determines when you're done outlining. You can then change the text in the SetOutliningNodeCollapsedText to take the passed outlining node and extract the entire line instead of just the token that was the start of outlining.

For example, I use the following code in the SetOut...Text method to display all text for a begin start to the user:

TokenCollection tokenStream = node.Document.Tokens;
string strToken = tokenStream[tokenIndex].Text;
int tokenIndex = tokenStream.IndexOf(node.StartOffset);
string collapsedText = String.Empty;

while (++tokenIndex &lt; tokenStream.Count)
{
// stop appending text to display when we reach the end of either a begin or the comment
// after the begin
if (tokenStream[tokenIndex].Key == "BeginEndToken" &#0124;&#0124; tokenStream[tokenIndex].Key == "CommentStringEndToken")
break;

collapsedText += tokenStream[tokenIndex].Text;
}

node.CollapsedText = strToken + collapsedText.Replace("--", "").Trim() + "...";

This lets me display the text I want for the token which includes the token and any comments the user might have typed after the token.

Hope this helps
Posted 15 years ago by NSXDavid
Avatar
Yeah, I already do something similar with the collapsed text... it works for the moost part.

So I guess the problem with the offset approach is that you can't scan forward because the text has not been parsed yet, is that it?

-- David
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Semantic parsing (including outlining) occurs after the lexical parsing is complete.


Actipro Software Support

Posted 15 years ago by Boyd - Automated Software Testing Consultant / Developer, Patterson Consulting, LLC
Avatar
I wanted to make one note about painetraine's approach. I used a similar technique for function definitions in a C-like language, but I did run into one major issue. For instance, I had the following function declaration:
public function function_name(in arg1, in arg2)
{
    // Function Body
}
I wanted to collapse the text that represents the function body so that I would get the following effect:
[+] public function function_name(in arg1, in arg2) [...]
I couldn't just use the curly braces for collapsing because those are also used for if-blocks and other control structures that I didn't want to collapse. I only want to collapse function declarations.

So when my semantic parser would encounter an opening curly brace, I had to determine if it opened the body of a function declaration. If so, it started an outlining node. Otherwise, it didn't do anything. This goal was easy to achieve by scanning backwards through the token stream to make sure it was part of a valid function declaration. So far good!

The problem is this. If I were to delete the 'function' keyword from my function declaration, it is no longer a valid function declaration and should NOT be outlined. The problem is that the sematic parser doesn't pick up this change. It's smart (for performance reasons), so it only looks for modifications made within the start and end offsets of the outlining node. Since these modifications occurred before the start offset, the semantic parser didn't re-parse the opening curly brace to recognize that it should no longer be an outlining node.

I thought I'd mention this so that you adequately test your code's responsiveness to changes in tokens that are not part of the outlining node.
Posted 15 years ago by NSXDavid
Avatar
If outlining occurs after the lexical parsing... then I don't see how the offset thing is a problem to implement.... or am I missing something?

-- David
Posted 15 years ago by Boyd - Automated Software Testing Consultant / Developer, Patterson Consulting, LLC
Avatar
I beleive Actipro is looking into the possibility of adding the suggested offsets for the collapsable region of a node.
The latest build of this product (v2018.1 build 0341) was released 9 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.