HTML -> Programmatic Language transition

SyntaxEditor for WPF Forum

Posted 7 years ago by Slava Shavlyuk
Version: 12.2.0573
Avatar

Hi guys, I do have a question about language transition. I spent a lot of efforts to implement JScript.NET language using LLParser and it works fine, with coloring and code completion. To acomplish this we've created dozen classes:

JScriptNETParser : LLParserBase

JScriptNETLexer :MergableLexerBase

...

code completion provider, grammar, etc.

...

JScriptNETSyntaxLanguage: SyntaxLanguage

where constructor register lexer, parse, etc.

 

It all works perfectly.

Now I have new task to be able to to edit JScript.NET embedded within html/xml inside asp.net <% %> , <%= %>. I've taken

AspStyleTransitionSyntaxLanguage class from samples project as example. Constructor:

 

            string xmlLangPath = "Xml.langdef";
            using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(xmlLangPath))
            {
                if (stream != null)
                {
                    SyntaxLanguageDefinitionSerializer serializer = new SyntaxLanguageDefinitionSerializer();
                    serializer.InitializeFromStream(this, stream);
                }
            }

            // Get the lexer for the parent language
            DynamicLexer parentLexer = this.GetLexer() as DynamicLexer;

            //jScriptLanguage = new ActiproSoftware.Text.Languages.Xml.Implementation.XmlSyntaxLanguage();
            // Get the lexer for the child language
            var childLexer = jScriptLanguage.GetLexer() as DynamicLexer;

            // Get the classification types that will be used (create and register if necessary)
            IClassificationType serverSideScriptClassificationType = AmbientHighlightingStyleRegistry.Instance["ServerSideScript"];
            if (serverSideScriptClassificationType == null)
            {
                serverSideScriptClassificationType = new ClassificationType("ServerSideScript", "Server-Side Script");

                        AmbientHighlightingStyleRegistry.Instance.Register(serverSideScriptClassificationType,
                    new HighlightingStyle(Brushes.Black, new SolidColorBrush(Color.FromArgb(0xff, 0xff, 0xee, 0x62))));

// Since we will be dynamically modifying the parent lexer, wrap it with a change batch
            using (IDisposable batch = parentLexer.CreateChangeBatch())
            {
                // Create a new transition lexical state in the parent language that will serve as the bridge between the two languages
                DynamicLexicalState lexicalState = new DynamicLexicalState(0, "ASPDirective");
                lexicalState.DefaultTokenKey = "ASPDirectiveText";
                parentLexer.LexicalStates.Add(lexicalState);

                // Insert the transition lexical state at the beginning of the parent language's 
                //   default state's child states list so that it has top matching priority
                parentLexer.DefaultLexicalState.ChildLexicalStates.Insert(0, lexicalState);

                // Create the lexical scope for the transition lexical state
                DynamicLexicalScope lexicalScope = new DynamicLexicalScope();
                lexicalState.LexicalScopes.Add(lexicalScope);
                lexicalScope.StartLexicalPatternGroup = new DynamicLexicalPatternGroup(DynamicLexicalPatternType.Explicit, "ASPDirectiveStartDelimiter", serverSideScriptClassificationType);
                lexicalScope.StartLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"<%="));
                lexicalScope.StartLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"<%"));
                
                lexicalScope.EndLexicalPatternGroup = new DynamicLexicalPatternGroup(DynamicLexicalPatternType.Explicit, "ASPDirectiveEndDelimiter", serverSideScriptClassificationType);
                lexicalScope.EndLexicalPatternGroup.Patterns.Add(new DynamicLexicalPattern(@"%>"));

                // Set up a direct transition on the lexical state so that when it is entered, 
                //   it will transition directly to the child language's default lexical state
                lexicalState.Transition = new LexicalStateTransition(jScriptLanguage, childLexer.DefaultLexicalState, null);
            }

 It did the job. I see that my JScriptNETLexer is triggered within <% %> block , but no parser, no classificationprovider, no completion are triggered. Text withing <% %> is left black color, intelliprompt doesn't work. Is it because I applied your example to programmatic language and not dynamic?

 

Thanks.

[Modified 7 years ago]

Comments (5)

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

Hi Slava,

That's great to hear that you put together a fully working JScript.NET language.  In the merged scenario, all the IntelliPrompt, etc. works on the root language.  So if you have multiple languages, you need to proxy calls to the child language when appropriate.

We actually have an internal sample here where we show full use of our .NET Languages Add-on's C# language within ASP-style tags (including things like automated IntelliPrompt).  If you write our support address and reference this post, we'll send you a link to the sample.  That should help you.


Actipro Software Support

Posted 7 years ago by Slava Shavlyuk
Avatar

Hi guys, again. I was able to use provided example and looks like most of the stuff works fine. I mean intellisense, quickprompt... But I have a little problem. Wihtin ParentParser child parser gives list of errors within parse data:

 

parseData.GeneratedParseData = generatedDocument.ParseData as ILLParseData;
foreach (var error in parseData.GeneratedParseData.Errors)
{
 //need to convert error position from generated text position to editor text position
 error.PositionRange
}

 We use error position to navigate person thru script error. It is just plain vanilla button "Next Error". My problem is that error.PositionRange has coordinates within generated code text. Somehow I need to convert this position to coordinates of real script editor text. I see that object ParentParseData has map textRangeMapping and method TranslateEditorToGenerated which is used to convert editor coordinates to generated text coordinates. Could you help me write method for opposite work - adjust error.PositionRange to be in real text editor coordinates?

 

Let me know if it does make sense.

[Modified 7 years ago]

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

Hi Slava,

Snapshot translation can work both ways.  So for the method you see, you could clone it and make a reverse way.  At a glance, it's probably a matter of swapping "snapshot" with "generatedParseData.Snapshot", and "mapping.Item1" with "mapping.Item2".  You'd have to test it of course but that might work since you have access to both snapshots, and the textRangeMappings stores how text ranges from one snapshot end up as in the other snapshot.


Actipro Software Support

Posted 7 years ago by Slava Shavlyuk
Avatar

That's what I thought, but wasn't sure. Good. One more questions - is anyway to make parent language to be HTML or XML with highlighting enabled? We have license for "web languages addon" for syntax editor. I just not sure how to connect it together.

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

Hi Slava,

Sure you could use any dynamic lexer we provide with SyntaxEditor, but note that you'd have to inject points programmmatically into that lexer (once loaded) to allow the child language transition.  So it would be similar to the code in the ParentLexer where a childLanguageTransitionState is added, but to various dynamic lexer child states as appropriate.

The Web Languages Add-on might not work though (unless you disable its default parsing parsing) because the grammar there is hardcoded and will report syntax errors if you start injecting a child language.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.