private void HandlePossibleConflict(ref OperatorData prevOpData, Operator <TTerm, TAfterString, TUserState> op, ref Reply <TTerm> reply, CharStream <TUserState> stream) { // "possible" conflict, because it's not a conflict when the // after-string-parser fails without changing the parser state. var state = stream.State; var ok = stream.Skip(op.String); Debug.Assert(ok); var stateTag = stream.StateTag; var asReply = op.AfterStringParser.Invoke(stream); if (asReply.Status == ReplyStatus.Ok) { stream.BacktrackTo(ref state); ReportConflict(ref prevOpData, op, asReply.Result, ref reply, stream); } else if (asReply.Status == ReplyStatus.Error && stateTag == stream.StateTag) { // backtrack and ignore the operator stream.BacktrackTo(ref state); reply.Error = ErrorMessageList.Merge(reply.Error, ExpectedInfixOrPostfixOperator); } else { // report AfterStringParser error instead of conflict reply.Error = asReply.Error; reply.Status = asReply.Status; } }
private string GetDebuggerDisplay() { if (Status == ReplyStatus.Ok) { string result; if (Result == null) { result = typeof(TResult) == typeof(Microsoft.FSharp.Core.Unit) ? "()" : "null"; } else if (typeof(TResult) == typeof(string)) { result = Text.DoubleQuote(Result.ToString()); } else { result = Result.ToString(); } return(Error == null ? "Reply(" + result + ")" : "Reply(Ok, " + result + ", " + ErrorMessageList.GetDebuggerDisplay(Error) + ")"); } else { var status = Status == ReplyStatus.Error ? "Error" : Status == ReplyStatus.FatalError ? "FatalError" : "(ReplyStatus)" + ((int)Status).ToString(); return(Error == null ? "Reply(" + status + ", NoErrorMessages)" : "Reply(" + status + ", " + ErrorMessageList.GetDebuggerDisplay(Error) + ")"); } }
public CompoundError(string labelOfCompound, Position nestedErrorPosition, object nestedErrorUserState, ErrorMessageList nestedErrorMessages) : base(ErrorMessageType.CompoundError) { String = labelOfCompound; NestedErrorPosition = nestedErrorPosition; NestedErrorUserState = nestedErrorUserState; NestedErrorMessages = nestedErrorMessages; }
private bool Remove(OperatorType operatorType, string opString) { var ops = operatorType == OperatorType.Prefix ? LhsOps : RhsOps; int i, j; if (!FindPosition(ops, opString, out i, out j)) { return(false); } var array = ops[i]; var n = array.Length; if (n == 1) { ops[i] = null; } else { var newArray = new Operator <TTerm, TAfterString, TUserState> [n - 1]; if (j != 0) { Array.Copy(array, 0, newArray, 0, j); } if (j + 1 != n) { Array.Copy(array, j + 1, newArray, j, n - j - 1); } ops[i] = newArray; } if (operatorType == OperatorType.Infix) { --InfixOpCount; if (InfixOpCount == 0) { ExpectedInfixOrPostfixOperator = PostfixOpCount == 0 ? null : Errors.ExpectedPostfixOperator; } } else if (operatorType == OperatorType.Postfix) { --PostfixOpCount; if (PostfixOpCount == 0) { ExpectedInfixOrPostfixOperator = InfixOpCount == 0 ? null : Errors.ExpectedInfixOperator; } } else { --PrefixOpCount; } return(true); }
private void HandleMissingTernary2ndStringError(ref OperatorData opData, ref Reply <TTerm> reply, CharStream <TUserState> stream) { var firstStringIndex = opData.IndexToken.GetIndex(stream); var firstStringColumn = firstStringIndex - opData.LineBegin + 1; var firstStringPos = new Position(stream.Name, firstStringIndex, opData.Line, firstStringColumn); var secondStringPos = stream.Position; var error1 = ExpectedInfixOrPostfixOperator; var error2 = MissingTernary2ndStringErrorFormatter.Invoke(Tuple.Create(firstStringPos, secondStringPos, (TernaryOperator <TTerm, TAfterString, TUserState>)opData.Operator, opData.AfterStringValue)); reply.Error = ErrorMessageList.Merge(reply.Error, ErrorMessageList.Merge(error1, error2)); reply.Status = ReplyStatus.Error; }
private void ReportConflict(ref OperatorData prevOpData, Operator <TTerm, TAfterString, TUserState> op, TAfterString afterStringValue, ref Reply <TTerm> reply, CharStream <TUserState> stream) { var prevOpIndex = prevOpData.IndexToken.GetIndex(stream); var prevOpColumn = prevOpIndex - prevOpData.LineBegin + 1; var prevOpPos = new Position(stream.Name, prevOpIndex, prevOpData.Line, prevOpColumn); var error = _OperatorConflictErrorFormatter.Invoke( Tuple.Create(prevOpPos, prevOpData.Operator, prevOpData.AfterStringValue), Tuple.Create(stream.Position, op, afterStringValue)); reply.Error = ErrorMessageList.Merge(reply.Error, error); reply.Status = ReplyStatus.Error; }
public override Reply <TResult> Invoke(CharStream <TUserState> stream) { var tag = stream.StateTag; var eReply = EndParser.Invoke(stream); if (eReply.Status == ReplyStatus.Error && tag == stream.StateTag) { var reply = CharParser1.Invoke(stream); if (reply.Status == ReplyStatus.Ok) { return(ParseRestOfString(stream, reply.Result, reply.Error)); } else { var error = tag == stream.StateTag ? ErrorMessageList.Merge(eReply.Error, reply.Error) : reply.Error; return(new Reply <TResult> { Status = reply.Status, Error = error }); } } else if (eReply.Status == ReplyStatus.Ok) { var result = Mapping.Invoke("", eReply.Result); return(new Reply <TResult> { Status = ReplyStatus.Ok, Result = result, Error = eReply.Error }); } else { return(new Reply <TResult> { Status = eReply.Status, Error = eReply.Error }); } }
ParseExpression(ref OperatorData prevOpData, // prevOpData is passed as ref for performance reasons, but is not mutated ref Reply <TTerm> reply, CharStream <TUserState> stream) { Operator <TTerm, TAfterString, TUserState> op; if (PrefixOpCount != 0 && ((op = PeekOp(stream, LhsOps)) != null)) { op = ParsePrefixOp(ref prevOpData, op, ref reply, stream); // ParsePrefixOp returns ErrorOp when it backtracks and we should try to parse a term if (op == null) { goto Break; } if (op != ErrorOp) { goto CheckNextOp; } } var error = reply.Error; var stateTag = stream.StateTag; reply = TermParser.Invoke(stream); // <-- this is where we parse the terms if (stateTag == stream.StateTag) { error = ErrorMessageList.Merge(error, reply.Error); if (PrefixOpCount != 0) { error = ErrorMessageList.Merge(error, Errors.ExpectedPrefixOperator); } reply.Error = error; } if (reply.Status != ReplyStatus.Ok) { goto ReturnNull; } op = PeekOp(stream, RhsOps); CheckNextOp: if (op != null) { var prevOp = prevOpData.Operator; if (prevOp.Precedence > op.Precedence) { goto Break; } if (prevOp.Precedence < op.Precedence) { goto Continue; } // prevOp.Precedence == op.Precedence if (op.Type == OperatorType.Infix) { var assoc = prevOp.Associativity & op.Associativity; if (assoc == Associativity.Left || prevOp.Type == OperatorType.Prefix) { goto Break; } if (assoc == Associativity.Right) { goto Continue; } } else { if (prevOp.Type == OperatorType.Infix) { goto Continue; } Debug.Assert(prevOp.Type == OperatorType.Prefix && op.Type == OperatorType.Postfix); if ((prevOp.Associativity | op.Associativity) != Associativity.None) { goto Break; } } HandlePossibleConflict(ref prevOpData, op, ref reply, stream); } else { error = ErrorMessageList.Merge(reply.Error, ExpectedInfixOrPostfixOperator); reply.Error = error; } ReturnNull: op = null; Break: return(op); Continue: return(ParseExpressionContinue(ref prevOpData, op, ref reply, stream)); }
public void AddOperator(Operator <TTerm, TAfterString, TUserState> op) { Operator <TTerm, TAfterString, TUserState> oldOp; if (Reserved.TryGetValue(op.String, out oldOp) || (op.IsTernary && Reserved.TryGetValue(op.TernaryRightString, out oldOp))) { ThrowDefinitionConflictException(op, oldOp); } var ops = op.Type == OperatorType.Prefix ? LhsOps : RhsOps; int i, j; if (FindPosition(ops, op.String, out i, out j)) { ThrowDefinitionConflictException(op, ops[i][j]); } if (op.IsTernary) { int i2, j2; // make sure the Ternary2ndString isn't registered as an operator if (FindPosition(LhsOps, op.TernaryRightString, out i2, out j2)) { ThrowDefinitionConflictException(op, LhsOps[i2][j2]); } if (FindPosition(RhsOps, op.TernaryRightString, out i2, out j2)) { ThrowDefinitionConflictException(op, RhsOps[i2][j2]); } Reserved.Add(op.TernaryRightString, op); } var array = ops[i]; if (array == null) { ops[i] = new Operator <TTerm, TAfterString, TUserState>[1] { op }; } else { int n = array.Length; var newArray = new Operator <TTerm, TAfterString, TUserState> [n + 1]; if (j != 0) { Array.Copy(array, 0, newArray, 0, j); } newArray[j] = op; if (j != n) { Array.Copy(array, j, newArray, j + 1, n - j); } ops[i] = newArray; } if (op.Type == OperatorType.Infix) { ++InfixOpCount; if (InfixOpCount == 1) { ExpectedInfixOrPostfixOperator = PostfixOpCount == 0 ? Errors.ExpectedInfixOperator : Errors.ExpectedInfixOrPostfixOperator; } } else if (op.Type == OperatorType.Postfix) { ++PostfixOpCount; if (PostfixOpCount == 1) { ExpectedInfixOrPostfixOperator = InfixOpCount == 0 ? Errors.ExpectedPostfixOperator : Errors.ExpectedInfixOrPostfixOperator; } } else { ++PrefixOpCount; } }
public Reply(ReplyStatus status, ErrorMessageList error) { Status = status; Error = error; Result = default(TResult); }
internal string GetDebuggerDisplay() { switch (Type) { case ErrorMessageType.Expected: return(String == null ? "Expected(null)" : Text.DoubleQuote("Expected(", String, ")")); case ErrorMessageType.ExpectedString: return(String == null ? "ExpectedString(null)" : Text.DoubleQuote("ExpectedString(", String, ")")); case ErrorMessageType.ExpectedCaseInsensitiveString: return(String == null ? "ExpectedCaseInsensitiveString(null)" : Text.DoubleQuote("ExpectedCaseInsensitiveString(", String, ")")); case ErrorMessageType.Unexpected: return(String == null ? "Unexpected(null)" : Text.DoubleQuote("Unexpected(", String, ")")); case ErrorMessageType.UnexpectedString: return(String == null ? "UnexpectedString(null)" : Text.DoubleQuote("UnexpectedString(", String, ")")); case ErrorMessageType.UnexpectedCaseInsensitiveString: return(String == null ? "UnexpectedCaseInsensitiveString(null)" : Text.DoubleQuote("UnexpectedCaseInsensitiveString(", String, ")")); case ErrorMessageType.Message: return(String == null ? "Message(null)" : Text.DoubleQuote("Message(", String, ")")); case ErrorMessageType.NestedError: { var ne = (NestedError)this; var pos = ne.Position == null ? "null" : ne.Position.ToString(); var msgs = ErrorMessageList.GetDebuggerDisplay(ne.Messages); return("NestedError(" + pos + ", ..., " + msgs + ")"); } case ErrorMessageType.CompoundError: { var ce = (CompoundError)this; var label = ce.String == null ? "null" : Text.Escape(ce.String, "", "\"", "\"", "", '"'); var pos = ce.NestedErrorPosition == null ? "" : ce.NestedErrorPosition.ToString(); var msgs = ErrorMessageList.GetDebuggerDisplay(ce.NestedErrorMessages); return("CompoundError(" + label + ", " + pos + ", ..., " + msgs + ")"); } case ErrorMessageType.Other: { var oe = (Other)this; return(oe.Data == null ? "Other(null)" : "Other(" + oe.ToString() + ")"); } default: throw new InvalidOperationException(); } }
public override int Compare(ErrorMessage x, ErrorMessage y) { if (x == null || y == null) { return(x == null && y == null ? 0 : (x == null ? -1 : 1)); } int d = (int)x.Type - (int)y.Type; if (d != 0) { return(d); } var type = x.Type; if (type <= ErrorMessageType.Message) { Debug.Assert(type >= 0); return(String.CompareOrdinal(x.String, y.String)); } else if (type == ErrorMessageType.NestedError) { var ne1 = (NestedError)x; var ne2 = (NestedError)y; var c = Position.Compare(ne1.Position, ne2.Position); if (c != 0) { return(c); } var msgs1 = ErrorMessageList.ToSortedArray(ne1.Messages); var msgs2 = ErrorMessageList.ToSortedArray(ne2.Messages); int n = Math.Min(msgs1.Length, msgs2.Length); for (int i = 0; i < n; ++i) { c = Compare(msgs1[i], msgs2[i]); if (c != 0) { return(c); } } return(msgs1.Length - msgs2.Length); } else if (type == ErrorMessageType.CompoundError) { var c = String.CompareOrdinal(x.String, y.String); if (c != 0) { return(c); } var ce1 = (CompoundError)x; var ce2 = (CompoundError)y; c = Position.Compare(ce1.NestedErrorPosition, ce2.NestedErrorPosition); if (c != 0) { return(c); } var msgs1 = ErrorMessageList.ToSortedArray(ce1.NestedErrorMessages); var msgs2 = ErrorMessageList.ToSortedArray(ce2.NestedErrorMessages); int n = Math.Min(msgs1.Length, msgs2.Length); for (int i = 0; i < n; ++i) { c = Compare(msgs1[i], msgs2[i]); if (c != 0) { return(c); } } return(msgs1.Length - msgs2.Length); } else { Debug.Assert(type == ErrorMessageType.Other); return(0); } }
public NestedError(Position position, object userState, ErrorMessageList messages) : base(ErrorMessageType.NestedError) { Position = position; UserState = userState; Messages = messages; }
public Reply(ReplyStatus status, TResult result, ErrorMessageList error) { Status = status; Error = error; Result = result; }
ParseExpressionContinue(ref OperatorData prevOpData, Operator <TTerm, TAfterString, TUserState> op, ref Reply <TTerm> reply, CharStream <TUserState> stream) { var opData = new OperatorData(); for (;;) { opData.Line = stream.Line; opData.LineBegin = stream.LineBegin; opData.IndexToken = stream.IndexToken; opData.Operator = op; #if DEBUG var ok = stream.Skip(op.String); Debug.Assert(ok); #else stream.Skip((uint)op.String.Length); #endif var stateTag = stream.StateTag; var asReply = op.AfterStringParser.Invoke(stream); if (asReply.Status == ReplyStatus.Ok) { opData.AfterStringValue = asReply.Result; reply.Error = asReply.Error; if (op.Type == OperatorType.Infix) { var result1 = reply.Result; if (!op.IsTernary) { var nextOp = ParseExpression(ref opData, ref reply, stream); if (reply.Status == ReplyStatus.Ok) { reply.Result = op.Mapping2.Invoke(opData.AfterStringValue, result1, reply.Result); } op = nextOp; if (op == null) { break; } goto CheckNextOp; } else { ParseExpression(ref ZeroPrecedenceOperatorData, ref reply, stream); if (reply.Status != ReplyStatus.Ok) { goto ReturnNull; } var result2 = reply.Result; if (stream.Skip(op.TernaryRightString)) { stateTag = stream.StateTag; asReply = op.AfterTernaryRightStringParser.Invoke(stream); if (asReply.Status == ReplyStatus.Ok) { reply.Error = asReply.Error; var nextOp = ParseExpression(ref opData, ref reply, stream); if (reply.Status == ReplyStatus.Ok) { reply.Result = op.Mapping3.Invoke(opData.AfterStringValue, asReply.Result, result1, result2, reply.Result); } op = nextOp; if (op == null) { break; } goto CheckNextOp; } else if (asReply.Status != ReplyStatus.Error || stateTag != stream.StateTag) { reply.Error = asReply.Error; reply.Status = asReply.Status; goto ReturnNull; } else { // backtrack stream.Skip(-op.TernaryRightString.Length); stream.StateTag -= 2; } } HandleMissingTernary2ndStringError(ref opData, ref reply, stream); goto ReturnNull; } } else { Debug.Assert(op.Type == OperatorType.Postfix); reply.Result = op.Mapping1.Invoke(opData.AfterStringValue, reply.Result); var lastOp = op; op = PeekOp(stream, RhsOps); // we check for adjacent postfix operators here ... if (op != null) { if (op.Type == OperatorType.Postfix && lastOp.Precedence <= op.Precedence) { if (lastOp.Precedence < op.Precedence || (lastOp.Associativity | op.Associativity) != Associativity.None) { continue; } // ... so we can report conflicting postfix operators HandlePossibleConflict(ref opData, op, ref reply, stream); goto ReturnNull; } } else { reply.Error = ErrorMessageList.Merge(reply.Error, ExpectedInfixOrPostfixOperator); break; } } CheckNextOp: var prevOp = prevOpData.Operator; if (prevOp.Precedence < op.Precedence) { continue; } if (prevOp.Precedence > op.Precedence) { break; } // prevOp.Precedence == op.Precedence if (op.Type == OperatorType.Infix) { var assoc = prevOp.Associativity & op.Associativity; if (assoc == Associativity.Left || prevOp.Type == OperatorType.Prefix) { break; } if (assoc == Associativity.Right) { continue; } } else // op.OperatorType == OperatorType.Postfix { if (prevOp.Type == OperatorType.Infix) { continue; } Debug.Assert(prevOp.Type == OperatorType.Prefix); if ((prevOp.Associativity | op.Associativity) != Associativity.None) { break; } } HandlePossibleConflict(ref prevOpData, op, ref reply, stream); } else // asReply.Status != ReplyStatus.Ok { if (asReply.Status == ReplyStatus.Error && stateTag == stream.StateTag) { // backtrack stream.Seek(opData.IndexToken); stream.StateTag -= 2; reply.Error = ErrorMessageList.Merge(reply.Error, ExpectedInfixOrPostfixOperator); } else { reply.Error = asReply.Error; reply.Status = asReply.Status; } } ReturnNull: op = null; break; } return(op); }
protected Reply <string> ParseRestOfString(CharStream <TUserState> stream, char firstChar, ErrorMessageList error) { #if LOW_TRUST var sb = new StringBuilder(16); sb.Append(firstChar); #else _16CharBuffer buffer_; // produces more efficient code on .NET than stackalloc char[16] char * buffer = (char *)(&buffer_); buffer[0] = firstChar; char[] chars = null; uint n = 1; #endif for (;;) { var tag = stream.StateTag; var reply = CharParser.Invoke(stream); if (reply.Status == ReplyStatus.Ok) { if (tag == stream.StateTag) { throw Internal.ParserCombinatorInInfiniteLoopHelper.CreateException("manyChars", stream); } error = reply.Error; #if LOW_TRUST sb.Append(reply.Result); #else var i = n % 16; if (i != 0) { buffer[i] = reply.Result; ++n; } else { if (chars == null) { chars = new char[32]; } else if (n == chars.Length) { var newChars = new char[2 * chars.Length]; Array.Copy(chars, newChars, chars.Length); chars = newChars; } for (i = 0; i < 16; ++i) { chars[n - 16 + i] = buffer[i]; } buffer[0] = reply.Result; ++n; } #endif } else if (reply.Status == ReplyStatus.Error && tag == stream.StateTag) { string str; #if LOW_TRUST str = sb.ToString(); #else if (n <= 16) { str = new String(buffer, 0, (int)n); } else { for (uint i = (n - 1) & 0x7ffffff0u; i < n; ++i) { chars[i] = buffer[i % 16]; } str = new string(chars, 0, (int)n); } #endif error = ErrorMessageList.Merge(error, reply.Error); return(new Reply <string> { Status = ReplyStatus.Ok, Result = str, Error = error }); } else { error = tag == stream.StateTag ? ErrorMessageList.Merge(error, reply.Error) : reply.Error; return(new Reply <string> { Status = reply.Status, Error = error }); } } }
public DebugView(ErrorMessageList list) { List = list; }
public Reply(TResult result) { Result = result; Error = null; Status = ReplyStatus.Ok; }