]> O.S.I.I.S - jp/crowedit.git/commitdiff
wip
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 4 Jul 2025 11:45:57 +0000 (13:45 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 4 Jul 2025 11:45:57 +0000 (13:45 +0200)
CrowEditBase/src/Compiler/SyntaxNodes/SingleTokenSyntax.cs
CrowEditBase/src/Compiler/SyntaxNodes/SyntaxNode.cs
CrowEditBase/src/SourceEditor.cs
plugins/CECrowPlugin/src/Parsing/IML/ImlDocument.cs
plugins/CECrowPlugin/src/Parsing/IML/ImlSyntaxAnalyser.cs
plugins/CEXmlPlugin/src/Parsing/XmlDocument.cs
plugins/CEXmlPlugin/src/Parsing/XmlSyntaxAnalyser.cs
plugins/CEXmlPlugin/src/Parsing/XmlSyntaxNodes.cs

index 3253e9f5edd7d233a4e61bc86bdbf156c48357be..56c486f4e0c2f0e7d3910fc9dca870a079bec5d1 100644 (file)
@@ -11,13 +11,20 @@ namespace CrowEditBase
                }
                #endregion
 
-               protected Token token;
+               public readonly Token token;
 
                #region SyntaxNode implementation
         public override TokenType Type => token.Type;
         public override int SpanStart => token.Start;
                public override int SpanEnd => token.End;
         public override bool IsComplete => token.Type != TokenType.Unknown && token.Length > 0;
-               #endregion
-       }
+        public override bool IsSimilar(object other)
+        {
+            return other is SingleTokenSyntax sts ?
+                               sts.Type == Type : other is TokenType tt ? Type == tt : false;
+
+        }
+        #endregion
+
+    }
 }
\ No newline at end of file
index 092d54b4e9dfd7de5aec75e1a128aee96e3dd3bd..bb639d62920ddc0594acc84e126beecd586e97ab 100644 (file)
@@ -2,6 +2,7 @@
 //
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 using System.Collections.Generic;
+using System.ComponentModel;
 using Crow.Text;
 
 namespace CrowEditBase
@@ -79,91 +80,12 @@ namespace CrowEditBase
                public string AsText() {
                        return Span.Length < 0 ? "" : Root.GetText(Span).ToString();
                }
-               public bool IsSimilar (SyntaxNode other) => this.GetType() == other?.GetType();
+               public virtual bool IsSimilar (object other) => this.GetType() == other?.GetType();
 
         public class CompareOnStartLine : IComparer<SyntaxNode>
         {
             public int Compare(SyntaxNode x, SyntaxNode y) => x.StartLocation.Line - y.StartLocation.Line;
         }
                public override string ToString() => $"{this.GetType().Name}";
