예제 #1
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();
        }
예제 #2
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");
     }
 }
예제 #3
0
        static void Main(string[] args)
        {
            try
            {
                if (args.Length != 7)
                    throw new Exception("Usage: TableTweaker.Console <inputFile> <fieldDelimitter> (quotedFields | unquotedFields) <filter> <patternFile> <codeFile> <outputPath>");

                var input = File.ReadAllText(args[0]);
                var fieldDelimiter = string.IsNullOrEmpty(args[1]) ? ',' : args[1][0];
                var quotedFields = args[2] == "quotedFields";
                var filter = string.IsNullOrEmpty(args[3]) ? ".*" : args[2];
                var pattern = string.IsNullOrEmpty(args[4]) ? "" : File.ReadAllText(args[3]);
                var code = string.IsNullOrEmpty(args[5]) ? "" : File.ReadAllText(args[4]);
                var outputPath = args[6];

                var engine = Engine.Instance;
                engine.FieldDelimiter = fieldDelimiter;
                engine.QuotedFields = quotedFields;
                var table = new Table(input, engine.FieldDelimiter, engine.QuotedFields, filter);

                var stopwatch = new Stopwatch();
                stopwatch.Reset();
                stopwatch.Start();
                var output = engine.Process(table, pattern, code).Replace("\r", "");
                stopwatch.Stop();

                File.WriteAllText(outputPath, output);

                var msg = $"{table.NumRows} filtered input rows processed in {stopwatch.ElapsedMilliseconds} ms";
                System.Console.WriteLine(msg);
            }
            catch (Exception ex)
            {
                System.Console.WriteLine("*** ERROR: " + ex);
            }

#if DEBUG
            System.Console.ReadLine();
#endif
        }
예제 #4
0
        private void Process()
        {
            try
            {
                if (!_windowIsInitialized)
                {
                    return; // called during initialization!
                }
                using (new WaitCursor())
                {
                    var filter = Filter;
                    if (string.IsNullOrEmpty(filter))
                    {
                        filter = ".*";
                    }

                    var input = GetText(TbxInput);
                    var table = new Table(input, _engine.FieldDelimiter, _engine.QuotedFields, filter);

                    var pattern = new TextRange(TbxPattern.Document.ContentStart, TbxPattern.Document.ContentEnd).Text;

                    var code = MyCodeEditor.Text;

                    _stopwatch.Reset();
                    _stopwatch.Start();
                    var output = _engine.Process(table, pattern, code).Replace("\r", "");
                    _stopwatch.Stop();

                    SetText(TbxOutput, output);

                    TblMessage.Text =
                        $"{TbxInput.Document.Blocks.Count} unfiltered input rows, {table.NumRows} filtered input rows, {TbxOutput.Document.Blocks.Count} output rows ({_stopwatch.ElapsedMilliseconds} ms)";
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, @"TableTweaker");
            }
        }
        private void Process()
        {
            try
            {
                if (!_windowIsInitialized)
                    return; // called during initialization!

                using (new WaitCursor())
                {
                    var filter = Filter;
                    if (string.IsNullOrEmpty(filter))
                    {
                        filter = ".*";
                    }

                    var input = GetText(TbxInput);
                    var table = new Table(input, _engine.FieldDelimiter, _engine.QuotedFields, filter);

                    var pattern = new TextRange(TbxPattern.Document.ContentStart, TbxPattern.Document.ContentEnd).Text;

                    var code = Editor.Text;

                    _stopwatch.Reset();
                    _stopwatch.Start();
                    var output = _engine.Process(table, pattern, code).Replace("\r", "");
                    _stopwatch.Stop();

                    SetText(TbxOutput, output);

                    TblMessage.Text =
                        $"{TbxInput.Document.Blocks.Count} unfiltered input rows, {table.NumRows} filtered input rows, {TbxOutput.Document.Blocks.Count} output rows ({_stopwatch.ElapsedMilliseconds} ms)";
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, @"TableTweaker");
            }
        }
