From b1f8ba62022041128de032951ec024b788d9f1a2 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 23 Mar 2015 21:02:40 -0700 Subject: [PATCH] Replace {left,right}_assoc w/ prec, with an associativity argument --- include/tree_sitter/compiler.h | 9 +++-- .../prepare_grammar/expand_tokens_spec.cc | 4 +-- spec/fixtures/grammars/golang.cc | 2 +- spec/fixtures/grammars/helpers.cc | 6 ++-- spec/fixtures/grammars/javascript.cc | 34 +++++++++---------- src/compiler/rules/metadata.h | 7 ++-- src/compiler/rules/rules.cc | 13 +++---- 7 files changed, 37 insertions(+), 38 deletions(-) diff --git a/include/tree_sitter/compiler.h b/include/tree_sitter/compiler.h index b14fc694..71f11e0a 100644 --- a/include/tree_sitter/compiler.h +++ b/include/tree_sitter/compiler.h @@ -14,6 +14,11 @@ namespace rules { class Rule; typedef std::shared_ptr rule_ptr; +enum Associativity { + AssociativityLeft = 1, + AssociativityRight +}; + rule_ptr blank(); rule_ptr choice(const std::vector &); rule_ptr repeat(const rule_ptr &); @@ -22,8 +27,8 @@ rule_ptr sym(const std::string &); rule_ptr pattern(const std::string &); rule_ptr str(const std::string &); rule_ptr err(const rule_ptr &); -rule_ptr left_assoc(int precedence, const rule_ptr &); -rule_ptr right_assoc(int precedence, const rule_ptr &); +rule_ptr prec(int precedence, const rule_ptr &); +rule_ptr prec(int precedence, const rule_ptr &, Associativity); rule_ptr token(const rule_ptr &rule); std::ostream &operator<<(std::ostream &stream, const rules::rule_ptr &rule); diff --git a/spec/compiler/prepare_grammar/expand_tokens_spec.cc b/spec/compiler/prepare_grammar/expand_tokens_spec.cc index 19fcd2f1..ba97d491 100644 --- a/spec/compiler/prepare_grammar/expand_tokens_spec.cc +++ b/spec/compiler/prepare_grammar/expand_tokens_spec.cc @@ -24,7 +24,7 @@ describe("expand_tokens", []() { AssertThat(result.first.rules, Equals(rule_list({ { "rule_A", seq({ i_sym(10), - token(left_assoc(1, seq({ character({ 'x' }), character({ 'y' }), character({ 'z' }) }))), + token(prec(1, seq({ character({ 'x' }), character({ 'y' }), character({ 'z' }) }))), i_sym(11) }) }, }))); }); @@ -38,7 +38,7 @@ describe("expand_tokens", []() { auto result = expand_tokens(grammar); AssertThat(result.first.rules, Equals(rule_list({ - { "rule_A", token(left_assoc(1, seq({ + { "rule_A", token(prec(1, seq({ character({ 945 }), character({ ' ' }), character({ 946 }) }))) } diff --git a/spec/fixtures/grammars/golang.cc b/spec/fixtures/grammars/golang.cc index 2e6d232e..a2ac52bc 100644 --- a/spec/fixtures/grammars/golang.cc +++ b/spec/fixtures/grammars/golang.cc @@ -146,7 +146,7 @@ extern const Grammar golang = Grammar({ infix_op(">=", "expression", 3), infix_op(">", "expression", 3), prefix_op("!", "expression", 4) }) }, - { "_func_signature", left_assoc(10, seq({ + { "_func_signature", prec(10, seq({ in_parens(comma_sep(seq({ comma_sep1(sym("var_name")), sym("type_expression") }))), diff --git a/spec/fixtures/grammars/helpers.cc b/spec/fixtures/grammars/helpers.cc index df258bcf..f70c2471 100644 --- a/spec/fixtures/grammars/helpers.cc +++ b/spec/fixtures/grammars/helpers.cc @@ -29,20 +29,20 @@ rule_ptr in_brackets(rule_ptr rule) { } rule_ptr infix_op(std::string op, std::string rule_name, int precedence) { - return left_assoc(precedence, seq({ + return prec(precedence, seq({ sym(rule_name), str(op), sym(rule_name) })); } rule_ptr prefix_op(std::string op, std::string rule_name, int precedence) { - return right_assoc(precedence, seq({ + return prec(precedence, seq({ str(op), sym(rule_name) })); } rule_ptr postfix_op(std::string op, std::string rule_name, int precedence) { - return left_assoc(precedence, seq({ + return prec(precedence, seq({ sym(rule_name), str(op) })); } diff --git a/spec/fixtures/grammars/javascript.cc b/spec/fixtures/grammars/javascript.cc index 509204c4..3ecd628c 100644 --- a/spec/fixtures/grammars/javascript.cc +++ b/spec/fixtures/grammars/javascript.cc @@ -65,16 +65,16 @@ extern const Grammar javascript = Grammar({ sym("identifier"), sym("var_assignment") }))) })) }, - { "statement_block", left_assoc(PREC_BLOCK, + { "statement_block", prec(PREC_BLOCK, in_braces(err(repeat(sym("statement"))))) }, - { "if_statement", right_assoc(0, seq({ + { "if_statement", prec(0, seq({ str("if"), sym("_paren_expression"), sym("statement"), optional(seq({ str("else"), - sym("statement") })) })) }, + sym("statement") })) }), AssociativityRight) }, { "switch_statement", seq({ str("switch"), @@ -99,7 +99,7 @@ extern const Grammar javascript = Grammar({ str("for"), str("("), optional(str("var")), - left_assoc(PREC_REL, seq({ + prec(PREC_REL, seq({ sym("identifier"), str("in"), sym("expression") })), @@ -215,56 +215,56 @@ extern const Grammar javascript = Grammar({ str(")"), sym("statement_block") }) }, - { "function_call", left_assoc(PREC_CALL, seq({ + { "function_call", prec(PREC_CALL, seq({ sym("expression"), str("("), optional(err(sym("arguments"))), str(")") })) }, { "constructor_call", choice({ - left_assoc(PREC_SHORT_NEW, seq({ + prec(PREC_SHORT_NEW, seq({ str("new"), sym("expression") })), - left_assoc(PREC_FULL_NEW, seq({ + prec(PREC_FULL_NEW, seq({ str("new"), sym("expression"), str("("), err(optional(sym("arguments"))), str(")") })) }) }, - { "member_access", left_assoc(PREC_MEMBER, seq({ + { "member_access", prec(PREC_MEMBER, seq({ sym("expression"), str("."), sym("identifier") })) }, - { "subscript_access", left_assoc(PREC_MEMBER, seq({ + { "subscript_access", prec(PREC_MEMBER, seq({ sym("expression"), str("["), err(sym("expression")), str("]") })) }, - { "assignment", right_assoc(PREC_ASSIGN, seq({ + { "assignment", prec(PREC_ASSIGN, seq({ choice({ sym("identifier"), sym("member_access"), sym("subscript_access") }), str("="), - sym("expression") })) }, + sym("expression") }), AssociativityRight) }, - { "math_assignment", right_assoc(PREC_ASSIGN, seq({ + { "math_assignment", prec(PREC_ASSIGN, seq({ choice({ sym("identifier"), sym("member_access"), sym("subscript_access") }), choice({ str("+="), str("-="), str("*="), str("/=") }), - sym("expression") })) }, + sym("expression") }), AssociativityRight) }, - { "ternary", right_assoc(PREC_TERNARY, seq({ + { "ternary", prec(PREC_TERNARY, seq({ sym("expression"), str("?"), sym("expression"), str(":"), - sym("expression") })) }, + sym("expression") }), AssociativityRight) }, { "bool_op", choice({ infix_op("||", "expression", PREC_OR), @@ -304,7 +304,7 @@ extern const Grammar javascript = Grammar({ infix_op(">", "expression", PREC_REL) }) }, { "type_op", choice({ - left_assoc(PREC_REL, seq({ + prec(PREC_REL, seq({ choice({ sym("expression"), sym("identifier") }), str("in"), sym("expression") })), @@ -344,7 +344,7 @@ extern const Grammar javascript = Grammar({ { "formal_parameters", comma_sep1(sym("identifier")) }, - { "arguments", left_assoc(-5, comma_sep1(err(sym("expression")))) }, + { "arguments", prec(-5, comma_sep1(err(sym("expression")))) }, { "pair", seq({ choice({ sym("string"), sym("identifier") }), diff --git a/src/compiler/rules/metadata.h b/src/compiler/rules/metadata.h index 13fd42bc..a43c158a 100644 --- a/src/compiler/rules/metadata.h +++ b/src/compiler/rules/metadata.h @@ -3,6 +3,7 @@ #include #include +#include "tree_sitter/compiler.h" #include "compiler/rules/rule.h" namespace tree_sitter { @@ -16,11 +17,7 @@ enum MetadataKey { ASSOCIATIVITY, }; -enum Associativity { - AssociativityUnspecified, - AssociativityLeft, - AssociativityRight, -}; +const Associativity AssociativityUnspecified = (Associativity)0; class Metadata : public Rule { public: diff --git a/src/compiler/rules/rules.cc b/src/compiler/rules/rules.cc index b4f24029..f133672c 100644 --- a/src/compiler/rules/rules.cc +++ b/src/compiler/rules/rules.cc @@ -43,25 +43,22 @@ rule_ptr sym(const string &name) { return make_shared(name); } rule_ptr pattern(const string &value) { return make_shared(value); } rule_ptr str(const string &value) { - return token(left_assoc(1, make_shared(value))); + return token(prec(1, make_shared(value))); } rule_ptr err(const rule_ptr &rule) { return choice({ rule, ERROR().copy() }); } -rule_ptr left_assoc(int precedence, const rule_ptr &rule) { +rule_ptr prec(int precedence, const rule_ptr &rule, Associativity associativity) { return metadata(rule, { { PRECEDENCE, precedence }, - { ASSOCIATIVITY, AssociativityLeft } + { ASSOCIATIVITY, associativity } }); } -rule_ptr right_assoc(int precedence, const rule_ptr &rule) { - return metadata(rule, { - { PRECEDENCE, precedence }, - { ASSOCIATIVITY, AssociativityRight } - }); +rule_ptr prec(int precedence, const rule_ptr &rule) { + return prec(precedence, rule, AssociativityLeft); } rule_ptr token(const rule_ptr &rule) {