/// Parses an ExprTree into Tru abstract syntax. public static new TruExpr Parse(ExprTree expr) { if (expr is ExprLiteral exprLit) { if (ExprTree.Match("true", exprLit)) { return(new TruBool(true)); } else if (ExprTree.Match("false", exprLit)) { return(new TruBool(false)); } else { return(TruId.Parse(exprLit)); } } else if (expr is ExprList exprList && exprList.list.Length > 0) // cast expr into exprList { if (ExprTree.Match("{lambda {LITERAL ...} ANY}", exprList)) { ExprTree[] parameters = ((ExprList)exprList.list[1]).list; return(new TruLambda( Helpers.ArrayMap(parameters, (p) => TruId.Parse(p).name), // Will throw error if contains an invalid id. TruExpr.Parse(exprList.list[2]) )); } else if (ExprTree.Match("{let {[LITERAL ANY] ...} ANY}", exprList)) { ExprList[] localExpr = Helpers.ArrayMap(((ExprList)exprList.list[1]).list, (x) => (ExprList)x); (string, TruExpr)[] locals = Helpers.ArrayMap(localExpr, // Convert into name, expr tuples.
/// Parses an ExprTree into Tru abstract syntax that can be Executed. public static TruStatement Parse(ExprTree expr) { if (expr is ExprList exprList && exprList.list.Length > 0) // cast expr into exprList { if (ExprTree.Match("{define LITERAL ANY}", exprList)) { return(new TruDef(TruId.Parse(exprList.list[1]).name, TruExpr.Parse(exprList.list[2]))); } else if (ExprTree.Match("{define {LITERAL LITERAL ...} ANY}", exprList)) { ExprTree[] signature = ((ExprList)exprList.list[1]).list; string[] paramaters = new string[signature.Length - 1]; // put all but first element into parameters as strings for (int i = 0; i < paramaters.Length; i++) { paramaters[i] = TruId.Parse(signature[i + 1]).name; } return(new TruDef(TruId.Parse(signature[0]).name, new TruLambda(paramaters, TruExpr.Parse(exprList.list[2])) )); } } // If not a define statement, its an expression. return(TruExpr.Parse(expr)); }
private static bool MatchHelper(ExprTree pattern, ExprTree expr) { if (pattern is ExprLiteral patternLit) { return(patternLit.val == "ANY" || (patternLit.val == "LITERAL" && expr is ExprLiteral) || (patternLit.val == "LIST" && expr is ExprList) || pattern.Equals(expr)); } else if (pattern is ExprList patList && expr is ExprList exprList) { int patI = patList.list.Length - 1, exprI = exprList.list.Length - 1; while (patI >= 0) // Loop through the lists backwards so that ... is visited before what it affects. // If a ... has nothing before it just match it like a normal symbol { if (patList.list[patI].Equals(new ExprLiteral("...")) && patI >= 1) { ExprTree repPattern = patList.list[patI - 1]; int matchCount = 0; for (/*exprI current value*/; exprI >= 0 && MatchHelper(repPattern, exprList.list[exprI]); exprI--) { matchCount++; } patI -= 2; // to prevent ... from eating the first a in {a a ...}, we count repetitions of the pattern in pattern // and make sure we found at least that many. int expectedCount = 0; for (/*patI current value*/; patI >= 0 && patList.list[patI].Equals(repPattern); patI--) { expectedCount++; } if (expectedCount > matchCount) { return(false); } } else { if (exprI < 0 || !MatchHelper(patList.list[patI], exprList.list[exprI])) { return(false); } patI--; exprI--; } } return(patI < 0 && exprI < 0); }
/// Parses a string into a list of TruStatements. public static TruStatement[] ParseAll(string code) { return(Helpers.ArrayMap(ExprTree.ParseAll(code), TruStatement.Parse)); }
/// Parses a string into Tru abstract syntax that can be Executed. public static TruStatement Parse(string code) { return(TruStatement.Parse(ExprTree.Parse(code))); }
/// Parses a string into Tru abstract syntax that can be interpreted. public static new TruExpr Parse(string code) { return(TruExpr.Parse(ExprTree.Parse(code))); }
/// Checks if expr matches pattern, meaning it has the same structure, /// Special tags can be used in the pattern as wildcards: /// ANY : matches any ExprTree /// LITERAL : matches any ExprLiteral /// LIST : matches any ExrList /// ... : Modifies the previous item to match 0 or more repetitions of the previous pattern in a list. public static bool Match(string pattern, ExprTree expr) { return(MatchHelper(Parse(pattern), expr)); }