Пример #1
0
 private static void MapSectionTypeToRowNumbers(
     TokenList tokenList,
     Table table,
     out int rowNoStart,
     out int rowNoSentinel)
 {
     switch (tokenList.Values[tokenList.Index++].Category)
     {
         case TokenCategory.Once:
             rowNoStart = 0;
             rowNoSentinel = 1;
             break;
         case TokenCategory.Each:
             rowNoStart = 0;
             rowNoSentinel = table.NumRows;
             if (rowNoSentinel == 0)
                 throw new Exception("Input is empty, but EACH needs at least one row for processing!");
             break;
         case TokenCategory.EachPlus:
             rowNoStart = 1;
             rowNoSentinel = table.NumRows;
             if (rowNoSentinel == 1)
                 throw new Exception("Input is empty or has only one row, but EACH needs at least two rows for processing!");
             break;
         default:
             throw new Exception("Section token ($ONCE, $EACH, $EACH+) expected");
     }
 }
Пример #2
0
        public string Process(Table table, string pattern, string code)
        {
            var output = new StringBuilder();

            if (table.NumRows == 0)
                return "";

            if (string.IsNullOrWhiteSpace(pattern))
                pattern = "$EACH\r\n$row\r\n";

            var scanner = new Scanner(pattern);
            var tokens = scanner.GetAllTokens();

            // Add EACH as default section token if 'tokens' does not start with any section token
            if (tokens[0].Category != TokenCategory.Each &&
                tokens[0].Category != TokenCategory.EachPlus &&
                tokens[0].Category != TokenCategory.Once)
            {
                tokens.Insert(0, new Token(TokenCategory.Each));
            }

            var tokenList = new TokenList(tokens);
            do
            {
                int rowNoStart;
                int rowNoSentinel;
                MapSectionTypeToRowNumbers(tokenList, table, out rowNoStart, out rowNoSentinel);

                ProcessSection(table, rowNoStart, rowNoSentinel, tokenList, code, output);
            } while (tokenList.Current.Category != TokenCategory.EndOfInput);

            return output.ToString();
        }
Пример #3
0
        public string Process(Table table, string pattern, string code)
        {
            var output = new StringBuilder();

            if (table.NumRows == 0)
            {
                return("");
            }

            if (string.IsNullOrWhiteSpace(pattern))
            {
                pattern = "$EACH\r\n$row\r\n";
            }

            var scanner = new Scanner(pattern);
            var tokens  = scanner.GetAllTokens();

            // Add EACH as default section token if 'tokens' does not start with any section token
            if (tokens[0].Category != TokenCategory.Each &&
                tokens[0].Category != TokenCategory.EachPlus &&
                tokens[0].Category != TokenCategory.Once)
            {
                tokens.Insert(0, new Token(TokenCategory.Each));
            }

            var tokenList = new TokenList(tokens);

            do
            {
                int rowNoStart;
                int rowNoSentinel;
                MapSectionTypeToRowNumbers(tokenList, table, out rowNoStart, out rowNoSentinel);

                ProcessSection(table, rowNoStart, rowNoSentinel, tokenList, code, output);
            } while (tokenList.Current.Category != TokenCategory.EndOfInput);

            return(output.ToString());
        }
Пример #4
0
        private void ProcessSection(Table table, int rowNoStart, int rowNoSentinel, TokenList tokens, string code, StringBuilder output)
        {
            var tokensSectionStartIndex = tokens.Index;

            for (var rowNo = rowNoStart; rowNo < rowNoSentinel; ++rowNo)
            {
                var endOfSection = false;
                tokens.Index = tokensSectionStartIndex; // reset to 1st token in section
                while (true)
                {
                    var token = tokens.Values[tokens.Index++];

                    string value;
                    int    colIndex;
                    switch (token.Category)
                    {
                    case TokenCategory.Text:
                        output.Append(token.Value);
                        break;

                    case TokenCategory.Dollar:
                        output.Append("$");
                        break;

                    case TokenCategory.HeaderIndex:
                        colIndex = int.Parse(token.Value);
                        CheckColIndex(table, colIndex);
                        value = table.RowFields[0][colIndex];
                        output.Append(value);
                        break;

                    case TokenCategory.InvertedHeaderIndex:
                        colIndex = table.NumFields - 1 - int.Parse(token.Value);
                        CheckColIndex(table, colIndex);
                        value = table.RowFields[0][colIndex];
                        output.Append(value);
                        break;

                    case TokenCategory.FieldIndex:
                        colIndex = int.Parse(token.Value);
                        CheckColIndex(table, colIndex);
                        value = table.RowFields[rowNo][colIndex];
                        output.Append(value);
                        break;

                    case TokenCategory.InvertedFieldIndex:
                        colIndex = table.NumFields - 1 - int.Parse(token.Value);
                        CheckColIndex(table, colIndex);
                        value = table.RowFields[rowNo][colIndex];
                        output.Append(value);
                        break;

                    case TokenCategory.Header:
                        output.Append(table.Header);
                        break;

                    case TokenCategory.Row:
                        output.Append(table.Rows[rowNo]);
                        break;

                    case TokenCategory.RowNum:
                        output.Append(rowNo);
                        break;

                    case TokenCategory.RowNumOne:
                        output.Append(rowNo + 1);
                        break;

                    case TokenCategory.NumFields:
                        output.Append(table.NumFields);
                        break;

                    case TokenCategory.NumRows:
                        output.Append(table.NumRows);
                        break;

                    case TokenCategory.MethodCall:
                        var pos        = token.Value.IndexOfAny("([{<".ToCharArray());
                        var methodName = token.Value.Substring(0, pos);
                        var args       = token.Value.Substring(pos + 1, token.Value.Length - pos - 2);

                        // process args
                        var argsOutput  = new StringBuilder();
                        var argsScanner = new Scanner(args);
                        var argsTokens  = new TokenList(argsScanner.GetAllTokens());
                        ProcessSection(table, rowNo, rowNo + 1, argsTokens, "", argsOutput);
                        var encodedArgs = EncodeQuotationMark(argsOutput.ToString());

                        var methodCall = $"{methodName}({encodedArgs})";     // without terminating ";" to signal scripting engine that it should return the value!

                        var result = ScriptCSharpCode(code + methodCall);

                        output.Append(result);
                        break;

                    case TokenCategory.Once:
                    case TokenCategory.Each:
                    case TokenCategory.EachPlus:
                    case TokenCategory.EndOfInput:
                        tokens.Index--;
                        endOfSection = true;
                        break;

                    default:
                        throw new Exception("No code implemented for token.Category=" + token.Category);
                    }

                    if (endOfSection)
                    {
                        break;
                    }
                }
            }
        }
