Lrama v0.6.11
This commit is contained in:
parent
34e6bb48af
commit
d8c152eead
Notes:
git
2024-12-23 06:16:50 +00:00
@ -1,12 +1,47 @@
|
|||||||
# NEWS for Lrama
|
# NEWS for Lrama
|
||||||
|
|
||||||
|
## Lrama 0.6.11 (2024-12-23)
|
||||||
|
|
||||||
|
### Add support for %type declarations using %nterm in Nonterminal Symbols
|
||||||
|
|
||||||
|
Allow to use `%nterm` in Nonterminal Symbols for `%type` declarations.
|
||||||
|
|
||||||
|
```yacc
|
||||||
|
%nterm <type> nonterminal…
|
||||||
|
```
|
||||||
|
|
||||||
|
This directive is also supported for compatibility with Bison, and only non-terminal symbols are allowed. In other words, definitions like the following will result in an error:
|
||||||
|
|
||||||
|
```yacc
|
||||||
|
%{
|
||||||
|
// Prologue
|
||||||
|
%}
|
||||||
|
|
||||||
|
%token EOI 0 "EOI"
|
||||||
|
%nterm EOI
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
program: /* empty */
|
||||||
|
;
|
||||||
|
```
|
||||||
|
|
||||||
|
It show an error message like the following:
|
||||||
|
|
||||||
|
```command
|
||||||
|
❯ exe/lrama nterm.y
|
||||||
|
nterm.y:6:7: symbol EOI redeclared as a nonterminal
|
||||||
|
%nterm EOI
|
||||||
|
^^^
|
||||||
|
```
|
||||||
|
|
||||||
## Lrama 0.6.10 (2024-09-11)
|
## Lrama 0.6.10 (2024-09-11)
|
||||||
|
|
||||||
### Aliased Named References for actions of RHS in parameterizing rules
|
### Aliased Named References for actions of RHS in parameterizing rules
|
||||||
|
|
||||||
Allow to use aliased named references for actions of RHS in parameterizing rules.
|
Allow to use aliased named references for actions of RHS in parameterizing rules.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%rule sum(X, Y): X[summand] '+' Y[addend] { $$ = $summand + $addend }
|
%rule sum(X, Y): X[summand] '+' Y[addend] { $$ = $summand + $addend }
|
||||||
;
|
;
|
||||||
```
|
```
|
||||||
@ -18,7 +53,7 @@ https://github.com/ruby/lrama/pull/410
|
|||||||
|
|
||||||
Allow to use named references for actions of RHS in parameterizing rules caller side.
|
Allow to use named references for actions of RHS in parameterizing rules caller side.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
opt_nl: '\n'?[nl] <str> { $$ = $nl; }
|
opt_nl: '\n'?[nl] <str> { $$ = $nl; }
|
||||||
;
|
;
|
||||||
```
|
```
|
||||||
@ -29,7 +64,7 @@ https://github.com/ruby/lrama/pull/414
|
|||||||
|
|
||||||
Allow to define parameterizing rules in the middle of the grammar.
|
Allow to define parameterizing rules in the middle of the grammar.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%rule defined_option(X): /* empty */
|
%rule defined_option(X): /* empty */
|
||||||
| X
|
| X
|
||||||
;
|
;
|
||||||
@ -52,8 +87,8 @@ https://github.com/ruby/lrama/pull/420
|
|||||||
Support to report unused terminal symbols.
|
Support to report unused terminal symbols.
|
||||||
Run `exe/lrama --report=terms` to show unused terminal symbols.
|
Run `exe/lrama --report=terms` to show unused terminal symbols.
|
||||||
|
|
||||||
```
|
```console
|
||||||
❯ exe/lrama --report=terms sample/calc.y
|
$ exe/lrama --report=terms sample/calc.y
|
||||||
11 Unused Terms
|
11 Unused Terms
|
||||||
0 YYerror
|
0 YYerror
|
||||||
1 YYUNDEF
|
1 YYUNDEF
|
||||||
@ -74,8 +109,8 @@ https://github.com/ruby/lrama/pull/439
|
|||||||
Support to report unused rules.
|
Support to report unused rules.
|
||||||
Run `exe/lrama --report=rules` to show unused rules.
|
Run `exe/lrama --report=rules` to show unused rules.
|
||||||
|
|
||||||
```
|
```console
|
||||||
❯ exe/lrama --report=rules sample/calc.y
|
$ exe/lrama --report=rules sample/calc.y
|
||||||
3 Unused Rules
|
3 Unused Rules
|
||||||
0 unused_option
|
0 unused_option
|
||||||
1 unused_list
|
1 unused_list
|
||||||
@ -96,8 +131,8 @@ https://github.com/ruby/lrama/pull/446
|
|||||||
Support to warning redefined parameterizing rules.
|
Support to warning redefined parameterizing rules.
|
||||||
Run `exe/lrama -W` or `exe/lrama --warnings` to show redefined parameterizing rules.
|
Run `exe/lrama -W` or `exe/lrama --warnings` to show redefined parameterizing rules.
|
||||||
|
|
||||||
```
|
```console
|
||||||
❯ exe/lrama -W sample/calc.y
|
$ exe/lrama -W sample/calc.y
|
||||||
parameterizing rule redefined: redefined_method(X)
|
parameterizing rule redefined: redefined_method(X)
|
||||||
parameterizing rule redefined: redefined_method(X)
|
parameterizing rule redefined: redefined_method(X)
|
||||||
```
|
```
|
||||||
@ -117,7 +152,7 @@ https://github.com/ruby/lrama/pull/457
|
|||||||
|
|
||||||
Allow to specify tag on callee side of parameterizing rules.
|
Allow to specify tag on callee side of parameterizing rules.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%union {
|
%union {
|
||||||
int i;
|
int i;
|
||||||
}
|
}
|
||||||
@ -130,7 +165,7 @@ Allow to specify tag on callee side of parameterizing rules.
|
|||||||
|
|
||||||
Allow to use named references for actions of RHS in parameterizing rules.
|
Allow to use named references for actions of RHS in parameterizing rules.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%rule option(number): /* empty */
|
%rule option(number): /* empty */
|
||||||
| number { $$ = $number; }
|
| number { $$ = $number; }
|
||||||
;
|
;
|
||||||
@ -142,7 +177,7 @@ Allow to use named references for actions of RHS in parameterizing rules.
|
|||||||
|
|
||||||
Allow to nested parameterizing rules with tag.
|
Allow to nested parameterizing rules with tag.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%union {
|
%union {
|
||||||
int i;
|
int i;
|
||||||
}
|
}
|
||||||
@ -179,8 +214,8 @@ User can use `'symbol'?`, `'symbol'+` and `'symbol'*` in RHS of user defined par
|
|||||||
Support trace actions for debugging.
|
Support trace actions for debugging.
|
||||||
Run `exe/lrama --trace=actions` to show grammar rules with actions.
|
Run `exe/lrama --trace=actions` to show grammar rules with actions.
|
||||||
|
|
||||||
```
|
```console
|
||||||
❯ exe/lrama --trace=actions sample/calc.y
|
$ exe/lrama --trace=actions sample/calc.y
|
||||||
Grammar rules with actions:
|
Grammar rules with actions:
|
||||||
$accept -> list, YYEOF {}
|
$accept -> list, YYEOF {}
|
||||||
list -> ε {}
|
list -> ε {}
|
||||||
@ -199,7 +234,7 @@ expr -> '(', expr, ')' { $$ = $2; }
|
|||||||
Support inlining for rules.
|
Support inlining for rules.
|
||||||
The `%inline` directive causes all references to symbols to be replaced with its definition.
|
The `%inline` directive causes all references to symbols to be replaced with its definition.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%rule %inline op: PLUS { + }
|
%rule %inline op: PLUS { + }
|
||||||
| TIMES { * }
|
| TIMES { * }
|
||||||
;
|
;
|
||||||
@ -213,7 +248,7 @@ expr : number { $$ = $1; }
|
|||||||
|
|
||||||
as same as
|
as same as
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
expr : number { $$ = $1; }
|
expr : number { $$ = $1; }
|
||||||
| expr '+' expr { $$ = $1 + $3; }
|
| expr '+' expr { $$ = $1 + $3; }
|
||||||
| expr '*' expr { $$ = $1 * $3; }
|
| expr '*' expr { $$ = $1 * $3; }
|
||||||
@ -226,7 +261,7 @@ expr : number { $$ = $1; }
|
|||||||
|
|
||||||
User can specify the type of mid rule action by tag (`<bar>`) instead of specifying it with in an action.
|
User can specify the type of mid rule action by tag (`<bar>`) instead of specifying it with in an action.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
primary: k_case expr_value terms?
|
primary: k_case expr_value terms?
|
||||||
{
|
{
|
||||||
$<val>$ = p->case_labels;
|
$<val>$ = p->case_labels;
|
||||||
@ -241,7 +276,7 @@ primary: k_case expr_value terms?
|
|||||||
|
|
||||||
can be written as
|
can be written as
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
primary: k_case expr_value terms?
|
primary: k_case expr_value terms?
|
||||||
{
|
{
|
||||||
$$ = p->case_labels;
|
$$ = p->case_labels;
|
||||||
@ -266,7 +301,7 @@ Bison supports this feature from 3.1.
|
|||||||
|
|
||||||
Support `preceded`, `terminated` and `delimited` rules.
|
Support `preceded`, `terminated` and `delimited` rules.
|
||||||
|
|
||||||
```
|
```text
|
||||||
program: preceded(opening, X)
|
program: preceded(opening, X)
|
||||||
|
|
||||||
// Expanded to
|
// Expanded to
|
||||||
@ -302,7 +337,7 @@ In general, these resources are freed by actions or after parsing.
|
|||||||
However if syntax error happens in parsing, these codes may not be executed.
|
However if syntax error happens in parsing, these codes may not be executed.
|
||||||
Codes associated to `%destructor` are executed when semantic value is popped from the stack by an error.
|
Codes associated to `%destructor` are executed when semantic value is popped from the stack by an error.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%token <val1> NUM
|
%token <val1> NUM
|
||||||
%type <val2> expr2
|
%type <val2> expr2
|
||||||
%type <val3> expr
|
%type <val3> expr
|
||||||
@ -350,7 +385,7 @@ Lrama provides these five callbacks. Registered functions are called when each e
|
|||||||
User also needs to access semantic value of their stack in grammar action. `$:n` provides the way to access to it. `$:n` is translated to the minus index from the top of the stack.
|
User also needs to access semantic value of their stack in grammar action. `$:n` provides the way to access to it. `$:n` is translated to the minus index from the top of the stack.
|
||||||
For example
|
For example
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
primary: k_if expr_value then compstmt if_tail k_end
|
primary: k_if expr_value then compstmt if_tail k_end
|
||||||
{
|
{
|
||||||
/*% ripper: if!($:2, $:4, $:5) %*/
|
/*% ripper: if!($:2, $:4, $:5) %*/
|
||||||
@ -375,7 +410,7 @@ https://github.com/ruby/lrama/pull/344
|
|||||||
|
|
||||||
Allow to pass an instantiated rule to other parameterizing rules.
|
Allow to pass an instantiated rule to other parameterizing rules.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%rule constant(X) : X
|
%rule constant(X) : X
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -392,7 +427,7 @@ program : option(constant(number)) // Nested rule
|
|||||||
|
|
||||||
Allow to use nested parameterizing rules when define parameterizing rules.
|
Allow to use nested parameterizing rules when define parameterizing rules.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%rule option(x) : /* empty */
|
%rule option(x) : /* empty */
|
||||||
| X
|
| X
|
||||||
;
|
;
|
||||||
@ -419,7 +454,7 @@ https://github.com/ruby/lrama/pull/337
|
|||||||
|
|
||||||
Allow to define parameterizing rule by `%rule` directive.
|
Allow to define parameterizing rule by `%rule` directive.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%rule pair(X, Y): X Y { $$ = $1 + $2; }
|
%rule pair(X, Y): X Y { $$ = $1 + $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -442,7 +477,7 @@ https://github.com/ruby/lrama/pull/285
|
|||||||
Allow to specify type of rules by specifying tag, `<i>` in below example.
|
Allow to specify type of rules by specifying tag, `<i>` in below example.
|
||||||
Tag is post-modification style.
|
Tag is post-modification style.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
%union {
|
%union {
|
||||||
int i;
|
int i;
|
||||||
}
|
}
|
||||||
@ -469,7 +504,7 @@ https://github.com/ruby/lrama/pull/197
|
|||||||
|
|
||||||
Support `separated_list` and `separated_nonempty_list` parameterizing rules.
|
Support `separated_list` and `separated_nonempty_list` parameterizing rules.
|
||||||
|
|
||||||
```
|
```text
|
||||||
program: separated_list(',', number)
|
program: separated_list(',', number)
|
||||||
|
|
||||||
// Expanded to
|
// Expanded to
|
||||||
@ -500,7 +535,7 @@ https://github.com/ruby/lrama/pull/204
|
|||||||
Parameterizing rules are template of rules.
|
Parameterizing rules are template of rules.
|
||||||
It's very common pattern to write "list" grammar rule like:
|
It's very common pattern to write "list" grammar rule like:
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
opt_args: /* none */
|
opt_args: /* none */
|
||||||
| args
|
| args
|
||||||
;
|
;
|
||||||
@ -532,7 +567,7 @@ https://github.com/ruby/lrama/pull/62
|
|||||||
|
|
||||||
### Runtime configuration for error recovery
|
### Runtime configuration for error recovery
|
||||||
|
|
||||||
Meke error recovery function configurable on runtime by two new macros.
|
Make error recovery function configurable on runtime by two new macros.
|
||||||
|
|
||||||
* `YYMAXREPAIR`: Expected to return max length of repair operations. `%parse-param` is passed to this function.
|
* `YYMAXREPAIR`: Expected to return max length of repair operations. `%parse-param` is passed to this function.
|
||||||
* `YYERROR_RECOVERY_ENABLED`: Expected to return bool value to determine error recovery is enabled or not. `%parse-param` is passed to this function.
|
* `YYERROR_RECOVERY_ENABLED`: Expected to return bool value to determine error recovery is enabled or not. `%parse-param` is passed to this function.
|
||||||
@ -555,7 +590,7 @@ https://github.com/ruby/lrama/pull/44
|
|||||||
Instead of positional references like `$1` or `$$`,
|
Instead of positional references like `$1` or `$$`,
|
||||||
named references allow to access to symbol by name.
|
named references allow to access to symbol by name.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
primary: k_class cpath superclass bodystmt k_end
|
primary: k_class cpath superclass bodystmt k_end
|
||||||
{
|
{
|
||||||
$primary = new_class($cpath, $bodystmt, $superclass);
|
$primary = new_class($cpath, $bodystmt, $superclass);
|
||||||
@ -564,7 +599,7 @@ primary: k_class cpath superclass bodystmt k_end
|
|||||||
|
|
||||||
Alias name can be declared.
|
Alias name can be declared.
|
||||||
|
|
||||||
```
|
```yacc
|
||||||
expr[result]: expr[ex-left] '+' expr[ex.right]
|
expr[result]: expr[ex-left] '+' expr[ex.right]
|
||||||
{
|
{
|
||||||
$result = $[ex-left] + $[ex.right];
|
$result = $[ex-left] + $[ex.right];
|
||||||
|
@ -13,7 +13,7 @@ module Lrama
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.to_array(int)
|
def self.to_array(int)
|
||||||
a = []
|
a = [] #: Array[Integer]
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
while int > 0 do
|
while int > 0 do
|
||||||
|
@ -405,7 +405,7 @@ module Lrama
|
|||||||
@check = []
|
@check = []
|
||||||
# Key is froms_and_tos, value is index position
|
# Key is froms_and_tos, value is index position
|
||||||
pushed = {}
|
pushed = {}
|
||||||
userd_res = {}
|
used_res = {}
|
||||||
lowzero = 0
|
lowzero = 0
|
||||||
high = 0
|
high = 0
|
||||||
|
|
||||||
@ -430,7 +430,7 @@ module Lrama
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ok && userd_res[res]
|
if ok && used_res[res]
|
||||||
ok = false
|
ok = false
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -458,7 +458,7 @@ module Lrama
|
|||||||
|
|
||||||
@base[state_id] = res
|
@base[state_id] = res
|
||||||
pushed[froms_and_tos] = res
|
pushed[froms_and_tos] = res
|
||||||
userd_res[res] = true
|
used_res[res] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@yylast = high
|
@yylast = high
|
||||||
|
@ -32,8 +32,10 @@ module Lrama
|
|||||||
conflict_state.conflicts.flat_map do |conflict|
|
conflict_state.conflicts.flat_map do |conflict|
|
||||||
case conflict.type
|
case conflict.type
|
||||||
when :shift_reduce
|
when :shift_reduce
|
||||||
|
# @type var conflict: State::ShiftReduceConflict
|
||||||
shift_reduce_example(conflict_state, conflict)
|
shift_reduce_example(conflict_state, conflict)
|
||||||
when :reduce_reduce
|
when :reduce_reduce
|
||||||
|
# @type var conflict: State::ReduceReduceConflict
|
||||||
reduce_reduce_examples(conflict_state, conflict)
|
reduce_reduce_examples(conflict_state, conflict)
|
||||||
end
|
end
|
||||||
end.compact
|
end.compact
|
||||||
@ -48,7 +50,7 @@ module Lrama
|
|||||||
@reverse_transitions = {}
|
@reverse_transitions = {}
|
||||||
|
|
||||||
@states.states.each do |src_state|
|
@states.states.each do |src_state|
|
||||||
trans = {}
|
trans = {} #: Hash[Grammar::Symbol, State]
|
||||||
|
|
||||||
src_state.transitions.each do |shift, next_state|
|
src_state.transitions.each do |shift, next_state|
|
||||||
trans[shift.next_sym] = next_state
|
trans[shift.next_sym] = next_state
|
||||||
@ -66,6 +68,7 @@ module Lrama
|
|||||||
|
|
||||||
@transitions[[src_state_item, sym]] = dest_state_item
|
@transitions[[src_state_item, sym]] = dest_state_item
|
||||||
|
|
||||||
|
# @type var key: [StateItem, Grammar::Symbol]
|
||||||
key = [dest_state_item, sym]
|
key = [dest_state_item, sym]
|
||||||
@reverse_transitions[key] ||= Set.new
|
@reverse_transitions[key] ||= Set.new
|
||||||
@reverse_transitions[key] << src_state_item
|
@reverse_transitions[key] << src_state_item
|
||||||
@ -82,7 +85,7 @@ module Lrama
|
|||||||
|
|
||||||
@states.states.each do |state|
|
@states.states.each do |state|
|
||||||
# LHS => Set(Item)
|
# LHS => Set(Item)
|
||||||
h = {}
|
h = {} #: Hash[Grammar::Symbol, Set[States::Item]]
|
||||||
|
|
||||||
state.closure.each do |item|
|
state.closure.each do |item|
|
||||||
sym = item.lhs
|
sym = item.lhs
|
||||||
@ -97,6 +100,7 @@ module Lrama
|
|||||||
|
|
||||||
sym = item.next_sym
|
sym = item.next_sym
|
||||||
state_item = StateItem.new(state, item)
|
state_item = StateItem.new(state, item)
|
||||||
|
# @type var key: [State, Grammar::Symbol]
|
||||||
key = [state, sym]
|
key = [state, sym]
|
||||||
|
|
||||||
@productions[state_item] = h[sym]
|
@productions[state_item] = h[sym]
|
||||||
@ -109,6 +113,7 @@ module Lrama
|
|||||||
|
|
||||||
def shift_reduce_example(conflict_state, conflict)
|
def shift_reduce_example(conflict_state, conflict)
|
||||||
conflict_symbol = conflict.symbols.first
|
conflict_symbol = conflict.symbols.first
|
||||||
|
# @type var shift_conflict_item: ::Lrama::States::Item
|
||||||
shift_conflict_item = conflict_state.items.find { |item| item.next_sym == conflict_symbol }
|
shift_conflict_item = conflict_state.items.find { |item| item.next_sym == conflict_symbol }
|
||||||
path2 = shortest_path(conflict_state, conflict.reduce.item, conflict_symbol)
|
path2 = shortest_path(conflict_state, conflict.reduce.item, conflict_symbol)
|
||||||
path1 = find_shift_conflict_shortest_path(path2, conflict_state, shift_conflict_item)
|
path1 = find_shift_conflict_shortest_path(path2, conflict_state, shift_conflict_item)
|
||||||
@ -153,12 +158,14 @@ module Lrama
|
|||||||
prev_state_item = prev_path&.to
|
prev_state_item = prev_path&.to
|
||||||
|
|
||||||
if target_state_item == state_item || target_state_item.item.start_item?
|
if target_state_item == state_item || target_state_item.item.start_item?
|
||||||
result.concat(reversed_reduce_path[_j..-1].map(&:to))
|
result.concat(
|
||||||
|
reversed_reduce_path[_j..-1] #: Array[StartPath|TransitionPath|ProductionPath]
|
||||||
|
.map(&:to))
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
if target_state_item.item.beginning_of_rule?
|
if target_state_item.item.beginning_of_rule?
|
||||||
queue = []
|
queue = [] #: Array[Array[StateItem]]
|
||||||
queue << [target_state_item]
|
queue << [target_state_item]
|
||||||
|
|
||||||
# Find reverse production
|
# Find reverse production
|
||||||
@ -174,15 +181,17 @@ module Lrama
|
|||||||
end
|
end
|
||||||
|
|
||||||
if si.item.beginning_of_rule?
|
if si.item.beginning_of_rule?
|
||||||
|
# @type var key: [State, Grammar::Symbol]
|
||||||
key = [si.state, si.item.lhs]
|
key = [si.state, si.item.lhs]
|
||||||
@reverse_productions[key].each do |item|
|
@reverse_productions[key].each do |item|
|
||||||
state_item = StateItem.new(si.state, item)
|
state_item = StateItem.new(si.state, item)
|
||||||
queue << (sis + [state_item])
|
queue << (sis + [state_item])
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
# @type var key: [StateItem, Grammar::Symbol]
|
||||||
key = [si, si.item.previous_sym]
|
key = [si, si.item.previous_sym]
|
||||||
@reverse_transitions[key].each do |prev_target_state_item|
|
@reverse_transitions[key].each do |prev_target_state_item|
|
||||||
next if prev_target_state_item.state != prev_state_item.state
|
next if prev_target_state_item.state != prev_state_item&.state
|
||||||
sis.shift
|
sis.shift
|
||||||
result.concat(sis)
|
result.concat(sis)
|
||||||
result << prev_target_state_item
|
result << prev_target_state_item
|
||||||
@ -195,9 +204,10 @@ module Lrama
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Find reverse transition
|
# Find reverse transition
|
||||||
|
# @type var key: [StateItem, Grammar::Symbol]
|
||||||
key = [target_state_item, target_state_item.item.previous_sym]
|
key = [target_state_item, target_state_item.item.previous_sym]
|
||||||
@reverse_transitions[key].each do |prev_target_state_item|
|
@reverse_transitions[key].each do |prev_target_state_item|
|
||||||
next if prev_target_state_item.state != prev_state_item.state
|
next if prev_target_state_item.state != prev_state_item&.state
|
||||||
result << prev_target_state_item
|
result << prev_target_state_item
|
||||||
target_state_item = prev_target_state_item
|
target_state_item = prev_target_state_item
|
||||||
i = j
|
i = j
|
||||||
@ -224,9 +234,9 @@ module Lrama
|
|||||||
|
|
||||||
def shortest_path(conflict_state, conflict_reduce_item, conflict_term)
|
def shortest_path(conflict_state, conflict_reduce_item, conflict_term)
|
||||||
# queue: is an array of [Triple, [Path]]
|
# queue: is an array of [Triple, [Path]]
|
||||||
queue = []
|
queue = [] #: Array[[Triple, Array[StartPath|TransitionPath|ProductionPath]]]
|
||||||
visited = {}
|
visited = {} #: Hash[Triple, true]
|
||||||
start_state = @states.states.first
|
start_state = @states.states.first #: Lrama::State
|
||||||
raise "BUG: Start state should be just one kernel." if start_state.kernels.count != 1
|
raise "BUG: Start state should be just one kernel." if start_state.kernels.count != 1
|
||||||
|
|
||||||
start = Triple.new(start_state, start_state.kernels.first, Set.new([@states.eof_symbol]))
|
start = Triple.new(start_state, start_state.kernels.first, Set.new([@states.eof_symbol]))
|
||||||
|
@ -18,7 +18,7 @@ module Lrama
|
|||||||
alias :inspect :to_s
|
alias :inspect :to_s
|
||||||
|
|
||||||
def render_strings_for_report
|
def render_strings_for_report
|
||||||
result = []
|
result = [] #: Array[String]
|
||||||
_render_for_report(self, 0, result, 0)
|
_render_for_report(self, 0, result, 0)
|
||||||
result.map(&:rstrip)
|
result.map(&:rstrip)
|
||||||
end
|
end
|
||||||
@ -44,18 +44,19 @@ module Lrama
|
|||||||
str << "#{item.next_sym.display_name}"
|
str << "#{item.next_sym.display_name}"
|
||||||
length = _render_for_report(derivation.left, len, strings, index + 1)
|
length = _render_for_report(derivation.left, len, strings, index + 1)
|
||||||
# I want String#ljust!
|
# I want String#ljust!
|
||||||
str << " " * (length - str.length)
|
str << " " * (length - str.length) if length > str.length
|
||||||
else
|
else
|
||||||
str << " • #{item.symbols_after_dot.map(&:display_name).join(" ")} "
|
str << " • #{item.symbols_after_dot.map(&:display_name).join(" ")} "
|
||||||
return str.length
|
return str.length
|
||||||
end
|
end
|
||||||
|
|
||||||
if derivation.right&.left
|
if derivation.right&.left
|
||||||
length = _render_for_report(derivation.right.left, str.length, strings, index + 1)
|
left = derivation.right&.left #: Derivation
|
||||||
str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} "
|
length = _render_for_report(left, str.length, strings, index + 1)
|
||||||
|
str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} " # steep:ignore
|
||||||
str << " " * (length - str.length) if length > str.length
|
str << " " * (length - str.length) if length > str.length
|
||||||
elsif item.next_next_sym
|
elsif item.next_next_sym
|
||||||
str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} "
|
str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} " # steep:ignore
|
||||||
end
|
end
|
||||||
|
|
||||||
return str.length
|
return str.length
|
||||||
|
@ -38,9 +38,10 @@ module Lrama
|
|||||||
private
|
private
|
||||||
|
|
||||||
def _derivations(paths)
|
def _derivations(paths)
|
||||||
derivation = nil
|
derivation = nil #: Derivation
|
||||||
current = :production
|
current = :production
|
||||||
lookahead_sym = paths.last.to.item.end_of_rule? ? @conflict_symbol : nil
|
last_path = paths.last #: Path
|
||||||
|
lookahead_sym = last_path.to.item.end_of_rule? ? @conflict_symbol : nil
|
||||||
|
|
||||||
paths.reverse_each do |path|
|
paths.reverse_each do |path|
|
||||||
item = path.to.item
|
item = path.to.item
|
||||||
@ -57,12 +58,14 @@ module Lrama
|
|||||||
when ProductionPath
|
when ProductionPath
|
||||||
derivation = Derivation.new(item, derivation)
|
derivation = Derivation.new(item, derivation)
|
||||||
current = :production
|
current = :production
|
||||||
|
else
|
||||||
|
raise "Unexpected. #{path}"
|
||||||
end
|
end
|
||||||
|
|
||||||
if lookahead_sym && item.next_next_sym && item.next_next_sym.first_set.include?(lookahead_sym)
|
if lookahead_sym && item.next_next_sym && item.next_next_sym.first_set.include?(lookahead_sym)
|
||||||
state_item = @counterexamples.transitions[[path.to, item.next_sym]]
|
state_item = @counterexamples.transitions[[path.to, item.next_sym]]
|
||||||
derivation2 = find_derivation_for_symbol(state_item, lookahead_sym)
|
derivation2 = find_derivation_for_symbol(state_item, lookahead_sym)
|
||||||
derivation.right = derivation2
|
derivation.right = derivation2 # steep:ignore
|
||||||
lookahead_sym = nil
|
lookahead_sym = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -89,7 +92,7 @@ module Lrama
|
|||||||
end
|
end
|
||||||
|
|
||||||
def find_derivation_for_symbol(state_item, sym)
|
def find_derivation_for_symbol(state_item, sym)
|
||||||
queue = []
|
queue = [] #: Array[Array[StateItem]]
|
||||||
queue << [state_item]
|
queue << [state_item]
|
||||||
|
|
||||||
while (sis = queue.shift)
|
while (sis = queue.shift)
|
||||||
|
@ -20,6 +20,10 @@ module Lrama
|
|||||||
"#<Path(#{type})>"
|
"#<Path(#{type})>"
|
||||||
end
|
end
|
||||||
alias :inspect :to_s
|
alias :inspect :to_s
|
||||||
|
|
||||||
|
def type
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -30,7 +30,7 @@ module Lrama
|
|||||||
:after_shift, :before_reduce, :after_reduce, :after_shift_error_token, :after_pop_stack,
|
:after_shift, :before_reduce, :after_reduce, :after_shift_error_token, :after_pop_stack,
|
||||||
:symbols_resolver, :types, :rules, :rule_builders, :sym_to_rules, :no_stdlib, :locations
|
:symbols_resolver, :types, :rules, :rule_builders, :sym_to_rules, :no_stdlib, :locations
|
||||||
|
|
||||||
def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term,
|
def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term, :find_term_by_s_value,
|
||||||
:find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol,
|
:find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol,
|
||||||
:find_symbol_by_s_value!, :fill_symbol_number, :fill_nterm_type,
|
:find_symbol_by_s_value!, :fill_symbol_number, :fill_nterm_type,
|
||||||
:fill_printer, :fill_destructor, :fill_error_token, :sort_by_number!
|
:fill_printer, :fill_destructor, :fill_error_token, :sort_by_number!
|
||||||
@ -382,7 +382,7 @@ module Lrama
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_rule_lhs_is_nterm!
|
def validate_rule_lhs_is_nterm!
|
||||||
errors = []
|
errors = [] #: Array[String]
|
||||||
|
|
||||||
rules.each do |rule|
|
rules.each do |rule|
|
||||||
next if rule.lhs.nterm?
|
next if rule.lhs.nterm?
|
||||||
|
@ -16,7 +16,7 @@ module Lrama
|
|||||||
return unless user_code
|
return unless user_code
|
||||||
|
|
||||||
resolved = Lexer::Token::UserCode.new(s_value: user_code.s_value, location: user_code.location)
|
resolved = Lexer::Token::UserCode.new(s_value: user_code.s_value, location: user_code.location)
|
||||||
var_to_arg = {}
|
var_to_arg = {} #: Hash[String, String]
|
||||||
symbols.each do |sym|
|
symbols.each do |sym|
|
||||||
resolved_sym = bindings.resolve_symbol(sym)
|
resolved_sym = bindings.resolve_symbol(sym)
|
||||||
if resolved_sym != sym
|
if resolved_sym != sym
|
||||||
|
@ -67,7 +67,7 @@ module Lrama
|
|||||||
end
|
end
|
||||||
|
|
||||||
def resolve_inline_rules
|
def resolve_inline_rules
|
||||||
resolved_builders = []
|
resolved_builders = [] #: Array[RuleBuilder]
|
||||||
rhs.each_with_index do |token, i|
|
rhs.each_with_index do |token, i|
|
||||||
if (inline_rule = @parameterizing_rule_resolver.find_inline(token))
|
if (inline_rule = @parameterizing_rule_resolver.find_inline(token))
|
||||||
inline_rule.rhs_list.each do |inline_rhs|
|
inline_rule.rhs_list.each do |inline_rhs|
|
||||||
|
@ -57,6 +57,10 @@ module Lrama
|
|||||||
nterm
|
nterm
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_term_by_s_value(s_value)
|
||||||
|
terms.find { |s| s.id.s_value == s_value }
|
||||||
|
end
|
||||||
|
|
||||||
def find_symbol_by_s_value(s_value)
|
def find_symbol_by_s_value(s_value)
|
||||||
symbols.find { |s| s.id.s_value == s_value }
|
symbols.find { |s| s.id.s_value == s_value }
|
||||||
end
|
end
|
||||||
|
@ -16,6 +16,7 @@ module Lrama
|
|||||||
%union
|
%union
|
||||||
%token
|
%token
|
||||||
%type
|
%type
|
||||||
|
%nterm
|
||||||
%left
|
%left
|
||||||
%right
|
%right
|
||||||
%nonassoc
|
%nonassoc
|
||||||
|
@ -16,7 +16,7 @@ module Lrama
|
|||||||
|
|
||||||
def _references
|
def _references
|
||||||
scanner = StringScanner.new(s_value)
|
scanner = StringScanner.new(s_value)
|
||||||
references = []
|
references = [] #: Array[Grammar::Reference]
|
||||||
|
|
||||||
until scanner.eos? do
|
until scanner.eos? do
|
||||||
case
|
case
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -26,9 +26,8 @@ module Lrama
|
|||||||
end
|
end
|
||||||
|
|
||||||
def selected_look_ahead
|
def selected_look_ahead
|
||||||
if @look_ahead
|
if look_ahead
|
||||||
# @type ivar @look_ahead: Array<Grammar::Symbol>
|
look_ahead - @not_selected_symbols
|
||||||
@look_ahead - @not_selected_symbols
|
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Lrama
|
module Lrama
|
||||||
VERSION = "0.6.10".freeze
|
VERSION = "0.6.11".freeze
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user