lrama 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/test.yaml +72 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/Gemfile +8 -0
- data/LEGAL.md +26 -0
- data/MIT +21 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/doc/TODO.md +50 -0
- data/exe/lrama +7 -0
- data/lib/lrama/command.rb +129 -0
- data/lib/lrama/context.rb +510 -0
- data/lib/lrama/grammar.rb +850 -0
- data/lib/lrama/lexer.rb +349 -0
- data/lib/lrama/output.rb +268 -0
- data/lib/lrama/parser.rb +321 -0
- data/lib/lrama/report.rb +35 -0
- data/lib/lrama/states.rb +1124 -0
- data/lib/lrama/version.rb +3 -0
- data/lib/lrama.rb +9 -0
- data/lrama.gemspec +22 -0
- data/template/bison/yacc.c +1750 -0
- data/template/bison/yacc.h +112 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1d7cf0f612d3e1ac4aea0b45db6c0533beadd6412f10a85dd17aceefcfb104a9
|
4
|
+
data.tar.gz: 9e60878988696b8d300700a442cb93bb7d7919be94be80a4bd96cbfe689dad1a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0fa702fd65a2b84c3d426c45ea6d09a5129391409408604d50767c71f8f2d059db45bbde0b8fd96f093caf3741479add35e8cb1434bdd763c38761f70a994d93
|
7
|
+
data.tar.gz: d2d5ed81585710107200595b38316120ccc5e01718247c08b6c7de7708ae619de1ec7e37d4ce987b6c21c31d81d5f5c812ecb385d7a6d2838be26e4cf52621f1
|
@@ -0,0 +1,72 @@
|
|
1
|
+
name: test
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
pull_request:
|
6
|
+
|
7
|
+
permissions:
|
8
|
+
contents: read
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
test:
|
12
|
+
runs-on: ubuntu-20.04
|
13
|
+
strategy:
|
14
|
+
fail-fast: false
|
15
|
+
matrix:
|
16
|
+
ruby: ['head', '3.2', '3.1', '3.0']
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v3
|
19
|
+
- uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{ matrix.ruby }}
|
22
|
+
bundler-cache: true
|
23
|
+
- run: bundle install
|
24
|
+
- run: bundle exec rspec
|
25
|
+
test-ruby:
|
26
|
+
runs-on: ubuntu-20.04
|
27
|
+
strategy:
|
28
|
+
fail-fast: false
|
29
|
+
matrix:
|
30
|
+
baseruby: ['3.0']
|
31
|
+
ruby_branch: ['master']
|
32
|
+
defaults:
|
33
|
+
run:
|
34
|
+
working-directory: ../ruby/build
|
35
|
+
steps:
|
36
|
+
- uses: actions/checkout@v3
|
37
|
+
- uses: ruby/setup-ruby@v1
|
38
|
+
with:
|
39
|
+
ruby-version: ${{ matrix.baseruby }}
|
40
|
+
bundler-cache: true
|
41
|
+
- run: git clone --depth=1 https://github.com/ruby/ruby.git -b ${{ matrix.ruby_branch }} ../ruby
|
42
|
+
working-directory:
|
43
|
+
- run: mkdir tool/lrama
|
44
|
+
working-directory: ../ruby
|
45
|
+
- name: Copy Lrama to ruby/tool
|
46
|
+
run: cp -r exe lib template ../ruby/tool/lrama
|
47
|
+
working-directory:
|
48
|
+
- run: tree tool/lrama
|
49
|
+
working-directory: ../ruby
|
50
|
+
# See also https://github.com/ruby/ruby/blob/master/.github/workflows/ubuntu.yml
|
51
|
+
- run: mkdir build
|
52
|
+
working-directory: ../ruby
|
53
|
+
- name: Set ENV
|
54
|
+
run: |
|
55
|
+
echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
|
56
|
+
- name: Install libraries
|
57
|
+
run: |
|
58
|
+
set -x
|
59
|
+
arch=${arch:+:${arch/i[3-6]86/i386}}
|
60
|
+
${arch:+sudo dpkg --add-architecture ${arch#:}}
|
61
|
+
sudo apt-get update -q || :
|
62
|
+
sudo apt-get install --no-install-recommends -q -y \
|
63
|
+
${arch:+cross}build-essential${arch/:/-} \
|
64
|
+
libssl-dev${arch} libyaml-dev${arch} libreadline6-dev${arch} \
|
65
|
+
zlib1g-dev${arch} libncurses5-dev${arch} libffi-dev${arch} \
|
66
|
+
autoconf
|
67
|
+
sudo apt-get install -q -y pkg-config${arch} || :
|
68
|
+
- run: sudo apt-get --purge remove bison
|
69
|
+
- run: ../autogen.sh
|
70
|
+
- run: ../configure -C --disable-install-doc
|
71
|
+
- run: make YACC=$(readlink -f $(pwd)/../tool/lrama/exe/lrama)
|
72
|
+
- run: make test-all
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LEGAL.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# LEGAL NOTICE INFORMATION
|
2
|
+
|
3
|
+
All the files in this distribution are covered under the MIT License except some files
|
4
|
+
mentioned below.
|
5
|
+
|
6
|
+
## GNU General Public License version 3
|
7
|
+
|
8
|
+
These files are licensed under the GNU General Public License version 3. See these files for more information.
|
9
|
+
|
10
|
+
* template/bison/yacc.c
|
11
|
+
* template/bison/yacc.h
|
12
|
+
|
13
|
+
## Same with Ruby
|
14
|
+
|
15
|
+
These files are licensed same with Ruby. See https://github.com/ruby/ruby/blob/master/COPYING for more information.
|
16
|
+
|
17
|
+
* spec/fixtures/integration/ruby_3_0_5/parse.tmp.y
|
18
|
+
* spec/fixtures/integration/ruby_3_0_5/y.tab.c
|
19
|
+
* spec/fixtures/integration/ruby_3_0_5/y.tab.h
|
20
|
+
* spec/fixtures/integration/ruby_3_1_0/parse.tmp.y
|
21
|
+
* spec/fixtures/integration/ruby_3_1_0/y.tab.c
|
22
|
+
* spec/fixtures/integration/ruby_3_1_0/y.tab.h
|
23
|
+
* spec/fixtures/integration/ruby_3_2_0/parse.tmp.y
|
24
|
+
* spec/fixtures/integration/ruby_3_2_0/y.tab.c
|
25
|
+
* spec/fixtures/integration/ruby_3_2_0/y.tab.h
|
26
|
+
|
data/MIT
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 Yuichiro Kaneko
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Lrama
|
2
|
+
|
3
|
+
Lrama is LALR (1) parser generator written by Ruby. The first goal of this project is providing error tolerant parser for CRuby with minimal changes on CRuby parse.y file.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
* Bison style grammar file is supported with some assumptions
|
8
|
+
* b4_locations_if is always true
|
9
|
+
* b4_pure_if is always true
|
10
|
+
* b4_pull_if is always false
|
11
|
+
* b4_lac_if is always false
|
12
|
+
* Error Tolerance parser
|
13
|
+
* Subset of [Repairing Syntax Errors in LR Parsers (Corchuelo et al.)](https://idus.us.es/bitstream/handle/11441/65631/Repairing%20syntax%20errors.pdf) algorithm is supported
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
```shell
|
18
|
+
$ bundle exec rake install
|
19
|
+
$ lrama --version
|
20
|
+
0.1.0
|
21
|
+
```
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
```shell
|
26
|
+
# "y.tab.c" is generated
|
27
|
+
$ lrama parse.y
|
28
|
+
```
|
29
|
+
|
30
|
+
## License
|
31
|
+
|
32
|
+
See LEGAL.md file.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/doc/TODO.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# TODO
|
2
|
+
|
3
|
+
* command
|
4
|
+
* [ ] Add "--bison" option
|
5
|
+
* lexer
|
6
|
+
* [x] Basic functionalities
|
7
|
+
* parser
|
8
|
+
* [x] Basic functionalities
|
9
|
+
* [x] Precedence in grammar
|
10
|
+
* LALR
|
11
|
+
* [x] compute_nullable
|
12
|
+
* [x] compute_lr0_states
|
13
|
+
* [x] Direct Read Sets
|
14
|
+
* [x] Reads Relation
|
15
|
+
* [x] Read Sets
|
16
|
+
* [x] Includes Relation
|
17
|
+
* [x] Lookback Relation
|
18
|
+
* [x] Follow Sets
|
19
|
+
* [x] Look-Ahead Sets
|
20
|
+
* [x] Precedence support
|
21
|
+
* [x] Conflict check
|
22
|
+
* [x] Algorithm Digraph
|
23
|
+
* Rendering
|
24
|
+
* [x] Table compaction
|
25
|
+
* [x] -d option
|
26
|
+
* yacc.c
|
27
|
+
* [ ] %lex-param
|
28
|
+
* [x] %parse-param
|
29
|
+
* [x] %printer
|
30
|
+
* [x] Replace $, @ in user codes
|
31
|
+
* [x] `[@oline@]`
|
32
|
+
* [ ] b4_symbol (for eof, error and so on)
|
33
|
+
* Assumption
|
34
|
+
* b4_locations_if is true
|
35
|
+
* b4_pure_if is true
|
36
|
+
* b4_pull_if is false
|
37
|
+
* b4_lac_if is false
|
38
|
+
* Performance improvement
|
39
|
+
* [ ]
|
40
|
+
* Licenses
|
41
|
+
* [x] Write down something about licenses
|
42
|
+
* Reporting
|
43
|
+
* [ ] Bison style
|
44
|
+
* Error Tolerance
|
45
|
+
* [x] Subset of Corchuelo et al.
|
46
|
+
* Lex state
|
47
|
+
* CI
|
48
|
+
* [x] Setup CI
|
49
|
+
* [x] Add ruby 3.1 or under
|
50
|
+
* [x] Add integration tests which installs Lrama, build ruby and run `make test`
|
data/exe/lrama
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Lrama
|
4
|
+
class Command
|
5
|
+
def run(argv)
|
6
|
+
opt = OptionParser.new
|
7
|
+
|
8
|
+
# opt.on('-h') {|v| p v }
|
9
|
+
opt.on('-V', '--version') {|v| puts Lrama::VERSION ; exit 0 }
|
10
|
+
|
11
|
+
# Tuning the Parser
|
12
|
+
skeleton = "bison/yacc.c"
|
13
|
+
|
14
|
+
opt.on('-S', '--skeleton=FILE') {|v| skeleton = v }
|
15
|
+
opt.on('-t') { } # Do nothing
|
16
|
+
|
17
|
+
# Output Files:
|
18
|
+
header = false
|
19
|
+
header_file = nil
|
20
|
+
report = []
|
21
|
+
report_file = nil
|
22
|
+
outfile = "y.tab.c"
|
23
|
+
|
24
|
+
opt.on('-h', '--header=[FILE]') {|v| header = true; header_file = v }
|
25
|
+
opt.on('-d') { header = true }
|
26
|
+
opt.on('-r', '--report=THINGS') {|v| report = v.split(',') }
|
27
|
+
opt.on('--report-file=FILE') {|v| report_file = v }
|
28
|
+
opt.on('-v') { } # Do nothing
|
29
|
+
opt.on('-o', '--output=FILE') {|v| outfile = v }
|
30
|
+
|
31
|
+
# Hidden
|
32
|
+
trace = []
|
33
|
+
opt.on('--trace=THINGS') {|v| trace = v.split(',') }
|
34
|
+
|
35
|
+
# Error Recovery
|
36
|
+
error_recovery = false
|
37
|
+
opt.on('-e') {|v| error_recovery = true }
|
38
|
+
|
39
|
+
opt.parse!(argv)
|
40
|
+
|
41
|
+
trace_opts = validate_trace(trace)
|
42
|
+
report_opts = validate_report(report)
|
43
|
+
|
44
|
+
grammar_file = argv.shift
|
45
|
+
|
46
|
+
if !report.empty? && report_file.nil? && grammar_file
|
47
|
+
report_file = File.dirname(grammar_file) + "/" + File.basename(grammar_file, ".*") + ".output"
|
48
|
+
end
|
49
|
+
|
50
|
+
if !header_file && header
|
51
|
+
case
|
52
|
+
when outfile
|
53
|
+
header_file = File.dirname(outfile) + "/" + File.basename(outfile, ".*") + ".h"
|
54
|
+
when grammar_file
|
55
|
+
header_file = File.dirname(grammar_file) + "/" + File.basename(grammar_file, ".*") + ".h"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if !grammar_file
|
60
|
+
puts "File should be specified\n"
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
|
64
|
+
Report::Duration.enable if trace_opts[:time]
|
65
|
+
|
66
|
+
y = File.read(grammar_file)
|
67
|
+
grammar = Lrama::Parser.new(y).parse
|
68
|
+
states = Lrama::States.new(grammar, trace_state: (trace_opts[:automaton] || trace_opts[:closure]))
|
69
|
+
states.compute
|
70
|
+
context = Lrama::Context.new(states)
|
71
|
+
|
72
|
+
if report_file
|
73
|
+
reporter = Lrama::StatesReporter.new(states)
|
74
|
+
File.open(report_file, "w+") do |f|
|
75
|
+
reporter.report(f, **report_opts)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
File.open(outfile, "w+") do |f|
|
80
|
+
Lrama::Output.new(
|
81
|
+
out: f,
|
82
|
+
output_file_path: outfile,
|
83
|
+
template_name: skeleton,
|
84
|
+
grammar_file_path: grammar_file,
|
85
|
+
header_file_path: header_file,
|
86
|
+
context: context,
|
87
|
+
grammar: grammar,
|
88
|
+
).render
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def validate_report(report)
|
95
|
+
list = %w[states itemsets lookaheads solved counterexamples cex all none]
|
96
|
+
not_supported = %w[counterexamples cex all none]
|
97
|
+
h = {}
|
98
|
+
|
99
|
+
report.each do |r|
|
100
|
+
if list.include?(r) && !not_supported.include?(r)
|
101
|
+
h[r.to_sym] = true
|
102
|
+
else
|
103
|
+
raise "Invalid report option \"#{r}\"."
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
return h
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate_trace(trace)
|
111
|
+
list = %w[
|
112
|
+
none locations scan parse automaton bitsets
|
113
|
+
closure grammar resource sets muscles tools
|
114
|
+
m4-early m4 skeleton time ielr cex all
|
115
|
+
]
|
116
|
+
h = {}
|
117
|
+
|
118
|
+
trace.each do |t|
|
119
|
+
if list.include?(t)
|
120
|
+
h[t.to_sym] = true
|
121
|
+
else
|
122
|
+
raise "Invalid trace option \"#{t}\"."
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
return h
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|