题目是给定一个字符串, 该字符串是一种简单的类似于Javascript函数调用。
比如 func1(123, 456) 或者 func1(123, 456, func2(78, 'abc'))
要求输出是该字符串的一个解析树。
func1(123, 456) 输出为
func1(123, 456) | ---------123 | ---------456
func1(123, 456, func2(78, 'abc')) 输出为
func1(123, 456, func2(78, 'abc')) | -----------------------------123 | ----------------------------456 | ----------------------------func2(78, 'abc') | --------------78 | --------------'abc'
为了简化题目,假设函数调用肯定是合法的,即函数左右括号肯定匹配,函数参数若是字符串都包括在单引号内,单引号内不存在括号、不存在逗号等等
这里直接给出了一个C#实现。如果有错误或者有更好的算法 请各位支出。
public class TreeNode { public string Function { get; set; } public List<object> Parameters { get; set; } public void Print(int emptyCount = 0) { var length = emptyCount + Function.Length; System.Console.WriteLine(new string(' ', emptyCount) + Function); if (Parameters != null) { foreach (var parameter in Parameters) { if (parameter is TreeNode) { (parameter as TreeNode).Print(length); } else { System.Console.WriteLine(new string(' ', length) + parameter); } } } } }
/// <summary> /// "func1(12, 'abc')" => ["12", "'abc'"] /// "func1(12, 'abc', func2(34, 56))" => ["12", "'abc'", "func2(34, 56)"] /// </summary> public static List<string> ParseFunction(string str) { if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("str"); int leftBracketIndex = str.IndexOf("(", StringComparison.OrdinalIgnoreCase); int rightBracketIndex = str.LastIndexOf(")", StringComparison.OrdinalIgnoreCase); if (leftBracketIndex < 0 || rightBracketIndex < 0) throw new ArgumentException(str + " is not a function call."); string value = str.Substring(leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1).Trim(); List<string> result = new List<string>(); string tmp = ""; int bracketCount = 0; foreach (char c in value) { if (c == '(') { bracketCount++; tmp += c; } else if (c == ')') { bracketCount--; tmp += c; } else if (c == ',') { if (bracketCount == 0) { result.Add(tmp.Trim()); tmp = ""; } else { tmp += c; } } else { tmp += c; } } if (tmp != "") { result.Add(tmp.Trim()); } return result; } public static bool IsFunctionCall(string str) { if (string.IsNullOrEmpty(str)) { return false; } if (str.Trim().First() == '\'' && str.Trim().Last() == '\'') { return false; } int leftBracketIndex = str.IndexOf("(", StringComparison.OrdinalIgnoreCase); int rightBracketIndex = str.LastIndexOf(")", StringComparison.OrdinalIgnoreCase); if (leftBracketIndex < 0 && rightBracketIndex < 0) { return false; } return true; } public static TreeNode ParseFunctionCall(string str) { TreeNode node = new TreeNode() {Function = str}; node.Parameters = new List<object>(); foreach (var param in ParseFunction(str)) { if (IsFunctionCall(param)) { node.Parameters.Add(ParseFunctionCall(param)); } else if(!string.IsNullOrEmpty(param)) { node.Parameters.Add(param); } } return node; }