public static bool PeekAndParse(CharStream cs, out FTL.AST.MemberList memberList) { // if next char is not a newline, we can just as well skip already char next = cs.PeekNext(); if (CharStream.IsEOF(next) || !CharStream.IsNL(next)) { memberList = null; return(false); } // let's keep peeking further, requiring our buffer int bufferPos = cs.Position; NewLine.Parse(cs); WhiteSpace.Parse(cs); // we'll always want to rewind no matter what bool isMemberList = Member.Peek(cs); cs.Rewind(bufferPos); if (isMemberList) { memberList = Parse(cs); return(true); } memberList = null; return(false); }
public static FTL.AST.INode Parse(CharStream cs) { FTL.AST.INode expression = Expresson.Parse(cs); int bufferPos = cs.Position; WhiteSpace.Parse(cs); if (cs.PeekNext() != SEPERATOR[0]) { // it's not a select expression, so let's return early cs.Rewind(bufferPos); return(expression); } // it must be a select expression cs.SkipString(SEPERATOR); WhiteSpace.Parse(cs); // we expect now a memberList (REQUIRED) FTL.AST.MemberList memberList = MemberList.Parse(cs); // skip extra new-line in case one is available if (CharStream.IsNL(cs.PeekNext())) { NewLine.Parse(cs); } // return it all return(new FTL.AST.SelectExpression(expression, memberList)); }
public static FTL.AST.MemberList Parse(CharStream cs) { // starts with a newline and optional newline NewLine.Parse(cs); WhiteSpace.Parse(cs); FTL.AST.MemberList memberList = new FTL.AST.MemberList(); // parse first required member, as we always need at least 1 memberList.AddMember(Member.Parse(cs)); char next; int bufferPos; do { next = cs.PeekNext(); if (CharStream.IsEOF(next) || !CharStream.IsNL(next)) { break; } bufferPos = cs.Position; NewLine.Parse(cs); WhiteSpace.Parse(cs); if (!Member.Peek(cs)) { cs.Rewind(bufferPos); break; } memberList.AddMember(Member.Parse(cs)); } while(true); return(memberList); }