public Ast.Resource Parse(TextReader input) { var ps = new FtlParserStream(input); ps.SkipBlankLines(); var entries = new List <Ast.Entry>(); Ast.Comment lastComment = null; while (ps.Current != Eof) { var entry = GetEntryOrJunk(ps); int blankLines = ps.SkipBlankLines(); // Regular Comments require special logic. Comments may be attached to // Messages or Terms if they are followed immediately by them. However // they should parse as standalone when they're followed by Junk. // Consequently, we only attach Comments once we know that the Message // or the Term parsed successfully. if (entry is Ast.Comment comment && blankLines == 0 && ps.Current != Eof) { // Stash the comment and decide what to do with it in the next pass. lastComment = comment; continue; } if (lastComment != null) { if (entry is Ast.MessageTermBase mt) { mt.Comment = lastComment; if (_withSpans) { mt.Span.Start = lastComment.Span.Start; } } else { entries.Add(lastComment); } // In either case, the stashed comment has been dealt with; clear it. lastComment = null; } // No special logic for other types of entries. entries.Add(entry); } var res = new Ast.Resource(entries); if (_withSpans) { res.AddSpan(Position.Start, ps.GetPosition()); } return(res); }
static void SerializeComment(IndentingWriter writer, Ast.Comment comment) { SerializeComment(writer, comment, "#"); }
public Message(Identifier id, Pattern pattern = null, IReadOnlyList <Attribute> attributes = null, Comment comment = null) : base(id, pattern, attributes, comment) { }
public Term(Identifier id, SyntaxNode value, IReadOnlyList <Attribute> attributes, Comment comment = null) : base(id, value, attributes, comment) { Value = value; }