MergableLexibleParser Requirements

SyntaxEditor for Windows Forms Forum

Posted 10 years ago by Kevin Carroll - Sr. Vice President, Sign Management Consultants, Inc.
Version: 4.0.0280
I have successfully implemented a programmatic lexical parser for a Lisp/Scheme-like scripting language for use with SyntaxEditor. My lexical parser implements IMergableLexicalParser like your SimpleLexicalParser class.

I would now like to extend my language to have embedded SQL strings that can be edited with syntax-highlighting. For example, in my language, I can populate an DataTable with a command like:
(define adoTable (select "select * from table where column = {0}" columnValue))

I plan to modify my language to something like:
(define adoTable (select %"select * from table where column = {0}"% columnValue))
with the stuff between %" and "% being edited as SQL. I would like to use the provided dynamic SQL language parser for my "child" language implementation.

Is this doable? In other words, can the "parent" language be non-dynamic with dynamic child languages? If so, can you point me to the best places in the documentation and samples to go to to get started? I have begun reviewing the samples but all of the mult-language examples I've found are based on both languages being dynamic.


Comments (4)

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Hi Kevin,

Sure, if your language is mergable you can do language transitions. Assuming you use our DefaultLexicalState class for lexical states, on the lexical state you add to your root language with scope patterns for %" and "%, set its LexicalStateTransitionLexicalState property to the default state of your SQL language. SyntaxEditor should take care of the rest for you.

And yes, dynamic and non-dynamic language can merge together as long as they are both "mergable".

Actipro Software Support

Posted 10 years ago by Kevin Carroll - Sr. Vice President, Sign Management Consultants, Inc.

