pax_global_header 0000666 0000000 0000000 00000000064 14652110230 0014504 g ustar 00root root 0000000 0000000 52 comment=5229883dca5b451c8bfd322272ccd2ca6d526695
racc-1.8.1/ 0000775 0000000 0000000 00000000000 14652110230 0012423 5 ustar 00root root 0000000 0000000 racc-1.8.1/.gitattributes 0000664 0000000 0000000 00000000030 14652110230 0015307 0 ustar 00root root 0000000 0000000 *.rb ident
*.rdoc ident
racc-1.8.1/.github/ 0000775 0000000 0000000 00000000000 14652110230 0013763 5 ustar 00root root 0000000 0000000 racc-1.8.1/.github/dependabot.yml 0000664 0000000 0000000 00000000321 14652110230 0016607 0 ustar 00root root 0000000 0000000 version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'
- package-ecosystem: 'bundler'
directory: '/'
schedule:
interval: 'weekly'
racc-1.8.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14652110230 0016020 5 ustar 00root root 0000000 0000000 racc-1.8.1/.github/workflows/test.yml 0000664 0000000 0000000 00000002502 14652110230 0017521 0 ustar 00root root 0000000 0000000 name: test
concurrency:
group: "${{github.workflow}}-${{github.ref}}"
cancel-in-progress: true
on:
workflow_dispatch:
pull_request:
types: [opened, synchronize]
branches:
- '*'
push:
schedule:
- cron: "0 8 * * 3" # At 08:00 on Wednesday # https://crontab.guru/#0_8_*_*_3
jobs:
ruby-versions:
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
with:
min_version: 2.5
test:
needs: ruby-versions
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
ruby: ${{fromJson(needs.ruby-versions.outputs.versions)}}
os: [ubuntu-latest, macos-latest, windows-latest]
exclude:
- {os: windows-latest, ruby: truffleruby-head}
- {os: windows-latest, ruby: truffleruby}
- {os: windows-latest, ruby: jruby-head}
- {os: windows-latest, ruby: jruby }
- {os: macos-latest, ruby: '2.5' }
- {os: macos-latest, ruby: truffleruby }
- {os: macos-latest, ruby: truffleruby-head }
- {os: macos-latest, ruby: jruby }
- {os: macos-latest, ruby: jruby-head }
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{matrix.ruby}}
- run: bundle install --jobs 4 --retry 3
- run: rake test
- run: rake build
racc-1.8.1/.gitignore 0000664 0000000 0000000 00000000231 14652110230 0014407 0 ustar 00root root 0000000 0000000 *.bundle
*.o
*.so
*.swp
/pkg
Makefile
lib/racc/parser-text.rb
tags
tmp
target
lib/java/racc/cparse-jruby.jar
lib/racc/cparse-jruby.jar
Gemfile.lock
html
racc-1.8.1/BSDL 0000664 0000000 0000000 00000002413 14652110230 0013072 0 ustar 00root root 0000000 0000000 Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
racc-1.8.1/COPYING 0000664 0000000 0000000 00000004573 14652110230 0013467 0 ustar 00root root 0000000 0000000 Ruby is copyrighted free software by Yukihiro Matsumoto .
You can redistribute it and/or modify it under either the terms of the
2-clause BSDL (see the file BSDL), or the conditions below:
1. You may make and give away verbatim copies of the source form of the
software without restriction, provided that you duplicate all of the
original copyright notices and associated disclaimers.
2. You may modify your copy of the software in any way, provided that
you do at least ONE of the following:
a. place your modifications in the Public Domain or otherwise
make them Freely Available, such as by posting said
modifications to Usenet or an equivalent medium, or by allowing
the author to include your modifications in the software.
b. use the modified software only within your corporation or
organization.
c. give non-standard binaries non-standard names, with
instructions on where to get the original software distribution.
d. make other distribution arrangements with the author.
3. You may distribute the software in object code or binary form,
provided that you do at least ONE of the following:
a. distribute the binaries and library files of the software,
together with instructions (in the manual page or equivalent)
on where to get the original distribution.
b. accompany the distribution with the machine-readable source of
the software.
c. give non-standard binaries non-standard names, with
instructions on where to get the original software distribution.
d. make other distribution arrangements with the author.
4. You may modify and include the part of the software into any other
software (possibly commercial). But some files in the distribution
are not written by the author, so that they are not under these terms.
For the list of those files and their copying conditions, see the
file LEGAL.
5. The scripts and library files supplied as input to or produced as
output from the software do not automatically fall under the
copyright of the software, but belong to whomever generated them,
and may be sold commercially, and may be aggregated with this
software.
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.
racc-1.8.1/ChangeLog 0000664 0000000 0000000 00000050157 14652110230 0014205 0 ustar 00root root 0000000 0000000 Tue Feb 20 18:45:45 2007 Minero Aoki
* lib/racc/grammar.rb (separated_by): last commit was wrong. use
optional default return value of #option.
Tue Feb 20 18:27:48 2007 Minero Aoki
* lib/racc/grammar.rb (separated_by): return [] for empty list.
Tue Nov 7 07:13:47 2006 Minero Aoki
* lib/racc/grammar.rb (Rule#prec): rule.prec{...} should set
action.
Tue Nov 7 06:38:57 2006 Minero Aoki
* lib/racc/grammar.rb: system call error on writing log file
should be ignored.
* lib/racc/grammar.rb: never define lvar which have same name with
block local variable.
* lib/racc/iset.rb: ditto.
* lib/racc/logfilegenerator.rb: ditto.
* lib/racc/parser.rb: ditto.
* lib/racc/state.rb: ditto.
* lib/racc/statetransitiontable.rb: ditto.
* test/test.rb: racc -c is obsolete, use --line-convert-all.
Sun Oct 29 13:27:30 2006 Minero Aoki
* lib/racc/grammarfileparser.rb: use String#lines instead of
#to_a.
* lib/racc/parserfilegenerator.rb: ditto.
* lib/racc/compat.rb: provide Object#__send.
* lib/racc/compat.rb: provide Object#__send!.
* lib/racc/compat.rb: provide String#lines.
Thu Aug 24 23:14:16 2006 Minero Aoki
* lib/racc/grammar.rb: report conflicts/useless if $DEBUG.
* lib/racc/statetransitiontable.rb: remove code for Ruby 1.4
compatibility.
Fri Aug 4 01:02:36 2006 Minero Aoki
* lib/racc/grammar.rb: #should_terminal should be called in
#check_terminals.
Fri Aug 4 00:44:56 2006 Minero Aoki
* bin/racc: getopts -> optparse.
* lib/racc/grammar.rb: value of error symbol is :error.
* lib/racc/grammar.rb (check_terminals): string symbols are
terminal.
* lib/racc/grammarfileparser.rb (add_rule_block): specified-prec
did not work.
Fri Aug 4 00:29:53 2006 Minero Aoki
* lib/racc/parserfilegenerator.rb
(serialize_integer_list_compressed): fix typo.
Thu Aug 3 22:20:34 2006 Minero Aoki
* bin/y2racc: fix filename.
Thu Aug 3 21:10:48 2006 Minero Aoki
* bin/y2racc: getopts -> optparse.
Thu Aug 3 19:35:34 2006 Minero Aoki
* setup.rb: updated.
Thu Aug 3 19:34:55 2006 Minero Aoki
* bin/racc2y: getopts -> optparse.
* bin/racc2y: rewrite code for new generator.
* lib/racc/grammar.rb (_regist): did not check @delayed rules (it
causes registering same dummy rules many times).
* lib/racc/grammarfileparser.rb: refactoring: simplify syntax.
* lib/racc/grammarfileparser.rb: new method
GrammarFileParser.parse.
* lib/racc/grammarfileparser.rb: new method
GrammarFileParser.parse_file.
Sat Jul 29 04:51:42 2006 Minero Aoki
* lib/racc/pre-setup: We need not make grammarfileparser.rb.
Sat Jul 29 04:30:33 2006 Minero Aoki
* lib/racc/grammar.rb: allow '|' operation with meta rules
(many, option...).
Sat Jul 29 03:17:20 2006 Minero Aoki
* lib/racc/grammar.rb (Grammar#parser_class): write log file when
$DEBUG=true.
* lib/racc/grammar.rb (Grammar.define): run block on a
Racc::Grammar::DefinitionEnv object, instead of a Racc::Grammar
object.
* lib/racc/grammar.rb (DefinitionEnv): new method #null.
* lib/racc/grammar.rb (DefinitionEnv): new method #many.
* lib/racc/grammar.rb (DefinitionEnv): new method #many1.
* lib/racc/grammar.rb (DefinitionEnv): new method #option.
* lib/racc/grammar.rb (DefinitionEnv): new method #seperated_by.
* lib/racc/grammar.rb (DefinitionEnv): new method #seperated_by1.
* lib/racc/grammar.rb (DefinitionEnv): new method #action.
Sat Jul 29 03:13:22 2006 Minero Aoki
* lib/racc/compat.rb: reduce warning.
Sun Jul 16 05:07:12 2006 Minero Aoki
* lib/racc/compat.rb: implement Enumerable#each_slice for Ruby
1.8.
* lib/racc/parserfilegenerator.rb: better output.
* ext/racc/cparse/cparse.c: always use VALUE instead of struct
cparse_params.
* ext/racc/cparse/cparse.c: mark params->value_v.
Thu Jul 6 20:44:48 2006 Minero Aoki
* lib/racc/grammar.rb: on-the-fly generator implemented.
* lib/racc/generator.rb -> statetransitiontable.rb,
parserfilegenerator.rb, logfilegenerator.rb.
* lib/racc/statetransitiontable.rb: new file.
* lib/racc/parserfilegenerator.rb: new file.
* lib/racc/logfilegenerator.rb: new file.
* lib/racc/grammarfileparser.rb.in: removed.
* lib/racc/grammarfileparser.rb: new file. uses on-the-fly
generator.
* misc/boot.rb: removed.
* lib/racc/static.rb: new file, to import static generator
(lib/racc.rb provides dynamic generator).
* lib/racc/grammar.rb: grand refactoring.
* lib/racc/sourcetext.rb: new method #to_s, #location.
* lib/racc/state.rb: compute NFA/DFA on demand.
* bin/racc: follow these changes.
Thu Jul 6 20:39:42 2006 Minero Aoki
* ext/racc/cparse/cparse.so: should mark VALUEs in cparse_params.
Tue Jul 4 02:24:27 2006 Minero Aoki
* bin/racc: simplify report code.
* lib/racc/grammar.rb: introduce new methods for racc command.
* lib/racc/states.rb: ditto.
* lib/racc/generator.rb: class CodeGenerator ->
ParserFileGenerator.
* lib/racc/generator.rb: new class ParserFileGenerator::Params.
* bin/racc: ditto.
* misc/boot.rb: ditto.
* lib/racc/grammarfileparser.rb.in: ditto.
* lib/racc/grammarfileparser.rb.in: merge grammarfilescanner.rb.
* lib/racc/grammarfilescanner.rb: removed.
* lib/racc/grammarfileparser.rb.in: parses user code blocks.
* lib/racc/usercodeparser.rb: removed.
* lib/racc/generator.rb: remove user code parsing code.
* lib/racc/grammarfileparser.rb.in: passes user code block by a
SourceText object.
* lib/racc/generator.rb: ditto.
* lib/racc/sourcetext.rb: new file.
* lib/racc/generator.rb: introduce DSL to describe file contents.
Tue Jul 4 02:15:36 2006 Minero Aoki
* lib/racc/debugflags.rb: remove unused class GenerationOptions.
Tue Jul 4 02:14:48 2006 Minero Aoki
* lib/racc/compat.rb: update coding style.
Mon Jul 3 04:34:32 2006 Minero Aoki
* lib/racc/compiler.rb: do not export Grammar/SymbolTable/States.
* lib/racc/compiler.rb: make a new class for debug flags
(Racc::DebugFlags).
* lib/racc/compiler.rb: removed.
* bin/racc: eliminate Racc::Compiler class.
* bin/racc: refactor profiling code.
* bin/racc: move file generation code to racc/generator.rb.
* misc/boot.rb: does not emulate Racc::Compiler interface.
* lib/racc.rb: new file to require whole generator.
* lib/racc/grammar.rb: class RuleTable -> Grammar.
* lib/racc/grammar.rb: Grammar.new does not accept a Compiler.
* lib/racc/grammar.rb: refactoring.
* lib/racc/grammarfileparser.rb.in: GrammarFileParser.new does not
accept a Compiler.
* lib/racc/grammarfileparser.rb.in: #parser takes more 2 args, a
filename and a base line number.
* lib/racc/grammarfileparser.rb.in: refactoring.
* lib/racc/output.rb -> generate.rb
* lib/racc/generate.rb: class Formatter -> CodeGenerator.
* lib/racc/generate.rb: CodeGenerator.new does not accept a
Compiler.
* lib/racc/generate.rb: a CodeGenerator got many parameters via
setter method.
* lib/racc/generate.rb: class VerboseOutputter ->
LogFileGenerator.
* lib/racc/generate.rb: LogFileGenerator.new does not accept a
Compiler.
* lib/racc/generate.rb: refactoring.
* lib/racc/state.rb: class StateTable -> States.
* lib/racc/state.rb: States.new does not accept a Compiler.
* lib/racc/state.rb: refactoring.
* test/test.rb: -Da is obsolete (I forgot what this flag is).
* test/test.rb: allow replacing racc via environment variable
$RACC.
Mon Jul 3 04:18:49 2006 Minero Aoki
* Makefile: new task bootstrap-force.
Sun Jul 2 19:46:58 2006 Minero Aoki
* test/ichk.y: update coding style.
Sun Jul 2 19:01:55 2006 Minero Aoki
* ext/racc/cparse/cparse.c: must require version.h to get
RUBY_VERSION_CODE.
Sun Jul 2 18:33:32 2006 Minero Aoki
* ext/racc/cparse/cparse.c: do not use rb_iterate to give a block
to the method, use rb_block_call instead. [ruby-dev:28445]
Mon Jun 19 02:38:18 2006 Minero Aoki
* bin/racc: -g option is now -t. -g option is obsolete and is an
alias of -t.
Mon Jun 19 02:35:59 2006 Minero Aoki
* ext/racc/cparse/cparse.c: K&R -> ANSI C.
Mon Nov 21 02:37:10 2005 Minero Aoki
* version 1.4.5 released.
Mon Nov 21 02:31:18 2005 Minero Aoki
* bin/racc: shebang line should include file extension.
* lib/racc/compat.rb: method removed: bug!.
* lib/racc/*.rb: racc compiler should not depend on
Racc::ParseError.
* lib/racc/*.rb: update copyright year.
* lib/racc/*.rb: update coding style.
* lib/racc/exception.rb: new file.
Mon Nov 21 00:49:18 2005 Minero Aoki
* Makefile: remove useless target `import'.
* Makefile: generate parser-text.rb.
* misc/dist.sh: setup.rb and COPYING is now in repository.
* misc/dist.sh: generate parser-text.rb.
Mon Nov 21 00:14:21 2005 Minero Aoki
* bin/racc: read racc/parser.rb from parser-text.rb.
* lib/racc/rubyloader.rb: no longer needed.
* lib/racc/pre-setup: new file.
* lib/racc/pre-setup: generate parser-text.rb.
* lib/racc/pre-setup: generate grammarfileparser.rb.
* misc/boot.rb: new method BootstrapCompiler.main.
* misc/boot.rb: new method BootstrapCompiler.generate, which is
used from pre-setup.
Mon Nov 21 00:09:04 2005 Minero Aoki
* bin/racc2y: refactoring.
* bin/y2racc: refactoring.
Sun Nov 20 23:46:42 2005 Minero Aoki
* lib/racc/pre-setup: new file.
Sun Nov 20 22:46:21 2005 Minero Aoki
* COPYING: new file.
Sun Nov 20 22:25:15 2005 Minero Aoki
* setup.rb: import setup.rb 3.4.1.
Thu Sep 29 02:51:56 2005 Minero Aoki
* Makefile (clean): invoke `make clean' in ext.
Thu Sep 29 02:50:56 2005 Minero Aoki
* lib/racc/.cvsignore: removed.
Thu Sep 29 02:46:30 2005 Minero Aoki
* Makefile: use .makeparams system.
* Makefile: unify lib/racc/Makefile.
* Makefile: new target lib/racc/grammarfileparser.rb.
* lib/racc/Makefile: unified by ./Makefile.
* lib/racc/boot: removed (moved under misc).
* misc/boot.rb: new file.
Thu Sep 29 02:43:30 2005 Minero Aoki
* setup.rb: new file.
Tue Jul 26 23:37:46 2005 Minero Aoki
* bin/racc: --no-omit-actions did not work (This patch is
contributed by OHKUBO Takuya).
Sun Jan 2 11:48:19 2005 Minero Aoki
* lib/racc/grammar.rb (once_writer): bug! needs argument.
Mon Feb 16 16:14:16 2004 Minero Aoki
* test/echk.y: fix typo.
* test/ichk.y: does not use amstd.
* test/opt.y: untabify.
Mon Feb 16 16:10:46 2004 Minero Aoki
* lib/racc/boot: update coding style.
* lib/racc/compat.rb: ditto.
* lib/racc/compiler.rb: ditto.
* lib/racc/grammar.rb: ditto.
* lib/racc/grammarfileparser.rb.in: ditto.
* lib/racc/grammarfilescanner.rb: ditto.
* lib/racc/info.rb: ditto.
* lib/racc/iset.rb: ditto.
* lib/racc/output.rb: ditto.
* lib/racc/parser.rb: ditto.
* lib/racc/state.rb: ditto.
* lib/racc/usercodeparser.rb: ditto.
Mon Feb 16 16:01:34 2004 Minero Aoki
* lib/racc/rubyloader.rb: imported rev1.6.
Fri Dec 12 01:57:47 2003 Minero Aoki
* sample/hash.y: use no_result_var option.
* sample/array.y: use latest (my) coding style.
* sample/array2.y: ditto.
* sample/hash.y: ditto.
* sample/lists.y: ditto.
Wed Nov 5 19:50:35 2003 Minero Aoki
* test/bench.y: remove dependency on amstd.
* test/chk.y: ditto.
* test/echk.y: ditto.
* test/ichk.y: ditto.
* test/intp.y: ditto.
* test/opt.y: ditto.
* test/percent.y: ditto.
Wed Nov 5 19:11:15 2003 Minero Aoki
* bin/racc (get_options): remove --no-extensions option;
racc/parser is preloaded, Racc_No_Extension does not work.
Mon Nov 3 22:41:42 2003 Minero Aoki
* bin/racc: apply latest coding style.
* lib/racc/parser.rb: ditto.
* lib/racc/compat.rb: add File.read.
Mon Nov 3 21:20:25 2003 Minero Aoki
* ext/racc/cparse/cparse.c (parse_main): abort if length of state
stack <=1, not ==0.
* lib/racc/parser.rb: use <=1, not <2.
* ext/racc/cparse/cparse.c: check_*() -> assert_*()
* ext/racc/cparse/cparse.c (racc_cparse): define lvar `v' for
debugging.
* ext/racc/cparse/cparse.c (racc_yyparse): ditto.
Mon Nov 3 17:21:55 2003 Minero Aoki
* Makefile (all): make cparse.so.
Mon Nov 3 17:19:26 2003 Minero Aoki
* lib/racc/parser.rb: update version.
* ext/racc/cparse/cparse.c: update version.
Mon Nov 3 17:19:01 2003 Minero Aoki
* Makefile: update version in parser.rb, cparse.c.
Sun Oct 12 23:49:58 2003 Minero Aoki
* version 1.4.4.
Sun Oct 12 23:49:40 2003 Minero Aoki
* bin/y2racc: did not work.
* bin/y2racc: -u options did not work.
Sun Oct 12 23:41:46 2003 Minero Aoki
* misc/dist.sh: cd before make.
Sun Oct 12 23:38:04 2003 Minero Aoki
* Makefile (site): create $siteroot/{ja,en}/man/racc/*.html.
Sun Oct 12 23:37:18 2003 Minero Aoki
* doc/parser.rrd.m: missing 'j'.
Sun Oct 12 23:29:11 2003 Minero Aoki
* Makefile: new target `doc'.
* Makefile: new target `clean'.
* lib/racc/Makefile: new target `clean'.
* misc/dist.sh: create documents before pack.
Sun Oct 12 23:27:58 2003 Minero Aoki
* doc/debug.rd.m: junk char was inserted.
* doc/index.html.m: en/ja text were mixed.
* doc/parser.rrd.m: add return values.
* doc/usage.html.m: fix hyper link.
Sun Oct 12 22:57:28 2003 Minero Aoki
* doc.en/changes.html, doc.ja/changes.html -> doc/NEWS.rd.m
* doc.en/command.html, doc.ja/command.html -> doc/command.html.m
* doc.en/debug.html, doc.ja/debug.html -> doc/debug.rd.m
* doc.en/grammar.html, doc.ja/grammar.html -> doc/grammar.rd.m
* doc.en/index.html, doc.ja/index.html -> doc/index.html.m
* doc.en/parser.html, doc.ja/parser.html -> doc/parser.rrd.m
* doc.en/usage.html, doc.ja/usage.html -> doc/usage.html.m
Sun Oct 12 18:46:21 2003 Minero Aoki
* web/racc.ja.html: update descriptions.
* web/racc.en.html: ditto.
Sun Oct 12 18:43:45 2003 Minero Aoki
* misc/dist.sh: remove web/ directory before distribute.
Sun Oct 12 18:37:29 2003 Minero Aoki
* Makefile: new target `site'.
* web/racc.ja.html: new file.
* web/racc.en.html: new file.
Sun Oct 12 18:30:55 2003 Minero Aoki
* misc/dist.sh: forgot to remove tmp comment out.
Sun Oct 12 18:12:09 2003 Minero Aoki
* lib/racc/info.rb: version 1.4.4.
Sun Oct 12 18:11:42 2003 Minero Aoki
* Makefile (dist): split out misc/dist.sh.
* misc/dist.sh: new file.
Sun Oct 12 17:18:47 2003 Minero Aoki
* README.en: update documents.
* README.ja: ditto.
* doc.en/changes.html: ditto.
* doc.en/command.html: ditto.
* doc.en/debug.html: ditto.
* doc.en/grammar.html: ditto.
* doc.en/index.html: ditto.
* doc.en/parser.html: ditto.
* doc.en/usage.html: ditto.
* doc.ja/changes.html: ditto.
* doc.ja/command.html: ditto.
* doc.ja/debug.html: ditto.
* doc.ja/index.html: ditto.
* doc.ja/parser.html: ditto.
* doc.ja/usage.html: ditto.
Sun Oct 12 16:24:46 2003 Minero Aoki
* sameple/calc-ja.y: simplify.
Sun Oct 12 16:24:16 2003 Minero Aoki
* misc/y2racc -> bin/y2racc
* misc/racc2y -> bin/racc2y
Sun Oct 12 15:56:30 2003 Minero Aoki
* bin/racc: follow method name change.
Sun Oct 12 15:34:14 2003 Minero Aoki
* Makefile: new target `test'.
* Makefile: missing $datadir.
Sun Oct 12 15:33:02 2003 Minero Aoki
* README.ja: update description.
* README.en: ditto.
Sun Oct 12 15:25:23 2003 Minero Aoki
* lib/racc/compiler.rb: adjust file names.
* lib/racc/grammarfileparser.rb.in: ditto.
* lib/racc/grammarfilescanner.rb: ditto.
Sun Oct 12 15:24:53 2003 Minero Aoki
* Makefile: new file.
Sun Oct 12 15:19:57 2003 Minero Aoki
* BUGS.en: removed.
* BUGS.ja: removed.
Sun Oct 12 15:10:38 2003 Minero Aoki
* racc -> bin/racc
* .cvsignore -> lib/racc/.cvsignore
* lib/racc/Makefile: new file.
* boot.rb -> lib/racc/boot
* compat.rb -> lib/racc/compat.rb
* compiler.rb -> lib/racc/compiler.rb
* grammar.rb -> lib/racc/grammar.rb
* in.raccp.rb -> lib/racc/grammarfileparser.rb.in
* raccs.rb -> lib/racc/grammarfilescanner.rb
* info.rb -> lib/racc/info.rb
* iset.rb -> lib/racc/iset.rb
* outpur.rb -> lib/racc/output.rb
* parser.rb -> lib/racc/parser.rb
* rubyloader.rb -> lib/racc/rubyloader.rb
* state.rb -> lib/racc/state.rb
* ucodep.rb -> lib/racc/usercodeparser.rb
* cparse/MANIFEST -> ext/racc/cparse/MANIFEST
* cparse/cparse.c -> ext/racc/cparse/cparse.c
* cparse/depend -> ext/racc/cparse/depend
* cparse/extconf.rb -> ext/racc/cparse/extconf.rb
* cparse/.cvsignore -> ext/racc/cparse/.cvsignore
Sun Oct 12 15:10:13 2003 Minero Aoki
* test/test.rb: use /bin/rm if exists.
Sun Oct 12 14:33:29 2003 Minero Aoki
* rubyloader.rb: imported from amstd, rev 1.5.
Sun Oct 12 14:24:47 2003 Minero Aoki
* boot.rb: reformat only.
* compiler.rb: ditto.
* grammar.rb: ditto.
* in.raccp.rb: ditto.
* iset.rb: ditto.
* output.rb: ditto.
* raccs.rb: ditto.
* state.rb: ditto.
Sun Oct 12 14:17:22 2003 Minero Aoki
* test/test.rb: refactoring.
Tue Jun 24 03:14:01 2003 Minero Aoki
* ucodep.rb: typo: Grammer -> Grammar
Mon May 26 23:06:58 2003 Minero Aoki
* compiler.rb: update copyright year.
* grammar.rb: ditto.
* in.raccp.rb: ditto.
* info.rb: ditto.
* iset.rb: ditto.
* output.rb: ditto.
* parser.rb: ditto.
* raccs.rb: ditto.
* state.rb: ditto.
* ucodep.rb: ditto.
Sun May 25 13:21:27 2003 Minero Aoki
* raccs.rb: update coding style.
Fri Nov 15 17:53:12 2002 Minero Aoki
* racc: changes style.
* parser.rb: ditto.
Fri Nov 15 17:11:52 2002 Minero Aoki
version 1.4.3.
Fri Nov 15 17:08:01 2002 Minero Aoki
* boot.rb, compiler.rb, grammar.rb, in.raccp.rb, iset.rb,
output.rb, parser.rb, racc, raccs.rb, state.rb, ucodep.rb,
misc/racc2y, misc/y2racc: follows (my) latest coding styles.
Thu Nov 14 14:39:53 2002 Minero Aoki
* raccs.rb: explicit method call for VCALL.
Wed Oct 16 15:45:11 2002 Minero Aoki
* parser.rb: reformat.
Fri Aug 9 18:21:01 2002 Minero Aoki
* cparse/cparse.c: use better variable/macro names.
Wed Aug 7 08:39:19 2002 Minero Aoki
* cparse/cparse.c: goto label requires stmt.
Mon Aug 5 21:53:07 2002 Minero Aoki
* cparse/cparse.c: grand refine.
* cparse/depend: re-added from ruby/ext/racc/cparse.
Tue Jun 4 00:15:28 2002 Minero Aoki
* boot.rb: allow to omit last 'end'.
Mon Jun 3 23:29:45 2002 Minero Aoki
* racc (write_table_file): shebang must placed on first line.
(reported by Hiroyuki Sato)
racc-1.8.1/Gemfile 0000664 0000000 0000000 00000000257 14652110230 0013722 0 ustar 00root root 0000000 0000000 source "https://rubygems.org"
group :development do
gem "rake", "13.0.6"
gem "rake-compiler", "1.2.3"
gem "test-unit", "3.6.1"
gem "test-unit-ruby-core", "1.0.5"
end
racc-1.8.1/README.ja.rdoc 0000664 0000000 0000000 00000003401 14652110230 0014620 0 ustar 00root root 0000000 0000000 = Racc
* https://github.com/ruby/racc
== DESCRIPTION:
Racc は LALR(1) パーサジェネレータです。
yacc の Ruby 版に相当します。
== 必要環境
* Ruby 2.5 以降
== インストール
gem インストール:
$ gem install racc
== テスト
sample/ 以下にいくつか Racc の文法ファイルのサンプルが用意
してあります。動くのも動かないのもありますが、少なくとも
calc-ja.y は動くのでこれを処理してみましょう。Racc をインス
トールしたあと
$ racc -ocalc.rb calc-ja.y
として下さい。処理は一瞬から数秒で終わるので、
$ ruby calc.rb
を実行してください。ちゃんと動いてますか?
Racc の文法など詳しいことは doc.ja/ ディレクトリ以下の HTML を
見てください。
== ライセンス
このパッケージに付属するファイルの著作権は青木峰郎が保持します。
ライセンスは Ruby ライセンスです。ただしユーザが書いた規則
ファイルや、Racc がそこから生成した Ruby スクリプトはその対象
外です。好きなライセンスで配布してください。
== バグなど
Racc を使っていてバグらしき現象に遭遇したら、下記のアドレスまで
メールをください。作者にはバグを修正する義務はありませんがその
意思はあります。また、そのときはできるだけバグを再現できる文法
ファイルを付けてください。
青木峰郎(あおきみねろう)
aamine@loveruby.net
http://i.loveruby.net
racc-1.8.1/README.rdoc 0000664 0000000 0000000 00000003062 14652110230 0014232 0 ustar 00root root 0000000 0000000 = Racc
* https://github.com/ruby/racc
== DESCRIPTION:
Racc is an LALR(1) parser generator.
It is written in Ruby itself, and generates Ruby program.
== Requirement
* Ruby 2.5 or later.
== Installation
gem install:
$ gem install racc
== Testing Racc
Racc comes with simple calculator. To compile this, on shell:
$ racc -o calc calc.y
This process costs few seconds (or less). Then type:
$ ruby calc
... Does it work?
For details of Racc, see HTML documents placed under 'doc/en/'
and sample grammar files under 'sample/'.
== Release flow
* Update VERSION number of these files
* RACC_VERSION in "ext/racc/com/headius/racc/Cparse.java"
* VERSION in "lib/racc/info.rb"
* Release as a gem by rake release with CRuby and JRuby because Racc gem provides 2 packages
* Create new release on {GitHub}[https://github.com/ruby/racc/releases]
== License
Racc is distributed under the same terms of ruby.
(see the file COPYING). Note that you do NOT need to follow
ruby license for your own parser (racc outputs).
You can distribute those files under any licenses you want.
== Bug Reports
Any kind of bug report is welcome.
If you find a bug of Racc, please report an issue at
https://github.com/ruby/racc/issues. Your grammar file,
debug output generated by "racc -g", are helpful.
Minero Aoki
aamine@loveruby.net
http://i.loveruby.net
racc-1.8.1/Rakefile 0000664 0000000 0000000 00000005317 14652110230 0014076 0 ustar 00root root 0000000 0000000 # -*- ruby -*-
require "bundler/gem_tasks"
require 'rdoc/task'
spec = Gem::Specification.load("racc.gemspec")
RDoc::Task.new(:docs) do |rd|
rd.main = "README.rdoc"
rd.rdoc_files.include(spec.files.find_all { |file_name|
file_name =~ /^(bin|lib|ext)/ || file_name !~ /\//
})
title = "#{spec.name}-#{spec.version} Documentation"
rd.options << "-t #{title}"
end
def java?
/java/ === RUBY_PLATFORM
end
def jruby?
Object.const_defined?(:RUBY_ENGINE) and 'jruby' == RUBY_ENGINE
end
file 'lib/racc/parser-text.rb' => ['lib/racc/parser.rb', 'lib/racc/info.rb', __FILE__] do |t|
source = 'lib/racc/parser.rb'
text = File.read(source)
text.sub!(/\A# *frozen[-_]string[-_]literal:.*\n/, '')
text.gsub!(/^require '(.*)'$/) do
lib = $1
code = File.read("lib/#{lib}.rb")
code.sub!(/\A(?:#.*\n)+/, '')
%[unless $".find {|p| p.end_with?('/#{lib}.rb')}\n$".push "\#{__dir__}/#{lib}.rb"\n#{code}\nend\n]
rescue
$&
end
File.open(t.name, 'wb') { |io|
io.write(<<-eorb)
module Racc
PARSER_TEXT = <<'__end_of_file__'
#{text}
__end_of_file__
end
eorb
}
end
javasrc, = Dir.glob('ext/racc/**/Cparse.java')
task :compile => javasrc do
code = File.binread(javasrc)
if code.sub!(/RACC_VERSION\s*=\s*"\K([^"]*)(?=")/) {|v| break if v == spec.version; spec.version}
File.binwrite(javasrc, code)
end
end
lib_dir = nil # for dummy rake/extensiontask.rb at ruby test-bundled-gems
if jruby?
# JRUBY
require "rake/javaextensiontask"
extask = Rake::JavaExtensionTask.new("cparse") do |ext|
jruby_home = RbConfig::CONFIG['prefix']
lib_dir = (ext.lib_dir << "/#{ext.platform}/racc")
ext.ext_dir = 'ext/racc'
# source/target jvm
ext.source_version = '1.8'
ext.target_version = '1.8'
jars = ["#{jruby_home}/lib/jruby.jar"] + FileList['lib/*.jar']
ext.classpath = jars.map { |x| File.expand_path x }.join( ':' )
ext.name = 'cparse-jruby'
end
task :build => "#{extask.lib_dir}/#{extask.name}.jar"
else
# MRI
require "rake/extensiontask"
extask = Rake::ExtensionTask.new "cparse" do |ext|
lib_dir = (ext.lib_dir << "/#{RUBY_VERSION}/#{ext.platform}/racc")
ext.ext_dir = 'ext/racc/cparse'
end
end
desc 'Make autogenerated sources'
task :srcs => ['lib/racc/parser-text.rb']
task :compile => :srcs
task :build => :srcs
task :test => :compile
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.libs << lib_dir if lib_dir
t.libs << "test/lib"
ENV["RUBYOPT"] = "-I" + t.libs.join(File::PATH_SEPARATOR)
t.ruby_opts << "-rhelper"
t.test_files = FileList["test/**/test_*.rb"]
if RUBY_VERSION >= "2.6"
t.ruby_opts << "--enable-frozen-string-literal"
t.ruby_opts << "--debug=frozen-string-literal" if RUBY_ENGINE != "truffleruby"
end
end
racc-1.8.1/TODO 0000664 0000000 0000000 00000000255 14652110230 0013115 0 ustar 00root root 0000000 0000000 * check 'error' token handling.
* interactive transition table monitor.
* support backtracking.
* output Ruby extension library?
* LL(k)? (But it should not be called Racc)
racc-1.8.1/bin/ 0000775 0000000 0000000 00000000000 14652110230 0013173 5 ustar 00root root 0000000 0000000 racc-1.8.1/bin/racc 0000775 0000000 0000000 00000021503 14652110230 0014032 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby
#
#
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
# You can distribute/modify this program under the same terms of ruby.
# see the file "COPYING".
require 'racc/static'
require 'optparse'
def main
output = nil
debug_parser = false
make_logfile = false
logfilename = nil
make_executable = false
rubypath = nil
embed_runtime = false
frozen_strings = false
debug_flags = Racc::DebugFlags.new
line_convert = true
line_convert_all = false
omit_action_call = true
superclass = nil
check_only = false
verbose = false
profiler = RaccProfiler.new(false)
parser = OptionParser.new
parser.banner = "Usage: #{File.basename($0)} [options] [input]"
parser.on('-o', '--output-file=PATH',
'output file name [.tab.rb]') {|name|
output = name
}
parser.on('-t', '--debug', 'Outputs debugging parser.') {|fl|
debug_parser = fl
}
parser.on('-g', 'Equivalent to -t (obsolete).') {|fl|
$stderr.puts "racc -g is obsolete. Use racc -t instead." if $VERBOSE
debug_parser = fl
}
parser.on('-v', '--verbose',
'Creates .output log file.') {|fl|
make_logfile = fl
}
parser.on('-O', '--log-file=PATH',
'Log file name [.output]') {|path|
make_logfile = true
logfilename = path
}
parser.on('-e', '--executable [RUBYPATH]', 'Makes executable parser.') {|path|
make_executable = true
rubypath = (path == 'ruby' ? nil : path)
}
parser.on('-E', '--embedded', "Embeds Racc runtime in output.") {
embed_runtime = true
}
parser.on('-F', '--frozen', "Add frozen_string_literals: true.") {
frozen_strings = true
}
parser.on('--line-convert-all', 'Converts line numbers of user codes.') {
line_convert_all = true
}
parser.on('-l', '--no-line-convert', 'Never convert line numbers.') {
line_convert = false
line_convert_all = false
}
parser.on('-a', '--no-omit-actions', 'Never omit actions.') {
omit_action_call = false
}
parser.on('--superclass=CLASSNAME',
'Uses CLASSNAME instead of Racc::Parser.') {|name|
superclass = name
}
parser.on('-C', '--check-only', 'Checks syntax and quit immediately.') {|fl|
check_only = fl
}
parser.on('-S', '--output-status', 'Outputs internal status time to time.') {
verbose = true
}
parser.on('-P', 'Enables generator profile') {
profiler = RaccProfiler.new(true)
}
parser.on('-D flags', "Flags for Racc debugging (do not use).") {|flags|
debug_flags = Racc::DebugFlags.parse_option_string(flags)
}
#parser.on('--no-extensions', 'Run Racc without any Ruby extension.') {
# Racc.const_set :Racc_No_Extensions, true
#}
parser.on('--version', 'Prints version and quit.') {
puts "racc version #{Racc::Version}"
exit
}
parser.on('--runtime-version', 'Prints runtime version and quit.') {
printf "racc runtime version %s; %s core version %s\n",
Racc::Parser::Racc_Runtime_Version,
Racc::Parser.racc_runtime_type,
if Racc::Parser.racc_runtime_type == 'ruby'
Racc::Parser::Racc_Runtime_Core_Version_R
else
Racc::Parser::Racc_Runtime_Core_Version_C
end
exit
}
parser.on('--copyright', 'Prints copyright and quit.') {
puts Racc::Copyright
exit
}
parser.on('--help', 'Prints this message and quit.') {
puts parser.help
exit
}
begin
parser.parse!
rescue OptionParser::ParseError => err
abort [err.message, parser.help].join("\n")
end
if ARGV.size > 1
abort 'too many input'
end
input = ARGV[0] || "stdin"
if input == "stdin" && !output then
abort 'You must specify a path to read or use -o for output.'
end
begin
$stderr.puts 'Parsing grammar file...' if verbose
result = profiler.section('parse') {
parser = Racc::GrammarFileParser.new(debug_flags)
content = input == "stdin" ? ARGF.read : File.read(input)
parser.parse(content, File.basename(input))
}
if check_only
$stderr.puts 'syntax ok'
exit
end
$stderr.puts 'Generating LALR states...' if verbose
states = profiler.section('nfa') {
Racc::States.new(result.grammar).nfa
}
$stderr.puts "Resolving #{states.size} states..." if verbose
profiler.section('dfa') {
states.dfa
}
$stderr.puts 'Creating parser file...' if verbose
params = result.params.dup
params.filename = File.basename(input)
# Overwrites parameters given by a grammar file with command line options.
params.superclass = superclass if superclass
params.omit_action_call = true if omit_action_call
# From command line option
if make_executable
params.make_executable = true
params.interpreter = rubypath
end
params.debug_parser = debug_parser
params.convert_line = line_convert
params.convert_line_all = line_convert_all
params.embed_runtime = embed_runtime
params.frozen_strings = frozen_strings
profiler.section('generation') {
generator = Racc::ParserFileGenerator.new(states, params)
generator.generate_parser_file(output || make_filename(input, '.tab.rb'))
}
if make_logfile
profiler.section('logging') {
$stderr.puts 'Creating log file...' if verbose
logfilename ||= make_filename(output || File.basename(input), '.output')
File.open(logfilename, 'w') {|f|
Racc::LogFileGenerator.new(states, debug_flags).output f
}
}
end
if debug_flags.status_logging
log_useless states.grammar
log_conflict states
else
has_useless = report_useless states.grammar
has_conflicts = report_conflict states
if has_useless || has_conflicts
preamble = make_logfile ? 'C' : 'Turn on logging with "-v" and c'
$stderr.puts %Q{#{preamble}heck ".output" file for details}
end
end
profiler.report
if states.should_error_on_expect_mismatch?
raise Racc::CompileError, "#{states.grammar.n_expected_srconflicts} shift/reduce conflicts are expected but #{states.n_srconflicts} shift/reduce conflicts exist"
end
rescue Racc::Error, Errno::ENOENT, Errno::EPERM => err
raise if $DEBUG or debug_flags.any?
lineno = err.message.slice(/\A\d+:/).to_s
abort "#{File.basename $0}: #{input}:#{lineno} #{err.message.strip}"
end
end
def make_filename(path, suffix)
path.sub(/(?:\..*?)?\z/, suffix)
end
LIST_LIMIT = 10
def report_list(enum, label)
c = enum.count
if c > 0
$stderr.puts "#{c} #{label}:"
enum.first(LIST_LIMIT).each do |item|
$stderr.puts " #{yield item}"
end
$stderr.puts " ..." if c > LIST_LIMIT
end
end
# @return [Boolean] if anything was reported
def report_conflict(states)
if states.should_report_srconflict?
reported = true
$stderr.puts "#{states.n_srconflicts} shift/reduce conflicts"
end
if states.rrconflict_exist?
reported = true
$stderr.puts "#{states.n_rrconflicts} reduce/reduce conflicts"
end
reported
end
def log_conflict(states)
logging('w') {|f|
f.puts "ex#{states.grammar.n_expected_srconflicts}"
if states.should_report_srconflict?
f.puts "sr#{states.n_srconflicts}"
end
if states.rrconflict_exist?
f.puts "rr#{states.n_rrconflicts}"
end
}
end
# @return [Boolean] if anything was reported
def report_useless(grammar)
reported = report_list(grammar.each_useless_nonterminal, 'useless nonterminals', &:to_s)
reported ||= report_list(grammar.each_useless_rule, 'useless rules') { |r| "##{r.ident} (#{r.target})" }
if grammar.start.useless?
$stderr.puts 'fatal: start symbol does not derive any sentence'
reported = true
end
reported
end
def log_useless(grammar)
logging('a') {|f|
if grammar.useless_nonterminal_exist?
f.puts "un#{grammar.n_useless_nonterminals}"
end
if grammar.useless_rule_exist?
f.puts "ur#{grammar.n_useless_rules}"
end
}
end
def logging(mode, &block)
File.open("log/#{File.basename(ARGV[0])}", mode, &block)
end
class RaccProfiler
def initialize(really)
@really = really
@log = []
end
def section(name)
if @really
t1 = ::Process.times.utime
result = yield
t2 = ::Process.times.utime
@log.push [name, t2 - t1]
result
else
yield
end
end
def report
return unless @really
f = $stderr
total = cumulative_time()
f.puts '--task-----------+--sec------+---%-'
@log.each do |name, time|
f.printf "%-19s %s %3d%%\n", name, pjust(time,4,4), (time/total*100).to_i
end
f.puts '-----------------+-----------+-----'
f.printf "%-20s%s\n", 'total', pjust(total,4,4)
end
private
def cumulative_time
t = @log.inject(0) {|sum, (name, time)| sum + time }
t == 0 ? 0.01 : t
end
def pjust(num, i, j)
m = /(\d+)(\.\d+)?/.match(num.to_s)
str = m[1].rjust(i)
str.concat m[2].ljust(j+1)[0,j+1] if m[2]
str
end
end
main
racc-1.8.1/doc/ 0000775 0000000 0000000 00000000000 14652110230 0013170 5 ustar 00root root 0000000 0000000 racc-1.8.1/doc/en/ 0000775 0000000 0000000 00000000000 14652110230 0013572 5 ustar 00root root 0000000 0000000 racc-1.8.1/doc/en/Overview-of-racc.md 0000664 0000000 0000000 00000025724 14652110230 0017244 0 ustar 00root root 0000000 0000000 This post follows from [Overview of rexical part 2](https://github.com/tenderlove/rexical/wiki/Overview-of-rexical-part-2). Taken from Jeff Nyman's [blog post](http://webcache.googleusercontent.com/search?q=cache:http://testerstories.com/2012/06/a-tester-learns-rex-and-racc-part-3/&num=1&strip=1&vwsrc=0).
# Combining rexical and racc
Assuming you’ve been following along, you’ve broken your input into a stream of tokens. Now you need some way to recognize higher-level patterns. This is where Racc comes in: Racc lets you describe what you want to do with those tokens. That’s what I’ll be covering here: how the parser works with the lexer.
You already know that you define a lexer specification with a rex file. This generates a lexer class. In a very similar fashion, you define a grammar with a racc file. This generates a parser class. If you want your own parser, you have to write grammar file. In the last post we started creating a new simple language to handle calculations of numbers. The language will consist of `ADD (+)`, `SUBTRACT (-)`, `MULTIPLY (*)`, and `DIVISION (/)`. Those operators are given as the symbol identifier as well as the actual symbol that maps to that identifier. The language also supports the notion of `DIGIT`. A `DIGIT` token must come before and after an operator. So there’s our language. Now we want to try to evaluate the code of this new language.
You have to create a grammar file. The first part of this file, as with the Rex specification file, is a class block. In your project directory, create a file called `test_language.y`. This will be our grammar file. As with the start of our Rex file, we’ll use our class:
``` ruby
class TestLanguage
end
```
Then you will have a grammar block. In Rex, the grammar block is a way to specify the patterns for specific symbols. In Racc, the grammar block describes grammar that can be understood by the parser. As with Rex specification files, we’ll eventually add a rule clause to signify our grammar block. In fact, this clause will mark the start of what are called the “production rules.” To fill in these rules, you have to understand the Racc grammar. So let’s just look at the basics before we try to fill in our nascent grammar file.
A grammar rule has the form:
```
some : THING ;
```
The symbols produced by a lexer are called terminals or tokens. The things assembled from them are called non-terminals. So in this schematic, ‘some’ represents a non-terminal while ‘THING’ is a terminal. So ‘THING’ must have been produced by the lexer and ‘some’ can only be created by assembling it from terminals. Here’s an example:
```
value : DIGIT ;
```
This means a construct called a value (a non-terminal) can be built up from a DIGIT (a terminal). Here’s another example:
```
expression : value '+' value ;
```
Here an expression can be built up from two values (which we know are DIGITS) and a plus sign. You can specify alternatives as well:
```
expression : value '+' value | value '-' value ;
```
Some people like to space all this out for better readability:
```
expression
:
value '+' value
| value '-' value
;
```
There’s a lot of terminology coming your way here so, for now, just understand that terminals are all the basic symbols or tokens of which a given language is composed. Non-terminals are the syntactic variables in the grammar which represent a set of strings that the grammar is composed of. The general style used is to have all terminals in uppercase and all non-terminals in lowercase.
As with Rex grammar, you can write actions inside curly braces. These actions are, once again, Ruby code. Since Racc needs tokens upon which to operate, Racc expects to call a method that yields tokens, where each token is a two element array with the first element being the type of token (matching the token declaration) and the second element the actual value of the token, which will usually be the actual text. This is a lot easier to show than talk about, although in reality it’s not so different from what you’ve seen with Rex files. So here’s an example:
```
expression : value '+' value { puts "Performing addition." }
```
But I could also do this:
```
expression : value '+' value { result = val[0] + val[2] }
```
If you ever read documentation on yacc, you’ll see mention of variables like `$$` and `$1` and so on. The equivalent of the above in yacc would be:
```
expression : value '+' value { $$ = $1 + $3; }
```
Here yacc’s `$$` is racc’s `result`, while yacc’s `$0`, `$1` would be the array `val`. Since Ruby is zero based, that’s why `$1` is `val[0]`. Okay, so let’s put this stuff to use. Change your grammar file so it looks like this:
``` ruby
class TestLanguage
rule
expression : DIGIT
| DIGIT ADD DIGIT { return val[0] + val[2] }
end
```
What I’m basically saying here is that something I want to call an “expression” can be recognized if it’s a `DIGIT` or a `DIGIT ADD DIGIT`. From the lexer file, we know that `DIGIT` is going to correspond to an array like this: `[:DIGIT, text.to_i]`. We know that `ADD` is going to correspond to an array like this `[:ADD, text]`. Further, we know that `DIGIT` means `\d+` (i.e., any group of numbers) and `ADD` means `\+` (i.e., the literal plus sign). I’m also saying that when `DIGIT` is encountered nothing should happen. There is no action provided for that. But if `DIGIT ADD DIGIT` is encountered, then I want a return value provided, which is the addition of the first `DIGIT` with the second `DIGIT`.
In order to compile this file, you can use the following command:
```
racc test_language.y -o parser.rb
```
To make that process more streamlined, let’s add a task to our Rakefile:
``` ruby
desc "Generate Parser"
task :parser do
`racc test_language.y -o parser.rb`
end
```
Now you can just type `rake parser` to generate the parser just as you can type `rake lexer` to generate the lexer. In fact, you might always want to force both things to happen, in which case you can add this task:
``` ruby
desc "Generate Lexer and Parser"
task :generate => [:lexer, :parser]
```
So how do we test this? Let’s create a file in our spec directory called `language_parser_spec.rb` and add the following to it:
``` ruby
require './parser.rb'
class TestLanguageParser
describe 'Testing the Parser' do
before do
@evaluator = TestLanguage.new
end
it 'tests for a digit' do
@result = @evaluator.parse("2")
@result.should == 2
end
end
end
```
Structurally you can see that this is similar to the test format we established in our `language_lexer_spec.rb` file. Running this test will tell you that there is no parse method. That’s true. Just as we added a tokenize method to our rex specification, we have to add a parse method to our grammar file. Here’s how you can do that:
``` ruby
class TestLanguage
rule
expression : DIGIT
| DIGIT ADD DIGIT { return val[0] + val[2] }
end
---- inner
def parse(input)
scan_str(input)
end
```
Once again, we use an inner section just as we did with our rex specification. Notice a few major differences here, though. First, you must preface the section with four hyphens (-). Also, notice that the inner section is **OUTSIDE** of the class block. This is different from the rex specification where the inner section was inside the class block. Make sure to regenerate your files and then run the test again. Now you will be told that the `scan_str` method is undefined. This method is defined in the lexer and so you have to add another section to your grammar file:
``` ruby
class TestLanguage
rule
expression : DIGIT
| DIGIT ADD DIGIT { return val[0] + val[2] }
end
---- header
require_relative 'lexer'
---- inner
def parse(input)
scan_str(input)
end
```
If you regenerate and run your test, the parser test should pass. However, we have not made it do a calculation yet. So add the following test:
``` ruby
...
it 'tests for addition' do
@result = @evaluator.parse("2+2")
@result.should == 4
end
...
```
If that’s working for you, congratulations! You now have the start of a working language. Granted, it’s just a calculator example but let’s not leave it just doing addition. You can fill out the rest of the grammar file as such:
``` ruby
class TestLanguage
rule
expression : DIGIT
| DIGIT ADD DIGIT { return val[0] + val[2] }
| DIGIT SUBTRACT DIGIT { return val[0] - val[2] }
| DIGIT MULTIPLY DIGIT { return val[0] * val[2] }
| DIGIT DIVIDE DIGIT { return val[0] / val[2] }
end
---- header
require_relative 'lexer'
---- inner
def parse(input)
scan_str(input)
end
```
I’ll leave it as an exercise to fill in the existing tests to prove that the grammar for all calculation types is being read and processed correctly.
This simple example still leaves a lot open. For example, while `2+2` will work `2 + 2` (with spaces) will not. This is because your lexer did not specify any white space and thus the parser does not know how to recognize it. Also, what about more complicated expressions? Can I do `2+2+2`? Try it and you’ll find that it does not. And even if I could support that, how would I handle operator precedence? For example would `2+3*2` give me `8`, as it should, or would it instead give me `10`?
Keep in mind that in order to solve problems like this, you have to account for how your grammar can be constructed. For example, to allow for spaces, you just have to indicate that (1) blank spaces are allowed and (2) that no action occurs when a blank space is matched. In fact, you’ve already seen this in prior examples here. Just add the following to your rex specification file (`test_language.rex`):
``` ruby
class TestLanguage
macro
BLANK [\ \t]+
DIGIT \d+
ADD \+
SUBTRACT \-
MULTIPLY \*
DIVIDE \/
rule
{BLANK} # no action
{DIGIT} { [:DIGIT, text.to_i] }
{ADD} { [:ADD, text] }
{SUBTRACT} { [:SUBTRACT, text] }
{MULTIPLY} { [:MULTIPLY, text] }
{DIVIDE} { [:DIVIDE, text] }
inner
def tokenize(code)
scan_setup(code)
tokens = []
while token = next_token
tokens << token
end
tokens
end
end
```
That simple bit of extra information allows your parser to handle `2 + 2` as well as it does `2+2`. The other problems are a little more involved. And with that, perhaps you can see now that even with a simple calculator, it takes some work to get it to do what you want in terms of a language. And yet all programming languages that you work with are ultimately constructed of grammar specified just in the way we have been doing it here.
I’ve learned a lot by trying to figure out how these tools work. One of my goals is to see if I can build an alternative to Gherkin, the language that is used by Cucumber to create what are called feature files. I think this will be a challenging exercise. Beyond that, I can see some good exercises here for constructing test grammars for test description languages. Playing around with concepts like these could, perhaps, lead to some interesting notions about how we communicate about tests.
racc-1.8.1/doc/en/grammar.en.rdoc 0000664 0000000 0000000 00000011423 14652110230 0016473 0 ustar 00root root 0000000 0000000 = Racc Grammar File Reference
== Global Structure
== Class Block and User Code Block
There are two top-level blocks: the 'class' block, and the 'user code'
block. The 'user code' block MUST be after the 'class' block.
== Comment
Comments can be added about everywhere. Two comment styles are
supported: Ruby style (`# ...`) and C style (`/* ... */`).
== Class Block
The class block is formed like this:
class CLASS_NAME
[precedence table]
[token declarations]
[expected number of S/R conflict]
[options]
[semantic value conversion]
[start rule]
rule
GRAMMARS
CLASS_NAME is a name of parser class.
This is the name of generating parser class.
If CLASS_NAME includes '::', Racc outputs module clause.
For example, writing "class M::C" causes creating the code below:
module M
class C
:
:
end
end
== Grammar Block
The grammar block describes the grammar
to be understood by parser. Syntax is:
(token): (token) (token) (token).... (action)
(token): (token) (token) (token).... (action)
| (token) (token) (token).... (action)
| (token) (token) (token).... (action)
(action) is an action which is executed when its (token)s are found.
(action) is a ruby code block, which is surrounded by braces:
{ print val[0]
puts val[1] }
Note that you cannot use '%' string, here document, '%r' regexp in action.
Actions can be omitted.
When it is omitted, '' (empty string) is used.
A return value of action is a value of left side value ($$).
It is value of result, or returned value by "return" statement.
Here is an example of whole grammar block.
rule
goal: definition rules source { result = val }
definition: /* none */ { result = [] }
| definition startdesig { result[0] = val[1] }
| definition
precrule # this line continue from upper line
{
result[1] = val[1]
}
startdesig: START TOKEN
You can use following special local variables in action.
* result ($$)
The value of left-hand side (lhs). A default value is val[0].
* val ($1,$2,$3...)
An array of value of right-hand side (rhs).
* _values (...$-2,$-1,$0)
A stack of values.
DO NOT MODIFY this stack unless you know what you are doing.
== Operator Precedence
This function is equal to '%prec' in yacc.
To designate this block:
prechigh
nonassoc '++'
left '*' '/'
left '+' '-'
right '='
preclow
`right' is yacc's %right, `left' is yacc's %left.
`=' + (symbol) means yacc's %prec:
prechigh
nonassoc UMINUS
left '*' '/'
left '+' '-'
preclow
rule
exp: exp '*' exp
| exp '-' exp
| '-' exp =UMINUS # equals to "%prec UMINUS"
:
:
== expect
Racc supports Bison's "expect" directive to declare the expected
number of shift/reduce conflicts.
class MyParser
expect 3
rule
:
:
Then warnings are issued only when the effective number of conflicts differs.
== Declaring Tokens
Declaring tokens avoids many bugs.
Racc outputs warnings for declared tokens that do not exist, or existing tokens not declared.
The syntax is:
token TOKEN_NAME AND_IS_THIS
ALSO_THIS_IS AGAIN_AND_AGAIN THIS_IS_LAST
== Options
You can write options for racc command in your racc file.
options OPTION OPTION ...
Options are:
* omit_action_call
omit empty action call or not.
* result_var
use/does not use local variable "result"
You can use 'no_' prefix to invert its meanings.
== Converting Token Symbol
Token symbols are, as default,
* naked token strings in racc file (TOK, XFILE, this_is_token, ...)
--> symbol (:TOK, :XFILE, :this_is_token, ...)
* quoted strings (':', '.', '(', ...)
--> same string (':', '.', '(', ...)
You can change this default using a "convert" block.
Here is an example:
convert
PLUS 'PlusClass' # We use PlusClass for symbol of `PLUS'
MIN 'MinusClass' # We use MinusClass for symbol of `MIN'
end
We can use almost all ruby value can be used by token symbol,
except 'false' and 'nil'. These are causes unexpected parse error.
If you want to use String as token symbol, special care is required.
For example:
convert
class '"cls"' # in code, "cls"
PLUS '"plus\n"' # in code, "plus\n"
MIN "\"minus#{val}\"" # in code, \"minus#{val}\"
end
== Start Rule
'%start' in yacc. This changes the start symbol.
start real_target
== User Code Block
A "User Code Block" is a piece of Ruby source code copied in the output.
There are three user code blocks, "header" "inner" and "footer".
User code blocks are introduced by four '-' at the beginning of a line,
followed by a single-word name:
---- header
ruby statement
ruby statement
ruby statement
---- inner
ruby statement
:
:
racc-1.8.1/doc/en/grammar2.en.rdoc 0000664 0000000 0000000 00000011741 14652110230 0016560 0 ustar 00root root 0000000 0000000 = Racc Grammar File Reference
== Global Structure
== Class Block and User Code Block
There are two blocks on the toplevel. One is the 'class' block, the other is the 'user code'
block. The 'user code' block MUST be placed after the 'class' block.
== Comments
You can insert comments about all places. Two styles of comments can be used, Ruby style '#.....' and C style '/\*......*\/'.
== Class Block
The class block is formed like this:
class CLASS_NAME
[precedence table]
[token declarations]
[expected number of S/R conflicts]
[options]
[semantic value conversion]
[start rule]
rule
GRAMMARS
CLASS_NAME is a name of the parser class. This is the name of the generating parser
class.
If CLASS_NAME includes '::', Racc outputs the module clause. For example, writing
"class M::C" causes the code below to be created:
module M
class C
:
:
end
end
== Grammar Block
The grammar block describes grammar which is able to be understood by the parser.
Syntax is:
(token): (token) (token) (token).... (action)
(token): (token) (token) (token).... (action)
| (token) (token) (token).... (action)
| (token) (token) (token).... (action)
(action) is an action which is executed when its (token)s are found.
(action) is a ruby code block, which is surrounded by braces:
{ print val[0]
puts val[1] }
Note that you cannot use '%' string, here document, '%r' regexp in action.
Actions can be omitted. When it is omitted, '' (empty string) is used.
A return value of action is a value of the left side value ($$). It is the value of the
result, or the returned value by `return` statement.
Here is an example of the whole grammar block.
rule
goal: definition rules source { result = val }
definition: /* none */ { result = [] }
| definition startdesig { result[0] = val[1] }
| definition
precrule # this line continues from upper line
{
result[1] = val[1]
}
startdesig: START TOKEN
You can use the following special local variables in action:
* result ($$)
The value of the left-hand side (lhs). A default value is val[0].
* val ($1,$2,$3...)
An array of value of the right-hand side (rhs).
* _values (...$-2,$-1,$0)
A stack of values. DO NOT MODIFY this stack unless you know what you are doing.
== Operator Precedence
This function is equal to '%prec' in yacc.
To designate this block:
prechigh
nonassoc '++'
left '*' '/'
left '+' '-'
right '='
preclow
`right` is yacc's %right, `left` is yacc's %left.
`=` + (symbol) means yacc's %prec:
prechigh
nonassoc UMINUS
left '*' '/'
left '+' '-'
preclow
rule
exp: exp '*' exp
| exp '-' exp
| '-' exp =UMINUS # equals to "%prec UMINUS"
:
:
== expect
Racc has bison's "expect" directive.
# Example
class MyParser
expect 3
rule
:
:
This directive declares "expected" number of shift/reduce conflicts. If
"expected" number is equal to real number of conflicts, Racc does not print
conflict warning message.
== Declaring Tokens
By declaring tokens, you can avoid many meaningless bugs. If declared token
does not exist or existing token does not decleared, Racc output warnings.
Declaration syntax is:
token TOKEN_NAME AND_IS_THIS
ALSO_THIS_IS AGAIN_AND_AGAIN THIS_IS_LAST
== Options
You can write options for Racc command in your Racc file.
options OPTION OPTION ...
Options are:
* omit_action_call
omits empty action call or not.
* result_var
uses local variable "result" or not.
You can use 'no_' prefix to invert their meanings.
== Converting Token Symbol
Token symbols are, as default,
* naked token string in Racc file (TOK, XFILE, this_is_token, ...)
--> symbol (:TOK, :XFILE, :this_is_token, ...)
* quoted string (':', '.', '(', ...)
--> same string (':', '.', '(', ...)
You can change this default by "convert" block.
Here is an example:
convert
PLUS 'PlusClass' # We use PlusClass for symbol of `PLUS'
MIN 'MinusClass' # We use MinusClass for symbol of `MIN'
end
We can use almost all ruby value can be used by token symbol,
except 'false' and 'nil'. These cause unexpected parse error.
If you want to use String as token symbol, special care is required.
For example:
convert
class '"cls"' # in code, "cls"
PLUS '"plus\n"' # in code, "plus\n"
MIN "\"minus#{val}\"" # in code, \"minus#{val}\"
end
== Start Rule
'%start' in yacc. This changes start rule.
start real_target
== User Code Block
"User Code Block" is a Ruby source code which is copied to output. There are
three user code blocks, "header" "inner" and "footer".
Format of user code is like this:
---- header
ruby statement
ruby statement
ruby statement
---- inner
ruby statement
:
:
If four '-' exist on the line head, Racc treats it as the beginning of the
user code block. The name of the user code block must be one word.
racc-1.8.1/doc/en/racc.en.rhtml 0000664 0000000 0000000 00000002044 14652110230 0016153 0 ustar 00root root 0000000 0000000 % require 'makefile'
% version = Makefile.get_parameter('Makefile', 'version')
Racc (Ruby yACC) is an LALR(1) parser generator for Ruby.
Version 1.4.x is stable release.
Parsers generated by Racc requires "Racc Runtime Module".
Ruby 1.8.x comes with this runtime.
If you want to run your parsers with ruby 1.6.x,
use "racc -E" command. For details, see online manual.
Git
You can use the latest version of Racc using git.
To clone out a working copy, type:
class MyParser
rule
if_stmt: IF expr then stmt_list elsif else END
then : THEN
|
elsif :
| ELSIF stmt_list
else :
| ELSE stmt_list
expr : NUMBER
| IDENT
| STRING
stmt_list : ふにゃふにゃ
end
Ruby スクリプトのように class でパーサクラス名を指定し、rule ... end
の間にパーサに解析させたい文法を記述します。
文法は、記号の並びでもって表します。rule ... end の間にあるコロンとバー
以外のもの、if_stmt IF expr then などが全て「記号」です。そしてコロン
が日本語で言う「〜は××だ」の「は」みたいなもんで、その左の記号が右の
記号の列と同じものを指す、というふうに定義します。また、バーは「または」
を意味します。それと、単純にコロンの左の記号のことを左辺、右を右辺とも
言います。以下はこちらのほうを使って説明しましょう。
少し注意が必要な点を述べます。まず、then の、バーのあとの定義 (規則) を
見てください。ここには何も書いていないので、これはその通り「無」であっ
てもいい、ということを表しています。つまり、then は記号 THEN 一個か、
またはなにもなし(省略する)でよい、ということです。記号 then は実際の
Ruby のソースコードにある then とは切り離して考えましょう
(それは実は大文字の記号 THEN が表しています)。
ここで、工夫が必要です。どうやら flag はローカル変数名だと思われますが、
変数名というのは他にもいろいろあります。しかし名前が i だろうが a だろ
うが vvvvvvvvvvvv だろうが、「構造」は同じです。つまり同じ扱いをされる
べきです。変数 a を書ける場所なら b も書けなくてはいけません。だったら
一時的に同じ名前で読んでもいいじゃん。ということで、この単語の列を以下
のように読みかえましょう。