Skip to content

Commit

Permalink
Merge pull request #197 from ydah/parameterizing_rules_2
Browse files Browse the repository at this point in the history
Support another syntactic sugar for parameterizing rules
  • Loading branch information
yui-knk authored Nov 5, 2023
2 parents ed65667 + 206f2e9 commit cb9f693
Show file tree
Hide file tree
Showing 8 changed files with 437 additions and 284 deletions.
9 changes: 8 additions & 1 deletion lib/lrama/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Lexer
attr_accessor :status
attr_accessor :end_symbol

SYMBOLS = %w(%{ %} %% { } \[ \] : \| ;)
SYMBOLS = ['%{', '%}', '%%', '{', '}', '\[', '\]', '\(', '\)', ':', '\|', ';']
PERCENT_TOKENS = %w(
%union
%token
Expand All @@ -29,6 +29,11 @@ class Lexer
%empty
%code
)
PARAMETERIZING_TOKENS = [
'option\(',
'nonempty_list\(',
'list\('
]

def initialize(text)
@scanner = StringScanner.new(text)
Expand Down Expand Up @@ -89,6 +94,8 @@ def lex_token
return [@scanner.matched, @scanner.matched]
when @scanner.scan(/#{PERCENT_TOKENS.join('|')}/)
return [@scanner.matched, @scanner.matched]
when @scanner.scan(/#{PARAMETERIZING_TOKENS.join('|')}/)
return [@scanner.matched, @scanner.matched]
when @scanner.scan(/[\?\+\*]/)
return [@scanner.matched, @scanner.matched]
when @scanner.scan(/<\w+>/)
Expand Down
6 changes: 3 additions & 3 deletions lib/lrama/lexer/token/parameterizing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ class Lexer
class Token
class Parameterizing < Token
def option?
self.s_value == "?"
%w(option ?).include?(self.s_value)
end

def nonempty_list?
self.s_value == "+"
%w(nonempty_list +).include?(self.s_value)
end

def list?
self.s_value == "*"
%w(list *).include?(self.s_value)
end
end
end
Expand Down
552 changes: 293 additions & 259 deletions lib/lrama/parser.rb

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ rule
token = Lrama::Lexer::Token::Parameterizing.new(s_value: val[1])
result = val[0].append(token)
}
| parameterizing_prefix rhs ")"
{
token = Lrama::Lexer::Token::Parameterizing.new(s_value: val[0].chop)
result = val[1].append(token)
}
| rhs "{"
{
if @prec_seen
Expand All @@ -345,6 +350,10 @@ rule
@prec_seen = true
}

parameterizing_prefix: "option("
| "nonempty_list("
| "list("

parameterizing_suffix: "?"
| "+"
| "*"
Expand Down
6 changes: 5 additions & 1 deletion spec/fixtures/parameterizing_rules/list.y
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ static int yyerror(YYLTYPE *loc, const char *str);
}

%token <i> number
%token <i> number_alias

%%

program : number*
program : list(number)
;

alias : number_alias*
;

%%
Expand Down
6 changes: 5 additions & 1 deletion spec/fixtures/parameterizing_rules/nonempty_list.y
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ static int yyerror(YYLTYPE *loc, const char *str);
}

%token <i> number
%token <i> number_alias

%%

program : number+
program : nonempty_list(number)
;

alias : number_alias+
;

%%
Expand Down
6 changes: 5 additions & 1 deletion spec/fixtures/parameterizing_rules/option.y
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ static int yyerror(YYLTYPE *loc, const char *str);
}

%token <i> number
%token <i> number_alias

%%

program : number?
program : option(number)
;

alias : number_alias?
;

%%
Expand Down
127 changes: 109 additions & 18 deletions spec/lrama/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,9 @@
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 8, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "alias"), alias_name: nil, number: 9, tag: nil, term: false, token_id: 2, nullable: false),
])

