commit 8a292241e3abed06dea75df5da5f26a79a9d3d70 Author: Michael Kuc Date: Thu Sep 19 14:11:48 2019 +0100 Added first example. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b155b5e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.ccls-cache +*.o +.tup diff --git a/examples/.clang-format b/examples/.clang-format new file mode 100644 index 0000000..cbd9bb8 --- /dev/null +++ b/examples/.clang-format @@ -0,0 +1,25 @@ +--- +BasedOnStyle: llvm +IndentWidth: 4 +--- +AccessModifierOffset: -4 +AllowShortFunctionsOnASingleLine: Empty +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBraces: Attach +BreakConstructorInitializers: BeforeColon +Cpp11BracedListStyle: false +ColumnLimit: 100 +DerivePointerAlignment: false +FixNamespaceComments: true +IndentCaseLabels: true +IndentPPDirectives: AfterHash +Language: Cpp +NamespaceIndentation: All +PointerAlignment: Left +SortIncludes: true +SortUsingDeclarations: true +Standard: Cpp11 +TabWidth: 4 +UseTab: ForIndentation + +... diff --git a/examples/true/.ccls b/examples/true/.ccls new file mode 100644 index 0000000..4888f81 --- /dev/null +++ b/examples/true/.ccls @@ -0,0 +1,3 @@ +clang++ +%cpp --std=c++17 +-Igenerated diff --git a/examples/true/.gitignore b/examples/true/.gitignore new file mode 100644 index 0000000..12cee0a --- /dev/null +++ b/examples/true/.gitignore @@ -0,0 +1,3 @@ +*.tab.* +trueArgGrammarScannerDef.cpp +true diff --git a/examples/true/Tupfile b/examples/true/Tupfile new file mode 100644 index 0000000..346182f --- /dev/null +++ b/examples/true/Tupfile @@ -0,0 +1,16 @@ +LEXER = flex +PARSER = bison +CXX = g++ +CXXFLAGS = -pedantic -std=c++17 -Wall -Wno-unused-parameter -Wno-reorder -Wno-sign-compare -Wno-address -Wno-noexcept-type -Wno-unknown-attributes -Wno-unknown-warning-option +CPPFLAGS = +LDFLAGS = +LIBS = + +SRC_DIR = . +BUILD_DIR = build +PROG = true + +: foreach $(SRC_DIR)/*.yy |> $(PARSER) -b %BArgGrammarParser %f |> $(SRC_DIR)/%BArgGrammarParser.tab.cc $(SRC_DIR)/%BArgGrammarParser.tab.hh +: foreach $(SRC_DIR)/*.ll | $(SRC_DIR)/*.hh |> $(LEXER) %f |> $(SRC_DIR)/%BArgGrammarScannerDef.cpp +: foreach $(SRC_DIR)/*.cpp $(SRC_DIR)/*.cc | $(SRC_DIR)/*.hh |> $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I $(SRC_DIR) -c %f -o %o |> $(BUILD_DIR)/%B.o +: $(BUILD_DIR)/*.o |> $(CXX) $(LDFLAGS) $(LIBS) %f -o %o |> $(PROG) diff --git a/examples/true/main.cpp b/examples/true/main.cpp new file mode 100644 index 0000000..2fc32f1 --- /dev/null +++ b/examples/true/main.cpp @@ -0,0 +1,28 @@ +#include "trueArgGrammarDriver.hpp" +#include + +using Result = trueArgGrammar::Driver::Result; + +int main(int argc, char* argv[]) { + trueArgGrammar::Driver driver{ argc, argv }; + auto res = driver.parse(); + + if (res != Result::success) { + if (res == Result::completedAction) + return 0; + + return -1; + } + + std::cout << "true"; + + if (auto hasHelp = driver.getArg(trueArgGrammar::SingleArg::help)) { + std::cout << " --help"; + } else if (auto hasVersion = driver.getArg(trueArgGrammar::SingleArg::version)) { + std::cout << " --version"; + } + + std::cout << std::endl; + + return 0; +} diff --git a/examples/true/true.argspec b/examples/true/true.argspec new file mode 100644 index 0000000..9ea7187 --- /dev/null +++ b/examples/true/true.argspec @@ -0,0 +1,13 @@ +Program: + +true +version "true (GNU coreutils) 8.31" +license "Copyright (C) 2019 Free Software Foundation, Inc." +help "NOTE: your shell may have its own version of true, which usually supersedes the version described here." + +Usage: + +true + +Arguments: + diff --git a/examples/true/true.ll b/examples/true/true.ll new file mode 100644 index 0000000..fafe1b8 --- /dev/null +++ b/examples/true/true.ll @@ -0,0 +1,85 @@ +%{ +#include +#include "trueArgGrammarParser.tab.hh" + +#include "trueArgGrammarScanner.hpp" +#undef YY_DECL +#define YY_DECL int trueArgGrammar::Scanner::yylex(trueArgGrammar::Parser::semantic_type* const lval) + +using token = trueArgGrammar::Parser::token; +%} + +%option debug +%option nodefault +%option yyclass="trueArgGrammar::Scanner" +%option noyywrap +%option c++ +%option outfile="trueArgGrammarScannerDef.cpp" + +%x SHORT_ARGUMENTS ARGUMENT_VALUE POSITIONAL_ARGUMENTS + +%% + +%{ /** Code executed at the beginning of yylex **/ + yyval = lval; +%} + +-- { /* end of arguments */ + BEGIN(POSITIONAL_ARGUMENTS); +} + +-/. { + BEGIN(SHORT_ARGUMENTS); + resetVal = INITIAL; +} + + /** Default arguments implemented for all parsers **/ + +--help { + return token::ARGUMENT_HELP_LONG; +} + +--version { + return token::ARGUMENT_VERSION_LONG; +} + +--[[:alnum:]][[:alnum:]\-]* { + std::cerr << "Unknown argument: \'" << yytext << "\' found\n"; + setResult(Result::wrongArgument); +} + +--.+ { /* show common error for invalid option */ + std::cerr << "Invalid argument: \'" << yytext << "\' found\n"; + setResult(Result::wrongArgument); +} + +. { + std::cerr << "Unknown argument \'-" << yytext << "\' found\n"; + setResult(Result::wrongArgument); +} + +.+ { + std::cerr << "Unknown positional argument \'" << yytext << "\' found\n"; + setResult(Result::wrongArgument); +} + +[^\-].* { /* unknown positional argument */ + std::cerr << "Unknown positional argument \'" << yytext << "\' found\n"; + setResult(Result::wrongArgument); +} + +. { + std::cerr << "Invalid character \'" << yytext << "\' found\n"; + setResult(Result::wrongArgument); +} + +%% + +namespace trueArgGrammar { +void Scanner::resetOnWrap() { + if (resetVal) + BEGIN(*resetVal); + + resetVal = INITIAL; +} +} diff --git a/examples/true/true.yy b/examples/true/true.yy new file mode 100644 index 0000000..437973d --- /dev/null +++ b/examples/true/true.yy @@ -0,0 +1,91 @@ +%skeleton "lalr1.cc" +%require "3.2" +%debug +%defines +%define api.namespace {trueArgGrammar} +%define api.parser.class {Parser} + +%code requires{ + namespace trueArgGrammar { + class Driver; + class Scanner; + } + +#ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +#endif +} + +%parse-param { Scanner& scanner } +%parse-param { Driver& driver } + +%code{ +#include +#include +#include + +#include "trueArgGrammarDriver.hpp" +#include "trueArgGrammarScanner.hpp" + +#undef yylex +#define yylex scanner.yylex +} + +%define api.value.type variant +%define parse.assert + +%token ARGUMENT_HELP_LONG +%token ARGUMENT_VERSION_LONG + +%start ARGUMENTS + +%% + +ARGUMENTS + : %empty + | ARGUMENT_HELP { + std::cout + << "Usage:\n" + << "\n" + << driver.getArgv()[0] << "\n" + << driver.getArgv()[0] << "