コード例 #1
0
		// This switch follows more or less a DEA to this EBNF
		// COMMAND-EBNF := COMMAND

		// COMMAND      := (!ARGUMENT \s+ (ARGUMENT|\s)*)
		// ARGUMENT     := COMMAND|FREESTRING|QUOTESTRING
		// FREESTRING   := [^)]+
		// QUOTESTRING  := "[<anything but ", \" is ok>]+"

		public static ASTNode ParseCommandRequest(string request)
		{
			ASTCommand root = null;
			var comAst = new Stack<ASTCommand>();
			BuildStatus build = BuildStatus.ParseCommand;
			var strb = new StringBuilder();
			var strPtr = new StringPtr(request);

			while (!strPtr.End)
			{
				ASTCommand buildCom;
				switch (build)
				{
				case BuildStatus.ParseCommand:
					// Got a command
					buildCom = new ASTCommand();
					// Consume CommandChar if left over
					if (strPtr.Char == CommandChar)
						strPtr.Next(CommandChar);

					if (root == null) root = buildCom;
					else comAst.Peek().Parameter.Add(buildCom);
					comAst.Push(buildCom);
					build = BuildStatus.SelectParam;
					break;

				case BuildStatus.SelectParam:
					strPtr.SkipSpace();

					if (strPtr.End)
						build = BuildStatus.End;
					else
					{
						switch (strPtr.Char)
						{
						case '"':
							build = BuildStatus.ParseQuotedString;
							break;
						case '(':
							if (!strPtr.HasNext)
								build = BuildStatus.ParseFreeString;
							else if (strPtr.IsNext(CommandChar))
							{
								strPtr.Next('(');
								build = BuildStatus.ParseCommand;
							}
							else
								build = BuildStatus.ParseFreeString;
							break;
						case ')':
							if (!comAst.Any())
								build = BuildStatus.End;
							else
							{
								comAst.Pop();
								if (!comAst.Any())
									build = BuildStatus.End;
							}
							strPtr.Next();
							break;
						default:
							build = BuildStatus.ParseFreeString;
							break;
						}
					}
					break;

				case BuildStatus.ParseFreeString:
					strb.Clear();

					var valFreeAst = new ASTValue();
					using (strPtr.TrackNode(valFreeAst))
					{
						for (; !strPtr.End; strPtr.Next())
						{
							if ((strPtr.Char == '(' && strPtr.HasNext && strPtr.IsNext(CommandChar))
								|| strPtr.Char == ')'
								|| char.IsWhiteSpace(strPtr.Char))
								break;
							strb.Append(strPtr.Char);
						}
					}
					valFreeAst.Value = strb.ToString();
					buildCom = comAst.Peek();
					buildCom.Parameter.Add(valFreeAst);
					build = BuildStatus.SelectParam;
					break;

				case BuildStatus.ParseQuotedString:
					strb.Clear();

					strPtr.Next('"');

					var valQuoAst = new ASTValue();
					using (strPtr.TrackNode(valQuoAst))
					{
						bool escaped = false;
						for (; !strPtr.End; strPtr.Next())
						{
							if (strPtr.Char == '\\') escaped = true;
							else if (strPtr.Char == '"')
							{
								if (escaped) strb.Length--;
								else { strPtr.Next(); break; }
								escaped = false;
							}
							else escaped = false;
							strb.Append(strPtr.Char);
						}
					}
					valQuoAst.Value = strb.ToString();
					buildCom = comAst.Peek();
					buildCom.Parameter.Add(valQuoAst);
					build = BuildStatus.SelectParam;
					break;

				case BuildStatus.End:
					strPtr.JumpToEnd();
					break;

				default: throw new InvalidOperationException();
				}
			}

			return root;
		}