Пример #5
0
        private void ProcessSection(Table table, int rowNoStart, int rowNoSentinel, TokenList tokens, string code, StringBuilder output)
        {
            var tokensSectionStartIndex = tokens.Index;
            for (var rowNo = rowNoStart; rowNo < rowNoSentinel; ++rowNo)
            {
                var endOfSection = false;
                tokens.Index = tokensSectionStartIndex; // reset to 1st token in section 
                while (true)
                {
                    var token = tokens.Values[tokens.Index++];

                    string value;
                    int colIndex;
                    switch (token.Category)
                    {
                        case TokenCategory.Text:
                            output.Append(token.Value);
                            break;

                        case TokenCategory.Dollar:
                            output.Append("$");
                            break;

                        case TokenCategory.HeaderIndex:
                            colIndex = int.Parse(token.Value);
                            CheckColIndex(table, colIndex);
                            value = table.RowFields[0][colIndex];
                            output.Append(value);
                            break;
                        case TokenCategory.InvertedHeaderIndex:
                            colIndex = table.NumFields - 1 - int.Parse(token.Value);
                            CheckColIndex(table, colIndex);
                            value = table.RowFields[0][colIndex];
                            output.Append(value);
                            break;
                        case TokenCategory.FieldIndex:
                            colIndex = int.Parse(token.Value);
                            CheckColIndex(table, colIndex);
                            value = table.RowFields[rowNo][colIndex];
                            output.Append(value);
                            break;
                        case TokenCategory.InvertedFieldIndex:
                            colIndex = table.NumFields - 1 - int.Parse(token.Value);
                            CheckColIndex(table, colIndex);
                            value = table.RowFields[rowNo][colIndex];
                            output.Append(value);
                            break;

                        case TokenCategory.Header:
                            output.Append(table.Header);
                            break;
                        case TokenCategory.Row:
                            output.Append(table.Rows[rowNo]);
                            break;
                        case TokenCategory.RowNum:
                            output.Append(rowNo);
                            break;
                        case TokenCategory.RowNumOne:
                            output.Append(rowNo + 1);
                            break;
                        case TokenCategory.NumFields:
                            output.Append(table.NumFields);
                            break;
                        case TokenCategory.NumRows:
                            output.Append(table.NumRows);
                            break;

                        case TokenCategory.MethodCall:
                            var pos = token.Value.IndexOfAny("([{<".ToCharArray());
                            var methodName = token.Value.Substring(0, pos);
                            var args = token.Value.Substring(pos + 1, token.Value.Length - pos - 2);

                            // process args
                            var argsOutput = new StringBuilder();
                            var argsScanner = new Scanner(args);
                            var argsTokens = new TokenList(argsScanner.GetAllTokens());
                            ProcessSection(table, rowNo, rowNo + 1, argsTokens, "", argsOutput);
                            var encodedArgs = EncodeQuotationMark(argsOutput.ToString());

                            var methodCall = $"{methodName}({encodedArgs})"; // without terminating ";" to signal scripting engine that it should return the value!

                            var result = ScriptCSharpCode(code + methodCall);

                            output.Append(result);
                            break;

                        case TokenCategory.Once:
                        case TokenCategory.Each:
                        case TokenCategory.EachPlus:
                        case TokenCategory.EndOfInput:
                            tokens.Index--;
                            endOfSection = true;
                            break;

                        default:
                            throw new Exception("No code implemented for token.Category=" + token.Category);
                    }

                    if (endOfSection)
                        break;
                }
            }
        }