diff --git a/packages/PEGTL/.appveyor.yml b/packages/PEGTL/.appveyor.yml index 716434a3043a74f22d63bcb374dac3b7a9c7766d..02289836c6090f6ceccf750a79ed6a2e875082c5 100644 --- a/packages/PEGTL/.appveyor.yml +++ b/packages/PEGTL/.appveyor.yml @@ -1,65 +1,29 @@ version: '{branch}-{build}' -os: - - Visual Studio 2017 - skip_commits: files: + - README.md - doc/**/* -environment: - matrix: - - GENERATOR: Visual Studio 15 2017 - platform: x86 - configuration: Debug +os: + - Visual Studio 2017 - - GENERATOR: Visual Studio 15 2017 - platform: x86 - configuration: Release +platform: + - x86 + - x64 - - GENERATOR: Visual Studio 15 2017 - platform: x64 - configuration: Debug +configuration: + - Debug + - Release +environment: + matrix: - GENERATOR: Visual Studio 15 2017 - platform: x64 - configuration: Release - - - GENERATOR: Visual Studio 15 2017 Win64 - platform: x86 - configuration: Debug - GENERATOR: Visual Studio 15 2017 Win64 - platform: x86 - configuration: Release - - - GENERATOR: Visual Studio 15 2017 Win64 - platform: x64 - configuration: Debug - - - GENERATOR: Visual Studio 15 2017 Win64 - platform: x64 - configuration: Release - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - GENERATOR: Visual Studio 16 2019 - platform: x86 - configuration: Debug - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 GENERATOR: Visual Studio 16 2019 - platform: x86 - configuration: Release - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - GENERATOR: Visual Studio 16 2019 - platform: x64 - configuration: Debug - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - GENERATOR: Visual Studio 16 2019 - platform: x64 - configuration: Release init: [] @@ -74,4 +38,3 @@ build_script: test_script: - ctest -C "%CONFIGURATION%" --output-on-failure - diff --git a/packages/PEGTL/.clang-format b/packages/PEGTL/.clang-format index 729f882aad10760bbc2afa0fe571376390a19bdb..c423ca2749e808e112ba69db6d6f33ee76ca955f 100644 --- a/packages/PEGTL/.clang-format +++ b/packages/PEGTL/.clang-format @@ -3,7 +3,7 @@ # clang-format -i -style=file $(find . -name '[^.]*.[hc]pp') Language: Cpp -Standard: Cpp11 +Standard: Latest AccessModifierOffset: -3 AlignAfterOpenBracket: Align diff --git a/packages/PEGTL/.clang-tidy b/packages/PEGTL/.clang-tidy index 14eb1216c414dfe3269d2b3195855173b18299f1..2af75f8edbfac208c7fef1dfcbbcb1da1093f367 100644 --- a/packages/PEGTL/.clang-tidy +++ b/packages/PEGTL/.clang-tidy @@ -21,6 +21,7 @@ Checks: >- readability-*, -readability-avoid-const-params-in-decls, -readability-magic-numbers, + -readability-static-accessed-through-instance, CheckOptions: - { key: readability-identifier-naming.ClassCase, value: lower_case } diff --git a/packages/PEGTL/.gitrepo b/packages/PEGTL/.gitrepo index 7eea19117c858927ae7c942b0fe1631d3c411044..00b4dcf367034ec66b746e464a2f7bb9ffdcf080 100644 --- a/packages/PEGTL/.gitrepo +++ b/packages/PEGTL/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = git@github.com:taocpp/PEGTL.git branch = master - commit = 1a4a2d0df43f773893e0e4102d56d85e6b3fb7fc - parent = 28dff7b443629a23205fd32909491e7e5de495a3 + commit = 3d4fee2837decb5ecff9543276c4aa922b280972 + parent = 0a259f7e3e4fe2364b8d45b641c7f48ff3bc7341 cmdver = 0.4.1 method = merge diff --git a/packages/PEGTL/.travis.yml b/packages/PEGTL/.travis.yml index 95e20d5032f8e6f5e3cd3adb8f7d200153d039a8..8d81bb3ce3272882de4fc246274b13ea56acfb72 100644 --- a/packages/PEGTL/.travis.yml +++ b/packages/PEGTL/.travis.yml @@ -4,43 +4,48 @@ dist: xenial jobs: include: - - &gcc-7 - compiler: gcc + - compiler: gcc addons: apt: sources: [ ubuntu-toolchain-r-test ] - packages: [ g++-7 ] + packages: [ g++-8 ] env: - - CXX=g++-7 + - CXX=g++-8 + - LDFLAGS="-lstdc++fs" - - &gcc-8 - compiler: gcc + - compiler: gcc addons: apt: sources: [ ubuntu-toolchain-r-test ] - packages: [ g++-8 ] - env: - - CXX=g++-8 - - - <<: *gcc-8 + packages: [ g++-9 ] env: - - CXX=g++-8 - - CPPFLAGS="-fno-rtti" + - CXX=g++-9 - - &gcc-9 + - &gcc-10 + dist: bionic compiler: gcc addons: apt: sources: [ ubuntu-toolchain-r-test ] - packages: [ g++-9 ] + packages: [ g++-10 ] env: - - CXX=g++-9 + - CXX=g++-10 + + - <<: *gcc-10 + env: + - CXX=g++-10 + - CXXSTD="-std=c++20" + + - <<: *gcc-10 + env: + - CXX=g++-10 + - CPPFLAGS="-fno-rtti" - compiler: clang addons: apt: sources: [ ubuntu-toolchain-r-test, llvm-toolchain-xenial-5 ] - packages: [ clang-5.0, g++-7 ] + packages: [ clang-5.0, g++-9 ] env: - CXX=clang++-5.0 @@ -48,7 +53,7 @@ jobs: addons: apt: sources: [ ubuntu-toolchain-r-test, llvm-toolchain-xenial-6 ] - packages: [ clang-6.0, g++-7 ] + packages: [ clang-6.0, g++-9 ] env: - CXX=clang++-6.0 @@ -56,7 +61,7 @@ jobs: addons: apt: sources: [ ubuntu-toolchain-r-test, llvm-toolchain-xenial-7 ] - packages: [ clang-7, g++-7 ] + packages: [ clang-7, g++-9 ] env: - CXX=clang++-7 @@ -64,14 +69,14 @@ jobs: addons: apt: sources: [ ubuntu-toolchain-r-test, llvm-toolchain-xenial-8 ] - packages: [ clang-8, g++-8 ] + packages: [ clang-8, g++-9 ] env: - CXX=clang++-8 - compiler: clang addons: apt: - sources: &clang-9-sources + sources: - ubuntu-toolchain-r-test - sourceline: deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main key_url: https://apt.llvm.org/llvm-snapshot.gpg.key @@ -80,17 +85,23 @@ jobs: - CXX=clang++-9 - &clang-10 + dist: bionic compiler: clang addons: apt: sources: &clang-10-sources - ubuntu-toolchain-r-test - - sourceline: deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main + - sourceline: deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main key_url: https://apt.llvm.org/llvm-snapshot.gpg.key - packages: [ clang-10, g++-9 ] + packages: [ clang-10, g++-10 ] env: - CXX=clang++-10 + - <<: *clang-10 + env: + - CXX=clang++-10 + - CXXSTD="-std=c++20" + - <<: *clang-10 env: - CXX=clang++-10 @@ -101,19 +112,12 @@ jobs: - CXX=clang++-10 - CPPFLAGS="-fno-rtti" - - &osx - os: osx - osx_image: xcode9.4 + - os: osx + osx_image: xcode11.4 compiler: clang env: - CXX=clang++ - - <<: *osx - osx_image: xcode10.3 - - - <<: *osx - osx_image: xcode11.4 - - &android compiler: clang addons: @@ -153,14 +157,14 @@ jobs: - ANDROID_ABI=arm64-v8a - ANDROID_PLATFORM=android-24 - - <<: *gcc-9 + - <<: *gcc-10 env: - - CXX=g++-9 + - CXX=g++-10 - CPPFLAGS="-fsanitize=undefined -fuse-ld=gold" - - <<: *gcc-9 + - <<: *gcc-10 env: - - CXX=g++-9 + - CXX=g++-10 - CPPFLAGS="-fsanitize=address -fuse-ld=gold" - <<: *clang-10 @@ -173,53 +177,57 @@ jobs: - CXX=clang++-10 - CPPFLAGS="-fsanitize=address" - - compiler: clang + - dist: bionic + compiler: clang addons: apt: sources: *clang-10-sources - packages: [ clang-10, clang-tidy-10, g++-9 ] + packages: [ clang-10, clang-tidy-10, g++-10 ] env: - CXX=clang++-10 - CLANG_TIDY=clang-tidy-10 script: - make -kj3 clang-tidy - - compiler: clang + - dist: bionic + compiler: clang addons: apt: sources: *clang-10-sources - packages: [ clang-tools-10, g++-9 ] + packages: [ clang-tools-10, g++-10 ] script: - scan-build-10 --use-c++=clang++-10 --status-bugs make -kj3 - - compiler: gcc + - dist: bionic + compiler: gcc addons: apt: sources: [ ubuntu-toolchain-r-test ] - packages: [ g++-9, valgrind ] + packages: [ g++-10, valgrind ] env: - - CXX=g++-9 + - CXX=g++-10 - SPECIAL=valgrind script: - make -kj3 valgrind - - <<: *gcc-7 + - <<: *gcc-10 env: - - CXX=g++-7 + - CXX=g++-10 - CXXFLAGS="-O0 --coverage" before_script: - pip install --user cpp-coveralls script: - make -kj3 check - - coveralls --gcov gcov-7 --gcov-options '\-lp' --exclude src + - coveralls --gcov gcov-10 --gcov-options '\-lp' --exclude src - - compiler: clang + - dist: bionic + compiler: clang addons: apt: - sources: *clang-9-sources - packages: [ clang-format-9, g++-9 ] + sources: *clang-10-sources + packages: [ clang-format-10, g++-10 ] script: - - clang-format-9 -i -style=file $(find . -name '[^.]*.[hc]pp') + - clang-format-10 -i -style=file $(find . -name '[^.]*.[hc]pp') - git diff --exit-code script: diff --git a/packages/PEGTL/Makefile b/packages/PEGTL/Makefile index 9ff538aff11cec39c905b5d76871e6338af76b73..3f47845535131816144829cf7cbecf1724fbe640 100644 --- a/packages/PEGTL/Makefile +++ b/packages/PEGTL/Makefile @@ -62,7 +62,7 @@ valgrind: $(UNIT_TESTS:%=%.valgrind) @echo "All $(words $(UNIT_TESTS)) valgrind tests passed." build/%.clang-tidy: % .clang-tidy - $(CLANG_TIDY) -quiet $< -- $(CXXSTD) -Iinclude $(CPPFLAGS) $(CXXFLAGS) 2>/dev/null + $(CLANG_TIDY) -quiet $< -- $(CXXSTD) -Iinclude $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) 2>/dev/null @mkdir -p $(@D) @touch $@ @@ -80,7 +80,7 @@ build/%.d: %.cpp Makefile $(CXX) $(CXXSTD) -Iinclude $(CPPFLAGS) -MM -MQ $@ $< -o $@ build/%: %.cpp build/%.d - $(CXX) $(CXXSTD) -Iinclude $(CPPFLAGS) $(CXXFLAGS) $< -o $@ + $(CXX) $(CXXSTD) -Iinclude $(CPPFLAGS) $(CXXFLAGS) $< $(LDFLAGS) -o $@ .PHONY: amalgamate amalgamate: build/amalgamated/pegtl.hpp @@ -94,7 +94,6 @@ build/amalgamated/pegtl.hpp: $(HEADERS) @sed -i -e 's%^//#include "%#include "%g' $$(find build/include -name '*.hpp') @for i in $$(find build/include -name '*.hpp'); do echo "#pragma once" >tmp.out; echo "#line 1" >>tmp.out; cat $$i >>tmp.out; mv tmp.out $$i; done @echo '#include "tao/pegtl.hpp"' >build/include/amalgamated.hpp - @echo '#include "tao/pegtl/analyze.hpp"' >>build/include/amalgamated.hpp @( cd build/include ; for i in tao/pegtl/contrib/*.hpp; do echo "#include \"$$i\""; done ) >>build/include/amalgamated.hpp @echo -e "/*\n\nWelcome to the Parsing Expression Grammar Template Library (PEGTL)." >$@ @echo -e "See https://github.com/taocpp/PEGTL/ for more information, documentation, etc.\n" >>$@ diff --git a/packages/PEGTL/README.md b/packages/PEGTL/README.md index 2b57955028ddacc5d5418558f98a2589c1fa6680..c11b0c8822e7f67f8280f0a17529ed6344b6b498 100644 --- a/packages/PEGTL/README.md +++ b/packages/PEGTL/README.md @@ -1,12 +1,5 @@ # Welcome to the PEGTL -[](https://github.com/taocpp/PEGTL/releases/latest) -[](https://bintray.com/conan/conan-center/taocpp-pegtl%3A_/_latestVersion) -[](https://travis-ci.org/taocpp/PEGTL) -[](https://ci.appveyor.com/project/taocpp/PEGTL) -[](https://coveralls.io/github/taocpp/PEGTL) -[](https://lgtm.com/projects/g/taocpp/PEGTL/context:cpp) - The Parsing Expression Grammar Template Library (PEGTL) is a zero-dependency C++ header-only parser combinator library for creating parsers according to a [Parsing Expression Grammar](http://en.wikipedia.org/wiki/Parsing_expression_grammar) (PEG). ## Documentation @@ -56,6 +49,9 @@ The rules are expressed in C++ as template instantiations, and it is the compile ## Status +[](https://travis-ci.org/taocpp/PEGTL) +[](https://ci.appveyor.com/project/taocpp/PEGTL) + Each commit is automatically tested with multiple architectures, operating systems, compilers, and versions thereof. * Windows @@ -65,17 +61,36 @@ Each commit is automatically tested with multiple architectures, operating syste * macOS (using libc++) - * macOS 10.13, Xcode 9.4 - * macOS 10.14, Xcode 10.3 - * macOS 10.14, Xcode 11.4 + * macOS 10.15, Xcode 11.4 * Ubuntu 16.04 LTS (using libstdc++) - * GCC 7.x, 8.x, 9.x - * Clang 5.x, 6.x, 7.x, 8.x, 9.x, 10.x + * GCC 8.x, 9.x + * Clang 5.x, 6.x, 7.x, 8.x, 9.x + +* Ubuntu 18.04 LTS (using libstdc++) + + * GCC 10.x + * Clang 10.x + +### Code Quality + +[](https://lgtm.com/projects/g/taocpp/PEGTL/context:cpp) + +Each commit is checked with Clang's [Static Analyzer](https://clang-analyzer.llvm.org/), GCC's and Clang's [sanitizers](https://github.com/google/sanitizers), [`clang-tidy`](http://clang.llvm.org/extra/clang-tidy/), and [`valgrind`](http://valgrind.org/). +Additionally, we use [LGTM](https://lgtm.com/) to scan for (security) issues. +Note that [LGTM](https://lgtm.com/) sometimes generate false positives, hence the above badge may not show an accurate grade. + +### Code Coverage + +[](https://coveralls.io/github/taocpp/PEGTL) -Additionally, each commit is checked with Clang's [Static Analyzer](https://clang-analyzer.llvm.org/), GCC's and Clang's [sanitizers](https://github.com/google/sanitizers), [`clang-tidy`](http://clang.llvm.org/extra/clang-tidy/), and [`valgrind`](http://valgrind.org/). Code coverage is automatically measured and the unit tests cover 100% of the core library code (for releases). +Note that the infrastructure is partially broken, hence the above badge may not show 100%. + +### Versioning + +[](https://github.com/taocpp/PEGTL/releases/latest) [Releases](https://github.com/taocpp/PEGTL/releases) are done in accordance with [Semantic Versioning](http://semver.org/). Incompatible API changes are *only* allowed to occur between major versions. @@ -85,47 +100,48 @@ For details see the [changelog](doc/Changelog.md). In appreciation of all contributions here are the people that have [directly contributed](https://github.com/taocpp/PEGTL/graphs/contributors) to the PEGTL and/or its development. -[<img alt="andoma" src="https://avatars.githubusercontent.com/u/216384?s=117" width="117">](https://github.com/andoma) -[<img alt="bjoe" src="https://avatars.githubusercontent.com/u/727911?s=117" width="117">](https://github.com/bjoe) -[<img alt="bwagner" src="https://avatars.githubusercontent.com/u/447049?s=117" width="117">](https://github.com/bwagner) -[<img alt="cdiggins" src="https://avatars.githubusercontent.com/u/1759994?s=460&v=4?s=117" width="117">](https://github.com/cdiggins) -[<img alt="delpinux" src="https://avatars.githubusercontent.com/u/35096584?s=117" width="117">](https://github.com/delpinux) -[<img alt="dkopecek" src="https://avatars.githubusercontent.com/u/1353140?s=117" width="117">](https://github.com/dkopecek) -[<img alt="irrequietus" src="https://avatars.githubusercontent.com/u/231192?s=117" width="117">](https://github.com/irrequietus) -[<img alt="jedelbo" src="https://avatars.githubusercontent.com/u/572755?s=117" width="117">](https://github.com/jedelbo) -[<img alt="joelfrederico" src="https://avatars.githubusercontent.com/u/458871?s=117" width="117">](https://github.com/joelfrederico) -[<img alt="johelegp" src="https://avatars.githubusercontent.com/u/21071787?s=117" width="117">](https://github.com/johelegp) -[<img alt="jovermann" src="https://avatars.githubusercontent.com/u/6087443?s=117" width="117">](https://github.com/jovermann) -[<img alt="kneth" src="https://avatars.githubusercontent.com/u/1225363?s=117" width="117">](https://github.com/kneth) -[<img alt="kuzmas" src="https://avatars.githubusercontent.com/u/1858553?s=117" width="117">](https://github.com/kuzmas) -[<img alt="lambdafu" src="https://avatars.githubusercontent.com/u/1138455?s=117" width="117">](https://github.com/lambdafu) -[<img alt="lichray" src="https://avatars.githubusercontent.com/u/433009?s=117" width="117">](https://github.com/lichray) -[<img alt="michael-brade" src="https://avatars.githubusercontent.com/u/8768950?s=117" width="117">](https://github.com/michael-brade) -[<img alt="mkrupcale" src="https://avatars.githubusercontent.com/u/13936020?s=117" width="117">](https://github.com/mkrupcale) -[<img alt="newproggie" src="https://avatars.githubusercontent.com/u/162319?s=460&v=4?s=117" width="117">](https://github.com/newproggie) -[<img alt="obiwahn" src="https://avatars.githubusercontent.com/u/741109?s=117" width="117">](https://github.com/obiwahn) -[<img alt="ohanar" src="https://avatars.githubusercontent.com/u/1442822?s=117" width="117">](https://github.com/ohanar) -[<img alt="pauloscustodio" src="https://avatars.githubusercontent.com/u/70773?s=117" width="117">](https://github.com/pauloscustodio) -[<img alt="pleroux0" src="https://avatars.githubusercontent.com/u/39619854?s=117" width="117">](https://github.com/pleroux0) -[<img alt="quadfault" src="https://avatars.githubusercontent.com/u/30195320?s=117" width="117">](https://github.com/quadfault) -[<img alt="robertcampion" src="https://avatars.githubusercontent.com/u/4220569?s=117" width="117">](https://github.com/robertcampion) -[<img alt="samhocevar" src="https://avatars.githubusercontent.com/u/245089?s=117" width="117">](https://github.com/samhocevar) -[<img alt="sanssecours" src="https://avatars.githubusercontent.com/u/691989?s=117" width="117">](https://github.com/sanssecours) -[<img alt="sgbeal" src="https://avatars.githubusercontent.com/u/235303?s=117" width="117">](https://github.com/sgbeal) -[<img alt="skyrich62" src="https://avatars.githubusercontent.com/u/23705081?s=117" width="117">](https://github.com/skyrich62) -[<img alt="studoot" src="https://avatars.githubusercontent.com/u/799344?s=117" width="117">](https://github.com/studoot) -[<img alt="svenjo" src="https://avatars.githubusercontent.com/u/1538181?s=460&v=4?s=117" width="117">](https://github.com/svenjo) -[<img alt="wickedmic" src="https://avatars.githubusercontent.com/u/12001183?s=117" width="117">](https://github.com/wickedmic) -[<img alt="wravery" src="https://avatars.githubusercontent.com/u/6502881?s=117" width="117">](https://github.com/wravery) -[<img alt="zhihaoy" src="https://avatars.githubusercontent.com/u/43971430?s=117" width="117">](https://github.com/zhihaoy) +[<img alt="andoma" src="https://avatars.githubusercontent.com/u/216384" width="120">](https://github.com/andoma) +[<img alt="bjoe" src="https://avatars.githubusercontent.com/u/727911" width="120">](https://github.com/bjoe) +[<img alt="bwagner" src="https://avatars.githubusercontent.com/u/447049" width="120">](https://github.com/bwagner) +[<img alt="cdiggins" src="https://avatars.githubusercontent.com/u/1759994" width="120">](https://github.com/cdiggins) +[<img alt="delpinux" src="https://avatars.githubusercontent.com/u/35096584" width="120">](https://github.com/delpinux) +[<img alt="dkopecek" src="https://avatars.githubusercontent.com/u/1353140" width="120">](https://github.com/dkopecek) +[<img alt="gene-hightower" src="https://avatars.githubusercontent.com/u/3957811" width="120">](https://github.com/gene-hightower) +[<img alt="irrequietus" src="https://avatars.githubusercontent.com/u/231192" width="120">](https://github.com/irrequietus) +[<img alt="jedelbo" src="https://avatars.githubusercontent.com/u/572755" width="120">](https://github.com/jedelbo) +[<img alt="joelfrederico" src="https://avatars.githubusercontent.com/u/458871" width="120">](https://github.com/joelfrederico) +[<img alt="johelegp" src="https://avatars.githubusercontent.com/u/21071787" width="120">](https://github.com/johelegp) +[<img alt="jovermann" src="https://avatars.githubusercontent.com/u/6087443" width="120">](https://github.com/jovermann) +[<img alt="kneth" src="https://avatars.githubusercontent.com/u/1225363" width="120">](https://github.com/kneth) +[<img alt="kuzmas" src="https://avatars.githubusercontent.com/u/1858553" width="120">](https://github.com/kuzmas) +[<img alt="lambdafu" src="https://avatars.githubusercontent.com/u/1138455" width="120">](https://github.com/lambdafu) +[<img alt="lichray" src="https://avatars.githubusercontent.com/u/433009" width="120">](https://github.com/lichray) +[<img alt="michael-brade" src="https://avatars.githubusercontent.com/u/8768950" width="120">](https://github.com/michael-brade) +[<img alt="mkrupcale" src="https://avatars.githubusercontent.com/u/13936020" width="120">](https://github.com/mkrupcale) +[<img alt="newproggie" src="https://avatars.githubusercontent.com/u/162319" width="120">](https://github.com/newproggie) +[<img alt="obiwahn" src="https://avatars.githubusercontent.com/u/741109" width="120">](https://github.com/obiwahn) +[<img alt="ohanar" src="https://avatars.githubusercontent.com/u/1442822" width="120">](https://github.com/ohanar) +[<img alt="pauloscustodio" src="https://avatars.githubusercontent.com/u/70773" width="120">](https://github.com/pauloscustodio) +[<img alt="pleroux0" src="https://avatars.githubusercontent.com/u/39619854" width="120">](https://github.com/pleroux0) +[<img alt="quadfault" src="https://avatars.githubusercontent.com/u/30195320" width="120">](https://github.com/quadfault) +[<img alt="robertcampion" src="https://avatars.githubusercontent.com/u/4220569" width="120">](https://github.com/robertcampion) +[<img alt="samhocevar" src="https://avatars.githubusercontent.com/u/245089" width="120">](https://github.com/samhocevar) +[<img alt="sanssecours" src="https://avatars.githubusercontent.com/u/691989" width="120">](https://github.com/sanssecours) +[<img alt="sgbeal" src="https://avatars.githubusercontent.com/u/235303" width="120">](https://github.com/sgbeal) +[<img alt="skyrich62" src="https://avatars.githubusercontent.com/u/23705081" width="120">](https://github.com/skyrich62) +[<img alt="studoot" src="https://avatars.githubusercontent.com/u/799344" width="120">](https://github.com/studoot) +[<img alt="svenjo" src="https://avatars.githubusercontent.com/u/1538181" width="120">](https://github.com/svenjo) +[<img alt="wickedmic" src="https://avatars.githubusercontent.com/u/12001183" width="120">](https://github.com/wickedmic) +[<img alt="wravery" src="https://avatars.githubusercontent.com/u/6502881" width="120">](https://github.com/wravery) +[<img alt="zhihaoy" src="https://avatars.githubusercontent.com/u/43971430" width="120">](https://github.com/zhihaoy) ## The Art of C++ The PEGTL is part of [The Art of C++](https://taocpp.github.io/). -[<img alt="colinh" src="https://avatars.githubusercontent.com/u/113184?s=117" width="117">](https://github.com/colinh) -[<img alt="d-frey" src="https://avatars.githubusercontent.com/u/3956325?s=117" width="117">](https://github.com/d-frey) -[<img alt="uilianries" src="https://avatars.githubusercontent.com/u/4870173?s=117" width="117">](https://github.com/uilianries) +[<img alt="colinh" src="https://avatars.githubusercontent.com/u/113184" width="120">](https://github.com/colinh) +[<img alt="d-frey" src="https://avatars.githubusercontent.com/u/3956325" width="120">](https://github.com/d-frey) +[<img alt="uilianries" src="https://avatars.githubusercontent.com/u/4870173" width="120">](https://github.com/uilianries) ## Contact diff --git a/packages/PEGTL/doc/Actions-and-States.md b/packages/PEGTL/doc/Actions-and-States.md index ae234dc28007583c315f81b06205a7198dfb8dc1..480df8140fae8188ddad1c9f2271b99ce21225f0 100644 --- a/packages/PEGTL/doc/Actions-and-States.md +++ b/packages/PEGTL/doc/Actions-and-States.md @@ -198,7 +198,7 @@ Conversely `iterator()` returns a pointer or iterator to the beginning of the ac More importantly the `action_input` does **not** own the data it points to, it belongs to the original input used in the parsing run. Therefore **the validity of the pointed-to data might not extend (much) beyond the call to `apply()`**! -When the original input has tracking mode `eager`, the `iterator_t` returned by `action_input::iterator()` will contain the `byte`, `line` and `byte_in_line` counters corresponding to the beginning of the matched input represented by the `action_input`. +When the original input has tracking mode `eager`, the `iterator_t` returned by `action_input::iterator()` will contain the `byte`, `line` and `column` counters corresponding to the beginning of the matched input represented by the `action_input`. When the original input has tracking mode `lazy`, then `action_input::position()` is not efficient because it calculates the line number etc. by scanning the complete original input from the beginning diff --git a/packages/PEGTL/doc/Changelog.md b/packages/PEGTL/doc/Changelog.md index 3198b38dfad39a10d59ff81600ee256c3b0ded67..a6290b6b79212f37de6db731df3879cf0646d58e 100644 --- a/packages/PEGTL/doc/Changelog.md +++ b/packages/PEGTL/doc/Changelog.md @@ -5,36 +5,51 @@ **Not yet released** * Use the [**migration guide**](Migration-Guide.md#version-300) when updating. -* Updated required C++ standard to C++17. -* Updated required [CMake](https://cmake.org/) version to 3.8. -* The macro `TAO_PEGTL_NAMESPACE` now contains the fully qualified namespace, e.g. `tao::pegtl`. -* Replaced `tao::pegtl::input_error` with `std::system_error`. -* Moved the analysis function and header to contrib. -* Replaced `analysis_t` with more general and complete `rule_t` and `subs_t`. -* Added functions to visit all rules of a grammar. -* Added infrastructure and functions to measure rule coverage of a parsing run. -* Added [`must_if<>`](Errors-and-Exceptions.md#custom-exception-messages) - * Allows to define custom error messages for global errors. - * As a non-intrusive way to define global parse errors for a grammar retroactively. -* Moved rule `eolf` from inline namespace `tao::pegtl::ascii` to `tao::pegtl`. -* Changed message of `tao::pegtl::parse_error` to no longer contain the position redundantly. -* Changed rules in `tao/pegtl/contrib/integer.hpp` to not accept redundant leading zeros. -* Added rules to `tao/pegtl/contrib/integer.hpp` that test unsigned values against a maximum. -* Removed option of [state](Rule-Reference.md#state-s-r-)'s `S::success()` to have an extended signature to get access to the current `apply_mode`, `rewind_mode`, *action*- and *control* class (template). -* Added `[[nodiscard]]` or `[[noreturn]]` to most non-void functions. -* Removed compatibility macros starting with `TAOCPP_PEGTL_`. -* Removed compatibility uppercase enumerators. -* Removed compatibility `peek_byte()` member functions. -* Removed compatibility header `changes.hpp` from contrib. -* Demoted UTF-16 and UTF-32 support to contrib. -* Demoted UINT-8, UINT-16, UINT-32 and UINT-64 support to contrib. -* Folded `contrib/counter.hpp` into `json_count.cpp`, count is superceded by coverage. -* Refactored demangling. - * Improves generated code to be shorter and more efficient. - * Removes the need for RTTI. - * Some broken/unknown compilers will use RTTI as a fallback, without demangling. -* Refactored parse tree type storage/handling. - * Removes the need for RTTI. +* Infrastructure + * Updated required C++ standard to C++17. + * Updated required [CMake](https://cmake.org/) version to 3.8. + * The macro `TAO_PEGTL_NAMESPACE` now contains the fully qualified namespace, e.g. `tao::pegtl`. + * Added `[[nodiscard]]` or `[[noreturn]]` to most non-void functions. +* Meta-Data Layer + * Replaced `analysis_t` with more general and complete `rule_t` and `subs_t`. + * Added functions to visit all rules of a grammar. + * Added functions to measure rule coverage of a parsing run. + * Moved the analysis function and header to contrib. +* Error Handling + * Replaced `tao::pegtl::input_error` with `std::system_error` and `std::filesystem::filesystem_error`. + * Added [`must_if<>`](Errors-and-Exceptions.md#custom-exception-messages) + * Allows to define custom error messages for global errors. + * Adds a non-intrusive way to define global parse errors for a grammar retroactively. +* Demangling + * Removed the need for RTTI. + * Some broken/unknown compilers will use RTTI as a fallback, without demangling. + * Moved `tao::pegtl::internal::demangle<T>()` to `tao::demangle<T>()`. + * Improved generated code to be shorter and more efficient. +* Parse Tree + * Removed the need for RTTI. +* Other + * Changed `std::string` to `std::filesystem::path` for filename parameters. + * Renamed `byte_in_line` to `column` and use 1-based counting. + * Moved rule `eolf` from inline namespace `tao::pegtl::ascii` to `tao::pegtl`. + * Changed rules in `tao/pegtl/contrib/integer.hpp` to not accept redundant leading zeros. + * Added rules to `tao/pegtl/contrib/integer.hpp` that test unsigned values against a maximum. + * Demoted UTF-16 and UTF-32 support to contrib. + * Demoted UINT-8, UINT-16, UINT-32 and UINT-64 support to contrib. + * Folded `contrib/counter.hpp` into `json_count.cpp`, count is superceded by coverage. +* Cleanup + * Removed option of [state](Rule-Reference.md#state-s-r-)'s `S::success()` to have an extended signature to get access to the current `apply_mode`, `rewind_mode`, *action*- and *control* class (template). + * Removed compatibility macros starting with `TAOCPP_PEGTL_`. + * Removed compatibility uppercase enumerators. + * Removed compatibility `peek_byte()` member functions. + * Removed compatibility header `changes.hpp` from contrib. + +## 2.8.3 + +Released 2020-04-22 + +* Fixed excessive read-ahead with incremental inputs. +* Added state manipulators `remove_first_state`, `remove_last_states`, `rotate_states_right`, `rotate_states_left`, and `reverse_states` to contrib. +* Reduced the number of intermediate parse tree nodes. ## 2.8.2 diff --git a/packages/PEGTL/doc/Control-and-Debug.md b/packages/PEGTL/doc/Control-and-Debug.md index c8817e611e8a84e2c7894da571b74798bf6edf7c..7d801ef358f8822937251303bf3991abdac4b9ee 100644 --- a/packages/PEGTL/doc/Control-and-Debug.md +++ b/packages/PEGTL/doc/Control-and-Debug.md @@ -71,6 +71,13 @@ struct normal The static member functions `start()`, `success()` and `failure()` can be used to debug a grammar by using them to provide insight into what exactly is going on during a parsing run, or to construct a parse tree, etc. +There is one more, *optional* hook function: `unwind()`. +It is called when a rule throws an exception, e.g. on global error. +It's signature is identical to `start()`/`success()`/`failure()`. +It is not included in the default control template `normal`, as the existence of an `unwind()` method requires an additional `try`/`catch` block. +This might potentially have an impact on the binary size and therefore, one should only add an `unwind()` method if necessary. +Several other control classes utilize the `unwind()` method to track the execution even in the presence of global errors. + The static member function `raise()` is used to create a global error, and any replacement should again throw an exception, or abort the application. The static member functions `apply()` and `apply0()` can customise how actions with, and without, receiving the matched input are called, respectively. @@ -89,17 +96,13 @@ Before attempting to match a rule `R`, the PEGTL calls `C< R >::start()` where ` Depending on what happens during the attempt to match `R`, one of the other three functions might be called. - If `R` succeeds, then `C< R >::success()` is called; compared to the call to `C< R >::start()`, the input will have consumed whatever the successful match of `R` consumed. - -- If `R` finishes with a failure, i.e. a return value of `false` from `match()`, then `C< R >::failure()` is called; a failed match **must not** consume input. - +- If `R` finishes with a local failure, i.e. a return value of `false` from `match()`, then `C< R >::failure()` is called; a failed match **must not** consume input. +- If `R` finishes with a global failure, i.e. an exception being thrown from `match()`, then, if present, `C< R >::unwind()` is called. - If `R` is wrapped in `must< R >`, a global failure is generated by calling `C< R >::raise()` to throw some exception as is expected by the PEGTL in this case. -- If a sub-rule of `R` finishes with a global failure, and the exception is not caught by a `try_catch` or similar combinator, then no other function of `C< R >` is called after `C< R >::start()`. - Additionally, if matching `R` was successful and actions are enabled: - If `C< R >::apply()` exists, then `C< R >::apply()` is called with the matched input and the current state arguments. - - If `C< R >::apply0()` exists, then `C< R >::apply0()` is called with the current state arguments. It is an error when both `C< R >::apply()` and `C< R >::apply0()` exist. @@ -112,7 +115,6 @@ If either produce a (local) failure then `C< R >::failure()` is called. In all cases where an action is called, the success or failure hooks are invoked after the action returns. The included class `tao::pegtl::tracer` in `<tao/pegtl/contrib/tracer.hpp>` gives a practical example that can be used as control class to debug grammars. -When an instance of class `tao::pegtl::trace_state` is used as single state in a parsing run with the tracer-control then the debug output contains a line number and rule number as additional information. ## Exception Throwing diff --git a/packages/PEGTL/doc/Errors-and-Exceptions.md b/packages/PEGTL/doc/Errors-and-Exceptions.md index 7cd752ef7eb009d7489070f9286d447613113e58..10408129978e2abd86bfced826725a9e9a519714 100644 --- a/packages/PEGTL/doc/Errors-and-Exceptions.md +++ b/packages/PEGTL/doc/Errors-and-Exceptions.md @@ -6,11 +6,12 @@ A parsing run, a call to one of the `parse()` functions as explained in [Inputs * A return value of `false` is called a *local failure* (even when propagated to the top). * An exception indicating a *global failure* is thrown. -The PEGTL parsing rules throw exceptions of type `tao::pegtl::parse_error`, some of the inputs throw exceptions of type `tao::pegtl::input_error`. +The PEGTL parsing rules throw exceptions of type `tao::pegtl::parse_error`, some of the inputs throw additional exceptions like `std::system_error` or `std::filesystem_error`. Other exception classes can be used freely from actions and custom parsing rules. ## Contents +* [Global Failure](#global-failure) * [Local to Global Failure](#local-to-global-failure) * [Intrusive Local to Global Failure](#intrusive-local-to-global-failure) * [Non-Intrusive Local to Global Failure](#non-intrusive-local-to-global-failure) @@ -18,6 +19,52 @@ Other exception classes can be used freely from actions and custom parsing rules * [Examples for Must Rules](#examples-for-must-rules) * [Custom Exception Messages](#custom-exception-messages) +## Global Failure + +By default, global failure means that an exception of type `tao::pegtl::parse_error` is thrown. + +Synposis: + +```c++ +namespace tao::pegtl +{ + class parse_error + : public std::runtime_error + { + parse_error( const char* msg, position p ); + + parse_error( const std::string& msg, position p ) + : parse_error( msg.c_str(), std::move( p ) ) + {} + + template< typename ParseInput > + parse_error( const char* msg, const ParseInput& in ) + : parse_error( msg, in.position() ) + {} + + template< typename ParseInput > + parse_error( const std::string& msg, const ParseInput& in ) + : parse_error( msg, in.position() ) + {} + + const char* what() const noexcept override; + + std::string_view message() const noexcept; + const std::vector< position >& positions() const noexcept; + + void add_position( position&& p ); + }; +} +``` + +The `what()` message will contain all positions as well as the original `msg`. +This allows retrieval of all information if the exception is handled as a `std::runtime_error` in a generic way. + +The `message()` function will return the original `msg`, while `positions()` allows access to the stored positions. +This is useful to decompose the exception and provide more helpful errors to the user. + +The constructors can be used by custom rules to signal global failure, while `add_position()` is often used when you are parsing nested data, so you can append the position in the original file which includes the nested file. + ## Local to Global Failure ### Intrusive Local to Global Failure @@ -144,14 +191,25 @@ struct error { template< typename Rule > static constexpr auto message = error_m template< typename Rule > using control = tao::pegtl::must_if< error >::control< Rule >; ``` +`must_if<>` expects a wrapper for the error message as its first template parameter. +There is a second parameter for the base control class, which defaults to `tao::pegtl::normal`, and which can combine `must_if`'s control class with other control classes. + Since `raise()` is only instantiated for those rules for which `must<>` could trigger an exception, it is sufficient to provide specialisations of the error message string for those rules. Furthermore, there will be a compile-time error (i.e. a `static_assert`) for all rules for which the specialisation was forgotten although `raise()` could be called. -The [control class](Control-and-Debug.md) provided by `must_if<>` also turns local failures into global failure if an error message is provided, i.e. if the error message is not `nullptr`. +The [control class](Control-and-Debug.md) provided by `must_if<>` also turns, by default, local failures into global failure if an error message is provided, i.e. if the error message is not `nullptr`. This means that one can provide additional points in the grammar where a global failure is triggered, even when the grammar contains no `must<>` error points. -`must_if<>` expects a wrapper for the error message as its first template parameter. -There is a second parameter for the base control class, which defaults to `tao::pegtl::normal`, and which can combine `must_if`'s control class with other control classes. +The above feature also means that a rule which is used both with and without `must<>`, one would not only provide a custom error message for the location where the rule is failing within a `must<>`-context, but local errors in other contexts are implicitly turned into global error. +If this behaviour is not intended, one can disable the "turn local to global failure" feature by setting `raise_on_failure` to `false` in the wrapper class: + +```c++ +struct error +{ + template< typename Rule > static constexpr bool raise_on_failure = false; + template< typename Rule > static constexpr auto message = error_message< Rule >; +}; +``` It is advisable to choose the error points in the grammar with prudence. This choice becoming particularly cumbersome and/or resulting in a large number of error points might be an indication of the grammar needing some kind of simplification or restructuring. diff --git a/packages/PEGTL/doc/Getting-Started.md b/packages/PEGTL/doc/Getting-Started.md index d2ef73f544ed8e824f94101b2c967c789e9227bc..50674bd2af263fd471050316fc5f84dbc31f25d1 100644 --- a/packages/PEGTL/doc/Getting-Started.md +++ b/packages/PEGTL/doc/Getting-Started.md @@ -4,9 +4,6 @@ Since the PEGTL is a parser library, here is an "inverse hello world" example th rather than prints, the string `Hello, foo!` for any sequence of alphabetic ASCII characters `foo`. ```c++ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - #include <string> #include <iostream> @@ -98,7 +95,174 @@ terminate called after throwing an instance of 'tao::pegtl::parse_error' Aborted (core dumped) ``` -Frequently an application will include a top-level `try-catch` block to handle -the exception. +The PEGTL provides multiple facilities that help to get started and develop your grammar. +In the following paragraphs we will show several small programs to showcase the capabilities of the PEGTL. + +Note, however, that all examples shown in this document will lack proper error handling. +Frequently an application will include `try-catch` blocks to handle the exceptions. +The correct way of handling errors is shown at the last paragraph of this page. + +## Grammar Analysis + +Every grammar must be free of cycles that make no progress, i.e. the cycle does not consume any input. +This is a common problem in parsing called [left recursion](https://en.wikipedia.org/wiki/Left_recursion). +Especially with the PEG formalism, it results in an infinite loop and, eventually, in a stack overflow. + +The PEGTL provides a [grammar analysis](Grammar-Analysis.md) with which a grammar can be verified. +Note that this is done at runtime as a pure compile-time analysis would lead to insupportable compile-times. +The analysis, however, is only based on the grammar itself and not on a specific input. +Additionally, the analysis is typically written as a separate program to keep any overhead from your normal applications. + +```c++ +#include <tao/pegtl.hpp> +#include <tao/pegtl/contrib/analyze.hpp> + +// This example uses the included JSON grammar +#include <tao/pegtl/contrib/json.hpp> + +namespace pegtl = tao::pegtl; + +using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; + +int main() +{ + if( pegtl::analyze< grammar >() != 0 ) { + std::cerr << "cycles without progress detected!\n"; + return 1; + } + + return 0; +} +``` + +## Tracer + +One of the most basic tools when developing a grammar is a tracer that prints every step of a parsing run. +The PEGTL provides a tracer that will print to stderr, as well as allowing users to write their own tracers to output other formats. + +```c++ +#include <tao/pegtl.hpp> +#include <tao/pegtl/contrib/trace.hpp> + +// This example uses the included JSON grammar +#include <tao/pegtl/contrib/json.hpp> + +namespace pegtl = tao::pegtl; + +using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; + +int main( int argc, char** argv ) +{ + if( argc != 2 ) return 1; + + pegtl::argv_input in( argv, i ); + pegtl::standard_tracer tr( in ); + tr.parse< grammar >( in ); + + return 0; +} +``` + +In the above each command line parameter is parsed as a JSON string. +As the output gets long quickly, we will not show it here, please have a look at the [Tracer](Tracer.md) documentation. + +TODO: Write `Tracer.md`. + +## Parse Tree / AST + +When developing grammars, a common goal is to generate a [parse tree](https://en.wikipedia.org/wiki/Parse_tree) or an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree). + +The PEGTL provides a [Parse Tree](Parse-Tree.md) builder that can filter and/or transform tree nodes on-the-fly. +Additionally, a helper is provided to print out the resulting data structure in the [DOT](https://en.wikipedia.org/wiki/DOT_(graph_description_language)) format, suitable for creating a graphical representation of the parse tree. + +The following example uses a selector to filter the parse tree nodes, as otherwise the graphical representation may become confusing quite quickly. + +```c++ +#include <tao/pegtl.hpp> +#include <tao/pegtl/contrib/parse_tree.hpp> +#include <tao/pegtl/contrib/parse_tree_to_dot.hpp> + +// This example uses the included JSON grammar +#include <tao/pegtl/contrib/json.hpp> + +namespace pegtl = tao::pegtl; + +using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; + +template< typename Rule > +using selector = pegtl::parse_tree::selector< + Rule, + pegtl::parse_tree::store_content::on< + pegtl::json::null, + pegtl::json::true_, + pegtl::json::false_, + pegtl::json::number, + pegtl::json::string, + pegtl::json::key, + pegtl::json::array, + pegtl::json::object, + pegtl::json::member > >; + +int main( int argc, char** argv ) +{ + if( argc != 2 ) return 1; + + pegtl::argv_input in( argv, i ); + const auto root = parse_tree::parse< grammar, selector >( in ); + if( root ) { + parse_tree::print_dot( std::cout, *root ); + } + + return 0; +} +``` + +Running the above program with some example input: + +```sh +$ build/src/example/pegtl/json_parse_tree '{"foo":[true,{}],"bar":[42,null]}' | dot -Tsvg -o json_parse_tree.svg +``` + +The above will generate an SVG file with a graphical representation of the parse tree. + + + +## Error Handling + +Although the PEGTL could be used without exceptions, most programs will use input classes or grammars that might throw exceptions. +Typically, the following pattern helps to print the exceptions properly: + +```c++ + // The surrounding try/catch for normal exceptions. + // These might occur if a file can not be opened, etc. + try { + tao::pegtl::file_input in( filename ); + + // The inner try/catch block, see below... + try { + + // The actual parser, tracer, parse tree, ... + pegtl::parse< grammar >( in ); + + } + catch( const pegtl::parse_error& e ) { + + // This catch block needs access to the input + const auto p = e.positions().front(); + std::cerr << e.what() << '\n' + << in.line_at( p ) << '\n' + << std::setw( p.column ) << '^' << std::endl; + + } + } + catch( const std::exception& e ) { + + // Generic catch block for other exceptions + std::cerr << e.what() << std::endl; + + } +``` + +For more information see [Errors and Exceptions](Errors-and-Exceptions.md). Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey diff --git a/packages/PEGTL/doc/Inputs-and-Parsing.md b/packages/PEGTL/doc/Inputs-and-Parsing.md index 689f0938c74c7c99f6dec5555dd554839524b925..2f00c8661cb61e5cdbbbb96f1446d2b7d9899d7d 100644 --- a/packages/PEGTL/doc/Inputs-and-Parsing.md +++ b/packages/PEGTL/doc/Inputs-and-Parsing.md @@ -51,7 +51,7 @@ All classes and functions on this page are in namespace `tao::pegtl`. ## Tracking Mode -Some input classes allow a choice of tracking mode, or whether the `byte`, `line` and `byte_in_line` counters are continuously updated during a parsing run with `tracking_mode::eager`, or only calculated on-demand in `position()` by scanning the complete input again with `tracking_mode::lazy`. +Some input classes allow a choice of tracking mode, or whether the `byte`, `line` and `column` counters are continuously updated during a parsing run with `tracking_mode::eager`, or only calculated on-demand in `position()` by scanning the complete input again with `tracking_mode::lazy`. Lazy tracking is recommended when the position is used very infrequently, for example only in the case of throwing a `parse_error`. @@ -78,7 +78,6 @@ The classes `file_input<>`, `read_input<>` and, on supported platforms, `mmap_in * `mmap_input<>` uses `mmap(2)` on POSIX compliant systems or `MapViewOfFile()` on Windows. * `file_input<>` is derived from `mmap_input<>` when available, and `read_input<>` otherwise, inheriting the respective constructors. -Most file input classes take a single argument, the filename, which can be supplied as `std::string` or `const char*`. They immediately make available the complete contents of the file; `read_input<>` reads the entire file upon construction. The constructors that take a `FILE*` argument take ownership of the file pointer, i.e. they `fclose()` it in the destructor. @@ -87,27 +86,24 @@ The constructors that take a `FILE*` argument take ownership of the file pointer template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > struct read_input { - explicit read_input( const char* filename ); - explicit read_input( const std::string& filename ); + explicit read_input( const std::filesystem::path& path ); + read_input( const std::filesystem::path& path, const std::string& source ); - read_input( FILE* file, const char* filename ); - read_input( FILE* file, const std::string& filename ); + read_input( FILE* file, const std::filesystem::path& path ); + read_input( FILE* file, const std::filesystem::path& path, const std::string& source ); }; template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > struct mmap_input { - explicit mmap_input( const char* filename ); - explicit mmap_input( const std::string& filename ); + explicit mmap_input( const std::filesystem::path& path ); + mmap_input( const std::filesystem::path& path, const std::string& source ); }; template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > using file_input = mmap_input< P, Eol >; // Or read_input when no mmap_input available. ``` -Note that the implementation of the constructors is different than shown. -They should be used "as if" this was the actual signature. - ## Memory Input The class `memory_input<>` can be used to parse existing contiguous blocks of memory like the contents of a `std::string`. @@ -119,7 +115,7 @@ If you don't want to specify a source just use the empty string (`""`). The constructors that only takes a `const char* begin` for the data uses `std::strlen()` to determine the length. It will therefore *only* work correctly with data that is terminated with a 0-byte (and does not contain embedded 0-bytes, which are otherwise fine). -The constructors that take additional `byte`, `line` and `byte_in_line` arguments initialise the internal counters with the supplied values, rather than the defaults of `0`, `1` and `0`. +The constructors that take additional `byte`, `line` and `column` arguments initialise the internal counters with the supplied values, rather than the defaults of `0`, `1` and `1`. ```c++ template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf, typename Source = std::string > @@ -142,7 +138,7 @@ class memory_input template< typename T > memory_input( const char* begin, const char* end, T&& source, - const std::size_t byte, const std::size_t line, const std::size_t byte_in_line ) noexcept(...); + const std::size_t byte, const std::size_t line, const std::size_t column ) noexcept(...); }; ``` @@ -207,7 +203,7 @@ class string_input template< typename V, typename T > string_input( V&& data, T&& source, - const std::size_t byte, const std::size_t line, const std::size_t byte_in_line ) noexcept(...); + const std::size_t byte, const std::size_t line, const std::size_t column ) noexcept(...); }; ``` @@ -532,10 +528,10 @@ try { // call parse on the input 'in' here... } catch( const parse_error& e ) { - const auto p = e.positions.front(); + const auto p = e.positions().front(); std::cerr << e.what() << std::endl - << in.line_at( p ) << std::endl - << std::string( p.byte_in_line, ' ' ) << '^' << std::endl; + << in.line_at( p ) << '\n' + << std::setw( p.column ) << '^' << std::endl; } ``` diff --git a/packages/PEGTL/doc/Installing-and-Using.md b/packages/PEGTL/doc/Installing-and-Using.md index ec4302e1314688def828e3c9f9737b5f0202c3bc..91fc2efec9a772708ab72d1c8aaa3b27193016a1 100644 --- a/packages/PEGTL/doc/Installing-and-Using.md +++ b/packages/PEGTL/doc/Installing-and-Using.md @@ -21,10 +21,15 @@ The PEGTL requires a C++17-capable compiler, e.g. one of -* GCC 7 +* GCC 8 * Clang 5 * Visual Studio 2017 +with (on Unix) + +* libstdc++ 8 +* libc++ 7 + on either * Linux @@ -34,6 +39,8 @@ on either It requires C++17, e.g. using the `--std=c++17` compiler switch. Using newer versions of the C++ standard is supported. +Note that using libstdc++ 8 requires linking with `-lstdc++fs`. + Larger projects will frequently require the `/bigobj` option when compiling with Visual Studio on Windows. It should also work with other C++17 compilers on other Unix systems (or any sufficiently compatible platform). @@ -50,6 +57,8 @@ Note that some of the listed packages are not updated regularly. ## Using Conan +[](https://bintray.com/conan/conan-center/taocpp-pegtl%3A_/_latestVersion) + You can download and install the PEGTL using the [Conan] package manager: ```bash @@ -246,9 +255,8 @@ $ make amalgamate ``` The above will generate a `build/amalgamated/pegtl.hpp` which will consist of -the headers `tao/pegtl.hpp`, `tao/pegtl/analyze.hpp`, their dependencies, -and all headers in `tao/pegtl/contrib/` except for the headers in -`tao/pegtl/contrib/icu/`. +the headers `tao/pegtl.hpp`, their dependencies, and all headers in +`tao/pegtl/contrib/` except for the headers in `tao/pegtl/contrib/icu/`. Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey diff --git a/packages/PEGTL/doc/Json-Parse-Tree.svg b/packages/PEGTL/doc/Json-Parse-Tree.svg new file mode 100644 index 0000000000000000000000000000000000000000..27d62db25f61291e3298077f1f0f2d3b9929ade2 --- /dev/null +++ b/packages/PEGTL/doc/Json-Parse-Tree.svg @@ -0,0 +1,162 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Generated by graphviz version 2.40.1 (0) + --> +<!-- Title: parse_tree Pages: 1 --> +<svg width="1205pt" height="403pt" + viewBox="0.00 0.00 1205.45 402.96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 398.9605)"> +<title>parse_tree</title> +<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-398.9605 1201.4457,-398.9605 1201.4457,4 -4,4"/> +<!-- x0x1690eb0 --> +<g id="node1" class="node"> +<title>x0x1690eb0</title> +<ellipse fill="none" stroke="#000000" cx="485.0158" cy="-376.9605" rx="38.1938" ry="18"/> +<text text-anchor="middle" x="485.0158" y="-373.2605" font-family="Times,serif" font-size="14.00" fill="#000000">ROOT</text> +</g> +<!-- x0x1691240 --> +<g id="node2" class="node"> +<title>x0x1691240</title> +<ellipse fill="none" stroke="#000000" cx="485.0158" cy="-296.0904" rx="194.4087" ry="26.7407"/> +<text text-anchor="middle" x="485.0158" y="-299.8904" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::object</text> +<text text-anchor="middle" x="485.0158" y="-284.8904" font-family="Times,serif" font-size="14.00" fill="#000000">"{\"foo\":[true,{}],\"bar\":[42,null]}"</text> +</g> +<!-- x0x1690eb0->x0x1691240 --> +<g id="edge1" class="edge"> +<title>x0x1690eb0->x0x1691240</title> +<path fill="none" stroke="#000000" d="M485.0158,-358.6098C485.0158,-351.0399 485.0158,-341.9805 485.0158,-333.1385"/> +<polygon fill="#000000" stroke="#000000" points="488.5159,-332.961 485.0158,-322.961 481.5159,-332.9611 488.5159,-332.961"/> +</g> +<!-- x0x16913f0 --> +<g id="node3" class="node"> +<title>x0x16913f0</title> +<ellipse fill="none" stroke="#000000" cx="341.0158" cy="-206.3503" rx="135.1148" ry="26.7407"/> +<text text-anchor="middle" x="341.0158" y="-210.1503" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::member</text> +<text text-anchor="middle" x="341.0158" y="-195.1503" font-family="Times,serif" font-size="14.00" fill="#000000">"\"foo\":[true,{}]"</text> +</g> +<!-- x0x1691240->x0x16913f0 --> +<g id="edge2" class="edge"> +<title>x0x1691240->x0x16913f0</title> +<path fill="none" stroke="#000000" d="M442.5899,-269.6508C426.341,-259.5246 407.6599,-247.8826 390.7852,-237.3663"/> +<polygon fill="#000000" stroke="#000000" points="392.4859,-234.3022 382.1479,-231.9836 388.7836,-240.243 392.4859,-234.3022"/> +</g> +<!-- x0x1691870 --> +<g id="node4" class="node"> +<title>x0x1691870</title> +<ellipse fill="none" stroke="#000000" cx="629.0158" cy="-206.3503" rx="135.1148" ry="26.7407"/> +<text text-anchor="middle" x="629.0158" y="-210.1503" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::member</text> +<text text-anchor="middle" x="629.0158" y="-195.1503" font-family="Times,serif" font-size="14.00" fill="#000000">"\"bar\":[42,null]"</text> +</g> +<!-- x0x1691240->x0x1691870 --> +<g id="edge3" class="edge"> +<title>x0x1691240->x0x1691870</title> +<path fill="none" stroke="#000000" d="M527.4417,-269.6508C543.6905,-259.5246 562.3716,-247.8826 579.2464,-237.3663"/> +<polygon fill="#000000" stroke="#000000" points="581.2479,-240.243 587.8837,-231.9836 577.5456,-234.3022 581.2479,-240.243"/> +</g> +<!-- x0x1691510 --> +<g id="node5" class="node"> +<title>x0x1691510</title> +<ellipse fill="none" stroke="#000000" cx="111.0158" cy="-116.6102" rx="111.0315" ry="26.7407"/> +<text text-anchor="middle" x="111.0158" y="-120.4102" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::key</text> +<text text-anchor="middle" x="111.0158" y="-105.4102" font-family="Times,serif" font-size="14.00" fill="#000000">"\"foo\""</text> +</g> +<!-- x0x16913f0->x0x1691510 --> +<g id="edge4" class="edge"> +<title>x0x16913f0->x0x1691510</title> +<path fill="none" stroke="#000000" d="M279.38,-182.3016C248.5091,-170.2566 211.0461,-155.6394 179.3035,-143.2543"/> +<polygon fill="#000000" stroke="#000000" points="180.2378,-139.8619 169.6496,-139.4876 177.6934,-146.3831 180.2378,-139.8619"/> +</g> +<!-- x0x16916c0 --> +<g id="node6" class="node"> +<title>x0x16916c0</title> +<ellipse fill="none" stroke="#000000" cx="360.0158" cy="-116.6102" rx="120.4167" ry="26.7407"/> +<text text-anchor="middle" x="360.0158" y="-120.4102" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::array</text> +<text text-anchor="middle" x="360.0158" y="-105.4102" font-family="Times,serif" font-size="14.00" fill="#000000">"[true,{}]"</text> +</g> +<!-- x0x16913f0->x0x16916c0 --> +<g id="edge5" class="edge"> +<title>x0x16913f0->x0x16916c0</title> +<path fill="none" stroke="#000000" d="M346.7164,-179.4253C348.4448,-171.2616 350.3742,-162.1491 352.2154,-153.4525"/> +<polygon fill="#000000" stroke="#000000" points="355.6719,-154.0243 354.3192,-143.5162 348.8237,-152.5743 355.6719,-154.0243"/> +</g> +<!-- x0x1691900 --> +<g id="node9" class="node"> +<title>x0x1691900</title> +<ellipse fill="none" stroke="#000000" cx="619.0158" cy="-116.6102" rx="111.0315" ry="26.7407"/> +<text text-anchor="middle" x="619.0158" y="-120.4102" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::key</text> +<text text-anchor="middle" x="619.0158" y="-105.4102" font-family="Times,serif" font-size="14.00" fill="#000000">"\"bar\""</text> +</g> +<!-- x0x1691870->x0x1691900 --> +<g id="edge8" class="edge"> +<title>x0x1691870->x0x1691900</title> +<path fill="none" stroke="#000000" d="M626.0154,-179.4253C625.1156,-171.3504 624.1124,-162.3471 623.1528,-153.7362"/> +<polygon fill="#000000" stroke="#000000" points="626.6,-153.067 622.014,-143.5162 619.6431,-153.8423 626.6,-153.067"/> +</g> +<!-- x0x1691c70 --> +<g id="node10" class="node"> +<title>x0x1691c70</title> +<ellipse fill="none" stroke="#000000" cx="868.0158" cy="-116.6102" rx="120.4167" ry="26.7407"/> +<text text-anchor="middle" x="868.0158" y="-120.4102" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::array</text> +<text text-anchor="middle" x="868.0158" y="-105.4102" font-family="Times,serif" font-size="14.00" fill="#000000">"[42,null]"</text> +</g> +<!-- x0x1691870->x0x1691c70 --> +<g id="edge9" class="edge"> +<title>x0x1691870->x0x1691c70</title> +<path fill="none" stroke="#000000" d="M692.4359,-182.5372C724.5318,-170.4858 763.6079,-155.8134 796.7409,-143.3726"/> +<polygon fill="#000000" stroke="#000000" points="798.2351,-146.5502 806.3666,-139.7583 795.7745,-139.9969 798.2351,-146.5502"/> +</g> +<!-- x0x1691480 --> +<g id="node7" class="node"> +<title>x0x1691480</title> +<ellipse fill="none" stroke="#000000" cx="154.0158" cy="-26.8701" rx="119.5021" ry="26.7407"/> +<text text-anchor="middle" x="154.0158" y="-30.6701" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::true_</text> +<text text-anchor="middle" x="154.0158" y="-15.6701" font-family="Times,serif" font-size="14.00" fill="#000000">"true"</text> +</g> +<!-- x0x16916c0->x0x1691480 --> +<g id="edge6" class="edge"> +<title>x0x16916c0->x0x1691480</title> +<path fill="none" stroke="#000000" d="M305.0822,-92.6794C278.4184,-81.0638 246.2148,-67.0349 218.403,-54.9192"/> +<polygon fill="#000000" stroke="#000000" points="219.7196,-51.6751 209.1539,-50.89 216.9239,-58.0926 219.7196,-51.6751"/> +</g> +<!-- x0x1691b50 --> +<g id="node8" class="node"> +<title>x0x1691b50</title> +<ellipse fill="none" stroke="#000000" cx="416.0158" cy="-26.8701" rx="124.4016" ry="26.7407"/> +<text text-anchor="middle" x="416.0158" y="-30.6701" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::object</text> +<text text-anchor="middle" x="416.0158" y="-15.6701" font-family="Times,serif" font-size="14.00" fill="#000000">"{}"</text> +</g> +<!-- x0x16916c0->x0x1691b50 --> +<g id="edge7" class="edge"> +<title>x0x16916c0->x0x1691b50</title> +<path fill="none" stroke="#000000" d="M376.8176,-89.6852C382.1888,-81.0778 388.2182,-71.4157 393.9077,-62.2983"/> +<polygon fill="#000000" stroke="#000000" points="396.901,-64.1127 399.2258,-53.776 390.9624,-60.4068 396.901,-64.1127"/> +</g> +<!-- x0x1691630 --> +<g id="node11" class="node"> +<title>x0x1691630</title> +<ellipse fill="none" stroke="#000000" cx="822.0158" cy="-26.8701" rx="132.8722" ry="26.7407"/> +<text text-anchor="middle" x="822.0158" y="-30.6701" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::number</text> +<text text-anchor="middle" x="822.0158" y="-15.6701" font-family="Times,serif" font-size="14.00" fill="#000000">"42"</text> +</g> +<!-- x0x1691c70->x0x1691630 --> +<g id="edge10" class="edge"> +<title>x0x1691c70->x0x1691630</title> +<path fill="none" stroke="#000000" d="M854.2142,-89.6852C849.8932,-81.2553 845.0535,-71.8137 840.4654,-62.863"/> +<polygon fill="#000000" stroke="#000000" points="843.4838,-61.0785 835.8075,-53.776 837.2545,-64.2716 843.4838,-61.0785"/> +</g> +<!-- x0x1691e80 --> +<g id="node12" class="node"> +<title>x0x1691e80</title> +<ellipse fill="none" stroke="#000000" cx="1085.0158" cy="-26.8701" rx="112.36" ry="26.7407"/> +<text text-anchor="middle" x="1085.0158" y="-30.6701" font-family="Times,serif" font-size="14.00" fill="#000000">tao::pegtl::json::null</text> +<text text-anchor="middle" x="1085.0158" y="-15.6701" font-family="Times,serif" font-size="14.00" fill="#000000">"null"</text> +</g> +<!-- x0x1691c70->x0x1691e80 --> +<g id="edge11" class="edge"> +<title>x0x1691c70->x0x1691e80</title> +<path fill="none" stroke="#000000" d="M925.3138,-92.9146C954.0934,-81.0129 989.1091,-66.5322 1019.0107,-54.1664"/> +<polygon fill="#000000" stroke="#000000" points="1020.6216,-57.2878 1028.525,-50.2318 1017.9464,-50.8191 1020.6216,-57.2878"/> +</g> +</g> +</svg> diff --git a/packages/PEGTL/doc/Meta-Data-and-Visit.md b/packages/PEGTL/doc/Meta-Data-and-Visit.md index e8c5f5223abe862508dab87112698284c40851a4..3f8207553087b91920fc06f03f7fe54b15da718e 100644 --- a/packages/PEGTL/doc/Meta-Data-and-Visit.md +++ b/packages/PEGTL/doc/Meta-Data-and-Visit.md @@ -83,10 +83,68 @@ Unlike `visit()`, `visit_rt()` returns the number of rules visited. ## Grammar Print -TODO. +The functions `print_rules()` and `print_sub_rules()` from `include/tao/pegtl/contrib/print.hpp` combine the `visit()` function with visitors that print some information about all (sub-)rules of the supplied grammar to the supplied `std::ostream`. + +See `src/example/pegtl/json_print_rules.cpp` and `src/example/pegtl/json_print_sub_rules.cpp` for how to use these functions, and what the output looks like. +As expected, the `internal` sub-rules are printed, too. ## Rule Coverage -TODO. +The function `coverage()` from `include/tao/pegtl/contrib/coverage.hpp` is very similar to the `parse()` function. +It is called like `parse()`, with the some of the same template parameters and all of the same function arguments, however it returns an object of type `coverage_result` instead of a `bool`. + +```c++ +template< typename Rule, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + typename ParseInput, + typename... States > +coverage_result coverage( ParseInput& in, + States&&... st ); +``` + +After a parsing run, the `coverage_result` indicates whether the run was a success or a failure, and contains "rule coverage" and "branch coverage" information. + +The "rule coverage" shows how often each rule was attempted to match, and how many of these attempts were a success or a -- local or global -- failure. + +The "branch coverage" consists in the matching information also being recorded for each immediate sub-rule of every rule; in the case of an `sor<>` this shows how often each sub-rule was taken, hence the name. + +The coverage information in the `coverage_result` can either be inspected and processed or printed manually, or the `ostream` output `operator<<` from `include/tao/pegtl/contrib/print_coverage.hpp` can be used. +The operator formats the output as JSON. + +```c++ +std::ostream operator<<( std::ostream&, const coverage_result& ); +``` + +The coverage information in the `coverage_result` is defined as follows. +The `coverage_info` is used in two places, as part of the `coverage_entry` for each rule, and as value in the `branches` map for each immediate sub-rule. + +```c++ +struct coverage_info +{ + std::size_t start = 0; // How often a rule was attempted to match. + std::size_t success = 0; // How many attempts were a success (true). + std::size_t failure = 0; // How many attempts were a local failure (false). + std::size_t unwind = 0; // How many attempts were aborted due to an exception (thrown here or elsewhere). + std::size_t raise = 0; // How many attempts were a global failure (exception thrown at this rule). +}; + +struct coverage_entry + : coverage_info // The coverage_info for each rule. +{ + std::map< std::string_view, coverage_info > branches; // The coverage_info for each immediate sub-rule. +}; + +struct coverage_result +{ + std::string_view grammar; // Name of the top-level grammar rule. + std::string source; // From the input. + + std::map< std::string_view, coverage_entry > map; // The coverage_entry for each rule. + bool result; // Whether the parsing run was a success. +}; +``` + +As usual, unless otherwise indicated, all functions and data structure are in the namespace `tao::pegtl`. Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey diff --git a/packages/PEGTL/doc/Migration-Guide.md b/packages/PEGTL/doc/Migration-Guide.md index ccbe64dad09a56632149765e2995260aa8574c18..2ef77f806dae469b588eb033c3b01e8671ee849a 100644 --- a/packages/PEGTL/doc/Migration-Guide.md +++ b/packages/PEGTL/doc/Migration-Guide.md @@ -4,13 +4,15 @@ * The build system needs to be configured for C++17 or later. * The macro `TAO_PEGTL_NAMESPACE` now defines the fully qualified namespace and was changed from `pegtl` to `tao::pegtl`. When setting `TAO_PEGTL_NAMESPACE`, adapt as needed; in case of doubt, add `tao::` as prefix. +* The 0-based `byte_in_line` was replaced with the 1-based `column`. * The control class template's `apply()` and `apply0()` must only be visible (e.g. via SFINAE) when an action class template function with the appropriate signature exists. See `tao::pegtl::normal` as example. -* The error message from `tao::pegtl::parse_error` no longer contains the position as a prefix. The positions are available from the `positions` member variable. * If you have a use-case for [state](Rule-Reference.md#state-s-r-)'s `S::success()` to have an extended signature to get access to the current `apply_mode`, `rewind_mode`, *action*- and *control* class (template), please let us know and we'll re-add this feature. * The compatibility macros starting with `TAOCPP_PEGTL_` were removed, the corresponding `TAO_PEGTL_`-prefixed macros must be used. * The compatibility uppercase enumerators were removed, the corresponding lowercase enumerators must be used. * The compatibility `peek_byte()` member functions were removed, the `peek_uint8()` member functions must be used. * The compatibility header `changes.hpp` was removed, use the action-based `change_*.hpp` headers. +* The parse tree nodes provide `node->type` (a `std::string_view`) instead of `node->name()`. +* The parse tree nodes provide `node->string_view()` and `node->string()` instead of `node->content()`. ## Version 2.8.0 diff --git a/packages/PEGTL/doc/Parse-Tree.md b/packages/PEGTL/doc/Parse-Tree.md index 59d5e6ec3f46da0f75f2375f0b15aadd052d1d91..f4a7f7c971296d87d00d18fde2ca18a1c46a4428 100644 --- a/packages/PEGTL/doc/Parse-Tree.md +++ b/packages/PEGTL/doc/Parse-Tree.md @@ -10,8 +10,6 @@ It provides the basic infrastructure to build a parse tree that * but can also be used with a custom tree node class that adheres to certain rules; * and supports on-the-fly tree transformations; some of the more common ones are included. -> The parse tree / AST part of the PEGTL is currently in active development and serves as a prove-of-concept, expect changes at any time. Try it out, experiment with it, and most importantly let us know what you think of it. We need **your** feedback! - ## Content * [Full Parse Tree](#full-parse-tree) @@ -34,7 +32,7 @@ auto root = tao::pegtl::parse_tree::parse< my_grammar >( in ); The result is a `std::unique_ptr< tao::pegtl::parse_tree::node >`. The pointer is empty when the input did not match the grammar, otherwise it contains the root node of the resulting parse tree. -The tree nodes have a `name()` member function that returns the name of the grammar rule of which it represents a successful match, `begin()` and `end()` member functions to access the position of the matched portion of the input, `string()` and `string_view()` to actually access said matched input, and a vector called `children` with unique pointers to the child nodes. +The tree nodes have a `type` member that contains the name of the grammar rule of which it represents a successful match, `begin()` and `end()` member functions to access the position of the matched portion of the input, `string()` and `string_view()` to actually access said matched input, and a vector called `children` with unique pointers to the child nodes. Note that the included tree node class **points** to the matched data, rather than copying it into the node, wherefore the input **must** still be "alive" when accessing the matched data! diff --git a/packages/PEGTL/doc/README.md b/packages/PEGTL/doc/README.md index 435f23193261a357715b02597dfa93a6c3148a3f..2fb1681fc3020828f0158ab0390b1c03415f77ba 100644 --- a/packages/PEGTL/doc/README.md +++ b/packages/PEGTL/doc/README.md @@ -45,6 +45,7 @@ * [State Mismatch](Actions-and-States.md#state-mismatch) * [Legacy Actions](Actions-and-States.md#legacy-actions) * [Errors and Exceptions](Errors-and-Exceptions.md) + * [Global Failure]((Errors-and-Exceptions.md#global-failure) * [Local to Global Failure](Errors-and-Exceptions.md#local-to-global-failure) * [Intrusive Local to Global Failure](Errors-and-Exceptions.md#intrusive-local-to-global-failure) * [Non-Intrusive Local to Global Failure](Errors-and-Exceptions.md#non-intrusive-local-to-global-failure) diff --git a/packages/PEGTL/doc/Rule-Reference.md b/packages/PEGTL/doc/Rule-Reference.md index 8464355a5ed3125ce0bf02a2300cd52818e8eb1b..4072fd94462affe39a677fb2358ff49470b9b2f7 100644 --- a/packages/PEGTL/doc/Rule-Reference.md +++ b/packages/PEGTL/doc/Rule-Reference.md @@ -473,7 +473,7 @@ Note that the `true` template parameter to `internal::if_must` corresponds to th ###### `until< R, S... >` * Matches `seq< S... >` as long as `at< R >` does not match and succeeds when `R` matches. -* [Equivalent] to `seq< star< not_at< R >, not_at< eof >, S... >, R >`. +* [Equivalent] to `seq< star< not_at< R >, S... >, R >`. * Does not apply if `S` is an empty rule pack, see the previous entry for the semantics of `until< R >`. * [Meta data] and [implementation] mapping: - `until< R, S >::rule_t` is `internal::until< R, S >` @@ -530,9 +530,9 @@ Atomic rules do not rely on other rules. ###### `bol` -* Succeeds at "beginning-of-line", i.e. when the input's `byte_in_line()` member function returns zero. +* Succeeds at "beginning-of-line", i.e. when the input's `column()` member function returns one. * Does not consume input. -* Does **not** work with inputs that don't have a `byte_in_line()` member function. +* Does **not** work with inputs that don't have a `column()` member function. * [Meta data] and [implementation] mapping: - `bol::rule_t` is `internal::bol` diff --git a/packages/PEGTL/doc/Rules-and-Grammars.md b/packages/PEGTL/doc/Rules-and-Grammars.md index 0fd0caa4c0a206832cc5baa886629277f686dec2..ece2da2dfc8269b4d95571f674c6957cf999dadf 100644 --- a/packages/PEGTL/doc/Rules-and-Grammars.md +++ b/packages/PEGTL/doc/Rules-and-Grammars.md @@ -71,44 +71,45 @@ Numbers are non-empty sequences of ASCII digits. The rule named `file` is the intended top-level rule of the grammar, i.e. the rule that is supplied as template argument to [the `parse()` function](Inputs-and-Parsing.md#parse-function) in order to start a parsing run with this grammar. ```c++ -using namespace tao::pegtl; - -struct line_comment - : until< eolf > {}; +struct hash_comment + : tao::pegtl::until< tao::pegtl::eolf > {}; struct list; struct list_comment - : if_must< at< one< '(' > >, disable< list > > {}; + : tao::pegtl::if_must< tao::pegtl::at< tao::pegtl::one< '(' > >, tao::pegtl::disable< list > > {}; -struct comment - : if_must< one< '#' >, sor< list_comment, line_comment > > {}; +struct read_include + : tao::pegtl::seq< tao::pegtl::one< ' ' >, tao::pegtl::one< '"' >, tao::pegtl::plus< tao::pegtl::not_one< '"' > >, tao::pegtl::one< '"' > > {}; -struct nothing - : sor< space, comment > {}; +struct hash_include + : tao::pegtl::if_must< tao::pegtl::string< 'i', 'n', 'c', 'l', 'u', 'd', 'e' >, read_include > {}; + +struct hashed + : tao::pegtl::if_must< tao::pegtl::one< '#' >, tao::pegtl::sor< hash_include, list_comment, hash_comment > > {}; struct number - : plus< digit > {}; + : tao::pegtl::plus< tao::pegtl::digit > {}; struct symbol - : identifier {}; + : tao::pegtl::identifier {}; struct atom - : sor< number, symbol > {}; + : tao::pegtl::sor< number, symbol > {}; struct anything; struct list - : if_must< one< '(' >, until< one< ')' >, anything > > {}; + : tao::pegtl::if_must< tao::pegtl::one< '(' >, tao::pegtl::until< tao::pegtl::one< ')' >, anything > > {}; -struct something - : sor< atom, list > {}; +struct normal + : tao::pegtl::sor< atom, list > {}; struct anything - : sor< nothing, something > {}; + : tao::pegtl::sor< tao::pegtl::space, hashed, normal > {}; -struct file - : until< eof, anything > {}; +struct main + : tao::pegtl::until< tao::pegtl::eof, tao::pegtl::must< anything > > {}; ``` In order to let a parsing run do more than verify whether an input conforms to the grammar, it is necessary to attach user-defined *actions* to some grammar rules, as explained in [Actions and States](Actions-and-States.md). diff --git a/packages/PEGTL/include/tao/pegtl/argv_input.hpp b/packages/PEGTL/include/tao/pegtl/argv_input.hpp index 741a3574ddf2ab2de83afd677237f19382826512..311965e7f7bcdd24ede6d6fac5ab2084fd9e302d 100644 --- a/packages/PEGTL/include/tao/pegtl/argv_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/argv_input.hpp @@ -42,7 +42,7 @@ namespace TAO_PEGTL_NAMESPACE }; template< typename... Ts > - argv_input( Ts&&... )->argv_input<>; + argv_input( Ts&&... ) -> argv_input<>; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/ascii.hpp b/packages/PEGTL/include/tao/pegtl/ascii.hpp index 1e4f1032f4287f4aac2c711c5659086c7666ad1d..e7948367c3a7ae6ff2272d51fd6390987c7a267d 100644 --- a/packages/PEGTL/include/tao/pegtl/ascii.hpp +++ b/packages/PEGTL/include/tao/pegtl/ascii.hpp @@ -15,8 +15,8 @@ namespace TAO_PEGTL_NAMESPACE inline namespace ascii { // clang-format off - struct alnum : internal::alnum {}; - struct alpha : internal::alpha {}; + struct alnum : internal::ranges< internal::peek_char, 'a', 'z', 'A', 'Z', '0', '9' > {}; + struct alpha : internal::ranges< internal::peek_char, 'a', 'z', 'A', 'Z' > {}; struct any : internal::any< internal::peek_char > {}; struct blank : internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > {}; struct digit : internal::range< internal::result_on_found::success, internal::peek_char, '0', '9' > {}; diff --git a/packages/PEGTL/include/tao/pegtl/buffer_input.hpp b/packages/PEGTL/include/tao/pegtl/buffer_input.hpp index f964787769d7f9ae5146ee3a29d99293ca1c556b..35637d145d05d996daeeff71d8ecbf320f44edc9 100644 --- a/packages/PEGTL/include/tao/pegtl/buffer_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/buffer_input.hpp @@ -96,9 +96,9 @@ namespace TAO_PEGTL_NAMESPACE return m_current.line; } - [[nodiscard]] std::size_t byte_in_line() const noexcept + [[nodiscard]] std::size_t column() const noexcept { - return m_current.byte_in_line; + return m_current.column; } [[nodiscard]] const Source& source() const noexcept @@ -149,7 +149,7 @@ namespace TAO_PEGTL_NAMESPACE if( m_current.data + amount > m_buffer.get() + m_maximum ) { throw std::overflow_error( "require beyond end of buffer" ); } - if( const auto r = m_reader( m_end, ( std::min )( buffer_free_after_end(), ( std::max )( amount, Chunk ) ) ) ) { + if( const auto r = m_reader( m_end, ( std::min )( buffer_free_after_end(), ( std::max )( amount - buffer_occupied(), Chunk ) ) ) ) { m_end += r; } } diff --git a/packages/PEGTL/include/tao/pegtl/contrib/alphabet.hpp b/packages/PEGTL/include/tao/pegtl/contrib/alphabet.hpp index 91747dd90a37d0b9cf402c8992bd3d6d8b5efeff..4c8f39d201747eed92511b757d46e9bfdec15eec 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/alphabet.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/alphabet.hpp @@ -8,59 +8,59 @@ namespace TAO_PEGTL_NAMESPACE::alphabet { - static const int a = 'a'; - static const int b = 'b'; - static const int c = 'c'; - static const int d = 'd'; - static const int e = 'e'; - static const int f = 'f'; - static const int g = 'g'; - static const int h = 'h'; - static const int i = 'i'; - static const int j = 'j'; - static const int k = 'k'; - static const int l = 'l'; - static const int m = 'm'; - static const int n = 'n'; - static const int o = 'o'; - static const int p = 'p'; - static const int q = 'q'; - static const int r = 'r'; - static const int s = 's'; - static const int t = 't'; - static const int u = 'u'; - static const int v = 'v'; - static const int w = 'w'; - static const int x = 'x'; - static const int y = 'y'; - static const int z = 'z'; + static const char a = 'a'; + static const char b = 'b'; + static const char c = 'c'; + static const char d = 'd'; + static const char e = 'e'; + static const char f = 'f'; + static const char g = 'g'; + static const char h = 'h'; + static const char i = 'i'; + static const char j = 'j'; + static const char k = 'k'; + static const char l = 'l'; + static const char m = 'm'; + static const char n = 'n'; + static const char o = 'o'; + static const char p = 'p'; + static const char q = 'q'; + static const char r = 'r'; + static const char s = 's'; + static const char t = 't'; + static const char u = 'u'; + static const char v = 'v'; + static const char w = 'w'; + static const char x = 'x'; + static const char y = 'y'; + static const char z = 'z'; - static const int A = 'A'; // NOLINT(readability-identifier-naming) - static const int B = 'B'; // NOLINT(readability-identifier-naming) - static const int C = 'C'; // NOLINT(readability-identifier-naming) - static const int D = 'D'; // NOLINT(readability-identifier-naming) - static const int E = 'E'; // NOLINT(readability-identifier-naming) - static const int F = 'F'; // NOLINT(readability-identifier-naming) - static const int G = 'G'; // NOLINT(readability-identifier-naming) - static const int H = 'H'; // NOLINT(readability-identifier-naming) - static const int I = 'I'; // NOLINT(readability-identifier-naming) - static const int J = 'J'; // NOLINT(readability-identifier-naming) - static const int K = 'K'; // NOLINT(readability-identifier-naming) - static const int L = 'L'; // NOLINT(readability-identifier-naming) - static const int M = 'M'; // NOLINT(readability-identifier-naming) - static const int N = 'N'; // NOLINT(readability-identifier-naming) - static const int O = 'O'; // NOLINT(readability-identifier-naming) - static const int P = 'P'; // NOLINT(readability-identifier-naming) - static const int Q = 'Q'; // NOLINT(readability-identifier-naming) - static const int R = 'R'; // NOLINT(readability-identifier-naming) - static const int S = 'S'; // NOLINT(readability-identifier-naming) - static const int T = 'T'; // NOLINT(readability-identifier-naming) - static const int U = 'U'; // NOLINT(readability-identifier-naming) - static const int V = 'V'; // NOLINT(readability-identifier-naming) - static const int W = 'W'; // NOLINT(readability-identifier-naming) - static const int X = 'X'; // NOLINT(readability-identifier-naming) - static const int Y = 'Y'; // NOLINT(readability-identifier-naming) - static const int Z = 'Z'; // NOLINT(readability-identifier-naming) + static const char A = 'A'; // NOLINT(readability-identifier-naming) + static const char B = 'B'; // NOLINT(readability-identifier-naming) + static const char C = 'C'; // NOLINT(readability-identifier-naming) + static const char D = 'D'; // NOLINT(readability-identifier-naming) + static const char E = 'E'; // NOLINT(readability-identifier-naming) + static const char F = 'F'; // NOLINT(readability-identifier-naming) + static const char G = 'G'; // NOLINT(readability-identifier-naming) + static const char H = 'H'; // NOLINT(readability-identifier-naming) + static const char I = 'I'; // NOLINT(readability-identifier-naming) + static const char J = 'J'; // NOLINT(readability-identifier-naming) + static const char K = 'K'; // NOLINT(readability-identifier-naming) + static const char L = 'L'; // NOLINT(readability-identifier-naming) + static const char M = 'M'; // NOLINT(readability-identifier-naming) + static const char N = 'N'; // NOLINT(readability-identifier-naming) + static const char O = 'O'; // NOLINT(readability-identifier-naming) + static const char P = 'P'; // NOLINT(readability-identifier-naming) + static const char Q = 'Q'; // NOLINT(readability-identifier-naming) + static const char R = 'R'; // NOLINT(readability-identifier-naming) + static const char S = 'S'; // NOLINT(readability-identifier-naming) + static const char T = 'T'; // NOLINT(readability-identifier-naming) + static const char U = 'U'; // NOLINT(readability-identifier-naming) + static const char V = 'V'; // NOLINT(readability-identifier-naming) + static const char W = 'W'; // NOLINT(readability-identifier-naming) + static const char X = 'X'; // NOLINT(readability-identifier-naming) + static const char Y = 'Y'; // NOLINT(readability-identifier-naming) + static const char Z = 'Z'; // NOLINT(readability-identifier-naming) } // namespace TAO_PEGTL_NAMESPACE::alphabet diff --git a/packages/PEGTL/include/tao/pegtl/contrib/analyze.hpp b/packages/PEGTL/include/tao/pegtl/contrib/analyze.hpp index 128017d0f9397aa2b0c29f32398d102b9787fcfb..b777c02bc86961c27e4f80da06d9bc9028187e84 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/analyze.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/analyze.hpp @@ -15,10 +15,12 @@ #include <vector> #include "../config.hpp" +#include "../demangle.hpp" #include "analyze_traits.hpp" -#include "../internal/demangle.hpp" +#include "internal/set_stack_guard.hpp" + #include "../internal/dependent_false.hpp" namespace TAO_PEGTL_NAMESPACE @@ -35,41 +37,6 @@ namespace TAO_PEGTL_NAMESPACE std::vector< std::string_view > subs; }; - template< typename C > - class analyze_guard - { - public: - analyze_guard( C& container, const typename C::value_type& value ) - : m_i( container.insert( value ) ), - m_c( container ) - {} - - analyze_guard( analyze_guard&& ) = delete; - analyze_guard( const analyze_guard& ) = delete; - - void operator=( analyze_guard&& ) = delete; - void operator=( const analyze_guard& ) = delete; - - ~analyze_guard() - { - if( m_i.second ) { - m_c.erase( m_i.first ); - } - } - - explicit operator bool() const noexcept - { - return m_i.second; - } - - private: - const std::pair< typename C::iterator, bool > m_i; - C& m_c; - }; - - template< typename C > - analyze_guard( C&, const typename C::value_type& )->analyze_guard< C >; - class analyze_cycles_impl { public: @@ -114,7 +81,7 @@ namespace TAO_PEGTL_NAMESPACE if( const auto j = m_cache.find( start->first ); j != m_cache.end() ) { return j->second; } - if( const auto g = analyze_guard( m_stack, start->first ) ) { + if( const auto g = set_stack_guard( m_stack, start->first ) ) { switch( start->second.type ) { case analyze_type::any: { bool a = false; @@ -150,7 +117,7 @@ namespace TAO_PEGTL_NAMESPACE if( !accum ) { ++m_problems; if( m_verbose ) { - std::cout << "problem: cycle without progress detected at rule class " << start->first << std::endl; // LCOV_EXCL_LINE + std::cerr << "problem: cycle without progress detected at rule class " << start->first << std::endl; // LCOV_EXCL_LINE } } return m_cache[ start->first ] = accum; diff --git a/packages/PEGTL/include/tao/pegtl/contrib/control_action.hpp b/packages/PEGTL/include/tao/pegtl/contrib/control_action.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c716c66d69c2f1f75ad01bedadfd0073a43c196d --- /dev/null +++ b/packages/PEGTL/include/tao/pegtl/contrib/control_action.hpp @@ -0,0 +1,77 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_PEGTL_CONTRIB_CONTROL_ACTION_HPP +#define TAO_PEGTL_CONTRIB_CONTROL_ACTION_HPP + +#include <utility> + +#include "../config.hpp" +#include "../match.hpp" +#include "../nothing.hpp" + +namespace TAO_PEGTL_NAMESPACE +{ + namespace internal + { + template< typename, typename Rule, template< typename... > class Action, typename ParseInput, typename... States > + inline constexpr bool action_has_unwind = false; + + template< typename Rule, template< typename... > class Action, typename ParseInput, typename... States > + inline constexpr bool action_has_unwind< decltype( (void)Action< Rule >::unwind( std::declval< const ParseInput& >(), std::declval< States&& >()... ) ), Rule, Action, ParseInput, States... > = true; + + } // namespace internal + + struct control_action + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename ParseInput, + typename... States > + [[nodiscard]] static bool match( ParseInput& in, States&&... st ) + { + if constexpr( internal::action_has_unwind< void, Rule, Action, ParseInput, States... > ) { + try { + return control_action::match_impl< Rule, A, M, Action, Control >( in, st... ); + } + catch( ... ) { + Action< Rule >::unwind( const_cast< const ParseInput& >( in ), st... ); + throw; + } + } + else { + return control_action::match_impl< Rule, A, M, Action, Control >( in, st... ); + } + } + + private: + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename ParseInput, + typename... States > + [[nodiscard]] static bool match_impl( ParseInput& in, States&&... st ) + { + Action< Rule >::start( const_cast< const ParseInput& >( in ), st... ); + if( TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ) ) { + Action< Rule >::success( const_cast< const ParseInput& >( in ), st... ); + return true; + } + Action< Rule >::failure( const_cast< const ParseInput& >( in ), st... ); + return false; + } + }; + +} // namespace TAO_PEGTL_NAMESPACE + +#endif diff --git a/packages/PEGTL/include/tao/pegtl/contrib/coverage.hpp b/packages/PEGTL/include/tao/pegtl/contrib/coverage.hpp index 582813a8c6de1a450eeb3cb5770fab60d1bd05c1..78e9c64d167258337a3c039c85f051f8c11bd7ce 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/coverage.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/coverage.hpp @@ -4,33 +4,31 @@ #ifndef TAO_PEGTL_CONTRIB_COVERAGE_HPP #define TAO_PEGTL_CONTRIB_COVERAGE_HPP -#include <cassert> #include <cstddef> #include <map> -#include <string> #include <string_view> #include <vector> -#include "remove_first_state.hpp" -#include "shuffle_states.hpp" +#include "state_control.hpp" +#include "../apply_mode.hpp" #include "../config.hpp" +#include "../demangle.hpp" #include "../normal.hpp" #include "../nothing.hpp" #include "../parse.hpp" +#include "../rewind_mode.hpp" #include "../type_list.hpp" #include "../visit.hpp" -#include "../internal/demangle.hpp" - namespace TAO_PEGTL_NAMESPACE { struct coverage_info { std::size_t start = 0; std::size_t success = 0; - std::size_t local_failure = 0; - std::size_t global_failure = 0; + std::size_t failure = 0; + std::size_t unwind = 0; std::size_t raise = 0; }; @@ -40,94 +38,98 @@ namespace TAO_PEGTL_NAMESPACE std::map< std::string_view, coverage_info > branches; }; - struct coverage_state - { - std::string_view grammar; - std::string source; - - std::map< std::string_view, coverage_entry > map; - bool result; - - std::vector< std::string_view > stack; - }; + using coverage_result = std::map< std::string_view, coverage_entry >; namespace internal { template< typename Rule > struct coverage_insert { - static void visit( coverage_state& state ) + static void visit( std::map< std::string_view, coverage_entry >& map ) { - visit_branches( state.map.try_emplace( internal::demangle< Rule >() ).first->second.branches, typename Rule::subs_t() ); + visit_branches( map.try_emplace( demangle< Rule >() ).first->second.branches, typename Rule::subs_t() ); } template< typename... Ts > static void visit_branches( std::map< std::string_view, coverage_info >& branches, type_list< Ts... > /*unused*/ ) { - ( branches.try_emplace( internal::demangle< Ts >() ), ... ); + ( branches.try_emplace( demangle< Ts >() ), ... ); } }; - template< template< typename... > class Control = normal > - struct make_coverage_control + struct coverage_state { template< typename Rule > - struct control - : remove_first_state< Control< Rule > > + static constexpr bool enable = true; + + explicit coverage_state( coverage_result& in_result ) + : result( in_result ) + {} + + coverage_result& result; + std::vector< std::string_view > stack; + + template< typename Rule, typename ParseInput, typename... States > + void start( const ParseInput& /*unused*/, States&&... /*unused*/ ) { - template< typename ParseInput, typename... States > - [[noreturn]] static void raise( const ParseInput& in, coverage_state& state, States&&... st ) - { - const auto name = internal::demangle< Rule >(); - ++state.map.at( name ).raise; - if( state.stack.size() > 1 ) { - ++state.map.at( state.stack.at( state.stack.size() - 2 ) ).branches.at( name ).raise; - } - Control< Rule >::raise( in, st... ); + const auto name = demangle< Rule >(); + ++result.at( name ).start; + if( !stack.empty() ) { + ++result.at( stack.back() ).branches.at( name ).start; } + stack.push_back( name ); + } - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control2, - typename ParseInput, - typename... States > - [[nodiscard]] static bool match( ParseInput& in, States&&... st ) - { - coverage_entry dummy; - auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) ); - const auto name = internal::demangle< Rule >(); - auto& entry = state.map.at( name ); - auto& previous = state.stack.empty() ? dummy : state.map.at( state.stack.back() ).branches.at( name ); - ++entry.start; - ++previous.start; - state.stack.push_back( name ); - try { - const bool result = Control< Rule >::template match< A, M, Action, Control2 >( in, st... ); - state.stack.pop_back(); - if( result ) { - ++entry.success; - ++previous.success; - } - else { - ++entry.local_failure; - ++previous.local_failure; - } - return result; - } - catch( ... ) { - state.stack.pop_back(); - ++entry.global_failure; - ++previous.global_failure; - throw; - } + template< typename Rule, typename ParseInput, typename... States > + void success( const ParseInput& /*unused*/, States&&... /*unused*/ ) + { + stack.pop_back(); + const auto name = demangle< Rule >(); + ++result.at( name ).success; + if( !stack.empty() ) { + ++result.at( stack.back() ).branches.at( name ).success; } - }; + } - template< typename Rule > - using type = rotate_states_right< control< Rule > >; + template< typename Rule, typename ParseInput, typename... States > + void failure( const ParseInput& /*unused*/, States&&... /*unused*/ ) + { + stack.pop_back(); + const auto name = demangle< Rule >(); + ++result.at( name ).failure; + if( !stack.empty() ) { + ++result.at( stack.back() ).branches.at( name ).failure; + } + } + + template< typename Rule, typename ParseInput, typename... States > + void raise( const ParseInput& /*unused*/, States&&... /*unused*/ ) + { + const auto name = demangle< Rule >(); + ++result.at( name ).raise; + if( !stack.empty() ) { + ++result.at( stack.back() ).branches.at( name ).raise; + } + } + + template< typename Rule, typename ParseInput, typename... States > + void unwind( const ParseInput& /*unused*/, States&&... /*unused*/ ) + { + stack.pop_back(); + const auto name = demangle< Rule >(); + ++result.at( name ).unwind; + if( !stack.empty() ) { + ++result.at( stack.back() ).branches.at( name ).unwind; + } + } + + template< typename Rule, typename ParseInput, typename... States > + void apply( const ParseInput& /*unused*/, States&&... /*unused*/ ) noexcept + {} + + template< typename Rule, typename ParseInput, typename... States > + void apply0( const ParseInput& /*unused*/, States&&... /*unused*/ ) noexcept + {} }; } // namespace internal @@ -137,21 +139,11 @@ namespace TAO_PEGTL_NAMESPACE template< typename... > class Control = normal, typename ParseInput, typename... States > - coverage_state coverage( ParseInput&& in, States&&... st ) + bool coverage( ParseInput&& in, coverage_result& result, States&&... st ) { - coverage_state state; - - state.grammar = internal::demangle< Rule >(); - state.source = in.source(); - - // populate state - visit< Rule, internal::coverage_insert >( state ); - - // parse - state.result = parse< Rule, Action, internal::make_coverage_control<>::template type >( in, st..., state ); - assert( state.stack.empty() ); - - return state; + internal::coverage_state state( result ); + visit< Rule, internal::coverage_insert >( state.result ); // Fill map with all sub-rules of the grammar. + return parse< Rule, Action, state_control< Control >::template type >( in, st..., state ); } } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/contrib/integer.hpp b/packages/PEGTL/include/tao/pegtl/contrib/integer.hpp index 9bbbf9977be4e39782f869ee288758fe33b34157..30ba5464faa0961f5c94e78680960b4eac891a5c 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/integer.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/integer.hpp @@ -7,6 +7,8 @@ #include <cstdint> #include <cstdlib> +#include <limits> +#include <string_view> #include <type_traits> #include "../ascii.hpp" @@ -148,7 +150,7 @@ namespace TAO_PEGTL_NAMESPACE if( is_digit( c ) ) { in.bump_in_this_line(); if( c == '0' ) { - return in.empty() || ( !is_digit( in.peek_char() ) ); // TODO: Throw exception on digit? + return in.empty() || ( !is_digit( in.peek_char() ) ); } while( ( !in.empty() ) && is_digit( in.peek_char() ) ) { in.bump_in_this_line(); @@ -171,11 +173,11 @@ namespace TAO_PEGTL_NAMESPACE if( is_digit( c ) ) { if( c == '0' ) { in.bump_in_this_line(); - return in.empty() || ( !is_digit( in.peek_char() ) ); // TODO: Throw exception on digit? + return in.empty() || ( !is_digit( in.peek_char() ) ); } do { if( !accumulate_digit< Unsigned, Maximum >( st, c ) ) { - throw parse_error( "integer overflow", in ); // Consistent with "as if" an action was doing the conversion. + throw TAO_PEGTL_NAMESPACE::parse_error( "integer overflow", in ); // Consistent with "as if" an action was doing the conversion. } in.bump_in_this_line(); } while( ( !in.empty() ) && is_digit( c = in.peek_char() ) ); @@ -192,7 +194,7 @@ namespace TAO_PEGTL_NAMESPACE // Assumes that 'in' contains a non-empty sequence of ASCII digits. template< typename ActionInput, typename Unsigned > - static auto apply( const ActionInput& in, Unsigned& st ) -> std::enable_if_t< std::is_unsigned_v< Unsigned >, void > + static void apply( const ActionInput& in, Unsigned& st ) { // This function "only" offers basic exception safety. st = 0; @@ -200,20 +202,6 @@ namespace TAO_PEGTL_NAMESPACE throw parse_error( "unsigned integer overflow", in ); } } - - template< typename ActionInput, typename State > - static auto apply( const ActionInput& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > - { - apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. - } - - template< typename ActionInput, typename Unsigned, typename... Ts > - static auto apply( const ActionInput& in, std::vector< Unsigned, Ts... >& st ) -> std::enable_if_t< std::is_unsigned_v< Unsigned >, void > - { - Unsigned u = 0; - apply( in, u ); - st.emplace_back( u ); - } }; struct unsigned_rule @@ -260,9 +248,6 @@ namespace TAO_PEGTL_NAMESPACE st = 0; return internal::match_and_convert_unsigned_with_maximum( in, st ); // Throws on overflow. } - - // TODO: Overload for st.converted? - // TODO: Overload for std::vector< Unsigned >? }; template< typename Unsigned, Unsigned Maximum > @@ -273,7 +258,7 @@ namespace TAO_PEGTL_NAMESPACE static_assert( std::is_unsigned_v< Unsigned > ); template< typename ActionInput, typename Unsigned2 > - static auto apply( const ActionInput& in, Unsigned2& st ) -> std::enable_if_t< std::is_same_v< Unsigned, Unsigned2 >, void > + static void apply( const ActionInput& in, Unsigned2& st ) { // This function "only" offers basic exception safety. st = 0; @@ -281,20 +266,6 @@ namespace TAO_PEGTL_NAMESPACE throw parse_error( "unsigned integer overflow", in ); } } - - template< typename ActionInput, typename State > - static auto apply( const ActionInput& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > - { - apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. - } - - template< typename ActionInput, typename Unsigned2, typename... Ts > - static auto apply( const ActionInput& in, std::vector< Unsigned2, Ts... >& st ) -> std::enable_if_t< std::is_same_v< Unsigned, Unsigned2 >, void > - { - Unsigned u = 0; - apply( in, u ); - st.emplace_back( u ); - } }; template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > @@ -349,9 +320,6 @@ namespace TAO_PEGTL_NAMESPACE st = 0; return internal::match_and_convert_unsigned_with_maximum< ParseInput, Unsigned, Maximum >( in, st ); // Throws on overflow. } - - // TODO: Overload for st.converted? - // TODO: Overload for std::vector< Unsigned >? }; struct signed_action @@ -360,7 +328,7 @@ namespace TAO_PEGTL_NAMESPACE // with optional leading sign; with sign, in.size() must be >= 2. template< typename ActionInput, typename Signed > - static auto apply( const ActionInput& in, Signed& st ) -> std::enable_if_t< std::is_signed_v< Signed >, void > + static void apply( const ActionInput& in, Signed& st ) { // This function "only" offers basic exception safety. st = 0; @@ -368,20 +336,6 @@ namespace TAO_PEGTL_NAMESPACE throw parse_error( "signed integer overflow", in ); } } - - template< typename ActionInput, typename State > - static auto apply( const ActionInput& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > - { - apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. - } - - template< typename ActionInput, typename Signed, typename... Ts > - static auto apply( const ActionInput& in, std::vector< Signed, Ts... >& st ) -> std::enable_if_t< std::is_signed_v< Signed >, void > - { - Signed s = 0; - apply( in, s ); - st.emplace_back( s ); - } }; struct signed_rule @@ -440,9 +394,6 @@ namespace TAO_PEGTL_NAMESPACE { return TAO_PEGTL_NAMESPACE::parse< signed_rule_new, internal::signed_action_action >( in, st ); // Throws on overflow. } - - // TODO: Overload for st.converted? - // TODO: Overload for std::vector< Signed >? }; template< typename Name > diff --git a/packages/PEGTL/include/tao/pegtl/contrib/internal/set_stack_guard.hpp b/packages/PEGTL/include/tao/pegtl/contrib/internal/set_stack_guard.hpp new file mode 100644 index 0000000000000000000000000000000000000000..99870f9b04d70fceb0a7785f1344d3b4d5555cf1 --- /dev/null +++ b/packages/PEGTL/include/tao/pegtl/contrib/internal/set_stack_guard.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_PEGTL_CONTRIB_INTERNAL_SET_STACK_GUARD_HPP +#define TAO_PEGTL_CONTRIB_INTERNAL_SET_STACK_GUARD_HPP + +#include <set> +#include <utility> + +#include "../../config.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename... Cs > + class set_stack_guard + { + public: + template< typename... Ts > + set_stack_guard( std::set< Cs... >& set, Ts&&... ts ) + : m_i( set.emplace( std::forward< Ts >( ts )... ) ), + m_s( set ) + {} + + set_stack_guard( set_stack_guard&& ) = delete; + set_stack_guard( const set_stack_guard& ) = delete; + + void operator=( set_stack_guard&& ) = delete; + void operator=( const set_stack_guard& ) = delete; + + ~set_stack_guard() + { + if( m_i.second ) { + m_s.erase( m_i.first ); + } + } + + explicit operator bool() const noexcept + { + return m_i.second; + } + + private: + const std::pair< typename std::set< Cs... >::iterator, bool > m_i; + std::set< Cs... >& m_s; + }; + + template< typename... Cs > + set_stack_guard( std::set< Cs... >&, const typename std::set< Cs... >::value_type& ) -> set_stack_guard< Cs... >; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/packages/PEGTL/include/tao/pegtl/contrib/parse_tree.hpp b/packages/PEGTL/include/tao/pegtl/contrib/parse_tree.hpp index 964fdf6f0ec8ef74e98c58cc29d87d69c44eb4ee..25742807037cd2fb5cc1288da7c7b7ce45de8f0b 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/parse_tree.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/parse_tree.hpp @@ -19,16 +19,16 @@ #include "../apply_mode.hpp" #include "../config.hpp" +#include "../demangle.hpp" #include "../memory_input.hpp" #include "../normal.hpp" #include "../nothing.hpp" #include "../parse.hpp" #include "../rewind_mode.hpp" -#include "../internal/demangle.hpp" #include "../internal/enable_control.hpp" +#include "../internal/has_unwind.hpp" #include "../internal/iterator.hpp" -#include "../internal/try_catch_type.hpp" namespace TAO_PEGTL_NAMESPACE::parse_tree { @@ -67,13 +67,13 @@ namespace TAO_PEGTL_NAMESPACE::parse_tree template< typename U > [[nodiscard]] bool is_type() const noexcept { - return type == TAO_PEGTL_NAMESPACE::internal::demangle< U >(); + return type == demangle< U >(); } template< typename U > void set_type() noexcept { - type = TAO_PEGTL_NAMESPACE::internal::demangle< U >(); + type = demangle< U >(); } [[nodiscard]] position begin() const @@ -107,13 +107,13 @@ namespace TAO_PEGTL_NAMESPACE::parse_tree [[nodiscard]] memory_input< P, Eol > as_memory_input() const { assert( has_content() ); - return { m_begin.data, m_end.data, source, m_begin.byte, m_begin.line, m_begin.byte_in_line }; + return { m_begin.data, m_end.data, source, m_begin.byte, m_begin.line, m_begin.column }; } template< typename... States > void remove_content( States&&... /*unused*/ ) noexcept { - m_end.reset(); + m_end = TAO_PEGTL_NAMESPACE::internal::iterator(); } // all non-root nodes are initialized by calling this method @@ -137,6 +137,11 @@ namespace TAO_PEGTL_NAMESPACE::parse_tree void failure( const ParseInput& /*unused*/, States&&... /*unused*/ ) noexcept {} + // if parsing of the rule failed with an exception, this method is called + template< typename Rule, typename ParseInput, typename... States > + void unwind( const ParseInput& /*unused*/, States&&... /*unused*/ ) noexcept + {} + // if parsing succeeded and the (optional) transform call // did not discard the node, it is appended to its parent. // note that "child" is the node whose Rule just succeeded @@ -155,12 +160,6 @@ namespace TAO_PEGTL_NAMESPACE::parse_tree namespace internal { - template< typename > - inline constexpr bool is_try_catch_type = false; - - template< typename Exception, typename... Rules > - inline constexpr bool is_try_catch_type< TAO_PEGTL_NAMESPACE::internal::try_catch_type< Exception, Rules... > > = true; - template< typename Node > struct state { @@ -195,14 +194,14 @@ namespace TAO_PEGTL_NAMESPACE::parse_tree template< typename Selector, typename ParseInput, typename Node, typename... States > auto transform( const ParseInput& in, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( in, n, st... ) ) ) - -> decltype( Selector::transform( in, n, st... ), void() ) + -> decltype( (void)Selector::transform( in, n, st... ) ) { Selector::transform( in, n, st... ); } template< typename Selector, typename ParseInput, typename Node, typename... States > auto transform( const ParseInput& /*unused*/, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( n, st... ) ) ) - -> decltype( Selector::transform( n, st... ), void() ) + -> decltype( (void)Selector::transform( n, st... ) ) { Selector::transform( n, st... ); } @@ -243,46 +242,33 @@ namespace TAO_PEGTL_NAMESPACE::parse_tree struct make_control< Node, Selector, Control >::state_handler< Rule, false, false > : remove_first_state< Control< Rule > > { - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control2, - typename ParseInput, - typename... States > - [[nodiscard]] static bool match( ParseInput& in, States&&... st ) + template< typename ParseInput, typename... States > + static void start( const ParseInput& /*unused*/, state< Node >& state, States&&... /*unused*/ ) { - auto& state = std::get< sizeof...( st ) - 1 >( std::tie( st... ) ); - if constexpr( is_try_catch_type< Rule > ) { - internal::state< Node > tmp; - tmp.emplace_back(); - tmp.stack.swap( state.stack ); - const bool result = Control< Rule >::template match< A, M, Action, Control2 >( in, st... ); - tmp.stack.swap( state.stack ); - if( result ) { - for( auto& c : tmp.back()->children ) { - state.back()->children.emplace_back( std::move( c ) ); - } - } - return result; - } - else { - state.emplace_back(); - const bool result = Control< Rule >::template match< A, M, Action, Control2 >( in, st... ); - if( result ) { - auto n = std::move( state.back() ); - state.pop_back(); - for( auto& c : n->children ) { - state.back()->children.emplace_back( std::move( c ) ); - } - } - else { - state.pop_back(); - } - return result; + state.emplace_back(); + } + + template< typename ParseInput, typename... States > + static void success( const ParseInput& /*unused*/, state< Node >& state, States&&... /*unused*/ ) + { + auto n = std::move( state.back() ); + state.pop_back(); + for( auto& c : n->children ) { + state.back()->children.emplace_back( std::move( c ) ); } } + + template< typename ParseInput, typename... States > + static void failure( const ParseInput& /*unused*/, state< Node >& state, States&&... /*unused*/ ) + { + state.pop_back(); + } + + template< typename ParseInput, typename... States > + static void unwind( const ParseInput& /*unused*/, state< Node >& state, States&&... /*unused*/ ) + { + state.pop_back(); + } }; template< typename Node, template< typename... > class Selector, template< typename... > class Control > @@ -301,7 +287,6 @@ namespace TAO_PEGTL_NAMESPACE::parse_tree template< typename ParseInput, typename... States > static void success( const ParseInput& in, state< Node >& state, States&&... st ) { - Control< Rule >::success( in, st... ); auto n = std::move( state.back() ); state.pop_back(); n->template success< Rule >( in, st... ); @@ -309,14 +294,25 @@ namespace TAO_PEGTL_NAMESPACE::parse_tree if( n ) { state.back()->emplace_back( std::move( n ), st... ); } + Control< Rule >::success( in, st... ); } template< typename ParseInput, typename... States > - static void failure( const ParseInput& in, state< Node >& state, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) && noexcept( std::declval< Node& >().template failure< Rule >( in, st... ) ) ) + static void failure( const ParseInput& in, state< Node >& state, States&&... st ) { - Control< Rule >::failure( in, st... ); state.back()->template failure< Rule >( in, st... ); state.pop_back(); + Control< Rule >::failure( in, st... ); + } + + template< typename ParseInput, typename... States > + static void unwind( const ParseInput& in, state< Node >& state, States&&... st ) + { + state.back()->template unwind< Rule >( in, st... ); + state.pop_back(); + if constexpr( TAO_PEGTL_NAMESPACE::internal::has_unwind< Control< Rule >, void, const ParseInput&, States... > ) { + Control< Rule >::unwind( in, st... ); + } } }; diff --git a/packages/PEGTL/include/tao/pegtl/contrib/print.hpp b/packages/PEGTL/include/tao/pegtl/contrib/print.hpp index 96c1792fe91d6798ea9b2ed267c3ccdc33c7d57c..cc4ce4857460945ebb382e4722cb61b29f62933b 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/print.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/print.hpp @@ -7,16 +7,16 @@ #include <ostream> #include "../config.hpp" +#include "../demangle.hpp" +#include "../type_list.hpp" #include "../visit.hpp" -#include "../internal/demangle.hpp" - namespace TAO_PEGTL_NAMESPACE { namespace internal { template< typename Name > - struct print_rules + struct print_names { static void visit( std::ostream& os ) { @@ -25,7 +25,7 @@ namespace TAO_PEGTL_NAMESPACE }; template< typename Name > - struct print_sub_rules + struct print_debug { static void visit( std::ostream& os ) { @@ -59,15 +59,15 @@ namespace TAO_PEGTL_NAMESPACE } // namespace internal template< typename Grammar > - void print_rules( std::ostream& os ) + void print_names( std::ostream& os ) { - visit< Grammar, internal::print_rules >( os ); + visit< Grammar, internal::print_names >( os ); } template< typename Grammar > - void print_sub_rules( std::ostream& os ) + void print_debug( std::ostream& os ) { - visit< Grammar, internal::print_sub_rules >( os ); + visit< Grammar, internal::print_debug >( os ); } } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/contrib/print_coverage.hpp b/packages/PEGTL/include/tao/pegtl/contrib/print_coverage.hpp index 0c49af45e70214c29d2fd7d1b48f489d96d3e9c7..f3ab737e8f1084e8f1920a5b78a9c048ce0e5dea 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/print_coverage.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/print_coverage.hpp @@ -10,31 +10,25 @@ namespace TAO_PEGTL_NAMESPACE { - // output is JSON - inline void print_coverage( std::ostream& os, const coverage_state& state ) + inline std::ostream& operator<<( std::ostream& os, const coverage_result& result ) { - os << "{\n" - << " \"grammar\": \"" << state.grammar << "\",\n" - << " \"source\": \"" << state.source << "\",\n" - << " \"result\": " << ( state.result ? "true" : "false" ) << ",\n" - << " \"coverage\":\n" - << " [\n"; + os << "[\n"; bool f = true; - for( const auto& [ k, v ] : state.map ) { + for( const auto& [ k, v ] : result ) { if( f ) { f = false; } else { os << ",\n"; } - os << " {\n" - << " \"rule\": \"" << k << "\",\n" - << " \"start\": " << v.start << ", \"success\": " << v.success << ", \"local_failure\": " << v.local_failure << ", \"global_failure\": " << v.global_failure << ", \"raise\": " << v.raise << ",\n"; + os << " {\n" + << " \"rule\": \"" << k << "\",\n" + << " \"start\": " << v.start << ", \"success\": " << v.success << ", \"failure\": " << v.failure << ", \"unwind\": " << v.unwind << ", \"raise\": " << v.raise << ",\n"; if( v.branches.empty() ) { - os << " \"branches\": []\n"; + os << " \"branches\": []\n"; } else { - os << " \"branches\": [\n"; + os << " \"branches\": [\n"; bool f2 = true; for( const auto& [ k2, v2 ] : v.branches ) { if( f2 ) { @@ -43,15 +37,15 @@ namespace TAO_PEGTL_NAMESPACE else { os << ",\n"; } - os << " { \"branch\": \"" << k2 << "\", \"start\": " << v2.start << ", \"success\": " << v2.success << ", \"local_failure\": " << v2.local_failure << ", \"global_failure\": " << v2.global_failure << ", \"raise\": " << v2.raise << " }"; + os << " { \"branch\": \"" << k2 << "\", \"start\": " << v2.start << ", \"success\": " << v2.success << ", \"failure\": " << v2.failure << ", \"unwind\": " << v2.unwind << ", \"raise\": " << v2.raise << " }"; } - os << "\n ]\n"; + os << "\n ]\n"; } - os << " }"; + os << " }"; } - os << "\n" - << " ]\n" - << "}\n"; + os << "\n"; + os << "]\n"; + return os; } } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/contrib/raw_string.hpp b/packages/PEGTL/include/tao/pegtl/contrib/raw_string.hpp index 7fc2e049bd994aa7ceb44a2e7bccb775c3d48331..3e4a6a7f4b561d25e1640879402738bc107f7a1e 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/raw_string.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/raw_string.hpp @@ -11,15 +11,7 @@ #include "../ascii.hpp" #include "../config.hpp" #include "../rewind_mode.hpp" - -#include "../internal/bytes.hpp" -#include "../internal/enable_control.hpp" -#include "../internal/eof.hpp" -#include "../internal/eol.hpp" -#include "../internal/must.hpp" -#include "../internal/not_at.hpp" -#include "../internal/seq.hpp" -#include "../internal/star.hpp" +#include "../rules.hpp" #include "analyze_traits.hpp" @@ -204,7 +196,7 @@ namespace TAO_PEGTL_NAMESPACE {}; using rule_t = raw_string; - using subs_t = type_list< internal::raw_string_open< Open, Marker >, internal::must< content > >; + using subs_t = empty_list; // type_list< internal::raw_string_open< Open, Marker >, internal::must< content > >; template< apply_mode A, rewind_mode M, diff --git a/packages/PEGTL/include/tao/pegtl/contrib/remove_first_state.hpp b/packages/PEGTL/include/tao/pegtl/contrib/remove_first_state.hpp index 48030def2e9bb687e86783ce0558029fd43ad96c..755b913498edbc776be1f85699cc7765e26ec7e0 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/remove_first_state.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/remove_first_state.hpp @@ -4,8 +4,12 @@ #ifndef TAO_PEGTL_CONTRIB_REMOVE_FIRST_STATE_HPP #define TAO_PEGTL_CONTRIB_REMOVE_FIRST_STATE_HPP +#include <type_traits> + #include "../config.hpp" +#include "../internal/has_unwind.hpp" + namespace TAO_PEGTL_NAMESPACE { // Applies to start(), success(), failure(), raise(), apply(), and apply0(): @@ -38,6 +42,13 @@ namespace TAO_PEGTL_NAMESPACE Base::raise( in, st... ); } + template< typename ParseInput, typename State, typename... States > + static auto unwind( const ParseInput& in, State&& /*unused*/, States&&... st ) + -> std::enable_if_t< internal::has_unwind< Base, void, const ParseInput&, States... > > + { + Base::unwind( in, st... ); + } + template< template< typename... > class Action, typename Iterator, typename ParseInput, typename State, typename... States > static auto apply( const Iterator& begin, const ParseInput& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Base::template apply< Action >( begin, in, st... ) ) ) -> decltype( Base::template apply< Action >( begin, in, st... ) ) diff --git a/packages/PEGTL/include/tao/pegtl/contrib/remove_last_states.hpp b/packages/PEGTL/include/tao/pegtl/contrib/remove_last_states.hpp index 5fb778b7dbb4d45c29107e987697bc5393b75658..a9006fe1d13e25d4d7535b94f9e8a4b00c19dc71 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/remove_last_states.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/remove_last_states.hpp @@ -9,6 +9,8 @@ #include "../config.hpp" +#include "../internal/has_unwind.hpp" + namespace TAO_PEGTL_NAMESPACE { // Remove the last N states of start(), success(), failure(), raise(), apply(), and apply0() @@ -64,6 +66,20 @@ namespace TAO_PEGTL_NAMESPACE raise_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - N >() ); } + template< typename ParseInput, typename Tuple, std::size_t... Is > + static auto unwind_impl( const ParseInput& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) + -> std::enable_if_t< internal::has_unwind< Base, void, const ParseInput&, std::tuple_element_t< Is, Tuple >... > > + { + Base::unwind( in, std::get< Is >( t )... ); + } + + template< typename ParseInput, typename... States > + static auto unwind( const ParseInput& in, States&&... st ) + -> decltype( unwind_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - N >() ) ) + { + unwind_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - N >() ); + } + template< template< typename... > class Action, typename Iterator, typename ParseInput, typename Tuple, std::size_t... Is > static auto apply_impl( const Iterator& begin, const ParseInput& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( Base::template apply< Action >( begin, in, std::get< Is >( t )... ) ) ) -> decltype( Base::template apply< Action >( begin, in, std::get< Is >( t )... ) ) diff --git a/packages/PEGTL/include/tao/pegtl/contrib/rep_one_min_max.hpp b/packages/PEGTL/include/tao/pegtl/contrib/rep_one_min_max.hpp index 7ec4639ef68c435f13d585b87a41fa8a5c7784e1..ee0a37820b2af3e548d61449383c246fd99cf2cf 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/rep_one_min_max.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/rep_one_min_max.hpp @@ -48,6 +48,28 @@ namespace TAO_PEGTL_NAMESPACE } }; + template< unsigned Max, char C > + struct rep_one_min_max< 0, Max, C > + { + using rule_t = rep_one_min_max; + using subs_t = empty_list; + + template< typename ParseInput > + [[nodiscard]] static bool match( ParseInput& in ) + { + const auto size = in.size( Max + 1 ); + std::size_t i = 0; + while( ( i < size ) && ( in.peek_char( i ) == C ) ) { + ++i; + } + if( i <= Max ) { + bump_help< result_on_found::success, ParseInput, char, C >( in, i ); + return true; + } + return false; + } + }; + template< unsigned Min, unsigned Max, char C > inline constexpr bool enable_control< rep_one_min_max< Min, Max, C > > = false; diff --git a/packages/PEGTL/include/tao/pegtl/contrib/shuffle_states.hpp b/packages/PEGTL/include/tao/pegtl/contrib/shuffle_states.hpp index e081051405ad231b944c5b2a14e5ddbfb25bef04..43912c4f26631b008cc9e4f1f029fcabfed9da6b 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/shuffle_states.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/shuffle_states.hpp @@ -5,10 +5,13 @@ #define TAO_PEGTL_CONTRIB_SHUFFLE_STATES_HPP #include <tuple> +#include <type_traits> #include <utility> #include "../config.hpp" +#include "../internal/has_unwind.hpp" + namespace TAO_PEGTL_NAMESPACE { namespace internal @@ -112,6 +115,27 @@ namespace TAO_PEGTL_NAMESPACE Base::raise( in, st ); } + template< typename ParseInput, typename Tuple, std::size_t... Is > + static auto unwind_impl( const ParseInput& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) + -> std::enable_if_t< internal::has_unwind< Base, void, const ParseInput&, std::tuple_element_t< Shuffle::template value< Is, sizeof...( Is ) >, Tuple >... > > + { + Base::unwind( in, std::get< Shuffle::template value< Is, sizeof...( Is ) > >( t )... ); + } + + template< typename ParseInput, typename... States > + static auto unwind( const ParseInput& in, States&&... st ) + -> decltype( unwind_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) >() ) ) + { + unwind_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) >() ); + } + + template< typename ParseInput, typename State > + static auto unwind( const ParseInput& in, State&& st ) + -> std::enable_if_t< internal::has_unwind< Base, void, const ParseInput&, State > > + { + Base::unwind( in, st ); + } + template< template< typename... > class Action, typename Iterator, typename ParseInput, typename Tuple, std::size_t... Is > static auto apply_impl( const Iterator& begin, const ParseInput& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( Base::template apply< Action >( begin, in, std::get< Shuffle::template value< Is, sizeof...( Is ) > >( t )... ) ) ) -> decltype( Base::template apply< Action >( begin, in, std::get< Shuffle::template value< Is, sizeof...( Is ) > >( t )... ) ) diff --git a/packages/PEGTL/include/tao/pegtl/contrib/state_control.hpp b/packages/PEGTL/include/tao/pegtl/contrib/state_control.hpp new file mode 100644 index 0000000000000000000000000000000000000000..28b105e913ae7a366d3cfa7c83bf3205e51a0b15 --- /dev/null +++ b/packages/PEGTL/include/tao/pegtl/contrib/state_control.hpp @@ -0,0 +1,118 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_PEGTL_CONTRIB_STATE_CONTROL_HPP +#define TAO_PEGTL_CONTRIB_STATE_CONTROL_HPP + +#include <type_traits> + +#include "shuffle_states.hpp" + +#include "../config.hpp" +#include "../internal/has_unwind.hpp" + +namespace TAO_PEGTL_NAMESPACE +{ + template< template< typename... > class Control > + struct state_control + { + template< typename Rule > + struct control + : Control< Rule > + { + static constexpr bool enable = true; + + template< typename ParseInput, typename State, typename... States > + static void start( [[maybe_unused]] const ParseInput& in, [[maybe_unused]] State& state, [[maybe_unused]] States&&... st ) + { + if constexpr( Control< Rule >::enable ) { + Control< Rule >::start( in, st... ); + } + if constexpr( State::template enable< Rule > ) { + state.template start< Rule >( in, st... ); + } +#if defined( _MSC_VER ) + ( (void)st, ... ); +#endif + } + + template< typename ParseInput, typename State, typename... States > + static void success( [[maybe_unused]] const ParseInput& in, [[maybe_unused]] State& state, [[maybe_unused]] States&&... st ) + { + if constexpr( State::template enable< Rule > ) { + state.template success< Rule >( in, st... ); + } + if constexpr( Control< Rule >::enable ) { + Control< Rule >::success( in, st... ); + } +#if defined( _MSC_VER ) + ( (void)st, ... ); +#endif + } + + template< typename ParseInput, typename State, typename... States > + static void failure( [[maybe_unused]] const ParseInput& in, [[maybe_unused]] State& state, [[maybe_unused]] States&&... st ) + { + if constexpr( State::template enable< Rule > ) { + state.template failure< Rule >( in, st... ); + } + if constexpr( Control< Rule >::enable ) { + Control< Rule >::failure( in, st... ); + } +#if defined( _MSC_VER ) + ( (void)st, ... ); +#endif + } + + template< typename ParseInput, typename State, typename... States > + [[noreturn]] static void raise( const ParseInput& in, [[maybe_unused]] State& state, States&&... st ) + { + if constexpr( State::template enable< Rule > ) { + state.template raise< Rule >( in, st... ); + } + Control< Rule >::raise( in, st... ); + } + + template< typename ParseInput, typename State, typename... States > + static auto unwind( [[maybe_unused]] const ParseInput& in, [[maybe_unused]] State& state, [[maybe_unused]] States&&... st ) + -> std::enable_if_t< State::template enable< Rule > || ( Control< Rule >::enable && internal::has_unwind< Control< Rule >, void, const ParseInput&, States... > ) > + { + if constexpr( State::template enable< Rule > ) { + state.template unwind< Rule >( in, st... ); + } + if constexpr( Control< Rule >::enable && internal::has_unwind< Control< Rule >, void, const ParseInput&, States... > ) { + Control< Rule >::unwind( in, st... ); + } +#if defined( _MSC_VER ) + ( (void)st, ... ); +#endif + } + + template< template< typename... > class Action, typename Iterator, typename ParseInput, typename State, typename... States > + static auto apply( const Iterator& begin, const ParseInput& in, [[maybe_unused]] State& state, States&&... st ) + -> decltype( Control< Rule >::template apply< Action >( begin, in, st... ) ) + { + if constexpr( State::template enable< Rule > ) { + state.template apply< Rule >( in, st... ); + } + return Control< Rule >::template apply< Action >( begin, in, st... ); + } + + template< template< typename... > class Action, typename ParseInput, typename State, typename... States > + static auto apply0( const ParseInput& in, [[maybe_unused]] State& state, States&&... st ) + -> decltype( Control< Rule >::template apply0< Action >( in, st... ) ) + { + if constexpr( State::template enable< Rule > ) { + state.template apply0< Rule >( in, st... ); + } + return Control< Rule >::template apply0< Action >( in, st... ); + } + }; + + template< typename Rule > + using type = rotate_states_right< control< Rule > >; + }; + +} // namespace TAO_PEGTL_NAMESPACE + +#endif diff --git a/packages/PEGTL/include/tao/pegtl/contrib/trace.hpp b/packages/PEGTL/include/tao/pegtl/contrib/trace.hpp index 798c951e6ab9cb518ab10622b2c4482ca326e537..9bc5976ac71a391c73bdc2657fca934e9bd9cbcc 100644 --- a/packages/PEGTL/include/tao/pegtl/contrib/trace.hpp +++ b/packages/PEGTL/include/tao/pegtl/contrib/trace.hpp @@ -1,153 +1,226 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #ifndef TAO_PEGTL_CONTRIB_TRACE_HPP #define TAO_PEGTL_CONTRIB_TRACE_HPP -#include <cassert> +#include <cstddef> #include <iomanip> #include <iostream> -#include <utility> -#include <vector> +#include <string_view> +#include <tuple> +#include "state_control.hpp" + +#include "../apply_mode.hpp" #include "../config.hpp" +#include "../demangle.hpp" #include "../normal.hpp" - -#include "../internal/demangle.hpp" +#include "../nothing.hpp" +#include "../parse.hpp" +#include "../rewind_mode.hpp" namespace TAO_PEGTL_NAMESPACE { - namespace internal + template< bool HideInternal = false, bool UseColor = true, std::size_t IndentIncrement = 2, std::size_t InitialIndent = 8 > + struct tracer_traits { + template< typename Rule > + static constexpr bool enable = ( HideInternal ? normal< Rule >::enable : true ); + + static constexpr std::size_t initial_indent = InitialIndent; + static constexpr std::size_t indent_increment = IndentIncrement; + + static constexpr std::string_view ansi_reset = UseColor ? "\033[m" : ""; + static constexpr std::string_view ansi_rule = UseColor ? "\033[36m" : ""; + static constexpr std::string_view ansi_hide = UseColor ? "\033[37m" : ""; + + static constexpr std::string_view ansi_position = UseColor ? "\033[1;34m" : ""; + static constexpr std::string_view ansi_success = UseColor ? "\033[32m" : ""; + static constexpr std::string_view ansi_failure = UseColor ? "\033[31m" : ""; + static constexpr std::string_view ansi_raise = UseColor ? "\033[1;31m" : ""; + static constexpr std::string_view ansi_unwind = UseColor ? "\033[31m" : ""; + static constexpr std::string_view ansi_apply = UseColor ? "\033[1;36m" : ""; + }; + + using standard_tracer_traits = tracer_traits< true >; + using complete_tracer_traits = tracer_traits< false >; + + template< typename TracerTraits > + struct tracer + { + const std::ios_base::fmtflags m_flags; + std::size_t m_count = 0; + std::vector< std::size_t > m_stack; + position m_position; + + template< typename Rule > + static constexpr bool enable = TracerTraits::template enable< Rule >; + template< typename ParseInput > - void print_current( const ParseInput& in ) + explicit tracer( const ParseInput& in ) + : m_flags( std::cerr.flags() ), + m_position( in.position() ) { - if( in.empty() ) { - std::cerr << "<eof>"; - } - else { - const auto c = in.peek_uint8(); - switch( c ) { - case 0: - std::cerr << "<nul> = "; - break; - case 9: - std::cerr << "<ht> = "; - break; - case 10: - std::cerr << "<lf> = "; - break; - case 13: - std::cerr << "<cr> = "; - break; - default: - if( isprint( c ) ) { - std::cerr << '\'' << c << "' = "; - } - } - std::cerr << "(char)" << unsigned( c ); - } + std::cerr << std::left; + print_position(); } - } // namespace internal + tracer( const tracer& ) = delete; + tracer( tracer&& ) = delete; - struct trace_state - { - unsigned rule = 0; - unsigned line = 0; - std::vector< unsigned > stack; - }; + ~tracer() + { + std::cerr.flags( m_flags ); + } - template< typename Rule, template< typename... > class Control > - struct basic_trace_control - : Control< Rule > - { - template< typename ParseInput, typename... States > - static void start( const ParseInput& in, States&&... st ) + tracer& operator=( const tracer& ) = delete; + tracer& operator=( tracer&& ) = delete; + + [[nodiscard]] std::size_t indent() const noexcept + { + return TracerTraits::initial_indent + TracerTraits::indent_increment * m_stack.size(); + } + + void print_position() const { - std::cerr << in.position() << " start " << internal::demangle< Rule >() << "; current "; - print_current( in ); - std::cerr << std::endl; - Control< Rule >::start( in, st... ); + std::cerr << std::setw( indent() ) << ' ' << TracerTraits::ansi_position << "position" << TracerTraits::ansi_reset << ' ' << m_position << '\n'; } - template< typename ParseInput, typename... States > - static void start( const ParseInput& in, trace_state& ts, States&&... st ) + void update_position( const position& p ) { - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ++ts.rule << " "; - start( in, st... ); - ts.stack.push_back( ts.rule ); + if( m_position != p ) { + m_position = p; + print_position(); + } } - template< typename ParseInput, typename... States > - static void success( const ParseInput& in, States&&... st ) + template< typename Rule, typename ParseInput, typename... States > + void start( const ParseInput& /*unused*/, States&&... /*unused*/ ) { - std::cerr << in.position() << " success " << internal::demangle< Rule >() << "; next "; - print_current( in ); - std::cerr << std::endl; - Control< Rule >::success( in, st... ); + std::cerr << '#' << std::setw( indent() - 1 ) << ++m_count << TracerTraits::ansi_rule << demangle< Rule >() << TracerTraits::ansi_reset << '\n'; + m_stack.push_back( m_count ); } - template< typename ParseInput, typename... States > - static void success( const ParseInput& in, trace_state& ts, States&&... st ) + template< typename Rule, typename ParseInput, typename... States > + void success( const ParseInput& in, States&&... /*unused*/ ) { - assert( !ts.stack.empty() ); - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " "; - success( in, st... ); - ts.stack.pop_back(); + const auto prev = m_stack.back(); + m_stack.pop_back(); + std::cerr << std::setw( indent() ) << ' ' << TracerTraits::ansi_success << "success" << TracerTraits::ansi_reset; + if( m_count != prev ) { + std::cerr << " #" << prev << ' ' << TracerTraits::ansi_hide << demangle< Rule >() << TracerTraits::ansi_reset; + } + std::cerr << '\n'; + update_position( in.position() ); } - template< typename ParseInput, typename... States > - static void failure( const ParseInput& in, States&&... st ) + template< typename Rule, typename ParseInput, typename... States > + void failure( const ParseInput& in, States&&... /*unused*/ ) { - std::cerr << in.position() << " failure " << internal::demangle< Rule >() << std::endl; - Control< Rule >::failure( in, st... ); + const auto prev = m_stack.back(); + m_stack.pop_back(); + std::cerr << std::setw( indent() ) << ' ' << TracerTraits::ansi_failure << "failure" << TracerTraits::ansi_reset; + if( m_count != prev ) { + std::cerr << " #" << prev << ' ' << TracerTraits::ansi_hide << demangle< Rule >() << TracerTraits::ansi_reset; + } + std::cerr << '\n'; + update_position( in.position() ); } - template< typename ParseInput, typename... States > - static void failure( const ParseInput& in, trace_state& ts, States&&... st ) + template< typename Rule, typename ParseInput, typename... States > + void raise( const ParseInput& /*unused*/, States&&... /*unused*/ ) { - assert( !ts.stack.empty() ); - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " "; - failure( in, st... ); - ts.stack.pop_back(); + std::cerr << std::setw( indent() ) << ' ' << TracerTraits::ansi_raise << "raise" << TracerTraits::ansi_reset << ' ' << TracerTraits::ansi_rule << demangle< Rule >() << TracerTraits::ansi_reset << '\n'; + } + + template< typename Rule, typename ParseInput, typename... States > + void unwind( const ParseInput& in, States&&... /*unused*/ ) + { + const auto prev = m_stack.back(); + m_stack.pop_back(); + std::cerr << std::setw( indent() ) << ' ' << TracerTraits::ansi_unwind << "unwind" << TracerTraits::ansi_reset; + if( m_count != prev ) { + std::cerr << " #" << prev << ' ' << TracerTraits::ansi_hide << demangle< Rule >() << TracerTraits::ansi_reset; + } + std::cerr << '\n'; + update_position( in.position() ); } - template< template< typename... > class Action, typename Iterator, typename ParseInput, typename... States > - static auto apply( const Iterator& begin, const ParseInput& in, States&&... st ) - -> decltype( Control< Rule >::template apply< Action >( begin, in, st... ) ) + template< typename Rule, typename ParseInput, typename... States > + void apply( const ParseInput& /*unused*/, States&&... /*unused*/ ) { - std::cerr << in.position() << " apply " << internal::demangle< Rule >() << std::endl; - return Control< Rule >::template apply< Action >( begin, in, st... ); + std::cerr << std::setw( static_cast< int >( indent() - TracerTraits::indent_increment ) ) << ' ' << TracerTraits::ansi_apply << "apply" << TracerTraits::ansi_reset << '\n'; } - template< template< typename... > class Action, typename Iterator, typename ParseInput, typename... States > - static auto apply( const Iterator& begin, const ParseInput& in, trace_state& ts, States&&... st ) - -> decltype( apply< Action >( begin, in, st... ) ) + template< typename Rule, typename ParseInput, typename... States > + void apply0( const ParseInput& /*unused*/, States&&... /*unused*/ ) { - std::cerr << std::setw( 6 ) << ++ts.line << " "; - return apply< Action >( begin, in, st... ); + std::cerr << std::setw( static_cast< int >( indent() - TracerTraits::indent_increment ) ) << ' ' << TracerTraits::ansi_apply << "apply0" << TracerTraits::ansi_reset << '\n'; } - template< template< typename... > class Action, typename ParseInput, typename... States > - static auto apply0( const ParseInput& in, States&&... st ) - -> decltype( Control< Rule >::template apply0< Action >( in, st... ) ) + template< typename Rule, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + typename ParseInput, + typename... States > + bool parse( ParseInput&& in, States&&... st ) { - std::cerr << in.position() << " apply0 " << internal::demangle< Rule >() << std::endl; - return Control< Rule >::template apply0< Action >( in, st... ); + return TAO_PEGTL_NAMESPACE::parse< Rule, Action, state_control< Control >::template type >( in, st..., *this ); } + }; - template< template< typename... > class Action, typename ParseInput, typename... States > - static auto apply0( const ParseInput& in, trace_state& ts, States&&... st ) - -> decltype( apply0< Action >( in, st... ) ) + template< typename Rule, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + typename ParseInput, + typename... States > + bool standard_trace( ParseInput&& in, States&&... st ) + { + tracer< standard_tracer_traits > tr( in ); + return tr.parse< Rule, Action, Control >( in, st... ); + } + + template< typename Rule, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + typename ParseInput, + typename... States > + bool complete_trace( ParseInput&& in, States&&... st ) + { + tracer< complete_tracer_traits > tr( in ); + return tr.parse< Rule, Action, Control >( in, st... ); + } + + template< typename Tracer > + struct trace + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename ParseInput, + typename... States > + [[nodiscard]] static bool match( ParseInput& in, States&&... st ) { - std::cerr << std::setw( 6 ) << ++ts.line << " "; - return apply0< Action >( in, st... ); + if constexpr( sizeof...( st ) == 0 ) { + return TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, state_control< Control >::template type >( in, st..., Tracer( in ) ); + } + else if constexpr( !std::is_same_v< std::tuple_element_t< sizeof...( st ) - 1, std::tuple< States... > >, Tracer& > ) { + return TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, state_control< Control >::template type >( in, st..., Tracer( in ) ); + } + else { + return TAO_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); + } } }; - template< typename Rule > - using trace_control = basic_trace_control< Rule, normal >; + using trace_standard = trace< tracer< standard_tracer_traits > >; + using trace_complete = trace< tracer< complete_tracer_traits > >; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/contrib/visit_rt.hpp b/packages/PEGTL/include/tao/pegtl/contrib/visit_rt.hpp deleted file mode 100644 index b4958e84399f2af15b0da7b940a2472fe52b16e2..0000000000000000000000000000000000000000 --- a/packages/PEGTL/include/tao/pegtl/contrib/visit_rt.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_PEGTL_CONTRIB_VISIT_RT_HPP -#define TAO_PEGTL_CONTRIB_VISIT_RT_HPP - -#include <set> -#include <string_view> - -#include "../config.hpp" -#include "../type_list.hpp" - -#include "../internal/demangle.hpp" - -namespace TAO_PEGTL_NAMESPACE -{ - namespace internal - { - template< template< typename... > class Func, typename... Rules > - struct visitor_rt - { - template< typename... Args > - static void visit( std::set< std::string_view >& done, Args&&... args ) - { - ( visit_rule< Rules >( typename Rules::subs_t(), done, args... ), ... ); - } - - private: - template< typename Rule, typename... Subs, typename... Args > - static void visit_rule( type_list< Subs... > /*unused*/, std::set< std::string_view >& done, Args&&... args ) - { - if( done.emplace( demangle< Rule >() ).second ) { - Func< Rule >::visit( args... ); - visitor_rt< Func, Subs... >::visit( done, args... ); - } - } - }; - - } // namespace internal - - template< typename Rule, template< typename... > class Func, typename... Args > - std::size_t visit_rt( Args&&... args ) - { - std::set< std::string_view > done; - internal::visitor_rt< Func, Rule >::visit( done, args... ); - return done.size(); - } - -} // namespace TAO_PEGTL_NAMESPACE - -#endif diff --git a/packages/PEGTL/include/tao/pegtl/cstream_input.hpp b/packages/PEGTL/include/tao/pegtl/cstream_input.hpp index cebc6f7aa6201b877991cd73bb0b5804092848b8..ad50942faf93da27efaebb8a15bf6b050ea51169 100644 --- a/packages/PEGTL/include/tao/pegtl/cstream_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/cstream_input.hpp @@ -25,7 +25,7 @@ namespace TAO_PEGTL_NAMESPACE }; template< typename... Ts > - cstream_input( Ts&&... )->cstream_input<>; + cstream_input( Ts&&... ) -> cstream_input<>; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/internal/demangle.hpp b/packages/PEGTL/include/tao/pegtl/demangle.hpp similarity index 94% rename from packages/PEGTL/include/tao/pegtl/internal/demangle.hpp rename to packages/PEGTL/include/tao/pegtl/demangle.hpp index 183134309bda8bd43843fb10f3db68880fc5788e..4122ce4afcee169ae4fbcb549704bc135dc81425 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/demangle.hpp +++ b/packages/PEGTL/include/tao/pegtl/demangle.hpp @@ -1,15 +1,13 @@ // Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL -#ifndef TAO_PEGTL_INTERNAL_DEMANGLE_HPP -#define TAO_PEGTL_INTERNAL_DEMANGLE_HPP +#ifndef TAO_PEGTL_DEMANGLE_HPP +#define TAO_PEGTL_DEMANGLE_HPP #include <ciso646> #include <string_view> -#include "../config.hpp" - -namespace TAO_PEGTL_NAMESPACE::internal +namespace tao { #if defined( __clang__ ) @@ -135,6 +133,6 @@ namespace TAO_PEGTL_NAMESPACE::internal #endif -} // namespace TAO_PEGTL_NAMESPACE::internal +} // namespace tao #endif diff --git a/packages/PEGTL/include/tao/pegtl/file_input.hpp b/packages/PEGTL/include/tao/pegtl/file_input.hpp index d54db990fb4bbba59e483a5e5831ff09f9289881..1fba74bb583d95d15deea4076919de820c00e559 100644 --- a/packages/PEGTL/include/tao/pegtl/file_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/file_input.hpp @@ -37,7 +37,7 @@ namespace TAO_PEGTL_NAMESPACE #endif template< typename... Ts > - explicit file_input( Ts&&... )->file_input<>; + explicit file_input( Ts&&... ) -> file_input<>; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/internal/alnum.hpp b/packages/PEGTL/include/tao/pegtl/internal/alnum.hpp deleted file mode 100644 index 45704b90475acfcc19196b1452416d5d843f2a2f..0000000000000000000000000000000000000000 --- a/packages/PEGTL/include/tao/pegtl/internal/alnum.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_PEGTL_INTERNAL_ALNUM_HPP -#define TAO_PEGTL_INTERNAL_ALNUM_HPP - -#include "../config.hpp" - -#include "peek_char.hpp" -#include "ranges.hpp" - -namespace TAO_PEGTL_NAMESPACE::internal -{ - using alnum = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9' >; - -} // namespace TAO_PEGTL_NAMESPACE::internal - -#endif diff --git a/packages/PEGTL/include/tao/pegtl/internal/alpha.hpp b/packages/PEGTL/include/tao/pegtl/internal/alpha.hpp deleted file mode 100644 index b1591d92b58c847655ee292149b47e135dd54fb4..0000000000000000000000000000000000000000 --- a/packages/PEGTL/include/tao/pegtl/internal/alpha.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_PEGTL_INTERNAL_ALPHA_HPP -#define TAO_PEGTL_INTERNAL_ALPHA_HPP - -#include "../config.hpp" - -#include "peek_char.hpp" -#include "ranges.hpp" - -namespace TAO_PEGTL_NAMESPACE::internal -{ - using alpha = ranges< peek_char, 'a', 'z', 'A', 'Z' >; - -} // namespace TAO_PEGTL_NAMESPACE::internal - -#endif diff --git a/packages/PEGTL/include/tao/pegtl/internal/apply.hpp b/packages/PEGTL/include/tao/pegtl/internal/apply.hpp index 92e24ef26b528eb3a8370ff88ff577b45529e461..7dac482bffd3cbf166e0f9c5dc48714fb89bf201 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/apply.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/apply.hpp @@ -29,7 +29,7 @@ namespace TAO_PEGTL_NAMESPACE::internal class Control, typename ParseInput, typename... States > - [[nodiscard]] static bool match( ParseInput& in, States&&... st ) + [[nodiscard]] static bool match( [[maybe_unused]] ParseInput& in, [[maybe_unused]] States&&... st ) { if constexpr( ( A == apply_mode::action ) && ( sizeof...( Actions ) > 0 ) ) { using action_t = typename ParseInput::action_t; @@ -38,8 +38,7 @@ namespace TAO_PEGTL_NAMESPACE::internal } else { #if defined( _MSC_VER ) - (void)in; - (void)( (void)st, ... ); + ( (void)st, ... ); #endif return true; } diff --git a/packages/PEGTL/include/tao/pegtl/internal/apply0.hpp b/packages/PEGTL/include/tao/pegtl/internal/apply0.hpp index 3ad4b3c2a2800ca4d5e5cc047dc7fcfb469ae417..7c3b92c626b83d630856fd07ae7aaeffdf100e9c 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/apply0.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/apply0.hpp @@ -29,14 +29,14 @@ namespace TAO_PEGTL_NAMESPACE::internal class Control, typename ParseInput, typename... States > - [[nodiscard]] static bool match( ParseInput& /*unused*/, States&&... st ) + [[nodiscard]] static bool match( ParseInput& /*unused*/, [[maybe_unused]] States&&... st ) { if constexpr( A == apply_mode::action ) { return ( apply0_single< Actions >::match( st... ) && ... ); } else { #if defined( _MSC_VER ) - (void)( (void)st, ... ); + ( (void)st, ... ); #endif return true; } diff --git a/packages/PEGTL/include/tao/pegtl/internal/bol.hpp b/packages/PEGTL/include/tao/pegtl/internal/bol.hpp index 3304cc5d4ff47005570e420c66ed86cc1bb3ce52..20f029e54204ad9ae0f21946de63a357d90e1b81 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/bol.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/bol.hpp @@ -5,11 +5,10 @@ #define TAO_PEGTL_INTERNAL_BOL_HPP #include "../config.hpp" +#include "../type_list.hpp" #include "enable_control.hpp" -#include "../type_list.hpp" - namespace TAO_PEGTL_NAMESPACE::internal { struct bol @@ -20,7 +19,7 @@ namespace TAO_PEGTL_NAMESPACE::internal template< typename ParseInput > [[nodiscard]] static bool match( ParseInput& in ) noexcept { - return in.byte_in_line() == 0; + return in.column() == 1; } }; diff --git a/packages/PEGTL/include/tao/pegtl/internal/bump.hpp b/packages/PEGTL/include/tao/pegtl/internal/bump.hpp index 74a1a7d7c749d12c55d570d762d590a5aa8aa554..fded8cc2e2315b25c5dbf170bddfe5729fdf3285 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/bump.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/bump.hpp @@ -15,10 +15,10 @@ namespace TAO_PEGTL_NAMESPACE::internal for( std::size_t i = 0; i < count; ++i ) { if( iter.data[ i ] == ch ) { ++iter.line; - iter.byte_in_line = 0; + iter.column = 1; } else { - ++iter.byte_in_line; + ++iter.column; } } iter.byte += count; @@ -29,14 +29,14 @@ namespace TAO_PEGTL_NAMESPACE::internal { iter.data += count; iter.byte += count; - iter.byte_in_line += count; + iter.column += count; } inline void bump_to_next_line( iterator& iter, const std::size_t count ) noexcept { ++iter.line; iter.byte += count; - iter.byte_in_line = 0; + iter.column = 1; iter.data += count; } diff --git a/packages/PEGTL/include/tao/pegtl/internal/dusel_mode.hpp b/packages/PEGTL/include/tao/pegtl/internal/dusel_mode.hpp deleted file mode 100644 index dadba26303728559424379934ab53eef38d4a3c1..0000000000000000000000000000000000000000 --- a/packages/PEGTL/include/tao/pegtl/internal/dusel_mode.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_PEGTL_INTERNAL_DUSEL_MODE_HPP -#define TAO_PEGTL_INTERNAL_DUSEL_MODE_HPP - -#include "../config.hpp" - -namespace TAO_PEGTL_NAMESPACE::internal -{ - enum class dusel_mode : char - { - nothing = 0, - control = 1, - control_and_apply_void = 2, - control_and_apply_bool = 3, - control_and_apply0_void = 4, - control_and_apply0_bool = 5 - }; - -} // namespace TAO_PEGTL_NAMESPACE::internal - -#endif diff --git a/packages/PEGTL/include/tao/pegtl/internal/duseltronik.hpp b/packages/PEGTL/include/tao/pegtl/internal/duseltronik.hpp deleted file mode 100644 index 53555e9faf04b63311c39eb15234fb35a9518db2..0000000000000000000000000000000000000000 --- a/packages/PEGTL/include/tao/pegtl/internal/duseltronik.hpp +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_PEGTL_INTERNAL_DUSELTRONIK_HPP -#define TAO_PEGTL_INTERNAL_DUSELTRONIK_HPP - -#include "../apply_mode.hpp" -#include "../config.hpp" -#include "../rewind_mode.hpp" - -#include "dusel_mode.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -namespace TAO_PEGTL_NAMESPACE::internal -{ - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - dusel_mode = dusel_mode::nothing > - struct duseltronik; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing > - { - template< typename ParseInput, typename... States > - [[nodiscard]] static auto match( ParseInput& in, States&&... st ) - -> decltype( Rule::template match< A, M, Action, Control >( in, st... ) ) - { - return Rule::template match< A, M, Action, Control >( in, st... ); - } - - template< typename ParseInput, typename... States, int = 1 > - [[nodiscard]] static auto match( ParseInput& in, States&&... /*unused*/ ) - -> decltype( Rule::match( in ) ) - { - return Rule::match( in ); - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control > - { - template< typename ParseInput, typename... States > - [[nodiscard]] static bool match( ParseInput& in, States&&... st ) - { - Control< Rule >::start( static_cast< const ParseInput& >( in ), st... ); - - if( duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - Control< Rule >::success( static_cast< const ParseInput& >( in ), st... ); - return true; - } - Control< Rule >::failure( static_cast< const ParseInput& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply_void > - { - template< typename ParseInput, typename... States > - [[nodiscard]] static bool match( ParseInput& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::required >(); - - Control< Rule >::start( static_cast< const ParseInput& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - Control< Rule >::template apply< Action >( m.iterator(), static_cast< const ParseInput& >( in ), st... ); - Control< Rule >::success( static_cast< const ParseInput& >( in ), st... ); - return m( true ); - } - Control< Rule >::failure( static_cast< const ParseInput& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply_bool > - { - template< typename ParseInput, typename... States > - [[nodiscard]] static bool match( ParseInput& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::required >(); - - Control< Rule >::start( static_cast< const ParseInput& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - if( Control< Rule >::template apply< Action >( m.iterator(), static_cast< const ParseInput& >( in ), st... ) ) { - Control< Rule >::success( static_cast< const ParseInput& >( in ), st... ); - return m( true ); - } - } - Control< Rule >::failure( static_cast< const ParseInput& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply0_void > - { - template< typename ParseInput, typename... States > - [[nodiscard]] static bool match( ParseInput& in, States&&... st ) - { - Control< Rule >::start( static_cast< const ParseInput& >( in ), st... ); - - if( duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - Control< Rule >::template apply0< Action >( static_cast< const ParseInput& >( in ), st... ); - Control< Rule >::success( static_cast< const ParseInput& >( in ), st... ); - return true; - } - Control< Rule >::failure( static_cast< const ParseInput& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply0_bool > - { - template< typename ParseInput, typename... States > - [[nodiscard]] static bool match( ParseInput& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::required >(); - - Control< Rule >::start( static_cast< const ParseInput& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - if( Control< Rule >::template apply0< Action >( static_cast< const ParseInput& >( in ), st... ) ) { - Control< Rule >::success( static_cast< const ParseInput& >( in ), st... ); - return m( true ); - } - } - Control< Rule >::failure( static_cast< const ParseInput& >( in ), st... ); - return false; - } - }; - -} // namespace TAO_PEGTL_NAMESPACE::internal - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/packages/PEGTL/include/tao/pegtl/internal/file_mapper_posix.hpp b/packages/PEGTL/include/tao/pegtl/internal/file_mapper_posix.hpp index cd4b5663e1c14c479835f1d2f7bfa88d48844bb5..86791340031f4f89b8aca1b90c5e807ec21e04eb 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/file_mapper_posix.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/file_mapper_posix.hpp @@ -4,22 +4,74 @@ #ifndef TAO_PEGTL_INTERNAL_FILE_MAPPER_POSIX_HPP #define TAO_PEGTL_INTERNAL_FILE_MAPPER_POSIX_HPP +#include <fcntl.h> #include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> -#include <system_error> +#include <filesystem> +#include <utility> #include "../config.hpp" -#include "file_opener.hpp" - namespace TAO_PEGTL_NAMESPACE::internal { + struct file_opener + { + explicit file_opener( const std::filesystem::path& path ) // NOLINT(modernize-pass-by-value) + : m_path( path ), + m_fd( open() ) + {} + + file_opener( const file_opener& ) = delete; + file_opener( file_opener&& ) = delete; + + ~file_opener() + { + ::close( m_fd ); + } + + void operator=( const file_opener& ) = delete; + void operator=( file_opener&& ) = delete; + + [[nodiscard]] std::size_t size() const + { + struct stat st; + errno = 0; + if( ::fstat( m_fd, &st ) < 0 ) { + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "fstat() failed", m_path, ec ); + } + return std::size_t( st.st_size ); + } + + const std::filesystem::path m_path; + const int m_fd; + + private: + [[nodiscard]] int open() const + { + errno = 0; + const int fd = ::open( m_path.c_str(), + O_RDONLY +#if defined( O_CLOEXEC ) + | O_CLOEXEC +#endif + ); + if( fd >= 0 ) { + return fd; + } + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "open() failed", m_path, ec ); + } + }; + class file_mapper { public: - explicit file_mapper( const char* filename ) - : file_mapper( file_opener( filename ) ) + explicit file_mapper( const std::filesystem::path& path ) + : file_mapper( file_opener( path ) ) {} explicit file_mapper( const file_opener& reader ) @@ -27,15 +79,15 @@ namespace TAO_PEGTL_NAMESPACE::internal m_data( static_cast< const char* >( ::mmap( nullptr, m_size, PROT_READ, MAP_PRIVATE, reader.m_fd, 0 ) ) ) { if( ( m_size != 0 ) && ( intptr_t( m_data ) == -1 ) ) { - const auto ec = errno; - throw std::system_error( ec, std::system_category(), reader.m_source ); + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "mmap() failed", reader.m_path, ec ); } } file_mapper( const file_mapper& ) = delete; file_mapper( file_mapper&& ) = delete; - ~file_mapper() noexcept + ~file_mapper() { // Legacy C interface requires pointer-to-mutable but does not write through the pointer. ::munmap( const_cast< char* >( m_data ), m_size ); diff --git a/packages/PEGTL/include/tao/pegtl/internal/file_mapper_win32.hpp b/packages/PEGTL/include/tao/pegtl/internal/file_mapper_win32.hpp index 27f9eaf955f141de0c02478d93d02a518af1bade..e8dab183317686ab86d49a511493892e20c90018 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/file_mapper_win32.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/file_mapper_win32.hpp @@ -26,7 +26,7 @@ #undef TAO_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED #endif -#include <system_error> +#include <filesystem> #include "../config.hpp" @@ -34,15 +34,15 @@ namespace TAO_PEGTL_NAMESPACE::internal { struct win32_file_opener { - explicit win32_file_opener( const char* filename ) - : m_source( filename ), + explicit win32_file_opener( const std::filesystem::path& path ) + : m_path( path ), m_handle( open() ) {} win32_file_opener( const win32_file_opener& ) = delete; win32_file_opener( win32_file_opener&& ) = delete; - ~win32_file_opener() noexcept + ~win32_file_opener() { ::CloseHandle( m_handle ); } @@ -54,23 +54,21 @@ namespace TAO_PEGTL_NAMESPACE::internal { LARGE_INTEGER size; if( !::GetFileSizeEx( m_handle, &size ) ) { - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), std::string( "GetFileSizeEx(): " ) + m_source ); + const std::error_code ec( ::GetLastError(), std::system_category() ); + throw std::filesystem::filesystem_error( "GetFileSizeEx() failed", m_path, ec ); } return std::size_t( size.QuadPart ); } - const char* const m_source; + const std::filesystem::path m_path; const HANDLE m_handle; private: [[nodiscard]] HANDLE open() const { SetLastError( 0 ); - std::wstring ws( m_source, m_source + strlen( m_source ) ); - #if( _WIN32_WINNT >= 0x0602 ) - const HANDLE handle = ::CreateFile2( ws.c_str(), + const HANDLE handle = ::CreateFile2( m_path.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, @@ -78,10 +76,10 @@ namespace TAO_PEGTL_NAMESPACE::internal if( handle != INVALID_HANDLE_VALUE ) { return handle; } - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), std::string( "CreateFile2(): " ) + m_source ); + const std::error_code ec( ::GetLastError(), std::system_category() ); + throw std::filesystem::filesystem_error( "CreateFile2() failed", m_path, ec ); #else - const HANDLE handle = ::CreateFileW( ws.c_str(), + const HANDLE handle = ::CreateFileW( m_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, @@ -91,16 +89,16 @@ namespace TAO_PEGTL_NAMESPACE::internal if( handle != INVALID_HANDLE_VALUE ) { return handle; } - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), std::string( "CreateFileW(): " ) + m_source ); + const std::error_code ec( ::GetLastError(), std::system_category() ); + throw std::filesystem::filesystem_error( "CreateFileW()", m_path, ec ); #endif } }; struct win32_file_mapper { - explicit win32_file_mapper( const char* filename ) - : win32_file_mapper( win32_file_opener( filename ) ) + explicit win32_file_mapper( const std::filesystem::path& path ) + : win32_file_mapper( win32_file_opener( path ) ) {} explicit win32_file_mapper( const win32_file_opener& reader ) @@ -111,7 +109,7 @@ namespace TAO_PEGTL_NAMESPACE::internal win32_file_mapper( const win32_file_mapper& ) = delete; win32_file_mapper( win32_file_mapper&& ) = delete; - ~win32_file_mapper() noexcept + ~win32_file_mapper() { ::CloseHandle( m_handle ); } @@ -140,16 +138,16 @@ namespace TAO_PEGTL_NAMESPACE::internal if( handle != NULL || file_size == 0 ) { return handle; } - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), std::string( "CreateFileMappingW(): " ) + reader.m_source ); + const std::error_code ec( ::GetLastError(), std::system_category() ); + throw std::filesystem::filesystem_error( "CreateFileMappingW() failed", reader.m_path, ec ); } }; class file_mapper { public: - explicit file_mapper( const char* filename ) - : file_mapper( win32_file_mapper( filename ) ) + explicit file_mapper( const std::filesystem::path& path ) + : file_mapper( win32_file_mapper( path ) ) {} explicit file_mapper( const win32_file_mapper& mapper ) @@ -161,15 +159,15 @@ namespace TAO_PEGTL_NAMESPACE::internal 0 ) ) ) { if( ( m_size != 0 ) && ( intptr_t( m_data ) == 0 ) ) { - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), "MapViewOfFile()" ); + const std::error_code ec( ::GetLastError(), std::system_category() ); + throw std::filesystem::filesystem_error( "MapViewOfFile() failed", ec ); } } file_mapper( const file_mapper& ) = delete; file_mapper( file_mapper&& ) = delete; - ~file_mapper() noexcept + ~file_mapper() { ::UnmapViewOfFile( LPCVOID( m_data ) ); } diff --git a/packages/PEGTL/include/tao/pegtl/internal/file_opener.hpp b/packages/PEGTL/include/tao/pegtl/internal/file_opener.hpp deleted file mode 100644 index 5f2521b6b1e3eafc4a7b294e8ce65f0dc2426c21..0000000000000000000000000000000000000000 --- a/packages/PEGTL/include/tao/pegtl/internal/file_opener.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_PEGTL_INTERNAL_FILE_OPENER_HPP -#define TAO_PEGTL_INTERNAL_FILE_OPENER_HPP - -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include <system_error> -#include <utility> - -#include "../config.hpp" - -namespace TAO_PEGTL_NAMESPACE::internal -{ - struct file_opener - { - explicit file_opener( const char* filename ) - : m_source( filename ), - m_fd( open() ) - {} - - file_opener( const file_opener& ) = delete; - file_opener( file_opener&& ) = delete; - - ~file_opener() noexcept - { - ::close( m_fd ); - } - - void operator=( const file_opener& ) = delete; - void operator=( file_opener&& ) = delete; - - [[nodiscard]] std::size_t size() const - { - struct stat st; - errno = 0; - if( ::fstat( m_fd, &st ) < 0 ) { - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); - } - return std::size_t( st.st_size ); - } - - const char* const m_source; - const int m_fd; - - private: - [[nodiscard]] int open() const - { - errno = 0; - const int fd = ::open( m_source, - O_RDONLY -#if defined( O_CLOEXEC ) - | O_CLOEXEC -#endif - ); - if( fd >= 0 ) { - return fd; - } - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); - } - }; - -} // namespace TAO_PEGTL_NAMESPACE::internal - -#endif diff --git a/packages/PEGTL/include/tao/pegtl/internal/file_reader.hpp b/packages/PEGTL/include/tao/pegtl/internal/file_reader.hpp index ac098e5921edae0d14f0ed7efe7e298670b95c9a..d2812abfc8fc62726ee55c93679beb91e07aa4ed 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/file_reader.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/file_reader.hpp @@ -5,31 +5,37 @@ #define TAO_PEGTL_INTERNAL_FILE_READER_HPP #include <cstdio> +#include <filesystem> #include <memory> #include <string> -#include <system_error> #include <utility> #include "../config.hpp" namespace TAO_PEGTL_NAMESPACE::internal { - [[nodiscard]] inline std::FILE* file_open( const char* filename ) + [[nodiscard]] inline std::FILE* file_open( const std::filesystem::path& path ) { errno = 0; #if defined( _MSC_VER ) std::FILE* file; - if( ::fopen_s( &file, filename, "rb" ) == 0 ) -#elif defined( __MINGW32__ ) - if( auto* file = std::fopen( filename, "rb" ) ) + if( ::_wfopen_s( &file, path.c_str(), L"rb" ) == 0 ) { + return file; + } + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "_wfopen_s() failed", path, ec ); #else - if( auto* file = std::fopen( filename, "rbe" ) ) +#if defined( __MINGW32__ ) + if( auto* file = std::fopen( path.c_str(), "rb" ) ) +#else + if( auto* file = std::fopen( path.c_str(), "rbe" ) ) #endif { return file; } - const auto ec = errno; - throw std::system_error( ec, std::system_category(), filename ); + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "std::fopen() failed", path, ec ); +#endif } struct file_close @@ -43,13 +49,12 @@ namespace TAO_PEGTL_NAMESPACE::internal class file_reader { public: - explicit file_reader( const char* filename ) - : m_source( filename ), - m_file( file_open( m_source ) ) + explicit file_reader( const std::filesystem::path& path ) + : file_reader( file_open( path ), path ) {} - file_reader( FILE* file, const char* filename ) noexcept - : m_source( filename ), + file_reader( FILE* file, const std::filesystem::path& path ) // NOLINT(modernize-pass-by-value) + : m_path( path ), m_file( file ) {} @@ -66,23 +71,23 @@ namespace TAO_PEGTL_NAMESPACE::internal errno = 0; if( std::fseek( m_file.get(), 0, SEEK_END ) != 0 ) { // LCOV_EXCL_START - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "std::fseek() failed [SEEK_END]", m_path, ec ); // LCOV_EXCL_STOP } errno = 0; const auto s = std::ftell( m_file.get() ); if( s < 0 ) { // LCOV_EXCL_START - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "std::ftell() failed", m_path, ec ); // LCOV_EXCL_STOP } errno = 0; if( std::fseek( m_file.get(), 0, SEEK_SET ) != 0 ) { // LCOV_EXCL_START - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "std::fseek() failed [SEEK_SET]", m_path, ec ); // LCOV_EXCL_STOP } return std::size_t( s ); @@ -95,15 +100,15 @@ namespace TAO_PEGTL_NAMESPACE::internal errno = 0; if( !nrv.empty() && ( std::fread( &nrv[ 0 ], nrv.size(), 1, m_file.get() ) != 1 ) ) { // LCOV_EXCL_START - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); + const std::error_code ec( errno, std::system_category() ); + throw std::filesystem::filesystem_error( "std::fread() failed", m_path, ec ); // LCOV_EXCL_STOP } return nrv; } private: - const char* const m_source; + const std::filesystem::path m_path; const std::unique_ptr< std::FILE, file_close > m_file; }; diff --git a/packages/PEGTL/include/tao/pegtl/internal/has_unwind.hpp b/packages/PEGTL/include/tao/pegtl/internal/has_unwind.hpp new file mode 100644 index 0000000000000000000000000000000000000000..20bd953f5b35b75f78588449507ae2234e0c899d --- /dev/null +++ b/packages/PEGTL/include/tao/pegtl/internal/has_unwind.hpp @@ -0,0 +1,21 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_PEGTL_INTERNAL_HAS_UNWIND_HPP +#define TAO_PEGTL_INTERNAL_HAS_UNWIND_HPP + +#include <utility> + +#include "../config.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + template< typename, typename... > + inline constexpr bool has_unwind = false; + + template< typename C, typename... S > + inline constexpr bool has_unwind< C, decltype( C::unwind( std::declval< S >()... ) ), S... > = true; + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/packages/PEGTL/include/tao/pegtl/internal/iterator.hpp b/packages/PEGTL/include/tao/pegtl/internal/iterator.hpp index 416b53d006beb875cf725d25649ceaf8014f26b1..ae2cca18d962d44aa7eb53ea62918fd2a64644d7 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/iterator.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/iterator.hpp @@ -4,6 +4,7 @@ #ifndef TAO_PEGTL_INTERNAL_ITERATOR_HPP #define TAO_PEGTL_INTERNAL_ITERATOR_HPP +#include <cassert> #include <cstdlib> #include "../config.hpp" @@ -18,12 +19,15 @@ namespace TAO_PEGTL_NAMESPACE::internal : data( in_data ) {} - iterator( const char* in_data, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept + iterator( const char* in_data, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_column ) noexcept : data( in_data ), byte( in_byte ), line( in_line ), - byte_in_line( in_byte_in_line ) - {} + column( in_column ) + { + assert( in_line != 0 ); + assert( in_column != 0 ); + } iterator( const iterator& ) = default; iterator( iterator&& ) = default; @@ -33,16 +37,11 @@ namespace TAO_PEGTL_NAMESPACE::internal iterator& operator=( const iterator& ) = default; iterator& operator=( iterator&& ) = default; - void reset() noexcept - { - *this = iterator(); - } - const char* data = nullptr; std::size_t byte = 0; std::size_t line = 1; - std::size_t byte_in_line = 0; + std::size_t column = 1; }; } // namespace TAO_PEGTL_NAMESPACE::internal diff --git a/packages/PEGTL/include/tao/pegtl/internal/marker.hpp b/packages/PEGTL/include/tao/pegtl/internal/marker.hpp index 27d4c0cf08e42cccac3502b93685251ce2556fa1..6cec4aa8f6122ff05e1180da6ef8fdcd16e272ac 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/marker.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/marker.hpp @@ -46,7 +46,7 @@ namespace TAO_PEGTL_NAMESPACE::internal marker( const marker& ) = delete; marker( marker&& ) = delete; - ~marker() noexcept + ~marker() { if( m_input != nullptr ) { ( *m_input ) = m_saved; diff --git a/packages/PEGTL/include/tao/pegtl/internal/missing_apply.hpp b/packages/PEGTL/include/tao/pegtl/internal/missing_apply.hpp index 0e3e51127f48a7ef7e6162b3bcb9ed2ec051193a..d1e8f76837a68acff767962ca7c1ef9c9eb92acc 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/missing_apply.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/missing_apply.hpp @@ -16,8 +16,11 @@ namespace TAO_PEGTL_NAMESPACE::internal typename... States > void missing_apply( ParseInput& in, States&&... st ) { + // This function only exists for better error messages, which means that it is only called when we know that it won't compile. + // LCOV_EXCL_START auto m = in.template mark< rewind_mode::required >(); (void)Control::template apply< Action >( m.iterator(), in, st... ); + // LCOV_EXCL_STOP } } // namespace TAO_PEGTL_NAMESPACE::internal diff --git a/packages/PEGTL/include/tao/pegtl/internal/missing_apply0.hpp b/packages/PEGTL/include/tao/pegtl/internal/missing_apply0.hpp index 345e50f6e9ec3dce59f0fec4fc0340c48d9aeb86..a7b65f8c925c0b2c174cd406d7edc027dd2257c5 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/missing_apply0.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/missing_apply0.hpp @@ -15,7 +15,10 @@ namespace TAO_PEGTL_NAMESPACE::internal typename... States > void missing_apply0( ParseInput& in, States&&... st ) { + // This function only exists for better error messages, which means that it is only called when we know that it won't compile. + // LCOV_EXCL_START (void)Control::template apply0< Action >( in, st... ); + // LCOV_EXCL_STOP } } // namespace TAO_PEGTL_NAMESPACE::internal diff --git a/packages/PEGTL/include/tao/pegtl/internal/path_to_string.hpp b/packages/PEGTL/include/tao/pegtl/internal/path_to_string.hpp new file mode 100644 index 0000000000000000000000000000000000000000..04b0774e069b45472b47cce1e4d5d275e19b69ed --- /dev/null +++ b/packages/PEGTL/include/tao/pegtl/internal/path_to_string.hpp @@ -0,0 +1,26 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_PEGTL_INTERNAL_PATH_TO_STRING_HPP +#define TAO_PEGTL_INTERNAL_PATH_TO_STRING_HPP + +#include <filesystem> +#include <string> + +#include "../config.hpp" + +namespace TAO_PEGTL_NAMESPACE::internal +{ + [[nodiscard]] inline std::string path_to_string( const std::filesystem::path& path ) + { +#if defined( __cpp_char8_t ) + const auto s = path.u8string(); + return { reinterpret_cast< const char* >( s.data() ), s.size() }; +#else + return path.u8string(); +#endif + } + +} // namespace TAO_PEGTL_NAMESPACE::internal + +#endif diff --git a/packages/PEGTL/include/tao/pegtl/internal/rules.hpp b/packages/PEGTL/include/tao/pegtl/internal/rules.hpp index 2e9554a70ff1b1818043035f29e944f695ddcb6d..de13adfbe8ff8c967b1d990b62c3ddbf87aa8268 100644 --- a/packages/PEGTL/include/tao/pegtl/internal/rules.hpp +++ b/packages/PEGTL/include/tao/pegtl/internal/rules.hpp @@ -5,8 +5,6 @@ #define TAO_PEGTL_INTERNAL_RULES_HPP #include "action.hpp" -#include "alnum.hpp" -#include "alpha.hpp" #include "any.hpp" #include "apply.hpp" #include "apply0.hpp" diff --git a/packages/PEGTL/include/tao/pegtl/istream_input.hpp b/packages/PEGTL/include/tao/pegtl/istream_input.hpp index d9a967ef91f71a5c9e26b61de282db57bb129b31..68a484000fa372b915646e4d7089c85baa35ffa5 100644 --- a/packages/PEGTL/include/tao/pegtl/istream_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/istream_input.hpp @@ -25,7 +25,7 @@ namespace TAO_PEGTL_NAMESPACE }; template< typename... Ts > - istream_input( Ts&&... )->istream_input<>; + istream_input( Ts&&... ) -> istream_input<>; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/match.hpp b/packages/PEGTL/include/tao/pegtl/match.hpp index 77f596b94c23954b5eb294bfe103686d0aae3434..6bb87565b83dbe01472890412e2861cc0af31bce 100644 --- a/packages/PEGTL/include/tao/pegtl/match.hpp +++ b/packages/PEGTL/include/tao/pegtl/match.hpp @@ -13,15 +13,79 @@ #include "require_apply0.hpp" #include "rewind_mode.hpp" -#include "internal/dusel_mode.hpp" -#include "internal/duseltronik.hpp" #include "internal/has_apply.hpp" #include "internal/has_apply0.hpp" +#include "internal/has_unwind.hpp" +#include "internal/marker.hpp" #include "internal/missing_apply.hpp" #include "internal/missing_apply0.hpp" +#if defined( _MSC_VER ) +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + namespace TAO_PEGTL_NAMESPACE { + namespace internal + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename ParseInput, + typename... States > + [[nodiscard]] static auto match_no_control( ParseInput& in, States&&... st ) + -> decltype( Rule::template match< A, M, Action, Control >( in, st... ) ) + { + return Rule::template match< A, M, Action, Control >( in, st... ); + } + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename ParseInput, + typename... States > + [[nodiscard]] static auto match_no_control( ParseInput& in, States&&... /*unused*/ ) + -> decltype( Rule::match( in ) ) + { + return Rule::match( in ); + } + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename ParseInput, + typename... States > + [[nodiscard]] auto match_control_unwind( ParseInput& in, States&&... st ) + { + if constexpr( has_unwind< Control< Rule >, void, const ParseInput&, States... > ) { + try { + return match_no_control< Rule, A, M, Action, Control >( in, st... ); + } + catch( ... ) { + Control< Rule >::unwind( static_cast< const ParseInput& >( in ), st... ); + throw; + } + } + else { + return match_no_control< Rule, A, M, Action, Control >( in, st... ); + } + } + + } // namespace internal + template< typename Rule, apply_mode A, rewind_mode M, @@ -31,42 +95,75 @@ namespace TAO_PEGTL_NAMESPACE class Control, typename ParseInput, typename... States > - [[nodiscard]] bool match( ParseInput& in, States&&... st ) + [[nodiscard]] auto match( ParseInput& in, States&&... st ) { - constexpr bool enable_control = Control< Rule >::enable; - constexpr bool enable_action = enable_control && ( A == apply_mode::action ); + if constexpr( !Control< Rule >::enable ) { + return internal::match_no_control< Rule, A, M, Action, Control >( in, st... ); + } + else { + constexpr bool enable_action = ( A == apply_mode::action ); - using iterator_t = typename ParseInput::iterator_t; - constexpr bool has_apply_void = enable_action && internal::has_apply< Control< Rule >, void, Action, const iterator_t&, const ParseInput&, States... >; - constexpr bool has_apply_bool = enable_action && internal::has_apply< Control< Rule >, bool, Action, const iterator_t&, const ParseInput&, States... >; - constexpr bool has_apply = has_apply_void || has_apply_bool; + using iterator_t = typename ParseInput::iterator_t; + constexpr bool has_apply_void = enable_action && internal::has_apply< Control< Rule >, void, Action, const iterator_t&, const ParseInput&, States... >; + constexpr bool has_apply_bool = enable_action && internal::has_apply< Control< Rule >, bool, Action, const iterator_t&, const ParseInput&, States... >; + constexpr bool has_apply = has_apply_void || has_apply_bool; - constexpr bool has_apply0_void = enable_action && internal::has_apply0< Control< Rule >, void, Action, const ParseInput&, States... >; - constexpr bool has_apply0_bool = enable_action && internal::has_apply0< Control< Rule >, bool, Action, const ParseInput&, States... >; - constexpr bool has_apply0 = has_apply0_void || has_apply0_bool; + constexpr bool has_apply0_void = enable_action && internal::has_apply0< Control< Rule >, void, Action, const ParseInput&, States... >; + constexpr bool has_apply0_bool = enable_action && internal::has_apply0< Control< Rule >, bool, Action, const ParseInput&, States... >; + constexpr bool has_apply0 = has_apply0_void || has_apply0_bool; - static_assert( !( has_apply && has_apply0 ), "both apply() and apply0() defined" ); + static_assert( !( has_apply && has_apply0 ), "both apply() and apply0() defined" ); - constexpr bool is_nothing = std::is_base_of_v< nothing< Rule >, Action< Rule > >; - static_assert( !( has_apply && is_nothing ), "unexpected apply() defined" ); - static_assert( !( has_apply0 && is_nothing ), "unexpected apply0() defined" ); + constexpr bool is_nothing = std::is_base_of_v< nothing< Rule >, Action< Rule > >; + static_assert( !( has_apply && is_nothing ), "unexpected apply() defined" ); + static_assert( !( has_apply0 && is_nothing ), "unexpected apply0() defined" ); - if constexpr( !has_apply && std::is_base_of_v< require_apply, Action< Rule > > ) { - internal::missing_apply< Control< Rule >, Action >( in, st... ); - } + if constexpr( !has_apply && std::is_base_of_v< require_apply, Action< Rule > > ) { + internal::missing_apply< Control< Rule >, Action >( in, st... ); + } - if constexpr( !has_apply0 && std::is_base_of_v< require_apply0, Action< Rule > > ) { - internal::missing_apply0< Control< Rule >, Action >( in, st... ); - } + if constexpr( !has_apply0 && std::is_base_of_v< require_apply0, Action< Rule > > ) { + internal::missing_apply0< Control< Rule >, Action >( in, st... ); + } - constexpr bool validate_nothing = std::is_base_of_v< maybe_nothing, Action< void > >; - constexpr bool is_maybe_nothing = std::is_base_of_v< maybe_nothing, Action< Rule > >; - static_assert( !enable_action || !validate_nothing || is_nothing || is_maybe_nothing || has_apply || has_apply0, "either apply() or apply0() must be defined" ); + constexpr bool validate_nothing = std::is_base_of_v< maybe_nothing, Action< void > >; + constexpr bool is_maybe_nothing = std::is_base_of_v< maybe_nothing, Action< Rule > >; + static_assert( !enable_action || !validate_nothing || is_nothing || is_maybe_nothing || has_apply || has_apply0, "either apply() or apply0() must be defined" ); - constexpr auto mode = static_cast< internal::dusel_mode >( enable_control + has_apply_void + 2 * has_apply_bool + 3 * has_apply0_void + 4 * has_apply0_bool ); - return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... ); + constexpr bool use_marker = has_apply || has_apply0_bool; + + auto m = in.template mark< ( use_marker ? rewind_mode::required : rewind_mode::dontcare ) >(); + Control< Rule >::start( static_cast< const ParseInput& >( in ), st... ); + auto result = internal::match_control_unwind< Rule, A, ( use_marker ? rewind_mode::active : M ), Action, Control >( in, st... ); + if( result ) { + if constexpr( has_apply_void ) { + Control< Rule >::template apply< Action >( m.iterator(), static_cast< const ParseInput& >( in ), st... ); + } + else if constexpr( has_apply_bool ) { + result = Control< Rule >::template apply< Action >( m.iterator(), static_cast< const ParseInput& >( in ), st... ); + } + else if constexpr( has_apply0_void ) { + Control< Rule >::template apply0< Action >( static_cast< const ParseInput& >( in ), st... ); + } + else if constexpr( has_apply0_bool ) { + result = Control< Rule >::template apply0< Action >( static_cast< const ParseInput& >( in ), st... ); + } + } + if( result ) { + Control< Rule >::success( static_cast< const ParseInput& >( in ), st... ); + } + else { + Control< Rule >::failure( static_cast< const ParseInput& >( in ), st... ); + } + (void)m( result ); + return result; + } } } // namespace TAO_PEGTL_NAMESPACE +#if defined( _MSC_VER ) +#pragma warning( pop ) +#endif + #endif diff --git a/packages/PEGTL/include/tao/pegtl/memory_input.hpp b/packages/PEGTL/include/tao/pegtl/memory_input.hpp index 6c4c8c9a5f21944bbe74b36361126b413d8d93ba..6f303f57c002f8dc936c6ca9ec2066c338579bf4 100644 --- a/packages/PEGTL/include/tao/pegtl/memory_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/memory_input.hpp @@ -4,6 +4,7 @@ #ifndef TAO_PEGTL_MEMORY_INPUT_HPP #define TAO_PEGTL_MEMORY_INPUT_HPP +#include <cassert> #include <cstddef> #include <cstdint> #include <cstring> @@ -89,9 +90,9 @@ namespace TAO_PEGTL_NAMESPACE return m_current.line; } - [[nodiscard]] std::size_t byte_in_line() const noexcept + [[nodiscard]] std::size_t column() const noexcept { - return m_current.byte_in_line; + return m_current.column; } void bump( const std::size_t in_count = 1 ) noexcept @@ -114,12 +115,15 @@ namespace TAO_PEGTL_NAMESPACE return TAO_PEGTL_NAMESPACE::position( it, m_source ); } - void restart( const std::size_t in_byte = 0, const std::size_t in_line = 1, const std::size_t in_byte_in_line = 0 ) + void restart( const std::size_t in_byte = 0, const std::size_t in_line = 1, const std::size_t in_column = 1 ) { + assert( in_line != 0 ); + assert( in_column != 0 ); + m_current.data = m_begin; m_current.byte = in_byte; m_current.line = in_line; - m_current.byte_in_line = in_byte_in_line; + m_current.column = in_column; } protected: @@ -255,8 +259,8 @@ namespace TAO_PEGTL_NAMESPACE {} template< typename T > - memory_input( const char* in_begin, const char* in_end, T&& in_source, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : memory_input( { in_begin, in_byte, in_line, in_byte_in_line }, in_end, std::forward< T >( in_source ) ) + memory_input( const char* in_begin, const char* in_end, T&& in_source, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_column ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : memory_input( { in_begin, in_byte, in_line, in_column }, in_end, std::forward< T >( in_source ) ) {} memory_input( const memory_input& ) = delete; @@ -334,7 +338,7 @@ namespace TAO_PEGTL_NAMESPACE [[nodiscard]] const char* begin_of_line( const TAO_PEGTL_NAMESPACE::position& p ) const noexcept { - return at( p ) - p.byte_in_line; + return at( p ) - ( p.column - 1 ); } [[nodiscard]] const char* end_of_line( const TAO_PEGTL_NAMESPACE::position& p ) const noexcept @@ -354,7 +358,7 @@ namespace TAO_PEGTL_NAMESPACE }; template< typename... Ts > - memory_input( Ts&&... )->memory_input<>; + memory_input( Ts&&... ) -> memory_input<>; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/mmap_input.hpp b/packages/PEGTL/include/tao/pegtl/mmap_input.hpp index 82206dee5ce1e351acd426dcf9a1836b2d511266..acc24bbca28508ba862aa17501dd060cb59bc57e 100644 --- a/packages/PEGTL/include/tao/pegtl/mmap_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/mmap_input.hpp @@ -4,14 +4,16 @@ #ifndef TAO_PEGTL_MMAP_INPUT_HPP #define TAO_PEGTL_MMAP_INPUT_HPP +#include <filesystem> #include <string> -#include <utility> #include "config.hpp" #include "eol.hpp" #include "memory_input.hpp" #include "tracking_mode.hpp" +#include "internal/path_to_string.hpp" + #if defined( __unix__ ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) #include <unistd.h> // Required for _POSIX_MAPPED_FILES #endif @@ -29,13 +31,10 @@ namespace TAO_PEGTL_NAMESPACE { struct mmap_holder { - const std::string filename; const file_mapper data; - template< typename T > - explicit mmap_holder( T&& in_filename ) - : filename( std::forward< T >( in_filename ) ), - data( filename.c_str() ) + explicit mmap_holder( const std::filesystem::path& path ) + : data( path ) {} mmap_holder( const mmap_holder& ) = delete; @@ -52,12 +51,15 @@ namespace TAO_PEGTL_NAMESPACE template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > struct mmap_input : private internal::mmap_holder, - public memory_input< P, Eol, const char* > + public memory_input< P, Eol > { - template< typename T > - explicit mmap_input( T&& in_filename ) - : internal::mmap_holder( std::forward< T >( in_filename ) ), - memory_input< P, Eol, const char* >( data.begin(), data.end(), filename.c_str() ) + mmap_input( const std::filesystem::path& path, const std::string& source ) + : internal::mmap_holder( path ), + memory_input< P, Eol >( data.begin(), data.end(), source ) + {} + + explicit mmap_input( const std::filesystem::path& path ) + : mmap_input( path, internal::path_to_string( path ) ) {} mmap_input( const mmap_input& ) = delete; @@ -70,7 +72,7 @@ namespace TAO_PEGTL_NAMESPACE }; template< typename... Ts > - explicit mmap_input( Ts&&... )->mmap_input<>; + explicit mmap_input( Ts&&... ) -> mmap_input<>; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/must_if.hpp b/packages/PEGTL/include/tao/pegtl/must_if.hpp index ab15cb6b6c71fbd0f287b3e5edda55c9ded4313e..d229ae5711fc221a8e554f1129d595ab5519bca7 100644 --- a/packages/PEGTL/include/tao/pegtl/must_if.hpp +++ b/packages/PEGTL/include/tao/pegtl/must_if.hpp @@ -4,6 +4,8 @@ #ifndef TAO_PEGTL_MUST_IF_HPP #define TAO_PEGTL_MUST_IF_HPP +#include <type_traits> + #include "config.hpp" #include "normal.hpp" @@ -11,15 +13,15 @@ namespace TAO_PEGTL_NAMESPACE { namespace internal { - template< typename T, typename Rule, typename = void > - inline constexpr bool raise_on_failure = ( T::template message< Rule > != nullptr ); + template< typename Errors, typename Rule, typename = void > + inline constexpr bool raise_on_failure = ( Errors::template message< Rule > != nullptr ); - template< typename T, typename Rule > - inline constexpr bool raise_on_failure< T, Rule, decltype( T::template raise_on_failure< Rule >, void() ) > = T::template raise_on_failure< Rule >; + template< typename Errors, typename Rule > + inline constexpr bool raise_on_failure< Errors, Rule, std::void_t< decltype( Errors::template raise_on_failure< Rule > ) > > = Errors::template raise_on_failure< Rule >; } // namespace internal - template< typename T, template< typename... > class Base = normal, bool RequireMessage = true > + template< typename Errors, template< typename... > class Base = normal, bool RequireMessage = true > struct must_if { template< typename Rule > @@ -27,9 +29,9 @@ namespace TAO_PEGTL_NAMESPACE : Base< Rule > { template< typename ParseInput, typename... States > - static void failure( const ParseInput& in, States&&... st ) noexcept( !internal::raise_on_failure< T, Rule > && noexcept( Base< Rule >::failure( in, st... ) ) ) + static void failure( const ParseInput& in, States&&... st ) noexcept( noexcept( Base< Rule >::failure( in, st... ) ) && !internal::raise_on_failure< Errors, Rule > ) { - if constexpr( internal::raise_on_failure< T, Rule > ) { + if constexpr( internal::raise_on_failure< Errors, Rule > ) { raise( in, st... ); } else { @@ -38,16 +40,16 @@ namespace TAO_PEGTL_NAMESPACE } template< typename ParseInput, typename... States > - [[noreturn]] static void raise( const ParseInput& in, States&&... st ) + [[noreturn]] static void raise( const ParseInput& in, [[maybe_unused]] States&&... st ) { if constexpr( RequireMessage ) { - static_assert( T::template message< Rule > != nullptr ); + static_assert( Errors::template message< Rule > != nullptr ); } - if constexpr( T::template message< Rule > != nullptr ) { - constexpr const char* p = T::template message< Rule >; + if constexpr( Errors::template message< Rule > != nullptr ) { + constexpr const char* p = Errors::template message< Rule >; throw parse_error( p, in ); #if defined( _MSC_VER ) - (void)( (void)st, ... ); + ( (void)st, ... ); #endif } else { diff --git a/packages/PEGTL/include/tao/pegtl/normal.hpp b/packages/PEGTL/include/tao/pegtl/normal.hpp index 5d7845b99433dd041d51ef05b1740d392f12dab7..dcb9e4d9430137ba2c5f9822d21e9ac8ae8a999a 100644 --- a/packages/PEGTL/include/tao/pegtl/normal.hpp +++ b/packages/PEGTL/include/tao/pegtl/normal.hpp @@ -10,11 +10,11 @@ #include "apply_mode.hpp" #include "config.hpp" +#include "demangle.hpp" #include "match.hpp" #include "parse_error.hpp" #include "rewind_mode.hpp" -#include "internal/demangle.hpp" #include "internal/enable_control.hpp" #include "internal/has_match.hpp" @@ -40,7 +40,7 @@ namespace TAO_PEGTL_NAMESPACE template< typename ParseInput, typename... States > [[noreturn]] static void raise( const ParseInput& in, States&&... /*unused*/ ) { - throw parse_error( "parse error matching " + std::string( internal::demangle< Rule >() ), in ); + throw parse_error( "parse error matching " + std::string( demangle< Rule >() ), in ); } template< template< typename... > class Action, diff --git a/packages/PEGTL/include/tao/pegtl/parse.hpp b/packages/PEGTL/include/tao/pegtl/parse.hpp index 7d435708a06209082cca146350cd993c218acf70..02528a032f5eab1c3a85911c1dea0a622e907e46 100644 --- a/packages/PEGTL/include/tao/pegtl/parse.hpp +++ b/packages/PEGTL/include/tao/pegtl/parse.hpp @@ -22,7 +22,7 @@ namespace TAO_PEGTL_NAMESPACE rewind_mode M = rewind_mode::required, typename ParseInput, typename... States > - bool parse( ParseInput&& in, States&&... st ) + auto parse( ParseInput&& in, States&&... st ) { return Control< Rule >::template match< A, M, Action, Control >( in, st... ); } @@ -35,13 +35,13 @@ namespace TAO_PEGTL_NAMESPACE typename OuterInput, typename ParseInput, typename... States > - bool parse_nested( const OuterInput& oi, ParseInput&& in, States&&... st ) + auto parse_nested( const OuterInput& oi, ParseInput&& in, States&&... st ) { try { return parse< Rule, Action, Control, A, M >( in, st... ); } catch( parse_error& e ) { - e.positions.push_back( oi.position() ); + e.add_position( oi.position() ); throw; } } diff --git a/packages/PEGTL/include/tao/pegtl/parse_error.hpp b/packages/PEGTL/include/tao/pegtl/parse_error.hpp index d48f95b830048929c62fbaba1348be9be915b721..b2f8741ff7ded4dc6343ec68276761eaee830947 100644 --- a/packages/PEGTL/include/tao/pegtl/parse_error.hpp +++ b/packages/PEGTL/include/tao/pegtl/parse_error.hpp @@ -4,10 +4,11 @@ #ifndef TAO_PEGTL_PARSE_ERROR_HPP #define TAO_PEGTL_PARSE_ERROR_HPP -#include <ostream> -#include <sstream> +#include <cstddef> +#include <memory> #include <stdexcept> #include <string> +#include <string_view> #include <utility> #include <vector> @@ -16,50 +17,97 @@ namespace TAO_PEGTL_NAMESPACE { - struct parse_error - : std::runtime_error + namespace internal { - template< typename Msg > - parse_error( Msg&& msg, std::vector< position > in_positions ) - : std::runtime_error( std::forward< Msg >( msg ) ), - positions( std::move( in_positions ) ) - {} + class parse_error + { + private: + std::string m_msg; + std::size_t m_prefix = 0; + std::vector< position > m_positions; - template< typename Msg > - parse_error( Msg&& msg, const position& pos ) - : std::runtime_error( std::forward< Msg >( msg ) ), - positions( 1, pos ) - {} + public: + explicit parse_error( const char* msg ) + : m_msg( msg ) + {} + + [[nodiscard]] const char* what() const noexcept + { + return m_msg.c_str(); + } + + [[nodiscard]] std::string_view message() const noexcept + { + return { m_msg.data() + m_prefix, m_msg.size() - m_prefix }; + } + + [[nodiscard]] const std::vector< position >& positions() const noexcept + { + return m_positions; + } + + void add_position( position&& p ) + { + const auto prefix = to_string( p ); + m_msg = prefix + ": " + m_msg; + m_prefix += prefix.size() + 2; + m_positions.emplace_back( std::move( p ) ); + } + }; - template< typename Msg > - parse_error( Msg&& msg, position&& pos ) - : std::runtime_error( std::forward< Msg >( msg ) ) + } // namespace internal + + class parse_error + : public std::runtime_error + { + private: + std::shared_ptr< internal::parse_error > m_impl; + + public: + parse_error( const char* msg, position p ) + : std::runtime_error( msg ), + m_impl( std::make_shared< internal::parse_error >( msg ) ) { - positions.emplace_back( std::move( pos ) ); + m_impl->add_position( std::move( p ) ); } - template< typename Msg, typename ParseInput > - parse_error( Msg&& msg, const ParseInput& in ) - : parse_error( std::forward< Msg >( msg ), in.position() ) + parse_error( const std::string& msg, position p ) + : parse_error( msg.c_str(), std::move( p ) ) {} - std::vector< position > positions; - }; + template< typename ParseInput > + parse_error( const char* msg, const ParseInput& in ) + : parse_error( msg, in.position() ) + {} - inline std::ostream& operator<<( std::ostream& o, const parse_error& e ) - { - for( auto it = e.positions.rbegin(); it != e.positions.rend(); ++it ) { - o << *it << ": "; + template< typename ParseInput > + parse_error( const std::string& msg, const ParseInput& in ) + : parse_error( msg.c_str(), in.position() ) + {} + + [[nodiscard]] const char* what() const noexcept override + { + return m_impl->what(); } - return o << e.what(); - } - [[nodiscard]] inline std::string to_string( const parse_error& e ) - { - std::ostringstream o; - o << e; - return o.str(); - } + [[nodiscard]] std::string_view message() const noexcept + { + return m_impl->message(); + } + + [[nodiscard]] const std::vector< position >& positions() const noexcept + { + return m_impl->positions(); + } + + void add_position( position&& p ) + { + if( m_impl.use_count() > 1 ) { + m_impl = std::make_shared< internal::parse_error >( *m_impl ); + } + m_impl->add_position( std::move( p ) ); + } + }; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/position.hpp b/packages/PEGTL/include/tao/pegtl/position.hpp index 6cdc07bd02077901d81769ab60ff3f573b187190..7543fdb0ecbee4471381d9640bd0dadc35bd0369 100644 --- a/packages/PEGTL/include/tao/pegtl/position.hpp +++ b/packages/PEGTL/include/tao/pegtl/position.hpp @@ -23,7 +23,7 @@ namespace TAO_PEGTL_NAMESPACE position( position&& p ) noexcept : byte( p.byte ), line( p.line ), - byte_in_line( p.byte_in_line ), + column( p.column ), source( std::move( p.source ) ) {} @@ -33,7 +33,7 @@ namespace TAO_PEGTL_NAMESPACE { byte = p.byte; line = p.line; - byte_in_line = p.byte_in_line; + column = p.column; source = std::move( p.source ); return *this; } @@ -44,7 +44,7 @@ namespace TAO_PEGTL_NAMESPACE position( const internal::iterator& in_iter, T&& in_source ) : byte( in_iter.byte ), line( in_iter.line ), - byte_in_line( in_iter.byte_in_line ), + column( in_iter.column ), source( std::forward< T >( in_source ) ) {} @@ -52,13 +52,23 @@ namespace TAO_PEGTL_NAMESPACE std::size_t byte; std::size_t line; - std::size_t byte_in_line; + std::size_t column; std::string source; }; - inline std::ostream& operator<<( std::ostream& o, const position& p ) + inline bool operator==( const position& lhs, const position& rhs ) noexcept { - return o << p.source << ':' << p.line << ':' << p.byte_in_line << '(' << p.byte << ')'; + return ( lhs.byte == rhs.byte ) && ( lhs.source == rhs.source ); + } + + inline bool operator!=( const position& lhs, const position& rhs ) noexcept + { + return !( lhs == rhs ); + } + + inline std::ostream& operator<<( std::ostream& os, const position& p ) + { + return os << p.source << ':' << p.line << ':' << p.column; } [[nodiscard]] inline std::string to_string( const position& p ) diff --git a/packages/PEGTL/include/tao/pegtl/read_input.hpp b/packages/PEGTL/include/tao/pegtl/read_input.hpp index 224b2e9a75874cbac59aff00dbe95b950b29d241..f830de3b90bad0e4f56fcf966da7933ba3206520 100644 --- a/packages/PEGTL/include/tao/pegtl/read_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/read_input.hpp @@ -4,6 +4,7 @@ #ifndef TAO_PEGTL_READ_INPUT_HPP #define TAO_PEGTL_READ_INPUT_HPP +#include <filesystem> #include <string> #include "config.hpp" @@ -12,46 +13,28 @@ #include "tracking_mode.hpp" #include "internal/file_reader.hpp" +#include "internal/path_to_string.hpp" namespace TAO_PEGTL_NAMESPACE { - namespace internal - { - struct filename_holder - { - const std::string filename; - - template< typename T > - explicit filename_holder( T&& in_filename ) - : filename( std::forward< T >( in_filename ) ) - {} - - filename_holder( const filename_holder& ) = delete; - filename_holder( filename_holder&& ) = delete; - - ~filename_holder() = default; - - void operator=( const filename_holder& ) = delete; - void operator=( filename_holder&& ) = delete; - }; - - } // namespace internal - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > struct read_input - : private internal::filename_holder, - public string_input< P, Eol, const char* > + : string_input< P, Eol > { - template< typename T > - explicit read_input( T&& in_filename ) - : internal::filename_holder( std::forward< T >( in_filename ) ), - string_input< P, Eol, const char* >( internal::file_reader( filename.c_str() ).read(), filename.c_str() ) + read_input( const std::filesystem::path& path, const std::string& source ) + : string_input< P, Eol >( internal::file_reader( path ).read(), source ) + {} + + explicit read_input( const std::filesystem::path& path ) + : read_input( path, internal::path_to_string( path ) ) + {} + + read_input( FILE* file, const std::filesystem::path& path, const std::string& source ) + : string_input< P, Eol >( internal::file_reader( file, path ).read(), source ) {} - template< typename T > - read_input( FILE* in_file, T&& in_filename ) - : internal::filename_holder( std::forward< T >( in_filename ) ), - string_input< P, Eol, const char* >( internal::file_reader( in_file, filename.c_str() ).read(), filename.c_str() ) + read_input( FILE* file, const std::filesystem::path& path ) + : read_input( file, path, internal::path_to_string( path ) ) {} read_input( const read_input& ) = delete; @@ -64,7 +47,7 @@ namespace TAO_PEGTL_NAMESPACE }; template< typename... Ts > - explicit read_input( Ts&&... )->read_input<>; + explicit read_input( Ts&&... ) -> read_input<>; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/include/tao/pegtl/rules.hpp b/packages/PEGTL/include/tao/pegtl/rules.hpp index 659619c0eda2725b8bf3d6d67ae1fb912ba17249..09f7ad5d188c881fc8ea08e020cc8b8d2cd98d6b 100644 --- a/packages/PEGTL/include/tao/pegtl/rules.hpp +++ b/packages/PEGTL/include/tao/pegtl/rules.hpp @@ -12,9 +12,9 @@ namespace TAO_PEGTL_NAMESPACE { // clang-format off + template< template< typename... > class Action, typename... Rules > struct action : internal::action< Action, Rules... > {}; template< typename... Actions > struct apply : internal::apply< Actions... > {}; template< typename... Actions > struct apply0 : internal::apply0< Actions... > {}; - template< template< typename... > class Action, typename... Rules > struct action : internal::action< Action, Rules... > {}; template< typename... Rules > struct at : internal::at< Rules... > {}; struct bof : internal::bof {}; struct bol : internal::bol {}; @@ -58,7 +58,7 @@ namespace TAO_PEGTL_NAMESPACE template< typename Cond, typename... Rules > struct star_must : internal::star_must< Cond, Rules... > {}; template< typename State, typename... Rules > struct state : internal::state< State, Rules... > {}; struct success : internal::success {}; - template< typename... Rules > struct try_catch : internal::seq< internal::try_catch_type< parse_error, Rules... > > {}; + template< typename... Rules > struct try_catch : internal::try_catch_type< parse_error, Rules... > {}; template< typename Exception, typename... Rules > struct try_catch_type : internal::seq< internal::try_catch_type< Exception, Rules... > > {}; template< typename Cond, typename... Rules > struct until : internal::until< Cond, Rules... > {}; // clang-format on diff --git a/packages/PEGTL/include/tao/pegtl/string_input.hpp b/packages/PEGTL/include/tao/pegtl/string_input.hpp index 06fec70d670f3554e5f3f167d33416048b81ef41..8bacffbc4d1daffb98a69193a6330aae57b580e4 100644 --- a/packages/PEGTL/include/tao/pegtl/string_input.hpp +++ b/packages/PEGTL/include/tao/pegtl/string_input.hpp @@ -57,7 +57,7 @@ namespace TAO_PEGTL_NAMESPACE }; template< typename... Ts > - explicit string_input( Ts&&... )->string_input<>; + explicit string_input( Ts&&... ) -> string_input<>; } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/example/pegtl/CMakeLists.txt b/packages/PEGTL/src/example/pegtl/CMakeLists.txt index 60518785710ccf34241b761ef4dfef3d6d6c4a52..0cbdd6288262e34785bd5aef39dff669aeb7d8e2 100644 --- a/packages/PEGTL/src/example/pegtl/CMakeLists.txt +++ b/packages/PEGTL/src/example/pegtl/CMakeLists.txt @@ -10,13 +10,19 @@ set(example_sources dynamic_match.cpp hello_world.cpp indent_aware.cpp + json_analyze.cpp + json_ast.cpp json_build.cpp json_count.cpp json_coverage.cpp json_parse.cpp - json_print_rules.cpp - json_print_sub_rules.cpp + json_print_debug.cpp + json_print_names.cpp + json_trace.cpp + lua53_analyze.cpp lua53_parse.cpp + lua53_print_debug.cpp + lua53_print_names.cpp modulus_match.cpp parse_tree.cpp parse_tree_user_state.cpp @@ -27,6 +33,8 @@ set(example_sources symbol_table.cpp unescape.cpp uri.cpp + uri_print_debug.cpp + uri_print_names.cpp uri_trace.cpp ) diff --git a/packages/PEGTL/src/example/pegtl/abnf2pegtl.cpp b/packages/PEGTL/src/example/pegtl/abnf2pegtl.cpp index 5af83c55112402a143afa902ce883e6b5bf2ce49..b019047c937ae57c44cfa5fbb2599f26cbbfd8bb 100644 --- a/packages/PEGTL/src/example/pegtl/abnf2pegtl.cpp +++ b/packages/PEGTL/src/example/pegtl/abnf2pegtl.cpp @@ -2,6 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include <algorithm> +#include <iomanip> #include <iostream> #include <iterator> #include <map> @@ -25,7 +26,6 @@ #include <tao/pegtl.hpp> #include <tao/pegtl/contrib/abnf.hpp> -#include <tao/pegtl/contrib/analyze.hpp> #include <tao/pegtl/contrib/parse_tree.hpp> namespace TAO_PEGTL_NAMESPACE @@ -145,7 +145,7 @@ namespace TAO_PEGTL_NAMESPACE rules_t::reverse_iterator find_rule( rules_t& r, const std::string& v, const rules_t::reverse_iterator& rbegin ) { - return std::find_if( rbegin, r.rend(), [&]( const rules_t::value_type& p ) { return TAO_PEGTL_STRCASECMP( p.c_str(), v.c_str() ) == 0; } ); + return std::find_if( rbegin, r.rend(), [ & ]( const rules_t::value_type& p ) { return TAO_PEGTL_STRCASECMP( p.c_str(), v.c_str() ) == 0; } ); } rules_t::reverse_iterator find_rule( rules_t& r, const std::string& v ) @@ -180,7 +180,7 @@ namespace TAO_PEGTL_NAMESPACE { it.data += delta; it.byte += delta; - it.byte_in_line += delta; + it.column += delta; } } // namespace @@ -535,7 +535,7 @@ namespace TAO_PEGTL_NAMESPACE template< typename T > void add( const function_t& f ) { - map_.try_emplace( internal::demangle< T >(), f ); + map_.try_emplace( demangle< T >(), f ); } std::string operator()( const node_ptr& n ) const @@ -717,14 +717,10 @@ int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) using namespace TAO_PEGTL_NAMESPACE; if( argc != 2 ) { - std::cerr << "Usage: " << argv[ 0 ] << " SOURCE" << std::endl; + std::cerr << "Usage: " << argv[ 0 ] << " SOURCE\n"; return 1; } - if( analyze< abnf::grammar::rulelist >() != 0 ) { - return 2; - } - file_input in( argv[ 1 ] ); try { const auto root = parse_tree::parse< abnf::grammar::rulelist, abnf::selector, nothing, abnf::control >( in ); @@ -734,14 +730,14 @@ int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) } for( const auto& rule : root->children ) { - std::cout << abnf::to_string( rule ) << std::endl; + std::cout << abnf::to_string( rule ) << '\n'; } } catch( const parse_error& e ) { - const auto p = e.positions.front(); - std::cerr << e.what() << std::endl - << in.line_at( p ) << std::endl - << std::string( p.byte_in_line, ' ' ) << '^' << std::endl; + const auto p = e.positions().front(); + std::cerr << e.what() << '\n' + << in.line_at( p ) << '\n' + << std::setw( p.column ) << '^' << '\n'; } return 0; diff --git a/packages/PEGTL/src/example/pegtl/dynamic_match.cpp b/packages/PEGTL/src/example/pegtl/dynamic_match.cpp index da9f2dc24623dc5ce150b1847d1347c994aecc1f..1f35ee9ec3d15e86bc80f6de9faa3eb8443355c7 100644 --- a/packages/PEGTL/src/example/pegtl/dynamic_match.cpp +++ b/packages/PEGTL/src/example/pegtl/dynamic_match.cpp @@ -96,8 +96,10 @@ namespace TAO_PEGTL_NAMESPACE int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) { - const auto issues = pegtl::analyze< dynamic::grammar >(); - assert( !issues ); + if( pegtl::analyze< dynamic::grammar >() != 0 ) { + std::cerr << "cycles without progress detected!" << std::endl; + return 1; + } if( argc > 1 ) { std::string id; diff --git a/packages/PEGTL/src/example/pegtl/json_analyze.cpp b/packages/PEGTL/src/example/pegtl/json_analyze.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bebef24754afbd5eb1a6c41032ca067c882c347d --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/json_analyze.cpp @@ -0,0 +1,25 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iostream> + +#include <tao/pegtl.hpp> +#include <tao/pegtl/contrib/analyze.hpp> +#include <tao/pegtl/contrib/json.hpp> + +namespace pegtl = TAO_PEGTL_NAMESPACE; + +namespace example +{ + using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; + +} // namespace example + +int main() // NOLINT(bugprone-exception-escape) +{ + if( pegtl::analyze< example::grammar >() != 0 ) { + std::cerr << "cycles without progress detected!" << std::endl; + return 1; + } + return 0; +} diff --git a/packages/PEGTL/src/example/pegtl/json_ast.cpp b/packages/PEGTL/src/example/pegtl/json_ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecc8e57a9fa8244cbaa060d8996026999b3d0297 --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/json_ast.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iomanip> +#include <iostream> + +#include <tao/pegtl.hpp> +#include <tao/pegtl/contrib/json.hpp> +#include <tao/pegtl/contrib/parse_tree.hpp> +#include <tao/pegtl/contrib/parse_tree_to_dot.hpp> + +#include "json_errors.hpp" + +namespace pegtl = TAO_PEGTL_NAMESPACE; + +namespace example +{ + using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; + + template< typename Rule > + using selector = pegtl::parse_tree::selector< + Rule, + pegtl::parse_tree::remove_content::on< + pegtl::json::null, + pegtl::json::true_, + pegtl::json::false_, + pegtl::json::array, + pegtl::json::object, + pegtl::json::member >, + pegtl::parse_tree::store_content::on< + pegtl::json::number, + pegtl::json::string, + pegtl::json::key > >; + +} // namespace example + +int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) +{ + if( argc != 2 ) { + std::cerr << "Usage: " << argv[ 0 ] << " JSON\n" + << "Generate a 'dot' file from the JSON text.\n\n" + << "Example: " << argv[ 0 ] << " \"{\"foo\":[42,null]}\" | dot -Tpng -o parse_tree.png\n"; + return 1; + } + + pegtl::argv_input in( argv, 1 ); + try { + const auto root = pegtl::parse_tree::parse< example::grammar, example::selector, pegtl::nothing, example::control >( in ); + pegtl::parse_tree::print_dot( std::cout, *root ); + } + catch( const pegtl::parse_error& e ) { + const auto p = e.positions().front(); + std::cerr << e.what() << std::endl + << in.line_at( p ) << std::endl + << std::setw( p.column ) << '^' << std::endl; + return 1; + } + + return 0; +} diff --git a/packages/PEGTL/src/example/pegtl/json_build.cpp b/packages/PEGTL/src/example/pegtl/json_build.cpp index f4ec3dc9f61b476969531ea45647a23d609fb7f0..fe8f06f44d1728529c4b34aa9d4aed0f6be572d1 100644 --- a/packages/PEGTL/src/example/pegtl/json_build.cpp +++ b/packages/PEGTL/src/example/pegtl/json_build.cpp @@ -14,7 +14,7 @@ namespace pegtl = TAO_PEGTL_NAMESPACE; -namespace examples +namespace example { // State class that stores the result of a JSON parsing run -- a single JSON object. // The other members are used temporarily, at the end of a (successful) parsing run. @@ -157,7 +157,7 @@ namespace examples using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; -} // namespace examples +} // namespace example int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) { @@ -165,9 +165,9 @@ int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) std::cerr << "usage: " << argv[ 0 ] << " <json>"; } else { - examples::json_state state; + example::json_state state; pegtl::file_input in( argv[ 1 ] ); - pegtl::parse< examples::grammar, examples::action, examples::control >( in, state ); + pegtl::parse< example::grammar, example::action, example::control >( in, state ); assert( state.keys.empty() ); assert( state.arrays.empty() ); assert( state.objects.empty() ); diff --git a/packages/PEGTL/src/example/pegtl/json_classes.hpp b/packages/PEGTL/src/example/pegtl/json_classes.hpp index 8513ec804d8aa2d6913778467bc676bbec8a40a8..9b0c8bb1eb9cf574b80fdd1878e18ff0472eaaaf 100644 --- a/packages/PEGTL/src/example/pegtl/json_classes.hpp +++ b/packages/PEGTL/src/example/pegtl/json_classes.hpp @@ -10,7 +10,7 @@ #include <string> #include <vector> -namespace examples +namespace example { enum class json_type { @@ -209,6 +209,6 @@ namespace examples } }; -} // namespace examples +} // namespace example #endif diff --git a/packages/PEGTL/src/example/pegtl/json_count.cpp b/packages/PEGTL/src/example/pegtl/json_count.cpp index e0fb731afaf1c260f367d49dbc8adcb8b35a80a0..ee4bb71c0b22b8e51dcfd07d74fac05cedb9df1c 100644 --- a/packages/PEGTL/src/example/pegtl/json_count.cpp +++ b/packages/PEGTL/src/example/pegtl/json_count.cpp @@ -32,19 +32,19 @@ namespace TAO_PEGTL_NAMESPACE template< typename Input > static void start( const Input& /*unused*/, counter_state& ts ) { - ++ts.counts[ internal::demangle< Rule >() ].start; + ++ts.counts[ demangle< Rule >() ].start; } template< typename Input > static void success( const Input& /*unused*/, counter_state& ts ) { - ++ts.counts[ internal::demangle< Rule >() ].success; + ++ts.counts[ demangle< Rule >() ].success; } template< typename Input > static void failure( const Input& /*unused*/, counter_state& ts ) { - ++ts.counts[ internal::demangle< Rule >() ].failure; + ++ts.counts[ demangle< Rule >() ].failure; } }; diff --git a/packages/PEGTL/src/example/pegtl/json_coverage.cpp b/packages/PEGTL/src/example/pegtl/json_coverage.cpp index b19c496929c3f5ce0cb3ad07c00599ed1b1b8c60..3d0ff1657d28288f8d8e457efa5db7b7e46bd375 100644 --- a/packages/PEGTL/src/example/pegtl/json_coverage.cpp +++ b/packages/PEGTL/src/example/pegtl/json_coverage.cpp @@ -1,19 +1,45 @@ // Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ +#include <iomanip> #include <iostream> #include <tao/pegtl.hpp> - #include <tao/pegtl/contrib/coverage.hpp> #include <tao/pegtl/contrib/json.hpp> #include <tao/pegtl/contrib/print_coverage.hpp> +#include "json_errors.hpp" + +namespace pegtl = TAO_PEGTL_NAMESPACE; + +namespace example +{ + using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; + +} // namespace example + int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) { - for( int i = 1; i < argc; ++i ) { - auto coverage = tao::pegtl::coverage< tao::pegtl::json::text >( tao::pegtl::file_input( argv[ i ] ) ); - tao::pegtl::print_coverage( std::cout, coverage ); + if( argc != 2 ) { + std::cerr << "Usage: " << argv[ 0 ] << " FILE\n" + << "Print coverage of parsing FILE as JSON." << std::endl; + return 1; + } + + pegtl::file_input in( argv[ 1 ] ); + try { + pegtl::coverage_result result; + pegtl::coverage< example::grammar, pegtl::nothing, example::control >( in, result ); // Ignore return value...? + std::cout << result; } + catch( const pegtl::parse_error& e ) { + const auto p = e.positions().front(); + std::cerr << e.what() << '\n' + << in.line_at( p ) << '\n' + << std::setw( p.column ) << '^' << std::endl; + return 1; + } + return 0; } diff --git a/packages/PEGTL/src/example/pegtl/json_errors.hpp b/packages/PEGTL/src/example/pegtl/json_errors.hpp index 4f674f805188bfd015944c3dcd30f325e4e2a8d7..847ae6fa5e4f534ea1dbda2227224a0b4c66b8ca 100644 --- a/packages/PEGTL/src/example/pegtl/json_errors.hpp +++ b/packages/PEGTL/src/example/pegtl/json_errors.hpp @@ -9,7 +9,7 @@ namespace pegtl = TAO_PEGTL_NAMESPACE; -namespace examples +namespace example { // This file shows how to throw exceptions with // custom error messages for parse errors. @@ -38,12 +38,16 @@ namespace examples template<> inline constexpr auto error_message< pegtl::eof > = "unexpected character after JSON value"; - // As must_if can not take error_message as a template parameter directly, we need to wrap it: - struct error { template< typename Rule > static constexpr auto message = error_message< Rule >; }; + // As must_if<> can not take error_message as a template parameter directly, we need to wrap it. + // Additionally, we make sure only must<>-rules trigger global error. + struct error { + template< typename Rule > static constexpr auto raise_on_failure = false; + template< typename Rule > static constexpr auto message = error_message< Rule >; + }; template< typename Rule > using control = pegtl::must_if< error >::control< Rule >; // clang-format on -} // namespace examples +} // namespace example #endif diff --git a/packages/PEGTL/src/example/pegtl/json_parse.cpp b/packages/PEGTL/src/example/pegtl/json_parse.cpp index 7db715bcc5314983cda4d7808c0bad1f6047e6b5..53cbd81e4b23d45c5bb1233d5afa76e1cbe43e7b 100644 --- a/packages/PEGTL/src/example/pegtl/json_parse.cpp +++ b/packages/PEGTL/src/example/pegtl/json_parse.cpp @@ -1,18 +1,43 @@ // Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ +#include <iomanip> +#include <iostream> + #include <tao/pegtl.hpp> +#include <tao/pegtl/contrib/json.hpp> +#include <tao/pegtl/contrib/trace.hpp> #include "json_errors.hpp" -using namespace TAO_PEGTL_NAMESPACE; -using grammar = must< json::text, eof >; +namespace pegtl = TAO_PEGTL_NAMESPACE; + +namespace example +{ + using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; + +} // namespace example int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) { - for( int i = 1; i < argc; ++i ) { - argv_input in( argv, i ); - parse< grammar, nothing, examples::control >( in ); + if( argc != 2 ) { + std::cerr << "Usage: " << argv[ 0 ] << " JSON\n" + << "Parse a JSON text.\n\n" + << "Example: " << argv[ 0 ] << " '{\"foo\":[42,null]}'" << std::endl; + return 1; } + + pegtl::argv_input in( argv, 1 ); + try { + pegtl::parse< example::grammar, pegtl::nothing, example::control >( in ); + } + catch( const pegtl::parse_error& e ) { + const auto p = e.positions().front(); + std::cerr << e.what() << '\n' + << in.line_at( p ) << '\n' + << std::setw( p.column ) << '^' << std::endl; + return 1; + } + return 0; } diff --git a/packages/PEGTL/src/example/pegtl/json_print_rules.cpp b/packages/PEGTL/src/example/pegtl/json_print_debug.cpp similarity index 82% rename from packages/PEGTL/src/example/pegtl/json_print_rules.cpp rename to packages/PEGTL/src/example/pegtl/json_print_debug.cpp index 87850508fe761c236314a356b174f8d617a54146..9815d2c1e0fb29446e5321e74c2e0488c04d1b92 100644 --- a/packages/PEGTL/src/example/pegtl/json_print_rules.cpp +++ b/packages/PEGTL/src/example/pegtl/json_print_debug.cpp @@ -8,6 +8,6 @@ int main() // NOLINT(bugprone-exception-escape) { - tao::pegtl::print_rules< tao::pegtl::json::text >( std::cout ); + tao::pegtl::print_debug< tao::pegtl::json::text >( std::cout ); return 0; } diff --git a/packages/PEGTL/src/example/pegtl/json_print_sub_rules.cpp b/packages/PEGTL/src/example/pegtl/json_print_names.cpp similarity index 80% rename from packages/PEGTL/src/example/pegtl/json_print_sub_rules.cpp rename to packages/PEGTL/src/example/pegtl/json_print_names.cpp index e28a04ef9fd3cd6ecd1fb0ca211be35401749f71..9f97008cf0469dab69603598de2b670a3bfb0ef5 100644 --- a/packages/PEGTL/src/example/pegtl/json_print_sub_rules.cpp +++ b/packages/PEGTL/src/example/pegtl/json_print_names.cpp @@ -8,6 +8,6 @@ int main() // NOLINT(bugprone-exception-escape) { - tao::pegtl::print_sub_rules< tao::pegtl::json::text >( std::cout ); + tao::pegtl::print_names< tao::pegtl::json::text >( std::cout ); return 0; } diff --git a/packages/PEGTL/src/example/pegtl/json_trace.cpp b/packages/PEGTL/src/example/pegtl/json_trace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5cba1349f8cbe12123a6dc237aff6f392f15ba6a --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/json_trace.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iomanip> +#include <iostream> + +#include <tao/pegtl.hpp> +#include <tao/pegtl/contrib/json.hpp> +#include <tao/pegtl/contrib/trace.hpp> + +#include "json_errors.hpp" + +namespace pegtl = TAO_PEGTL_NAMESPACE; + +namespace example +{ + using grammar = pegtl::must< pegtl::json::text, pegtl::eof >; + +} // namespace example + +int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) +{ + if( argc != 2 ) { + std::cerr << "Usage: " << argv[ 0 ] << " JSON\n" + << "Trace parsing a JSON text.\n\n" + << "Example: " << argv[ 0 ] << " '{\"foo\":[42,null]}'" << std::endl; + return 1; + } + + pegtl::argv_input in( argv, 1 ); + try { + pegtl::standard_trace< example::grammar, pegtl::nothing, example::control >( in ); + } + catch( const pegtl::parse_error& e ) { + const auto p = e.positions().front(); + std::cerr << e.what() << '\n' + << in.line_at( p ) << '\n' + << std::setw( p.column ) << '^' << std::endl; + return 1; + } + + return 0; +} diff --git a/packages/PEGTL/src/example/pegtl/json_unescape.hpp b/packages/PEGTL/src/example/pegtl/json_unescape.hpp index 974c6afb77f46aa04614f8fb629c45fd41b4175d..60e30c7beff0eddadd0077f0acb6171e002203ce 100644 --- a/packages/PEGTL/src/example/pegtl/json_unescape.hpp +++ b/packages/PEGTL/src/example/pegtl/json_unescape.hpp @@ -10,7 +10,7 @@ #include <tao/pegtl/contrib/json.hpp> #include <tao/pegtl/contrib/unescape.hpp> -namespace examples +namespace example { // Action class for parsing literal strings, uses the PEGTL unescape utilities, cf. unescape.cpp. @@ -24,6 +24,6 @@ namespace examples using json_unescape = tao::pegtl::change_action_and_states< json_unescape_action, std::string >; -} // namespace examples +} // namespace example #endif diff --git a/packages/PEGTL/src/example/pegtl/lua53.hpp b/packages/PEGTL/src/example/pegtl/lua53.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5f040509029fb3e8ef40d450032f92dad2af7dff --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/lua53.hpp @@ -0,0 +1,335 @@ +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_PEGTL_SRC_EXAMPLES_PEGTL_LUA53_HPP +#define TAO_PEGTL_SRC_EXAMPLES_PEGTL_LUA53_HPP + +#include <tao/pegtl.hpp> +#include <tao/pegtl/contrib/raw_string.hpp> + +namespace lua53 +{ + // PEGTL grammar for the Lua 5.3.0 lexer and parser. + // + // The grammar here is not very similar to the grammar + // in the Lua reference documentation on which it is based + // which is due to multiple causes. + // + // The main difference is that this grammar includes really + // "everything", not just the structural parts from the + // reference documentation: + // - The PEG-approach combines lexer and parser; this grammar + // handles comments and tokenisation. + // - The operator precedence and associativity are reflected + // in the structure of this grammar. + // - All details for all types of literals are included, with + // escape-sequences for literal strings, and long literals. + // + // The second necessary difference is that all left-recursion + // had to be eliminated. + // + // In some places the grammar was optimised to require as little + // back-tracking as possible, most prominently for expressions. + // The original grammar contains the following production rules: + // + // prefixexp ::= var | functioncall | ‘(’ exp ‘)’ + // functioncall ::= prefixexp args | prefixexp ‘:’ Name args + // var ::= Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name + // + // We need to eliminate the left-recursion, and we also want to + // remove the ambiguity between function calls and variables, + // i.e. the fact that we can have expressions like + // + // ( a * b ).c()[ d ].e:f() + // + // where only the last element decides between function call and + // variable, making it necessary to parse the whole thing again + // if we chose wrong at the beginning. + // First we eliminate prefixexp and obtain: + // + // functioncall ::= ( var | functioncall | ‘(’ exp ‘)’ ) ( args | ‘:’ Name args ) + // var ::= Name | ( var | functioncall | ‘(’ exp ‘)’ ) ( ‘[’ exp ‘]’ | ‘.’ Name ) + // + // Next we split function_call and variable into a first part, + // a "head", or how they can start, and a second part, the "tail", + // which, in a sequence like above, is the final deciding part: + // + // vartail ::= '[' exp ']' | '.' Name + // varhead ::= Name | '(' exp ')' vartail + // functail ::= args | ':' Name args + // funchead ::= Name | '(' exp ')' + // + // This allows us to rewrite var and function_call as follows. + // + // var ::= varhead { { functail } vartail } + // function_call ::= funchead [ { vartail } functail ] + // + // Finally we can define a single expression that takes care + // of var, function_call, and expressions in a bracket: + // + // chead ::= '(' exp ')' | Name + // combined ::= chead { functail | vartail } + // + // Such a combined expression starts with a bracketed + // expression or a name, and continues with an arbitrary + // number of functail and/or vartail parts, all in a one + // grammar rule without back-tracking. + // + // The rule expr_thirteen below implements "combined". + // + // Another issue of interest when writing a PEG is how to + // manage the separators, the white-space and comments that + // can occur in many places; in the classical two-stage + // lexer-parser approach the lexer would have taken care of + // this, but here we use the PEG approach that combines both. + // + // In the following grammar most rules adopt the convention + // that they take care of "internal padding", i.e. spaces + // and comments that can occur within the rule, but not + // "external padding", i.e. they don't start or end with + // a rule that "eats up" all extra padding (spaces and + // comments). In some places, where it is more efficient, + // right padding is used. + + // clang-format off + struct short_comment : tao::pegtl::until< tao::pegtl::eolf > {}; + struct long_string : tao::pegtl::raw_string< '[', '=', ']' > {}; + struct comment : tao::pegtl::disable< tao::pegtl::two< '-' >, tao::pegtl::sor< long_string, short_comment > > {}; + + struct sep : tao::pegtl::sor< tao::pegtl::ascii::space, comment > {}; + struct seps : tao::pegtl::star< sep > {}; + + struct str_and : TAO_PEGTL_STRING( "and" ) {}; + struct str_break : TAO_PEGTL_STRING( "break" ) {}; + struct str_do : TAO_PEGTL_STRING( "do" ) {}; + struct str_else : TAO_PEGTL_STRING( "else" ) {}; + struct str_elseif : TAO_PEGTL_STRING( "elseif" ) {}; + struct str_end : TAO_PEGTL_STRING( "end" ) {}; + struct str_false : TAO_PEGTL_STRING( "false" ) {}; + struct str_for : TAO_PEGTL_STRING( "for" ) {}; + struct str_function : TAO_PEGTL_STRING( "function" ) {}; + struct str_goto : TAO_PEGTL_STRING( "goto" ) {}; + struct str_if : TAO_PEGTL_STRING( "if" ) {}; + struct str_in : TAO_PEGTL_STRING( "in" ) {}; + struct str_local : TAO_PEGTL_STRING( "local" ) {}; + struct str_nil : TAO_PEGTL_STRING( "nil" ) {}; + struct str_not : TAO_PEGTL_STRING( "not" ) {}; + struct str_or : TAO_PEGTL_STRING( "or" ) {}; + struct str_repeat : TAO_PEGTL_STRING( "repeat" ) {}; + struct str_return : TAO_PEGTL_STRING( "return" ) {}; + struct str_then : TAO_PEGTL_STRING( "then" ) {}; + struct str_true : TAO_PEGTL_STRING( "true" ) {}; + struct str_until : TAO_PEGTL_STRING( "until" ) {}; + struct str_while : TAO_PEGTL_STRING( "while" ) {}; + + // Note that 'elseif' precedes 'else' in order to prevent only matching + // the "else" part of an "elseif" and running into an error in the + // 'keyword' rule. + + template< typename Key > + struct key : tao::pegtl::seq< Key, tao::pegtl::not_at< tao::pegtl::identifier_other > > {}; + + struct sor_keyword : tao::pegtl::sor< str_and, str_break, str_do, str_elseif, str_else, str_end, str_false, str_for, str_function, str_goto, str_if, str_in, str_local, str_nil, str_not, str_repeat, str_return, str_then, str_true, str_until, str_while > {}; + + struct key_and : key< str_and > {}; + struct key_break : key< str_break > {}; + struct key_do : key< str_do > {}; + struct key_else : key< str_else > {}; + struct key_elseif : key< str_elseif > {}; + struct key_end : key< str_end > {}; + struct key_false : key< str_false > {}; + struct key_for : key< str_for > {}; + struct key_function : key< str_function > {}; + struct key_goto : key< str_goto > {}; + struct key_if : key< str_if > {}; + struct key_in : key< str_in > {}; + struct key_local : key< str_local > {}; + struct key_nil : key< str_nil > {}; + struct key_not : key< str_not > {}; + struct key_or : key< str_or > {}; + struct key_repeat : key< str_repeat > {}; + struct key_return : key< str_return > {}; + struct key_then : key< str_then > {}; + struct key_true : key< str_true > {}; + struct key_until : key< str_until > {}; + struct key_while : key< str_while > {}; + + struct keyword : key< sor_keyword > {}; + + template< typename R > + struct pad : tao::pegtl::pad< R, sep > {}; + + struct name : tao::pegtl::seq< tao::pegtl::not_at< keyword >, tao::pegtl::identifier > {}; + + struct single : tao::pegtl::one< 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0', '\n' > {}; + struct spaces : tao::pegtl::seq< tao::pegtl::one< 'z' >, tao::pegtl::star< tao::pegtl::space > > {}; + struct hexbyte : tao::pegtl::if_must< tao::pegtl::one< 'x' >, tao::pegtl::xdigit, tao::pegtl::xdigit > {}; + struct decbyte : tao::pegtl::if_must< tao::pegtl::digit, tao::pegtl::rep_opt< 2, tao::pegtl::digit > > {}; + struct unichar : tao::pegtl::if_must< tao::pegtl::one< 'u' >, tao::pegtl::one< '{' >, tao::pegtl::plus< tao::pegtl::xdigit >, tao::pegtl::one< '}' > > {}; + struct escaped : tao::pegtl::if_must< tao::pegtl::one< '\\' >, tao::pegtl::sor< hexbyte, decbyte, unichar, single, spaces > > {}; + struct regular : tao::pegtl::not_one< '\r', '\n' > {}; + struct character : tao::pegtl::sor< escaped, regular > {}; + + template< char Q > + struct short_string : tao::pegtl::if_must< tao::pegtl::one< Q >, tao::pegtl::until< tao::pegtl::one< Q >, character > > {}; + struct literal_string : tao::pegtl::sor< short_string< '"' >, short_string< '\'' >, long_string > {}; + + template< typename E > + struct exponent : tao::pegtl::opt_must< E, tao::pegtl::opt< tao::pegtl::one< '+', '-' > >, tao::pegtl::plus< tao::pegtl::digit > > {}; + + template< typename D, typename E > + struct numeral_three : tao::pegtl::seq< tao::pegtl::if_must< tao::pegtl::one< '.' >, tao::pegtl::plus< D > >, exponent< E > > {}; + template< typename D, typename E > + struct numeral_two : tao::pegtl::seq< tao::pegtl::plus< D >, tao::pegtl::opt< tao::pegtl::one< '.' >, tao::pegtl::star< D > >, exponent< E > > {}; + template< typename D, typename E > + struct numeral_one : tao::pegtl::sor< numeral_two< D, E >, numeral_three< D, E > > {}; + + struct decimal : numeral_one< tao::pegtl::digit, tao::pegtl::one< 'e', 'E' > > {}; + struct hexadecimal : tao::pegtl::if_must< tao::pegtl::istring< '0', 'x' >, numeral_one< tao::pegtl::xdigit, tao::pegtl::one< 'p', 'P' > > > {}; + struct numeral : tao::pegtl::sor< hexadecimal, decimal > {}; + + struct label_statement : tao::pegtl::if_must< tao::pegtl::two< ':' >, seps, name, seps, tao::pegtl::two< ':' > > {}; + struct goto_statement : tao::pegtl::if_must< key_goto, seps, name > {}; + + struct statement; + struct expression; + + struct name_list : tao::pegtl::list< name, tao::pegtl::one< ',' >, sep > {}; + struct name_list_must : tao::pegtl::list_must< name, tao::pegtl::one< ',' >, sep > {}; + struct expr_list_must : tao::pegtl::list_must< expression, tao::pegtl::one< ',' >, sep > {}; + + struct statement_return : tao::pegtl::seq< tao::pegtl::pad_opt< expr_list_must, sep >, tao::pegtl::opt< tao::pegtl::one< ';' >, seps > > {}; + + template< typename E > + struct statement_list : tao::pegtl::seq< seps, tao::pegtl::until< tao::pegtl::sor< E, tao::pegtl::if_must< key_return, statement_return, E > >, statement, seps > > {}; + + template< char O, char... N > + struct op_one : tao::pegtl::seq< tao::pegtl::one< O >, tao::pegtl::at< tao::pegtl::not_one< N... > > > {}; + template< char O, char P, char... N > + struct op_two : tao::pegtl::seq< tao::pegtl::string< O, P >, tao::pegtl::at< tao::pegtl::not_one< N... > > > {}; + + struct table_field_one : tao::pegtl::if_must< tao::pegtl::one< '[' >, seps, expression, seps, tao::pegtl::one< ']' >, seps, tao::pegtl::one< '=' >, seps, expression > {}; + struct table_field_two : tao::pegtl::if_must< tao::pegtl::seq< name, seps, op_one< '=', '=' > >, seps, expression > {}; + struct table_field : tao::pegtl::sor< table_field_one, table_field_two, expression > {}; + struct table_field_list : tao::pegtl::list_tail< table_field, tao::pegtl::one< ',', ';' >, sep > {}; + struct table_constructor : tao::pegtl::if_must< tao::pegtl::one< '{' >, tao::pegtl::pad_opt< table_field_list, sep >, tao::pegtl::one< '}' > > {}; + + struct parameter_list_one : tao::pegtl::seq< name_list, tao::pegtl::opt_must< pad< tao::pegtl::one< ',' > >, tao::pegtl::ellipsis > > {}; + struct parameter_list : tao::pegtl::sor< tao::pegtl::ellipsis, parameter_list_one > {}; + + struct function_body : tao::pegtl::seq< tao::pegtl::one< '(' >, tao::pegtl::pad_opt< parameter_list, sep >, tao::pegtl::one< ')' >, seps, statement_list< key_end > > {}; + struct function_literal : tao::pegtl::if_must< key_function, seps, function_body > {}; + + struct bracket_expr : tao::pegtl::if_must< tao::pegtl::one< '(' >, seps, expression, seps, tao::pegtl::one< ')' > > {}; + + struct function_args_one : tao::pegtl::if_must< tao::pegtl::one< '(' >, tao::pegtl::pad_opt< expr_list_must, sep >, tao::pegtl::one< ')' > > {}; + struct function_args : tao::pegtl::sor< function_args_one, table_constructor, literal_string > {}; + + struct variable_tail_one : tao::pegtl::if_must< tao::pegtl::one< '[' >, seps, expression, seps, tao::pegtl::one< ']' > > {}; + struct variable_tail_two : tao::pegtl::if_must< tao::pegtl::seq< tao::pegtl::not_at< tao::pegtl::two< '.' > >, tao::pegtl::one< '.' > >, seps, name > {}; + struct variable_tail : tao::pegtl::sor< variable_tail_one, variable_tail_two > {}; + + struct function_call_tail_one : tao::pegtl::if_must< tao::pegtl::seq< tao::pegtl::not_at< tao::pegtl::two< ':' > >, tao::pegtl::one< ':' > >, seps, name, seps, function_args > {}; + struct function_call_tail : tao::pegtl::sor< function_args, function_call_tail_one > {}; + + struct variable_head_one : tao::pegtl::seq< bracket_expr, seps, variable_tail > {}; + struct variable_head : tao::pegtl::sor< name, variable_head_one > {}; + + struct function_call_head : tao::pegtl::sor< name, bracket_expr > {}; + + struct variable : tao::pegtl::seq< variable_head, tao::pegtl::star< tao::pegtl::star< seps, function_call_tail >, seps, variable_tail > > {}; + struct function_call : tao::pegtl::seq< function_call_head, tao::pegtl::plus< tao::pegtl::until< tao::pegtl::seq< seps, function_call_tail >, seps, variable_tail > > > {}; + + template< typename S, typename O > + struct left_assoc : tao::pegtl::seq< S, seps, tao::pegtl::star_must< O, seps, S, seps > > {}; + template< typename S, typename O > + struct right_assoc : tao::pegtl::seq< S, seps, tao::pegtl::opt_must< O, seps, right_assoc< S, O > > > {}; + + struct unary_operators : tao::pegtl::sor< tao::pegtl::one< '-' >, + tao::pegtl::one< '#' >, + op_one< '~', '=' >, + key_not > {}; + + struct expr_ten; + struct expr_thirteen : tao::pegtl::seq< tao::pegtl::sor< bracket_expr, name >, tao::pegtl::star< seps, tao::pegtl::sor< function_call_tail, variable_tail > > > {}; + struct expr_twelve : tao::pegtl::sor< key_nil, + key_true, + key_false, + tao::pegtl::ellipsis, + numeral, + literal_string, + function_literal, + expr_thirteen, + table_constructor > {}; + struct expr_eleven : tao::pegtl::seq< expr_twelve, seps, tao::pegtl::opt< tao::pegtl::one< '^' >, seps, expr_ten, seps > > {}; + struct unary_apply : tao::pegtl::if_must< unary_operators, seps, expr_ten, seps > {}; + struct expr_ten : tao::pegtl::sor< unary_apply, expr_eleven > {}; + struct operators_nine : tao::pegtl::sor< tao::pegtl::two< '/' >, + tao::pegtl::one< '/' >, + tao::pegtl::one< '*' >, + tao::pegtl::one< '%' > > {}; + struct expr_nine : left_assoc< expr_ten, operators_nine > {}; + struct operators_eight : tao::pegtl::sor< tao::pegtl::one< '+' >, + tao::pegtl::one< '-' > > {}; + struct expr_eight : left_assoc< expr_nine, operators_eight > {}; + struct expr_seven : right_assoc< expr_eight, op_two< '.', '.', '.' > > {}; + struct operators_six : tao::pegtl::sor< tao::pegtl::two< '<' >, + tao::pegtl::two< '>' > > {}; + struct expr_six : left_assoc< expr_seven, operators_six > {}; + struct expr_five : left_assoc< expr_six, tao::pegtl::one< '&' > > {}; + struct expr_four : left_assoc< expr_five, op_one< '~', '=' > > {}; + struct expr_three : left_assoc< expr_four, tao::pegtl::one< '|' > > {}; + struct operators_two : tao::pegtl::sor< tao::pegtl::two< '=' >, + tao::pegtl::string< '<', '=' >, + tao::pegtl::string< '>', '=' >, + op_one< '<', '<' >, + op_one< '>', '>' >, + tao::pegtl::string< '~', '=' > > {}; + struct expr_two : left_assoc< expr_three, operators_two > {}; + struct expr_one : left_assoc< expr_two, key_and > {}; + struct expression : left_assoc< expr_one, key_or > {}; + + struct do_statement : tao::pegtl::if_must< key_do, statement_list< key_end > > {}; + struct while_statement : tao::pegtl::if_must< key_while, seps, expression, seps, key_do, statement_list< key_end > > {}; + struct repeat_statement : tao::pegtl::if_must< key_repeat, statement_list< key_until >, seps, expression > {}; + + struct at_elseif_else_end : tao::pegtl::sor< tao::pegtl::at< key_elseif >, tao::pegtl::at< key_else >, tao::pegtl::at< key_end > > {}; + struct elseif_statement : tao::pegtl::if_must< key_elseif, seps, expression, seps, key_then, statement_list< at_elseif_else_end > > {}; + struct else_statement : tao::pegtl::if_must< key_else, statement_list< key_end > > {}; + struct if_statement : tao::pegtl::if_must< key_if, seps, expression, seps, key_then, statement_list< at_elseif_else_end >, seps, tao::pegtl::until< tao::pegtl::sor< else_statement, key_end >, elseif_statement, seps > > {}; + + struct for_statement_one : tao::pegtl::seq< tao::pegtl::one< '=' >, seps, expression, seps, tao::pegtl::one< ',' >, seps, expression, tao::pegtl::pad_opt< tao::pegtl::if_must< tao::pegtl::one< ',' >, seps, expression >, sep > > {}; + struct for_statement_two : tao::pegtl::seq< tao::pegtl::opt_must< tao::pegtl::one< ',' >, seps, name_list_must, seps >, key_in, seps, expr_list_must, seps > {}; + struct for_statement : tao::pegtl::if_must< key_for, seps, name, seps, tao::pegtl::sor< for_statement_one, for_statement_two >, key_do, statement_list< key_end > > {}; + + struct assignment_variable_list : tao::pegtl::list_must< variable, tao::pegtl::one< ',' >, sep > {}; + struct assignments_one : tao::pegtl::if_must< tao::pegtl::one< '=' >, seps, expr_list_must > {}; + struct assignments : tao::pegtl::seq< assignment_variable_list, seps, assignments_one > {}; + struct function_name : tao::pegtl::seq< tao::pegtl::list< name, tao::pegtl::one< '.' >, sep >, seps, tao::pegtl::opt_must< tao::pegtl::one< ':' >, seps, name, seps > > {}; + struct function_definition : tao::pegtl::if_must< key_function, seps, function_name, function_body > {}; + + struct local_function : tao::pegtl::if_must< key_function, seps, name, seps, function_body > {}; + struct local_variables : tao::pegtl::if_must< name_list_must, seps, tao::pegtl::opt< assignments_one > > {}; + struct local_statement : tao::pegtl::if_must< key_local, seps, tao::pegtl::sor< local_function, local_variables > > {}; + + struct semicolon : tao::pegtl::one< ';' > {}; + struct statement : tao::pegtl::sor< semicolon, + assignments, + function_call, + label_statement, + key_break, + goto_statement, + do_statement, + while_statement, + repeat_statement, + if_statement, + for_statement, + function_definition, + local_statement > {}; + + struct grammar : tao::pegtl::must< tao::pegtl::opt< tao::pegtl::shebang >, statement_list< tao::pegtl::eof > > {}; + // clang-format on + +} // namespace lua53 + +#endif diff --git a/packages/PEGTL/src/example/pegtl/lua53_analyze.cpp b/packages/PEGTL/src/example/pegtl/lua53_analyze.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6d6c847e7c576726bc6e86e6a7effd8929f205a --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/lua53_analyze.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iostream> + +#include <tao/pegtl/contrib/analyze.hpp> + +#include "lua53.hpp" + +int main() // NOLINT(bugprone-exception-escape) +{ + if( const auto problems = TAO_PEGTL_NAMESPACE::analyze< lua53::grammar >() != 0 ) { + std::cout << "problems: " << problems << std::endl; + return 1; + } + return 0; +} diff --git a/packages/PEGTL/src/example/pegtl/lua53_parse.cpp b/packages/PEGTL/src/example/pegtl/lua53_parse.cpp index ddb1df06b2c75ac04874ec1fc074e49a0cb81469..6b84aff24753be1b2027d050b7516e390badf282 100644 --- a/packages/PEGTL/src/example/pegtl/lua53_parse.cpp +++ b/packages/PEGTL/src/example/pegtl/lua53_parse.cpp @@ -1,347 +1,16 @@ // Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#include <tao/pegtl.hpp> -#include <tao/pegtl/contrib/analyze.hpp> -#include <tao/pegtl/contrib/raw_string.hpp> +#include <iostream> -namespace lua53 -{ - // PEGTL grammar for the Lua 5.3.0 lexer and parser. - // - // The grammar here is not very similar to the grammar - // in the Lua reference documentation on which it is based - // which is due to multiple causes. - // - // The main difference is that this grammar includes really - // "everything", not just the structural parts from the - // reference documentation: - // - The PEG-approach combines lexer and parser; this grammar - // handles comments and tokenisation. - // - The operator precedence and associativity are reflected - // in the structure of this grammar. - // - All details for all types of literals are included, with - // escape-sequences for literal strings, and long literals. - // - // The second necessary difference is that all left-recursion - // had to be eliminated. - // - // In some places the grammar was optimised to require as little - // back-tracking as possible, most prominently for expressions. - // The original grammar contains the following production rules: - // - // prefixexp ::= var | functioncall | ‘(’ exp ‘)’ - // functioncall ::= prefixexp args | prefixexp ‘:’ Name args - // var ::= Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name - // - // We need to eliminate the left-recursion, and we also want to - // remove the ambiguity between function calls and variables, - // i.e. the fact that we can have expressions like - // - // ( a * b ).c()[ d ].e:f() - // - // where only the last element decides between function call and - // variable, making it necessary to parse the whole thing again - // if we chose wrong at the beginning. - // First we eliminate prefixexp and obtain: - // - // functioncall ::= ( var | functioncall | ‘(’ exp ‘)’ ) ( args | ‘:’ Name args ) - // var ::= Name | ( var | functioncall | ‘(’ exp ‘)’ ) ( ‘[’ exp ‘]’ | ‘.’ Name ) - // - // Next we split function_call and variable into a first part, - // a "head", or how they can start, and a second part, the "tail", - // which, in a sequence like above, is the final deciding part: - // - // vartail ::= '[' exp ']' | '.' Name - // varhead ::= Name | '(' exp ')' vartail - // functail ::= args | ':' Name args - // funchead ::= Name | '(' exp ')' - // - // This allows us to rewrite var and function_call as follows. - // - // var ::= varhead { { functail } vartail } - // function_call ::= funchead [ { vartail } functail ] - // - // Finally we can define a single expression that takes care - // of var, function_call, and expressions in a bracket: - // - // chead ::= '(' exp ')' | Name - // combined ::= chead { functail | vartail } - // - // Such a combined expression starts with a bracketed - // expression or a name, and continues with an arbitrary - // number of functail and/or vartail parts, all in a one - // grammar rule without back-tracking. - // - // The rule expr_thirteen below implements "combined". - // - // Another issue of interest when writing a PEG is how to - // manage the separators, the white-space and comments that - // can occur in many places; in the classical two-stage - // lexer-parser approach the lexer would have taken care of - // this, but here we use the PEG approach that combines both. - // - // In the following grammar most rules adopt the convention - // that they take care of "internal padding", i.e. spaces - // and comments that can occur within the rule, but not - // "external padding", i.e. they don't start or end with - // a rule that "eats up" all extra padding (spaces and - // comments). In some places, where it is more efficient, - // right padding is used. - - namespace pegtl = TAO_PEGTL_NAMESPACE; - - // clang-format off - struct short_comment : pegtl::until< pegtl::eolf > {}; - struct long_string : pegtl::raw_string< '[', '=', ']' > {}; - struct comment : pegtl::disable< pegtl::two< '-' >, pegtl::sor< long_string, short_comment > > {}; - - struct sep : pegtl::sor< pegtl::ascii::space, comment > {}; - struct seps : pegtl::star< sep > {}; - - struct str_and : TAO_PEGTL_STRING( "and" ) {}; - struct str_break : TAO_PEGTL_STRING( "break" ) {}; - struct str_do : TAO_PEGTL_STRING( "do" ) {}; - struct str_else : TAO_PEGTL_STRING( "else" ) {}; - struct str_elseif : TAO_PEGTL_STRING( "elseif" ) {}; - struct str_end : TAO_PEGTL_STRING( "end" ) {}; - struct str_false : TAO_PEGTL_STRING( "false" ) {}; - struct str_for : TAO_PEGTL_STRING( "for" ) {}; - struct str_function : TAO_PEGTL_STRING( "function" ) {}; - struct str_goto : TAO_PEGTL_STRING( "goto" ) {}; - struct str_if : TAO_PEGTL_STRING( "if" ) {}; - struct str_in : TAO_PEGTL_STRING( "in" ) {}; - struct str_local : TAO_PEGTL_STRING( "local" ) {}; - struct str_nil : TAO_PEGTL_STRING( "nil" ) {}; - struct str_not : TAO_PEGTL_STRING( "not" ) {}; - struct str_or : TAO_PEGTL_STRING( "or" ) {}; - struct str_repeat : TAO_PEGTL_STRING( "repeat" ) {}; - struct str_return : TAO_PEGTL_STRING( "return" ) {}; - struct str_then : TAO_PEGTL_STRING( "then" ) {}; - struct str_true : TAO_PEGTL_STRING( "true" ) {}; - struct str_until : TAO_PEGTL_STRING( "until" ) {}; - struct str_while : TAO_PEGTL_STRING( "while" ) {}; - - // Note that 'elseif' precedes 'else' in order to prevent only matching - // the "else" part of an "elseif" and running into an error in the - // 'keyword' rule. - - struct str_keyword : pegtl::sor< str_and, str_break, str_do, str_elseif, str_else, str_end, str_false, str_for, str_function, str_goto, str_if, str_in, str_local, str_nil, str_not, str_repeat, str_return, str_then, str_true, str_until, str_while > {}; - - template< typename Key > - struct key : pegtl::seq< Key, pegtl::not_at< pegtl::identifier_other > > {}; - - struct key_and : key< str_and > {}; - struct key_break : key< str_break > {}; - struct key_do : key< str_do > {}; - struct key_else : key< str_else > {}; - struct key_elseif : key< str_elseif > {}; - struct key_end : key< str_end > {}; - struct key_false : key< str_false > {}; - struct key_for : key< str_for > {}; - struct key_function : key< str_function > {}; - struct key_goto : key< str_goto > {}; - struct key_if : key< str_if > {}; - struct key_in : key< str_in > {}; - struct key_local : key< str_local > {}; - struct key_nil : key< str_nil > {}; - struct key_not : key< str_not > {}; - struct key_or : key< str_or > {}; - struct key_repeat : key< str_repeat > {}; - struct key_return : key< str_return > {}; - struct key_then : key< str_then > {}; - struct key_true : key< str_true > {}; - struct key_until : key< str_until > {}; - struct key_while : key< str_while > {}; - - struct keyword : key< str_keyword > {}; - - template< typename R > - struct pad : pegtl::pad< R, sep > {}; - - struct name : pegtl::seq< pegtl::not_at< keyword >, pegtl::identifier > {}; - - struct single : pegtl::one< 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0', '\n' > {}; - struct spaces : pegtl::seq< pegtl::one< 'z' >, pegtl::star< pegtl::space > > {}; - struct hexbyte : pegtl::if_must< pegtl::one< 'x' >, pegtl::xdigit, pegtl::xdigit > {}; - struct decbyte : pegtl::if_must< pegtl::digit, pegtl::rep_opt< 2, pegtl::digit > > {}; - struct unichar : pegtl::if_must< pegtl::one< 'u' >, pegtl::one< '{' >, pegtl::plus< pegtl::xdigit >, pegtl::one< '}' > > {}; - struct escaped : pegtl::if_must< pegtl::one< '\\' >, pegtl::sor< hexbyte, decbyte, unichar, single, spaces > > {}; - struct regular : pegtl::not_one< '\r', '\n' > {}; - struct character : pegtl::sor< escaped, regular > {}; - - template< char Q > - struct short_string : pegtl::if_must< pegtl::one< Q >, pegtl::until< pegtl::one< Q >, character > > {}; - struct literal_string : pegtl::sor< short_string< '"' >, short_string< '\'' >, long_string > {}; - - template< typename E > - struct exponent : pegtl::opt_must< E, pegtl::opt< pegtl::one< '+', '-' > >, pegtl::plus< pegtl::digit > > {}; - - template< typename D, typename E > - struct numeral_three : pegtl::seq< pegtl::if_must< pegtl::one< '.' >, pegtl::plus< D > >, exponent< E > > {}; - template< typename D, typename E > - struct numeral_two : pegtl::seq< pegtl::plus< D >, pegtl::opt< pegtl::one< '.' >, pegtl::star< D > >, exponent< E > > {}; - template< typename D, typename E > - struct numeral_one : pegtl::sor< numeral_two< D, E >, numeral_three< D, E > > {}; - - struct decimal : numeral_one< pegtl::digit, pegtl::one< 'e', 'E' > > {}; - struct hexadecimal : pegtl::if_must< pegtl::istring< '0', 'x' >, numeral_one< pegtl::xdigit, pegtl::one< 'p', 'P' > > > {}; - struct numeral : pegtl::sor< hexadecimal, decimal > {}; - - struct label_statement : pegtl::if_must< pegtl::two< ':' >, seps, name, seps, pegtl::two< ':' > > {}; - struct goto_statement : pegtl::if_must< key_goto, seps, name > {}; - - struct statement; - struct expression; - - struct name_list : pegtl::list< name, pegtl::one< ',' >, sep > {}; - struct name_list_must : pegtl::list_must< name, pegtl::one< ',' >, sep > {}; - struct expr_list_must : pegtl::list_must< expression, pegtl::one< ',' >, sep > {}; - - struct statement_return : pegtl::seq< pegtl::pad_opt< expr_list_must, sep >, pegtl::opt< pegtl::one< ';' >, seps > > {}; - - template< typename E > - struct statement_list : pegtl::seq< seps, pegtl::until< pegtl::sor< E, pegtl::if_must< key_return, statement_return, E > >, statement, seps > > {}; - - template< char O, char... N > - struct op_one : pegtl::seq< pegtl::one< O >, pegtl::at< pegtl::not_one< N... > > > {}; - template< char O, char P, char... N > - struct op_two : pegtl::seq< pegtl::string< O, P >, pegtl::at< pegtl::not_one< N... > > > {}; - - struct table_field_one : pegtl::if_must< pegtl::one< '[' >, seps, expression, seps, pegtl::one< ']' >, seps, pegtl::one< '=' >, seps, expression > {}; - struct table_field_two : pegtl::if_must< pegtl::seq< name, seps, op_one< '=', '=' > >, seps, expression > {}; - struct table_field : pegtl::sor< table_field_one, table_field_two, expression > {}; - struct table_field_list : pegtl::list_tail< table_field, pegtl::one< ',', ';' >, sep > {}; - struct table_constructor : pegtl::if_must< pegtl::one< '{' >, pegtl::pad_opt< table_field_list, sep >, pegtl::one< '}' > > {}; - - struct parameter_list_one : pegtl::seq< name_list, pegtl::opt_must< pad< pegtl::one< ',' > >, pegtl::ellipsis > > {}; - struct parameter_list : pegtl::sor< pegtl::ellipsis, parameter_list_one > {}; - - struct function_body : pegtl::seq< pegtl::one< '(' >, pegtl::pad_opt< parameter_list, sep >, pegtl::one< ')' >, seps, statement_list< key_end > > {}; - struct function_literal : pegtl::if_must< key_function, seps, function_body > {}; - - struct bracket_expr : pegtl::if_must< pegtl::one< '(' >, seps, expression, seps, pegtl::one< ')' > > {}; - - struct function_args_one : pegtl::if_must< pegtl::one< '(' >, pegtl::pad_opt< expr_list_must, sep >, pegtl::one< ')' > > {}; - struct function_args : pegtl::sor< function_args_one, table_constructor, literal_string > {}; - - struct variable_tail_one : pegtl::if_must< pegtl::one< '[' >, seps, expression, seps, pegtl::one< ']' > > {}; - struct variable_tail_two : pegtl::if_must< pegtl::seq< pegtl::not_at< pegtl::two< '.' > >, pegtl::one< '.' > >, seps, name > {}; - struct variable_tail : pegtl::sor< variable_tail_one, variable_tail_two > {}; - - struct function_call_tail_one : pegtl::if_must< pegtl::seq< pegtl::not_at< pegtl::two< ':' > >, pegtl::one< ':' > >, seps, name, seps, function_args > {}; - struct function_call_tail : pegtl::sor< function_args, function_call_tail_one > {}; - - struct variable_head_one : pegtl::seq< bracket_expr, seps, variable_tail > {}; - struct variable_head : pegtl::sor< name, variable_head_one > {}; - - struct function_call_head : pegtl::sor< name, bracket_expr > {}; - - struct variable : pegtl::seq< variable_head, pegtl::star< pegtl::star< seps, function_call_tail >, seps, variable_tail > > {}; - struct function_call : pegtl::seq< function_call_head, pegtl::plus< pegtl::until< pegtl::seq< seps, function_call_tail >, seps, variable_tail > > > {}; - - template< typename S, typename O > - struct left_assoc : pegtl::seq< S, seps, pegtl::star_must< O, seps, S, seps > > {}; - template< typename S, typename O > - struct right_assoc : pegtl::seq< S, seps, pegtl::opt_must< O, seps, right_assoc< S, O > > > {}; - - struct unary_operators : pegtl::sor< pegtl::one< '-' >, - pegtl::one< '#' >, - op_one< '~', '=' >, - key_not > {}; - - struct expr_ten; - struct expr_thirteen : pegtl::seq< pegtl::sor< bracket_expr, name >, pegtl::star< seps, pegtl::sor< function_call_tail, variable_tail > > > {}; - struct expr_twelve : pegtl::sor< key_nil, - key_true, - key_false, - pegtl::ellipsis, - numeral, - literal_string, - function_literal, - expr_thirteen, - table_constructor > {}; - struct expr_eleven : pegtl::seq< expr_twelve, seps, pegtl::opt< pegtl::one< '^' >, seps, expr_ten, seps > > {}; - struct unary_apply : pegtl::if_must< unary_operators, seps, expr_ten, seps > {}; - struct expr_ten : pegtl::sor< unary_apply, expr_eleven > {}; - struct operators_nine : pegtl::sor< pegtl::two< '/' >, - pegtl::one< '/' >, - pegtl::one< '*' >, - pegtl::one< '%' > > {}; - struct expr_nine : left_assoc< expr_ten, operators_nine > {}; - struct operators_eight : pegtl::sor< pegtl::one< '+' >, - pegtl::one< '-' > > {}; - struct expr_eight : left_assoc< expr_nine, operators_eight > {}; - struct expr_seven : right_assoc< expr_eight, op_two< '.', '.', '.' > > {}; - struct operators_six : pegtl::sor< pegtl::two< '<' >, - pegtl::two< '>' > > {}; - struct expr_six : left_assoc< expr_seven, operators_six > {}; - struct expr_five : left_assoc< expr_six, pegtl::one< '&' > > {}; - struct expr_four : left_assoc< expr_five, op_one< '~', '=' > > {}; - struct expr_three : left_assoc< expr_four, pegtl::one< '|' > > {}; - struct operators_two : pegtl::sor< pegtl::two< '=' >, - pegtl::string< '<', '=' >, - pegtl::string< '>', '=' >, - op_one< '<', '<' >, - op_one< '>', '>' >, - pegtl::string< '~', '=' > > {}; - struct expr_two : left_assoc< expr_three, operators_two > {}; - struct expr_one : left_assoc< expr_two, key_and > {}; - struct expression : left_assoc< expr_one, key_or > {}; - - struct do_statement : pegtl::if_must< key_do, statement_list< key_end > > {}; - struct while_statement : pegtl::if_must< key_while, seps, expression, seps, key_do, statement_list< key_end > > {}; - struct repeat_statement : pegtl::if_must< key_repeat, statement_list< key_until >, seps, expression > {}; - - struct at_elseif_else_end : pegtl::sor< pegtl::at< key_elseif >, pegtl::at< key_else >, pegtl::at< key_end > > {}; - struct elseif_statement : pegtl::if_must< key_elseif, seps, expression, seps, key_then, statement_list< at_elseif_else_end > > {}; - struct else_statement : pegtl::if_must< key_else, statement_list< key_end > > {}; - struct if_statement : pegtl::if_must< key_if, seps, expression, seps, key_then, statement_list< at_elseif_else_end >, seps, pegtl::until< pegtl::sor< else_statement, key_end >, elseif_statement, seps > > {}; - - struct for_statement_one : pegtl::seq< pegtl::one< '=' >, seps, expression, seps, pegtl::one< ',' >, seps, expression, pegtl::pad_opt< pegtl::if_must< pegtl::one< ',' >, seps, expression >, sep > > {}; - struct for_statement_two : pegtl::seq< pegtl::opt_must< pegtl::one< ',' >, seps, name_list_must, seps >, key_in, seps, expr_list_must, seps > {}; - struct for_statement : pegtl::if_must< key_for, seps, name, seps, pegtl::sor< for_statement_one, for_statement_two >, key_do, statement_list< key_end > > {}; - - struct assignment_variable_list : pegtl::list_must< variable, pegtl::one< ',' >, sep > {}; - struct assignments_one : pegtl::if_must< pegtl::one< '=' >, seps, expr_list_must > {}; - struct assignments : pegtl::seq< assignment_variable_list, seps, assignments_one > {}; - struct function_name : pegtl::seq< pegtl::list< name, pegtl::one< '.' >, sep >, seps, pegtl::opt_must< pegtl::one< ':' >, seps, name, seps > > {}; - struct function_definition : pegtl::if_must< key_function, seps, function_name, function_body > {}; - - struct local_function : pegtl::if_must< key_function, seps, name, seps, function_body > {}; - struct local_variables : pegtl::if_must< name_list_must, seps, pegtl::opt< assignments_one > > {}; - struct local_statement : pegtl::if_must< key_local, seps, pegtl::sor< local_function, local_variables > > {}; - - struct semicolon : pegtl::one< ';' > {}; - struct statement : pegtl::sor< semicolon, - assignments, - function_call, - label_statement, - key_break, - goto_statement, - do_statement, - while_statement, - repeat_statement, - if_statement, - for_statement, - function_definition, - local_statement > {}; - - struct interpreter : pegtl::seq< pegtl::one< '#' >, pegtl::until< pegtl::eolf > > {}; - struct grammar : pegtl::must< pegtl::opt< interpreter >, statement_list< pegtl::eof > > {}; - // clang-format on - -} // namespace lua53 +#include "lua53.hpp" int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) { - if( TAO_PEGTL_NAMESPACE::analyze< lua53::grammar >() != 0 ) { - return 1; - } - for( int i = 1; i < argc; ++i ) { TAO_PEGTL_NAMESPACE::file_input in( argv[ i ] ); - TAO_PEGTL_NAMESPACE::parse< lua53::grammar >( in ); + const auto r = TAO_PEGTL_NAMESPACE::parse< lua53::grammar >( in ); + std::cout << argv[ i ] << " " << r << std::endl; } return 0; } diff --git a/packages/PEGTL/src/example/pegtl/lua53_print_debug.cpp b/packages/PEGTL/src/example/pegtl/lua53_print_debug.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9303d54ab36b514b7856e36cc3b44d2426b55b3 --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/lua53_print_debug.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iostream> + +#include <tao/pegtl/contrib/print.hpp> + +#include "lua53.hpp" + +int main() // NOLINT(bugprone-exception-escape) +{ + tao::pegtl::print_debug< lua53::grammar >( std::cout ); + return 0; +} diff --git a/packages/PEGTL/src/example/pegtl/lua53_print_names.cpp b/packages/PEGTL/src/example/pegtl/lua53_print_names.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39bb917e710c1c8f6500279cd5567de3b92c6494 --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/lua53_print_names.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iostream> + +#include <tao/pegtl/contrib/print.hpp> + +#include "lua53.hpp" + +int main() // NOLINT(bugprone-exception-escape) +{ + tao::pegtl::print_names< lua53::grammar >( std::cout ); + return 0; +} diff --git a/packages/PEGTL/src/example/pegtl/parse_tree.cpp b/packages/PEGTL/src/example/pegtl/parse_tree.cpp index 9f0053f225a5d2bce91c51ce0e6489edf8d93547..1ccde1fef374eeb6ad47918a684bb9e2c8e24b61 100644 --- a/packages/PEGTL/src/example/pegtl/parse_tree.cpp +++ b/packages/PEGTL/src/example/pegtl/parse_tree.cpp @@ -2,6 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include <array> +#include <iomanip> #include <iostream> #include <string> #include <type_traits> @@ -174,10 +175,10 @@ int main( int argc, char** argv ) return 0; } catch( const parse_error& e ) { - const auto p = e.positions.front(); + const auto p = e.positions().front(); std::cerr << e.what() << std::endl << in.line_at( p ) << std::endl - << std::string( p.byte_in_line, ' ' ) << '^' << std::endl; + << std::setw( p.column ) << '^' << std::endl; } catch( const std::exception& e ) { std::cerr << e.what() << std::endl; diff --git a/packages/PEGTL/src/example/pegtl/recover.cpp b/packages/PEGTL/src/example/pegtl/recover.cpp index 6353a7442074a645a105e31999a2400bd3331adb..c76a5f9f3199700425203f8d1050d1dcec21ab6c 100644 --- a/packages/PEGTL/src/example/pegtl/recover.cpp +++ b/packages/PEGTL/src/example/pegtl/recover.cpp @@ -69,7 +69,7 @@ struct found static void apply( const ActionInput& in, bool& error ) { if( !error ) { - std::cout << in.position() << ": Found " << internal::demangle< R >() << ": \"" << in.string() << "\"" << std::endl; + std::cout << in.position() << ": Found " << tao::demangle< R >() << ": \"" << in.string() << "\"" << std::endl; } } }; @@ -101,10 +101,10 @@ struct my_control : normal< Rule > { template< typename ParseInput, typename... States > - [[noreturn]] static void raise( const ParseInput& in, States&&... /*unused*/ ) + [[noreturn]] static void raise( const ParseInput& in, States&&... st ) { - std::cout << in.position() << ": Parse error matching " << internal::demangle< Rule >() << std::endl; - throw parse_error( "parse error matching " + std::string( internal::demangle< Rule >() ), in ); + std::cout << in.position() << ": Parse error matching " << tao::demangle< Rule >() << std::endl; + normal< Rule >::raise( in, st... ); } }; diff --git a/packages/PEGTL/src/example/pegtl/s_expression.cpp b/packages/PEGTL/src/example/pegtl/s_expression.cpp index 7c47f1c8b9b11217a070b5ac6d8355beca569f02..8eb4204708e80a9653613de26bfb9f108115c649 100644 --- a/packages/PEGTL/src/example/pegtl/s_expression.cpp +++ b/packages/PEGTL/src/example/pegtl/s_expression.cpp @@ -6,35 +6,33 @@ #include <tao/pegtl.hpp> #include <tao/pegtl/contrib/analyze.hpp> -using namespace TAO_PEGTL_NAMESPACE; - namespace sexpr { // clang-format off - struct hash_comment : until< eolf > {}; + struct hash_comment : tao::pegtl::until< tao::pegtl::eolf > {}; struct list; - struct list_comment : if_must< at< one< '(' > >, disable< list > > {}; + struct list_comment : tao::pegtl::if_must< tao::pegtl::at< tao::pegtl::one< '(' > >, tao::pegtl::disable< list > > {}; - struct read_include : seq< one< ' ' >, one< '"' >, plus< not_one< '"' > >, one< '"' > > {}; - struct hash_include : if_must< string< 'i', 'n', 'c', 'l', 'u', 'd', 'e' >, read_include > {}; + struct read_include : tao::pegtl::seq< tao::pegtl::one< ' ' >, tao::pegtl::one< '"' >, tao::pegtl::plus< tao::pegtl::not_one< '"' > >, tao::pegtl::one< '"' > > {}; + struct hash_include : tao::pegtl::if_must< tao::pegtl::string< 'i', 'n', 'c', 'l', 'u', 'd', 'e' >, read_include > {}; - struct hashed : if_must< one< '#' >, sor< hash_include, list_comment, hash_comment > > {}; + struct hashed : tao::pegtl::if_must< tao::pegtl::one< '#' >, tao::pegtl::sor< hash_include, list_comment, hash_comment > > {}; - struct number : plus< digit > {}; - struct symbol : identifier {}; + struct number : tao::pegtl::plus< tao::pegtl::digit > {}; + struct symbol : tao::pegtl::identifier {}; - struct atom : sor< number, symbol > {}; + struct atom : tao::pegtl::sor< number, symbol > {}; struct anything; - struct list : if_must< one< '(' >, until< one< ')' >, anything > > {}; + struct list : tao::pegtl::if_must< tao::pegtl::one< '(' >, tao::pegtl::until< tao::pegtl::one< ')' >, anything > > {}; - struct normal : sor< atom, list > {}; + struct normal : tao::pegtl::sor< atom, list > {}; - struct anything : sor< space, hashed, normal > {}; + struct anything : tao::pegtl::sor< tao::pegtl::space, hashed, normal > {}; - struct main : until< eof, must< anything > > {}; + struct main : tao::pegtl::until< tao::pegtl::eof, tao::pegtl::must< anything > > {}; // clang-format on template< typename Rule > @@ -42,7 +40,7 @@ namespace sexpr {}; template<> - struct action< plus< not_one< '"' > > > + struct action< tao::pegtl::plus< tao::pegtl::not_one< '"' > > > { template< typename ActionInput > static void apply( const ActionInput& in, std::string& fn ) @@ -64,8 +62,8 @@ namespace sexpr // last string literal that we use as filename here, and // the input is passed on for chained error messages (as // in "error in line x file foo included from file bar...) - file_input i2( fn ); - parse_nested< main, sexpr::action >( in, i2, f2 ); + tao::pegtl::file_input i2( fn ); + tao::pegtl::parse_nested< main, sexpr::action >( in, i2, f2 ); } }; @@ -73,14 +71,13 @@ namespace sexpr int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) { - if( analyze< sexpr::main >() != 0 ) { + if( tao::pegtl::analyze< sexpr::main >() != 0 ) { return 1; } - for( int i = 1; i < argc; ++i ) { std::string fn; - argv_input in( argv, i ); - parse< sexpr::main, sexpr::action >( in, fn ); + tao::pegtl::argv_input in( argv, i ); + tao::pegtl::parse< sexpr::main, sexpr::action >( in, fn ); } return 0; } diff --git a/packages/PEGTL/src/example/pegtl/symbol_table.cpp b/packages/PEGTL/src/example/pegtl/symbol_table.cpp index 5d0a7b51ab7a503008cc787c3ade45738dcf4af2..75a520135bc31b9202ef01e6c6673cb1ca8f5f83 100644 --- a/packages/PEGTL/src/example/pegtl/symbol_table.cpp +++ b/packages/PEGTL/src/example/pegtl/symbol_table.cpp @@ -47,9 +47,12 @@ namespace example template<> struct action< value > - : public pegtl::unsigned_action { - // Sets st.converted to the integer value of the matched string. + template< typename ActionInput > + static void apply( const ActionInput& in, state& st ) + { + pegtl::unsigned_action::apply( in, st.converted ); + } }; template<> diff --git a/packages/PEGTL/src/example/pegtl/uri_print_debug.cpp b/packages/PEGTL/src/example/pegtl/uri_print_debug.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25858179b541efb9f646892944be31b630b55315 --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/uri_print_debug.cpp @@ -0,0 +1,13 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iostream> + +#include <tao/pegtl/contrib/print.hpp> +#include <tao/pegtl/contrib/uri.hpp> + +int main() // NOLINT(bugprone-exception-escape) +{ + tao::pegtl::print_debug< tao::pegtl::uri::URI >( std::cout ); + return 0; +} diff --git a/packages/PEGTL/src/example/pegtl/uri_print_names.cpp b/packages/PEGTL/src/example/pegtl/uri_print_names.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6867333364e527b20fe24fd76e72f3e33f8368d9 --- /dev/null +++ b/packages/PEGTL/src/example/pegtl/uri_print_names.cpp @@ -0,0 +1,13 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iostream> + +#include <tao/pegtl/contrib/print.hpp> +#include <tao/pegtl/contrib/uri.hpp> + +int main() // NOLINT(bugprone-exception-escape) +{ + tao::pegtl::print_names< tao::pegtl::uri::URI >( std::cout ); + return 0; +} diff --git a/packages/PEGTL/src/example/pegtl/uri_trace.cpp b/packages/PEGTL/src/example/pegtl/uri_trace.cpp index cbd354ef15277ed3d126633757fd0adcc9316bc3..14a3a29588640562d1f2f73d4ad7cfb71c7abaf0 100644 --- a/packages/PEGTL/src/example/pegtl/uri_trace.cpp +++ b/packages/PEGTL/src/example/pegtl/uri_trace.cpp @@ -16,7 +16,7 @@ int main( int argc, char** argv ) // NOLINT(bugprone-exception-escape) for( int i = 1; i < argc; ++i ) { std::cout << "Parsing " << argv[ i ] << std::endl; pegtl::argv_input in( argv, i ); - pegtl::parse< grammar, pegtl::nothing, pegtl::trace_control >( in ); + pegtl::complete_trace< grammar >( in ); } return 0; } diff --git a/packages/PEGTL/src/test/pegtl/CMakeLists.txt b/packages/PEGTL/src/test/pegtl/CMakeLists.txt index 964d99432ce8e434ccc7e807aaec5aaeb376cf92..446ef2921f64949a984155553cf0c099a6bcecf3 100644 --- a/packages/PEGTL/src/test/pegtl/CMakeLists.txt +++ b/packages/PEGTL/src/test/pegtl/CMakeLists.txt @@ -25,6 +25,7 @@ set(test_sources change_states.cpp contrib_alphabet.cpp contrib_analyze.cpp + contrib_control_action.cpp contrib_http.cpp contrib_if_then.cpp contrib_integer.cpp @@ -33,13 +34,16 @@ set(test_sources contrib_partial_trace.cpp contrib_raw_string.cpp contrib_rep_one_min_max.cpp + contrib_state_control.cpp contrib_to_string.cpp contrib_tracer.cpp contrib_unescape.cpp contrib_uri.cpp + control_unwind.cpp data_cstring.cpp demangle.cpp discard_input.cpp + enable_control.cpp error_message.cpp file_cstream.cpp file_file.cpp @@ -49,6 +53,7 @@ set(test_sources internal_endian.cpp internal_file_mapper.cpp internal_file_opener.cpp + parse_error.cpp pegtl_string_t.cpp position.cpp rule_action.cpp @@ -60,6 +65,7 @@ set(test_sources rule_bytes.cpp rule_control.cpp rule_disable.cpp + rule_discard.cpp rule_enable.cpp rule_eof.cpp rule_failure.cpp @@ -78,6 +84,7 @@ set(test_sources rule_pad.cpp rule_pad_opt.cpp rule_plus.cpp + rule_raise.cpp rule_rematch.cpp rule_rep.cpp rule_rep_max.cpp diff --git a/packages/PEGTL/src/test/pegtl/actions_one.cpp b/packages/PEGTL/src/test/pegtl/actions_one.cpp index 1e5c2f81312439714ad6cd5475cde7480431e370..40128c1680bcc28b83eb49d148790449454cffc2 100644 --- a/packages/PEGTL/src/test/pegtl/actions_one.cpp +++ b/packages/PEGTL/src/test/pegtl/actions_one.cpp @@ -29,16 +29,16 @@ namespace TAO_PEGTL_NAMESPACE { TAO_PEGTL_TEST_ASSERT( applied.size() == 10 ); - TAO_PEGTL_TEST_ASSERT( applied[ 0 ].first == internal::demangle< one< 'b' > >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 1 ].first == internal::demangle< foo >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 2 ].first == internal::demangle< at< one< 'a' > > >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 3 ].first == internal::demangle< two< 'a' > >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 4 ].first == internal::demangle< fiz >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 5 ].first == internal::demangle< foo >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 6 ].first == internal::demangle< one< 'b' > >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 7 ].first == internal::demangle< foo >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 8 ].first == internal::demangle< eof >() ); - TAO_PEGTL_TEST_ASSERT( applied[ 9 ].first == internal::demangle< bar >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 0 ].first == tao::demangle< one< 'b' > >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 1 ].first == tao::demangle< foo >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 2 ].first == tao::demangle< at< one< 'a' > > >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 3 ].first == tao::demangle< two< 'a' > >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 4 ].first == tao::demangle< fiz >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 5 ].first == tao::demangle< foo >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 6 ].first == tao::demangle< one< 'b' > >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 7 ].first == tao::demangle< foo >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 8 ].first == tao::demangle< eof >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 9 ].first == tao::demangle< bar >() ); TAO_PEGTL_TEST_ASSERT( applied[ 0 ].second == "b" ); TAO_PEGTL_TEST_ASSERT( applied[ 1 ].second == "b" ); @@ -60,7 +60,7 @@ namespace TAO_PEGTL_NAMESPACE template< typename ActionInput > static void apply( const ActionInput& in ) { - applied.emplace_back( internal::demangle< Rule >(), in.string() ); + applied.emplace_back( tao::demangle< Rule >(), in.string() ); } }; @@ -69,7 +69,7 @@ namespace TAO_PEGTL_NAMESPACE parse< disable< test1::bar >, test_action >( memory_input( "baab", __FUNCTION__ ) ); TAO_PEGTL_TEST_ASSERT( applied.size() == 1 ); - TAO_PEGTL_TEST_ASSERT( applied[ 0 ].first == internal::demangle< disable< test1::bar > >() ); + TAO_PEGTL_TEST_ASSERT( applied[ 0 ].first == tao::demangle< disable< test1::bar > >() ); TAO_PEGTL_TEST_ASSERT( applied[ 0 ].second == "baab" ); applied.clear(); diff --git a/packages/PEGTL/src/test/pegtl/actions_two.cpp b/packages/PEGTL/src/test/pegtl/actions_two.cpp index a21d222ff32abb8014c7e0f9a6906298ccf8c2d3..d3dcb224ee3d83324ca39e5eebd72ea6d95338da 100644 --- a/packages/PEGTL/src/test/pegtl/actions_two.cpp +++ b/packages/PEGTL/src/test/pegtl/actions_two.cpp @@ -91,7 +91,7 @@ namespace TAO_PEGTL_NAMESPACE const std::size_t count_byte = 12345; const std::size_t count_line = 42; - const std::size_t count_byte_in_line = 12; + const std::size_t count_column = 12; const char* count_source = "count_source"; @@ -103,7 +103,7 @@ namespace TAO_PEGTL_NAMESPACE { TAO_PEGTL_TEST_ASSERT( in.iterator().byte == count_byte ); TAO_PEGTL_TEST_ASSERT( in.iterator().line == count_line ); - TAO_PEGTL_TEST_ASSERT( in.iterator().byte_in_line == count_byte_in_line ); + TAO_PEGTL_TEST_ASSERT( in.iterator().column == count_column ); TAO_PEGTL_TEST_ASSERT( in.input().source() == count_source ); TAO_PEGTL_TEST_ASSERT( in.size() == 1 ); TAO_PEGTL_TEST_ASSERT( in.begin() + 1 == in.end() ); @@ -115,7 +115,7 @@ namespace TAO_PEGTL_NAMESPACE void count_test() { const char* foo = "f"; - memory_input in( foo, foo + 1, count_source, count_byte, count_line, count_byte_in_line ); + memory_input in( foo, foo + 1, count_source, count_byte, count_line, count_column ); const auto result = parse< must< alpha >, count_action >( in ); TAO_PEGTL_TEST_ASSERT( result ); } diff --git a/packages/PEGTL/src/test/pegtl/ascii_classes.cpp b/packages/PEGTL/src/test/pegtl/ascii_classes.cpp index c3301af9784c8cdd7dc3312b0945fc4f82452222..8271091cbe15d587337bf8d17b5016d758a096eb 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_classes.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_classes.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_char.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_eol.cpp b/packages/PEGTL/src/test/pegtl/ascii_eol.cpp index 9724234d375da805ad1ae7de7de235b3ffe0921f..2d46c03a5b49600fd060201f49afc863c43862f4 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_eol.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_eol.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_char.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_eolf.cpp b/packages/PEGTL/src/test/pegtl/ascii_eolf.cpp index 2cb54e528a1390a4e1f1f72490c8fa39344b9f16..c91c155100b4e230c32cf559d5f6b6b3c26201c6 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_eolf.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_eolf.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_char.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_forty_two.cpp b/packages/PEGTL/src/test/pegtl/ascii_forty_two.cpp index fcce5471fefbd91eaa0a07bf5b8b2b297e6a3687..1bbc0c01db01dda98b504969936f5971fa05783f 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_forty_two.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_forty_two.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_identifier.cpp b/packages/PEGTL/src/test/pegtl/ascii_identifier.cpp index 3a4fcbceb5cf43451afabe5469e5f91c60052fa1..5d521d4d2745c74b286ef486b0f08cfd7524f3d0 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_identifier.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_identifier.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_istring.cpp b/packages/PEGTL/src/test/pegtl/ascii_istring.cpp index 73a9e733fbc181586a27e095cb524354c5239f92..b29b8a6eceafe1771a7f2b0d8b7e3334954b3e4d 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_istring.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_istring.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_keyword.cpp b/packages/PEGTL/src/test/pegtl/ascii_keyword.cpp index 17746344dbd488e701312e6684a6adb1d1b83e80..6959625add9b26b1a96ea6828573039e4ad33591 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_keyword.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_keyword.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_shebang.cpp b/packages/PEGTL/src/test/pegtl/ascii_shebang.cpp index 57042c9a2f0c7cae8c188d8f4238e530339f48c5..47d9bc9b3a82dcfb6a73e7c81c84f18dd5e3ea9a 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_shebang.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_shebang.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_string.cpp b/packages/PEGTL/src/test/pegtl/ascii_string.cpp index 6d24356c9ac5e4d416751f8ffd724710b1ba5d80..bc97c6f947902773937886792ee2e6937dc0bc63 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_string.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_string.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_three.cpp b/packages/PEGTL/src/test/pegtl/ascii_three.cpp index 23a9226306333bf57e75311db35c7b0c9634c5c5..e6341dcc4bb1df8c019324eabd0c5434ff5494e6 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_three.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_three.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/ascii_two.cpp b/packages/PEGTL/src/test/pegtl/ascii_two.cpp index 020954b185a013a436acb149209f4df77c207788..5ca9d36b00716d44f8ed924e1ef421c648bbba19 100644 --- a/packages/PEGTL/src/test/pegtl/ascii_two.cpp +++ b/packages/PEGTL/src/test/pegtl/ascii_two.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/contrib_analyze.cpp b/packages/PEGTL/src/test/pegtl/contrib_analyze.cpp index dee2d0408fa9d1188cb7cd556b53625e6092710a..65f1d4831fc4be550caf3fb191114105fe7e4af0 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_analyze.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_analyze.cpp @@ -2,12 +2,35 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" namespace TAO_PEGTL_NAMESPACE { + template< typename... Rules > + struct strange + { + using rule_t = strange; + using subs_t = type_list< Rules... >; + + static_assert( sizeof...( Rules ) > 1 ); + + // Pretend to be a rule that consumes on success by itself _and_ has sub-rules, + // to test a supported combination even though it is not frequently encountered. + }; + + template< typename Name, typename... Rules > + struct analyze_traits< Name, strange< Rules... > > + : analyze_any_traits< Rules... > + {}; + void unit_test() { + verify_analyze< strange< alpha, digit > >( __LINE__, __FILE__, true, false ); + verify_analyze< strange< opt< alpha >, opt< digit > > >( __LINE__, __FILE__, true, false ); + + verify_analyze< strange< star< star< alpha > >, digit > >( __LINE__, __FILE__, true, true ); + verify_analyze< strange< digit, star< star< alpha > > > >( __LINE__, __FILE__, true, true ); + verify_analyze< eof >( __LINE__, __FILE__, false, false ); verify_analyze< eolf >( __LINE__, __FILE__, false, false ); verify_analyze< success >( __LINE__, __FILE__, false, false ); diff --git a/packages/PEGTL/src/test/pegtl/contrib_control_action.cpp b/packages/PEGTL/src/test/pegtl/contrib_control_action.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d03133953e1cfaf098ea167dcb30be1b4372bd9 --- /dev/null +++ b/packages/PEGTL/src/test/pegtl/contrib_control_action.cpp @@ -0,0 +1,140 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <string> + +#include "test.hpp" + +#include <tao/pegtl/contrib/control_action.hpp> + +namespace TAO_PEGTL_NAMESPACE +{ + template< typename Rule > + struct test_action + : nothing< Rule > + {}; + + struct first_rule + : sor< alpha, digit > + {}; + + struct second_rule + : must< alnum > + {}; + + std::string story; + + template<> + struct test_action< first_rule > + : control_action + { + template< typename ParseInput > + static void start( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'a'; + } + + template< typename ParseInput > + static void success( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'b'; + } + + template< typename ParseInput > + static void failure( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'c'; + } + }; + + template<> + struct test_action< alpha > + : control_action + { + template< typename ParseInput > + static void start( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'd'; + } + + template< typename ParseInput > + static void success( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'e'; + } + template< typename ParseInput > + static void failure( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'f'; + } + }; + + template<> + struct test_action< digit > + : control_action + { + template< typename ParseInput > + static void start( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'g'; + } + + template< typename ParseInput > + static void success( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'h'; + } + template< typename ParseInput > + static void failure( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'i'; + } + }; + + template<> + struct test_action< second_rule > + : control_action + { + template< typename ParseInput > + static void start( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'j'; + } + + template< typename ParseInput > + static void success( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'k'; + } + template< typename ParseInput > + static void failure( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'l'; + } + + template< typename ParseInput > + static void unwind( const ParseInput& /*unused*/, int /*unused*/ ) + { + story += 'm'; + } + }; + + void unit_test() + { + { + memory_input in( "0", __FUNCTION__ ); + const auto b = parse< first_rule, test_action >( in, 42 ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( story == "adfghb" ); + } + story.clear(); + { + memory_input in( "*", __FUNCTION__ ); + TAO_PEGTL_TEST_THROWS( parse< second_rule, test_action >( in, 42 ) ); + TAO_PEGTL_TEST_ASSERT( story == "jm" ); + } + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/packages/PEGTL/src/test/pegtl/contrib_http.cpp b/packages/PEGTL/src/test/pegtl/contrib_http.cpp index b4f74cd5adc0e3c5a2cdceccd8351e38a0ca0272..0273d43b10a34b25b94bf35bda4bc5ffaa0f4639 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_http.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_http.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include <tao/pegtl/contrib/http.hpp> diff --git a/packages/PEGTL/src/test/pegtl/contrib_integer.cpp b/packages/PEGTL/src/test/pegtl/contrib_integer.cpp index 9290f670de8575ba55f0feacaeaaee80912ac2c2..0a9cc8eaf857e700bb96b0ea237e5dee69b506e7 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_integer.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_integer.cpp @@ -6,19 +6,13 @@ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" #include <tao/pegtl/contrib/integer.hpp> namespace TAO_PEGTL_NAMESPACE { - template< typename I > - struct int_state - { - I converted = 55; - }; - template< typename Rule > struct int_action : nothing< Rule > @@ -43,12 +37,6 @@ namespace TAO_PEGTL_NAMESPACE parse< must< signed_rule, eof >, int_action >( in, st ); TAO_PEGTL_TEST_ASSERT( st == s ); } - { - int_state< S > st; - memory_input in( i, __FUNCTION__ ); - parse< must< signed_rule, eof >, int_action >( in, st ); - TAO_PEGTL_TEST_ASSERT( st.converted == s ); - } { S st = -123; memory_input in( i, __FUNCTION__ ); @@ -60,7 +48,7 @@ namespace TAO_PEGTL_NAMESPACE template< typename S > void test_signed( const std::string& i ) { - int_state< S > st; + S st; memory_input in( i, __FUNCTION__ ); TAO_PEGTL_TEST_THROWS( parse< must< signed_rule, eof >, int_action >( in, st ) ); } @@ -76,11 +64,11 @@ namespace TAO_PEGTL_NAMESPACE template< typename S > void test_signed( const S s ) { - int_state< S > st; + S st; const auto i = lexical_cast( s ); memory_input in( i, __FUNCTION__ ); parse< must< signed_rule, eof >, int_action >( in, st ); - TAO_PEGTL_TEST_ASSERT( st.converted == s ); + TAO_PEGTL_TEST_ASSERT( st == s ); } template< typename S > @@ -92,12 +80,6 @@ namespace TAO_PEGTL_NAMESPACE parse< must< unsigned_rule, eof >, int_action >( in, st ); TAO_PEGTL_TEST_ASSERT( st == s ); } - { - int_state< S > st; - memory_input in( i, __FUNCTION__ ); - parse< must< unsigned_rule, eof >, int_action >( in, st ); - TAO_PEGTL_TEST_ASSERT( st.converted == s ); - } { S st = 123; memory_input in( i, __FUNCTION__ ); diff --git a/packages/PEGTL/src/test/pegtl/contrib_json.cpp b/packages/PEGTL/src/test/pegtl/contrib_json.cpp index 67abd1d1d9083abeb67e8d68ed0a5080fa6312b3..2cd30e1320783cbf066e844b8f3d40168b5b41b2 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_json.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_json.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_fail.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" #include <tao/pegtl/contrib/json.hpp> diff --git a/packages/PEGTL/src/test/pegtl/contrib_parse_tree.cpp b/packages/PEGTL/src/test/pegtl/contrib_parse_tree.cpp index 521a8140cdb8d7eaac1c78d370b38ee9cbbbf8f9..bce6834501b9d887fe3cae3bc773a6f6d8998cff 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_parse_tree.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_parse_tree.cpp @@ -13,6 +13,8 @@ namespace TAO_PEGTL_NAMESPACE struct C : one< 'c' > {}; struct D : sor< seq< A, B >, seq< A, C > > {}; + + struct D2 : sor< try_catch< if_must< A, B > >, seq< A, C > > {}; // clang-format on template< typename Rule > @@ -22,28 +24,74 @@ namespace TAO_PEGTL_NAMESPACE void unit_test() { - memory_input in( "ac", "input" ); - const auto r = parse_tree::parse< D, selector >( in ); - TAO_PEGTL_TEST_ASSERT( r->is_root() ); - TAO_PEGTL_TEST_ASSERT( !r->has_content() ); - TAO_PEGTL_TEST_ASSERT( r->children.size() == 1 ); - - const auto& d = r->children.front(); - TAO_PEGTL_TEST_ASSERT( !d->is_root() ); - TAO_PEGTL_TEST_ASSERT( d->is_type< D >() ); - - TAO_PEGTL_TEST_ASSERT( d->has_content() ); - TAO_PEGTL_TEST_ASSERT( d->begin().byte == 0 ); - TAO_PEGTL_TEST_ASSERT( d->end().byte == 2 ); - TAO_PEGTL_TEST_ASSERT( d->string_view() == "ac" ); - - TAO_PEGTL_TEST_ASSERT( d->children.size() == 2 ); - TAO_PEGTL_TEST_ASSERT( d->children.front()->is_type< A >() ); - TAO_PEGTL_TEST_ASSERT( d->children.back()->is_type< C >() ); - - memory_input in2( "x", "input" ); - const auto r2 = parse_tree::parse< D, selector >( in2 ); - TAO_PEGTL_TEST_ASSERT( !r2 ); + { + memory_input in( "ac", "input" ); + const auto r = parse_tree::parse< D, selector >( in ); + TAO_PEGTL_TEST_ASSERT( r ); + TAO_PEGTL_TEST_ASSERT( r->is_root() ); + TAO_PEGTL_TEST_ASSERT( !r->has_content() ); + TAO_PEGTL_TEST_ASSERT( r->children.size() == 1 ); + + const auto& d = r->children.front(); + TAO_PEGTL_TEST_ASSERT( !d->is_root() ); + TAO_PEGTL_TEST_ASSERT( d->is_type< D >() ); + + TAO_PEGTL_TEST_ASSERT( d->has_content() ); + TAO_PEGTL_TEST_ASSERT( d->begin().byte == 0 ); + TAO_PEGTL_TEST_ASSERT( d->end().byte == 2 ); + TAO_PEGTL_TEST_ASSERT( d->string_view() == "ac" ); + + TAO_PEGTL_TEST_ASSERT( d->children.size() == 2 ); + TAO_PEGTL_TEST_ASSERT( d->children.front()->is_type< A >() ); + TAO_PEGTL_TEST_ASSERT( d->children.back()->is_type< C >() ); + + memory_input in2( "x", "input" ); + const auto r2 = parse_tree::parse< D, selector >( in2 ); + TAO_PEGTL_TEST_ASSERT( !r2 ); + } + + { + memory_input in( "ac", "input" ); + const auto r = parse_tree::parse< D2, selector >( in ); + TAO_PEGTL_TEST_ASSERT( r ); + TAO_PEGTL_TEST_ASSERT( r->is_root() ); + TAO_PEGTL_TEST_ASSERT( !r->has_content() ); + + TAO_PEGTL_TEST_ASSERT( r->children.size() == 2 ); + TAO_PEGTL_TEST_ASSERT( r->children.front()->is_type< A >() ); + TAO_PEGTL_TEST_ASSERT( r->children.back()->is_type< C >() ); + } + + { + memory_input in( "ac", "input" ); + const auto r = parse_tree::parse< D2 >( in ); + TAO_PEGTL_TEST_ASSERT( r ); + TAO_PEGTL_TEST_ASSERT( r->is_root() ); + TAO_PEGTL_TEST_ASSERT( !r->has_content() ); + TAO_PEGTL_TEST_ASSERT( r->children.size() == 1 ); + + const auto& d2 = r->children.front(); + TAO_PEGTL_TEST_ASSERT( !d2->is_root() ); + TAO_PEGTL_TEST_ASSERT( d2->is_type< D2 >() ); + + TAO_PEGTL_TEST_ASSERT( d2->has_content() ); + TAO_PEGTL_TEST_ASSERT( d2->begin().byte == 0 ); + TAO_PEGTL_TEST_ASSERT( d2->end().byte == 2 ); + TAO_PEGTL_TEST_ASSERT( d2->string() == "ac" ); + + const auto& internal = d2->children.front(); + TAO_PEGTL_TEST_ASSERT( !internal->is_root() ); + TAO_PEGTL_TEST_ASSERT( internal->is_type< seq< A, C > >() ); + + TAO_PEGTL_TEST_ASSERT( internal->has_content() ); + TAO_PEGTL_TEST_ASSERT( internal->begin().byte == 0 ); + TAO_PEGTL_TEST_ASSERT( internal->end().byte == 2 ); + TAO_PEGTL_TEST_ASSERT( internal->string_view() == "ac" ); + + TAO_PEGTL_TEST_ASSERT( internal->children.size() == 2 ); + TAO_PEGTL_TEST_ASSERT( internal->children.front()->is_type< A >() ); + TAO_PEGTL_TEST_ASSERT( internal->children.back()->is_type< C >() ); + } } } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/contrib_partial_trace.cpp b/packages/PEGTL/src/test/pegtl/contrib_partial_trace.cpp index b8ac7a168bbedd7c66f3020e04e4b35793febec5..5743114608c7c0adabe767034808b880443d4799 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_partial_trace.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_partial_trace.cpp @@ -8,17 +8,17 @@ namespace TAO_PEGTL_NAMESPACE { // clang-format off - struct inner : seq< one< 'a' >, sor< one< 'b' >, one< 'c' > > > {}; + struct inner : seq< one< 'a' >, sor< one< 'b' >, one< 'c' >, inner > > {}; struct outer : seq< one< 'x' >, inner, one< 'y' > > {}; // how to run a tracer on a *part* of the grammar: template< typename > struct partial_action {}; - template<> struct partial_action< inner > : change_control< trace_control > {}; + template<> struct partial_action< inner > : trace_standard {}; // clang-format on void unit_test() { - memory_input in( "xacy", "trace test please ignore" ); + memory_input in( "xaacy", "trace test please ignore" ); const auto result = parse< outer, partial_action >( in ); TAO_PEGTL_TEST_ASSERT( result ); } diff --git a/packages/PEGTL/src/test/pegtl/contrib_raw_string.cpp b/packages/PEGTL/src/test/pegtl/contrib_raw_string.cpp index 95d2737e72d37b5bea2ffce010c4e3e822503b72..6ae1980754fdc5f6402a5a8d96f437312063c00c 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_raw_string.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_raw_string.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_fail.hpp" +#include "verify_meta.hpp" #include <tao/pegtl/contrib/raw_string.hpp> @@ -54,13 +54,13 @@ namespace TAO_PEGTL_NAMESPACE void verify_data( const std::size_t line, const char* file, const char ( &m )[ M ], const char ( &n )[ N ] ) { content.clear(); - memory_input in( m, m + M - 1, file, 0, line, 0 ); + memory_input in( m, m + M - 1, file, 0, line, 1 ); const auto r = parse< Rule, Action >( in ); if( ( !r ) || ( content != std::string_view( n, N - 1 ) ) ) { TAO_PEGTL_TEST_FAILED( "input data [ '" << m << "' ] expected success with [ '" << n << "' ] but got [ '" << content << "' ] result [ " << r << " ]" ); } content.clear(); - memory_input< tracking_mode::lazy > in2( m, m + M - 1, file, 0, line, 0 ); + memory_input< tracking_mode::lazy > in2( m, m + M - 1, file, 0, line, 1 ); const auto r2 = parse< Rule, Action >( in2 ); if( ( !r2 ) || ( content != std::string_view( n, N - 1 ) ) ) { TAO_PEGTL_TEST_FAILED( "input data [ '" << m << "' ] with tracking_mode::lazy expected success with [ '" << n << "' ] but got [ '" << content << "' ] result [ " << r2 << " ]" ); diff --git a/packages/PEGTL/src/test/pegtl/contrib_rep_one_min_max.cpp b/packages/PEGTL/src/test/pegtl/contrib_rep_one_min_max.cpp index b190a0cca7737bf17dd160fdcff57b9f50a491df..ee9ecf7b6c2efa06b9a2249169698f1f03061f12 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_rep_one_min_max.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_rep_one_min_max.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" #include <tao/pegtl/contrib/rep_one_min_max.hpp> diff --git a/packages/PEGTL/src/test/pegtl/contrib_state_control.cpp b/packages/PEGTL/src/test/pegtl/contrib_state_control.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8dc07cf3460ae9082b9b47a1977a45233301b6ac --- /dev/null +++ b/packages/PEGTL/src/test/pegtl/contrib_state_control.cpp @@ -0,0 +1,190 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <iostream> +#include <string_view> +#include <vector> + +#include "test.hpp" + +#include <tao/pegtl/contrib/state_control.hpp> + +namespace TAO_PEGTL_NAMESPACE +{ + struct test_entry + { + std::string_view rule; + std::string_view func; + std::size_t b; + }; + + inline bool operator==( const test_entry& l, const test_entry& r ) noexcept + { + return ( l.rule == r.rule ) && ( l.func == r.func ) && ( l.b == r.b ); + } + + template< bool E > + struct test_state + { + std::vector< test_entry > trace; + + template< typename Rule > + static constexpr bool enable = E; + + template< typename Rule, typename Input, typename... States > + void start( const Input& /*unused*/, const int a, std::size_t& b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + trace.push_back( { demangle< Rule >(), "start", ++b } ); + } + + template< typename Rule, typename Input, typename... States > + void success( const Input& /*unused*/, const int a, std::size_t& b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + trace.push_back( { demangle< Rule >(), "success", ++b } ); + } + + template< typename Rule, typename Input, typename... States > + void failure( const Input& /*unused*/, const int a, std::size_t& b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + trace.push_back( { demangle< Rule >(), "failure", ++b } ); + } + + template< typename Rule, typename Input, typename... States > + void raise( const Input& /*unused*/, const int a, std::size_t& b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + trace.push_back( { demangle< Rule >(), "raise", ++b } ); + } + + template< typename Rule, typename Input, typename... States > + void unwind( const Input& /*unused*/, const int a, std::size_t& b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + trace.push_back( { demangle< Rule >(), "unwind", ++b } ); + } + + template< typename Rule, typename Input, typename... States > + void apply( const Input& /*unused*/, const int a, std::size_t& b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + trace.push_back( { demangle< Rule >(), "apply", ++b } ); + } + + template< typename Rule, typename Input, typename... States > + void apply0( const Input& /*unused*/, const int a, std::size_t& b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + trace.push_back( { demangle< Rule >(), "apply0", ++b } ); + } + }; + + struct test_grammar : must< sor< one< 'a' >, try_catch< seq< one< 'b' >, must< one< 'c' > > > >, two< 'b' > >, eof > + {}; + + template< typename Rule > + struct test_action + : nothing< Rule > + {}; + + bool test_action_one = false; + + template<> + struct test_action< one< 'b' > > + { + static void apply0( const int a, const std::size_t b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + if( test_action_one ) { + TAO_PEGTL_TEST_ASSERT( b == 0 ); + test_action_one = false; + } + else { + TAO_PEGTL_TEST_ASSERT( b == 9 ); + test_action_one = true; + } + } + }; + + bool test_action_two = false; + + template<> + struct test_action< two< 'b' > > + { + template< typename ActionInput > + static void apply( const ActionInput& /*unused*/, const int a, const std::size_t b ) + { + TAO_PEGTL_TEST_ASSERT( a == -1 ); + if( test_action_two ) { + TAO_PEGTL_TEST_ASSERT( b == 0 ); + test_action_two = false; + } + else { + TAO_PEGTL_TEST_ASSERT( b == 19 ); + test_action_two = true; + } + } + }; + + void unit_test() + { + { + test_state< true > st; + memory_input in( "bb", __FUNCTION__ ); + std::size_t b = 0; + const bool result = parse< test_grammar, test_action, state_control< normal >::type >( in, -1, b, st ); + TAO_PEGTL_TEST_ASSERT( result ); + TAO_PEGTL_TEST_ASSERT( test_action_one ); + TAO_PEGTL_TEST_ASSERT( test_action_two ); + TAO_PEGTL_TEST_ASSERT( b == st.trace.size() ); + b = 0; + std::size_t i = 0; + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< test_grammar >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< internal::must< sor< one< 'a' >, try_catch< seq< one< 'b' >, must< one< 'c' > > > >, two< 'b' > > > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< sor< one< 'a' >, try_catch< seq< one< 'b' >, must< one< 'c' > > > >, two< 'b' > > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< one< 'a' > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< one< 'a' > >(), "failure", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< try_catch< seq< one< 'b' >, must< one< 'c' > > > > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< seq< one< 'b' >, must< one< 'c' > > > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< one< 'b' > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< one< 'b' > >(), "apply0", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< one< 'b' > >(), "success", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< must< one< 'c' > > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< one< 'c' > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< one< 'c' > >(), "failure", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< one< 'c' > >(), "raise", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< must< one< 'c' > > >(), "unwind", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< seq< one< 'b' >, must< one< 'c' > > > >(), "unwind", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< try_catch< seq< one< 'b' >, must< one< 'c' > > > > >(), "failure", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< two< 'b' > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< two< 'b' > >(), "apply", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< two< 'b' > >(), "success", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< sor< one< 'a' >, try_catch< seq< one< 'b' >, must< one< 'c' > > > >, two< 'b' > > >(), "success", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< internal::must< sor< one< 'a' >, try_catch< seq< one< 'b' >, must< one< 'c' > > > >, two< 'b' > > > >(), "success", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< internal::must< eof > >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< eof >(), "start", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< eof >(), "success", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< internal::must< eof > >(), "success", ++b } ); + TAO_PEGTL_TEST_ASSERT( st.trace[ i++ ] == test_entry{ demangle< test_grammar >(), "success", ++b } ); + + TAO_PEGTL_TEST_ASSERT( i == st.trace.size() ); + TAO_PEGTL_TEST_ASSERT( b == st.trace.size() ); + } + { + test_state< false > st; + memory_input in( "bb", __FUNCTION__ ); + std::size_t b = 0; + const bool result = parse< test_grammar, test_action, state_control< normal >::type >( in, -1, b, st ); + TAO_PEGTL_TEST_ASSERT( result ); + TAO_PEGTL_TEST_ASSERT( !test_action_one ); + TAO_PEGTL_TEST_ASSERT( !test_action_two ); + TAO_PEGTL_TEST_ASSERT( st.trace.empty() ); + TAO_PEGTL_TEST_ASSERT( b == 0 ); + } + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/packages/PEGTL/src/test/pegtl/contrib_tracer.cpp b/packages/PEGTL/src/test/pegtl/contrib_tracer.cpp index 074c701f71d2eed0486754949762ede23348fd3b..a6f20b1a04b4d87febd4877f128a57cdeac3c339 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_tracer.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_tracer.cpp @@ -7,8 +7,10 @@ namespace TAO_PEGTL_NAMESPACE { - using GRAMMAR = sor< failure, one< 'a' > >; + using GRAMMAR1 = sor< failure, one< 'a' > >; using GRAMMAR2 = seq< one< 'a' >, any, any, any, any, one< 'b' >, eof >; + using GRAMMAR3 = sor< one< 'a' >, one< 'b' > >; + using GRAMMAR4 = try_catch< sor< one< 'a' >, must< one< 'b' > > > >; template< typename Rule > struct trace_action @@ -28,7 +30,7 @@ namespace TAO_PEGTL_NAMESPACE }; template<> - struct trace_action< GRAMMAR > + struct trace_action< GRAMMAR1 > { template< typename... Ts > static void apply( Ts&&... /*unused*/ ) @@ -41,47 +43,41 @@ namespace TAO_PEGTL_NAMESPACE { { memory_input in( "ab", "trace test please ignore" ); - const auto result = parse< GRAMMAR, nothing, trace_control >( in ); + const auto result = standard_trace< GRAMMAR1 >( in ); TAO_PEGTL_TEST_ASSERT( result ); TAO_PEGTL_TEST_ASSERT( a0 == 0 ); TAO_PEGTL_TEST_ASSERT( a == 0 ); } { memory_input in( "ab", "trace test please ignore" ); - const auto result = parse< GRAMMAR, trace_action, trace_control >( in ); + const auto result = standard_trace< GRAMMAR1, trace_action >( in ); TAO_PEGTL_TEST_ASSERT( result ); TAO_PEGTL_TEST_ASSERT( a0 == 1 ); TAO_PEGTL_TEST_ASSERT( a == 1 ); } { - trace_state ts; - memory_input in( "ab", "trace test please ignore" ); - const auto result = parse< GRAMMAR, nothing, trace_control >( in, ts ); + memory_input in( "a\r\n\t\0b", 6, "trace test please ignore" ); + const auto result = standard_trace< GRAMMAR2 >( in ); TAO_PEGTL_TEST_ASSERT( result ); TAO_PEGTL_TEST_ASSERT( a0 == 1 ); TAO_PEGTL_TEST_ASSERT( a == 1 ); } { - trace_state ts; - memory_input in( "ab", "trace test please ignore" ); - const auto result = parse< GRAMMAR, trace_action, trace_control >( in, ts ); + memory_input in( "a\r\n\t\0b", 6, "trace test please ignore" ); + const auto result = standard_trace< GRAMMAR2, trace_action >( in ); TAO_PEGTL_TEST_ASSERT( result ); TAO_PEGTL_TEST_ASSERT( a0 == 2 ); - TAO_PEGTL_TEST_ASSERT( a == 2 ); + TAO_PEGTL_TEST_ASSERT( a == 1 ); } { - trace_state ts; - memory_input in( "a\r\n\t\0b", 6, "trace test please ignore" ); - const auto result = parse< GRAMMAR2, nothing, trace_control >( in, ts ); - TAO_PEGTL_TEST_ASSERT( result ); - TAO_PEGTL_TEST_ASSERT( a0 == 2 ); - TAO_PEGTL_TEST_ASSERT( a == 2 ); + memory_input in( "c", "trace test please ignore" ); + const auto result = standard_trace< GRAMMAR3 >( in ); + TAO_PEGTL_TEST_ASSERT( !result ); } { - trace_state ts; - memory_input in( "a\r\n\t\0b", 6, "trace test please ignore" ); - const auto result = parse< GRAMMAR2, trace_action, trace_control >( in, ts ); - TAO_PEGTL_TEST_ASSERT( result ); + memory_input in( "c", "trace test please ignore" ); + const auto result = standard_trace< GRAMMAR4 >( in ); + TAO_PEGTL_TEST_ASSERT( !result ); } } diff --git a/packages/PEGTL/src/test/pegtl/contrib_uri.cpp b/packages/PEGTL/src/test/pegtl/contrib_uri.cpp index a35ce90992ce71826711abb2d3131b629ec110a8..e77c3996744537c9fc4692705b359ced4de14e94 100644 --- a/packages/PEGTL/src/test/pegtl/contrib_uri.cpp +++ b/packages/PEGTL/src/test/pegtl/contrib_uri.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_fail.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" #include <tao/pegtl/contrib/uri.hpp> diff --git a/packages/PEGTL/src/test/pegtl/control_unwind.cpp b/packages/PEGTL/src/test/pegtl/control_unwind.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad7d1251b84831c605f45256dc4b1e0f29318a8d --- /dev/null +++ b/packages/PEGTL/src/test/pegtl/control_unwind.cpp @@ -0,0 +1,70 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <tao/pegtl.hpp> + +#include "test.hpp" + +namespace TAO_PEGTL_NAMESPACE +{ + struct r + : seq< alpha, digit > + {}; + + template< typename R > + struct a + : nothing< R > + {}; + + template< typename R > + struct c + : normal< R > + {}; + + unsigned flags = 0; + + template<> + struct a< alpha > + { + static void apply0() + { + flags |= 1; + } + }; + + template<> + struct a< digit > + { + static void apply0() + { + throw 42; + } + }; + + template<> + struct c< r > + : normal< r > + { + template< typename Input > + static void unwind( const Input& /*unused*/ ) + { + flags |= 2; + } + }; + + void unit_test() + { + memory_input in( "a1", __FUNCTION__ ); + try { + parse< r, a, c >( in ); + TAO_PEGTL_TEST_ASSERT( false ); + } + catch( const int& e ) { + TAO_PEGTL_TEST_ASSERT( e == 42 ); + } + TAO_PEGTL_TEST_ASSERT( flags == 3 ); + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/packages/PEGTL/src/test/pegtl/demangle.cpp b/packages/PEGTL/src/test/pegtl/demangle.cpp index ee76d1db381833e12ee8df9d72c3792c0c18eb21..8288a5d87ca48d9abf703692f1630b9da73bd198 100644 --- a/packages/PEGTL/src/test/pegtl/demangle.cpp +++ b/packages/PEGTL/src/test/pegtl/demangle.cpp @@ -3,14 +3,14 @@ #include "test.hpp" -#include <tao/pegtl/internal/demangle.hpp> +#include <tao/pegtl/demangle.hpp> namespace TAO_PEGTL_NAMESPACE { template< typename T > void test( const std::string& s ) { - TAO_PEGTL_TEST_ASSERT( internal::demangle< T >() == s ); + TAO_PEGTL_TEST_ASSERT( demangle< T >() == s ); } void unit_test() @@ -23,6 +23,7 @@ namespace TAO_PEGTL_NAMESPACE #elif defined( _MSC_VER ) test< int >( "int" ); test< double >( "double" ); + // in the Microsoft world, class and struct are not the same! test< seq< bytes< 42 >, eof > >( "struct tao::pegtl::seq<struct tao::pegtl::bytes<42>,struct tao::pegtl::eof>" ); #else test< int >( "int" ); diff --git a/packages/PEGTL/src/test/pegtl/enable_control.cpp b/packages/PEGTL/src/test/pegtl/enable_control.cpp new file mode 100644 index 0000000000000000000000000000000000000000..672b4a4a932c97c6baf202d030dc5ee81aa805ae --- /dev/null +++ b/packages/PEGTL/src/test/pegtl/enable_control.cpp @@ -0,0 +1,70 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include <tao/pegtl.hpp> + +#include "test.hpp" + +namespace TAO_PEGTL_NAMESPACE +{ + struct r + : seq< internal::seq< any > > + {}; + + static_assert( !internal::enable_control< internal::seq< any > > ); + static_assert( internal::enable_control< seq< any > > ); + static_assert( !internal::enable_control< internal::seq< internal::seq< any > > > ); + static_assert( internal::enable_control< seq< internal::seq< any > > > ); + static_assert( internal::enable_control< r > ); + + static_assert( !normal< internal::seq< any > >::enable ); + static_assert( normal< seq< any > >::enable ); + static_assert( !normal< internal::seq< internal::seq< any > > >::enable ); + static_assert( normal< seq< internal::seq< any > > >::enable ); + static_assert( normal< r >::enable ); + + template< typename R > + struct a + : nothing< R > + {}; + + unsigned flags = 0; + + template<> + struct a< r > + { + static void apply0() + { + flags |= 0x01; + } + }; + + template<> + struct a< any > + { + static void apply0() + { + flags |= 0x02; + } + }; + + template<> + struct a< internal::seq< any > > + { + static void apply0() + { + flags |= 0x10; + } + }; + + void unit_test() + { + memory_input in( "a", __FUNCTION__ ); + const bool b = parse< r, a >( in ); + TAO_PEGTL_TEST_ASSERT( b ); + TAO_PEGTL_TEST_ASSERT( flags == 3 ); + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/packages/PEGTL/src/test/pegtl/error_message.cpp b/packages/PEGTL/src/test/pegtl/error_message.cpp index 05870afbaf6e2ff595f9eefec1e27fdd6f8543c1..ff4d1780e9d69ce85a727d1d181c98fdb9168d95 100644 --- a/packages/PEGTL/src/test/pegtl/error_message.cpp +++ b/packages/PEGTL/src/test/pegtl/error_message.cpp @@ -13,7 +13,7 @@ namespace test1 struct grammar : sor< a, b > {}; template< typename > inline constexpr const char* error_message = nullptr; - template<> inline constexpr auto error_message< test1::a > = "test123"; + template<> inline constexpr auto error_message< test1::b > = "test123"; struct error { template< typename Rule > static constexpr auto message = error_message< Rule >; }; template< typename Rule > using control = must_if< error >::control< Rule >; @@ -26,11 +26,11 @@ namespace TAO_PEGTL_NAMESPACE void unit_test() { try { - parse< test1::grammar, nothing, test1::control >( memory_input( "b", __FUNCTION__ ) ); + parse< test1::grammar, nothing, test1::control >( memory_input( "c", __FUNCTION__ ) ); TAO_PEGTL_TEST_ASSERT( false ); } catch( const parse_error& e ) { - if( e.what() != std::string( "test123" ) ) { + if( e.message() != "test123" ) { throw; } } diff --git a/packages/PEGTL/src/test/pegtl/file_read.cpp b/packages/PEGTL/src/test/pegtl/file_read.cpp index 00b0184ee21b5190136da3c3334549a952f87bee..66f52fdd54e348df8d2265be8aec14dee403f51a 100644 --- a/packages/PEGTL/src/test/pegtl/file_read.cpp +++ b/packages/PEGTL/src/test/pegtl/file_read.cpp @@ -10,12 +10,8 @@ namespace TAO_PEGTL_NAMESPACE struct open_input : public read_input< P, Eol > { - explicit open_input( const char* in_filename ) - : read_input< P, Eol >( internal::file_open( in_filename ), in_filename ) - {} - - explicit open_input( const std::string& in_filename ) - : open_input( in_filename.c_str() ) + explicit open_input( const std::filesystem::path& path ) + : read_input< P, Eol >( internal::file_open( path ), path ) {} }; diff --git "a/packages/PEGTL/src/test/pegtl/file_\303\244\303\266\303\274\360\235\204\236_data.txt" "b/packages/PEGTL/src/test/pegtl/file_\303\244\303\266\303\274\360\235\204\236_data.txt" new file mode 100644 index 0000000000000000000000000000000000000000..d1c7bba09c907f77a6eb263e90b8a5d5b7873a7e --- /dev/null +++ "b/packages/PEGTL/src/test/pegtl/file_\303\244\303\266\303\274\360\235\204\236_data.txt" @@ -0,0 +1,11 @@ +dummy content +dummy content +dummy content +dummy content +dummy content +dummy content +dummy content +dummy content +dummy content +dummy content +dummy content diff --git a/packages/PEGTL/src/test/pegtl/internal_file_mapper.cpp b/packages/PEGTL/src/test/pegtl/internal_file_mapper.cpp index 567ed28a6e1a1acd846e5831f00eba31cfb008e1..99133ba8b0638b9da36e5498b38f20e4df7f20cc 100644 --- a/packages/PEGTL/src/test/pegtl/internal_file_mapper.cpp +++ b/packages/PEGTL/src/test/pegtl/internal_file_mapper.cpp @@ -16,12 +16,21 @@ namespace TAO_PEGTL_NAMESPACE std::cerr << "pegtl: unit test failed for [ internal::file_mapper ]" << std::endl; ++failed; } - catch( const std::system_error& e ) { + catch( const std::system_error& ) { } catch( ... ) { std::cerr << "pegtl: unit test failed for [ internal::file_mapper ] with unexpected exception" << std::endl; ++failed; } + + const std::string s = "dummy content\n"; + const std::string dummy_content = s + s + s + s + s + s + s + s + s + s + s; + + internal::file_mapper mapper( "src/test/pegtl/file_data.txt" ); + TAO_PEGTL_TEST_ASSERT( !mapper.empty() ); + TAO_PEGTL_TEST_ASSERT( mapper.size() == 154 ); + TAO_PEGTL_TEST_ASSERT( std::string_view( mapper.data(), mapper.size() ) == dummy_content ); + TAO_PEGTL_TEST_ASSERT( std::string_view( mapper.begin(), mapper.end() - mapper.begin() ) == dummy_content ); } } // namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/parse_error.cpp b/packages/PEGTL/src/test/pegtl/parse_error.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6cab22e9a71bb7982b9162cc70e4bbf880ca2af1 --- /dev/null +++ b/packages/PEGTL/src/test/pegtl/parse_error.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include "test.hpp" + +#include "verify_meta.hpp" + +namespace TAO_PEGTL_NAMESPACE +{ + template< tracking_mode M > + void unit_test() + { + const std::string rulename{ demangle< digit >() }; + + memory_input< M > in( "foo\nbar bla blubb\nbaz", "test_source" ); + + try { + parse< seq< identifier, eol, identifier, one< ' ' >, must< digit > > >( in ); + } + catch( const parse_error& e ) { + TAO_PEGTL_TEST_ASSERT( e.what() == "test_source:2:5: parse error matching " + rulename ); + + TAO_PEGTL_TEST_ASSERT( e.message() == "parse error matching " + rulename ); + + TAO_PEGTL_TEST_ASSERT( e.positions().size() == 1 ); + const auto& p = e.positions().front(); + + TAO_PEGTL_TEST_ASSERT( p.byte == 8 ); + TAO_PEGTL_TEST_ASSERT( p.line == 2 ); + TAO_PEGTL_TEST_ASSERT( p.column == 5 ); + TAO_PEGTL_TEST_ASSERT( p.source == "test_source" ); + + TAO_PEGTL_TEST_ASSERT( in.line_at( p ) == "bar bla blubb" ); + + position p2 = p; + p2.source = "foo"; + p2.line = 42; + p2.column = 123; + + parse_error e2 = e; + e2.add_position( std::move( p2 ) ); + + TAO_PEGTL_TEST_ASSERT( e2.what() == "foo:42:123: test_source:2:5: parse error matching " + rulename ); + TAO_PEGTL_TEST_ASSERT( e.what() == "test_source:2:5: parse error matching " + rulename ); + + return; + } + TAO_PEGTL_TEST_UNREACHABLE; + } + + void unit_test() + { + unit_test< tracking_mode::eager >(); + unit_test< tracking_mode::lazy >(); + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/packages/PEGTL/src/test/pegtl/position.cpp b/packages/PEGTL/src/test/pegtl/position.cpp index 92e8e45a0d64692e4bc42ab02c1ca54df1667749..c1912679067f95fd543519135bf6b5eaeb4a7bbd 100644 --- a/packages/PEGTL/src/test/pegtl/position.cpp +++ b/packages/PEGTL/src/test/pegtl/position.cpp @@ -24,7 +24,7 @@ namespace TAO_PEGTL_NAMESPACE TAO_PEGTL_TEST_ASSERT( parse< Rule >( i1 ) ); TAO_PEGTL_TEST_ASSERT( i1.line() == 2 ); - TAO_PEGTL_TEST_ASSERT( i1.byte_in_line() == 0 ); + TAO_PEGTL_TEST_ASSERT( i1.column() == 1 ); } template< typename Rule, typename ParseInput = memory_input<> > @@ -36,7 +36,7 @@ namespace TAO_PEGTL_NAMESPACE TAO_PEGTL_TEST_ASSERT( parse< Rule >( i2 ) ); TAO_PEGTL_TEST_ASSERT( i2.line() == 1 ); - TAO_PEGTL_TEST_ASSERT( i2.byte_in_line() == 1 ); + TAO_PEGTL_TEST_ASSERT( i2.column() == 2 ); } template< typename Rule, typename ParseInput = memory_input<> > @@ -48,7 +48,7 @@ namespace TAO_PEGTL_NAMESPACE TAO_PEGTL_TEST_ASSERT( !parse< Rule >( i3 ) ); TAO_PEGTL_TEST_ASSERT( i3.line() == 1 ); - TAO_PEGTL_TEST_ASSERT( i3.byte_in_line() == 0 ); + TAO_PEGTL_TEST_ASSERT( i3.column() == 1 ); } struct outer_grammar @@ -73,7 +73,7 @@ namespace TAO_PEGTL_NAMESPACE TAO_PEGTL_TEST_ASSERT( p.source == "outer" ); TAO_PEGTL_TEST_ASSERT( p.byte == 2 ); TAO_PEGTL_TEST_ASSERT( p.line == 1 ); - TAO_PEGTL_TEST_ASSERT( p.byte_in_line == 2 ); + TAO_PEGTL_TEST_ASSERT( p.column == 3 ); memory_input in( "dFF", "inner" ); parse_nested< inner_grammar >( oi, in ); } @@ -87,15 +87,15 @@ namespace TAO_PEGTL_NAMESPACE parse< outer_grammar, outer_action >( oi ); } catch( const parse_error& e ) { - TAO_PEGTL_TEST_ASSERT( e.positions.size() == 2 ); - TAO_PEGTL_TEST_ASSERT( e.positions[ 0 ].source == "inner" ); - TAO_PEGTL_TEST_ASSERT( e.positions[ 0 ].byte == 1 ); - TAO_PEGTL_TEST_ASSERT( e.positions[ 0 ].line == 1 ); - TAO_PEGTL_TEST_ASSERT( e.positions[ 0 ].byte_in_line == 1 ); - TAO_PEGTL_TEST_ASSERT( e.positions[ 1 ].source == "outer" ); - TAO_PEGTL_TEST_ASSERT( e.positions[ 1 ].byte == 2 ); - TAO_PEGTL_TEST_ASSERT( e.positions[ 1 ].line == 1 ); - TAO_PEGTL_TEST_ASSERT( e.positions[ 1 ].byte_in_line == 2 ); + TAO_PEGTL_TEST_ASSERT( e.positions().size() == 2 ); + TAO_PEGTL_TEST_ASSERT( e.positions()[ 0 ].source == "inner" ); + TAO_PEGTL_TEST_ASSERT( e.positions()[ 0 ].byte == 1 ); + TAO_PEGTL_TEST_ASSERT( e.positions()[ 0 ].line == 1 ); + TAO_PEGTL_TEST_ASSERT( e.positions()[ 0 ].column == 2 ); + TAO_PEGTL_TEST_ASSERT( e.positions()[ 1 ].source == "outer" ); + TAO_PEGTL_TEST_ASSERT( e.positions()[ 1 ].byte == 2 ); + TAO_PEGTL_TEST_ASSERT( e.positions()[ 1 ].line == 1 ); + TAO_PEGTL_TEST_ASSERT( e.positions()[ 1 ].column == 3 ); } } diff --git a/packages/PEGTL/src/test/pegtl/rule_action.cpp b/packages/PEGTL/src/test/pegtl/rule_action.cpp index 6b0c1c0dc0f11c0eefc7d50b512d49837ee42ee0..2e5096da0c437c788d73ddf50d032bcb6d5b9065 100644 --- a/packages/PEGTL/src/test/pegtl/rule_action.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_action.cpp @@ -2,6 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" + +#include "verify_meta.hpp" #include "verify_seqs.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_apply.cpp b/packages/PEGTL/src/test/pegtl/rule_apply.cpp index 92bf49220e739f065c782161800b5156ed46a9a6..147e27936eb67e2179a8725a5aa16585365daa50 100644 --- a/packages/PEGTL/src/test/pegtl/rule_apply.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_apply.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_apply0.cpp b/packages/PEGTL/src/test/pegtl/rule_apply0.cpp index 4a25a5b3922409bcaa610d1b4fd7e019a1fbe094..1a5aebe7744ae421732a66289a017599bb9c1c20 100644 --- a/packages/PEGTL/src/test/pegtl/rule_apply0.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_apply0.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_at.cpp b/packages/PEGTL/src/test/pegtl/rule_at.cpp index 3d7f6dd484ed45ca35161a6476779f30f2c61c95..0fd1626781d3ca9eb6c25ec2d31836b2fe02e7c8 100644 --- a/packages/PEGTL/src/test/pegtl/rule_at.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_at.cpp @@ -2,7 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" + +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_bof.cpp b/packages/PEGTL/src/test/pegtl/rule_bof.cpp index ee02311678a3825ed5eafe01ad55a3ebe8f1ecc6..996505c1645ad9bd9ec9273a6ffba2e231a67429 100644 --- a/packages/PEGTL/src/test/pegtl/rule_bof.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_bof.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_bol.cpp b/packages/PEGTL/src/test/pegtl/rule_bol.cpp index d50a41bbedba9aa926a55784b3019fe599bd2f46..cda3de5a6ae3a24dedfef17d68582aa765db51cb 100644 --- a/packages/PEGTL/src/test/pegtl/rule_bol.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_bol.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_bytes.cpp b/packages/PEGTL/src/test/pegtl/rule_bytes.cpp index 9485df93ff904fbc19338ed999d033c1ee8716c0..ea20546d3b80c25fe28db9512c6c05faad23a70d 100644 --- a/packages/PEGTL/src/test/pegtl/rule_bytes.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_bytes.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_char.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_control.cpp b/packages/PEGTL/src/test/pegtl/rule_control.cpp index 7153086e24c9e34bdcbd0d5ddc56fec1e54a6fee..214e536b7010ea6f1d04dbeff3ce4e35c29e0645 100644 --- a/packages/PEGTL/src/test/pegtl/rule_control.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_control.cpp @@ -2,6 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" + +#include "verify_meta.hpp" #include "verify_seqs.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_disable.cpp b/packages/PEGTL/src/test/pegtl/rule_disable.cpp index f48626d9e5be265c60b4a988cd5e66e8f7b2b9b6..f3b67b8ff55ab248327c465cb5fa1aec9d5258ed 100644 --- a/packages/PEGTL/src/test/pegtl/rule_disable.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_disable.cpp @@ -2,6 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" + +#include "verify_meta.hpp" #include "verify_seqs.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_discard.cpp b/packages/PEGTL/src/test/pegtl/rule_discard.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5cb4b52d3a15784cbee390b2d7695a474612cdd7 --- /dev/null +++ b/packages/PEGTL/src/test/pegtl/rule_discard.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include "test.hpp" + +#include "verify_meta.hpp" +#include "verify_rule.hpp" + +namespace TAO_PEGTL_NAMESPACE +{ + void unit_test() + { + verify_meta< discard, internal::discard >(); + + verify_analyze< discard >( __LINE__, __FILE__, false, false ); + + verify_rule< discard >( __LINE__, __FILE__, "", result_type::success, 0 ); + + for( char i = 1; i < 127; ++i ) { + char t[] = { i, 0 }; + verify_rule< discard >( __LINE__, __FILE__, std::string( t ), result_type::success, 1 ); + } + } + +} // namespace TAO_PEGTL_NAMESPACE + +#include "main.hpp" diff --git a/packages/PEGTL/src/test/pegtl/rule_enable.cpp b/packages/PEGTL/src/test/pegtl/rule_enable.cpp index 121b18ce458da1c145df3f132f74fbb8ee3975e0..b045319e4b76b4d1185ee73ea64d321746a3fa19 100644 --- a/packages/PEGTL/src/test/pegtl/rule_enable.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_enable.cpp @@ -2,6 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" + +#include "verify_meta.hpp" #include "verify_seqs.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_eof.cpp b/packages/PEGTL/src/test/pegtl/rule_eof.cpp index 2d200d564fc3b920ebe9cf120e0550fe5bd0f725..f608a1597d745b5de5fc8a2fcd35705ff1be4a89 100644 --- a/packages/PEGTL/src/test/pegtl/rule_eof.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_eof.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_char.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_failure.cpp b/packages/PEGTL/src/test/pegtl/rule_failure.cpp index 2f116fa201fccec496bdf9a7d9deaf6a2db7288a..9beb769b89ce0d27079fffd66e323868b8fd29a5 100644 --- a/packages/PEGTL/src/test/pegtl/rule_failure.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_failure.cpp @@ -2,8 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" #include "verify_char.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_if_must.cpp b/packages/PEGTL/src/test/pegtl/rule_if_must.cpp index 51ef74024c5e9bc45e83701b1f4c8fde7e5a10c2..54297f01d46e7e63e6b6d39c3253581a0bf31c03 100644 --- a/packages/PEGTL/src/test/pegtl/rule_if_must.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_if_must.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_list.cpp b/packages/PEGTL/src/test/pegtl/rule_list.cpp index 08748154bc642f35494232acec7f526c323f3fe6..dfd789f75236b2283e54a81a0a20e90519c32c09 100644 --- a/packages/PEGTL/src/test/pegtl/rule_list.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_list.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_list_must.cpp b/packages/PEGTL/src/test/pegtl/rule_list_must.cpp index 980a4214dc75169bf3749003187aa520a8ccce77..b036d33ce36ff105065c25e90f6e60ac138f39af 100644 --- a/packages/PEGTL/src/test/pegtl/rule_list_must.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_list_must.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_list_tail.cpp b/packages/PEGTL/src/test/pegtl/rule_list_tail.cpp index 02b18f1c5d62ade3db9698d1a7c606fb46f9b779..e121f083b2e43e9c0b7c615614680c727f9188ed 100644 --- a/packages/PEGTL/src/test/pegtl/rule_list_tail.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_list_tail.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_minus.cpp b/packages/PEGTL/src/test/pegtl/rule_minus.cpp index b7c3431b30d899063fb5374d4660a33d26f83a19..8c55093e00cdb4c27bb155ccb90820b7ca32a113 100644 --- a/packages/PEGTL/src/test/pegtl/rule_minus.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_minus.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_not_at.cpp b/packages/PEGTL/src/test/pegtl/rule_not_at.cpp index 7fe69a528d45ab2e6501c1d0f4abee690c685ff7..25dfc9648631ddecb9673b16c9b2eb170ce11f04 100644 --- a/packages/PEGTL/src/test/pegtl/rule_not_at.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_not_at.cpp @@ -2,7 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" + +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_opt.cpp b/packages/PEGTL/src/test/pegtl/rule_opt.cpp index 05507c8c559c188671408d4dd3fdb7cbc71af81c..3c300b9a59a6bb7ba5c6fb7654938a704909a87a 100644 --- a/packages/PEGTL/src/test/pegtl/rule_opt.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_opt.cpp @@ -2,7 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" + +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_opt_must.cpp b/packages/PEGTL/src/test/pegtl/rule_opt_must.cpp index 783b0d994cb14c8b9bda715ce80b7f527433c5c7..e13ef58af6f34396e5444c497241c5b5d1d72873 100644 --- a/packages/PEGTL/src/test/pegtl/rule_opt_must.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_opt_must.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_pad.cpp b/packages/PEGTL/src/test/pegtl/rule_pad.cpp index 5e495b7d587dcb7602a3ed8c3de4e5528e2b1714..a3151dc20a7aca37a218cf7d3b48d1a553064874 100644 --- a/packages/PEGTL/src/test/pegtl/rule_pad.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_pad.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_pad_opt.cpp b/packages/PEGTL/src/test/pegtl/rule_pad_opt.cpp index 7b63fcd7566a8e8c2182ea56821f2f7ed7aea59e..bb06f3e483605f623bcbb6ef219207a5a91d29fb 100644 --- a/packages/PEGTL/src/test/pegtl/rule_pad_opt.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_pad_opt.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_plus.cpp b/packages/PEGTL/src/test/pegtl/rule_plus.cpp index 6882ebfced1f7765c662060b070fff3667ab24d7..6345b4a46a5cc56368d30e4eebce9bc70b16588e 100644 --- a/packages/PEGTL/src/test/pegtl/rule_plus.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_plus.cpp @@ -2,13 +2,17 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" + +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE { void unit_test() { + verify_meta< plus< alpha >, internal::plus< alpha >, alpha >(); + verify_meta< plus< alpha, digit >, internal::plus< internal::seq< alpha, digit > >, internal::seq< alpha, digit > >(); + verify_analyze< plus< eof > >( __LINE__, __FILE__, false, true ); verify_analyze< plus< any > >( __LINE__, __FILE__, true, false ); verify_analyze< plus< eof, eof, eof > >( __LINE__, __FILE__, false, true ); diff --git a/packages/PEGTL/src/test/pegtl/rule_raise.cpp b/packages/PEGTL/src/test/pegtl/rule_raise.cpp new file mode 100644 index 0000000000000000000000000000000000000000..565df60d294c3f90d8546d53fd9018981db0d7fe --- /dev/null +++ b/packages/PEGTL/src/test/pegtl/rule_raise.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#include "test.hpp" + +#include "verify_meta.hpp" + +#if defined( _MSC_VER ) +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +namespace TAO_PEGTL_NAMESPACE +{ + void unit_test() + { + verify_meta< raise< int >, internal::raise< int > >(); + verify_meta< raise< any >, internal::raise< any > >(); + + verify_analyze< raise< int > >( __LINE__, __FILE__, true, false ); + verify_analyze< raise< any > >( __LINE__, __FILE__, true, false ); + + memory_input in( "foo", __FUNCTION__ ); + + TAO_PEGTL_TEST_THROWS( parse< raise< int > >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.size( 4 ) == 3 ); + TAO_PEGTL_TEST_THROWS( parse< raise< any > >( in ) ); + TAO_PEGTL_TEST_ASSERT( in.size( 4 ) == 3 ); + } + +} // namespace TAO_PEGTL_NAMESPACE + +#if defined( _MSC_VER ) +#pragma warning( pop ) +#endif + +#include "main.hpp" diff --git a/packages/PEGTL/src/test/pegtl/rule_rematch.cpp b/packages/PEGTL/src/test/pegtl/rule_rematch.cpp index 6eec3dba03df0aa960660d090371929d39e2845e..ee467deee34864932f88d88e7c1144881fdb9011 100644 --- a/packages/PEGTL/src/test/pegtl/rule_rematch.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_rematch.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_rep.cpp b/packages/PEGTL/src/test/pegtl/rule_rep.cpp index d57410382c60e1940b46ea148b32990f45122fea..b4bd7f97abd7f596e0e391741824c7e111bc54a9 100644 --- a/packages/PEGTL/src/test/pegtl/rule_rep.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_rep.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_rep_max.cpp b/packages/PEGTL/src/test/pegtl/rule_rep_max.cpp index 09b52e8587b2845cfdc5b4bba324c2675a5e48fa..db1205a68e79ba15dca8f677006d539d567ece23 100644 --- a/packages/PEGTL/src/test/pegtl/rule_rep_max.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_rep_max.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_rep_min.cpp b/packages/PEGTL/src/test/pegtl/rule_rep_min.cpp index 73fc6ea3797ac73125756d4dd7ad9700d132f4ed..c3648b94d43c67feb8c1b71938ba0422c517689a 100644 --- a/packages/PEGTL/src/test/pegtl/rule_rep_min.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_rep_min.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_rep_min_max.cpp b/packages/PEGTL/src/test/pegtl/rule_rep_min_max.cpp index 0833aa62c5b558f9f8bd555f272c33a3037e46cf..de847617749f3ff0d6756d6b6c415608fb92aa9e 100644 --- a/packages/PEGTL/src/test/pegtl/rule_rep_min_max.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_rep_min_max.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_rep_opt.cpp b/packages/PEGTL/src/test/pegtl/rule_rep_opt.cpp index 4c66f6eac4070464a368a8c86b51dfeac70fb9a3..5d3cbc708b6c624d6e1301cb3ec051b353efde72 100644 --- a/packages/PEGTL/src/test/pegtl/rule_rep_opt.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_rep_opt.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_require.cpp b/packages/PEGTL/src/test/pegtl/rule_require.cpp index 0d2ce914743f822b7cd8cb7f31ccca0c1b02e56d..4f4206696f49641626100bc79f5721ba15cf3c34 100644 --- a/packages/PEGTL/src/test/pegtl/rule_require.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_require.cpp @@ -2,13 +2,17 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" + +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE { void unit_test() { + verify_meta< require< 0 >, internal::success >(); + verify_meta< require< 1 >, internal::require< 1 > >(); + verify_analyze< require< 0 > >( __LINE__, __FILE__, false, false ); verify_analyze< require< 1 > >( __LINE__, __FILE__, false, false ); verify_analyze< require< 9 > >( __LINE__, __FILE__, false, false ); diff --git a/packages/PEGTL/src/test/pegtl/rule_seq.cpp b/packages/PEGTL/src/test/pegtl/rule_seq.cpp index 22505494a0df37cfee9b0523ef65df5b4335d9c9..c5e3722b3d3c419e05669fdc0dfe668a2c9f281c 100644 --- a/packages/PEGTL/src/test/pegtl/rule_seq.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_seq.cpp @@ -2,12 +2,18 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" + +#include "verify_meta.hpp" #include "verify_seqs.hpp" namespace TAO_PEGTL_NAMESPACE { void unit_test() { + verify_meta< seq<>, internal::success >(); + verify_meta< seq< alpha >, internal::seq< alpha >, alpha >(); + verify_meta< seq< alpha, digit >, internal::seq< alpha, digit >, alpha, digit >(); + verify_seqs< seq >(); } diff --git a/packages/PEGTL/src/test/pegtl/rule_sor.cpp b/packages/PEGTL/src/test/pegtl/rule_sor.cpp index b0792b4432c7b68b6f14ac4cbe3fa87c3aa2d69c..11eb9a623619aa5d3aa546f5a13bd9c7693bb3ce 100644 --- a/packages/PEGTL/src/test/pegtl/rule_sor.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_sor.cpp @@ -2,13 +2,18 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" + +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE { void unit_test() { + verify_meta< sor<>, internal::failure >(); + verify_meta< sor< alpha >, internal::sor< alpha >, alpha >(); + verify_meta< sor< alpha, digit >, internal::sor< alpha, digit >, alpha, digit >(); + verify_analyze< sor< eof > >( __LINE__, __FILE__, false, false ); verify_analyze< sor< any > >( __LINE__, __FILE__, true, false ); diff --git a/packages/PEGTL/src/test/pegtl/rule_star.cpp b/packages/PEGTL/src/test/pegtl/rule_star.cpp index 8cfaa6ca695a69d54eac63338bac3c5dbaa93215..f870d6a4c475e721f595a29516c721d8b49198fa 100644 --- a/packages/PEGTL/src/test/pegtl/rule_star.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_star.cpp @@ -2,13 +2,17 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" + +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE { void unit_test() { + verify_meta< star< alpha >, internal::star< alpha >, alpha >(); + verify_meta< star< alpha, digit >, internal::star< internal::seq< alpha, digit > >, internal::seq< alpha, digit > >(); + verify_analyze< star< eof > >( __LINE__, __FILE__, false, true ); verify_analyze< star< any > >( __LINE__, __FILE__, false, false ); verify_analyze< star< eof, eof, eof > >( __LINE__, __FILE__, false, true ); diff --git a/packages/PEGTL/src/test/pegtl/rule_star_must.cpp b/packages/PEGTL/src/test/pegtl/rule_star_must.cpp index e0f863a3f45860fab3940b56f250067ef9e5d26b..0a6410ad554db9e40ca1c1288bdb7ce5cc3a56ee 100644 --- a/packages/PEGTL/src/test/pegtl/rule_star_must.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_star_must.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/rule_state.cpp b/packages/PEGTL/src/test/pegtl/rule_state.cpp index 77ed17f01bb18186b64b8f6a6b2dd2ffa7647d0b..c940ac224445716b15358e941b6ea77bd15ff108 100644 --- a/packages/PEGTL/src/test/pegtl/rule_state.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_state.cpp @@ -2,6 +2,8 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" + +#include "verify_meta.hpp" #include "verify_seqs.hpp" namespace TAO_PEGTL_NAMESPACE @@ -22,6 +24,10 @@ namespace TAO_PEGTL_NAMESPACE void unit_test() { + verify_meta< state< test_state_state >, internal::success >(); + verify_meta< state< test_state_state, any >, internal::state< test_state_state, any >, any >(); + verify_meta< state< test_state_state, alpha, digit >, internal::state< test_state_state, internal::seq< alpha, digit > >, internal::seq< alpha, digit > >(); + verify_seqs< test_state_rule >(); } diff --git a/packages/PEGTL/src/test/pegtl/rule_success.cpp b/packages/PEGTL/src/test/pegtl/rule_success.cpp index fcaff87acb0fd6f9562dedb90f4c7fd2ba78116e..a6917da3c701a709ca8a2eb24956ed9ec28d4870 100644 --- a/packages/PEGTL/src/test/pegtl/rule_success.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_success.cpp @@ -2,13 +2,16 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" + +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE { void unit_test() { + verify_meta< success, internal::success >(); + verify_analyze< success >( __LINE__, __FILE__, false, false ); verify_rule< success >( __LINE__, __FILE__, "", result_type::success, 0 ); diff --git a/packages/PEGTL/src/test/pegtl/rule_until.cpp b/packages/PEGTL/src/test/pegtl/rule_until.cpp index f1e49d3946460dcf36194298c3a3b4f07ea7128d..24ab38ef008d8ebec2cfad979862dec765925ace 100644 --- a/packages/PEGTL/src/test/pegtl/rule_until.cpp +++ b/packages/PEGTL/src/test/pegtl/rule_until.cpp @@ -2,7 +2,7 @@ // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #include "test.hpp" -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/test.hpp b/packages/PEGTL/src/test/pegtl/test.hpp index 18868e018cd60583c214a4073059bb9aaa193f71..5b017a559477a5b5fb499fdf2c6312b3f237a17c 100644 --- a/packages/PEGTL/src/test/pegtl/test.hpp +++ b/packages/PEGTL/src/test/pegtl/test.hpp @@ -25,7 +25,7 @@ namespace TAO_PEGTL_NAMESPACE #define TAO_PEGTL_TEST_FAILED( MeSSaGe ) \ do { \ std::cerr << "pegtl: unit test failed for [ " \ - << internal::demangle< Rule >() \ + << tao::demangle< Rule >() \ << " ] " \ << TAO_PEGTL_TEST_UNWRAP( MeSSaGe ) \ << " in line [ " \ @@ -67,4 +67,10 @@ namespace TAO_PEGTL_NAMESPACE } \ } while( false ) +#define TAO_PEGTL_TEST_UNREACHABLE \ + do { \ + std::cerr << "Code should be unreachable in " << __FUNCTION__ << " (" << __FILE__ << ':' << __LINE__ << ')' << std::endl; \ + std::abort(); \ + } while( false ) + #endif diff --git a/packages/PEGTL/src/test/pegtl/verify_file.hpp b/packages/PEGTL/src/test/pegtl/verify_file.hpp index 7ac5683c4444ece26b41c569e5f6c831d09bbb94..2f8a16a87eb1a0d7e59b47819cbadc78b4d965e6 100644 --- a/packages/PEGTL/src/test/pegtl/verify_file.hpp +++ b/packages/PEGTL/src/test/pegtl/verify_file.hpp @@ -8,6 +8,12 @@ #include "test.hpp" +#if defined( _MSC_VER ) +#define TAO_PEGTL_TEST_FILENAME u"src/test/pegtl/file_äöü𝄞_data.txt" +#else +#define TAO_PEGTL_TEST_FILENAME "src/test/pegtl/file_äöü𝄞_data.txt" +#endif + namespace TAO_PEGTL_NAMESPACE { struct file_content @@ -51,9 +57,8 @@ namespace TAO_PEGTL_NAMESPACE void verify_file() { { - const std::string f{ "src/test/pegtl/no_such_file.txt" }; try { - T in( f ); + T in( "src/test/pegtl/no_such_file.txt" ); parse< file_grammar >( in ); TAO_PEGTL_TEST_ASSERT( !"no error on opening non-existing file" ); } @@ -61,43 +66,34 @@ namespace TAO_PEGTL_NAMESPACE } } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( "src/test/pegtl/file_data.txt" ); std::cout << in.source() << std::endl; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); + TAO_PEGTL_TEST_ASSERT( in.source() == "src/test/pegtl/file_data.txt" ); TAO_PEGTL_TEST_ASSERT( parse< file_grammar >( in ) ); - TAO_PEGTL_TEST_ASSERT( in.source() == f ); + TAO_PEGTL_TEST_ASSERT( in.source() == "src/test/pegtl/file_data.txt" ); } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( TAO_PEGTL_TEST_FILENAME ); bool flag = true; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); TAO_PEGTL_TEST_ASSERT( parse< file_grammar >( in, flag ) ); TAO_PEGTL_TEST_ASSERT( flag == true ); } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( TAO_PEGTL_TEST_FILENAME ); bool flag = false; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); TAO_PEGTL_TEST_ASSERT( parse< file_grammar >( in, flag ) ); TAO_PEGTL_TEST_ASSERT( flag == false ); } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( TAO_PEGTL_TEST_FILENAME ); bool flag = false; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); const bool result = parse< file_grammar, file_action >( in, flag ); TAO_PEGTL_TEST_ASSERT( result ); TAO_PEGTL_TEST_ASSERT( flag == true ); } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( TAO_PEGTL_TEST_FILENAME ); bool flag = false; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); const bool result = parse< file_grammar, nothing, file_control >( in, flag ); TAO_PEGTL_TEST_ASSERT( result ); TAO_PEGTL_TEST_ASSERT( flag == true ); @@ -105,42 +101,31 @@ namespace TAO_PEGTL_NAMESPACE const char* foo = "foo"; const memory_input m( foo, foo + 3, foo ); { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); - TAO_PEGTL_TEST_ASSERT( in.source() == f ); + T in( TAO_PEGTL_TEST_FILENAME ); TAO_PEGTL_TEST_ASSERT( parse_nested< file_grammar >( m, in ) ); - TAO_PEGTL_TEST_ASSERT( in.source() == f ); } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( TAO_PEGTL_TEST_FILENAME ); bool flag = true; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); TAO_PEGTL_TEST_ASSERT( parse_nested< file_grammar >( m, in, flag ) ); TAO_PEGTL_TEST_ASSERT( flag == true ); } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( TAO_PEGTL_TEST_FILENAME ); bool flag = false; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); TAO_PEGTL_TEST_ASSERT( parse_nested< file_grammar >( m, in, flag ) ); TAO_PEGTL_TEST_ASSERT( flag == false ); } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( TAO_PEGTL_TEST_FILENAME ); bool flag = false; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); const bool result = parse_nested< file_grammar, file_action >( m, in, flag ); TAO_PEGTL_TEST_ASSERT( result ); TAO_PEGTL_TEST_ASSERT( flag == true ); } { - const std::string f{ "src/test/pegtl/file_data.txt" }; - T in( f ); + T in( TAO_PEGTL_TEST_FILENAME ); bool flag = false; - TAO_PEGTL_TEST_ASSERT( in.source() == f ); const bool result = parse_nested< file_grammar, nothing, file_control >( m, in, flag ); TAO_PEGTL_TEST_ASSERT( result ); TAO_PEGTL_TEST_ASSERT( flag == true ); diff --git a/packages/PEGTL/src/test/pegtl/verify_ifmt.hpp b/packages/PEGTL/src/test/pegtl/verify_ifmt.hpp index ac9368178f87a178b186d7fd68c8334a1d42c30f..0e17e8c75a95df897949e4c44301567941a9f1e4 100644 --- a/packages/PEGTL/src/test/pegtl/verify_ifmt.hpp +++ b/packages/PEGTL/src/test/pegtl/verify_ifmt.hpp @@ -6,7 +6,7 @@ #include <tao/pegtl.hpp> -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/packages/PEGTL/src/test/pegtl/verify_impl.hpp b/packages/PEGTL/src/test/pegtl/verify_impl.hpp index 83ad2977ca4f4d6abc0e540f594d7bbfbe026ff6..b98cf45a35af2cdcc57fa9297adad95065f1b0c1 100644 --- a/packages/PEGTL/src/test/pegtl/verify_impl.hpp +++ b/packages/PEGTL/src/test/pegtl/verify_impl.hpp @@ -31,8 +31,7 @@ namespace TAO_PEGTL_NAMESPACE return result_type::global_failure; } catch( ... ) { - std::cerr << "Code should be unreachable in " << __FUNCTION__ << " (" << __FILE__ << ':' << __LINE__ << ')' << std::endl; - std::abort(); + TAO_PEGTL_TEST_UNREACHABLE; } } diff --git a/packages/PEGTL/src/test/pegtl/verify_analyze.hpp b/packages/PEGTL/src/test/pegtl/verify_meta.hpp similarity index 70% rename from packages/PEGTL/src/test/pegtl/verify_analyze.hpp rename to packages/PEGTL/src/test/pegtl/verify_meta.hpp index befefba5b6d8eaf5046aaf672db2719719507718..9c005eb9f197a45cc7edaa1cf12592656421bbb3 100644 --- a/packages/PEGTL/src/test/pegtl/verify_analyze.hpp +++ b/packages/PEGTL/src/test/pegtl/verify_meta.hpp @@ -1,8 +1,12 @@ // Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAO_PEGTL_SRC_TEST_PEGTL_VERIFY_ANALYZE_HPP -#define TAO_PEGTL_SRC_TEST_PEGTL_VERIFY_ANALYZE_HPP +#ifndef TAO_PEGTL_SRC_TEST_PEGTL_VERIFY_META_HPP +#define TAO_PEGTL_SRC_TEST_PEGTL_VERIFY_META_HPP + +#include <type_traits> + +#include <tao/pegtl/type_list.hpp> #include <tao/pegtl/contrib/analyze.hpp> @@ -10,6 +14,13 @@ namespace TAO_PEGTL_NAMESPACE { + template< typename Name, typename Rule, typename... Rules > + void verify_meta() + { + static_assert( std::is_same_v< typename Name::rule_t, Rule > ); + static_assert( std::is_same_v< typename Name::subs_t, type_list< Rules... > > ); + } + template< typename Rule > void verify_analyze( const unsigned line, const char* file, const bool expect_consume, const bool expect_problems ) { diff --git a/packages/PEGTL/src/test/pegtl/verify_rule.hpp b/packages/PEGTL/src/test/pegtl/verify_rule.hpp index fc614e06da2d5a0711f804544a245833de4cd1d3..4ee93a9c8bc228894736da8221f234e2514aa193 100644 --- a/packages/PEGTL/src/test/pegtl/verify_rule.hpp +++ b/packages/PEGTL/src/test/pegtl/verify_rule.hpp @@ -17,13 +17,6 @@ namespace TAO_PEGTL_NAMESPACE { - template< typename Name, typename Rule, typename... Rules > - void verify_meta() - { - static_assert( std::is_same_v< typename Name::rule_t, Rule > ); - static_assert( std::is_same_v< typename Name::subs_t, type_list< Rules... > > ); - } - template< typename Rule > struct verify_action_impl { @@ -47,19 +40,19 @@ namespace TAO_PEGTL_NAMESPACE remain = ( expected == result_type::success ) ? 0 : int( data.size() ); } { - memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 0 ); + memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 1 ); verify_impl_one< Rule, nothing >( line, file, data, in, expected, remain ); memory_input< tracking_mode::lazy, Eol > i2( data.data(), data.data() + data.size(), file ); verify_impl_one< Rule, nothing >( line, file, data, i2, expected, remain ); } { - memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 0 ); + memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 1 ); verify_impl_one< Rule, verify_action_impl >( line, file, data, in, expected, remain ); memory_input< tracking_mode::lazy, Eol > i2( data.data(), data.data() + data.size(), file ); verify_impl_one< Rule, verify_action_impl >( line, file, data, i2, expected, remain ); } { - memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 0 ); + memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 1 ); verify_impl_one< Rule, verify_action_impl0 >( line, file, data, in, expected, remain ); memory_input< tracking_mode::lazy, Eol > i2( data.data(), data.data() + data.size(), file ); verify_impl_one< Rule, verify_action_impl0 >( line, file, data, i2, expected, remain ); @@ -70,15 +63,15 @@ namespace TAO_PEGTL_NAMESPACE void verify_only( const std::size_t line, const char* file, const std::string& data, const result_type expected, const std::size_t remain ) { { - memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 0 ); + memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 1 ); verify_impl_one< Rule, nothing >( line, file, data, in, expected, remain ); } { - memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 0 ); + memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 1 ); verify_impl_one< Rule, verify_action_impl >( line, file, data, in, expected, remain ); } { - memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 0 ); + memory_input< tracking_mode::eager, Eol > in( data.data(), data.data() + data.size(), file, 0, line, 1 ); verify_impl_one< Rule, verify_action_impl0 >( line, file, data, in, expected, remain ); } } diff --git a/packages/PEGTL/src/test/pegtl/verify_seqs.hpp b/packages/PEGTL/src/test/pegtl/verify_seqs.hpp index 82d84b0e8bd026a56d2fb0d911f2e27e4ba10fa4..29c21681233b6682511640ee51cf5732f001f99b 100644 --- a/packages/PEGTL/src/test/pegtl/verify_seqs.hpp +++ b/packages/PEGTL/src/test/pegtl/verify_seqs.hpp @@ -6,7 +6,7 @@ #include <tao/pegtl.hpp> -#include "verify_analyze.hpp" +#include "verify_meta.hpp" #include "verify_rule.hpp" namespace TAO_PEGTL_NAMESPACE diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index 336fb5583fb4e163f37feb30956acbf27cef36ab..61ba912a567c4a6d868d22cc7915e7557f484518 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -3,6 +3,8 @@ #include <pegtl.hpp> +#include <language/utils/ParseError.hpp> + using namespace TAO_PEGTL_NAMESPACE; namespace language @@ -325,12 +327,12 @@ struct errors : public normal<Rule> static void raise(const Input& in, States&&... /*unused*/) { - throw parse_error(error_message, std::vector{in.position()}); + throw ParseError(error_message, std::vector{in.position()}); } }; template <typename Rule> -inline const std::string errors<Rule>::error_message = "parse error matching "+ demangle(internal::demangle< Rule >()); +inline const std::string errors<Rule>::error_message = "parse error matching "+ demangle(tao::demangle< Rule >()); template <> inline const std::string errors<language::module_name>::error_message = "parse error, missing module name"; diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp index 235eab368dccfd2c41dde312a6f24264388a7813..75842ad029795a579a213b2d50bed15bcfb68b30 100644 --- a/src/language/PugsParser.cpp +++ b/src/language/PugsParser.cpp @@ -90,14 +90,14 @@ parser(const std::string& filename) try { parse_and_execute(input); } - catch (const parse_error& e) { - const auto p = e.positions.front(); + catch (const ParseError& e) { + const auto p = e.positions().front(); - std::cerr << rang::style::bold << p.source << ':' << p.line << ':' << p.byte_in_line << ": " << rang::style::reset + std::cerr << rang::style::bold << p.source << ':' << p.line << ':' << p.column << ": " << rang::style::reset << rang::fgB::red << "error: " << rang::fg::reset << rang::style::bold << e.what() << rang::style::reset << '\n' << input.line_at(p) << '\n' - << std::string(p.byte_in_line, ' ') << rang::fgB::yellow << '^' << rang::fg::reset << '\n'; + << std::string(p.column, ' ') << rang::fgB::yellow << '^' << rang::fg::reset << '\n'; finalize(); std::exit(1); } diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp index 43bd40932c82310d039f851c9ddc810744c6f72b..e27bd531d743b410ecb381e665bb4af145e4731f 100644 --- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp @@ -4,6 +4,7 @@ #include <language/PEGGrammar.hpp> #include <language/ast/ASTNodeNaturalConversionChecker.hpp> #include <language/node_processor/AffectationProcessor.hpp> +#include <language/utils/ParseError.hpp> #include <utils/Exceptions.hpp> @@ -33,8 +34,8 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined operand type for affectation", - std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: undefined operand type for affectation", + std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } @@ -83,7 +84,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } } // LCOV_EXCL_START - throw parse_error("unexpected error: invalid integral value", std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: invalid integral value", std::vector{n.children[1]->begin()}); // LCOV_EXCL_STOP } case ASTNodeDataType::double_t: { @@ -94,7 +95,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid operand type", std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: invalid operand type", std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } @@ -107,7 +108,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid operand type", std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: invalid operand type", std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } @@ -130,11 +131,11 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode break; } default: { - throw parse_error("expecting scalar operand type", std::vector{n.children[1]->begin()}); + throw ParseError("expecting scalar operand type", std::vector{n.children[1]->begin()}); } } } else { - throw parse_error("invalid affectation operator for " + dataTypeName(n.m_data_type), std::vector{n.begin()}); + throw ParseError("invalid affectation operator for " + dataTypeName(n.m_data_type), std::vector{n.begin()}); } }; @@ -179,8 +180,8 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector dimension for string affectation", - std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: invalid vector dimension for string affectation", + std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } @@ -188,13 +189,13 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined operand type for string affectation", - std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: undefined operand type for string affectation", + std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } } else { - throw parse_error("invalid affectation operator for string", std::vector{n.begin()}); + throw ParseError("invalid affectation operator for string", std::vector{n.begin()}); } }; @@ -209,14 +210,14 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined operand type for embedded data affectation", - std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: undefined operand type for embedded data affectation", + std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } } else { - throw parse_error("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'", - std::vector{n.begin()}); + throw ParseError("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'", + std::vector{n.begin()}); } }; @@ -266,8 +267,8 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector dimension for tuple affectation", - std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: invalid vector dimension for tuple affectation", + std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } @@ -321,8 +322,8 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector dimension for tuple affectation", - std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: invalid vector dimension for tuple affectation", + std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } @@ -330,15 +331,15 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined operand type for tuple affectation", - std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: undefined operand type for tuple affectation", + std::vector{n.children[1]->begin()}); } // LCOV_EXCL_STOP } } } else { - throw parse_error("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'", - std::vector{n.begin()}); + throw ParseError("invalid affectation operator for '" + dataTypeName(n.children[0]->m_data_type) + "'", + std::vector{n.begin()}); } }; @@ -378,7 +379,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: unexpected vector dimension", std::vector{n.begin()}); + throw ParseError("unexpected error: unexpected vector dimension", std::vector{n.begin()}); } // LCOV_EXCL_STOP } @@ -398,8 +399,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode break; } default: { - throw parse_error("unexpected error: undefined value type for affectation", - std::vector{n.children[0]->begin()}); + throw ParseError("unexpected error: undefined value type for affectation", std::vector{n.children[0]->begin()}); } } }; @@ -430,6 +430,6 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } else if (n.is_type<language::minuseq_op>()) { set_affectation_processor(n, language::minuseq_op{}); } else { - throw parse_error("unexpected error: undefined affectation operator", std::vector{n.begin()}); + throw ParseError("unexpected error: undefined affectation operator", std::vector{n.begin()}); } } diff --git a/src/language/ast/ASTNodeArraySubscriptExpressionBuilder.cpp b/src/language/ast/ASTNodeArraySubscriptExpressionBuilder.cpp index e50b84668b6cb11d900554002ade3d6ba2937608..350a4070e9a6bc65906627d54b2e2ed87c403cc6 100644 --- a/src/language/ast/ASTNodeArraySubscriptExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeArraySubscriptExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <algebra/TinyVector.hpp> #include <language/node_processor/ArraySubscriptProcessor.hpp> +#include <language/utils/ParseError.hpp> ASTNodeArraySubscriptExpressionBuilder::ASTNodeArraySubscriptExpressionBuilder(ASTNode& node) { @@ -22,11 +23,11 @@ ASTNodeArraySubscriptExpressionBuilder::ASTNodeArraySubscriptExpressionBuilder(A break; } default: { - throw parse_error("unexpected error: invalid array dimension", array_expression.begin()); + throw ParseError("unexpected error: invalid array dimension", array_expression.begin()); break; } } } else { - throw parse_error("unexpected error: invalid array type", array_expression.begin()); + throw ParseError("unexpected error: invalid array type", array_expression.begin()); } } diff --git a/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp b/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp index 92074474abd0b1109feee7a53537deac2d4e44d4..64ff14deb191921c81e28ef1b3f36a0651ffc0e2 100644 --- a/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeBinaryOperatorExpressionBuilder.cpp @@ -3,6 +3,7 @@ #include <language/PEGGrammar.hpp> #include <language/node_processor/BinaryExpressionProcessor.hpp> #include <language/node_processor/ConcatExpressionProcessor.hpp> +#include <language/utils/ParseError.hpp> ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(ASTNode& n) { @@ -35,7 +36,7 @@ ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(A break; } default: { - throw parse_error("undefined operand type for binary operator", std::vector{n.children[1]->begin()}); + throw ParseError("undefined operand type for binary operator", std::vector{n.children[1]->begin()}); } } @@ -44,10 +45,10 @@ ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(A if (data_type_b == ASTNodeDataType::string_t) { n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, std::string>>(n); } else { - throw parse_error("undefined operand type for binary operator", std::vector{n.begin()}); + throw ParseError("undefined operand type for binary operator", std::vector{n.begin()}); } } else { - throw parse_error("undefined operand type for binary operator", std::vector{n.begin()}); + throw ParseError("undefined operand type for binary operator", std::vector{n.begin()}); } } else if constexpr (std::is_same_v<DataTA, TinyVector<1>> or std::is_same_v<DataTA, TinyVector<2>> or std::is_same_v<DataTA, TinyVector<3>>) { @@ -58,15 +59,15 @@ ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(A if (data_a.dimension() == data_type_b.dimension()) { n.m_node_processor = std::make_unique<BinaryExpressionProcessor<OperatorT, DataTA, DataTA>>(n); } else { - throw parse_error("incompatible dimensions of operands", std::vector{n.begin()}); + throw ParseError("incompatible dimensions of operands", std::vector{n.begin()}); } } else { - throw parse_error("invalid binary operator", std::vector{n.begin()}); + throw ParseError("invalid binary operator", std::vector{n.begin()}); } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid operand type for binary operator", - std::vector{n.children[1]->begin()}); + throw ParseError("unexpected error: invalid operand type for binary operator", + std::vector{n.children[1]->begin()}); // LCOV_EXCL_STOP } } else { @@ -104,7 +105,7 @@ ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(A } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid dimension", std::vector{n.children[0]->begin()}); + throw ParseError("unexpected error: invalid dimension", std::vector{n.children[0]->begin()}); } // LCOV_EXCL_STOP } @@ -112,7 +113,7 @@ ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(A } } default: { - throw parse_error("undefined operand type for binary operator", std::vector{n.children[1]->begin()}); + throw ParseError("undefined operand type for binary operator", std::vector{n.children[1]->begin()}); } } } @@ -157,14 +158,14 @@ ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(A } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid dimension", std::vector{n.children[0]->begin()}); + throw ParseError("unexpected error: invalid dimension", std::vector{n.children[0]->begin()}); } // LCOV_EXCL_STOP } break; } default: { - throw parse_error("undefined operand type for binary operator", std::vector{n.children[0]->begin()}); + throw ParseError("undefined operand type for binary operator", std::vector{n.children[0]->begin()}); } } }; @@ -201,6 +202,6 @@ ASTNodeBinaryOperatorExpressionBuilder::ASTNodeBinaryOperatorExpressionBuilder(A } else if (n.is_type<language::not_eq_op>()) { set_binary_operator_processor(n, language::not_eq_op{}); } else { - throw parse_error("unexpected error: undefined binary operator", std::vector{n.begin()}); + throw ParseError("unexpected error: undefined binary operator", std::vector{n.begin()}); } } diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp index 9d914d7ee4799c9908253ffaa2958180a9d67bd3..6dc726f555219b855e2a125b0ab22b586dec2dad 100644 --- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -4,6 +4,7 @@ #include <language/ast/ASTNodeDataTypeFlattener.hpp> #include <language/ast/ASTNodeNaturalConversionChecker.hpp> #include <language/node_processor/BuiltinFunctionProcessor.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> PUGS_INLINE std::unique_ptr<IFunctionArgumentConverter> @@ -29,8 +30,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid argument type for function", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid argument type for function", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -47,8 +48,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(argument_number); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid argument dimension", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid argument dimension", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); // LCOV_EXCL_STOP } } @@ -66,8 +67,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid argument type", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid argument type", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -78,8 +79,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(argument_number); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid argument dimension", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid argument dimension", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); // LCOV_EXCL_STOP } } @@ -88,8 +89,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(argument_number); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid argument dimension", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid argument dimension", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); // LCOV_EXCL_STOP } } @@ -103,8 +104,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid argument type", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid argument type", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -122,8 +123,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid argument type for function", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid argument type for function", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -213,8 +214,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid argument type for function", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid argument type for function", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -247,8 +248,8 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined parameter type for function", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: undefined parameter type for function", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -286,9 +287,9 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: unexpected tuple content for function: '" + - dataTypeName(parameter_type) + "'", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: unexpected tuple content for function: '" + dataTypeName(parameter_type) + + "'", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -298,16 +299,16 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: unexpected tuple content type for function", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: unexpected tuple content type for function", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined parameter type for function", - std::vector{argument_node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: undefined parameter type for function", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -356,7 +357,7 @@ ASTNodeBuiltinFunctionExpressionBuilder::_buildArgumentProcessors( std::ostringstream error_message; error_message << "bad number of arguments: expecting " << rang::fgB::yellow << parameters_number << rang::style::reset << ", provided " << rang::fgB::yellow << arguments_number << rang::style::reset; - throw parse_error(error_message.str(), argument_nodes.begin()); + throw ParseError(error_message.str(), argument_nodes.begin()); } for (size_t i = 0; i < arguments_number; ++i) { diff --git a/src/language/ast/ASTNodeDataType.cpp b/src/language/ast/ASTNodeDataType.cpp index 18b812c0e7bb7c62466a7bce6b1dfd279eacec43..c77659d983c58a571ac3dd8426437be6478ceddb 100644 --- a/src/language/ast/ASTNodeDataType.cpp +++ b/src/language/ast/ASTNodeDataType.cpp @@ -2,17 +2,18 @@ #include <language/PEGGrammar.hpp> #include <language/ast/ASTNode.hpp> +#include <language/utils/ParseError.hpp> #include <utils/PugsAssert.hpp> ASTNodeDataType getVectorDataType(const ASTNode& type_node) { if (not(type_node.is_type<language::vector_type>() and (type_node.children.size() == 2))) { - throw parse_error("unexpected node type", type_node.begin()); + throw ParseError("unexpected node type", type_node.begin()); } ASTNode& dimension_node = *type_node.children[1]; if (not dimension_node.is_type<language::integer>()) { - throw parse_error("unexpected non integer constant dimension", dimension_node.begin()); + throw ParseError("unexpected non integer constant dimension", dimension_node.begin()); } const size_t dimension = std::stol(dimension_node.string()); return ASTNodeDataType{ASTNodeDataType::vector_t, dimension}; diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index 96ff62bfc20cd9a6526f140d14a4cee7218e241d..7da94cc5f7d00132b226f8ba0e7e5d95d4097b35 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -3,6 +3,7 @@ #include <language/PEGGrammar.hpp> #include <language/ast/ASTNodeNaturalConversionChecker.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> #include <utils/PugsAssert.hpp> @@ -17,7 +18,7 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo << type_node.string() << rang::style::reset << rang::style::bold << " differs from number of variables (" << name_node.children.size() << ") " << rang::fgB::yellow << name_node.string() << rang::style::reset << std::ends; - throw parse_error(message.str(), name_node.begin()); + throw ParseError(message.str(), name_node.begin()); } for (size_t i = 0; i < type_node.children.size(); ++i) { @@ -47,12 +48,12 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo const auto [i_type_symbol, found] = symbol_table.find(type_name_id, content_node->begin()); if (not found) { - throw parse_error("undefined type identifier", std::vector{content_node->begin()}); + throw ParseError("undefined type identifier", std::vector{content_node->begin()}); } else if (i_type_symbol->attributes().dataType() != ASTNodeDataType::type_name_id_t) { std::ostringstream os; os << "invalid type identifier, '" << type_name_id << "' was previously defined as a '" << dataTypeName(i_type_symbol->attributes().dataType()) << "'" << std::ends; - throw parse_error(os.str(), std::vector{content_node->begin()}); + throw ParseError(os.str(), std::vector{content_node->begin()}); } content_node->m_data_type = ASTNodeDataType{ASTNodeDataType::type_id_t, type_name_id}; @@ -84,19 +85,19 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo auto [i_type_symbol, found] = symbol_table.find(type_name_id, type_node.begin()); if (not found) { - throw parse_error("undefined type identifier", std::vector{type_node.begin()}); + throw ParseError("undefined type identifier", std::vector{type_node.begin()}); } else if (i_type_symbol->attributes().dataType() != ASTNodeDataType::type_name_id_t) { std::ostringstream os; os << "invalid type identifier, '" << type_name_id << "' was previously defined as a '" << dataTypeName(i_type_symbol->attributes().dataType()) << "'" << std::ends; - throw parse_error(os.str(), std::vector{type_node.begin()}); + throw ParseError(os.str(), std::vector{type_node.begin()}); } data_type = ASTNodeDataType{ASTNodeDataType::type_id_t, type_name_id}; } if (name_node.is_type<language::name_list>()) { - throw parse_error("unexpected variable list for single space", std::vector{name_node.begin()}); + throw ParseError("unexpected variable list for single space", std::vector{name_node.begin()}); } Assert(name_node.is_type<language::name>()); @@ -196,7 +197,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const << parameters_domain_node.string() << rang::style::reset << rang::style::bold << " differs from number of variables (" << nb_parameter_names << ") " << rang::fgB::yellow << parameters_name_node.string() << rang::style::reset << std::ends; - throw parse_error(message.str(), parameters_domain_node.begin()); + throw ParseError(message.str(), parameters_domain_node.begin()); } auto simple_type_allocator = [&](const ASTNode& type_node, ASTNode& symbol_node) { @@ -218,7 +219,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const // LCOV_EXCL_START if (data_type == ASTNodeDataType::undefined_t) { - throw parse_error("invalid parameter type", type_node.begin()); + throw ParseError("invalid parameter type", type_node.begin()); } // LCOV_EXCL_STOP @@ -270,7 +271,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const message << "expecting " << image_type.dimension() << " scalar expressions or an " << dataTypeName(image_type) << ", found " << nb_image_expressions << " scalar expressions" << std::ends; - throw parse_error(message.str(), image_domain_node.begin()); + throw ParseError(message.str(), image_domain_node.begin()); } } else { std::ostringstream message; @@ -278,7 +279,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const << image_domain_node.string() << rang::style::reset << rang::style::bold << " differs from number of expressions (" << nb_image_expressions << ") " << rang::fgB::yellow << image_expression_node.string() << rang::style::reset << std::ends; - throw parse_error(message.str(), image_domain_node.begin()); + throw ParseError(message.str(), image_domain_node.begin()); } } @@ -300,7 +301,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const // LCOV_EXCL_START if (value_type == ASTNodeDataType::undefined_t) { - throw parse_error("invalid value type", image_node.begin()); + throw ParseError("invalid value type", image_node.begin()); } // LCOV_EXCL_STOP }; @@ -399,7 +400,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const message << "undefined binary operator\n" << "note: incompatible operand types " << n.children[0]->string() << " (" << dataTypeName(type_0) << ") and " << n.children[1]->string() << " (" << dataTypeName(type_1) << ')' << std::ends; - throw parse_error(message.str(), n.begin()); + throw ParseError(message.str(), n.begin()); } } else if (n.is_type<language::function_evaluation>()) { if (n.children[0]->m_data_type == ASTNodeDataType::function_t) { @@ -452,7 +453,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const message << "invalid function call\n" << "note: '" << n.children[0]->string() << "' (type: " << dataTypeName(n.children[0]->m_data_type) << ") is not a function!" << std::ends; - throw parse_error(message.str(), n.begin()); + throw ParseError(message.str(), n.begin()); } } else if (n.is_type<language::subscript_expression>()) { Assert(n.children.size() == 2, "invalid number of sub-expressions in array subscript expression"); @@ -466,7 +467,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const << rang::style::reset << '[' << dataTypeName(index_expression.m_data_type) << ']' << "' for array subscript" << std::ends; - throw parse_error(message.str(), n.begin()); + throw ParseError(message.str(), n.begin()); } else { n.m_data_type = ASTNodeDataType::double_t; } diff --git a/src/language/ast/ASTNodeDataTypeChecker.cpp b/src/language/ast/ASTNodeDataTypeChecker.cpp index 87ecba522b17666aa5ce1610f1caf54ce0db15e3..3e6774849a5bbef6386f606a1bfe8a6993a84192 100644 --- a/src/language/ast/ASTNodeDataTypeChecker.cpp +++ b/src/language/ast/ASTNodeDataTypeChecker.cpp @@ -1,10 +1,12 @@ #include <language/ast/ASTNodeDataTypeChecker.hpp> +#include <language/utils/ParseError.hpp> + void ASTNodeDataTypeChecker::_checkNodeDataTypes(const ASTNode& n) { if (n.m_data_type == ASTNodeDataType::undefined_t) { - throw parse_error("unexpected error: undefined datatype for AST node for " + n.name(), n.begin()); + throw ParseError("unexpected error: undefined datatype for AST node for " + n.name(), n.begin()); } for (const auto& child : n.children) { diff --git a/src/language/ast/ASTNodeDataTypeFlattener.cpp b/src/language/ast/ASTNodeDataTypeFlattener.cpp index f19ed6667be11f429e9ab08e24ea33e264323cdb..da2d064c6dd677e9eae4444cde59700c3a61ec2d 100644 --- a/src/language/ast/ASTNodeDataTypeFlattener.cpp +++ b/src/language/ast/ASTNodeDataTypeFlattener.cpp @@ -51,7 +51,7 @@ ASTNodeDataTypeFlattener::ASTNodeDataTypeFlattener(ASTNode& node, FlattenedDataT } // LCOV_EXCL_START default: { - throw parse_error("unexpected function type", node.begin()); + throw ParseError("unexpected function type", node.begin()); } // LCOV_EXCL_STOP } diff --git a/src/language/ast/ASTNodeExpressionBuilder.cpp b/src/language/ast/ASTNodeExpressionBuilder.cpp index 9b9a0efbcb206b164ad31d6db18b3ca3727e09f9..fcdc4e1b93ab9135a6942e0e338144dff9474116 100644 --- a/src/language/ast/ASTNodeExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeExpressionBuilder.cpp @@ -1,5 +1,6 @@ #include <language/ast/ASTNodeExpressionBuilder.hpp> +#include <language/PEGGrammar.hpp> #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeArraySubscriptExpressionBuilder.hpp> #include <language/ast/ASTNodeBinaryOperatorExpressionBuilder.hpp> @@ -22,8 +23,7 @@ #include <language/node_processor/TupleToVectorProcessor.hpp> #include <language/node_processor/ValueProcessor.hpp> #include <language/node_processor/WhileProcessor.hpp> - -#include <language/PEGGrammar.hpp> +#include <language/utils/ParseError.hpp> void ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) @@ -121,7 +121,7 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) } else { std::ostringstream error_message; error_message << "undefined node processor type '" << rang::fgB::red << n.name() << rang::fg::reset << "'"; - throw parse_error{error_message.str(), std::vector{n.begin()}}; + throw ParseError{error_message.str(), std::vector{n.begin()}}; } for (auto& child : n.children) { diff --git a/src/language/ast/ASTNodeFunctionEvaluationExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionEvaluationExpressionBuilder.cpp index 5eb2ed3b0defeb35d47cd6f8e6812f2f82319883..13af5a812bd46ae0a6309eb65c1eecdda2cb027e 100644 --- a/src/language/ast/ASTNodeFunctionEvaluationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeFunctionEvaluationExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <language/ast/ASTNodeBuiltinFunctionExpressionBuilder.hpp> #include <language/ast/ASTNodeFunctionExpressionBuilder.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> ASTNodeFunctionEvaluationExpressionBuilder::ASTNodeFunctionEvaluationExpressionBuilder(ASTNode& node) @@ -20,7 +21,7 @@ ASTNodeFunctionEvaluationExpressionBuilder::ASTNodeFunctionEvaluationExpressionB } // LCOV_EXCL_START default: { - throw parse_error("unexpected function type", node.begin()); + throw ParseError("unexpected function type", node.begin()); } // LCOV_EXCL_STOP } diff --git a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp index f2369940873394a33db2718a7ff42fe4870cffc2..072a2af6015eed0dab37468c0c5e7211ec887eff 100644 --- a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp @@ -35,7 +35,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid argument type 0", + throw ParseError("unexpected error: invalid argument type 0", std::vector{node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP @@ -51,7 +51,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(parameter_id); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid argument dimension", + throw ParseError("unexpected error: invalid argument dimension", std::vector{node_sub_data_type.m_parent_node.begin()}); // LCOV_EXCL_STOP } @@ -61,7 +61,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy return std::make_unique<FunctionTinyVectorArgumentConverter<ParameterT, ParameterT>>(parameter_id); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid argument dimension", + throw ParseError("unexpected error: invalid argument dimension", std::vector{node_sub_data_type.m_parent_node.begin()}); // LCOV_EXCL_STOP } @@ -76,7 +76,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid argument type", + throw ParseError("unexpected error: invalid argument type", std::vector{node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP @@ -121,7 +121,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined parameter type", std::vector{m_node.begin()}); + throw ParseError("unexpected error: undefined parameter type", std::vector{m_node.begin()}); } // LCOV_EXCL_STOP } @@ -171,7 +171,7 @@ ASTNodeFunctionExpressionBuilder::_buildArgumentConverter(FunctionDescriptor& fu std::ostringstream error_message; error_message << "bad number of arguments: expecting " << rang::fgB::yellow << parameters_number << rang::style::reset << ", provided " << rang::fgB::yellow << arguments_number << rang::style::reset; - throw parse_error(error_message.str(), argument_nodes.begin()); + throw ParseError(error_message.str(), argument_nodes.begin()); } if (arguments_number > 1) { @@ -211,13 +211,13 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r return std::make_unique<FunctionExpressionProcessor<ReturnT, std::string>>(function_component_expression); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid string conversion", std::vector{node.children[1]->begin()}); + throw ParseError("unexpected error: invalid string conversion", std::vector{node.children[1]->begin()}); // LCOV_EXCL_STOP } } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined expression value type for function", + throw ParseError("unexpected error: undefined expression value type for function", std::vector{node.children[1]->begin()}); } // LCOV_EXCL_STOP @@ -232,7 +232,7 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r return std::make_unique<FunctionExpressionProcessor<ReturnT, ReturnT>>(function_component_expression); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid dimension for returned vector", + throw ParseError("unexpected error: invalid dimension for returned vector", std::vector{function_component_expression.begin()}); // LCOV_EXCL_STOP } @@ -243,7 +243,7 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r function_component_expression); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid dimension for returned vector", + throw ParseError("unexpected error: invalid dimension for returned vector", std::vector{function_component_expression.begin()}); // LCOV_EXCL_STOP } @@ -255,13 +255,13 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r } } // LCOV_EXCL_START - throw parse_error("unexpected error: undefined expression value type for function", + throw ParseError("unexpected error: undefined expression value type for function", std::vector{function_component_expression.begin()}); // LCOV_EXCL_STOP } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined expression value type for function", + throw ParseError("unexpected error: undefined expression value type for function", std::vector{function_component_expression.begin()}); } // LCOV_EXCL_STOP @@ -299,7 +299,7 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid dimension in returned type", std::vector{node.begin()}); + throw ParseError("unexpected error: invalid dimension in returned type", std::vector{node.begin()}); } // LCOV_EXCL_STOP } @@ -309,7 +309,7 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined return type for function", std::vector{node.begin()}); + throw ParseError("unexpected error: undefined return type for function", std::vector{node.begin()}); } // LCOV_EXCL_STOP } @@ -393,7 +393,7 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); + throw ParseError("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); } // LCOV_EXCL_STOP } @@ -417,13 +417,13 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); + throw ParseError("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); } // LCOV_EXCL_STOP } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: expecting 0", std::vector{function_expression.begin()}); + throw ParseError("unexpected error: expecting 0", std::vector{function_expression.begin()}); // LCOV_EXCL_STOP } } else { diff --git a/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp b/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp index c5eccdfcf61c597f97be00afcb688e3da857a220..71e5c3c4b16d8535091b98cab298ff6624661508 100644 --- a/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeIncDecExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <language/PEGGrammar.hpp> #include <language/node_processor/IncDecExpressionProcessor.hpp> +#include <language/utils/ParseError.hpp> ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(ASTNode& n) { @@ -22,7 +23,7 @@ ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(ASTNode& n) break; } default: { - throw parse_error("unexpected error: undefined data type for unary operator", std::vector{n.begin()}); + throw ParseError("unexpected error: undefined data type for unary operator", std::vector{n.begin()}); } } }; @@ -30,9 +31,9 @@ ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(ASTNode& n) if (not n.children[0]->is_type<language::name>()) { if (n.children[0]->is_type<language::post_minusminus>() or n.children[0]->is_type<language::post_plusplus>() or n.children[0]->is_type<language::unary_minusminus>() or n.children[0]->is_type<language::unary_plusplus>()) { - throw parse_error("chaining ++ or -- operators is not allowed", std::vector{n.children[0]->begin()}); + throw ParseError("chaining ++ or -- operators is not allowed", std::vector{n.children[0]->begin()}); } else { - throw parse_error("invalid operand type for unary operator", std::vector{n.children[0]->begin()}); + throw ParseError("invalid operand type for unary operator", std::vector{n.children[0]->begin()}); } } @@ -48,6 +49,6 @@ ASTNodeIncDecExpressionBuilder::ASTNodeIncDecExpressionBuilder(ASTNode& n) } else if (n.is_type<language::post_plusplus>()) { set_inc_dec_operator_processor(n, language::post_plusplus{}); } else { - throw parse_error("unexpected error: undefined increment/decrement operator", std::vector{n.begin()}); + throw ParseError("unexpected error: undefined increment/decrement operator", std::vector{n.begin()}); } } diff --git a/src/language/ast/ASTNodeJumpPlacementChecker.cpp b/src/language/ast/ASTNodeJumpPlacementChecker.cpp index c699d8dce4866cd229c46c9cd8ab3dde513226f6..3d34b8394ba39031ac04569a158fea2c4d4d5262 100644 --- a/src/language/ast/ASTNodeJumpPlacementChecker.cpp +++ b/src/language/ast/ASTNodeJumpPlacementChecker.cpp @@ -1,6 +1,7 @@ #include <language/ast/ASTNodeJumpPlacementChecker.hpp> #include <language/PEGGrammar.hpp> +#include <language/utils/ParseError.hpp> void ASTNodeJumpPlacementChecker::_checkJumpPlacement(ASTNode& n, bool is_inside_loop) @@ -15,7 +16,7 @@ ASTNodeJumpPlacementChecker::_checkJumpPlacement(ASTNode& n, bool is_inside_loop std::ostringstream error_message; error_message << "unexpected '" << rang::fgB::red << n.string() << rang::fg::reset << "' outside of loop or switch statement"; - throw parse_error(error_message.str(), std::vector{n.begin()}); + throw ParseError(error_message.str(), std::vector{n.begin()}); } } else { for (auto& child : n.children) { diff --git a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp index 48b7e4f5ddacd4b788ff38bf0bceb82442230f70..daa5a0bd371150ffd3d33a60993a3d4d10c48d96 100644 --- a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp @@ -4,6 +4,7 @@ #include <language/ast/ASTNodeDataTypeFlattener.hpp> #include <language/ast/ASTNodeNaturalConversionChecker.hpp> #include <language/node_processor/AffectationProcessor.hpp> +#include <language/utils/ParseError.hpp> template <typename OperatorT> void @@ -33,8 +34,8 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid operand type for affectation", - std::vector{node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid operand type for affectation", + std::vector{node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -62,17 +63,17 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( list_affectation_processor->template add<ValueT, ZeroType>(value_node); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid operand value", - std::vector{node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid operand value", + std::vector{node_sub_data_type.m_parent_node.begin()}); // LCOV_EXCL_STOP } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid dimension", std::vector{node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid dimension", std::vector{node_sub_data_type.m_parent_node.begin()}); // LCOV_EXCL_STOP } } else { - throw parse_error("unexpected error: invalid value type", std::vector{node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid value type", std::vector{node_sub_data_type.m_parent_node.begin()}); } }; @@ -115,8 +116,8 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector dimension", - std::vector{node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error: invalid vector dimension", + std::vector{node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -124,14 +125,13 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( } // LCOV_EXCL_START default: { - throw parse_error("unexpected error:invalid operand type for string affectation", - std::vector{node_sub_data_type.m_parent_node.begin()}); + throw ParseError("unexpected error:invalid operand type for string affectation", + std::vector{node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } } else { - throw parse_error("unexpected error: undefined operator type for string affectation", - std::vector{m_node.begin()}); + throw ParseError("unexpected error: undefined operator type for string affectation", std::vector{m_node.begin()}); } }; @@ -170,7 +170,7 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( } // LCOV_EXCL_START default: { - throw parse_error("invalid dimension", std::vector{value_node.begin()}); + throw ParseError("invalid dimension", std::vector{value_node.begin()}); } // LCOV_EXCL_STOP } @@ -182,8 +182,7 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: undefined value type for tuple affectation", - std::vector{value_node.begin()}); + throw ParseError("unexpected error: undefined value type for tuple affectation", std::vector{value_node.begin()}); } // LCOV_EXCL_STOP } @@ -212,7 +211,7 @@ ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor() ASTNode& name_list_node = *m_node.children[0]; if (name_list_node.children.size() != flattened_rhs_data_type_list.size()) { - throw parse_error("incompatible list sizes in affectation", std::vector{m_node.begin()}); + throw ParseError("incompatible list sizes in affectation", std::vector{m_node.begin()}); } using ListAffectationProcessorT = ListAffectationProcessor<OperatorT>; @@ -234,9 +233,9 @@ ASTNodeListAffectationExpressionBuilder::ASTNodeListAffectationExpressionBuilder if (node.is_type<language::eq_op>()) { this->_buildListAffectationProcessor<language::eq_op>(); } else { - throw parse_error("undefined affectation operator for tuples", std::vector{node.begin()}); + throw ParseError("undefined affectation operator for tuples", std::vector{node.begin()}); } } else { - throw parse_error("invalid right hand side in tuple affectation", std::vector{node.children[1]->begin()}); + throw ParseError("invalid right hand side in tuple affectation", std::vector{node.children[1]->begin()}); } } diff --git a/src/language/ast/ASTNodeNaturalConversionChecker.cpp b/src/language/ast/ASTNodeNaturalConversionChecker.cpp index b01ff1fc346856797b37f58a20b72039e8b49f59..0faabac4fa7d0cb197ba3b8f35ffcfadce3f162a 100644 --- a/src/language/ast/ASTNodeNaturalConversionChecker.cpp +++ b/src/language/ast/ASTNodeNaturalConversionChecker.cpp @@ -1,6 +1,7 @@ #include <language/ast/ASTNodeNaturalConversionChecker.hpp> #include <language/PEGGrammar.hpp> +#include <language/utils/ParseError.hpp> #include <utils/Exceptions.hpp> void @@ -17,7 +18,7 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalTypeConversion(const ASTNode& no if ((data_type == ASTNodeDataType::undefined_t) or (target_data_type == ASTNodeDataType::undefined_t)) { throw UnexpectedError(error_message.str()); } else { - throw parse_error(error_message.str(), node.begin()); + throw ParseError(error_message.str(), node.begin()); } } } @@ -31,7 +32,7 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNo switch (node.m_data_type) { case ASTNodeDataType::list_t: { if (node.children.size() != target_data_type.dimension()) { - throw parse_error("incompatible dimensions in affectation", std::vector{node.begin()}); + throw ParseError("incompatible dimensions in affectation", std::vector{node.begin()}); } for (const auto& child : node.children) { this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, ASTNodeDataType::double_t); @@ -41,7 +42,7 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNo } case ASTNodeDataType::vector_t: { if (data_type.dimension() != target_data_type.dimension()) { - throw parse_error("incompatible dimensions in affectation", std::vector{node.begin()}); + throw ParseError("incompatible dimensions in affectation", std::vector{node.begin()}); } break; } diff --git a/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp b/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp index ff081cea9e53378c6ea3639e3b7fd0a7b9162ca3..7d94c3f58fe1762b582a0d984edc797b0fafd021 100644 --- a/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <language/PEGGrammar.hpp> #include <language/node_processor/UnaryExpressionProcessor.hpp> +#include <language/utils/ParseError.hpp> ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(ASTNode& n) { @@ -28,8 +29,8 @@ ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(AST break; } default: { - throw parse_error("unexpected error: invalid operand type for unary operator", - std::vector{n.children[0]->begin()}); + throw ParseError("unexpected error: invalid operand type for unary operator", + std::vector{n.children[0]->begin()}); } } }; @@ -69,19 +70,19 @@ ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(AST } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector dimension", std::vector{n.begin()}); + throw ParseError("unexpected error: invalid vector dimension", std::vector{n.begin()}); } // LCOV_EXCL_STOP } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid unary operator for vector data", std::vector{n.begin()}); + throw ParseError("unexpected error: invalid unary operator for vector data", std::vector{n.begin()}); // LCOV_EXCL_STOP } break; } default: { - throw parse_error("undefined value type for unary operator", std::vector{n.begin()}); + throw ParseError("undefined value type for unary operator", std::vector{n.begin()}); } } }; @@ -94,6 +95,6 @@ ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(AST } else if (n.is_type<language::unary_not>()) { set_unary_operator_processor(n, language::unary_not{}); } else { - throw parse_error("unexpected error: undefined unary operator", std::vector{n.begin()}); + throw ParseError("unexpected error: undefined unary operator", std::vector{n.begin()}); } } diff --git a/src/language/ast/ASTSymbolInitializationChecker.cpp b/src/language/ast/ASTSymbolInitializationChecker.cpp index b68e6d05a5872c95c546b108ad6ef8c9256e1965..3a8c846a3626a3acb815a401767d898b378f546c 100644 --- a/src/language/ast/ASTSymbolInitializationChecker.cpp +++ b/src/language/ast/ASTSymbolInitializationChecker.cpp @@ -1,6 +1,7 @@ #include <language/ast/ASTSymbolInitializationChecker.hpp> #include <language/PEGGrammar.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> void @@ -16,13 +17,13 @@ ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node) auto check_correct_name_in_definition = [](ASTNode& decl_name_node, ASTNode& def_name_node) { if (def_name_node.is_type<language::name_list>()) { - throw parse_error("unexpected variable list, expecting one identifier", std::vector{def_name_node.begin()}); + throw ParseError("unexpected variable list, expecting one identifier", std::vector{def_name_node.begin()}); } Assert(def_name_node.is_type<language::name>()); if (decl_name_node.string() != def_name_node.string()) { std::ostringstream os; os << "invalid identifier, expecting '" << decl_name_node.string() << "'" << std::ends; - throw parse_error(os.str(), std::vector{def_name_node.begin()}); + throw ParseError(os.str(), std::vector{def_name_node.begin()}); } }; @@ -44,13 +45,13 @@ ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node) std::ostringstream os; os << "invalid number of definition identifiers, expecting " << decl_name_list_node.children.size() << " found " << def_name_list_node.children.size() << std::ends; - throw parse_error(os.str(), std::vector{def_name_list_node.begin()}); + throw ParseError(os.str(), std::vector{def_name_list_node.begin()}); } if (def_name_list_node.children.size() != expression_list_node.children.size()) { std::ostringstream os; os << "invalid number of definition expressions, expecting " << decl_name_list_node.children.size() << " found " << expression_list_node.children.size() << std::ends; - throw parse_error(os.str(), std::vector{expression_list_node.begin()}); + throw ParseError(os.str(), std::vector{expression_list_node.begin()}); } this->_checkSymbolInitialization(expression_list_node); @@ -113,7 +114,7 @@ ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node) if (not i_symbol->attributes().isInitialized()) { std::ostringstream error_message; error_message << "uninitialized symbol '" << rang::fg::red << node.string() << rang::fg::reset << '\''; - throw parse_error(error_message.str(), std::vector{node.begin()}); + throw ParseError(error_message.str(), std::vector{node.begin()}); } } diff --git a/src/language/ast/ASTSymbolTableBuilder.cpp b/src/language/ast/ASTSymbolTableBuilder.cpp index 2c8f4850a5cd477eac43fb43c30d6eb0d7cca671..feb0b0130dd316df1cf768ad3506fa31f42b68b8 100644 --- a/src/language/ast/ASTSymbolTableBuilder.cpp +++ b/src/language/ast/ASTSymbolTableBuilder.cpp @@ -1,6 +1,7 @@ #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/PEGGrammar.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> void @@ -25,7 +26,7 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> if (not success) { std::ostringstream error_message; error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << "' was already defined!"; - throw parse_error(error_message.str(), std::vector{n.begin()}); + throw ParseError(error_message.str(), std::vector{n.begin()}); } for (auto& child : n.children) { @@ -46,7 +47,7 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> std::ostringstream error_message; error_message << "symbol '" << rang::fg::red << argument_node.string() << rang::fg::reset << "' was already defined!"; - throw parse_error(error_message.str(), std::vector{argument_node.begin()}); + throw ParseError(error_message.str(), std::vector{argument_node.begin()}); } }; @@ -65,7 +66,7 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> std::ostringstream error_message; error_message << "symbol '" << rang::fg::red << argument_node.string() << rang::fg::reset << "' was already defined!"; - throw parse_error(error_message.str(), std::vector{argument_node.begin()}); + throw ParseError(error_message.str(), std::vector{argument_node.begin()}); } // Symbols will be initialized at call i_symbol->attributes().setIsInitialized(); @@ -84,7 +85,7 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> if (not found) { std::ostringstream error_message; error_message << "undefined symbol '" << rang::fg::red << n.string() << rang::fg::reset << '\''; - throw parse_error(error_message.str(), std::vector{n.begin()}); + throw ParseError(error_message.str(), std::vector{n.begin()}); } } } diff --git a/src/language/modules/ModuleRepository.cpp b/src/language/modules/ModuleRepository.cpp index 768661e9999a3dd720455f23daa7c252f555d16f..aa5c1fce3ee96c5318d930d75f2047df0d209735 100644 --- a/src/language/modules/ModuleRepository.cpp +++ b/src/language/modules/ModuleRepository.cpp @@ -6,6 +6,7 @@ #include <language/modules/SchemeModule.hpp> #include <language/modules/VTKModule.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> #include <utils/PugsAssert.hpp> @@ -41,7 +42,7 @@ ModuleRepository::_populateEmbedderTableT(const ASTNode& module_name_node, std::ostringstream error_message; error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name << "', it is already defined!"; - throw parse_error(error_message.str(), module_name_node.begin()); + throw ParseError(error_message.str(), module_name_node.begin()); } i_symbol->attributes().setDataType(data_type); @@ -68,6 +69,6 @@ ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTab this->_populateEmbedderTableT(module_name_node, populating_module.getNameTypeMap(), ASTNodeDataType::type_name_id_t, symbol_table, symbol_table.typeEmbedderTable()); } else { - throw parse_error(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()}); + throw ParseError(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()}); } } diff --git a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp index ec37d74ee5c815695c229d3b93d5d0acdb79bc9d..7ed93683d1b6bcfd54e624385429bce4319976d5 100644 --- a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp +++ b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp @@ -3,6 +3,7 @@ #include <language/PEGGrammar.hpp> #include <language/node_processor/INodeProcessor.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> #include <vector> @@ -61,7 +62,7 @@ class ASTNodeExpressionListProcessor final : public INodeProcessor } // LCOV_EXCL_START default: { - throw parse_error("unexpected function type", m_node.begin()); + throw ParseError("unexpected function type", m_node.begin()); } // LCOV_EXCL_STOP } diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 31e1f070f5fadc1366ad4470b49a8052977bfce2..6898bb2c2b25e4fe44a8f6e9ad271930086f0a81 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -3,6 +3,7 @@ #include <language/PEGGrammar.hpp> #include <language/node_processor/INodeProcessor.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> #include <utils/Exceptions.hpp> #include <utils/PugsTraits.hpp> @@ -86,7 +87,7 @@ class AffectationExecutor final : public IAffectationExecutor { // LCOV_EXCL_START if constexpr (not m_is_defined) { - throw parse_error("unexpected error: invalid operands to affectation expression", std::vector{node.begin()}); + throw ParseError("unexpected error: invalid operands to affectation expression", std::vector{node.begin()}); } // LCOV_EXCL_STOP } @@ -186,7 +187,7 @@ class ComponentAffectationExecutor final : public IAffectationExecutor { // LCOV_EXCL_START if constexpr (not m_is_defined) { - throw parse_error("unexpected error: invalid operands to affectation expression", std::vector{node.begin()}); + throw ParseError("unexpected error: invalid operands to affectation expression", std::vector{node.begin()}); } // LCOV_EXCL_STOP } @@ -204,7 +205,7 @@ class ComponentAffectationExecutor final : public IAffectationExecutor index_value = value; } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid index type", std::vector{m_index_expression.begin()}); + throw ParseError("unexpected error: invalid index type", std::vector{m_index_expression.begin()}); // LCOV_EXCL_STOP } }, @@ -286,8 +287,8 @@ class AffectationProcessor final : public INodeProcessor // LCOV_EXCL_START if (array_expression.m_data_type != ASTNodeDataType::vector_t) { - throw parse_error("unexpected error: invalid lhs (expecting R^d)", - std::vector{array_subscript_expression.begin()}); + throw ParseError("unexpected error: invalid lhs (expecting R^d)", + std::vector{array_subscript_expression.begin()}); } // LCOV_EXCL_STOP @@ -326,15 +327,14 @@ class AffectationProcessor final : public INodeProcessor } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector dimension", - std::vector{array_subscript_expression.begin()}); + throw ParseError("unexpected error: invalid vector dimension", std::vector{array_subscript_expression.begin()}); } // LCOV_EXCL_STOP } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid lhs", std::vector{node.children[0]->begin()}); + throw ParseError("unexpected error: invalid lhs", std::vector{node.children[0]->begin()}); // LCOV_EXCL_STOP } } @@ -366,7 +366,7 @@ class AffectationToTinyVectorFromListProcessor final : public INodeProcessor v[i] = child_value; } else { // LCOV_EXCL_START - throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin()); + throw ParseError("unexpected error: unexpected right hand side type in affectation", m_node.begin()); // LCOV_EXCL_STOP } }, @@ -421,7 +421,7 @@ class AffectationToTupleProcessor final : public INodeProcessor *m_lhs = std::vector{TinyVector<1>{static_cast<double>(v)}}; } else { // LCOV_EXCL_START - throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin()); + throw ParseError("unexpected error: unexpected right hand side type in affectation", m_node.begin()); // LCOV_EXCL_STOP } }, @@ -480,8 +480,8 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor v[j] = vj; } else { // LCOV_EXCL_START - throw parse_error("unexpected error: unexpected right hand side type in affectation", - m_node.children[1]->children[i]->begin()); + throw ParseError("unexpected error: unexpected right hand side type in affectation", + m_node.children[1]->children[i]->begin()); // LCOV_EXCL_STOP } }, @@ -493,14 +493,14 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor tuple_value[i] = ZeroType{}; } else { // LCOV_EXCL_START - throw parse_error("unexpected error: unexpected right hand side type in affectation", - m_node.children[1]->children[i]->begin()); + throw ParseError("unexpected error: unexpected right hand side type in affectation", + m_node.children[1]->children[i]->begin()); // LCOV_EXCL_STOP } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: unexpected right hand side type in affectation", - m_node.children[1]->children[i]->begin()); + throw ParseError("unexpected error: unexpected right hand side type in affectation", + m_node.children[1]->children[i]->begin()); // LCOV_EXCL_STOP } }, @@ -536,8 +536,8 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: unexpected right hand side type in tuple affectation", - m_node.children[1]->begin()); + throw ParseError("unexpected error: unexpected right hand side type in tuple affectation", + m_node.children[1]->begin()); // LCOV_EXCL_STOP } @@ -559,8 +559,8 @@ class AffectationToTupleFromListProcessor final : public INodeProcessor this->_copyVector(value_list); } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid lhs (expecting list or tuple)", - std::vector{m_node.children[1]->begin()}); + throw ParseError("unexpected error: invalid lhs (expecting list or tuple)", + std::vector{m_node.children[1]->begin()}); // LCOV_EXCL_STOP } }, @@ -645,8 +645,8 @@ class ListAffectationProcessor final : public INodeProcessor if (array_expression.m_data_type != ASTNodeDataType::vector_t) { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid lhs (expecting R^d)", - std::vector{array_subscript_expression.begin()}); + throw ParseError("unexpected error: invalid lhs (expecting R^d)", + std::vector{array_subscript_expression.begin()}); // LCOV_EXCL_STOP } @@ -685,14 +685,13 @@ class ListAffectationProcessor final : public INodeProcessor } // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid vector dimension", - std::vector{array_subscript_expression.begin()}); + throw ParseError("unexpected error: invalid vector dimension", std::vector{array_subscript_expression.begin()}); } // LCOV_EXCL_STOP } } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid left hand side", std::vector{lhs_node.begin()}); + throw ParseError("unexpected error: invalid left hand side", std::vector{lhs_node.begin()}); // LCOV_EXCL_STOP } } diff --git a/src/language/node_processor/ArraySubscriptProcessor.hpp b/src/language/node_processor/ArraySubscriptProcessor.hpp index 4853c65d326657a63599d62fc9d52713a96d1d5f..3a71c01846b9e17ce28818d732716aea764d2496 100644 --- a/src/language/node_processor/ArraySubscriptProcessor.hpp +++ b/src/language/node_processor/ArraySubscriptProcessor.hpp @@ -3,6 +3,7 @@ #include <language/ast/ASTNode.hpp> #include <language/node_processor/INodeProcessor.hpp> +#include <language/utils/ParseError.hpp> template <typename ArrayTypeT> class ArraySubscriptProcessor : public INodeProcessor @@ -25,7 +26,7 @@ class ArraySubscriptProcessor : public INodeProcessor index_value = value; } else { // LCOV_EXCL_START - throw parse_error("unexpected error: invalid index type", std::vector{index_expression.begin()}); + throw ParseError("unexpected error: invalid index type", std::vector{index_expression.begin()}); // LCOV_EXCL_STOP } }, diff --git a/src/language/node_processor/BinaryExpressionProcessor.hpp b/src/language/node_processor/BinaryExpressionProcessor.hpp index 2e4fcef12ffe74dcd5cf972b4353ba88ab8d0e55..8f5d9c3220cf3018104d5d53e2036b9bb8217214 100644 --- a/src/language/node_processor/BinaryExpressionProcessor.hpp +++ b/src/language/node_processor/BinaryExpressionProcessor.hpp @@ -4,6 +4,7 @@ #include <language/PEGGrammar.hpp> #include <language/ast/ASTNode.hpp> #include <language/node_processor/INodeProcessor.hpp> +#include <language/utils/ParseError.hpp> template <typename Op> struct BinOp; @@ -211,7 +212,7 @@ class BinaryExpressionProcessor final : public INodeProcessor { if constexpr (not m_is_defined) { // LCOV_EXCL_START - throw parse_error("invalid operands to binary expression", std::vector{m_node.begin()}); + throw ParseError("invalid operands to binary expression", std::vector{m_node.begin()}); // LCOV_EXCL_STOP } } diff --git a/src/language/node_processor/BuiltinFunctionProcessor.hpp b/src/language/node_processor/BuiltinFunctionProcessor.hpp index 755680f5fee0a2da69e02f0fd04a550e7e971846..302cbaf2d2ce3570678fb62a57d4e463e47a2432 100644 --- a/src/language/node_processor/BuiltinFunctionProcessor.hpp +++ b/src/language/node_processor/BuiltinFunctionProcessor.hpp @@ -5,6 +5,7 @@ #include <language/node_processor/FunctionArgumentConverter.hpp> #include <language/node_processor/INodeProcessor.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> +#include <language/utils/ParseError.hpp> #include <utils/SignalManager.hpp> @@ -69,7 +70,7 @@ class BuiltinFunctionProcessor : public INodeProcessor return m_function_expression_processor->execute(context_exec_policy); } catch (std::runtime_error& e) { - throw parse_error(e.what(), {m_argument_node.begin()}); + throw ParseError(e.what(), {m_argument_node.begin()}); } } } diff --git a/src/language/node_processor/OStreamProcessor.hpp b/src/language/node_processor/OStreamProcessor.hpp index 606247653b397998fab2016b970d87637201c527..e67dd7b6d9fcfa2440a59367efecd42ffd35a8ca 100644 --- a/src/language/node_processor/OStreamProcessor.hpp +++ b/src/language/node_processor/OStreamProcessor.hpp @@ -3,6 +3,7 @@ #include <language/ast/ASTNode.hpp> #include <language/node_processor/INodeProcessor.hpp> +#include <language/utils/ParseError.hpp> class OStreamProcessor final : public INodeProcessor { @@ -27,8 +28,8 @@ class OStreamProcessor final : public INodeProcessor if ((child->m_data_type == ASTNodeDataType::type_name_id_t) or (child->m_data_type == ASTNodeDataType::function_t) or (child->m_data_type == ASTNodeDataType::builtin_function_t)) { - throw parse_error("invalid argument, cannot print a '" + dataTypeName(child->m_data_type) + "'", - std::vector{child->begin()}); + throw ParseError("invalid argument, cannot print a '" + dataTypeName(child->m_data_type) + "'", + std::vector{child->begin()}); } } } diff --git a/src/language/utils/ParseError.hpp b/src/language/utils/ParseError.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6c15b07cd49f2c5cd3f8a85d339e006822d2b4c1 --- /dev/null +++ b/src/language/utils/ParseError.hpp @@ -0,0 +1,38 @@ +#ifndef PARSE_ERROR_HPP +#define PARSE_ERROR_HPP + +#include <utils/Exceptions.hpp> + +#include <pegtl/position.hpp> + +#include <vector> + +class ParseError : public IExitError +{ + private: + std::string m_error_msg; + std::vector<TAO_PEGTL_NAMESPACE::position> m_positions; + + public: + const auto& + positions() const + { + return m_positions; + } + + ParseError(const std::string_view msg, std::vector<TAO_PEGTL_NAMESPACE::position>&& positions) + : IExitError(msg), m_positions{std::move(positions)} + {} + + ParseError(const std::string_view msg, const std::vector<TAO_PEGTL_NAMESPACE::position>& positions) + : IExitError(msg), m_positions{positions} + {} + + ParseError(const std::string_view msg, const TAO_PEGTL_NAMESPACE::position& positions) + : IExitError(msg), m_positions{positions} + {} + + ~ParseError() = default; +}; + +#endif // PARSE_ERROR_HPP diff --git a/tests/test_ASTModulesImporter.cpp b/tests/test_ASTModulesImporter.cpp index 7ac28918aec2110eefe734b67bf73da2a55ea952..42638d918a362516b53a0f05772096b477f943b4 100644 --- a/tests/test_ASTModulesImporter.cpp +++ b/tests/test_ASTModulesImporter.cpp @@ -84,7 +84,7 @@ import unknown_module; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTModulesImporter{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTModulesImporter{*ast}, ParseError); } SECTION("symbol already defined") @@ -98,7 +98,7 @@ import math; ast->m_symbol_table->add("sin", ast->begin()); - REQUIRE_THROWS_AS(ASTModulesImporter{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTModulesImporter{*ast}, ParseError); } } } diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 9e44625e1ef31b116954e7b6859b1409873b6e11..c5c691a28db39749f1910521b875eca0af0e8271 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -5,6 +5,7 @@ #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/utils/ASTNodeDataTypeTraits.hpp> #include <language/utils/ASTPrinter.hpp> +#include <language/utils/ParseError.hpp> #include <language/utils/TypeDescriptor.hpp> #include <utils/Exceptions.hpp> @@ -825,7 +826,7 @@ let f : R*Z -> B, x -> 3; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); } SECTION("wrong parameter number 2") @@ -837,7 +838,7 @@ let f : R -> B, (x,y) -> 3; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); } SECTION("wrong image size") @@ -1090,7 +1091,7 @@ not_a_function(2,3); auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); } } } @@ -1545,7 +1546,7 @@ if ("string"); string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); } } @@ -1631,7 +1632,7 @@ while ("string"); string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); } } @@ -1717,7 +1718,7 @@ do 1; while ("string"); string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); } } @@ -2036,7 +2037,7 @@ true xor false; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); } } } diff --git a/tests/test_ASTNodeDataTypeChecker.cpp b/tests/test_ASTNodeDataTypeChecker.cpp index 7ce833b6d43cecaaadf28086435378c0a6788933..e016e1087281b3175eba0076cb21aaab7234c89b 100644 --- a/tests/test_ASTNodeDataTypeChecker.cpp +++ b/tests/test_ASTNodeDataTypeChecker.cpp @@ -4,6 +4,7 @@ #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDataTypeChecker.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ParseError.hpp> #include <pegtl/string_input.hpp> @@ -46,6 +47,6 @@ for(let i:Z, i=0; i<10; ++i) { ast->children[0]->m_data_type = ASTNodeDataType::undefined_t; - REQUIRE_THROWS_AS(ASTNodeDataTypeChecker{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeDataTypeChecker{*ast}, ParseError); } } diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp index 801d27d01f0dd89f206d5e9902c9e9414687559f..956b5a2527e8e80bb1cef2287f9b2c72a16768aa 100644 --- a/tests/test_ASTNodeExpressionBuilder.cpp +++ b/tests/test_ASTNodeExpressionBuilder.cpp @@ -889,6 +889,6 @@ continue; // One is sure that language::ignored is not treated so its a good candidate // for this test ast->children[0]->set_type<language::ignored>(); - REQUIRE_THROWS_AS(ASTNodeExpressionBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeExpressionBuilder{*ast}, ParseError); } } diff --git a/tests/test_ASTNodeFunctionExpressionBuilder.cpp b/tests/test_ASTNodeFunctionExpressionBuilder.cpp index 7e892c86367a3984cab7cb93a4d27631cda52d28..3ce9d041604f5a10cbe9ea97f063c3d24a1fd04d 100644 --- a/tests/test_ASTNodeFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeFunctionExpressionBuilder.cpp @@ -53,7 +53,7 @@ \ ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ ASTNodeTypeCleaner<language::fct_declaration>{*ast}; \ - REQUIRE_THROWS_AS(ASTNodeExpressionBuilder{*ast}, parse_error); \ + REQUIRE_THROWS_AS(ASTNodeExpressionBuilder{*ast}, ParseError); \ } #define CHECK_AST_THROWS_WITH(data, error) \ diff --git a/tests/test_ASTNodeJumpPlacementChecker.cpp b/tests/test_ASTNodeJumpPlacementChecker.cpp index 419519cd5803473aadb56abea772d537aaf38c2a..631b172775f381405bbc8ff830d19aad92b9c8e5 100644 --- a/tests/test_ASTNodeJumpPlacementChecker.cpp +++ b/tests/test_ASTNodeJumpPlacementChecker.cpp @@ -4,6 +4,7 @@ #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeJumpPlacementChecker.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ParseError.hpp> #include <pegtl/string_input.hpp> @@ -76,7 +77,7 @@ do { ast->children[0]->m_data_type = ASTNodeDataType::undefined_t; - REQUIRE_THROWS_AS(ASTNodeJumpPlacementChecker{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeJumpPlacementChecker{*ast}, ParseError); } } @@ -145,7 +146,7 @@ do { ast->children[0]->m_data_type = ASTNodeDataType::undefined_t; - REQUIRE_THROWS_AS(ASTNodeJumpPlacementChecker{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTNodeJumpPlacementChecker{*ast}, ParseError); } } } diff --git a/tests/test_ASTSymbolTableBuilder.cpp b/tests/test_ASTSymbolTableBuilder.cpp index 0398914c084e4c264bcae9f28f8356ed5885d3dc..028f79882eed45e8dc99c17efd414ce63c7ddd4e 100644 --- a/tests/test_ASTSymbolTableBuilder.cpp +++ b/tests/test_ASTSymbolTableBuilder.cpp @@ -2,6 +2,7 @@ #include <language/ast/ASTBuilder.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/ParseError.hpp> #include <pegtl/string_input.hpp> @@ -74,7 +75,7 @@ let n:N, n = a; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); } SECTION("Re-declared symbol") @@ -87,7 +88,7 @@ let n:N, n = 1; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); } SECTION("Re-declared symbol (function)") @@ -100,7 +101,7 @@ let f : R -> R, x -> 1; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); } SECTION("Re-declared parameter (function)") @@ -112,7 +113,7 @@ let f : R*R*N -> R, (x,y,x) -> 1; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, parse_error); + REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); } } } diff --git a/tests/test_BuiltinFunctionRegister.hpp b/tests/test_BuiltinFunctionRegister.hpp index fdf46213388b23e46c1457a56ea213cf17ac83f0..1583f1df99d7eddefc3337529611a5d5720912a0 100644 --- a/tests/test_BuiltinFunctionRegister.hpp +++ b/tests/test_BuiltinFunctionRegister.hpp @@ -162,7 +162,7 @@ class test_BuiltinFunctionRegister if (not success) { std::ostringstream error_message; error_message << "cannot add symbol '" << symbol_name << "' it is already defined"; - throw parse_error(error_message.str(), root_node.begin()); + throw ParseError(error_message.str(), root_node.begin()); } i_symbol->attributes().setDataType(ASTNodeDataType::builtin_function_t);