From 8908e51aeaee91d6b63684a21ed1ca16de49916f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Aug 2018 14:24:03 +0300 Subject: full precedence --- src/grammar.ron | 5 ++++ src/grammar/expressions/mod.rs | 56 ++++++++++++++++++++++-------------------- src/parser_api.rs | 4 +++ src/parser_impl/mod.rs | 6 +++++ src/syntax_kinds/generated.rs | 14 +++++++++++ 5 files changed, 59 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/grammar.ron b/src/grammar.ron index b525476c2..0620a8b8c 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -43,6 +43,10 @@ Grammar( ["-=", "MINUSEQ"], ["&&", "AMPAMP"], ["||", "PIPEPIPE"], + ["<<", "SHL"], + [">>", "SHR"], + ["<<=", "SHLEQ"], + [">>=", "SHREQ"], ], keywords: [ "use", @@ -168,6 +172,7 @@ Grammar( "REF_EXPR", "DEREF_EXPR", "NOT_EXPR", + "NEG_EXPR", "RANGE_EXPR", // just weird "BIN_EXPR", diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index c137fe654..5b7228146 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs @@ -3,7 +3,7 @@ mod atom; use super::*; pub(super) use self::atom::literal; -const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST; +const EXPR_FIRST: TokenSet = LHS_FIRST; pub(super) fn expr(p: &mut Parser) { let r = Restrictions { forbid_structs: false }; @@ -38,26 +38,6 @@ enum Op { Composite(SyntaxKind, u8), } -// test expr_binding_power -// fn foo() { -// 1 + 2 * 3 == 1 * 2 + 3; -// *x = 1 + 1; -// } - -// test range_binding_power -// fn foo() { -// .. 1 + 1; -// .. z = 2; -// x = false .. 1 == 1; -// } - -// test compound_ops -// fn foo() { -// x += 1; -// 1 + 1 <= 2 * 3; -// z -= 3 >= 0; -// true || true && false; -// } fn current_op(p: &Parser) -> (u8, Op) { if p.at_compound2(PLUS, EQ) { return (1, Op::Composite(PLUSEQ, 2)); @@ -65,6 +45,12 @@ fn current_op(p: &Parser) -> (u8, Op) { if p.at_compound2(MINUS, EQ) { return (1, Op::Composite(MINUSEQ, 2)); } + if p.at_compound3(L_ANGLE, L_ANGLE, EQ) { + return (1, Op::Composite(SHLEQ, 3)); + } + if p.at_compound3(R_ANGLE, R_ANGLE, EQ) { + return (1, Op::Composite(SHREQ, 3)); + } if p.at_compound2(PIPE, PIPE) { return (3, Op::Composite(PIPEPIPE, 2)); } @@ -77,13 +63,22 @@ fn current_op(p: &Parser) -> (u8, Op) { if p.at_compound2(R_ANGLE, EQ) { return (5, Op::Composite(GTEQ, 2)); } + if p.at_compound2(L_ANGLE, L_ANGLE) { + return (9, Op::Composite(SHL, 2)); + } + if p.at_compound2(R_ANGLE, R_ANGLE) { + return (9, Op::Composite(SHR, 2)); + } let bp = match p.current() { EQ => 1, DOTDOT => 2, EQEQ | NEQ => 5, - MINUS | PLUS => 6, - STAR | SLASH => 7, + PIPE => 6, + CARET => 7, + AMP => 8, + MINUS | PLUS => 10, + STAR | SLASH | PERCENT => 11, _ => 0, }; (bp, Op::Simple) @@ -107,13 +102,13 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { p.bump_compound(kind, n); } } - lhs = bin_expr(p, r, lhs, op_bp); + lhs = bin_expr(p, r, lhs, op_bp + 1); } } -const UNARY_EXPR_FIRST: TokenSet = +const LHS_FIRST: TokenSet = token_set_union![ - token_set![AMP, STAR, EXCL], + token_set![AMP, STAR, EXCL, DOTDOT, MINUS], atom::ATOM_EXPR_FIRST, ]; @@ -149,6 +144,15 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option { p.bump(); NOT_EXPR } + // test neg_expr + // fn foo() { + // --1; + // } + MINUS => { + m = p.start(); + p.bump(); + NEG_EXPR + } DOTDOT => { m = p.start(); p.bump(); diff --git a/src/parser_api.rs b/src/parser_api.rs index fef21c5fd..c739b1321 100644 --- a/src/parser_api.rs +++ b/src/parser_api.rs @@ -62,6 +62,10 @@ impl<'t> Parser<'t> { self.0.at_compound2(c1, c2) } + pub(crate) fn at_compound3(&self, c1: SyntaxKind, c2: SyntaxKind, c3: SyntaxKind) -> bool { + self.0.at_compound3(c1, c2, c3) + } + /// Checks if the current token is contextual keyword with text `t`. pub(crate) fn at_contextual_kw(&self, t: &str) -> bool { self.0.at_kw(t) diff --git a/src/parser_impl/mod.rs b/src/parser_impl/mod.rs index d640a7784..06c16cdb4 100644 --- a/src/parser_impl/mod.rs +++ b/src/parser_impl/mod.rs @@ -70,6 +70,12 @@ impl<'t> ParserImpl<'t> { && self.inp.start(self.pos + 1) == self.inp.start(self.pos) + self.inp.len(self.pos) } + pub(super) fn at_compound3(&self, c1: SyntaxKind, c2: SyntaxKind, c3: SyntaxKind) -> bool { + self.inp.kind(self.pos) == c1 && self.inp.kind(self.pos + 1) == c2 && self.inp.kind(self.pos + 2) == c3 + && self.inp.start(self.pos + 1) == self.inp.start(self.pos) + self.inp.len(self.pos) + && self.inp.start(self.pos + 2) == self.inp.start(self.pos + 1) + self.inp.len(self.pos + 1) + } + pub(super) fn nth(&self, n: u32) -> SyntaxKind { self.inp.kind(self.pos + n) } diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 005f4a9dc..db8c20004 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -46,6 +46,10 @@ pub enum SyntaxKind { MINUSEQ, AMPAMP, PIPEPIPE, + SHL, + SHR, + SHLEQ, + SHREQ, USE_KW, FN_KW, STRUCT_KW, @@ -154,6 +158,7 @@ pub enum SyntaxKind { REF_EXPR, DEREF_EXPR, NOT_EXPR, + NEG_EXPR, RANGE_EXPR, BIN_EXPR, EXTERN_BLOCK_EXPR, @@ -280,6 +285,10 @@ impl SyntaxKind { MINUSEQ => &SyntaxInfo { name: "MINUSEQ" }, AMPAMP => &SyntaxInfo { name: "AMPAMP" }, PIPEPIPE => &SyntaxInfo { name: "PIPEPIPE" }, + SHL => &SyntaxInfo { name: "SHL" }, + SHR => &SyntaxInfo { name: "SHR" }, + SHLEQ => &SyntaxInfo { name: "SHLEQ" }, + SHREQ => &SyntaxInfo { name: "SHREQ" }, USE_KW => &SyntaxInfo { name: "USE_KW" }, FN_KW => &SyntaxInfo { name: "FN_KW" }, STRUCT_KW => &SyntaxInfo { name: "STRUCT_KW" }, @@ -388,6 +397,7 @@ impl SyntaxKind { REF_EXPR => &SyntaxInfo { name: "REF_EXPR" }, DEREF_EXPR => &SyntaxInfo { name: "DEREF_EXPR" }, NOT_EXPR => &SyntaxInfo { name: "NOT_EXPR" }, + NEG_EXPR => &SyntaxInfo { name: "NEG_EXPR" }, RANGE_EXPR => &SyntaxInfo { name: "RANGE_EXPR" }, BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" }, EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" }, @@ -534,6 +544,10 @@ impl SyntaxKind { MINUSEQ => "-=", AMPAMP => "&&", PIPEPIPE => "||", + SHL => "<<", + SHR => ">>", + SHLEQ => "<<=", + SHREQ => ">>=", USE_KW => "use", FN_KW => "fn", -- cgit v1.2.3