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 }); }
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); }
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; } } } }
void Op(string name, int p, int flags = 0) { token = 'O'; op = prog.uniques.GetOp(name, p, flags); }
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")); } }