pax_global_header 0000666 0000000 0000000 00000000064 12701300672 0014510 g ustar 00root root 0000000 0000000 52 comment=5b137f3c2f7fa5fa833f2c3a5ea8d5fb21d2a3b7
PEGTL-1.3.1/ 0000775 0000000 0000000 00000000000 12701300672 0012365 5 ustar 00root root 0000000 0000000 PEGTL-1.3.1/.gitignore 0000664 0000000 0000000 00000000032 12701300672 0014350 0 ustar 00root root 0000000 0000000 .svn
build
manual
private
PEGTL-1.3.1/.travis.yml 0000664 0000000 0000000 00000004772 12701300672 0014510 0 ustar 00root root 0000000 0000000 language: cpp
matrix:
include:
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8']
env: COMPILER=g++-4.8
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9']
env: COMPILER=g++-4.9
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5']
env: COMPILER=g++-5
- os: linux
compiler: clang
env: COMPILER=clang++ V='3.4'
- os: linux
compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5']
packages: ['clang-3.5']
env: COMPILER=clang++-3.5
- os: linux
compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
packages: ['clang-3.6']
env: COMPILER=clang++-3.6
- os: linux
compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7']
packages: ['clang-3.7']
env: COMPILER=clang++-3.7
- os: linux
compiler: clang
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
packages: ['clang-3.8']
env: COMPILER=clang++-3.8
- os: osx
compiler: clang
env: COMPILER=clang++ V='Apple LLVM 6.0' # Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
- os: osx
osx_image: xcode6.4
compiler: clang
env: COMPILER=clang++
- os: osx
osx_image: xcode7
compiler: clang
env: COMPILER=clang++ V='Apple LLVM 7.0.0' # Apple LLVM version 7.0.0 (clang-700.0.72)
- os: osx
osx_image: xcode7.1
compiler: clang
env: COMPILER=clang++
- os: osx
osx_image: xcode7.2
compiler: clang
env: COMPILER=clang++
- os: osx
osx_image: xcode7.3
compiler: clang
env: COMPILER=clang++
- os: linux
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5']
env:
- COMPILER=g++-5
- PEGTL_CXXFLAGS="-O0 --coverage"
before_script:
- pip install --user cpp-coveralls
after_success:
- coveralls --gcov gcov-5 --gcov-options '\-lp' --exclude unit_tests --exclude examples
script:
make CXX=$COMPILER -j3
PEGTL-1.3.1/LICENSE 0000664 0000000 0000000 00000002121 12701300672 0013366 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2014-2016 Dr. Colin Hirsch and Daniel Frey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
PEGTL-1.3.1/Makefile 0000664 0000000 0000000 00000003010 12701300672 0014017 0 ustar 00root root 0000000 0000000 # Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
# Please see LICENSE for license or visit https://github.com/ColinH/PEGTL
ifeq ($(OS),Windows_NT)
UNAME_S := $(OS)
ifeq ($(shell gcc -dumpmachine),mingw32)
MINGW_CXXFLAGS = -U__STRICT_ANSI__
endif
else
UNAME_S := $(shell uname -s)
endif
# For Darwin (Mac OS X) we assume that the default compiler
# clang++ is used; when $(CXX) is some version of g++, then
# $(PEGTL_CXXSTD) has to be set to -std=c++11 (or newer) so
# that -stdlib=libc++ is not automatically added.
ifeq ($(PEGTL_CXXSTD),)
PEGTL_CXXSTD := -std=c++11
ifeq ($(UNAME_S),Darwin)
PEGTL_CXXSTD += -stdlib=libc++
endif
endif
# Ensure strict standard compliance and no warnings, can be
# changed if desired.
PEGTL_CPPFLAGS ?= -pedantic
PEGTL_CXXFLAGS ?= -Wall -Wextra -Werror -O3 $(MINGW_CXXFLAGS)
.PHONY: all clean
SOURCES := $(wildcard */*.cc)
DEPENDS := $(SOURCES:%.cc=build/%.d)
BINARIES := $(SOURCES:%.cc=build/%)
UNIT_TESTS := $(filter build/unit_tests/%,$(BINARIES))
all: $(BINARIES)
@echo "Built with '$(CXX) $(PEGTL_CXXSTD) -I. $(PEGTL_CPPFLAGS) $(PEGTL_CXXFLAGS)'."
@set -e; for T in $(UNIT_TESTS); do echo $$T; $$T > /dev/null; done
@echo "All $(words $(UNIT_TESTS)) unit tests passed."
clean:
rm -rf build/*
.SECONDARY:
build/%.d: %.cc Makefile
@mkdir -p $(@D)
$(CXX) $(PEGTL_CXXSTD) -I. $(PEGTL_CPPFLAGS) -MM -MQ $@ $< -o $@
build/%: %.cc build/%.d
$(CXX) $(PEGTL_CXXSTD) -I. $(PEGTL_CPPFLAGS) $(PEGTL_CXXFLAGS) $< -o $@
ifeq ($(findstring $(MAKECMDGOALS),clean),)
-include $(DEPENDS)
endif
PEGTL-1.3.1/README.md 0000664 0000000 0000000 00000025015 12701300672 0013647 0 ustar 00root root 0000000 0000000 ## Welcome to the PEGTL
[](https://github.com/ColinH/PEGTL/releases/latest)
[](#license)
[](https://travis-ci.org/ColinH/PEGTL)
[](https://coveralls.io/github/ColinH/PEGTL)
[](https://github.com/ColinH/PEGTL/issues)
The Parsing Expression Grammar Template Library (PEGTL) is a zero-dependency C++11 header-only library for creating parsers according to a [Parsing Expression Grammar](http://en.wikipedia.org/wiki/Parsing_expression_grammar) (PEG).
#### Introduction
Grammars are written as regular C++ code, created with template programming (not template meta programming), i.e. nested template instantiations that naturally correspond to the inductive definition of PEGs or other parser combinator approaches.
A comprehensive set of parser rules that can be combined and extended by the user is included, as are mechanisms for debugging grammars and attaching user-defined actions to grammar rules.
Here is an example of how a PEG grammar rule is implemented as C++ class with the PEGTL.
```c++
// PEG rule for integers consisting of a non-empty
// sequence of digits with an optional sign:
// integer ::= ( '+' / '-' )? digit+
// The same parsing rule implemented with the PEGTL:
struct integer
: pegtl::seq< pegtl::opt< pegtl::one< '+', '-' > >,
pegtl::plus< pegtl::digit > > {};
```
PEGs are superficially similar to Context-Free Grammars (CFGs), however the more deterministic nature of PEGs gives rise to some very important differences.
The included [grammar analysis](https://github.com/ColinH/PEGTL/wiki/Grammar-Analysis) finds several typical errors in PEGs, including left recursion.
#### Design
The PEGTL is mostly concerned with parsing combinators and grammar rules, and with giving the user control over what else happens during a parsing run.
The PEGTL is designed to be "lean and mean".
The actual core library has about 3000 lines of code.
Emphasis is on simplicity and efficiency but without adding any large constructions for optimising parsers.
Whether and which actions are taken, and which data structures are created during a parsing run, is entirely up to the user of the library, however we provide some [examples](https://github.com/ColinH/PEGTL/wiki/Contrib-and-Examples#examples) for typical situation like unescaping escape sequences in strings, building a generic [JSON](http://www.json.org/) data structure, and on-the-fly evaluation of arithmetic expressions.
Through the use of template programming and template specialisations it is possible to write a grammar once, and use it in multiple ways with different (semantic) actions in different (or the same) parsing runs.
Unlike [Antlr](http://www.antlr.org/) and Yacc/[Bison](http://www.gnu.org/software/bison/), the grammar is expressed in C++ and is part of the C++ source code.
Also, with the PEG formalism the separation into lexer and parser stages is usually dropped -- everything is done in a single grammar.
Unlike [Spirit](http://boost-spirit.com/), the grammar is implemented with compile-time template instantiations rather than run-time operator calls.
This leads to slightly increased compile times as the C++ compiler is given the task of optimising PEGTL grammars.
#### Status
The master branch of the PEGTL is stable in the sense that all known bugs are fixed and all unit tests run without errors. Each commit is automatically tested with multiple operating systems, compilers and versions, currently:
* Linux, GCC (4.8, 4.9, 5) with libstdc++
* Linux, Clang (3.4, 3.5, 3.6, 3.7, 3.8) with libstdc++
* MacOS X, XCode (6, 7) with libc++
(Visual Studio 2015 on Windows is *not* automatically tested, *yet*.)
The coverage is also automatically measured. Our unit tests cover 100% of the core library code.
Releases are not stable in the sense that incompatible API changes can happen, but only between major versions.
[Releases](https://github.com/ColinH/PEGTL/releases) are done in accordance with [Semantic Versioning](http://semver.org/).
For details see the [changelog](https://github.com/ColinH/PEGTL/wiki/Changelog).
## Documentation
* [Getting Started](https://github.com/ColinH/PEGTL/wiki/Getting-Started)
* [Hello, world!](https://github.com/ColinH/PEGTL/wiki/Getting-Started#hello-world)
* [Requirements](https://github.com/ColinH/PEGTL/wiki/Getting-Started#requirements)
* [Compilation](https://github.com/ColinH/PEGTL/wiki/Getting-Started#compilation)
* [Limitations](https://github.com/ColinH/PEGTL/wiki/Getting-Started#limitations)
* [Rules and Grammars](https://github.com/ColinH/PEGTL/wiki/Rules-and-Grammars)
* [Combining Existing Rules](https://github.com/ColinH/PEGTL/wiki/Rules-and-Grammars#combining-existing-rules)
* [Actions and States](https://github.com/ColinH/PEGTL/wiki/Actions-and-States)
* [Actions](https://github.com/ColinH/PEGTL/wiki/Actions-and-States#actions)
* [States](https://github.com/ColinH/PEGTL/wiki/Actions-and-States#states)
* [Action Specialisation](https://github.com/ColinH/PEGTL/wiki/Actions-and-States#action-specialisation)
* [Changing Actions](https://github.com/ColinH/PEGTL/wiki/Actions-and-States#changing-actions)
* [Errors and Exceptions](https://github.com/ColinH/PEGTL/wiki/Errors-and-Exceptions)
* [Failure](https://github.com/ColinH/PEGTL/wiki/Errors-and-Exceptions#failure)
* [Error Messages](https://github.com/ColinH/PEGTL/wiki/Errors-and-Exceptions#error-messages)
* [Rule Reference](https://github.com/ColinH/PEGTL/wiki/Rule-Reference)
* [Meta Rules](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#meta-rules)
* [Combinators](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#combinators)
* [Convenience](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#convenience)
* [Atomic Rules](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#atomic-rules)
* [ASCII Rules](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#ascii-rules)
* [UTF-8 Rules](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#utf-8-rules)
* [UTF-16 Rules](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#utf-16-rules)
* [UTF-32 Rules](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#utf-32-rules)
* [Full Index](https://github.com/ColinH/PEGTL/wiki/Rule-Reference#full-index)
* [Parser Reference](https://github.com/ColinH/PEGTL/wiki/Parser-Reference)
* [Input and Errors](https://github.com/ColinH/PEGTL/wiki/Parser-Reference#input-and-errors)
* [Parser Functions](https://github.com/ColinH/PEGTL/wiki/Parser-Reference#parser-functions)
* [Tracer Functions](https://github.com/ColinH/PEGTL/wiki/Parser-Reference#tracer-functions)
* [Parser Classes](https://github.com/ColinH/PEGTL/wiki/Parser-Reference#parser-classes)
* [Contrib and Examples](https://github.com/ColinH/PEGTL/wiki/Contrib-and-Examples)
* [Contrib](https://github.com/ColinH/PEGTL/wiki/Contrib-and-Examples#contrib)
* [Examples](https://github.com/ColinH/PEGTL/wiki/Contrib-and-Examples#examples)
* [Control Hooks](https://github.com/ColinH/PEGTL/wiki/Control-Hooks)
* [Normal Control](https://github.com/ColinH/PEGTL/wiki/Control-Hooks#normal-control)
* [Debug Functions](https://github.com/ColinH/PEGTL/wiki/Control-Hooks#debug-functions)
* [Exception Throwing](https://github.com/ColinH/PEGTL/wiki/Control-Hooks#exception-throwing)
* [Debugging and Tracing](https://github.com/ColinH/PEGTL/wiki/Control-Hooks#debugging-and-tracing)
* [Advanced Control](https://github.com/ColinH/PEGTL/wiki/Control-Hooks#advanced-control)
* [Changing Control](https://github.com/ColinH/PEGTL/wiki/Control-Hooks#changing-control)
* [Advanced Rules](https://github.com/ColinH/PEGTL/wiki/Advanced-Rules)
* [Simple Rules](https://github.com/ColinH/PEGTL/wiki/Advanced-Rules#simple-rules)
* [Complex Rules](https://github.com/ColinH/PEGTL/wiki/Advanced-Rules#complex-rules)
* [Switching Style](https://github.com/ColinH/PEGTL/wiki/Switching-Style)
* [Grammar Analysis](https://github.com/ColinH/PEGTL/wiki/Grammar-Analysis)
* [Calculator Example](https://github.com/ColinH/PEGTL/wiki/Calculator-Example)
* [Changelog](https://github.com/ColinH/PEGTL/wiki/Changelog)
* [2014 Refactoring](https://github.com/ColinH/PEGTL/wiki/2014-Refactoring)
#### Thank You
* Christopher Diggins and the YARD parser for the general idea.
* Stephan Beal for the bug reports, suggestions and discussions.
* Johannes Overmann for his invaluable [`streplace`](https://code.google.com/p/streplace/) command-line tool.
* Sam Hocevar for contributing Visual Studio 2015 compatibility.
* George Makrydakis for the [inspiration](https://github.com/irrequietus/typestring) to `pegtl_string_t`.
* Kenneth Geisshirt for Android compatibility.
## License
The PEGTL is certified [Open Source](http://www.opensource.org/docs/definition.html) software. It may be used for any purpose, including commercial purposes, at absolutely no cost. It is distributed under the terms of the [MIT license](http://www.opensource.org/licenses/mit-license.html) reproduced here.
> Copyright (c) 2014-2016 Dr. Colin Hirsch and Daniel Frey
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This site and software is not affiliated with or endorsed by the Open Source Initiative. For questions and suggestions about the PEGTL please contact the authors at `pegtl(at)colin-hirsch.net`.
PEGTL-1.3.1/examples/ 0000775 0000000 0000000 00000000000 12701300672 0014203 5 ustar 00root root 0000000 0000000 PEGTL-1.3.1/examples/abnf.abnf 0000664 0000000 0000000 00000004063 12701300672 0015744 0 ustar 00root root 0000000 0000000 ; grammar for ABNFs taken from RFC 5234 + RFC 7405,
; slightly adapted and extended to PEGs
rulelist = 1*( rule / (*c-wsp c-nl) )
rule = rulename defined-as elements c-nl
; continues if next line starts
; with white space
rulename = ALPHA *(ALPHA / DIGIT / "-")
defined-as = *c-wsp ("=/" / "=") *c-wsp
; basic rules definition and
; incremental alternatives
; different order due to PEG
elements = alternation *c-wsp
c-wsp = WSP / (c-nl WSP)
c-nl = comment / CRLF
; comment or newline
comment = ";" *(WSP / VCHAR) CRLF
alternation = concatenation
*(*c-wsp "/" *c-wsp concatenation)
concatenation = predicate *(1*c-wsp predicate)
predicate = ["&" / "!"] repetition
; extension for PEGs
repetition = [repeat] element
repeat = (*DIGIT "*" *DIGIT) / 1*DIGIT
; different order due to PEG
element = rulename / group / option /
char-val / num-val / prose-val
group = "(" *c-wsp alternation *c-wsp ")"
option = "[" *c-wsp alternation *c-wsp "]"
char-val = DQUOTE *(%x20-21 / %x23-7E) DQUOTE
; quoted string of SP and VCHAR
; without DQUOTE
num-val = "%" (bin-val / dec-val / hex-val)
bin-val = "b" 1*BIT
[ 1*("." 1*BIT) / ("-" 1*BIT) ]
; series of concatenated bit values
; or single ONEOF range
dec-val = "d" 1*DIGIT
[ 1*("." 1*DIGIT) / ("-" 1*DIGIT) ]
hex-val = "x" 1*HEXDIG
[ 1*("." 1*HEXDIG) / ("-" 1*HEXDIG) ]
prose-val = "<" *(%x20-3D / %x3F-7E) ">"
; bracketed string of SP and VCHAR
; without angles
; prose description, to be used as
; last resort
PEGTL-1.3.1/examples/abnf2pegtl.cc 0000664 0000000 0000000 00000057114 12701300672 0016546 0 ustar 00root root 0000000 0000000 // Copyright (c) 2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace pegtl
{
namespace abnf
{
namespace grammar
{
// ABNF grammar according to RFC 5234, updated by RFC 7405, with
// the following differences:
//
// To form a C++ identifier from a rulename, all minuses are
// replaced with underscores.
//
// As C++ identifiers are case-sensitive, we remember the "correct"
// spelling from the first occurrence of a rulename, all other
// occurrences are automatically changed to that.
//
// Certain rulenames are reserved as their equivalent C++ identifier is
// reserved as a keyword, an alternative token, by the standard or
// for other, special reasons.
//
// When using numerical values (num-val, repeat), the values
// must be in the range of the corresponsing C++ data type.
//
// Remember we are defining a PEG, not a CFG. Simply copying some
// ABNF from somewhere might lead to surprising results as the
// alternations are now sequential, using the pegtl::sor<> rule.
//
// PEG also require two extensions: the and-predicate and the
// not-predicate. They are expressed by '&' and '!' respectively,
// being allowed (optionally, only one of them) before the
// repetition. You can use braces for more complex expressions.
//
// Finally, instead of the pre-defined CRLF sequence, we accept
// any type of line ending as a convencience extension:
struct CRLF : sor< abnf::CRLF, CR, LF > {};
// The rest is according to the RFC(s):
struct comment_cont : until< CRLF, sor< WSP, VCHAR > > {};
struct comment : if_must< one< ';' >, comment_cont > {};
struct c_nl : sor< comment, CRLF > {};
struct c_wsp : sor< WSP, seq< c_nl, WSP > > {};
struct rulename : seq< ALPHA, star< ranges< 'a', 'z', 'A', 'Z', '0', '9', '-' > > > {};
struct quoted_string_cont : until< DQUOTE, print > {};
struct quoted_string : if_must< DQUOTE, quoted_string_cont > {};
struct case_insensitive_string : seq< opt< istring< '%', 'i' > >, quoted_string > {};
struct case_sensitive_string : seq< istring< '%', 's' >, quoted_string > {};
struct char_val : sor< case_insensitive_string, case_sensitive_string > {};
struct prose_val_cont : until< one< '>' >, print > {};
struct prose_val : if_must< one< '<' >, prose_val_cont > {};
template< char First, typename Digit >
struct gen_val
{
struct value : plus< Digit > {};
struct range : if_must< one< '-' >, value > {};
struct next_value : must< value > {};
struct type : seq< istring< First >, must< value >, sor< range, star< one< '.' >, next_value > > > {};
};
using hex_val = gen_val< 'x', HEXDIG >;
using dec_val = gen_val< 'd', DIGIT >;
using bin_val = gen_val< 'b', BIT >;
struct num_val_choice : sor< bin_val::type, dec_val::type, hex_val::type > {};
struct num_val : if_must< one< '%' >, num_val_choice > {};
struct alternation;
struct option_close : one< ']' > {};
struct option : seq< one< '[' >, pad< must< alternation >, c_wsp >, must< option_close > > {};
struct group_close : one< ')' > {};
struct group : seq< one< '(' >, pad< must< alternation >, c_wsp >, must< group_close > > {};
struct rulename_val : rulename {};
struct element : sor< rulename_val, group, option, char_val, num_val, prose_val > {};
struct repeat : sor< seq< star< DIGIT >, one< '*' >, star< DIGIT > >, plus< DIGIT > > {};
struct repetition : seq< opt< repeat >, element > {};
struct and_predicate : if_must< one< '&' >, repetition > {};
struct not_predicate : if_must< one< '!' >, repetition > {};
struct predicate : sor< and_predicate, not_predicate, repetition > {};
struct push_stack : success {};
struct concatenation : seq< push_stack, list< predicate, plus< c_wsp > > > {};
struct alternation : seq< push_stack, list_must< concatenation, pad< one< '/' >, c_wsp > > > {};
struct defined_as_op : sor< string< '=', '/' >, one< '=' > > {};
struct defined_as : pad< defined_as_op, c_wsp > {};
struct rule : seq< push_stack, if_must< rulename, defined_as, alternation >, star< c_wsp >, must< c_nl > > {};
struct rulelist : until< eof, sor< seq< star< c_wsp >, c_nl >, must< rule > > > {};
// end of grammar
template< typename Rule >
struct error_control
: public normal< Rule >
{
static const std::string error_message;
template< typename Input, typename ... States >
static void raise( const Input & in, States && ... )
{
throw parse_error( error_message, in );
}
};
template<> const std::string error_control< comment_cont >::error_message = "unterminated comment";
template<> const std::string error_control< quoted_string_cont >::error_message = "unterminated string (missing '\"')";
template<> const std::string error_control< prose_val_cont >::error_message = "unterminated prose description (missing '>')";
template<> const std::string error_control< hex_val::value >::error_message = "expected hexadecimal value";
template<> const std::string error_control< dec_val::value >::error_message = "expected decimal value";
template<> const std::string error_control< bin_val::value >::error_message = "expected binary value";
template<> const std::string error_control< num_val_choice >::error_message = "expected base specifier (one of 'bBdDxX')";
template<> const std::string error_control< option_close >::error_message = "unterminated option (missing ']')";
template<> const std::string error_control< group_close >::error_message = "unterminated group (missing ')')";
template<> const std::string error_control< repetition >::error_message = "expected element";
template<> const std::string error_control< concatenation >::error_message = "expected element";
template<> const std::string error_control< alternation >::error_message = "expected element";
template<> const std::string error_control< defined_as >::error_message = "expected '=' or '=/'";
template<> const std::string error_control< c_nl >::error_message = "unterminated rule";
template<> const std::string error_control< rule >::error_message = "expected rule";
} // grammar
} // abnf
} // pegtl
namespace abnf2pegtl
{
struct data
{
std::string rulename;
std::vector< std::vector< std::string > > elements;
using rules_t = std::vector< std::pair< std::string, std::string > >;
rules_t rules;
rules_t::reverse_iterator find_rule( const std::string& v, const rules_t::reverse_iterator& rbegin )
{
return std::find_if( rbegin, rules.rend(), [&]( const rules_t::value_type& p ){ return ::strcasecmp( p.first.c_str(), v.c_str() ) == 0; } );
}
rules_t::reverse_iterator find_rule( const std::string& v )
{
return find_rule( v, rules.rbegin() );
}
};
namespace
{
std::set< std::string > keywords = {
"alignas", "alignof", "and", "and_eq",
"asm", "auto", "bitand", "bitor",
"bool", "break", "case", "catch",
"char", "char16_t", "char32_t", "class",
"compl", "const", "constexpr", "const_cast",
"continue", "decltype", "default", "delete",
"do", "double", "dynamic_cast", "else",
"enum", "explicit", "export", "extern",
"false", "float", "for", "friend",
"goto", "if", "inline", "int",
"long", "mutable", "namespace", "new",
"noexcept", "not", "not_eq", "nullptr",
"operator", "or", "or_eq", "private",
"protected", "public", "register", "reinterpret_cast",
"return", "short", "signed", "sizeof",
"static", "static_assert", "static_cast", "struct",
"switch", "template", "this", "thread_local",
"throw", "true", "try", "typedef",
"typeid", "typename", "union", "unsigned",
"using", "virtual", "void", "volatile",
"wchar_t", "while", "xor", "xor_eq",
"pegtl" // this would not end well :)
};
}
std::string get_rulename( const pegtl::input & in, data & d )
{
std::string v = in.string();
std::replace( v.begin(), v.end(), '-', '_' );
const auto it = d.find_rule( v );
if( it != d.rules.rend() ) {
return it->first;
}
if( keywords.find( v ) != keywords.end() || v.find( "__" ) != std::string::npos ) {
throw pegtl::parse_error( "'" + in.string() + "' is a reserved rulename", in );
}
return v;
}
namespace grammar = pegtl::abnf::grammar;
template< typename Rule >
struct action
: pegtl::nothing< Rule > {};
template<> struct action< grammar::push_stack >
{
static void apply( const pegtl::input &, data & d )
{
d.elements.emplace_back();
}
};
template<> struct action< grammar::rulename >
{
static void apply( const pegtl::input & in, data & d )
{
d.rulename = get_rulename( in, d );
}
};
template<> struct action< grammar::rulename_val >
{
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
std::string v = get_rulename( in, d );
const auto it = d.find_rule( v );
if( it == d.rules.rend() ) {
d.rules.emplace_back( v, "" );
}
d.elements.back().push_back( v );
}
};
template<> struct action< grammar::quoted_string >
{
static bool append( std::string& s, const char c )
{
if( !s.empty() ) {
s += ", ";
}
s += '\'';
if( c == '\'' ) {
s += '\\';
}
s += c;
s += '\'';
return std::isalpha( c );
}
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
std::string s;
bool alpha = append( s, in.peek_char( 1 ) );
for( std::size_t pos = 2; pos < in.size() - 1; ++pos ) {
alpha = append( s, in.peek_char( pos ) ) || alpha;
}
if( alpha ) {
d.elements.back().push_back( "pegtl::istring< " + s + " >" );
}
else if( in.size() > 3 ) {
d.elements.back().push_back( "pegtl::string< " + s + " >" );
}
else {
d.elements.back().push_back( "pegtl::one< " + s + " >" );
}
}
};
template<> struct action< grammar::prose_val >
{
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
const auto v = in.string();
d.elements.back().push_back( "/* " + v.substr( 1, v.size() - 2 ) + " */" );
}
};
template<> struct action< grammar::case_sensitive_string >
{
static void apply( const pegtl::input &, data & d )
{
assert( !d.elements.empty() );
assert( !d.elements.back().empty() );
if( d.elements.back().back()[ 7 ] == 'i' ) {
d.elements.back().back().erase( 7, 1 );
}
}
};
template<> struct action< grammar::bin_val::value >
{
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
const auto v = in.string();
d.elements.back().push_back( "pegtl::one< " + std::to_string( std::strtoull( v.c_str(), nullptr, 2 ) ) + " >" );
}
};
template<> struct action< grammar::bin_val::range >
{
static void apply( const pegtl::input &, data & d )
{
assert( !d.elements.empty() );
assert( !d.elements.back().empty() );
const auto end = d.elements.back().back();
d.elements.back().pop_back();
assert( !d.elements.back().empty() );
const auto begin = d.elements.back().back();
d.elements.back().back() = "pegtl::range< " + begin.substr( 12, begin.size() - 14 ) + ", " + end.substr( 12, end.size() - 14 ) + " >";
}
};
template<> struct action< grammar::bin_val::next_value >
{
static void apply( const pegtl::input &, data & d )
{
assert( !d.elements.empty() );
assert( !d.elements.back().empty() );
const auto end = d.elements.back().back();
d.elements.back().pop_back();
assert( !d.elements.back().empty() );
d.elements.back().back().replace( d.elements.back().back().size() - 2, 2, ", " + end.substr( 12 ) );
}
};
template<> struct action< grammar::dec_val::value >
{
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
const auto v = in.string();
const auto p = v.find_first_not_of( '0' );
d.elements.back().push_back( "pegtl::one< " + ( ( p == std::string::npos ) ? "0" : v.substr( p ) ) + " >" );
}
};
template<> struct action< grammar::dec_val::range > : action< grammar::bin_val::range > {};
template<> struct action< grammar::dec_val::next_value > : action< grammar::bin_val::next_value > {};
template<> struct action< grammar::hex_val::value >
{
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
d.elements.back().push_back( "pegtl::one< 0x" + in.string() + " >" );
}
};
template<> struct action< grammar::hex_val::range > : action< grammar::bin_val::range > {};
template<> struct action< grammar::hex_val::next_value > : action< grammar::bin_val::next_value > {};
template<> struct action< grammar::option >
{
static void apply( const pegtl::input &, data & d )
{
assert( !d.elements.empty() );
assert( !d.elements.back().empty() );
d.elements.back().back() = "pegtl::opt< " + d.elements.back().back() + " >";
}
};
template<> struct action< grammar::repeat >
{
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
d.elements.back().push_back( in.string() );
}
};
template<> struct action< grammar::repetition >
{
static std::string remove_leading_zeroes( const std::string& v )
{
const auto pos = v.find_first_not_of( '0' );
if( pos == std::string::npos ) {
return "";
}
return v.substr( pos );
}
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
assert( !d.elements.back().empty() );
const auto size = d.elements.back().size();
if( size > 1 ) {
const auto value = d.elements.back()[ size - 2 ];
if( value.find_first_not_of( "0123456789*" ) == std::string::npos ) {
const auto element = d.elements.back().back();
d.elements.back().pop_back();
d.elements.back().pop_back();
const auto star = value.find( '*' );
if( star == std::string::npos ) {
const auto num = remove_leading_zeroes( value );
if( num == "" ) {
throw pegtl::parse_error( "repetition of zero not allowed", in );
}
d.elements.back().push_back( "pegtl::rep< " + num + ", " + element + " >" );
}
else {
const auto min = remove_leading_zeroes( value.substr( 0, star ) );
const auto max = remove_leading_zeroes( value.substr( star + 1 ) );
if( star != value.size() - 1 && max == "" ) {
throw pegtl::parse_error( "repetition maximum of zero not allowed", in );
}
if( min.empty() && max.empty() ) {
d.elements.back().push_back( "pegtl::star< " + element + " >" );
}
else if( !min.empty() && max.empty() ) {
if( min == "1" ) {
d.elements.back().push_back( "pegtl::plus< " + element + " >" );
}
else {
d.elements.back().push_back( "pegtl::rep_min< " + min + ", " + element + " >" );
}
}
else if( min.empty() && !max.empty() ) {
if( max == "1" ) {
d.elements.back().push_back( "pegtl::opt< " + element + " >" );
}
else {
d.elements.back().push_back( "pegtl::rep_opt< " + max + ", " + element + " >" );
}
}
else {
const auto min_val = std::strtoull( min.c_str(), nullptr, 10 );
const auto max_val = std::strtoull( max.c_str(), nullptr, 10 );
if( min_val > max_val ) {
throw pegtl::parse_error( "repetition minimum which is greater than the repetition maximum not allowed", in );
}
const auto min_element = ( min_val == 1 ) ? element : "pegtl::rep< " + min + ", " + element + " >";
if( min_val == max_val ) {
d.elements.back().push_back( min_element );
}
else if( max_val - min_val == 1 ) {
const auto max_element = "pegtl::opt< " + element + " >";
d.elements.back().push_back( "pegtl::seq< " + min_element + ", " + max_element + " >" );
}
else {
const auto max_element = "pegtl::rep_opt< " + std::to_string( max_val - min_val ) + ", " + element + " >";
d.elements.back().push_back( "pegtl::seq< " + min_element + ", " + max_element + " >" );
}
}
}
}
}
}
};
template<> struct action< grammar::and_predicate >
{
static void apply( const pegtl::input &, data & d )
{
assert( !d.elements.empty() );
assert( !d.elements.back().empty() );
d.elements.back().back() = "pegtl::at< " + d.elements.back().back() + " >";
}
};
template<> struct action< grammar::not_predicate >
{
static void apply( const pegtl::input &, data & d )
{
assert( !d.elements.empty() );
assert( !d.elements.back().empty() );
d.elements.back().back() = "pegtl::not_at< " + d.elements.back().back() + " >";
}
};
template<> struct action< grammar::concatenation >
{
static void apply( const pegtl::input &, data & d )
{
assert( !d.elements.empty() );
if( d.elements.back().size() == 1 ) {
assert( d.elements.back().size() == 1 );
const auto v = d.elements.back().back();
d.elements.pop_back();
assert( !d.elements.empty() );
d.elements.back().push_back( v );
}
else {
std::string s = d.elements.back().front();
for( std::size_t p = 1; p != d.elements.back().size(); ++p ) {
s += ", ";
s += d.elements.back()[ p ];
}
d.elements.pop_back();
assert( !d.elements.empty() );
d.elements.back().push_back( "pegtl::seq< " + s + " >" );
}
}
};
template<> struct action< grammar::alternation >
{
static bool is_one( const std::string& v )
{
return v.compare( 0, 12, "pegtl::one< " ) == 0;
}
static void apply( const pegtl::input &, data & d )
{
assert( !d.elements.empty() );
if( d.elements.back().size() == 1 ) {
assert( d.elements.back().size() == 1 );
const auto v = d.elements.back().back();
d.elements.pop_back();
assert( !d.elements.empty() );
d.elements.back().push_back( v );
}
else {
std::string s = d.elements.back().front();
bool one = is_one( s );
for( std::size_t p = 1; p != d.elements.back().size(); ++p ) {
const auto v = d.elements.back()[ p ];
if( one && is_one( v ) ) {
s.replace( s.size() - 2, 2, ", " + v.substr( 12 ) );
}
else {
one = false;
s += ", ";
s += v;
}
}
d.elements.pop_back();
assert( !d.elements.empty() );
if( !one ) {
s = "pegtl::sor< " + s + " >";
}
d.elements.back().push_back( s );
}
}
};
template<> struct action< grammar::defined_as_op >
{
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
d.elements.back().push_back( in.string() );
}
};
template<> struct action< grammar::rule >
{
static std::string strip_sor( const std::string& v )
{
return ( v.compare( 0, 12, "pegtl::sor< " ) == 0 ) ? v.substr( 12, v.size() - 14 ) : v;
}
static void apply( const pegtl::input & in, data & d )
{
assert( !d.elements.empty() );
assert( d.elements.back().size() == 2 );
auto value = d.elements.back().back();
d.elements.back().pop_back();
const auto op = d.elements.back().back();
d.elements.back().pop_back();
const auto it = d.find_rule( d.rulename );
if( op == "=" ) {
if( it != d.rules.rend() && it->second != "" ) {
throw pegtl::parse_error( "'" + d.rulename + "' has already been assigned", in );
}
}
else {
assert( op == "=/" );
if( it == d.rules.rend() || it->second == "" ) {
throw pegtl::parse_error( "'" + d.rulename + "' has not yet been assigned", in );
}
value = "pegtl::sor< " + strip_sor( it->second ) + ", " + strip_sor( value ) + " >";
if( d.find_rule( d.rulename, std::next( it ) ) == d.rules.rend() ) {
it->second.clear();
}
else {
d.rules.erase( --it.base() );
}
}
d.rules.emplace_back( d.rulename, value );
d.elements.pop_back();
assert( d.elements.empty() );
}
};
} // abnf2pegtl
int main( int argc, char ** argv )
{
using namespace pegtl;
if( argc != 2 ) {
analyze< abnf::grammar::rulelist >();
std::cerr << "Usage: " << argv[ 0 ] << " SOURCE" << std::endl;
return 1;
}
abnf2pegtl::data d;
file_parser( argv[ 1 ] ).parse< abnf::grammar::rulelist, abnf2pegtl::action, abnf::grammar::error_control >( d );
for( const auto& e : d.rules ) {
if( e.second.empty() ) {
if( !d.find_rule( e.first )->second.empty() ) {
std::cout << "struct " << e.first << ";\n";
}
}
else {
std::cout << "struct " << e.first << " : " << e.second << " {};\n";
}
}
return 0;
}
PEGTL-1.3.1/examples/calculator.cc 0000664 0000000 0000000 00000025645 12701300672 0016657 0 ustar 00root root 0000000 0000000 // Copyright (c) 2014-2016 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/
#include