Here's what I've tried. Below is a constructor for my SyntaxLanguage. It works as I wish it to if you comment out all the code between // New Code and // End of New Code. I've tried to make the "New Code" parallel your example tutorial for "Merging Two Languages at Run-Time Using a Direct Lexical State Transition". If I include this code, when I assign the SyntaxEditor's Document's Text property, an exception is thrown (see Exception Stack Trace below code). Any ideas of where I've gone wrong or additional steps I need to add?:
public SmcScriptLanguage(bool inTestMode)
                : base("SmcScript")
                IsUpdating = true;

                // Initialize highlighting styles
                HighlightingStyles.Add(new HighlightingStyle("KeywordStyle", null, Color.Blue, Color.Empty,
                HighlightingStyles.Add(new HighlightingStyle("CommentStyle", null, Color.Green, Color.Empty,
                HighlightingStyles.Add(new HighlightingStyle("NumberStyle", null, Color.Purple, Color.Empty));
                HighlightingStyles.Add(new HighlightingStyle("StringStyle", null, Color.Maroon, Color.Empty));
                HighlightingStyles.Add(new HighlightingStyle("AttributeStyle", null, Color.Purple, Color.Empty));
                HighlightingStyles.Add(new HighlightingStyle("InvalidStyle", null, HighlightingStyles["DefaultStyle"].ForeColor, HighlightingStyles["DefaultStyle"].BackColor,
                HighlightingStyles.Add(new HighlightingStyle("SqlDelimiterStyle", null, Color.Black, Color.Yellow));

                // Initialize lexical states
                LexicalStates.Add(new DefaultLexicalState(0, "DefaultState"));

                DefaultLexicalState = LexicalStates["DefaultState"];
                LexicalStates["DefaultState"].DefaultHighlightingStyle = HighlightingStyles["DefaultStyle"];

                _lexicalParser = new SmcScriptLexicalParser(inTestMode);

                // New Code --------------------------------------------------
                // Provide support for secondary language (Sql)
                if (SqlLanguage == null)  // SqlLanguage is a ReadOnly static property.  It's field is _sqlLanguage.  This makes sure it is only initialized once
                    _sqlLanguage = DynamicSyntaxLanguage.LoadFromXml("ActiproSoftware.SQL.xml", 0);

                SqlLanguage.IsUpdating = true;

                DynamicLexicalState sqlState = new DynamicLexicalState(1, "SqlState");
                sqlState.DefaultTokenKey = "SqlDefaultToken";
                sqlState.DefaultHighlightingStyle = HighlightingStyles["DefaultStyle"];
                sqlState.LexicalStateTransitionLexicalState = SqlLanguage.LexicalStates["DefaultState"];

                LexicalStates["DefaultState"].ChildLexicalStates.Insert(0, sqlState);

                DynamicLexicalScope sqlScope = new DynamicLexicalScope();
                sqlScope.StartLexicalPatternGroup = new LexicalPatternGroup(
                    HighlightingStyles["SqlDelimiterStyle"], "%\"");

                sqlScope.EndLexicalPatternGroup = new LexicalPatternGroup(
                    HighlightingStyles["SqlDelimiterStyle"], "\"%");

                SqlLanguage.IsUpdating = false;
                // End of New Code ------------------------------------------------

                IsUpdating = false;

Inner Exception 1: [System.InvalidCastException] Unable to cast object of type 'SmcScriptLanguage' to type 'ActiproSoftware.SyntaxEditor.Addons.Dynamic.DynamicSyntaxLanguage'.
Stack Trace 1:
at ActiproSoftware.SyntaxEditor.Addons.Dynamic.LexicalPatternGroup.b()
at ActiproSoftware.SyntaxEditor.Addons.Dynamic.LexicalPatternGroup.a(ITextBufferReader A_0, LexicalPattern& A_1)
at ActiproSoftware.SyntaxEditor.Addons.Dynamic.DynamicLexicalScope.IsScopeStart(ITextBufferReader reader, ITokenLexicalParseData& lexicalParseData)
at u.a(Document A_0, TextRange A_1, Int32 A_2, Int32 A_3, ILexicalParseTarget A_4)
at ActiproSoftware.SyntaxEditor.MergableSyntaxLanguage.PerformLexicalParse(Document document, TextRange parseTextRange, ILexicalParseTarget parseTarget)
at ActiproSoftware.SyntaxEditor.Document.a(DocumentModification A_0, Boolean A_1)
at ActiproSoftware.SyntaxEditor.Document.set_Text(String value)

at SmcManager.ScriptMaintenance_Form.LoadEditorFromScriptSource(Boolean isNew) in ScriptMaintenance_Form.cs line 711
at SmcManager.ScriptMaintenance_Form.LoadFieldsFromRow(DataRow row) in ScriptMaintenance_Form.cs line 692
at SmcManager.ScriptMaintenance_Form.LoadFieldsFromSelectedRow() in ScriptMaintenance_Form.cs line 647
at SmcManager.ScriptMaintenance_Form.xgr_Scripts_SelectedRowsChanged(Object sender, EventArgs e) in ScriptMaintenance_Form.cs line 638
Posted 10 years ago by Kevin Carroll - Sr. Vice President, Sign Management Consultants, Inc.

Changed DynamicLexicalState to DefaultLexicalState and I get further. It does load my source; however, as soon as I type my start pattern to indicate the switch over to SQL, I now get this exception:

[System.NullReferenceException] Object reference not set to an instance of an object.
Stack Trace:
at aw.e()
at ActiproSoftware.SyntaxEditor.MergableToken.get_Language()
at ActiproSoftware.SyntaxEditor.TextStream.GoToNextMatchingToken(IToken startToken, Int32 endTokenID)
at ActiproSoftware.SyntaxEditor.TextStream.GoToNextMatchingToken(IToken startToken)
at ActiproSoftware.SyntaxEditor.BracketHighlighting.a()
at ActiproSoftware.SyntaxEditor.EditorView.a(Object A_0, SelectionEventArgs A_1)
at ActiproSoftware.SyntaxEditor.Selection.a(SelectionEventArgs A_0)
at ActiproSoftware.SyntaxEditor.Selection.b(Boolean A_0)
at ActiproSoftware.SyntaxEditor.Selection.ResumeEvents()
at ActiproSoftware.SyntaxEditor.Commands.TypingCommand.Execute(EditCommandContext context)
at ActiproSoftware.SyntaxEditor.MacroRecording.a(EditCommand A_0, EditCommandContext A_1)
at ActiproSoftware.SyntaxEditor.EditorView.a(EditCommand A_0, Boolean A_1)
at ActiproSoftware.SyntaxEditor.SyntaxEditor.a(EditorView A_0, Keys A_1, Char A_2, Boolean A_3)
at ActiproSoftware.SyntaxEditor.SyntaxEditor.OnKeyPress(KeyPressEventArgs e)
at System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m)
at System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
at System.Windows.Forms.Control.WmKeyChar(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at ActiproSoftware.SyntaxEditor.SyntaxEditor.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA

Can you wrap all this up in a simple sample project and email it over to our support address so we can debug it? It's hard to say what is wrong from looking at a forum post. Thanks!

And you are correct, for non-dynamic languages you don't want to be using dynamic lexical states, etc.

Actipro Software Support

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.