-
-               #region to clean
-               /*public int StartLine { get; private set; }
-               public virtual int LineCount => lineCount;*/
-
-               /*List<SyntaxException> exceptions = new List<SyntaxException>();
-               public IEnumerable<SyntaxException> Exceptions => exceptions;
-               public void AddException(SyntaxException e) => exceptions.Add(e);
-               public void ResetExceptions(SyntaxException e) => exceptions.Clear();
-               public IEnumerable<SyntaxException> GetAllExceptions() {
-                               foreach (SyntaxException e in exceptions)
-                                       yield return e;
-                               foreach (SyntaxNode n in Children) {
-                                       foreach (SyntaxException ce in n.GetAllExceptions())
-                                               yield return ce;
-                               }
-               }*/
-       
-               //public int IndexOf (SyntaxNode node) => children.IndexOf (node);
-
-               /*public virtual int TokenIndexBase { get; private set; }
-               public virtual int TokenCount => lastTokenOfset.HasValue ? lastTokenOfset.Value + 1 : 0;
-               public int? LastTokenIndex =>  lastTokenOfset.HasValue ? TokenIndexBase + lastTokenOfset.Value : null;
-
-               public int EndLine {
-                       set {
-                               lineCount = value - StartLine + 1;
-                       }
-                       get => StartLine + lineCount - 1;
-               }*/
-
-               /*
-               public void Replace (SyntaxNode newNode) {
-                       Parent.replaceChild (this, newNode);
-               }
-               void replaceChild (SyntaxNode oldNode, SyntaxNode newNode) {
-                       int idx = children.IndexOf (oldNode);
-                       children[idx] = newNode;
-                       newNode.Parent = this;
-                       int tokIdxDiff = newNode.TokenCount - oldNode.TokenCount;
-                       int lineDiff = newNode.EndLine - oldNode.EndLine;
-                       if (tokIdxDiff == 0 && lineDiff == 0)
-                               return;
-
-                       SyntaxNode curNode = this;
-                       while (curNode != null) {
-                               curNode.lineCount += lineDiff;
-                               curNode.TokenCount += tokIdxDiff;
-                               if (curNode is SyntaxRootNode)
-                                       break;
-                               while (++idx < curNode.children.Count)
-                                       curNode.children[idx].offset (tokIdxDiff, lineDiff);
-                               idx = curNode.Parent.children.IndexOf (curNode);
-                               curNode = curNode.Parent;
-                       }
-               }*/
-               /*void offset (int tokenOffset, int lineOffset) {
-                       TokenIndexBase += tokenOffset;
-                       StartLine += lineOffset;
-                       foreach (SyntaxNode child in children) {
-                               child.offset (tokenOffset, lineOffset);
-                       }
-               }*/
-/*             
-               public T FindNodeIncludingPosition<T> (int pos) {
-                       foreach (SyntaxNode node in children) {
-                               if (node.Contains (pos))
-                                       return node.FindNodeIncludingPosition<T> (pos);
-                       }
-
-                       return this is T tt ? tt : default;
-               }*/
-               /*public void Dump (int level = 0) {
-                       Console.WriteLine ($"{new string('\t', level)}{this}");
-                       foreach (SyntaxNode node in children)
-                               node.Dump (level + 1);
-               }*/
-               //public override string ToString() => $"l:({StartLine,3},{LineCount,3}) tks:{TokenIndexBase},{TokenCount} {this.GetType().Name}";
-               #endregion
     }
 }
