/// <summary>Converts a list of LNodes to a single LNode by using the list /// as the argument list in a call to the specified identifier, or, if the /// list contains a single item, by returning that single item.</summary> /// <param name="listIdentifier">Target of the node that is created if <c>list</c> /// does not contain exactly one item. Typical values include "{}" and "#splice".</param> /// <remarks>This is the reverse of the operation performed by <see cref="AsList(LNode,Symbol)"/>.</remarks> public static LNode AsLNode(this RVList<LNode> list, Symbol listIdentifier) { if (list.Count == 1) return list[0]; else { var r = SourceRange.Nowhere; if (list.Count != 0) { r = list[0].Range; r = new SourceRange(r.Source, r.StartIndex, list.Last.Range.EndIndex - r.StartIndex); } return LNode.Call(listIdentifier, list, r); } }
private Maybe <Trivia> CurrentTrivia(out SourceRange range) { var trivia = SortedTrivia.TryGet(NextIndex); if (trivia.HasValue) { range = GetRange(trivia.Value); } else { range = default(SourceRange); } return(trivia); }
/// <summary>Converts a list of LNodes to a single LNode by using the list /// as the argument list in a call to the specified identifier, or, if the /// list contains a single item, by returning that single item.</summary> /// <param name="listIdentifier">Target of the node that is created if <c>list</c> /// does not contain exactly one item. Typical values include "{}" and "#splice".</param> /// <remarks>This is the reverse of the operation performed by <see cref="AsList(LNode,Symbol)"/>.</remarks> public static LNode AsLNode(this RVList <LNode> list, Symbol listIdentifier) { if (list.Count == 1) { return(list[0]); } else { var r = SourceRange.Nowhere; if (list.Count != 0) { r = list[0].Range; r = new SourceRange(r.Source, r.StartIndex, list.Last.Range.EndIndex - r.StartIndex); } return(LNode.Call(listIdentifier, list, r)); } }
/// <summary>Called to transform a trivia token into a trivia attribute.</summary> /// <remarks>If a trivia token is not recognized, null is returned to ignore the trivia.</remarks> protected virtual LNode MakeTriviaAttribute(Token t) { if (t.TypeInt == NewlineTypeInt) { return(_trivia_newline); } else { Symbol commentType = null; UString text; if (t.Value == null || t.Value == WhitespaceTag.Value) { text = SourceFile.Text.Slice(t.StartIndex, t.Length); } else { text = t.Value is UString ? ((UString)t.Value) : t.Value.ToString(); } if (MLCommentPrefix != null && text.StartsWith(MLCommentPrefix)) { commentType = S.TriviaMLComment; text = text.Substring(MLCommentPrefix.Length); if (text.EndsWith(MLCommentSuffix)) { text = text.Left(text.Length - MLCommentSuffix.Length); } } else if (SLCommentPrefix != null && text.StartsWith(SLCommentPrefix)) { commentType = S.TriviaSLComment; text = text.Substring(SLCommentPrefix.Length); if (SLCommentSuffix != null && text.EndsWith(SLCommentSuffix)) { text = text.Left(text.Length - SLCommentSuffix.Length); } } if (commentType == null) { return(null); } return(LNode.Trivia(commentType, text.ToString(), SourceRange.New(SourceFile, t))); } }
public StdSimpleCallNodeWithAttrs(RVList <LNode> attrs, Symbol name, RVList <LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(name, args, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
public StdSimpleCallNode(Symbol name, RVList <LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(args, range, style) { _name = name ?? GSymbol.Empty; DetectTargetRange(); }
public StdLiteralNodeWithAttrs(RVList <LNode> attrs, object value, SourceRange range, NodeStyle style = NodeStyle.Default) : base(value, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
public StdTriviaNode(Symbol name, object value, SourceRange range, NodeStyle style = NodeStyle.Default) : base(range, style) { _name = name ?? GSymbol.Empty; _tokenValue = value; }
private Maybe <Trivia> AdvanceTrivia(out SourceRange range) { ++NextIndex; return(CurrentTrivia(out range)); }
private void InjectTriviaInChildren(LNode parent, out SourceRange triviaRange, out Maybe <Trivia> trivia, int indexInParent, ref LNode node) { // Current trivia's range is within node's range: Apply it to // the node's children, if any. First gather list of children // and sort by source-code order, if necessary: int min = node.Min; InternalList <Pair <LNode, int> > children = InternalList <Pair <LNode, int> > .Empty; children.Resize(node.Max - min + 1); bool inOrder = true; int start, prevStart = int.MinValue; for (int i = 0; i < children.Count; i++, prevStart = start) { children[i] = Pair.Create(node[i + min], i + min); start = children[i].A.Range.StartIndex; if (prevStart > start) { inOrder = false; } } if (!inOrder) { children.Sort((a, b) => a.Item1.Range.StartIndex.CompareTo(b.Item1.Range.StartIndex)); } // Call ourself recursively to apply trivia to children. Usually, // newChildren is the same length as children, but it may have extra // trivia attributes added. InternalList <Pair <LNode, int> > newChildren = new InternalList <Pair <LNode, int> >(children.Count); var output = RunCore(children.GetEnumerator(), node); bool changed = false; while (output.MoveNext()) { var @new = output.Current; newChildren.Add(@new); if (@new.Item1 != children[@new.Item2 - min].Item1) { changed = true; } } // At the end, gather up any remaining trivia InternalList <Trivia> triviaList = InternalList <Trivia> .Empty; trivia = CurrentTrivia(out triviaRange); while (trivia.HasValue && triviaRange.EndIndex <= node.Range.EndIndex) { triviaList.Add(trivia.Value); trivia = AdvanceTrivia(out triviaRange); changed = true; } if (changed) { // If this is a call, attach any remaining trivia to the last child. if (node.IsCall && !triviaList.IsEmpty) { int i = newChildren.Count - 1; var last = newChildren.InternalArray[i]; newChildren.InternalArray[i].A = AttachTriviaTo(last.A, triviaList, TriviaLocation.TrailingExtra, node, last.B) ?? last.A; } // Put the children back in their "conceptual" order if (!inOrder) { newChildren.StableSort((a, b) => a.Item2.CompareTo(b.Item2)); } // Update node's attributes, if any int numAttrs = newChildren.TakeWhile(p => p.B < -1).Count(); if (numAttrs > 0) { var attrs = LNode.List(newChildren.Slice(0, numAttrs).SelectArray(p => p.A)); node = node.WithAttrs(attrs); } if (node.IsCall) { Debug.Assert(newChildren[numAttrs].B == -1); var newArgs = newChildren.Slice(numAttrs + 1).SelectArray(p => p.A); node = node.With(newChildren[numAttrs].A, LNode.List(newArgs)); } else if (!triviaList.IsEmpty) { // If current node is not a call, attach any remaining trivia to it. node = AttachTriviaTo(node, triviaList, TriviaLocation.Ambiguous, parent, indexInParent); } } }
public bool Contains(SourceRange inner) { return Source == inner.Source && StartIndex <= inner.StartIndex && EndIndex >= inner.EndIndex; }
public StdSimpleCallNodeWithAttrs(RVList<LNode> attrs, Symbol name, RVList<LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(name, args, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
public StdLiteralNodeWithAttrs(VList<LNode> attrs, object value, SourceRange range, NodeStyle style = NodeStyle.Default) : base(value, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
public StdLiteralNode(object value, SourceRange range, NodeStyle style = NodeStyle.Default) : base(range, style) { _value = value; }
public StdTriviaNode(Symbol name, object value, SourceRange range, NodeStyle style = NodeStyle.Default) : base(name, range, style) { _value = value; }
private void InjectTriviaInChildren(LNode parent, out SourceRange triviaRange, out Maybe <Trivia> trivia, int indexInParent, ref LNode node) { // Current trivia's range is within node's range: Apply it to // the node's children, if any. First gather list of children // and sort by source-code order, if necessary: int min = node.Min; InternalList <Pair <LNode, int> > children = InternalList <Pair <LNode, int> > .Empty; children.Resize(node.Max - min + 1); bool inOrder = true; int start, prevStart = int.MinValue; for (int i = 0; i < children.Count; i++, prevStart = start) { children[i] = Pair.Create(node[i + min], i + min); start = children[i].A.Range.StartIndex; if (prevStart > start) { inOrder = false; } } if (!inOrder) { children.Sort((a, b) => a.Item1.Range.StartIndex.CompareTo(b.Item1.Range.StartIndex)); } // Call ourself recursively to apply trivia to children. Usually, // newChildren is the same length as children, but it may have extra // trivia attributes added. InternalList <Pair <LNode, int> > newChildren = new InternalList <Pair <LNode, int> >(children.Count); var output = RunCore(children.GetEnumerator(), node); bool changed = false; while (output.MoveNext()) { var @new = output.Current; newChildren.Add(@new); if (@new.Item1 != children[@new.Item2 - min].Item1) { changed = true; } } // At the end, gather up any remaining trivia in the node's range that wasn't // associated with a child. // // A newline is treated specially here, because sometimes (e.g. in LES3 token // lists) a newline can be reified into its own node but also exist in the trivia // list. In this case, node will be something like `'\n` when triviaRange equals // node.Range. So let's say the node stream is something like Ann, `'\n`, Bob. If // we attach the newline to the `'\n` node as usual (using the // TriviaLocation.Ambiguous attachment mode, since the newline is neither leading // nor trailing), the output node list will be something rather complicated: // Ann, @`%appendStatement` @(`%trailing`(`%newline`)) `'\n`, @`%appendStatement` Bob // If we ignore the newline temporarily so that it gets treated as leading trivia // of Bob instead, we get simpler output: // Ann, @`%appendStatement` `'\n`, Bob InternalList <Trivia> triviaList = InternalList <Trivia> .Empty; trivia = CurrentTrivia(out triviaRange); while (trivia.HasValue && triviaRange.EndIndex <= node.Range.EndIndex && !(IsNewline(trivia.Value) && triviaRange == node.Range)) { triviaList.Add(trivia.Value); trivia = AdvanceTrivia(out triviaRange); changed = true; } if (changed) { // If this is a call, attach any remaining trivia to the last child. if (node.IsCall && !triviaList.IsEmpty) { int i = newChildren.Count - 1; var last = newChildren.InternalArray[i]; newChildren.InternalArray[i].A = AttachTriviaTo(last.A, triviaList, TriviaLocation.TrailingExtra, node, last.B) ?? last.A; } // Put the children back in their "conceptual" order if (!inOrder) { newChildren.StableSort((a, b) => a.Item2.CompareTo(b.Item2)); } // Update node's attributes, if any int numAttrs = newChildren.TakeWhile(p => p.B < -1).Count(); if (numAttrs > 0) { var attrs = LNode.List(newChildren.Slice(0, numAttrs).SelectArray(p => p.A)); node = node.WithAttrs(attrs); } if (node.IsCall) { Debug.Assert(newChildren[numAttrs].B == -1); var newArgs = newChildren.Slice(numAttrs + 1).SelectArray(p => p.A); node = node.With(newChildren[numAttrs].A, LNode.List(newArgs)); } else if (!triviaList.IsEmpty) { // If current node is not a call, attach any remaining trivia to it. node = AttachTriviaTo(node, triviaList, TriviaLocation.Ambiguous, parent, indexInParent); } } }
public StdSimpleCallNode(Symbol name, VList<LNode> args, SourceRange range, int targetStart, int targetEnd, NodeStyle style = NodeStyle.Default) : base(args, range, style) { _name = name ?? GSymbol.Empty; _targetOffs = ClipUShort(targetStart - RAS.StartIndex); _targetLen = ClipUShort(targetEnd - targetStart); }
public StdComplexCallNode(LNode target, RVList <LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(args, range, style) { CheckParam.IsNotNull("target", target); _target = target; }
public StdCallNode(VList<LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(range, style) { _args = args; NoNulls(args, "Args"); }
/// <summary>Returns the same node with a parentheses attribute added.</summary> /// <remarks>The node's range is changed to the provided <see cref="SourceRange"/>.</remarks> public static LNode InParens(this LNode node, SourceRange range) { return(node.WithRange(range).PlusAttrBefore(LNode.Id(CodeSymbols.TriviaInParens))); }
protected LiteralNode(SourceRange range, NodeStyle style) : base(range, style) { }
public StdSimpleCallNode(Symbol name, VList<LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(args, range, style) { _name = name ?? GSymbol.Empty; DetectTargetRange(); }
protected CallNode(SourceRange range, NodeStyle style) : base(range, style) { }
public StdSimpleCallNode(Loyc.Syntax.Lexing.Token targetToken, VList<LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(args, range, style) { _name = (Symbol)(targetToken.Value ?? GSymbol.Empty); _targetOffs = ClipUShort(targetToken.StartIndex - RAS.StartIndex); _targetLen = ClipUShort(targetToken.Length); }
public StdIdNode(Symbol name, SourceRange range, NodeStyle style = NodeStyle.Default) : base(range, style) { if ((_name = name) == null) throw new ArgumentException("Cannot set IdNode.Name to null."); }
public StdSimpleCallNodeWithAttrs(VList<LNode> attrs, Loyc.Syntax.Lexing.Token targetToken, VList<LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(targetToken, args, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
/// <summary>Returns the same node with a parentheses attribute added.</summary> /// <remarks>The node's range is changed to the provided <see cref="SourceRange"/> /// and the original range of the node is assigned to the parentheses attribute.</remarks> public static LNode InParens(this LNode node, SourceRange range) { return node.WithRange(range).PlusAttrBefore(LNode.Id(CodeSymbols.TriviaInParens)); }
public StdComplexCallNode(LNode target, VList<LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(args, range, style) { CheckParam.IsNotNull("target", target); _target = target; }
public StdComplexCallNodeWithAttrs(VList<LNode> attrs, LNode target, VList<LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(target, args, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
public StdCallNode(RVList <LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(range, style) { _args = args; NoNulls(args, "Args"); }
public StdIdNodeWithAttrs(VList<LNode> attrs, Symbol name, SourceRange range, NodeStyle style = NodeStyle.Default) : base(name, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
public StdSimpleCallNode(Loyc.Syntax.Lexing.Token targetToken, RVList <LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(args, range, style) { _name = (Symbol)(targetToken.Value ?? GSymbol.Empty); _targetOffs = ClipUShort(targetToken.StartIndex - RAS.StartIndex); _targetLen = ClipUShort(targetToken.Length); }
public StdSimpleCallNodeWithAttrs(RVList <LNode> attrs, Loyc.Syntax.Lexing.Token targetToken, RVList <LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(targetToken, args, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
void MissingEndMarker(LNode previousExpr, TokenType endMarker) { var location = new SourceRange(SourceFile, LT(-1).EndIndex + 1); ErrorSink.Write(Severity.Error, location, "Expected '{0}'", endMarker == TT.Comma ? ',' : ';'); }
public StdComplexCallNodeWithAttrs(RVList <LNode> attrs, LNode target, RVList <LNode> args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(target, args, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
public void CheckForSpaceAtEndOfAttribute() { if (LT0.StartIndex == LT(-1).EndIndex) { var location = new SourceRange(SourceFile, LT0.StartIndex); ErrorSink.Write(Severity.Error, location, "Expected space after attribute"); } }
public StdIdNodeWithAttrs(LNodeList attrs, Symbol name, SourceRange range, NodeStyle style = NodeStyle.Default) : base(name, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }
public bool Contains(SourceRange inner) { return(Source == inner.Source && StartIndex <= inner.StartIndex && EndIndex >= inner.EndIndex); }