1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
use lang:bs:macro;
use lang:bs;
use core:lang;
// Type of the result.
package Value resultType(Value original) {
if (original == Value())
Value(named{Bool});
else
wrapMaybe(original);
}
// Generate a toS function body.
package Function toSFunction(Type type) {
Scope scope = rootScope;
scope.lookup = BSLookup();
BSTreeFn fn(Value(), SStr("toS"), [ValParam(type, "this"), ValParam(named{StrBuf}, "to")], null);
FnBody body(fn, scope);
fn.body = body;
LocalVarAccess me(SrcPos(), body.parameters[0]);
LocalVarAccess to(SrcPos(), body.parameters[1]);
var b = pattern(body) {
${to} << "{\n";
${to}.indent();
${to} << "value: " << ${me}.value << "\n";
${to} << "end: " << ${me}.end << "\n";
${to} << "error: " << ${me}.error << "\n";
${to}.dedent();
${to} << "}";
};
body.add(b);
fn;
}
/**
* Result type from the parsers. Contains information about a parse.
*/
Result : generate(params) {
if (params.count != 1)
return null;
var resType = params[0].asRef(false);
Type t("Result", [resType], TypeFlags:typeClass);
// Data members:
// Parse value, if parse succeeded.
t.add(MemberVar("value", resultType(resType), t));
// Last position successfully parsed.
t.add(MemberVar("end", named{Str:Iter}, t));
// Error message.
t.add(MemberVar("error", named{Maybe<Error>}, t));
// To string function.
t.add(toSFunction(t));
// We know that all of these are default-constructible, so we can generate a default ctor.
t.add(TypeDefaultCtor(t));
t.add(TypeCopyCtor(t));
t.add(TypeAssign(t));
t.add(TypeDeepCopy(t));
t;
}
/**
* Result type from parsers in binary mode.
*/
BinaryResult : generate(params) {
if (params.count != 1)
return null;
var resType = params[0].asRef(false);
Type t("BinaryResult", [resType], TypeFlags:typeClass);
// Data members:
// Parse value, if parse succeeded.
t.add(MemberVar("value", resultType(resType), t));
// Last position parsed successfully.
t.add(MemberVar("end", named{Nat}, t));
// Error message.
t.add(MemberVar("error", named{Maybe<BinaryError>}, t));
// To string function.
t.add(toSFunction(t));
// We know that all of these are default-constructible, so we can generate a default ctor.
t.add(TypeDefaultCtor(t));
t.add(TypeCopyCtor(t));
t.add(TypeAssign(t));
t.add(TypeDeepCopy(t));
t;
}
/**
* Error location for a string parse.
*/
class Error {
// Error message.
Str message;
// Error location.
Str:Iter pos;
// Create.
init(Str message, Str:Iter pos) {
init { message = message; pos = pos; }
}
// To string.
void toS(StrBuf to) {
to << "{\n";
to.indent();
to << "message: " << message << "\n";
to << "pos: " << pos << "\n";
to.dedent();
to << "}";
}
}
/**
* Error location for a binary parse.
*/
class BinaryError {
// Error message.
Str message;
// Error location.
Nat pos;
// Create.
init(Str message, Nat pos) {
init { message = message; pos = pos; }
}
// To string.
void toS(StrBuf to) {
to << "{\n";
to.indent();
to << "message: " << message << "\n";
to << "pos: " << pos << "\n";
to.dedent();
to << "}";
}
}
// Helper to create an appropriate error.
Error createError(Str message, Str:Iter pos) {
Error(message, pos);
}
BinaryError createError(Str message, Nat pos) {
BinaryError(message, pos);
}
|