コード例 #2
0
        // This switch follows more or less a DEA to this EBNF
        // COMMAND-EBNF := COMMAND

        // COMMAND      := (!ARGUMENT \s+ (ARGUMENT|\s)*)
        // ARGUMENT     := COMMAND|FREESTRING|QUOTESTRING
        // FREESTRING   := [^)]+
        // QUOTESTRING  := "[<anything but ", \" is ok>]+"

        public static ASTNode ParseCommandRequest(string request, char commandChar = DefaultCommandChar, char delimeterChar = DefaultDelimeterChar)
        {
            ASTCommand  root   = null;
            var         comAst = new Stack <ASTCommand>();
            BuildStatus build  = BuildStatus.ParseCommand;
            var         strb   = new StringBuilder();
            var         strPtr = new StringPtr(request);

            while (!strPtr.End)
            {
                ASTCommand buildCom;
                switch (build)
                {
                case BuildStatus.ParseCommand:
                    // Got a command
                    buildCom = new ASTCommand();
                    // Consume CommandChar if left over
                    if (strPtr.Char == commandChar)
                    {
                        strPtr.Next(commandChar);
                    }

                    if (root == null)
                    {
                        root = buildCom;
                    }
                    else
                    {
                        comAst.Peek().Parameter.Add(buildCom);
                    }
                    comAst.Push(buildCom);
                    build = BuildStatus.SelectParam;
                    break;

                case BuildStatus.SelectParam:
                    strPtr.SkipChar(delimeterChar);

                    if (strPtr.End)
                    {
                        build = BuildStatus.End;
                    }
                    else
                    {
                        switch (strPtr.Char)
                        {
                        case '"':
                            build = BuildStatus.ParseQuotedString;
                            //goto case BuildStatus.ParseQuotedString;
                            break;

                        case '(':
                            if (!strPtr.HasNext)
                            {
                                build = BuildStatus.ParseFreeString;
                            }
                            else if (strPtr.IsNext(commandChar))
                            {
                                strPtr.Next('(');
                                build = BuildStatus.ParseCommand;
                            }
                            else
                            {
                                build = BuildStatus.ParseFreeString;
                            }
                            break;

                        case ')':
                            if (!comAst.Any())
                            {
                                build = BuildStatus.End;
                            }
                            else
                            {
                                comAst.Pop();
                                if (!comAst.Any())
                                {
                                    build = BuildStatus.End;
                                }
                            }
                            strPtr.Next();
                            break;

                        default:
                            build = BuildStatus.ParseFreeString;
                            break;
                        }
                    }
                    break;

                case BuildStatus.ParseFreeString:
                    strb.Clear();

                    var valFreeAst = new ASTValue();
                    using (strPtr.TrackNode(valFreeAst))
                    {
                        for (; !strPtr.End; strPtr.Next())
                        {
                            if ((strPtr.Char == '(' && strPtr.HasNext && strPtr.IsNext(commandChar)) ||
                                strPtr.Char == ')' ||
                                strPtr.Char == delimeterChar)
                            {
                                break;
                            }
                            strb.Append(strPtr.Char);
                        }
                    }
                    valFreeAst.Value = strb.ToString();
                    buildCom         = comAst.Peek();
                    buildCom.Parameter.Add(valFreeAst);
                    build = BuildStatus.SelectParam;
                    break;

                case BuildStatus.ParseQuotedString:
                    strb.Clear();

                    strPtr.Next('"');

                    var valQuoAst = new ASTValue();
                    using (strPtr.TrackNode(valQuoAst))
                    {
                        bool escaped = false;
                        for (; !strPtr.End; strPtr.Next())
                        {
                            if (strPtr.Char == '\\')
                            {
                                escaped = true;
                            }
                            else if (strPtr.Char == '"')
                            {
                                if (escaped)
                                {
                                    strb.Length--;
                                }
                                else
                                {
                                    strPtr.Next(); break;
                                }
                                escaped = false;
                            }
                            else
                            {
                                escaped = false;
                            }
                            strb.Append(strPtr.Char);
                        }
                    }
                    valQuoAst.Value = strb.ToString();
                    buildCom        = comAst.Peek();
                    buildCom.Parameter.Add(valQuoAst);
                    build = BuildStatus.SelectParam;
                    break;

                case BuildStatus.End:
                    strPtr.JumpToEnd();
                    break;

                default: throw new InvalidOperationException();
                }
            }

            return(root);
        }