diff --git a/lib/api/dsl.js b/lib/api/dsl.js index 8cab48e..a5994f0 100644 --- a/lib/api/dsl.js +++ b/lib/api/dsl.js @@ -90,6 +90,7 @@ function alias(rule, value) { result.named = true; result.value = value.symbol.name; return result; + case SymbolRule: case Object: if (typeof value.type === 'string' && value.type === 'SYMBOL') { result.named = true; @@ -129,11 +130,25 @@ function string(value) { }; } +class SymbolRule { + constructor (name) { + this.type = 'SYMBOL'; + this.name = name; + } + + exclude (...tokens) { + return choice( + this, + ...tokens.map(token => ({ + type: 'EXCLUDE', + content: normalize(token) + })) + ); + } +} + function sym(name) { - return { - type: "SYMBOL", - name: name - }; + return new SymbolRule(name); } function token(value) { @@ -174,7 +189,7 @@ function normalize(value) { if (typeof value.type === 'string') { return value; } else { - throw new TypeError("Invalid rule: " + value.toString()); + throw new TypeError("Invalid rule: " + JSON.stringify(value)) } } } @@ -198,7 +213,7 @@ function grammar(baseGrammar, options) { throw new Error("Grammar's 'externals' property must be a function."); } - const externalsRuleBuilder = new RuleBuilder() + const externalsRuleBuilder = new RuleBuilder(sym, null) const externalRules = options.externals.call(externalsRuleBuilder, externalsRuleBuilder, baseGrammar.externals); if (!Array.isArray(externalRules)) { @@ -221,7 +236,7 @@ function grammar(baseGrammar, options) { } } - const ruleBuilder = new RuleBuilder(rulesSet); + const ruleBuilder = new RuleBuilder(sym, rulesSet); const name = options.name; if (typeof name !== "string") { diff --git a/src/rule_builder.cc b/src/rule_builder.cc index 6eaacca..e26c656 100644 --- a/src/rule_builder.cc +++ b/src/rule_builder.cc @@ -10,16 +10,12 @@ using namespace v8; Nan::Persistent constructor; -Local build_symbol(Local name) { - auto result = Nan::New(); - result->Set(Nan::New("type").ToLocalChecked(), Nan::New("SYMBOL").ToLocalChecked()); - result->Set(Nan::New("name").ToLocalChecked(), name); - return result; -} - static void GetProperty(Local property, const Nan::PropertyCallbackInfo &info) { - Local rules = info.This()->GetInternalField(0); - Local symbol = build_symbol(property); + Local symbol_constructor = info.This()->GetInternalField(0); + Local rules = info.This()->GetInternalField(1); + + Local argv = {property}; + Local symbol = Local::Cast(symbol_constructor)->Call(Nan::Null(), 1, &argv); if (rules->IsObject()) { Local rules_object = Local::Cast(rules); @@ -39,18 +35,20 @@ static void GetProperty(Local property, const Nan::PropertyCallbackInfo< } static void construct(const Nan::FunctionCallbackInfo &info) { - Local data = Nan::Null(); - if (info.Length() == 1 && info[0]->IsObject()) { - data = info[0]; + if (info.Length() < 2) { + Nan::ThrowTypeError("Must pass RuleBuilder two arguments"); + return; } - info.This()->SetInternalField(0, data); + + info.This()->SetInternalField(0, info[0]); + info.This()->SetInternalField(1, info[1]); } void Init(Handle exports) { Local tpl = Nan::New(construct); tpl->SetClassName(Nan::New("RuleBuilder").ToLocalChecked()); Nan::SetNamedPropertyHandler(tpl->InstanceTemplate(), GetProperty); - tpl->InstanceTemplate()->SetInternalFieldCount(1); + tpl->InstanceTemplate()->SetInternalFieldCount(2); constructor.Reset(tpl->GetFunction()); exports->Set(Nan::New("RuleBuilder").ToLocalChecked(), Nan::New(constructor)); } diff --git a/vendor/tree-sitter b/vendor/tree-sitter index 41df6d9..5c57167 160000 --- a/vendor/tree-sitter +++ b/vendor/tree-sitter @@ -1 +1 @@ -Subproject commit 41df6d94b734a98f77b27794b9289be2391bc29b +Subproject commit 5c57167f82ece51d113060dc40532179f04a4ca1