/// 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));
        }
Exemplo n.º 3
0
        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)));
 }
Exemplo n.º 7
0
 /// 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));
 }