\ No newline at end of file
index 4e10f6d94f8c25c6ef2c82e1688cd1766d8e8dc8..43a31e192b8800a55707748df1532e5ce661f6d7 100644 (file)
@@ -127,13 +127,18 @@ namespace CrowEditBase
                protected void tryGetSuggestions () {
                        if (currentLoc.HasValue && Document is SourceDocument srcDoc && srcDoc.IsParsed) {
                                int pos = srcDoc.GetAbsolutePosition(CurrentLoc.Value);
-                               var tmp = srcDoc.GetSuggestions (pos, currentTokenIndex, currentNode, CurrentLoc.Value);
-                               if (tmp?.Count == 1 && tmp[0].TryCast(out Suggestion sug) && sug.Change.HasNoEffect(srcDoc.source))
-                                       Suggestions = null;
-                               else
-                                       Suggestions = tmp;
-                       } else
-                               Suggestions = null;
+                               if (pos > 0) {
+                                       SyntaxNode node = srcDoc.FindNodeIncludingPosition(pos-1);
+                                       if (node != null) {
+                                               var tmp = srcDoc.GetSuggestions (pos,
+                                                                       srcDoc.FindTokenIndexIncludingPosition(pos -1), node, CurrentLoc.Value);
+                                               if (!(tmp?.Count == 1 && tmp[0].TryCast(out Suggestion sug) && sug.Change.HasNoEffect(srcDoc.source)))
+                                                       Suggestions = tmp;
+                                               return;
+                                       }
+                               }
+                       }
+                       Suggestions = null;
                }
                void showOverlay () {
                        lock (IFace.UpdateMutex) {
@@ -426,7 +431,7 @@ namespace CrowEditBase
 
                                        return;
                                }
-                               if (Document is SourceDocument doc) {
+                               if (Document is SourceDocument doc && doc.IsParsed) {
                                        switch (e.Key) {
                                                /*case Key.F3:
                                                        doc.Root?.Dump();
@@ -593,26 +598,28 @@ namespace CrowEditBase
 
                }
                protected override void drawContent (IContext gr) {
+                       sourceDocument.EnterReadLock ();
+
+                       double lineHeight = fe.Ascent + fe.Descent;
+                       updateMargin ();
+
+                       bool printLineNumbers = App.PrintLineNumbers;
+                       Color marginBG = App.MarginBackground;
+                       Color marginFG = Colors.Ivory;
+                       Rectangle cb = ClientRectangle;
+                       RectangleD marginRect = new RectangleD (cb.X, cb.Y, leftMargin - leftMarginRightGap, cb.Height);
+
+                       gr.SetSource (marginBG);
+                       gr.Rectangle (marginRect);
+                       gr.Fill();                      
+
                        if (!parsingOk) {
                                base.drawContent (gr);
+                               sourceDocument.ExitReadLock ();
                                return;
                        }
 
-                       sourceDocument.EnterReadLock ();
                        try {
-                               double lineHeight = fe.Ascent + fe.Descent;
-                               updateMargin ();
-
-                               bool printLineNumbers = App.PrintLineNumbers;
-                               Color marginBG = App.MarginBackground;
-                               Color marginFG = Colors.Ivory;
-                               Rectangle cb = ClientRectangle;
-                               RectangleD marginRect = new RectangleD (cb.X, cb.Y, leftMargin - leftMarginRightGap, cb.Height);
-
-                               gr.SetSource (marginBG);
-                               gr.Rectangle (marginRect);
-                               gr.Fill();
-
                                gr.Translate (-ScrollX, 0);
 
                                double lineNumWidth = gr.TextExtents (Document.LinesCount.ToString()).Width;
@@ -901,7 +908,7 @@ namespace CrowEditBase
                        RegisterForGraphicUpdate();
                }
                void updateCurrentTokAndNode() {
-                       if (currentLoc.HasValue && Document is SourceDocument srcdoc) {
+                       if (currentLoc.HasValue && Document is SourceDocument srcdoc && srcdoc.Tokens.Length > 0) {
                                int pos = srcdoc.GetAbsolutePosition(currentLoc.Value);
                                currentTokenIndex = srcdoc.FindTokenIndexIncludingPosition(pos);
                                Token tok = srcdoc.GetTokenByIndex(currentTokenIndex);
index f4c42a396d9afae5b8c1af8c221669694a173b14..11ac33831a43799e5d26118fa59c7f6dbed1ea93 100644 (file)
@@ -5,6 +5,7 @@
 using System;
 using System.Linq;
 using Crow.Text;
+using System.Collections;
 using System.Collections.Generic;
 using Crow;
 using IML = Crow.IML;
@@ -18,9 +19,16 @@ using System.Diagnostics;
 
 namespace CECrowPlugin
 {
+       public static class Extensions {
+               public static ImlTokenType GetTokenType (this Token tok) {
+                       return (ImlTokenType)tok.Type;
+               }
+               public static void SetTokenType (this Token tok, ImlTokenType type) {
+                       tok.Type = (TokenType)type;
+               }
+               public static bool Is(this Token tok, ImlTokenType type) => (ImlTokenType)tok.Type == type;
+       }               
        public class ImlDocument : XmlDocument {
-
-
                public ImlDocument (string fullPath, string editorPath) : base (fullPath, editorPath) {
                        App.GetService<CrowService> ()?.Start ();
 
@@ -28,6 +36,7 @@ namespace CECrowPlugin
                                if (msbp.IsCrowProject)
                        }*/
                }
+
                protected override SyntaxAnalyser CreateSyntaxAnalyser() => new ImlSyntaxAnalyser (ImmutableBufferCopy);
                public override string GetTokenTypeString (TokenType tokenType) => ((ImlTokenType)tokenType).ToString();
 
@@ -46,8 +55,8 @@ namespace CECrowPlugin
                        if (widgetType == null)
                                return null;
 
-                       IEnumerable<Type> widgetTypes = widgetType.Assembly.GetExportedTypes ().Where(t=>
-                               widgetType.IsAssignableFrom (t) && !t.IsAbstract);
+                       IEnumerable<Type> widgetTypes = widgetType.Assembly.GetExportedTypes ().Where(
+                               t=>!t.IsAbstract &&     widgetType.IsAssignableFrom (t));
                        int curNameLength = 0;
                        if (!string.IsNullOrEmpty(curName)) {
                                widgetTypes = widgetTypes.Where(t=>t.Name.StartsWith(curName, StringComparison.OrdinalIgnoreCase));
@@ -114,13 +123,21 @@ namespace CECrowPlugin
                        }
                        return null;
                }
-        /*public override IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode CurrentNode, CharLocation loc) {
+        public override IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode CurrentNode, CharLocation loc) {
+                       Token tok = GetTokenByIndex(currentTokenIndex);
+                       Console.Write($"{absoluteTextPos}({tok.Span}){tok.GetTokenType()}");
+                       if (currentTokenIndex > 0)
+                               Console.Write($" prev:{GetTokenByIndex(currentTokenIndex-1).GetTokenType()}");                  
+                       if (currentTokenIndex < Tokens.Length - 1)
+                               Console.Write($" next:{GetTokenByIndex(currentTokenIndex+1).GetTokenType()}");  
+                       Console.WriteLine($" node:{CurrentNode} ({loc})");
+                       
                        IList sugs = base.GetSuggestions (absoluteTextPos, currentTokenIndex, CurrentNode, loc);
                        if (sugs != null)
                                return sugs;
-
+/*
+                       
                        
-                       Token tok = GetTokenByIndex(currentTokenIndex);
 
                        if (tok.GetTokenType() == XmlTokenType.ElementOpen)
                                return new List<string> (allWidgetNames);
@@ -188,9 +205,9 @@ namespace CECrowPlugin
                                //else if (tok.Type == TokenType.ElementName)
                                //      Suggestions = getAllCrowTypeMembers (eltStartTag.NameToken.Value.AsString (Source)).ToList ();
                        } else {
-                       }
+                       }*/
                        return null;
-               }*/
+               }
 
                public override Color GetColorForToken(Token token)
                {
index 5c1fb3d80ef5600500966192c8563d0c3e0c6ec7..e39984988764496a9d87b978d37b774e2c8bf714 100644 (file)
-// Copyright (c) 2021-2021  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+// Copyright (c) 2021-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
 //
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
-using System;
-using System.Collections.Generic;
-using System.Linq;
 using CrowEditBase;
 using CrowEdit.Xml;
-using System.Threading.Tasks;
-using System.Threading;
 
 namespace CECrowPlugin
 {
        public class ImlSyntaxAnalyser : XmlSyntaxAnalyser {
                public ImlSyntaxAnalyser (ReadOnlyTextBuffer document) : base (document) {}
 
-
-               public override async Task<SyntaxRootNode> Process (CancellationToken cancel = default) {
-
-                       return await base.Process();
-
-/*
-                       ImlDocument xmlDoc = source as ImlDocument;
-                       Exceptions = new List<SyntaxException> ();
-                       currentNode = new XMLRootSyntax (xmlDoc);
-                       currentLine = 0;
-                       Span<Token> toks = source.Tokens;
-                       tokIdx = 0;
-
-                       while (tokIdx < toks.Length) {
-                               Token curTok = toks[tokIdx];
-                               if (curTok.Type == TokenType.LineBreak)
-                                       currentLine++;
-                               else if (!curTok.Type.HasFlag (TokenType.Trivia)) {
-                                       if (currentNode is ElementStartTagSyntax tag) {
-                                               if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
-                                                       AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
-                                                       attribute.name = 0;
-                                                       currentNode = currentNode.AddChild (attribute);
-                                               } else if (curTok.GetTokenType() == XmlTokenType.ElementName)
-                                                       tag.name = tokIdx - tag.TokenIndexBase;
-                                               else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
-                                                       storeCurrentNode ();
-                                                       currentNode.RemoveChild (tag);
-                                                       currentNode = currentNode.AddChild (new ElementSyntax (tag));
-                                               } else if (curTok.GetTokenType() == XmlTokenType.EmptyElementClosing) {
-                                                       storeCurrentNode ();
-                                                       currentNode.RemoveChild (tag);
-                                                       currentNode = currentNode.AddChild (new EmptyElementSyntax (tag));
-                                                       setCurrentNodeEndLine (currentLine);
-                                                       currentNode = currentNode.Parent;
-                                               } else {
-                                                       Exceptions.Add (new SyntaxException  ("Unexpected Token", curTok));
-                                                       storeCurrentNode (-1);
-                                                       continue;
-                                               }
-                                       } else if (currentNode is ElementSyntax elt) {
-                                               if (curTok.GetTokenType() == XmlTokenType.ElementOpen)
-                                                       currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
-                                               else if (curTok.GetTokenType() == XmlTokenType.EndElementOpen) {
-                                                       elt.EndTag = new ElementEndTagSyntax (currentLine, tokIdx);
-                                                       currentNode = elt.AddChild (elt.EndTag);
-                                               }
-                                       } else if (currentNode is AttributeSyntax attrib) {
-                                               if (curTok.GetTokenType() == XmlTokenType.EqualSign)
-                                                       if (attrib.equal.HasValue)
-                                                               Exceptions.Add (new SyntaxException  ("Extra equal sign in attribute syntax", curTok));
-                                                       else
-                                                               attrib.equal = tokIdx - attrib.TokenIndexBase;
-                                               else if (curTok.GetTokenType() == XmlTokenType.AttributeValueOpen)
-                                                       attrib.valueOpen = tokIdx - attrib.TokenIndexBase;
-                                               else if (curTok.GetTokenType() == XmlTokenType.AttributeValue)
-                                                       attrib.valueTok = tokIdx - attrib.TokenIndexBase;
-                                               else if (curTok.GetTokenType() == XmlTokenType.AttributeValueClose) {
-                                                       attrib.valueClose = tokIdx - attrib.TokenIndexBase;
-                                                       storeCurrentNode ();
-                                               } else {
-                                                       Exceptions.Add (new SyntaxException  ("Unexpected Token", curTok));
-                                                       storeCurrentNode (-1);
-                                                       continue;
-                                               }
-                                       } else if (currentNode is ElementEndTagSyntax eltEndTag) {
-                                               if (curTok.GetTokenType() == XmlTokenType.ElementName)
-                                                       eltEndTag.name = tokIdx - eltEndTag.TokenIndexBase;
-                                               else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
-                                                       //go up 2 times
-                                                       storeCurrentNode (); storeCurrentNode ();
-                                               } else {
-                                                       Exceptions.Add (new SyntaxException  ("Unexpected Token", curTok));
-                                                       storeCurrentNode (-1);
-                                                       storeCurrentNode (-1);
-                                                       continue;
-                                               }
-                                       } else if (currentNode is XMLRootSyntax) {
-                                               switch (curTok.GetTokenType()) {
-                                                       case XmlTokenType.ElementOpen:
-                                                               currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
-                                                               break;
-                                                       case XmlTokenType.PI_Start:
-                                                               currentNode = currentNode.AddChild (new ProcessingInstructionSyntax (currentLine, tokIdx));
-                                                               break;
-                                                       default:
-                                                               Exceptions.Add (new SyntaxException  ("Unexpected Token", curTok));
-                                                               break;
-                                               }
-                                       } else if (currentNode is ProcessingInstructionSyntax pi) {
-                                               if (curTok.GetTokenType() == XmlTokenType.PI_Target)
-                                                       pi.name = tokIdx - pi.TokenIndexBase;
-                                               else if (curTok.GetTokenType() == XmlTokenType.PI_End) {
-                                                       storeCurrentNode ();
-                                               } else if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
-                                                       AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
-                                                       attribute.name = 0;
-                                                       currentNode = currentNode.AddChild (attribute);
-                                               } else {
-                                                       Exceptions.Add (new SyntaxException  ("Unexpected Token", curTok));
-                                                       storeCurrentNode (-1);
-                                                       continue;
-                                               }
-                                       }
-                               }
-                               tokIdx++;
-                       }
-                       while (currentNode.Parent != null) {
-                               if (!currentNode.LastTokenOffset.HasValue)
-                                       storeCurrentNode (-1);
-                               else
-                                       currentNode = currentNode.Parent;
-                       }
-                       setCurrentNodeEndLine (currentLine);
-                       */
-               }
+        protected override Token[] tokenize()
+        {
+            Tokenizer tokenizer = new ImlTokenizer();
+                       return tokenizer.Tokenize(source.Source.Span);
+        }
        }
 }
\ No newline at end of file
index 38d70f703c71028655b2e3be86dd2acf8ddedf6d..43a3d2d57ea91b85efaf5211c0e306632e3e7efb 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2021  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+// Copyright (c) 2013-2025  Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
 //
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 
@@ -10,6 +10,7 @@ using System.Collections.Generic;
 using System;
 using Crow;
 using System.Linq;
+using System.Diagnostics;
 
 namespace CrowEdit.Xml
 {
@@ -23,7 +24,40 @@ namespace CrowEdit.Xml
                protected virtual IEnumerable<Suggestion> getAttributeNameSuggestions(string eltName, string attribName, TextChange change) => null;
                protected virtual IEnumerable<Suggestion> getAttributeValueSuggestions(string eltName, string attribName, string attribValue, TextChange change) => null;
                public override IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode CurrentNode, CharLocation loc) {
-                       /*Token tok = GetTokenByIndex(currentTokenIndex);       
+                       Console.WriteLine($"absPos:{absoluteTextPos} tokIdx:{currentTokenIndex} node:{CurrentNode} charLoc:{loc}");
+                       Token tok = GetTokenByIndex(currentTokenIndex);
+                       XmlTokenType tokType = tok.GetTokenType();
+                       if (CurrentNode is SingleTokenSyntax sts) {
+                               XmlTokenType tk = sts.token.GetTokenType();
+                               if (CurrentNode.Parent is ElementTagSyntax ets) {
+                                       if (ets is ElementEndTagSyntax eets) {
+                                               if (eets.Parent is ElementSyntax es) {
+                                                       string name = es.StartTag?.Name;
+                                                       if (!string.IsNullOrEmpty(name)){
+                                                               Suggestion sug = new Suggestion(name);
+                                                               if (tk == XmlTokenType.ElementName && name.StartsWith(sts.AsText(), StringComparison.OrdinalIgnoreCase))
+                                                                       sug.Change = new TextChange (tok.Start, tok.Length, sug.Caption);
+                                                               else if (tk == XmlTokenType.EndElementOpen)
+                                                                       sug.Change = new TextChange (tok.End, 0, sug.Caption);
+                                                               else
+                                                                       return null;
+                                                               if (!eets.HasClosingToken)
+                                                                       sug.Change.ChangedText += ">";
+                                                               return new List<Suggestion>([sug]);
+                                                       } 
+                                               }
+                                       } else {
+                                               string txtEnd = ets.HasClosingToken ? "" : ">";
+                                               if (tk == XmlTokenType.ElementOpen) {
+                                                       return getElementNameSuggestions("", new TextChange(tok.End, 0, txtEnd)).ToList();
+                                               }
+                                               if (tk == XmlTokenType.ElementName) {
+                                                       return getElementNameSuggestions(sts.AsText(), new TextChange(tok.Start, tok.Length, txtEnd)).ToList();
+                                               }
+                                       }
+                               } 
+                       }
+                       /*      
                        if (tok.Start != absoluteTextPos //middle of edited tok
                                && currentTokenIndex >= CurrentNode?.Root.TokenCount - 1) //occurs when curTok is last tok of text
                        {
index 96bb444dbd9c9af44f6950fe0e3cadd35a54df1a..e678241f0139f3e16d9aea276d9f48ef49ef14cf 100644 (file)
@@ -117,14 +117,15 @@ namespace CrowEdit.Xml
                }
                void processElementNode(MultiNodeSyntax node) {
                        ElementStartTagSyntax start = new ElementStartTagSyntax(Read());
+                       MultiNodeSyntax elt = null;
                        if (accept (start, XmlTokenType.ElementName)) {
                                while (skipTriviaAndComments(node)) {
                                        if (accept (start, XmlTokenType.EmptyElementClosing)) {
-                                               node.AddChild(new EmptyElementSyntax(start));
+                                               elt = new EmptyElementSyntax(start);
                                                break;
                                        }
                                        if (accept (start, XmlTokenType.ClosingSign)) {
-                                               node.AddChild(processElement(new ElementSyntax(start)));
+                                               elt = processElement(new ElementSyntax(start));
                                                break;
                                        }                                       
                                        if (Peek().Is(XmlTokenType.AttributeName))
@@ -133,17 +134,26 @@ namespace CrowEdit.Xml
                                                start.AddChild(new UnexpectedTokenSyntax(Read()));
                                }
                        } else {
-                               start.AddChild(new UnexpectedTokenSyntax(Read()));
-                               node.AddChild(new ElementSyntax(start));
+                               if (!EOF)
+                                       start.AddChild(new UnexpectedTokenSyntax(Read()));
+                               elt = new ElementSyntax(start);
                        }
-               }               
-               public override async Task<SyntaxRootNode> Process (CancellationToken cancel = default) {
+                       if (elt == null)
+                               elt = new ElementSyntax(start);
+                       node.AddChild(elt);
+               }
+               protected virtual Token[] tokenize() {
                        Tokenizer tokenizer = new XmlTokenizer();
-                       Token[] tokens = tokenizer.Tokenize(source.Source.Span);
+                       return tokenizer.Tokenize(source.Source.Span);
+               }
+
+               public override async Task<SyntaxRootNode> Process (CancellationToken cancel = default) {
+                       Token[] tokens = tokenize();
                        tokIdx = 0;
                        this.cancel = cancel;//?
                        
                        Root = new XMLRootSyntax (source, tokens);
+                       
                        while (!EOF) {
                                if (cancel.IsCancellationRequested)
                                        break;
index 7e870c25d6abae48cb6cc6c4a52062863ff6046c..e877d5356eb33816b7daf44e8d197ce750725665 100644 (file)
@@ -26,35 +26,45 @@ namespace CrowEdit.Xml
 
        public abstract class ElementTagSyntax : MultiNodeSyntax {
 //             public override bool IsComplete => base.IsComplete & name.HasValue & close.HasValue;
+               protected ElementTagSyntax (){}
                protected ElementTagSyntax (Token openTok) {
                        AddChild(new SingleTokenSyntax(openTok));
                }
+        public override bool IsComplete => ChildSequenceIs();
+               public string Name => Children.ElementAtOrDefault(1) is SingleTokenSyntax sts &&
+                                                         sts.token.GetTokenType() == XmlTokenType.ElementName ? sts.AsText(): "";
+               public abstract bool HasClosingToken { get; }
        }
        /*public class ElementNameSyntax : SingleTokenSyntax {
                public ElementNameSyntax(Token name) : base(name) {}
        }*/
        public class ElementStartTagSyntax : ElementTagSyntax {
                public ElementStartTagSyntax (Token openTok) : base(openTok) {}
+               public override bool HasClosingToken => Children.LastOrDefault() is SingleTokenSyntax sts && sts.token.GetTokenType() == XmlTokenType.ClosingSign;
+
        }
        public class ElementEndTagSyntax : ElementTagSyntax {
                public ElementEndTagSyntax (Token openTok) : base(openTok) {}
+        public override bool HasClosingToken => Children.LastOrDefault() is SingleTokenSyntax sts && sts.token.GetTokenType() == XmlTokenType.ClosingSign;
        }
 
-       public class EmptyElementSyntax : MultiNodeSyntax {
+       public class EmptyElementSyntax : ElementTagSyntax {
                public EmptyElementSyntax (ElementStartTagSyntax startNode) {
                        foreach (var child in startNode.Children)
                                AddChild(child);
                }
+               public override bool HasClosingToken => Children.LastOrDefault() is SingleTokenSyntax sts && sts.token.GetTokenType() == XmlTokenType.EmptyElementClosing;
         //public override bool IsComplete => base.IsComplete && StartTag != null;
     }
 
        public class ElementSyntax : MultiNodeSyntax {
-
-               public override bool IsComplete => base.IsComplete;// & StartTag.IsComplete & (EndTag != null && EndTag.IsComplete);
-
+               public override bool IsComplete => StartTag != null && EndTag != null && StartTag.IsComplete && EndTag.IsComplete && StartTag.Name == EndTag.Name;
                public ElementSyntax (ElementStartTagSyntax startNode) {
                        AddChild (startNode);
                }
+
+               public ElementStartTagSyntax StartTag => Children.ElementAtOrDefault(0) as ElementStartTagSyntax;
+               public ElementEndTagSyntax EndTag => Children.LastOrDefault() as ElementEndTagSyntax;
        }
        public class AttributeSyntax : MultiNodeSyntax {                        
                //public override bool IsComplete => base.IsComplete & name.HasValue & equal.HasValue & valueTok.HasValue & valueOpen.HasValue & valueClose.HasValue;