Ejemplo n.º 1
0
 private static void SetError(int lineIndex, int charIndex, string message, out JsonException exception)
 {
     exception = new JsonException(message, lineIndex, charIndex);
 }
Ejemplo n.º 2
0
        public static JsonObject Parse(string text, out JsonException exception)
        {
            exception = null;
              if (!text.TrimStart().StartsWith("{"))
              {
            exception = new JsonException("JsonNode should start with {", 0, 0);
            return null;
              }
              Stack<string> path = new Stack<string>();
              Stack<JsonObject> nodeStack = new Stack<JsonObject>();
              JsonObject currentNode = null;
              bool inQuats = false;
              bool isEscaped = false;
              string key = null;
              StringBuilder stringBuilder = new StringBuilder();
              int textLineIndex = 0;
              int textCharIndex = 0;
              int keyLineIndex = 0;
              int keyCharIndex = 0;
              int seperatorLineIndex = 0;
              int seperatorCharIndex = 0;
              int charIndex = 0;
              int lineIndex = 0;
              bool needSeperator = false;
              StringBuilder lineBuilder = new StringBuilder();
              for (int index = 0; index < text.Length; index++)
              {
            char c = text[index];
            lineBuilder.Append(c);
            charIndex++;
            if (lineBuilder.Length > 1 & (c == '\n' || c == '\r'))
            {
              lineIndex++;
              lineBuilder.Remove(0, lineBuilder.Length);
              charIndex = 0;
            }
            if (!inQuats && Char.IsWhiteSpace(c))
            {
              continue;
            }
            if (inQuats && (c != '"' || isEscaped))
            {
              if (stringBuilder.Length == 0)
              {
            textLineIndex = lineIndex;
            textCharIndex = charIndex;
              }
              if (c == '\\' && !isEscaped)
              {
            isEscaped = true;
            continue;
              }
              if (isEscaped)
              {
            switch (c)
            {
              case 't':
                stringBuilder.Append('\t');
                break;
              case '"':
                stringBuilder.Append('"');
                break;
              case '\'':
                stringBuilder.Append('\'');
                break;
              case 'r':
                stringBuilder.Append('\r');
                break;
              case 'n':
                stringBuilder.Append('\n');
                break;
              case '\\':
                stringBuilder.Append('\\');
                break;
              default:
                exception = new JsonException("unknown escape charctar \\" + c, lineIndex, charIndex);
                return null;
            }
            isEscaped = false;
            continue;
              }
              stringBuilder.Append(c);
              continue;
            }
            switch (c)
            {
              case '{':
            {
              if (needSeperator)
              {
                SetError(seperatorLineIndex, seperatorCharIndex, "expected comma.", out exception);
                while (nodeStack.Count > 0)
                  currentNode = nodeStack.Pop();
                return currentNode;
              }
              needSeperator = false;
              if (key == null && currentNode == null)
              {
                currentNode = new JsonNode(lineIndex, charIndex);
                nodeStack.Push(currentNode);
                break;
              }
              JsonNode newJsonNode = new JsonNode(lineIndex, charIndex);
              JsonNode parentJsonNode = currentNode as JsonNode;
              if (parentJsonNode != null)
              {
                path.Push(key);
                parentJsonNode.Add(key, newJsonNode, lineIndex, charIndex);
                key = null;
              }
              else
              {
                if (!(currentNode is JsonArray))
                  throw new JsonException("Exspected JsonArray", lineIndex, charIndex);
                path.Push("[" + DeterminArrayIndex(text, index) + "]");
                ((JsonArray)currentNode).Add(newJsonNode);
              }
              nodeStack.Push(currentNode);
              currentNode = newJsonNode;
            }
            break;
              case '}':
            {
              needSeperator = true;
              seperatorCharIndex = charIndex + 1;
              seperatorLineIndex = lineIndex;
              path.Push(key);
              CheckForNumboerAndBool(stringBuilder, currentNode, ref key, textLineIndex, textCharIndex, keyLineIndex, keyCharIndex);
              path.Pop();
              if (currentNode is JsonArray)
              {
                SetError(lineIndex, charIndex, "] expected first.", out exception);
                while (nodeStack.Count > 0)
                  currentNode = nodeStack.Pop();
                return currentNode;
              }
              if (nodeStack.Count == 0)
              {
                SetError(lineIndex, charIndex, "To many }", out exception);
                while (nodeStack.Count > 0)
                  currentNode = nodeStack.Pop();
                return currentNode;
              }
              if (path.Count > 0)
                path.Pop();
              currentNode = nodeStack.Pop();
            }
            break;
              case '[':
            {
              if (needSeperator)
              {
                SetError(seperatorLineIndex, seperatorCharIndex, "expected comma.", out exception);
                while (nodeStack.Count > 0)
                  currentNode = nodeStack.Pop();
                return currentNode;
              }
              needSeperator = false;
              if (key == null && currentNode == null)
              {
                currentNode = new JsonArray(lineIndex, charIndex);
                nodeStack.Push(currentNode);
                break;
              }
              JsonArray newJsonArray = new JsonArray(lineIndex, charIndex);
              JsonNode parentJsonNode = currentNode as JsonNode;
              if (parentJsonNode != null)
              {
                path.Push(key);

                parentJsonNode.Add(key, newJsonArray, lineIndex, charIndex);
                key = null;
              }
              else
              {
                if (!(currentNode is JsonArray))
                  throw new JsonException("Exspected JsonArray", lineIndex, charIndex);
                path.Push("[" + DeterminArrayIndex(text, index) + "]");
                ((JsonArray)currentNode).Add(newJsonArray);
              }
              nodeStack.Push(currentNode);
              currentNode = newJsonArray;
            }
            break;
              case ']':
            {
              needSeperator = true;
              seperatorCharIndex = charIndex + 1;
              seperatorLineIndex = lineIndex;
              path.Push(key);
              CheckForNumboerAndBool(stringBuilder, currentNode, ref key, lineIndex, charIndex, keyLineIndex, keyCharIndex);
              path.Pop();
              if (currentNode is JsonNode)
              {
                SetError(lineIndex, charIndex, "} expected first.", out exception);
                return null;
              }
              if (nodeStack.Count == 0)
              {
                SetError(lineIndex, charIndex, "To many ]", out exception);
                return null;
              }
              path.Pop();
              currentNode = nodeStack.Pop();
            }
            break;
              case ':':
            if (key == null)
            {
              SetError(keyLineIndex, keyCharIndex, "value missing", out exception);
              while (nodeStack.Count > 0)
                currentNode = nodeStack.Pop();
              return currentNode;
            }
            break;
              case '"':
            if (isEscaped)
            {
              stringBuilder.Append("\"");
              isEscaped = false;
              break;
            }
            if (needSeperator)
            {
              SetError(seperatorLineIndex, seperatorCharIndex, "expected comma.", out exception);
              while (nodeStack.Count > 0)
                currentNode = nodeStack.Pop();
              return currentNode;
            }
            if (inQuats)
            {
              inQuats = false;
              JsonNode node = currentNode as JsonNode;
              if (node != null)
              {
                if (key == null)
                {
                  key = stringBuilder.ToString();
                  keyLineIndex = lineIndex;
                  keyCharIndex = charIndex;
                  path.Push(key);

                  path.Pop();
                }
                else
                {
                  path.Push(key);
                  node.Add(key, new JsonValue(stringBuilder.ToString(), textLineIndex, textCharIndex), lineIndex, charIndex);
                  path.Pop();
                  key = null;
                  needSeperator = true;
                  seperatorCharIndex = charIndex + 1;
                  seperatorLineIndex = lineIndex;
                }
              }
              else
              {
                if (!(currentNode is JsonArray))
                  throw new JsonException("Exspected JsonArray", lineIndex, charIndex);
                JsonArray jsonArray = currentNode as JsonArray;
                jsonArray.Add(new JsonValue(stringBuilder.ToString(), textLineIndex, textCharIndex));
              }
              stringBuilder.Remove(0, stringBuilder.Length);
            }
            else
            {
              if (stringBuilder.Length > 0)
              {
                SetError(textLineIndex, textCharIndex, "text in unexpected place", out exception);
                while (nodeStack.Count > 0)
                  currentNode = nodeStack.Pop();
                return currentNode;
              }
              inQuats = true;
            }
            break;
              case '\\':
            if (!inQuats)
            {
              SetError(lineIndex, charIndex, "\\ found in wrong place", out exception);
              while (nodeStack.Count > 0)
                currentNode = nodeStack.Pop();
              return currentNode;
            }
            if (isEscaped)
            {
              stringBuilder.Append("\\");
              isEscaped = false;
            }
            else
              isEscaped = true;
            break;
              case ',':
            {
              if (key == null && !needSeperator && currentNode is JsonNode)
              {
                SetError(lineIndex, charIndex, "extra comma found", out exception);
                while (nodeStack.Count > 0)
                  currentNode = nodeStack.Pop();
                return currentNode;
              }
              needSeperator = false;
              path.Push(key);
              CheckForNumboerAndBool(stringBuilder, currentNode, ref key, lineIndex, charIndex, keyLineIndex, keyCharIndex);
              path.Pop();
            }
            break;
              default:
            isEscaped = false;
            if (needSeperator)
            {
              SetError(seperatorLineIndex, seperatorCharIndex, "expected comma.", out exception);
              while (nodeStack.Count > 0)
                currentNode = nodeStack.Pop();
              return currentNode;
            }
            if (stringBuilder.Length == 0)
            {
              textLineIndex = lineIndex;
              textCharIndex = charIndex;
            }
            stringBuilder.Append(c);
            break;
            }
              }
              if (stringBuilder.Length > 0)
            SetError(textLineIndex, textCharIndex, "text in unexpected place", out exception);
              if (key != null)
            SetError(keyLineIndex, keyCharIndex, "value missing", out exception);
              if (nodeStack.Count > 0)
              {
            SetError(lineBuilder.Length > 0 ? lineIndex : lineIndex - 1, charIndex, currentNode is JsonArray ? "missing ]" : "missing }", out exception);
              }
              while (nodeStack.Count > 0)
            currentNode = nodeStack.Pop();
              return currentNode;
        }