From cc8877d26f7f55ffb92890f74f09e5b28e4416e2 Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Sat, 4 Nov 2023 16:53:40 +0900 Subject: [PATCH] Implement parameterizing rules for list --- lib/lrama/grammar.rb | 7 +++++++ lib/lrama/lexer.rb | 2 +- lib/lrama/lexer/token.rb | 1 + parser.y | 5 +++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/lrama/grammar.rb b/lib/lrama/grammar.rb index 609be70e..652abbba 100644 --- a/lib/lrama/grammar.rb +++ b/lib/lrama/grammar.rb @@ -578,6 +578,13 @@ def normalize_rules @rules << Rule.new(id: @rules.count, lhs: lhs, rhs: [nonempty_list_token], code: c, precedence_sym: precedence_sym, lineno: lineno) @rules << Rule.new(id: @rules.count, lhs: nonempty_list_token, rhs: [token], code: c, precedence_sym: precedence_sym, lineno: lineno) @rules << Rule.new(id: @rules.count, lhs: nonempty_list_token, rhs: [nonempty_list_token, token], code: c, precedence_sym: precedence_sym, lineno: lineno) + elsif rhs2.any? {|r| r.type == Token::List } + list_token = Token.new(type: Token::Ident, s_value: "list_#{rhs2[0].s_value}") + token = Token.new(type: Token::Ident, s_value: rhs2[0].s_value) + add_term(id: list_token) + @rules << Rule.new(id: @rules.count, lhs: lhs, rhs: [list_token], code: c, precedence_sym: precedence_sym, lineno: lineno) + @rules << Rule.new(id: @rules.count, lhs: list_token, rhs: [], code: c, precedence_sym: precedence_sym, lineno: lineno) + @rules << Rule.new(id: @rules.count, lhs: list_token, rhs: [list_token, token], code: c, precedence_sym: precedence_sym, lineno: lineno) else @rules << Rule.new(id: @rules.count, lhs: lhs, rhs: rhs2, code: c, precedence_sym: precedence_sym, lineno: lineno) end diff --git a/lib/lrama/lexer.rb b/lib/lrama/lexer.rb index 6d9d21fb..970d4566 100644 --- a/lib/lrama/lexer.rb +++ b/lib/lrama/lexer.rb @@ -79,7 +79,7 @@ def lex_token return [@scanner.matched, @scanner.matched] when @scanner.scan(/#{PERCENT_TOKENS.join('|')}/) return [@scanner.matched, @scanner.matched] - when @scanner.scan(/[\?\+]/) + when @scanner.scan(/[\?\+\*]/) return [@scanner.matched, @scanner.matched] when @scanner.scan(/<\w+>/) return [:TAG, build_token(type: Token::Tag, s_value: @scanner.matched)] diff --git a/lib/lrama/lexer/token.rb b/lib/lrama/lexer/token.rb index b30d087a..67e01734 100644 --- a/lib/lrama/lexer/token.rb +++ b/lib/lrama/lexer/token.rb @@ -37,6 +37,7 @@ def self.define_type(name) define_type(:Char) # '+' define_type(:Option) # actual? define_type(:Nonempty_list) # actual+ + define_type(:List) # actual* end end end diff --git a/parser.y b/parser.y index e2a94745..f6bed361 100644 --- a/parser.y +++ b/parser.y @@ -304,6 +304,11 @@ rule token = Token.new(type: Token::Nonempty_list, s_value: val[1]) result = val[0].append(token) } + | rhs "*" + { + token = Token.new(type: Token::List, s_value: val[1]) + result = val[0].append(token) + } | rhs "{" { if @prec_seen