示例#1
0
    internal BuiltinOp GetOp(string name, int p, int flags)
    {
        BuiltinOp op;

        if (builtinops.TryGetValue(name, out op))
        {
            return(op);
        }
        return(builtinops[name] = new BuiltinOp {
            name = name, precedence = p, flags = flags
        });
    }
示例#2
0
    internal Uniques()
    {
        var mis = typeof(Runtime).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public |
                                             BindingFlags.Instance | BindingFlags.Static);

        foreach (var mi in mis)
        {
            var pis = mi.GetParameters();
            Debug.WriteLine("method: " + mi.Name + ":" + pis.Length);
            builtins[mi.Name] = new Builtin {
                name = mi.Name, clrf = mi
            };
        }

        applyop = GetOp("__apply", 1000, 0);
        tupleop = GetOp("__tuple", 0, BuiltinOp.no_precedence);
        listop  = GetOp("__list", 0, BuiltinOp.no_precedence);
    }
示例#3
0
    void Next()
    {
        op = null;     // token is not an operator

        for (;;)
        {
            switch (token = buf[pos++])
            {
            case '\0': pos--; token = 'E'; return;

            case '\n': line++; continue;

            case ' ':
            case '\t':
            case '\r': continue;

            case '(':
            case ')':
            case ',':
            case '`':
            case '[':
            case ']': return;

            case '+': Op("+", 50, BuiltinOp.is_add); return;

            case '-': Op("-", 50, BuiltinOp.unary_and_binary); return;

            case '*': Op("*", 60); return;

            case '/': Op("/", 60); return;

            case '=':
                if (buf[pos] == '=')
                {
                    pos++; Op("==", 40, BuiltinOp.int_result);
                }
                else if (buf[pos] == '>')
                {
                    pos++; Op("=>", 5, BuiltinOp.right_assoc);
                }
                else
                {
                    Op("=", 20, BuiltinOp.right_assoc);
                }

                return;

            case '>':
                if (buf[pos] == '=')
                {
                    pos++; Op(">=", 41, BuiltinOp.int_result);
                }
                else
                {
                    Op(">", 41, BuiltinOp.int_result);
                }
                return;

            case '<':
                if (buf[pos] == '=')
                {
                    pos++; Op("<=", 41, BuiltinOp.int_result);
                }
                else
                {
                    Op("<", 41, BuiltinOp.int_result);
                }
                return;

            case '!':
                if (buf[pos] == '=')
                {
                    pos++; Op("!=", 40, BuiltinOp.int_result);
                }
                else
                {
                    Op("!", 40, BuiltinOp.unary_only | BuiltinOp.int_to_int);
                }
                return;

            case '|':
                if (buf[pos] == '>')
                {
                    pos++; Op("|>", 30);
                }
                else
                {
                    Error("unimplemented operator: |");
                }
                return;

            case ';': Op(";", 10, BuiltinOp.right_assoc); return;

            case '\"':
                attr  = "";
                token = 'S';
                for (; ;)
                {
                    char c = buf[pos];
                    if (c < ' ')
                    {
                        Error("illegal character in string constant: " + (int)c);
                    }
                    pos++;
                    if (c == '\"')
                    {
                        break;
                    }
                    attr += c;
                }
                return;

            default:
            {
                attr = token.ToString();
                if (Char.IsLetter(token) || token == '_')
                {
                    while (Char.IsLetter(buf[pos]) || buf[pos] == '_')
                    {
                        attr += buf[pos++];
                    }
                    token = 'I';
                }
                else if (Char.IsDigit(token))
                {
                    while (Char.IsDigit(buf[pos]))
                    {
                        attr += buf[pos++];
                    }
                    token = 'N';
                    if (buf[pos] == '.')
                    {
                        pos++;
                        attr += '.';
                        while (Char.IsDigit(buf[pos]))
                        {
                            attr += buf[pos++];
                        }
                        token = 'F';
                    }
                }
                else
                {
                    Error("unknown character: " + (token < ' ' ? ((int)token).ToString() : attr));
                }
                return;
            }
            }
        }
    }
示例#4
0
 void Op(string name, int p, int flags = 0)
 {
     token = 'O';
     op    = prog.uniques.GetOp(name, p, flags);
 }
示例#5
0
    Node ParseFactor()
    {
        Node r;

        switch (token)
        {
        case 'N':
            r = new Node(prog.uniques.GetInt(int.Parse(attr)));
            Next();
            return(r);

        case 'F':
            r = new Node(prog.uniques.GetReal(real.Parse(attr)));
            Next();
            return(r);

        case 'S':
            r = new Node(prog.uniques.GetStr(attr));
            Next();
            return(r);

        case '(':
            Next();
            r = ParseExp();
            if (token == ',')
            {
                r = new Node(prog.uniques.tupleop, r);
                do
                {
                    Next();
                    r.Add(ParseExp());
                } while (token == ',');
            }
            Expect(')');
            return(r);

        case '[':
            Next();
            r = new Node(prog.uniques.listop);
            if (token != ']')
            {
                for (; ;)
                {
                    r.Add(ParseExp());
                    if (token == ']')
                    {
                        break;
                    }
                    Expect(',');
                }
            }
            Next();
            return(r);

        case '`':
            Next();
            r = new Node(new FunctionValue {
                name = attr, undeclared = true
            });
            Expect('I');
            return(r);

        case 'I':
            string name = attr;
            r = new Node(new PlaceHolder {
                name = name, undeclared = true
            });
            Next();

            bool isapply;
            if (isapply = token == '!')
            {
                Next();
                r = new Node(prog.uniques.applyop, r);
            }

            if (token == '(')
            {
                Next();

                if (!isapply)
                {
                    Builtin bf;
                    prog.uniques.builtins.TryGetValue(name, out bf);

                    r = new Node(bf ?? (NodeType) new Function {
                        name = name, undeclared = true
                    });
                }

                if (token != ')')
                {
                    for (;;)
                    {
                        r.Add(ParseExp());
                        if (token == ')')
                        {
                            break;
                        }
                        Expect(',');
                    }
                }
                Next();
            }

            return(r);

        default:
            if (op != null)
            {
                if ((op.flags & (BuiltinOp.unary_only | BuiltinOp.unary_and_binary)) == 0)
                {
                    Error(op.name + " cannot be used as a unary operator");
                }

                BuiltinOp sop = op;
                Next();
                // FIXME: set this to whatever minprec the op requires
                return(new Node(sop, ParseExp(100)));
            }

            return(Error("expression expected"));
        }
    }