if (tokType.HasFlag (TokenType.Punctuation))
return Colors.DarkGrey;
if (tokType.HasFlag (TokenType.WhiteSpace))
- return Colors.Gainsboro;
- if (tokType.HasFlag (TokenType.Trivia))
return Colors.Silver;
+ if (tokType.HasFlag (TokenType.Trivia))
+ return Colors.DimGrey;
if (tokType == TokenType.Keyword)
- return Colors.DarkSlateBlue;
+ return Colors.Blue;
return Colors.Red;
}
public virtual string GetTokenTypeString (TokenType tokenType) => tokenType.ToString();
cancelSource = new CancellationTokenSource();
backgroundCompilationTask = Task.Run(()=>parseAssync(cancelSource.Token));
+ //TODO: to do
+ await backgroundCompilationTask;
//CurrentNode?.ExpandToTheTop();
// 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 Drawing2D;
+
namespace CrowEditBase
{
public class SingleTokenSyntax : SyntaxNode {
public override bool IsSimilar(object other)
{
return other is SingleTokenSyntax sts ?
- sts.Type == Type : other is TokenType tt ? Type == tt : false;
-
+ sts.Type == Type : (int)other == (int)Type;
}
#endregion
+ public static implicit operator TokenType (SingleTokenSyntax sts) => sts == null ? TokenType.Unknown : sts.Type;
}
}
\ No newline at end of file
return null;
}
}
+ public bool NextSiblingIs(TokenType tokType)
+ => NextSibling is SingleTokenSyntax sts && sts.token.Type == tokType;
+ public bool PreviousSiblingIs(TokenType tokType)
+ => PreviousSibling is SingleTokenSyntax sts && sts.token.Type == tokType;
protected Token getTokenByIndex (int idx) => Root.GetTokenByIndex(idx);
");
overlay.DataSource = this;
overlay.Loaded += (sender, arg) => (sender as ListBox).SelectedIndex = 0;
- } else
+ } else {
+ overlay.DataSource = this;
overlay.IsVisible = true;
+ }
overlay.RegisterForLayouting(LayoutingType.Sizing);
}
}
void hideOverlay () {
if (overlay == null)
return;
- lock(App.UpdateMutex)
+ lock(App.UpdateMutex) {
overlay.IsVisible = false;
+ overlay.DataSource = null;
+ }
}
void completeToken () {
disableSuggestions = true;
return;
}
}
-
base.onKeyDown(sender, e);
/*} finally {
Document.ExitReadLock ();
gr.Stroke ();
}
- if (++tokPtr >= sourceDocument.Tokens.Length)
+ if (tokPtr >= sourceDocument.Tokens.Length)
break;
tok = sourceDocument.Tokens[tokPtr];
updateCurrentTokAndNode();
+ hideOverlay();
if (!disableSuggestions &&!disableTextChangedEvent && HasFocus)
tryGetSuggestions ();
return crowType.GetMember (memberName, BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
}*/
- protected override IEnumerable<Suggestion> getElementNameSuggestions(string curName, TextChange change)
+ protected override IEnumerable<Suggestion> getElementNameSuggestions(string curName, TextChange change, int finalPositionOffset = 0)
{
CrowService srv = App.GetService<CrowService>();
if (srv == null || !srv.IsRunning)
widgetTypes = widgetTypes.Where(t=>t.Name.StartsWith(curName, StringComparison.OrdinalIgnoreCase));
curNameLength = curName.Length;
}
- int endPosOffset = change.HasNewText ? -change.ChangedText.Length : 0;
return widgetTypes.Select (t
=> new WidgetSuggestion(t,
- new TextChange(change.Start, change.Length, t.Name + change.ChangedText), endPosOffset));
+ new TextChange(change.Start, change.Length, t.Name + change.ChangedText), finalPositionOffset));
}
- protected override IEnumerable<Suggestion> getAttributeNameSuggestions(string eltName, string curName, TextChange change) {
- int endPosOffset = change.HasNewText ? -1 : 0;
+ protected override IEnumerable<Suggestion> getAttributeNameSuggestions(string eltName, string curName, TextChange change, int finalPositionOffset = 0) {
+ //int endPosOffset = change.HasNewText ? -1 : 0;
var members = App.GetService<CrowService>()?.GetAllCrowTypeMembers(eltName);
if (members != null) {
var suggs = members?.Where(m=>m.MemberType == MemberTypes.Property)?.Select(p
=> new CrowPropertySuggestion(p as PropertyInfo,
- new TextChange(change.Start, change.Length, p.Name + change.ChangedText), endPosOffset));
+ new TextChange(change.Start, change.Length, p.Name + change.ChangedText), finalPositionOffset));
foreach (var tmp in suggs.Where(s=>s.Category == "Divers"))
yield return tmp;
}
}
- protected override IEnumerable<Suggestion> getAttributeValueSuggestions(string eltName, string attribName, string attribValue, TextChange change) {
+ protected override IEnumerable<Suggestion> getAttributeValueSuggestions(string eltName, string attribName, string attribValue, TextChange change, int finalPositionOffset = 0) {
MemberInfo mi = App.GetService<CrowService>()?.GetAllCrowTypeMembers(eltName)?.Where(m=>m.Name.Equals(attribName, StringComparison.Ordinal)).FirstOrDefault();
if (mi is PropertyInfo pi) {
if (pi.Name == "Style")
return App.Styling.Keys
.Where (s => s.StartsWith (attribValue, StringComparison.OrdinalIgnoreCase))
.Select(s=>new Suggestion(s,
- new TextChange(change.Start, change.Length, s + change.ChangedText)));
+ new TextChange(change.Start, change.Length, s + change.ChangedText), finalPositionOffset));
if (pi.PropertyType.IsEnum)
return Enum.GetNames (pi.PropertyType)
.Where (s => s.StartsWith (attribValue, StringComparison.OrdinalIgnoreCase))
.Select(s=>new Suggestion(s,
- new TextChange(change.Start, change.Length, s + change.ChangedText)));
+ new TextChange(change.Start, change.Length, s + change.ChangedText), finalPositionOffset));
if (pi.PropertyType == typeof(bool))
return (new string[] {"true", "false"}).
Where (s => s.StartsWith (attribValue, StringComparison.OrdinalIgnoreCase))
.Select(s=>new Suggestion(s,
- new TextChange(change.Start, change.Length, s + change.ChangedText)));
+ new TextChange(change.Start, change.Length, s + change.ChangedText), finalPositionOffset));
if (pi.PropertyType.Name == "Measure")
return (new string[] {"Stretched", "Fit"}).
Where (s => s.StartsWith (attribValue, StringComparison.OrdinalIgnoreCase))
.Select(s=>new Suggestion(s,
- new TextChange(change.Start, change.Length, s + change.ChangedText)));
+ new TextChange(change.Start, change.Length, s + change.ChangedText), finalPositionOffset));
if (pi.PropertyType.Name == "Fill")
return EnumsNET.Enums.GetValues<Colors> ()
.Where (s => s.ToString().StartsWith (attribValue, StringComparison.OrdinalIgnoreCase))
.Select(c=>new ColorSuggestion(c,
- new TextChange(change.Start, change.Length, c + change.ChangedText)));
+ new TextChange(change.Start, change.Length, c + change.ChangedText), finalPositionOffset));
}
return null;
}
- 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})");
-
+ public override IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode CurrentNode, CharLocation loc) {
IList sugs = base.GetSuggestions (absoluteTextPos, currentTokenIndex, CurrentNode, loc);
if (sugs != null)
return sugs;
}
reader.Read ();
}
+ if (reader.EndOfSpan)//occurs when no closing quote
+ addTok(ref reader, XmlTokenType.AttributeValue);
}
}
VisitLeadingTrivia (token);
Microsoft.CodeAnalysis.Text.TextSpan fs = token.Span;
- /*if (SyntaxFacts.IsLiteralExpression (token.Kind ()))
+ if (SyntaxFacts.IsLiteralExpression (token.Kind ()))
addMultilineToken(token.ToString(), token.Span, (TokenType)token.RawKind);
- else*/
- if (fs.Length == 0)
+ else if (fs.Length == 0)
Debug.WriteLine($"Empty token: {token}");
else {
Microsoft.CodeAnalysis.Text.TextSpan span = token.Span;
using Crow;
using System.Linq;
using System.Diagnostics;
+using System.Xml;
+using System.Text;
namespace CrowEdit.Xml
{
protected override SyntaxAnalyser CreateSyntaxAnalyser() => new XmlSyntaxAnalyser (ImmutableBufferCopy);
public override string GetTokenTypeString (TokenType tokenType) => ((XmlTokenType)tokenType).ToString();
- protected virtual IEnumerable<Suggestion> getElementNameSuggestions(string curName, TextChange change) => null;
- 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;
+ protected virtual IEnumerable<Suggestion> getElementNameSuggestions(string curName, TextChange change, int finalPositionOffset = 0) => null;
+ protected virtual IEnumerable<Suggestion> getAttributeNameSuggestions(string eltName, string attribName, TextChange change, int finalPositionOffset = 0) => null;
+ protected virtual IEnumerable<Suggestion> getAttributeValueSuggestions(string eltName, string attribName, string attribValue, TextChange change, int finalPositionOffset = 0) => null;
public override IList GetSuggestions (int absoluteTextPos, int currentTokenIndex, SyntaxNode CurrentNode, CharLocation loc) {
- Console.WriteLine($"absPos:{absoluteTextPos} tokIdx:{currentTokenIndex} node:{CurrentNode} charLoc:{loc}");
Token tok = GetTokenByIndex(currentTokenIndex);
+ Token nextTok = currentTokenIndex < Tokens.Length - 1 ? GetTokenByIndex(currentTokenIndex + 1) : null;
+ //Console.WriteLine($"absPos:{absoluteTextPos} {tok.GetTokenType()} tokIdx:{currentTokenIndex} node:{CurrentNode} parent:{CurrentNode?.Parent} charLoc:{loc}");
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)){
+ string eltName = sts.AsText();
+ if (!string.IsNullOrEmpty(name) && !string.Equals(name, eltName)){
Suggestion sug = new Suggestion(name);
- if (tk == XmlTokenType.ElementName && name.StartsWith(sts.AsText(), StringComparison.OrdinalIgnoreCase))
+ if (tk == XmlTokenType.ElementName && name.StartsWith(eltName, 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);
return new List<Suggestion>([sug]);
}
}
- } else {
- string txtEnd = ets.HasClosingToken ? "" : ">";
- if (tk == XmlTokenType.ElementOpen) {
- return getElementNameSuggestions("", new TextChange(tok.End, 0, txtEnd)).ToList();
+ } else {//startTag or empty element
+ StringBuilder txtEnd = new StringBuilder(10);
+ int offset = 0;
+ if (nextTok?.GetTokenType() != XmlTokenType.WhiteSpace)
+ txtEnd.Append(" ");
+ if (!ets.HasClosingToken) {
+ txtEnd.Append(">");
+ offset = -1;
}
- if (tk == XmlTokenType.ElementName) {
- return getElementNameSuggestions(sts.AsText(), new TextChange(tok.Start, tok.Length, txtEnd)).ToList();
+ List<Suggestion> sugs;
+ if (tk == XmlTokenType.ElementOpen) {
+ sugs = getElementNameSuggestions("", new TextChange(tok.End, 0, txtEnd.ToString()), offset).ToList();
+ }else if (tk == XmlTokenType.ElementName) {
+ sugs = getElementNameSuggestions(sts.AsText(), new TextChange(tok.Start, tok.Length, txtEnd.ToString()), offset).ToList();
+ } else {
+ return null;
}
- }
- }
- }
- /*
- if (tok.Start != absoluteTextPos //middle of edited tok
- && currentTokenIndex >= CurrentNode?.Root.TokenCount - 1) //occurs when curTok is last tok of text
- {
- return null;
- }
- Token prevTok = GetTokenByIndex(currentTokenIndex-1);
-
- if (CurrentNode is ElementEndTagSyntax eltEndTag) {
- //sug = corresponding eltName
- if (!tok.Is(XmlTokenType.ElementName) &&
- eltEndTag.Parent is ElementSyntax elt &&
- elt.StartTag?.Name != null) {
-
- Suggestion sug = new Suggestion(elt.StartTag.Name);
- string curEndName = null;
- if (prevTok.Is(XmlTokenType.ElementName) && !elt.StartTag.Name.Equals(curEndName, StringComparison.Ordinal)) {
- curEndName = root.GetTokenString(prevTok);
- sug.Change = new TextChange (prevTok.Start, prevTok.Length, sug.Caption);
- } else if (prevTok.Is(XmlTokenType.EndElementOpen)) {
- curEndName = "";
- sug.Change = new TextChange (prevTok.End, 0, sug.Caption);
- } else
- return null;
-
- //if (!tok.Is(XmlTokenType.ClosingSign))
- if (!eltEndTag.close.HasValue)
- sug.Change.ChangedText += ">";
-
- if (elt.StartTag.Name.StartsWith (curEndName, StringComparison.OrdinalIgnoreCase))
- return new List<Suggestion> ([sug]);
- }
- } else if (CurrentNode is ElementStartTagSyntax eltStartTag) {
- if (!tok.Is(XmlTokenType.ElementName)) {
- TextChange change = default;
-
- if (prevTok.Is(XmlTokenType.ElementName))
- change = new TextChange (prevTok.Start, prevTok.Length);
- else if (prevTok.Is(XmlTokenType.ElementOpen))
- change = new TextChange (prevTok.End, 0);
- else if (eltStartTag.name.HasValue) {
- string attribName = "";
- if (prevTok.Type.HasFlag(TokenType.Trivia) ||
- (tok.Type.HasFlag(TokenType.Trivia) && GetTokenByIndex(currentTokenIndex+1).Type.HasFlag(TokenType.Trivia)))//attribute
- change = new TextChange(tok.Start, 0);
- else if (prevTok.Is(XmlTokenType.AttributeName)) {
- change = new TextChange(prevTok.Start, prevTok.Length);
- attribName = prevTok.AsString(source);
- } else
+ if (sugs.Count == 1 && sugs[0].Caption == sts.AsText())
return null;
- if (!tok.Is(XmlTokenType.EqualSign))
- change.ChangedText += "=\"\"";
- return getAttributeNameSuggestions(eltStartTag.Name, attribName, change).ToList();
- } else
- return null;
-
- //if (!tok.Is(XmlTokenType.ClosingSign))
- if (!eltStartTag.close.HasValue)
- change.ChangedText = ">";
-
- return getElementNameSuggestions(eltStartTag.Name, change).ToList();
-
- }
- } else if (CurrentNode is AttributeSyntax attrib &&
- attrib.Parent is ElementStartTagSyntax eltStart &&
- eltStart.name.HasValue) {
-
- if (prevTok.Is(XmlTokenType.AttributeName)) {
- TextChange change = new TextChange(prevTok.Start, prevTok.Length);
- if (!tok.Is(XmlTokenType.EqualSign))
- change.ChangedText += "=\"\"";
- return getAttributeNameSuggestions(eltStart.Name, attrib.Name, change).ToList();
- } else if (attrib.name.HasValue) {
- if (prevTok.Is(XmlTokenType.AttributeValueOpen)) {
- return getAttributeValueSuggestions(eltStart.Name, attrib.Name, "",
- tok.Is(XmlTokenType.AttributeValueClose) ?
- new TextChange(prevTok.End, 0)
- : new TextChange(prevTok.End, 0, "\""))?.ToList();
- } else if (prevTok.Is(XmlTokenType.AttributeValue) && attrib.valueTok.HasValue) {
- return getAttributeValueSuggestions(eltStart.Name, attrib.Name, attrib.Value,
- tok.Is(XmlTokenType.AttributeValueClose) ?
- new TextChange(prevTok.Start, prevTok.Length)
- : new TextChange(tok.Start, tok.Length, "\""))?.ToList();
+ return sugs;
}
+ } else if (CurrentNode.Parent is AttributeSyntax atts) {
- }
-
- *if (tokType == XmlTokenType.AttributeName) {
- if (attrib.ValueToken.HasValue) {
- change = new TextChange (tok.Start, tok.Length, selectedSugg);
- newSelection = new TextSpan(
- attrib.ValueToken.Value.Start + change.CharDiff + 1,
- attrib.ValueToken.Value.End + change.CharDiff - 1
- );
+ if (tokType == XmlTokenType.WhiteSpace) {
+ Console.WriteLine($"*** {tk}");
+ //return getAttributeNameSuggestions(atts.Name, "", new TextChange(tok.End, 0)).ToList();
} else {
- change = new TextChange (tok.Start, tok.Length, selectedSugg + "=\"\"");
- newSelection = TextSpan.FromStartAndLength (tok.Start + selectedSugg.Length + 2);
- }
- } else {
- int offset = 1;
- if (!attrib.valueClose.HasValue) {
- selectedSugg += root.GetTokenStringByIndex(attrib.valueClose.Value);
- offset = 0;
- }
- if (tokType == XmlTokenType.AttributeValueOpen)
- change = new TextChange (tok.End, 0, selectedSugg);
- else if (tokType == XmlTokenType.AttributeValue)
- change = new TextChange (tok.Start, tok.Length, selectedSugg);
- newSelection = TextSpan.FromStartAndLength (change.End2 + offset);
- }*
- }*/
-
- return null;
- }
- /*
- public override bool TryCompleteToken (Suggestion suggestion) {
- newSelection = null;
- change = default;
-
- string selectedSugg = suggestion?.ToString ();
-
- if (selectedSugg == null)
- return false;
-
- XmlTokenType tokType = tok.GetTokenType();
-
- if (tokType.HasFlag(XmlTokenType.WhiteSpace)) {
-
- if (typeof(ElementTagSyntax).IsAssignableFrom(node?.GetType())) {
- ElementTagSyntax ets = node as ElementTagSyntax;
- if (ets.name.HasValue) {
- change = new TextChange (tok.End, 0, selectedSugg + "=\"\"");
- newSelection = TextSpan.FromStartAndLength(change.End2 - 1);
- } else
- change = new TextChange (tok.End, 0, selectedSugg + " ");
- } else {
- change = new TextChange (tok.End, 0, selectedSugg);
- }
- } else if (tokType == XmlTokenType.EndElementOpen) {
- change = new TextChange (tok.End, 0, selectedSugg + ">");
- } else if (tokType == XmlTokenType.ElementName) {
- if (node is ElementEndTagSyntax)
- change = new TextChange (tok.Start, tok.Length, selectedSugg + ">");
- else {
- change = new TextChange (tok.Start, tok.Length, selectedSugg + ">");
- newSelection = TextSpan.FromStartAndLength (change.End2 - 1);
- }
- } else if (node is AttributeSyntax attrib) {
-
- } else if (tokType == XmlTokenType.ElementOpen) {
- change = new TextChange (tok.End, 0, selectedSugg + " ");
- } else
- change = new TextChange (tok.Start, tok.Length, selectedSugg);
-
- return true;
-
+ if (atts.Parent is ElementTagSyntax et) {
+ if (tokType == XmlTokenType.AttributeName) {
+ string txtEnd = sts.NextSiblingIs(XmlTokenType.EqualSign) ? "" : "=\"\"";
+ List<Suggestion> sugs = getAttributeNameSuggestions(et.Name, atts.Name, new TextChange(tok.Start, tok.Length, txtEnd), txtEnd.Length > 0 ? -1 : 0).ToList();
+ if (sugs.Count == 0 || (sugs.Count == 1 && sugs[0].Caption == sts.AsText()))
+ return null;
- if (tok.GetTokenType() == XmlTokenType.ElementOpen ||
- tok.GetTokenType() == XmlTokenType.WhiteSpace ||
- tok.GetTokenType() == XmlTokenType.AttributeValueOpen) {
- change = new TextChange (tok.End, 0, selectedSugg);
- return true;
- }
- if (tok.GetTokenType() == XmlTokenType.AttributeName && CurrentNode is AttributeSyntax attrib) {
- if (attrib.ValueToken.HasValue) {
- change = new TextChange (tok.Start, tok.Length, selectedSugg);
- newSelection = new TextSpan(
- attrib.ValueToken.Value.Start + change.CharDiff + 1,
- attrib.ValueToken.Value.End + change.CharDiff - 1
- );
- } else {
- change = new TextChange (tok.Start, tok.Length, selectedSugg + "=\"\"");
- newSelection = TextSpan.FromStartAndLength (tok.Start + selectedSugg.Length + 2);
+ return sugs;
+ } else if (atts.HasName) {
+ if(tokType == XmlTokenType.AttributeValueOpen) {
+ return getAttributeValueSuggestions(et.Name, atts.Name, "", new TextChange(tok.End, 0))?.ToList();
+ } else if (tokType == XmlTokenType.AttributeValue) {
+ return getAttributeValueSuggestions(et.Name, atts.Name, CurrentNode.AsText(), new TextChange(tok.Start, tok.Length))?.ToList();
+ }
+ }
+ } else {
+ System.Diagnostics.Debugger.Break();
+ }
+ }
}
- return true;
+ } else if (CurrentNode is ElementTagSyntax ts) {
+ string txtEnd = nextTok?.GetTokenType() == XmlTokenType.EqualSign ? "" : "=\"\"";
+ return getAttributeNameSuggestions(ts.Name, "", new TextChange(tok.End, 0, txtEnd), txtEnd.Length > 0 ? -1 : 0).ToList();
}
-
- change = new TextChange (tok.Start, tok.Length, selectedSugg);
- return true;
- }*/
+ return null;
+ }
public override Color GetColorForToken(Token token)
{
TokenType tokType = token.Type;
XmlTokenType xmlTokType = (XmlTokenType)tokType;
- if (xmlTokType.HasFlag (XmlTokenType.Punctuation))
- return Colors.DarkGrey;
- if (tokType.HasFlag (TokenType.WhiteSpace))
- return Colors.Silver;
- if (xmlTokType.HasFlag (XmlTokenType.Trivia))
- return Colors.DimGrey;
- else if (xmlTokType == XmlTokenType.ElementName)
+ if (xmlTokType == XmlTokenType.ElementName)
return Colors.Green;
if (xmlTokType == XmlTokenType.AttributeName)
return Colors.Blue;
return Colors.Black;
if (xmlTokType == XmlTokenType.PI_Target)
return Colors.DarkSlateBlue;
- return Colors.Red;
+ return base.GetColorForToken(token);
}
- //protected bool previousTokHasFlag(XmlTokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
}
}
\ No newline at end of file
tok.Type = (TokenType)type;
}
public static bool Is(this Token tok, XmlTokenType type) => (XmlTokenType)tok.Type == type;
+ public static bool NextSiblingIs(this SyntaxNode sts, XmlTokenType tt) => sts.NextSiblingIs((TokenType)tt);
+ public static bool PreviousSiblingIs(this SyntaxNode sts, XmlTokenType tt) => sts.PreviousSiblingIs((TokenType)tt);
}
public class XmlSyntaxAnalyser : SyntaxAnalyser {
public XmlSyntaxAnalyser (ReadOnlyTextBuffer document) : base (document) {}
break;
case XmlTokenType.BlockCommentStart:
MultiNodeSyntax bc = new CommentTriviaSyntax(true);
- bc.AddChild(new SingleTokenSyntax(Read()));
+ bc.AddChild(new XMLSingleTokenSyntax(Read()));
while(tryPeek(out Token tok)) {
if (tok.Type == TokenType.BlockCommentEnd) {
- bc.AddChild(new SingleTokenSyntax(Read()));
+ bc.AddChild(new XMLSingleTokenSyntax(Read()));
break;
}
if (tok.Type == TokenType.LineBreak) {
return true;
Read();
} else {
- bc.AddChild(new SingleTokenSyntax(Read()));
+ bc.AddChild(new XMLSingleTokenSyntax(Read()));
}
}
currentNode.AddChild(bc);
return !EOF;
}
- bool accept(MultiNodeSyntax node, Enum tokenType) {
- if (EOF)
+ bool accept(MultiNodeSyntax node, Enum tokenType, bool skipTrivia = true, bool skipLineBreaks = true) {
+ if (skipTrivia && !skipTriviaAndComments(node, skipLineBreaks))
return false;
if (Peek().Type == (TokenType)tokenType) {
- node.AddChild(new SingleTokenSyntax(Read()));
+ node.AddChild(new XMLSingleTokenSyntax(Read()));
return true;
}
return false;
}
- public virtual void ProcessAttributeValueSyntax(AttributeSyntax attrib) {
+ /*public virtual void ProcessAttributeValueSyntax(AttributeSyntax attrib) {
//attrib.valueTok = tokIdx - attrib.TokenIndexBase;
- }
+ }*/
AttributeSyntax processNode(AttributeSyntax attrib) {
- if (accept(attrib, XmlTokenType.EqualSign))
- if (accept(attrib, XmlTokenType.AttributeValueOpen))
- if(accept(attrib, XmlTokenType.AttributeValue))
- accept(attrib, XmlTokenType.AttributeValueClose);
+ if (accept(attrib, XmlTokenType.EqualSign, true))
+ if (accept(attrib, XmlTokenType.AttributeValueOpen, true)) {
+ accept(attrib, XmlTokenType.AttributeValue);
+ accept(attrib, XmlTokenType.AttributeValueClose);
+ }
return attrib;
}
ElementEndTagSyntax processNode(ElementEndTagSyntax et) {
if (accept(et, XmlTokenType.ElementName))
- accept(et, XmlTokenType.ClosingSign);
+ accept(et, XmlTokenType.ClosingSign, true);
return et;
}
ProcessingInstructionSyntax processNode(ProcessingInstructionSyntax pi) {
pi.AddChild(new PITargetSyntax(Read()));
while (skipTriviaAndComments(pi, false)) {
if (Peek().Is(XmlTokenType.PI_End)) {
- pi.AddChild(new SingleTokenSyntax(Read()));
+ pi.AddChild(new XMLSingleTokenSyntax(Read()));
break;
}
if (Peek().Is(XmlTokenType.AttributeName))
if (accept (start, XmlTokenType.ClosingSign)) {
elt = processElement(new ElementSyntax(start));
break;
- }
+ }
+ //wouldd be better in tokenizer, and break on unexpected tok
+ if (Peek().Is(XmlTokenType.ElementOpen) || Peek().Is(XmlTokenType.EndElementOpen)) {
+ start.AddChild(new UnexpectedTokenSyntax(Read()));
+ break;
+ }
+
if (Peek().Is(XmlTokenType.AttributeName))
start.AddChild(processNode(new AttributeSyntax(Read())));
else
public class XMLRootSyntax : SyntaxRootNode {
public XMLRootSyntax (ReadOnlyTextBuffer buff, Token[] tokens) : base (buff, tokens) { }
}
+
public class ProcessingInstructionSyntax : MultiNodeSyntax {
// public override bool IsComplete => base.IsComplete & name.HasValue & PIClose.HasValue;
public ProcessingInstructionSyntax (Token openTok){
- AddChild(new SingleTokenSyntax(openTok));
+ AddChild(new XMLSingleTokenSyntax(openTok));
}
}
- public class PITargetSyntax : SingleTokenSyntax {
+ public class PITargetSyntax : XMLSingleTokenSyntax {
// public override bool IsComplete => base.IsComplete & name.HasValue & PIClose.HasValue;
public PITargetSyntax (Token target) : base(target) { }
}
-
+ public class XMLSingleTokenSyntax : SingleTokenSyntax {
+ public XMLSingleTokenSyntax(Token tok) : base(tok) { }
+ public static implicit operator XmlTokenType (XMLSingleTokenSyntax sts) => sts == null ? XmlTokenType.Unknown : (XmlTokenType)sts.Type;
+ }
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));
+ AddChild(new XMLSingleTokenSyntax(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 ElementEndTagSyntax (Token openTok) : base(openTok) {}
public override bool HasClosingToken => Children.LastOrDefault() is SingleTokenSyntax sts && sts.token.GetTokenType() == XmlTokenType.ClosingSign;
}
-
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 HasClosingToken => HasChilds && Children.LastOrDefault().IsSimilar(XmlTokenType.EmptyElementClosing);
//public override bool IsComplete => base.IsComplete && StartTag != null;
}
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;
+ public class AttributeSyntax : MultiNodeSyntax {
+ public override bool IsComplete => HasName && HasEquals;
public AttributeSyntax(Token name) {
- AddChild (new SingleTokenSyntax(name));
+ AddChild (new XMLSingleTokenSyntax(name));
+ }
+ public string Name => Children.FirstOrDefault() is SingleTokenSyntax sts &&
+ sts.token.GetTokenType() == XmlTokenType.AttributeName ? sts.AsText(): "";
+ public bool HasName => HasChilds && Children.First().IsSimilar(XmlTokenType.AttributeName);
+ public bool HasEquals => HasChilds &&
+ ((HasName && Children.First().NextSiblingIs(XmlTokenType.EqualSign)) ||
+ (!HasName && Children.First().IsSimilar(XmlTokenType.EqualSign)));
+
+ }
+ public class AttributeValueSyntax : MultiNodeSyntax {
+ public AttributeValueSyntax(Token openTok) {
+ AddChild(new XMLSingleTokenSyntax(openTok));
}
}
}
\ No newline at end of file
break;
}
}
-
+ addTok (ref reader, XmlTokenType.Unknown);
return Toks.ToArray();
}