예제 #6
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;
                }
            }
        }
예제 #7
0
 public void ProcessQuotationMarkEngineTest()
 {
     var engine = Engine.Instance;
     var table = new Table("A\"B", CommaFieldDelimitter, false, "");
     var output = engine.Process(table, "$ToLower(\"$0\")", "public static string ToLower(string s) { return s.ToLower(); }");
     Assert.Equal("a\"b", output);
 }
예제 #8
0
 private static void CheckColIndex(Table table, int colIndex)
 {
     if (colIndex < 0)
     {
         throw new Exception("Column index $i can not be negative!");
     }
     if (colIndex >= table.NumFields)
     {
         throw new Exception(
             $"Column index ${colIndex} is 0-based and cannot be larger than $numFields ({table.NumFields})!");
     }
 }
예제 #9
0
 public void CopyQuotationMarkEngineTest()
 {
     var engine = Engine.Instance;
     var table = new Table("A\"B", CommaFieldDelimitter, false, "");
     var output = engine.Process(table, "$0", MyCode);
     Assert.Equal("A\"B", output);
 }
예제 #10
0
 public void AllTokenPatternEngineTest()
 {
     var engine = Engine.Instance;
     var table = new Table(HeaderAndThreeRowsInput, CommaFieldDelimitter, QuotedFields, "");
     var output = engine.Process(table, AllTokenPattern, MyCode);
     Assert.Equal(HeaderAndThreeRowsAllTokenPatternOutput, output);
 }
예제 #11
0
 public void InvertedCopyPatternEngineTest()
 {
     var engine = Engine.Instance;
     var table = new Table(HeaderAndThreeRowsInput, CommaFieldDelimitter, QuotedFields, "");
     var output = engine.Process(table, InvertedCopyPattern, "");
     Assert.Equal(HeaderAndThreeRowsInput, output);
 }
예제 #12
0
 public void EmptyInputEngineTest()
 {
     var engine = Engine.Instance;
     var input = "\r\n";
     var table = new Table(input, CommaFieldDelimitter, QuotedFields, "");
     var output = engine.Process(table, "", "");
     Assert.Equal(input, output);
 }
예제 #13
0
        public void TableTestWithQuotedFields()
        {
            var table = new Table(HeaderAndThreeRowsInputWithQuotedFields, CommaFieldDelimitter, true, ".*");

            Assert.NotNull(table);
            Assert.Equal(3, table.NumFields);
            Assert.Equal(4, table.NumRows);

            Assert.Equal("Last Name,First Name,Company", table.Header);

            Assert.Equal("Last Name,First Name,Company", table.Rows[0]);
            Assert.Equal("Jobs,Steve,Apple", table.Rows[1]);
            Assert.Equal("Cook,Tim,Apple", table.Rows[2]);
            Assert.Equal("Gates,William \"Bill\",Microsoft", table.Rows[3]);

            Assert.Equal("Last Name", table.HeaderFields[0]);
            Assert.Equal("First Name", table.HeaderFields[1]);
            Assert.Equal("Company", table.HeaderFields[2]);

            Assert.Equal("Last Name", table.RowFields[0][0]);
            Assert.Equal("First Name", table.RowFields[0][1]);
            Assert.Equal("Company", table.RowFields[0][2]);

            Assert.Equal("Jobs", table.RowFields[1][0]);
            Assert.Equal("Steve", table.RowFields[1][1]);
            Assert.Equal("Apple", table.RowFields[1][2]);

            Assert.Equal("Cook", table.RowFields[2][0]);
            Assert.Equal("Tim", table.RowFields[2][1]);
            Assert.Equal("Apple", table.RowFields[2][2]);

            Assert.Equal("Gates", table.RowFields[3][0]);
            Assert.Equal("William \"Bill\"", table.RowFields[3][1]);
            Assert.Equal("Microsoft", table.RowFields[3][2]);
        }