/// <summary>Compares the elements of the token tree for equality.</summary> /// <remarks>Because <see cref="LNode"/>s are compared by value and not by /// reference, and LNodes can contain TokenTrees, TokenTrees should also be /// compared by value.</remarks> public bool Equals(TokenTree other) { if (other == null || Count != other.Count) { return(false); } return(this.SequenceEqual(other)); }
/// <summary>Compares the elements of the token tree for equality.</summary> /// <remarks>Because <see cref="LNode"/>s are compared by value and not by /// reference, and LNodes can contain TokenTrees, TokenTrees should also be /// compared by value.</remarks> public bool Equals(TokenTree other) { if (other == null) { return(false); } return(LinqToLists.SequenceEqual <Token>(this, other)); }
private void TestToLNode(Token t, ISourceFile file, string lesString) { LNode n = TokenTree.TokenToLNode(t, file); AreEqual(lesString, Les2LanguageService.Value.Print(n, null, ParsingMode.Expressions)); AreEqual(file, n.Source); AreEqual(t.StartIndex, n.Range.StartIndex); AreEqual((t.Children != null && t.Children.Count > 0 ? t.Children.Last : t).EndIndex, n.Range.EndIndex); }
public void ToBracketsLNodeTests() { var file = EmptySourceFile.Unknown; var child = new TokenTree(file, new[] { new Token((int)TokenKind.Id, 6, 1, NodeStyle.Default, GSymbol.Get("x")) }); TestToLNode(EmptySourceFile.Unknown, new List <Pair <Token, string> >() { P(new Token((int)TokenKind.LParen, 5, 1, 0, child), @"LParen(x)"), P(new Token((int)TokenKind.RParen, 7, 1, 0, null), @"RParen()"), P(new Token((int)TokenKind.LParen, 5, 1, 0, null), @"LParen()"), P(new Token((int)TokenKind.RParen, 7, 1, 0, null), @"RParen()"), P(new Token((int)TokenKind.LBrack, 5, 1, 0, child), @"LBrack(x)"), P(new Token((int)TokenKind.RBrack, 7, 1, 0, null), @"RBrack()"), P(new Token((int)TokenKind.LBrace, 5, 1, 0, child), @"LBrace(x)"), P(new Token((int)TokenKind.RBrace, 7, 1, 0, null), @"RBrace()"), P(new Token((int)TokenKind.Indent, 5, 1, 0, child), @"Indent(x)"), P(new Token((int)TokenKind.Dedent, 7, 1, 0, null), @"Dedent()"), P(new Token((int)TokenKind.LOther, 5, 1, 0, child), @"LOther(x)"), P(new Token((int)TokenKind.ROther, 7, 1, 0, null), @"ROther()"), }); }
void GatherChildren(ref Token openToken) { Debug.Assert(openToken.Value == null); if (openToken.Value != null && openToken.Children != null) { return; // wtf, it's already a tree } TK ott = openToken.Kind; int oldIndentLevel = _source.IndentLevel; TokenTree children = new TokenTree(_source.SourceFile); for (;;) { Token?t = LLNextToken(); // handles LBrace, LParen, LBrack internally if (t == null) { WriteError(openToken.StartIndex, "Reached end-of-file before '{0}' was closed", openToken); break; } TK tt = t.Value.Kind; if (IsOpener(tt)) { var v = t.Value; GatherChildren(ref v); children.Add(v); if (_closer != null && _closerMatched) { children.Add(_closer.Value); _closer = null; } } else if (IsCloser(tt)) { // indent must match dedent, '{' must match '}' (the parser // can complain itself about "(]" and "[)" if it wants; we // allow these to match because some languages might want it.) bool dentMismatch = (ott == TK.Indent) != (tt == TK.Dedent); if (dentMismatch || (ott == TK.LBrace) != (tt == TK.RBrace)) { WriteError(openToken.StartIndex, "Opening '{0}' does not match closing '{1}' on line {2}", openToken.ToString(), t.Value.ToString(), SourceFile.IndexToLine(t.Value.StartIndex).Line); // - If dentMismatch and ott == TK.Indent, do not close. // - If dentMismatch and tt = TK.Dedent, close but do not match. // - If the closer is more indented than the opener, do not close. // - If the closer is less indented than the opener, close but do not match. // - If the closer is the same indentation as the opener, close and match. if (dentMismatch ? tt == TK.Dedent : IndentLevel <= oldIndentLevel) { // close _closer = t.Value; _closerMatched = !dentMismatch && (IndentLevel == oldIndentLevel); break; } else { children.Add(t.Value); // do not close } } else { _closer = t.Value; _closerMatched = true; break; } } else { children.Add(t.Value); } } openToken.Value = children; }
public LNode ToLNode(ISourceFile file) => TokenTree.TokenToLNode(this, file);