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(); }
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()); }
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; } } } }
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; } } }
public void FullPatternScannerTest() { var scanner = new Scanner(AllTokenPattern); var tokens = scanner.GetAllTokens(); Assert.NotNull(tokens); //Assert.Equal(_allTokenReference.Count, tokens.Count); for (var i = 0; i < _allTokenReference.Count; ++i) { var token = tokens[i]; Assert.Equal(_allTokenReference[i].Category, token.Category); Assert.Equal(_allTokenReference[i].Value, token.Value); Assert.Equal(_allTokenReference[i].Value, token.Value); } }
public void CopyPatternScannerTest() { var scanner = new Scanner(CopyPattern); var tokens = scanner.GetAllTokens(); Assert.NotNull(tokens); Assert.Equal(7, tokens.Count); Assert.Equal(TokenCategory.FieldIndex, tokens[0].Category); Assert.Equal("0", tokens[0].Value); Assert.Equal(TokenCategory.Text, tokens[1].Category); Assert.Equal(",", tokens[1].Value); Assert.Equal(TokenCategory.FieldIndex, tokens[2].Category); Assert.Equal("1", tokens[2].Value); Assert.Equal(TokenCategory.Text, tokens[3].Category); Assert.Equal(",", tokens[3].Value); Assert.Equal(TokenCategory.FieldIndex, tokens[4].Category); Assert.Equal("2", tokens[4].Value); Assert.Equal(TokenCategory.Text, tokens[5].Category); Assert.Equal("\r\n", tokens[5].Value); Assert.Equal(TokenCategory.EndOfInput, tokens[tokens.Count - 1].Category); }
public void EmptyInputScannerTest() { var scanner = new Scanner(""); var tokens = scanner.GetAllTokens(); Assert.NotNull(tokens); Assert.Equal(1, tokens.Count); Assert.Equal(TokenCategory.EndOfInput, tokens[0].Category); }