diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9827680..1da320a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: ruby: - 2.6 - 2.7 - - 3.0 + - "3.0" - 3.1 - ruby-head - jruby diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml new file mode 100644 index 0000000..b8d16ed --- /dev/null +++ b/.github/workflows/generate-docs.yml @@ -0,0 +1,27 @@ +name: Build & deploy documentation +on: + push: + branches: + - master + workflow_dispatch: +jobs: + build: + runs-on: ubuntu-latest + name: Update gh-pages with docs + steps: + - name: Clone repository + uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.1" + - name: Install required gem dependencies + run: gem install yard --no-document + - name: Build YARD Ruby Documentation + run: yardoc + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./doc/yard + publish_branch: gh-pages diff --git a/README.md b/README.md index 8c79112..6cfd5e3 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ ## Description This is a [Ruby][] implementation of an [EBNF][] and [BNF][] parser and parser generator. -### [PEG][]/[Packrat][] Parser -In the primary mode, it supports a Parsing Expression Grammar ([PEG][]) parser generator. This performs more minmal transformations on the parsed grammar to extract sub-productions, which allows each component of a rule to generate its own parsing event. +### [PEG][] / [Packrat][] Parser +In the primary mode, it supports a Parsing Expression Grammar ([PEG][]) parser generator. This performs more minimal transformations on the parsed grammar to extract sub-productions, which allows each component of a rule to generate its own parsing event. The resulting {EBNF::PEG::Rule} objects then parse each associated rule according to the operator semantics and use a [Packrat][] memoizer to reduce extra work when backtracking. @@ -77,13 +77,13 @@ Generate formatted grammar using HTML (requires [Haml][Haml] gem): The EBNF gem can also parse [ISO/EIC 14977] Grammars (ISOEBNF) to [S-Expressions][S-Expression]. - grammar = EBNF.parse(File.open('./etc/iso-ebnf.isoebnf', format: :isoebnf)) + grammar = EBNF.parse(File.open('./etc/iso-ebnf.isoebnf'), format: :isoebnf) ### Parsing an ABNF Grammar The EBNF gem can also parse [ABNF] Grammars to [S-Expressions][S-Expression]. - grammar = EBNF.parse(File.open('./etc/abnf.abnf', format: :abnf)) + grammar = EBNF.parse(File.open('./etc/abnf.abnf'), format: :abnf) ### Parser Debugging @@ -278,7 +278,7 @@ A copy of the [Turtle EBNF][] and derived parser files are included in the repos [ABNF]: https://www.rfc-editor.org/rfc/rfc5234 [BNF]: https://en.wikipedia.org/wiki/Backus–Naur_form [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation -[EBNF doc]: https://rubydoc.info/github/dryruby/ebnf +[EBNF doc]: https://dryruby.github.io/ebnf [First/Follow]: https://en.wikipedia.org/wiki/LL_parser#Constructing_an_LL.281.29_parsing_table [ISO/IEC 14977]:https://www.iso.org/standard/26153.html [LL(1)]: https://www.csd.uwo.ca/~moreno//CS447/Lectures/Syntax.html/node14.html diff --git a/VERSION b/VERSION index 276cbf9..2bf1c1c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3.0 +2.3.1 diff --git a/ebnf.gemspec b/ebnf.gemspec index 36b2306..5b60f1d 100755 --- a/ebnf.gemspec +++ b/ebnf.gemspec @@ -10,6 +10,12 @@ Gem::Specification.new do |gem| gem.license = 'Unlicense' gem.summary = "EBNF parser and parser generator in Ruby." gem.description = %q{EBNF is a Ruby parser for W3C EBNF and a parser generator for PEG and LL(1). Also includes parsing modes for ISO EBNF and ABNF.} + gem.metadata = { + "documentation_uri" => "https://dryruby.github.io/ebnf", + "bug_tracker_uri" => "https://github.com/dryruby/ebnf/issues", + "homepage_uri" => "https://github.com/dryruby/ebnf", + "source_code_uri" => "https://github.com/dryruby/ebnf", + } gem.authors = ['Gregg Kellogg'] gem.email = 'public-rdf-ruby@w3.org' diff --git a/examples/ebnf-peg-parser/README.md b/examples/ebnf-peg-parser/README.md index a51ccb3..2e3b91a 100644 --- a/examples/ebnf-peg-parser/README.md +++ b/examples/ebnf-peg-parser/README.md @@ -158,7 +158,7 @@ The `ebnf` production uses the `alt` operator. When matching the production itse [YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md [PDD]: https://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation -[EBNF doc]: https://rubydoc.info/github/dryruby/ebnf/ +[EBNF doc]: https://dryruby.github.io/ebnf [Packrat]: https://pdos.csail.mit.edu/~baford/packrat/thesis/ [PEG]: https://en.wikipedia.org/wiki/Parsing_expression_grammar [S-expression]: https://en.wikipedia.org/wiki/S-expression diff --git a/examples/isoebnf/README.md b/examples/isoebnf/README.md index 957fb6e..15b97f5 100644 --- a/examples/isoebnf/README.md +++ b/examples/isoebnf/README.md @@ -129,7 +129,7 @@ Looking at the grammar itself, we can see that the first declaration is [YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md [PDD]: https://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation -[EBNF doc]: https://rubydoc.info/github/dryruby/ebnf/ +[EBNF doc]: https://dryruby.github.io/ebnf [Packrat]: https://pdos.csail.mit.edu/~baford/packrat/thesis/ [PEG]: https://en.wikipedia.org/wiki/Parsing_expression_grammar [ISO/IEC 14977]:https://www.iso.org/standard/26153.html diff --git a/lib/ebnf/rule.rb b/lib/ebnf/rule.rb index 39625e6..37fb189 100644 --- a/lib/ebnf/rule.rb +++ b/lib/ebnf/rule.rb @@ -367,11 +367,11 @@ def to_peg def to_regexp case expr.first when :hex - Regexp.new(translate_codepoints(expr[1])) + Regexp.new(Regexp.escape(translate_codepoints(expr[1]))) when :istr /#{expr.last}/ui when :range - Regexp.new("[#{translate_codepoints(expr[1])}]") + Regexp.new("[#{escape_regexp_character_range(translate_codepoints(expr[1]))}]") else raise "Can't turn #{expr.inspect} into a regexp" end @@ -770,5 +770,11 @@ def make_sym_id(variation = nil) @id_seq += 1 ["_#{@sym}_#{@id_seq}#{variation}".to_sym, ("#{@id}.#{@id_seq}#{variation}" if @id)] end + + # Escape "[", "]", and "\" in ranges so they don't result in a warning or error + # about empty character classes. + def escape_regexp_character_range(character_range) + character_range.gsub(/([\[\]\\])/) {|char| "\\#{char}"} + end end -end \ No newline at end of file +end diff --git a/spec/rule_spec.rb b/spec/rule_spec.rb index bffb777..a11f56a 100644 --- a/spec/rule_spec.rb +++ b/spec/rule_spec.rb @@ -481,9 +481,13 @@ describe "#to_regexp" do { hex: [:hex, "#x20", / /], + hex: [:hex, "#x5c", /\\/], range: [:range, "a-b", /[a-b]/], range2: [:range, "a-zA-Z", /[a-zA-Z]/], range3: [:range, "abc-", /[abc-]/], + range4: [:range, "#x23-#x5b", /[#-\[]/], + range5: [:range, "#x5d-#x5e", /[\]-^]/], + range6: [:range, "#x5c-#x5e", /[\\-^]/], }.each do |title, (op, exp, regexp)| it title do expect(EBNF::Rule.new(title, nil, [op, exp]).to_regexp).to eql regexp @@ -1055,4 +1059,4 @@ end end end -end \ No newline at end of file +end