expect(grammar.rules).to eq([
Expand All @@ -574,7 +575,7 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("YYEOF"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 1,
Expand All @@ -585,7 +586,7 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("option_number"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 2,
Expand All @@ -594,7 +595,7 @@
token_code: nil,
nullable: true,
precedence_sym: nil,
lineno: 20,
lineno: 21,
),
Rule.new(
id: 3,
Expand All @@ -605,7 +606,35 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("number"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 4,
lhs: grammar.find_symbol_by_s_value!("alias"),
rhs: [
grammar.find_symbol_by_s_value!("option_number_alias"),
],
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("option_number_alias"),
lineno: 24,
),
Rule.new(
id: 5,
lhs: grammar.find_symbol_by_s_value!("option_number_alias"),
rhs: [],
nullable: true,
precedence_sym: nil,
lineno: 24,
),
Rule.new(
id: 6,
lhs: grammar.find_symbol_by_s_value!("option_number_alias"),
rhs: [
grammar.find_symbol_by_s_value!("number_alias"),
],
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("number_alias"),
lineno: 24,
),
])
end
Expand All @@ -616,8 +645,9 @@
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 8, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "alias"), alias_name: nil, number: 9, tag: nil, term: false, token_id: 2, nullable: false),
])

expect(grammar.rules).to eq([
Expand All @@ -631,7 +661,7 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("YYEOF"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 1,
Expand All @@ -642,7 +672,7 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("nonempty_list_number"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 2,
Expand All @@ -653,7 +683,7 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("number"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 3,
Expand All @@ -665,7 +695,38 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("number"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 4,
lhs: grammar.find_symbol_by_s_value!("alias"),
rhs: [
grammar.find_symbol_by_s_value!("nonempty_list_number_alias"),
],
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("nonempty_list_number_alias"),
lineno: 24,
),
Rule.new(
id: 5,
lhs: grammar.find_symbol_by_s_value!("nonempty_list_number_alias"),
rhs: [
grammar.find_symbol_by_s_value!("number_alias"),
],
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("number_alias"),
lineno: 24,
),
Rule.new(
id: 6,
lhs: grammar.find_symbol_by_s_value!("nonempty_list_number_alias"),
rhs: [
grammar.find_symbol_by_s_value!("nonempty_list_number_alias"),
grammar.find_symbol_by_s_value!("number_alias"),
],
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("number_alias"),
lineno: 24,
),
])
end
Expand All @@ -676,8 +737,9 @@
grammar = Lrama::Parser.new(y, path).parse

expect(grammar.nterms.sort_by(&:number)).to eq([
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 5, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 6, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "$accept"), alias_name: nil, number: 7, tag: nil, term: false, token_id: 0, nullable: false),
Sym.new(id: T::Ident.new(s_value: "program"), alias_name: nil, number: 8, tag: nil, term: false, token_id: 1, nullable: false),
Sym.new(id: T::Ident.new(s_value: "alias"), alias_name: nil, number: 9, tag: nil, term: false, token_id: 2, nullable: false),
])

expect(grammar.rules).to eq([
Expand All @@ -691,7 +753,7 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("YYEOF"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 1,
Expand All @@ -702,7 +764,7 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("list_number"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 2,
Expand All @@ -711,7 +773,7 @@
token_code: nil,
nullable: true,
precedence_sym: nil,
lineno: 20,
lineno: 21,
),
Rule.new(
id: 3,
Expand All @@ -723,7 +785,36 @@
token_code: nil,
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("number"),
lineno: 20,
lineno: 21,
),
Rule.new(
id: 4,
lhs: grammar.find_symbol_by_s_value!("alias"),
rhs: [
grammar.find_symbol_by_s_value!("list_number_alias"),
],
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("list_number_alias"),
lineno: 24,
),
Rule.new(
id: 5,
lhs: grammar.find_symbol_by_s_value!("list_number_alias"),
rhs: [],
nullable: true,
precedence_sym: nil,
lineno: 24,
),
Rule.new(
id: 6,
lhs: grammar.find_symbol_by_s_value!("list_number_alias"),
rhs: [
grammar.find_symbol_by_s_value!("list_number_alias"),
grammar.find_symbol_by_s_value!("number_alias"),
],
nullable: false,
precedence_sym: grammar.find_symbol_by_s_value!("number_alias"),
lineno: 24,
),
])
end
Expand Down

0 comments on commit cb9f693

Please sign in to comment.