From 163360813d324a94f4bd6f1e981f84d526139e3c Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 14:34:33 +0200 Subject: [PATCH 01/40] Add 'std::' in several places as suggested by clang --- src/lalr/Grammar.cpp | 8 ++++---- src/lalr/GrammarCompiler.cpp | 8 ++++---- src/lalr/RegexCompiler.cpp | 8 ++++---- src/lalr/RegexGenerator.cpp | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 1156ad8..7adc17a 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -369,7 +369,7 @@ GrammarSymbol* Grammar::add_symbol( const char* lexeme, int line, LexemeType lex symbol->set_line( line ); symbol->set_lexeme_type( lexeme_type ); symbol->set_symbol_type( symbol_type ); - symbols_.push_back( move(symbol) ); + symbols_.push_back( std::move(symbol) ); return symbols_.back().get(); } @@ -389,12 +389,12 @@ GrammarProduction* Grammar::add_production( GrammarSymbol* symbol, int line ) unique_ptr production( new GrammarProduction(int(productions_.size()), start_symbol_, 0, 0, NULL) ); production->append_symbol( symbol ); start_symbol_->append_production( production.get() ); - productions_.push_back( move(production) ); + productions_.push_back( std::move(production) ); } unique_ptr production( new GrammarProduction(int(productions_.size()), symbol, line, -1, nullptr) ); symbol->append_production( production.get() ); - productions_.push_back( move(production) ); + productions_.push_back( std::move(production) ); return productions_.back().get(); } @@ -410,7 +410,7 @@ GrammarAction* Grammar::add_action( const char* identifier ) { int index = int(actions_.size()); unique_ptr action( new GrammarAction(index, identifier) ); - actions_.push_back( move(action) ); + actions_.push_back( std::move(action) ); return actions_.back().get(); } return i->get(); diff --git a/src/lalr/GrammarCompiler.cpp b/src/lalr/GrammarCompiler.cpp index 29b0065..db53e95 100644 --- a/src/lalr/GrammarCompiler.cpp +++ b/src/lalr/GrammarCompiler.cpp @@ -149,7 +149,7 @@ void GrammarCompiler::set_actions( std::unique_ptr& actions, int LALR_ASSERT( parser_state_machine_ ); LALR_ASSERT( actions || actions_size == 0 ); LALR_ASSERT( actions_size >= 0 ); - actions_ = move( actions ); + actions_ = std::move( actions ); parser_state_machine_->actions_size = actions_size; parser_state_machine_->actions = actions_.get(); } @@ -159,7 +159,7 @@ void GrammarCompiler::set_symbols( std::unique_ptr& symbols, int LALR_ASSERT( parser_state_machine_ ); LALR_ASSERT( symbols ); LALR_ASSERT( symbols_size >= 3 ); - symbols_ = move( symbols ); + symbols_ = std::move( symbols ); parser_state_machine_->symbols_size = symbols_size; parser_state_machine_->symbols = symbols_.get(); parser_state_machine_->start_symbol = &symbols_[0]; @@ -172,7 +172,7 @@ void GrammarCompiler::set_transitions( std::unique_ptr& tran { LALR_ASSERT( transitions ); LALR_ASSERT( transitions_size >= 0 ); - transitions_ = move( transitions ); + transitions_ = std::move( transitions ); parser_state_machine_->transitions_size = transitions_size; parser_state_machine_->transitions = transitions_.get(); } @@ -182,7 +182,7 @@ void GrammarCompiler::set_states( std::unique_ptr& states, int st LALR_ASSERT( states ); LALR_ASSERT( states_size >= 0 ); LALR_ASSERT( start_state ); - states_ = move( states ); + states_ = std::move( states ); parser_state_machine_->states_size = states_size; parser_state_machine_->states = states_.get(); parser_state_machine_->start_state = start_state; diff --git a/src/lalr/RegexCompiler.cpp b/src/lalr/RegexCompiler.cpp index 5db6a13..34fa977 100644 --- a/src/lalr/RegexCompiler.cpp +++ b/src/lalr/RegexCompiler.cpp @@ -21,7 +21,7 @@ RegexCompiler::RegexCompiler() , actions_() , transitions_() , states_() -, state_machine_() +, state_machine_() { } @@ -64,21 +64,21 @@ const char* RegexCompiler::add_string( const std::string& string ) void RegexCompiler::set_actions( std::unique_ptr& actions, int actions_size ) { - actions_ = move( actions ); + actions_ = std::move( actions ); state_machine_->actions_size = actions_size; state_machine_->actions = actions_.get(); } void RegexCompiler::set_transitions( std::unique_ptr& transitions, int transitions_size ) { - transitions_ = move( transitions ); + transitions_ = std::move( transitions ); state_machine_->transitions_size = transitions_size; state_machine_->transitions = transitions_.get(); } void RegexCompiler::set_states( std::unique_ptr& states, int states_size, const LexerState* start_state ) { - states_ = move( states ); + states_ = std::move( states ); state_machine_->states_size = states_size; state_machine_->states = states_.get(); state_machine_->start_state = start_state; diff --git a/src/lalr/RegexGenerator.cpp b/src/lalr/RegexGenerator.cpp index d2b9999..a64e15f 100644 --- a/src/lalr/RegexGenerator.cpp +++ b/src/lalr/RegexGenerator.cpp @@ -143,7 +143,7 @@ const RegexAction* RegexGenerator::add_lexer_action( const std::string& identifi if ( i == actions_.end() ) { unique_ptr action( new RegexAction(int(actions_.size()), identifier) ); - actions_.push_back( move(action) ); + actions_.push_back( std::move(action) ); i = actions_.end() - 1; } return i->get(); @@ -241,7 +241,7 @@ void RegexGenerator::generate_states( const RegexSyntaxTree& syntax_tree ) state->add_item( syntax_tree.node()->get_first_positions() ); generate_symbol_for_state( state.get() ); start_state_ = state.get(); - states_.insert( move(state) ); + states_.insert( std::move(state) ); vector next_states; vector states; @@ -287,7 +287,7 @@ void RegexGenerator::generate_states( const RegexSyntaxTree& syntax_tree ) state->add_transition( begin, end, goto_state.get() ); generate_symbol_for_state( goto_state.get() ); next_states.push_back(goto_state.get() ); - states_.insert( move(goto_state) ); + states_.insert( std::move(goto_state) ); } else { From 40074978eab26783d5c9fbb0cf4897bc5690e057 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 14:45:30 +0200 Subject: [PATCH 02/40] Fix to detect identifiers referenced in rules but not defined --- src/lalr/Grammar.cpp | 4 +++- src/lalr/GrammarGenerator.cpp | 2 +- src/lalr/GrammarSymbol.cpp | 6 ++++++ src/lalr/GrammarSymbol.hpp | 3 +++ src/lalr/GrammarSymbol.ipp | 5 +++++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 7adc17a..3e65a0e 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -327,7 +327,9 @@ Grammar& Grammar::identifier( const char* identifier, int line ) } else { - active_production_->append_symbol( non_terminal_symbol(identifier, line) ); + GrammarSymbol* symbol = non_terminal_symbol(identifier, line ); + symbol->set_referenced_in_rule(true); + active_production_->append_symbol( symbol ); } } return *this; diff --git a/src/lalr/GrammarGenerator.cpp b/src/lalr/GrammarGenerator.cpp index b730ade..8f77c1a 100644 --- a/src/lalr/GrammarGenerator.cpp +++ b/src/lalr/GrammarGenerator.cpp @@ -396,7 +396,7 @@ void GrammarGenerator::check_for_undefined_symbol_errors() { const GrammarSymbol* symbol = i->get(); LALR_ASSERT( symbol ); - if ( symbol->symbol_type() == SYMBOL_NON_TERMINAL && symbol->productions().empty() && !symbol->referenced_in_precedence_directive() ) + if ( symbol->symbol_type() == SYMBOL_NON_TERMINAL && symbol->productions().empty() && (symbol->referenced_in_rule() || !symbol->referenced_in_precedence_directive()) ) { error( symbol->line(), PARSER_ERROR_UNDEFINED_SYMBOL, "undefined symbol '%s'", symbol->identifier().c_str(), identifier_.c_str() ); } diff --git a/src/lalr/GrammarSymbol.cpp b/src/lalr/GrammarSymbol.cpp index 779379b..98b48a2 100644 --- a/src/lalr/GrammarSymbol.cpp +++ b/src/lalr/GrammarSymbol.cpp @@ -20,6 +20,7 @@ GrammarSymbol::GrammarSymbol( const char* lexeme ) , index_( -1 ) , nullable_( false ) , referenced_in_precedence_directive_( false ) +, referenced_in_rule_( false ) , first_{0} , follow_{0} , productions_() @@ -128,6 +129,11 @@ void GrammarSymbol::set_referenced_in_precedence_directive( bool referenced_in_p referenced_in_precedence_directive_ = referenced_in_precedence_directive; } +void GrammarSymbol::set_referenced_in_rule( bool referenced_in_rule ) +{ + referenced_in_rule_ = referenced_in_rule; +} + void GrammarSymbol::append_production( GrammarProduction* production ) { LALR_ASSERT( production ); diff --git a/src/lalr/GrammarSymbol.hpp b/src/lalr/GrammarSymbol.hpp index 57fd79d..198f291 100644 --- a/src/lalr/GrammarSymbol.hpp +++ b/src/lalr/GrammarSymbol.hpp @@ -26,6 +26,7 @@ class GrammarSymbol int index_; ///< The index of this symbol among all symbols. bool nullable_; ///< True if this symbol is nullable otherwise false. bool referenced_in_precedence_directive_; ///< True if this symbol is referenced by a %precedence directive. + bool referenced_in_rule_; ///< True if this symbol is referenced by a rule. GrammarSymbolSet first_; ///< The symbols that can start this symbol in a production or regular expression. GrammarSymbolSet follow_; ///< The symbols that can follow this symbol in a production or regular expression. std::vector productions_; ///< The productions that reduce to this symbol. @@ -45,6 +46,7 @@ class GrammarSymbol inline int index() const; inline bool nullable() const; inline bool referenced_in_precedence_directive() const; + inline bool referenced_in_rule() const; inline const GrammarSymbolSet& first() const; inline const GrammarSymbolSet& follow() const; inline const std::vector& productions() const; @@ -63,6 +65,7 @@ class GrammarSymbol void set_index( int index ); void set_nullable( bool nullable ); void set_referenced_in_precedence_directive( bool referenced_in_precedence_directive ); + void set_referenced_in_rule( bool referenced_in_rule ); void append_production( GrammarProduction* production ); void append_reachable_production( GrammarProduction* production ); void calculate_identifier(); diff --git a/src/lalr/GrammarSymbol.ipp b/src/lalr/GrammarSymbol.ipp index 86c6e79..79ce014 100644 --- a/src/lalr/GrammarSymbol.ipp +++ b/src/lalr/GrammarSymbol.ipp @@ -67,6 +67,11 @@ bool GrammarSymbol::referenced_in_precedence_directive() const return referenced_in_precedence_directive_; } +bool GrammarSymbol::referenced_in_rule() const +{ + return referenced_in_rule_; +} + const GrammarSymbolSet& GrammarSymbol::first() const { return first_; From 01e753c53d33d148811458a1b5dc23ec033d1bbe Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 14:48:14 +0200 Subject: [PATCH 03/40] Add preprocessor guards to allow build without threads/threadpool. --- src/lalr/GrammarGenerator.cpp | 16 +++++++++++++++- src/lalr/GrammarGenerator.hpp | 4 ++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lalr/GrammarGenerator.cpp b/src/lalr/GrammarGenerator.cpp index 8f77c1a..8b455ef 100644 --- a/src/lalr/GrammarGenerator.cpp +++ b/src/lalr/GrammarGenerator.cpp @@ -21,7 +21,9 @@ #include "ParserStateMachine.hpp" #include "RegexGenerator.hpp" #include "RegexCompiler.hpp" +#ifndef LALR_NO_THREADS #include "ThreadPool.hpp" +#endif #include "ErrorPolicy.hpp" #include "ErrorCode.hpp" #include "assert.hpp" @@ -49,7 +51,9 @@ using namespace lalr; */ GrammarGenerator::GrammarGenerator() : error_policy_( nullptr ) +#ifndef LALR_NO_THREADS , thread_pool_( nullptr ) +#endif , identifier_() , actions_() , productions_() @@ -64,14 +68,18 @@ GrammarGenerator::GrammarGenerator() , start_state_( nullptr ) , errors_( 0 ) { +#ifndef LALR_NO_THREADS thread_pool_ = new ThreadPool; thread_pool_->start( 8 ); +#endif } GrammarGenerator::~GrammarGenerator() { +#ifndef LALR_NO_THREADS delete thread_pool_; thread_pool_ = nullptr; +#endif } const std::vector>& GrammarGenerator::actions() const @@ -756,7 +764,9 @@ void GrammarGenerator::generate_goto_items() { for ( const shared_ptr& state : states_ ) { +#ifndef LALR_NO_THREADS thread_pool_->push_job( [this, state]() +#endif { for ( GrammarTransition* transition : state->transitions() ) { @@ -799,9 +809,13 @@ void GrammarGenerator::generate_goto_items() } } } +#ifndef LALR_NO_THREADS ); +#endif } - thread_pool_->wait_idle(); +#ifndef LALR_NO_THREADS + thread_pool_->wait_idle(); +#endif } /** diff --git a/src/lalr/GrammarGenerator.hpp b/src/lalr/GrammarGenerator.hpp index eb4112b..c03e58d 100644 --- a/src/lalr/GrammarGenerator.hpp +++ b/src/lalr/GrammarGenerator.hpp @@ -15,7 +15,9 @@ namespace lalr { class ErrorPolicy; +#ifndef LALR_NO_THREADS class ThreadPool; +#endif class LexerStateMachine; class GrammarCompiler; class GrammarAction; @@ -34,7 +36,9 @@ class Grammar; class GrammarGenerator { ErrorPolicy* error_policy_; ///< The event sink to report errors to and print with or null to ignore errors and prints. +#ifndef LALR_NO_THREADS ThreadPool* thread_pool_; ///< The pool of threads to use to generate the parser. +#endif std::string identifier_; ///< The identifier of the parser. std::vector> actions_; ///< The actions in the parser. std::vector> productions_; ///< The productions in the parser. From fe8da356e1e17d9e44c4e84ba5ffddebe214147e Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 14:58:57 +0200 Subject: [PATCH 04/40] Make possible to accept associativity/precedence syntax like bison/byacc --- src/lalr/Associativity.hpp | 1 + src/lalr/Grammar.cpp | 11 +++++++++++ src/lalr/Grammar.hpp | 1 + src/lalr/GrammarParser.cpp | 9 +++++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/lalr/Associativity.hpp b/src/lalr/Associativity.hpp index e3d84fe..f2f4187 100644 --- a/src/lalr/Associativity.hpp +++ b/src/lalr/Associativity.hpp @@ -13,6 +13,7 @@ enum Associativity { ASSOCIATE_NULL, ///< The symbol has undefined associativity. ASSOCIATE_NONE, ///< The symbol has no associativity. + ASSOCIATE_PREC, ///< The symbol has only precedence level. ASSOCIATE_LEFT, ///< The symbol associates to the left. ASSOCIATE_RIGHT ///< The symbol associates to the right. }; diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 3e65a0e..85ac69c 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -143,6 +143,17 @@ Grammar& Grammar::whitespace() return *this; } +Grammar& Grammar::assoc_prec( int /*line*/ ) +{ + associativity_ = ASSOCIATE_PREC; + ++precedence_; + active_whitespace_directive_ = false; + active_precedence_directive_ = false; + active_production_ = nullptr; + active_symbol_ = nullptr; + return *this; +} + Grammar& Grammar::precedence() { LALR_ASSERT( active_symbol_ ); diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index c76648e..6de710e 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -54,6 +54,7 @@ class Grammar Grammar& left( int line ); Grammar& right( int line ); Grammar& none( int line ); + Grammar& assoc_prec( int line ); Grammar& whitespace(); Grammar& precedence(); Grammar& production( const char* identifier, int line ); diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index a1a53e6..74cc1be 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -160,11 +160,16 @@ bool GrammarParser::match_associativity() grammar_->right( line_ ); return true; } - else if ( match("%none") ) + else if ( match("%none") || match("%nonassoc")) { grammar_->none( line_ ); return true; } + else if ( match("%precedence") ) + { + grammar_->assoc_prec( line_ ); + return true; + } return false; } @@ -187,7 +192,7 @@ bool GrammarParser::match_expression() bool GrammarParser::match_precedence() { - if ( match("%precedence") ) + if ( match("%precedence") || match("%prec") ) { grammar_->precedence(); match_symbol(); From 98444cb6d6105616d9d329bf431e59a49b5ad7e4 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 15:04:47 +0200 Subject: [PATCH 05/40] Add an error message for empty literal/regex declarations, also fix to accept "'\''" literal. --- src/lalr/ErrorCode.hpp | 1 + src/lalr/GrammarParser.cpp | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/lalr/ErrorCode.hpp b/src/lalr/ErrorCode.hpp index 4ed44c3..0fcab63 100644 --- a/src/lalr/ErrorCode.hpp +++ b/src/lalr/ErrorCode.hpp @@ -12,6 +12,7 @@ enum ErrorCode PARSER_ERROR_NONE, ///< No %error. LALR_ERROR_SYNTAX, ///< Syntax %error occured while parsing input. LALR_ERROR_UNTERMINATED_LITERAL, ///< Unterminated literal in an lalr grammar. + LALR_ERROR_EMPTY_LITERAL, ///< Empty literal in an lalr grammar. LEXER_ERROR_MISSING_ACTION_HANDLER, ///< A lexer action hasn't been bound to a function. LEXER_ERROR_SYNTAX, ///< Syntax %error occured while parsing some input. LEXER_ERROR_SYMBOL_CONFLICT, ///< A lexer state matches more than one symbol. diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index 74cc1be..d73f84f 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -232,12 +232,22 @@ bool GrammarParser::match_literal() { escaped = *position == '\\'; ++position; + if(*position == '\\' && escaped) + { + ++position; + escaped = false; + } } if ( position == end_ || !is_new_line(position) ) { lexeme_.assign( position_, position ); position_ = position; expect( "'" ); + if(lexeme_.size() == 0) + { + error(line_, LALR_ERROR_EMPTY_LITERAL, "empty literal" ); + return false; + } return true; } error( line_, LALR_ERROR_UNTERMINATED_LITERAL, "unterminated literal" ); @@ -257,10 +267,20 @@ bool GrammarParser::match_regex() { escaped = *position == '\\'; ++position; + if(*position == '\\' && escaped) + { + ++position; + escaped = false; + } } lexeme_.assign( position_, position ); position_ = position; expect( "\"" ); + if(lexeme_.size() == 0) + { + error(line_, LALR_ERROR_EMPTY_LITERAL, "empty regex" ); + return false; + } return true; } return false; From 82bfdf5b85fcb56e5759f7ee7b20bee4e46f55e7 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 15:11:59 +0200 Subject: [PATCH 06/40] Check if '%whitespace' directive is present in the grammar and if not emit an error message. --- src/lalr/GrammarParser.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index d73f84f..a7a8b30 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -42,6 +42,10 @@ int GrammarParser::parse( const char* start, const char* finish, ErrorPolicy* er { error( 1, LALR_ERROR_SYNTAX, "parsing grammar failed" ); } + if( grammar_->whitespace_tokens().empty() ) + { + error(line_, PARSER_ERROR_UNDEFINED_SYMBOL, "no '%%whitespace' directive defined" ); + } return errors_; } From 0e05c13844c44697ced439e2f17a90d9e091fd1d Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 15:19:41 +0200 Subject: [PATCH 07/40] Add code to allow generate an EBNF for railroad diagram generation --- src/lalr/Grammar.cpp | 78 ++++++++++++++++++++++++++++++++++++ src/lalr/Grammar.hpp | 1 + src/lalr/GrammarCompiler.cpp | 7 +++- src/lalr/GrammarCompiler.hpp | 2 +- 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 85ac69c..8749116 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -346,6 +346,84 @@ Grammar& Grammar::identifier( const char* identifier, int line ) return *this; } +static void ouptputTerminal(const GrammarSymbol *sym) +{ + if(sym->symbol_type() == SYMBOL_TERMINAL) { + if(sym->lexeme_type() == LEXEME_LITERAL) + printf("'%s'", sym->lexeme().c_str()); + else + printf("\"%s\"", sym->lexeme().c_str()); + } + else + printf("%s", sym->lexeme().c_str()); +} + +static bool isTerminalRegex(const GrammarSymbol *symbol) +{ + return symbol->symbol_type() == SymbolType::SYMBOL_TERMINAL + && symbol->lexeme_type() == LexemeType::LEXEME_REGULAR_EXPRESSION; +} + +void Grammar::genEBNF() +{ + printf( + "//\n" + "// EBNF to be viewd at https://www.bottlecaps.de/rr/ui\n" + "//\n" + "// Copy and paste this at https://www.bottlecaps.de/rr/ui in the 'Edit Grammar' tab \n" + "// then click the 'View Diagram' tab.\n" + "//\n" + ); + GrammarSymbol* last_production_symbol = NULL; + bool production_continuation = false; + for ( vector>::const_iterator i = productions().begin(); i != productions().end(); ++i ) + { + GrammarProduction* production = i->get(); + LALR_ASSERT( production ); + GrammarSymbol *curr_symbol = production->symbol(); + bool same_production = last_production_symbol && last_production_symbol == curr_symbol; + const char *prefix = (isTerminalRegex(curr_symbol) + || (production->length() == 1 && isTerminalRegex(production->symbol_by_position(0)))) + ? "//" : ""; + if(same_production) { + production_continuation = true; + //printf(" //%s ::= %d", production->symbol()->lexeme().c_str(), production->length()); + } + else { + production_continuation = false; + const char *sym_prefix = ""; + const char *sym_name = curr_symbol->lexeme().c_str(); + if(sym_name[0] == '.') + { + ++sym_name; + sym_prefix = "ebnf_x_"; + } + //printf("\n\n%s%s ::= // %d\n\t", sym_prefix, sym_name, production->length()); + printf("\n\n%s%s%s ::=\n%s\t", prefix, sym_prefix, sym_name, prefix); + } + if(production->length() > 0) { + for(int elm=0; elm < production->length(); ++elm) { + const GrammarSymbol *sym = production->symbol_by_position(elm); + if(production_continuation) { + production_continuation = false; + printf("\n%s\t| ", prefix); + } + else printf(" "); + ouptputTerminal(sym); + } + } + else { + printf("/*empty*/"); + } + if(production->precedence_symbol()) { + printf(" //%%precedence "); + ouptputTerminal(production->precedence_symbol()); + } + last_production_symbol = curr_symbol; + } + printf("\n\n// end EBNF\n"); +} + GrammarSymbol* Grammar::literal_symbol( const char* lexeme, int line ) { LALR_ASSERT( lexeme ); diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index 6de710e..664816c 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -65,6 +65,7 @@ class Grammar Grammar& literal( const char* literal, int line ); Grammar& regex( const char* regex, int line ); Grammar& identifier( const char* identifier, int line ); + void genEBNF(); private: GrammarSymbol* literal_symbol( const char* lexeme, int line ); diff --git a/src/lalr/GrammarCompiler.cpp b/src/lalr/GrammarCompiler.cpp index db53e95..9b05e9f 100644 --- a/src/lalr/GrammarCompiler.cpp +++ b/src/lalr/GrammarCompiler.cpp @@ -73,7 +73,7 @@ void GrammarCompiler::labels_enabled( bool enabled ) labels_enabled_ = enabled; } -int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* error_policy ) +int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* error_policy, bool genEBNF ) { Grammar grammar; @@ -81,6 +81,11 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e int errors = parser.parse( begin, end, error_policy, &grammar ); if ( errors == 0 ) { + if(genEBNF) + { + grammar.genEBNF(); + return errors; + } GrammarGenerator generator; errors = generator.generate( grammar, error_policy ); diff --git a/src/lalr/GrammarCompiler.hpp b/src/lalr/GrammarCompiler.hpp index f3571ac..16cce94 100644 --- a/src/lalr/GrammarCompiler.hpp +++ b/src/lalr/GrammarCompiler.hpp @@ -39,7 +39,7 @@ class GrammarCompiler const RegexCompiler* whitespace_lexer() const; const ParserStateMachine* parser_state_machine() const; void labels_enabled( bool enabled ); - int compile( const char* begin, const char* end, ErrorPolicy* error_policy = nullptr ); + int compile( const char* begin, const char* end, ErrorPolicy* error_policy = nullptr, bool genEBNF = false ); private: const char* add_string( const std::string& string ); From 061bf241df0f90992b40000611704f2af22ce134 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 15:25:53 +0200 Subject: [PATCH 08/40] Add method to dump the input from the lexer. --- src/lalr/Parser.hpp | 1 + src/lalr/Parser.ipp | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/lalr/Parser.hpp b/src/lalr/Parser.hpp index a9e2a69..85e7674 100644 --- a/src/lalr/Parser.hpp +++ b/src/lalr/Parser.hpp @@ -79,6 +79,7 @@ class Parser void parse( Iterator start, Iterator finish ); bool parse( const void* symbol, const std::basic_string& lexeme, int line, int column ); bool parse( const ParserSymbol* symbol, const std::basic_string& lexeme, int line, int column ); + void dumpLex( Iterator start, Iterator finish ); private: const ParserTransition* find_transition( const ParserSymbol* symbol, const ParserState* state ) const; diff --git a/src/lalr/Parser.ipp b/src/lalr/Parser.ipp index dad237c..6bbc7f6 100644 --- a/src/lalr/Parser.ipp +++ b/src/lalr/Parser.ipp @@ -146,6 +146,33 @@ const UserData& Parser::user_data() return user_data_.front(); } +template +void Parser::dumpLex( Iterator start, Iterator finish ) +{ + LALR_ASSERT( state_machine_ ); + + reset(); + lexer_.reset( start, finish ); + lexer_.advance(); + printf("=line:column:type:index:identifier:lexeme:value\n"); + while ( !lexer_.full() ) + { + const ParserSymbol* symbol = reinterpret_cast( lexer_.symbol() ); + //printf("%d:%d:%d:%d:[%s]:[%s]:[%s]\n", lexer_.line(), lexer_.column(), symbol->type, symbol->index, symbol->identifier, symbol->lexeme, lexer_.lexeme().c_str()); + //printf("%d:%d:%d:%d:[%s]\n", lexer_.line(), lexer_.column(), symbol->type, symbol->index, symbol->identifier); + //printf("%d:%d:%d:%d\n", lexer_.line(), lexer_.column(), symbol->type, symbol->index); + //printf("%d:%d:%p\n", lexer_.line(), lexer_.column(), symbol); + printf("%d:%d:", lexer_.line(), lexer_.column()); + if(symbol) printf("%d:%d:[%s]:[%s]", symbol->type, symbol->index, symbol->identifier, symbol->lexeme); + else printf("-1:-1:[]:[]"); + printf(":[%s]\n", lexer_.lexeme().c_str()); + //fflush(stdout); + lexer_.advance(); + } + + full_ = lexer_.full(); +} + /** // Get the Lexer that is being used by this Parser. From 7a668bb2479b07e785623b1567218a2a1021e789 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 16:33:58 +0200 Subject: [PATCH 09/40] Reuse result of already called function. --- src/lalr/Lexer.ipp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lalr/Lexer.ipp b/src/lalr/Lexer.ipp index 8b1a951..30233b4 100644 --- a/src/lalr/Lexer.ipp +++ b/src/lalr/Lexer.ipp @@ -282,7 +282,7 @@ void Lexer::advance() full_ = position_.ended(); matched_lexeme_.clear(); matched_symbol_ = nullptr; - symbol_ = !position_.ended() ? run() : end_symbol_; + symbol_ = !full_ ? run() : end_symbol_; } /** From 924359539c20b8b6198b61882b401c9a936a576b Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 16:36:25 +0200 Subject: [PATCH 10/40] Add a method to show grammar compilation stats. --- src/lalr/GrammarCompiler.cpp | 26 ++++++++++++++++++++++++-- src/lalr/GrammarCompiler.hpp | 1 + src/lalr/GrammarGenerator.cpp | 4 ++++ src/lalr/GrammarGenerator.hpp | 8 ++++++-- src/lalr/ParserStateMachine.hpp | 2 ++ src/lalr/RegexCompiler.hpp | 1 + src/lalr/lalrc/lalrc.cpp | 2 ++ 7 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/lalr/GrammarCompiler.cpp b/src/lalr/GrammarCompiler.cpp index 9b05e9f..652bbe8 100644 --- a/src/lalr/GrammarCompiler.cpp +++ b/src/lalr/GrammarCompiler.cpp @@ -93,7 +93,7 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e { populate_parser_state_machine( grammar, generator ); - // Generate tokens for generating the lexical analyzer from each of + // Generate tokens for generating the lexical analyzer from each of // the terminal symbols in the grammar. vector tokens; int column = 1; @@ -171,7 +171,7 @@ void GrammarCompiler::set_symbols( std::unique_ptr& symbols, int parser_state_machine_->end_symbol = &symbols_[1]; parser_state_machine_->error_symbol = &symbols_[2]; parser_state_machine_->whitespace_symbol = &symbols_[3]; -} +} void GrammarCompiler::set_transitions( std::unique_ptr& transitions, int transitions_size ) { @@ -283,4 +283,26 @@ void GrammarCompiler::populate_parser_state_machine( const Grammar& grammar, con set_symbols( symbols, symbols_size ); set_transitions( transitions, transitions_size ); set_states( states, states_size, start_state ); + parser_state_machine_->shift_reduce_count_ = generator.shift_reduce_count(); + parser_state_machine_->reduce_reduce_count_ = generator.reduce_reduce_count(); +} + +#include "LexerStateMachine.hpp" + +void GrammarCompiler::showStats() +{ + const ParserStateMachine *psm = parser_state_machine_.get(); + printf("Parser state machine stats:\n"); + printf(" Symbols : %d\n", psm->symbols_size); + printf(" Actions : %d\n", psm->actions_size); + printf(" States : %d\n", psm->states_size); + printf(" Transitions : %d\n", psm->transitions_size); + printf(" Solved conflicts : shift/reduce = %d, reduce/reduce = %d\n", psm->shift_reduce_count_, psm->reduce_reduce_count_); + const LexerStateMachine* lsm = lexer_->state_machine(); + if(!lsm) return; + printf("Lexer state machine stats:\n"); + printf(" Strings : %zd\n", lexer_->strings_size()); + printf(" Actions : %d\n", lsm->actions_size); + printf(" States : %d\n", lsm->states_size); + printf(" Transitions : %d\n", lsm->transitions_size); } diff --git a/src/lalr/GrammarCompiler.hpp b/src/lalr/GrammarCompiler.hpp index 16cce94..7920c3f 100644 --- a/src/lalr/GrammarCompiler.hpp +++ b/src/lalr/GrammarCompiler.hpp @@ -40,6 +40,7 @@ class GrammarCompiler const ParserStateMachine* parser_state_machine() const; void labels_enabled( bool enabled ); int compile( const char* begin, const char* end, ErrorPolicy* error_policy = nullptr, bool genEBNF = false ); + void showStats(); private: const char* add_string( const std::string& string ); diff --git a/src/lalr/GrammarGenerator.cpp b/src/lalr/GrammarGenerator.cpp index 8b455ef..c10f53e 100644 --- a/src/lalr/GrammarGenerator.cpp +++ b/src/lalr/GrammarGenerator.cpp @@ -67,6 +67,8 @@ GrammarGenerator::GrammarGenerator() , whitespace_symbol_( nullptr ) , start_state_( nullptr ) , errors_( 0 ) +, shift_reduce_count_( 0 ) +, reduce_reduce_count_( 0 ) { #ifndef LALR_NO_THREADS thread_pool_ = new ThreadPool; @@ -1020,6 +1022,7 @@ void GrammarGenerator::generate_reduce_transition( GrammarState* state, const Gr else if ( production->precedence() > symbol->precedence() || (symbol->precedence() == production->precedence() && symbol->associativity() == ASSOCIATE_RIGHT) ) { transition->override_shift_to_reduce( production ); + ++shift_reduce_count_; } } else @@ -1032,6 +1035,7 @@ void GrammarGenerator::generate_reduce_transition( GrammarState* state, const Gr else if ( production->precedence() > transition->precedence() ) { transition->override_reduce_to_reduce( production ); + ++reduce_reduce_count_; } } } diff --git a/src/lalr/GrammarGenerator.hpp b/src/lalr/GrammarGenerator.hpp index c03e58d..08df641 100644 --- a/src/lalr/GrammarGenerator.hpp +++ b/src/lalr/GrammarGenerator.hpp @@ -52,6 +52,8 @@ class GrammarGenerator GrammarSymbol* whitespace_symbol_; ///< The whitespace symbol. GrammarState* start_state_; ///< The start state. int errors_; ///< The number of errors that occured during parsing and generation. + int shift_reduce_count_; ///< The number of shift/reduce resolved conflicts that occured during parsing and generation. + int reduce_reduce_count_; ///< The number of reduce/reduce resolved conflicts that occured during parsing and generation. public: GrammarGenerator(); @@ -65,7 +67,9 @@ class GrammarGenerator std::string label_state( const GrammarState& state ) const; std::string label_item( const GrammarItem& item ) const; int generate( Grammar& grammar, ErrorPolicy* error_policy ); - + int shift_reduce_count() const {return shift_reduce_count_;} + int reduce_reduce_count() const {return reduce_reduce_count_;} + private: void error( int line, int error, const char* format, ... ); GrammarTransition* shift_transition( const GrammarSymbol* symbol, GrammarState* state ); @@ -79,7 +83,7 @@ class GrammarGenerator void check_for_error_symbol_on_left_hand_side_errors(); void check_for_implicit_terminal_duplicate_associativity(); void calculate_identifiers(); - void calculate_terminal_and_non_terminal_symbols(); + void calculate_terminal_and_non_terminal_symbols(); void calculate_implicit_terminal_symbols(); void calculate_precedence_of_productions(); void calculate_symbol_indices(); diff --git a/src/lalr/ParserStateMachine.hpp b/src/lalr/ParserStateMachine.hpp index c021c8c..79252bf 100644 --- a/src/lalr/ParserStateMachine.hpp +++ b/src/lalr/ParserStateMachine.hpp @@ -28,6 +28,8 @@ class ParserStateMachine int symbols_size; ///< The number of symbols. int transitions_size; ///< The total number of transitions. int states_size; ///< The number of states. + int shift_reduce_count_; ///< The number of shift/reduce resolved conflicts that occured during parsing and generation. + int reduce_reduce_count_; ///< The number of reduce/reduce resolved conflicts that occured during parsing and generation. const ParserAction* actions; ///< The parser actions for this ParserStateMachine. const ParserSymbol* symbols; ///< The symbols in the grammar for this ParserStateMachine. const ParserTransition* transitions; ///< The transitions in the state machine for this ParserStateMachine. diff --git a/src/lalr/RegexCompiler.hpp b/src/lalr/RegexCompiler.hpp index aee1068..c79366e 100644 --- a/src/lalr/RegexCompiler.hpp +++ b/src/lalr/RegexCompiler.hpp @@ -39,6 +39,7 @@ class RegexCompiler void set_transitions( std::unique_ptr& transitions, int transitions_size ); void set_states( std::unique_ptr& states, int states_size, const LexerState* start_state ); void populate_lexer_state_machine( const RegexGenerator& generator ); + size_t strings_size() {return strings_.size();}; }; } diff --git a/src/lalr/lalrc/lalrc.cpp b/src/lalr/lalrc/lalrc.cpp index 8d8e5b3..c9366a8 100644 --- a/src/lalr/lalrc/lalrc.cpp +++ b/src/lalr/lalrc/lalrc.cpp @@ -368,6 +368,8 @@ void generate_cxx_parser_state_machine( const ParserStateMachine* state_machine write( " %d, // #symbols\n", state_machine->symbols_size ); write( " %d, // #transitions\n", state_machine->transitions_size ); write( " %d, // #states\n", state_machine->states_size ); + write( " %d, // #shift_reduce_count\n", state_machine->shift_reduce_count_ ); + write( " %d, // #reduce_reduce_count\n", state_machine->reduce_reduce_count_ ); write( " actions,\n" ); write( " symbols,\n" ); write( " transitions,\n" ); From a64710d99d84a3dbc6a44321c27eb397f3e54f0b Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 16:54:46 +0200 Subject: [PATCH 11/40] Reorder class member for better memory usage/alignment. --- src/lalr/ParserSymbol.hpp | 2 +- src/lalr/lalrc/lalrc.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lalr/ParserSymbol.hpp b/src/lalr/ParserSymbol.hpp index 5666bf1..a99b717 100644 --- a/src/lalr/ParserSymbol.hpp +++ b/src/lalr/ParserSymbol.hpp @@ -13,10 +13,10 @@ class ParserSymbol { public: int index; ///< The index of this symbol. + SymbolType type; ///< The type of this symbol. const char* identifier; ///< The identifier of this symbol. const char* lexeme; ///< The lexeme of this symbol or null if this symbol is non-terminal. const char* label; ///< The human-readable label for this symbol. - SymbolType type; ///< The type of this symbol. }; } diff --git a/src/lalr/lalrc/lalrc.cpp b/src/lalr/lalrc/lalrc.cpp index c9366a8..8e7144e 100644 --- a/src/lalr/lalrc/lalrc.cpp +++ b/src/lalr/lalrc/lalrc.cpp @@ -296,15 +296,15 @@ void generate_cxx_parser_state_machine( const ParserStateMachine* state_machine const ParserSymbol* symbols_end = symbols + state_machine->symbols_size; for ( const ParserSymbol* symbol = symbols; symbol != symbols_end; ++symbol ) { - write( " {%d, \"%s\", \"%s\", \"%s\", (SymbolType) %d},\n", - symbol->index, - symbol->identifier, + write( " {%d, (SymbolType) %d, \"%s\", \"%s\", \"%s\"},\n", + symbol->index, + symbol->type, + symbol->identifier, sanitize(symbol->lexeme).c_str(), - sanitize(symbol->label).c_str(), - symbol->type + sanitize(symbol->label).c_str() ); } - write( " {-1, nullptr, nullptr, nullptr, (SymbolType) 0}\n" ); + write( " {-1, (SymbolType) 0, nullptr, nullptr, nullptr}\n" ); write( "};\n" ); write( "\n" ); From 642de0b45c478a54becf5c917f6827c6e51a9396 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 16:58:29 +0200 Subject: [PATCH 12/40] Rename write output function to prevent clash with C lib ::write --- src/lalr/lalrc/dot.cpp | 22 ++-- src/lalr/lalrc/lalrc.cpp | 242 +++++++++++++++++++-------------------- 2 files changed, 132 insertions(+), 132 deletions(-) diff --git a/src/lalr/lalrc/dot.cpp b/src/lalr/lalrc/dot.cpp index 09ec186..c9f91f7 100644 --- a/src/lalr/lalrc/dot.cpp +++ b/src/lalr/lalrc/dot.cpp @@ -8,7 +8,7 @@ using namespace lalr; -extern void write( const char* format, ... ); +extern void writeToOutput( const char* format, ... ); namespace lalr { @@ -17,23 +17,23 @@ void write_graphviz_dot( const ParserStateMachine* state_machine ) { LALR_ASSERT( state_machine ); - write( "digraph %s {\n", state_machine->identifier ); - write( " rankdir = LR;\n" ); - write( " size = \"8, 5\";\n" ); - write( " bgcolor = transparent;\n" ); - write( "\n" ); - write( " node [shape = circle];\n" ); + writeToOutput( "digraph %s {\n", state_machine->identifier ); + writeToOutput( " rankdir = LR;\n" ); + writeToOutput( " size = \"8, 5\";\n" ); + writeToOutput( " bgcolor = transparent;\n" ); + writeToOutput( "\n" ); + writeToOutput( " node [shape = circle];\n" ); const ParserState* states = state_machine->states; const ParserState* states_end = states + state_machine->states_size; for ( const ParserState* state = states; state != states_end; ++state ) { - write( " node [label =\"%s\"] i%d;\n", + writeToOutput( " node [label =\"%s\"] i%d;\n", state->label, state->index ); } - write( "\n" ); + writeToOutput( "\n" ); for ( const ParserState* state = states; state != states_end; ++state ) { @@ -43,7 +43,7 @@ void write_graphviz_dot( const ParserStateMachine* state_machine ) { if ( transition->state ) { - write( " i%d -> i%d [label =\"%s\"];\n", + writeToOutput( " i%d -> i%d [label =\"%s\"];\n", state->index, transition->state->index, transition->symbol->label @@ -52,7 +52,7 @@ void write_graphviz_dot( const ParserStateMachine* state_machine ) } } - write( "}\n" ); + writeToOutput( "}\n" ); } } diff --git a/src/lalr/lalrc/lalrc.cpp b/src/lalr/lalrc/lalrc.cpp index 8e7144e..c686971 100644 --- a/src/lalr/lalrc/lalrc.cpp +++ b/src/lalr/lalrc/lalrc.cpp @@ -205,7 +205,7 @@ static void close() file_ = nullptr; } -void write( const char* format, ... ) +void writeToOutput( const char* format, ... ) { if ( file_ ) { @@ -227,76 +227,76 @@ void print_cxx_parser_state_machine( const ParserStateMachine* state_machine ) const ParserState* states_end = states + state_machine->states_size; for ( const ParserState* state = states; state != states_end; ++state ) { - write( "state %d:\n", state->index ); + writeToOutput( "state %d:\n", state->index ); const ParserTransition* transitions = state->transitions; const ParserTransition* transitions_end = transitions + state->length; for ( const ParserTransition* transition = transitions; transition != transitions_end; ++transition ) { if ( transition->state ) { - write( " %s -> state %d\n", transition->symbol->lexeme, transition->state->index ); + writeToOutput( " %s -> state %d\n", transition->symbol->lexeme, transition->state->index ); } else { - write( " %s <- %s\n", transition->symbol->lexeme, transition->reduced_symbol->lexeme ); + writeToOutput( " %s <- %s\n", transition->symbol->lexeme, transition->reduced_symbol->lexeme ); } } - write( "\n" ); + writeToOutput( "\n" ); } } void generate_cxx_parser_state_machine( const ParserStateMachine* state_machine ) { - write( "\n" ); - write( "#include \n" ); - write( "#include \n" ); - write( "#include \n" ); - write( "#include \n" ); - write( "#include \n" ); - write( "#include \n" ); - write( "#include \n" ); - write( "#include \n" ); - write( "#include \n" ); - write( "\n" ); - write( "namespace\n" ); - write( "{\n" ); - write( "\n" ); - write( "using namespace lalr;\n" ); - write( "\n" ); - write( "extern const LexerAction lexer_actions [];\n" ); - write( "extern const LexerTransition lexer_transitions [];\n" ); - write( "extern const LexerState lexer_states [];\n" ); - write( "extern const LexerAction whitespace_lexer_actions [];\n" ); - write( "extern const LexerTransition whitespace_lexer_transitions [];\n" ); - write( "extern const LexerState whitespace_lexer_states [];\n" ); - write( "extern const ParserAction actions [];\n" ); - write( "extern const ParserSymbol symbols [];\n" ); - write( "extern const ParserTransition transitions [];\n" ); - write( "extern const ParserState states [];\n" ); - write( "\n" ); - - write( "const ParserAction actions [] = \n" ); - write( "{\n" ); + writeToOutput( "\n" ); + writeToOutput( "#include \n" ); + writeToOutput( "#include \n" ); + writeToOutput( "#include \n" ); + writeToOutput( "#include \n" ); + writeToOutput( "#include \n" ); + writeToOutput( "#include \n" ); + writeToOutput( "#include \n" ); + writeToOutput( "#include \n" ); + writeToOutput( "#include \n" ); + writeToOutput( "\n" ); + writeToOutput( "namespace\n" ); + writeToOutput( "{\n" ); + writeToOutput( "\n" ); + writeToOutput( "using namespace lalr;\n" ); + writeToOutput( "\n" ); + writeToOutput( "extern const LexerAction lexer_actions [];\n" ); + writeToOutput( "extern const LexerTransition lexer_transitions [];\n" ); + writeToOutput( "extern const LexerState lexer_states [];\n" ); + writeToOutput( "extern const LexerAction whitespace_lexer_actions [];\n" ); + writeToOutput( "extern const LexerTransition whitespace_lexer_transitions [];\n" ); + writeToOutput( "extern const LexerState whitespace_lexer_states [];\n" ); + writeToOutput( "extern const ParserAction actions [];\n" ); + writeToOutput( "extern const ParserSymbol symbols [];\n" ); + writeToOutput( "extern const ParserTransition transitions [];\n" ); + writeToOutput( "extern const ParserState states [];\n" ); + writeToOutput( "\n" ); + + writeToOutput( "const ParserAction actions [] = \n" ); + writeToOutput( "{\n" ); const ParserAction* actions = state_machine->actions; const ParserAction* actions_end = actions + state_machine->actions_size; for ( const ParserAction* action = actions; action != actions_end; ++action ) { - write( " {%d, \"%s\"},\n", - action->index, + writeToOutput( " {%d, \"%s\"},\n", + action->index, action->identifier ); } - write( " {-1, nullptr}\n" ); - write( "};\n" ); - write( "\n" ); + writeToOutput( " {-1, nullptr}\n" ); + writeToOutput( "};\n" ); + writeToOutput( "\n" ); - write( "const ParserSymbol symbols [] = \n" ); - write( "{\n" ); + writeToOutput( "const ParserSymbol symbols [] = \n" ); + writeToOutput( "{\n" ); const ParserSymbol* symbols = state_machine->symbols; const ParserSymbol* symbols_end = symbols + state_machine->symbols_size; for ( const ParserSymbol* symbol = symbols; symbol != symbols_end; ++symbol ) { - write( " {%d, (SymbolType) %d, \"%s\", \"%s\", \"%s\"},\n", + writeToOutput( " {%d, (SymbolType) %d, \"%s\", \"%s\", \"%s\"},\n", symbol->index, symbol->type, symbol->identifier, @@ -304,19 +304,19 @@ void generate_cxx_parser_state_machine( const ParserStateMachine* state_machine sanitize(symbol->label).c_str() ); } - write( " {-1, (SymbolType) 0, nullptr, nullptr, nullptr}\n" ); - write( "};\n" ); - write( "\n" ); + writeToOutput( " {-1, (SymbolType) 0, nullptr, nullptr, nullptr}\n" ); + writeToOutput( "};\n" ); + writeToOutput( "\n" ); - write( "const ParserTransition transitions [] = \n" ); - write( "{\n" ); + writeToOutput( "const ParserTransition transitions [] = \n" ); + writeToOutput( "{\n" ); const ParserTransition* transitions = state_machine->transitions; const ParserTransition* transitions_end = transitions + state_machine->transitions_size; for ( const ParserTransition* transition = transitions; transition != transitions_end; ++transition ) { if ( transition->reduced_symbol ) { - write( " {&symbols[%d], nullptr, &symbols[%d], %d, %d, %d, %d},\n", + writeToOutput( " {&symbols[%d], nullptr, &symbols[%d], %d, %d, %d, %d},\n", transition->symbol ? transition->symbol->index : -1, transition->reduced_symbol->index, transition->reduced_length, @@ -327,7 +327,7 @@ void generate_cxx_parser_state_machine( const ParserStateMachine* state_machine } else { - write( " {&symbols[%d], &states[%d], nullptr, %d, %d, %d, %d},\n", + writeToOutput( " {&symbols[%d], &states[%d], nullptr, %d, %d, %d, %d},\n", transition->symbol ? transition->symbol->index : -1, transition->state ? transition->state->index : -1, transition->reduced_length, @@ -337,85 +337,85 @@ void generate_cxx_parser_state_machine( const ParserStateMachine* state_machine ); } } - write( " {nullptr, nullptr, nullptr, 0, 0, 0, -1}\n" ); - write( "};\n" ); - write( "\n" ); + writeToOutput( " {nullptr, nullptr, nullptr, 0, 0, 0, -1}\n" ); + writeToOutput( "};\n" ); + writeToOutput( "\n" ); - write( "const ParserState states [] = \n" ); - write( "{\n" ); + writeToOutput( "const ParserState states [] = \n" ); + writeToOutput( "{\n" ); const ParserState* states = state_machine->states; const ParserState* states_end = states + state_machine->states_size; for ( const ParserState* state = states; state != states_end; ++state ) { - write( " {%d, %d, &transitions[%d], \"%s\"},\n", + writeToOutput( " {%d, %d, &transitions[%d], \"%s\"},\n", state->index, state->length, state->transitions->index, state->label ? sanitize( state->label ).c_str() : nullptr ); } - write( " {-1, 0, nullptr}\n" ); - write( "};\n" ); - write( "\n" ); + writeToOutput( " {-1, 0, nullptr}\n" ); + writeToOutput( "};\n" ); + writeToOutput( "\n" ); generate_cxx_lexer_state_machine( state_machine->lexer_state_machine, "lexer" ); generate_cxx_lexer_state_machine( state_machine->whitespace_lexer_state_machine, "whitespace_lexer" ); - write( "const ParserStateMachine parser_state_machine = \n" ); - write( "{\n" ); - write( " \"%s\",\n", state_machine->identifier ); - write( " %d, // #actions\n", state_machine->actions_size ); - write( " %d, // #symbols\n", state_machine->symbols_size ); - write( " %d, // #transitions\n", state_machine->transitions_size ); - write( " %d, // #states\n", state_machine->states_size ); - write( " %d, // #shift_reduce_count\n", state_machine->shift_reduce_count_ ); - write( " %d, // #reduce_reduce_count\n", state_machine->reduce_reduce_count_ ); - write( " actions,\n" ); - write( " symbols,\n" ); - write( " transitions,\n" ); - write( " states,\n" ); - write( " &symbols[%d], // start symbol\n", state_machine->start_symbol->index ); - write( " &symbols[%d], // end symbol\n", state_machine->end_symbol->index ); - write( " &symbols[%d], // error symbol\n", state_machine->error_symbol->index ); - write( " &symbols[%d], // whitespace symbol\n", state_machine->whitespace_symbol->index ); - write( " &states[%d], // start state\n", state_machine->start_state->index ); - write( " %s, // lexer state machine\n", state_machine->lexer_state_machine ? "&lexer_state_machine" : "null" ); - write( " %s // whitespace lexer state machine\n", state_machine->whitespace_lexer_state_machine ? "&whitespace_lexer_state_machine" : "null" ); - write( "};\n" ); - - write( "\n" ); - write( "}\n" ); - write( "\n" ); - - write( "const lalr::ParserStateMachine* %s_parser_state_machine = &parser_state_machine;\n", state_machine->identifier ); + writeToOutput( "const ParserStateMachine parser_state_machine = \n" ); + writeToOutput( "{\n" ); + writeToOutput( " \"%s\",\n", state_machine->identifier ); + writeToOutput( " %d, // #actions\n", state_machine->actions_size ); + writeToOutput( " %d, // #symbols\n", state_machine->symbols_size ); + writeToOutput( " %d, // #transitions\n", state_machine->transitions_size ); + writeToOutput( " %d, // #states\n", state_machine->states_size ); + writeToOutput( " %d, // #shift_reduce_count\n", state_machine->shift_reduce_count_ ); + writeToOutput( " %d, // #reduce_reduce_count\n", state_machine->reduce_reduce_count_ ); + writeToOutput( " actions,\n" ); + writeToOutput( " symbols,\n" ); + writeToOutput( " transitions,\n" ); + writeToOutput( " states,\n" ); + writeToOutput( " &symbols[%d], // start symbol\n", state_machine->start_symbol->index ); + writeToOutput( " &symbols[%d], // end symbol\n", state_machine->end_symbol->index ); + writeToOutput( " &symbols[%d], // error symbol\n", state_machine->error_symbol->index ); + writeToOutput( " &symbols[%d], // whitespace symbol\n", state_machine->whitespace_symbol->index ); + writeToOutput( " &states[%d], // start state\n", state_machine->start_state->index ); + writeToOutput( " %s, // lexer state machine\n", state_machine->lexer_state_machine ? "&lexer_state_machine" : "null" ); + writeToOutput( " %s // whitespace lexer state machine\n", state_machine->whitespace_lexer_state_machine ? "&whitespace_lexer_state_machine" : "null" ); + writeToOutput( "};\n" ); + + writeToOutput( "\n" ); + writeToOutput( "}\n" ); + writeToOutput( "\n" ); + + writeToOutput( "const lalr::ParserStateMachine* %s_parser_state_machine = &parser_state_machine;\n", state_machine->identifier ); } void generate_cxx_lexer_state_machine( const LexerStateMachine* state_machine, const char* prefix ) { if ( state_machine ) { - write( "const LexerAction %s_actions [] = \n", prefix ); - write( "{\n" ); + writeToOutput( "const LexerAction %s_actions [] = \n", prefix ); + writeToOutput( "{\n" ); const LexerAction* actions = state_machine->actions; const LexerAction* actions_end = actions + state_machine->actions_size; for ( const LexerAction* action = actions; action != actions_end; ++action ) { - write( " {%d, \"%s\"},\n", - action->index, + writeToOutput( " {%d, \"%s\"},\n", + action->index, action->identifier ); } - write( " {-1, nullptr}\n" ); - write( "};\n" ); - write( "\n" ); + writeToOutput( " {-1, nullptr}\n" ); + writeToOutput( "};\n" ); + writeToOutput( "\n" ); - write( "const LexerTransition %s_transitions [] = \n", prefix ); - write( "{\n" ); + writeToOutput( "const LexerTransition %s_transitions [] = \n", prefix ); + writeToOutput( "{\n" ); const LexerTransition* transitions = state_machine->transitions; const LexerTransition* transitions_end = transitions + state_machine->transitions_size; for ( const LexerTransition* transition = transitions; transition != transitions_end; ++transition ) { - write( " {%d, %d, &%s_states[%d], ", + writeToOutput( " {%d, %d, &%s_states[%d], ", transition->begin, transition->end, prefix, @@ -423,24 +423,24 @@ void generate_cxx_lexer_state_machine( const LexerStateMachine* state_machine, c ); if ( transition->action ) { - write( "&%s_actions[%d]},\n", prefix, transition->action->index ); + writeToOutput( "&%s_actions[%d]},\n", prefix, transition->action->index ); } else { - write( "nullptr},\n" ); + writeToOutput( "nullptr},\n" ); } } - write( " {-1, -1, nullptr, nullptr}\n" ); - write( "};\n" ); - write( "\n" ); + writeToOutput( " {-1, -1, nullptr, nullptr}\n" ); + writeToOutput( "};\n" ); + writeToOutput( "\n" ); - write( "const LexerState %s_states [] = \n", prefix ); - write( "{\n" ); + writeToOutput( "const LexerState %s_states [] = \n", prefix ); + writeToOutput( "{\n" ); const LexerState* states = state_machine->states; const LexerState* states_end = states + state_machine->states_size; for ( const LexerState* state = states; state != states_end; ++state ) { - write( " {%d, %d, &%s_transitions[%d], ", + writeToOutput( " {%d, %d, &%s_transitions[%d], ", state->index, state->length, prefix, @@ -449,28 +449,28 @@ void generate_cxx_lexer_state_machine( const LexerStateMachine* state_machine, c const ParserSymbol* symbol = reinterpret_cast( state->symbol ); if ( symbol ) { - write( "&symbols[%d]},\n", symbol->index ); + writeToOutput( "&symbols[%d]},\n", symbol->index ); } else { - write( "nullptr},\n" ); + writeToOutput( "nullptr},\n" ); } } - write( " {-1, 0, nullptr, nullptr}\n" ); - write( "};\n" ); - write( "\n" ); - - write( "const LexerStateMachine %s_state_machine = \n", prefix ); - write( "{\n" ); - write( " %d, // #actions\n", state_machine->actions_size ); - write( " %d, // #transitions\n", state_machine->transitions_size ); - write( " %d, // #states\n", state_machine->states_size ); - write( " %s_actions, // actions\n", prefix ); - write( " %s_transitions, // transitions\n", prefix ); - write( " %s_states, // states\n", prefix ); - write( " &%s_states[%d] // start state\n", prefix, state_machine->start_state->index ); - write( "};\n" ); - write( "\n" ); + writeToOutput( " {-1, 0, nullptr, nullptr}\n" ); + writeToOutput( "};\n" ); + writeToOutput( "\n" ); + + writeToOutput( "const LexerStateMachine %s_state_machine = \n", prefix ); + writeToOutput( "{\n" ); + writeToOutput( " %d, // #actions\n", state_machine->actions_size ); + writeToOutput( " %d, // #transitions\n", state_machine->transitions_size ); + writeToOutput( " %d, // #states\n", state_machine->states_size ); + writeToOutput( " %s_actions, // actions\n", prefix ); + writeToOutput( " %s_transitions, // transitions\n", prefix ); + writeToOutput( " %s_states, // states\n", prefix ); + writeToOutput( " &%s_states[%d] // start state\n", prefix, state_machine->start_state->index ); + writeToOutput( "};\n" ); + writeToOutput( "\n" ); } } From a5387f332684f888899a9b662bc2be4ecd2d40f9 Mon Sep 17 00:00:00 2001 From: mingodad Date: Thu, 22 Jun 2023 17:55:52 +0200 Subject: [PATCH 13/40] Use a typedef and macros to allow easy experimenting with different type to store bitfields. --- src/lalr/GrammarSymbolSet.cpp | 14 +++++++------- src/lalr/GrammarSymbolSet.hpp | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/lalr/GrammarSymbolSet.cpp b/src/lalr/GrammarSymbolSet.cpp index 45a17a1..3d0424c 100644 --- a/src/lalr/GrammarSymbolSet.cpp +++ b/src/lalr/GrammarSymbolSet.cpp @@ -15,8 +15,8 @@ using std::vector; using std::numeric_limits; using namespace lalr; -static const size_t ONE = 1; -static const size_t BITS_PER_ELEMENT = sizeof(size_t) * 8; +#define VECTOR_SET_T_ONE ((vector_set_t)1) +#define BITS_PER_ELEMENT (sizeof(vector_set_t) * 8) GrammarSymbolSet::GrammarSymbolSet( size_t symbols ) : set_() @@ -72,12 +72,12 @@ int GrammarSymbolSet::maximum_index() const return int((maximum_ + 1) * BITS_PER_ELEMENT); } -bool GrammarSymbolSet::contains( int symbol_index ) const +bool GrammarSymbolSet::contains( size_t symbol_index ) const { size_t index = symbol_index / BITS_PER_ELEMENT; if ( index >= minimum_ && index <= maximum_ ) { - size_t mask = ONE << (symbol_index % BITS_PER_ELEMENT); + vector_set_t mask = VECTOR_SET_T_ONE << (symbol_index % BITS_PER_ELEMENT); return (set_[index] & mask) != 0; } return false; @@ -92,7 +92,7 @@ bool GrammarSymbolSet::insert( const GrammarSymbol* symbol ) { set_.insert( set_.end(), index - set_.size() + 1, 0 ); } - size_t mask = ONE << (symbol->index() % BITS_PER_ELEMENT); + vector_set_t mask = VECTOR_SET_T_ONE << (symbol->index() % BITS_PER_ELEMENT); if ( !(set_[index] & mask) ) { set_[index] |= mask; @@ -114,8 +114,8 @@ int GrammarSymbolSet::insert( const GrammarSymbolSet& set ) int added = 0; for ( size_t i = set.minimum_; i < set.maximum_ + 1; ++i ) { - size_t mask = set_[i]; - size_t new_mask = mask | set.set_[i]; + vector_set_t mask = set_[i]; + vector_set_t new_mask = mask | set.set_[i]; if ( mask != new_mask ) { set_[i] = new_mask; diff --git a/src/lalr/GrammarSymbolSet.hpp b/src/lalr/GrammarSymbolSet.hpp index 03f2b48..60bcebc 100644 --- a/src/lalr/GrammarSymbolSet.hpp +++ b/src/lalr/GrammarSymbolSet.hpp @@ -11,7 +11,8 @@ class GrammarSymbol; class GrammarSymbolSet { - std::vector set_; + typedef size_t vector_set_t; + std::vector set_; size_t minimum_; size_t maximum_; @@ -24,7 +25,7 @@ class GrammarSymbolSet int minimum_index() const; int maximum_index() const; - bool contains( int symbol_index ) const; + bool contains( size_t symbol_index ) const; bool insert( const GrammarSymbol* symbol ); int insert( const GrammarSymbolSet& set ); }; From d7cacbc3d9ccef3eb843385cb23cafd3aa122987 Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 23 Jun 2023 11:12:17 +0200 Subject: [PATCH 14/40] Simplify GrammaSymbolSet --- src/lalr/GrammarGenerator.cpp | 8 ++++---- src/lalr/GrammarSymbolSet.cpp | 29 +++++++++++++++-------------- src/lalr/GrammarSymbolSet.hpp | 4 ++-- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/lalr/GrammarGenerator.cpp b/src/lalr/GrammarGenerator.cpp index c10f53e..11173ec 100644 --- a/src/lalr/GrammarGenerator.cpp +++ b/src/lalr/GrammarGenerator.cpp @@ -972,9 +972,9 @@ void GrammarGenerator::generate_reduce_transitions() if ( item->position() >= production->length() ) { const GrammarSymbolSet& lookaheads = lookaheads_[item->index()].lookaheads(); - int start = lookaheads.minimum_index(); - int finish = lookaheads.maximum_index(); - for ( int index = start; index < finish; ++index ) + size_t start = lookaheads.minimum_index(); + size_t finish = lookaheads.maximum_index(); + for ( size_t index = start; index <= finish; ++index ) { if ( lookaheads.contains(index) ) { @@ -983,7 +983,7 @@ void GrammarGenerator::generate_reduce_transitions() generate_reduce_transition( state, symbol, production ); } } - } + } } } } diff --git a/src/lalr/GrammarSymbolSet.cpp b/src/lalr/GrammarSymbolSet.cpp index 3d0424c..bf83a50 100644 --- a/src/lalr/GrammarSymbolSet.cpp +++ b/src/lalr/GrammarSymbolSet.cpp @@ -15,7 +15,7 @@ using std::vector; using std::numeric_limits; using namespace lalr; -#define VECTOR_SET_T_ONE ((vector_set_t)1) +#define VECTOTR_SET_T_ONE ((vector_set_t)1) #define BITS_PER_ELEMENT (sizeof(vector_set_t) * 8) GrammarSymbolSet::GrammarSymbolSet( size_t symbols ) @@ -59,25 +59,25 @@ GrammarSymbolSet& GrammarSymbolSet::operator=( const GrammarSymbolSet& set ) minimum_ = set.minimum_; maximum_ = set.maximum_; } - return *this; + return *this; } -int GrammarSymbolSet::minimum_index() const +size_t GrammarSymbolSet::minimum_index() const { - return int(minimum_ * BITS_PER_ELEMENT); + return minimum_; } -int GrammarSymbolSet::maximum_index() const +size_t GrammarSymbolSet::maximum_index() const { - return int((maximum_ + 1) * BITS_PER_ELEMENT); + return maximum_ ; } bool GrammarSymbolSet::contains( size_t symbol_index ) const { - size_t index = symbol_index / BITS_PER_ELEMENT; - if ( index >= minimum_ && index <= maximum_ ) + if ( symbol_index >= minimum_ && symbol_index <= maximum_ ) { - vector_set_t mask = VECTOR_SET_T_ONE << (symbol_index % BITS_PER_ELEMENT); + size_t index = symbol_index / BITS_PER_ELEMENT; + vector_set_t mask = VECTOTR_SET_T_ONE << (symbol_index % BITS_PER_ELEMENT); return (set_[index] & mask) != 0; } return false; @@ -87,17 +87,18 @@ bool GrammarSymbolSet::insert( const GrammarSymbol* symbol ) { if ( symbol ) { - size_t index = symbol->index() / BITS_PER_ELEMENT; + size_t symbol_index = symbol->index(); + size_t index = symbol_index / BITS_PER_ELEMENT; if ( index >= set_.size() ) { set_.insert( set_.end(), index - set_.size() + 1, 0 ); } - vector_set_t mask = VECTOR_SET_T_ONE << (symbol->index() % BITS_PER_ELEMENT); + vector_set_t mask = VECTOTR_SET_T_ONE << (symbol_index % BITS_PER_ELEMENT); if ( !(set_[index] & mask) ) { set_[index] |= mask; - minimum_ = min( minimum_, index ); - maximum_ = max( maximum_, index ); + minimum_ = min( minimum_, symbol_index ); + maximum_ = max( maximum_, symbol_index ); return true; } } @@ -112,7 +113,7 @@ int GrammarSymbolSet::insert( const GrammarSymbolSet& set ) } int added = 0; - for ( size_t i = set.minimum_; i < set.maximum_ + 1; ++i ) + for ( size_t i = 0, imax = set.set_.size(); i < imax; ++i ) { vector_set_t mask = set_[i]; vector_set_t new_mask = mask | set.set_[i]; diff --git a/src/lalr/GrammarSymbolSet.hpp b/src/lalr/GrammarSymbolSet.hpp index 60bcebc..ba6d90b 100644 --- a/src/lalr/GrammarSymbolSet.hpp +++ b/src/lalr/GrammarSymbolSet.hpp @@ -23,8 +23,8 @@ class GrammarSymbolSet GrammarSymbolSet& operator=( GrammarSymbolSet&& set ); GrammarSymbolSet& operator=( const GrammarSymbolSet& set ); - int minimum_index() const; - int maximum_index() const; + size_t minimum_index() const; + size_t maximum_index() const; bool contains( size_t symbol_index ) const; bool insert( const GrammarSymbol* symbol ); int insert( const GrammarSymbolSet& set ); From 06dfb8eeee230d4a317cbfb52153a44a944630c4 Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 23 Jun 2023 11:13:29 +0200 Subject: [PATCH 15/40] Only check for '%whitespace' directive if the grammar has no other errors. --- src/lalr/GrammarParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index a7a8b30..2cc18e6 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -42,7 +42,7 @@ int GrammarParser::parse( const char* start, const char* finish, ErrorPolicy* er { error( 1, LALR_ERROR_SYNTAX, "parsing grammar failed" ); } - if( grammar_->whitespace_tokens().empty() ) + else if( grammar_->whitespace_tokens().empty() ) { error(line_, PARSER_ERROR_UNDEFINED_SYMBOL, "no '%%whitespace' directive defined" ); } From deb8e3ef6ca99c2590105ce1298aee8522b8be1a Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 23 Jun 2023 11:15:00 +0200 Subject: [PATCH 16/40] Fix examples/test that were missing '%whitespace' directive. --- .../lalr_hello_world_example.cpp | 1 + src/lalr/lalr_test/TestParsers.cpp | 28 +++++++++++++++++-- .../lalr_test/TestPrecedenceDirectives.cpp | 3 ++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/lalr/lalr_examples/lalr_hello_world_example.cpp b/src/lalr/lalr_examples/lalr_hello_world_example.cpp index 393b69e..78076ef 100644 --- a/src/lalr/lalr_examples/lalr_hello_world_example.cpp +++ b/src/lalr/lalr_examples/lalr_hello_world_example.cpp @@ -11,6 +11,7 @@ void lalr_hello_world_example() { const char* hello_world_grammar = "hello_world {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " hello_world: 'Hello World!' [hello_world];\n" "}\n" ; diff --git a/src/lalr/lalr_test/TestParsers.cpp b/src/lalr/lalr_test/TestParsers.cpp index e65cfaf..038509d 100644 --- a/src/lalr/lalr_test/TestParsers.cpp +++ b/src/lalr/lalr_test/TestParsers.cpp @@ -106,6 +106,7 @@ SUITE( Parsers ) { const char* or_grammar = "OrOperator {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: one | two | three;\n" " one: '1';\n" " two: '2';\n" @@ -146,6 +147,7 @@ SUITE( Parsers ) { const char* alternate_grammar = "Alternate {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: one two_three;\n" " two_three: two | three;\n" " one: '1';\n" @@ -183,6 +185,7 @@ SUITE( Parsers ) { const char* zero_to_many_repeats_grammar = "ZeroToManyRepeats {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " %left two; \n" " unit: one twos three;\n" " twos: twos two | two | %precedence two;\n" @@ -229,6 +232,7 @@ SUITE( Parsers ) { const char* one_to_many_repeats_grammar = "OneToManyRepeats {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: one twos three;\n" " twos: twos two | two;\n" " one: '1';\n" @@ -270,6 +274,7 @@ SUITE( Parsers ) { const char* optional_grammar = "Optional {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: one two_opt three;\n" " two_opt: two | ;\n" " one: '1';\n" @@ -315,6 +320,7 @@ SUITE( Parsers ) { const char* compound_grammar = "Compound {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " compound: one one_two three;\n" " one_two: one two | two one;\n" " one: '1';\n" @@ -360,6 +366,7 @@ SUITE( Parsers ) { const char* binary_operator_grammar = "BinaryOperator {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " E: E '+' T | T;\n" " T: T '*' F | F;\n" " F: '(' E ')' | i;\n" @@ -414,6 +421,7 @@ SUITE( Parsers ) { const char* nested_productions_grammar = "NestedProductions {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " %left 'b' 'c';\n" " A: 'a' bcs 'd';\n" " bcs: bcs bc | bc | %precedence 'b';\n" @@ -450,6 +458,7 @@ SUITE( Parsers ) { const char* follow_generator_grammar = "FollowGeneration {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: one two four | one three four;\n" " one: '1';\n" " two: '2';\n" @@ -491,6 +500,7 @@ SUITE( Parsers ) { const char* canonical_grammar = "Canonical {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " S: C C;\n" " C: 'c' C | 'd';\n" "}" @@ -522,6 +532,7 @@ SUITE( Parsers ) { const char* multiple_dot_nodes_grammar = "MultipleDotNodesParser {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: lt | lt question;\n" " lt: '<';\n" " question: '?';\n" @@ -553,6 +564,7 @@ SUITE( Parsers ) { const char* productions_on_collapsed_symbols_grammar = "ProductionsOnCollapsedSymbols {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: 'a' [unit];\n" "}" ; @@ -569,6 +581,7 @@ SUITE( Parsers ) { const char* reduce_star_node_grammar = "ReduceStarNode {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " %left one;\n" " unit: ones;\n" " ones: ones one | one | %precedence one;\n" @@ -593,6 +606,7 @@ SUITE( Parsers ) { const char* reduce_parenthesis_grammar = "ReduceParenthesis {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " expr: '(' expr ')' | '1';\n" "}" ; @@ -626,6 +640,7 @@ SUITE( Parsers ) { const char* reduce_star_and_parenthesis_grammar = "ReduceStarAndParenthesis {\n" + " %whitespace \"[ \\t\\r\\n]\" ;\n" " %left '(' '1';\n" " expr: '(' exprs ')' | '1';\n" " exprs: exprs expr | expr | %precedence '(';\n" @@ -877,8 +892,8 @@ SUITE( Parsers ) { const char* unreferenced_symbol_error_grammar = "UnreferencedSymbolError {\n" - " one: 'one';\n" - " unreferenced_symbol: 'two';\n" + " %whitespace \"[ \\t\\r\\n]*\";\n" + " one: 'one';\n" " unreferenced_symbol: 'two';\n" "}" ; @@ -896,6 +911,7 @@ SUITE( Parsers ) { const char* precedence_directive_symbols_grammar = "SymbolsOnlyAppearingInPrecedenceDirectivesAreCountedAsReferenced { \n" + " %whitespace \"[ \\t\\r\\n]*\";\n" " %left unary_minus; \n" " %left '+' '-'; \n" " %left '/' '*'; \n" @@ -994,6 +1010,7 @@ SUITE( Parsers ) { const char* associativity_grammar = "AssociativityDirectives {\n" + " %whitespace \"[ \\t\\r\\n]*\";\n" " %left '+' '-';\n" " %left '*' '/';\n" " %none integer;\n" @@ -1032,6 +1049,7 @@ SUITE( Parsers ) { const char* precedence_grammar = "PrecedenceDirectives {\n" + " %whitespace \"[ \\t\\r\\n]*\";\n" " %left '+';\n" " %left '-';\n" " %none integer;\n" @@ -1080,6 +1098,7 @@ SUITE( Parsers ) { const char* error_processing_grammar = "ErrorProcessing {" + " %whitespace \"[ \\t\\r\\n]*\";\n" " %left error;\n" " %left '+';\n" " expr: expr '+' expr [add] | expr error expr [error] | integer;\n" @@ -1105,6 +1124,7 @@ SUITE( Parsers ) { const char* empty_production_grammar = "EmptyProduction { \n" + " %whitespace \"[ \\t\\r\\n]*\";\n" " %left integer; \n" " unit: statements; \n" " statements: statements statement | statement %precedence integer | %precedence integer; \n" @@ -1142,6 +1162,7 @@ SUITE( Parsers ) "// Line comment LF CR \n\r" "// Line comment CR LF \r\n" "LineComment { \n" + " %whitespace \"[ \\t\\r\\n]*\";\n" " unit: line_comment_example; \n" " line_comment_example: 'LineCommentExample'; // Line comment at the end of a valid line \n" "} \n" @@ -1161,6 +1182,7 @@ SUITE( Parsers ) "...that spans several lines... \n" "*/ \n" "BlockComment /* Block comment between tokens */ { \n" + " %whitespace \"[ \\t\\r\\n]*\";\n" " unit: block_comment_example; /* Block comment at the end of a line */ \n" " block_comment_example: /* Another block comment between tokens */ 'BlockCommentExample'; // Line comment at the end of a valid line \n" "} \n" @@ -1174,6 +1196,7 @@ SUITE( Parsers ) const char* unterminated_block_comment_grammar = "BlockComment { \n" + " %whitespace \"[ \\t\\r\\n]*\";\n" " unit: 'BlockCommentExample'; \n" "} \n" "/* Unterminated block comment... \n" @@ -1186,6 +1209,7 @@ SUITE( Parsers ) { const char* integers_grammar = "integers { \n" + " %whitespace \"[ \\t\\r\\n]*\";\n" " %none error; \n" " %none integer; \n" " statements: statements statement | statement | %precedence integer; \n" diff --git a/src/lalr/lalr_test/TestPrecedenceDirectives.cpp b/src/lalr/lalr_test/TestPrecedenceDirectives.cpp index 0abb829..c96ced9 100644 --- a/src/lalr/lalr_test/TestPrecedenceDirectives.cpp +++ b/src/lalr/lalr_test/TestPrecedenceDirectives.cpp @@ -65,6 +65,7 @@ SUITE( PrecedenceDirectives ) TEST( MissingGrammarHeader ) { const char* grammar = + " %whitespace \"[ \\t\\r\\n]*\"; \n" " %left 'int' float' 'void'; \n" "} \n" ; @@ -77,6 +78,7 @@ SUITE( PrecedenceDirectives ) { const char* grammar = "missing_footer { \n" + " %whitespace \"[ \\t\\r\\n]*\"; \n" " %left 'int' 'float' 'void'; \n" ; EventSink event_sink( LALR_ERROR_SYNTAX ); @@ -88,6 +90,7 @@ SUITE( PrecedenceDirectives ) { const char* grammar = "unterminated_directive_literals { \n" + " %whitespace \"[ \\t\\r\\n]*\"; \n" "%left 'int' float' 'void'; \n" "%left 'return' 'break' 'continue' 'if' 'while' 'for' identifier '{'; \n" "} \n" From 49af659afdc2a40f9457590d5b0b246963d73b38 Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 23 Jun 2023 11:48:36 +0200 Subject: [PATCH 17/40] Check if we are at the end and then stop --- src/lalr/Parser.ipp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lalr/Parser.ipp b/src/lalr/Parser.ipp index 6bbc7f6..aadfbfd 100644 --- a/src/lalr/Parser.ipp +++ b/src/lalr/Parser.ipp @@ -387,6 +387,7 @@ void Parser::parse( Iterator start, const ParserSymbol* symbol = reinterpret_cast( lexer_.symbol() ); while ( parse(symbol, lexer_.lexeme(), lexer_.line(), lexer_.column()) ) { + if(lexer_.full()) break; lexer_.advance(); symbol = reinterpret_cast( lexer_.symbol() ); } From 4e5acced94a259342399f2a038bca31fc3f37271 Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 23 Jun 2023 11:53:53 +0200 Subject: [PATCH 18/40] First working version of an wasm browser based playground --- playground/build.sh | 41 +++ playground/index.html | 74 +++++ playground/index.js | 479 +++++++++++++++++++++++++++++++++ playground/lalr_playground.cpp | 147 ++++++++++ playground/style.css | 101 +++++++ 5 files changed, 842 insertions(+) create mode 100755 playground/build.sh create mode 100644 playground/index.html create mode 100644 playground/index.js create mode 100644 playground/lalr_playground.cpp create mode 100644 playground/style.css diff --git a/playground/build.sh b/playground/build.sh new file mode 100755 index 0000000..17c0ec9 --- /dev/null +++ b/playground/build.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +umask 022 + +myflags="-flto -O2 -s TOTAL_STACK=8MB" +#myflags="-flto -O2 -s TOTAL_STACK=128MB -s INITIAL_MEMORY=256MB" +#myflags="-g4 -fsanitize=address -fsanitize=undefined" + +emsdk-env em++ \ + -std=c++17 $myflags -Wall -Wno-unused-function -pedantic \ + -s EXPORTED_FUNCTIONS=_parse -s EXPORTED_RUNTIME_METHODS=ccall,cwrap \ + -s ALLOW_MEMORY_GROWTH=1 \ + -I../src -DLALR_NO_THREADS \ + ../src/lalr/ErrorPolicy.cpp \ + ../src/lalr/Grammar.cpp \ + ../src/lalr/GrammarAction.cpp \ + ../src/lalr/GrammarCompiler.cpp \ + ../src/lalr/GrammarGenerator.cpp \ + ../src/lalr/GrammarParser.cpp \ + ../src/lalr/GrammarState.cpp \ + ../src/lalr/GrammarSymbol.cpp \ + ../src/lalr/GrammarSymbolSet.cpp \ + ../src/lalr/GrammarTransition.cpp \ + ../src/lalr/RegexAction.cpp \ + ../src/lalr/RegexCharacter.cpp \ + ../src/lalr/RegexCompiler.cpp \ + ../src/lalr/RegexGenerator.cpp \ + ../src/lalr/RegexItem.cpp \ + ../src/lalr/RegexNode.cpp \ + ../src/lalr/RegexNodeLess.cpp \ + ../src/lalr/RegexParser.cpp \ + ../src/lalr/RegexState.cpp \ + ../src/lalr/RegexStateLess.cpp \ + ../src/lalr/RegexSyntaxTree.cpp \ + ../src/lalr/RegexToken.cpp \ + ../src/lalr/RegexTransition.cpp \ + lalr_playground.cpp \ + -o lalr_playground.js + +# --pre-js chpeg-pre.js \ +# -g2 -gsource-map --source-map-base='./' diff --git a/playground/index.html b/playground/index.html new file mode 100644 index 0000000..6580d67 --- /dev/null +++ b/playground/index.html @@ -0,0 +1,74 @@ + + + +LALR Playground + + + +
+
+
    +
  • +
  • Grammar
  • +
  • +
      +
    • + +
    • +
    +
  • +
+
{{syntax}}
+
+
+
+
    +
  • +
  • Input source
  • +
  • +
      +
    • +
    • +
    • +
    +
  • +
+
{{source}}
+
     + mode:  +
+

+    
+
+ +
+
+
+
+ + + + + + diff --git a/playground/index.js b/playground/index.js new file mode 100644 index 0000000..2dc8df3 --- /dev/null +++ b/playground/index.js @@ -0,0 +1,479 @@ +// Setup editors +function setupInfoArea(id) { + const e = ace.edit(id); + e.setShowPrintMargin(false); + e.setOptions({ + readOnly: true, + highlightActiveLine: false, + highlightGutterLine: false + }) + e.renderer.$cursorLayer.element.style.opacity=0; + return e; +} + +function setupEditorArea(id, lsKey) { + const e = ace.edit(id); + e.setShowPrintMargin(false); + e.setValue(localStorage.getItem(lsKey) || ''); + e.moveCursorTo(0, 0); + return e; +} + +const grammarEditor = setupEditorArea("grammar-editor", "grammarText"); +grammarEditor.getSession().setMode("ace/mode/yaml"); +const codeEditor = setupEditorArea("code-editor", "codeText"); + +const codeAst = setupInfoArea("code-ast"); +const codeLexer = setupInfoArea("code-lexer"); + +function loadLalr_sample(self) { + let base_url = "./" + switch(self.options[self.selectedIndex].value) { + case "Json parser": + $.get(base_url + "json3.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.json.txt", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/json"); + }); + break; + case "Lua parser": + $.get(base_url + "lua.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.lua", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/lua"); + }); + break; + case "Carbon parser": + $.get(base_url + "carbon-lang.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "prelude.carbon", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/typescript"); + }); + break; + case "Postgresql parser (be patient)": + $.get(base_url + "postgresql-16.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.sql", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/sql"); + }); + break; + case "C++ parser (bug)": + $.get(base_url + "cxx-parser.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.cpp", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/c_cpp"); + }); + break; + case "Linden Script parser": + $.get(base_url + "lsl_ext.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.lsl", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/text"); + }); + break; + case "Bison parser (not working)": + $.get(base_url + "bison.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "carbon-lang.y", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/yaml"); + }); + break; + case "DParser parser (not working)": + $.get(base_url + "dparser.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.dparser", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/yaml"); + }); + break; + case "Parse_gen parser (not working)": + $.get(base_url + "parse_gen.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.parse_gen", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/yaml"); + }); + break; + case "Tameparse parser (not working)": + $.get(base_url + "tameparser.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.tameparser", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/yaml"); + }); + break; + case "Javascript parser (not working)": + $.get(base_url + "javascript.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.js", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/javascript"); + }); + break; + case "JavascriptCore parser": + $.get(base_url + "javascript-core.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.js", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/javascript"); + }); + break; + case "Ansi C parser": + $.get(base_url + "cparser.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.c", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/c_cpp"); + }); + break; + case "Java11 parser": + $.get(base_url + "java11.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.java", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/java"); + }); + break; + case "Rust parser": + $.get(base_url + "rust.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.rs", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/rust"); + }); + break; + case "Go parser (not working)": + $.get(base_url + "go.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.go", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/golang"); + }); + break; + case "PHP-8.2 parser (not working)": + $.get(base_url + "php-8.2.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.php", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/php"); + }); + break; + case "Gringo/Clingo non grounded parser": + $.get(base_url + "gringo-ng.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.clingo", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/text"); + }); + break; + case "Ada parser": + $.get(base_url + "ada-adayacc.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.adb", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/ada"); + }); + break; + } +} + +$('#opt-mode').val(localStorage.getItem('optimizationMode') || '2'); +$('#gen-ebnf').prop('checked', localStorage.getItem('gen-ebnf') === 'true'); +$('#auto-refresh').prop('checked', localStorage.getItem('autoRefresh') === 'true'); +$('#parse').prop('disabled', $('#auto-refresh').prop('checked')); + +// Parse +function escapeHtml(unsafe) { + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + +function nl2br(str) { + return str.replace(/\n/g, '
\n') +} + +function textToErrors(str) { + let errors = []; + var regExp = /([^\n]+?)\n/g, match; + while (match = regExp.exec(str)) { + let msg = match[1]; + let line_col = msg.match(/^lalr \((\d+):(\d+)\):/); + if (line_col) { + errors.push({"ln": line_col[1], "col":line_col[2], "msg": msg}); + } else { + errors.push({"msg": msg}); + } + } + return errors; +} + +function generateErrorListHTML(errors) { + let html = '
    '; + + html += $.map(errors, function (x) { + if (x.ln > 0) { + return '
  • ' + escapeHtml(x.msg) + '
  • '; + } else { + return '
  • ' + escapeHtml(x.msg) + '
  • '; + } + }).join(''); + + html += '
      '; + + return html; +} + +function updateLocalStorage() { + localStorage.setItem('grammarText', grammarEditor.getValue()); + localStorage.setItem('codeText', codeEditor.getValue()); + localStorage.setItem('optimizationMode', $('#opt-mode').val()); + localStorage.setItem('gen-ebnf', $('#gen-ebnf').prop('checked')); + localStorage.setItem('autoRefresh', $('#auto-refresh').prop('checked')); +} + +var parse_start_time = 0; + +function parse() { + const $grammarValidation = $('#grammar-validation'); + const $grammarInfo = $('#grammar-info'); + const grammarText = grammarEditor.getValue(); + + const $codeValidation = $('#code-validation'); + const $codeInfo = $('#code-info'); + const codeText = codeEditor.getValue(); + + const optimizationMode = $('#opt-mode').val(); + const generate_ebnf = $('#gen-ebnf').prop('checked'); + const lexer = $('#show-lexer').prop('checked'); + + $grammarInfo.html(''); + $grammarValidation.hide(); + $codeInfo.html(''); + $codeValidation.hide(); + codeAst.setValue(''); + codeLexer.setValue(''); + + outputs.compile_status = ''; + outputs.parse_status = ''; + outputs.parse_stats = ''; + outputs.ast = ''; + outputs.lexer = ''; + outputs.parse_time = ''; + + if (grammarText.length === 0) { + return; + } + + $('#overlay').css({ + 'z-index': '1', + 'display': 'block', + 'background-color': 'rgba(0, 0, 0, 0.1)' + }); + + window.setTimeout(() => { + parse_start_time = new Date().getTime(); + lalr_parse(grammarText, codeText, lexer, generate_ebnf, 0); + + $('#overlay').css({ + 'z-index': '-1', + 'display': 'none', + 'background-color': 'rgba(1, 1, 1, 1.0)' + }); + + const isGenEBNF = result.parse == -3; + if (result.compile == 0 || isGenEBNF) { + $grammarValidation.removeClass('validation-invalid').show(); + + codeAst.insert(outputs.ast); + codeLexer.insert(outputs.lexer); + + if (result.parse == 0) { + $codeValidation.removeClass('validation-invalid').show(); + } else { + $codeValidation.addClass('validation-invalid').show(); + } + + if(isGenEBNF) { + $grammarInfo.html("
      " + escapeHtml(outputs.compile_status.replaceAll("'\\''", '"\'"')) + "
      "); + return; + } + + if (outputs.parse_status.length > 0) { + const errors = textToErrors(outputs.parse_status); + const html = generateErrorListHTML(errors); + $codeInfo.html(html); + } + else { + //const parse_end_time = new Date().getTime(); + //$codeInfo.html('Execution time: ' + (parse_end_time - parse_start_time) + ' ms'); + $codeInfo.html(outputs.parse_time); + $grammarInfo.html("
      " + outputs.parse_stats + "
      "); + } + } else { + $grammarValidation.addClass('validation-invalid').show(); + } + + if (outputs.compile_status.length > 0) { + const errors = textToErrors(outputs.compile_status); + const html = generateErrorListHTML(errors); + $grammarInfo.html(html); + } + }, 0); +} + +// Event handing for text editing +let timer; +function setupTimer() { + clearTimeout(timer); + timer = setTimeout(() => { + updateLocalStorage(); + if ($('#auto-refresh').prop('checked')) { + parse(); + } + }, 200); +}; +grammarEditor.getSession().on('change', setupTimer); +codeEditor.getSession().on('change', setupTimer); + +// Event handing in the info area +function makeOnClickInInfo(editor) { + return function () { + const el = $(this); + let line = el.data('ln') - 1; + let col = el.data('col') - 1; + editor.navigateTo(line, col); + editor.scrollToLine(line, true, false, null); + editor.focus(); + } +}; +$('#grammar-info').on('click', 'li[data-ln]', makeOnClickInInfo(grammarEditor)); +$('#code-info').on('click', 'li[data-ln]', makeOnClickInInfo(codeEditor)); + +// Event handing in the AST optimization +$('#opt-mode').on('change', setupTimer); +$('#gen-ebnf').on('change', setupTimer); +$('#show-lexer').on('change', setupTimer); +$('#auto-refresh').on('change', () => { + updateLocalStorage(); + $('#parse').prop('disabled', $('#auto-refresh').prop('checked')); + setupTimer(); +}); +$('#parse').on('click', parse); + +// Resize editors to fit their parents +function resizeEditorsToParent() { + codeEditor.resize(); + codeEditor.renderer.updateFull(); + codeAst.resize(); + codeAst.renderer.updateFull(); + codeLexer.resize(); + codeLexer.renderer.updateFull(); +} + +// Show windows +function setupToolWindow(lsKeyName, buttonSel, codeSel, showDefault) { + let storedValue = localStorage.getItem(lsKeyName); + if (!storedValue) { + localStorage.setItem(lsKeyName, showDefault); + storedValue = localStorage.getItem(lsKeyName); + } + let show = storedValue === 'true'; + $(buttonSel).prop('checked', show); + $(codeSel).css({ 'display': show ? 'block' : 'none' }); + + $(buttonSel).on('change', () => { + show = !show; + localStorage.setItem(lsKeyName, show); + $(codeSel).css({ 'display': show ? 'block' : 'none' }); + resizeEditorsToParent(); + }); +} + +setupToolWindow('show-ast', '#show-ast', '#code-ast', true); +setupToolWindow('show-lexer', '#show-lexer', '#code-lexer', false); + +// Show page +$('#main').css({ + 'display': 'flex', +}); + +// used to collect output from C +var outputs = { + 'default': '', + 'compile_status': '', + 'ast': '', + 'parse_status': '', + 'parse_stats': '', + 'parse_time': '', +}; + +// current output (key in `outputs`) +var output = "default"; + +// results of the various stages +var result = { + 'compile': 0, + 'parse': 0, + 'ast': 0, + 'lexer': 0, +}; + +// lalr_parse function: initialized when emscripten runtime loads +var lalr_parse = null; + +// Emscripten +var Module = { + + // intercept stdout (print) and stderr (printErr) + // note: text received is line based and missing final '\n' + + 'print': function(text) { + outputs[output] += text + "\n"; + }, + 'printErr': function(text) { + outputs[output] += text + "\n"; + }, + + // called when emscripten runtime is initialized + 'onRuntimeInitialized': function() { + // wrap the C `parse` function + lalr_parse = cwrap('parse', 'number', ['string', 'string', 'number']); + // Initial parse + if ($('#auto-refresh').prop('checked')) { + parse(); + } + }, +}; + +// vim: sw=2:sts=2 diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp new file mode 100644 index 0000000..8baf166 --- /dev/null +++ b/playground/lalr_playground.cpp @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include + +EM_JS(void, switch_output, (const char* which), { + output = UTF8ToString(which); +}) + +EM_JS(void, set_result, (const char* which, int value), { + result_name = UTF8ToString(which); + result[result_name] = value; +}) + +EM_JS(void, showDiffTime, (const char *title), { + const now = new Date().getTime(); + const diff_time = now - parse_start_time; + + outputs.parse_time += UTF8ToString(title) + " -> Time taken : " + diff_time + "ms
      \n"; + parse_start_time = now; +}); + +typedef unsigned char mychar_t; + +struct C_MultLineCommentLexer +{ + static lalr::PositionIterator string_lexer( const lalr::PositionIterator& begin, + const lalr::PositionIterator& end, + std::basic_string* lexeme, + const void** /*symbol*/ ) + { + LALR_ASSERT( lexeme ); + + lexeme->clear(); + //printf("C_MultLineCommentLexer : %s\n", lexeme->c_str()); + + bool done = false; + lalr::PositionIterator i = begin; + while ( i != end && !done) + { + switch( *i ) + { + case '*': + ++i; + if(i != end && *i == '/') done = true; + continue; + break; + } + ++i; + } + if ( i != end ) + { + LALR_ASSERT( *i == '/' ); + ++i; + } + return i; + } +}; + + +extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLexer, int generate_ebnf, int profile) +{ + int err = 0; // currently, zero is always returned; result codes for each part + // are sent to JS via set_result() + + // default result values (-1 indicates we didn't reach a part) + int compile_result = -1; + int parse_result = -1; + int ast_result = -1; + int profile_result = -1; + + // baked-in verbose levels + const int compile_verbose = 0; + const int parse_verbose = 0; + + // + // Compile Grammar + // + + switch_output("compile_status"); + + lalr::GrammarCompiler compiler; + lalr::ErrorPolicy error_policy; + int errors = compiler.compile( grammar, grammar + strlen(grammar), &error_policy, generate_ebnf != 0); + + if (errors != 0) { + fprintf(stderr, "Error compiling grammar. " + "Error count = %d\n", errors); + err = -1; + goto done; + } + else { + if(generate_ebnf) { + err = -3; + parse_result = 0; + goto done; + } + if (compile_verbose) { + fprintf(stderr, "Grammar compiled successfully.\n"); + } + showDiffTime("Compile grammar"); + } + + switch_output("parse_stats"); + compiler.showStats(); + + // + // Parse input + // + + switch_output("parse_status"); + + if(input) { + lalr::ErrorPolicy error_policy_input; + lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); + parser.lexer_action_handlers() + ( "C_MultilineComment", &C_MultLineCommentLexer::string_lexer ) + ; + if(dumpLexer) { + switch_output("lexer"); + parser.dumpLex( input, input + strlen((const char*)input) ); + } + else parser.parse( input, input + strlen((const char*)input) ); + + parse_result = parser.accepted() == 1 && parser.full() == 1; + if (parse_result) { + if (parse_verbose) { + fprintf(stderr, "Parse successful.\n"); + } + showDiffTime("Parse input"); + } + else { + err = -2; + goto done; + } + } + + +done: + + set_result("compile", errors); + set_result("parse", parse_result ? 0 : err); + + return err; +} diff --git a/playground/style.css b/playground/style.css new file mode 100644 index 0000000..0580428 --- /dev/null +++ b/playground/style.css @@ -0,0 +1,101 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; + text-decoration: none; + list-style: none; +} +body { + display: flex; + flex-direction: column; + height: 100vh; +} +#main { + flex: 1; + display: none; + z-index: 0; +} +.editor-container { + flex: 1; + width: 100%; + display: flex; + flex-direction: column; + margin: 6px; +} +.editor-container:first-child { + margin-right: 0; +} +.editor-header { + display: flex; + margin: 0 2px; +} +.editor-header > li { + height: 32px; + line-height: 24px; +} +.editor-header > li > span { + margin-right: 6px; +} +.editor-options { + margin-left: auto; +} +.editor-header-options { + display: flex; +} +.validation { + display: inline-block; + height: 20px; + width: 20px; + margin: 2px 0; + border-radius: 50%; + background-color: lightgreen; +} +.validation-invalid { + background-color: pink; +} +.option { + margin-right: 8px; +} +.option:last-child { + margin-right: 0; +} +.option input[type=checkbox] { + margin-right: 4px; +} +.option .parse { + padding-left: 8px; + padding-right: 8px; + height: 24px; + cursor: pointer; +} +.editor-area { + flex: 1; + border: 1px solid lightgray; +} +.editor-info { + margin-top: 6px; + height: 160px; + border: 1px solid lightgray; + padding: 8px; + overflow-y: auto; +} +.editor-info li[data-ln] { + cursor: pointer; +} +.editor-info li[data-ln]:hover{ + background-color: lightyellow; +} +.editor-sub-header { + padding: 4px; +} +.show-toggle { + margin-right: 6px; +} +#overlay { + position: absolute; + width: 100vw; + height: 100vh; + cursor: wait; + display: none; + z-index: -1; +} From 41860c1570ec45799f275ee0642fa99a62e85b3b Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 23 Jun 2023 16:05:20 +0200 Subject: [PATCH 19/40] Add a naive implementation of "%case_insensitive" directive, right now it only work on literals and only for ASCII --- src/lalr/Grammar.cpp | 7 +++++ src/lalr/Grammar.hpp | 3 +++ src/lalr/GrammarCompiler.cpp | 50 ++++++++++++++++++++++++++++++++++-- src/lalr/GrammarParser.cpp | 12 +++++++++ src/lalr/GrammarParser.hpp | 1 + src/lalr/RegexGenerator.cpp | 2 +- src/lalr/RegexToken.cpp | 2 +- src/lalr/RegexToken.hpp | 2 +- 8 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 8749116..8b5b9c8 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -30,6 +30,7 @@ Grammar::Grammar() , whitespace_tokens_() , active_whitespace_directive_( false ) , active_precedence_directive_( false ) +, active_case_insensitive_(false) , associativity_( ASSOCIATE_NULL ) , precedence_( 0 ) , active_production_( nullptr ) @@ -154,6 +155,12 @@ Grammar& Grammar::assoc_prec( int /*line*/ ) return *this; } +Grammar& Grammar::case_insensitive() +{ + active_case_insensitive_ = true; + return *this; +} + Grammar& Grammar::precedence() { LALR_ASSERT( active_symbol_ ); diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index 664816c..a6c701a 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -29,6 +29,7 @@ class Grammar std::vector whitespace_tokens_; ///< Regular expressions that define whitespace in this grammar. bool active_whitespace_directive_; ///< True iff a whitespace directive is active. bool active_precedence_directive_; ///< True iff a precedence directive is active. + bool active_case_insensitive_; ///< True iff a case insensitive directive is active. Associativity associativity_; ///< Most recently set associativity. int precedence_; ///< Current precedence. GrammarProduction* active_production_; ///< Currently active production. @@ -56,6 +57,7 @@ class Grammar Grammar& none( int line ); Grammar& assoc_prec( int line ); Grammar& whitespace(); + Grammar& case_insensitive(); Grammar& precedence(); Grammar& production( const char* identifier, int line ); Grammar& end_production(); @@ -65,6 +67,7 @@ class Grammar Grammar& literal( const char* literal, int line ); Grammar& regex( const char* regex, int line ); Grammar& identifier( const char* identifier, int line ); + bool is_case_insensitive() const {return active_case_insensitive_;}; void genEBNF(); private: diff --git a/src/lalr/GrammarCompiler.cpp b/src/lalr/GrammarCompiler.cpp index 652bbe8..9c733ab 100644 --- a/src/lalr/GrammarCompiler.cpp +++ b/src/lalr/GrammarCompiler.cpp @@ -86,6 +86,7 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e grammar.genEBNF(); return errors; } + bool isCaseInsensitive = grammar.is_case_insensitive(); GrammarGenerator generator; errors = generator.generate( grammar, error_policy ); @@ -97,6 +98,9 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e // the terminal symbols in the grammar. vector tokens; int column = 1; + const char *symbol_lexeme; + std::string regex; + if(isCaseInsensitive) regex.reserve(255); const vector>& grammar_symbols = generator.symbols(); for ( size_t i = 0; i < grammar_symbols.size(); ++i, ++column ) { @@ -107,8 +111,50 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e const ParserSymbol* symbol = &symbols_[i]; LALR_ASSERT( symbol ); int line = grammar_symbol->line(); - RegexTokenType token_type = grammar_symbol->lexeme_type() == LEXEME_REGULAR_EXPRESSION ? TOKEN_REGULAR_EXPRESSION : TOKEN_LITERAL; - tokens.emplace_back( RegexToken(token_type, line, column, symbol, symbol->lexeme) ); + RegexTokenType token_type; + symbol_lexeme = symbol->lexeme; + switch(grammar_symbol->lexeme_type()) + { + case LEXEME_REGULAR_EXPRESSION: token_type = TOKEN_REGULAR_EXPRESSION; break; + case LEXEME_NULL: token_type = TOKEN_LITERAL; break; + default: + if(isCaseInsensitive) + { + bool needRegex = false; + const char *p = symbol->lexeme; + regex.clear(); + for(; *p; ++p) + { + bool isLower = *p >= 'a' && *p <= 'z'; + bool isUpper = *p >= 'A' && *p <= 'Z'; + if(isLower || isUpper) + { + needRegex = true; + regex.push_back('['); + regex.push_back(*p); + if(isLower) + { + regex.push_back(*p -32); + } + else + { + regex.push_back(*p +32); + } + regex.push_back(']'); + } + else regex.push_back(*p); + } + if(needRegex) + { + token_type = TOKEN_REGULAR_EXPRESSION; + symbol_lexeme = regex.c_str(); + //printf("Literal2Regex : %s : %s\n", symbol->lexeme, symbol_lexeme); + break; + } + } + token_type = TOKEN_LITERAL; + } + tokens.emplace_back( RegexToken(token_type, line, column, symbol, symbol_lexeme) ); } } diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index 2cc18e6..a3e8b20 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -75,6 +75,7 @@ bool GrammarParser::match_statement() return match_associativity_statement() || match_whitespace_statement() || + match_case_insensitive_statement() || match_production_statement() ; } @@ -105,6 +106,17 @@ bool GrammarParser::match_whitespace_statement() return false; } +bool GrammarParser::match_case_insensitive_statement() +{ + if ( match("%case_insensitive") ) + { + grammar_->case_insensitive(); + expect( ";" ); + return true; + } + return false; +} + bool GrammarParser::match_production_statement() { if ( match_identifier() ) diff --git a/src/lalr/GrammarParser.hpp b/src/lalr/GrammarParser.hpp index b77d364..aca7105 100644 --- a/src/lalr/GrammarParser.hpp +++ b/src/lalr/GrammarParser.hpp @@ -30,6 +30,7 @@ class GrammarParser bool match_statement(); bool match_associativity_statement(); bool match_whitespace_statement(); + bool match_case_insensitive_statement(); bool match_production_statement(); bool match_symbols(); bool match_symbol(); diff --git a/src/lalr/RegexGenerator.cpp b/src/lalr/RegexGenerator.cpp index a64e15f..1ecdcb0 100644 --- a/src/lalr/RegexGenerator.cpp +++ b/src/lalr/RegexGenerator.cpp @@ -159,7 +159,7 @@ int RegexGenerator::generate( const std::string& regular_expression, void* symbo start_state_ = nullptr; ranges_.clear(); - RegexToken token( TOKEN_REGULAR_EXPRESSION, 0, 0, symbol, regular_expression ); + RegexToken token( TOKEN_REGULAR_EXPRESSION, 0, 0, symbol, regular_expression.c_str() ); syntax_tree_->reset( token, this ); generate_states( *syntax_tree_ ); error_policy_ = nullptr; diff --git a/src/lalr/RegexToken.cpp b/src/lalr/RegexToken.cpp index 27e724a..03a7119 100644 --- a/src/lalr/RegexToken.cpp +++ b/src/lalr/RegexToken.cpp @@ -10,7 +10,7 @@ using std::find; using std::vector; using namespace lalr; -RegexToken::RegexToken( RegexTokenType type, int line, int column, const void* symbol, const std::string& lexeme ) +RegexToken::RegexToken( RegexTokenType type, int line, int column, const void* symbol, const char* lexeme ) : type_( type ) , line_( line ) , column_( column ) diff --git a/src/lalr/RegexToken.hpp b/src/lalr/RegexToken.hpp index adfb183..f3506a8 100644 --- a/src/lalr/RegexToken.hpp +++ b/src/lalr/RegexToken.hpp @@ -21,7 +21,7 @@ class RegexToken mutable std::vector conflicted_with_; ///< The RegexTokens that this RegexToken has conflicted with. public: - RegexToken( RegexTokenType type, int line, int column, const void* symbol, const std::string& lexeme ); + RegexToken( RegexTokenType type, int line, int column, const void* symbol, const char* lexeme ); RegexToken( const RegexToken& token, const void* symbol ); RegexTokenType type() const; int line() const; From 0aec408f835235b915a48d6e2ae5c580d073127f Mon Sep 17 00:00:00 2001 From: mingodad Date: Fri, 23 Jun 2023 20:20:32 +0200 Subject: [PATCH 20/40] Add column info to error messages in ErrorPolicy --- src/lalr/ErrorPolicy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lalr/ErrorPolicy.cpp b/src/lalr/ErrorPolicy.cpp index d458f0d..793ac8e 100644 --- a/src/lalr/ErrorPolicy.cpp +++ b/src/lalr/ErrorPolicy.cpp @@ -33,9 +33,9 @@ ErrorPolicy::~ErrorPolicy() // @param ... // Arguments as described by *format*. */ -void ErrorPolicy::lalr_error( int line, int /*column*/, int /*error*/, const char* format, va_list args ) +void ErrorPolicy::lalr_error( int line, int column, int /*error*/, const char* format, va_list args ) { - fprintf( stderr, "lalr (%d): ERROR: ", line ); + fprintf( stderr, "lalr (%d:%d): ERROR: ", line, column ); vfprintf( stderr, format, args ); fprintf( stderr, "\n" ); } From d9e8e15f18f2b2afaf38c5f806a7dd3e096e9eb0 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sun, 25 Jun 2023 09:00:17 +0200 Subject: [PATCH 21/40] Add special regex character escape for the naive case insensitive implementation --- src/lalr/GrammarCompiler.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/lalr/GrammarCompiler.cpp b/src/lalr/GrammarCompiler.cpp index 9c733ab..51bf7df 100644 --- a/src/lalr/GrammarCompiler.cpp +++ b/src/lalr/GrammarCompiler.cpp @@ -84,6 +84,7 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e if(genEBNF) { grammar.genEBNF(); + //grammar.genNakedGrammar(); return errors; } bool isCaseInsensitive = grammar.is_case_insensitive(); @@ -142,7 +143,25 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e } regex.push_back(']'); } - else regex.push_back(*p); + else + { + switch(*p) + { + case '+': + case '-': + case '*': + case '?': + case '[': + case ']': + case '(': + case ')': + case '|': + case '\\': + regex.push_back('\\'); + break; + } + regex.push_back(*p); + } } if(needRegex) { From 9b72871612720e0e8c21edf35d0eceb4a911da41 Mon Sep 17 00:00:00 2001 From: mingodad Date: Mon, 26 Jun 2023 10:23:59 +0200 Subject: [PATCH 22/40] Make trivial methods inline. --- playground/build.sh | 6 -- src/lalr/Grammar.cpp | 45 ------------ src/lalr/Grammar.hpp | 20 +++--- src/lalr/GrammarAction.cpp | 36 ---------- src/lalr/GrammarAction.hpp | 22 +++++- src/lalr/GrammarState.cpp | 44 ------------ src/lalr/GrammarState.hpp | 8 +-- src/lalr/GrammarTransition.cpp | 77 -------------------- src/lalr/GrammarTransition.hpp | 43 ++++++++--- src/lalr/RegexAction.cpp | 45 ------------ src/lalr/RegexAction.hpp | 10 ++- src/lalr/RegexCharacter.cpp | 62 ---------------- src/lalr/RegexCharacter.hpp | 40 +++++++++-- src/lalr/RegexGenerator.cpp | 15 ---- src/lalr/RegexGenerator.hpp | 9 ++- src/lalr/RegexItem.cpp | 30 -------- src/lalr/RegexItem.hpp | 21 ++++-- src/lalr/RegexNode.cpp | 127 --------------------------------- src/lalr/RegexNode.hpp | 63 ++++++++++++---- src/lalr/RegexNodeLess.cpp | 30 -------- src/lalr/RegexNodeLess.hpp | 21 ------ src/lalr/RegexState.cpp | 90 ----------------------- src/lalr/RegexState.hpp | 44 +++++++++--- src/lalr/RegexStateLess.cpp | 14 ---- src/lalr/RegexStateLess.hpp | 22 ------ src/lalr/RegexSyntaxTree.cpp | 1 - src/lalr/RegexSyntaxTree.hpp | 3 +- src/lalr/RegexToken.cpp | 24 ------- src/lalr/RegexToken.hpp | 10 +-- src/lalr/RegexTransition.cpp | 108 ---------------------------- src/lalr/RegexTransition.hpp | 57 +++++++++++++-- src/lalr/lalr.forge | 7 -- 32 files changed, 270 insertions(+), 884 deletions(-) delete mode 100644 src/lalr/GrammarAction.cpp delete mode 100644 src/lalr/RegexAction.cpp delete mode 100644 src/lalr/RegexCharacter.cpp delete mode 100644 src/lalr/RegexNodeLess.cpp delete mode 100644 src/lalr/RegexNodeLess.hpp delete mode 100644 src/lalr/RegexStateLess.cpp delete mode 100644 src/lalr/RegexStateLess.hpp delete mode 100644 src/lalr/RegexTransition.cpp diff --git a/playground/build.sh b/playground/build.sh index 17c0ec9..aad41a7 100755 --- a/playground/build.sh +++ b/playground/build.sh @@ -13,7 +13,6 @@ emsdk-env em++ \ -I../src -DLALR_NO_THREADS \ ../src/lalr/ErrorPolicy.cpp \ ../src/lalr/Grammar.cpp \ - ../src/lalr/GrammarAction.cpp \ ../src/lalr/GrammarCompiler.cpp \ ../src/lalr/GrammarGenerator.cpp \ ../src/lalr/GrammarParser.cpp \ @@ -21,19 +20,14 @@ emsdk-env em++ \ ../src/lalr/GrammarSymbol.cpp \ ../src/lalr/GrammarSymbolSet.cpp \ ../src/lalr/GrammarTransition.cpp \ - ../src/lalr/RegexAction.cpp \ - ../src/lalr/RegexCharacter.cpp \ ../src/lalr/RegexCompiler.cpp \ ../src/lalr/RegexGenerator.cpp \ ../src/lalr/RegexItem.cpp \ ../src/lalr/RegexNode.cpp \ - ../src/lalr/RegexNodeLess.cpp \ ../src/lalr/RegexParser.cpp \ ../src/lalr/RegexState.cpp \ - ../src/lalr/RegexStateLess.cpp \ ../src/lalr/RegexSyntaxTree.cpp \ ../src/lalr/RegexToken.cpp \ - ../src/lalr/RegexTransition.cpp \ lalr_playground.cpp \ -o lalr_playground.js diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 8b5b9c8..219cd57 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -50,51 +50,6 @@ Grammar::~Grammar() { } -const std::string& Grammar::identifier() const -{ - return identifier_; -} - -std::vector>& Grammar::symbols() -{ - return symbols_; -} - -std::vector>& Grammar::productions() -{ - return productions_; -} - -std::vector>& Grammar::actions() -{ - return actions_; -} - -const std::vector& Grammar::whitespace_tokens() const -{ - return whitespace_tokens_; -} - -GrammarSymbol* Grammar::start_symbol() const -{ - return start_symbol_; -} - -GrammarSymbol* Grammar::end_symbol() const -{ - return end_symbol_; -} - -GrammarSymbol* Grammar::error_symbol() const -{ - return error_symbol_; -} - -GrammarSymbol* Grammar::whitespace_symbol() const -{ - return whitespace_symbol_; -} - Grammar& Grammar::grammar( const std::string& identifier ) { identifier_ = identifier; diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index a6c701a..73aeafa 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -42,15 +42,15 @@ class Grammar public: Grammar(); ~Grammar(); - const std::string& identifier() const; - std::vector>& symbols(); - std::vector>& productions(); - std::vector>& actions(); - const std::vector& whitespace_tokens() const; - GrammarSymbol* start_symbol() const; - GrammarSymbol* end_symbol() const; - GrammarSymbol* error_symbol() const; - GrammarSymbol* whitespace_symbol() const; + const std::string& identifier() const { return identifier_;} + std::vector>& symbols() { return symbols_;} + std::vector>& productions() { return productions_;} + std::vector>& actions() { return actions_;} + const std::vector& whitespace_tokens() const { return whitespace_tokens_;} + GrammarSymbol* start_symbol() const { return start_symbol_;} + GrammarSymbol* end_symbol() const { return end_symbol_;} + GrammarSymbol* error_symbol() const { return error_symbol_;} + GrammarSymbol* whitespace_symbol() const { return whitespace_symbol_;} Grammar& grammar( const std::string& identifier ); Grammar& left( int line ); Grammar& right( int line ); @@ -67,7 +67,7 @@ class Grammar Grammar& literal( const char* literal, int line ); Grammar& regex( const char* regex, int line ); Grammar& identifier( const char* identifier, int line ); - bool is_case_insensitive() const {return active_case_insensitive_;}; + bool is_case_insensitive() const {return active_case_insensitive_;} void genEBNF(); private: diff --git a/src/lalr/GrammarAction.cpp b/src/lalr/GrammarAction.cpp deleted file mode 100644 index a14a6b0..0000000 --- a/src/lalr/GrammarAction.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// GrammarAction.cpp -// Copyright (c) Charles Baker. All rights reserved. -// - -#include "GrammarAction.hpp" -#include "assert.hpp" - -using namespace lalr; - -/** -// Constructor. -// -// @param index -// The index of this action (assumed >= 0). -// -// @param identifier -// The identifier of this action (assumed not empty). -*/ -GrammarAction::GrammarAction( int index, const std::string& identifier ) -: index_( index ) -, identifier_( identifier ) -{ - LALR_ASSERT( index_ >= 0 ); - LALR_ASSERT( !identifier_.empty() ); -} - -int GrammarAction::index() const -{ - return index_; -} - -const std::string& GrammarAction::identifier() const -{ - return identifier_; -} diff --git a/src/lalr/GrammarAction.hpp b/src/lalr/GrammarAction.hpp index 4b0d2c6..262efa1 100644 --- a/src/lalr/GrammarAction.hpp +++ b/src/lalr/GrammarAction.hpp @@ -2,6 +2,7 @@ #define LALR_GRAMMARACTION_HPP_INCLUDED #include +#include "assert.hpp" namespace lalr { @@ -15,9 +16,24 @@ class GrammarAction std::string identifier_; ///< The identifier of this action. public: - GrammarAction( int index, const std::string& identifier ); - int index() const; - const std::string& identifier() const; +/** +// Constructor. +// +// @param index +// The index of this action (assumed >= 0). +// +// @param identifier +// The identifier of this action (assumed not empty). +*/ + GrammarAction( int index, const std::string& identifier ) + : index_( index ) + , identifier_( identifier ) + { + LALR_ASSERT( index_ >= 0 ); + LALR_ASSERT( !identifier_.empty() ); + } + int index() const { return index_;}; + const std::string& identifier() const { return identifier_;}; static const int INVALID_INDEX = -1; }; diff --git a/src/lalr/GrammarState.cpp b/src/lalr/GrammarState.cpp index 27b0025..9cc1027 100644 --- a/src/lalr/GrammarState.cpp +++ b/src/lalr/GrammarState.cpp @@ -66,17 +66,6 @@ GrammarItem* GrammarState::find_item( GrammarProduction* production, int positio return i != items_.end() ? const_cast(&(*i)) : nullptr; } -/** -// Get the items in this state. -// -// @return -// The items. -*/ -const std::set& GrammarState::items() const -{ - return items_; -} - /** // Find a transition on \e symbol from this state. // @@ -102,17 +91,6 @@ const GrammarTransition* GrammarState::find_transition_by_symbol( const GrammarS return nullptr; } -/** -// Get the transitions from this state. -// -// @return -// The transitions. -*/ -const std::vector& GrammarState::transitions() const -{ - return transitions_; -} - int GrammarState::count_valid_transitions() const { int valid_transitions = 0; @@ -123,17 +101,6 @@ int GrammarState::count_valid_transitions() const return valid_transitions; } -/** -// Get the index of this state. -// -// @return -// The index of this state. -*/ -int GrammarState::index() const -{ - return index_; -} - /** // Less than operator. // @@ -232,17 +199,6 @@ GrammarTransition* GrammarState::find_transition_by_symbol( const GrammarSymbol* return nullptr; } -/** -// Set the index of this state. -// -// @param index -// The value to set the index of this state to. -*/ -void GrammarState::set_index( int index ) -{ - index_ = index; -} - void GrammarState::add_transition( GrammarTransition* transition ) { LALR_ASSERT( transition ); diff --git a/src/lalr/GrammarState.hpp b/src/lalr/GrammarState.hpp index 3a82d68..01adb70 100644 --- a/src/lalr/GrammarState.hpp +++ b/src/lalr/GrammarState.hpp @@ -28,19 +28,19 @@ class GrammarState GrammarState( const GrammarState& state ); GrammarItem* find_item( GrammarProduction* production, int position ) const; - const std::set& items() const; + const std::set& items() const {return items_;} const GrammarTransition* find_transition_by_symbol( const GrammarSymbol* symbol ) const; - const std::vector& transitions() const; + const std::vector& transitions() const {return transitions_;} int count_valid_transitions() const; std::string label() const; - int index() const; + int index() const { return index_;} bool operator<( const GrammarState& state ) const; int add_item( GrammarProduction* production, int position ); void add_shift_transition( GrammarTransition* transition ); void add_reduce_transition( GrammarTransition* transition ); GrammarTransition* find_transition_by_symbol( const GrammarSymbol* symbol ); - void set_index( int index ); + void set_index( int index ) {index_ = index;} static const int INVALID_INDEX = -1; diff --git a/src/lalr/GrammarTransition.cpp b/src/lalr/GrammarTransition.cpp index ed52859..c607b88 100644 --- a/src/lalr/GrammarTransition.cpp +++ b/src/lalr/GrammarTransition.cpp @@ -48,83 +48,6 @@ GrammarTransition::GrammarTransition( const GrammarSymbol* symbol, GrammarState* LALR_ASSERT( state_ ); } -/** -// Get the state that this transition is to. -// -// @return -// The state or null if this transition is a reduction. -*/ -GrammarState* GrammarTransition::state() const -{ - return state_; -} - -/** -// Get the production that this transition reduces. -// -// @return -// The reduced production or null if this transition is a shift. -*/ -const GrammarProduction* GrammarTransition::production() const -{ - return production_; -} - -bool GrammarTransition::is_shift() const -{ - return state_ != nullptr; -} - -bool GrammarTransition::is_reduce() const -{ - return production_ != nullptr; -} - -const GrammarSymbol* GrammarTransition::reduced_symbol() const -{ - return production_ ? production_->symbol() : nullptr; -} - -int GrammarTransition::reduced_length() const -{ - return production_ ? production_->length() : 0; -} - -int GrammarTransition::precedence() const -{ - return production_ ? production_->precedence() : 0; -} - -int GrammarTransition::action() const -{ - return production_ ? production_->action_index() : 0; -} - -/** -// Is this transition made on \e symbol? -// -// @param symbol -// The symbol to check this transition being made on. -// -// @return -// True if this transition is taken on \e symbol otherwise false. -*/ -bool GrammarTransition::taken_on_symbol( const GrammarSymbol* symbol ) const -{ - return symbol_ == symbol; -} - -/** -// Get the symbol that this transition is on. -// -// @return -// The symbol. -*/ -const GrammarSymbol* GrammarTransition::symbol() const -{ - return symbol_; -} - /** // Change this transition from a shift into a reduction. // diff --git a/src/lalr/GrammarTransition.hpp b/src/lalr/GrammarTransition.hpp index ddd0450..65d258c 100644 --- a/src/lalr/GrammarTransition.hpp +++ b/src/lalr/GrammarTransition.hpp @@ -2,6 +2,7 @@ #define LALR_GRAMMARTRANSITION_HPP_INCLUDED #include "TransitionType.hpp" +#include "GrammarProduction.hpp" #include #include @@ -10,7 +11,6 @@ namespace lalr class GrammarState; class GrammarSymbol; -class GrammarProduction; /** // A transition in a parser's state machine. @@ -24,16 +24,37 @@ class GrammarTransition public: GrammarTransition( const GrammarSymbol* symbol, const GrammarProduction* production ); GrammarTransition( const GrammarSymbol* symbol, GrammarState* state ); - GrammarState* state() const; - const GrammarProduction* production() const; - bool is_shift() const; - bool is_reduce() const; - const GrammarSymbol* reduced_symbol() const; - int reduced_length() const; - int precedence() const; - int action() const; - bool taken_on_symbol( const GrammarSymbol* symbol ) const; - const GrammarSymbol* symbol() const; +/** +// Get the state that this transition is to. +// +// @return +// The state or null if this transition is a reduction. +*/ + GrammarState* state() const { return state_;} +/** +// Get the production that this transition reduces. +// +// @return +// The reduced production or null if this transition is a shift. +*/ + const GrammarProduction* production() const { return production_;} + bool is_shift() const { return state_ != nullptr;} + bool is_reduce() const { return production_ != nullptr;} + const GrammarSymbol* reduced_symbol() const {return production_ ? production_->symbol() : nullptr;} + int reduced_length() const {return production_ ? production_->length() : 0;} + int precedence() const {return production_ ? production_->precedence() : 0;} + int action() const {return production_ ? production_->action_index() : 0;} +/** +// Is this transition made on \e symbol? +// +// @param symbol +// The symbol to check this transition being made on. +// +// @return +// True if this transition is taken on \e symbol otherwise false. +*/ + bool taken_on_symbol( const GrammarSymbol* symbol ) const {return symbol_ == symbol;} + const GrammarSymbol* symbol() const {return symbol_;} void override_shift_to_reduce( const GrammarProduction* production ) const; void override_reduce_to_reduce( const GrammarProduction* production ) const; diff --git a/src/lalr/RegexAction.cpp b/src/lalr/RegexAction.cpp deleted file mode 100644 index 08c9aed..0000000 --- a/src/lalr/RegexAction.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// RegexAction.cpp -// Copyright (c) Charles Baker. All rights reserved. -// - -#include "RegexAction.hpp" - -using namespace lalr; - -/** -// Constructor. -// -// @param index -// The index of this action. -// -// @param identifier -// The identifier of this action. -*/ -RegexAction::RegexAction( int index, const std::string& identifier ) -: index_( index ) -, identifier_( identifier ) -{ -} - -/** -// Get the index of this action. -// -// @return -// The index. -*/ -int RegexAction::index() const -{ - return index_; -} - -/** -// Get the identifier of this action. -// -// @return -// The identifier of this action. -*/ -const std::string& RegexAction::identifier() const -{ - return identifier_; -} diff --git a/src/lalr/RegexAction.hpp b/src/lalr/RegexAction.hpp index 30687b5..54bb45f 100644 --- a/src/lalr/RegexAction.hpp +++ b/src/lalr/RegexAction.hpp @@ -15,9 +15,13 @@ class RegexAction std::string identifier_; ///< The identifier of this action. public: - RegexAction( int index, const std::string& identifier ); - int index() const; - const std::string& identifier() const; + RegexAction( int index, const std::string& identifier ) + : index_( index ) + , identifier_( identifier ) + { + } + int index() const {return index_;} + const std::string& identifier() const {return identifier_;} static const int INVALID_INDEX = -1; }; diff --git a/src/lalr/RegexCharacter.cpp b/src/lalr/RegexCharacter.cpp deleted file mode 100644 index 75cd0b3..0000000 --- a/src/lalr/RegexCharacter.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// RegexCharacter.cpp -// Copyright (c) Charles Baker. All rights reserved. -// - -#include "RegexCharacter.hpp" -#include "assert.hpp" - -using namespace lalr; - -/** -// Constructor. -// -// @param begin_character -// The first character in the represented interval. -// -// @param end_character -// One past the last character in the represented interval. -*/ -RegexCharacter::RegexCharacter( int begin_character, int end_character ) -: begin_character_( begin_character ) -, end_character_( end_character ) -{ - LALR_ASSERT( begin_character_ < end_character_ ); -} - -/** -// Get the first character in the represented interval. -// -// @return -// The begin character. -*/ -int RegexCharacter::begin_character() const -{ - return begin_character_; -} - -/** -// Get the character one past the last character in the represented interval. -// -// @return -// The end character. -*/ -int RegexCharacter::end_character() const -{ - return end_character_; -} - -/** -// Less than operator. -// -// @param regex_character -// The character to compare with. -// -// @return -// True if the end of the interval represented by this character is less -// than the beginning of the interval represented by \e regex_character. -*/ -bool RegexCharacter::operator<( const RegexCharacter& regex_character ) const -{ - return end_character_ < regex_character.begin_character_; -} diff --git a/src/lalr/RegexCharacter.hpp b/src/lalr/RegexCharacter.hpp index e0517a6..bef89a2 100644 --- a/src/lalr/RegexCharacter.hpp +++ b/src/lalr/RegexCharacter.hpp @@ -1,6 +1,8 @@ #ifndef LALR_REGEXCHARACTER_HPP_INCLUDED #define LALR_REGEXCHARACTER_HPP_INCLUDED +#include "assert.hpp" + namespace lalr { @@ -15,10 +17,40 @@ class RegexCharacter int end_character_; ///< One past the last character in the range of characters. public: - RegexCharacter( int begin_character, int end_character ); - int begin_character() const; - int end_character() const; - bool operator<( const RegexCharacter& regex_character ) const; + RegexCharacter( int begin_character, int end_character ) + : begin_character_( begin_character ) + , end_character_( end_character ) + { + LALR_ASSERT( begin_character_ < end_character_ ); + } +/** +// Get the first character in the represented interval. +// +// @return +// The begin character. +*/ + int begin_character() const {return begin_character_;} +/** +// Get the character one past the last character in the represented interval. +// +// @return +// The end character. +*/ + int end_character() const {return end_character_;} +/** +// Less than operator. +// +// @param regex_character +// The character to compare with. +// +// @return +// True if the end of the interval represented by this character is less +// than the beginning of the interval represented by \e regex_character. +*/ + bool operator<( const RegexCharacter& regex_character ) const + { + return end_character_ < regex_character.begin_character_; + } }; } diff --git a/src/lalr/RegexGenerator.cpp b/src/lalr/RegexGenerator.cpp index 1ecdcb0..f047d63 100644 --- a/src/lalr/RegexGenerator.cpp +++ b/src/lalr/RegexGenerator.cpp @@ -47,21 +47,6 @@ RegexGenerator::~RegexGenerator() delete syntax_tree_; } -const std::vector>& RegexGenerator::actions() const -{ - return actions_; -} - -const std::set, RegexStateLess>& RegexGenerator::states() const -{ - return states_; -} - -const RegexState* RegexGenerator::start_state() const -{ - return start_state_; -} - /** // Fire an error from this generator. // diff --git a/src/lalr/RegexGenerator.hpp b/src/lalr/RegexGenerator.hpp index 2e3789f..9d981a5 100644 --- a/src/lalr/RegexGenerator.hpp +++ b/src/lalr/RegexGenerator.hpp @@ -2,7 +2,7 @@ #define LALR_LEXERGENERATOR_HPP_INCLUDED #include "RegexToken.hpp" -#include "RegexStateLess.hpp" +#include "RegexState.hpp" #include #include #include @@ -18,7 +18,6 @@ namespace lalr { class ErrorPolicy; -class RegexState; class RegexAction; class RegexSyntaxTree; @@ -39,9 +38,9 @@ class RegexGenerator public: RegexGenerator(); ~RegexGenerator(); - const std::vector>& actions() const; - const std::set, RegexStateLess>& states() const; - const RegexState* start_state() const; + const std::vector>& actions() const {return actions_;} + const std::set, RegexStateLess>& states() const {return states_;} + const RegexState* start_state() const {return start_state_;} void fire_error( int line, int column, int error, const char* format, ... ) const; void fire_printf( const char* format, ... ) const; const RegexAction* add_lexer_action( const std::string& identifier ); diff --git a/src/lalr/RegexItem.cpp b/src/lalr/RegexItem.cpp index 9c8bc24..798a4aa 100644 --- a/src/lalr/RegexItem.cpp +++ b/src/lalr/RegexItem.cpp @@ -10,36 +10,6 @@ using namespace lalr; -/** -// Constructor. -*/ -RegexItem::RegexItem() -: next_nodes_() -{ -} - -/** -// Constructor. -// -// @param next_nodes -// The nodes that appear after the dot in this item. -*/ -RegexItem::RegexItem( const std::set& next_nodes ) -: next_nodes_( next_nodes ) -{ -} - -/** -// Get the nodes that appear after the dot in this item. -// -// @return -// The next nodes. -*/ -const std::set& RegexItem::next_nodes() const -{ - return next_nodes_; -} - /** // Calculate the nodes that can be visited after [\e begin, \e end) is // transitioned on from this item. diff --git a/src/lalr/RegexItem.hpp b/src/lalr/RegexItem.hpp index 67abe2e..9bb4d23 100644 --- a/src/lalr/RegexItem.hpp +++ b/src/lalr/RegexItem.hpp @@ -1,14 +1,13 @@ #ifndef LALR_REGEXITEM_HPP_INCLUDED #define LALR_REGEXITEM_HPP_INCLUDED -#include "RegexNodeLess.hpp" +#include "RegexNode.hpp" #include #include namespace lalr { -class RegexNode; class RegexAction; /** @@ -20,9 +19,21 @@ class RegexItem std::set next_nodes_; ///< The nodes that appear after the dot in this item. public: - RegexItem(); - RegexItem( const std::set& next_nodes ); - const std::set& next_nodes() const; + RegexItem(): next_nodes_(){} +/** +// Constructor. +// +// @param next_nodes +// The nodes that appear after the dot in this item. +*/ + RegexItem( const std::set& next_nodes ): next_nodes_( next_nodes ){} +/** +// Get the nodes that appear after the dot in this item. +// +// @return +// The next nodes. +*/ + const std::set& next_nodes() const {return next_nodes_;} std::set next_nodes( int begin, int end ) const; const RegexAction* find_action_by_interval( int begin, int end ) const; bool operator<( const RegexItem& item ) const; diff --git a/src/lalr/RegexNode.cpp b/src/lalr/RegexNode.cpp index 662cd0c..940f547 100644 --- a/src/lalr/RegexNode.cpp +++ b/src/lalr/RegexNode.cpp @@ -132,22 +132,6 @@ RegexNode::RegexNode( int index, const RegexAction* action ) LALR_ASSERT( action_ ); } -/** -// Get the index of this node. -*/ -int RegexNode::get_index() const -{ - return index_; -} - -/** -// Get the type of this node. -*/ -RegexNodeType RegexNode::get_type() const -{ - return type_; -} - /** // Get the lexeme of this node. */ @@ -198,51 +182,6 @@ const char* RegexNode::get_lexeme() const return lexeme; } -/** -// Get the first character in the interval of this node. -// -// @return -// The begin character. -*/ -int RegexNode::get_begin_character() const -{ - return begin_character_; -} - -/** -// Get the character that is one past the last character in the interval of -// this node. -// -// @return -// The end character. -*/ -int RegexNode::get_end_character() const -{ - return end_character_; -} - -/** -// Get the RegexToken that is recognized at this node. -// -// @return -// The token or null if this node doesn't recognize a token. -*/ -const RegexToken* RegexNode::get_token() const -{ - return token_; -} - -/** -// Get the action at this node. -// -// @return -// The action. -*/ -const RegexAction* RegexNode::get_action() const -{ - return action_; -} - /** // Does this node match [\e begin, \e end)? // @@ -276,17 +215,6 @@ bool RegexNode::is_end() const return type_ == LEXER_NODE_SYMBOL && begin_character_ == INVALID_BEGIN_CHARACTER && end_character_ == INVALID_END_CHARACTER; } -/** -// Is this node an action node? -// -// @return -// True if this node is an action otherwise false. -*/ -bool RegexNode::is_action() const -{ - return type_ == LEXER_NODE_ACTION; -} - /** // Add \e node as a child of this node. // @@ -317,61 +245,6 @@ RegexNode* RegexNode::get_node( int n ) const return nodes_[n].get(); } -/** -// Get the nodes that are children of this node. -// -// @return -// The child nodes. -*/ -const std::vector >& RegexNode::get_nodes() const -{ - return nodes_; -} - -/** -// Is this node nullable? -// -// @return -// True if this node is nullable otherwise false. -*/ -bool RegexNode::is_nullable() const -{ - return nullable_; -} - -/** -// Get the first positions at this node. -// -// @return -// The first positions. -*/ -const std::set& RegexNode::get_first_positions() const -{ - return first_positions_; -} - -/** -// Get the last positions at this node. -// -// @return -// The last positions. -*/ -const std::set& RegexNode::get_last_positions() const -{ - return last_positions_; -} - -/** -// Get the follow positions at this node. -// -// @return -// The follow positions. -*/ -const std::set& RegexNode::get_follow_positions() const -{ - return follow_positions_; -} - /** // Get the nodes that can appear after this node. // diff --git a/src/lalr/RegexNode.hpp b/src/lalr/RegexNode.hpp index 7324b26..39161d7 100644 --- a/src/lalr/RegexNode.hpp +++ b/src/lalr/RegexNode.hpp @@ -1,15 +1,26 @@ #ifndef LALR_REGEXNODE_HPP_INCLUDED #define LALR_REGEXNODE_HPP_INCLUDED -#include "RegexNodeLess.hpp" #include "RegexNodeType.hpp" #include #include #include +#include "assert.hpp" namespace lalr { +class RegexNode; +/** +// @internal +// +// Indirectly compare two RegexNodes. +*/ +struct RegexNodeLess +{ + inline bool operator()( const RegexNode* lhs, const RegexNode* rhs ) const; +}; + /** // @internal // @@ -74,25 +85,31 @@ class RegexNode : public std::enable_shared_from_this RegexNode( int index, int begin_character, int end_character, const RegexToken* token ); RegexNode( int index, const RegexAction* action ); - int get_index() const; - RegexNodeType get_type() const; + int get_index() const {return index_;} + RegexNodeType get_type() const {return type_;} const char* get_lexeme() const; - int get_begin_character() const; - int get_end_character() const; - const RegexToken* get_token() const; - const RegexAction* get_action() const; + int get_begin_character() const {return begin_character_;} + int get_end_character() const {return end_character_;} + const RegexToken* get_token() const {return token_;} + const RegexAction* get_action() const {return action_;} bool is_match( int begin, int end ) const; bool is_end() const; - bool is_action() const; + bool is_action() const {return type_ == LEXER_NODE_ACTION;} void add_node( const std::shared_ptr& node ); RegexNode* get_node( int index ) const; - const std::vector >& get_nodes() const; +/** +// Get the nodes that are children of this node. +// +// @return +// The child nodes. +*/ + const std::vector >& get_nodes() const {return nodes_;} - bool is_nullable() const; - const std::set& get_first_positions() const; - const std::set& get_last_positions() const; - const std::set& get_follow_positions() const; + bool is_nullable() const {return nullable_;} + const std::set& get_first_positions() const {return first_positions_;} + const std::set& get_last_positions() const {return last_positions_;} + const std::set& get_follow_positions() const {return follow_positions_;} const std::set& get_next_positions() const; void calculate_nullable(); @@ -105,6 +122,26 @@ class RegexNode : public std::enable_shared_from_this void print( const std::set& dot_nodes ) const; }; +/** +// Compare two RegexNodes. +// +// @param lhs +// The first RegexNode to compare. +// +// @param rhs +// The second RegexNode to compare. +// +// @return +// True if the index of \e lhs is less than the index of \e rhs otherwise +// false. +*/ +bool RegexNodeLess::operator()( const RegexNode* lhs, const RegexNode* rhs ) const +{ + LALR_ASSERT( lhs ); + LALR_ASSERT( rhs ); + return *lhs < *rhs; +} + } #endif diff --git a/src/lalr/RegexNodeLess.cpp b/src/lalr/RegexNodeLess.cpp deleted file mode 100644 index 3cfd627..0000000 --- a/src/lalr/RegexNodeLess.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// RegexNodeLess.cpp -// Copyright (c) Charles Baker. All rights reserved. -// - -#include "RegexNodeLess.hpp" -#include "RegexNode.hpp" -#include "assert.hpp" - -using namespace lalr; - -/** -// Compare two RegexNodes. -// -// @param lhs -// The first RegexNode to compare. -// -// @param rhs -// The second RegexNode to compare. -// -// @return -// True if the index of \e lhs is less than the index of \e rhs otherwise -// false. -*/ -bool RegexNodeLess::operator()( const RegexNode* lhs, const RegexNode* rhs ) const -{ - LALR_ASSERT( lhs ); - LALR_ASSERT( rhs ); - return *lhs < *rhs; -} diff --git a/src/lalr/RegexNodeLess.hpp b/src/lalr/RegexNodeLess.hpp deleted file mode 100644 index 89d5d5c..0000000 --- a/src/lalr/RegexNodeLess.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef LALR_REGEXNODELESS_HPP_INCLUDED -#define LALR_REGEXNODELESS_HPP_INCLUDED - -namespace lalr -{ - -class RegexNode; - -/** -// @internal -// -// Indirectly compare two RegexNodes. -*/ -struct RegexNodeLess -{ - bool operator()( const RegexNode* lhs, const RegexNode* rhs ) const; -}; - -} - -#endif diff --git a/src/lalr/RegexState.cpp b/src/lalr/RegexState.cpp index 84590ed..fb4f899 100644 --- a/src/lalr/RegexState.cpp +++ b/src/lalr/RegexState.cpp @@ -27,17 +27,6 @@ RegexState::RegexState() { } -/** -// Get the items that make up this state. -// -// @return -// The items that make up this state. -*/ -const std::set& RegexState::get_items() const -{ - return items_; -} - /** // Find the transition from this state on \e character. // @@ -59,51 +48,6 @@ const RegexTransition* RegexState::find_transition_by_character( int character ) return transition != transitions_.end() ? &(*transition) : nullptr; } -/** -// Get the transitions from this state. -// -// @return -// The transitions from this state. -*/ -const std::set& RegexState::get_transitions() const -{ - return transitions_; -} - -/** -// Get the symbol that this state matches. -// -// @return -// The symbol that this state matches or null if this state doesn't match a -// symbol. -*/ -const void* RegexState::get_symbol() const -{ - return symbol_; -} - -/** -// Has this state been processed? -// -// @return -// True if this state has been processed otherwise false. -*/ -bool RegexState::is_processed() const -{ - return processed_; -} - -/** -// Get the index of this state. -// -// @return -// The index of this state. -*/ -int RegexState::index() const -{ - return index_; -} - /** // Less than operator. // @@ -160,37 +104,3 @@ void RegexState::add_transition( int begin, int end, RegexState* state ) LALR_ASSERT( inserted ); (void) inserted; } - -/** -// Set the symbol that this state matches. -// -// @param symbol -// The symbol to set this state as matching (assumed not null). -*/ -void RegexState::set_symbol( const void* symbol ) -{ - LALR_ASSERT( !symbol_ ); - symbol_ = symbol; -} - -/** -// Set whether or not this state has been processed. -// -// @param processed -// True to set this state as processed. -*/ -void RegexState::set_processed( bool processed ) -{ - processed_ = processed; -} - -/** -// Set the index of this state. -// -// @param index -// The value to set the index of this state to. -*/ -void RegexState::set_index( int index ) -{ - index_ = index; -} diff --git a/src/lalr/RegexState.hpp b/src/lalr/RegexState.hpp index 2df4f64..a5e0a10 100644 --- a/src/lalr/RegexState.hpp +++ b/src/lalr/RegexState.hpp @@ -5,6 +5,7 @@ #include "RegexTransition.hpp" #include #include +#include "assert.hpp" namespace lalr { @@ -24,18 +25,45 @@ class RegexState public: RegexState(); - const std::set& get_items() const; + const std::set& get_items() const {return items_;}; const RegexTransition* find_transition_by_character( int character ) const; - const std::set& get_transitions() const; - const void* get_symbol() const; - bool is_processed() const; - int index() const; + const std::set& get_transitions() const {return transitions_;} + const void* get_symbol() const {return symbol_;} + bool is_processed() const {return processed_;} + int index() const {return index_;} bool operator<( const RegexState& state ) const; int add_item( const std::set& next_nodes ); void add_transition( int begin, int end, RegexState* state ); - void set_symbol( const void* symbol ); - void set_processed( bool processed ); - void set_index( int index ); +/** +// Set the symbol that this state matches. +// +// @param symbol +// The symbol to set this state as matching (assumed not null). +*/ + void set_symbol( const void* symbol ) + { + LALR_ASSERT( !symbol_ ); + symbol_ = symbol; + } +/** +// Set whether or not this state has been processed. +// +// @param processed +// True to set this state as processed. +*/ + void set_processed( bool processed ) {processed_ = processed;} + void set_index( int index ) {index_ = index;} +}; + +/** +// Indirectly compare objects through two `std::unique_ptr<>` objects. +*/ +struct RegexStateLess +{ + bool operator()( const std::unique_ptr& lhs, const std::unique_ptr& rhs ) const + { + return *lhs < *rhs; + } }; } diff --git a/src/lalr/RegexStateLess.cpp b/src/lalr/RegexStateLess.cpp deleted file mode 100644 index 94fe5d9..0000000 --- a/src/lalr/RegexStateLess.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// -// RegexStateLess.cpp -// Copyright (c) Charles Baker. All rights reserved -// - -#include "RegexStateLess.hpp" -#include "RegexState.hpp" - -using namespace lalr; - -bool RegexStateLess::operator()( const std::unique_ptr& lhs, const std::unique_ptr& rhs ) const -{ - return *lhs < *rhs; -} diff --git a/src/lalr/RegexStateLess.hpp b/src/lalr/RegexStateLess.hpp deleted file mode 100644 index f77035e..0000000 --- a/src/lalr/RegexStateLess.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef LALR_REGEXSTATELESS_HPP_INCLUDED -#define LALR_REGEXSTATELESS_HPP_INCLUDED - -#include - -namespace lalr -{ - -class RegexState; - -/** -// Indirectly compare objects through two `std::unique_ptr<>` objects. -*/ -class RegexStateLess -{ -public: - bool operator()( const std::unique_ptr& lhs, const std::unique_ptr& rhs ) const; -}; - -} - -#endif diff --git a/src/lalr/RegexSyntaxTree.cpp b/src/lalr/RegexSyntaxTree.cpp index 9c2ffdd..932b78b 100644 --- a/src/lalr/RegexSyntaxTree.cpp +++ b/src/lalr/RegexSyntaxTree.cpp @@ -6,7 +6,6 @@ #include "RegexSyntaxTree.hpp" #include "RegexParser.hpp" #include "RegexNode.hpp" -#include "RegexNodeLess.hpp" #include "RegexCharacter.hpp" #include "RegexGenerator.hpp" #include "ErrorCode.hpp" diff --git a/src/lalr/RegexSyntaxTree.hpp b/src/lalr/RegexSyntaxTree.hpp index 740a345..0f2b77c 100644 --- a/src/lalr/RegexSyntaxTree.hpp +++ b/src/lalr/RegexSyntaxTree.hpp @@ -2,7 +2,7 @@ #define LALR_REGEXSYNTAXTREE_HPP_INCLUDED #include "RegexCharacter.hpp" -#include "RegexNodeLess.hpp" +#include "RegexNode.hpp" #include "RegexNodeType.hpp" #include "RegexToken.hpp" #include @@ -15,7 +15,6 @@ namespace lalr class RegexGenerator; class RegexAction; -class RegexNode; /** // @internal diff --git a/src/lalr/RegexToken.cpp b/src/lalr/RegexToken.cpp index 03a7119..db12cab 100644 --- a/src/lalr/RegexToken.cpp +++ b/src/lalr/RegexToken.cpp @@ -30,30 +30,6 @@ RegexToken::RegexToken( const RegexToken& token, const void* symbol ) { } -RegexTokenType RegexToken::type() const -{ - return type_; -} - -int RegexToken::line() const -{ - return line_; -} - -int RegexToken::column() const -{ - return column_; -} - -const void* RegexToken::symbol() const -{ - return symbol_; -} - -const std::string& RegexToken::lexeme() const -{ - return lexeme_; -} bool RegexToken::conflicted_with( const RegexToken* token ) const { diff --git a/src/lalr/RegexToken.hpp b/src/lalr/RegexToken.hpp index f3506a8..cd6bb61 100644 --- a/src/lalr/RegexToken.hpp +++ b/src/lalr/RegexToken.hpp @@ -23,11 +23,11 @@ class RegexToken public: RegexToken( RegexTokenType type, int line, int column, const void* symbol, const char* lexeme ); RegexToken( const RegexToken& token, const void* symbol ); - RegexTokenType type() const; - int line() const; - int column() const; - const void* symbol() const; - const std::string& lexeme() const; + RegexTokenType type() const {return type_;} + int line() const {return line_;} + int column() const {return column_;} + const void* symbol() const {return symbol_;} + const std::string& lexeme() const {return lexeme_;} bool conflicted_with( const RegexToken* token ) const; void add_conflicted_with( const RegexToken* token ) const; }; diff --git a/src/lalr/RegexTransition.cpp b/src/lalr/RegexTransition.cpp deleted file mode 100644 index 35ac09a..0000000 --- a/src/lalr/RegexTransition.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// RegexTransition.cpp -// Copyright (c) Charles Baker. All rights reserved. -// - -#include "RegexTransition.hpp" -#include "RegexAction.hpp" -#include "RegexState.hpp" -#include "assert.hpp" - -using namespace lalr; - -/** -// Constructor. -// -// @param begin -// The first character in the interval that this transition can be taken on. -// -// @param end -// One past the last character in the interval that this transition can be -// taken on. -// -// @param state -// The state that is transitioned to (assumed not null). -// -// @param action -// The action to take when this transition is taken or null if this -// transition doesn't take an action. -*/ -RegexTransition::RegexTransition( int begin, int end, const RegexState* state, const RegexAction* action ) -: begin_( begin ) -, end_( end ) -, state_( state ) -, action_( action ) -{ - LALR_ASSERT( begin_ < end_ ); - LALR_ASSERT( state_ ); -} - -/** -// Is this transition taken on \e character? -// -// @return -// True if this transition is taken on character otherwise false. -*/ -bool RegexTransition::on_character( int character ) const -{ - return character >= begin_ && character < end_; -} - -/** -// Get the first character in the interval that this transition can be taken -// on. -// -// @return -// The first character. -*/ -int RegexTransition::begin() const -{ - return begin_; -} - -/** -// Get the character that is one past the last character in the interval -// that this transition can be taken on. -// -// @return -// The last character. -*/ -int RegexTransition::end() const -{ - return end_; -} - -/** -// Get the action that is taken when this transition is taken. -// -// @return -// The action or null if this transition doesn't have an action. -*/ -const RegexAction* RegexTransition::action() const -{ - return action_; -} - -/** -// Get the state that this transition is to. -// -// @return -// The state. -*/ -const RegexState* RegexTransition::state() const -{ - LALR_ASSERT( state_ ); - return state_; -} - -/** -// Less than operator. -// -// @return -// True if both the beginning and end of this transition's interval is less -// than the beginning of \e transition's interval. -*/ -bool RegexTransition::operator<( const RegexTransition& transition ) const -{ - return begin_ < transition.begin_ && end_ <= transition.begin_; -} diff --git a/src/lalr/RegexTransition.hpp b/src/lalr/RegexTransition.hpp index 3e745a4..54044aa 100644 --- a/src/lalr/RegexTransition.hpp +++ b/src/lalr/RegexTransition.hpp @@ -1,6 +1,8 @@ #ifndef LALR_REGEXTRANSITION_HPP_INCLUDED #define LALR_REGEXTRANSITION_HPP_INCLUDED +#include "assert.hpp" + namespace lalr { @@ -18,13 +20,54 @@ class RegexTransition const RegexAction* action_; ///< The action that is taken on the transition or null if no action is taken. public: - RegexTransition( int begin, int end, const RegexState* state, const RegexAction* action ); - int begin() const; - int end() const; - bool on_character( int character ) const; - const RegexState* state() const; - const RegexAction* action() const; - bool operator<( const RegexTransition& transition ) const; +/** +// Constructor. +// +// @param begin +// The first character in the interval that this transition can be taken on. +// +// @param end +// One past the last character in the interval that this transition can be +// taken on. +// +// @param state +// The state that is transitioned to (assumed not null). +// +// @param action +// The action to take when this transition is taken or null if this +// transition doesn't take an action. +*/ + RegexTransition( int begin, int end, const RegexState* state, const RegexAction* action ) + : begin_( begin ) + , end_( end ) + , state_( state ) + , action_( action ) + { + LALR_ASSERT( begin_ < end_ ); + LALR_ASSERT( state_ ); + } + + int begin() const {return begin_;} + int end() const {return end_;} + bool on_character( int character ) const {return character >= begin_ && character < end_;} + const RegexState* state() const + { + LALR_ASSERT( state_ ); + return state_; + } + const RegexAction* action() const {return action_;} +/** +// Less than operator. +// +// @return +// True if both the beginning and end of this transition's interval is less +// than the beginning of \e transition's interval. +*/ + bool operator<( const RegexTransition& transition ) const + { + return begin_ < transition.begin_ && end_ <= transition.begin_; + } + }; } diff --git a/src/lalr/lalr.forge b/src/lalr/lalr.forge index 41a8921..91a15d1 100644 --- a/src/lalr/lalr.forge +++ b/src/lalr/lalr.forge @@ -13,30 +13,23 @@ for _, cc in toolsets('^cc.*') do cc:Cxx '${obj}/%1' { 'Grammar.cpp', - 'GrammarAction.cpp', 'GrammarCompiler.cpp', 'GrammarGenerator.cpp', 'GrammarParser.cpp', 'GrammarState.cpp', 'GrammarSymbol.cpp', 'GrammarSymbolSet.cpp', - 'GrammarTransition.cpp' }; cc:Cxx '${obj}/%1' { - 'RegexAction.cpp', - 'RegexCharacter.cpp', 'RegexCompiler.cpp', 'RegexGenerator.cpp', 'RegexItem.cpp', 'RegexNode.cpp', - 'RegexNodeLess.cpp', 'RegexParser.cpp', 'RegexState.cpp', - 'RegexStateLess.cpp', 'RegexSyntaxTree.cpp', 'RegexToken.cpp', - 'RegexTransition.cpp' }; }; }; From 3aa9a4a2e8544e00031a8d5d3dc0651877ce258e Mon Sep 17 00:00:00 2001 From: mingodad Date: Mon, 26 Jun 2023 11:01:04 +0200 Subject: [PATCH 23/40] Add column info to GrammarSymbol and error messages --- src/lalr/Grammar.cpp | 85 +++++++++++++++++++------------------- src/lalr/Grammar.hpp | 24 +++++------ src/lalr/GrammarParser.cpp | 54 ++++++++++++++---------- src/lalr/GrammarParser.hpp | 4 +- src/lalr/GrammarSymbol.cpp | 7 ++++ src/lalr/GrammarSymbol.hpp | 3 ++ src/lalr/GrammarSymbol.ipp | 5 +++ 7 files changed, 105 insertions(+), 77 deletions(-) diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 219cd57..7dec5aa 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -40,10 +40,10 @@ Grammar::Grammar() , error_symbol_( nullptr ) , whitespace_symbol_( nullptr ) { - start_symbol_ = add_symbol( ".start", 0, LEXEME_NULL, SYMBOL_NON_TERMINAL ); - end_symbol_ = add_symbol( ".end", 0, LEXEME_NULL, SYMBOL_END ); - error_symbol_ = add_symbol( "error", 0, LEXEME_NULL, SYMBOL_NULL ); - whitespace_symbol_ = add_symbol( ".whitespace", 0, LEXEME_NULL, SYMBOL_NULL ); + start_symbol_ = add_symbol( ".start", 0, 0, LEXEME_NULL, SYMBOL_NON_TERMINAL ); + end_symbol_ = add_symbol( ".end", 0, 0, LEXEME_NULL, SYMBOL_END ); + error_symbol_ = add_symbol( "error", 0, 0, LEXEME_NULL, SYMBOL_NULL ); + whitespace_symbol_ = add_symbol( ".whitespace", 0, 0, LEXEME_NULL, SYMBOL_NULL ); } Grammar::~Grammar() @@ -126,14 +126,14 @@ Grammar& Grammar::precedence() return *this; } -Grammar& Grammar::production( const char* identifier, int line ) +Grammar& Grammar::production( const char* identifier, int line, int column ) { LALR_ASSERT( identifier ); associativity_ = ASSOCIATE_NULL; active_whitespace_directive_ = false; active_precedence_directive_ = false; active_production_ = nullptr; - active_symbol_ = non_terminal_symbol( identifier, line ); + active_symbol_ = non_terminal_symbol(identifier, line , column); return *this; } @@ -148,44 +148,44 @@ Grammar& Grammar::end_production() return *this; } -Grammar& Grammar::end_expression( int line ) +Grammar& Grammar::end_expression(int line, int column) { LALR_ASSERT( line >= 1 ); // If there is an active symbol but no active production then an empty - // production is being specified (the nil action marks the end of a + // production is being specified (the nil action marks the end of a // production for which no symbols have been specified). if ( active_symbol_ ) { if ( !active_production_ ) { - active_production_ = add_production( active_symbol_, line ); + active_production_ = add_production( active_symbol_, line , column); } } active_production_ = nullptr; return *this; } -Grammar& Grammar::error( int line ) +Grammar& Grammar::error(int line, int column) { LALR_ASSERT( line >= 1 ); if ( associativity_ != ASSOCIATE_NULL ) { GrammarSymbol* symbol = error_symbol(); - symbol->set_associativity( associativity_ ); - symbol->set_precedence( precedence_ ); + symbol->set_associativity( associativity_ ); + symbol->set_precedence( precedence_ ); } else if ( active_symbol_ ) { if ( !active_production_ ) { - active_production_ = add_production( active_symbol_, line ); + active_production_ = add_production( active_symbol_, line , column ); } - active_production_->append_symbol( error_symbol() ); + active_production_->append_symbol( error_symbol() ); } return *this; } -Grammar& Grammar::action( const char* identifier, int line ) +Grammar& Grammar::action(const char* identifier, int line , int column) { LALR_ASSERT( identifier ); LALR_ASSERT( line >= 1 ); @@ -194,7 +194,7 @@ Grammar& Grammar::action( const char* identifier, int line ) { if ( !active_production_ ) { - active_production_ = add_production( active_symbol_, line ); + active_production_ = add_production(active_symbol_, line , column); } active_production_->set_action( add_action(identifier) ); active_production_ = nullptr; @@ -202,7 +202,7 @@ Grammar& Grammar::action( const char* identifier, int line ) return *this; } -Grammar& Grammar::literal( const char* literal, int line ) +Grammar& Grammar::literal(const char* literal, int line , int column) { LALR_ASSERT( literal ); LALR_ASSERT( line >= 0 ); @@ -213,7 +213,7 @@ Grammar& Grammar::literal( const char* literal, int line ) } else if ( associativity_ != ASSOCIATE_NULL ) { - GrammarSymbol* symbol = literal_symbol( literal, line ); + GrammarSymbol* symbol = literal_symbol(literal, line , column); symbol->set_associativity( associativity_ ); symbol->set_precedence( precedence_ ); } @@ -221,24 +221,24 @@ Grammar& Grammar::literal( const char* literal, int line ) { if ( !active_production_ ) { - active_production_ = add_production( active_symbol_, line ); - } + active_production_ = add_production( active_symbol_, line, column ); + } if ( active_precedence_directive_ ) { - GrammarSymbol* symbol = literal_symbol( literal, line ); + GrammarSymbol* symbol = literal_symbol(literal, line , column); active_production_->set_precedence_symbol( symbol ); symbol->set_referenced_in_precedence_directive( true ); active_precedence_directive_ = false; } else { - active_production_->append_symbol( literal_symbol(literal, line) ); + active_production_->append_symbol( literal_symbol(literal, line, column) ); } } return *this; } -Grammar& Grammar::regex( const char* regex, int line ) +Grammar& Grammar::regex( const char* regex, int line, int column ) { LALR_ASSERT( regex ); LALR_ASSERT( line >= 0 ); @@ -249,7 +249,7 @@ Grammar& Grammar::regex( const char* regex, int line ) } else if ( associativity_ != ASSOCIATE_NULL ) { - GrammarSymbol* symbol = regex_symbol( regex, line ); + GrammarSymbol* symbol = regex_symbol(regex, line , column); symbol->set_associativity( associativity_ ); symbol->set_precedence( precedence_ ); } @@ -257,31 +257,31 @@ Grammar& Grammar::regex( const char* regex, int line ) { if ( !active_production_ ) { - active_production_ = add_production( active_symbol_, line ); + active_production_ = add_production(active_symbol_, line , column); } if ( active_precedence_directive_ ) { - GrammarSymbol* symbol = regex_symbol( regex, line ); + GrammarSymbol* symbol = regex_symbol(regex, line , column); symbol->set_referenced_in_precedence_directive( true ); active_production_->set_precedence_symbol( symbol ); active_precedence_directive_ = false; } else { - active_production_->append_symbol( regex_symbol(regex, line) ); + active_production_->append_symbol( regex_symbol(regex, line , column) ); } } return *this; } -Grammar& Grammar::identifier( const char* identifier, int line ) +Grammar& Grammar::identifier( const char* identifier, int line, int column ) { LALR_ASSERT( identifier ); LALR_ASSERT( line >= 0 ); LALR_ASSERT( active_symbol_ || associativity_ != ASSOCIATE_NULL ); if ( associativity_ != ASSOCIATE_NULL ) { - GrammarSymbol* symbol = non_terminal_symbol( identifier, line ); + GrammarSymbol* symbol = non_terminal_symbol(identifier, line , column); symbol->set_associativity( associativity_ ); symbol->set_precedence( precedence_ ); } @@ -289,18 +289,18 @@ Grammar& Grammar::identifier( const char* identifier, int line ) { if ( !active_production_ ) { - active_production_ = add_production( active_symbol_, line ); + active_production_ = add_production(active_symbol_, line , column); } if ( active_precedence_directive_ ) { - GrammarSymbol* symbol = non_terminal_symbol( identifier, line ); + GrammarSymbol* symbol = non_terminal_symbol(identifier, line , column); symbol->set_referenced_in_precedence_directive( true ); active_production_->set_precedence_symbol( symbol ); active_precedence_directive_ = false; } else { - GrammarSymbol* symbol = non_terminal_symbol(identifier, line ); + GrammarSymbol* symbol = non_terminal_symbol(identifier, line , column); symbol->set_referenced_in_rule(true); active_production_->append_symbol( symbol ); } @@ -386,28 +386,28 @@ void Grammar::genEBNF() printf("\n\n// end EBNF\n"); } -GrammarSymbol* Grammar::literal_symbol( const char* lexeme, int line ) +GrammarSymbol* Grammar::literal_symbol( const char* lexeme, int line , int column) { LALR_ASSERT( lexeme ); LALR_ASSERT( line >= 0 ); - return add_symbol( lexeme, line, LEXEME_LITERAL, SYMBOL_TERMINAL ); + return add_symbol(lexeme, line, column, LEXEME_LITERAL, SYMBOL_TERMINAL ); } -GrammarSymbol* Grammar::regex_symbol( const char* lexeme, int line ) +GrammarSymbol* Grammar::regex_symbol(const char* lexeme, int line , int column) { LALR_ASSERT( lexeme ); LALR_ASSERT( line >= 0 ); - return add_symbol( lexeme, line, LEXEME_REGULAR_EXPRESSION, SYMBOL_TERMINAL ); + return add_symbol(lexeme, line, column, LEXEME_REGULAR_EXPRESSION, SYMBOL_TERMINAL ); } -GrammarSymbol* Grammar::non_terminal_symbol( const char* lexeme, int line ) +GrammarSymbol* Grammar::non_terminal_symbol(const char* lexeme, int line , int column) { LALR_ASSERT( lexeme ); LALR_ASSERT( line >= 0 ); - return add_symbol( lexeme, line, LEXEME_NULL, SYMBOL_NON_TERMINAL ); + return add_symbol(lexeme, line, column, LEXEME_NULL, SYMBOL_NON_TERMINAL ); } -GrammarSymbol* Grammar::add_symbol( const char* lexeme, int line, LexemeType lexeme_type, SymbolType symbol_type ) +GrammarSymbol* Grammar::add_symbol(const char* lexeme, int line, int column, LexemeType lexeme_type, SymbolType symbol_type ) { LALR_ASSERT( lexeme ); LALR_ASSERT( line >= 0 ); @@ -415,11 +415,12 @@ GrammarSymbol* Grammar::add_symbol( const char* lexeme, int line, LexemeType lex while ( i != symbols_.end() && !(*i)->matches(lexeme, symbol_type) ) { ++i; - } + } if ( i == symbols_.end() ) { unique_ptr symbol( new GrammarSymbol(lexeme) ); symbol->set_line( line ); + symbol->set_column( column ); symbol->set_lexeme_type( lexeme_type ); symbol->set_symbol_type( symbol_type ); symbols_.push_back( std::move(symbol) ); @@ -432,7 +433,7 @@ GrammarSymbol* Grammar::add_symbol( const char* lexeme, int line, LexemeType lex return symbol; } -GrammarProduction* Grammar::add_production( GrammarSymbol* symbol, int line ) +GrammarProduction* Grammar::add_production(GrammarSymbol* symbol, int line , int column) { LALR_ASSERT( symbol ); LALR_ASSERT( line > 0 ); @@ -445,7 +446,7 @@ GrammarProduction* Grammar::add_production( GrammarSymbol* symbol, int line ) productions_.push_back( std::move(production) ); } - unique_ptr production( new GrammarProduction(int(productions_.size()), symbol, line, -1, nullptr) ); + unique_ptr production( new GrammarProduction(int(productions_.size()), symbol, line, column, nullptr) ); symbol->append_production( production.get() ); productions_.push_back( std::move(production) ); return productions_.back().get(); diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index 73aeafa..21490c9 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -59,23 +59,23 @@ class Grammar Grammar& whitespace(); Grammar& case_insensitive(); Grammar& precedence(); - Grammar& production( const char* identifier, int line ); + Grammar& production( const char* identifier, int line, int column ); Grammar& end_production(); - Grammar& end_expression( int line ); - Grammar& error( int line ); - Grammar& action( const char* identifier, int line ); - Grammar& literal( const char* literal, int line ); - Grammar& regex( const char* regex, int line ); - Grammar& identifier( const char* identifier, int line ); + Grammar& end_expression( int line, int column); + Grammar& error( int line, int column ); + Grammar& action( const char* identifier, int line, int column ); + Grammar& literal( const char* literal, int line, int column ); + Grammar& regex( const char* regex, int line, int column ); + Grammar& identifier( const char* identifier, int line, int column ); bool is_case_insensitive() const {return active_case_insensitive_;} void genEBNF(); private: - GrammarSymbol* literal_symbol( const char* lexeme, int line ); - GrammarSymbol* regex_symbol( const char* lexeme, int line ); - GrammarSymbol* non_terminal_symbol( const char* lexeme, int line ); - GrammarSymbol* add_symbol( const char* lexeme, int line, LexemeType lexeme_type, SymbolType symbol_type ); - GrammarProduction* add_production( GrammarSymbol* symbol, int line ); + GrammarSymbol* literal_symbol(const char* lexeme, int line , int column); + GrammarSymbol* regex_symbol(const char* lexeme, int line , int column); + GrammarSymbol* non_terminal_symbol(const char* lexeme, int line , int column); + GrammarSymbol* add_symbol(const char* lexeme, int line, int column, LexemeType lexeme_type, SymbolType symbol_type ); + GrammarProduction* add_production(GrammarSymbol* symbol, int line , int column); GrammarAction* add_action( const char* id ); }; diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index a3e8b20..25a66e9 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -19,6 +19,7 @@ GrammarParser::GrammarParser() , grammar_( nullptr ) , position_( nullptr ) , end_( nullptr ) +, line_position_( nullptr ) , line_( 1 ) , lexeme_() , errors_( 0 ) @@ -34,17 +35,17 @@ int GrammarParser::parse( const char* start, const char* finish, ErrorPolicy* er LALR_ASSERT( grammar ); error_policy_ = error_policy; grammar_ = grammar; - position_ = start; + line_position_ = position_ = start; end_ = finish; line_ = 1; errors_ = 0; if ( !match_grammar() ) { - error( 1, LALR_ERROR_SYNTAX, "parsing grammar failed" ); + error(line_, get_line_column(position_), LALR_ERROR_SYNTAX, "parsing grammar failed" ); } - else if( grammar_->whitespace_tokens().empty() ) + if( grammar_->whitespace_tokens().empty() ) { - error(line_, PARSER_ERROR_UNDEFINED_SYMBOL, "no '%%whitespace' directive defined" ); + error(line_, get_line_column(position_), PARSER_ERROR_UNDEFINED_SYMBOL, "no '%%whitespace' directive defined" ); } return errors_; } @@ -67,12 +68,12 @@ bool GrammarParser::match_statements() while ( match_statement() ) { } - return true; + return true; } bool GrammarParser::match_statement() { - return + return match_associativity_statement() || match_whitespace_statement() || match_case_insensitive_statement() || @@ -98,7 +99,7 @@ bool GrammarParser::match_whitespace_statement() grammar_->whitespace(); if ( match_regex() ) { - grammar_->regex( lexeme_.c_str(), line_ ); + grammar_->regex( lexeme_.c_str(), line_, get_line_column(position_) ); } expect( ";" ); return true; @@ -121,7 +122,7 @@ bool GrammarParser::match_production_statement() { if ( match_identifier() ) { - grammar_->production( lexeme_.c_str(), line_ ); + grammar_->production( lexeme_.c_str(), line_, get_line_column(position_) ); expect( ":" ); match_expressions(); expect( ";" ); @@ -143,22 +144,22 @@ bool GrammarParser::match_symbol() { if ( match_error() ) { - grammar_->error( line_ ); + grammar_->error( line_, get_line_column(position_) ); return true; } else if ( match_literal() ) { - grammar_->literal( lexeme_.c_str(), line_ ); + grammar_->literal( lexeme_.c_str(), line_, get_line_column(position_) ); return true; } else if ( match_regex() ) { - grammar_->regex( lexeme_.c_str(), line_ ); + grammar_->regex( lexeme_.c_str(), line_, get_line_column(position_) ); return true; } else if ( match_identifier() ) { - grammar_->identifier( lexeme_.c_str(), line_ ); + grammar_->identifier( lexeme_.c_str(), line_, get_line_column(position_) ); return true; } return false; @@ -223,12 +224,12 @@ bool GrammarParser::match_action() { if ( match_identifier() ) { - grammar_->action( lexeme_.c_str(), line_ ); + grammar_->action( lexeme_.c_str(), line_, get_line_column(position_) ); } expect( "]" ); return true; } - grammar_->end_expression( line_ ); + grammar_->end_expression(line_, get_line_column(position_)); return false; } @@ -261,12 +262,12 @@ bool GrammarParser::match_literal() expect( "'" ); if(lexeme_.size() == 0) { - error(line_, LALR_ERROR_EMPTY_LITERAL, "empty literal" ); + error(line_, get_line_column(position), LALR_ERROR_EMPTY_LITERAL, "empty literal" ); return false; } return true; } - error( line_, LALR_ERROR_UNTERMINATED_LITERAL, "unterminated literal" ); + error(line_, get_line_column(position), LALR_ERROR_UNTERMINATED_LITERAL, "unterminated literal" ); return false; } return false; @@ -294,7 +295,7 @@ bool GrammarParser::match_regex() expect( "\"" ); if(lexeme_.size() == 0) { - error(line_, LALR_ERROR_EMPTY_LITERAL, "empty regex" ); + error(line_, get_line_column(position), LALR_ERROR_EMPTY_LITERAL, "empty regex" ); return false; } return true; @@ -338,11 +339,12 @@ bool GrammarParser::match_whitespace() if ( is_new_line(position) ) { ++line_; + line_position_ = position; } ++position; } position_ = position; - return true; + return true; } return false; } @@ -389,7 +391,7 @@ bool GrammarParser::match_block_comment() } } position_ = position; - return true; + return true; } return false; } @@ -429,11 +431,11 @@ bool GrammarParser::expect( const char* lexeme ) return true; } position_ = end_; - error( line_, LALR_ERROR_SYNTAX, "expected '%s' not found", lexeme ); + error(line_, get_line_column(position_), LALR_ERROR_SYNTAX, "expected '%s' not found", lexeme ); return false; } -void GrammarParser::error( int line, int error, const char* format, ... ) +void GrammarParser::error(int line, int column, int error, const char* format, ... ) { LALR_ASSERT( format ); ++errors_; @@ -441,7 +443,7 @@ void GrammarParser::error( int line, int error, const char* format, ... ) { va_list args; va_start( args, format ); - error_policy_->lalr_error( line, 0, error, format, args ); + error_policy_->lalr_error( line, column, error, format, args ); va_end( args ); } } @@ -458,6 +460,7 @@ const char* GrammarParser::new_line( const char* position ) ++position; } ++line_; + line_position_ = position; } else if ( *position == '\r' ) { @@ -467,6 +470,7 @@ const char* GrammarParser::new_line( const char* position ) ++position; } ++line_; + line_position_ = position; } } return position; @@ -476,3 +480,9 @@ bool GrammarParser::is_new_line( const char* position ) { return *position == '\n' || *position == '\r'; } + +int GrammarParser::get_line_column(const char* position) +{ + return position - line_position_; + +} diff --git a/src/lalr/GrammarParser.hpp b/src/lalr/GrammarParser.hpp index aca7105..cb27217 100644 --- a/src/lalr/GrammarParser.hpp +++ b/src/lalr/GrammarParser.hpp @@ -16,6 +16,7 @@ class GrammarParser Grammar* grammar_; ///< Grammar to build from parsing input. const char* position_; ///< Current input position. const char* end_; ///< One past the last character of input to parse. + const char* line_position_; ///< Current line position. int line_; ///< Current line number. std::string lexeme_; ///< Currently parsed lexeme. int errors_; ///< The number of errors that occured during parsing and generation. @@ -51,9 +52,10 @@ class GrammarParser bool match( const char* lexeme ); bool match_without_skipping_whitespace( const char* lexeme ); bool expect( const char* lexeme ); - void error( int line, int error, const char* format, ... ); + void error(int line, int column, int error, const char* format, ... ); const char* new_line( const char* position ); static bool is_new_line( const char* position ); + int get_line_column(const char* position); }; } diff --git a/src/lalr/GrammarSymbol.cpp b/src/lalr/GrammarSymbol.cpp index 98b48a2..67430a4 100644 --- a/src/lalr/GrammarSymbol.cpp +++ b/src/lalr/GrammarSymbol.cpp @@ -17,6 +17,7 @@ GrammarSymbol::GrammarSymbol( const char* lexeme ) , associativity_( ASSOCIATE_NULL ) , precedence_( 0 ) , line_( 0 ) +, column_( 0 ) , index_( -1 ) , nullable_( false ) , referenced_in_precedence_directive_( false ) @@ -113,6 +114,12 @@ void GrammarSymbol::set_line( int line ) line_ = line; } +void GrammarSymbol::set_column( int column ) +{ + LALR_ASSERT( column >= 0 ); + column_ = column; +} + void GrammarSymbol::set_index( int index ) { LALR_ASSERT( index >= 0 ); diff --git a/src/lalr/GrammarSymbol.hpp b/src/lalr/GrammarSymbol.hpp index 198f291..44788b0 100644 --- a/src/lalr/GrammarSymbol.hpp +++ b/src/lalr/GrammarSymbol.hpp @@ -23,6 +23,7 @@ class GrammarSymbol Associativity associativity_; ///< The associativity of this symbol. int precedence_; ///< The precedence of this symbol. int line_; ///< The line that this symbol is defined on. + int column_; ///< The line column that this symbol is defined on. int index_; ///< The index of this symbol among all symbols. bool nullable_; ///< True if this symbol is nullable otherwise false. bool referenced_in_precedence_directive_; ///< True if this symbol is referenced by a %precedence directive. @@ -43,6 +44,7 @@ class GrammarSymbol inline Associativity associativity() const; inline int precedence() const; inline int line() const; + inline int column() const; inline int index() const; inline bool nullable() const; inline bool referenced_in_precedence_directive() const; @@ -62,6 +64,7 @@ class GrammarSymbol void set_associativity( Associativity associativity ); void set_precedence( int precedence ); void set_line( int line ); + void set_column( int column ); void set_index( int index ); void set_nullable( bool nullable ); void set_referenced_in_precedence_directive( bool referenced_in_precedence_directive ); diff --git a/src/lalr/GrammarSymbol.ipp b/src/lalr/GrammarSymbol.ipp index 79ce014..6cdc823 100644 --- a/src/lalr/GrammarSymbol.ipp +++ b/src/lalr/GrammarSymbol.ipp @@ -52,6 +52,11 @@ int GrammarSymbol::line() const return line_; } +int GrammarSymbol::column() const +{ + return column_; +} + int GrammarSymbol::index() const { return index_; From f59b70c44b1ad6b9314047ccfdc3a5a1e8c30f49 Mon Sep 17 00:00:00 2001 From: mingodad Date: Wed, 28 Jun 2023 12:07:52 +0200 Subject: [PATCH 24/40] First implementation for outptut an parse tree. The MissingHeaders test is failing and need review. --- forge.lua | 8 +- playground/index.html | 16 +- playground/index.js | 25 ++- playground/lalr_playground.cpp | 103 +++++++++- src/lalr/AddParserActionHandler.hpp | 2 +- src/lalr/Grammar.cpp | 71 +++++-- src/lalr/Grammar.hpp | 1 + src/lalr/GrammarGenerator.cpp | 4 +- src/lalr/Parser.hpp | 4 +- src/lalr/Parser.ipp | 31 ++- src/lalr/RegexGenerator.cpp | 61 +++--- src/lalr/lalr.forge | 3 +- .../lalr_examples/lalr_calculator_example.cpp | 38 ++-- ...lalr_error_handling_calculator_example.cpp | 53 ++--- .../lalr_hello_world_example.cpp | 12 +- src/lalr/lalr_examples/lalr_json_example.cpp | 65 +++--- src/lalr/lalr_examples/lalr_xml_example.cpp | 72 ++++--- src/lalr/lalr_test/TestParsers.cpp | 185 +++++++++--------- 18 files changed, 481 insertions(+), 273 deletions(-) diff --git a/forge.lua b/forge.lua index 6fe0459..423ddda 100644 --- a/forge.lua +++ b/forge.lua @@ -50,11 +50,11 @@ local cc = forge.Toolset 'cc_${platform}' { cc:install( 'forge.cc' ); --- Bump the C++ standard to c++14 when building on Windows as that is the +-- Bump the C++ standard to c++14 when building on Windows as that is the -- lowest standard supported by Microsoft Visual C++. -if cc.platform == 'windows' then - cc.standard = 'c++14'; -end +--if cc.platform == 'windows' then + cc.standard = 'c++17'; +--end local lalr = require 'forge.lalr'; cc:install( lalr ); diff --git a/playground/index.html b/playground/index.html index 6580d67..b31906d 100644 --- a/playground/index.html +++ b/playground/index.html @@ -19,21 +19,23 @@ - + + + + + + + + + - - - - - -
    diff --git a/playground/index.js b/playground/index.js index 2dc8df3..101243a 100644 --- a/playground/index.js +++ b/playground/index.js @@ -65,6 +65,15 @@ function loadLalr_sample(self) { codeEditor.getSession().setMode("ace/mode/sql"); }); break; + case "Postgresql parser case insensitive (be patient)": + $.get(base_url + "postgresql-16-nc.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.sql", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/sql"); + }); + break; case "C++ parser (bug)": $.get(base_url + "cxx-parser.g", function( data ) { grammarEditor.setValue( data ); @@ -200,6 +209,15 @@ function loadLalr_sample(self) { codeEditor.getSession().setMode("ace/mode/ada"); }); break; + case "Ada parser case insensitive": + $.get(base_url + "ada-adayacc-nc.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.adb", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/ada"); + }); + break; } } @@ -276,6 +294,7 @@ function parse() { const optimizationMode = $('#opt-mode').val(); const generate_ebnf = $('#gen-ebnf').prop('checked'); const lexer = $('#show-lexer').prop('checked'); + const generate_ast = $('#show-ast').prop('checked'); $grammarInfo.html(''); $grammarValidation.hide(); @@ -303,7 +322,7 @@ function parse() { window.setTimeout(() => { parse_start_time = new Date().getTime(); - lalr_parse(grammarText, codeText, lexer, generate_ebnf, 0); + lalr_parse(grammarText, codeText, lexer, generate_ebnf, generate_ast); $('#overlay').css({ 'z-index': '-1', @@ -349,6 +368,10 @@ function parse() { const html = generateErrorListHTML(errors); $grammarInfo.html(html); } + + if (outputs.ast.length > 0) { + $codeAst.setValue(outputs.ast); + } }, 0); } diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp index 8baf166..65ae64c 100644 --- a/playground/lalr_playground.cpp +++ b/playground/lalr_playground.cpp @@ -59,8 +59,99 @@ struct C_MultLineCommentLexer } }; +struct ParseTreeUserData { + std::vector children; + const lalr::ParserSymbol *symbol; + std::basic_string lexeme; ///< The lexeme at this node (empty if this node's symbol is non-terminal). + ParseTreeUserData():children(0),symbol(nullptr) {}; +}; + + +static bool parsetreeMaker( ParseTreeUserData& result, const ParseTreeUserData* start, const lalr::ParserNode* nodes, size_t length ) +{ + if(length == 2 && nodes[0].symbol()->type == lalr::SymbolType::SYMBOL_NON_TERMINAL && nodes[1].symbol()->type == lalr::SymbolType::SYMBOL_NON_TERMINAL) + { + if(start[0].symbol == nodes[0].symbol()) + { + result = start[0]; + } + else + { + result.symbol = nodes[0].symbol(); + } + ParseTreeUserData& udt = result.children.emplace_back(); + udt.symbol = nodes[1].symbol(); + udt.children.push_back(start[1]); + } + else + { + for(size_t i_node = 0; i_node < length; ++i_node) + { + const lalr::ParserNode& the_node = nodes[i_node]; + switch(the_node.symbol()->type) + { + case lalr::SymbolType::SYMBOL_TERMINAL: + { + ParseTreeUserData& udt = (length == 1) ? result : result.children.emplace_back(); + udt.symbol = the_node.symbol(); + udt.symbol = the_node.symbol(); + udt.lexeme = the_node.lexeme(); + //printf("TERMINAL: %s : %s\n", udt.symbol->identifier, udt.lexeme.c_str()); + } + break; + case lalr::SymbolType::SYMBOL_NON_TERMINAL: + { + ParseTreeUserData& udt = (length == 1) ? result : result.children.emplace_back(); + udt.symbol = the_node.symbol(); + udt.children.push_back(start[i_node]); + //printf("NON_TERMINAL: %s\n", result.symbol->identifier); + } + break; + default: + //LALR_ASSERT( ?? ); + printf("Unexpected symbol %p\n", the_node.symbol()); + } + } + } + return true; +} + +static void indent( int level ) +{ + for ( int i = 0; i < level; ++i ) + { + printf( " |" ); + } +} + +static void print_parsetree( const ParseTreeUserData& ast, int level ) +{ + if(ast.symbol) + { + indent( level ); + switch(ast.symbol->type) + { + case lalr::SymbolType::SYMBOL_TERMINAL: + if(ast.lexeme.size()) + { + //indent( level -1); + printf("%s -> %s\n", ast.symbol->identifier, ast.lexeme.c_str()); + } + break; + case lalr::SymbolType::SYMBOL_NON_TERMINAL: + //indent( level ); + printf("%s\n", ast.symbol->lexeme); + break; + } + } + + for (std::vector::const_iterator child = ast.children.begin(); child != ast.children.end(); ++child) + { + print_parsetree( *child, ast.symbol ? (level + 1) : level ); + } +} -extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLexer, int generate_ebnf, int profile) +extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLexer, int generate_ebnf, int generate_parsetree) { int err = 0; // currently, zero is always returned; result codes for each part // are sent to JS via set_result() @@ -114,7 +205,9 @@ extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLe if(input) { lalr::ErrorPolicy error_policy_input; - lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); + //lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); + lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); + parser.set_default_action_handler(parsetreeMaker); parser.lexer_action_handlers() ( "C_MultilineComment", &C_MultLineCommentLexer::string_lexer ) ; @@ -125,6 +218,12 @@ extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLe else parser.parse( input, input + strlen((const char*)input) ); parse_result = parser.accepted() == 1 && parser.full() == 1; + if(generate_parsetree) + { + switch_output("ast"); + print_parsetree( parser.user_data(), 0 ); + switch_output("parse_status"); + } if (parse_result) { if (parse_verbose) { fprintf(stderr, "Parse successful.\n"); diff --git a/src/lalr/AddParserActionHandler.hpp b/src/lalr/AddParserActionHandler.hpp index 3c35181..669c489 100644 --- a/src/lalr/AddParserActionHandler.hpp +++ b/src/lalr/AddParserActionHandler.hpp @@ -16,7 +16,7 @@ template class AddParserActionHandler { - typedef std::function* nodes, size_t length)> ParserActionFunction; + typedef std::function* nodes, size_t length)> ParserActionFunction; Parser* parser_; ///< The Parser to add handlers to. public: diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 7dec5aa..46322b1 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -209,7 +209,7 @@ Grammar& Grammar::literal(const char* literal, int line , int column) LALR_ASSERT( active_whitespace_directive_ || associativity_ != ASSOCIATE_NULL || active_symbol_ ); if ( active_whitespace_directive_ ) { - whitespace_tokens_.push_back( RegexToken(TOKEN_LITERAL, 0, 0, whitespace_symbol_, literal) ); + whitespace_tokens_.emplace_back( TOKEN_LITERAL, 0, 0, whitespace_symbol_, literal ); } else if ( associativity_ != ASSOCIATE_NULL ) { @@ -245,7 +245,7 @@ Grammar& Grammar::regex( const char* regex, int line, int column ) LALR_ASSERT( active_whitespace_directive_ || associativity_ != ASSOCIATE_NULL || active_symbol_ ); if ( active_whitespace_directive_ ) { - whitespace_tokens_.push_back( RegexToken(TOKEN_REGULAR_EXPRESSION, 0, 0, whitespace_symbol_, regex) ); + whitespace_tokens_.emplace_back( TOKEN_REGULAR_EXPRESSION, 0, 0, whitespace_symbol_, regex ); } else if ( associativity_ != ASSOCIATE_NULL ) { @@ -386,6 +386,55 @@ void Grammar::genEBNF() printf("\n\n// end EBNF\n"); } +void Grammar::genNakedGrammar() +{ + printf( "%s {\n", identifier_.c_str()); + GrammarSymbol* last_production_symbol = NULL; + bool production_continuation = false; + for ( vector>::const_iterator i = productions().begin(); i != productions().end(); ++i ) + { + GrammarProduction* production = i->get(); + LALR_ASSERT( production ); + GrammarSymbol *curr_symbol = production->symbol(); + bool same_production = last_production_symbol && last_production_symbol == curr_symbol; + if(same_production) { + production_continuation = true; + //printf(" //%s ::= %d", production->symbol()->lexeme().c_str(), production->length()); + } + else { + production_continuation = false; + const char *sym_prefix = ""; + const char *sym_name = curr_symbol->lexeme().c_str(); + if(sym_name[0] == '.') + { + ++sym_name; + sym_prefix = "ebnf_x_"; + } + //printf("\n\n%s%s ::= // %d\n\t", sym_prefix, sym_name, production->length()); + printf("\n\t;\n\n%s%s :\n\t", sym_prefix, sym_name); + } + if(production->length() > 0) { + for(int elm=0; elm < production->length(); ++elm) { + const GrammarSymbol *sym = production->symbol_by_position(elm); + if(production_continuation) { + production_continuation = false; + printf("\n\t| "); + } + else printf(" "); + ouptputTerminal(sym); + } + } + else { + printf("/*empty*/"); + } + if(production->precedence_symbol()) { + printf(" %%prec %s", production->precedence_symbol()->lexeme().c_str()); + } + last_production_symbol = curr_symbol; + } + printf("\n\t;\n\n}\n"); +} + GrammarSymbol* Grammar::literal_symbol( const char* lexeme, int line , int column) { LALR_ASSERT( lexeme ); @@ -418,13 +467,12 @@ GrammarSymbol* Grammar::add_symbol(const char* lexeme, int line, int column, Lex } if ( i == symbols_.end() ) { - unique_ptr symbol( new GrammarSymbol(lexeme) ); + unique_ptr &symbol = symbols_.emplace_back( new GrammarSymbol(lexeme) ); symbol->set_line( line ); symbol->set_column( column ); symbol->set_lexeme_type( lexeme_type ); symbol->set_symbol_type( symbol_type ); - symbols_.push_back( std::move(symbol) ); - return symbols_.back().get(); + return symbol.get(); } GrammarSymbol* symbol = i->get(); @@ -440,16 +488,14 @@ GrammarProduction* Grammar::add_production(GrammarSymbol* symbol, int line , int if ( productions_.empty() ) { LALR_ASSERT( start_symbol_ ); - unique_ptr production( new GrammarProduction(int(productions_.size()), start_symbol_, 0, 0, NULL) ); + unique_ptr &production = productions_.emplace_back( new GrammarProduction(int(productions_.size()), start_symbol_, 0, 0, NULL) ); production->append_symbol( symbol ); start_symbol_->append_production( production.get() ); - productions_.push_back( std::move(production) ); } - unique_ptr production( new GrammarProduction(int(productions_.size()), symbol, line, column, nullptr) ); + unique_ptr &production = productions_.emplace_back( new GrammarProduction(int(productions_.size()), symbol, line, column, nullptr) ); symbol->append_production( production.get() ); - productions_.push_back( std::move(production) ); - return productions_.back().get(); + return production.get(); } GrammarAction* Grammar::add_action( const char* identifier ) @@ -463,9 +509,8 @@ GrammarAction* Grammar::add_action( const char* identifier ) if ( i == actions_.end() ) { int index = int(actions_.size()); - unique_ptr action( new GrammarAction(index, identifier) ); - actions_.push_back( std::move(action) ); - return actions_.back().get(); + unique_ptr &action = actions_.emplace_back( new GrammarAction(index, identifier) ); + return action.get(); } return i->get(); } diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index 21490c9..4d1b096 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -69,6 +69,7 @@ class Grammar Grammar& identifier( const char* identifier, int line, int column ); bool is_case_insensitive() const {return active_case_insensitive_;} void genEBNF(); + void genNakedGrammar(); private: GrammarSymbol* literal_symbol(const char* lexeme, int line , int column); diff --git a/src/lalr/GrammarGenerator.cpp b/src/lalr/GrammarGenerator.cpp index 11173ec..b29b7c8 100644 --- a/src/lalr/GrammarGenerator.cpp +++ b/src/lalr/GrammarGenerator.cpp @@ -245,13 +245,13 @@ void GrammarGenerator::error( int line, int error, const char* format, ... ) GrammarTransition* GrammarGenerator::shift_transition( const GrammarSymbol* symbol, GrammarState* state ) { - transitions_.push_back( make_unique(symbol, state) ); + transitions_.emplace_back( make_unique(symbol, state) ); return transitions_.back().get(); } GrammarTransition* GrammarGenerator::reduce_transition( const GrammarSymbol* symbol, const GrammarProduction* production ) { - transitions_.push_back( make_unique(symbol, production) ); + transitions_.emplace_back( make_unique(symbol, production) ); return transitions_.back().get(); } diff --git a/src/lalr/Parser.hpp b/src/lalr/Parser.hpp index 85e7674..083f969 100644 --- a/src/lalr/Parser.hpp +++ b/src/lalr/Parser.hpp @@ -36,7 +36,7 @@ class Parser typedef lalr::ParserNode ParserNode; typedef typename std::vector::const_iterator ParserNodeConstIterator; typedef std::function (const PositionIterator& begin, const PositionIterator& end, std::basic_string* lexeme, const void** symbol)> LexerActionFunction; - typedef std::function ParserActionFunction; + typedef std::function ParserActionFunction; private: struct ParserActionHandler @@ -86,7 +86,7 @@ class Parser typename std::vector::iterator find_node_to_reduce_to( const ParserTransition* transition, std::vector& nodes ); void debug_shift( const ParserNode& node ) const; void debug_reduce( const ParserSymbol* reduced_symbol, std::ptrdiff_t start, std::ptrdiff_t finish ) const; - UserData handle( const ParserTransition* transition, std::ptrdiff_t start, std::ptrdiff_t finish ) const; + bool handle(UserData& result, const ParserTransition* transition, std::ptrdiff_t start, std::ptrdiff_t finish ) const; std::string expected_symbols( const ParserState* state ) const; void shift( const ParserTransition* transition, const std::basic_string& lexeme, int line, int column ); void reduce( const ParserTransition* transition, bool* accepted, bool* rejected ); diff --git a/src/lalr/Parser.ipp b/src/lalr/Parser.ipp index aadfbfd..d3798ca 100644 --- a/src/lalr/Parser.ipp +++ b/src/lalr/Parser.ipp @@ -78,14 +78,14 @@ Parser::Parser( const ParserStateMa const ParserAction* actions_end = action + state_machine_->actions_size; while ( action != actions_end ) { - action_handlers_.push_back( ParserActionHandler(action, nullptr) ); + action_handlers_.emplace_back( action, nullptr ); ++action; } nodes_.reserve( 64 ); user_data_.reserve( 64 ); - nodes_.push_back( ParserNode(state_machine_->start_state, nullptr, 0, 1) ); - user_data_.push_back( UserData() ); + nodes_.emplace_back( state_machine_->start_state, nullptr, 0, 1 ); + user_data_.emplace_back( ); } /** @@ -355,8 +355,8 @@ void Parser::reset() full_ = false; nodes_.clear(); user_data_.clear(); - nodes_.push_back( ParserNode(state_machine_->start_state, nullptr, 0, 1) ); - user_data_.push_back( UserData() ); + nodes_.emplace_back( state_machine_->start_state, nullptr, 0, 1 ); + user_data_.emplace_back( ); } /** @@ -594,7 +594,7 @@ void Parser::debug_reduce( const Pa // The user data that results from the reduction. */ template -UserData Parser::handle( const ParserTransition* transition, std::ptrdiff_t start, std::ptrdiff_t finish ) const +bool Parser::handle(UserData& result, const ParserTransition* transition, std::ptrdiff_t start, std::ptrdiff_t finish ) const { LALR_ASSERT( start >= 0 && size_t(start) <= nodes_.size() ); LALR_ASSERT( start >= 0 && size_t(start) <= user_data_.size() ); @@ -613,16 +613,16 @@ UserData Parser::handle( const Pars LALR_ASSERT( action >= 0 && action < static_cast(action_handlers_.size()) ); if ( action_handlers_[action].function_ ) { - return action_handlers_[action].function_( user_data, nodes, length ); + return action_handlers_[action].function_( result, user_data, nodes, length ); } } if ( default_action_handler_ ) { - return default_action_handler_( user_data, nodes, length ); + return default_action_handler_( result, user_data, nodes, length ); } - return UserData(); + return false; } /** @@ -678,10 +678,9 @@ void Parser::shift( const ParserTra LALR_ASSERT( transition ); LALR_ASSERT( line >= 0 ); LALR_ASSERT( column >= 1 ); - ParserNode node( transition->state, transition->symbol, lexeme, line, column ); + ParserNode &node = nodes_.emplace_back( transition->state, transition->symbol, lexeme, line, column ); debug_shift( node ); - nodes_.push_back( node ); - user_data_.push_back( UserData() ); + user_data_.emplace_back( ); } /** @@ -713,14 +712,14 @@ void Parser::reduce( const ParserTr debug_reduce( transition->reduced_symbol, start, finish ); int line = i != nodes_.end() ? nodes_[start].line() : 0; int column = i != nodes_.end() ? nodes_[start].column() : 1; - UserData user_data = handle( transition, start, finish ); + UserData user_data; + handle(user_data, transition, start, finish ); nodes_.erase( nodes_.begin() + start, nodes_.end() ); user_data_.erase( user_data_.begin() + start, user_data_.end() ); const ParserTransition* transition = find_transition( symbol, nodes_.back().state() ); LALR_ASSERT( transition ); - ParserNode node( transition->state, symbol, line, column ); - nodes_.push_back( node ); - user_data_.push_back( user_data ); + nodes_.emplace_back( transition->state, symbol, line, column ); + user_data_.emplace_back( user_data ); } else { diff --git a/src/lalr/RegexGenerator.cpp b/src/lalr/RegexGenerator.cpp index f047d63..b2b1fdd 100644 --- a/src/lalr/RegexGenerator.cpp +++ b/src/lalr/RegexGenerator.cpp @@ -58,9 +58,9 @@ RegexGenerator::~RegexGenerator() // // @param error // The error code that indicates the error that occured. -// +// // @param format -// A printf-style format string describing the error that occured (assumed +// A printf-style format string describing the error that occured (assumed // not null). // // @param ... @@ -103,23 +103,23 @@ void RegexGenerator::fire_printf( const char* format, ... ) const /** // Add a new or retrieve an existing RegexAction. // -// If the parser already has a RegexAction whose identifier -// matches \e identifier then that RegexAction is returned. Otherwise -// a new RegexAction is created, added to this `Generator` so that it +// If the parser already has a RegexAction whose identifier +// matches \e identifier then that RegexAction is returned. Otherwise +// a new RegexAction is created, added to this `Generator` so that it // can be returned later if necessary, and returned from this call. // // @param identifier // The identifier of the RegexAction to add or retrieve. // // @return -// The RegexAction whose identifier matches \e identifier or null if +// The RegexAction whose identifier matches \e identifier or null if // \e identifier is empty. */ const RegexAction* RegexGenerator::add_lexer_action( const std::string& identifier ) { LALR_ASSERT( !identifier.empty() ); if ( !identifier.empty() ) - { + { vector >::const_iterator i = actions_.begin(); while ( i != actions_.end() && (*i)->identifier() != identifier ) { @@ -127,8 +127,7 @@ const RegexAction* RegexGenerator::add_lexer_action( const std::string& identifi } if ( i == actions_.end() ) { - unique_ptr action( new RegexAction(int(actions_.size()), identifier) ); - actions_.push_back( std::move(action) ); + actions_.emplace_back( new RegexAction(int(actions_.size()), identifier) ); i = actions_.end() - 1; } return i->get(); @@ -158,7 +157,7 @@ int RegexGenerator::generate( const std::vector& tokens, ErrorPolicy states_.clear(); start_state_ = nullptr; ranges_.clear(); - + syntax_tree_->reset( tokens, this ); generate_states( *syntax_tree_ ); error_policy_ = nullptr; @@ -204,7 +203,7 @@ std::unique_ptr RegexGenerator::goto_( const RegexState* state, int // Generate the states for a LexerStateMachine from \e syntax_tree. // // @param syntax_tree -// The RegexSyntaxTree to get the RegexNodes from that are then used to generate +// The RegexSyntaxTree to get the RegexNodes from that are then used to generate // states. // // @param states @@ -236,7 +235,7 @@ void RegexGenerator::generate_states( const RegexSyntaxTree& syntax_tree ) { for ( RegexState* state : states ) { - // Create the distinct ranges of characters that can be + // Create the distinct ranges of characters that can be // transitioned on from the current state. clear(); const std::set& items = state->get_items(); @@ -253,16 +252,16 @@ void RegexGenerator::generate_states( const RegexSyntaxTree& syntax_tree ) } } } - - // Create a goto state and a transition from the current + + // Create a goto state and a transition from the current // state for each distinct range. vector>::const_iterator j = ranges_.begin(); while ( j != ranges_.end() ) - { + { int begin = (j + 0)->first; int end = (j + 1)->first; LALR_ASSERT( begin < end ); - + std::unique_ptr goto_state = goto_( state, begin, end ); if ( !goto_state->get_items().empty() ) { @@ -278,7 +277,7 @@ void RegexGenerator::generate_states( const RegexSyntaxTree& syntax_tree ) { state->add_transition( begin, end, existing_goto_state->get() ); } - } + } ++j; if ( !j->second ) @@ -302,7 +301,7 @@ void RegexGenerator::generate_states( const RegexSyntaxTree& syntax_tree ) */ void RegexGenerator::generate_indices_for_states() { - int index = 0; + int index = 0; for ( auto i = states_.begin(); i != states_.end(); ++i ) { RegexState* state = i->get(); @@ -356,15 +355,15 @@ void RegexGenerator::generate_symbol_for_state( RegexState* state ) const LALR_ASSERT( token ); if ( !token->conflicted_with(node->get_token()) ) { - fire_error( token->line(), token->column(), LEXER_ERROR_SYMBOL_CONFLICT, "'%s' and '%s' conflict but are both defined on line %d", token->lexeme().c_str(), node->get_token()->lexeme().c_str(), token->line() ); + fire_error( token->line(), token->column(), LEXER_ERROR_SYMBOL_CONFLICT, "'%s' and '%s' conflict but are both defined on line %d", token->lexeme().c_str(), node->get_token()->lexeme().c_str(), token->line() ); token->add_conflicted_with( node->get_token() ); } } } - + ++i; } - } + } state->set_symbol( token ? token->symbol() : NULL ); } @@ -378,17 +377,17 @@ void RegexGenerator::clear() } /** -// Insert the range [\e begin, \e end) into the current distinct ranges for +// Insert the range [\e begin, \e end) into the current distinct ranges for // this RegexGenerator. // // The ranges are stored as a vector of pair. The first element of // the pair represents the character and the second element represents whether // or not that character is considered in or out. // -// This is done so that transitions can be efficiently calculated for -// independent ranges of characters. For example if a state has three next -// nodes that represent characters in the the ranges [0, 256), [0, 32), and -// [0, 64) then three goto states should be generated with transitions on +// This is done so that transitions can be efficiently calculated for +// independent ranges of characters. For example if a state has three next +// nodes that represent characters in the the ranges [0, 256), [0, 32), and +// [0, 64) then three goto states should be generated with transitions on // [0, 32), [32, 64), and [64, 256) respectively. // // @param begin @@ -399,28 +398,28 @@ void RegexGenerator::clear() */ void RegexGenerator::insert( int begin, int end ) { - bool in = false; + bool in = false; vector >::iterator i = ranges_.begin(); while ( i != ranges_.end() && i->first < begin ) { in = i->second; ++i; - } + } if ( i == ranges_.end() || i->first != begin ) { i = ranges_.insert( i, make_pair(begin, true) ); ++i; } - + while ( i != ranges_.end() && i->first < end ) { in = i->second; i->second = true; ++i; - } - + } + if ( i == ranges_.end() || i->first != end ) { ranges_.insert( i, make_pair(end, in) ); diff --git a/src/lalr/lalr.forge b/src/lalr/lalr.forge index 91a15d1..2679816 100644 --- a/src/lalr/lalr.forge +++ b/src/lalr/lalr.forge @@ -3,7 +3,7 @@ buildfile 'lalrc/lalrc.forge'; buildfile 'lalr_examples/lalr_examples.forge'; buildfile 'lalr_test/lalr_test.forge'; -for _, cc in toolsets('^cc.*') do +for _, cc in toolsets('^cc.*') do cc:all { cc:StaticLibrary '${lib}/lalr_${platform}_${architecture}' { cc:Cxx '${obj}/%1' { @@ -19,6 +19,7 @@ for _, cc in toolsets('^cc.*') do 'GrammarState.cpp', 'GrammarSymbol.cpp', 'GrammarSymbolSet.cpp', + 'GrammarTransition.cpp' }; cc:Cxx '${obj}/%1' { diff --git a/src/lalr/lalr_examples/lalr_calculator_example.cpp b/src/lalr/lalr_examples/lalr_calculator_example.cpp index 05b72d1..d2de376 100644 --- a/src/lalr/lalr_examples/lalr_calculator_example.cpp +++ b/src/lalr/lalr_examples/lalr_calculator_example.cpp @@ -32,35 +32,41 @@ void lalr_calculator_example() compiler.compile( calculator_grammar, calculator_grammar + strlen(calculator_grammar) ); Parser parser( compiler.parser_state_machine() ); parser.parser_action_handlers() - ( "add", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "add", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[0] + data[2]; - } + result = data[0] + data[2]; + return true; + } ) - ( "subtract", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "subtract", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[0] - data[2]; + result = data[0] - data[2]; + return true; } ) - ( "multiply", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "multiply", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[0] * data[2]; - } + result = data[0] * data[2]; + return true; + } ) - ( "divide", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "divide", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[0] / data[2]; - } + result = data[0] / data[2]; + return true; + } ) - ( "compound", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "compound", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[1]; + result = data[1]; + return true; } ) - ( "integer", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "integer", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) { - return ::atoi( nodes[0].lexeme().c_str() ); - } + result = ::atoi( nodes[0].lexeme().c_str() ); + return true; + } ) ; diff --git a/src/lalr/lalr_examples/lalr_error_handling_calculator_example.cpp b/src/lalr/lalr_examples/lalr_error_handling_calculator_example.cpp index 14f6fb2..63de6ad 100644 --- a/src/lalr/lalr_examples/lalr_error_handling_calculator_example.cpp +++ b/src/lalr/lalr_examples/lalr_error_handling_calculator_example.cpp @@ -14,58 +14,67 @@ void lalr_error_handling_calculator_example() extern const lalr::ParserStateMachine* error_handling_calculator_parser_state_machine; Parser parser( error_handling_calculator_parser_state_machine ); parser.parser_action_handlers() - ( "add", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "add", [] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[0] + data[2]; - } + result = data[0] + data[2]; + return true; + } ) - ( "subtract", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "subtract", [] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[0] - data[2]; + result = data[0] - data[2]; + return true; } ) - ( "multiply", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "multiply", [] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[0] * data[2]; - } + result = data[0] * data[2]; + return true; + } ) - ( "divide", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "divide", [] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[0] / data[2]; - } + result = data[0] / data[2]; + return true; + } ) - ( "compound", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "compound", [] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { - return data[1]; + result = data[1]; + return true; } ) - ( "integer", [] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "integer", [] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { - return ::atoi( nodes[0].lexeme().c_str() ); - } + result = ::atoi( nodes[0].lexeme().c_str() ); + return true; + } ) - ( "result", [&error] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "result", [&error] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { if ( !error ) { printf( "%d\n", data[0] ); } error = false; - return data[0]; + result = data[0]; + return true; } ) - ( "unexpected_error", [&error] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "unexpected_error", [&error] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { error = true; printf( "Unexpected error!\n" ); - return 0; + result = 0; + return true; } ) - ( "unknown_operator_error", [&error] ( const int* data, const ParserNode<>* nodes, size_t length ) + ( "unknown_operator_error", [&error] ( int& result, const int* data, const ParserNode<>* nodes, size_t length ) { error = true; printf( "Unknown operator error!\n" ); - return 0; + result = 0; + return true; } ) ; diff --git a/src/lalr/lalr_examples/lalr_hello_world_example.cpp b/src/lalr/lalr_examples/lalr_hello_world_example.cpp index 78076ef..657c22e 100644 --- a/src/lalr/lalr_examples/lalr_hello_world_example.cpp +++ b/src/lalr/lalr_examples/lalr_hello_world_example.cpp @@ -9,7 +9,7 @@ using namespace lalr; void lalr_hello_world_example() { - const char* hello_world_grammar = + const char* hello_world_grammar = "hello_world {\n" " %whitespace \"[ \\t\\r\\n]\" ;\n" " hello_world: 'Hello World!' [hello_world];\n" @@ -20,14 +20,16 @@ void lalr_hello_world_example() compiler.compile( hello_world_grammar, hello_world_grammar + strlen(hello_world_grammar) ); Parser parser( compiler.parser_state_machine() ); parser.parser_action_handlers() - ( "hello_world", [] (const shared_ptr>* data, const ParserNode<>* nodes, size_t length) + ( "hello_world", [] (shared_ptr>& result, + const shared_ptr>* data, + const ParserNode<>* nodes, size_t length) { printf( "Hello World!\n" ); - return shared_ptr>(); - } + return true; + } ); ; - + const char* input = "Hello World!"; parser.parse( input, input + strlen(input) ); LALR_ASSERT( parser.accepted() ); diff --git a/src/lalr/lalr_examples/lalr_json_example.cpp b/src/lalr/lalr_examples/lalr_json_example.cpp index cfb611c..366e7d2 100644 --- a/src/lalr/lalr_examples/lalr_json_example.cpp +++ b/src/lalr/lalr_examples/lalr_json_example.cpp @@ -18,7 +18,7 @@ using namespace std; using namespace lalr; -namespace +namespace { typedef std::basic_string String; @@ -56,19 +56,19 @@ struct Attribute , value_() { } - + Attribute( const String& name, const shared_ptr& value ) : name_( name ) , value_( value ) { - } + } }; struct JsonUserData { String name_; shared_ptr value_; - + JsonUserData() : name_() , value_() @@ -79,73 +79,82 @@ struct JsonUserData : name_() , value_( value ) { - } + } JsonUserData( const String& name, shared_ptr value ) : name_( name ) , value_( value ) { - } + } }; -static JsonUserData document( const JsonUserData* start, const ParserNode* nodes, size_t length ) +static bool document( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) { - return start[1]; + result = start[1]; + return true; } -static JsonUserData attribute( const JsonUserData* start, const ParserNode* nodes, size_t length ) -{ - const shared_ptr& attribute = start[2].value_; - return JsonUserData( nodes[0].lexeme(), attribute ); +static bool attribute( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) +{ + result.value_ = start[2].value_; + result.name_ = nodes[0].lexeme(); + return true; } -static JsonUserData null( const JsonUserData* start, const ParserNode* nodes, size_t length ) +static bool null( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr null_value = make_shared(); - return JsonUserData( null_value ); + result.value_ = null_value; + return true; } -static JsonUserData value( const JsonUserData* start, const ParserNode* nodes, size_t length ) +static bool value( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr value = make_shared( nodes[0].lexeme() ); - return JsonUserData( value ); + result.value_ = value; + return true; } -static JsonUserData object( const JsonUserData* start, const ParserNode* nodes, size_t length ) +static bool object( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) { - return start[1]; + result = start[1]; + return true; } -static JsonUserData add_to_object( const JsonUserData* start, const ParserNode* nodes, size_t length ) +static bool add_to_object( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) { const shared_ptr& object = start[0].value_; shared_ptr attribute = make_shared( start[2].name_, start[2].value_ ); object->attributes_.push_back( attribute ); - return JsonUserData( object ); + result.value_ = object; + return true; } -static JsonUserData create_object( const JsonUserData* start, const ParserNode* nodes, size_t length ) +static bool create_object( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr object = make_shared(); shared_ptr attribute = make_shared( start[0].name_, start[0].value_ ); object->attributes_.push_back( attribute ); - return JsonUserData( object ); + result.value_ = object; + return true; } -static JsonUserData add_to_array( const JsonUserData* start, const ParserNode* nodes, size_t length ) +static bool add_to_array( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) { const shared_ptr& array = start[0].value_; const shared_ptr& element = start[2].value_; array->elements_.push_back( element ); - return JsonUserData( array ); + result.value_ = array; + return true; } -static JsonUserData create_array( const JsonUserData* start, const ParserNode* nodes, size_t length ) +static bool create_array( JsonUserData& result, const JsonUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr array = make_shared(); const shared_ptr& element = start[0].value_; array->elements_.push_back( element ); - return JsonUserData( array ); + result.value_ = array; + return true; } static void indent( int level ) @@ -153,7 +162,7 @@ static void indent( int level ) for ( int i = 0; i < level; ++i ) { printf( " " ); - } + } } static void print( const Value& value, int level ) @@ -169,7 +178,7 @@ static void print( const Value& value, int level ) if ( value.attributes_.empty() && value.elements_.empty() ) { indent( level + 1 ); - printf( "%s='%s'\n", + printf( "%s='%s'\n", utf8.to_bytes(attribute->name_).c_str(), utf8.to_bytes(attribute->value_->value_).c_str() ); diff --git a/src/lalr/lalr_examples/lalr_xml_example.cpp b/src/lalr/lalr_examples/lalr_xml_example.cpp index 6512426..30c2b6a 100644 --- a/src/lalr/lalr_examples/lalr_xml_example.cpp +++ b/src/lalr/lalr_examples/lalr_xml_example.cpp @@ -18,12 +18,12 @@ struct Attribute { String name_; String value_; - + Attribute( const String& name, const String& value ) : name_( name ) , value_( value ) { - } + } }; struct Element @@ -31,7 +31,7 @@ struct Element String name_; std::list > attributes_; std::list > elements_; - + Element() : name_(), attributes_(), @@ -44,58 +44,66 @@ struct XmlUserData { shared_ptr attribute_; shared_ptr element_; - + XmlUserData() : attribute_(), element_() { } - + XmlUserData( shared_ptr attribute ) : attribute_( attribute ), element_() { - } - + } + XmlUserData( shared_ptr element ) : attribute_(), element_( element ) { - } + } }; -static XmlUserData document( const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool document( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) { const XmlUserData* end = start + length; while ( start != end && !start[0].element_ ) { ++start; - } - return start != end ? start[0] : XmlUserData(); + } + if(start != end) + { + result = start[0]; + return true; + } + return false; } -static XmlUserData add_element( const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool add_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr element = start[0].element_; element->elements_.push_back( start[1].element_ ); - return XmlUserData( element ); + result.element_ = element; + return true; } -static XmlUserData create_element( const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool create_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr element( new Element() ); element->elements_.push_back( start[0].element_ ); - return XmlUserData( element ); + result.element_ = element; + return true; } -static XmlUserData short_element( const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool short_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr element = start[2].element_; element->name_ = nodes[1].lexeme(); - return XmlUserData( element ); + result.element_ = element; + return true; } -static XmlUserData long_element( const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool long_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr element = start[2].element_; if ( !element ) @@ -108,30 +116,34 @@ static XmlUserData long_element( const XmlUserData* start, const ParserNodeelements_, start[4].element_->elements_ ); } - return XmlUserData( element ); + result.element_ = element; + return true; } -static XmlUserData add_attribute( const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool add_attribute( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) { LALR_ASSERT( start[0].element_ ); shared_ptr element = start[0].element_; LALR_ASSERT( start[1].attribute_ ); element->attributes_.push_back( start[1].attribute_ ); - return XmlUserData( element ); + result.element_ = element; + return true; } -static XmlUserData create_attribute( const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool create_attribute( XmlUserData &result, const XmlUserData* start, const ParserNode* nodes, size_t length ) { LALR_ASSERT( start[0].attribute_ ); shared_ptr element( new Element() ); element->attributes_.push_back( start[0].attribute_ ); - return XmlUserData( element ); + result.element_ = element; + return true; } -static XmlUserData attribute( const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool attribute( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) { shared_ptr attribute( new Attribute(nodes[0].lexeme(), nodes[2].lexeme()) ); - return XmlUserData( attribute ); + result.attribute_ = attribute; + return true; } static void indent( int level ) @@ -139,7 +151,7 @@ static void indent( int level ) for ( int i = 0; i < level; ++i ) { printf( " " ); - } + } } static void print( const Element* element, int level ) @@ -147,7 +159,7 @@ static void print( const Element* element, int level ) LALR_ASSERT( element ); indent( level ); printf( "%s\n", element->name_.c_str() ); - + for ( list >::const_iterator i = element->attributes_.begin(); i != element->attributes_.end(); ++i ) { const Attribute* attribute = i->get(); @@ -155,7 +167,7 @@ static void print( const Element* element, int level ) indent( level + 1 ); printf( "%s='%s'\n", attribute->name_.c_str(), attribute->value_.c_str() ); } - + for ( list >::const_iterator i = element->elements_.begin(); i != element->elements_.end(); ++i ) { const Element* element = i->get(); @@ -184,7 +196,7 @@ void lalr_xml_example() ( "attribute", &attribute ) ; - const char* input = + const char* input = "\n" " \n" " \n" @@ -192,7 +204,7 @@ void lalr_xml_example() " \n" " " ; - + parser.parse( (const uint8_t*) input, (const uint8_t*) input + strlen(input) ); LALR_ASSERT( parser.accepted() ); LALR_ASSERT( parser.full() ); diff --git a/src/lalr/lalr_test/TestParsers.cpp b/src/lalr/lalr_test/TestParsers.cpp index 038509d..ba65890 100644 --- a/src/lalr/lalr_test/TestParsers.cpp +++ b/src/lalr/lalr_test/TestParsers.cpp @@ -29,7 +29,7 @@ SUITE( Parsers ) while ( symbol != symbols_end && strcmp(symbol->identifier, identifier) != 0 ) { ++symbol; - } + } return symbol != symbols_end ? symbol : nullptr ; } @@ -41,7 +41,7 @@ SUITE( Parsers ) } }; - struct PrintParserErrorPolicy : public ErrorPolicy + struct PrintParserErrorPolicy : public ErrorPolicy { int errors; @@ -54,7 +54,7 @@ SUITE( Parsers ) { vprintf( format, args ); } - + void lalr_error( int line, int column, int /*error*/, const char* format, va_list args ) { char message [1024]; @@ -65,10 +65,10 @@ SUITE( Parsers ) }; struct CheckParserErrorPolicy : public ErrorPolicy - { + { int expected_error; - int errors; - + int errors; + CheckParserErrorPolicy( int expected_error ) : expected_error( expected_error ) , errors( 0 ) @@ -82,12 +82,12 @@ SUITE( Parsers ) CHECK( error == expected_error ); } }; - + struct CheckLexerErrorPolicy : public ErrorPolicy - { + { int expected_error; int errors; - + CheckLexerErrorPolicy( int expected_error ) : expected_error( expected_error ) , errors( 0 ) @@ -101,10 +101,10 @@ SUITE( Parsers ) CHECK( error == expected_error ); } }; - + TEST( OrOperator ) { - const char* or_grammar = + const char* or_grammar = "OrOperator {\n" " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: one | two | three;\n" @@ -115,9 +115,9 @@ SUITE( Parsers ) ; GrammarCompiler compiler; - compiler.compile( or_grammar, or_grammar + strlen(or_grammar) ); + compiler.compile( or_grammar, or_grammar + strlen(or_grammar) ); Parser parser( compiler.parser_state_machine() ); - + const char* input = "1"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); @@ -183,7 +183,7 @@ SUITE( Parsers ) TEST( ZeroToManyRepeats ) { - const char* zero_to_many_repeats_grammar = + const char* zero_to_many_repeats_grammar = "ZeroToManyRepeats {\n" " %whitespace \"[ \\t\\r\\n]\" ;\n" " %left two; \n" @@ -272,8 +272,8 @@ SUITE( Parsers ) TEST( Optional ) { - const char* optional_grammar = - "Optional {\n" + const char* optional_grammar = + "Optional {\n" " %whitespace \"[ \\t\\r\\n]\" ;\n" " unit: one two_opt three;\n" " two_opt: two | ;\n" @@ -397,16 +397,16 @@ SUITE( Parsers ) input = "(1+2)*3"; parser.parse( input, input + strlen(input) ); - CHECK( parser.accepted() ); - + CHECK( parser.accepted() ); + input = "1+2+3*(2+3)"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); - + input = "((1+2)*3"; parser.parse( input, input + strlen(input) ); CHECK( !parser.accepted() ); - + input = "1+"; parser.parse( input, input + strlen(input) ); CHECK( !parser.accepted() ); @@ -495,7 +495,7 @@ SUITE( Parsers ) parser.parse( input, input + strlen(input) ); CHECK( !parser.accepted() ); } - + TEST( Canonical ) { const char* canonical_grammar = @@ -559,7 +559,7 @@ SUITE( Parsers ) parser.parse( input, input + strlen(input) ); CHECK( !parser.accepted() ); } - + TEST( ProductionsOnCollapsedSymbols ) { const char* productions_on_collapsed_symbols_grammar = @@ -571,14 +571,14 @@ SUITE( Parsers ) GrammarCompiler compiler; compiler.compile( productions_on_collapsed_symbols_grammar, productions_on_collapsed_symbols_grammar + strlen(productions_on_collapsed_symbols_grammar) ); Parser parser( compiler.parser_state_machine() ); - + const char* input = "a"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); } - + TEST( ReduceStarNode ) - { + { const char* reduce_star_node_grammar = "ReduceStarNode {\n" " %whitespace \"[ \\t\\r\\n]\" ;\n" @@ -592,11 +592,11 @@ SUITE( Parsers ) GrammarCompiler compiler; compiler.compile( reduce_star_node_grammar, reduce_star_node_grammar + strlen(reduce_star_node_grammar) ); Parser parser( compiler.parser_state_machine() ); - + const char* input = "1"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); - + input = "111"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); @@ -614,12 +614,12 @@ SUITE( Parsers ) GrammarCompiler compiler; compiler.compile( reduce_parenthesis_grammar, reduce_parenthesis_grammar + strlen(reduce_parenthesis_grammar) ); Parser parser( compiler.parser_state_machine() ); - + const char* input = "1"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); CHECK( parser.full() ); - + input = "(1)"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); @@ -650,7 +650,7 @@ SUITE( Parsers ) GrammarCompiler compiler; compiler.compile( reduce_star_and_parenthesis_grammar, reduce_star_and_parenthesis_grammar + strlen(reduce_star_and_parenthesis_grammar) ); Parser parser( compiler.parser_state_machine() ); - + const char* input = "(1)"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); @@ -661,7 +661,7 @@ SUITE( Parsers ) CHECK( parser.accepted() ); CHECK( parser.full() ); } - + TEST( Whitespace ) { const char* whitespace_grammar = @@ -678,7 +678,7 @@ SUITE( Parsers ) GrammarCompiler compiler; compiler.compile( whitespace_grammar, whitespace_grammar + strlen(whitespace_grammar) ); Parser parser( compiler.parser_state_machine() ); - + const char* input = "a b"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); @@ -703,8 +703,8 @@ SUITE( Parsers ) parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); CHECK( parser.full() ); - } - + } + TEST( String ) { struct StringLexer @@ -720,17 +720,17 @@ SUITE( Parsers ) { *lexeme += *i; ++i; - } + } if ( i != end ) { LALR_ASSERT( *i == '\'' ); ++i; - } + } return i; } }; - - const char* string_grammar = + + const char* string_grammar = "String { \n" " %whitespace \"[ \\t\\r\\n]*\";\n" " unit: strings;\n" @@ -744,7 +744,7 @@ SUITE( Parsers ) Parser parser( compiler.parser_state_machine() ); parser.lexer_action_handlers() ( "string", &StringLexer::string_lexer ) - ; + ; const char* input = "'first' 'second' 'third'"; parser.parse( input, input + strlen(input) ); @@ -757,10 +757,10 @@ SUITE( Parsers ) CHECK( parser.accepted() ); CHECK( parser.full() ); } - + TEST( LineCommentInWhitespaceDirective ) { - const char* line_comment_grammar = + const char* line_comment_grammar = "LineComment {\n" " %whitespace \"([ \\t\\r\\n]|\\/\\/:line_comment:)*\";\n" " unit: digits;\n" @@ -776,12 +776,12 @@ SUITE( Parsers ) ( "line_comment", &line_comment ) ; - const char* input = + const char* input = "1 2 // This is a comment\n" "3 4 // This is another comment\r" "// 5 6 \n\r" ; - + parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); CHECK( parser.full() ); @@ -789,7 +789,7 @@ SUITE( Parsers ) TEST( BlockCommentInWhitespaceDirective ) { - const char* block_comment_grammar = + const char* block_comment_grammar = "BlockComment {\n" " %whitespace \"([ \\t\\r\\n]|\\/\\*:block_comment:)*\";\n" " unit: digits;\n" @@ -805,12 +805,12 @@ SUITE( Parsers ) ( "block_comment", &block_comment ) ; - const char* input = + const char* input = "1 2 /* This is a comment\n" "3 */ 4 /* This is another comment\r" "*/ 5 6 /* This is a third comment */ \n\r" ; - + parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); CHECK( parser.full() ); @@ -819,8 +819,8 @@ SUITE( Parsers ) /* TEST( SyntaxErrorsInGrammar ) { - { - const char* missing_open_brace = + { + const char* missing_open_brace = "MissingOpenBrace \n" " %whitespace \"[ \\t\\r\\n]*\";\n" " unit: string;\n" @@ -836,7 +836,7 @@ SUITE( Parsers ) } { - const char* missing_close_quotes = + const char* missing_close_quotes = "MissingCloseQuotes { \n" " %whitespace \"[ \\t\\r\\n]*;\n" " unit: strings;\n" @@ -851,12 +851,12 @@ SUITE( Parsers ) CHECK( parser_state_machine.start_state() == NULL ); CHECK( parser_state_machine.states().empty() ); } - } + } */ TEST( SyntaxErrorsInRegularExpressions ) { - const char* syntax_errors_in_regular_expressions_grammar = + const char* syntax_errors_in_regular_expressions_grammar = "SyntaxErrorsInRegularExpressions {\n" " %whitespace \"[ \\t\\r\\n*\";\n" " one: \"[A-z*\";\n" @@ -865,8 +865,8 @@ SUITE( Parsers ) CheckLexerErrorPolicy error_policy( LEXER_ERROR_SYNTAX ); GrammarCompiler compiler; - compiler.compile( - syntax_errors_in_regular_expressions_grammar, + compiler.compile( + syntax_errors_in_regular_expressions_grammar, syntax_errors_in_regular_expressions_grammar + strlen(syntax_errors_in_regular_expressions_grammar), &error_policy ); @@ -875,7 +875,7 @@ SUITE( Parsers ) TEST( UndefinedSymbolError ) { - const char* undefined_symbol_grammar = + const char* undefined_symbol_grammar = "UndefinedSymbolError {\n" " %whitespace \"[ \\t\\r\\n]*\";\n" " one: undefined_symbol;\n" @@ -885,12 +885,12 @@ SUITE( Parsers ) CheckParserErrorPolicy error_policy( PARSER_ERROR_UNDEFINED_SYMBOL ); GrammarCompiler compiler; compiler.compile( undefined_symbol_grammar, undefined_symbol_grammar + strlen(undefined_symbol_grammar), &error_policy ); - CHECK( error_policy.errors == 1 ); + CHECK( error_policy.errors == 1 ); } TEST( UnreferencedSymbolError ) { - const char* unreferenced_symbol_error_grammar = + const char* unreferenced_symbol_error_grammar = "UnreferencedSymbolError {\n" " %whitespace \"[ \\t\\r\\n]*\";\n" " one: 'one';\n" " unreferenced_symbol: 'two';\n" @@ -899,17 +899,17 @@ SUITE( Parsers ) CheckParserErrorPolicy error_policy( PARSER_ERROR_UNREFERENCED_SYMBOL ); GrammarCompiler compiler; - compiler.compile( - unreferenced_symbol_error_grammar, + compiler.compile( + unreferenced_symbol_error_grammar, unreferenced_symbol_error_grammar + strlen(unreferenced_symbol_error_grammar), &error_policy ); CHECK( error_policy.errors == 1 ); } - + TEST( SymbolsOnlyAppearingInPrecedenceDirectivesAreCountedAsReferenced ) { - const char* precedence_directive_symbols_grammar = + const char* precedence_directive_symbols_grammar = "SymbolsOnlyAppearingInPrecedenceDirectivesAreCountedAsReferenced { \n" " %whitespace \"[ \\t\\r\\n]*\";\n" " %left unary_minus; \n" @@ -933,10 +933,10 @@ SUITE( Parsers ) compiler.compile( precedence_directive_symbols_grammar, precedence_directive_symbols_grammar + strlen(precedence_directive_symbols_grammar), &error_policy ); CHECK( error_policy.errors == 0 ); } - + TEST( LexerConflict ) { - const char* lexer_conflict_grammar = + const char* lexer_conflict_grammar = "LexerConflictError {\n" " %whitespace \"[ \\t\\r\\n]*\";\n" " %left prototype value;\n" @@ -972,10 +972,10 @@ SUITE( Parsers ) return begin; } }; - + TEST( LexerConflictResolution ) { - const char* lexer_conflict_grammar = + const char* lexer_conflict_grammar = "LexerSymbolConflictResolvedByAction {\n" " %whitespace \"[ \\t\\r\\n]*\";\n" " %left prototype value;\n" @@ -1005,10 +1005,10 @@ SUITE( Parsers ) CHECK( parser.full() ); } } - + TEST( AssociativityDirectives ) { - const char* associativity_grammar = + const char* associativity_grammar = "AssociativityDirectives {\n" " %whitespace \"[ \\t\\r\\n]*\";\n" " %left '+' '-';\n" @@ -1032,12 +1032,12 @@ SUITE( Parsers ) parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); CHECK( parser.full() ); - + input = "1+2*3"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); CHECK( parser.full() ); - + input = "1*2+3"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); @@ -1047,7 +1047,7 @@ SUITE( Parsers ) TEST( PrecedenceDirectives ) { - const char* precedence_grammar = + const char* precedence_grammar = "PrecedenceDirectives {\n" " %whitespace \"[ \\t\\r\\n]*\";\n" " %left '+';\n" @@ -1060,7 +1060,7 @@ SUITE( Parsers ) " ;\n" " integer: \"[0-9]+\";\n" "}" - ; + ; GrammarCompiler compiler; CheckParserErrorPolicy error_policy( PARSER_ERROR_PARSE_TABLE_CONFLICT ); @@ -1076,10 +1076,10 @@ SUITE( Parsers ) // CHECK( expr->get_productions()[2]->get_precedence() == 3 ); } } - + TEST( ErrorSymbolOnLeftHandSideError ) { - const char* grammar = + const char* grammar = "ErrorSymbolOnLeftHandSideError {\n" " %whitespace \"[ \\t\\r\\n]*\";\n" " unit: prototype '{' error '}';\n" @@ -1087,13 +1087,13 @@ SUITE( Parsers ) " error: ;\n" "}" ; - + GrammarCompiler compiler; CheckParserErrorPolicy error_policy( PARSER_ERROR_ERROR_SYMBOL_ON_LEFT_HAND_SIDE ); compiler.compile( grammar, grammar + strlen(grammar), &error_policy ); - CHECK( error_policy.errors == 1 ); + CHECK( error_policy.errors == 1 ); } - + TEST( ErrorProcessing ) { const char* error_processing_grammar = @@ -1112,14 +1112,14 @@ SUITE( Parsers ) Parser parser( compiler.parser_state_machine() ); parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); - CHECK( parser.full() ); + CHECK( parser.full() ); input = "1-2"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); - CHECK( parser.full() ); + CHECK( parser.full() ); } - + TEST( EmptyProduction ) { const char* empty_production_grammar = @@ -1132,7 +1132,7 @@ SUITE( Parsers ) " integer: \"[0-9]+\"; \n" "}" ; - + PrintParserErrorPolicy error_policy; GrammarCompiler compiler; compiler.compile( empty_production_grammar, empty_production_grammar + strlen(empty_production_grammar), &error_policy ); @@ -1146,7 +1146,7 @@ SUITE( Parsers ) input = "1;"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); - CHECK( parser.full() ); + CHECK( parser.full() ); input = ""; parser.parse( input, input + strlen(input) ); @@ -1168,7 +1168,7 @@ SUITE( Parsers ) "} \n" "// Unterminated line comment" ; - + PrintParserErrorPolicy error_policy; GrammarCompiler compiler; compiler.compile( line_comment_grammar, line_comment_grammar + strlen(line_comment_grammar), &error_policy ); @@ -1188,13 +1188,13 @@ SUITE( Parsers ) "} \n" "/* Block comment at the end of input */" ; - + PrintParserErrorPolicy error_policy; GrammarCompiler compiler; compiler.compile( block_comment_grammar, block_comment_grammar + strlen(block_comment_grammar), &error_policy ); CHECK( error_policy.errors == 0 ); - const char* unterminated_block_comment_grammar = + const char* unterminated_block_comment_grammar = "BlockComment { \n" " %whitespace \"[ \\t\\r\\n]*\";\n" " unit: 'BlockCommentExample'; \n" @@ -1207,7 +1207,7 @@ SUITE( Parsers ) TEST( IntegersErrorHandlingExample ) { - const char* integers_grammar = + const char* integers_grammar = "integers { \n" " %whitespace \"[ \\t\\r\\n]*\";\n" " %none error; \n" @@ -1229,7 +1229,7 @@ SUITE( Parsers ) TEST( LineNumbering ) { - const char* line_numbering_grammar = + const char* line_numbering_grammar = "line_numbering { \n" " %whitespace \"[ \\t\\n\\r]*\";" " %none error; \n" @@ -1251,11 +1251,12 @@ SUITE( Parsers ) Parser parser( compiler.parser_state_machine() ); parser.parser_action_handlers() - ( "result", [] ( const int* /*data*/, const ParserNode<>* nodes, size_t /*length*/ ) + ( "result", [] ( int& result, const int* /*data*/, const ParserNode<>* nodes, size_t /*length*/ ) { int value = ::atoi( nodes[0].lexeme().c_str() ); CHECK( value == nodes[0].line() ); - return value; + result = value; + return true; } ) ; @@ -1263,13 +1264,13 @@ SUITE( Parsers ) const char* input = "1;\n2;\n3;\n"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); - CHECK( parser.full() ); + CHECK( parser.full() ); parser.parser_action_handlers() - ( "unexpected_error", [] ( const int* /*data*/, const ParserNode<>* nodes, size_t /*length*/ ) + ( "unexpected_error", [] ( int& /*result*/, const int* /*data*/, const ParserNode<>* nodes, size_t /*length*/ ) { CHECK( nodes[0].line() == 3 ); - return 0; + return false; } ) ; @@ -1277,12 +1278,12 @@ SUITE( Parsers ) input = "1;\n2;\na;\n4;\n"; parser.parse( input, input + strlen(input) ); CHECK( parser.accepted() ); - CHECK( parser.full() ); + CHECK( parser.full() ); } TEST( MissingLexicalActionHandler ) { - const char* line_comment_grammar = + const char* line_comment_grammar = "MissingLexicalActionHandler {\n" " %whitespace \"([ \\t\\r\\n]|\\/\\/:line_comment:)*\";\n" " unit: '1';\n" From 02178b9a7e3c4c4e1c1150bad7e5b218d620c5ca Mon Sep 17 00:00:00 2001 From: mingodad Date: Wed, 28 Jun 2023 17:42:09 +0200 Subject: [PATCH 25/40] Check if the input is accepted && full before print the parse tree --- playground/index.html | 1 + playground/index.js | 12 ++++++++++-- playground/lalr_playground.cpp | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/playground/index.html b/playground/index.html index b31906d..63b4d73 100644 --- a/playground/index.html +++ b/playground/index.html @@ -23,6 +23,7 @@ + diff --git a/playground/index.js b/playground/index.js index 101243a..5dc4c22 100644 --- a/playground/index.js +++ b/playground/index.js @@ -155,6 +155,15 @@ function loadLalr_sample(self) { codeEditor.getSession().setMode("ace/mode/c_cpp"); }); break; + case "Ispc parser": + $.get(base_url + "ispc.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.ispc", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/c_cpp"); + }); + break; case "Java11 parser": $.get(base_url + "java11.g", function( data ) { grammarEditor.setValue( data ); @@ -334,7 +343,6 @@ function parse() { if (result.compile == 0 || isGenEBNF) { $grammarValidation.removeClass('validation-invalid').show(); - codeAst.insert(outputs.ast); codeLexer.insert(outputs.lexer); if (result.parse == 0) { @@ -370,7 +378,7 @@ function parse() { } if (outputs.ast.length > 0) { - $codeAst.setValue(outputs.ast); + codeAst.setValue(outputs.ast); } }, 0); } diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp index 65ae64c..c8ffb40 100644 --- a/playground/lalr_playground.cpp +++ b/playground/lalr_playground.cpp @@ -218,7 +218,7 @@ extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLe else parser.parse( input, input + strlen((const char*)input) ); parse_result = parser.accepted() == 1 && parser.full() == 1; - if(generate_parsetree) + if(generate_parsetree && parse_result) { switch_output("ast"); print_parsetree( parser.user_data(), 0 ); From eb7ff4cb9b966bcbf2585774d61c57f014e72b48 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sun, 16 Jul 2023 09:55:58 +0200 Subject: [PATCH 26/40] Now I've got closer to a good parse tree dump --- playground/index.html | 9 +- playground/index.js | 23 +++-- playground/lalr_playground.cpp | 167 +++++++++++++++++++++++---------- 3 files changed, 142 insertions(+), 57 deletions(-) diff --git a/playground/index.html b/playground/index.html index 63b4d73..5095b61 100644 --- a/playground/index.html +++ b/playground/index.html @@ -29,6 +29,7 @@ + @@ -52,14 +53,14 @@
    • -
    • +
{{source}}
     - mode:  + mode: 

     
@@ -71,6 +72,10 @@
+ diff --git a/playground/index.js b/playground/index.js index 5dc4c22..a7bbf7b 100644 --- a/playground/index.js +++ b/playground/index.js @@ -132,7 +132,7 @@ function loadLalr_sample(self) { $.get(base_url + "javascript.g", function( data ) { grammarEditor.setValue( data ); }); - $.get(base_url + "test.js", function( data ) { + $.get(base_url + "test.js.txt", function( data ) { codeEditor.setValue( data ); codeEditor.getSession().setMode("ace/mode/javascript"); }); @@ -141,7 +141,7 @@ function loadLalr_sample(self) { $.get(base_url + "javascript-core.g", function( data ) { grammarEditor.setValue( data ); }); - $.get(base_url + "test.js", function( data ) { + $.get(base_url + "test.js.txt", function( data ) { codeEditor.setValue( data ); codeEditor.getSession().setMode("ace/mode/javascript"); }); @@ -227,10 +227,19 @@ function loadLalr_sample(self) { codeEditor.getSession().setMode("ace/mode/ada"); }); break; + case "XML parser": + $.get(base_url + "xml.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "test.xml.txt", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/xml"); + }); + break; } } -$('#opt-mode').val(localStorage.getItem('optimizationMode') || '2'); +//$('#ast-mode').val(localStorage.getItem('optimizationMode') || '2'); $('#gen-ebnf').prop('checked', localStorage.getItem('gen-ebnf') === 'true'); $('#auto-refresh').prop('checked', localStorage.getItem('autoRefresh') === 'true'); $('#parse').prop('disabled', $('#auto-refresh').prop('checked')); @@ -284,7 +293,7 @@ function generateErrorListHTML(errors) { function updateLocalStorage() { localStorage.setItem('grammarText', grammarEditor.getValue()); localStorage.setItem('codeText', codeEditor.getValue()); - localStorage.setItem('optimizationMode', $('#opt-mode').val()); + //localStorage.setItem('optimizationMode', $('#opt-mode').val()); localStorage.setItem('gen-ebnf', $('#gen-ebnf').prop('checked')); localStorage.setItem('autoRefresh', $('#auto-refresh').prop('checked')); } @@ -300,10 +309,12 @@ function parse() { const $codeInfo = $('#code-info'); const codeText = codeEditor.getValue(); - const optimizationMode = $('#opt-mode').val(); + const astMode = $('#ast-mode').val(); const generate_ebnf = $('#gen-ebnf').prop('checked'); const lexer = $('#show-lexer').prop('checked'); - const generate_ast = $('#show-ast').prop('checked'); + let generate_ast = $('#show-ast').prop('checked'); + if(generate_ast && astMode == 2) + generate_ast = 2; $grammarInfo.html(''); $grammarValidation.hide(); diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp index c8ffb40..4d2488f 100644 --- a/playground/lalr_playground.cpp +++ b/playground/lalr_playground.cpp @@ -59,6 +59,41 @@ struct C_MultLineCommentLexer } }; + +struct ParseTreeUserDataDbg { + int index; + int stack_index; + static int next_index; + static int total; + ParseTreeUserDataDbg():index(total++), stack_index(next_index++) {}; +}; +int ParseTreeUserDataDbg::next_index = 0; +int ParseTreeUserDataDbg::total = 0; + + +static bool parseTreeMakerDbg( ParseTreeUserDataDbg& result, const ParseTreeUserDataDbg* start, const lalr::ParserNode* nodes, size_t length ) +{ + switch_output("ast"); +// //printf("astMaker: %s\n", nodes[0].lexeme().c_str()); +// const char *lexstr = (length > 0 ? (const char *)nodes[0].lexeme().c_str() : "::lnull"); +// const char *idstr = (length > 0 ? nodes[0].symbol()->identifier : "::inull"); +// int line = (length > 0 ? nodes[0].line() : 0); +// int column = (length > 0 ? nodes[0].column() : 0); +// //const char *stateLabel = (length > 0 ? nodes[0].state()->label : "::inull"); +// printf("astMaker: %p\t%zd:%d:%d\t%p\t%zd\t->\t%s : %s :%d:%d\n", start, length, +// length ? start->index : -1, length ? start->stack_index : -1, +// nodes, length, idstr, lexstr, line, column); + printf("----\n"); + for(size_t i=0; i< length; ++i) + printf("%zd:%d\t%p\t%d:%d\t%p <:> %s <:> %s <:> %s <:> %d:%d\n", i, nodes[i].symbol()->type, + start+i, start[i].index, start[i].stack_index, nodes+i, + nodes[i].symbol()->identifier, nodes[i].symbol()->lexeme, + nodes[i].lexeme().c_str(), nodes[i].line(), nodes[i].column()); + switch_output("parse_status"); + return true; +} + + struct ParseTreeUserData { std::vector children; const lalr::ParserSymbol *symbol; @@ -69,48 +104,48 @@ struct ParseTreeUserData { static bool parsetreeMaker( ParseTreeUserData& result, const ParseTreeUserData* start, const lalr::ParserNode* nodes, size_t length ) { - if(length == 2 && nodes[0].symbol()->type == lalr::SymbolType::SYMBOL_NON_TERMINAL && nodes[1].symbol()->type == lalr::SymbolType::SYMBOL_NON_TERMINAL) - { - if(start[0].symbol == nodes[0].symbol()) - { - result = start[0]; - } - else - { - result.symbol = nodes[0].symbol(); - } - ParseTreeUserData& udt = result.children.emplace_back(); - udt.symbol = nodes[1].symbol(); - udt.children.push_back(start[1]); - } - else + if(length == 0) return false; + result.symbol = nodes[length-1].state()->transitions->reduced_symbol; + for(size_t i_node = 0; i_node < length; ++i_node) { - for(size_t i_node = 0; i_node < length; ++i_node) + const lalr::ParserNode& the_node = nodes[i_node]; + switch(the_node.symbol()->type) { - const lalr::ParserNode& the_node = nodes[i_node]; - switch(the_node.symbol()->type) + case lalr::SymbolType::SYMBOL_TERMINAL: + { + ParseTreeUserData& udt = result.children.emplace_back(); + udt.symbol = the_node.symbol(); + udt.lexeme = the_node.lexeme(); + //printf("TERMINAL: %s : %s\n", udt.symbol->identifier, udt.lexeme.c_str()); + } + break; + case lalr::SymbolType::SYMBOL_NON_TERMINAL: { - case lalr::SymbolType::SYMBOL_TERMINAL: + if(the_node.symbol() == result.symbol) { - ParseTreeUserData& udt = (length == 1) ? result : result.children.emplace_back(); - udt.symbol = the_node.symbol(); - udt.symbol = the_node.symbol(); - udt.lexeme = the_node.lexeme(); - //printf("TERMINAL: %s : %s\n", udt.symbol->identifier, udt.lexeme.c_str()); + const ParseTreeUserData& startx = start[i_node]; + for (std::vector::const_iterator child = startx.children.begin(); child != startx.children.end(); ++child) + { + result.children.push_back( std::move(*child) ); + } } - break; - case lalr::SymbolType::SYMBOL_NON_TERMINAL: + else { - ParseTreeUserData& udt = (length == 1) ? result : result.children.emplace_back(); + ParseTreeUserData& udt = result.children.emplace_back(); udt.symbol = the_node.symbol(); - udt.children.push_back(start[i_node]); - //printf("NON_TERMINAL: %s\n", result.symbol->identifier); + if(udt.symbol == start[i_node].symbol) + { + udt.children = start[i_node].children; + } + else + udt.children.push_back(std::move(start[i_node])); } - break; - default: - //LALR_ASSERT( ?? ); - printf("Unexpected symbol %p\n", the_node.symbol()); + //printf("NON_TERMINAL: %s\n", result.symbol->identifier); } + break; + default: + //LALR_ASSERT( ?? ); + printf("Unexpected symbol %p\n", the_node.symbol()); } } return true; @@ -205,30 +240,64 @@ extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLe if(input) { lalr::ErrorPolicy error_policy_input; - //lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); - lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); - parser.set_default_action_handler(parsetreeMaker); - parser.lexer_action_handlers() - ( "C_MultilineComment", &C_MultLineCommentLexer::string_lexer ) - ; - if(dumpLexer) { - switch_output("lexer"); - parser.dumpLex( input, input + strlen((const char*)input) ); + if(generate_parsetree == 1) + { + lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); + parser.set_default_action_handler(parsetreeMaker); + parser.lexer_action_handlers() + ( "C_MultilineComment", &C_MultLineCommentLexer::string_lexer ) + ; + if(dumpLexer) { + switch_output("lexer"); + parser.dumpLex( input, input + strlen((const char*)input) ); + } + else parser.parse( input, input + strlen((const char*)input) ); + + parse_result = parser.accepted() == 1 && parser.full() == 1; + if(generate_parsetree && parse_result) + { + showDiffTime("Parse input"); + switch_output("ast"); + print_parsetree( parser.user_data(), 0 ); + switch_output("parse_status"); + showDiffTime("Print parse tree"); + } } - else parser.parse( input, input + strlen((const char*)input) ); + if(generate_parsetree > 1) + { + lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); + parser.set_default_action_handler(parseTreeMakerDbg); + parser.lexer_action_handlers() + ( "C_MultilineComment", &C_MultLineCommentLexer::string_lexer ) + ; + if(dumpLexer) { + switch_output("lexer"); + parser.dumpLex( input, input + strlen((const char*)input) ); + } + else parser.parse( input, input + strlen((const char*)input) ); - parse_result = parser.accepted() == 1 && parser.full() == 1; - if(generate_parsetree && parse_result) + parse_result = parser.accepted() == 1 && parser.full() == 1; + } + else { - switch_output("ast"); - print_parsetree( parser.user_data(), 0 ); - switch_output("parse_status"); + lalr::Parser parser( compiler.parser_state_machine(), &error_policy_input ); + parser.lexer_action_handlers() + ( "C_MultilineComment", &C_MultLineCommentLexer::string_lexer ) + ; + if(dumpLexer) { + switch_output("lexer"); + parser.dumpLex( input, input + strlen((const char*)input) ); + } + else parser.parse( input, input + strlen((const char*)input) ); + + parse_result = parser.accepted() == 1 && parser.full() == 1; } if (parse_result) { if (parse_verbose) { fprintf(stderr, "Parse successful.\n"); } - showDiffTime("Parse input"); + if(generate_parsetree != 1) + showDiffTime("Parse input"); } else { err = -2; From ccdca1a3f6816103bc51c83db1ab7526ea094518 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sun, 16 Jul 2023 13:53:07 +0200 Subject: [PATCH 27/40] Missing fixes for a better parse tree output --- playground/lalr_playground.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp index 4d2488f..841053e 100644 --- a/playground/lalr_playground.cpp +++ b/playground/lalr_playground.cpp @@ -133,12 +133,7 @@ static bool parsetreeMaker( ParseTreeUserData& result, const ParseTreeUserData* { ParseTreeUserData& udt = result.children.emplace_back(); udt.symbol = the_node.symbol(); - if(udt.symbol == start[i_node].symbol) - { - udt.children = start[i_node].children; - } - else - udt.children.push_back(std::move(start[i_node])); + udt.children.push_back(std::move(start[i_node])); } //printf("NON_TERMINAL: %s\n", result.symbol->identifier); } From 9f907f68ca01c9eb41116b1e1a75394e65679698 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sun, 16 Jul 2023 13:54:51 +0200 Subject: [PATCH 28/40] Show an error message when associativity is assigned to a non-terminal. --- src/lalr/ErrorCode.hpp | 3 ++- src/lalr/GrammarGenerator.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lalr/ErrorCode.hpp b/src/lalr/ErrorCode.hpp index 0fcab63..faf1683 100644 --- a/src/lalr/ErrorCode.hpp +++ b/src/lalr/ErrorCode.hpp @@ -25,7 +25,8 @@ enum ErrorCode PARSER_ERROR_UNDEFINED_SYMBOL, ///< A grammar symbol is referenced but not defined. PARSER_ERROR_UNREFERENCED_SYMBOL, ///< A grammar symbol is defined but not referenced. PARSER_ERROR_ERROR_SYMBOL_ON_LEFT_HAND_SIDE, ///< The 'error' symbol has been used on the left hand side of a production. - PARSER_ERROR_DUPLICATE_ASSOCIATION_ON_IMPLICIT_TERMINAL ///< Both implicit terminal forms specify associativity and precedence. + PARSER_ERROR_DUPLICATE_ASSOCIATION_ON_IMPLICIT_TERMINAL, ///< Both implicit terminal forms specify associativity and precedence. + PARSER_ERROR_ASSOCIATIVITY_ASSIGNED_ON_NON_TERMINAL ///< Associativity has been assigned to a non-terminal. }; } diff --git a/src/lalr/GrammarGenerator.cpp b/src/lalr/GrammarGenerator.cpp index b29b7c8..954b79e 100644 --- a/src/lalr/GrammarGenerator.cpp +++ b/src/lalr/GrammarGenerator.cpp @@ -573,6 +573,10 @@ void GrammarGenerator::calculate_implicit_terminal_symbols() replace_references_to_symbol( non_terminal_symbol, terminal_symbol ); i->reset(); } + else if(non_terminal_symbol->associativity() != ASSOCIATE_NULL && non_terminal_symbol->productions().size()) + { + error( non_terminal_symbol->line(), PARSER_ERROR_ASSOCIATIVITY_ASSIGNED_ON_NON_TERMINAL, "associativity has been assigned to a non-terminal: %s", non_terminal_symbol->identifier().c_str()); + } } } From 1d092219d6f0dd2cd148b7edc6bffbe56843c8e7 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sun, 16 Jul 2023 14:11:18 +0200 Subject: [PATCH 29/40] Undo a mistaken removing code for a better parse tree output. --- playground/lalr_playground.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp index 841053e..4d2488f 100644 --- a/playground/lalr_playground.cpp +++ b/playground/lalr_playground.cpp @@ -133,7 +133,12 @@ static bool parsetreeMaker( ParseTreeUserData& result, const ParseTreeUserData* { ParseTreeUserData& udt = result.children.emplace_back(); udt.symbol = the_node.symbol(); - udt.children.push_back(std::move(start[i_node])); + if(udt.symbol == start[i_node].symbol) + { + udt.children = start[i_node].children; + } + else + udt.children.push_back(std::move(start[i_node])); } //printf("NON_TERMINAL: %s\n", result.symbol->identifier); } From 8aa81d29de194bd75fbf15b80578ffdc21087fc8 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sun, 16 Jul 2023 17:50:06 +0200 Subject: [PATCH 30/40] Fix generation of empty productions for genEBNF --- src/lalr/Grammar.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 46322b1..6e7b238 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -375,6 +375,10 @@ void Grammar::genEBNF() } } else { + if(production_continuation) { + production_continuation = false; + printf("\n%s\t| ", prefix); + } printf("/*empty*/"); } if(production->precedence_symbol()) { From 51ab70ed351d9056404dae1137ae04f7f2a357e9 Mon Sep 17 00:00:00 2001 From: mingodad Date: Mon, 17 Jul 2023 08:45:53 +0200 Subject: [PATCH 31/40] Add YACC generation from LALR grammars. --- playground/index.html | 8 +- playground/index.js | 18 +++- playground/lalr_playground.cpp | 6 +- src/lalr/Grammar.cpp | 164 +++++++++++++++++++++++++++++++++ src/lalr/Grammar.hpp | 1 + src/lalr/GrammarCompiler.cpp | 7 +- src/lalr/GrammarCompiler.hpp | 2 +- 7 files changed, 195 insertions(+), 11 deletions(-) diff --git a/playground/index.html b/playground/index.html index 5095b61..0098ee8 100644 --- a/playground/index.html +++ b/playground/index.html @@ -31,6 +31,7 @@ + @@ -52,7 +53,12 @@
  • Input source
    • -
    • +
    • +
    diff --git a/playground/index.js b/playground/index.js index a7bbf7b..b0827b2 100644 --- a/playground/index.js +++ b/playground/index.js @@ -92,6 +92,15 @@ function loadLalr_sample(self) { codeEditor.getSession().setMode("ace/mode/text"); }); break; + case "LALR parser (not working)": + $.get(base_url + "lalr.g", function( data ) { + grammarEditor.setValue( data ); + }); + $.get(base_url + "lalr.g", function( data ) { + codeEditor.setValue( data ); + codeEditor.getSession().setMode("ace/mode/yaml"); + }); + break; case "Bison parser (not working)": $.get(base_url + "bison.g", function( data ) { grammarEditor.setValue( data ); @@ -240,7 +249,6 @@ function loadLalr_sample(self) { } //$('#ast-mode').val(localStorage.getItem('optimizationMode') || '2'); -$('#gen-ebnf').prop('checked', localStorage.getItem('gen-ebnf') === 'true'); $('#auto-refresh').prop('checked', localStorage.getItem('autoRefresh') === 'true'); $('#parse').prop('disabled', $('#auto-refresh').prop('checked')); @@ -294,7 +302,6 @@ function updateLocalStorage() { localStorage.setItem('grammarText', grammarEditor.getValue()); localStorage.setItem('codeText', codeEditor.getValue()); //localStorage.setItem('optimizationMode', $('#opt-mode').val()); - localStorage.setItem('gen-ebnf', $('#gen-ebnf').prop('checked')); localStorage.setItem('autoRefresh', $('#auto-refresh').prop('checked')); } @@ -310,7 +317,8 @@ function parse() { const codeText = codeEditor.getValue(); const astMode = $('#ast-mode').val(); - const generate_ebnf = $('#gen-ebnf').prop('checked'); + const generate_ebnf = $('#generate-action').val() == 'ebnf'; + const generate_yacc = $('#generate-action').val() == 'yacc'; const lexer = $('#show-lexer').prop('checked'); let generate_ast = $('#show-ast').prop('checked'); if(generate_ast && astMode == 2) @@ -342,7 +350,7 @@ function parse() { window.setTimeout(() => { parse_start_time = new Date().getTime(); - lalr_parse(grammarText, codeText, lexer, generate_ebnf, generate_ast); + lalr_parse(grammarText, codeText, lexer, generate_ebnf, generate_yacc, generate_ast); $('#overlay').css({ 'z-index': '-1', @@ -424,7 +432,7 @@ $('#code-info').on('click', 'li[data-ln]', makeOnClickInInfo(codeEditor)); // Event handing in the AST optimization $('#opt-mode').on('change', setupTimer); -$('#gen-ebnf').on('change', setupTimer); +$('#generate-action').on('change', setupTimer); $('#show-lexer').on('change', setupTimer); $('#auto-refresh').on('change', () => { updateLocalStorage(); diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp index 4d2488f..adad8da 100644 --- a/playground/lalr_playground.cpp +++ b/playground/lalr_playground.cpp @@ -186,7 +186,7 @@ static void print_parsetree( const ParseTreeUserData& ast, int level ) } } -extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLexer, int generate_ebnf, int generate_parsetree) +extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLexer, int generate_ebnf, int generate_yacc, int generate_parsetree) { int err = 0; // currently, zero is always returned; result codes for each part // are sent to JS via set_result() @@ -209,7 +209,7 @@ extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLe lalr::GrammarCompiler compiler; lalr::ErrorPolicy error_policy; - int errors = compiler.compile( grammar, grammar + strlen(grammar), &error_policy, generate_ebnf != 0); + int errors = compiler.compile( grammar, grammar + strlen(grammar), &error_policy, generate_ebnf, generate_yacc); if (errors != 0) { fprintf(stderr, "Error compiling grammar. " @@ -218,7 +218,7 @@ extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLe goto done; } else { - if(generate_ebnf) { + if(generate_ebnf || generate_yacc) { err = -3; parse_result = 0; goto done; diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 6e7b238..701d55a 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -326,6 +326,11 @@ static bool isTerminalRegex(const GrammarSymbol *symbol) && symbol->lexeme_type() == LexemeType::LEXEME_REGULAR_EXPRESSION; } +static bool isTerminal(const GrammarSymbol *symbol) +{ + return symbol->symbol_type() == SymbolType::SYMBOL_TERMINAL; +} + void Grammar::genEBNF() { printf( @@ -390,6 +395,165 @@ void Grammar::genEBNF() printf("\n\n// end EBNF\n"); } +void Grammar::genYACC() +{ + const char *prefix = ""; + printf( + "//\n" + "// YACC grammar for %s\n" + "//\n" + , identifier().c_str() + ); + printf("\n/*Tokens*/\n"); + GrammarSymbol* last_production_symbol = NULL; + bool production_continuation = false; + for ( vector>::const_iterator i = productions().begin(); i != productions().end(); ++i ) + { + GrammarProduction* production = i->get(); + LALR_ASSERT( production ); + GrammarSymbol *curr_symbol = production->symbol(); + bool same_production = last_production_symbol && last_production_symbol == curr_symbol; + vector>::const_iterator production_next = (i+1); + bool hasMoreProductions = same_production || (production_next != productions().end() && production_next->get()->symbol() == curr_symbol); + if(!same_production) + { + if( isTerminalRegex(curr_symbol) + || (!hasMoreProductions && production->length() == 1 && isTerminal(production->symbol_by_position(0))) ) + { + printf("%%token %s ;\n", curr_symbol->lexeme().c_str()); + } + } + last_production_symbol = curr_symbol; + } + + int max_prec = 0; + for ( vector>::const_iterator i = symbols().begin(); i != symbols().end(); ++i ) + { + GrammarSymbol* curr_symbol = i->get(); + LALR_ASSERT( curr_symbol ); + + if(curr_symbol->precedence() > max_prec) + { + max_prec = curr_symbol->precedence(); + } + } + + if(max_prec > 0) + { + printf("\n/*Asociativity/Precedence*/\n"); + for(int ip = 1; ip <= max_prec; ++ip) + { + production_continuation = false; + int last_prec = 0; + for ( vector>::const_iterator i = symbols().begin(); i != symbols().end(); ++i ) + { + GrammarSymbol* curr_symbol = i->get(); + LALR_ASSERT( curr_symbol ); + + if(curr_symbol->precedence() == ip) + { + if(curr_symbol->precedence() > max_prec) + { + max_prec = curr_symbol->precedence(); + } + if(last_prec != ip ) + { + switch(curr_symbol->associativity()) + { + case lalr::Associativity::ASSOCIATE_NONE: + printf("\n%%nonassoc "); + break; + case lalr::Associativity::ASSOCIATE_LEFT: + printf("\n%%left "); + break; + case lalr::Associativity::ASSOCIATE_RIGHT: + printf("\n%%right "); + break; + case lalr::Associativity::ASSOCIATE_PREC: + printf("\n%%precedence "); + break; + } + last_prec = ip; + printf(" /*%d*/ ", ip); + } + if(last_prec == curr_symbol->precedence()) + { + ouptputTerminal(curr_symbol); + printf(" "); + } + } + } + if(last_prec > 0) + printf(";"); + } + } + + printf("\n\n%%%%\n"); + last_production_symbol = NULL; + production_continuation = false; + for ( vector>::const_iterator i = productions().begin(); i != productions().end(); ++i ) + { + GrammarProduction* production = i->get(); + LALR_ASSERT( production ); + GrammarSymbol *curr_symbol = production->symbol(); + bool same_production = last_production_symbol && last_production_symbol == curr_symbol; + vector>::const_iterator production_next = (i+1); + bool hasMoreProductions = same_production || (production_next != productions().end() && production_next->get()->symbol() == curr_symbol); + if (isTerminalRegex(curr_symbol) + || (!hasMoreProductions && production->length() == 1 && isTerminal(production->symbol_by_position(0)))) + { + continue; + } + if(same_production) { + production_continuation = true; + //printf(" //%s ::= %d", production->symbol()->lexeme().c_str(), production->length()); + } + else { + production_continuation = false; + const char *sym_prefix = ""; + const char *sym_name = curr_symbol->lexeme().c_str(); + if(sym_name[0] == '.') + { + continue; + } + //printf("\n\n%s%s ::= // %d\n\t", sym_prefix, sym_name, production->length()); + if(last_production_symbol) + { + printf("\n%s\t;", prefix); + } + printf("\n\n%s%s%s :\n%s\t", prefix, sym_prefix, sym_name, prefix); + } + if(production->length() > 0) { + for(int elm=0; elm < production->length(); ++elm) { + const GrammarSymbol *sym = production->symbol_by_position(elm); + if(production_continuation) { + production_continuation = false; + printf("\n%s\t| ", prefix); + } + else printf(" "); + ouptputTerminal(sym); + } + } + else { + if(production_continuation) { + production_continuation = false; + printf("\n%s\t| ", prefix); + } + printf("/*empty*/"); + } + if(production->precedence_symbol()) { + printf(" %%prec /*%d*/ ", production->precedence_symbol()->precedence()); + ouptputTerminal(production->precedence_symbol()); + } + last_production_symbol = curr_symbol; + } + if(last_production_symbol) + { + printf("\n%s\t;", prefix); + } + printf("\n\n// end YACC\n"); +} + void Grammar::genNakedGrammar() { printf( "%s {\n", identifier_.c_str()); diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index 4d1b096..7d5e633 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -69,6 +69,7 @@ class Grammar Grammar& identifier( const char* identifier, int line, int column ); bool is_case_insensitive() const {return active_case_insensitive_;} void genEBNF(); + void genYACC(); void genNakedGrammar(); private: diff --git a/src/lalr/GrammarCompiler.cpp b/src/lalr/GrammarCompiler.cpp index 51bf7df..1c30acd 100644 --- a/src/lalr/GrammarCompiler.cpp +++ b/src/lalr/GrammarCompiler.cpp @@ -73,7 +73,7 @@ void GrammarCompiler::labels_enabled( bool enabled ) labels_enabled_ = enabled; } -int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* error_policy, bool genEBNF ) +int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* error_policy, bool genEBNF, bool genYACC ) { Grammar grammar; @@ -87,6 +87,11 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e //grammar.genNakedGrammar(); return errors; } + if(genYACC) + { + grammar.genYACC(); + return errors; + } bool isCaseInsensitive = grammar.is_case_insensitive(); GrammarGenerator generator; errors = generator.generate( grammar, error_policy ); diff --git a/src/lalr/GrammarCompiler.hpp b/src/lalr/GrammarCompiler.hpp index 7920c3f..4324220 100644 --- a/src/lalr/GrammarCompiler.hpp +++ b/src/lalr/GrammarCompiler.hpp @@ -39,7 +39,7 @@ class GrammarCompiler const RegexCompiler* whitespace_lexer() const; const ParserStateMachine* parser_state_machine() const; void labels_enabled( bool enabled ); - int compile( const char* begin, const char* end, ErrorPolicy* error_policy = nullptr, bool genEBNF = false ); + int compile( const char* begin, const char* end, ErrorPolicy* error_policy = nullptr, bool genEBNF = false, bool genYACC = false ); void showStats(); private: From 208eda60fecf46eaced41ef62731d8b977478043 Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 18 Jul 2023 14:26:51 +0200 Subject: [PATCH 32/40] Fix to only match fully words, because before it was matching a substring like 'error' inside 'errors' --- src/lalr/GrammarParser.cpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index 25a66e9..152918c 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -94,7 +94,7 @@ bool GrammarParser::match_associativity_statement() bool GrammarParser::match_whitespace_statement() { - if ( match("%whitespace") ) + if ( match_word("%whitespace") ) { grammar_->whitespace(); if ( match_regex() ) @@ -109,7 +109,7 @@ bool GrammarParser::match_whitespace_statement() bool GrammarParser::match_case_insensitive_statement() { - if ( match("%case_insensitive") ) + if ( match_word("%case_insensitive") ) { grammar_->case_insensitive(); expect( ";" ); @@ -167,22 +167,22 @@ bool GrammarParser::match_symbol() bool GrammarParser::match_associativity() { - if ( match("%left") ) + if ( match_word("%left") ) { grammar_->left( line_ ); return true; } - else if ( match("%right") ) + else if ( match_word("%right") ) { grammar_->right( line_ ); return true; } - else if ( match("%none") || match("%nonassoc")) + else if ( match_word("%none") || match_word("%nonassoc")) { grammar_->none( line_ ); return true; } - else if ( match("%precedence") ) + else if ( match_word("%precedence") ) { grammar_->assoc_prec( line_ ); return true; @@ -209,7 +209,7 @@ bool GrammarParser::match_expression() bool GrammarParser::match_precedence() { - if ( match("%precedence") || match("%prec") ) + if ( match_word("%precedence") || match_word("%prec") ) { grammar_->precedence(); match_symbol(); @@ -235,7 +235,7 @@ bool GrammarParser::match_action() bool GrammarParser::match_error() { - return match( "error" ); + return match_word( "error" ); } bool GrammarParser::match_literal() @@ -408,6 +408,21 @@ bool GrammarParser::match( const char* keyword ) return match_without_skipping_whitespace( keyword ); } +bool GrammarParser::match_word( const char* keyword ) +{ + match_whitespace_and_comments(); + const char *saved_position = position_; + bool result = match_without_skipping_whitespace( keyword ); + //check for fully word match + if(result && position_ != end_ && (isalnum(*position_) || isdigit(*position_) || *position_ == '_')) + { + position_ = saved_position; + return false; + } + + return result; +} + bool GrammarParser::match_without_skipping_whitespace( const char* lexeme ) { const char* position = position_; From fc4077008378e9ac3a3722a366c3f7119929b9e4 Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 18 Jul 2023 18:02:53 +0200 Subject: [PATCH 33/40] Add a missing case when generating a YACC file --- src/lalr/Grammar.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index 701d55a..a184ce0 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -472,6 +472,9 @@ void Grammar::genYACC() case lalr::Associativity::ASSOCIATE_PREC: printf("\n%%precedence "); break; + case lalr::Associativity::ASSOCIATE_NULL: + printf("\n%%? "); + break; } last_prec = ip; printf(" /*%d*/ ", ip); From 08939baf5b60fd9b833c604cbd2d96822c2de209 Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 18 Jul 2023 18:06:09 +0200 Subject: [PATCH 34/40] Add the reducing transition as a parameter to action handlers, this way I can generate a better parse tree. --- playground/lalr_playground.cpp | 23 +++++++----- src/lalr/Parser.hpp | 2 +- src/lalr/Parser.ipp | 65 ++++++++++++++++++---------------- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp index adad8da..1c8bd71 100644 --- a/playground/lalr_playground.cpp +++ b/playground/lalr_playground.cpp @@ -71,7 +71,7 @@ int ParseTreeUserDataDbg::next_index = 0; int ParseTreeUserDataDbg::total = 0; -static bool parseTreeMakerDbg( ParseTreeUserDataDbg& result, const ParseTreeUserDataDbg* start, const lalr::ParserNode* nodes, size_t length ) +static bool parseTreeMakerDbg( ParseTreeUserDataDbg& result, const ParseTreeUserDataDbg* start, const lalr::ParserNode* nodes, size_t length, const lalr::ParserTransition* transition ) { switch_output("ast"); // //printf("astMaker: %s\n", nodes[0].lexeme().c_str()); @@ -84,11 +84,18 @@ static bool parseTreeMakerDbg( ParseTreeUserDataDbg& result, const ParseTreeUser // length ? start->index : -1, length ? start->stack_index : -1, // nodes, length, idstr, lexstr, line, column); printf("----\n"); - for(size_t i=0; i< length; ++i) - printf("%zd:%d\t%p\t%d:%d\t%p <:> %s <:> %s <:> %s <:> %d:%d\n", i, nodes[i].symbol()->type, - start+i, start[i].index, start[i].stack_index, nodes+i, - nodes[i].symbol()->identifier, nodes[i].symbol()->lexeme, - nodes[i].lexeme().c_str(), nodes[i].line(), nodes[i].column()); + if(length == 0) + { + printf("*:%d reducing empty %s : %s\n", transition->reduced_symbol->type, transition->reduced_symbol->identifier, transition->reduced_symbol->lexeme); + } + else + { + for(size_t i=0; i < length; ++i) + printf("%zd:%d\t%p\t%d:%d\t%p <:> %s <:> %s <:> %s <:> %d:%d\n", i, nodes[i].symbol()->type, + start+i, start[i].index, start[i].stack_index, nodes+i, + nodes[i].symbol()->identifier, nodes[i].symbol()->lexeme, + nodes[i].lexeme().c_str(), nodes[i].line(), nodes[i].column()); + } switch_output("parse_status"); return true; } @@ -102,10 +109,10 @@ struct ParseTreeUserData { }; -static bool parsetreeMaker( ParseTreeUserData& result, const ParseTreeUserData* start, const lalr::ParserNode* nodes, size_t length ) +static bool parsetreeMaker( ParseTreeUserData& result, const ParseTreeUserData* start, const lalr::ParserNode* nodes, size_t length, const lalr::ParserTransition* transition ) { if(length == 0) return false; - result.symbol = nodes[length-1].state()->transitions->reduced_symbol; + result.symbol = transition->reduced_symbol; for(size_t i_node = 0; i_node < length; ++i_node) { const lalr::ParserNode& the_node = nodes[i_node]; diff --git a/src/lalr/Parser.hpp b/src/lalr/Parser.hpp index 083f969..456aeb0 100644 --- a/src/lalr/Parser.hpp +++ b/src/lalr/Parser.hpp @@ -36,7 +36,7 @@ class Parser typedef lalr::ParserNode ParserNode; typedef typename std::vector::const_iterator ParserNodeConstIterator; typedef std::function (const PositionIterator& begin, const PositionIterator& end, std::basic_string* lexeme, const void** symbol)> LexerActionFunction; - typedef std::function ParserActionFunction; + typedef std::function ParserActionFunction; private: struct ParserActionHandler diff --git a/src/lalr/Parser.ipp b/src/lalr/Parser.ipp index d3798ca..a48c0c5 100644 --- a/src/lalr/Parser.ipp +++ b/src/lalr/Parser.ipp @@ -47,11 +47,11 @@ Parser::ParserActionHandler::Parser // Constructor. // // @param state_machine -// The state machine and actions that this %Parser will use (assumed not +// The state machine and actions that this %Parser will use (assumed not // null). // // @param error_policy -// The error policy to notify syntax errors and debug information to or null +// The error policy to notify syntax errors and debug information to or null // to silently swallow syntax errors and print debug information to stdout. // // @param lexer_error_policy @@ -72,7 +72,7 @@ Parser::Parser( const ParserStateMa , full_( false ) { LALR_ASSERT( state_machine_ ); - + action_handlers_.reserve( state_machine_->actions_size ); const ParserAction* action = state_machine_->actions; const ParserAction* actions_end = action + state_machine_->actions_size; @@ -82,10 +82,13 @@ Parser::Parser( const ParserStateMa ++action; } - nodes_.reserve( 64 ); - user_data_.reserve( 64 ); - nodes_.emplace_back( state_machine_->start_state, nullptr, 0, 1 ); - user_data_.emplace_back( ); + if ( state_machine_->start_state ) + { + nodes_.reserve( 64 ); + user_data_.reserve( 64 ); + nodes_.emplace_back( state_machine_->start_state, nullptr, 0, 1 ); + user_data_.emplace_back( ); + } } /** @@ -125,11 +128,11 @@ bool Parser::full() const template bool Parser::valid() const { - return lexer_.valid(); + return state_machine_ && state_machine_->start_state && lexer_.valid(); } /** -// Get the user data that resulted from the most recent call to +// Get the user data that resulted from the most recent call to // Parser::parser() on this %Parser. // // Assumes that the most recent parse was accepted. @@ -295,20 +298,20 @@ void Parser::set_default_action_han // The identifier of the action handler to set the function for. // // @param function -// The function to set the action handler to or null to set the action +// The function to set the action handler to or null to set the action // handler to have no function. */ template void Parser::set_action_handler( const char* identifier, ParserActionFunction function ) { LALR_ASSERT( identifier ); - + typename std::vector::iterator action_handler = action_handlers_.begin(); while ( action_handler != action_handlers_.end() && strcmp(action_handler->action_->identifier, identifier) != 0 ) { ++action_handler; } - + if ( action_handler != action_handlers_.end() ) { action_handler->function_ = function; @@ -322,7 +325,7 @@ void Parser::set_action_handler( co // The identifier of the action handler to set the function for. // // @param function -// The function to set the action handler to or null to set the action +// The function to set the action handler to or null to set the action // handler to have no function. */ template @@ -336,7 +339,7 @@ void Parser::set_lexer_action_handl // Set whether or not shift operations are printed. // // @param debug_enabled -// True to cause any shift or reduce operations to be printed or false to +// True to cause any shift or reduce operations to be printed or false to // suppress this behaviour. */ template @@ -362,7 +365,7 @@ void Parser::reset() /** // Parse [\e start, \e finish). // -// After the parse the Parser::full() and Parser::accepted() functions can +// After the parse the Parser::full() and Parser::accepted() functions can // be used to determine whether or not the parse was successful and whether // or not it consumed all of the available input. // @@ -382,7 +385,7 @@ void Parser::parse( Iterator start, if ( valid() ) { reset(); - lexer_.reset( start, finish ); + lexer_.reset( start, finish ); lexer_.advance(); const ParserSymbol* symbol = reinterpret_cast( lexer_.symbol() ); while ( parse(symbol, lexer_.lexeme(), lexer_.line(), lexer_.column()) ) @@ -438,14 +441,14 @@ bool Parser::parse( const ParserSym { bool accepted = false; bool rejected = false; - + const ParserTransition* transition = find_transition( symbol, nodes_.back().state() ); while ( !accepted && !rejected && transition && transition->reduced_symbol ) { reduce( transition, &accepted, &rejected ); transition = find_transition( symbol, nodes_.back().state() ); } - + if ( transition && transition->state ) { shift( transition, lexeme, line, column ); @@ -454,7 +457,7 @@ bool Parser::parse( const ParserSym { error( &accepted, &rejected, line, column); } - + accepted_ = accepted; return !accepted_ && !rejected; } @@ -562,7 +565,7 @@ void Parser::debug_reduce( const Pa fire_printf( "(%s %s %d:%d)", symbol ? symbol->identifier : "", lexeme.c_str(), line, column ); ++node; } - + while ( node != node_end ) { const ParserSymbol* symbol = node->symbol(); @@ -572,7 +575,7 @@ void Parser::debug_reduce( const Pa fire_printf( " (%s %s %d:%d)", symbol ? symbol->identifier : "", lexeme.c_str(), line, column ); ++node; } - + fire_printf( "\n" ); } } @@ -610,16 +613,16 @@ bool Parser::handle(UserData& resul int action = transition->action; if ( action != ParserAction::INVALID_INDEX ) { - LALR_ASSERT( action >= 0 && action < static_cast(action_handlers_.size()) ); + LALR_ASSERT( action >= 0 && action < static_cast(action_handlers_.size()) ); if ( action_handlers_[action].function_ ) { - return action_handlers_[action].function_( result, user_data, nodes, length ); + return action_handlers_[action].function_( result, user_data, nodes, length, transition ); } } if ( default_action_handler_ ) { - return default_action_handler_( result, user_data, nodes, length ); + return default_action_handler_( result, user_data, nodes, length, transition ); } return false; @@ -668,7 +671,7 @@ std::string Parser::expected_symbol // The lexeme of the token that is being shifted onto the stack. // // @param line -// The line number at the start of the token that is being shifted onto the +// The line number at the start of the token that is being shifted onto the // stack (assumed >= 0). */ template @@ -701,7 +704,7 @@ void Parser::reduce( const ParserTr LALR_ASSERT( state_machine_ ); LALR_ASSERT( transition ); LALR_ASSERT( accepted ); - + const ParserSymbol* symbol = transition->reduced_symbol; if ( symbol != state_machine_->start_symbol ) { @@ -722,20 +725,20 @@ void Parser::reduce( const ParserTr user_data_.emplace_back( user_data ); } else - { + { LALR_ASSERT( nodes_.size() == 2 ); LALR_ASSERT( user_data_.size() == 2 ); nodes_.erase( nodes_.begin() ); user_data_.erase( user_data_.begin() ); *accepted = true; - } + } } /** // Handle an error. // // Pops states from the stack until the 'error' token can be shifted and then -// shifts the error token. Any transitions that call for a reduce on the +// shifts the error token. Any transitions that call for a reduce on the // 'error' token are taken. // // @param accepted @@ -771,7 +774,7 @@ void Parser::error( bool* accepted, else { LALR_ASSERT( transition->reduced_symbol ); - reduce( transition, accepted, rejected ); + reduce( transition, accepted, rejected ); } } else @@ -780,7 +783,7 @@ void Parser::error( bool* accepted, user_data_.pop_back(); } } - + if ( nodes_.empty() ) { if ( symbol ) From ee28902cbe1c4a23aab86cacc456026c99cabdf8 Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 18 Jul 2023 18:25:54 +0200 Subject: [PATCH 35/40] Update examples to use the extra action handler parameter recently introduced --- src/lalr/AddParserActionHandler.hpp | 3 ++- src/lalr/GrammarParser.hpp | 1 + .../lalr_examples/lalr_calculator_example.cpp | 12 ++++++------ .../lalr_examples/lalr_hello_world_example.cpp | 2 +- src/lalr/lalr_examples/lalr_xml_example.cpp | 16 ++++++++-------- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/lalr/AddParserActionHandler.hpp b/src/lalr/AddParserActionHandler.hpp index 669c489..4b74daa 100644 --- a/src/lalr/AddParserActionHandler.hpp +++ b/src/lalr/AddParserActionHandler.hpp @@ -2,6 +2,7 @@ #define LALR_ADDPARSERACTIONHANDLER_HPP_INCLUDED #include "ParserNode.hpp" +#include "ParserTransition.hpp" #include namespace lalr @@ -16,7 +17,7 @@ template class AddParserActionHandler { - typedef std::function* nodes, size_t length)> ParserActionFunction; + typedef std::function* nodes, size_t length, const ParserTransition *transition)> ParserActionFunction; Parser* parser_; ///< The Parser to add handlers to. public: diff --git a/src/lalr/GrammarParser.hpp b/src/lalr/GrammarParser.hpp index cb27217..b76f8ee 100644 --- a/src/lalr/GrammarParser.hpp +++ b/src/lalr/GrammarParser.hpp @@ -50,6 +50,7 @@ class GrammarParser bool match_block_comment(); bool match_end(); bool match( const char* lexeme ); + bool match_word( const char* lexeme ); bool match_without_skipping_whitespace( const char* lexeme ); bool expect( const char* lexeme ); void error(int line, int column, int error, const char* format, ... ); diff --git a/src/lalr/lalr_examples/lalr_calculator_example.cpp b/src/lalr/lalr_examples/lalr_calculator_example.cpp index d2de376..bf0fbf4 100644 --- a/src/lalr/lalr_examples/lalr_calculator_example.cpp +++ b/src/lalr/lalr_examples/lalr_calculator_example.cpp @@ -32,37 +32,37 @@ void lalr_calculator_example() compiler.compile( calculator_grammar, calculator_grammar + strlen(calculator_grammar) ); Parser parser( compiler.parser_state_machine() ); parser.parser_action_handlers() - ( "add", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) + ( "add", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length, const ParserTransition */*transition*/ ) { result = data[0] + data[2]; return true; } ) - ( "subtract", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) + ( "subtract", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length, const ParserTransition */*transition*/ ) { result = data[0] - data[2]; return true; } ) - ( "multiply", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) + ( "multiply", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length, const ParserTransition */*transition*/ ) { result = data[0] * data[2]; return true; } ) - ( "divide", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) + ( "divide", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length, const ParserTransition */*transition*/ ) { result = data[0] / data[2]; return true; } ) - ( "compound", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) + ( "compound", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length, const ParserTransition */*transition*/ ) { result = data[1]; return true; } ) - ( "integer", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length ) + ( "integer", [] ( int &result, const int* data, const ParserNode<>* nodes, size_t length, const ParserTransition */*transition*/ ) { result = ::atoi( nodes[0].lexeme().c_str() ); return true; diff --git a/src/lalr/lalr_examples/lalr_hello_world_example.cpp b/src/lalr/lalr_examples/lalr_hello_world_example.cpp index 657c22e..9987432 100644 --- a/src/lalr/lalr_examples/lalr_hello_world_example.cpp +++ b/src/lalr/lalr_examples/lalr_hello_world_example.cpp @@ -22,7 +22,7 @@ void lalr_hello_world_example() parser.parser_action_handlers() ( "hello_world", [] (shared_ptr>& result, const shared_ptr>* data, - const ParserNode<>* nodes, size_t length) + const ParserNode<>* nodes, size_t length, const ParserTransition */*transition*/) { printf( "Hello World!\n" ); return true; diff --git a/src/lalr/lalr_examples/lalr_xml_example.cpp b/src/lalr/lalr_examples/lalr_xml_example.cpp index 30c2b6a..7b209f0 100644 --- a/src/lalr/lalr_examples/lalr_xml_example.cpp +++ b/src/lalr/lalr_examples/lalr_xml_example.cpp @@ -64,7 +64,7 @@ struct XmlUserData } }; -static bool document( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool document( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length, const ParserTransition */*transition*/ ) { const XmlUserData* end = start + length; while ( start != end && !start[0].element_ ) @@ -79,7 +79,7 @@ static bool document( XmlUserData& result, const XmlUserData* start, const Parse return false; } -static bool add_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool add_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length, const ParserTransition */*transition*/ ) { shared_ptr element = start[0].element_; element->elements_.push_back( start[1].element_ ); @@ -87,7 +87,7 @@ static bool add_element( XmlUserData& result, const XmlUserData* start, const Pa return true; } -static bool create_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool create_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length, const ParserTransition */*transition*/ ) { shared_ptr element( new Element() ); element->elements_.push_back( start[0].element_ ); @@ -95,7 +95,7 @@ static bool create_element( XmlUserData& result, const XmlUserData* start, const return true; } -static bool short_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool short_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length, const ParserTransition */*transition*/ ) { shared_ptr element = start[2].element_; element->name_ = nodes[1].lexeme(); @@ -103,7 +103,7 @@ static bool short_element( XmlUserData& result, const XmlUserData* start, const return true; } -static bool long_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool long_element( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length, const ParserTransition */*transition*/ ) { shared_ptr element = start[2].element_; if ( !element ) @@ -120,7 +120,7 @@ static bool long_element( XmlUserData& result, const XmlUserData* start, const P return true; } -static bool add_attribute( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool add_attribute( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length, const ParserTransition */*transition*/ ) { LALR_ASSERT( start[0].element_ ); shared_ptr element = start[0].element_; @@ -130,7 +130,7 @@ static bool add_attribute( XmlUserData& result, const XmlUserData* start, const return true; } -static bool create_attribute( XmlUserData &result, const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool create_attribute( XmlUserData &result, const XmlUserData* start, const ParserNode* nodes, size_t length, const ParserTransition */*transition*/ ) { LALR_ASSERT( start[0].attribute_ ); shared_ptr element( new Element() ); @@ -139,7 +139,7 @@ static bool create_attribute( XmlUserData &result, const XmlUserData* start, con return true; } -static bool attribute( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length ) +static bool attribute( XmlUserData& result, const XmlUserData* start, const ParserNode* nodes, size_t length, const ParserTransition */*transition*/ ) { shared_ptr attribute( new Attribute(nodes[0].lexeme(), nodes[2].lexeme()) ); result.attribute_ = attribute; From f5c1810a75a1785accb032eead46199ff5a8608f Mon Sep 17 00:00:00 2001 From: mingodad Date: Wed, 19 Jul 2023 18:32:36 +0200 Subject: [PATCH 36/40] Add 2 new grammar options to easy debug, also fix line counting when the line end is multi character like of '\r\n' --- src/lalr/Grammar.cpp | 14 ++++++++++++++ src/lalr/Grammar.hpp | 6 ++++++ src/lalr/GrammarParser.cpp | 36 ++++++++++++++++++++++++++++++++---- src/lalr/GrammarParser.hpp | 1 + 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/lalr/Grammar.cpp b/src/lalr/Grammar.cpp index a184ce0..18e5a41 100644 --- a/src/lalr/Grammar.cpp +++ b/src/lalr/Grammar.cpp @@ -31,6 +31,8 @@ Grammar::Grammar() , active_whitespace_directive_( false ) , active_precedence_directive_( false ) , active_case_insensitive_(false) +, error_recovery_off_(false) +, error_recovery_show_(false) , associativity_( ASSOCIATE_NULL ) , precedence_( 0 ) , active_production_( nullptr ) @@ -116,6 +118,18 @@ Grammar& Grammar::case_insensitive() return *this; } +Grammar& Grammar::error_recovery_off() +{ + error_recovery_off_ = true; + return *this; +} + +Grammar& Grammar::error_recovery_show() +{ + error_recovery_show_ = true; + return *this; +} + Grammar& Grammar::precedence() { LALR_ASSERT( active_symbol_ ); diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index 7d5e633..bcde285 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -30,6 +30,8 @@ class Grammar bool active_whitespace_directive_; ///< True iff a whitespace directive is active. bool active_precedence_directive_; ///< True iff a precedence directive is active. bool active_case_insensitive_; ///< True iff a case insensitive directive is active. + bool error_recovery_off_; ///< True iff we want to turn off error recovery for debug. + bool error_recovery_show_; ///< True iff we want to show error recovery for debug. Associativity associativity_; ///< Most recently set associativity. int precedence_; ///< Current precedence. GrammarProduction* active_production_; ///< Currently active production. @@ -58,6 +60,8 @@ class Grammar Grammar& assoc_prec( int line ); Grammar& whitespace(); Grammar& case_insensitive(); + Grammar& error_recovery_off(); + Grammar& error_recovery_show(); Grammar& precedence(); Grammar& production( const char* identifier, int line, int column ); Grammar& end_production(); @@ -68,6 +72,8 @@ class Grammar Grammar& regex( const char* regex, int line, int column ); Grammar& identifier( const char* identifier, int line, int column ); bool is_case_insensitive() const {return active_case_insensitive_;} + bool is_error_recovery_off() const {return error_recovery_off_;} + bool is_error_recovery_show() const {return error_recovery_show_;} void genEBNF(); void genYACC(); void genNakedGrammar(); diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index 152918c..dd05c47 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -77,6 +77,7 @@ bool GrammarParser::match_statement() match_associativity_statement() || match_whitespace_statement() || match_case_insensitive_statement() || + match_error_recovery_debug_statement() || match_production_statement() ; } @@ -118,6 +119,24 @@ bool GrammarParser::match_case_insensitive_statement() return false; } +bool GrammarParser::match_error_recovery_debug_statement() +{ + bool rc = false; + if ( match_word("%error_recovery_off") ) + { + grammar_->error_recovery_off(); + expect( ";" ); + rc = true; + } + else if ( match_word("%error_recovery_show") ) + { + grammar_->error_recovery_show(); + expect( ";" ); + rc = true; + } + return rc; +} + bool GrammarParser::match_production_statement() { if ( match_identifier() ) @@ -338,10 +357,9 @@ bool GrammarParser::match_whitespace() { if ( is_new_line(position) ) { - ++line_; - line_position_ = position; + position = new_line( position ); } - ++position; + else ++position; } position_ = position; return true; @@ -369,6 +387,7 @@ bool GrammarParser::match_block_comment() if ( match_without_skipping_whitespace("/*") ) { bool done = false; + int nested = 1; const char* position = position_; while ( position != end_ && !done ) { @@ -377,7 +396,7 @@ bool GrammarParser::match_block_comment() ++position; if ( position != end_ && *position == '/' ) { - done = true; + if(--nested == 0) done = true; ++position; } } @@ -385,6 +404,15 @@ bool GrammarParser::match_block_comment() { position = new_line( position ); } + else if ( *position == '/' ) + { + ++position; + if ( position != end_ && *position == '*' ) + { + ++nested; + ++position; + } + } else { ++position; diff --git a/src/lalr/GrammarParser.hpp b/src/lalr/GrammarParser.hpp index b76f8ee..46d9a50 100644 --- a/src/lalr/GrammarParser.hpp +++ b/src/lalr/GrammarParser.hpp @@ -32,6 +32,7 @@ class GrammarParser bool match_associativity_statement(); bool match_whitespace_statement(); bool match_case_insensitive_statement(); + bool match_error_recovery_debug_statement(); bool match_production_statement(); bool match_symbols(); bool match_symbol(); From 6f73f32d391e52c2ce303f7ef4f47f9b01920190 Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 14 Nov 2023 14:58:24 +0100 Subject: [PATCH 37/40] Add code to detect user content changes and alert him/her --- playground/index.html | 34 ++--- playground/index.js | 327 ++++++++++++++---------------------------- 2 files changed, 117 insertions(+), 244 deletions(-) diff --git a/playground/index.html b/playground/index.html index 0098ee8..850eb7d 100644 --- a/playground/index.html +++ b/playground/index.html @@ -4,7 +4,8 @@ LALR Playground - + +
      @@ -15,30 +16,6 @@
    @@ -53,14 +30,21 @@
  • Input source
    • +
    • +
  • diff --git a/playground/index.js b/playground/index.js index b0827b2..2100cb3 100644 --- a/playground/index.js +++ b/playground/index.js @@ -19,232 +19,96 @@ function setupEditorArea(id, lsKey) { return e; } +let userContentHasChanged = false; +let grammarContentHasChanged = false; +let inputContentHasChanged = false; +function grammarOnChange(delta) { + if(!grammarContentHasChanged) { + grammarContentHasChanged = true; + userContentHasChanged = true; + } +} +function inputOnChange(delta) { + if(!inputContentHasChanged) { + inputContentHasChanged = true; + userContentHasChanged = true; + } +} + const grammarEditor = setupEditorArea("grammar-editor", "grammarText"); +grammarEditor.on("change", grammarOnChange); grammarEditor.getSession().setMode("ace/mode/yaml"); const codeEditor = setupEditorArea("code-editor", "codeText"); +codeEditor.on("change", inputOnChange); +userContentHasChanged = localStorage.getItem("userContentHasChanged"); const codeAst = setupInfoArea("code-ast"); const codeLexer = setupInfoArea("code-lexer"); +const sampleList = [ + //title, grammar, input, input ace syntax + ["XML parser", "xml.g", "test.xml.txt", "ace/mode/xml"], + ["LALR parser", "lalr.g", "lalr.g", "ace/mode/yaml"], + ["Calculator error handling parser", "error_handling_calculator.g", "error_handling_calculator.txt", "ace/mode/text"], + ["Json parser", "json3.g", "test.json.txt", "ace/mode/json"], + ["Json5 parser", "json5.g", "test.json5.txt", "ace/mode/json"], + ["Lua parser", "lua.g", "test.lua", "ace/mode/lua"], + ["JavascriptCore parser", "javascript-core.g", "test.js.txt", "ace/mode/javascript"], + ["Carbon parser", "carbon-lang.g", "prelude.carbon", "ace/mode/typescript"], + ["Linden Script parser", "lsl_ext.g", "test.lsl", "ace/mode/text"], + ["Ansi C parser", "cparser.g", "test.c", "ace/mode/c_cpp"], + ["Ispc parser", "ispc.g", "test.ispc", "ace/mode/c_cpp"], + ["Java11 parser", "java11.g", "test.java", "ace/mode/java"], + ["Rust parser", "rust.g", "test.rs", "ace/mode/rust"], + ["CQL parser (be patient)", "cql.g", "test.cql", "ace/mode/sql"], + ["Postgresql parser (be patient)", "postgresql-16.g", "test.sql", "ace/mode/sql"], + ["Postgresql parser case insensitive (be patient)", "postgresql-16-nc.g", "test.sql", "ace/mode/sql"], + ["Gringo/Clingo non grounded parser", "gringo-ng.g", "test.clingo", "ace/mode/text"], + ["Ada parser", "ada-adayacc.g", "test.adb", "ace/mode/ada"], + ["Ada parser case insensitive", "ada-adayacc-n.g", "test.adb", "ace/mode/ada"], + ["Textmapper parser", "textmapper.g", "test.tm", "ace/mode/yaml"], + ["C++ parser (bug)", "cxx-parser.g", "test.cpp", "ace/mode/c_cpp"], + ["Bison parser (not working)", "bison.g", "carbon-lang.y", "ace/mode/yaml"], + ["DParser parser (not working)", "dparser.g", "test.dparser", "ace/mode/yaml"], + ["Parse_gen parser (not working)", "parse_gen.g", "test.parse_gen", "ace/mode/yaml"], + ["Tameparse parser (not working)", "tameparser.g", "test.tameparser", "ace/mode/yaml"], + ["Javascript parser (not working)", "javascript.g", "test.js.txt", "ace/mode/javascript"], + ["Go parser (not working)", "go.g", "test.go", "ace/mode/golang"], + ["PHP-8.2 parser (not working)", "php-8.2.g", "test.php", "ace/mode/php"], + ["BC calculator parser", "bc.g", "test.bc", "ace/mode/text"], + ["CFront3 parser (notworking)", "cfront3.g", "test.cpp", "ace/mode/c_cpp"], + ["C++98 parser (notworking)", "cpp-98-parser.g", "test.cpp", "ace/mode/c_cpp"], + ["Cyclone parser (notworking)", "cyclone.g", "test.c", "ace/mode/c_cpp"], + ["Cobalt CSS parser (notworking)", "cobalt-css.g", "style.css", "ace/mode/css"], + ["Flex parser (notworking)", "flex-parser.g", "test.flex", "ace/mode/yaml"], + ["Frege parser (notworking)", "frege-parser.g", "test.c", "ace/mode/c_cpp"], + ["GHC parser (notworking)", "ghc-parser.g", "test.c", "ace/mode/c_cpp"], + ["Graphql-ruby parser (be patient)", "graphql-ruby.g", "test.cql", "ace/mode/sql"], + ["HTML parser (be patient)", "html-parser.g", "index.html", "ace/mode/html"], + ["HTTPD parser (be patient)", "httpd-parser.g", "index.html", "ace/mode/html"], + ["IVerilog parser (be patient)", "iverilog-parser.g", "test.vl", "ace/mode/verilog"], +]; + function loadLalr_sample(self) { + if(userContentHasChanged) + { + let ok = confirm("Your changes will be lost !\nIf the changes you've made are important save then before proceed.\nCopy and paste to your prefered editor and save it.\nEither OK or Cancel."); + if(!ok) return false; + } let base_url = "./" - switch(self.options[self.selectedIndex].value) { - case "Json parser": - $.get(base_url + "json3.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.json.txt", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/json"); - }); - break; - case "Lua parser": - $.get(base_url + "lua.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.lua", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/lua"); - }); - break; - case "Carbon parser": - $.get(base_url + "carbon-lang.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "prelude.carbon", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/typescript"); - }); - break; - case "Postgresql parser (be patient)": - $.get(base_url + "postgresql-16.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.sql", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/sql"); - }); - break; - case "Postgresql parser case insensitive (be patient)": - $.get(base_url + "postgresql-16-nc.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.sql", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/sql"); - }); - break; - case "C++ parser (bug)": - $.get(base_url + "cxx-parser.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.cpp", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/c_cpp"); - }); - break; - case "Linden Script parser": - $.get(base_url + "lsl_ext.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.lsl", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/text"); - }); - break; - case "LALR parser (not working)": - $.get(base_url + "lalr.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "lalr.g", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/yaml"); - }); - break; - case "Bison parser (not working)": - $.get(base_url + "bison.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "carbon-lang.y", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/yaml"); - }); - break; - case "DParser parser (not working)": - $.get(base_url + "dparser.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.dparser", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/yaml"); - }); - break; - case "Parse_gen parser (not working)": - $.get(base_url + "parse_gen.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.parse_gen", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/yaml"); - }); - break; - case "Tameparse parser (not working)": - $.get(base_url + "tameparser.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.tameparser", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/yaml"); - }); - break; - case "Javascript parser (not working)": - $.get(base_url + "javascript.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.js.txt", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/javascript"); - }); - break; - case "JavascriptCore parser": - $.get(base_url + "javascript-core.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.js.txt", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/javascript"); - }); - break; - case "Ansi C parser": - $.get(base_url + "cparser.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.c", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/c_cpp"); - }); - break; - case "Ispc parser": - $.get(base_url + "ispc.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.ispc", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/c_cpp"); - }); - break; - case "Java11 parser": - $.get(base_url + "java11.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.java", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/java"); - }); - break; - case "Rust parser": - $.get(base_url + "rust.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.rs", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/rust"); - }); - break; - case "Go parser (not working)": - $.get(base_url + "go.g", function( data ) { + if(self.selectedIndex > 0) { + let sample_to_use = sampleList[self.selectedIndex-1]; + $.get(base_url + sample_to_use[1], function( data ) { grammarEditor.setValue( data ); + grammarContentHasChanged = false; + userContentHasChanged = false; }); - $.get(base_url + "test.go", function( data ) { + $.get(base_url + sample_to_use[2], function( data ) { codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/golang"); - }); - break; - case "PHP-8.2 parser (not working)": - $.get(base_url + "php-8.2.g", function( data ) { - grammarEditor.setValue( data ); + codeEditor.getSession().setMode(sample_to_use[3]); + inputContentHasChanged = false; + userContentHasChanged = false; }); - $.get(base_url + "test.php", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/php"); - }); - break; - case "Gringo/Clingo non grounded parser": - $.get(base_url + "gringo-ng.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.clingo", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/text"); - }); - break; - case "Ada parser": - $.get(base_url + "ada-adayacc.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.adb", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/ada"); - }); - break; - case "Ada parser case insensitive": - $.get(base_url + "ada-adayacc-nc.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.adb", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/ada"); - }); - break; - case "XML parser": - $.get(base_url + "xml.g", function( data ) { - grammarEditor.setValue( data ); - }); - $.get(base_url + "test.xml.txt", function( data ) { - codeEditor.setValue( data ); - codeEditor.getSession().setMode("ace/mode/xml"); - }); - break; } } @@ -271,7 +135,7 @@ function textToErrors(str) { var regExp = /([^\n]+?)\n/g, match; while (match = regExp.exec(str)) { let msg = match[1]; - let line_col = msg.match(/^lalr \((\d+):(\d+)\):/); + let line_col = msg.match(/lalr \((\d+):(\d+)\):/); if (line_col) { errors.push({"ln": line_col[1], "col":line_col[2], "msg": msg}); } else { @@ -299,10 +163,16 @@ function generateErrorListHTML(errors) { } function updateLocalStorage() { - localStorage.setItem('grammarText', grammarEditor.getValue()); - localStorage.setItem('codeText', codeEditor.getValue()); + if(grammarContentHasChanged || inputContentHasChanged) + { + localStorage.setItem('grammarText', grammarEditor.getValue()); + localStorage.setItem('codeText', codeEditor.getValue()); + grammarContentHasChanged = false; + inputContentHasChanged = false; + localStorage.setItem('userContentHasChanged', userContentHasChanged); + } //localStorage.setItem('optimizationMode', $('#opt-mode').val()); - localStorage.setItem('autoRefresh', $('#auto-refresh').prop('checked')); + //localStorage.setItem('autoRefresh', $('#auto-refresh').prop('checked')); } var parse_start_time = 0; @@ -319,6 +189,7 @@ function parse() { const astMode = $('#ast-mode').val(); const generate_ebnf = $('#generate-action').val() == 'ebnf'; const generate_yacc = $('#generate-action').val() == 'yacc'; + const generate_yacc_html = $('#generate-action').val() == 'yacc_html'; const lexer = $('#show-lexer').prop('checked'); let generate_ast = $('#show-ast').prop('checked'); if(generate_ast && astMode == 2) @@ -350,7 +221,7 @@ function parse() { window.setTimeout(() => { parse_start_time = new Date().getTime(); - lalr_parse(grammarText, codeText, lexer, generate_ebnf, generate_yacc, generate_ast); + lalr_parse(grammarText, codeText, lexer, generate_ebnf, generate_yacc, generate_yacc_html, generate_ast); $('#overlay').css({ 'z-index': '-1', @@ -371,7 +242,15 @@ function parse() { } if(isGenEBNF) { - $grammarInfo.html("
    " + escapeHtml(outputs.compile_status.replaceAll("'\\''", '"\'"')) + "
    "); + //if(generate_yacc_html) + //{ + // const win = window.open('', 'Yacc_HTML_linked'); + // win.document.write(outputs.compile_status); + // win.document.close(); + // win.focus(); + //} + //else + $grammarInfo.html("
    " + escapeHtml(outputs.compile_status.replaceAll("'\\''", '"\'"')) + "
    "); return; } @@ -526,4 +405,14 @@ var Module = { }, }; +function doFinalSettings() { + let select_samples = document.getElementById('opt-samples'); + sampleList.map( (lang, i) => { + let opt = document.createElement("option"); + opt.value = i; // the index + opt.innerHTML = lang[0]; + select_samples.append(opt); + }); +} + // vim: sw=2:sts=2 From 02946cc1430abca344c9c8ff893f4d0726bfb0bb Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 14 Nov 2023 15:16:26 +0100 Subject: [PATCH 38/40] Added grammar examples --- playground/ada-adayacc-nc.g | 1178 ++++ playground/ada-adayacc.g | 1176 ++++ playground/bc.g | 276 + playground/bison.g | 338 ++ playground/carbon-lang.g | 870 +++ playground/carbon-lang.y | 737 +++ playground/cfront3.g | 808 +++ playground/cobalt-css-parser.g | 2650 +++++++++ playground/cparser.g | 513 ++ playground/cpp-98-parser.g | 752 +++ playground/cql.g | 1664 ++++++ playground/cxx-parser.g | 1254 +++++ playground/cyclone.g | 1539 +++++ playground/dparser.g | 297 + playground/error_handling_calculator.g | 23 + playground/error_handling_calculator.txt | 1 + playground/flex-parser.g | 343 ++ playground/frege-parser.g | 939 ++++ playground/ghc-parser.g | 2406 ++++++++ playground/go.g | 762 +++ playground/graphql-ruby.g | 537 ++ playground/gringo-ng.g | 745 +++ playground/html-parser.g | 1149 ++++ playground/httpd-parser.g | 456 ++ playground/ispc.g | 1011 ++++ playground/iverilog-parser.g | 2922 ++++++++++ playground/java11.g | 682 +++ playground/javascript-core.g | 1149 ++++ playground/jscript-parser.g | 708 +++ playground/json3.g | 61 + playground/json5.g | 127 + playground/lalr.g | 119 + playground/lsl_ext.g | 415 ++ playground/lua.g | 372 ++ playground/php-8.2.g | 1440 +++++ playground/postgresql-16-nc.g | 6487 ++++++++++++++++++++++ playground/postgresql-16.g | 6485 +++++++++++++++++++++ playground/prelude.carbon | 736 +++ playground/rust.g | 1858 +++++++ playground/tameparser.g | 404 ++ playground/test.adb | 125 + playground/test.bc | 53 + playground/test.c | 112 + playground/test.clingo | 35 + playground/test.cpp | 209 + playground/test.cql | 2558 +++++++++ playground/test.flex | 58 + playground/test.go | 2712 +++++++++ playground/test.ispc | 24 + playground/test.java | 466 ++ playground/test.js.txt | 195 + playground/test.json.txt | 162 + playground/test.json5.txt | 12 + playground/test.lsl | 711 +++ playground/test.lua | 87 + playground/test.parse_gen | 271 + playground/test.php | 422 ++ playground/test.rs | 188 + playground/test.sql | 2430 ++++++++ playground/test.tameparser | 221 + playground/test.tm | 501 ++ playground/test.vl | 114 + playground/test.xml.txt | 6 + playground/textmapper.g | 764 +++ playground/xml.g | 13 + 65 files changed, 58838 insertions(+) create mode 100644 playground/ada-adayacc-nc.g create mode 100644 playground/ada-adayacc.g create mode 100644 playground/bc.g create mode 100644 playground/bison.g create mode 100644 playground/carbon-lang.g create mode 100644 playground/carbon-lang.y create mode 100644 playground/cfront3.g create mode 100644 playground/cobalt-css-parser.g create mode 100644 playground/cparser.g create mode 100644 playground/cpp-98-parser.g create mode 100644 playground/cql.g create mode 100644 playground/cxx-parser.g create mode 100644 playground/cyclone.g create mode 100644 playground/dparser.g create mode 100644 playground/error_handling_calculator.g create mode 100644 playground/error_handling_calculator.txt create mode 100644 playground/flex-parser.g create mode 100644 playground/frege-parser.g create mode 100644 playground/ghc-parser.g create mode 100644 playground/go.g create mode 100644 playground/graphql-ruby.g create mode 100644 playground/gringo-ng.g create mode 100644 playground/html-parser.g create mode 100644 playground/httpd-parser.g create mode 100644 playground/ispc.g create mode 100644 playground/iverilog-parser.g create mode 100644 playground/java11.g create mode 100644 playground/javascript-core.g create mode 100644 playground/jscript-parser.g create mode 100644 playground/json3.g create mode 100644 playground/json5.g create mode 100644 playground/lalr.g create mode 100644 playground/lsl_ext.g create mode 100644 playground/lua.g create mode 100644 playground/php-8.2.g create mode 100644 playground/postgresql-16-nc.g create mode 100644 playground/postgresql-16.g create mode 100644 playground/prelude.carbon create mode 100644 playground/rust.g create mode 100644 playground/tameparser.g create mode 100644 playground/test.adb create mode 100644 playground/test.bc create mode 100644 playground/test.c create mode 100644 playground/test.clingo create mode 100644 playground/test.cpp create mode 100644 playground/test.cql create mode 100644 playground/test.flex create mode 100644 playground/test.go create mode 100644 playground/test.ispc create mode 100644 playground/test.java create mode 100644 playground/test.js.txt create mode 100644 playground/test.json.txt create mode 100644 playground/test.json5.txt create mode 100644 playground/test.lsl create mode 100644 playground/test.lua create mode 100644 playground/test.parse_gen create mode 100644 playground/test.php create mode 100644 playground/test.rs create mode 100644 playground/test.sql create mode 100644 playground/test.tameparser create mode 100644 playground/test.tm create mode 100644 playground/test.vl create mode 100644 playground/test.xml.txt create mode 100644 playground/textmapper.g create mode 100644 playground/xml.g diff --git a/playground/ada-adayacc-nc.g b/playground/ada-adayacc-nc.g new file mode 100644 index 0000000..56e5481 --- /dev/null +++ b/playground/ada-adayacc-nc.g @@ -0,0 +1,1178 @@ +//From: https://github.com/Ada-France/ayacc/blob/master/examples/ada_parser/ada.y + +ada_adayacc { + +%whitespace "([ \t\r\n]*)|(\-\-[^\n]*)"; + +%case_insensitive ; + +//%token '&' +//%token '\'' +//%token '(' +//%token ')' +//%token '*' +//%token '+' +//%token ',' +//%token '-' +//%token '.' +//%token '/' +//%token ':' +//%token ';' +//%token '<' +//%token '=' +//%token '>' +//%token '|' +//%token '!' +//%token ARROW +//%token DOUBLE_DOT +//%token DOUBLE_STAR +//%token ASSIGNMENT +//%token INEQUALITY +//%token GREATER_THAN_OR_EQUAL +//%token LESS_THAN_OR_EQUAL +//%token LEFT_LABEL_BRACKET +//%token RIGHT_LABEL_BRACKET +//%token BOX +//%token ABORT_TOKEN +//%token ABS_TOKEN +//%token ACCEPT_TOKEN +//%token ACCESS_TOKEN +//%token ALL_TOKEN +//%token AND_TOKEN +//%token ARRAY_TOKEN +//%token AT_TOKEN +//%token BEGIN_TOKEN +//%token BODY_TOKEN +//%token CASE_TOKEN +//%token CONSTANT_TOKEN +//%token DECLARE_TOKEN +//%token DELAY_TOKEN +//%token DELTA_TOKEN +//%token DIGITS_TOKEN +//%token DO_TOKEN +//%token ELSE_TOKEN +//%token ELSIF_TOKEN +//%token END_TOKEN +//%token ENTRY_TOKEN +//%token EXCEPTION_TOKEN +//%token EXIT_TOKEN +//%token FOR_TOKEN +//%token FUNCTION_TOKEN +//%token GENERIC_TOKEN +//%token GOTO_TOKEN +//%token IF_TOKEN +//%token IN_TOKEN +//%token IS_TOKEN +//%token LIMITED_TOKEN +//%token LOOP_TOKEN +//%token MOD_TOKEN +//%token NEW_TOKEN +//%token NOT_TOKEN +//%token NULL_TOKEN +//%token OF_TOKEN +//%token OR_TOKEN +//%token OTHERS_TOKEN +//%token OUT_TOKEN +//%token PACKAGE_TOKEN +//%token PRAGMA_TOKEN +//%token PRIVATE_TOKEN +//%token PROCEDURE_TOKEN +//%token RAISE_TOKEN +//%token RANGE_TOKEN +//%token RECORD_TOKEN +//%token REM_TOKEN +//%token RENAMES_TOKEN +//%token RETURN_TOKEN +//%token REVERSE_TOKEN +//%token SELECT_TOKEN +//%token SEPARATE_TOKEN +//%token SUBTYPE_TOKEN +//%token TASK_TOKEN +//%token TERMINATE_TOKEN +//%token THEN_TOKEN +//%token TYPE_TOKEN +//%token USE_TOKEN +//%token WHEN_TOKEN +//%token WHILE_TOKEN +//%token WITH_TOKEN +//%token XOR_TOKEN +//%token IDENTIFIER +//%token INTEGER_LITERAL +//%token REAL_LITERAL +//%token CHARACTER_LITERAL +//%token STRING_LITERAL +//%token ERROR1 +//%token ERROR2 +//%token ERROR3 +//%token ERROR4 +//%token ERROR5 +//%token ERROR6 +//%token ERROR7 +//%token ERROR8 +//%token ERROR9 +//%token ERROR10 +//%token ERROR11 +//%token ERROR12 +//%token ERROR13 +//%token ERROR14 +//%token ERROR15 + + +//%start compilation + +//%% + +compilation : + __compilation_unit__ + ; + + +prag : + PRAGMA_TOKEN IDENTIFIER _arg_ascs ';' + ; +arg_asc : + expr + | IDENTIFIER ARROW expr + ; +numeric_literal : + REAL_LITERAL + | INTEGER_LITERAL + ; +basic_d : + object_d + | ty_d + | subty_d + | subprg_d + | pkg_d + | task_d + | gen_d + | excptn_d + | gen_inst + | renaming_d + | number_d + | error ';' + ; +object_d : + idents ':' subty_ind __ASN_expr_ ';' + | idents ':' CONSTANT_TOKEN subty_ind __ASN_expr_ ';' + | idents ':' c_arr_def __ASN_expr_ ';' + | idents ':' CONSTANT_TOKEN c_arr_def __ASN_expr_ ';' + ; +number_d : + idents ':' CONSTANT_TOKEN ASSIGNMENT expr ';' + ; +idents : + IDENTIFIER ___ident__ + ; +ty_d : + full_ty_d + | incomplete_ty_d + | priv_ty_d + ; +full_ty_d : + TYPE_TOKEN IDENTIFIER IS_TOKEN ty_def ';' + | TYPE_TOKEN IDENTIFIER discr_part IS_TOKEN ty_def ';' + ; +ty_def : + enum_ty_def + | integer_ty_def + | real_ty_def + | array_ty_def + | rec_ty_def + | access_ty_def + | derived_ty_def + ; +subty_d : + SUBTYPE_TOKEN IDENTIFIER IS_TOKEN subty_ind ';' + ; +subty_ind : + ty_mk _constrt_ + ; +ty_mk : + expanded_n + ; +constrt : + rng_c + | fltg_point_c + | fixed_point_c + | aggr + ; +derived_ty_def : + NEW_TOKEN subty_ind + ; +rng_c : + RANGE_TOKEN rng + ; +rng : + name + | sim_expr DOUBLE_DOT sim_expr + ; +enum_ty_def : + '(' enum_lit_spec ___enum_lit_spec__ ')' + ; +enum_lit_spec : + enum_lit + ; +enum_lit : + IDENTIFIER + | CHARACTER_LITERAL + ; +integer_ty_def : + rng_c + ; +real_ty_def : + fltg_point_c + | fixed_point_c + ; +fltg_point_c : + fltg_accuracy_def _rng_c_ + ; +fltg_accuracy_def : + DIGITS_TOKEN sim_expr + ; +fixed_point_c : + fixed_accuracy_def _rng_c_ + ; +fixed_accuracy_def : + DELTA_TOKEN sim_expr + ; +array_ty_def : + uncnstrnd_array_def + | c_arr_def + ; +uncnstrnd_array_def : + ARRAY_TOKEN '(' idx_subty_def ___idx_subty_def__ ')' OF_TOKEN subty_ind + ; +c_arr_def : + ARRAY_TOKEN idx_c OF_TOKEN subty_ind + ; +idx_subty_def : + name RANGE_TOKEN BOX + ; +idx_c : + '(' dscr_rng ___dscr_rng__ ')' + ; +dscr_rng : + rng + | name rng_c + ; +rec_ty_def : + RECORD_TOKEN cmpons END_TOKEN RECORD_TOKEN + ; +cmpons : + __prag__ __cmpon_d__ cmpon_d __prag__ + | __prag__ __cmpon_d__ variant_part __prag__ + | __prag__ NULL_TOKEN ';' __prag__ + ; +cmpon_d : + idents ':' cmpon_subty_def __ASN_expr_ ';' + ; +cmpon_subty_def : + subty_ind + ; +discr_part : + '(' discr_spec ___discr_spec__ ')' + ; +discr_spec : + idents ':' ty_mk __ASN_expr_ + ; +variant_part : + CASE_TOKEN sim_n IS_TOKEN __prag__ variant __variant__ END_TOKEN CASE_TOKEN ';' + ; +variant : + WHEN_TOKEN choice __or_choice__ ARROW cmpons + ; +paramchoice : + sim_expr + | name rng_c + | sim_expr DOUBLE_DOT sim_expr + | OTHERS_TOKEN + | error + ; +choice : + sim_expr + | name rng_c + | sim_expr DOUBLE_DOT sim_expr + | OTHERS_TOKEN + | error + ; +access_ty_def : + ACCESS_TOKEN subty_ind + ; +incomplete_ty_d : + TYPE_TOKEN IDENTIFIER ';' + | TYPE_TOKEN IDENTIFIER discr_part ';' + ; +decl_part : + __basic_decl_item__ + | __basic_decl_item__ body __later_decl_item__ + ; +basic_decl_item : + basic_d + | rep_cl + | use_cl + ; +later_decl_item : + body + | subprg_d + | pkg_d + | task_d + | gen_d + | use_cl + | gen_inst + ; +body : + proper_body + | body_stub + ; +proper_body : + subprg_body + | pkg_body + | task_body + ; +name : + sim_n + | CHARACTER_LITERAL + | op_symbol + | idxed_cmpon + | selected_cmpon + | attribute + ; +sim_n : + IDENTIFIER + ; +prefix : + name + ; +idxed_cmpon : + prefix aggr + ; +selected_cmpon : + prefix '.' selector + ; +selector : + sim_n + | CHARACTER_LITERAL + | op_symbol + | ALL_TOKEN + ; +attribute : + prefix '\'' attribute_designator + ; +attribute_designator : + sim_n + | DIGITS_TOKEN + | DELTA_TOKEN + | RANGE_TOKEN + ; +aggr : + '(' cmpon_asc ___cmpon_asc__ ')' + ; +cmpon_asc : + expr + | paramchoice __or_paramchoice__ ARROW expr + | sim_expr DOUBLE_DOT sim_expr + | name rng_c + ; +expr : + rel__AND__rel__ + | rel__AND__THEN__rel__ + | rel__OR__rel__ + | rel__OR__ELSE__rel__ + | rel__XOR__rel__ + | xrel + ; +xrel : + sim_expr _relal_op__sim_expr_ + | sim_expr_NOT_IN__rng_or_sim_expr_NOT_IN__ty_mk + ; +rel : + sim_expr _relal_op__sim_expr_ + | sim_expr_NOT_IN__rng_or_sim_expr_NOT_IN__ty_mk + ; +sim_expr : + _unary_add_op_term__binary_add_op__term__ + ; +term : + factor__mult_op__factor__ + ; +factor : + pri __EXP___pri_ + | ABS_TOKEN pri + | NOT_TOKEN '(' expr ')' + | NOT_TOKEN qualified_expr + | NOT_TOKEN name + ; +pri : + numeric_literal + | NULL_TOKEN + | allocator + | qualified_expr + | name + | aggr + ; +relal_op : + '=' + | INEQUALITY + | '<' + | LESS_THAN_OR_EQUAL + | '>' + | GREATER_THAN_OR_EQUAL + ; +binary_add_op : + '+' + | '-' + | '&' + ; +unary_add_op : + '+' + | '-' + ; +mult_op : + '*' + | '/' + | MOD_TOKEN + | REM_TOKEN + ; +qualified_expr : + ty_mkaggr_or_ty_mkPexprP_ + ; +allocator : + NEW_TOKEN ty_mk + | NEW_TOKEN ty_mk aggr + | NEW_TOKEN ty_mk '\'' aggr + ; +seq_of_stmts : + __prag__ stmt __stmt__ + ; +stmt : + __label__ sim_stmt + | __label__ compound_stmt + | error ';' + ; +sim_stmt : + null_stmt + | assignment_stmt + | exit_stmt + | return_stmt + | goto_stmt + | delay_stmt + | abort_stmt + | raise_stmt + | code_stmt + | name ';' + ; +compound_stmt : + if_stmt + | case_stmt + | loop_stmt + | block_stmt + | accept_stmt + | select_stmt + ; +label : + LEFT_LABEL_BRACKET sim_n RIGHT_LABEL_BRACKET + ; +null_stmt : + NULL_TOKEN ';' + ; +assignment_stmt : + name ASSIGNMENT expr ';' + ; +if_stmt : + IF_TOKEN cond THEN_TOKEN seq_of_stmts __ELSIF__cond__THEN__seq_of_stmts__ _ELSE__seq_of_stmts_ END_TOKEN IF_TOKEN ';' + ; +cond : + expr + ; +case_stmt : + CASE_TOKEN expr IS_TOKEN case_stmt_alt__case_stmt_alt__ END_TOKEN CASE_TOKEN ';' + ; +case_stmt_alt : + WHEN_TOKEN choice __or_choice__ ARROW seq_of_stmts + ; +loop_stmt : + _sim_nC_ _iteration_scheme_ LOOP_TOKEN seq_of_stmts END_TOKEN LOOP_TOKEN _sim_n_ ';' + ; +type_of_while : + cond + | error + ; +type_of_for : + loop_prm_spec + | error + ; +iteration_scheme : + WHILE_TOKEN type_of_while + | FOR_TOKEN type_of_for + ; +loop_prm_spec : + IDENTIFIER IN_TOKEN _REVERSE_ dscr_rng + ; +block_stmt : + _sim_nC_ _DECLARE__decl_part_ BEGIN_TOKEN seq_of_stmts _EXCEPTION__excptn_handler__excptn_handler___ END_TOKEN _sim_n_ ';' + ; +exit_stmt : + EXIT_TOKEN _expanded_n_ _WHEN__cond_ ';' + ; +return_stmt : + RETURN_TOKEN _expr_ ';' + ; +goto_stmt : + GOTO_TOKEN expanded_n ';' + ; +subprg_d : + subprg_spec ';' + ; +subprg_spec : + PROCEDURE_TOKEN IDENTIFIER _fml_part_ + | FUNCTION_TOKEN designator _fml_part_ RETURN_TOKEN ty_mk + ; +designator : + IDENTIFIER + | op_symbol + ; +op_symbol : + STRING_LITERAL + ; +fml_part : + '(' prm_spec ____prm_spec__ ')' + ; +prm_spec : + idents ':' mode ty_mk __ASN_expr_ + ; +mode : + _IN_ + | IN_TOKEN OUT_TOKEN + | OUT_TOKEN + ; +subprg_body : + subprg_spec IS_TOKEN _decl_part_ BEGIN_TOKEN seq_of_stmts _EXCEPTION__excptn_handler__excptn_handler___ END_TOKEN _designator_ ';' + ; +pkg_d : + pkg_spec ';' + ; +pkg_spec : + PACKAGE_TOKEN IDENTIFIER IS_TOKEN __basic_decl_item__ _PRIVATE__basic_decl_item___ END_TOKEN _sim_n_ + ; +pkg_body : + PACKAGE_TOKEN BODY_TOKEN sim_n IS_TOKEN _decl_part_ _BEGIN__seq_of_stmts_EXCEPTION__excptn_handler__excptn_handler___ END_TOKEN _sim_n_ ';' + ; +priv_ty_d : + TYPE_TOKEN IDENTIFIER IS_TOKEN _LIMITED_ PRIVATE_TOKEN ';' + | TYPE_TOKEN IDENTIFIER discr_part IS_TOKEN _LIMITED_ PRIVATE_TOKEN ';' + ; +use_cl : + USE_TOKEN expanded_n ___expanded_n__ ';' + ; +renaming_d : + idents ':' ty_mk RENAMES_TOKEN name ';' + | idents ':' EXCEPTION_TOKEN RENAMES_TOKEN expanded_n ';' + | PACKAGE_TOKEN IDENTIFIER RENAMES_TOKEN expanded_n ';' + | subprg_spec RENAMES_TOKEN name ';' + ; +task_d : + task_spec ';' + ; +task_spec : + TASK_TOKEN _TYPE_ IDENTIFIER _IS__ent_d___rep_cl_END_sim_n_ + ; +task_body : + TASK_TOKEN BODY_TOKEN sim_n IS_TOKEN _decl_part_ BEGIN_TOKEN seq_of_stmts _EXCEPTION__excptn_handler__excptn_handler___ END_TOKEN _sim_n_ ';' + ; +ent_d : + ENTRY_TOKEN IDENTIFIER _fml_part_ ';' + | ENTRY_TOKEN IDENTIFIER '(' dscr_rng ')' _fml_part_ ';' + ; +ent_call_stmt : + __prag__ name ';' + ; +accept_stmt : + ACCEPT_TOKEN sim_n _Pent_idx_P__fml_part_ _DO__seq_of_stmts__END_sim_n__ ';' + ; +ent_idx : + expr + ; +delay_stmt : + DELAY_TOKEN sim_expr ';' + ; +select_stmt : + selec_wait + | condal_ent_call + | timed_ent_call + ; +selec_wait : + SELECT_TOKEN select_alt __OR__select_alt__ _ELSE__seq_of_stmts_ END_TOKEN SELECT_TOKEN ';' + ; +select_alt : + _WHEN__condARROW_selec_wait_alt + ; +selec_wait_alt : + accept_alt + | delay_alt + | terminate_alt + ; +accept_alt : + accept_stmt_seq_of_stmts_ + ; +delay_alt : + delay_stmt_seq_of_stmts_ + ; +terminate_alt : + TERM_stmt + ; +condal_ent_call : + SELECT_TOKEN ent_call_stmt _seq_of_stmts_ ELSE_TOKEN seq_of_stmts END_TOKEN SELECT_TOKEN ';' + ; +timed_ent_call : + SELECT_TOKEN ent_call_stmt _seq_of_stmts_ OR_TOKEN delay_alt END_TOKEN SELECT_TOKEN ';' + ; +abort_stmt : + ABORT_TOKEN name ___name__ ';' + ; +compilation_unit : + context_cl library_unit + | context_cl secondary_unit + ; +library_unit : + subprg_d + | pkg_d + | gen_d + | gen_inst + | subprg_body + ; +secondary_unit : + library_unit_body + | subunit + ; +library_unit_body : + pkg_body_or_subprg_body + ; +context_cl : + __with_cl__use_cl____ + ; +with_cl : + WITH_TOKEN sim_n ___sim_n__ ';' + ; +body_stub : + subprg_spec IS_TOKEN SEPARATE_TOKEN ';' + | PACKAGE_TOKEN BODY_TOKEN sim_n IS_TOKEN SEPARATE_TOKEN ';' + | TASK_TOKEN BODY_TOKEN sim_n IS_TOKEN SEPARATE_TOKEN ';' + ; +subunit : + SEPARATE_TOKEN '(' expanded_n ')' proper_body + ; +excptn_d : + idents ':' EXCEPTION_TOKEN ';' + ; +excptn_handler : + WHEN_TOKEN excptn_choice __or_excptn_choice__ ARROW seq_of_stmts + ; +excptn_choice : + expanded_n + | OTHERS_TOKEN + ; +raise_stmt : + RAISE_TOKEN _expanded_n_ ';' + ; +gen_d : + gen_spec ';' + ; +gen_spec : + gen_fml_part subprg_spec + | gen_fml_part pkg_spec + ; +gen_fml_part : + GENERIC_TOKEN __gen_prm_d__ + ; +gen_prm_d : + idents ':' _IN_OUT__ ty_mk __ASN_expr_ ';' + | TYPE_TOKEN IDENTIFIER IS_TOKEN gen_ty_def ';' + | priv_ty_d + | WITH_TOKEN subprg_spec _IS_BOX__ ';' + ; +gen_ty_def : + '(' BOX ')' + | RANGE_TOKEN BOX + | DIGITS_TOKEN BOX + | DELTA_TOKEN BOX + | array_ty_def + | access_ty_def + ; +gen_inst : + PACKAGE_TOKEN IDENTIFIER IS_TOKEN NEW_TOKEN expanded_n _gen_act_part_ ';' + | PROCEDURE__ident__IS_ NEW_TOKEN expanded_n _gen_act_part_ ';' + | FUNCTION_TOKEN designator IS_TOKEN NEW_TOKEN expanded_n _gen_act_part_ ';' + ; +gen_act_part : + '(' gen_asc ___gen_asc__ ')' + ; +gen_asc : + _gen_fml_prmARROW_gen_act_prm + ; +gen_fml_prm : + sim_n + | op_symbol + ; +gen_act_prm : + expr_or_name_or_subprg_n_or_ent_n_or_ty_mk + ; +rep_cl : + ty_rep_cl + | address_cl + ; +ty_rep_cl : + length_cl + | enum_rep_cl + | rec_rep_cl + ; +length_cl : + FOR_TOKEN attribute USE_TOKEN sim_expr ';' + ; +enum_rep_cl : + FOR__ty_sim_n__USE_ aggr ';' + ; +rec_rep_cl : + FOR__ty_sim_n__USE_ RECORD_TOKEN _algt_cl_ __cmpon_cl__ END_TOKEN RECORD_TOKEN ';' + ; +algt_cl : + AT_TOKEN MOD_TOKEN sim_expr ';' + ; +cmpon_cl : + name AT_TOKEN sim_expr RANGE_TOKEN rng ';' + ; +address_cl : + FOR_TOKEN sim_n USE_TOKEN AT_TOKEN sim_expr ';' + ; +code_stmt : + ty_mk_rec_aggr ';' + ; +__prag__ : + /*empty*/ + | __prag__ prag + ; +_arg_ascs : + /*empty*/ + | '(' arg_ascs ')' + ; +arg_ascs : + arg_asc + | arg_ascs ',' arg_asc + ; +__ASN_expr_ : + /*empty*/ + | ASSIGNMENT expr + ; +___ident__ : + /*empty*/ + | ___ident__ ',' IDENTIFIER + ; +_constrt_ : + /*empty*/ + | constrt + ; +expanded_n : + IDENTIFIER + | expanded_n '.' IDENTIFIER + ; +___enum_lit_spec__ : + /*empty*/ + | ___enum_lit_spec__ ',' enum_lit_spec + ; +_rng_c_ : + /*empty*/ + | rng_c + ; +___idx_subty_def__ : + /*empty*/ + | ___idx_subty_def__ ',' idx_subty_def + ; +___dscr_rng__ : + /*empty*/ + | ___dscr_rng__ ',' dscr_rng + ; +__cmpon_d__ : + /*empty*/ + | __cmpon_d__ cmpon_d __prag__ + ; +___discr_spec__ : + /*empty*/ + | ___discr_spec__ ';' discr_spec + ; +__variant__ : + /*empty*/ + | __variant__ variant + ; +__or_choice__ : + /*empty*/ + | __or_choice__ '|' choice + | __or_choice__ '!' choice + ; +__or_paramchoice__ : + /*empty*/ + | __or_paramchoice__ '|' paramchoice + | __or_paramchoice__ '!' paramchoice + ; +__basic_decl_item__ : + __prag__ + | __basic_decl_item__ basic_decl_item __prag__ + ; +__later_decl_item__ : + __prag__ + | __later_decl_item__ later_decl_item __prag__ + ; +___cmpon_asc__ : + /*empty*/ + | ___cmpon_asc__ ',' cmpon_asc + ; +rel__AND__rel__ : + rel AND_TOKEN rel + | rel__AND__rel__ AND_TOKEN rel + ; +rel__OR__rel__ : + rel OR_TOKEN rel + | rel__OR__rel__ OR_TOKEN rel + ; +rel__XOR__rel__ : + rel XOR_TOKEN rel + | rel__XOR__rel__ XOR_TOKEN rel + ; +rel__AND__THEN__rel__ : + rel AND_TOKEN THEN_TOKEN rel + | rel__AND__THEN__rel__ AND_TOKEN THEN_TOKEN rel + ; +rel__OR__ELSE__rel__ : + rel OR_TOKEN ELSE_TOKEN rel + | rel__OR__ELSE__rel__ OR_TOKEN ELSE_TOKEN rel + ; +_relal_op__sim_expr_ : + /*empty*/ + | relal_op sim_expr + ; +sim_expr_NOT_IN__rng_or_sim_expr_NOT_IN__ty_mk : + sim_expr _NOT_ IN_TOKEN rng + ; +_NOT_ : + /*empty*/ + | NOT_TOKEN + ; +_unary_add_op_term__binary_add_op__term__ : + term + | unary_add_op term + | _unary_add_op_term__binary_add_op__term__ binary_add_op term + ; +factor__mult_op__factor__ : + factor + | factor__mult_op__factor__ mult_op factor + ; +__EXP___pri_ : + /*empty*/ + | DOUBLE_STAR pri + ; +ty_mkaggr_or_ty_mkPexprP_ : + prefix '\'' aggr + ; +__stmt__ : + __prag__ + | __stmt__ stmt __prag__ + ; +__label__ : + /*empty*/ + | __label__ label + ; +__ELSIF__cond__THEN__seq_of_stmts__ : + /*empty*/ + | __ELSIF__cond__THEN__seq_of_stmts__ ELSIF_TOKEN cond THEN_TOKEN seq_of_stmts + ; +_ELSE__seq_of_stmts_ : + /*empty*/ + | ELSE_TOKEN seq_of_stmts + ; +case_stmt_alt__case_stmt_alt__ : + __prag__ case_stmt_alt __case_stmt_alt__ + ; +__case_stmt_alt__ : + /*empty*/ + | __case_stmt_alt__ case_stmt_alt + ; +_sim_nC_ : + /*empty*/ + | sim_n ':' + ; +_sim_n_ : + /*empty*/ + | sim_n + ; +_iteration_scheme_ : + /*empty*/ + | iteration_scheme + ; +_REVERSE_ : + /*empty*/ + | REVERSE_TOKEN + ; +_DECLARE__decl_part_ : + /*empty*/ + | DECLARE_TOKEN decl_part + ; +_EXCEPTION__excptn_handler__excptn_handler___ : + /*empty*/ + | EXCEPTION_TOKEN __prag__ excptn_handlers + ; +excptn_handlers : + excptn_handler + | excptn_handlers excptn_handler + ; +_expanded_n_ : + /*empty*/ + | expanded_n + ; +_WHEN__cond_ : + /*empty*/ + | WHEN_TOKEN cond + ; +_expr_ : + /*empty*/ + | expr + ; +_fml_part_ : + /*empty*/ + | fml_part + ; +____prm_spec__ : + /*empty*/ + | ____prm_spec__ ';' prm_spec + ; +_IN_ : + /*empty*/ + | IN_TOKEN + ; +_decl_part_ : + decl_part + ; +_designator_ : + /*empty*/ + | designator + ; +_PRIVATE__basic_decl_item___ : + /*empty*/ + | PRIVATE_TOKEN __basic_decl_item__ + ; +_BEGIN__seq_of_stmts_EXCEPTION__excptn_handler__excptn_handler___ : + /*empty*/ + | BEGIN_TOKEN seq_of_stmts _EXCEPTION__excptn_handler__excptn_handler___ + ; +_LIMITED_ : + /*empty*/ + | LIMITED_TOKEN + ; +___expanded_n__ : + /*empty*/ + | ___expanded_n__ ',' expanded_n + ; +_TYPE_ : + /*empty*/ + | TYPE_TOKEN + ; +_IS__ent_d___rep_cl_END_sim_n_ : + /*empty*/ + | IS_TOKEN __ent_d__ __rep_cl__ END_TOKEN _sim_n_ + ; +__ent_d__ : + __prag__ + | __ent_d__ ent_d __prag__ + ; +__rep_cl__ : + /*empty*/ + | __rep_cl__ rep_cl __prag__ + ; +_Pent_idx_P__fml_part_ : + _fml_part_ + | '(' ent_idx ')' _fml_part_ + ; +_DO__seq_of_stmts__END_sim_n__ : + /*empty*/ + | DO_TOKEN seq_of_stmts END_TOKEN _sim_n_ + ; +__OR__select_alt__ : + /*empty*/ + | __OR__select_alt__ OR_TOKEN select_alt + ; +_WHEN__condARROW_selec_wait_alt : + selec_wait_alt + | WHEN_TOKEN cond ARROW selec_wait_alt + ; +accept_stmt_seq_of_stmts_ : + __prag__ accept_stmt _seq_of_stmts_ + ; +delay_stmt_seq_of_stmts_ : + __prag__ delay_stmt _seq_of_stmts_ + ; +TERM_stmt : + __prag__ TERMINATE_TOKEN ';' __prag__ + ; +_seq_of_stmts_ : + __prag__ + | seq_of_stmts + ; +___name__ : + /*empty*/ + | ___name__ ',' name + ; +__compilation_unit__ : + __prag__ + | __compilation_unit__ compilation_unit __prag__ + ; +pkg_body_or_subprg_body : + pkg_body + ; +__with_cl__use_cl____ : + /*empty*/ + | __with_cl__use_cl____ with_cl use_cls + ; +use_cls : + __prag__ + | use_cls use_cl __prag__ + ; +___sim_n__ : + /*empty*/ + | ___sim_n__ ',' sim_n + ; +__or_excptn_choice__ : + /*empty*/ + | __or_excptn_choice__ '|' excptn_choice + | __or_excptn_choice__ '!' excptn_choice + ; +__gen_prm_d__ : + /*empty*/ + | __gen_prm_d__ gen_prm_d + ; +_IN_OUT__ : + _IN_ + | IN_TOKEN OUT_TOKEN + ; +_IS_BOX__ : + /*empty*/ + | IS_TOKEN name + | IS_TOKEN BOX + ; +PROCEDURE__ident__IS_ : + subprg_spec IS_TOKEN + ; +_gen_act_part_ : + /*empty*/ + | gen_act_part + ; +___gen_asc__ : + /*empty*/ + | ___gen_asc__ ',' gen_asc + ; +_gen_fml_prmARROW_gen_act_prm : + gen_act_prm + | gen_fml_prm ARROW gen_act_prm + ; +expr_or_name_or_subprg_n_or_ent_n_or_ty_mk : + expr + ; +FOR__ty_sim_n__USE_ : + FOR_TOKEN sim_n USE_TOKEN + ; +_algt_cl_ : + __prag__ + | __prag__ algt_cl __prag__ + ; +__cmpon_cl__ : + /*empty*/ + | __cmpon_cl__ cmpon_cl __prag__ + ; +ty_mk_rec_aggr : + qualified_expr + ; + +//Lexer + +// \({\S+\)\s+{ECHO_L; ENTER(Z); return(\([^)]+\));} +ABORT_TOKEN : 'abort' ; +ABS_TOKEN : 'abs' ; +ACCEPT_TOKEN : 'accept' ; +ACCESS_TOKEN : 'access' ; +ALL_TOKEN : 'all' ; +AND_TOKEN : 'and' ; +ARRAY_TOKEN : 'array' ; +AT_TOKEN : 'at' ; +BEGIN_TOKEN : 'begin' ; +BODY_TOKEN : 'body' ; +CASE_TOKEN : 'case' ; +CONSTANT_TOKEN : 'constant' ; +DECLARE_TOKEN : 'declare' ; +DELAY_TOKEN : 'delay' ; +DELTA_TOKEN : 'delta' ; +DIGITS_TOKEN : 'digits' ; +DO_TOKEN : 'do' ; +ELSE_TOKEN : 'else' ; +ELSIF_TOKEN : 'elsif' ; +END_TOKEN : 'end' ; +ENTRY_TOKEN : 'entry' ; +EXCEPTION_TOKEN : 'exception' ; +EXIT_TOKEN : 'exit' ; +FOR_TOKEN : 'for' ; +FUNCTION_TOKEN : 'function' ; +GENERIC_TOKEN : 'generic' ; +GOTO_TOKEN : 'goto' ; +IF_TOKEN : 'if' ; +IN_TOKEN : 'in' ; +IS_TOKEN : 'is' ; +LIMITED_TOKEN : 'limited' ; +LOOP_TOKEN : 'loop' ; +MOD_TOKEN : 'mod' ; +NEW_TOKEN : 'new' ; +NOT_TOKEN : 'not' ; +NULL_TOKEN : 'null' ; +OF_TOKEN : 'of' ; +OR_TOKEN : 'or' ; +OTHERS_TOKEN : 'others' ; +OUT_TOKEN : 'out' ; +PACKAGE_TOKEN : 'package' ; +PRAGMA_TOKEN : 'pragma' ; +PRIVATE_TOKEN : 'private' ; +PROCEDURE_TOKEN : 'procedure' ; +RAISE_TOKEN : 'raise' ; +RANGE_TOKEN : 'range' ; +RECORD_TOKEN : 'record' ; +REM_TOKEN : 'rem' ; +RENAMES_TOKEN : 'renames' ; +RETURN_TOKEN : 'return' ; +REVERSE_TOKEN : 'reverse' ; +SELECT_TOKEN : 'select' ; +SEPARATE_TOKEN : 'separate' ; +SUBTYPE_TOKEN : 'subtype' ; +TASK_TOKEN : 'task' ; +TERMINATE_TOKEN : 'terminate' ; +THEN_TOKEN : 'then' ; +TYPE_TOKEN : 'type' ; +USE_TOKEN : 'use' ; +WHEN_TOKEN : 'when' ; +WHILE_TOKEN : 'while' ; +WITH_TOKEN : 'with' ; +XOR_TOKEN : 'xor' ; + + //-- Match all the compound Ada delimiters. See Ada LRM 2.2. + +ARROW : '=>' ; +DOUBLE_DOT : '..' ; +DOUBLE_STAR : '**' ; +ASSIGNMENT : ':=' ; +INEQUALITY : '/=' ; +GREATER_THAN_OR_EQUAL : '>=' ; +LESS_THAN_OR_EQUAL : '<=' ; +LEFT_LABEL_BRACKET : '<<' ; +RIGHT_LABEL_BRACKET : '>>' ; +BOX : '<>' ; + +IDENTIFIER : "[a-zA-Z]([_]?[a-zA-Z0-9])*" ; +REAL_LITERAL : "([0-9]+\.[0-9]*|\.[0-9]+)([Ee](\+|\-)?[0-9]+)?" ; +INTEGER_LITERAL : "[0-9]+" ; +CHARACTER_LITERAL : "'(\\.|[^'])[']" ; +STRING_LITERAL : "\"(\\.|[^\"\n])*\"" ; + +} \ No newline at end of file diff --git a/playground/ada-adayacc.g b/playground/ada-adayacc.g new file mode 100644 index 0000000..224970a --- /dev/null +++ b/playground/ada-adayacc.g @@ -0,0 +1,1176 @@ +//From: https://github.com/Ada-France/ayacc/blob/master/examples/ada_parser/ada.y + +ada_adayacc { + +%whitespace "([ \t\r\n]*)|(\-\-[^\n]*)"; + +//%token '&' +//%token '\'' +//%token '(' +//%token ')' +//%token '*' +//%token '+' +//%token ',' +//%token '-' +//%token '.' +//%token '/' +//%token ':' +//%token ';' +//%token '<' +//%token '=' +//%token '>' +//%token '|' +//%token '!' +//%token ARROW +//%token DOUBLE_DOT +//%token DOUBLE_STAR +//%token ASSIGNMENT +//%token INEQUALITY +//%token GREATER_THAN_OR_EQUAL +//%token LESS_THAN_OR_EQUAL +//%token LEFT_LABEL_BRACKET +//%token RIGHT_LABEL_BRACKET +//%token BOX +//%token ABORT_TOKEN +//%token ABS_TOKEN +//%token ACCEPT_TOKEN +//%token ACCESS_TOKEN +//%token ALL_TOKEN +//%token AND_TOKEN +//%token ARRAY_TOKEN +//%token AT_TOKEN +//%token BEGIN_TOKEN +//%token BODY_TOKEN +//%token CASE_TOKEN +//%token CONSTANT_TOKEN +//%token DECLARE_TOKEN +//%token DELAY_TOKEN +//%token DELTA_TOKEN +//%token DIGITS_TOKEN +//%token DO_TOKEN +//%token ELSE_TOKEN +//%token ELSIF_TOKEN +//%token END_TOKEN +//%token ENTRY_TOKEN +//%token EXCEPTION_TOKEN +//%token EXIT_TOKEN +//%token FOR_TOKEN +//%token FUNCTION_TOKEN +//%token GENERIC_TOKEN +//%token GOTO_TOKEN +//%token IF_TOKEN +//%token IN_TOKEN +//%token IS_TOKEN +//%token LIMITED_TOKEN +//%token LOOP_TOKEN +//%token MOD_TOKEN +//%token NEW_TOKEN +//%token NOT_TOKEN +//%token NULL_TOKEN +//%token OF_TOKEN +//%token OR_TOKEN +//%token OTHERS_TOKEN +//%token OUT_TOKEN +//%token PACKAGE_TOKEN +//%token PRAGMA_TOKEN +//%token PRIVATE_TOKEN +//%token PROCEDURE_TOKEN +//%token RAISE_TOKEN +//%token RANGE_TOKEN +//%token RECORD_TOKEN +//%token REM_TOKEN +//%token RENAMES_TOKEN +//%token RETURN_TOKEN +//%token REVERSE_TOKEN +//%token SELECT_TOKEN +//%token SEPARATE_TOKEN +//%token SUBTYPE_TOKEN +//%token TASK_TOKEN +//%token TERMINATE_TOKEN +//%token THEN_TOKEN +//%token TYPE_TOKEN +//%token USE_TOKEN +//%token WHEN_TOKEN +//%token WHILE_TOKEN +//%token WITH_TOKEN +//%token XOR_TOKEN +//%token IDENTIFIER +//%token INTEGER_LITERAL +//%token REAL_LITERAL +//%token CHARACTER_LITERAL +//%token STRING_LITERAL +//%token ERROR1 +//%token ERROR2 +//%token ERROR3 +//%token ERROR4 +//%token ERROR5 +//%token ERROR6 +//%token ERROR7 +//%token ERROR8 +//%token ERROR9 +//%token ERROR10 +//%token ERROR11 +//%token ERROR12 +//%token ERROR13 +//%token ERROR14 +//%token ERROR15 + + +//%start compilation + +//%% + +compilation : + __compilation_unit__ + ; + + +prag : + PRAGMA_TOKEN IDENTIFIER _arg_ascs ';' + ; +arg_asc : + expr + | IDENTIFIER ARROW expr + ; +numeric_literal : + REAL_LITERAL + | INTEGER_LITERAL + ; +basic_d : + object_d + | ty_d + | subty_d + | subprg_d + | pkg_d + | task_d + | gen_d + | excptn_d + | gen_inst + | renaming_d + | number_d + | error ';' + ; +object_d : + idents ':' subty_ind __ASN_expr_ ';' + | idents ':' CONSTANT_TOKEN subty_ind __ASN_expr_ ';' + | idents ':' c_arr_def __ASN_expr_ ';' + | idents ':' CONSTANT_TOKEN c_arr_def __ASN_expr_ ';' + ; +number_d : + idents ':' CONSTANT_TOKEN ASSIGNMENT expr ';' + ; +idents : + IDENTIFIER ___ident__ + ; +ty_d : + full_ty_d + | incomplete_ty_d + | priv_ty_d + ; +full_ty_d : + TYPE_TOKEN IDENTIFIER IS_TOKEN ty_def ';' + | TYPE_TOKEN IDENTIFIER discr_part IS_TOKEN ty_def ';' + ; +ty_def : + enum_ty_def + | integer_ty_def + | real_ty_def + | array_ty_def + | rec_ty_def + | access_ty_def + | derived_ty_def + ; +subty_d : + SUBTYPE_TOKEN IDENTIFIER IS_TOKEN subty_ind ';' + ; +subty_ind : + ty_mk _constrt_ + ; +ty_mk : + expanded_n + ; +constrt : + rng_c + | fltg_point_c + | fixed_point_c + | aggr + ; +derived_ty_def : + NEW_TOKEN subty_ind + ; +rng_c : + RANGE_TOKEN rng + ; +rng : + name + | sim_expr DOUBLE_DOT sim_expr + ; +enum_ty_def : + '(' enum_lit_spec ___enum_lit_spec__ ')' + ; +enum_lit_spec : + enum_lit + ; +enum_lit : + IDENTIFIER + | CHARACTER_LITERAL + ; +integer_ty_def : + rng_c + ; +real_ty_def : + fltg_point_c + | fixed_point_c + ; +fltg_point_c : + fltg_accuracy_def _rng_c_ + ; +fltg_accuracy_def : + DIGITS_TOKEN sim_expr + ; +fixed_point_c : + fixed_accuracy_def _rng_c_ + ; +fixed_accuracy_def : + DELTA_TOKEN sim_expr + ; +array_ty_def : + uncnstrnd_array_def + | c_arr_def + ; +uncnstrnd_array_def : + ARRAY_TOKEN '(' idx_subty_def ___idx_subty_def__ ')' OF_TOKEN subty_ind + ; +c_arr_def : + ARRAY_TOKEN idx_c OF_TOKEN subty_ind + ; +idx_subty_def : + name RANGE_TOKEN BOX + ; +idx_c : + '(' dscr_rng ___dscr_rng__ ')' + ; +dscr_rng : + rng + | name rng_c + ; +rec_ty_def : + RECORD_TOKEN cmpons END_TOKEN RECORD_TOKEN + ; +cmpons : + __prag__ __cmpon_d__ cmpon_d __prag__ + | __prag__ __cmpon_d__ variant_part __prag__ + | __prag__ NULL_TOKEN ';' __prag__ + ; +cmpon_d : + idents ':' cmpon_subty_def __ASN_expr_ ';' + ; +cmpon_subty_def : + subty_ind + ; +discr_part : + '(' discr_spec ___discr_spec__ ')' + ; +discr_spec : + idents ':' ty_mk __ASN_expr_ + ; +variant_part : + CASE_TOKEN sim_n IS_TOKEN __prag__ variant __variant__ END_TOKEN CASE_TOKEN ';' + ; +variant : + WHEN_TOKEN choice __or_choice__ ARROW cmpons + ; +paramchoice : + sim_expr + | name rng_c + | sim_expr DOUBLE_DOT sim_expr + | OTHERS_TOKEN + | error + ; +choice : + sim_expr + | name rng_c + | sim_expr DOUBLE_DOT sim_expr + | OTHERS_TOKEN + | error + ; +access_ty_def : + ACCESS_TOKEN subty_ind + ; +incomplete_ty_d : + TYPE_TOKEN IDENTIFIER ';' + | TYPE_TOKEN IDENTIFIER discr_part ';' + ; +decl_part : + __basic_decl_item__ + | __basic_decl_item__ body __later_decl_item__ + ; +basic_decl_item : + basic_d + | rep_cl + | use_cl + ; +later_decl_item : + body + | subprg_d + | pkg_d + | task_d + | gen_d + | use_cl + | gen_inst + ; +body : + proper_body + | body_stub + ; +proper_body : + subprg_body + | pkg_body + | task_body + ; +name : + sim_n + | CHARACTER_LITERAL + | op_symbol + | idxed_cmpon + | selected_cmpon + | attribute + ; +sim_n : + IDENTIFIER + ; +prefix : + name + ; +idxed_cmpon : + prefix aggr + ; +selected_cmpon : + prefix '.' selector + ; +selector : + sim_n + | CHARACTER_LITERAL + | op_symbol + | ALL_TOKEN + ; +attribute : + prefix '\'' attribute_designator + ; +attribute_designator : + sim_n + | DIGITS_TOKEN + | DELTA_TOKEN + | RANGE_TOKEN + ; +aggr : + '(' cmpon_asc ___cmpon_asc__ ')' + ; +cmpon_asc : + expr + | paramchoice __or_paramchoice__ ARROW expr + | sim_expr DOUBLE_DOT sim_expr + | name rng_c + ; +expr : + rel__AND__rel__ + | rel__AND__THEN__rel__ + | rel__OR__rel__ + | rel__OR__ELSE__rel__ + | rel__XOR__rel__ + | xrel + ; +xrel : + sim_expr _relal_op__sim_expr_ + | sim_expr_NOT_IN__rng_or_sim_expr_NOT_IN__ty_mk + ; +rel : + sim_expr _relal_op__sim_expr_ + | sim_expr_NOT_IN__rng_or_sim_expr_NOT_IN__ty_mk + ; +sim_expr : + _unary_add_op_term__binary_add_op__term__ + ; +term : + factor__mult_op__factor__ + ; +factor : + pri __EXP___pri_ + | ABS_TOKEN pri + | NOT_TOKEN '(' expr ')' + | NOT_TOKEN qualified_expr + | NOT_TOKEN name + ; +pri : + numeric_literal + | NULL_TOKEN + | allocator + | qualified_expr + | name + | aggr + ; +relal_op : + '=' + | INEQUALITY + | '<' + | LESS_THAN_OR_EQUAL + | '>' + | GREATER_THAN_OR_EQUAL + ; +binary_add_op : + '+' + | '-' + | '&' + ; +unary_add_op : + '+' + | '-' + ; +mult_op : + '*' + | '/' + | MOD_TOKEN + | REM_TOKEN + ; +qualified_expr : + ty_mkaggr_or_ty_mkPexprP_ + ; +allocator : + NEW_TOKEN ty_mk + | NEW_TOKEN ty_mk aggr + | NEW_TOKEN ty_mk '\'' aggr + ; +seq_of_stmts : + __prag__ stmt __stmt__ + ; +stmt : + __label__ sim_stmt + | __label__ compound_stmt + | error ';' + ; +sim_stmt : + null_stmt + | assignment_stmt + | exit_stmt + | return_stmt + | goto_stmt + | delay_stmt + | abort_stmt + | raise_stmt + | code_stmt + | name ';' + ; +compound_stmt : + if_stmt + | case_stmt + | loop_stmt + | block_stmt + | accept_stmt + | select_stmt + ; +label : + LEFT_LABEL_BRACKET sim_n RIGHT_LABEL_BRACKET + ; +null_stmt : + NULL_TOKEN ';' + ; +assignment_stmt : + name ASSIGNMENT expr ';' + ; +if_stmt : + IF_TOKEN cond THEN_TOKEN seq_of_stmts __ELSIF__cond__THEN__seq_of_stmts__ _ELSE__seq_of_stmts_ END_TOKEN IF_TOKEN ';' + ; +cond : + expr + ; +case_stmt : + CASE_TOKEN expr IS_TOKEN case_stmt_alt__case_stmt_alt__ END_TOKEN CASE_TOKEN ';' + ; +case_stmt_alt : + WHEN_TOKEN choice __or_choice__ ARROW seq_of_stmts + ; +loop_stmt : + _sim_nC_ _iteration_scheme_ LOOP_TOKEN seq_of_stmts END_TOKEN LOOP_TOKEN _sim_n_ ';' + ; +type_of_while : + cond + | error + ; +type_of_for : + loop_prm_spec + | error + ; +iteration_scheme : + WHILE_TOKEN type_of_while + | FOR_TOKEN type_of_for + ; +loop_prm_spec : + IDENTIFIER IN_TOKEN _REVERSE_ dscr_rng + ; +block_stmt : + _sim_nC_ _DECLARE__decl_part_ BEGIN_TOKEN seq_of_stmts _EXCEPTION__excptn_handler__excptn_handler___ END_TOKEN _sim_n_ ';' + ; +exit_stmt : + EXIT_TOKEN _expanded_n_ _WHEN__cond_ ';' + ; +return_stmt : + RETURN_TOKEN _expr_ ';' + ; +goto_stmt : + GOTO_TOKEN expanded_n ';' + ; +subprg_d : + subprg_spec ';' + ; +subprg_spec : + PROCEDURE_TOKEN IDENTIFIER _fml_part_ + | FUNCTION_TOKEN designator _fml_part_ RETURN_TOKEN ty_mk + ; +designator : + IDENTIFIER + | op_symbol + ; +op_symbol : + STRING_LITERAL + ; +fml_part : + '(' prm_spec ____prm_spec__ ')' + ; +prm_spec : + idents ':' mode ty_mk __ASN_expr_ + ; +mode : + _IN_ + | IN_TOKEN OUT_TOKEN + | OUT_TOKEN + ; +subprg_body : + subprg_spec IS_TOKEN _decl_part_ BEGIN_TOKEN seq_of_stmts _EXCEPTION__excptn_handler__excptn_handler___ END_TOKEN _designator_ ';' + ; +pkg_d : + pkg_spec ';' + ; +pkg_spec : + PACKAGE_TOKEN IDENTIFIER IS_TOKEN __basic_decl_item__ _PRIVATE__basic_decl_item___ END_TOKEN _sim_n_ + ; +pkg_body : + PACKAGE_TOKEN BODY_TOKEN sim_n IS_TOKEN _decl_part_ _BEGIN__seq_of_stmts_EXCEPTION__excptn_handler__excptn_handler___ END_TOKEN _sim_n_ ';' + ; +priv_ty_d : + TYPE_TOKEN IDENTIFIER IS_TOKEN _LIMITED_ PRIVATE_TOKEN ';' + | TYPE_TOKEN IDENTIFIER discr_part IS_TOKEN _LIMITED_ PRIVATE_TOKEN ';' + ; +use_cl : + USE_TOKEN expanded_n ___expanded_n__ ';' + ; +renaming_d : + idents ':' ty_mk RENAMES_TOKEN name ';' + | idents ':' EXCEPTION_TOKEN RENAMES_TOKEN expanded_n ';' + | PACKAGE_TOKEN IDENTIFIER RENAMES_TOKEN expanded_n ';' + | subprg_spec RENAMES_TOKEN name ';' + ; +task_d : + task_spec ';' + ; +task_spec : + TASK_TOKEN _TYPE_ IDENTIFIER _IS__ent_d___rep_cl_END_sim_n_ + ; +task_body : + TASK_TOKEN BODY_TOKEN sim_n IS_TOKEN _decl_part_ BEGIN_TOKEN seq_of_stmts _EXCEPTION__excptn_handler__excptn_handler___ END_TOKEN _sim_n_ ';' + ; +ent_d : + ENTRY_TOKEN IDENTIFIER _fml_part_ ';' + | ENTRY_TOKEN IDENTIFIER '(' dscr_rng ')' _fml_part_ ';' + ; +ent_call_stmt : + __prag__ name ';' + ; +accept_stmt : + ACCEPT_TOKEN sim_n _Pent_idx_P__fml_part_ _DO__seq_of_stmts__END_sim_n__ ';' + ; +ent_idx : + expr + ; +delay_stmt : + DELAY_TOKEN sim_expr ';' + ; +select_stmt : + selec_wait + | condal_ent_call + | timed_ent_call + ; +selec_wait : + SELECT_TOKEN select_alt __OR__select_alt__ _ELSE__seq_of_stmts_ END_TOKEN SELECT_TOKEN ';' + ; +select_alt : + _WHEN__condARROW_selec_wait_alt + ; +selec_wait_alt : + accept_alt + | delay_alt + | terminate_alt + ; +accept_alt : + accept_stmt_seq_of_stmts_ + ; +delay_alt : + delay_stmt_seq_of_stmts_ + ; +terminate_alt : + TERM_stmt + ; +condal_ent_call : + SELECT_TOKEN ent_call_stmt _seq_of_stmts_ ELSE_TOKEN seq_of_stmts END_TOKEN SELECT_TOKEN ';' + ; +timed_ent_call : + SELECT_TOKEN ent_call_stmt _seq_of_stmts_ OR_TOKEN delay_alt END_TOKEN SELECT_TOKEN ';' + ; +abort_stmt : + ABORT_TOKEN name ___name__ ';' + ; +compilation_unit : + context_cl library_unit + | context_cl secondary_unit + ; +library_unit : + subprg_d + | pkg_d + | gen_d + | gen_inst + | subprg_body + ; +secondary_unit : + library_unit_body + | subunit + ; +library_unit_body : + pkg_body_or_subprg_body + ; +context_cl : + __with_cl__use_cl____ + ; +with_cl : + WITH_TOKEN sim_n ___sim_n__ ';' + ; +body_stub : + subprg_spec IS_TOKEN SEPARATE_TOKEN ';' + | PACKAGE_TOKEN BODY_TOKEN sim_n IS_TOKEN SEPARATE_TOKEN ';' + | TASK_TOKEN BODY_TOKEN sim_n IS_TOKEN SEPARATE_TOKEN ';' + ; +subunit : + SEPARATE_TOKEN '(' expanded_n ')' proper_body + ; +excptn_d : + idents ':' EXCEPTION_TOKEN ';' + ; +excptn_handler : + WHEN_TOKEN excptn_choice __or_excptn_choice__ ARROW seq_of_stmts + ; +excptn_choice : + expanded_n + | OTHERS_TOKEN + ; +raise_stmt : + RAISE_TOKEN _expanded_n_ ';' + ; +gen_d : + gen_spec ';' + ; +gen_spec : + gen_fml_part subprg_spec + | gen_fml_part pkg_spec + ; +gen_fml_part : + GENERIC_TOKEN __gen_prm_d__ + ; +gen_prm_d : + idents ':' _IN_OUT__ ty_mk __ASN_expr_ ';' + | TYPE_TOKEN IDENTIFIER IS_TOKEN gen_ty_def ';' + | priv_ty_d + | WITH_TOKEN subprg_spec _IS_BOX__ ';' + ; +gen_ty_def : + '(' BOX ')' + | RANGE_TOKEN BOX + | DIGITS_TOKEN BOX + | DELTA_TOKEN BOX + | array_ty_def + | access_ty_def + ; +gen_inst : + PACKAGE_TOKEN IDENTIFIER IS_TOKEN NEW_TOKEN expanded_n _gen_act_part_ ';' + | PROCEDURE__ident__IS_ NEW_TOKEN expanded_n _gen_act_part_ ';' + | FUNCTION_TOKEN designator IS_TOKEN NEW_TOKEN expanded_n _gen_act_part_ ';' + ; +gen_act_part : + '(' gen_asc ___gen_asc__ ')' + ; +gen_asc : + _gen_fml_prmARROW_gen_act_prm + ; +gen_fml_prm : + sim_n + | op_symbol + ; +gen_act_prm : + expr_or_name_or_subprg_n_or_ent_n_or_ty_mk + ; +rep_cl : + ty_rep_cl + | address_cl + ; +ty_rep_cl : + length_cl + | enum_rep_cl + | rec_rep_cl + ; +length_cl : + FOR_TOKEN attribute USE_TOKEN sim_expr ';' + ; +enum_rep_cl : + FOR__ty_sim_n__USE_ aggr ';' + ; +rec_rep_cl : + FOR__ty_sim_n__USE_ RECORD_TOKEN _algt_cl_ __cmpon_cl__ END_TOKEN RECORD_TOKEN ';' + ; +algt_cl : + AT_TOKEN MOD_TOKEN sim_expr ';' + ; +cmpon_cl : + name AT_TOKEN sim_expr RANGE_TOKEN rng ';' + ; +address_cl : + FOR_TOKEN sim_n USE_TOKEN AT_TOKEN sim_expr ';' + ; +code_stmt : + ty_mk_rec_aggr ';' + ; +__prag__ : + /*empty*/ + | __prag__ prag + ; +_arg_ascs : + /*empty*/ + | '(' arg_ascs ')' + ; +arg_ascs : + arg_asc + | arg_ascs ',' arg_asc + ; +__ASN_expr_ : + /*empty*/ + | ASSIGNMENT expr + ; +___ident__ : + /*empty*/ + | ___ident__ ',' IDENTIFIER + ; +_constrt_ : + /*empty*/ + | constrt + ; +expanded_n : + IDENTIFIER + | expanded_n '.' IDENTIFIER + ; +___enum_lit_spec__ : + /*empty*/ + | ___enum_lit_spec__ ',' enum_lit_spec + ; +_rng_c_ : + /*empty*/ + | rng_c + ; +___idx_subty_def__ : + /*empty*/ + | ___idx_subty_def__ ',' idx_subty_def + ; +___dscr_rng__ : + /*empty*/ + | ___dscr_rng__ ',' dscr_rng + ; +__cmpon_d__ : + /*empty*/ + | __cmpon_d__ cmpon_d __prag__ + ; +___discr_spec__ : + /*empty*/ + | ___discr_spec__ ';' discr_spec + ; +__variant__ : + /*empty*/ + | __variant__ variant + ; +__or_choice__ : + /*empty*/ + | __or_choice__ '|' choice + | __or_choice__ '!' choice + ; +__or_paramchoice__ : + /*empty*/ + | __or_paramchoice__ '|' paramchoice + | __or_paramchoice__ '!' paramchoice + ; +__basic_decl_item__ : + __prag__ + | __basic_decl_item__ basic_decl_item __prag__ + ; +__later_decl_item__ : + __prag__ + | __later_decl_item__ later_decl_item __prag__ + ; +___cmpon_asc__ : + /*empty*/ + | ___cmpon_asc__ ',' cmpon_asc + ; +rel__AND__rel__ : + rel AND_TOKEN rel + | rel__AND__rel__ AND_TOKEN rel + ; +rel__OR__rel__ : + rel OR_TOKEN rel + | rel__OR__rel__ OR_TOKEN rel + ; +rel__XOR__rel__ : + rel XOR_TOKEN rel + | rel__XOR__rel__ XOR_TOKEN rel + ; +rel__AND__THEN__rel__ : + rel AND_TOKEN THEN_TOKEN rel + | rel__AND__THEN__rel__ AND_TOKEN THEN_TOKEN rel + ; +rel__OR__ELSE__rel__ : + rel OR_TOKEN ELSE_TOKEN rel + | rel__OR__ELSE__rel__ OR_TOKEN ELSE_TOKEN rel + ; +_relal_op__sim_expr_ : + /*empty*/ + | relal_op sim_expr + ; +sim_expr_NOT_IN__rng_or_sim_expr_NOT_IN__ty_mk : + sim_expr _NOT_ IN_TOKEN rng + ; +_NOT_ : + /*empty*/ + | NOT_TOKEN + ; +_unary_add_op_term__binary_add_op__term__ : + term + | unary_add_op term + | _unary_add_op_term__binary_add_op__term__ binary_add_op term + ; +factor__mult_op__factor__ : + factor + | factor__mult_op__factor__ mult_op factor + ; +__EXP___pri_ : + /*empty*/ + | DOUBLE_STAR pri + ; +ty_mkaggr_or_ty_mkPexprP_ : + prefix '\'' aggr + ; +__stmt__ : + __prag__ + | __stmt__ stmt __prag__ + ; +__label__ : + /*empty*/ + | __label__ label + ; +__ELSIF__cond__THEN__seq_of_stmts__ : + /*empty*/ + | __ELSIF__cond__THEN__seq_of_stmts__ ELSIF_TOKEN cond THEN_TOKEN seq_of_stmts + ; +_ELSE__seq_of_stmts_ : + /*empty*/ + | ELSE_TOKEN seq_of_stmts + ; +case_stmt_alt__case_stmt_alt__ : + __prag__ case_stmt_alt __case_stmt_alt__ + ; +__case_stmt_alt__ : + /*empty*/ + | __case_stmt_alt__ case_stmt_alt + ; +_sim_nC_ : + /*empty*/ + | sim_n ':' + ; +_sim_n_ : + /*empty*/ + | sim_n + ; +_iteration_scheme_ : + /*empty*/ + | iteration_scheme + ; +_REVERSE_ : + /*empty*/ + | REVERSE_TOKEN + ; +_DECLARE__decl_part_ : + /*empty*/ + | DECLARE_TOKEN decl_part + ; +_EXCEPTION__excptn_handler__excptn_handler___ : + /*empty*/ + | EXCEPTION_TOKEN __prag__ excptn_handlers + ; +excptn_handlers : + excptn_handler + | excptn_handlers excptn_handler + ; +_expanded_n_ : + /*empty*/ + | expanded_n + ; +_WHEN__cond_ : + /*empty*/ + | WHEN_TOKEN cond + ; +_expr_ : + /*empty*/ + | expr + ; +_fml_part_ : + /*empty*/ + | fml_part + ; +____prm_spec__ : + /*empty*/ + | ____prm_spec__ ';' prm_spec + ; +_IN_ : + /*empty*/ + | IN_TOKEN + ; +_decl_part_ : + decl_part + ; +_designator_ : + /*empty*/ + | designator + ; +_PRIVATE__basic_decl_item___ : + /*empty*/ + | PRIVATE_TOKEN __basic_decl_item__ + ; +_BEGIN__seq_of_stmts_EXCEPTION__excptn_handler__excptn_handler___ : + /*empty*/ + | BEGIN_TOKEN seq_of_stmts _EXCEPTION__excptn_handler__excptn_handler___ + ; +_LIMITED_ : + /*empty*/ + | LIMITED_TOKEN + ; +___expanded_n__ : + /*empty*/ + | ___expanded_n__ ',' expanded_n + ; +_TYPE_ : + /*empty*/ + | TYPE_TOKEN + ; +_IS__ent_d___rep_cl_END_sim_n_ : + /*empty*/ + | IS_TOKEN __ent_d__ __rep_cl__ END_TOKEN _sim_n_ + ; +__ent_d__ : + __prag__ + | __ent_d__ ent_d __prag__ + ; +__rep_cl__ : + /*empty*/ + | __rep_cl__ rep_cl __prag__ + ; +_Pent_idx_P__fml_part_ : + _fml_part_ + | '(' ent_idx ')' _fml_part_ + ; +_DO__seq_of_stmts__END_sim_n__ : + /*empty*/ + | DO_TOKEN seq_of_stmts END_TOKEN _sim_n_ + ; +__OR__select_alt__ : + /*empty*/ + | __OR__select_alt__ OR_TOKEN select_alt + ; +_WHEN__condARROW_selec_wait_alt : + selec_wait_alt + | WHEN_TOKEN cond ARROW selec_wait_alt + ; +accept_stmt_seq_of_stmts_ : + __prag__ accept_stmt _seq_of_stmts_ + ; +delay_stmt_seq_of_stmts_ : + __prag__ delay_stmt _seq_of_stmts_ + ; +TERM_stmt : + __prag__ TERMINATE_TOKEN ';' __prag__ + ; +_seq_of_stmts_ : + __prag__ + | seq_of_stmts + ; +___name__ : + /*empty*/ + | ___name__ ',' name + ; +__compilation_unit__ : + __prag__ + | __compilation_unit__ compilation_unit __prag__ + ; +pkg_body_or_subprg_body : + pkg_body + ; +__with_cl__use_cl____ : + /*empty*/ + | __with_cl__use_cl____ with_cl use_cls + ; +use_cls : + __prag__ + | use_cls use_cl __prag__ + ; +___sim_n__ : + /*empty*/ + | ___sim_n__ ',' sim_n + ; +__or_excptn_choice__ : + /*empty*/ + | __or_excptn_choice__ '|' excptn_choice + | __or_excptn_choice__ '!' excptn_choice + ; +__gen_prm_d__ : + /*empty*/ + | __gen_prm_d__ gen_prm_d + ; +_IN_OUT__ : + _IN_ + | IN_TOKEN OUT_TOKEN + ; +_IS_BOX__ : + /*empty*/ + | IS_TOKEN name + | IS_TOKEN BOX + ; +PROCEDURE__ident__IS_ : + subprg_spec IS_TOKEN + ; +_gen_act_part_ : + /*empty*/ + | gen_act_part + ; +___gen_asc__ : + /*empty*/ + | ___gen_asc__ ',' gen_asc + ; +_gen_fml_prmARROW_gen_act_prm : + gen_act_prm + | gen_fml_prm ARROW gen_act_prm + ; +expr_or_name_or_subprg_n_or_ent_n_or_ty_mk : + expr + ; +FOR__ty_sim_n__USE_ : + FOR_TOKEN sim_n USE_TOKEN + ; +_algt_cl_ : + __prag__ + | __prag__ algt_cl __prag__ + ; +__cmpon_cl__ : + /*empty*/ + | __cmpon_cl__ cmpon_cl __prag__ + ; +ty_mk_rec_aggr : + qualified_expr + ; + +//Lexer + +// \({\S+\)\s+{ECHO_L; ENTER(Z); return(\([^)]+\));} +ABORT_TOKEN : "[Aa][Bb][Oo][Rr][Tt]" ; +ABS_TOKEN : "[Aa][Bb][Ss]" ; +ACCEPT_TOKEN : "[Aa][Cc][Cc][Ee][Pp][Tt]" ; +ACCESS_TOKEN : "[Aa][Cc][Cc][Ee][Ss][Ss]" ; +ALL_TOKEN : "[Aa][Ll][Ll]" ; +AND_TOKEN : "[Aa][Nn][Dd]" ; +ARRAY_TOKEN : "[Aa][Rr][Rr][Aa][Yy]" ; +AT_TOKEN : "[Aa][Tt]" ; +BEGIN_TOKEN : "[Bb][Ee][Gg][Ii][Nn]" ; +BODY_TOKEN : "[Bb][Oo][Dd][Yy]" ; +CASE_TOKEN : "[Cc][Aa][Ss][Ee]" ; +CONSTANT_TOKEN : "[Cc][Oo][Nn][Ss][Tt][Aa][Nn][Tt]" ; +DECLARE_TOKEN : "[Dd][Ee][Cc][Ll][Aa][Rr][Ee]" ; +DELAY_TOKEN : "[Dd][Ee][Ll][Aa][Yy]" ; +DELTA_TOKEN : "[Dd][Ee][Ll][Tt][Aa]" ; +DIGITS_TOKEN : "[Dd][Ii][Gg][Ii][Tt][Ss]" ; +DO_TOKEN : "[Dd][Oo]" ; +ELSE_TOKEN : "[Ee][Ll][Ss][Ee]" ; +ELSIF_TOKEN : "[Ee][Ll][Ss][Ii][Ff]" ; +END_TOKEN : "[Ee][Nn][Dd]" ; +ENTRY_TOKEN : "[Ee][Nn][Tt][Rr][Yy]" ; +EXCEPTION_TOKEN : "[Ee][Xx][Cc][Ee][Pp][Tt][Ii][Oo][Nn]" ; +EXIT_TOKEN : "[Ee][Xx][Ii][Tt]" ; +FOR_TOKEN : "[Ff][Oo][Rr]" ; +FUNCTION_TOKEN : "[Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn]" ; +GENERIC_TOKEN : "[Gg][Ee][Nn][Ee][Rr][Ii][Cc]" ; +GOTO_TOKEN : "[Gg][Oo][Tt][Oo]" ; +IF_TOKEN : "[Ii][Ff]" ; +IN_TOKEN : "[Ii][Nn]" ; +IS_TOKEN : "[Ii][Ss]" ; +LIMITED_TOKEN : "[Ll][Ii][Mm][Ii][Tt][Ee][Dd]" ; +LOOP_TOKEN : "[Ll][Oo][Oo][Pp]" ; +MOD_TOKEN : "[Mm][Oo][Dd]" ; +NEW_TOKEN : "[Nn][Ee][Ww]" ; +NOT_TOKEN : "[Nn][Oo][Tt]" ; +NULL_TOKEN : "[Nn][Uu][Ll][Ll]" ; +OF_TOKEN : "[Oo][Ff]" ; +OR_TOKEN : "[Oo][Rr]" ; +OTHERS_TOKEN : "[Oo][Tt][Hh][Ee][Rr][Ss]" ; +OUT_TOKEN : "[Oo][Uu][Tt]" ; +PACKAGE_TOKEN : "[Pp][Aa][Cc][Kk][Aa][Gg][Ee]" ; +PRAGMA_TOKEN : "[Pp][Rr][Aa][Gg][Mm][Aa]" ; +PRIVATE_TOKEN : "[Pp][Rr][Ii][Vv][Aa][Tt][Ee]" ; +PROCEDURE_TOKEN : "[Pp][Rr][Oo][Cc][Ee][Dd][Uu][Rr][Ee]" ; +RAISE_TOKEN : "[Rr][Aa][Ii][Ss][Ee]" ; +RANGE_TOKEN : "[Rr][Aa][Nn][Gg][Ee]" ; +RECORD_TOKEN : "[Rr][Ee][Cc][Oo][Rr][Dd]" ; +REM_TOKEN : "[Rr][Ee][Mm]" ; +RENAMES_TOKEN : "[Rr][Ee][Nn][Aa][Mm][Ee][Ss]" ; +RETURN_TOKEN : "[Rr][Ee][Tt][Uu][Rr][Nn]" ; +REVERSE_TOKEN : "[Rr][Ee][Vv][Ee][Rr][Ss][Ee]" ; +SELECT_TOKEN : "[Ss][Ee][Ll][Ee][Cc][Tt]" ; +SEPARATE_TOKEN : "[Ss][Ee][Pp][Aa][Rr][Aa][Tt][Ee]" ; +SUBTYPE_TOKEN : "[Ss][Uu][Bb][Tt][Yy][Pp][Ee]" ; +TASK_TOKEN : "[Tt][Aa][Ss][Kk]" ; +TERMINATE_TOKEN : "[Tt][Ee][Rr][Mm][Ii][Nn][Aa][Tt][Ee]" ; +THEN_TOKEN : "[Tt][Hh][Ee][Nn]" ; +TYPE_TOKEN : "[Tt][Yy][Pp][Ee]" ; +USE_TOKEN : "[Uu][Ss][Ee]" ; +WHEN_TOKEN : "[Ww][Hh][Ee][Nn]" ; +WHILE_TOKEN : "[Ww][Hh][Ii][Ll][Ee]" ; +WITH_TOKEN : "[Ww][Ii][Tt][Hh]" ; +XOR_TOKEN : "[Xx][Oo][Rr]" ; + + //-- Match all the compound Ada delimiters. See Ada LRM 2.2. + +ARROW : '=>' ; +DOUBLE_DOT : '..' ; +DOUBLE_STAR : '**' ; +ASSIGNMENT : ':=' ; +INEQUALITY : '/=' ; +GREATER_THAN_OR_EQUAL : '>=' ; +LESS_THAN_OR_EQUAL : '<=' ; +LEFT_LABEL_BRACKET : '<<' ; +RIGHT_LABEL_BRACKET : '>>' ; +BOX : '<>' ; + +IDENTIFIER : "[a-zA-Z]([_]?[a-zA-Z0-9])*" ; +REAL_LITERAL : "([0-9]+\.[0-9]*|\.[0-9]+)([Ee](\+|\-)?[0-9]+)?" ; +INTEGER_LITERAL : "[0-9]+" ; +CHARACTER_LITERAL : "'(\\.|[^'])[']" ; +STRING_LITERAL : "\"(\\.|[^\"\n])*\"" ; + +} \ No newline at end of file diff --git a/playground/bc.g b/playground/bc.g new file mode 100644 index 0000000..a4904a0 --- /dev/null +++ b/playground/bc.g @@ -0,0 +1,276 @@ +//From: https://mirrors.ocf.berkeley.edu/gnu/bc/bc-1.07.1.tar.gz +bc { + +%whitespace "[ \t]*"; +%whitespace "#[^\r\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/* +%token ENDOFLINE +%token AND +%token OR +%token NOT +%token STRING +%token NAME +%token NUMBER +%token ASSIGN_OP +%token REL_OP +%token INCR_DECR +%token Define +%token Break +%token Quit +%token Length +%token Return +%token For +%token If +%token While +%token Sqrt +%token Else +%token Scale +%token Ibase +%token Obase +%token Auto +%token Read +%token Random +%token Warranty +%token Halt +%token Last +%token Continue +%token Print +%token Limits +%token UNARY_MINUS +%token HistoryVar +%token Void +%token '+' +%token '-' +%token '*' +%token '/' +%token '%' +%token '^' +%token ';' +%token '(' +%token ')' +%token '{' +%token '}' +%token ',' +%token '[' +%token ']' +%token '&' +*/ + +%nonassoc IF_WITHOUT_ELSE ; +%nonassoc Else ; +%left /*1*/ OR ; +%left /*2*/ AND ; +%nonassoc /*3*/ NOT ; +%left /*4*/ REL_OP ; +%right /*5*/ ASSIGN_OP ; +%left /*6*/ '+' '-' ; +%left /*7*/ '*' '/' '%' ; +%right /*8*/ '^' ; +%nonassoc /*9*/ UNARY_MINUS ; +%nonassoc /*10*/ INCR_DECR ; + +//%start program + +//%% + +program : + /*empty*/ + | program input_item + ; +input_item : + semicolon_list ENDOFLINE + | function + | error ENDOFLINE + ; +opt_newline : + /*empty*/ + | ENDOFLINE + ; +semicolon_list : + /*empty*/ + | statement_or_error + | semicolon_list ';' statement_or_error + | semicolon_list ';' + ; +statement_list : + /*empty*/ + | statement_or_error + | statement_list ENDOFLINE + | statement_list ENDOFLINE statement_or_error + | statement_list ';' + | statement_list ';' statement + ; +statement_or_error : + statement + | error statement + ; +statement : + Warranty + | Limits + | expression + | STRING + | Break + | Continue + | Quit + | Halt + | Return return_expression + ; +statement : + For '(' opt_expression ';' opt_expression ';' opt_expression ')' opt_newline statement + ; +statement : + If '(' expression ')' opt_newline statement opt_else + ; +statement : + While '(' expression ')' opt_newline statement + | '{' statement_list '}' + ; +statement : + Print print_list + ; +print_list : + print_element + | print_element ',' print_list + ; +print_element : + STRING + | expression + ; +opt_else : + /*empty*/ %prec IF_WITHOUT_ELSE + ; +opt_else : + Else opt_newline statement + ; +function : + Define opt_void NAME '(' opt_parameter_list ')' opt_newline '{' required_eol opt_auto_define_list statement_list '}' + ; +opt_void : + /*empty*/ + | Void + ; +opt_parameter_list : + /*empty*/ + | define_list + ; +opt_auto_define_list : + /*empty*/ + | Auto define_list ENDOFLINE + | Auto define_list ';' + ; +define_list : + NAME + | NAME '[' ']' + | '*' /*7L*/ NAME '[' ']' + | '&' NAME '[' ']' + | define_list ',' NAME + | define_list ',' NAME '[' ']' + | define_list ',' '*' /*7L*/ NAME '[' ']' + | define_list ',' '&' NAME '[' ']' + ; +opt_argument_list : + /*empty*/ + | argument_list + ; +argument_list : + expression + | NAME '[' ']' + | argument_list ',' expression + | argument_list ',' NAME '[' ']' + ; +opt_expression : + /*empty*/ + | expression + ; +return_expression : + /*empty*/ + | expression + ; +expression : + named_expression ASSIGN_OP /*5R*/ expression + ; +expression : + expression AND /*2L*/ expression + ; +expression : + expression OR /*1L*/ expression + | NOT /*3N*/ expression + | expression REL_OP /*4L*/ expression + | expression '+' /*6L*/ expression + | expression '-' /*6L*/ expression + | expression '*' /*7L*/ expression + | expression '/' /*7L*/ expression + | expression '%' /*7L*/ expression + | expression '^' /*8R*/ expression + | '-' /*6L*/ expression %prec UNARY_MINUS /*9N*/ + | named_expression + | NUMBER + | '(' expression ')' + | NAME '(' opt_argument_list ')' + | INCR_DECR /*10N*/ named_expression + | named_expression INCR_DECR /*10N*/ + | Length '(' expression ')' + | Sqrt '(' expression ')' + | Scale '(' expression ')' + | Read '(' ')' + | Random '(' ')' + ; +named_expression : + NAME + | NAME '[' expression ']' + | Ibase + | Obase + | Scale + | HistoryVar + | Last + ; +required_eol : + /*empty*/ + | ENDOFLINE + | required_eol ENDOFLINE + ; + +//Lexer + +//\(\S+\)\s+return(\([^)]+\)); +Define : 'define' ; +Break : 'break' ; +Quit : 'quit' ; +Length : 'length' ; +Return : 'return' ; +For : 'for' ; +If : 'if' ; +While : 'while' ; +Sqrt : 'sqrt' ; +Scale : 'scale' ; +Ibase : 'ibase' ; +Obase : 'obase' ; +Auto : 'auto' ; +Else : 'else' ; +Read : 'read' ; +Random : 'random' ; +Halt : 'halt' ; +Last : 'last' ; +Void : 'void' ; + +OR : '||' ; +AND : '&&' ; +NOT : '!' ; +REL_OP : "==|<=|>=|!=|<|>" ; +ASSIGN_OP : "=|\+=|\-=|\*=|/=|%=|\^=" ; +INCR_DECR : "\+\+|\-\-" ; +ENDOFLINE : '\n'; +Warranty : 'Warranty' ; +Limits : 'Limits' ; +Continue : 'Continue' ; +Print : 'Print' ; +HistoryVar : 'HistoryVar' ; + +NAME : "[a-z][a-z0-9_]*" ; +STRING : "\"(\\.|[^\"\n])*\"" ; +NUMBER : "[0-9]+(\.[0-9]+)?"; + +} \ No newline at end of file diff --git a/playground/bison.g b/playground/bison.g new file mode 100644 index 0000000..5f95e07 --- /dev/null +++ b/playground/bison.g @@ -0,0 +1,338 @@ +// /home/mingo/dev/c/A_grammars/lalr/lalr-nb/dist/Release/GNU-Linux/lalr-nb bison.g + +bison { + +//%error_recovery_show; +%error_recovery_off; +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token STRING +//%token TSTRING +//%token PERCENT_TOKEN +//%token PERCENT_NTERM +//%token PERCENT_TYPE +//%token PERCENT_DESTRUCTOR +//%token PERCENT_PRINTER +//%token PERCENT_LEFT +//%token PERCENT_RIGHT +//%token PERCENT_NONASSOC +//%token PERCENT_PRECEDENCE +//%token PERCENT_PREC +//%token PERCENT_DPREC +//%token PERCENT_MERGE +//%token PERCENT_CODE +//%token PERCENT_DEFAULT_PREC +//%token PERCENT_DEFINE +//%token PERCENT_ERROR_VERBOSE +//%token PERCENT_EXPECT +//%token PERCENT_EXPECT_RR +//%token PERCENT_FILE_PREFIX +//%token PERCENT_FLAG +//%token PERCENT_GLR_PARSER +//%token PERCENT_HEADER +//%token PERCENT_INITIAL_ACTION +//%token PERCENT_LANGUAGE +//%token PERCENT_NAME_PREFIX +//%token PERCENT_NO_DEFAULT_PREC +//%token PERCENT_NO_LINES +//%token PERCENT_NONDETERMINISTIC_PARSER +//%token PERCENT_OUTPUT +//%token PERCENT_PURE_PARSER +//%token PERCENT_REQUIRE +//%token PERCENT_SKELETON +//%token PERCENT_START +//%token PERCENT_TOKEN_TABLE +//%token PERCENT_VERBOSE +//%token PERCENT_YACC +//%token BRACED_CODE +//%token BRACED_PREDICATE +//%token BRACKETED_ID +//%token CHAR_LITERAL +//%token COLON +//%token EPILOGUE +//%token EQUAL +//%token ID +//%token ID_COLON +//%token PERCENT_PERCENT +//%token PIPE +//%token PROLOGUE +//%token SEMICOLON +//%token TAG +//%token TAG_ANY +//%token TAG_NONE +//%token INT_LITERAL +//%token PERCENT_PARAM +//%token PERCENT_UNION +//%token PERCENT_EMPTY + + +//%start input + +//%% + +input : + //YYEOF + /*|*/ prologue_declarations SECTION_MARK grammar epilogue_opt + ; + +prologue_declarations : + /*empty*/ + | prologue_declarations prologue_declaration + ; + +prologue_declaration : + grammar_declaration + | VERBATIN_CODE + | '%' + | '%define' variable value + | '%header' string_opt + | '%error-verbose' + | '%expect' INT_LITERAL + | '%expect-rr' INT_LITERAL + | '%file-prefix' STRING + | '%glr-parser' + | '%initial-action' ACTION_CODE + | '%language' STRING + | '%name-prefix' STRING + | '%no-lines' + | '%nondeterministic-parser' + | '%output' STRING + | '%param' params + | '%pure-parser' + | '%require' STRING + | '%skeleton' STRING + | '%token-table' + | '%verbose' + | '%yacc' + | error ';' + | ';' + ; + +params : + params ACTION_CODE + | ACTION_CODE + ; + +grammar_declaration : + symbol_declaration + | '%start' symbols_1 + | code_props_type ACTION_CODE generic_symlist + | '%default-prec' + | '%no-default-prec' + | '%code' ACTION_CODE + | '%code' ID ACTION_CODE + ; + +code_props_type : + '%destructor' + | '%printer' + ; + +union_name : + /*empty*/ + | ID + ; + +grammar_declaration : + '%union' union_name ACTION_CODE + ; + +symbol_declaration : + '%nterm' nterm_decls + | '%token' token_decls + | '%type' symbol_decls + | precedence_declarator token_decls_for_prec + ; + +precedence_declarator : + '%left' + | '%right' + | '%nonassoc' + | '%precedence' + ; + +string_opt : + /*empty*/ + | STRING + ; + +tag_opt : + /*empty*/ + | TAG + ; + +generic_symlist : + generic_symlist_item + | generic_symlist generic_symlist_item + ; + +generic_symlist_item : + symbol + | tag + ; + +tag : + TAG + //| '<*>' + //| '<>' + ; + +nterm_decls : + token_decls + ; + +token_decls : + token_decl_1 + | TAG token_decl_1 + | token_decls TAG token_decl_1 + ; + +token_decl_1 : + token_decl + | token_decl_1 token_decl + ; + +token_decl : + id int_opt alias + ; + +int_opt : + /*empty*/ + | INT_LITERAL + ; + +alias : + /*empty*/ + | string_as_id + | TSTRING + ; + +token_decls_for_prec : + token_decl_for_prec_1 + | TAG token_decl_for_prec_1 + | token_decls_for_prec TAG token_decl_for_prec_1 + ; + +token_decl_for_prec_1 : + token_decl_for_prec + | token_decl_for_prec_1 token_decl_for_prec + ; + +token_decl_for_prec : + id int_opt + | string_as_id + ; + +symbol_decls : + symbols_1 + | TAG symbols_1 + | symbol_decls TAG symbols_1 + ; + +symbols_1 : + symbol + | symbols_1 symbol + ; + +grammar : + rules_or_grammar_declaration + | grammar rules_or_grammar_declaration + ; + +rules_or_grammar_declaration : + rules + | grammar_declaration ';' + | error ';' + ; + +rules : + id_colon named_ref_opt ':' rhses_1 + ; + +rhses_1 : + rhs + | rhses_1 '|' rhs + | rhses_1 ';' + ; + +rhs : + /*empty*/ + | rhs symbol named_ref_opt + | rhs tag_opt '{...}' named_ref_opt + | rhs '%?{...}' + | rhs '%empty' + | rhs '%prec' symbol + | rhs '%dprec' INT_LITERAL + | rhs '%merge' TAG + | rhs '%expect' INT_LITERAL + | rhs '%expect-rr' INT_LITERAL + ; + +named_ref_opt : + /*empty*/ + | BRACKETED_ID + ; + +variable : + ID + ; + +value : + /*empty*/ + | ID + | STRING + | '{...}' + ; + +id : + ID + | CHAR_LITERAL + ; + +id_colon : + ID_COLON + ; + +symbol : + id + | string_as_id + ; + +string_as_id : + STRING + ; + +epilogue_opt : + /*empty*/ + | SECTION_MARK EPILOGUE + ; + +// Tokens + +SECTION_MARK : '%%' ; + +INT_LITERAL : "[0-9]+" ; +STRING : "\"[^\"\n]*\"|'[^'\n]*'" ; +TSTRING : '_(' STRING ')' ; +//ID_COLON : ID ':' ; +ID_COLON : "[a-zA-Z_][a-zA-Z_.0-9]*[[:space:]]*\:" ; //Order matter, need be before ID +ID : "[a-zA-Z_][a-zA-Z_.0-9]*" ; +//BRACKETED_ID : '[' ID ']' ; +BRACKETED_ID : "\[[a-zA-Z_][a-zA-Z_.0-9]*\]" ; +TAG : "<[^>]*>" ; +CHAR_LITERAL : "'[^']'" ; + +ACTION_CODE : '{...}' ; +VERBATIN_CODE : '%{...%}' ; + +//EPILOGUE : ".+" ; //with this we have segfault +EPILOGUE : 'xxxxx' ; //".*" ; + +} diff --git a/playground/carbon-lang.g b/playground/carbon-lang.g new file mode 100644 index 0000000..ba46272 --- /dev/null +++ b/playground/carbon-lang.g @@ -0,0 +1,870 @@ +// /home/mingo/dev/c/A_grammars/lalr/lalr-nb/dist/Release/GNU-Linux/lalr-nb carbon-lang.g +// /usr/bin/time /home/mingo/dev/c/A_grammars/lalr/test-grammar-nb/dist/Release/GNU-Linux/test-grammar-nb -g carbon-lang.g -i prelude.carbon + +carbon { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token END_OF_FILE +//%token YYerror +//%token YYUNDEF +//%token integer_literal +//%token identifier +//%token intrinsic_identifier +//%token sized_type_literal +//%token string_literal +//%token ABSTRACT +//%token ADDR +//%token ALIAS +//%token AMPERSAND +//%token AMPERSAND_EQUAL +//%token AND +//%token API +//%token ARROW +//%token AS +//%token AUTO +//%token AWAIT +//%token BASE +//%token BOOL +//%token BREAK +//%token CARET +//%token CARET_EQUAL +//%token CASE +//%token CHOICE +//%token CLASS +//%token COLON +//%token COLON_BANG +//%token COMMA +//%token CONSTRAINT +//%token CONTINUATION +//%token CONTINUATION_TYPE +//%token CONTINUE +//%token DEFAULT +//%token DESTRUCTOR +//%token DOUBLE_ARROW +//%token ELSE +//%token EQUAL +//%token EQUAL_EQUAL +//%token EXTENDS +//%token EXTERNAL +//%token FALSE +//%token FN +//%token FN_TYPE +//%token FOR +//%token FORALL +//%token GREATER +//%token GREATER_EQUAL +//%token GREATER_GREATER +//%token GREATER_GREATER_EQUAL +//%token IF +//%token IMPL +//%token IMPORT +//%token IN +//%token INTERFACE +//%token IS +//%token LEFT_CURLY_BRACE +//%token LEFT_PARENTHESIS +//%token LEFT_SQUARE_BRACKET +//%token LESS +//%token LESS_EQUAL +//%token LESS_LESS +//%token LESS_LESS_EQUAL +//%token LET +//%token LIBRARY +//%token MATCH +//%token MATCH_FIRST +//%token MINUS +//%token MINUS_EQUAL +//%token MINUS_MINUS +//%token MIX +//%token MIXIN +//%token NAMESPACE +//%token NOT +//%token NOT_EQUAL +//%token OR +//%token OR_EQUAL +//%token PACKAGE +//%token PERCENT +//%token PERCENT_EQUAL +//%token PERIOD +//%token PIPE +//%token PIPE_EQUAL +//%token PLUS +//%token PLUS_EQUAL +//%token PLUS_PLUS +//%token RETURN +//%token RETURNED +//%token RIGHT_CURLY_BRACE +//%token RIGHT_PARENTHESIS +//%token RIGHT_SQUARE_BRACKET +//%token RUN +//%token SELF +//%token SEMICOLON +//%token SLASH +//%token SLASH_EQUAL +//%token STAR_EQUAL +//%token STRING +//%token TEMPLATE +//%token THEN +//%token TRUE +//%token TYPE +//%token UNDERSCORE +//%token UNIMPL_EXAMPLE +//%token VAR +//%token VIRTUAL +//%token WHERE +//%token WHILE +//%token FNARROW +//%token UNARY_STAR +//%token PREFIX_STAR +//%token POSTFIX_STAR +//%token BINARY_STAR + + +//%start input + +//%% + +input : + //END_OF_FILE + package_directive import_directives declaration_list + ; + +package_directive : + PACKAGE identifier optional_library_path api_or_impl SEMICOLON + ; + +import_directive : + IMPORT identifier optional_library_path SEMICOLON + ; + +import_directives : + /*empty*/ + | import_directives import_directive + ; + +optional_library_path : + /*empty*/ + | LIBRARY string_literal + ; + +api_or_impl : + API + | IMPL + ; + +primary_expression : + identifier + | designator + | PERIOD SELF + | integer_literal + | string_literal + | TRUE + | FALSE + | sized_type_literal + | SELF + | STRING + | BOOL + | TYPE + | CONTINUATION_TYPE + | paren_expression + | struct_literal + | struct_type_literal + | LEFT_SQUARE_BRACKET expression SEMICOLON expression RIGHT_SQUARE_BRACKET + ; + +postfix_expression : + primary_expression + | postfix_expression designator + | postfix_expression ARROW identifier + | postfix_expression PERIOD LEFT_PARENTHESIS expression RIGHT_PARENTHESIS + | postfix_expression ARROW LEFT_PARENTHESIS expression RIGHT_PARENTHESIS + | postfix_expression LEFT_SQUARE_BRACKET expression RIGHT_SQUARE_BRACKET + | intrinsic_identifier tuple + | postfix_expression tuple + | postfix_expression POSTFIX_STAR + | postfix_expression UNARY_STAR + ; + +ref_deref_expression : + postfix_expression + | PREFIX_STAR ref_deref_expression + | UNARY_STAR ref_deref_expression + | AMPERSAND ref_deref_expression + ; + +fn_type_expression : + FN_TYPE tuple ARROW type_expression + ; + +type_expression : + ref_deref_expression + | bitwise_and_expression + | fn_type_expression + ; + +minus_expression : + MINUS ref_deref_expression + ; + +complement_expression : + CARET ref_deref_expression + ; + +unary_expression : + minus_expression + | complement_expression + ; + +simple_binary_operand : + ref_deref_expression + | unary_expression + ; + +multiplicative_lhs : + simple_binary_operand + | multiplicative_expression + ; + +multiplicative_expression : + multiplicative_lhs BINARY_STAR simple_binary_operand + | multiplicative_lhs SLASH simple_binary_operand + ; + +additive_operand : + simple_binary_operand + | multiplicative_expression + ; + +additive_lhs : + simple_binary_operand + | additive_expression + ; + +additive_expression : + multiplicative_expression + | additive_lhs PLUS additive_operand + | additive_lhs MINUS additive_operand + ; + +modulo_expression : + simple_binary_operand PERCENT simple_binary_operand + ; + +bitwise_and_lhs : + simple_binary_operand + | bitwise_and_expression + ; + +bitwise_and_expression : + bitwise_and_lhs AMPERSAND simple_binary_operand + ; + +bitwise_or_lhs : + simple_binary_operand + | bitwise_or_expression + ; + +bitwise_or_expression : + bitwise_or_lhs PIPE simple_binary_operand + ; + +bitwise_xor_lhs : + simple_binary_operand + | bitwise_xor_expression + ; + +bitwise_xor_expression : + bitwise_xor_lhs CARET simple_binary_operand + ; + +bitwise_expression : + bitwise_and_expression + | bitwise_or_expression + | bitwise_xor_expression + ; + +bit_shift_expression : + simple_binary_operand LESS_LESS simple_binary_operand + | simple_binary_operand GREATER_GREATER simple_binary_operand + ; + +as_expression : + simple_binary_operand AS simple_binary_operand + ; + +unimpl_expression : + ref_deref_expression UNIMPL_EXAMPLE ref_deref_expression + ; + +value_expression : + additive_expression + | as_expression + | bitwise_expression + | bit_shift_expression + | fn_type_expression + | modulo_expression + | unary_expression + | unimpl_expression + ; + +comparison_operand : + ref_deref_expression + | value_expression + ; + +comparison_operator : + EQUAL_EQUAL + | LESS + | LESS_EQUAL + | GREATER + | GREATER_EQUAL + | NOT_EQUAL + ; + +comparison_expression : + value_expression + | comparison_operand comparison_operator comparison_operand + ; + +not_expression : + NOT ref_deref_expression + ; + +predicate_expression : + not_expression + | comparison_expression + ; + +and_or_operand : + ref_deref_expression + | predicate_expression + ; + +and_lhs : + and_or_operand + | and_expression + ; + +and_expression : + and_lhs AND and_or_operand + ; + +or_lhs : + and_or_operand + | or_expression + ; + +or_expression : + or_lhs OR and_or_operand + ; + +where_clause : + comparison_operand IS comparison_operand + | comparison_operand EQUAL_EQUAL comparison_operand + | designator EQUAL comparison_operand + ; + +where_clause_list : + where_clause + | where_clause_list AND where_clause + ; + +where_expression : + type_expression WHERE where_clause_list + ; + +type_or_where_expression : + type_expression + | where_expression + ; + +statement_expression : + ref_deref_expression + | predicate_expression + | and_expression + | or_expression + | where_expression + ; + +if_expression : + statement_expression + | IF expression THEN if_expression ELSE if_expression + ; + +expression : + if_expression + ; + +designator : + PERIOD identifier + | PERIOD BASE + ; + +paren_expression : + paren_expression_base + ; + +tuple : + paren_expression_base + ; + +paren_expression_base : + LEFT_PARENTHESIS RIGHT_PARENTHESIS + | LEFT_PARENTHESIS paren_expression_contents RIGHT_PARENTHESIS + | LEFT_PARENTHESIS paren_expression_contents COMMA RIGHT_PARENTHESIS + ; + +paren_expression_contents : + expression + | paren_expression_contents COMMA expression + ; + +struct_literal : + LEFT_CURLY_BRACE RIGHT_CURLY_BRACE + | LEFT_CURLY_BRACE struct_literal_contents RIGHT_CURLY_BRACE + | LEFT_CURLY_BRACE struct_literal_contents COMMA RIGHT_CURLY_BRACE + ; + +struct_literal_contents : + designator EQUAL expression + | struct_literal_contents COMMA designator EQUAL expression + ; + +struct_type_literal : + LEFT_CURLY_BRACE struct_type_literal_contents RIGHT_CURLY_BRACE + | LEFT_CURLY_BRACE struct_type_literal_contents COMMA RIGHT_CURLY_BRACE + ; + +struct_type_literal_contents : + designator COLON expression + | struct_type_literal_contents COMMA designator COLON expression + ; + +pattern : + non_expression_pattern + | expression + ; + +non_expression_pattern : + AUTO + | binding_lhs COLON pattern + | binding_lhs COLON_BANG expression + | TEMPLATE binding_lhs COLON_BANG expression + | paren_pattern + | postfix_expression tuple_pattern + | VAR non_expression_pattern + ; + +binding_lhs : + identifier + | UNDERSCORE + ; + +paren_pattern : + paren_pattern_base + ; + +paren_pattern_base : + LEFT_PARENTHESIS paren_pattern_contents RIGHT_PARENTHESIS + | LEFT_PARENTHESIS paren_pattern_contents COMMA RIGHT_PARENTHESIS + ; + +paren_pattern_contents : + non_expression_pattern + | paren_expression_contents COMMA non_expression_pattern + | paren_pattern_contents COMMA expression + | paren_pattern_contents COMMA non_expression_pattern + ; + +tuple_pattern : + paren_pattern_base + ; + +maybe_empty_tuple_pattern : + LEFT_PARENTHESIS RIGHT_PARENTHESIS + | tuple_pattern + ; + +clause : + CASE pattern DOUBLE_ARROW block + | DEFAULT DOUBLE_ARROW block + ; + +clause_list : + /*empty*/ + | clause_list clause + ; + +statement : + assign_statement + | VAR pattern SEMICOLON + | VAR pattern EQUAL expression SEMICOLON + | RETURNED VAR variable_declaration SEMICOLON + | RETURNED VAR variable_declaration EQUAL expression SEMICOLON + | LET pattern EQUAL expression SEMICOLON + | statement_expression SEMICOLON + | if_statement + | WHILE LEFT_PARENTHESIS expression RIGHT_PARENTHESIS block + | BREAK SEMICOLON + | CONTINUE SEMICOLON + | RETURN return_expression SEMICOLON + | RETURN VAR SEMICOLON + | MATCH LEFT_PARENTHESIS expression RIGHT_PARENTHESIS LEFT_CURLY_BRACE clause_list RIGHT_CURLY_BRACE + | CONTINUATION identifier block + | RUN expression SEMICOLON + | AWAIT SEMICOLON + | FOR LEFT_PARENTHESIS variable_declaration IN type_expression RIGHT_PARENTHESIS block + ; + +assign_statement : + statement_expression assign_operator expression SEMICOLON + | PLUS_PLUS expression SEMICOLON + | MINUS_MINUS expression SEMICOLON + ; + +assign_operator : + EQUAL + | PLUS_EQUAL + | SLASH_EQUAL + | STAR_EQUAL + | PERCENT_EQUAL + | MINUS_EQUAL + | AMPERSAND_EQUAL + | PIPE_EQUAL + | CARET_EQUAL + | LESS_LESS_EQUAL + | GREATER_GREATER_EQUAL + ; + +if_statement : + IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS block optional_else + ; + +optional_else : + /*empty*/ + | ELSE if_statement + | ELSE block + ; + +return_expression : + /*empty*/ + | expression + ; + +statement_list : + /*empty*/ + | statement_list statement + ; + +block : + LEFT_CURLY_BRACE statement_list RIGHT_CURLY_BRACE + ; + +return_term : + /*empty*/ + | ARROW AUTO + | ARROW expression + ; + +generic_binding : + identifier COLON_BANG expression + | TEMPLATE identifier COLON_BANG expression + ; + +deduced_param : + generic_binding + | variable_declaration + | ADDR variable_declaration + ; + +deduced_param_list : + /*empty*/ + | deduced_param + | deduced_param_list COMMA deduced_param + ; + +deduced_params : + /*empty*/ + | LEFT_SQUARE_BRACKET deduced_param_list RIGHT_SQUARE_BRACKET + ; + +impl_deduced_params : + /*empty*/ + | FORALL LEFT_SQUARE_BRACKET deduced_param_list RIGHT_SQUARE_BRACKET + ; + +declared_name : + identifier + | declared_name PERIOD identifier + | LEFT_PARENTHESIS declared_name RIGHT_PARENTHESIS + ; + +fn_virtual_override_intro : + FN + | ABSTRACT FN + | VIRTUAL FN + | IMPL FN + ; + +function_declaration : + fn_virtual_override_intro declared_name deduced_params maybe_empty_tuple_pattern return_term block + | fn_virtual_override_intro declared_name deduced_params maybe_empty_tuple_pattern return_term SEMICOLON + ; + +variable_declaration : + identifier COLON pattern + ; + +alias_declaration : + ALIAS declared_name EQUAL expression SEMICOLON + ; + +mix_declaration : + MIX expression SEMICOLON + ; + +alternative : + identifier tuple + | identifier + ; + +alternative_list : + /*empty*/ + | alternative_list_contents + | alternative_list_contents COMMA + ; + +alternative_list_contents : + alternative + | alternative_list_contents COMMA alternative + ; + +type_params : + /*empty*/ + | tuple_pattern + ; + +mixin_import : + /*empty*/ + | FOR expression + ; + +class_declaration_extensibility : + /*empty*/ + | ABSTRACT + | BASE + ; + +class_declaration_extends : + /*empty*/ + | EXTENDS expression + ; + +declaration : + NAMESPACE declared_name SEMICOLON + | function_declaration + | destructor_declaration + | class_declaration_extensibility CLASS declared_name type_params class_declaration_extends LEFT_CURLY_BRACE class_body RIGHT_CURLY_BRACE + | MIXIN declared_name type_params mixin_import LEFT_CURLY_BRACE mixin_body RIGHT_CURLY_BRACE + | CHOICE declared_name type_params LEFT_CURLY_BRACE alternative_list RIGHT_CURLY_BRACE + | VAR variable_declaration SEMICOLON + | VAR variable_declaration EQUAL expression SEMICOLON + | LET variable_declaration EQUAL expression SEMICOLON + | INTERFACE declared_name type_params LEFT_CURLY_BRACE interface_body RIGHT_CURLY_BRACE + | CONSTRAINT declared_name type_params LEFT_CURLY_BRACE interface_body RIGHT_CURLY_BRACE + | impl_declaration + | match_first_declaration + | alias_declaration + ; + +impl_declaration : + impl_kind_intro impl_deduced_params impl_type AS type_or_where_expression LEFT_CURLY_BRACE impl_body RIGHT_CURLY_BRACE + ; + +impl_kind_intro : + IMPL + | EXTERNAL IMPL + ; + +impl_type : + /*empty*/ + | type_expression + ; + +match_first_declaration : + MATCH_FIRST LEFT_CURLY_BRACE match_first_declaration_list RIGHT_CURLY_BRACE + ; + +match_first_declaration_list : + /*empty*/ + | match_first_declaration_list impl_declaration + ; + +destructor_virtual_override_intro : + DESTRUCTOR + | VIRTUAL DESTRUCTOR + | IMPL DESTRUCTOR + ; + +destructor_declaration : + destructor_virtual_override_intro deduced_params block + ; + +declaration_list : + /*empty*/ + | declaration_list declaration + ; + +class_body : + /*empty*/ + | class_body declaration + | class_body mix_declaration + ; + +mixin_body : + /*empty*/ + | mixin_body function_declaration + | mixin_body mix_declaration + ; + +interface_body : + /*empty*/ + | interface_body function_declaration + | interface_body LET generic_binding SEMICOLON + | interface_body EXTENDS expression SEMICOLON + | interface_body IMPL impl_type AS type_or_where_expression SEMICOLON + ; + +impl_body : + /*empty*/ + | impl_body function_declaration + | impl_body alias_declaration + ; + +// Tokens +//\(\S+\)\s+"\([^"]+\)" +ABSTRACT : 'abstract' ; +ADDR : 'addr' ; +ALIAS : 'alias' ; +AMPERSAND : '&' ; +AMPERSAND_EQUAL : '&=' ; +AND : 'and' ; +API : 'api' ; +ARROW : '->' ; +AS : 'as' ; +AUTO : 'auto' ; +AWAIT : '__await' ; +BASE : 'base' ; +BOOL : 'bool' ; +BREAK : 'break' ; +CARET : '^' ; +CARET_EQUAL : '^=' ; +CASE : 'case' ; +CHOICE : 'choice' ; +CLASS : 'class' ; +COLON : ':' ; +COLON_BANG : ':!' ; +COMMA : ',' ; +CONSTRAINT : 'constraint' ; +CONTINUATION : '__continuation' ; +CONTINUATION_TYPE : '__Continuation' ; +CONTINUE : 'continue' ; +DEFAULT : 'default' ; +DESTRUCTOR : 'destructor' ; +DOUBLE_ARROW : '=>' ; +ELSE : 'else' ; +EQUAL : '=' ; +EQUAL_EQUAL : '==' ; +EXTENDS : 'extends' ; +EXTERNAL : 'external' ; +FALSE : 'false' ; +FN : 'fn' ; +FN_TYPE : '__Fn' ; +FOR : 'for' ; +FORALL : 'forall' ; +GREATER : '>' ; +GREATER_EQUAL : '>=' ; +GREATER_GREATER : '>>' ; +GREATER_GREATER_EQUAL : '>>=' ; +IF : 'if' ; +IMPL : 'impl' ; +IMPORT : 'import' ; +IN : 'in' ; +INTERFACE : 'interface' ; +IS : 'is' ; +LEFT_CURLY_BRACE : '{' ; +LEFT_PARENTHESIS : '(' ; +LEFT_SQUARE_BRACKET : '[' ; +LESS : '<' ; +LESS_EQUAL : '<=' ; +LESS_LESS : '<<' ; +LESS_LESS_EQUAL : '<<=' ; +LET : 'let' ; +LIBRARY : 'library' ; +MATCH : 'match' ; +MATCH_FIRST : '__match_first' ; +MINUS : '-' ; +MINUS_EQUAL : '-=' ; +MINUS_MINUS : '--' ; +MIX : '__mix' ; +MIXIN : '__mixin' ; +NAMESPACE : 'namespace' ; +NOT : 'not' ; +NOT_EQUAL : '!=' ; +OR : 'or' ; +PACKAGE : 'package' ; +PERCENT : '%' ; +PERCENT_EQUAL : '%=' ; +PERIOD : '.' ; +PIPE : '|' ; +PIPE_EQUAL : '|=' ; +PLUS : '+' ; +PLUS_EQUAL : '+=' ; +PLUS_PLUS : '++' ; +RETURN : 'return' ; +RETURNED : 'returned' ; +RIGHT_CURLY_BRACE : '}' ; +RIGHT_PARENTHESIS : ')' ; +RIGHT_SQUARE_BRACKET : ']' ; +RUN : '__run' ; +SELF : 'Self' ; +SEMICOLON : ';' ; +SLASH : '/' ; +SLASH_EQUAL : '/=' ; +STAR_EQUAL : '*=' ; +STRING : 'String' ; +TEMPLATE : 'template' ; +THEN : 'then' ; +TRUE : 'true' ; +TYPE : 'type' ; +UNDERSCORE : '_' ; +UNIMPL_EXAMPLE : '__unimplemented_example_infix' ; +VAR : 'var' ; +VIRTUAL : 'virtual' ; +WHERE : 'where' ; +WHILE : 'while' ; + +////==== +/* +The order of rules matter for the lexer, like the two rules bellow, +otherwise "intrinsic_identifier" will never be recognized +*/ +intrinsic_identifier : "Print|__intrinsic_[A-Za-z0-9_]*" ; +identifier : "[A-Za-z_][A-Za-z0-9_]*" ; +////==== + +sized_type_literal : "[iuf](0|[1-9][0-9]*)" ; +integer_literal : "0|[1-9][0-9]*" ; +string_literal : "\"(\\.|[^\"\n])*\"|'''(\\.|[^\'])*'''" ; + +BINARY_STAR : "\\*[[:space:]]+" ; +POSTFIX_STAR : "[[:space:]]+\\*[[:space:]]+" ; +PREFIX_STAR : "[[:space:]]+\\*" ; +UNARY_STAR : '*' ; + +} diff --git a/playground/carbon-lang.y b/playground/carbon-lang.y new file mode 100644 index 0000000..fc2eb5e --- /dev/null +++ b/playground/carbon-lang.y @@ -0,0 +1,737 @@ +/*Tokens*/ +%token END_OF_FILE +%token YYerror +%token YYUNDEF +%token integer_literal +%token identifier +%token intrinsic_identifier +%token sized_type_literal +%token string_literal +%token ABSTRACT +%token ADDR +%token ALIAS +%token AMPERSAND +%token AMPERSAND_EQUAL +%token AND +%token API +%token ARROW +%token AS +%token AUTO +%token AWAIT +%token BASE +%token BOOL +%token BREAK +%token CARET +%token CARET_EQUAL +%token CASE +%token CHOICE +%token CLASS +%token COLON +%token COLON_BANG +%token COMMA +%token CONSTRAINT +%token CONTINUATION +%token CONTINUATION_TYPE +%token CONTINUE +%token DEFAULT +%token DESTRUCTOR +%token DOUBLE_ARROW +%token ELSE +%token EQUAL +%token EQUAL_EQUAL +%token EXTENDS +%token EXTERNAL +%token FALSE +%token FN +%token FN_TYPE +%token FOR +%token FORALL +%token GREATER +%token GREATER_EQUAL +%token GREATER_GREATER +%token GREATER_GREATER_EQUAL +%token IF +%token IMPL +%token IMPORT +%token IN +%token INTERFACE +%token IS +%token LEFT_CURLY_BRACE +%token LEFT_PARENTHESIS +%token LEFT_SQUARE_BRACKET +%token LESS +%token LESS_EQUAL +%token LESS_LESS +%token LESS_LESS_EQUAL +%token LET +%token LIBRARY +%token MATCH +%token MATCH_FIRST +%token MINUS +%token MINUS_EQUAL +%token MINUS_MINUS +%token MIX +%token MIXIN +%token NAMESPACE +%token NOT +%token NOT_EQUAL +%token OR +%token OR_EQUAL +%token PACKAGE +%token PERCENT +%token PERCENT_EQUAL +%token PERIOD +%token PIPE +%token PIPE_EQUAL +%token PLUS +%token PLUS_EQUAL +%token PLUS_PLUS +%token RETURN +%token RETURNED +%token RIGHT_CURLY_BRACE +%token RIGHT_PARENTHESIS +%token RIGHT_SQUARE_BRACKET +%token RUN +%token SELF +%token SEMICOLON +%token SLASH +%token SLASH_EQUAL +%token STAR_EQUAL +%token STRING +%token TEMPLATE +%token THEN +%token TRUE +%token TYPE +%token UNDERSCORE +%token UNIMPL_EXAMPLE +%token VAR +%token VIRTUAL +%token WHERE +%token WHILE +%token FNARROW +%token UNARY_STAR +%token PREFIX_STAR +%token POSTFIX_STAR +%token BINARY_STAR + + +%start input + +%% + +input : + END_OF_FILE + | package_directive import_directives declaration_list + ; + +package_directive : + PACKAGE identifier optional_library_path api_or_impl SEMICOLON + ; + +import_directive : + IMPORT identifier optional_library_path SEMICOLON + ; + +import_directives : + /*empty*/ + | import_directives import_directive + ; + +optional_library_path : + /*empty*/ + | LIBRARY string_literal + ; + +api_or_impl : + API + | IMPL + ; + +primary_expression : + identifier + | designator + | PERIOD SELF + | integer_literal + | string_literal + | TRUE + | FALSE + | sized_type_literal + | SELF + | STRING + | BOOL + | TYPE + | CONTINUATION_TYPE + | paren_expression + | struct_literal + | struct_type_literal + | LEFT_SQUARE_BRACKET expression SEMICOLON expression RIGHT_SQUARE_BRACKET + ; + +postfix_expression : + primary_expression + | postfix_expression designator + | postfix_expression ARROW identifier + | postfix_expression PERIOD LEFT_PARENTHESIS expression RIGHT_PARENTHESIS + | postfix_expression ARROW LEFT_PARENTHESIS expression RIGHT_PARENTHESIS + | postfix_expression LEFT_SQUARE_BRACKET expression RIGHT_SQUARE_BRACKET + | intrinsic_identifier tuple + | postfix_expression tuple + | postfix_expression POSTFIX_STAR + | postfix_expression UNARY_STAR + ; + +ref_deref_expression : + postfix_expression + | PREFIX_STAR ref_deref_expression + | UNARY_STAR ref_deref_expression + | AMPERSAND ref_deref_expression + ; + +fn_type_expression : + FN_TYPE tuple ARROW type_expression + ; + +type_expression : + ref_deref_expression + | bitwise_and_expression + | fn_type_expression + ; + +minus_expression : + MINUS ref_deref_expression + ; + +complement_expression : + CARET ref_deref_expression + ; + +unary_expression : + minus_expression + | complement_expression + ; + +simple_binary_operand : + ref_deref_expression + | unary_expression + ; + +multiplicative_lhs : + simple_binary_operand + | multiplicative_expression + ; + +multiplicative_expression : + multiplicative_lhs BINARY_STAR simple_binary_operand + | multiplicative_lhs SLASH simple_binary_operand + ; + +additive_operand : + simple_binary_operand + | multiplicative_expression + ; + +additive_lhs : + simple_binary_operand + | additive_expression + ; + +additive_expression : + multiplicative_expression + | additive_lhs PLUS additive_operand + | additive_lhs MINUS additive_operand + ; + +modulo_expression : + simple_binary_operand PERCENT simple_binary_operand + ; + +bitwise_and_lhs : + simple_binary_operand + | bitwise_and_expression + ; + +bitwise_and_expression : + bitwise_and_lhs AMPERSAND simple_binary_operand + ; + +bitwise_or_lhs : + simple_binary_operand + | bitwise_or_expression + ; + +bitwise_or_expression : + bitwise_or_lhs PIPE simple_binary_operand + ; + +bitwise_xor_lhs : + simple_binary_operand + | bitwise_xor_expression + ; + +bitwise_xor_expression : + bitwise_xor_lhs CARET simple_binary_operand + ; + +bitwise_expression : + bitwise_and_expression + | bitwise_or_expression + | bitwise_xor_expression + ; + +bit_shift_expression : + simple_binary_operand LESS_LESS simple_binary_operand + | simple_binary_operand GREATER_GREATER simple_binary_operand + ; + +as_expression : + simple_binary_operand AS simple_binary_operand + ; + +unimpl_expression : + ref_deref_expression UNIMPL_EXAMPLE ref_deref_expression + ; + +value_expression : + additive_expression + | as_expression + | bitwise_expression + | bit_shift_expression + | fn_type_expression + | modulo_expression + | unary_expression + | unimpl_expression + ; + +comparison_operand : + ref_deref_expression + | value_expression + ; + +comparison_operator : + EQUAL_EQUAL + | LESS + | LESS_EQUAL + | GREATER + | GREATER_EQUAL + | NOT_EQUAL + ; + +comparison_expression : + value_expression + | comparison_operand comparison_operator comparison_operand + ; + +not_expression : + NOT ref_deref_expression + ; + +predicate_expression : + not_expression + | comparison_expression + ; + +and_or_operand : + ref_deref_expression + | predicate_expression + ; + +and_lhs : + and_or_operand + | and_expression + ; + +and_expression : + and_lhs AND and_or_operand + ; + +or_lhs : + and_or_operand + | or_expression + ; + +or_expression : + or_lhs OR and_or_operand + ; + +where_clause : + comparison_operand IS comparison_operand + | comparison_operand EQUAL_EQUAL comparison_operand + | designator EQUAL comparison_operand + ; + +where_clause_list : + where_clause + | where_clause_list AND where_clause + ; + +where_expression : + type_expression WHERE where_clause_list + ; + +type_or_where_expression : + type_expression + | where_expression + ; + +statement_expression : + ref_deref_expression + | predicate_expression + | and_expression + | or_expression + | where_expression + ; + +if_expression : + statement_expression + | IF expression THEN if_expression ELSE if_expression + ; + +expression : + if_expression + ; + +designator : + PERIOD identifier + | PERIOD BASE + ; + +paren_expression : + paren_expression_base + ; + +tuple : + paren_expression_base + ; + +paren_expression_base : + LEFT_PARENTHESIS RIGHT_PARENTHESIS + | LEFT_PARENTHESIS paren_expression_contents RIGHT_PARENTHESIS + | LEFT_PARENTHESIS paren_expression_contents COMMA RIGHT_PARENTHESIS + ; + +paren_expression_contents : + expression + | paren_expression_contents COMMA expression + ; + +struct_literal : + LEFT_CURLY_BRACE RIGHT_CURLY_BRACE + | LEFT_CURLY_BRACE struct_literal_contents RIGHT_CURLY_BRACE + | LEFT_CURLY_BRACE struct_literal_contents COMMA RIGHT_CURLY_BRACE + ; + +struct_literal_contents : + designator EQUAL expression + | struct_literal_contents COMMA designator EQUAL expression + ; + +struct_type_literal : + LEFT_CURLY_BRACE struct_type_literal_contents RIGHT_CURLY_BRACE + | LEFT_CURLY_BRACE struct_type_literal_contents COMMA RIGHT_CURLY_BRACE + ; + +struct_type_literal_contents : + designator COLON expression + | struct_type_literal_contents COMMA designator COLON expression + ; + +pattern : + non_expression_pattern + | expression + ; + +non_expression_pattern : + AUTO + | binding_lhs COLON pattern + | binding_lhs COLON_BANG expression + | TEMPLATE binding_lhs COLON_BANG expression + | paren_pattern + | postfix_expression tuple_pattern + | VAR non_expression_pattern + ; + +binding_lhs : + identifier + | UNDERSCORE + ; + +paren_pattern : + paren_pattern_base + ; + +paren_pattern_base : + LEFT_PARENTHESIS paren_pattern_contents RIGHT_PARENTHESIS + | LEFT_PARENTHESIS paren_pattern_contents COMMA RIGHT_PARENTHESIS + ; + +paren_pattern_contents : + non_expression_pattern + | paren_expression_contents COMMA non_expression_pattern + | paren_pattern_contents COMMA expression + | paren_pattern_contents COMMA non_expression_pattern + ; + +tuple_pattern : + paren_pattern_base + ; + +maybe_empty_tuple_pattern : + LEFT_PARENTHESIS RIGHT_PARENTHESIS + | tuple_pattern + ; + +clause : + CASE pattern DOUBLE_ARROW block + | DEFAULT DOUBLE_ARROW block + ; + +clause_list : + /*empty*/ + | clause_list clause + ; + +statement : + assign_statement + | VAR pattern SEMICOLON + | VAR pattern EQUAL expression SEMICOLON + | RETURNED VAR variable_declaration SEMICOLON + | RETURNED VAR variable_declaration EQUAL expression SEMICOLON + | LET pattern EQUAL expression SEMICOLON + | statement_expression SEMICOLON + | if_statement + | WHILE LEFT_PARENTHESIS expression RIGHT_PARENTHESIS block + | BREAK SEMICOLON + | CONTINUE SEMICOLON + | RETURN return_expression SEMICOLON + | RETURN VAR SEMICOLON + | MATCH LEFT_PARENTHESIS expression RIGHT_PARENTHESIS LEFT_CURLY_BRACE clause_list RIGHT_CURLY_BRACE + | CONTINUATION identifier block + | RUN expression SEMICOLON + | AWAIT SEMICOLON + | FOR LEFT_PARENTHESIS variable_declaration IN type_expression RIGHT_PARENTHESIS block + ; + +assign_statement : + statement_expression assign_operator expression SEMICOLON + | PLUS_PLUS expression SEMICOLON + | MINUS_MINUS expression SEMICOLON + ; + +assign_operator : + EQUAL + | PLUS_EQUAL + | SLASH_EQUAL + | STAR_EQUAL + | PERCENT_EQUAL + | MINUS_EQUAL + | AMPERSAND_EQUAL + | PIPE_EQUAL + | CARET_EQUAL + | LESS_LESS_EQUAL + | GREATER_GREATER_EQUAL + ; + +if_statement : + IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS block optional_else + ; + +optional_else : + /*empty*/ + | ELSE if_statement + | ELSE block + ; + +return_expression : + /*empty*/ + | expression + ; + +statement_list : + /*empty*/ + | statement_list statement + ; + +block : + LEFT_CURLY_BRACE statement_list RIGHT_CURLY_BRACE + ; + +return_term : + /*empty*/ + | ARROW AUTO + | ARROW expression + ; + +generic_binding : + identifier COLON_BANG expression + | TEMPLATE identifier COLON_BANG expression + ; + +deduced_param : + generic_binding + | variable_declaration + | ADDR variable_declaration + ; + +deduced_param_list : + /*empty*/ + | deduced_param + | deduced_param_list COMMA deduced_param + ; + +deduced_params : + /*empty*/ + | LEFT_SQUARE_BRACKET deduced_param_list RIGHT_SQUARE_BRACKET + ; + +impl_deduced_params : + /*empty*/ + | FORALL LEFT_SQUARE_BRACKET deduced_param_list RIGHT_SQUARE_BRACKET + ; + +declared_name : + identifier + | declared_name PERIOD identifier + | LEFT_PARENTHESIS declared_name RIGHT_PARENTHESIS + ; + +fn_virtual_override_intro : + FN + | ABSTRACT FN + | VIRTUAL FN + | IMPL FN + ; + +function_declaration : + fn_virtual_override_intro declared_name deduced_params maybe_empty_tuple_pattern return_term block + | fn_virtual_override_intro declared_name deduced_params maybe_empty_tuple_pattern return_term SEMICOLON + ; + +variable_declaration : + identifier COLON pattern + ; + +alias_declaration : + ALIAS declared_name EQUAL expression SEMICOLON + ; + +mix_declaration : + MIX expression SEMICOLON + ; + +alternative : + identifier tuple + | identifier + ; + +alternative_list : + /*empty*/ + | alternative_list_contents + | alternative_list_contents COMMA + ; + +alternative_list_contents : + alternative + | alternative_list_contents COMMA alternative + ; + +type_params : + /*empty*/ + | tuple_pattern + ; + +mixin_import : + /*empty*/ + | FOR expression + ; + +class_declaration_extensibility : + /*empty*/ + | ABSTRACT + | BASE + ; + +class_declaration_extends : + /*empty*/ + | EXTENDS expression + ; + +declaration : + NAMESPACE declared_name SEMICOLON + | function_declaration + | destructor_declaration + | class_declaration_extensibility CLASS declared_name type_params class_declaration_extends LEFT_CURLY_BRACE class_body RIGHT_CURLY_BRACE + | MIXIN declared_name type_params mixin_import LEFT_CURLY_BRACE mixin_body RIGHT_CURLY_BRACE + | CHOICE declared_name type_params LEFT_CURLY_BRACE alternative_list RIGHT_CURLY_BRACE + | VAR variable_declaration SEMICOLON + | VAR variable_declaration EQUAL expression SEMICOLON + | LET variable_declaration EQUAL expression SEMICOLON + | INTERFACE declared_name type_params LEFT_CURLY_BRACE interface_body RIGHT_CURLY_BRACE + | CONSTRAINT declared_name type_params LEFT_CURLY_BRACE interface_body RIGHT_CURLY_BRACE + | impl_declaration + | match_first_declaration + | alias_declaration + ; + +impl_declaration : + impl_kind_intro impl_deduced_params impl_type AS type_or_where_expression LEFT_CURLY_BRACE impl_body RIGHT_CURLY_BRACE + ; + +impl_kind_intro : + IMPL + | EXTERNAL IMPL + ; + +impl_type : + /*empty*/ + | type_expression + ; + +match_first_declaration : + MATCH_FIRST LEFT_CURLY_BRACE match_first_declaration_list RIGHT_CURLY_BRACE + ; + +match_first_declaration_list : + /*empty*/ + | match_first_declaration_list impl_declaration + ; + +destructor_virtual_override_intro : + DESTRUCTOR + | VIRTUAL DESTRUCTOR + | IMPL DESTRUCTOR + ; + +destructor_declaration : + destructor_virtual_override_intro deduced_params block + ; + +declaration_list : + /*empty*/ + | declaration_list declaration + ; + +class_body : + /*empty*/ + | class_body declaration + | class_body mix_declaration + ; + +mixin_body : + /*empty*/ + | mixin_body function_declaration + | mixin_body mix_declaration + ; + +interface_body : + /*empty*/ + | interface_body function_declaration + | interface_body LET generic_binding SEMICOLON + | interface_body EXTENDS expression SEMICOLON + | interface_body IMPL impl_type AS type_or_where_expression SEMICOLON + ; + +impl_body : + /*empty*/ + | impl_body function_declaration + | impl_body alias_declaration + ; diff --git a/playground/cfront3.g b/playground/cfront3.g new file mode 100644 index 0000000..6f0e40b --- /dev/null +++ b/playground/cfront3.g @@ -0,0 +1,808 @@ +cfront3 { + +%whitespace "[ \t\n\r]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +//%token EOFTOK +//%token ASM +//%token AUTO +//%token BREAK +//%token CASE +//%token CONTINUE +//%token DEFAULT +//%token DELETE +//%token DO +//%token ELSE +//%token ENUM +//%token FOR +//%token FORTRAN +//%token FRIEND +//%token GOTO +//%token IF +//%token NEW +//%token OPERATOR +//%token RETURN +//%token SIZEOF +//%token SWITCH +//%token THIS +//%token WHILE +//%token LP +//%token RP +//%token LB +//%token RB +//%token REF +//%token DOT +//%token NOT +//%token COMPL +//%token MUL +//%token AND +//%token PLUS +//%token MINUS +//%token LT +//%token GT +//%token ER +//%token OR +//%token ANDAND +//%token OROR +//%token QUEST +//%token COLON +//%token ASSIGN +//%token CM +//%token SM +//%token LC +//%token RC +//%token ID +//%token STRING +//%token ICON +//%token FCON +//%token CCON +//%token NAME +//%token ZERO +//%token ASOP +//%token RELOP +//%token EQUOP +//%token DIVOP +//%token SHIFTOP +//%token ICOP +//%token TYPE +//%token CATCH +//%token THROW +//%token TRY +//%token TNAME +//%token EMPTY +//%token NO_ID +//%token NO_EXPR +//%token FDEF +//%token ELLIPSIS +//%token AGGR +//%token MEM +//%token MEMPTR +//%token PR +//%token MEMQ +//%token TSCOPE +//%token DECL_MARKER +//%token REFMUL +//%token LDOUBLE +//%token LINKAGE +//%token TEMPLATE +//%token XVIRT +//%token XNLIST +//%token XILINE +//%token XIA +//%token SM_PARAM +//%token PTNAME +//%token NEW_INIT_KLUDGE +//%token XDELETED_NODE +//%token VEC_DELETE +//%token VEC_NEW +//%token DUMMY_LAST_NODE + +%left /*1*/ EMPTY ; +%left /*2*/ NO_ID ; +%left /*3*/ BREAK CASE CONTINUE DEFAULT DELETE DO ENUM FOR GOTO IF RETURN WHILE LC RC ID TYPE TNAME AGGR TSCOPE ; +%left /*4*/ NO_EXPR ; +%left /*5*/ CM ; +%right /*6*/ ASSIGN ASOP ; +%right /*7*/ QUEST COLON ; +%left /*8*/ OROR ; +%left /*9*/ ANDAND ; +%left /*10*/ OR ; +%left /*11*/ ER ; +%left /*12*/ AND ; +%left /*13*/ EQUOP ; +%left /*14*/ LT GT RELOP ; +%left /*15*/ SHIFTOP ; +%left /*16*/ PLUS MINUS ; +%left /*17*/ MUL DIVOP MEMPTR ; +%left /*18*/ REFMUL ; +%right /*19*/ NEW NOT COMPL ; +%right /*20*/ SIZEOF ICOP ; +%left /*21*/ LP LB REF DOT MEM ; + +//%start ext_def + +//%% + +ext_def : + external_def + | SM + | EOFTOK + | LINKAGE LC /*3L*/ + | RC /*3L*/ + | template + ; +template : + TEMPLATE LT /*14L*/ template_parm_list GT /*14L*/ template_def + ; +template_def : + data_dcl + | att_fct_def + | fct_def + | fct_dcl + | class_dcl SM + ; +identifier : + ID /*3L*/ + | qualified_tname + ; +external_def : + data_dcl + | att_fct_def + | fct_def + | fct_dcl + | ASM LP /*21L*/ STRING RP SM + ; +fct_dcl : + decl ASSIGN /*6R*/ initializer SM + | decl SM + ; +att_fct_def : + type decl arg_dcl_list check_inline base_init block + | type decl arg_dcl_list check_inline EMPTY /*1L*/ + | type decl arg_dcl_list check_inline NO_ID /*2L*/ + ; +fct_def : + decl arg_dcl_list check_inline base_init block + | decl arg_dcl_list check_inline EMPTY /*1L*/ + | decl arg_dcl_list check_inline NO_ID /*2L*/ + ; +inline_fct_def : + FDEF base_init block + ; +check_inline : + /*empty*/ + ; +base_init : + COLON /*7R*/ init_list + | /*empty*/ %prec EMPTY /*1L*/ + ; +init_list : + binit + | init_list CM /*5L*/ binit + ; +binit : + LP /*21L*/ elist RP + | ttag LP /*21L*/ elist RP + ; +arg_dcl_list : + arg_dcl_list data_dcl + | /*empty*/ %prec EMPTY /*1L*/ + ; +dl : + decl + ; +dl : + ID /*3L*/ COLON /*7R*/ e %prec CM /*5L*/ + | COLON /*7R*/ e %prec CM /*5L*/ + ; +dl : + decl ASSIGN /*6R*/ initializer + ; +decl_list : + dl + | decl_list CM /*5L*/ dl + ; +data_dcl : + type decl_list SM + | type SM + ; +lt : + LT /*14L*/ + ; +gt : + GT /*14L*/ + ; +tname : + qualified_tname + | qualified_tname lt temp_inst_parms gt + | NAME lt temp_inst_parms gt + ; +tp : + TYPE /*3L*/ + | LINKAGE + | tname %prec NO_ID /*2L*/ + | tn_list DECL_MARKER + | class_dcl + | enum_dcl + | DECL_MARKER + ; +type : + tp + | type TYPE /*3L*/ + | type tname %prec NO_ID /*2L*/ + | type class_dcl + | type enum_dcl + | type DECL_MARKER + ; +cm : + CM /*5L*/ + ; +temp_inst_parms : + temp_inst_parms cm temp_inst_parm + | temp_inst_parm + ; +new_decl2 : + /*empty*/ %prec NO_ID /*2L*/ + | arg_lp new_decl2 RP + | ptr new_decl2 %prec MUL /*17L*/ + | new_decl2 arg_list + | new_decl2 vec %prec LB /*21L*/ + ; +new_type2 : + type new_decl2 + ; +temp_inst_parm : + new_type2 + | e %prec GT /*14L*/ + ; +enumtag : + tag + | DECL_MARKER + | tn_list DECL_MARKER + ; +enum_dcl : + ENUM /*3L*/ LC /*3L*/ moe_list RC /*3L*/ + ; +enum_dcl : + ENUM /*3L*/ enumtag LC /*3L*/ moe_list RC /*3L*/ + | ENUM /*3L*/ enumtag + ; +moe_list : + moe + | moe_list CM /*5L*/ moe + ; +template_parm_list : + template_parm_list CM /*5L*/ template_parm + | template_parm + | /*empty*/ + ; +template_parm : + AGGR /*3L*/ identifier + | type formal_decl + ; +formal_decl : + ID /*3L*/ + | ptr formal_decl %prec MUL /*17L*/ + | formal_decl vec %prec LB /*21L*/ + | formal_decl arg_list + | arg_lp formal_decl RP + ; +moe : + ID /*3L*/ %prec NO_ID /*2L*/ + ; +moe : + ID /*3L*/ ASSIGN /*6R*/ e + | /*empty*/ + ; +class_dcl : + class_head cl_mem_list RC /*3L*/ inline_mem_defs + | AGGR /*3L*/ tag + | AGGR /*3L*/ qualified_tname lt temp_inst_parms gt + | AGGR /*3L*/ DECL_MARKER + ; +inline_mem_defs : + /*empty*/ + | inline_mem_defs inline_fct_def + ; +base_list : + COLON /*7R*/ base_unit_list + | /*empty*/ %prec EMPTY /*1L*/ + ; +base_unit_list : + base_unit + | base_unit_list CM /*5L*/ base_unit + ; +base_unit : + ttag + | PR ttag + | TYPE /*3L*/ ttag + | PR TYPE /*3L*/ ttag + | TYPE /*3L*/ PR ttag + ; +class_head : + AGGR /*3L*/ LC /*3L*/ + | AGGR /*3L*/ tag base_list LC /*3L*/ + | AGGR /*3L*/ qualified_tname lt temp_inst_parms gt base_list LC /*3L*/ + ; +tag : + ID /*3L*/ + | qualified_tname + ; +ttag : + ID /*3L*/ + | tname + ; +cl_mem_list : + cl_mem_list cl_mem + | /*empty*/ %prec EMPTY /*1L*/ + | cl_mem_list template + ; +cl_mem : + data_dcl + | att_fct_def SM + | fct_def SM + | fct_def + | att_fct_def + | fct_dcl + | PR COLON /*7R*/ + | scope_qualifiers fname SM + ; +fname : + ID /*3L*/ + | COMPL /*19R*/ TNAME /*3L*/ + | OPERATOR oper + | OPERATOR c_type + ; +oper : + PLUS /*16L*/ + | MINUS /*16L*/ + | MUL /*17L*/ + | AND /*12L*/ + | OR /*10L*/ + | ER /*11L*/ + | SHIFTOP /*15L*/ + | EQUOP /*13L*/ + | DIVOP /*17L*/ + | RELOP /*14L*/ + | LT /*14L*/ + | GT /*14L*/ + | ANDAND /*9L*/ + | OROR /*8L*/ + | LP /*21L*/ RP + | LB /*21L*/ RB + | NOT /*19R*/ + | COMPL /*19R*/ + | ICOP /*20R*/ + | ASOP /*6R*/ + | ASSIGN /*6R*/ + | NEW /*19R*/ + | NEW /*19R*/ LB /*21L*/ RB + | DELETE /*3L*/ + | DELETE /*3L*/ LB /*21L*/ RB + | REF /*21L*/ + | CM /*5L*/ + | REFMUL /*18L*/ + ; +scope_qualifiers : + tn_list + ; +tn_list : + tscope + | tn_list tscope + ; +qualified_tname : + tn_list TNAME /*3L*/ + | TNAME /*3L*/ + ; +fct_attributes : + /*empty*/ + | fct_attributes TYPE /*3L*/ + | fct_attributes THROW LP /*21L*/ type_list RP + ; +type_list : + tag + | type_list CM /*5L*/ tag + ; +decl : + decl arg_list + | decl LP /*21L*/ RP fct_attributes + | tname arg_list + | decl arg_lp elist RP + | tname LP /*21L*/ MUL /*17L*/ ID /*3L*/ RP arg_list + | tname LP /*21L*/ AND /*12L*/ ID /*3L*/ RP arg_list + | tname LP /*21L*/ elist RP + | tname LP /*21L*/ RP fct_attributes + | tname LP /*21L*/ MEMPTR /*17L*/ decl RP arg_list + | fname + | ID /*3L*/ DOT /*21L*/ fname + | scope_qualifiers fname + | scope_qualifiers ID /*3L*/ DOT /*21L*/ fname + | ptr decl %prec MUL /*17L*/ + | ptr tname %prec MUL /*17L*/ + | tname vec %prec LB /*21L*/ + | decl vec %prec LB /*21L*/ + | arg_lp decl RP + ; +arg_decl : + ID /*3L*/ + | ptr qualified_tname %prec MUL /*17L*/ + | /*empty*/ %prec NO_ID /*2L*/ + | ptr arg_decl %prec MUL /*17L*/ + | arg_decl vec %prec LB /*21L*/ + | arg_decl arg_list + | arg_lp arg_decl RP + ; +new_decl : + /*empty*/ %prec NO_ID /*2L*/ + | ptr new_decl %prec MUL /*17L*/ + | new_decl vec %prec LB /*21L*/ + ; +cast_decl : + /*empty*/ %prec NO_ID /*2L*/ + | ptr cast_decl %prec MUL /*17L*/ + | cast_decl vec %prec LB /*21L*/ + | LP /*21L*/ cast_decl RP arg_list + | LP /*21L*/ cast_decl RP vec + ; +c_decl : + /*empty*/ %prec NO_ID /*2L*/ + | ptr c_decl %prec MUL /*17L*/ + ; +stmt_list : + /*empty*/ + | stmt_list TEMPLATE + | stmt_list caselab_stmt + ; +caselab_stmt : + caselablist statement + ; +caselablist : + /*empty*/ + ; +condition : + LP /*21L*/ e RP + ; +block : + LC /*3L*/ stmt_list RC /*3L*/ + | LC /*3L*/ RC /*3L*/ + | LC /*3L*/ error RC /*3L*/ + ; +simple : + ee + | BREAK /*3L*/ + | CONTINUE /*3L*/ + | GOTO /*3L*/ ID /*3L*/ + ; +simple : + DO /*3L*/ caselab_stmt WHILE /*3L*/ condition + | ASM LP /*21L*/ STRING RP + ; +sm : + SM + ; +statement : + simple sm + | SM + | RETURN /*3L*/ e SM + | TYPE /*3L*/ STRING block + | data_dcl + | att_fct_def + | block + | IF /*3L*/ condition caselab_stmt + | IF /*3L*/ condition caselab_stmt ELSE caselab_stmt + | WHILE /*3L*/ condition caselab_stmt + ; +statement : + FOR /*3L*/ LP /*21L*/ caselab_stmt e SM e RP caselab_stmt + ; +statement : + SWITCH condition caselab_stmt + ; +statement : + ID /*3L*/ COLON /*7R*/ caselab_stmt + ; +statement : + TNAME /*3L*/ COLON /*7R*/ caselab_stmt + ; +statement : + CASE /*3L*/ e COLON /*7R*/ caselab_stmt + ; +statement : + DEFAULT /*3L*/ COLON /*7R*/ caselab_stmt + | TRY block handler_list + ; +handler_list : + /*empty*/ + | handler_list handler + ; +handler : + CATCH exception_type block + ; +exception_type : + arg_lp type arg_decl RP + | LP /*21L*/ ELLIPSIS RP + ; +elist : + ex_list + ; +ex_list : + initializer %prec CM /*5L*/ + | ex_list CM /*5L*/ initializer + ; +initializer : + e %prec CM /*5L*/ + | LC /*3L*/ elist RC /*3L*/ + ; +ee : + ee ASSIGN /*6R*/ ee + | ee PLUS /*16L*/ ee + | ee MINUS /*16L*/ ee + | ee MUL /*17L*/ ee + | ee AND /*12L*/ ee + | ee OR /*10L*/ ee + | ee ER /*11L*/ ee + | ee SHIFTOP /*15L*/ ee + | ee EQUOP /*13L*/ ee + | ee DIVOP /*17L*/ ee + | ee RELOP /*14L*/ ee + | ee GT /*14L*/ ee + | ee LT /*14L*/ ee + | ee ANDAND /*9L*/ ee + | ee OROR /*8L*/ ee + | ee ASOP /*6R*/ ee + | ee CM /*5L*/ ee + | ee QUEST /*7R*/ ee COLON /*7R*/ ee + | ee REFMUL /*18L*/ ee + | DELETE /*3L*/ term + | DELETE /*3L*/ LB /*21L*/ e RB term + | MEM /*21L*/ DELETE /*3L*/ term + | MEM /*21L*/ DELETE /*3L*/ LB /*21L*/ e RB term + | term + | THROW term + ; +e : + e ASSIGN /*6R*/ e + | e PLUS /*16L*/ e + | e MINUS /*16L*/ e + | e MUL /*17L*/ e + | e AND /*12L*/ e + | e OR /*10L*/ e + | e ER /*11L*/ e + | e SHIFTOP /*15L*/ e + | e EQUOP /*13L*/ e + | e DIVOP /*17L*/ e + | e RELOP /*14L*/ e + | e LT /*14L*/ e + | e GT /*14L*/ e + | e ANDAND /*9L*/ e + | e OROR /*8L*/ e + | e ASOP /*6R*/ e + | e CM /*5L*/ e + | e QUEST /*7R*/ e COLON /*7R*/ e + | e REFMUL /*18L*/ e + | DELETE /*3L*/ term + | DELETE /*3L*/ LB /*21L*/ e RB term + | MEM /*21L*/ DELETE /*3L*/ term + | MEM /*21L*/ DELETE /*3L*/ LB /*21L*/ e RB term + | term + | THROW term + | /*empty*/ %prec NO_EXPR /*4L*/ + ; +term : + NEW /*19R*/ cast_type + | NEW /*19R*/ new_type + | MEM /*21L*/ NEW /*19R*/ cast_type + | MEM /*21L*/ NEW /*19R*/ new_type + | term ICOP /*20R*/ + | cast_type term %prec ICOP /*20R*/ + | MUL /*17L*/ term + | AND /*12L*/ term + | MINUS /*16L*/ term + | PLUS /*16L*/ term + | NOT /*19R*/ term + | COMPL /*19R*/ term + | ICOP /*20R*/ term + | SIZEOF /*20R*/ term + | SIZEOF /*20R*/ cast_type %prec SIZEOF /*20R*/ + | term LB /*21L*/ e RB + | term REF /*21L*/ prim + | term REF /*21L*/ MEMQ prim + | term REF /*21L*/ MEMQ TNAME /*3L*/ + | term REF /*21L*/ dtorspec + | term REF /*21L*/ scope_qualifiers prim + | term REF /*21L*/ scope_qualifiers TNAME /*3L*/ + | term DOT /*21L*/ prim + | term DOT /*21L*/ MEMQ prim + | term DOT /*21L*/ MEMQ TNAME /*3L*/ + | term DOT /*21L*/ dtorspec + | term DOT /*21L*/ scope_qualifiers prim + | term DOT /*21L*/ scope_qualifiers TNAME /*3L*/ + | prim + | scope_qualifiers prim + | tn_list COMPL /*19R*/ tag + | tn_list COMPL /*19R*/ TYPE /*3L*/ + | term_elist + | term_lp e RP + | ZERO + | ICON + | FCON + | STRING + | CCON + | THIS + ; +dtorspec : + COMPL /*19R*/ tag + | MEMQ COMPL /*19R*/ tag + | TYPE /*3L*/ MEM /*21L*/ COMPL /*19R*/ TYPE /*3L*/ + | COMPL /*19R*/ TYPE /*3L*/ + | TYPE /*3L*/ MEM /*21L*/ COMPL /*19R*/ tag + | MEMQ COMPL /*19R*/ TYPE /*3L*/ + | tn_list COMPL /*19R*/ tag + | tn_list COMPL /*19R*/ TYPE /*3L*/ + ; +term_elist : + TYPE /*3L*/ LP /*21L*/ elist RP + | tname LP /*21L*/ elist RP + | NEW /*19R*/ term_lp elist RP cast_type + | NEW /*19R*/ term_lp elist RP new_type + | MEM /*21L*/ NEW /*19R*/ term_lp elist RP cast_type + | MEM /*21L*/ NEW /*19R*/ term_lp elist RP new_type + | term LP /*21L*/ elist RP + ; +ptname : + PTNAME lt temp_inst_parms gt + ; +tscope : + TSCOPE /*3L*/ + | MEM /*21L*/ + | ptname TSCOPE /*3L*/ + ; +prim : + ID /*3L*/ + | OPERATOR oper + | OPERATOR c_type + ; +cast_type : + term_lp type cast_decl RP + ; +term_lp : + LP /*21L*/ + ; +c_tp : + TYPE /*3L*/ + | tname + | c_tp TYPE /*3L*/ + | c_tp tname + ; +c_type : + c_tp c_decl + ; +new_type : + type new_decl + ; +arg_type : + type arg_decl + ; +arg_type : + type arg_decl ASSIGN /*6R*/ initializer + ; +arg_lp : + LP /*21L*/ + ; +arg_list : + arg_lp arg_type_list ellipsis_opt RP fct_attributes + ; +arg_type_list : + arg_type_list CM /*5L*/ at + | at %prec CM /*5L*/ + ; +at : + arg_type + | /*empty*/ %prec EMPTY /*1L*/ + ; +ellipsis_opt : + /*empty*/ + | ELLIPSIS + | CM /*5L*/ ELLIPSIS + ; +ptr : + MUL /*17L*/ %prec NO_ID /*2L*/ + | AND /*12L*/ %prec NO_ID /*2L*/ + | MUL /*17L*/ TYPE /*3L*/ %prec NO_ID /*2L*/ + | ptr TYPE /*3L*/ %prec NO_ID /*2L*/ + | AND /*12L*/ TYPE /*3L*/ %prec NO_ID /*2L*/ + | ptname MEMPTR /*17L*/ %prec NO_ID /*2L*/ + | MEMPTR /*17L*/ %prec NO_ID /*2L*/ + | ptname MEMPTR /*17L*/ TYPE /*3L*/ %prec NO_ID /*2L*/ + | MEMPTR /*17L*/ TYPE /*3L*/ %prec NO_ID /*2L*/ + ; +vec : + LB /*21L*/ e RB + | NOT /*19R*/ %prec LB /*21L*/ + ; + +//Lexer + +//lalr (\d+:\d+): ERROR: undefined symbol '\([^']+\)' +EMPTY : 'EMPTY' ; +NO_ID : 'NO_ID' ; +BREAK : 'break' ; +CASE : 'case' ; +CONTINUE : 'continue' ; +DEFAULT : 'default' ; +DELETE : 'delete' ; +DO : 'do' ; +ENUM : 'enum' ; +FOR : 'for' ; +GOTO : 'goto' ; +IF : 'if' ; +RETURN : 'return' ; +WHILE : 'while' ; +LC : '{' ; +RC : '}' ; +ID : "[a-zA-Z_][a-zA-Z_0-9]*" ; +TYPE : 'TYPE' ; +TNAME : 'TNAME' ; +AGGR : 'AGGR' ; +TSCOPE : 'TSCOPE' ; +CM : ',' ; +ASSIGN : '=' ; +ASOP : 'ASOP' ; +QUEST : '?' ; +COLON : ':' ; +OROR : '||' ; +ANDAND : '&&' ; +OR : '|' ; +ER : '^' ; +AND : '&' ; +EQUOP : '==' ; +LT : '<' ; +GT : '>' ; +RELOP : 'RELOP' ; +SHIFTOP : 'SHIFTOP' ; +PLUS : '+' ; +MINUS : '-' ; +MUL : '*' ; +DIVOP : '/' ; +MEMPTR : 'MEMPTR' ; +REFMUL : 'REFMUL' ; +NEW : 'new' ; +NOT : '!' ; +COMPL : '~' ; +SIZEOF : 'sizeof' ; +ICOP : 'ICOP' ; +LP : ')' ; +LB : '[' ; +REF : 'REF' ; +DOT : '.' ; +MEM : 'MEM' ; +SM : ';' ; +EOFTOK : 'EOFTOK' ; +LINKAGE : 'LINKAGE' ; +TEMPLATE : 'template' ; +ASM : 'asm' ; +STRING : "\"(\\.|[^\"\n])*\"" ; +RP : '(' ; +FDEF : 'FDEF' ; +NAME : 'NAME' ; +DECL_MARKER : 'DECL_MARKER' ; +PR : 'PR' ; +OPERATOR : 'operator' ; +RB : ']' ; +THROW : 'throw' ; +ELSE : 'else' ; +SWITCH : 'switch' ; +TRY : 'try' ; +CATCH : 'catch' ; +ELLIPSIS : '...' ; +MEMQ : 'MEMQ' ; +ZERO : 'ZERO' ; +ICON : 'ICON' ; +FCON : 'FCON' ; +CCON : 'CCON' ; +THIS : 'this' ; +PTNAME : 'PTNAME' ; + +} diff --git a/playground/cobalt-css-parser.g b/playground/cobalt-css-parser.g new file mode 100644 index 0000000..140081e --- /dev/null +++ b/playground/cobalt-css-parser.g @@ -0,0 +1,2650 @@ +//From: https://github.com/youtube/cobalt/blob/main/cobalt/css_parser/grammar.y + +cobalt_css { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token kEndOfFileToken +//%token YYerror +//%token YYUNDEF +//%token kMediaListEntryPointToken +//%token kMediaQueryEntryPointToken +//%token kStyleSheetEntryPointToken +//%token kRuleEntryPointToken +//%token kStyleDeclarationListEntryPointToken +//%token kFontFaceDeclarationListEntryPointToken +//%token kPropertyValueEntryPointToken +//%token kPropertyIntoDeclarationDataEntryPointToken +//%token kWhitespaceToken +//%token kSgmlCommentDelimiterToken +//%token kCommentToken +//%token kImportantToken +//%token kAllToken +//%token kAlignContentToken +//%token kAlignItemsToken +//%token kAlignSelfToken +//%token kAnimationDelayToken +//%token kAnimationDirectionToken +//%token kAnimationDurationToken +//%token kAnimationFillModeToken +//%token kAnimationIterationCountToken +//%token kAnimationNameToken +//%token kAnimationTimingFunctionToken +//%token kAnimationToken +//%token kBackgroundColorToken +//%token kBackgroundImageToken +//%token kBackgroundPositionToken +//%token kBackgroundRepeatToken +//%token kBackgroundSizeToken +//%token kBackgroundToken +//%token kBorderToken +//%token kBorderBottomLeftRadiusToken +//%token kBorderBottomRightRadiusToken +//%token kBorderBottomToken +//%token kBorderBottomColorToken +//%token kBorderBottomStyleToken +//%token kBorderBottomWidthToken +//%token kBorderColorToken +//%token kBorderLeftToken +//%token kBorderLeftColorToken +//%token kBorderLeftStyleToken +//%token kBorderLeftWidthToken +//%token kBorderRadiusToken +//%token kBorderRightToken +//%token kBorderRightColorToken +//%token kBorderRightStyleToken +//%token kBorderRightWidthToken +//%token kBorderStyleToken +//%token kBorderTopToken +//%token kBorderTopColorToken +//%token kBorderTopLeftRadiusToken +//%token kBorderTopRightRadiusToken +//%token kBorderTopStyleToken +//%token kBorderTopWidthToken +//%token kBorderWidthToken +//%token kBottomToken +//%token kBoxShadowToken +//%token kColorToken +//%token kContentToken +//%token kDisplayToken +//%token kFilterToken +//%token kFlexToken +//%token kFlexBasisToken +//%token kFlexDirectionToken +//%token kFlexFlowToken +//%token kFlexGrowToken +//%token kFlexShrinkToken +//%token kFlexWrapToken +//%token kFontToken +//%token kFontFamilyToken +//%token kFontSizeToken +//%token kFontStyleToken +//%token kFontWeightToken +//%token kHeightToken +//%token kIntersectionObserverRootMarginToken +//%token kJustifyContentToken +//%token kLeftToken +//%token kLineHeightToken +//%token kMarginBottomToken +//%token kMarginLeftToken +//%token kMarginRightToken +//%token kMarginToken +//%token kMarginTopToken +//%token kMaxHeightToken +//%token kMaxWidthToken +//%token kMinHeightToken +//%token kMinWidthToken +//%token kOpacityToken +//%token kOrderToken +//%token kOutlineToken +//%token kOutlineColorToken +//%token kOutlineStyleToken +//%token kOutlineWidthToken +//%token kOverflowToken +//%token kOverflowWrapToken +//%token kPaddingBottomToken +//%token kPaddingLeftToken +//%token kPaddingRightToken +//%token kPaddingToken +//%token kPaddingTopToken +//%token kPointerEventsToken +//%token kPositionToken +//%token kRightToken +//%token kSrcToken +//%token kTextAlignToken +//%token kTextDecorationToken +//%token kTextDecorationColorToken +//%token kTextDecorationLineToken +//%token kTextIndentToken +//%token kTextOverflowToken +//%token kTextShadowToken +//%token kTextTransformToken +//%token kTopToken +//%token kTransformToken +//%token kTransformOriginToken +//%token kTransitionDelayToken +//%token kTransitionDurationToken +//%token kTransitionPropertyToken +//%token kTransitionTimingFunctionToken +//%token kTransitionToken +//%token kUnicodeRangePropertyToken +//%token kVerticalAlignToken +//%token kVisibilityToken +//%token kWhiteSpacePropertyToken +//%token kWidthToken +//%token kWordWrapToken +//%token kZIndexToken +//%token kAbsoluteToken +//%token kAlternateToken +//%token kAlternateReverseToken +//%token kAquaToken +//%token kAtToken +//%token kAutoToken +//%token kBackwardsToken +//%token kBaselineToken +//%token kBlackToken +//%token kBlockToken +//%token kBlueToken +//%token kBoldToken +//%token kBothToken +//%token kBreakWordToken +//%token kCenterToken +//%token kCircleToken +//%token kClipToken +//%token kClosestCornerToken +//%token kClosestSideToken +//%token kCollapseToken +//%token kColumnToken +//%token kColumnReverseToken +//%token kContainToken +//%token kCoverToken +//%token kCursiveToken +//%token kEaseInOutToken +//%token kEaseInToken +//%token kEaseOutToken +//%token kEaseToken +//%token kEllipseToken +//%token kEllipsisToken +//%token kEndToken +//%token kEquirectangularToken +//%token kFantasyToken +//%token kFarthestCornerToken +//%token kFarthestSideToken +//%token kFixedToken +//%token kFlexEndToken +//%token kFlexStartToken +//%token kForwardsToken +//%token kFromToken +//%token kFuchsiaToken +//%token kGrayToken +//%token kGreenToken +//%token kHiddenToken +//%token kInfiniteToken +//%token kInheritToken +//%token kInitialToken +//%token kInlineBlockToken +//%token kInlineToken +//%token kInlineFlexToken +//%token kInsetToken +//%token kItalicToken +//%token kLimeToken +//%token kLinearToken +//%token kLineThroughToken +//%token kMaroonToken +//%token kMiddleToken +//%token kMonoscopicToken +//%token kMonospaceToken +//%token kNavyToken +//%token kNoneToken +//%token kNoRepeatToken +//%token kNormalToken +//%token kNowrapToken +//%token kObliqueToken +//%token kOliveToken +//%token kPreToken +//%token kPreLineToken +//%token kPreWrapToken +//%token kPurpleToken +//%token kRectangularToken +//%token kRedToken +//%token kRepeatToken +//%token kRepeatXToken +//%token kRepeatYToken +//%token kRelativeToken +//%token kReverseToken +//%token kRowToken +//%token kRowReverseToken +//%token kSansSerifToken +//%token kScrollToken +//%token kSerifToken +//%token kSilverToken +//%token kSolidToken +//%token kSpaceAroundToken +//%token kSpaceBetweenToken +//%token kStartToken +//%token kStaticToken +//%token kStepEndToken +//%token kStepStartToken +//%token kStereoscopicLeftRightToken +//%token kStereoscopicTopBottomToken +//%token kStretchToken +//%token kTealToken +//%token kToToken +//%token kTransparentToken +//%token kUppercaseToken +//%token kVisibleToken +//%token kWhiteToken +//%token kWrapToken +//%token kWrapReverseToken +//%token kYellowToken +//%token kActiveToken +//%token kEmptyToken +//%token kFocusToken +//%token kHoverToken +//%token kAfterToken +//%token kBeforeToken +//%token kIncludesToken +//%token kDashMatchToken +//%token kBeginsWithToken +//%token kEndsWithToken +//%token kContainsToken +//%token kMediaAndToken +//%token kMediaNotToken +//%token kMediaOnlyToken +//%token kMediaMinimumToken +//%token kMediaMaximumToken +//%token kAllMediaTypeToken +//%token kTVMediaTypeToken +//%token kScreenMediaTypeToken +//%token kLengthMediaFeatureTypeToken +//%token kOrientationMediaFeatureTypeToken +//%token kRatioMediaFeatureTypeToken +//%token kNonNegativeIntegerMediaFeatureTypeToken +//%token kResolutionMediaFeatureTypeToken +//%token kScanMediaFeatureTypeToken +//%token kZeroOrOneMediaFeatureTypeToken +//%token kInterlaceMediaFeatureKeywordValueToken +//%token kLandscapeMediaFeatureKeywordValueToken +//%token kPortraitMediaFeatureKeywordValueToken +//%token kProgressiveMediaFeatureKeywordValueToken +//%token kSupportsAndToken +//%token kSupportsNotToken +//%token kSupportsOrToken +//%token kImportToken +//%token kKeyframesToken +//%token kPageToken +//%token kMediaToken +//%token kFontFaceToken +//%token kCharsetToken +//%token kNamespaceToken +//%token kSupportsToken +//%token kTopLeftCornerToken +//%token kTopLeftToken +//%token kTopCenterToken +//%token kTopRightToken +//%token kTopRightCornerToken +//%token kBottomLeftCornerToken +//%token kBottomLeftToken +//%token kBottomCenterToken +//%token kBottomRightToken +//%token kBottomRightCornerToken +//%token kLeftTopToken +//%token kLeftMiddleToken +//%token kLeftBottomToken +//%token kRightTopToken +//%token kRightMiddleToken +//%token kRightBottomToken +//%token kCalcFunctionToken +//%token kCubicBezierFunctionToken +//%token kCueFunctionToken +//%token kFormatFunctionToken +//%token kHslFunctionToken +//%token kHslaFunctionToken +//%token kLinearGradientFunctionToken +//%token kLocalFunctionToken +//%token kMapToMeshFunctionToken +//%token kMatrixFunctionToken +//%token kMatrix3dFunctionToken +//%token kNotFunctionToken +//%token kNthChildFunctionToken +//%token kNthLastChildFunctionToken +//%token kNthLastOfTypeFunctionToken +//%token kNthOfTypeFunctionToken +//%token kRotateFunctionToken +//%token kScaleFunctionToken +//%token kScaleXFunctionToken +//%token kScaleYFunctionToken +//%token kStepsFunctionToken +//%token kTranslateFunctionToken +//%token kTranslateXFunctionToken +//%token kTranslateYFunctionToken +//%token kTranslateZFunctionToken +//%token kRadialGradientFunctionToken +//%token kRGBFunctionToken +//%token kRGBAFunctionToken +//%token kCobaltMtmFunctionToken +//%token kCobaltUiNavFocusTransformFunctionToken +//%token kCobaltUiNavSpotlightTransformFunctionToken +//%token kStringToken +//%token kIdentifierToken +//%token kNthToken +//%token kHexToken +//%token kIdSelectorToken +//%token kUriToken +//%token kInvalidFunctionToken +//%token kInvalidNumberToken +//%token kInvalidDimensionToken +//%token kInvalidAtBlockToken +//%token kOtherBrowserAtBlockToken +//%token kIntegerToken +//%token kRealToken +//%token kPercentageToken +//%token kRootElementFontSizesAkaRemToken +//%token kZeroGlyphWidthsAkaChToken +//%token kFontSizesAkaEmToken +//%token kXHeightsAkaExToken +//%token kPixelsToken +//%token kCentimetersToken +//%token kMillimetersToken +//%token kInchesToken +//%token kPointsToken +//%token kPicasToken +//%token kDegreesToken +//%token kRadiansToken +//%token kGradiansToken +//%token kTurnsToken +//%token kMillisecondsToken +//%token kSecondsToken +//%token kHertzToken +//%token kKilohertzToken +//%token kViewportWidthPercentsAkaVwToken +//%token kViewportHeightPercentsAkaVhToken +//%token kViewportSmallerSizePercentsAkaVminToken +//%token kViewportLargerSizePercentsAkaVmaxToken +//%token kDotsPerPixelToken +//%token kDotsPerInchToken +//%token kDotsPerCentimeterToken +//%token kFractionsToken +//%token kUnicodeRangeToken +//%token '{' +//%token '}' +//%token '(' +//%token ')' +//%token ',' +//%token '*' +//%token '=' +//%token '[' +//%token ']' +//%token '.' +//%token ':' +//%token '>' +//%token '+' +//%token '~' +//%token '-' +//%token '/' +//%token ';' + + +//%start entry_point + +//%% + +entry_point : + kEndOfFileToken + ; + +maybe_whitespace : + /*empty*/ + | maybe_whitespace kWhitespaceToken + ; + +errors : + error + | errors error + ; + +at_font_face_rule : + kFontFaceToken maybe_whitespace '{' maybe_whitespace font_face_declaration_list '}' maybe_whitespace + ; + +at_media_rule : + kMediaToken maybe_whitespace media_list rule_list_block + ; + +orientation_media_feature_keyword_value : + kLandscapeMediaFeatureKeywordValueToken maybe_whitespace + | kPortraitMediaFeatureKeywordValueToken maybe_whitespace + ; + +scan_media_feature_keyword_value : + kInterlaceMediaFeatureKeywordValueToken maybe_whitespace + | kProgressiveMediaFeatureKeywordValueToken maybe_whitespace + ; + +media_feature_operator : + kMediaMinimumToken + | kMediaMaximumToken + ; + +media_feature_without_value : + kLengthMediaFeatureTypeToken maybe_whitespace + | kOrientationMediaFeatureTypeToken maybe_whitespace + | kRatioMediaFeatureTypeToken maybe_whitespace + | kNonNegativeIntegerMediaFeatureTypeToken maybe_whitespace + | kResolutionMediaFeatureTypeToken maybe_whitespace + | kScanMediaFeatureTypeToken maybe_whitespace + | kZeroOrOneMediaFeatureTypeToken maybe_whitespace + ; + +media_feature_with_value : + kOrientationMediaFeatureTypeToken maybe_whitespace colon orientation_media_feature_keyword_value + | kScanMediaFeatureTypeToken maybe_whitespace colon scan_media_feature_keyword_value + | kZeroOrOneMediaFeatureTypeToken maybe_whitespace colon zero_or_one + ; + +media_feature_allowing_operator_with_value : + kLengthMediaFeatureTypeToken maybe_whitespace colon length + | kNonNegativeIntegerMediaFeatureTypeToken maybe_whitespace colon non_negative_integer + | kRatioMediaFeatureTypeToken maybe_whitespace colon ratio + | kResolutionMediaFeatureTypeToken maybe_whitespace colon resolution + ; + +media_feature : + media_feature_without_value + | media_feature_with_value + | media_feature_allowing_operator_with_value + | media_feature_operator media_feature_allowing_operator_with_value + ; + +media_feature_block : + '(' maybe_whitespace media_feature ')' maybe_whitespace + ; + +media_feature_list : + media_feature_block + | media_feature_list kMediaAndToken maybe_whitespace media_feature_block + ; + +media_type_unknown : + kIdentifierToken + | kMediaAndToken + | kMediaMinimumToken + | kMediaMaximumToken + | kLengthMediaFeatureTypeToken + | kOrientationMediaFeatureTypeToken + | kRatioMediaFeatureTypeToken + | kNonNegativeIntegerMediaFeatureTypeToken + | kResolutionMediaFeatureTypeToken + | kScanMediaFeatureTypeToken + | kZeroOrOneMediaFeatureTypeToken + ; + +media_type_known : + kAllMediaTypeToken + | kTVMediaTypeToken + | kScreenMediaTypeToken + ; + +media_type_specified : + media_type_unknown + | media_type_known + ; + +evaluated_media_type : + media_type_specified + | kMediaNotToken kWhitespaceToken media_type_specified + | kMediaOnlyToken kWhitespaceToken media_type_specified + | kMediaOnlyToken kWhitespaceToken kMediaNotToken + | kMediaNotToken kWhitespaceToken kMediaOnlyToken + ; + +media_query : + /*empty*/ + | media_feature_list + | evaluated_media_type maybe_whitespace + | evaluated_media_type maybe_whitespace kMediaAndToken maybe_whitespace media_feature_list + | errors + ; + +media_list : + media_query + | media_list comma media_query + ; + +at_keyframes_rule : + kKeyframesToken maybe_whitespace kIdentifierToken maybe_whitespace '{' maybe_whitespace keyframe_rule_list '}' maybe_whitespace + ; + +keyframe_rule_list : + keyframe_rule + | error + | keyframe_rule_list keyframe_rule + ; + +keyframe_rule : + keyframe_selector style_declaration_block + ; + +keyframe_selector : + keyframe_offset + | keyframe_selector ',' maybe_whitespace keyframe_offset + ; + +keyframe_offset : + kFromToken maybe_whitespace + | kToToken maybe_whitespace + | kPercentageToken maybe_whitespace + ; + +identifier_token : + kIdentifierToken + | kAllToken + | kAlignContentToken + | kAlignItemsToken + | kAlignSelfToken + | kAnimationDelayToken + | kAnimationDirectionToken + | kAnimationDurationToken + | kAnimationFillModeToken + | kAnimationIterationCountToken + | kAnimationNameToken + | kAnimationTimingFunctionToken + | kAnimationToken + | kBackgroundColorToken + | kBackgroundImageToken + | kBackgroundPositionToken + | kBackgroundRepeatToken + | kBackgroundSizeToken + | kBackgroundToken + | kBorderToken + | kBorderBottomLeftRadiusToken + | kBorderBottomRightRadiusToken + | kBorderBottomToken + | kBorderBottomColorToken + | kBorderBottomStyleToken + | kBorderBottomWidthToken + | kBorderLeftToken + | kBorderColorToken + | kBorderLeftColorToken + | kBorderLeftStyleToken + | kBorderLeftWidthToken + | kBorderRadiusToken + | kBorderRightToken + | kBorderRightColorToken + | kBorderRightStyleToken + | kBorderRightWidthToken + | kBorderStyleToken + | kBorderTopToken + | kBorderTopColorToken + | kBorderTopLeftRadiusToken + | kBorderTopRightRadiusToken + | kBorderTopStyleToken + | kBorderTopWidthToken + | kBorderWidthToken + | kBottomToken + | kBoxShadowToken + | kColorToken + | kContentToken + | kDisplayToken + | kFilterToken + | kFlexToken + | kFlexBasisToken + | kFlexDirectionToken + | kFlexFlowToken + | kFlexGrowToken + | kFlexShrinkToken + | kFlexWrapToken + | kFontToken + | kFontFamilyToken + | kFontSizeToken + | kFontStyleToken + | kFontWeightToken + | kHeightToken + | kIntersectionObserverRootMarginToken + | kJustifyContentToken + | kLeftToken + | kLineHeightToken + | kMarginBottomToken + | kMarginLeftToken + | kMarginRightToken + | kMarginToken + | kMarginTopToken + | kMaxHeightToken + | kMaxWidthToken + | kMinHeightToken + | kMinWidthToken + | kOpacityToken + | kOrderToken + | kOutlineToken + | kOutlineColorToken + | kOutlineStyleToken + | kOutlineWidthToken + | kOverflowToken + | kOverflowWrapToken + | kPaddingBottomToken + | kPaddingLeftToken + | kPaddingRightToken + | kPaddingToken + | kPaddingTopToken + | kPointerEventsToken + | kPositionToken + | kRightToken + | kSrcToken + | kTextAlignToken + | kTextDecorationToken + | kTextDecorationColorToken + | kTextDecorationLineToken + | kTextIndentToken + | kTextOverflowToken + | kTextShadowToken + | kTextTransformToken + | kTopToken + | kTransformToken + | kTransformOriginToken + | kTransitionDelayToken + | kTransitionDurationToken + | kTransitionPropertyToken + | kTransitionTimingFunctionToken + | kTransitionToken + | kUnicodeRangePropertyToken + | kVerticalAlignToken + | kVisibilityToken + | kWhiteSpacePropertyToken + | kWidthToken + | kWordWrapToken + | kZIndexToken + | kAbsoluteToken + | kAlternateToken + | kAlternateReverseToken + | kAquaToken + | kAtToken + | kAutoToken + | kBackwardsToken + | kBaselineToken + | kBlackToken + | kBlockToken + | kBlueToken + | kBoldToken + | kBothToken + | kBreakWordToken + | kCenterToken + | kCircleToken + | kClipToken + | kClosestCornerToken + | kClosestSideToken + | kCollapseToken + | kColumnToken + | kColumnReverseToken + | kContainToken + | kCoverToken + | kCursiveToken + | kEaseInOutToken + | kEaseInToken + | kEaseOutToken + | kEaseToken + | kEllipseToken + | kEllipsisToken + | kEndToken + | kEquirectangularToken + | kFantasyToken + | kFarthestCornerToken + | kFarthestSideToken + | kFixedToken + | kFlexEndToken + | kFlexStartToken + | kForwardsToken + | kFromToken + | kFuchsiaToken + | kGrayToken + | kGreenToken + | kHiddenToken + | kInfiniteToken + | kInheritToken + | kInitialToken + | kInlineBlockToken + | kInlineToken + | kInlineFlexToken + | kInsetToken + | kItalicToken + | kLimeToken + | kLinearToken + | kLineThroughToken + | kMaroonToken + | kMiddleToken + | kMonoscopicToken + | kMonospaceToken + | kNavyToken + | kNoneToken + | kNoRepeatToken + | kNormalToken + | kNowrapToken + | kObliqueToken + | kOliveToken + | kPreToken + | kPreLineToken + | kPreWrapToken + | kPurpleToken + | kRedToken + | kRepeatToken + | kRepeatXToken + | kRepeatYToken + | kRelativeToken + | kReverseToken + | kRowToken + | kRowReverseToken + | kSansSerifToken + | kScrollToken + | kSerifToken + | kSilverToken + | kSolidToken + | kSpaceAroundToken + | kSpaceBetweenToken + | kStartToken + | kStaticToken + | kStepEndToken + | kStepStartToken + | kStereoscopicLeftRightToken + | kStereoscopicTopBottomToken + | kStretchToken + | kTealToken + | kToToken + | kTransparentToken + | kUppercaseToken + | kVisibleToken + | kWhiteToken + | kWrapToken + | kWrapReverseToken + | kYellowToken + | kActiveToken + | kEmptyToken + | kFocusToken + | kHoverToken + | kAfterToken + | kBeforeToken + ; + +universal_selector_token : + '*' + ; + +type_selector_token : + identifier_token + ; + +attribute_match : + '=' maybe_whitespace + | kIncludesToken maybe_whitespace + | kDashMatchToken maybe_whitespace + | kBeginsWithToken maybe_whitespace + | kEndsWithToken maybe_whitespace + | kContainsToken maybe_whitespace + ; + +attribute_selector_token : + '[' maybe_whitespace identifier_token maybe_whitespace ']' + | '[' maybe_whitespace identifier_token maybe_whitespace attribute_match kStringToken maybe_whitespace ']' + | '[' maybe_whitespace identifier_token maybe_whitespace attribute_match identifier_token maybe_whitespace ']' + ; + +class_selector_token : + '.' identifier_token + ; + +id_selector_token : + kIdSelectorToken + | kHexToken + ; + +pseudo_class_token : + ':' kActiveToken + | ':' kEmptyToken + | ':' kFocusToken + | ':' kHoverToken + | ':' kNotFunctionToken compound_selector_token ')' + | ':' kNotFunctionToken errors ')' + | ':' errors + ; + +pseudo_element_token : + ':' kAfterToken + | ':' kBeforeToken + | ':' ':' kAfterToken + | ':' ':' kBeforeToken + | ':' ':' errors + ; + +simple_selector_token : + attribute_selector_token + | class_selector_token + | id_selector_token + | pseudo_class_token + | pseudo_element_token + | type_selector_token + | universal_selector_token + ; + +compound_selector_token : + simple_selector_token + | compound_selector_token simple_selector_token + ; + +combinator : + kWhitespaceToken + | '>' maybe_whitespace + | '+' maybe_whitespace + | '~' maybe_whitespace + ; + +complex_selector : + compound_selector_token + | complex_selector combinator compound_selector_token + | complex_selector kWhitespaceToken + ; + +selector_list : + complex_selector + | selector_list comma complex_selector + ; + +auto : + kAutoToken maybe_whitespace + ; + +maybe_sign_token : + /*empty*/ + | '+' + | '-' + ; + +zero_or_one : + integer + ; + +integer : + maybe_sign_token kIntegerToken maybe_whitespace + ; + +non_negative_integer : + integer + ; + +positive_integer : + integer + ; + +number : + integer + | maybe_sign_token kRealToken maybe_whitespace + ; + +non_negative_number : + number + ; + +percentage : + maybe_sign_token kPercentageToken maybe_whitespace + ; + +positive_percentage : + percentage + ; + +alpha : + number + ; + +length : + number + | absolute_or_relative_length + ; + +non_negative_absolute_or_relative_length : + absolute_or_relative_length + ; + +absolute_or_relative_length : + maybe_sign_token kFontSizesAkaEmToken maybe_whitespace + | maybe_sign_token kRootElementFontSizesAkaRemToken maybe_whitespace + | maybe_sign_token kViewportWidthPercentsAkaVwToken maybe_whitespace + | maybe_sign_token kViewportHeightPercentsAkaVhToken maybe_whitespace + | maybe_sign_token kPixelsToken maybe_whitespace + ; + +positive_length : + length + ; + +ratio : + positive_integer '/' maybe_whitespace positive_integer + ; + +resolution : + maybe_sign_token kDotsPerInchToken maybe_whitespace + | maybe_sign_token kDotsPerCentimeterToken maybe_whitespace + ; + +angle : + maybe_sign_token kDegreesToken maybe_whitespace + | maybe_sign_token kGradiansToken maybe_whitespace + | maybe_sign_token kRadiansToken maybe_whitespace + | maybe_sign_token kTurnsToken maybe_whitespace + ; + +time : + number + | time_with_units_required + ; + +time_with_units_required : + maybe_sign_token kSecondsToken maybe_whitespace + | maybe_sign_token kMillisecondsToken maybe_whitespace + ; + +colon : + ':' maybe_whitespace + ; + +comma : + ',' maybe_whitespace + ; + +common_values : + common_values_without_errors + | errors + ; + +common_values_without_errors : + kInheritToken maybe_whitespace + | kInitialToken maybe_whitespace + ; + +color : + kHexToken maybe_whitespace + | kRGBFunctionToken maybe_whitespace integer comma integer comma integer ')' maybe_whitespace + | kRGBAFunctionToken maybe_whitespace integer comma integer comma integer comma alpha ')' maybe_whitespace + | kHslFunctionToken maybe_whitespace integer comma positive_percentage comma positive_percentage ')' + | kHslaFunctionToken maybe_whitespace integer comma positive_percentage comma positive_percentage comma alpha ')' + | kAquaToken maybe_whitespace + | kBlackToken maybe_whitespace + | kBlueToken maybe_whitespace + | kFuchsiaToken maybe_whitespace + | kGrayToken maybe_whitespace + | kGreenToken maybe_whitespace + | kLimeToken maybe_whitespace + | kMaroonToken maybe_whitespace + | kNavyToken maybe_whitespace + | kOliveToken maybe_whitespace + | kPurpleToken maybe_whitespace + | kRedToken maybe_whitespace + | kSilverToken maybe_whitespace + | kTealToken maybe_whitespace + | kTransparentToken maybe_whitespace + | kWhiteToken maybe_whitespace + | kYellowToken maybe_whitespace + ; + +url : + kUriToken ')' maybe_whitespace + ; + +length_percent_property_value : + length + | percentage + ; + +positive_length_percent_property_value : + positive_length + | positive_percentage + ; + +background_property_element : + color + | background_image_property_list_element + ; + +maybe_background_size_property_value : + /*empty*/ + | '/' maybe_whitespace background_size_property_value_without_common_values + ; + +background_position_and_size_shorthand_property_value : + validated_position_property maybe_background_size_property_value + ; + +background_repeat_shorthand_property_value : + background_repeat_property_value_without_common_values + ; + +background_position_and_repeat_combination : + background_position_and_size_shorthand_property_value + | background_repeat_shorthand_property_value + | background_position_and_size_shorthand_property_value background_repeat_shorthand_property_value + | background_repeat_shorthand_property_value background_position_and_size_shorthand_property_value + ; + +final_background_layer_without_position_and_repeat : + /*empty*/ + | final_background_layer background_property_element + ; + +final_background_layer : + /*empty*/ + | final_background_layer_without_position_and_repeat background_position_and_repeat_combination + | final_background_layer background_property_element + ; + +background_property_value : + final_background_layer + | common_values + ; + +background_color_property_value : + color + | common_values + ; + +color_stop : + color + | color length_percent_property_value + ; + +comma_separated_color_stop_list : + color_stop comma color_stop + | comma_separated_color_stop_list comma color_stop + ; + +side : + kBottomToken maybe_whitespace + | kLeftToken maybe_whitespace + | kRightToken maybe_whitespace + | kTopToken maybe_whitespace + ; + +side_or_corner : + side + | side side + ; + +linear_gradient_params : + comma_separated_color_stop_list + | angle comma comma_separated_color_stop_list + | kToToken kWhitespaceToken maybe_whitespace side_or_corner comma comma_separated_color_stop_list + ; + +size_keyword : + kClosestSideToken maybe_whitespace + | kFarthestSideToken maybe_whitespace + | kClosestCornerToken maybe_whitespace + | kFarthestCornerToken maybe_whitespace + ; + +circle_with_size_keyword : + kCircleToken maybe_whitespace size_keyword + | size_keyword kCircleToken maybe_whitespace + ; + +circle_with_positive_length : + positive_length + | positive_length kCircleToken maybe_whitespace + | kCircleToken maybe_whitespace positive_length + ; + +maybe_ellipse_with_size_keyword : + kEllipseToken maybe_whitespace size_keyword + | size_keyword kEllipseToken maybe_whitespace + | size_keyword + ; + +ellipse_with_2_positive_length_percents : + positive_length_percent_property_value positive_length_percent_property_value + | positive_length_percent_property_value positive_length_percent_property_value kEllipseToken maybe_whitespace + | kEllipseToken maybe_whitespace positive_length_percent_property_value positive_length_percent_property_value + ; + +at_position : + kAtToken maybe_whitespace validated_position_property + ; + +maybe_at_position : + /*empty*/ + | at_position + ; + +radial_gradient_params : + circle_with_positive_length maybe_at_position comma comma_separated_color_stop_list + | ellipse_with_2_positive_length_percents maybe_at_position comma comma_separated_color_stop_list + | circle_with_size_keyword maybe_at_position comma comma_separated_color_stop_list + | maybe_ellipse_with_size_keyword maybe_at_position comma comma_separated_color_stop_list + | kCircleToken maybe_whitespace maybe_at_position comma comma_separated_color_stop_list + | kEllipseToken maybe_whitespace maybe_at_position comma comma_separated_color_stop_list + | at_position comma comma_separated_color_stop_list + | comma_separated_color_stop_list + ; + +background_image_property_list_element : + url + | kLinearGradientFunctionToken maybe_whitespace linear_gradient_params ')' + | kRadialGradientFunctionToken maybe_whitespace radial_gradient_params ')' + | kNoneToken maybe_whitespace + ; + +comma_separated_background_image_list : + background_image_property_list_element + | comma_separated_background_image_list comma background_image_property_list_element + ; + +background_image_property_value : + comma_separated_background_image_list + | common_values + ; + +position_list_element : + kBottomToken maybe_whitespace + | kCenterToken maybe_whitespace + | kLeftToken maybe_whitespace + | kRightToken maybe_whitespace + | kTopToken maybe_whitespace + | length_percent_property_value + ; + +position_list : + position_list_element + | position_list position_list_element + ; + +validated_position_property : + position_list + ; + +background_position_property_value : + validated_position_property + | common_values + ; + +background_repeat_element : + kNoRepeatToken maybe_whitespace + | kRepeatToken maybe_whitespace + ; + +background_repeat_property_value_without_common_values : + background_repeat_element + | background_repeat_element background_repeat_element + | kRepeatXToken maybe_whitespace + | kRepeatYToken maybe_whitespace + ; + +background_repeat_property_value : + background_repeat_property_value_without_common_values + | common_values + ; + +background_size_property_list_element : + length + | positive_percentage + | auto + ; + +background_size_property_list : + background_size_property_list_element + | background_size_property_list_element background_size_property_list_element + ; + +background_size_property_value_without_common_values : + background_size_property_list + | kContainToken maybe_whitespace + | kCoverToken maybe_whitespace + ; + +background_size_property_value : + background_size_property_value_without_common_values + | common_values + ; + +border_color_property_list : + /*empty*/ + | border_color_property_list color + ; + +border_color_property_value : + border_color_property_list + | common_values + ; + +line_style : + kNoneToken maybe_whitespace + | kHiddenToken maybe_whitespace + | kSolidToken maybe_whitespace + ; + +line_style_with_common_values : + line_style + | common_values + ; + +border_style_property_list : + /*empty*/ + | border_style_property_list line_style + ; + +border_style_property_value : + border_style_property_list + | common_values + ; + +border_width_element : + positive_length + ; + +border_width_element_with_common_values : + border_width_element + | common_values + ; + +border_width_property_list : + /*empty*/ + | border_width_property_list border_width_element + ; + +border_width_property_value : + border_width_property_list + | common_values + ; + +border_or_outline_property_element : + color + | line_style + | positive_length + ; + +border_or_outline_property_list : + /*empty*/ + | border_or_outline_property_list border_or_outline_property_element + ; + +border_or_outline_property_value : + border_or_outline_property_list + | common_values + ; + +border_radius_element : + positive_length_percent_property_value + ; + +border_radius_element_with_common_values : + border_radius_element + | common_values + ; + +border_radius_property_list : + /*empty*/ + | border_radius_property_list border_radius_element + ; + +border_radius_property_value : + border_radius_property_list + | common_values + ; + +box_shadow_property_element : + length + | color + | kInsetToken maybe_whitespace + ; + +box_shadow_list : + /*empty*/ + | box_shadow_list box_shadow_property_element + ; + +validated_box_shadow_list : + box_shadow_list + ; + +comma_separated_box_shadow_list : + validated_box_shadow_list + | comma_separated_box_shadow_list comma validated_box_shadow_list + ; + +box_shadow_property_value : + comma_separated_box_shadow_list + | kNoneToken maybe_whitespace + | common_values + ; + +color_property_value : + color + | common_values + ; + +content_property_value : + kNoneToken maybe_whitespace + | kNormalToken maybe_whitespace + | url + | kStringToken maybe_whitespace + | common_values + ; + +display_property_value : + kBlockToken maybe_whitespace + | kFlexToken maybe_whitespace + | kInlineToken maybe_whitespace + | kInlineBlockToken maybe_whitespace + | kInlineFlexToken maybe_whitespace + | kNoneToken maybe_whitespace + | common_values + ; + +font_face_url_src : + url kFormatFunctionToken maybe_whitespace kStringToken maybe_whitespace ')' maybe_whitespace + | url + ; + +font_face_local_src : + kLocalFunctionToken maybe_whitespace font_family_specific_name ')' maybe_whitespace + ; + +font_face_src_list_element : + font_face_url_src + | font_face_local_src + ; + +comma_separated_font_face_src_list : + font_face_src_list_element + | comma_separated_font_face_src_list comma font_face_src_list_element + ; + +font_face_src_property_value : + comma_separated_font_face_src_list + | common_values + ; + +font_family_name_identifier_list : + identifier_token maybe_whitespace + | font_family_name_identifier_list identifier_token maybe_whitespace + ; + +font_family_string_name : + kStringToken maybe_whitespace + ; + +font_family_specific_name : + font_family_name_identifier_list + | font_family_string_name + ; + +font_family_specific_name_no_single_identifier : + font_family_name_identifier_list identifier_token maybe_whitespace + | font_family_string_name + ; + +font_family_name : + identifier_token maybe_whitespace + | font_family_specific_name_no_single_identifier + ; + +comma_separated_font_family_name_list : + font_family_name + | comma_separated_font_family_name_list comma font_family_name + ; + +font_family_property_value : + identifier_token maybe_whitespace + | font_family_specific_name_no_single_identifier + | comma_separated_font_family_name_list comma font_family_name + | errors + ; + +font_size_property_value : + positive_length_percent_property_value + | common_values + ; + +font_style_exclusive_property_value : + kItalicToken maybe_whitespace + | kObliqueToken maybe_whitespace + ; + +font_style_property_value : + font_style_exclusive_property_value + | kNormalToken maybe_whitespace + | common_values + ; + +font_weight_exclusive_property_value : + kBoldToken maybe_whitespace + | positive_integer + ; + +font_weight_property_value : + font_weight_exclusive_property_value + | kNormalToken maybe_whitespace + | common_values + ; + +optional_font_element : + font_style_exclusive_property_value + | kNormalToken maybe_whitespace + | error maybe_whitespace + ; + +optional_font_value_list : + /*empty*/ + | non_empty_optional_font_value_list + ; + +non_empty_optional_font_value_list : + optional_font_value_list optional_font_element + ; + +font_property_value : + optional_font_value_list positive_length_percent_property_value comma_separated_font_family_name_list + | optional_font_value_list font_weight_exclusive_property_value positive_length_percent_property_value comma_separated_font_family_name_list + | common_values_without_errors + ; + +height_property_value : + positive_length_percent_property_value + | auto + | common_values + ; + +intersection_observer_root_margin_property_list : + length_percent_property_value + | length_percent_property_value length_percent_property_value + | length_percent_property_value length_percent_property_value length_percent_property_value + | length_percent_property_value length_percent_property_value length_percent_property_value length_percent_property_value + ; + +intersection_observer_root_margin_property_value : + intersection_observer_root_margin_property_list + ; + +min_height_property_value : + kAutoToken maybe_whitespace + | positive_length_percent_property_value + | common_values + ; + +max_height_property_value : + kNoneToken maybe_whitespace + | positive_length_percent_property_value + | common_values + ; + +line_height_property_value : + kNormalToken maybe_whitespace + | non_negative_number + | absolute_or_relative_length + | positive_percentage + | common_values + ; + +margin_width : + length_percent_property_value + | auto + ; + +margin_side_property_value : + margin_width + | common_values + ; + +margin_property_value : + margin_width + | margin_width margin_width + | margin_width margin_width margin_width + | margin_width margin_width margin_width margin_width + | common_values + ; + +offset_property_value : + length_percent_property_value + | auto + | common_values + ; + +opacity_property_value : + alpha + | common_values + ; + +overflow_property_value : + kAutoToken maybe_whitespace + | kHiddenToken maybe_whitespace + | kScrollToken maybe_whitespace + | kVisibleToken maybe_whitespace + | common_values + ; + +overflow_wrap_property_value : + kBreakWordToken maybe_whitespace + | kNormalToken maybe_whitespace + | common_values + ; + +padding_side_property_value : + positive_length_percent_property_value + | common_values + ; + +padding_property_value : + positive_length_percent_property_value + | positive_length_percent_property_value positive_length_percent_property_value + | positive_length_percent_property_value positive_length_percent_property_value positive_length_percent_property_value + | positive_length_percent_property_value positive_length_percent_property_value positive_length_percent_property_value positive_length_percent_property_value + | common_values + ; + +pointer_events_property_value : + kAutoToken maybe_whitespace + | kNoneToken maybe_whitespace + | common_values + ; + +position_property_value : + kAbsoluteToken maybe_whitespace + | kFixedToken maybe_whitespace + | kRelativeToken maybe_whitespace + | kStaticToken maybe_whitespace + | common_values + ; + +scale_function_parameters : + number + | number comma number + ; + +text_align_property_value : + kEndToken maybe_whitespace + | kLeftToken maybe_whitespace + | kCenterToken maybe_whitespace + | kRightToken maybe_whitespace + | kStartToken maybe_whitespace + | common_values + ; + +text_decoration_line : + kNoneToken maybe_whitespace + | kLineThroughToken maybe_whitespace + ; + +text_decoration_line_property_value : + text_decoration_line + | common_values + ; + +text_decoration_property_element : + text_decoration_line + | color + ; + +text_decoration_property_list : + /*empty*/ + | text_decoration_property_list text_decoration_property_element + ; + +text_decoration_property_value : + text_decoration_property_list + | common_values + ; + +text_indent_property_value : + length + | common_values + ; + +text_overflow_property_value : + kClipToken maybe_whitespace + | kEllipsisToken maybe_whitespace + | common_values + ; + +text_shadow_property_element : + length + | color + ; + +text_shadow_list : + /*empty*/ + | text_shadow_list text_shadow_property_element + ; + +validated_text_shadow_list : + text_shadow_list + ; + +comma_separated_text_shadow_list : + validated_text_shadow_list + | comma_separated_text_shadow_list comma validated_text_shadow_list + ; + +text_shadow_property_value : + comma_separated_text_shadow_list + | kNoneToken maybe_whitespace + | common_values + ; + +text_transform_property_value : + kNoneToken maybe_whitespace + | kUppercaseToken maybe_whitespace + | common_values + ; + +transform_function : + kMatrixFunctionToken maybe_whitespace number comma number comma number comma number comma number comma number ')' maybe_whitespace + | kRotateFunctionToken maybe_whitespace angle ')' maybe_whitespace + | kScaleFunctionToken maybe_whitespace scale_function_parameters ')' maybe_whitespace + | kScaleXFunctionToken maybe_whitespace number ')' maybe_whitespace + | kScaleYFunctionToken maybe_whitespace number ')' maybe_whitespace + | kTranslateFunctionToken maybe_whitespace length_percent_property_value ')' maybe_whitespace + | kTranslateFunctionToken maybe_whitespace length_percent_property_value comma length_percent_property_value ')' maybe_whitespace + | kTranslateXFunctionToken maybe_whitespace length_percent_property_value ')' maybe_whitespace + | kTranslateYFunctionToken maybe_whitespace length_percent_property_value ')' maybe_whitespace + | kTranslateZFunctionToken maybe_whitespace length ')' maybe_whitespace + | kCobaltUiNavFocusTransformFunctionToken maybe_whitespace ')' maybe_whitespace + | kCobaltUiNavFocusTransformFunctionToken maybe_whitespace number ')' maybe_whitespace + | kCobaltUiNavFocusTransformFunctionToken maybe_whitespace number comma number ')' maybe_whitespace + | kCobaltUiNavSpotlightTransformFunctionToken maybe_whitespace ')' maybe_whitespace + ; + +transform_list : + /*empty*/ + | transform_list transform_function + ; + +transform_property_value : + kNoneToken maybe_whitespace + | transform_list + | transform_list errors + | common_values_without_errors + ; + +validated_two_position_list_elements : + position_list_element position_list_element + ; + +transform_origin_property_value : + position_list_element + | validated_two_position_list_elements + | validated_two_position_list_elements length + | common_values + ; + +vertical_align_property_value : + kBottomToken maybe_whitespace + | kTopToken maybe_whitespace + | kMiddleToken maybe_whitespace + | kBaselineToken maybe_whitespace + | common_values + ; + +visibility_property_value : + kCollapseToken maybe_whitespace + | kHiddenToken maybe_whitespace + | kVisibleToken maybe_whitespace + | common_values + ; + +comma_separated_time_list : + time + | comma_separated_time_list comma time + ; + +time_list_property_value : + comma_separated_time_list + | common_values + ; + +maybe_steps_start_or_end_parameter : + /*empty*/ + | comma kStartToken maybe_whitespace + | comma kEndToken maybe_whitespace + ; + +single_timing_function : + kCubicBezierFunctionToken maybe_whitespace number comma number comma number comma number ')' + | kStepsFunctionToken maybe_whitespace kIntegerToken maybe_whitespace maybe_steps_start_or_end_parameter ')' + | kEaseInOutToken + | kEaseInToken + | kEaseOutToken + | kEaseToken + | kLinearToken + | kStepEndToken + | kStepStartToken + ; + +comma_separated_single_timing_function_list : + single_timing_function + | comma_separated_single_timing_function_list comma single_timing_function + ; + +timing_function_list_property_value : + comma_separated_single_timing_function_list + | common_values + ; + +animation_delay_property_value : + time_list_property_value + ; + +animation_direction_list_element : + kNormalToken maybe_whitespace + | kReverseToken maybe_whitespace + | kAlternateToken maybe_whitespace + | kAlternateReverseToken maybe_whitespace + ; + +comma_separated_animation_direction_list : + animation_direction_list_element + | comma_separated_animation_direction_list comma animation_direction_list_element + ; + +animation_direction_property_value : + comma_separated_animation_direction_list + | common_values_without_errors + | errors + ; + +animation_duration_property_value : + time_list_property_value + ; + +animation_fill_mode_list_element : + kNoneToken maybe_whitespace + | kForwardsToken maybe_whitespace + | kBackwardsToken maybe_whitespace + | kBothToken maybe_whitespace + ; + +comma_separated_animation_fill_mode_list : + animation_fill_mode_list_element + | comma_separated_animation_fill_mode_list comma animation_fill_mode_list_element + ; + +animation_fill_mode_property_value : + comma_separated_animation_fill_mode_list + | common_values_without_errors + | errors + ; + +animation_iteration_count_list_element : + kInfiniteToken maybe_whitespace + | non_negative_number + ; + +comma_separated_animation_iteration_count_list : + animation_iteration_count_list_element + | comma_separated_animation_iteration_count_list comma animation_iteration_count_list_element + ; + +animation_iteration_count_property_value : + comma_separated_animation_iteration_count_list + | common_values_without_errors + | errors + ; + +animation_name_list_element : + kNoneToken maybe_whitespace + | kIdentifierToken maybe_whitespace + ; + +comma_separated_animation_name_list : + animation_name_list_element + | comma_separated_animation_name_list comma animation_name_list_element + ; + +animation_name_property_value : + comma_separated_animation_name_list + | common_values_without_errors + | errors + ; + +animation_timing_function_property_value : + timing_function_list_property_value + ; + +single_animation_element : + kIdentifierToken maybe_whitespace + | animation_direction_list_element + | animation_fill_mode_list_element + | animation_iteration_count_list_element + | time_with_units_required + | single_timing_function maybe_whitespace + | error maybe_whitespace + ; + +single_animation : + /*empty*/ + | single_non_empty_animation + ; + +single_non_empty_animation : + single_animation single_animation_element + ; + +comma_separated_animation_list : + single_non_empty_animation + | comma_separated_animation_list comma single_non_empty_animation + ; + +animation_property_value : + comma_separated_animation_list + | common_values_without_errors + ; + +transition_delay_property_value : + time_list_property_value + ; + +transition_duration_property_value : + time_list_property_value + ; + +transition_timing_function_property_value : + timing_function_list_property_value + ; + +comma_separated_animatable_property_name_list : + animatable_property_token maybe_whitespace + | comma_separated_animatable_property_name_list comma animatable_property_token maybe_whitespace + | errors + ; + +transition_property_property_value : + kNoneToken maybe_whitespace + | comma_separated_animatable_property_name_list + | common_values_without_errors + ; + +single_transition_element : + animatable_property_token maybe_whitespace + | kNoneToken maybe_whitespace + | time + | single_timing_function maybe_whitespace + | error maybe_whitespace + ; + +single_transition : + /*empty*/ + | single_non_empty_transition + ; + +single_non_empty_transition : + single_transition single_transition_element + ; + +comma_separated_transition_list : + single_non_empty_transition + | comma_separated_transition_list comma single_non_empty_transition + ; + +transition_property_value : + comma_separated_transition_list + | common_values_without_errors + ; + +unicode_range_property_value : + comma_separated_unicode_range_list + | common_values + ; + +comma_separated_unicode_range_list : + kUnicodeRangeToken maybe_whitespace + | comma_separated_unicode_range_list comma kUnicodeRangeToken maybe_whitespace + ; + +white_space_property_value : + kNormalToken maybe_whitespace + | kNowrapToken maybe_whitespace + | kPreToken maybe_whitespace + | kPreLineToken maybe_whitespace + | kPreWrapToken maybe_whitespace + | common_values + ; + +width_property_value : + positive_length_percent_property_value + | auto + | common_values + ; + +min_width_property_value : + kAutoToken maybe_whitespace + | positive_length_percent_property_value + | common_values + ; + +max_width_property_value : + kNoneToken maybe_whitespace + | positive_length_percent_property_value + | common_values + ; + +maybe_important : + /*empty*/ + | kImportantToken maybe_whitespace + ; + +z_index_property_value : + integer + | auto + | common_values + ; + +flex_start_end_center_property_value : + kFlexStartToken maybe_whitespace + | kFlexEndToken maybe_whitespace + | kCenterToken maybe_whitespace + ; + +space_between_around_property_value : + kSpaceBetweenToken maybe_whitespace + | kSpaceAroundToken maybe_whitespace + ; + +baseline_stretch_property_value : + kBaselineToken maybe_whitespace + | kStretchToken maybe_whitespace + ; + +justify_content_property_value : + flex_start_end_center_property_value + | space_between_around_property_value + | common_values + ; + +align_content_property_value : + flex_start_end_center_property_value + | space_between_around_property_value + | kStretchToken maybe_whitespace + | common_values + ; + +align_items_property_value : + flex_start_end_center_property_value + | baseline_stretch_property_value + | common_values + ; + +align_self_property_value : + kAutoToken maybe_whitespace + | flex_start_end_center_property_value + | baseline_stretch_property_value + | common_values + ; + +flex_basis_keywords : + kContentToken maybe_whitespace + | kAutoToken maybe_whitespace + ; + +flex_basis_property_value : + flex_basis_keywords + | positive_length_percent_property_value + | common_values + ; + +flex_basis_element : + flex_basis_keywords + | non_negative_absolute_or_relative_length + | positive_percentage + ; + +flex_single_flex_basis_element : + kContentToken maybe_whitespace + | non_negative_absolute_or_relative_length + | positive_percentage + ; + +flex_single_property_value : + flex_single_flex_basis_element + | non_negative_number + | kAutoToken maybe_whitespace + | kNoneToken maybe_whitespace + ; + +flex_two_property_values : + non_negative_number non_negative_number + | non_negative_number flex_basis_element + | flex_basis_element non_negative_number + ; + +flex_three_property_values : + non_negative_number non_negative_number flex_basis_element + | flex_basis_element non_negative_number non_negative_number + | non_negative_number non_negative_number non_negative_number + ; + +flex_property_value : + flex_single_property_value + | flex_two_property_values + | flex_three_property_values + | common_values + ; + +flex_factor_property_value : + non_negative_number + | common_values + ; + +order_property_value : + integer + | common_values + ; + +flex_direction : + kRowToken maybe_whitespace + | kRowReverseToken maybe_whitespace + | kColumnToken maybe_whitespace + | kColumnReverseToken maybe_whitespace + ; + +flex_direction_property_value : + flex_direction + | common_values + ; + +flex_flow_property_element : + flex_direction + | flex_wrap + ; + +flex_flow_property_list : + /*empty*/ + | flex_flow_property_list flex_flow_property_element + ; + +flex_flow_property_value : + flex_flow_property_list + | common_values + ; + +flex_wrap : + kNowrapToken maybe_whitespace + | kWrapToken maybe_whitespace + | kWrapReverseToken maybe_whitespace + ; + +flex_wrap_property_value : + flex_wrap + | common_values + ; + +animatable_property_token : + kAllToken + | kBackgroundColorToken + | kBorderBottomColorToken + | kBorderLeftColorToken + | kBorderRightColorToken + | kBorderTopColorToken + | kColorToken + | kOpacityToken + | kOutlineColorToken + | kOutlineWidthToken + | kTransformToken + ; + +maybe_declaration : + /*empty*/ + | kAlignContentToken maybe_whitespace colon align_content_property_value maybe_important + | kAlignItemsToken maybe_whitespace colon align_items_property_value maybe_important + | kAlignSelfToken maybe_whitespace colon align_self_property_value maybe_important + | kAnimationDelayToken maybe_whitespace colon animation_delay_property_value maybe_important + | kAnimationDirectionToken maybe_whitespace colon animation_direction_property_value maybe_important + | kAnimationDurationToken maybe_whitespace colon animation_duration_property_value maybe_important + | kAnimationFillModeToken maybe_whitespace colon animation_fill_mode_property_value maybe_important + | kAnimationIterationCountToken maybe_whitespace colon animation_iteration_count_property_value maybe_important + | kAnimationNameToken maybe_whitespace colon animation_name_property_value maybe_important + | kAnimationTimingFunctionToken maybe_whitespace colon animation_timing_function_property_value maybe_important + | kAnimationToken maybe_whitespace colon animation_property_value maybe_important + | kBackgroundToken maybe_whitespace colon background_property_value maybe_important + | kBackgroundColorToken maybe_whitespace colon background_color_property_value maybe_important + | kBackgroundImageToken maybe_whitespace colon background_image_property_value maybe_important + | kBackgroundPositionToken maybe_whitespace colon background_position_property_value maybe_important + | kBackgroundRepeatToken maybe_whitespace colon background_repeat_property_value maybe_important + | kBackgroundSizeToken maybe_whitespace colon background_size_property_value maybe_important + | kBorderToken maybe_whitespace colon border_or_outline_property_value maybe_important + | kBorderBottomLeftRadiusToken maybe_whitespace colon border_radius_element_with_common_values maybe_important + | kBorderBottomRightRadiusToken maybe_whitespace colon border_radius_element_with_common_values maybe_important + | kBorderBottomToken maybe_whitespace colon border_or_outline_property_value maybe_important + | kBorderBottomColorToken maybe_whitespace colon color_property_value maybe_important + | kBorderBottomStyleToken maybe_whitespace colon line_style_with_common_values maybe_important + | kBorderBottomWidthToken maybe_whitespace colon border_width_element_with_common_values maybe_important + | kBorderColorToken maybe_whitespace colon border_color_property_value maybe_important + | kBorderLeftToken maybe_whitespace colon border_or_outline_property_value maybe_important + | kBorderLeftColorToken maybe_whitespace colon color_property_value maybe_important + | kBorderLeftStyleToken maybe_whitespace colon line_style_with_common_values maybe_important + | kBorderLeftWidthToken maybe_whitespace colon border_width_element_with_common_values maybe_important + | kBorderRadiusToken maybe_whitespace colon border_radius_property_value maybe_important + | kBorderRightToken maybe_whitespace colon border_or_outline_property_value maybe_important + | kBorderRightColorToken maybe_whitespace colon color_property_value maybe_important + | kBorderRightStyleToken maybe_whitespace colon line_style_with_common_values maybe_important + | kBorderRightWidthToken maybe_whitespace colon border_width_element_with_common_values maybe_important + | kBorderStyleToken maybe_whitespace colon border_style_property_value maybe_important + | kBorderTopToken maybe_whitespace colon border_or_outline_property_value maybe_important + | kBorderTopColorToken maybe_whitespace colon color_property_value maybe_important + | kBorderTopLeftRadiusToken maybe_whitespace colon border_radius_element_with_common_values maybe_important + | kBorderTopRightRadiusToken maybe_whitespace colon border_radius_element_with_common_values maybe_important + | kBorderTopStyleToken maybe_whitespace colon line_style_with_common_values maybe_important + | kBorderTopWidthToken maybe_whitespace colon border_width_element_with_common_values maybe_important + | kBorderWidthToken maybe_whitespace colon border_width_property_value maybe_important + | kBottomToken maybe_whitespace colon offset_property_value maybe_important + | kBoxShadowToken maybe_whitespace colon box_shadow_property_value maybe_important + | kColorToken maybe_whitespace colon color_property_value maybe_important + | kContentToken maybe_whitespace colon content_property_value maybe_important + | kDisplayToken maybe_whitespace colon display_property_value maybe_important + | kFilterToken maybe_whitespace colon filter_property_value maybe_important + | kFlexToken maybe_whitespace colon flex_property_value maybe_important + | kFlexBasisToken maybe_whitespace colon flex_basis_property_value maybe_important + | kFlexDirectionToken maybe_whitespace colon flex_direction_property_value maybe_important + | kFlexFlowToken maybe_whitespace colon flex_flow_property_value maybe_important + | kFlexGrowToken maybe_whitespace colon flex_factor_property_value maybe_important + | kFlexShrinkToken maybe_whitespace colon flex_factor_property_value maybe_important + | kFlexWrapToken maybe_whitespace colon flex_wrap_property_value maybe_important + | kFontToken maybe_whitespace colon font_property_value maybe_important + | kFontFamilyToken maybe_whitespace colon font_family_property_value maybe_important + | kFontSizeToken maybe_whitespace colon font_size_property_value maybe_important + | kFontStyleToken maybe_whitespace colon font_style_property_value maybe_important + | kFontWeightToken maybe_whitespace colon font_weight_property_value maybe_important + | kHeightToken maybe_whitespace colon height_property_value maybe_important + | kIntersectionObserverRootMarginToken maybe_whitespace colon intersection_observer_root_margin_property_value maybe_important + | kJustifyContentToken maybe_whitespace colon justify_content_property_value maybe_important + | kLeftToken maybe_whitespace colon offset_property_value maybe_important + | kLineHeightToken maybe_whitespace colon line_height_property_value maybe_important + | kMarginBottomToken maybe_whitespace colon margin_side_property_value maybe_important + | kMarginLeftToken maybe_whitespace colon margin_side_property_value maybe_important + | kMarginRightToken maybe_whitespace colon margin_side_property_value maybe_important + | kMarginTopToken maybe_whitespace colon margin_side_property_value maybe_important + | kMarginToken maybe_whitespace colon margin_property_value maybe_important + | kMaxHeightToken maybe_whitespace colon max_height_property_value maybe_important + | kMaxWidthToken maybe_whitespace colon max_width_property_value maybe_important + | kMinHeightToken maybe_whitespace colon min_height_property_value maybe_important + | kMinWidthToken maybe_whitespace colon min_width_property_value maybe_important + | kOpacityToken maybe_whitespace colon opacity_property_value maybe_important + | kOrderToken maybe_whitespace colon order_property_value maybe_important + | kOutlineToken maybe_whitespace colon border_or_outline_property_value maybe_important + | kOutlineColorToken maybe_whitespace colon color_property_value maybe_important + | kOutlineStyleToken maybe_whitespace colon line_style_with_common_values maybe_important + | kOutlineWidthToken maybe_whitespace colon border_width_element_with_common_values maybe_important + | kOverflowToken maybe_whitespace colon overflow_property_value maybe_important + | kOverflowWrapToken maybe_whitespace colon overflow_wrap_property_value maybe_important + | kPaddingBottomToken maybe_whitespace colon padding_side_property_value maybe_important + | kPaddingLeftToken maybe_whitespace colon padding_side_property_value maybe_important + | kPaddingRightToken maybe_whitespace colon padding_side_property_value maybe_important + | kPaddingTopToken maybe_whitespace colon padding_side_property_value maybe_important + | kPaddingToken maybe_whitespace colon padding_property_value maybe_important + | kPointerEventsToken maybe_whitespace colon pointer_events_property_value maybe_important + | kPositionToken maybe_whitespace colon position_property_value maybe_important + | kRightToken maybe_whitespace colon offset_property_value maybe_important + | kSrcToken maybe_whitespace colon font_face_src_property_value maybe_important + | kTextAlignToken maybe_whitespace colon text_align_property_value maybe_important + | kTextIndentToken maybe_whitespace colon text_indent_property_value maybe_important + | kTextDecorationToken maybe_whitespace colon text_decoration_property_value maybe_important + | kTextDecorationColorToken maybe_whitespace colon color_property_value maybe_important + | kTextDecorationLineToken maybe_whitespace colon text_decoration_line_property_value maybe_important + | kTextOverflowToken maybe_whitespace colon text_overflow_property_value maybe_important + | kTextShadowToken maybe_whitespace colon text_shadow_property_value maybe_important + | kTextTransformToken maybe_whitespace colon text_transform_property_value maybe_important + | kTopToken maybe_whitespace colon offset_property_value maybe_important + | kTransformToken maybe_whitespace colon transform_property_value maybe_important + | kTransformOriginToken maybe_whitespace colon transform_origin_property_value maybe_important + | kTransitionToken maybe_whitespace colon transition_property_value maybe_important + | kTransitionDelayToken maybe_whitespace colon transition_delay_property_value maybe_important + | kTransitionDurationToken maybe_whitespace colon transition_duration_property_value maybe_important + | kTransitionPropertyToken maybe_whitespace colon transition_property_property_value maybe_important + | kTransitionTimingFunctionToken maybe_whitespace colon transition_timing_function_property_value maybe_important + | kUnicodeRangePropertyToken maybe_whitespace colon unicode_range_property_value maybe_important + | kVerticalAlignToken maybe_whitespace colon vertical_align_property_value maybe_important + | kVisibilityToken maybe_whitespace colon visibility_property_value maybe_important + | kWhiteSpacePropertyToken maybe_whitespace colon white_space_property_value maybe_important + | kWidthToken maybe_whitespace colon width_property_value maybe_important + | kWordWrapToken maybe_whitespace colon overflow_wrap_property_value maybe_important + | kZIndexToken maybe_whitespace colon z_index_property_value maybe_important + | kIdentifierToken maybe_whitespace colon errors + | errors + ; + +semicolon : + ';' maybe_whitespace + ; + +style_declaration_list : + maybe_declaration + | style_declaration_list semicolon maybe_declaration + ; + +font_face_declaration_list : + maybe_declaration + | font_face_declaration_list semicolon maybe_declaration + ; + +style_declaration_block : + '{' maybe_whitespace style_declaration_list '}' maybe_whitespace + ; + +rule_list_block : + '{' maybe_whitespace rule_list '}' maybe_whitespace + | semicolon + ; + +style_rule : + selector_list style_declaration_block + ; + +qualified_rule : + style_rule + | error style_declaration_block + ; + +invalid_rule : + kInvalidAtBlockToken maybe_whitespace + | kOtherBrowserAtBlockToken maybe_whitespace + ; + +rule : + kSgmlCommentDelimiterToken maybe_whitespace + | qualified_rule + | at_font_face_rule + | at_media_rule + | at_keyframes_rule + | invalid_rule + ; + +rule_list : + /*empty*/ + | rule_list rule + ; + +style_sheet : + rule_list + ; + +entry_point : + kStyleSheetEntryPointToken maybe_whitespace style_sheet + | kMediaListEntryPointToken maybe_whitespace media_list + | kMediaQueryEntryPointToken maybe_whitespace media_query + | kRuleEntryPointToken maybe_whitespace rule + | kStyleDeclarationListEntryPointToken maybe_whitespace style_declaration_list + | kFontFaceDeclarationListEntryPointToken maybe_whitespace font_face_declaration_list + | kPropertyValueEntryPointToken maybe_whitespace maybe_declaration + | kPropertyIntoDeclarationDataEntryPointToken maybe_whitespace maybe_declaration + ; + +filter_property_value : + kNoneToken maybe_whitespace + | filter_function_list + | common_values + ; + +filter_function_list : + filter_function + ; + +filter_function : + cobalt_mtm_filter_function + ; + +cobalt_mtm_filter_function : + cobalt_mtm_function_name maybe_whitespace cobalt_map_to_mesh_spec comma angle angle comma cobalt_mtm_transform_function maybe_cobalt_mtm_stereo_mode ')' maybe_whitespace + | cobalt_mtm_function_name maybe_whitespace kRectangularToken comma kNoneToken comma kNoneToken maybe_cobalt_mtm_stereo_mode ')' maybe_whitespace + ; + +cobalt_map_to_mesh_spec : + kEquirectangularToken + | url cobalt_mtm_resolution_matched_mesh_list + ; + +cobalt_mtm_function_name : + kCobaltMtmFunctionToken + | kMapToMeshFunctionToken + ; + +cobalt_mtm_resolution_matched_mesh_list : + /*empty*/ + | cobalt_mtm_resolution_matched_mesh_list cobalt_mtm_resolution_matched_mesh + ; + +cobalt_mtm_resolution_matched_mesh : + non_negative_integer non_negative_integer url + ; + +cobalt_mtm_transform_function : + kMatrix3dFunctionToken maybe_whitespace number_matrix ')' maybe_whitespace + ; + +number_matrix : + number + | number_matrix comma number + ; + +maybe_cobalt_mtm_stereo_mode : + /*empty*/ + | comma cobalt_mtm_stereo_mode + ; + +cobalt_mtm_stereo_mode : + kMonoscopicToken maybe_whitespace + | kStereoscopicLeftRightToken maybe_whitespace + | kStereoscopicTopBottomToken maybe_whitespace + ; + +//Lexer + +kEndOfFileToken : 'kEndOfFileToken' ; +kWhitespaceToken : 'kWhitespaceToken' ; +kFontFaceToken : 'kFontFaceToken' ; +kMediaToken : 'kMediaToken' ; +kLandscapeMediaFeatureKeywordValueToken : 'kLandscapeMediaFeatureKeywordValueToken' ; +kPortraitMediaFeatureKeywordValueToken : 'kPortraitMediaFeatureKeywordValueToken' ; +kInterlaceMediaFeatureKeywordValueToken : 'kInterlaceMediaFeatureKeywordValueToken' ; +kProgressiveMediaFeatureKeywordValueToken : 'kProgressiveMediaFeatureKeywordValueToken' ; +kMediaMinimumToken : 'kMediaMinimumToken' ; +kMediaMaximumToken : 'kMediaMaximumToken' ; +kLengthMediaFeatureTypeToken : 'kLengthMediaFeatureTypeToken' ; +kOrientationMediaFeatureTypeToken : 'kOrientationMediaFeatureTypeToken' ; +kRatioMediaFeatureTypeToken : 'kRatioMediaFeatureTypeToken' ; +kNonNegativeIntegerMediaFeatureTypeToken : 'kNonNegativeIntegerMediaFeatureTypeToken' ; +kResolutionMediaFeatureTypeToken : 'kResolutionMediaFeatureTypeToken' ; +kScanMediaFeatureTypeToken : 'kScanMediaFeatureTypeToken' ; +kZeroOrOneMediaFeatureTypeToken : 'kZeroOrOneMediaFeatureTypeToken' ; +kMediaAndToken : 'kMediaAndToken' ; +kIdentifierToken : 'kIdentifierToken' ; +kAllMediaTypeToken : 'kAllMediaTypeToken' ; +kTVMediaTypeToken : 'kTVMediaTypeToken' ; +kScreenMediaTypeToken : 'kScreenMediaTypeToken' ; +kMediaNotToken : 'kMediaNotToken' ; +kMediaOnlyToken : 'kMediaOnlyToken' ; +kKeyframesToken : 'kKeyframesToken' ; +kFromToken : 'kFromToken' ; +kToToken : 'kToToken' ; +kPercentageToken : 'kPercentageToken' ; +kAllToken : 'kAllToken' ; +kAlignContentToken : 'kAlignContentToken' ; +kAlignItemsToken : 'kAlignItemsToken' ; +kAlignSelfToken : 'kAlignSelfToken' ; +kAnimationDelayToken : 'kAnimationDelayToken' ; +kAnimationDirectionToken : 'kAnimationDirectionToken' ; +kAnimationDurationToken : 'kAnimationDurationToken' ; +kAnimationFillModeToken : 'kAnimationFillModeToken' ; +kAnimationIterationCountToken : 'kAnimationIterationCountToken' ; +kAnimationNameToken : 'kAnimationNameToken' ; +kAnimationTimingFunctionToken : 'kAnimationTimingFunctionToken' ; +kAnimationToken : 'kAnimationToken' ; +kBackgroundColorToken : 'kBackgroundColorToken' ; +kBackgroundImageToken : 'kBackgroundImageToken' ; +kBackgroundPositionToken : 'kBackgroundPositionToken' ; +kBackgroundRepeatToken : 'kBackgroundRepeatToken' ; +kBackgroundSizeToken : 'kBackgroundSizeToken' ; +kBackgroundToken : 'kBackgroundToken' ; +kBorderToken : 'kBorderToken' ; +kBorderBottomLeftRadiusToken : 'kBorderBottomLeftRadiusToken' ; +kBorderBottomRightRadiusToken : 'kBorderBottomRightRadiusToken' ; +kBorderBottomToken : 'kBorderBottomToken' ; +kBorderBottomColorToken : 'kBorderBottomColorToken' ; +kBorderBottomStyleToken : 'kBorderBottomStyleToken' ; +kBorderBottomWidthToken : 'kBorderBottomWidthToken' ; +kBorderLeftToken : 'kBorderLeftToken' ; +kBorderColorToken : 'kBorderColorToken' ; +kBorderLeftColorToken : 'kBorderLeftColorToken' ; +kBorderLeftStyleToken : 'kBorderLeftStyleToken' ; +kBorderLeftWidthToken : 'kBorderLeftWidthToken' ; +kBorderRadiusToken : 'kBorderRadiusToken' ; +kBorderRightToken : 'kBorderRightToken' ; +kBorderRightColorToken : 'kBorderRightColorToken' ; +kBorderRightStyleToken : 'kBorderRightStyleToken' ; +kBorderRightWidthToken : 'kBorderRightWidthToken' ; +kBorderStyleToken : 'kBorderStyleToken' ; +kBorderTopToken : 'kBorderTopToken' ; +kBorderTopColorToken : 'kBorderTopColorToken' ; +kBorderTopLeftRadiusToken : 'kBorderTopLeftRadiusToken' ; +kBorderTopRightRadiusToken : 'kBorderTopRightRadiusToken' ; +kBorderTopStyleToken : 'kBorderTopStyleToken' ; +kBorderTopWidthToken : 'kBorderTopWidthToken' ; +kBorderWidthToken : 'kBorderWidthToken' ; +kBottomToken : 'kBottomToken' ; +kBoxShadowToken : 'kBoxShadowToken' ; +kColorToken : 'kColorToken' ; +kContentToken : 'kContentToken' ; +kDisplayToken : 'kDisplayToken' ; +kFilterToken : 'kFilterToken' ; +kFlexToken : 'kFlexToken' ; +kFlexBasisToken : 'kFlexBasisToken' ; +kFlexDirectionToken : 'kFlexDirectionToken' ; +kFlexFlowToken : 'kFlexFlowToken' ; +kFlexGrowToken : 'kFlexGrowToken' ; +kFlexShrinkToken : 'kFlexShrinkToken' ; +kFlexWrapToken : 'kFlexWrapToken' ; +kFontToken : 'kFontToken' ; +kFontFamilyToken : 'kFontFamilyToken' ; +kFontSizeToken : 'kFontSizeToken' ; +kFontStyleToken : 'kFontStyleToken' ; +kFontWeightToken : 'kFontWeightToken' ; +kHeightToken : 'kHeightToken' ; +kIntersectionObserverRootMarginToken : 'kIntersectionObserverRootMarginToken' ; +kJustifyContentToken : 'kJustifyContentToken' ; +kLeftToken : 'kLeftToken' ; +kLineHeightToken : 'kLineHeightToken' ; +kMarginBottomToken : 'kMarginBottomToken' ; +kMarginLeftToken : 'kMarginLeftToken' ; +kMarginRightToken : 'kMarginRightToken' ; +kMarginToken : 'kMarginToken' ; +kMarginTopToken : 'kMarginTopToken' ; +kMaxHeightToken : 'kMaxHeightToken' ; +kMaxWidthToken : 'kMaxWidthToken' ; +kMinHeightToken : 'kMinHeightToken' ; +kMinWidthToken : 'kMinWidthToken' ; +kOpacityToken : 'kOpacityToken' ; +kOrderToken : 'kOrderToken' ; +kOutlineToken : 'kOutlineToken' ; +kOutlineColorToken : 'kOutlineColorToken' ; +kOutlineStyleToken : 'kOutlineStyleToken' ; +kOutlineWidthToken : 'kOutlineWidthToken' ; +kOverflowToken : 'kOverflowToken' ; +kOverflowWrapToken : 'kOverflowWrapToken' ; +kPaddingBottomToken : 'kPaddingBottomToken' ; +kPaddingLeftToken : 'kPaddingLeftToken' ; +kPaddingRightToken : 'kPaddingRightToken' ; +kPaddingToken : 'kPaddingToken' ; +kPaddingTopToken : 'kPaddingTopToken' ; +kPointerEventsToken : 'kPointerEventsToken' ; +kPositionToken : 'kPositionToken' ; +kRightToken : 'kRightToken' ; +kSrcToken : 'kSrcToken' ; +kTextAlignToken : 'kTextAlignToken' ; +kTextDecorationToken : 'kTextDecorationToken' ; +kTextDecorationColorToken : 'kTextDecorationColorToken' ; +kTextDecorationLineToken : 'kTextDecorationLineToken' ; +kTextIndentToken : 'kTextIndentToken' ; +kTextOverflowToken : 'kTextOverflowToken' ; +kTextShadowToken : 'kTextShadowToken' ; +kTextTransformToken : 'kTextTransformToken' ; +kTopToken : 'kTopToken' ; +kTransformToken : 'kTransformToken' ; +kTransformOriginToken : 'kTransformOriginToken' ; +kTransitionDelayToken : 'kTransitionDelayToken' ; +kTransitionDurationToken : 'kTransitionDurationToken' ; +kTransitionPropertyToken : 'kTransitionPropertyToken' ; +kTransitionTimingFunctionToken : 'kTransitionTimingFunctionToken' ; +kTransitionToken : 'kTransitionToken' ; +kUnicodeRangePropertyToken : 'kUnicodeRangePropertyToken' ; +kVerticalAlignToken : 'kVerticalAlignToken' ; +kVisibilityToken : 'kVisibilityToken' ; +kWhiteSpacePropertyToken : 'kWhiteSpacePropertyToken' ; +kWidthToken : 'kWidthToken' ; +kWordWrapToken : 'kWordWrapToken' ; +kZIndexToken : 'kZIndexToken' ; +kAbsoluteToken : 'kAbsoluteToken' ; +kAlternateToken : 'kAlternateToken' ; +kAlternateReverseToken : 'kAlternateReverseToken' ; +kAquaToken : 'kAquaToken' ; +kAtToken : 'kAtToken' ; +kAutoToken : 'kAutoToken' ; +kBackwardsToken : 'kBackwardsToken' ; +kBaselineToken : 'kBaselineToken' ; +kBlackToken : 'kBlackToken' ; +kBlockToken : 'kBlockToken' ; +kBlueToken : 'kBlueToken' ; +kBoldToken : 'kBoldToken' ; +kBothToken : 'kBothToken' ; +kBreakWordToken : 'kBreakWordToken' ; +kCenterToken : 'kCenterToken' ; +kCircleToken : 'kCircleToken' ; +kClipToken : 'kClipToken' ; +kClosestCornerToken : 'kClosestCornerToken' ; +kClosestSideToken : 'kClosestSideToken' ; +kCollapseToken : 'kCollapseToken' ; +kColumnToken : 'kColumnToken' ; +kColumnReverseToken : 'kColumnReverseToken' ; +kContainToken : 'kContainToken' ; +kCoverToken : 'kCoverToken' ; +kCursiveToken : 'kCursiveToken' ; +kEaseInOutToken : 'kEaseInOutToken' ; +kEaseInToken : 'kEaseInToken' ; +kEaseOutToken : 'kEaseOutToken' ; +kEaseToken : 'kEaseToken' ; +kEllipseToken : 'kEllipseToken' ; +kEllipsisToken : 'kEllipsisToken' ; +kEndToken : 'kEndToken' ; +kEquirectangularToken : 'kEquirectangularToken' ; +kFantasyToken : 'kFantasyToken' ; +kFarthestCornerToken : 'kFarthestCornerToken' ; +kFarthestSideToken : 'kFarthestSideToken' ; +kFixedToken : 'kFixedToken' ; +kFlexEndToken : 'kFlexEndToken' ; +kFlexStartToken : 'kFlexStartToken' ; +kForwardsToken : 'kForwardsToken' ; +kFuchsiaToken : 'kFuchsiaToken' ; +kGrayToken : 'kGrayToken' ; +kGreenToken : 'kGreenToken' ; +kHiddenToken : 'kHiddenToken' ; +kInfiniteToken : 'kInfiniteToken' ; +kInheritToken : 'kInheritToken' ; +kInitialToken : 'kInitialToken' ; +kInlineBlockToken : 'kInlineBlockToken' ; +kInlineToken : 'kInlineToken' ; +kInlineFlexToken : 'kInlineFlexToken' ; +kInsetToken : 'kInsetToken' ; +kItalicToken : 'kItalicToken' ; +kLimeToken : 'kLimeToken' ; +kLinearToken : 'kLinearToken' ; +kLineThroughToken : 'kLineThroughToken' ; +kMaroonToken : 'kMaroonToken' ; +kMiddleToken : 'kMiddleToken' ; +kMonoscopicToken : 'kMonoscopicToken' ; +kMonospaceToken : 'kMonospaceToken' ; +kNavyToken : 'kNavyToken' ; +kNoneToken : 'kNoneToken' ; +kNoRepeatToken : 'kNoRepeatToken' ; +kNormalToken : 'kNormalToken' ; +kNowrapToken : 'kNowrapToken' ; +kObliqueToken : 'kObliqueToken' ; +kOliveToken : 'kOliveToken' ; +kPreToken : 'kPreToken' ; +kPreLineToken : 'kPreLineToken' ; +kPreWrapToken : 'kPreWrapToken' ; +kPurpleToken : 'kPurpleToken' ; +kRedToken : 'kRedToken' ; +kRepeatToken : 'kRepeatToken' ; +kRepeatXToken : 'kRepeatXToken' ; +kRepeatYToken : 'kRepeatYToken' ; +kRelativeToken : 'kRelativeToken' ; +kReverseToken : 'kReverseToken' ; +kRowToken : 'kRowToken' ; +kRowReverseToken : 'kRowReverseToken' ; +kSansSerifToken : 'kSansSerifToken' ; +kScrollToken : 'kScrollToken' ; +kSerifToken : 'kSerifToken' ; +kSilverToken : 'kSilverToken' ; +kSolidToken : 'kSolidToken' ; +kSpaceAroundToken : 'kSpaceAroundToken' ; +kSpaceBetweenToken : 'kSpaceBetweenToken' ; +kStartToken : 'kStartToken' ; +kStaticToken : 'kStaticToken' ; +kStepEndToken : 'kStepEndToken' ; +kStepStartToken : 'kStepStartToken' ; +kStereoscopicLeftRightToken : 'kStereoscopicLeftRightToken' ; +kStereoscopicTopBottomToken : 'kStereoscopicTopBottomToken' ; +kStretchToken : 'kStretchToken' ; +kTealToken : 'kTealToken' ; +kTransparentToken : 'kTransparentToken' ; +kUppercaseToken : 'kUppercaseToken' ; +kVisibleToken : 'kVisibleToken' ; +kWhiteToken : 'kWhiteToken' ; +kWrapToken : 'kWrapToken' ; +kWrapReverseToken : 'kWrapReverseToken' ; +kYellowToken : 'kYellowToken' ; +kActiveToken : 'kActiveToken' ; +kEmptyToken : 'kEmptyToken' ; +kFocusToken : 'kFocusToken' ; +kHoverToken : 'kHoverToken' ; +kAfterToken : 'kAfterToken' ; +kBeforeToken : 'kBeforeToken' ; +kIncludesToken : 'kIncludesToken' ; +kDashMatchToken : 'kDashMatchToken' ; +kBeginsWithToken : 'kBeginsWithToken' ; +kEndsWithToken : 'kEndsWithToken' ; +kContainsToken : 'kContainsToken' ; +kStringToken : 'kStringToken' ; +kIdSelectorToken : 'kIdSelectorToken' ; +kHexToken : 'kHexToken' ; +kNotFunctionToken : 'kNotFunctionToken' ; +kIntegerToken : 'kIntegerToken' ; +kRealToken : 'kRealToken' ; +kFontSizesAkaEmToken : 'kFontSizesAkaEmToken' ; +kRootElementFontSizesAkaRemToken : 'kRootElementFontSizesAkaRemToken' ; +kViewportWidthPercentsAkaVwToken : 'kViewportWidthPercentsAkaVwToken' ; +kViewportHeightPercentsAkaVhToken : 'kViewportHeightPercentsAkaVhToken' ; +kPixelsToken : 'kPixelsToken' ; +kDotsPerInchToken : 'kDotsPerInchToken' ; +kDotsPerCentimeterToken : 'kDotsPerCentimeterToken' ; +kDegreesToken : 'kDegreesToken' ; +kGradiansToken : 'kGradiansToken' ; +kRadiansToken : 'kRadiansToken' ; +kTurnsToken : 'kTurnsToken' ; +kSecondsToken : 'kSecondsToken' ; +kMillisecondsToken : 'kMillisecondsToken' ; +kRGBFunctionToken : 'kRGBFunctionToken' ; +kRGBAFunctionToken : 'kRGBAFunctionToken' ; +kHslFunctionToken : 'kHslFunctionToken' ; +kHslaFunctionToken : 'kHslaFunctionToken' ; +kUriToken : 'kUriToken' ; +kLinearGradientFunctionToken : 'kLinearGradientFunctionToken' ; +kRadialGradientFunctionToken : 'kRadialGradientFunctionToken' ; +kFormatFunctionToken : 'kFormatFunctionToken' ; +kLocalFunctionToken : 'kLocalFunctionToken' ; +kMatrixFunctionToken : 'kMatrixFunctionToken' ; +kRotateFunctionToken : 'kRotateFunctionToken' ; +kScaleFunctionToken : 'kScaleFunctionToken' ; +kScaleXFunctionToken : 'kScaleXFunctionToken' ; +kScaleYFunctionToken : 'kScaleYFunctionToken' ; +kTranslateFunctionToken : 'kTranslateFunctionToken' ; +kTranslateXFunctionToken : 'kTranslateXFunctionToken' ; +kTranslateYFunctionToken : 'kTranslateYFunctionToken' ; +kTranslateZFunctionToken : 'kTranslateZFunctionToken' ; +kCobaltUiNavFocusTransformFunctionToken : 'kCobaltUiNavFocusTransformFunctionToken' ; +kCobaltUiNavSpotlightTransformFunctionToken : 'kCobaltUiNavSpotlightTransformFunctionToken' ; +kCubicBezierFunctionToken : 'kCubicBezierFunctionToken' ; +kStepsFunctionToken : 'kStepsFunctionToken' ; +kUnicodeRangeToken : 'kUnicodeRangeToken' ; +kImportantToken : 'kImportantToken' ; +kInvalidAtBlockToken : 'kInvalidAtBlockToken' ; +kOtherBrowserAtBlockToken : 'kOtherBrowserAtBlockToken' ; +kSgmlCommentDelimiterToken : 'kSgmlCommentDelimiterToken' ; +kStyleSheetEntryPointToken : 'kStyleSheetEntryPointToken' ; +kMediaListEntryPointToken : 'kMediaListEntryPointToken' ; +kMediaQueryEntryPointToken : 'kMediaQueryEntryPointToken' ; +kRuleEntryPointToken : 'kRuleEntryPointToken' ; +kStyleDeclarationListEntryPointToken : 'kStyleDeclarationListEntryPointToken' ; +kFontFaceDeclarationListEntryPointToken : 'kFontFaceDeclarationListEntryPointToken' ; +kPropertyValueEntryPointToken : 'kPropertyValueEntryPointToken' ; +kPropertyIntoDeclarationDataEntryPointToken : 'kPropertyIntoDeclarationDataEntryPointToken' ; +kRectangularToken : 'kRectangularToken' ; +kCobaltMtmFunctionToken : 'kCobaltMtmFunctionToken' ; +kMapToMeshFunctionToken : 'kMapToMeshFunctionToken' ; +kMatrix3dFunctionToken : 'kMatrix3dFunctionToken' ; + +} diff --git a/playground/cparser.g b/playground/cparser.g new file mode 100644 index 0000000..55e21fb --- /dev/null +++ b/playground/cparser.g @@ -0,0 +1,513 @@ +// From: https://github.com/zyp001a/ansi-c-grammar.git + +cparser { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +//%token IDENTIFIER +//%token CONSTANT +//%token STRING_LITERAL +//%token SIZEOF +//%token PTR_OP +//%token INC_OP +//%token DEC_OP +//%token LEFT_OP +//%token RIGHT_OP +//%token LE_OP +//%token GE_OP +//%token EQ_OP +//%token NE_OP +//%token AND_OP +//%token OR_OP +//%token MUL_ASSIGN +//%token DIV_ASSIGN +//%token MOD_ASSIGN +//%token ADD_ASSIGN +//%token SUB_ASSIGN +//%token LEFT_ASSIGN +//%token RIGHT_ASSIGN +//%token AND_ASSIGN +//%token XOR_ASSIGN +//%token OR_ASSIGN +//%token TYPE_NAME +//%token TYPEDEF +//%token EXTERN +//%token STATIC +//%token AUTO +//%token REGISTER +//%token CHAR +//%token SHORT +//%token INT +//%token LONG +//%token SIGNED +//%token UNSIGNED +//%token FLOAT +//%token DOUBLE +//%token CONST +//%token VOLATILE +//%token VOID +//%token STRUCT +//%token UNION +//%token ENUM +//%token ELLIPSIS +//%token CASE +//%token DEFAULT +//%token IF +//%token ELSE +//%token SWITCH +//%token WHILE +//%token DO +//%token FOR +//%token GOTO +//%token CONTINUE +//%token BREAK +//%token RETURN +//%token '(' +//%token ')' +//%token '[' +//%token ']' +//%token '.' +//%token ',' +//%token '&' +//%token '*' +//%token '+' +//%token '-' +//%token '~' +//%token '!' +//%token '/' +//%token '%' +//%token '<' +//%token '>' +//%token '^' +//%token '|' +//%token '?' +//%token ':' +//%token '=' +//%token ';' +//%token '{' +//%token '}' + + +//%start translation_unit + +//%% + +translation_unit : + external_declaration + | translation_unit external_declaration + ; + +primary_expression : + IDENTIFIER + | CONSTANT + | STRING_LITERAL + | '(' expression ')' + ; +postfix_expression : + primary_expression + | postfix_expression '[' expression ']' + | postfix_expression '(' ')' + | postfix_expression '(' argument_expression_list ')' + | postfix_expression '.' IDENTIFIER + | postfix_expression PTR_OP IDENTIFIER + | postfix_expression INC_OP + | postfix_expression DEC_OP + ; +argument_expression_list : + assignment_expression + | argument_expression_list ',' assignment_expression + ; +unary_expression : + postfix_expression + | INC_OP unary_expression + | DEC_OP unary_expression + | unary_operator cast_expression + | SIZEOF unary_expression + | SIZEOF '(' type_name ')' + ; +unary_operator : + '&' + | '*' + | '+' + | '-' + | '~' + | '!' + ; +cast_expression : + unary_expression + | '(' type_name ')' cast_expression + ; +multiplicative_expression : + cast_expression + | multiplicative_expression '*' cast_expression + | multiplicative_expression '/' cast_expression + | multiplicative_expression '%' cast_expression + ; +additive_expression : + multiplicative_expression + | additive_expression '+' multiplicative_expression + | additive_expression '-' multiplicative_expression + ; +shift_expression : + additive_expression + | shift_expression LEFT_OP additive_expression + | shift_expression RIGHT_OP additive_expression + ; +relational_expression : + shift_expression + | relational_expression '<' shift_expression + | relational_expression '>' shift_expression + | relational_expression LE_OP shift_expression + | relational_expression GE_OP shift_expression + ; +equality_expression : + relational_expression + | equality_expression EQ_OP relational_expression + | equality_expression NE_OP relational_expression + ; +and_expression : + equality_expression + | and_expression '&' equality_expression + ; +exclusive_or_expression : + and_expression + | exclusive_or_expression '^' and_expression + ; +inclusive_or_expression : + exclusive_or_expression + | inclusive_or_expression '|' exclusive_or_expression + ; +logical_and_expression : + inclusive_or_expression + | logical_and_expression AND_OP inclusive_or_expression + ; +logical_or_expression : + logical_and_expression + | logical_or_expression OR_OP logical_and_expression + ; +conditional_expression : + logical_or_expression + | logical_or_expression '?' expression ':' conditional_expression + ; +assignment_expression : + conditional_expression + | unary_expression assignment_operator assignment_expression + ; +assignment_operator : + '=' + | MUL_ASSIGN + | DIV_ASSIGN + | MOD_ASSIGN + | ADD_ASSIGN + | SUB_ASSIGN + | LEFT_ASSIGN + | RIGHT_ASSIGN + | AND_ASSIGN + | XOR_ASSIGN + | OR_ASSIGN + ; +expression : + assignment_expression + | expression ',' assignment_expression + ; +constant_expression : + conditional_expression + ; +declaration : + declaration_specifiers ';' + | declaration_specifiers init_declarator_list ';' + ; +declaration_specifiers : + storage_class_specifier + | storage_class_specifier declaration_specifiers + | type_specifier + | type_specifier declaration_specifiers + | type_qualifier + | type_qualifier declaration_specifiers + ; +init_declarator_list : + init_declarator + | init_declarator_list ',' init_declarator + ; +init_declarator : + declarator + | declarator '=' initializer + ; +storage_class_specifier : + TYPEDEF + | EXTERN + | STATIC + | AUTO + | REGISTER + ; +type_specifier : + VOID + | CHAR + | SHORT + | INT + | LONG + | FLOAT + | DOUBLE + | SIGNED + | UNSIGNED + | struct_or_union_specifier + | enum_specifier + | TYPE_NAME + ; +struct_or_union_specifier : + struct_or_union IDENTIFIER '{' struct_declaration_list '}' + | struct_or_union '{' struct_declaration_list '}' + | struct_or_union IDENTIFIER + ; +struct_or_union : + STRUCT + | UNION + ; +struct_declaration_list : + struct_declaration + | struct_declaration_list struct_declaration + ; +struct_declaration : + specifier_qualifier_list struct_declarator_list ';' + ; +specifier_qualifier_list : + type_specifier specifier_qualifier_list + | type_specifier + | type_qualifier specifier_qualifier_list + | type_qualifier + ; +struct_declarator_list : + struct_declarator + | struct_declarator_list ',' struct_declarator + ; +struct_declarator : + declarator + | ':' constant_expression + | declarator ':' constant_expression + ; +enum_specifier : + ENUM '{' enumerator_list '}' + | ENUM IDENTIFIER '{' enumerator_list '}' + | ENUM IDENTIFIER + ; +enumerator_list : + enumerator + | enumerator_list ',' enumerator + ; +enumerator : + IDENTIFIER + | IDENTIFIER '=' constant_expression + ; +type_qualifier : + CONST + | VOLATILE + ; +declarator : + pointer direct_declarator + | direct_declarator + ; +direct_declarator : + IDENTIFIER + | '(' declarator ')' + | direct_declarator '[' constant_expression ']' + | direct_declarator '[' ']' + | direct_declarator '(' parameter_type_list ')' + | direct_declarator '(' identifier_list ')' + | direct_declarator '(' ')' + ; +pointer : + '*' + | '*' type_qualifier_list + | '*' pointer + | '*' type_qualifier_list pointer + ; +type_qualifier_list : + type_qualifier + | type_qualifier_list type_qualifier + ; +parameter_type_list : + parameter_list + | parameter_list ',' ELLIPSIS + ; +parameter_list : + parameter_declaration + | parameter_list ',' parameter_declaration + ; +parameter_declaration : + declaration_specifiers declarator + | declaration_specifiers abstract_declarator + | declaration_specifiers + ; +identifier_list : + IDENTIFIER + | identifier_list ',' IDENTIFIER + ; +type_name : + specifier_qualifier_list + | specifier_qualifier_list abstract_declarator + ; +abstract_declarator : + pointer + | direct_abstract_declarator + | pointer direct_abstract_declarator + ; +direct_abstract_declarator : + '(' abstract_declarator ')' + | '[' ']' + | '[' constant_expression ']' + | direct_abstract_declarator '[' ']' + | direct_abstract_declarator '[' constant_expression ']' + | '(' ')' + | '(' parameter_type_list ')' + | direct_abstract_declarator '(' ')' + | direct_abstract_declarator '(' parameter_type_list ')' + ; +initializer : + assignment_expression + | '{' initializer_list '}' + | '{' initializer_list ',' '}' + ; +initializer_list : + initializer + | initializer_list ',' initializer + ; +statement : + open_statement + | closed_statement + ; +open_statement : + IF '(' expression ')' statement + | IF '(' expression ')' closed_statement ELSE open_statement + | loop_header open_statement + ; +closed_statement : + simple_statement + | IF '(' expression ')' closed_statement ELSE closed_statement + | loop_header closed_statement + ; +simple_statement : + compound_statement + | expression_statement + | jump_statement + | DO statement WHILE '(' expression ')' ';' + ; +loop_header : + labeled_header + | iteration_header + | selection_header + ; +labeled_header : + IDENTIFIER ':' + | CASE constant_expression ':' + | DEFAULT ':' + ; +iteration_header : + WHILE '(' expression ')' + | FOR '(' expression_statement expression_statement ')' + | FOR '(' expression_statement expression_statement expression ')' + ; +selection_header : + SWITCH '(' expression ')' + ; +compound_statement : + '{' '}' + | '{' statement_list '}' + | '{' declaration_list '}' + | '{' declaration_list statement_list '}' + ; +declaration_list : + declaration + | declaration_list declaration + ; +statement_list : + statement + | statement_list statement + ; +expression_statement : + ';' + | expression ';' + ; +jump_statement : + GOTO IDENTIFIER ';' + | CONTINUE ';' + | BREAK ';' + | RETURN ';' + | RETURN expression ';' + ; + +external_declaration : + function_definition + | declaration + ; +function_definition : + declaration_specifiers declarator declaration_list compound_statement + | declaration_specifiers declarator compound_statement + | declarator declaration_list compound_statement + | declarator compound_statement + ; + +//Lexer + +IDENTIFIER : "[a-zA-Z_][a-zA-Z_0-9]*" ; +CONSTANT : "'([^'\n]|\\[^\n])'|0[xX][a-fA-F0-9]+|[0-9]+([Ee][+-]?[0-9]+)?|[0-9]*\\.[0-9]+([Ee][+-]?[0-9]+)?" ; +STRING_LITERAL : "\"([^\"\n]|\\[^\n])*\"" ; +PTR_OP : 'PTR_OP' ; +INC_OP : '++' ; +DEC_OP : '--' ; +SIZEOF : 'sizeof' ; +LEFT_OP : '<<' ; +RIGHT_OP : '>>' ; +LE_OP : '<=' ; +GE_OP : '>=' ; +EQ_OP : '==' ; +NE_OP : '!=' ; +AND_OP : '&&' ; +OR_OP : '||' ; +MUL_ASSIGN : '*=' ; +DIV_ASSIGN : '/=' ; +MOD_ASSIGN : '%=' ; +ADD_ASSIGN : '+=' ; +SUB_ASSIGN : '-=' ; +LEFT_ASSIGN : '<<=' ; +RIGHT_ASSIGN : '>>=' ; +AND_ASSIGN : '&=' ; +XOR_ASSIGN : '^=' ; +OR_ASSIGN : '|=' ; +TYPEDEF : 'typedef' ; +EXTERN : 'extern' ; +STATIC : 'static' ; +AUTO : 'auto' ; +REGISTER : 'register' ; +VOID : 'void' ; +CHAR : 'char' ; +SHORT : 'short' ; +INT : 'int' ; +LONG : 'long' ; +FLOAT : 'float' ; +DOUBLE : 'double' ; +SIGNED : 'signed' ; +UNSIGNED : 'unsigned' ; +TYPE_NAME : 'TYPE_NAME' ; +STRUCT : 'struct' ; +UNION : 'union' ; +ENUM : 'enum' ; +CONST : 'const' ; +VOLATILE : 'volatile' ; +ELLIPSIS : '...' ; +IF : 'if' ; +ELSE : 'else' ; +DO : 'do' ; +WHILE : 'while' ; +CASE : 'case' ; +DEFAULT : 'default' ; +FOR : 'for' ; +SWITCH : 'switch' ; +GOTO : 'goto' ; +CONTINUE : 'continue' ; +BREAK : 'break' ; +RETURN : 'return' ; + +} diff --git a/playground/cpp-98-parser.g b/playground/cpp-98-parser.g new file mode 100644 index 0000000..d19f7db --- /dev/null +++ b/playground/cpp-98-parser.g @@ -0,0 +1,752 @@ +//From: https://github.com/IvanAli/CPPSemanticAnalysis/blob/master/cpp.y +cpp_98 { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token INT +//%token FLOAT +//%token STRING +//%token BOOL +//%token H_CHAR +//%token Q_CHAR +//%token C_CHAR +//%token IDENTIFIER +//%token ZERO +//%token CLASS +//%token PUBLIC +//%token PRIVATE +//%token NEW +//%token DOUBLEKW +//%token CHARKW +//%token VOIDKW +//%token BOOLKW +//%token IF +//%token FOR +//%token CONST +//%token USING +//%token NAMESPACE +//%token AND +//%token OR +//%token BITWISE_AND +//%token BITWISE_OR +//%token BITWISE_XOR +//%token LESS_OR_EQUAL_THAN +//%token GREATER_OR_EQUAL_THAN +//%token LESS_THAN +//%token GREATER_THAN +//%token EQUAL +//%token NOT_EQUAL +//%token ASSIGNMENT +//%token ADDITION +//%token SUBTRACTION +//%token MULTIPLICATION +//%token DIVISION +//%token MODULO +//%token INCREMENT +//%token DECREMENT +//%token ADDITION_EQUAL +//%token SUBTRACTION_EQUAL +//%token MULTIPLICATION_EQUAL +//%token DIVISION_EQUAL +//%token MODULO_EQUAL +//%token AND_EQUAL +//%token OR_EQUAL +//%token XOR_EQUAL +//%token LEFT_SHIFT_EQUAL +//%token RIGHT_SHIFT_EQUAL +//%token OBJECT_ACCESS +//%token POINTER_ACCESS +//%token COLON +//%token TERNARY +//%token DOUBLE_COLON +//%token SEMI_COLON +//%token LEFT_SHIFT +//%token RIGHT_SHIFT +//%token CHARACTER +//%token OPEN_PARENTHESES +//%token CLOSE_PARENTHESES +//%token OPEN_BRACE +//%token CLOSE_BRACE +//%token OPEN_BRACKET +//%token CLOSE_BRACKET +//%token DOUBLEP +//%token CHARP +//%token VOIDP +//%token POINTERID +//%token DEPOINTERID +//%token RETURN +//%token COMMA +//%token ELSE +//%token TRUE +//%token FALSE +//%token THIS +//%token NOT +//%token DIRECTIVE +//%token INTKW +//%token INTP +//%token BOOLP +//%token SINGLE_QUOTE +//%token DOUBLE_QUOTE +//%token ESCAPE_SEQUENCE +//%token "." +//%token "->" +//%token "0" + + +//%start translation_unit + +//%% + +translation_unit : + declaration_seq + ; + +preprocessing_token : + header_name + ; + +tok : + keyword + | literal + | operator_token + ; + +header_name : + LESS_THAN h_char_sequence GREATER_THAN + | DOUBLE_QUOTE q_char_sequence DOUBLE_QUOTE + ; + +h_char_sequence : + H_CHAR + | h_char_sequence H_CHAR + ; + +q_char_sequence : + Q_CHAR + | q_char_sequence Q_CHAR + ; + +identifier : + IDENTIFIER + ; + +keyword : + BOOLKW + | RETURN + | DOUBLEKW + | IF + | NEW + | PRIVATE + | FALSE + | VOIDKW + | ELSE + | INTKW + | PUBLIC + | THIS + | CHARKW + | FOR + | CLASS + | TRUE + ; + +open_brace : + OPEN_BRACE + ; + +close_brace : + CLOSE_BRACE + ; + +open_parentheses : + OPEN_PARENTHESES + ; + +close_parentheses : + CLOSE_PARENTHESES + ; + +literal : + integer_literal + | character_literal + | floating_literal + | string_literal + | boolean_literal + ; + +integer_literal : + INT + ; + +character_literal : + SINGLE_QUOTE c_char_sequence SINGLE_QUOTE + ; + +c_char_sequence : + C_CHAR + | c_char_sequence C_CHAR + ; + +escape_sequence : + ESCAPE_SEQUENCE + ; + +floating_literal : + FLOAT + ; + +string_literal : + STRING + ; + +boolean_literal : + BOOL + ; + +operator_token : + OPEN_BRACE + | CLOSE_BRACE + | OPEN_BRACKET + | CLOSE_BRACKET + | OPEN_PARENTHESES + | CLOSE_PARENTHESES + | SEMI_COLON + | COLON + | NEW + | OBJECT_ACCESS + | ADDITION + | SUBTRACTION + | MULTIPLICATION + | DIVISION + | MODULO + | BITWISE_XOR + | BITWISE_AND + | BITWISE_OR + | NOT + | ASSIGNMENT + | LESS_THAN + | GREATER_THAN + | ADDITION_EQUAL + | SUBTRACTION_EQUAL + | MULTIPLICATION_EQUAL + | DIVISION_EQUAL + | MODULO_EQUAL + | XOR_EQUAL + | AND_EQUAL + | OR_EQUAL + | LEFT_SHIFT + | RIGHT_SHIFT + | LEFT_SHIFT_EQUAL + | RIGHT_SHIFT_EQUAL + | EQUAL + | NOT_EQUAL + | LESS_OR_EQUAL_THAN + | GREATER_OR_EQUAL_THAN + | AND + | OR + | INCREMENT + | DECREMENT + | COMMA + | POINTER_ACCESS + ; + +primary_expression : + literal + | THIS + | OPEN_PARENTHESES expression CLOSE_PARENTHESES + | id_expression + ; + +id_expression : + unqualified_id + ; + +unqualified_id : + identifier + ; + +qualified_id : + nested_name_specifier unqualified_id + ; + +nested_name_specifier : + class_name DOUBLE_COLON nested_name_specifier + ; + +postfix_expression : + primary_expression + | postfix_expression OPEN_BRACKET expression CLOSE_BRACKET + | simple_type_specifier OPEN_PARENTHESES CLOSE_PARENTHESES + | simple_type_specifier OPEN_PARENTHESES expression_list CLOSE_PARENTHESES + | postfix_expression OPEN_PARENTHESES expression_list CLOSE_PARENTHESES + | postfix_expression OPEN_PARENTHESES CLOSE_PARENTHESES + | postfix_expression INCREMENT + | postfix_expression DECREMENT + | postfix_expression "." id_expression + | postfix_expression "->" id_expression + ; + +expression_list : + assignment_expression + | expression_list COMMA assignment_expression + ; + +unary_expression : + postfix_expression + | INCREMENT unary_expression + | DECREMENT unary_expression + | new_expression + ; + +new_expression : + NEW new_type_id + ; + +new_type_id : + type_specifier_seq + ; + +cast_expression : + unary_expression + ; + +pm_expression : + cast_expression + ; + +multiplicative_expression : + unary_expression + | multiplicative_expression MULTIPLICATION unary_expression + | multiplicative_expression DIVISION unary_expression + | multiplicative_expression MODULO unary_expression + ; + +additive_expression : + multiplicative_expression + | additive_expression ADDITION multiplicative_expression + | additive_expression SUBTRACTION multiplicative_expression + ; + +shift_expression : + additive_expression + | shift_expression LEFT_SHIFT additive_expression + | shift_expression RIGHT_SHIFT additive_expression + ; + +relational_expression : + shift_expression + | relational_expression LESS_THAN shift_expression + | relational_expression GREATER_THAN shift_expression + | relational_expression LESS_OR_EQUAL_THAN shift_expression + | relational_expression GREATER_OR_EQUAL_THAN shift_expression + ; + +equality_expression : + relational_expression + | equality_expression EQUAL relational_expression + | equality_expression NOT_EQUAL relational_expression + ; + +and_expression : + equality_expression + | and_expression BITWISE_AND equality_expression + ; + +exclusive_or_expression : + and_expression + | exclusive_or_expression BITWISE_XOR and_expression + ; + +inclusive_or_expression : + exclusive_or_expression + | inclusive_or_expression BITWISE_OR exclusive_or_expression + ; + +logical_and_expression : + inclusive_or_expression + | logical_and_expression AND inclusive_or_expression + ; + +logical_or_expression : + logical_and_expression + | logical_or_expression OR logical_and_expression + ; + +conditional_expression : + logical_or_expression + ; + +assignment_expression : + conditional_expression + | logical_or_expression assignment_operator assignment_expression + ; + +assignment_operator : + ASSIGNMENT + | MULTIPLICATION_EQUAL + | DIVISION_EQUAL + | MODULO_EQUAL + | ADDITION_EQUAL + | SUBTRACTION_EQUAL + | RIGHT_SHIFT_EQUAL + | LEFT_SHIFT_EQUAL + | AND_EQUAL + | XOR_EQUAL + | OR_EQUAL + ; + +expression : + assignment_expression + | expression COMMA assignment_expression + ; + +constant_expression : + conditional_expression + ; + +statement : + expression_statement + | compound_statement + | selection_statement + | iteration_statement + | declaration_statement + | jump_statement + ; + +expression_statement : + expression SEMI_COLON + ; + +compound_statement : + open_brace close_brace + | open_brace statement_seq_opt close_brace + ; + +statement_seq_opt : + statement + | statement_seq_opt statement + ; + +selection_statement : + IF OPEN_PARENTHESES condition CLOSE_PARENTHESES statement + | IF OPEN_PARENTHESES condition CLOSE_PARENTHESES statement ELSE statement + ; + +condition : + expression + | simple_type_specifier identifier ASSIGNMENT assignment_expression + ; + +iteration_statement : + FOR open_parentheses condition SEMI_COLON expression SEMI_COLON assignment_expression close_parentheses statement + ; + +for_init_statement : + expression_statement + | simple_declaration + ; + +jump_statement : + RETURN expression SEMI_COLON + ; + +declaration_statement : + simple_declaration + ; + +declaration_seq : + declaration + | declaration_seq declaration + ; + +declaration : + simple_declaration + | function_definition + ; + +block_declaration : + simple_declaration + ; + +simple_declaration : + cv_qualifier simple_type_specifier init_declarator_list SEMI_COLON + | simple_type_specifier init_declarator_list SEMI_COLON + | elaborated_type_specifier init_declarator_list SEMI_COLON + | class_specifier init_declarator_list SEMI_COLON + | class_specifier SEMI_COLON + ; + +init_declarator_list : + init_declarator + | init_declarator_list COMMA init_declarator + ; + +init_declarator : + declarator + | declarator initializer_opt + ; + +initializer_opt : + ASSIGNMENT initializer_clause + | OPEN_PARENTHESES expression_list CLOSE_PARENTHESES + ; + +decl_specifier_seq : + decl_specifier + | decl_specifier decl_specifier_seq + ; + +decl_specifier : + type_specifier + ; + +type_specifier_seq : + type_specifier + | type_specifier type_specifier_seq + ; + +type_specifier : + simple_type_specifier + | elaborated_type_specifier + | cv_qualifier + | class_specifier + ; + +simple_type_specifier : + CHARKW + | BOOLKW + | INTKW + | DOUBLEKW + | VOIDKW + ; + +elaborated_type_specifier : + class_key identifier + ; + +function_definition : + simple_type_specifier declarator function_body + ; + +function_body : + OPEN_BRACE CLOSE_BRACE + | OPEN_BRACE statement_seq_opt CLOSE_BRACE + ; + +type_name : + class_name + ; + +declarator : + direct_declarator + | ptr_operator declarator + ; + +direct_declarator : + declarator_id + | direct_declarator parameters_and_qualifiers + | direct_declarator OPEN_BRACKET constant_expression CLOSE_BRACKET + | direct_declarator OPEN_BRACKET CLOSE_BRACKET + ; + +noptr_declarator : + declarator_id + ; + +parameters_and_qualifiers : + open_parentheses parameter_declaration_clause_opt close_parentheses + ; + +parameter_declaration_clause_opt : + /*empty*/ + | parameter_declaration_list + ; + +parameter_declaration_list : + parameter_declaration + | parameter_declaration_list COMMA parameter_declaration + ; + +parameter_declaration : + simple_type_specifier identifier + ; + +ptr_operator : + MULTIPLICATION cv_qualifier_seq + | BITWISE_AND + ; + +cv_qualifier_seq : + cv_qualifier cv_qualifier_seq + ; + +cv_qualifier : + CONST + ; + +declarator_id : + id_expression + ; + +initializer_clause : + assignment_expression + | open_brace initializer_list COMMA close_brace + | open_brace close_brace + ; + +initializer_list : + initializer_clause + | initializer_list COMMA initializer_clause + ; + +class_name : + identifier + ; + +class_specifier : + class_head open_brace member_specification_opt close_brace + ; + +class_head : + class_key identifier + ; + +class_key : + CLASS + ; + +member_specification_opt : + /*empty*/ + | member_declaration member_specification_opt + | access_specifier COLON member_specification_opt + ; + +access_specifier : + PUBLIC + | PRIVATE + ; + +member_declaration : + simple_type_specifier member_declarator_list SEMI_COLON + | function_definition SEMI_COLON + | function_definition + ; + +member_declarator_list : + member_declarator + | member_declarator_list COMMA member_declarator + ; + +member_declarator : + declarator + | declarator pure_specifier + ; + +pure_specifier : + ASSIGNMENT "0" + ; + +constant_initializer : + ASSIGNMENT constant_expression + ; + +ctor_initializer : + COLON mem_initializer_list + ; + +mem_initializer_list : + mem_initializer + | mem_initializer COMMA mem_initializer_list + ; + +mem_initializer : + mem_initializer_id OPEN_PARENTHESES expression_list CLOSE_PARENTHESES + ; + +mem_initializer_id : + identifier + | DOUBLE_COLON nested_name_specifier class_name + ; + +//Lexer + +LESS_THAN : 'LESS_THAN' ; +GREATER_THAN : 'GREATER_THAN' ; +DOUBLE_QUOTE : 'DOUBLE_QUOTE' ; +H_CHAR : 'H_CHAR' ; +Q_CHAR : 'Q_CHAR' ; +IDENTIFIER : 'IDENTIFIER' ; +BOOLKW : 'BOOLKW' ; +RETURN : 'RETURN' ; +DOUBLEKW : 'DOUBLEKW' ; +IF : 'IF' ; +NEW : 'NEW' ; +PRIVATE : 'PRIVATE' ; +FALSE : 'FALSE' ; +VOIDKW : 'VOIDKW' ; +ELSE : 'ELSE' ; +INTKW : 'INTKW' ; +PUBLIC : 'PUBLIC' ; +THIS : 'THIS' ; +CHARKW : 'CHARKW' ; +FOR : 'FOR' ; +CLASS : 'CLASS' ; +TRUE : 'TRUE' ; +OPEN_BRACE : 'OPEN_BRACE' ; +CLOSE_BRACE : 'CLOSE_BRACE' ; +OPEN_PARENTHESES : 'OPEN_PARENTHESES' ; +CLOSE_PARENTHESES : 'CLOSE_PARENTHESES' ; +INT : 'INT' ; +SINGLE_QUOTE : 'SINGLE_QUOTE' ; +C_CHAR : 'C_CHAR' ; +ESCAPE_SEQUENCE : 'ESCAPE_SEQUENCE' ; +FLOAT : 'FLOAT' ; +STRING : 'STRING' ; +BOOL : 'BOOL' ; +OPEN_BRACKET : 'OPEN_BRACKET' ; +CLOSE_BRACKET : 'CLOSE_BRACKET' ; +SEMI_COLON : 'SEMI_COLON' ; +COLON : 'COLON' ; +OBJECT_ACCESS : 'OBJECT_ACCESS' ; +ADDITION : 'ADDITION' ; +SUBTRACTION : 'SUBTRACTION' ; +MULTIPLICATION : 'MULTIPLICATION' ; +DIVISION : 'DIVISION' ; +MODULO : 'MODULO' ; +BITWISE_XOR : 'BITWISE_XOR' ; +BITWISE_AND : 'BITWISE_AND' ; +BITWISE_OR : 'BITWISE_OR' ; +NOT : 'NOT' ; +ASSIGNMENT : 'ASSIGNMENT' ; +ADDITION_EQUAL : 'ADDITION_EQUAL' ; +SUBTRACTION_EQUAL : 'SUBTRACTION_EQUAL' ; +MULTIPLICATION_EQUAL : 'MULTIPLICATION_EQUAL' ; +DIVISION_EQUAL : 'DIVISION_EQUAL' ; +MODULO_EQUAL : 'MODULO_EQUAL' ; +XOR_EQUAL : 'XOR_EQUAL' ; +AND_EQUAL : 'AND_EQUAL' ; +OR_EQUAL : 'OR_EQUAL' ; +LEFT_SHIFT : 'LEFT_SHIFT' ; +RIGHT_SHIFT : 'RIGHT_SHIFT' ; +LEFT_SHIFT_EQUAL : 'LEFT_SHIFT_EQUAL' ; +RIGHT_SHIFT_EQUAL : 'RIGHT_SHIFT_EQUAL' ; +EQUAL : 'EQUAL' ; +NOT_EQUAL : 'NOT_EQUAL' ; +LESS_OR_EQUAL_THAN : 'LESS_OR_EQUAL_THAN' ; +GREATER_OR_EQUAL_THAN : 'GREATER_OR_EQUAL_THAN' ; +AND : 'AND' ; +OR : 'OR' ; +INCREMENT : 'INCREMENT' ; +DECREMENT : 'DECREMENT' ; +COMMA : 'COMMA' ; +POINTER_ACCESS : 'POINTER_ACCESS' ; +DOUBLE_COLON : 'DOUBLE_COLON' ; +CONST : 'CONST' ; + +} diff --git a/playground/cql.g b/playground/cql.g new file mode 100644 index 0000000..8905171 --- /dev/null +++ b/playground/cql.g @@ -0,0 +1,1664 @@ +// /usr/bin/time /home/mingo/dev/c/A_grammars/lalr/test-grammar-nb/dist/Release/GNU-Linux/test-grammar-nb -g cql.g -i cg_test.sql + +cql { + +%left UNION_ALL UNION INTERSECT EXCEPT ; +%right ASSIGN ; +%left OR ; +%left AND ; +%left NOT ; +%left BETWEEN NOT_BETWEEN NE NE_ '=' EQEQ LIKE NOT_LIKE GLOB NOT_GLOB MATCH NOT_MATCH REGEXP NOT_REGEXP IN NOT_IN IS_NOT IS IS_TRUE IS_FALSE IS_NOT_TRUE IS_NOT_FALSE ; +%right ISNULL NOTNULL ; +%left '<' '>' GE LE ; +%left LS RS '&' '|' ; +%left '+' '-' ; +%left '*' '/' '%' ; +%left CONCAT ; +%left COLLATE ; +%right UMINUS '~' ; + +%whitespace "[ \t\r\n]*"; +%whitespace "\-\-[^\n\r]*"; +%whitespace "/\*:C_MultilineComment:"; + +program : + opt_stmt_list + ; + +opt_stmt_list : + /* empty */ + | stmt_list + ; + +stmt_list : + stmt ';' + | stmt_list stmt ';' + ; + +stmt : + misc_attrs any_stmt + ; + +any_stmt : + alter_table_add_column_stmt + | begin_schema_region_stmt + | begin_trans_stmt + | call_stmt + | close_stmt + | commit_return_stmt + | commit_trans_stmt + | continue_stmt + | create_index_stmt + | create_proc_stmt + | create_table_stmt + | create_trigger_stmt + | create_view_stmt + | create_virtual_table_stmt + | declare_deployable_region_stmt + | declare_enum_stmt + | declare_func_stmt + | declare_out_call_stmt + | declare_proc_no_check_stmt + | declare_proc_stmt + | declare_schema_region_stmt + | declare_stmt + | delete_stmt + | drop_index_stmt + | drop_table_stmt + | drop_trigger_stmt + | drop_view_stmt + | echo_stmt + | emit_enums_stmt + | emit_group_stmt + | emit_constants_stmt + | end_schema_region_stmt + | enforce_normal_stmt + | enforce_pop_stmt + | enforce_push_stmt + | enforce_reset_stmt + | enforce_strict_stmt + | explain_stmt + | fetch_call_stmt + | fetch_stmt + | fetch_values_stmt + | guard_stmt + | if_stmt + | insert_stmt + | leave_stmt + | let_stmt + | loop_stmt + | open_stmt + | out_stmt + | out_union_stmt + | previous_schema_stmt + | proc_savepoint_stmt + | release_savepoint_stmt + | return_stmt + | rollback_return_stmt + | rollback_trans_stmt + | savepoint_stmt + | select_stmt + | schema_ad_hoc_migration_stmt + | schema_upgrade_script_stmt + | schema_upgrade_version_stmt + | set_stmt + | switch_stmt + | throw_stmt + | trycatch_stmt + | update_cursor_stmt + | update_stmt + | upsert_stmt + | while_stmt + | with_delete_stmt + | with_insert_stmt + | with_update_stmt + | with_upsert_stmt + ; + +explain_stmt : + EXPLAIN opt_query_plan explain_target + ; + +opt_query_plan : + /* empty */ + | QUERY_PLAN + ; + +explain_target : + select_stmt + | update_stmt + | delete_stmt + | with_delete_stmt + | with_insert_stmt + | insert_stmt + | upsert_stmt + | drop_table_stmt + | drop_view_stmt + | drop_index_stmt + | drop_trigger_stmt + | begin_trans_stmt + | commit_trans_stmt + ; + +previous_schema_stmt : + AT_PREVIOUS_SCHEMA + ; + +schema_upgrade_script_stmt : + AT_SCHEMA_UPGRADE_SCRIPT + ; + +schema_upgrade_version_stmt : + AT_SCHEMA_UPGRADE_VERSION '(' INTLIT ')' + ; + +set_stmt : + SET name ASSIGN expr + | SET name FROM CURSOR name + ; + +let_stmt : + LET name ASSIGN expr + ; + +version_attrs_opt_recreate : + /* empty */ + | AT_RECREATE + | AT_RECREATE '(' name ')' + | version_attrs + ; + +opt_version_attrs : + /* empty */ + | version_attrs + ; + +version_attrs : + AT_CREATE version_annotation opt_version_attrs + | AT_DELETE version_annotation opt_version_attrs + ; + +opt_delete_version_attr : + /* empty */ + | AT_DELETE version_annotation + ; + +drop_table_stmt : + DROP TABLE IF EXISTS name + | DROP TABLE name + ; + +drop_view_stmt : + DROP VIEW IF EXISTS name + | DROP VIEW name + ; + +drop_index_stmt : + DROP INDEX IF EXISTS name + | DROP INDEX name + ; + +drop_trigger_stmt : + DROP TRIGGER IF EXISTS name + | DROP TRIGGER name + ; + +create_virtual_table_stmt : + CREATE VIRTUAL TABLE opt_if_not_exists name USING name opt_module_args AS '(' col_key_list ')' opt_delete_version_attr + ; + +opt_module_args : + /* empty */ + | '(' misc_attr_value_list ')' + | '(' ARGUMENTS FOLLOWING ')' + ; + +create_table_stmt : + CREATE opt_temp TABLE opt_if_not_exists name '(' col_key_list ')' opt_no_rowid version_attrs_opt_recreate + ; + +opt_temp : + /* empty */ + | TEMP + ; + +opt_if_not_exists : + /* empty */ + | IF NOT EXISTS + ; + +opt_no_rowid : + /* empty */ + | WITHOUT ROWID + ; + +col_key_list : + col_key_def + | col_key_def ',' col_key_list + ; + +col_key_def : + col_def + | pk_def + | fk_def + | unq_def + | check_def + | shape_def + ; + +check_def : + CONSTRAINT name CHECK '(' expr ')' + | CHECK '(' expr ')' + ; + +shape_def : + LIKE name + | LIKE name ARGUMENTS + ; + +col_name : + name + ; + +misc_attr_key : + name + | name ':' name + ; + +misc_attr_value_list : + misc_attr_value + | misc_attr_value ',' misc_attr_value_list + ; + +misc_attr_value : + name + | any_literal + | const_expr + | '(' misc_attr_value_list ')' + | '-' num_literal + ; + +misc_attr : + AT_ATTRIBUTE '(' misc_attr_key ')' + | AT_ATTRIBUTE '(' misc_attr_key '=' misc_attr_value ')' + ; + +misc_attrs : + /* empty */ + | misc_attr misc_attrs + ; + +col_def : + misc_attrs col_name data_type_any col_attrs + ; + +pk_def : + CONSTRAINT name PRIMARY KEY '(' indexed_columns ')' opt_conflict_clause + | PRIMARY KEY '(' indexed_columns ')' opt_conflict_clause + ; + +opt_conflict_clause : + /* empty */ + | conflict_clause + ; + +conflict_clause : + ON_CONFLICT ROLLBACK + | ON_CONFLICT ABORT + | ON_CONFLICT FAIL + | ON_CONFLICT IGNORE + | ON_CONFLICT REPLACE + ; + +opt_fk_options : + /* empty */ + | fk_options + ; + +fk_options : + fk_on_options + | fk_deferred_options + | fk_on_options fk_deferred_options + ; + +fk_on_options : + ON DELETE fk_action + | ON UPDATE fk_action + | ON UPDATE fk_action ON DELETE fk_action + | ON DELETE fk_action ON UPDATE fk_action + ; + +fk_action : + SET NULL_ + | SET DEFAULT + | CASCADE + | RESTRICT + | NO ACTION + ; + +fk_deferred_options : + DEFERRABLE fk_initial_state + | NOT_DEFERRABLE fk_initial_state + ; + +fk_initial_state : + /* empty */ + | INITIALLY DEFERRED + | INITIALLY IMMEDIATE + ; + +fk_def : + CONSTRAINT name FOREIGN KEY '(' name_list ')' fk_target_options + | FOREIGN KEY '(' name_list ')' fk_target_options + ; + +fk_target_options : + REFERENCES name '(' name_list ')' opt_fk_options + ; + +unq_def : + CONSTRAINT name UNIQUE '(' indexed_columns ')' opt_conflict_clause + | UNIQUE '(' indexed_columns ')' opt_conflict_clause + ; + +opt_unique : + /* empty */ + | UNIQUE + ; + +indexed_column : + expr opt_asc_desc + ; + +indexed_columns : + indexed_column + | indexed_column ',' indexed_columns + ; + +create_index_stmt : + CREATE opt_unique INDEX opt_if_not_exists name ON name '(' indexed_columns ')' opt_where opt_delete_version_attr + ; + +name : + ID + | TEXT + | TRIGGER + | ROWID + | REPLACE + | KEY + | VIRTUAL + | TYPE + | HIDDEN + | PRIVATE + ; + +opt_name : + /* empty */ + | name + ; + +name_list : + name + | name ',' name_list + ; + +opt_name_list : + /* empty */ + | name_list + ; + +col_attrs : + /* empty */ + | NOT NULL_ opt_conflict_clause col_attrs + | PRIMARY KEY opt_conflict_clause col_attrs + | PRIMARY KEY opt_conflict_clause AUTOINCREMENT col_attrs + | DEFAULT '-' num_literal col_attrs + | DEFAULT num_literal col_attrs + | DEFAULT const_expr col_attrs + | DEFAULT str_literal col_attrs + | COLLATE name col_attrs + | CHECK '(' expr ')' col_attrs + | UNIQUE opt_conflict_clause col_attrs + | HIDDEN col_attrs + | AT_SENSITIVE col_attrs + | AT_CREATE version_annotation col_attrs + | AT_DELETE version_annotation col_attrs + | fk_target_options col_attrs + ; + +version_annotation : + '(' INTLIT ',' name ')' + | '(' INTLIT ',' name ':' name ')' + | '(' INTLIT ')' + ; + +opt_kind : + /* empty */ + | '<' name '>' + ; + +data_type_numeric : + INT_ opt_kind + | INTEGER opt_kind + | REAL opt_kind + | LONG_ opt_kind + | BOOL_ opt_kind + | LONG_ INTEGER opt_kind + | LONG_ INT_ opt_kind + | LONG_INT opt_kind + | LONG_INTEGER opt_kind + ; + +data_type_any : + data_type_numeric + | TEXT opt_kind + | BLOB opt_kind + | OBJECT opt_kind + | OBJECT '<' name CURSOR '>' + | ID + ; + +data_type_with_options : + data_type_any + | data_type_any NOT NULL_ + | data_type_any AT_SENSITIVE + | data_type_any AT_SENSITIVE NOT NULL_ + | data_type_any NOT NULL_ AT_SENSITIVE + ; + +str_literal : + STRLIT + | CSTRLIT + ; + +num_literal : + INTLIT + | LONGLIT + | REALLIT + | TRUE_ + | FALSE_ + ; + +const_expr : + CONST '(' expr ')' + ; + +any_literal : + str_literal + | num_literal + | NULL_ + | AT_FILE '(' str_literal ')' + | AT_PROC + | BLOBLIT + ; + +raise_expr : + RAISE '(' IGNORE ')' + | RAISE '(' ROLLBACK ',' expr ')' + | RAISE '(' ABORT ',' expr ')' + | RAISE '(' FAIL ',' expr ')' + ; + +call : + name '(' arg_list ')' opt_filter_clause + | name '(' DISTINCT arg_list ')' opt_filter_clause + ; + +basic_expr : + name + | AT_RC + | name '.' name + | any_literal + | const_expr + | '(' expr ')' + | call + | window_func_inv + | raise_expr + | '(' select_stmt ')' + | '(' select_stmt IF NOTHING expr ')' + | '(' select_stmt IF NOTHING OR NULL_ expr ')' + | '(' select_stmt IF NOTHING THROW ')' + | EXISTS '(' select_stmt ')' + | CASE expr case_list END + | CASE expr case_list ELSE expr END + | CASE case_list END + | CASE case_list ELSE expr END + | CAST '(' expr AS data_type_any ')' + ; + +math_expr : + basic_expr + | math_expr '&' math_expr + | math_expr '|' math_expr + | math_expr LS math_expr + | math_expr RS math_expr + | math_expr '+' math_expr + | math_expr '-' math_expr + | math_expr '*' math_expr + | math_expr '/' math_expr + | math_expr '%' math_expr + | math_expr IS_NOT_TRUE + | math_expr IS_NOT_FALSE + | math_expr ISNULL + | math_expr NOTNULL + | math_expr IS_TRUE + | math_expr IS_FALSE + | '-' math_expr %precedence UMINUS + | '~' math_expr %precedence UMINUS + | NOT math_expr + | math_expr '=' math_expr + | math_expr EQEQ math_expr + | math_expr '<' math_expr + | math_expr '>' math_expr + | math_expr NE math_expr + | math_expr NE_ math_expr + | math_expr GE math_expr + | math_expr LE math_expr + | math_expr NOT_IN '(' expr_list ')' + | math_expr NOT_IN '(' select_stmt ')' + | math_expr IN '(' expr_list ')' + | math_expr IN '(' select_stmt ')' + | math_expr LIKE math_expr + | math_expr NOT_LIKE math_expr + | math_expr MATCH math_expr + | math_expr NOT_MATCH math_expr + | math_expr REGEXP math_expr + | math_expr NOT_REGEXP math_expr + | math_expr GLOB math_expr + | math_expr NOT_GLOB math_expr + | math_expr BETWEEN math_expr AND math_expr %precedence BETWEEN + | math_expr NOT_BETWEEN math_expr AND math_expr %precedence BETWEEN + | math_expr IS_NOT math_expr + | math_expr IS math_expr + | math_expr CONCAT math_expr + | math_expr COLLATE name + ; + +expr : + math_expr + | expr AND expr + | expr OR expr + ; + +case_list : + WHEN expr THEN expr + | WHEN expr THEN expr case_list + ; + +arg_expr : + '*' + | expr + | shape_arguments + ; + +arg_list : + /* empty */ + | arg_expr + | arg_expr ',' arg_list + ; + +expr_list : + expr + | expr ',' expr_list + ; + +shape_arguments : + FROM name + | FROM name shape_def + | FROM ARGUMENTS + | FROM ARGUMENTS shape_def + ; + +call_expr : + expr + | shape_arguments + ; + +call_expr_list : + call_expr + | call_expr ',' call_expr_list + ; + +cte_tables : + cte_table + | cte_table ',' cte_tables + ; + +cte_table : + name '(' name_list ')' AS '(' select_stmt_no_with ')' + | name '(' '*' ')' AS '(' select_stmt_no_with ')' + ; + +with_prefix : + WITH cte_tables + | WITH RECURSIVE cte_tables + ; + +with_select_stmt : + with_prefix select_stmt_no_with + ; + +select_stmt : + with_select_stmt + | select_stmt_no_with + ; + +select_stmt_no_with : + select_core_list opt_orderby opt_limit opt_offset + ; + +select_core_list : + select_core + | select_core compound_operator select_core_list + ; + +values : + '(' insert_list ')' + | '(' insert_list ')' ',' values + ; + +select_core : + SELECT select_opts select_expr_list opt_from_query_parts opt_where opt_groupby opt_having opt_select_window + | VALUES values + ; + +compound_operator : + UNION + | UNION_ALL + | INTERSECT + | EXCEPT + ; + +window_func_inv : + name '(' arg_list ')' opt_filter_clause OVER window_name_or_defn + ; + +opt_filter_clause : + /* empty */ + | FILTER '(' opt_where ')' + ; + +window_name_or_defn : + window_defn + | name + ; + +window_defn : + '(' opt_partition_by opt_orderby opt_frame_spec ')' + ; + +opt_frame_spec : + /* empty */ + | frame_type frame_boundary_opts frame_exclude + ; + +frame_type : + RANGE + | ROWS + | GROUPS + ; + +frame_exclude : + /* empty */ + | EXCLUDE_NO_OTHERS + | EXCLUDE_CURRENT_ROW + | EXCLUDE_GROUP + | EXCLUDE_TIES + ; + +frame_boundary_opts : + frame_boundary + | BETWEEN frame_boundary_start AND frame_boundary_end + ; + +frame_boundary_start : + UNBOUNDED PRECEDING + | expr PRECEDING + | CURRENT_ROW + | expr FOLLOWING + ; + +frame_boundary_end : + expr PRECEDING + | CURRENT_ROW + | expr FOLLOWING + | UNBOUNDED FOLLOWING + ; + +frame_boundary : + UNBOUNDED PRECEDING + | expr PRECEDING + | CURRENT_ROW + ; + +opt_partition_by : + /* empty */ + | PARTITION BY expr_list + ; + +opt_select_window : + /* empty */ + | window_clause + ; + +window_clause : + WINDOW window_name_defn_list + ; + +window_name_defn_list : + window_name_defn + | window_name_defn ',' window_name_defn_list + ; + +window_name_defn : + name AS window_defn + ; + +region_spec : + name + | name PRIVATE + ; + +region_list : + region_spec ',' region_list + | region_spec + ; + +declare_schema_region_stmt : + AT_DECLARE_SCHEMA_REGION name + | AT_DECLARE_SCHEMA_REGION name USING region_list + ; + +declare_deployable_region_stmt : + AT_DECLARE_DEPLOYABLE_REGION name + | AT_DECLARE_DEPLOYABLE_REGION name USING region_list + ; + +begin_schema_region_stmt : + AT_BEGIN_SCHEMA_REGION name + ; + +end_schema_region_stmt : + AT_END_SCHEMA_REGION + ; + +schema_ad_hoc_migration_stmt : + AT_SCHEMA_AD_HOC_MIGRATION version_annotation + | AT_SCHEMA_AD_HOC_MIGRATION FOR AT_RECREATE '(' name ',' name ')' + ; + +emit_enums_stmt : + AT_EMIT_ENUMS opt_name_list + ; + +emit_group_stmt: + AT_EMIT_GROUP opt_name_list + ; + +emit_constants_stmt: + AT_EMIT_CONSTANTS name_list + ; + +opt_from_query_parts : + /* empty */ + | FROM query_parts + ; + +opt_where : + /* empty */ + | WHERE expr + ; + +opt_groupby : + /* empty */ + | GROUP BY groupby_list + ; + +groupby_list : + groupby_item + | groupby_item ',' groupby_list + ; + +groupby_item : + expr opt_asc_desc + ; + +opt_asc_desc : + /* empty */ + | ASC + | DESC + ; + +opt_having : + /* empty */ + | HAVING expr + ; + +opt_orderby : + /* empty */ + | ORDER BY groupby_list + ; + +opt_limit : + /* empty */ + | LIMIT expr + ; + +opt_offset : + /* empty */ + | OFFSET expr + ; + +select_opts : + /* empty */ + | ALL + | DISTINCT + | DISTINCTROW + ; + +select_expr_list : + select_expr + | select_expr ',' select_expr_list + | '*' + ; + +select_expr : + expr opt_as_alias + | name '.' '*' + ; + +opt_as_alias : + /* empty */ + | as_alias + ; + +as_alias : + AS name + | name + ; + +query_parts : + table_or_subquery_list + | join_clause + ; + +table_or_subquery_list : + table_or_subquery + | table_or_subquery ',' table_or_subquery_list + ; + +join_clause : + table_or_subquery join_target_list + ; + +join_target_list : + join_target + | join_target join_target_list + ; + +table_or_subquery : + name opt_as_alias + | '(' select_stmt ')' opt_as_alias + | table_function opt_as_alias + | '(' query_parts ')' + ; + +join_type : + /* empty */ + | LEFT + | RIGHT + | LEFT OUTER + | RIGHT OUTER + | INNER + | CROSS + ; + +join_target : + join_type JOIN table_or_subquery opt_join_cond + ; + +opt_join_cond : + /* empty */ + | join_cond + ; + +join_cond : + ON expr + | USING '(' name_list ')' + ; + +table_function : + name '(' arg_list ')' + ; + +create_view_stmt : + CREATE opt_temp VIEW opt_if_not_exists name AS select_stmt opt_delete_version_attr + ; + +with_delete_stmt : + with_prefix delete_stmt + ; + +delete_stmt : + DELETE FROM name opt_where + ; + +opt_insert_dummy_spec : + /* empty */ + | AT_DUMMY_SEED '(' expr ')' dummy_modifier + ; + +dummy_modifier : + /* empty */ + | AT_DUMMY_NULLABLES + | AT_DUMMY_DEFAULTS + | AT_DUMMY_NULLABLES AT_DUMMY_DEFAULTS + | AT_DUMMY_DEFAULTS AT_DUMMY_NULLABLES + ; + +insert_stmt_type : + INSERT INTO + | INSERT OR REPLACE INTO + | INSERT OR IGNORE INTO + | INSERT OR ROLLBACK INTO + | INSERT OR ABORT INTO + | INSERT OR FAIL INTO + | REPLACE INTO + ; + +with_insert_stmt : + with_prefix insert_stmt + ; + +opt_column_spec : + /* empty */ + | '(' opt_name_list ')' + | '(' shape_def ')' + ; + +from_shape : + FROM CURSOR name opt_column_spec + | FROM name opt_column_spec + | FROM ARGUMENTS opt_column_spec + ; + +insert_stmt : + insert_stmt_type name opt_column_spec select_stmt opt_insert_dummy_spec + | insert_stmt_type name opt_column_spec from_shape opt_insert_dummy_spec + | insert_stmt_type name DEFAULT VALUES + | insert_stmt_type name USING select_stmt + | insert_stmt_type name USING expr_names opt_insert_dummy_spec + ; + +insert_list : + /* empty */ + | expr + | expr ',' insert_list + ; + +basic_update_stmt : + UPDATE opt_name SET update_list opt_where + ; + +with_update_stmt : + with_prefix update_stmt + ; + +update_stmt : + UPDATE name SET update_list opt_where opt_orderby opt_limit + ; + +update_entry : + name '=' expr + ; + +update_list : + update_entry + | update_entry ',' update_list + ; + +with_upsert_stmt : + with_prefix upsert_stmt + ; + +upsert_stmt : + insert_stmt ON_CONFLICT conflict_target DO NOTHING + | insert_stmt ON_CONFLICT conflict_target DO basic_update_stmt + ; + +update_cursor_stmt : + UPDATE CURSOR name opt_column_spec FROM VALUES '(' insert_list ')' + | UPDATE CURSOR name opt_column_spec from_shape + | UPDATE CURSOR name USING expr_names + ; + +conflict_target : + /* empty */ + | '(' indexed_columns ')' opt_where + ; + +function : + FUNC + | FUNCTION + ; + +declare_out_call_stmt : + DECLARE OUT call_stmt + ; + +declare_enum_stmt : + DECLARE ENUM name data_type_numeric '(' enum_values ')' + ; + +enum_values : + enum_value + | enum_value ',' enum_values + ; + +enum_value : + name + | name '=' expr + ; + +declare_func_stmt : + DECLARE function name '(' params ')' data_type_with_options + | DECLARE SELECT function name '(' params ')' data_type_with_options + | DECLARE function name '(' params ')' CREATE data_type_with_options + | DECLARE SELECT function name '(' params ')' '(' typed_names ')' + ; + +procedure : + PROC + | PROCEDURE + ; + +declare_proc_no_check_stmt : + DECLARE procedure name NO CHECK + ; + +declare_proc_stmt : + DECLARE procedure name '(' params ')' + | DECLARE procedure name '(' params ')' '(' typed_names ')' + | DECLARE procedure name '(' params ')' USING TRANSACTION + | DECLARE procedure name '(' params ')' OUT '(' typed_names ')' + | DECLARE procedure name '(' params ')' OUT '(' typed_names ')' USING TRANSACTION + | DECLARE procedure name '(' params ')' OUT UNION '(' typed_names ')' + | DECLARE procedure name '(' params ')' OUT UNION '(' typed_names ')' USING TRANSACTION + ; + +create_proc_stmt : + CREATE procedure name '(' params ')' BEGIN_ opt_stmt_list END + ; + +inout : + IN + | OUT + | INOUT + ; + +typed_name : + name data_type_with_options + | shape_def + | name shape_def + ; + +typed_names : + typed_name + | typed_name ',' typed_names + ; + +param : + name data_type_with_options + | inout name data_type_with_options + | shape_def + | name shape_def + ; + +params : + /* empty */ + | param + | param ',' params + ; + +declare_stmt : + DECLARE name_list data_type_with_options + | DECLARE name CURSOR FOR select_stmt + | DECLARE name CURSOR FOR explain_stmt + | DECLARE name CURSOR FOR call_stmt + | DECLARE name CURSOR FETCH FROM call_stmt + | DECLARE name CURSOR shape_def + | DECLARE name CURSOR LIKE select_stmt + | DECLARE name CURSOR FOR name + | DECLARE name TYPE data_type_with_options + ; + +call_stmt : + CALL name '(' ')' + | CALL name '(' call_expr_list ')' + ; + +while_stmt : + WHILE expr BEGIN_ opt_stmt_list END + ; + +switch_stmt : + SWITCH expr switch_case switch_cases + | SWITCH expr ALL VALUES switch_case switch_cases + ; + +switch_case : + WHEN expr_list THEN stmt_list + | WHEN expr_list THEN NOTHING + ; + +switch_cases : + switch_case switch_cases + | ELSE stmt_list END + | END + ; + +loop_stmt : + LOOP fetch_stmt BEGIN_ opt_stmt_list END + ; + +leave_stmt : + LEAVE + ; + +return_stmt : + RETURN + ; + +rollback_return_stmt : + ROLLBACK RETURN + ; + +commit_return_stmt : + COMMIT RETURN + ; + +throw_stmt : + THROW + ; + +trycatch_stmt : + BEGIN_ TRY opt_stmt_list END TRY ';' BEGIN_ CATCH opt_stmt_list END CATCH + ; + +continue_stmt : + CONTINUE + ; + +fetch_stmt : + FETCH name INTO name_list + | FETCH name + ; + +fetch_values_stmt : + FETCH name opt_column_spec FROM VALUES '(' insert_list ')' opt_insert_dummy_spec + | FETCH name opt_column_spec from_shape opt_insert_dummy_spec + | FETCH name USING expr_names opt_insert_dummy_spec + ; + +expr_names : + expr_name + | expr_name ',' expr_names + ; + +expr_name : + expr as_alias + ; + +fetch_call_stmt : + FETCH name opt_column_spec FROM call_stmt + ; + +open_stmt : + OPEN name + ; + +close_stmt : + CLOSE name + ; + +out_stmt : + OUT name + ; + +out_union_stmt : + OUT UNION name + ; + +if_stmt : + IF expr THEN opt_stmt_list opt_elseif_list opt_else END IF + ; + +opt_else : + /* empty */ + | ELSE opt_stmt_list + ; + +elseif_item : + ELSE_IF expr THEN opt_stmt_list + ; + +elseif_list : + elseif_item + | elseif_item elseif_list + ; + +opt_elseif_list : + /* empty */ + | elseif_list + ; + +control_stmt : + commit_return_stmt + | continue_stmt + | leave_stmt + | return_stmt + | rollback_return_stmt + | throw_stmt + ; + +guard_stmt : + IF expr control_stmt + ; + +transaction_mode : + /* empty */ + | DEFERRED + | IMMEDIATE + | EXCLUSIVE + ; + +begin_trans_stmt : + BEGIN_ transaction_mode TRANSACTION + | BEGIN_ transaction_mode + ; + +rollback_trans_stmt : + ROLLBACK + | ROLLBACK TRANSACTION + | ROLLBACK TO savepoint_name + | ROLLBACK TRANSACTION TO savepoint_name + | ROLLBACK TO SAVEPOINT savepoint_name + | ROLLBACK TRANSACTION TO SAVEPOINT savepoint_name + ; + +commit_trans_stmt : + COMMIT TRANSACTION + | COMMIT + ; + +proc_savepoint_stmt : + procedure SAVEPOINT BEGIN_ opt_stmt_list END + ; + +savepoint_name : + AT_PROC + | name + ; + +savepoint_stmt : + SAVEPOINT savepoint_name + ; + +release_savepoint_stmt : + RELEASE savepoint_name + | RELEASE SAVEPOINT savepoint_name + ; + +echo_stmt : + AT_ECHO name ',' str_literal + ; + +alter_table_add_column_stmt : + ALTER TABLE name ADD COLUMN col_def + ; + +create_trigger_stmt : + CREATE opt_temp TRIGGER opt_if_not_exists trigger_def opt_delete_version_attr + ; + +trigger_def : + name trigger_condition trigger_operation ON name trigger_action + ; + +trigger_condition : + /* empty */ + | BEFORE + | AFTER + | INSTEAD OF + ; + +trigger_operation : + DELETE + | INSERT + | UPDATE opt_of + ; + +opt_of : + /* empty */ + | OF name_list + ; + +trigger_action : + opt_foreachrow opt_when_expr BEGIN_ trigger_stmts END + ; + +opt_foreachrow : + /* empty */ + | FOR_EACH_ROW + ; + +opt_when_expr : + /* empty */ + | WHEN expr + ; + +trigger_stmts : + trigger_stmt + | trigger_stmt trigger_stmts + ; + +trigger_stmt : + trigger_update_stmt ';' + | trigger_insert_stmt ';' + | trigger_delete_stmt ';' + | trigger_select_stmt ';' + ; + +trigger_select_stmt : + select_stmt_no_with + ; + +trigger_insert_stmt : + insert_stmt + ; + +trigger_delete_stmt : + delete_stmt + ; + +trigger_update_stmt : + basic_update_stmt + ; + +enforcement_options : + FOREIGN KEY ON UPDATE + | FOREIGN KEY ON DELETE + | JOIN + | UPSERT STATEMENT + | WINDOW function + | WITHOUT ROWID + | TRANSACTION + | SELECT IF NOTHING + | INSERT SELECT + | TABLE FUNCTION + | ENCODE CONTEXT_COLUMN + | ENCODE CONTEXT_TYPE INTEGER + | ENCODE CONTEXT_TYPE LONG_INTEGER + | ENCODE CONTEXT_TYPE REAL + | ENCODE CONTEXT_TYPE BOOL_ + | ENCODE CONTEXT_TYPE TEXT + | ENCODE CONTEXT_TYPE BLOB + | IS_TRUE + | CAST + | NULL_ CHECK ON NOT NULL_ + ; + +enforce_strict_stmt : + AT_ENFORCE_STRICT enforcement_options + ; + +enforce_normal_stmt : + AT_ENFORCE_NORMAL enforcement_options + ; + +enforce_reset_stmt : + AT_ENFORCE_RESET + ; + +enforce_push_stmt : + AT_ENFORCE_PUSH + ; + +enforce_pop_stmt : + AT_ENFORCE_POP + ; + +//Lex + +UNBOUNDED : "[Uu][Nn][Bb][Oo][Uu][Nn][Dd][Ee][Dd]" ; +EXPLAIN : "[Ee][Xx][Pp][Ll][Aa][Ii][Nn]" ; +QUERY_PLAN : "[Qq][Uu][Ee][Rr][Yy][[:space:]]+[Pp][Ll][Aa][Nn]" ; +AT_PREVIOUS_SCHEMA : "@[Pp][Rr][Ee][Vv][Ii][Oo][Uu][Ss]_[Ss][Cc][Hh][Ee][Mm][Aa]" ; +AT_SCHEMA_UPGRADE_SCRIPT : "@[Ss][Cc][Hh][Ee][Mm][Aa]_[Uu][Pp][Gg][Rr][Aa][Dd][Ee]_[Ss][Cc][Rr][Ii][Pp][Tt]" ; +AT_SCHEMA_UPGRADE_VERSION : "@[Ss][Cc][Hh][Ee][Mm][Aa]_[Uu][Pp][Gg][Rr][Aa][Dd][Ee]_[Vv][Ee][Rr][Ss][Ii][Oo][Nn]" ; +SET : "[Ss][Ee][Tt]" ; +FROM : "[Ff][Rr][Oo][Mm]" ; +CURSOR : "[Cc][Uu][Rr][Ss][Oo][Rr]" ; +LET : "[Ll][Ee][Tt]" ; +AT_RECREATE : "@[Rr][Ee][Cc][Rr][Ee][Aa][Tt][Ee]" ; +AT_CREATE : "@[Cc][Rr][Ee][Aa][Tt][Ee]" ; +AT_DELETE : "@[Dd][Ee][Ll][Ee][Tt][Ee]" ; +DROP : "[Dd][Rr][Oo][Pp]" ; +TABLE : "[Tt][Aa][Bb][Ll][Ee]" ; +IF : "[Ii][Ff]" ; +EXISTS : "[Ee][Xx][Ii][Ss][Tt][Ss]" ; +VIEW : "[Vv][Ii][Ee][Ww]" ; +INDEX : "[Ii][Nn][Dd][Ee][Xx]" ; +TRIGGER : "[Tt][Rr][Ii][Gg][Gg][Ee][Rr]" ; +CREATE : "[Cc][Rr][Ee][Aa][Tt][Ee]" ; +VIRTUAL : "[Vv][Ii][Rr][Tt][Uu][Aa][Ll]" ; +USING : "[Uu][Ss][Ii][Nn][Gg]" ; +AS : "[Aa][Ss]" ; +ARGUMENTS : "[Aa][Rr][Gg][Uu][Mm][Ee][Nn][Tt][Ss]" ; +FOLLOWING : "[Ff][Oo][Ll][Ll][Oo][Ww][Ii][Nn][Gg]" ; +TEMP : "[Tt][Ee][Mm][Pp]" ; +WITHOUT : "[Ww][Ii][Tt][Hh][Oo][Uu][Tt]" ; +ROWID : "[Rr][Oo][Ww][Ii][Dd]" ; +CONSTRAINT : "[Cc][Oo][Nn][Ss][Tt][Rr][Aa][Ii][Nn][Tt]" ; +CHECK : "[Cc][Hh][Ee][Cc][Kk]" ; +AT_ATTRIBUTE : "@[Aa][Tt][Tt][Rr][Ii][Bb][Uu][Tt][Ee]" ; +PRIMARY : "[Pp][Rr][Ii][Mm][Aa][Rr][Yy]" ; +KEY : "[Kk][Ee][Yy]" ; +ON_CONFLICT : "[Oo][Nn][[:space:]]+[Cc][Oo][Nn][Ff][Ll][Ii][Cc][Tt]" ; +ROLLBACK : "[Rr][Oo][Ll][Ll][Bb][Aa][Cc][Kk]" ; +ABORT : "[Aa][Bb][Oo][Rr][Tt]" ; +FAIL : "[Ff][Aa][Ii][Ll]" ; +IGNORE : "[Ii][Gg][Nn][Oo][Rr][Ee]" ; +REPLACE : "[Rr][Ee][Pp][Ll][Aa][Cc][Ee]" ; +ON : "[Oo][Nn]" ; +DELETE : "[Dd][Ee][Ll][Ee][Tt][Ee]" ; +UPDATE : "[Uu][Pp][Dd][Aa][Tt][Ee]" ; +NULL_ : "[Nn][Uu][Ll][Ll]" ; +DEFAULT : "[Dd][Ee][Ff][Aa][Uu][Ll][Tt]" ; +CASCADE : "[Cc][Aa][Ss][Cc][Aa][Dd][Ee]" ; +RESTRICT : "[Rr][Ee][Ss][Tt][Rr][Ii][Cc][Tt]" ; +NO : "[Nn][Oo]" ; +ACTION : "[Aa][Cc][Tt][Ii][Oo][Nn]" ; +DEFERRABLE : "[Dd][Ee][Ff][Ee][Rr][Rr][Aa][Bb][Ll][Ee]" ; +NOT_DEFERRABLE : "[Nn][Oo][Tt][[:space:]]+[Dd][Ee][Ff][Ee][Rr][Rr][Aa][Bb][Ll][Ee]" ; +INITIALLY : "[Ii][Nn][Ii][Tt][Ii][Aa][Ll][Ll][Yy]" ; +DEFERRED : "[Dd][Ee][Ff][Ee][Rr][Rr][Ee][Dd]" ; +IMMEDIATE : "[Ii][Mm][Mm][Ee][Dd][Ii][Aa][Tt][Ee]" ; +FOREIGN : "[Ff][Oo][Rr][Ee][Ii][Gg][Nn]" ; +REFERENCES : "[Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee][Ss]" ; +UNIQUE : "[Uu][Nn][Ii][Qq][Uu][Ee]" ; +TEXT : "[Tt][Ee][Xx][Tt]" ; +TYPE : "[Tt][Yy][Pp][Ee]" ; +HIDDEN : "[Hh][Ii][Dd][Dd][Ee][Nn]" ; +PRIVATE : "[Pp][Rr][Ii][Vv][Aa][Tt][Ee]" ; +AUTOINCREMENT : "[Aa][Uu][Tt][Oo][Ii][Nn][Cc][Rr][Ee][Mm][Ee][Nn][Tt]" ; +AT_SENSITIVE : "@[Ss][Ee][Nn][Ss][Ii][Tt][Ii][Vv][Ee]" ; +INT_ : "[Ii][Nn][Tt]" ; +INTEGER : "[Ii][Nn][Tt][Ee][Gg][Ee][Rr]" ; +REAL : "[Rr][Ee][Aa][Ll]" ; +LONG_ : "[Ll][Oo][Nn][Gg]" ; +BOOL_ : "[Bb][Oo][Oo][Ll]" ; +LONG_INT : "[Ll][Oo][Nn][Gg][[:space:]]+[Ii][Nn][Tt]" ; +LONG_INTEGER : "[Ll][Oo][Nn][Gg][[:space:]]+[Ii][Nn][Tt][Ee][Gg][Ee][Rr]" ; +BLOB : "[Bb][Ll][Oo][Bb]" ; +OBJECT : "[Oo][Bb][Jj][Ee][Cc][Tt]" ; +STRLIT : "'(''|[^'\n])*'" ; +CSTRLIT : "\"(\\.|[^\"\n])*\"" ; +TRUE_ : "[Tt][Rr][Uu][Ee]_" ; +FALSE_ : "[Ff][Aa][Ll][Ss][Ee]" ; +CONST : "[Cc][Oo][Nn][Ss][Tt]" ; +AT_FILE : "@[Ff][Ii][Ll][Ee]" ; +AT_PROC : "@[Pp][Rr][Oo][Cc]" ; +BLOBLIT : 'BLOBLIT' ; +RAISE : "[Rr][Aa][Ii][Ss][Ee]" ; +DISTINCT : "[Dd][Ii][Ss][Tt][Ii][Nn][Cc][Tt]" ; +AT_RC : "@[Rr][Cc]" ; +NOTHING : "[Nn][Oo][Tt][Hh][Ii][Nn][Gg]" ; +THROW : "[Tt][Hh][Rr][Oo][Ww]" ; +CASE : "[Cc][Aa][Ss][Ee]" ; +END : "[Ee][Nn][Dd]" ; +ELSE : "[Ee][Ll][Ss][Ee]" ; +CAST : "[Cc][Aa][Ss][Tt]" ; +WHEN : "[Ww][Hh][Ee][Nn]" ; +THEN : "[Tt][Hh][Ee][Nn]" ; +WITH : "[Ww][Ii][Tt][Hh]" ; +RECURSIVE : "[Rr][Ee][Cc][Uu][Rr][Ss][Ii][Vv][Ee]" ; +SELECT : "[Ss][Ee][Ll][Ee][Cc][Tt]" ; +VALUES : "[Vv][Aa][Ll][Uu][Ee][Ss]" ; +OVER : "[Oo][Vv][Ee][Rr]" ; +FILTER : "[Ff][Ii][Ll][Tt][Ee][Rr]" ; +RANGE : "[Rr][Aa][Nn][Gg][Ee]" ; +ROWS : "[Rr][Oo][Ww][Ss]" ; +GROUPS : "[Gg][Rr][Oo][Uu][Pp][Ss]" ; +EXCLUDE_NO_OTHERS : "[Ee][Xx][Cc][Ll][Uu][Dd][Ee][[:space:]]+[Nn][Oo][[:space:]]+[Oo][Tt][Hh][Ee][Rr][Ss]" ; +EXCLUDE_CURRENT_ROW : "[Ee][Xx][Cc][Ll][Uu][Dd][Ee][[:space:]]+[Cc][Uu][Rr][Rr][Ee][Nn][Tt][[:space:]]+[Rr][Oo][Ww]" ; +EXCLUDE_GROUP : "[Ee][Xx][Cc][Ll][Uu][Dd][Ee][[:space:]]+[Gg][Rr][Oo][Uu][Pp]" ; +EXCLUDE_TIES : "[Ee][Xx][Cc][Ll][Uu][Dd][Ee][[:space:]]+[Tt][Ii][Ee][Ss]" ; +PRECEDING : "[Pp][Rr][Ee][Cc][Ee][Dd][Ii][Nn][Gg]" ; +CURRENT_ROW : "[Cc][Uu][Rr][Rr][Ee][Nn][Tt][[:space:]]+[Rr][Oo][Ww]" ; +PARTITION : "[Pp][Aa][Rr][Tt][Ii][Tt][Ii][Oo][Nn]" ; +BY : "[Bb][Yy]" ; +WINDOW : "[Ww][Ii][Nn][Dd][Oo][Ww]" ; +AT_DECLARE_SCHEMA_REGION : "@[Dd][Ee][Cc][Ll][Aa][Rr][Ee]_[Ss][Cc][Hh][Ee][Mm][Aa]_[Rr][Ee][Gg][Ii][Oo][Nn]" ; +AT_DECLARE_DEPLOYABLE_REGION : "@[Dd][Ee][Cc][Ll][Aa][Rr][Ee]_[Dd][Ee][Pp][Ll][Oo][Yy][Aa][Bb][Ll][Ee]_[Rr][Ee][Gg][Ii][Oo][Nn]" ; +AT_BEGIN_SCHEMA_REGION : "@[Bb][Ee][Gg][Ii][Nn]_[Ss][Cc][Hh][Ee][Mm][Aa]_[Rr][Ee][Gg][Ii][Oo][Nn]" ; +AT_END_SCHEMA_REGION : "@[Ee][Nn][Dd]_[Ss][Cc][Hh][Ee][Mm][Aa]_[Rr][Ee][Gg][Ii][Oo][Nn]" ; +AT_SCHEMA_AD_HOC_MIGRATION : "@[Ss][Cc][Hh][Ee][Mm][Aa]_[Aa][Dd]_[Hh][Oo][Cc]_[Mm][Ii][Gg][Rr][Aa][Tt][Ii][Oo][Nn]" ; +FOR : "[Ff][Oo][Rr]" ; +AT_EMIT_CONSTANTS : "@[Ee][Mm][Ii][Tt]_[Cc][Oo][Nn][Ss][Tt][Aa][Nn][Tt][Ss]" ; +AT_EMIT_ENUMS : "@[Ee][Mm][Ii][Tt]_[Ee][Nn][Uu][Mm][Ss]" ; +AT_EMIT_GROUP : "@[Ee][Mm][Ii][Tt]_[Gg][Rr][Oo][Uu][Pp]" ; +WHERE : "[Ww][Hh][Ee][Rr][Ee]" ; +GROUP : "[Gg][Rr][Oo][Uu][Pp]" ; +ASC : "[Aa][Ss][Cc]" ; +DESC : "[Dd][Ee][Ss][Cc]" ; +HAVING : "[Hh][Aa][Vv][Ii][Nn][Gg]" ; +ORDER : "[Oo][Rr][Dd][Ee][Rr]" ; +LIMIT : "[Ll][Ii][Mm][Ii][Tt]" ; +OFFSET : "[Oo][Ff][Ff][Ss][Ee][Tt]" ; +ALL : "[Aa][Ll][Ll]" ; +DISTINCTROW : "[Dd][Ii][Ss][Tt][Ii][Nn][Cc][Tt][Rr][Oo][Ww]" ; +LEFT : "[Ll][Ee][Ff][Tt]" ; +RIGHT : "[Rr][Ii][Gg][Hh][Tt]" ; +OUTER : "[Oo][Uu][Tt][Ee][Rr]" ; +INNER : "[Ii][Nn][Nn][Ee][Rr]" ; +CROSS : "[Cc][Rr][Oo][Ss][Ss]" ; +JOIN : "[Jj][Oo][Ii][Nn]" ; +AT_DUMMY_SEED : "@[Dd][Uu][Mm][Mm][Yy]_[Ss][Ee][Ee][Dd]" ; +AT_DUMMY_NULLABLES : "@[Dd][Uu][Mm][Mm][Yy]_[Nn][Uu][Ll][Ll][Aa][Bb][Ll][Ee][Ss]" ; +AT_DUMMY_DEFAULTS : "@[Dd][Uu][Mm][Mm][Yy]_[Dd][Ee][Ff][Aa][Uu][Ll][Tt][Ss]" ; +INSERT : "[Ii][Nn][Ss][Ee][Rr][Tt]" ; +INTO : "[Ii][Nn][Tt][Oo]" ; +DO : "[Dd][Oo]" ; +FUNC : "[Ff][Uu][Nn][Cc]" ; +FUNCTION : "[Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn]" ; +DECLARE : "[Dd][Ee][Cc][Ll][Aa][Rr][Ee]" ; +OUT : "[Oo][Uu][Tt]" ; +ENUM : "[Ee][Nn][Uu][Mm]" ; +PROC : "[Pp][Rr][Oo][Cc]" ; +PROCEDURE : "[Pp][Rr][Oo][Cc][Ee][Dd][Uu][Rr][Ee]" ; +TRANSACTION : "[Tt][Rr][Aa][Nn][Ss][Aa][Cc][Tt][Ii][Oo][Nn]" ; +BEGIN_ : "[Bb][Ee][Gg][Ii][Nn]" ; +INOUT : "[Ii][Nn][Oo][Uu][Tt]" ; +FETCH : "[Ff][Ee][Tt][Cc][Hh]" ; +CALL : "[Cc][Aa][Ll][Ll]" ; +WHILE : "[Ww][Hh][Ii][Ll][Ee]" ; +SWITCH : "[Ss][Ww][Ii][Tt][Cc][Hh]" ; +LOOP : "[Ll][Oo][Oo][Pp]" ; +LEAVE : "[Ll][Ee][Aa][Vv][Ee]" ; +RETURN : "[Rr][Ee][Tt][Uu][Rr][Nn]" ; +COMMIT : "[Cc][Oo][Mm][Mm][Ii][Tt]" ; +TRY : "[Tt][Rr][Yy]" ; +CATCH : "[Cc][Aa][Tt][Cc][Hh]" ; +CONTINUE : "[Cc][Oo][Nn][Tt][Ii][Nn][Uu][Ee]" ; +OPEN : "[Oo][Pp][Ee][Nn]" ; +CLOSE : "[Cc][Ll][Oo][Ss][Ee]" ; +ELSE_IF : "[Ee][Ll][Ss][Ee][[:space:]]+[Ii][Ff]" ; +EXCLUSIVE : "[Ee][Xx][Cc][Ll][Uu][Ss][Ii][Vv][Ee]" ; +TO : "[Tt][Oo]" ; +SAVEPOINT : "[Ss][Aa][Vv][Ee][Pp][Oo][Ii][Nn][Tt]" ; +RELEASE : "[Rr][Ee][Ll][Ee][Aa][Ss][Ee]" ; +AT_ECHO : "@[Ee][Cc][Hh][Oo]" ; +ALTER : "[Aa][Ll][Tt][Ee][Rr]" ; +ADD : "[Aa][Dd][Dd]" ; +COLUMN : "[Cc][Oo][Ll][Uu][Mm][Nn]" ; +BEFORE : "[Bb][Ee][Ff][Oo][Rr][Ee]" ; +AFTER : "[Aa][Ff][Tt][Ee][Rr]" ; +INSTEAD : "[Ii][Nn][Ss][Tt][Ee][Aa][Dd]" ; +OF : "[Oo][Ff]" ; +FOR_EACH_ROW : "[Ff][Oo][Rr][[:space:]]+[Ee][Aa][Cc][Hh][[:space:]]+[Rr][Oo][Ww]" ; +UPSERT : "[Uu][Pp][Ss][Ee][Rr][Tt]" ; +STATEMENT : "[Ss][Tt][Aa][Tt][Ee][Mm][Ee][Nn][Tt]" ; +ENCODE : "[Ee][Nn][Cc][Oo][Dd][Ee]" ; +CONTEXT_COLUMN : "[Cc][Oo][Nn][Tt][Ee][Xx][Tt][[:space:]]+[Cc][Oo][Ll][Uu][Mm][Nn]" ; +CONTEXT_TYPE : "[Cc][Oo][Nn][Tt][Ee][Xx][Tt][[:space:]]+[Tt][Yy][Pp][Ee]" ; +AT_ENFORCE_STRICT : "@[Ee][Nn][Ff][Oo][Rr][Cc][Ee]_[Ss][Tt][Rr][Ii][Cc][Tt]" ; +AT_ENFORCE_NORMAL : "@[Ee][Nn][Ff][Oo][Rr][Cc][Ee]_[Nn][Oo][Rr][Mm][Aa][Ll]" ; +AT_ENFORCE_RESET : "@[Ee][Nn][Ff][Oo][Rr][Cc][Ee]_[Rr][Ee][Ss][Ee][Tt]" ; +AT_ENFORCE_PUSH : "@[Ee][Nn][Ff][Oo][Rr][Cc][Ee]_[Pp][Uu][Ss][Hh]" ; +AT_ENFORCE_POP : "@[Ee][Nn][Ff][Oo][Rr][Cc][Ee]_[Pp][Oo][Pp]" ; +UNION_ALL : "[Uu][Nn][Ii][Oo][Nn][[:space:]]+[Aa][Ll][Ll]" ; +UNION : "[Uu][Nn][Ii][Oo][Nn]" ; +INTERSECT : "[Ii][Nn][Tt][Ee][Rr][Ss][Ee][Cc][Tt]" ; +EXCEPT : "[Ee][Xx][Cc][Ee][Pp][Tt]" ; +OR : "[Oo][Rr]" ; +AND : "[Aa][Nn][Dd]" ; +NOT : "[Nn][Oo][Tt]" ; +NOT_BETWEEN : "[Nn][Oo][Tt][[:space:]]+[Bb][Ee][Tt][Ww][Ee][Ee][Nn]" ; +BETWEEN : "[Bb][Ee][Tt][Ww][Ee][Ee][Nn]" ; +LIKE : "[Ll][Ii][Kk][Ee]" ; +NOT_LIKE : "[Nn][Oo][Tt][[:space:]]+[Ll][Ii][Kk][Ee]" ; +GLOB : "[Gg][Ll][Oo][Bb]" ; +NOT_GLOB : "[Nn][Oo][Tt][[:space:]]+[Gg][Ll][Oo][Bb]" ; +MATCH : "[Mm][Aa][Tt][Cc][Hh]" ; +NOT_MATCH : "[Nn][Oo][Tt][[:space:]]+[Mm][Aa][Tt][Cc][Hh]" ; +REGEXP : "[Rr][Ee][Gg][Ee][Xx][Pp]" ; +NOT_REGEXP : "[Nn][Oo][Tt][[:space:]]+[Rr][Ee][Gg][Ee][Xx][Pp]" ; +IN : "[Ii][Nn]" ; +NOT_IN : "[Nn][Oo][Tt][[:space:]]+[Ii][Nn]" ; +IS_NOT : "[Ii][Ss][[:space:]]+[Nn][Oo][Tt]" ; +IS : "[Ii][Ss]" ; +IS_TRUE : "[Ii][Ss][[:space:]]+[Tt][Rr][Uu][Ee]" ; +IS_FALSE : "[Ii][Ss][[:space:]]+[Ff][Aa][Ll][Ss][Ee]" ; +IS_NOT_TRUE : "[Ii][Ss][[:space:]]+[Nn][Oo][Tt][[:space:]]+[Tt][Rr][Uu][Ee]" ; +IS_NOT_FALSE : "[Ii][Ss][[:space:]]+[Nn][Oo][Tt][[:space:]]+[Ff][Aa][Ll][Ss][Ee]" ; +ISNULL : "[Ii][Ss][Nn][Uu][Ll][Ll]" ; +NOTNULL : "[Nn][Oo][Tt][Nn][Uu][Ll][Ll]" ; +COLLATE : "[Cc][Oo][Ll][Ll][Aa][Tt][Ee]" ; + +ID : "[_a-zA-Z][a-zA-Z0-9_]*" ; +REALLIT : "([0-9]+\.[0-9]*|\.[0-9]+)([Ee](\+|\-)?[0-9]+)?" ; +INTLIT : "[0-9]+" ; +LONGLIT : "[0-9]+L" ; + +ASSIGN : ':=' ; +CONCAT : '||' ; +EQEQ : '==' ; +GE : '>=' ; +LE : '<=' ; +LS : '<<' ; +NE : '<>' ; +NE_ : '!=' ; +RS : '>>' ; + +} diff --git a/playground/cxx-parser.g b/playground/cxx-parser.g new file mode 100644 index 0000000..109824d --- /dev/null +++ b/playground/cxx-parser.g @@ -0,0 +1,1254 @@ +// /usr/bin/time /home/mingo/dev/c/A_grammars/lalr/lalr-nb/dist/Release/GNU-Linux/lalr-nb cxx-parser.g +// /usr/bin/time /home/mingo/dev/c/A_grammars/lalr/test-grammar-nb/dist/Release/GNU-Linux/test-grammar-nb -g cxx-parser.g -i lemon.pp.c +// /usr/bin/time /home/mingo/dev/c/A_grammars/lalr/test-grammar-nb/dist/Release/GNU-Linux/test-grammar-nb -g cxx-parser.g -i test.c + + +cxxparser { + +//%error_recovery_show; +%error_recovery_off; +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +//%token '+' +//%token '-' +//%token '*' +//%token '/' +//%token '%' +//%token '^' +//%token '&' +//%token '|' +//%token '~' +//%token '!' +//%token '<' +//%token '>' +//%token '=' +//%token ':' +//%token '[' +//%token ']' +//%token '{' +//%token '}' +//%token '(' +//%token ')' +//%token '?' +//%token '.' +//%token '\'' +//%token '"' +//%token '\\' +//%token '@' +//%token '$' +//%token ';' +//%token ',' +//%token ARROW +//%token ARROW_STAR +//%token DEC +//%token EQ +//%token GE +//%token INC +//%token LE +//%token LOG_AND +//%token LOG_OR +//%token NE +//%token SHL +//%token SHR +//%token ASS_ADD +//%token ASS_AND +//%token ASS_DIV +//%token ASS_MOD +//%token ASS_MUL +//%token ASS_OR +//%token ASS_SHL +//%token ASS_SHR +//%token ASS_SUB +//%token ASS_XOR +//%token DOT_STAR +//%token ELLIPSIS +//%token SCOPE +//%token PRIVATE +//%token PROTECTED +//%token PUBLIC +//%token BOOL +//%token CHAR +//%token DOUBLE +//%token FLOAT +//%token INT +//%token LONG +//%token SHORT +//%token SIGNED +//%token UNSIGNED +//%token VOID +//%token WCHAR_T +//%token CLASS +//%token ENUM +//%token NAMESPACE +//%token STRUCT +//%token TYPENAME +//%token UNION +//%token CONST +//%token VOLATILE +//%token AUTO +//%token EXPLICIT +//%token EXPORT +//%token EXTERN +//%token FRIEND +//%token INLINE +//%token MUTABLE +//%token REGISTER +//%token STATIC +//%token TEMPLATE +//%token TYPEDEF +//%token USING +//%token VIRTUAL +//%token ASM +//%token ATTRIBUTE +//%token BREAK +//%token CASE +//%token CATCH +//%token CONST_CAST +//%token CONTINUE +//%token DEFAULT +//%token DELETE +//%token DO +//%token DYNAMIC_CAST +//%token ELSE +//%token FALSE +//%token FOR +//%token GOTO +//%token IF +//%token NEW +//%token OPERATOR +//%token REINTERPRET_CAST +//%token RETURN +//%token SIZEOF +//%token STATIC_CAST +//%token SWITCH +//%token THIS +//%token THROW +//%token TRUE +//%token TRY +//%token TYPEID +//%token WHILE +//%token CharacterLiteral +//%token FloatingLiteral +//%token Identifier +//%token IntegerLiteral +//%token NumberLiteral +//%token StringLiteral +//%token SHIFT_THERE +//%token REDUCE_HERE_MOSTLY +//%token '#' + +%nonassoc /*1*/ SHIFT_THERE ; +%nonassoc /*2*/ '+' '-' '*' '&' '<' ':' '[' '{' DEC INC SCOPE ELSE StringLiteral ; +%nonassoc /*3*/ REDUCE_HERE_MOSTLY ; +%nonassoc /*4*/ '(' ; + +//%start translation_unit + +//%% + +translation_unit : + declaration_seq_opt + ; + +identifier_word : + Identifier + ; +identifier : + identifier_word %prec SHIFT_THERE /*1N*/ + ; +id : + identifier %prec SHIFT_THERE /*1N*/ + | identifier template_test '+' /*2N*/ template_argument_list '>' + | identifier template_test '+' /*2N*/ '>' + | identifier template_test '-' /*2N*/ + | template_id + ; +template_test : + '<' /*2N*/ + ; +global_scope : + SCOPE /*2N*/ + | TEMPLATE global_scope + ; +id_scope : + id SCOPE /*2N*/ + ; +nested_id : + id %prec SHIFT_THERE /*1N*/ + | id_scope nested_id + ; +scoped_id : + nested_id + | global_scope nested_id + ; +destructor_id : + '~' id + | TEMPLATE destructor_id + ; +special_function_id : + conversion_function_id + | operator_function_id + | TEMPLATE special_function_id + ; +nested_special_function_id : + special_function_id + | id_scope destructor_id + | id_scope nested_special_function_id + ; +scoped_special_function_id : + nested_special_function_id + | global_scope nested_special_function_id + ; +declarator_id : + scoped_id + | scoped_special_function_id + | destructor_id + ; +built_in_type_id : + built_in_type_specifier + | built_in_type_id built_in_type_specifier + ; +pseudo_destructor_id : + built_in_type_id SCOPE /*2N*/ '~' built_in_type_id + | '~' built_in_type_id + | TEMPLATE pseudo_destructor_id + ; +nested_pseudo_destructor_id : + pseudo_destructor_id + | id_scope nested_pseudo_destructor_id + ; +scoped_pseudo_destructor_id : + nested_pseudo_destructor_id + | global_scope scoped_pseudo_destructor_id + ; +string : + StringLiteral /*2N*/ + ; +literal : + IntegerLiteral + | CharacterLiteral + | FloatingLiteral + | string + | boolean_literal + ; +boolean_literal : + FALSE + | TRUE + ; +primary_expression : + literal + | THIS + | suffix_decl_specified_ids + | abstract_expression %prec REDUCE_HERE_MOSTLY /*3N*/ + ; +abstract_expression : + parenthesis_clause + | '[' /*2N*/ expression_opt ']' + | TEMPLATE parenthesis_clause + ; +type1_parameters : + parameter_declaration_list ';' + | type1_parameters parameter_declaration_list ';' + ; +mark_type1 : + /*empty*/ + ; +postfix_expression : + primary_expression + | postfix_expression parenthesis_clause mark_type1 '-' /*2N*/ + | postfix_expression parenthesis_clause mark_type1 '+' /*2N*/ type1_parameters mark '{' /*2N*/ error + | postfix_expression parenthesis_clause mark_type1 '+' /*2N*/ type1_parameters mark error + | postfix_expression parenthesis_clause mark_type1 '+' /*2N*/ error + | postfix_expression '[' /*2N*/ expression_opt ']' + | postfix_expression '.' declarator_id + | postfix_expression '.' scoped_pseudo_destructor_id + | postfix_expression ARROW declarator_id + | postfix_expression ARROW scoped_pseudo_destructor_id + | postfix_expression INC /*2N*/ + | postfix_expression DEC /*2N*/ + | DYNAMIC_CAST '<' /*2N*/ type_id '>' '(' /*4N*/ expression ')' + | STATIC_CAST '<' /*2N*/ type_id '>' '(' /*4N*/ expression ')' + | REINTERPRET_CAST '<' /*2N*/ type_id '>' '(' /*4N*/ expression ')' + | CONST_CAST '<' /*2N*/ type_id '>' '(' /*4N*/ expression ')' + | TYPEID parameters_clause + ; +expression_list_opt : + /*empty*/ + | expression_list + ; +expression_list : + assignment_expression + | expression_list ',' assignment_expression + ; +unary_expression : + postfix_expression + | INC /*2N*/ cast_expression + | DEC /*2N*/ cast_expression + | ptr_operator cast_expression + | suffix_decl_specified_scope star_ptr_operator cast_expression + | '+' /*2N*/ cast_expression + | '-' /*2N*/ cast_expression + | '!' cast_expression + | '~' cast_expression + | SIZEOF unary_expression + | new_expression + | global_scope new_expression + | delete_expression + | global_scope delete_expression + ; +delete_expression : + DELETE cast_expression + ; +new_expression : + NEW new_type_id new_initializer_opt + | NEW parameters_clause new_type_id new_initializer_opt + | NEW parameters_clause + | NEW parameters_clause parameters_clause new_initializer_opt + ; +new_type_id : + type_specifier ptr_operator_seq_opt + | type_specifier new_declarator + | type_specifier new_type_id + ; +new_declarator : + ptr_operator new_declarator + | direct_new_declarator + ; +direct_new_declarator : + '[' /*2N*/ expression ']' + | direct_new_declarator '[' /*2N*/ constant_expression ']' + ; +new_initializer_opt : + /*empty*/ + | '(' /*4N*/ expression_list_opt ')' + ; +cast_expression : + unary_expression + | abstract_expression cast_expression + ; +pm_expression : + cast_expression + | pm_expression DOT_STAR cast_expression + | pm_expression ARROW_STAR cast_expression + ; +multiplicative_expression : + pm_expression + | multiplicative_expression star_ptr_operator pm_expression + | multiplicative_expression '/' pm_expression + | multiplicative_expression '%' pm_expression + ; +additive_expression : + multiplicative_expression + | additive_expression '+' /*2N*/ multiplicative_expression + | additive_expression '-' /*2N*/ multiplicative_expression + ; +shift_expression : + additive_expression + | shift_expression SHL additive_expression + | shift_expression SHR additive_expression + ; +relational_expression : + shift_expression + | relational_expression '<' /*2N*/ shift_expression + | relational_expression '>' shift_expression + | relational_expression LE shift_expression + | relational_expression GE shift_expression + ; +equality_expression : + relational_expression + | equality_expression EQ relational_expression + | equality_expression NE relational_expression + ; +and_expression : + equality_expression + | and_expression '&' /*2N*/ equality_expression + ; +exclusive_or_expression : + and_expression + | exclusive_or_expression '^' and_expression + ; +inclusive_or_expression : + exclusive_or_expression + | inclusive_or_expression '|' exclusive_or_expression + ; +logical_and_expression : + inclusive_or_expression + | logical_and_expression LOG_AND inclusive_or_expression + ; +logical_or_expression : + logical_and_expression + | logical_or_expression LOG_OR logical_and_expression + ; +conditional_expression : + logical_or_expression + | logical_or_expression '?' expression ':' /*2N*/ assignment_expression + ; +assignment_expression : + conditional_expression + | logical_or_expression assignment_operator assignment_expression + | logical_or_expression '=' braced_initializer + | throw_expression + ; +assignment_operator : + '=' + | ASS_ADD + | ASS_AND + | ASS_DIV + | ASS_MOD + | ASS_MUL + | ASS_OR + | ASS_SHL + | ASS_SHR + | ASS_SUB + | ASS_XOR + ; +expression_opt : + /*empty*/ + | expression + ; +expression : + assignment_expression + | expression_list ',' assignment_expression + ; +constant_expression : + conditional_expression + ; +templated_relational_expression : + shift_expression + | templated_relational_expression '<' /*2N*/ shift_expression + | templated_relational_expression LE shift_expression + | templated_relational_expression GE shift_expression + ; +templated_equality_expression : + templated_relational_expression + | templated_equality_expression EQ templated_relational_expression + | templated_equality_expression NE templated_relational_expression + ; +templated_and_expression : + templated_equality_expression + | templated_and_expression '&' /*2N*/ templated_equality_expression + ; +templated_exclusive_or_expression : + templated_and_expression + | templated_exclusive_or_expression '^' templated_and_expression + ; +templated_inclusive_or_expression : + templated_exclusive_or_expression + | templated_inclusive_or_expression '|' templated_exclusive_or_expression + ; +templated_logical_and_expression : + templated_inclusive_or_expression + | templated_logical_and_expression LOG_AND templated_inclusive_or_expression + ; +templated_logical_or_expression : + templated_logical_and_expression + | templated_logical_or_expression LOG_OR templated_logical_and_expression + ; +templated_conditional_expression : + templated_logical_or_expression + | templated_logical_or_expression '?' templated_expression ':' /*2N*/ templated_assignment_expression + ; +templated_assignment_expression : + templated_conditional_expression + | templated_logical_or_expression assignment_operator templated_assignment_expression + | templated_throw_expression + ; +templated_expression : + templated_assignment_expression + | templated_expression_list ',' templated_assignment_expression + ; +templated_expression_list : + templated_assignment_expression + | templated_expression_list ',' templated_assignment_expression + ; +looping_statement : + start_search looped_statement + ; +looped_statement : + statement + | advance_search '+' /*2N*/ looped_statement + | advance_search '-' /*2N*/ + ; +statement : + control_statement + | compound_statement + | declaration_statement + | try_block + ; +control_statement : + labeled_statement + | selection_statement + | iteration_statement + | jump_statement + ; +labeled_statement : + identifier_word ':' /*2N*/ looping_statement + | CASE constant_expression ':' /*2N*/ looping_statement + | DEFAULT ':' /*2N*/ looping_statement + ; +compound_statement : + '{' /*2N*/ statement_seq_opt '}' + | '{' /*2N*/ statement_seq_opt looping_statement '#' bang error '}' + ; +statement_seq_opt : + /*empty*/ + | statement_seq_opt looping_statement + | statement_seq_opt looping_statement '#' bang error ';' + ; +selection_statement : + IF '(' /*4N*/ condition ')' looping_statement %prec SHIFT_THERE /*1N*/ + | IF '(' /*4N*/ condition ')' looping_statement ELSE /*2N*/ looping_statement + | SWITCH '(' /*4N*/ condition ')' looping_statement + ; +condition_opt : + /*empty*/ + | condition + ; +condition : + parameter_declaration_list + ; +iteration_statement : + WHILE '(' /*4N*/ condition ')' looping_statement + | DO looping_statement WHILE '(' /*4N*/ expression ')' ';' + | FOR '(' /*4N*/ for_init_statement condition_opt ';' expression_opt ')' looping_statement + ; +for_init_statement : + simple_declaration + ; +jump_statement : + BREAK ';' + | CONTINUE ';' + | RETURN expression_opt ';' + | GOTO identifier ';' + ; +declaration_statement : + block_declaration + ; +compound_declaration : + '{' /*2N*/ nest declaration_seq_opt '}' + | '{' /*2N*/ nest declaration_seq_opt util looping_declaration '#' bang error '}' + ; +declaration_seq_opt : + /*empty*/ + | declaration_seq_opt util looping_declaration + | declaration_seq_opt util looping_declaration '#' bang error ';' + ; +looping_declaration : + start_search1 looped_declaration + ; +looped_declaration : + declaration + | advance_search '+' /*2N*/ looped_declaration + | advance_search '-' /*2N*/ + ; +declaration : + block_declaration + | function_definition + | template_declaration + | explicit_specialization + | specialised_declaration + ; +specialised_declaration : + linkage_specification + | namespace_definition + | TEMPLATE specialised_declaration + ; +block_declaration : + simple_declaration + | specialised_block_declaration + ; +specialised_block_declaration : + asm_definition + | namespace_alias_definition + | using_declaration + | using_directive + | TEMPLATE specialised_block_declaration + ; +simple_declaration : + ';' + | init_declaration ';' + | init_declarations ';' + | decl_specifier_prefix simple_declaration + ; +suffix_built_in_decl_specifier_raw : + built_in_type_specifier + | suffix_built_in_decl_specifier_raw built_in_type_specifier + | suffix_built_in_decl_specifier_raw decl_specifier_suffix + ; +suffix_built_in_decl_specifier : + suffix_built_in_decl_specifier_raw + | TEMPLATE suffix_built_in_decl_specifier + ; +suffix_named_decl_specifier : + scoped_id + | elaborate_type_specifier + | suffix_named_decl_specifier decl_specifier_suffix + ; +suffix_named_decl_specifier_bi : + suffix_named_decl_specifier + | suffix_named_decl_specifier suffix_built_in_decl_specifier_raw + ; +suffix_named_decl_specifiers : + suffix_named_decl_specifier_bi + | suffix_named_decl_specifiers suffix_named_decl_specifier_bi + ; +suffix_named_decl_specifiers_sf : + scoped_special_function_id + | suffix_named_decl_specifiers + | suffix_named_decl_specifiers scoped_special_function_id + ; +suffix_decl_specified_ids : + suffix_built_in_decl_specifier + | suffix_built_in_decl_specifier suffix_named_decl_specifiers_sf + | suffix_named_decl_specifiers_sf + ; +suffix_decl_specified_scope : + suffix_named_decl_specifiers SCOPE /*2N*/ + | suffix_built_in_decl_specifier suffix_named_decl_specifiers SCOPE /*2N*/ + | suffix_built_in_decl_specifier SCOPE /*2N*/ + ; +decl_specifier_affix : + storage_class_specifier + | function_specifier + | FRIEND + | TYPEDEF + | cv_qualifier + ; +decl_specifier_suffix : + decl_specifier_affix + ; +decl_specifier_prefix : + decl_specifier_affix + | TEMPLATE decl_specifier_prefix + ; +storage_class_specifier : + REGISTER + | STATIC + | MUTABLE + | EXTERN %prec SHIFT_THERE /*1N*/ + | AUTO + ; +function_specifier : + EXPLICIT + | INLINE + | VIRTUAL + ; +type_specifier : + simple_type_specifier + | elaborate_type_specifier + | cv_qualifier + ; +elaborate_type_specifier : + class_specifier + | enum_specifier + | elaborated_type_specifier + | TEMPLATE elaborate_type_specifier + ; +simple_type_specifier : + scoped_id + | built_in_type_specifier + ; +built_in_type_specifier : + CHAR + | WCHAR_T + | BOOL + | SHORT + | INT + | LONG + | SIGNED + | UNSIGNED + | FLOAT + | DOUBLE + | VOID + ; +elaborated_type_specifier : + elaborated_class_specifier + | elaborated_enum_specifier + | TYPENAME scoped_id + ; +elaborated_enum_specifier : + ENUM scoped_id %prec SHIFT_THERE /*1N*/ + ; +enum_specifier : + ENUM scoped_id enumerator_clause + | ENUM enumerator_clause + ; +enumerator_clause : + '{' /*2N*/ enumerator_list_ecarb + | '{' /*2N*/ enumerator_list enumerator_list_ecarb + | '{' /*2N*/ enumerator_list ',' enumerator_definition_ecarb + ; +enumerator_list_ecarb : + '}' + | bang error '}' + ; +enumerator_definition_ecarb : + '}' + | bang error '}' + ; +enumerator_definition_filler : + /*empty*/ + | bang error ',' + ; +enumerator_list_head : + enumerator_definition_filler + | enumerator_list ',' enumerator_definition_filler + ; +enumerator_list : + enumerator_list_head enumerator_definition + ; +enumerator_definition : + enumerator + | enumerator '=' constant_expression + ; +enumerator : + identifier + ; +namespace_definition : + NAMESPACE scoped_id compound_declaration + | NAMESPACE compound_declaration + ; +namespace_alias_definition : + NAMESPACE scoped_id '=' scoped_id ';' + ; +using_declaration : + USING declarator_id ';' + | USING TYPENAME declarator_id ';' + ; +using_directive : + USING NAMESPACE scoped_id ';' + ; +asm_definition : + ASM '(' /*4N*/ string ')' ';' + ; +linkage_specification : + EXTERN string looping_declaration + | EXTERN string compound_declaration + ; +init_declarations : + assignment_expression ',' init_declaration + | init_declarations ',' init_declaration + ; +init_declaration : + assignment_expression + ; +star_ptr_operator : + '*' /*2N*/ + | star_ptr_operator cv_qualifier + ; +nested_ptr_operator : + star_ptr_operator + | id_scope nested_ptr_operator + ; +ptr_operator : + '&' /*2N*/ + | nested_ptr_operator + | global_scope nested_ptr_operator + ; +ptr_operator_seq : + ptr_operator + | ptr_operator ptr_operator_seq + ; +ptr_operator_seq_opt : + /*empty*/ %prec SHIFT_THERE /*1N*/ + | ptr_operator ptr_operator_seq_opt + ; +cv_qualifier_seq_opt : + /*empty*/ + | cv_qualifier_seq_opt cv_qualifier + ; +cv_qualifier : + CONST + | VOLATILE + ; +type_id : + type_specifier abstract_declarator_opt + | type_specifier type_id + ; +abstract_declarator_opt : + /*empty*/ + | ptr_operator abstract_declarator_opt + | direct_abstract_declarator + ; +direct_abstract_declarator_opt : + /*empty*/ + | direct_abstract_declarator + ; +direct_abstract_declarator : + direct_abstract_declarator_opt parenthesis_clause + | direct_abstract_declarator_opt '[' /*2N*/ ']' + | direct_abstract_declarator_opt '[' /*2N*/ constant_expression ']' + ; +parenthesis_clause : + parameters_clause cv_qualifier_seq_opt + | parameters_clause cv_qualifier_seq_opt exception_specification + ; +parameters_clause : + '(' /*4N*/ parameter_declaration_clause ')' + ; +parameter_declaration_clause : + /*empty*/ + | parameter_declaration_list + | parameter_declaration_list ELLIPSIS + ; +parameter_declaration_list : + parameter_declaration + | parameter_declaration_list ',' parameter_declaration + ; +abstract_pointer_declaration : + ptr_operator_seq + | multiplicative_expression star_ptr_operator ptr_operator_seq_opt + ; +abstract_parameter_declaration : + abstract_pointer_declaration + | and_expression '&' /*2N*/ + | and_expression '&' /*2N*/ abstract_pointer_declaration + ; +special_parameter_declaration : + abstract_parameter_declaration + | abstract_parameter_declaration '=' assignment_expression + | ELLIPSIS + ; +parameter_declaration : + assignment_expression + | special_parameter_declaration + | decl_specifier_prefix parameter_declaration + ; +templated_parameter_declaration : + templated_assignment_expression + | templated_abstract_declaration + | templated_abstract_declaration '=' templated_assignment_expression + | decl_specifier_prefix templated_parameter_declaration + ; +templated_abstract_declaration : + abstract_pointer_declaration + | templated_and_expression '&' /*2N*/ + | templated_and_expression '&' /*2N*/ abstract_pointer_declaration + ; +function_definition : + ctor_definition + | func_definition + ; +func_definition : + assignment_expression function_try_block + | assignment_expression function_body + | decl_specifier_prefix func_definition + ; +ctor_definition : + constructor_head function_try_block + | constructor_head function_body + | decl_specifier_prefix ctor_definition + ; +constructor_head : + bit_field_init_declaration + | constructor_head ',' assignment_expression + ; +function_try_block : + TRY function_block handler_seq + ; +function_block : + ctor_initializer_opt function_body + ; +function_body : + compound_statement + ; +initializer_clause : + assignment_expression + | braced_initializer + ; +braced_initializer : + '{' /*2N*/ initializer_list '}' + | '{' /*2N*/ initializer_list ',' '}' + | '{' /*2N*/ '}' + | '{' /*2N*/ looping_initializer_clause '#' bang error '}' + | '{' /*2N*/ initializer_list ',' looping_initializer_clause '#' bang error '}' + ; +initializer_list : + looping_initializer_clause + | initializer_list ',' looping_initializer_clause + ; +looping_initializer_clause : + start_search looped_initializer_clause + ; +looped_initializer_clause : + initializer_clause + | advance_search '+' /*2N*/ looped_initializer_clause + | advance_search '-' /*2N*/ + ; +colon_mark : + ':' /*2N*/ + ; +elaborated_class_specifier : + class_key scoped_id %prec SHIFT_THERE /*1N*/ + | class_key scoped_id colon_mark error + ; +class_specifier_head : + class_key scoped_id colon_mark base_specifier_list '{' /*2N*/ + | class_key ':' /*2N*/ base_specifier_list '{' /*2N*/ + | class_key scoped_id '{' /*2N*/ + | class_key '{' /*2N*/ + ; +class_key : + CLASS + | STRUCT + | UNION + ; +class_specifier : + class_specifier_head member_specification_opt '}' + | class_specifier_head member_specification_opt util looping_member_declaration '#' bang error '}' + ; +member_specification_opt : + /*empty*/ + | member_specification_opt util looping_member_declaration + | member_specification_opt util looping_member_declaration '#' bang error ';' + ; +looping_member_declaration : + start_search looped_member_declaration + ; +looped_member_declaration : + member_declaration + | advance_search '+' /*2N*/ looped_member_declaration + | advance_search '-' /*2N*/ + ; +member_declaration : + accessibility_specifier + | simple_member_declaration + | function_definition + | using_declaration + | template_declaration + ; +simple_member_declaration : + ';' + | assignment_expression ';' + | constructor_head ';' + | member_init_declarations ';' + | decl_specifier_prefix simple_member_declaration + ; +member_init_declarations : + assignment_expression ',' member_init_declaration + | constructor_head ',' bit_field_init_declaration + | member_init_declarations ',' member_init_declaration + ; +member_init_declaration : + assignment_expression + | bit_field_init_declaration + ; +accessibility_specifier : + access_specifier ':' /*2N*/ + ; +bit_field_declaration : + assignment_expression ':' /*2N*/ bit_field_width + | ':' /*2N*/ bit_field_width + ; +bit_field_width : + logical_or_expression + | logical_or_expression '?' bit_field_width ':' /*2N*/ bit_field_width + ; +bit_field_init_declaration : + bit_field_declaration + | bit_field_declaration '=' initializer_clause + ; +base_specifier_list : + base_specifier + | base_specifier_list ',' base_specifier + ; +base_specifier : + scoped_id + | access_specifier base_specifier + | VIRTUAL base_specifier + ; +access_specifier : + PRIVATE + | PROTECTED + | PUBLIC + ; +conversion_function_id : + OPERATOR conversion_type_id + ; +conversion_type_id : + type_specifier ptr_operator_seq_opt + | type_specifier conversion_type_id + ; +ctor_initializer_opt : + /*empty*/ + | ctor_initializer + ; +ctor_initializer : + ':' /*2N*/ mem_initializer_list + | ':' /*2N*/ mem_initializer_list bang error + ; +mem_initializer_list : + mem_initializer + | mem_initializer_list_head mem_initializer + ; +mem_initializer_list_head : + mem_initializer_list ',' + | mem_initializer_list bang error ',' + ; +mem_initializer : + mem_initializer_id '(' /*4N*/ expression_list_opt ')' + ; +mem_initializer_id : + scoped_id + ; +operator_function_id : + OPERATOR operator + ; +operator : + NEW + | DELETE + | '+' /*2N*/ + | '-' /*2N*/ + | '*' /*2N*/ + | '/' + | '%' + | '^' + | '&' /*2N*/ + | '|' + | '~' + | '!' + | '=' + | '<' /*2N*/ + | '>' + | ASS_ADD + | ASS_SUB + | ASS_MUL + | ASS_DIV + | ASS_MOD + | ASS_XOR + | ASS_AND + | ASS_OR + | SHL + | SHR + | ASS_SHR + | ASS_SHL + | EQ + | NE + | LE + | GE + | LOG_AND + | LOG_OR + | INC /*2N*/ + | DEC /*2N*/ + | ',' + | ARROW_STAR + | ARROW + | '(' /*4N*/ ')' + | '[' /*2N*/ ']' + ; +template_declaration : + template_parameter_clause declaration + | EXPORT template_declaration + ; +template_parameter_clause : + TEMPLATE '<' /*2N*/ template_parameter_list '>' + ; +template_parameter_list : + template_parameter + | template_parameter_list ',' template_parameter + ; +template_parameter : + simple_type_parameter + | simple_type_parameter '=' type_id + | templated_type_parameter + | templated_type_parameter '=' identifier + | templated_parameter_declaration + | bang error + ; +simple_type_parameter : + CLASS + | TYPENAME + ; +templated_type_parameter : + template_parameter_clause CLASS + | template_parameter_clause CLASS identifier + ; +template_id : + TEMPLATE identifier '<' /*2N*/ template_argument_list '>' + | TEMPLATE template_id + ; +template_argument_list : + template_argument + | template_argument_list ',' template_argument + ; +template_argument : + templated_parameter_declaration + ; +explicit_specialization : + TEMPLATE '<' /*2N*/ '>' declaration + ; +try_block : + TRY compound_statement handler_seq + ; +handler_seq : + handler + | handler handler_seq + ; +handler : + CATCH '(' /*4N*/ exception_declaration ')' compound_statement + ; +exception_declaration : + parameter_declaration + ; +throw_expression : + THROW + | THROW assignment_expression + ; +templated_throw_expression : + THROW + | THROW templated_assignment_expression + ; +exception_specification : + THROW '(' /*4N*/ ')' + | THROW '(' /*4N*/ type_id_list ')' + ; +type_id_list : + type_id + | type_id_list ',' type_id + ; +advance_search : + error + ; +bang : + /*empty*/ + ; +mark : + /*empty*/ + ; +nest : + /*empty*/ + ; +start_search : + /*empty*/ + ; +start_search1 : + /*empty*/ + ; +util : + /*empty*/ + ; + +// Tokens +//"\([^"]+\)"\s+{ LEX_STATIC_TOKEN(\([^)]+\)); } +//"\([^"]+\)"\s+{ LEX_C_STATIC_TOKEN(\([^)]+\)); } + +//ATTRIBUTE : '__attribute__' ; +ASM : 'asm' ; +AUTO : 'auto' ; +BOOL : 'bool' ; +BREAK : 'break' ; +CASE : 'case' ; +CATCH : 'catch' ; +CHAR : 'char' ; +CLASS : 'class' ; +CONST : 'const' ; +CONST_CAST : 'const_cast' ; +CONTINUE : 'continue' ; +DEFAULT : 'default' ; +DELETE : 'delete' ; +DO : 'do' ; +DOUBLE : 'double' ; +DYNAMIC_CAST : 'dynamic_cast' ; +ELSE : 'else' ; +ENUM : 'enum' ; +EXPLICIT : 'explicit' ; +EXPORT : 'export' ; +EXTERN : 'extern' ; +FALSE : 'false' ; +FLOAT : 'float' ; +FOR : 'for' ; +FRIEND : 'friend' ; +GOTO : 'goto' ; +IF : 'if' ; +INLINE : 'inline' ; +INT : 'int' ; +LONG : 'long' ; +MUTABLE : 'mutable' ; +NAMESPACE : 'namespace' ; +NEW : 'new' ; +OPERATOR : 'operator' ; +PRIVATE : 'private' ; +PROTECTED : 'protected' ; +PUBLIC : 'public' ; +REGISTER : 'register' ; +REINTERPRET_CAST : 'reinterpret_cast' ; +RETURN : 'return' ; +SHORT : 'short' ; +SIGNED : 'signed' ; +SIZEOF : 'sizeof' ; +STATIC : 'static' ; +STATIC_CAST : 'static_cast' ; +STRUCT : 'struct' ; +SWITCH : 'switch' ; +TEMPLATE : 'template' ; +THIS : 'this' ; +THROW : 'throw' ; +TRUE : 'true' ; +TRY : 'try' ; +TYPEDEF : 'typedef' ; +TYPEID : 'typeid' ; +TYPENAME : 'typename' ; +UNION : 'union' ; +UNSIGNED : 'unsigned' ; +USING : 'using' ; +VIRTUAL : 'virtual' ; +VOID : 'void' ; +VOLATILE : 'volatile' ; +WCHAR_T : 'wchar_t' ; +WHILE : 'while' ; + +SCOPE : '::' ; +ELLIPSIS : '...' ; +SHL : '<<' ; +SHR : '>>' ; +EQ : '==' ; +NE : '!=' ; +LE : '<=' ; +GE : '>=' ; +LOG_AND : '&&' ; +LOG_OR : '||' ; +INC : '++' ; +DEC : '--' ; +ARROW_STAR : '->*' ; +ARROW : '->' ; +DOT_STAR : '.*' ; +ASS_ADD : '+=' ; +ASS_SUB : '-=' ; +ASS_MUL : '*=' ; +ASS_DIV : '/=' ; +ASS_MOD : '%=' ; +ASS_XOR : '^=' ; +ASS_AND : '&=' ; +ASS_OR : '|=' ; +ASS_SHR : '>>=' ; +ASS_SHL : '<<=' ; + +//digit : "[0-9]" ; +//hex : "[0-9A-Fa-f]" ; +//letter : "[A-Z_a-z]" ; +//simple_escape_sequence : "\\\'|\\\"|\\\?|\\\\|\\a|\\b|\\f|\\n|\\r|\\t|\\v" ; +//octal_escape_sequence : "\\[0-7]|\\[0-7][0-7]|\\[0-7][0-7][0-7]" ; +//hexadecimal_escape_sequence : "\\x[0-9A-Fa-f]+" ; +//escape_sequence : simple_escape_sequence | octal_escape_sequence | hexadecimal_escape_sequence ; +//universal_character_name : '\\u' hex hex hex hex | '\\U' hex hex hex hex hex hex hex hex ; +//non_digit : letter | universal_character_name ; +//identifier : non_digit(non_digit|digit)* ; + +//character_lit : "L?'([^'\\\n]|\\.)*" ; +//character_literal : character_lit '\'' ; + +//string_lit : "L?\"([^\"\\\n]|\\.)*" ; +//string_literal : string_lit '"' ; + +//pp_number : '.'? digit (digit | non_digit | "[eE][-+]" | '.')* ; +//pp_number : "\\.?[0-9]([0-9] | [eE][-+] | \\.)*" ; + +Identifier : "[A-Z_a-z][A-Z_a-z0-9]*" ; +StringLiteral : "\"(\\.|[^\"\n])*\"" ; +IntegerLiteral : "[0-9]+" ; +CharacterLiteral : "'(\\.|[^'])[']" ; +FloatingLiteral : "([0-9]+\.[0-9]*|\.[0-9]+)([Ee](\+|\-)?[0-9]+)?" ; +} diff --git a/playground/cyclone.g b/playground/cyclone.g new file mode 100644 index 0000000..c7641d5 --- /dev/null +++ b/playground/cyclone.g @@ -0,0 +1,1539 @@ +cyclone { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token AUTO +//%token REGISTER +//%token STATIC +//%token EXTERN +//%token TYPEDEF +//%token VOID +//%token CHAR +//%token SHORT +//%token INT +//%token LONG +//%token ISIZE_T +//%token USIZE_T +//%token FLOAT +//%token FLOAT128 +//%token DOUBLE +//%token SIGNED +//%token UNSIGNED +//%token CONST +//%token VOLATILE +//%token RESTRICT +//%token STRUCT +//%token UNION +//%token CASE +//%token DEFAULT +//%token INLINE +//%token SIZEOF +//%token OFFSETOF +//%token IF +//%token ELSE +//%token SWITCH +//%token WHILE +//%token DO +//%token FOR +//%token GOTO +//%token CONTINUE +//%token BREAK +//%token RETURN +//%token ENUM +//%token TYPEOF +//%token BUILTIN_VA_LIST +//%token EXTENSION +//%token COMPLEX +//%token NULL_kw +//%token LET +//%token THROW +//%token TRY +//%token CATCH +//%token EXPORT +//%token OVERRIDE +//%token HIDE +//%token NEW +//%token QNEW +//%token ABSTRACT +//%token FALLTHRU +//%token USING +//%token NAMESPACE +//%token NOINFERENCE +//%token DATATYPE +//%token MALLOC +//%token RMALLOC +//%token RVMALLOC +//%token RMALLOC_INLINE +//%token QMALLOC +//%token CALLOC +//%token QCALLOC +//%token RCALLOC +//%token SWAP +//%token ASSERT +//%token REGION_T +//%token TAG_T +//%token REGION +//%token RNEW +//%token REGIONS +//%token PORTON +//%token PORTOFF +//%token PRAGMA +//%token TEMPESTON +//%token TEMPESTOFF +//%token AQ_ALIASABLE +//%token AQ_REFCNT +//%token AQ_RESTRICTED +//%token AQ_UNIQUE +//%token AQUAL_T +//%token NUMELTS +//%token TAGOF +//%token VALUEOF +//%token VALUEOF_T +//%token TAGCHECK +//%token NUMELTS_QUAL +//%token THIN_QUAL +//%token FAT_QUAL +//%token NOTNULL_QUAL +//%token NULLABLE_QUAL +//%token REQUIRES_QUAL +//%token ENSURES_QUAL +//%token EFFECT_QUAL +//%token THROWS_QUAL +//%token SUBSET_QUAL +//%token REGION_QUAL +//%token NOZEROTERM_QUAL +//%token ZEROTERM_QUAL +//%token TAGGED_QUAL +//%token ASSERT_QUAL +//%token ASSERT_FALSE_QUAL +//%token ALIAS_QUAL +//%token AQUALS +//%token CHECKS_QUAL +//%token EXTENSIBLE_QUAL +//%token AUTORELEASED_QUAL +//%token PTR_OP +//%token INC_OP +//%token DEC_OP +//%token LEFT_OP +//%token RIGHT_OP +//%token LE_OP +//%token GE_OP +//%token EQ_OP +//%token NE_OP +//%token AND_OP +//%token OR_OP +//%token MUL_ASSIGN +//%token DIV_ASSIGN +//%token MOD_ASSIGN +//%token ADD_ASSIGN +//%token SUB_ASSIGN +//%token LEFT_ASSIGN +//%token RIGHT_ASSIGN +//%token AND_ASSIGN +//%token XOR_ASSIGN +//%token OR_ASSIGN +//%token ELLIPSIS +//%token LEFT_RIGHT +//%token COLON_COLON +//%token IDENTIFIER +//%token INTEGER_CONSTANT +//%token STRING +//%token WSTRING +//%token CHARACTER_CONSTANT +//%token WCHARACTER_CONSTANT +//%token FLOATING_CONSTANT +//%token TYPE_VAR +//%token TYPEDEF_NAME +//%token QUAL_IDENTIFIER +//%token QUAL_TYPEDEF_NAME +//%token AQUAL_SHORT_CONST +//%token ATTRIBUTE +//%token ASM_TOK +//%token ';' +//%token '{' +//%token '}' +//%token ',' +//%token '*' +//%token '=' +//%token '<' +//%token '>' +//%token '(' +//%token ')' +//%token '_' +//%token '$' +//%token '|' +//%token ':' +//%token '.' +//%token '[' +//%token ']' +//%token '@' +//%token '?' +//%token '+' +//%token '^' +//%token '&' +//%token '-' +//%token '/' +//%token '%' +//%token '~' +//%token '!' +//%token 'A' +//%token 'V' + + +//%start prog_or_constraints + +//%% + +prog_or_constraints : + /*YYEOF + |*/ prog + | all_constraints + ; + +prog : + translation_unit + ; + +translation_unit : + external_declaration translation_unit + | using_action ';' translation_unit + | using_action '{' translation_unit unusing_action translation_unit + | namespace_action ';' translation_unit + | namespace_action '{' translation_unit unnamespace_action translation_unit + | noinference_action '{' translation_unit unnoinference_action translation_unit + | extern_c_action '{' translation_unit end_extern_c override_opt export_list_opt hide_list_opt translation_unit + | PORTON ';' translation_unit + | PORTOFF ';' translation_unit + | tempest_on_action ';' translation_unit + | tempest_off_action ';' translation_unit + | /*empty*/ + ; + +tempest_on_action : + TEMPESTON + ; + +tempest_off_action : + TEMPESTOFF + ; + +extern_c_action : + EXTERN STRING + ; + +end_extern_c : + '}' + ; + +hide_list_opt : + /*empty*/ + | HIDE '{' hide_list_values '}' + ; + +hide_list_values : + struct_union_name + | struct_union_name ';' + | struct_union_name ',' hide_list_values + ; + +export_list_opt : + /*empty*/ + | export_list + ; + +export_list : + EXPORT '{' export_list_values '}' + | EXPORT '{' '}' + | EXPORT '{' '*' '}' + ; + +export_list_values : + struct_union_name optional_semi + | struct_union_name ',' export_list_values + ; + +override_opt : + /*empty*/ + | OVERRIDE '{' translation_unit '}' + ; + +external_declaration : + function_definition + | declaration + | error + ; + +optional_semi : + ';' + | /*empty*/ + ; + +function_definition : + declarator fndef_compound_statement optional_semi + | declaration_specifiers declarator fndef_compound_statement optional_semi + | declarator declaration_list fndef_compound_statement optional_semi + | declaration_specifiers declarator declaration_list fndef_compound_statement optional_semi + ; + +function_definition2 : + declaration_specifiers declarator compound_statement + | declaration_specifiers declarator declaration_list compound_statement + ; + +using_action : + USING qual_opt_identifier + ; + +unusing_action : + '}' + ; + +namespace_action : + NAMESPACE IDENTIFIER + ; + +unnamespace_action : + '}' + ; + +noinference_action : + NOINFERENCE + ; + +unnoinference_action : + '}' + ; + +declaration : + declaration_specifiers ';' + | declaration_specifiers init_declarator_list_rev ';' + | LET pattern '=' expression ';' + | LET identifier_list ';' + | REGION '<' TYPE_VAR '>' IDENTIFIER ';' + | REGION IDENTIFIER open_opt ';' + ; + +open_opt : + /*empty*/ + | '=' IDENTIFIER '(' expression ')' + ; + +declaration_list : + declaration + | declaration_list declaration + ; + +declaration_specifiers : + storage_class_specifier + | storage_class_specifier declaration_specifiers + | EXTENSION declaration_specifiers + | type_specifier + | type_specifier declaration_specifiers + | type_qualifier + | type_qualifier declaration_specifiers + | INLINE + | INLINE declaration_specifiers + | attributes + | attributes declaration_specifiers + ; + +storage_class_specifier : + AUTO + | REGISTER + | STATIC + | EXTERN + | EXTERN STRING + | TYPEDEF + | ABSTRACT + ; + +attributes_opt : + /*empty*/ + | attributes + ; + +attributes : + ATTRIBUTE '(' '(' attribute_list ')' ')' + ; + +attribute_list : + attribute + | attribute ',' attribute_list + ; + +attribute : + IDENTIFIER + | CONST + | IDENTIFIER '(' assignment_expression ')' + | IDENTIFIER '(' IDENTIFIER ',' INTEGER_CONSTANT ',' INTEGER_CONSTANT ')' + ; + +type_specifier : + type_specifier_notypedef + | qual_opt_typedef type_params_opt + ; + +type_specifier_notypedef : + VOID + | CHAR + | SHORT + | INT + | ISIZE_T + | USIZE_T + | LONG + | FLOAT + | FLOAT128 + | DOUBLE + | SIGNED + | UNSIGNED + | COMPLEX + | enum_specifier + | struct_or_union_specifier + | TYPEOF '(' expression ')' + | BUILTIN_VA_LIST + | datatype_specifier + | type_var + | '_' + | '_' COLON_COLON kind + | '$' '(' parameter_list ')' + | REGION_T '<' any_type_name right_angle + | REGION_T + | AQUAL_T '<' aqual_specifier right_angle + | TAG_T '<' any_type_name right_angle + | TAG_T + | VALUEOF_T '(' expression ')' + | SUBSET_QUAL '(' specifier_qualifier_list declarator_withtypedef '|' constant_expression ')' + ; + +kind : + field_name + ; + +type_qualifier : + CONST + | VOLATILE + | RESTRICT + ; + +enum_specifier : + ENUM qual_opt_identifier '{' enum_declaration_list '}' + | ENUM qual_opt_identifier + | ENUM '{' enum_declaration_list '}' + ; + +enum_field : + qual_opt_identifier + | qual_opt_identifier '=' constant_expression + ; + +enum_declaration_list : + enum_field + | enum_field ',' + | enum_field ',' enum_declaration_list + ; + +struct_or_union_specifier : + struct_or_union '{' struct_declaration_list '}' + | maybe_tagged_struct_union struct_union_name type_params_opt '{' type_params_opt optional_effconstr_qualbnd struct_declaration_list '}' + | maybe_tagged_struct_union struct_union_name type_params_opt + ; + +maybe_tagged_struct_union : + TAGGED_QUAL struct_or_union + | struct_or_union + ; + +struct_or_union : + STRUCT + | UNION + ; + +type_params_opt : + /*empty*/ + | '<' type_name_list right_angle + ; + +struct_declaration_list : + /*empty*/ + | struct_declaration_list0 + ; + +struct_declaration_list0 : + struct_declaration + | struct_declaration_list0 struct_declaration + ; + +init_declarator_list_rev : + init_declarator + | init_declarator_list_rev ',' init_declarator + ; + +init_declarator : + declarator + | declarator ASM_TOK asm_expr + | declarator '=' initializer + | declarator ASM_TOK asm_expr '=' initializer + ; + +struct_declaration : + specifier_qualifier_list struct_declarator_list_rev ';' + ; + +specifier_qualifier_list : + type_specifier + | type_specifier notypedef_specifier_qualifier_list + | type_qualifier + | type_qualifier specifier_qualifier_list + | attributes + | attributes specifier_qualifier_list + ; + +notypedef_specifier_qualifier_list : + type_specifier_notypedef + | type_specifier_notypedef notypedef_specifier_qualifier_list + | type_qualifier + | type_qualifier notypedef_specifier_qualifier_list + | attributes + | attributes notypedef_specifier_qualifier_list + ; + +struct_declarator_list_rev : + struct_declarator + | struct_declarator_list_rev ',' struct_declarator + ; + +struct_declarator : + declarator_withtypedef requires_clause_opt + | ':' constant_expression + | /*empty*/ + | declarator_withtypedef ':' constant_expression + ; + +requires_clause_opt : + REQUIRES_QUAL '(' constant_expression ')' + | /*empty*/ + ; + +datatype_specifier : + qual_datatype qual_opt_identifier type_params_opt '{' datatypefield_list '}' + | qual_datatype qual_opt_identifier type_params_opt + | qual_datatype qual_opt_identifier '.' qual_opt_identifier type_params_opt + ; + +qual_datatype : + DATATYPE + | EXTENSIBLE_QUAL DATATYPE + ; + +datatypefield_list : + datatypefield + | datatypefield ';' + | datatypefield ',' datatypefield_list + | datatypefield ';' datatypefield_list + ; + +datatypefield_scope : + /*empty*/ + | EXTERN + | STATIC + ; + +datatypefield : + datatypefield_scope qual_opt_identifier + | datatypefield_scope qual_opt_identifier '(' parameter_list ')' + ; + +declarator : + direct_declarator + | pointer direct_declarator + ; + +declarator_withtypedef : + direct_declarator_withtypedef + | pointer direct_declarator_withtypedef + ; + +direct_declarator : + qual_opt_identifier + | '(' declarator ')' + | '(' attributes declarator ')' + | direct_declarator '[' ']' zeroterm_qual_opt + | direct_declarator '[' assignment_expression ']' zeroterm_qual_opt + | direct_declarator '(' parameter_type_list ')' chk_req_ens_thr_opt + | direct_declarator '(' identifier_list ')' + | direct_declarator '<' type_name_list right_angle + | direct_declarator attributes + ; + +direct_declarator_withtypedef : + qual_opt_identifier + | qual_opt_typedef + | '(' declarator_withtypedef ')' + | '(' attributes declarator_withtypedef ')' + | direct_declarator_withtypedef '[' ']' zeroterm_qual_opt + | direct_declarator_withtypedef '[' assignment_expression ']' zeroterm_qual_opt + | direct_declarator_withtypedef '(' parameter_type_list ')' chk_req_ens_thr_opt + | direct_declarator_withtypedef '(' identifier_list ')' + | direct_declarator_withtypedef '<' type_name_list right_angle + | direct_declarator_withtypedef attributes + ; + +pointer : + one_pointer + | one_pointer pointer + ; + +one_pointer : + pointer_null_and_bound pointer_quals eff_opt attributes_opt tqual_list + ; + +pointer_quals : + /*empty*/ + | pointer_qual pointer_quals + ; + +pointer_qual : + NUMELTS_QUAL '(' assignment_expression ')' + | REGION_QUAL '(' any_type_name ')' + | EFFECT_QUAL '(' eff_set ')' + | THIN_QUAL + | FAT_QUAL + | AUTORELEASED_QUAL + | ZEROTERM_QUAL + | NOZEROTERM_QUAL + | NOTNULL_QUAL + | NULLABLE_QUAL + | ALIAS_QUAL '(' aqual_specifier ')' + | AQUAL_SHORT_CONST + ; + +aqual_specifier : + aqual_const + | type_var + | AQUALS '(' any_type_name ')' + ; + +//aqual_opt : +// /*empty*/ +// | AQUAL_SHORT_CONST +// ; + +pointer_null_and_bound : + '*' pointer_bound + | '@' pointer_bound + | '?' + ; + +pointer_bound : + /*empty*/ + | '{' assignment_expression '}' + | '{' TYPE_VAR '}' + ; + +zeroterm_qual_opt : + /*empty*/ + | ZEROTERM_QUAL + | NOZEROTERM_QUAL + ; + +eff_set : + type_var + | type_var '+' eff_set + ; + +eff_opt : + /*empty*/ + | eff_set + | '_' + ; + +tqual_list : + /*empty*/ + | type_qualifier tqual_list + ; + +parameter_type_list : + optional_effect optional_effconstr_qualbnd + | parameter_list optional_effect optional_effconstr_qualbnd + | parameter_list ',' ELLIPSIS optional_effect optional_effconstr_qualbnd + | ELLIPSIS optional_inject parameter_declaration optional_effect optional_effconstr_qualbnd + | parameter_list ',' ELLIPSIS optional_inject parameter_declaration optional_effect optional_effconstr_qualbnd + ; + +opt_aqual_bnd : + /*empty*/ + | AQUAL_SHORT_CONST + ; + +type_var : + TYPE_VAR opt_aqual_bnd + | TYPE_VAR COLON_COLON kind opt_aqual_bnd + ; + +optional_effect : + /*empty*/ + | ';' effect_set + ; + +optional_effconstr_qualbnd : + /*empty*/ + | ':' effconstr_qualbnd + ; + +effconstr_qualbnd : + effconstr_elt + | qual_bnd_elt + | effconstr_elt ',' effconstr_qualbnd + | qual_bnd_elt ',' effconstr_qualbnd + ; + +effconstr_elt : + atomic_effect LE_OP TYPE_VAR + | atomic_effect '|' atomic_effect + | IDENTIFIER '(' atomic_effect ')' + ; + +qual_bnd_elt : + qual_bnd_const GE_OP qual_bnd_term + ; + +aqual_const : + AQ_ALIASABLE + | AQ_UNIQUE + | AQ_REFCNT + | AQ_RESTRICTED + | AQUAL_SHORT_CONST + ; + +qual_bnd_const : + aqual_const + | AQUALS '(' any_type_name ')' + ; + +qual_bnd_term : + TYPE_VAR + | AQUALS '(' any_type_name ')' + ; + +optional_inject : + /*empty*/ + | IDENTIFIER + ; + +effect_set : + atomic_effect + | atomic_effect '+' effect_set + ; + +atomic_effect : + '{' '}' + | '{' region_set '}' + | REGIONS '(' any_type_name ')' + | type_var + ; + +region_set : + type_name + | type_name ',' region_set + ; + +parameter_list : + parameter_declaration + | parameter_list ',' parameter_declaration + ; + +parameter_declaration : + specifier_qualifier_list declarator_withtypedef + | specifier_qualifier_list + | specifier_qualifier_list abstract_declarator + ; + +identifier_list : + identifier_list0 + ; + +identifier_list0 : + IDENTIFIER + | identifier_list0 ',' IDENTIFIER + ; + +initializer : + assignment_expression + | array_initializer + ; + +array_initializer : + '{' '}' + | '{' initializer_list '}' + | '{' initializer_list ',' '}' + | '{' FOR IDENTIFIER '<' expression ':' expression '}' + | '{' FOR IDENTIFIER '<' expression ':' type_name '}' + ; + +initializer_list : + initializer + | designation initializer + | initializer_list ',' initializer + | initializer_list ',' designation initializer + ; + +designation : + designator_list '=' + | field_name ':' + ; + +designator_list : + designator + | designator_list designator + ; + +designator : + '[' constant_expression ']' + | '.' field_name + ; + +type_name : + specifier_qualifier_list + | specifier_qualifier_list abstract_declarator + ; + +any_type_name : + type_name + | '{' '}' + | '{' region_set '}' + | REGIONS '(' any_type_name ')' + | any_type_name '+' atomic_effect + | qual_bnd_const + ; + +type_name_list : + any_type_name + | type_name_list ',' any_type_name + ; + +abstract_declarator : + pointer + | direct_abstract_declarator + | pointer direct_abstract_declarator + ; + +direct_abstract_declarator : + '(' abstract_declarator ')' + | '[' ']' zeroterm_qual_opt + | direct_abstract_declarator '[' ']' zeroterm_qual_opt + | '[' assignment_expression ']' zeroterm_qual_opt + | direct_abstract_declarator '[' assignment_expression ']' zeroterm_qual_opt + | '(' parameter_type_list ')' chk_req_ens_thr_opt + | direct_abstract_declarator '(' parameter_type_list ')' chk_req_ens_thr_opt + | direct_abstract_declarator '<' type_name_list right_angle + | direct_abstract_declarator attributes + ; + +chk_req_ens_thr : + CHECKS_QUAL '(' constant_expression ')' + | REQUIRES_QUAL '(' constant_expression ')' + | ENSURES_QUAL '(' constant_expression ')' + | THROWS_QUAL '(' constant_expression ')' + | CHECKS_QUAL '(' constant_expression ')' chk_req_ens_thr + | REQUIRES_QUAL '(' constant_expression ')' chk_req_ens_thr + | ENSURES_QUAL '(' constant_expression ')' chk_req_ens_thr + | THROWS_QUAL '(' constant_expression ')' chk_req_ens_thr + ; + +chk_req_ens_thr_opt : + /*empty*/ + | chk_req_ens_thr + ; + +statement : + labeled_statement + | expression_statement + | compound_statement + | selection_statement + | iteration_statement + | jump_statement + ; + +labeled_statement : + IDENTIFIER ':' statement + ; + +expression_statement : + ';' + | expression ';' + ; + +start_fndef_block : + '{' + ; + +end_fndef_block : + '}' + ; + +fndef_compound_statement : + start_fndef_block end_fndef_block + | start_fndef_block block_item_list end_fndef_block + ; + +compound_statement : + '{' '}' + | '{' block_item_list '}' + ; + +block_item_list : + declaration + | declaration block_item_list + | IDENTIFIER ':' declaration + | IDENTIFIER ':' declaration block_item_list + | statement + | statement block_item_list + | function_definition2 + | function_definition2 block_item_list + ; + +selection_statement : + IF '(' expression ')' statement + | IF '(' expression ')' statement ELSE statement + | SWITCH '(' expression ')' '{' switch_clauses '}' + | SWITCH qual_opt_identifier '{' switch_clauses '}' + | SWITCH '$' '(' argument_expression_list ')' '{' switch_clauses '}' + | TRY statement CATCH '{' switch_clauses '}' + ; + +switch_clauses : + /*empty*/ + | DEFAULT ':' block_item_list switch_clauses + | CASE exp_pattern ':' switch_clauses + | CASE exp_pattern ':' block_item_list switch_clauses + | CASE pattern AND_OP expression ':' switch_clauses + | CASE pattern AND_OP expression ':' block_item_list switch_clauses + ; + +iteration_statement : + WHILE '(' expression ')' statement + | DO statement WHILE '(' expression ')' ';' + | FOR '(' for_exp_opt ';' for_exp_opt ';' for_exp_opt ')' statement + | FOR '(' declaration for_exp_opt ';' for_exp_opt ')' statement + ; + +for_exp_opt : + /*empty*/ + | expression + ; + +jump_statement : + GOTO IDENTIFIER ';' + | CONTINUE ';' + | BREAK ';' + | RETURN ';' + | RETURN expression ';' + | FALLTHRU ';' + | FALLTHRU '(' ')' ';' + | FALLTHRU '(' argument_expression_list ')' ';' + ; + +exp_pattern : + conditional_pattern + ; + +conditional_pattern : + logical_or_pattern + | logical_or_pattern '?' expression ':' conditional_expression + ; + +logical_or_pattern : + logical_and_pattern + | logical_or_pattern OR_OP logical_and_expression + ; + +logical_and_pattern : + inclusive_or_pattern + | inclusive_or_pattern AND_OP inclusive_or_expression + ; + +inclusive_or_pattern : + exclusive_or_pattern + | exclusive_or_pattern '|' exclusive_or_expression + ; + +exclusive_or_pattern : + and_pattern + | and_pattern '^' exclusive_or_expression + ; + +and_pattern : + equality_pattern + | and_pattern '&' equality_expression + ; + +equality_pattern : + relational_pattern + | equality_pattern equality_op relational_expression + ; + +relational_pattern : + shift_pattern + | relational_pattern relational_op shift_expression + ; + +shift_pattern : + additive_pattern + | shift_pattern LEFT_OP additive_expression + | shift_pattern RIGHT_OP additive_expression + ; + +additive_pattern : + multiplicative_pattern + | additive_pattern additive_op multiplicative_expression + ; + +multiplicative_pattern : + cast_pattern + | multiplicative_pattern multiplicative_op cast_expression + ; + +cast_pattern : + unary_pattern + | '(' type_name ')' cast_expression + ; + +unary_pattern : + postfix_pattern + | unary_operator cast_expression + | SIZEOF '(' type_name ')' + | SIZEOF unary_expression + | OFFSETOF '(' type_name ',' field_expression ')' + ; + +postfix_pattern : + primary_pattern + ; + +primary_pattern : + pattern + ; + +pattern : + '_' + | '(' expression ')' + | qual_opt_identifier + | '&' pattern + | constant + | IDENTIFIER IDENTIFIER pattern + | IDENTIFIER '<' TYPE_VAR '>' type_name IDENTIFIER + | TYPEDEF_NAME '<' TYPE_VAR '>' type_name IDENTIFIER + | '$' '(' field_pattern_list ')' + | qual_opt_identifier '(' tuple_pattern_list ')' + | qual_opt_identifier '{' type_params_opt field_pattern_list '}' + | '{' type_params_opt field_pattern_list '}' + | AND_OP pattern + | '*' IDENTIFIER + | '*' IDENTIFIER IDENTIFIER pattern + | IDENTIFIER '<' TYPE_VAR '>' + | IDENTIFIER '<' '_' '>' + ; + +tuple_pattern_list : + tuple_pattern_list0 + | tuple_pattern_list0 ',' ELLIPSIS + | ELLIPSIS + ; + +tuple_pattern_list0 : + pattern + | tuple_pattern_list0 ',' pattern + ; + +field_pattern : + pattern + | designation pattern + ; + +field_pattern_list : + field_pattern_list0 + | field_pattern_list0 ',' ELLIPSIS + | ELLIPSIS + ; + +field_pattern_list0 : + field_pattern + | field_pattern_list0 ',' field_pattern + ; + +expression : + assignment_expression + | expression ',' assignment_expression + ; + +assignment_expression : + conditional_expression + | unary_expression assignment_operator assignment_expression + | unary_expression SWAP assignment_expression + ; + +assignment_operator : + '=' + | MUL_ASSIGN + | DIV_ASSIGN + | MOD_ASSIGN + | ADD_ASSIGN + | SUB_ASSIGN + | LEFT_ASSIGN + | RIGHT_ASSIGN + | AND_ASSIGN + | XOR_ASSIGN + | OR_ASSIGN + ; + +conditional_expression : + logical_or_expression + | logical_or_expression '?' expression ':' conditional_expression + | THROW conditional_expression + | NEW array_initializer + | NEW logical_or_expression + | QNEW '(' expression ')' array_initializer + | QNEW '(' expression ')' logical_or_expression + | RNEW '(' expression ')' array_initializer + | RNEW '(' expression ')' logical_or_expression + ; + +constant_expression : + conditional_expression + ; + +logical_or_expression : + logical_and_expression + | logical_or_expression OR_OP logical_and_expression + ; + +logical_and_expression : + inclusive_or_expression + | logical_and_expression AND_OP inclusive_or_expression + ; + +inclusive_or_expression : + exclusive_or_expression + | inclusive_or_expression '|' exclusive_or_expression + ; + +exclusive_or_expression : + and_expression + | exclusive_or_expression '^' and_expression + ; + +and_expression : + equality_expression + | and_expression '&' equality_expression + ; + +equality_expression : + relational_expression + | equality_expression equality_op relational_expression + ; + +relational_expression : + shift_expression + | relational_expression relational_op shift_expression + ; + +shift_expression : + additive_expression + | shift_expression LEFT_OP additive_expression + | shift_expression RIGHT_OP additive_expression + ; + +additive_expression : + multiplicative_expression + | additive_expression additive_op multiplicative_expression + ; + +multiplicative_expression : + cast_expression + | multiplicative_expression multiplicative_op cast_expression + ; + +equality_op : + EQ_OP + | NE_OP + ; + +relational_op : + '<' + | '>' + | LE_OP + | GE_OP + ; + +additive_op : + '+' + | '-' + ; + +multiplicative_op : + '*' + | '/' + | '%' + ; + +cast_expression : + unary_expression + | '(' type_name ')' cast_expression + ; + +unary_expression : + postfix_expression + | INC_OP unary_expression + | DEC_OP unary_expression + | '&' cast_expression + | '*' cast_expression + | unary_operator cast_expression + | SIZEOF '(' type_name ')' + | SIZEOF unary_expression + | OFFSETOF '(' type_name ',' field_expression ')' + | MALLOC '(' assignment_expression ')' + | QMALLOC '(' assignment_expression ',' assignment_expression ',' assignment_expression ')' + | RMALLOC '(' expression ',' assignment_expression ')' + | RVMALLOC '(' expression ',' assignment_expression ')' + | RMALLOC_INLINE '(' expression ',' assignment_expression ')' + | CALLOC '(' assignment_expression ',' SIZEOF '(' type_name ')' ')' + | QCALLOC '(' assignment_expression ',' assignment_expression ',' assignment_expression ',' SIZEOF '(' type_name ')' ')' + | RCALLOC '(' assignment_expression ',' assignment_expression ',' SIZEOF '(' type_name ')' ')' + | NUMELTS '(' assignment_expression ')' + | TAGOF '(' assignment_expression ')' + | TAGCHECK '(' postfix_expression '.' field_name ')' + | TAGCHECK '(' postfix_expression PTR_OP field_name ')' + | VALUEOF '(' type_name ')' + | ASM_TOK asm_expr + | EXTENSION unary_expression + | ASSERT '(' assignment_expression ')' + | ASSERT_QUAL '(' assignment_expression ')' + | ASSERT_FALSE_QUAL '(' assignment_expression ')' + ; + +unary_operator : + '~' + | '!' + | '-' + | '+' + ; + +asm_expr : + volatile_opt '(' STRING asm_out_opt ')' + ; + +volatile_opt : + /*empty*/ + | VOLATILE + ; + +asm_out_opt : + /*empty*/ + | ':' asm_in_opt + | ':' asm_outlist asm_in_opt + ; + +asm_outlist : + asm_io_elt + | asm_outlist ',' asm_io_elt + ; + +asm_in_opt : + /*empty*/ + | ':' asm_clobber_opt + | ':' asm_inlist asm_clobber_opt + ; + +asm_inlist : + asm_io_elt + | asm_inlist ',' asm_io_elt + ; + +asm_io_elt : + STRING '(' expression ')' + ; + +asm_clobber_opt : + /*empty*/ + | ':' + | ':' asm_clobber_list + ; + +asm_clobber_list : + STRING + | asm_clobber_list ',' STRING + ; + +postfix_expression : + primary_expression + | postfix_expression '[' expression ']' + | postfix_expression '(' ')' + | postfix_expression '(' argument_expression_list ')' + | postfix_expression '.' field_name + | postfix_expression PTR_OP field_name + | postfix_expression INC_OP + | postfix_expression DEC_OP + | '(' type_name ')' '{' '}' + | '(' type_name ')' '{' initializer_list '}' + | '(' type_name ')' '{' initializer_list ',' '}' + ; + +field_expression : + field_name + | INTEGER_CONSTANT + | field_expression '.' field_name + | field_expression '.' INTEGER_CONSTANT + ; + +primary_expression : + qual_opt_identifier + | PRAGMA '(' IDENTIFIER ')' + | constant + | STRING + | WSTRING + | '(' expression ')' + | primary_expression LEFT_RIGHT + | primary_expression '@' '<' type_name_list right_angle + | qual_opt_identifier '{' type_params_opt initializer_list '}' + | '$' '(' argument_expression_list ')' + | '(' '{' block_item_list '}' ')' + ; + +argument_expression_list : + argument_expression_list0 + ; + +argument_expression_list0 : + assignment_expression + | argument_expression_list0 ',' assignment_expression + ; + +constant : + INTEGER_CONSTANT + | CHARACTER_CONSTANT + | WCHARACTER_CONSTANT + | NULL_kw + | FLOATING_CONSTANT + ; + +qual_opt_identifier : + IDENTIFIER + | QUAL_IDENTIFIER + ; + +qual_opt_typedef : + TYPEDEF_NAME + | QUAL_TYPEDEF_NAME + ; + +struct_union_name : + qual_opt_identifier + | qual_opt_typedef + ; + +field_name : + IDENTIFIER + | TYPEDEF_NAME + ; + +right_angle : + '>' + | RIGHT_OP + ; + +all_constraints : + /*empty*/ + | TYPE_VAR STRING ',' STRING '(' constraint_list_opt ')' all_constraints + ; + +constraint_list_opt : + /*empty*/ + | constraint_list + ; + +constraint_list : + constraint + | constraint ';' constraint_list + ; + +tvar_or_string : + TYPE_VAR + | STRING + ; + +constraint : + STRING '!' '(' constraint ')' + | STRING '^' '(' c_op ',' tvar_or_string ',' tvar_or_string ')' + | STRING '?' '(' tvar_or_string ',' tvar_or_string ')' + | STRING '=' '(' tvar_or_string ',' tvar_or_string ')' + | STRING '<' '(' tvar_or_string ',' tvar_or_string ')' + | STRING '>' '(' constraint ',' constraint ')' + | STRING '+' '(' c_op ',' constraint ',' constraint ')' + ; + +c_op : + 'A' + | 'V' + | '!' + | '=' + | '<' + ; + +//Lexer +//lalr (\d+:\d+): ERROR: undefined symbol '\([^']+\)' +PORTON : 'PORTON' ; +PORTOFF : 'PORTOFF' ; +TEMPESTON : 'TEMPESTON' ; +TEMPESTOFF : 'TEMPESTOFF' ; +EXTERN : 'extern' ; +STRING : 'STRING' ; +HIDE : 'hide' ; +EXPORT : 'export' ; +OVERRIDE : 'override' ; +USING : 'using' ; +NAMESPACE : 'namespace' ; +IDENTIFIER : 'IDENTIFIER' ; +NOINFERENCE : 'NOINFERENCE' ; +LET : 'let' ; +REGION : 'region' ; +TYPE_VAR : 'TYPE_VAR' ; +EXTENSION : 'extension' ; +INLINE : 'inline' ; +AUTO : 'auto' ; +REGISTER : 'register' ; +STATIC : 'static' ; +TYPEDEF : 'typedef' ; +ABSTRACT : 'abstract' ; +ATTRIBUTE : 'ATTRIBUTE' ; +CONST : 'const' ; +INTEGER_CONSTANT : 'INTEGER_CONSTANT' ; +VOID : 'void' ; +CHAR : 'char' ; +SHORT : 'short' ; +INT : 'int' ; +ISIZE_T : 'isize_t' ; +USIZE_T : 'usize_t' ; +LONG : 'long' ; +FLOAT : 'float' ; +FLOAT128 : 'float128' ; +DOUBLE : 'double' ; +SIGNED : 'signed' ; +UNSIGNED : 'unsigned' ; +COMPLEX : 'COMPLEX' ; +TYPEOF : 'typeof' ; +BUILTIN_VA_LIST : 'BUILTIN_VA_LIST' ; +COLON_COLON : '::' ; +REGION_T : 'REGION_T' ; +AQUAL_T : 'AQUAL_T' ; +TAG_T : 'TAG_T' ; +VALUEOF_T : 'VALUEOF_T' ; +SUBSET_QUAL : 'SUBSET_QUAL' ; +VOLATILE : 'volatile' ; +RESTRICT : 'restrict' ; +ENUM : 'enum' ; +TAGGED_QUAL : 'TAGGED_QUAL' ; +STRUCT : 'struct' ; +UNION : 'union' ; +ASM_TOK : 'ASM_TOK' ; +REQUIRES_QUAL : 'REQUIRES_QUAL' ; +DATATYPE : 'DATATYPE' ; +EXTENSIBLE_QUAL : 'EXTENSIBLE_QUAL' ; +NUMELTS_QUAL : 'NUMELTS_QUAL' ; +REGION_QUAL : 'REGION_QUAL' ; +EFFECT_QUAL : 'EFFECT_QUAL' ; +THIN_QUAL : 'THIN_QUAL' ; +FAT_QUAL : 'FAT_QUAL' ; +AUTORELEASED_QUAL : 'AUTORELEASED_QUAL' ; +ZEROTERM_QUAL : 'ZEROTERM_QUAL' ; +NOZEROTERM_QUAL : 'NOZEROTERM_QUAL' ; +NOTNULL_QUAL : 'NOTNULL_QUAL' ; +NULLABLE_QUAL : 'NULLABLE_QUAL' ; +ALIAS_QUAL : 'ALIAS_QUAL' ; +AQUAL_SHORT_CONST : 'AQUAL_SHORT_CONST' ; +AQUALS : 'AQUALS' ; +ELLIPSIS : '...' ; +LE_OP : '<=' ; +GE_OP : '>=' ; +AQ_ALIASABLE : 'AQ_ALIASABLE' ; +AQ_UNIQUE : 'AQ_UNIQUE' ; +AQ_REFCNT : 'AQ_REFCNT' ; +AQ_RESTRICTED : 'AQ_RESTRICTED' ; +REGIONS : 'REGIONS' ; +FOR : 'for' ; +CHECKS_QUAL : 'CHECKS_QUAL' ; +ENSURES_QUAL : 'ENSURES_QUAL' ; +THROWS_QUAL : 'THROWS_QUAL' ; +IF : 'if' ; +ELSE : 'else' ; +SWITCH : 'switch' ; +TRY : 'try' ; +CATCH : 'catch' ; +DEFAULT : 'default' ; +CASE : 'case' ; +AND_OP : '&&' ; +WHILE : 'while' ; +DO : 'do' ; +GOTO : 'goto' ; +CONTINUE : 'continue' ; +BREAK : 'break' ; +RETURN : 'return' ; +FALLTHRU : 'FALLTHRU' ; +OR_OP : '||' ; +LEFT_OP : '<<' ; +RIGHT_OP : '>>' ; +SIZEOF : 'sizeof' ; +OFFSETOF : 'offsetof' ; +TYPEDEF_NAME : 'TYPEDEF_NAME' ; +SWAP : 'SWAP' ; +MUL_ASSIGN : '*=' ; +DIV_ASSIGN : '/=' ; +MOD_ASSIGN : '%=' ; +ADD_ASSIGN : '+=' ; +SUB_ASSIGN : '-=' ; +LEFT_ASSIGN : '<<=' ; +RIGHT_ASSIGN : '>>=' ; +AND_ASSIGN : '&=' ; +XOR_ASSIGN : '~=' ; +OR_ASSIGN : '|=' ; +THROW : 'throw' ; +NEW : 'new' ; +QNEW : 'QNEW' ; +RNEW : 'RNEW' ; +EQ_OP : '==' ; +NE_OP : '!=' ; +INC_OP : '++' ; +DEC_OP : '--' ; +MALLOC : 'MALLOC' ; +QMALLOC : 'QMALLOC' ; +RMALLOC : 'RMALLOC' ; +RVMALLOC : 'RVMALLOC' ; +RMALLOC_INLINE : 'RMALLOC_INLINE' ; +CALLOC : 'CALLOC' ; +QCALLOC : 'QCALLOC' ; +RCALLOC : 'RCALLOC' ; +NUMELTS : 'NUMELTS' ; +TAGOF : 'TAGOF' ; +TAGCHECK : 'TAGCHECK' ; +PTR_OP : 'PTR_OP' ; +VALUEOF : 'VALUEOF' ; +ASSERT : 'assert' ; +ASSERT_QUAL : 'ASSERT_QUAL' ; +ASSERT_FALSE_QUAL : 'ASSERT_FALSE_QUAL' ; +PRAGMA : 'PRAGMA' ; +WSTRING : 'WSTRING' ; +LEFT_RIGHT : 'LEFT_RIGHT' ; +CHARACTER_CONSTANT : 'CHARACTER_CONSTANT' ; +WCHARACTER_CONSTANT : 'WCHARACTER_CONSTANT' ; +NULL_kw : 'NULL' ; +FLOATING_CONSTANT : 'FLOATING_CONSTANT' ; +QUAL_IDENTIFIER : 'QUAL_IDENTIFIER' ; +QUAL_TYPEDEF_NAME : 'QUAL_TYPEDEF_NAME' ; + +} \ No newline at end of file diff --git a/playground/dparser.g b/playground/dparser.g new file mode 100644 index 0000000..a0d2d34 --- /dev/null +++ b/playground/dparser.g @@ -0,0 +1,297 @@ +//From: https://github.com/jplevyak/dparser/blob/master/grammar.g + +dparser { + +%whitespace "[ \t]*"; +%whitespace "//[^\r\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +grammar : + top_level_statement_zom + ; + +top_level_statement_zom : + /*empty*/ + | top_level_statement + | top_level_statement_zom top_level_statement + ; + +top_level_statement : + global_code + | production + | include_statement + ; + +include_statement: + INCLUDE regex + ; + +global_code : + '%<' balanced_code_zom '%>' + | curly_code + | '${scanner' balanced_code_oom '}' + | '${declare' declarationtype identifier_zom '}' + | '${token' token_identifier_oom '}' + ; + +pass_types : + /*empty*/ + | pass_type pass_types + ; + +pass_type : + 'preorder' + | 'postorder' + | 'manual' + | 'for_all' + | 'for_undefined' + ; + +declarationtype : + 'tokenize' + | 'longest_match' + | 'whitespace' + | 'all_matches' + | 'set_op_priority_from_rule' + | 'all_subparsers' + | 'subparser' + | 'save_parse_tree' + ; + +token_identifier_oom : + token_identifier + | token_identifier_oom token_identifier + ; + +token_identifier : + identifier + ; + +production : + production_name ':' rules ';' + | production_name regex_production rules ';' + | ';' + ; + +regex_production : + '::=' + ; + +production_name : + identifier + | '_' + ; + +rules : + rule rule_alt_zom + ; + +rule_alt : + '|' rule + ; + +rule_alt_zom : + /*empty*/ + | rule_alt + | rule_alt_zom rule_alt + ; + +rule : + new_rule element_and_modifier_simple_opt rule_modifier_zom rule_code + ; + +element_and_modifier_simple_opt : + /*empty*/ + | element_and_modifier_zom simple_element element_modifier_zom + ; + +element_and_modifier_zom : + /*empty*/ + | element element_modifier_zom + | element_and_modifier_zom element element_modifier_zom + ; + +new_rule : + /*empty*/ + ; + +simple_element : + string + | regex + | unicode_char + | identifier + | '${scan' balanced_code_oom '}' + | '(' new_subrule rules ')' + ; + +element : + simple_element + | bracket_code + | curly_code + ; + +new_subrule : + /*empty*/ + ; + +element_modifier_zom : + /*empty*/ + | element_modifier + | element_modifier_zom element_modifier + ; + +element_modifier : + '$term' integer + | '$name' string + | '$name' regex + | '/i' + | '?' + | '*' + | '+' + | '@' integer + | '@' integer ':' integer + ; + +rule_modifier_zom : + /*empty*/ + | rule_modifier + | rule_modifier_zom rule_modifier + ; + +rule_modifier : + rule_assoc rule_priority + | external_action + ; + +rule_assoc : + '$unary_op_right' + | '$unary_op_left' + | '$binary_op_right' + | '$binary_op_left' + | '$unary_right' + | '$unary_left' + | '$binary_right' + | '$binary_left' + | '$right' + | '$left' + ; + +rule_priority : + integer + ; + +external_action : + '${action}' + | '${action' integer '}' + ; + +rule_code : + speculative_code_opt final_code_opt pass_code_zom + ; + + +speculative_code_opt : + /*empty*/ + | speculative_code + ; + +speculative_code : + bracket_code + ; + +final_code_opt : + /*empty*/ + | final_code + ; + +final_code : + curly_code + ; + +pass_code_zom : + /*empty*/ + | pass_code + | pass_code_zom pass_code + ; + +pass_code : + identifier ':' curly_code + ; + +curly_code : + '{' balanced_code_zom '}' + ; + +bracket_code : + '[' balanced_code_zom ']' + ; + +balanced_code_oom : + balanced_code + | balanced_code_oom balanced_code + ; + +balanced_code_zom : + /*empty*/ + | balanced_code_oom + ; + +balanced_code : + '(' balanced_code_zom ')' + | '[' balanced_code_zom ']' + | '{' balanced_code_zom '}' + | string + | identifier + | regex + | integer + | symbols + ; + +symbols : + "[!~`@#$%^&*\-_+=|:;\\<,>.?/]" + ; + +string : + "'([^'\\]|\\[^])*'" + ; + +regex : + "\"([^\"\\]|\\[^])*\"" + ; + +unicode_char : + "[uU]\+[0-9a-fA-F]+" + ; + +INCLUDE : 'include' ; + +identifier_zom : + /*empty*/ + | identifier + | identifier_zom identifier + ; + +identifier : + "[a-zA-Z_][a-zA-Z_0-9]*" //$term -1 + ; + +integer : + decimalint + | hexint + | octalint + ; + +decimalint : + "0|-?[1-9][0-9]*[uUlL]?" + ; + +hexint : + "-?(0x|0X)[0-9a-fA-F]+[uUlL]?" + ; + +octalint : + "-?0[0-7]*[uUlL]?" + ; + +} diff --git a/playground/error_handling_calculator.g b/playground/error_handling_calculator.g new file mode 100644 index 0000000..6269b40 --- /dev/null +++ b/playground/error_handling_calculator.g @@ -0,0 +1,23 @@ +error_handling_calculator { + %whitespace "[ \t\r\n]*"; + %none error; + %left '(' ')'; + %left '+' '-'; + %left '*' '/'; + %none integer; + stmts: stmts stmt | stmt | %precedence '('; + stmt: + expr ';' [result] | + error ';' [unexpected_error] + ; + expr: + expr '+' expr [add] | + expr '-' expr [subtract] | + expr '*' expr [multiply] | + expr '/' expr [divide] | + expr error expr [unknown_operator_error] | + '(' expr ')' [compound] | + integer [integer] + ; + integer: "[0-9]+"; +} diff --git a/playground/error_handling_calculator.txt b/playground/error_handling_calculator.txt new file mode 100644 index 0000000..9499ae8 --- /dev/null +++ b/playground/error_handling_calculator.txt @@ -0,0 +1 @@ +1 + 2 * (3 + 4) + 5; 2 ^ 3; 3 * 4; foo!; \ No newline at end of file diff --git a/playground/flex-parser.g b/playground/flex-parser.g new file mode 100644 index 0000000..8271e8d --- /dev/null +++ b/playground/flex-parser.g @@ -0,0 +1,343 @@ +//From: https://github.com/westes/flex/blob/master/src/parse.y + +flex { + +%error_recovery_off; +//%error_recovery_show; +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token CHAR +//%token NUMBER +//%token SECTEND +//%token SCDECL +//%token XSCDECL +//%token NAME +//%token PREVCCL +//%token EOF_OP +//%token TOK_OPTION +//%token TOK_OUTFILE +//%token TOK_PREFIX +//%token TOK_YYCLASS +//%token TOK_HEADER_FILE +//%token TOK_EXTRA_TYPE +//%token TOK_TABLES_FILE +//%token TOK_YYLMAX +//%token TOK_NUMERIC +//%token TOK_YYDECL +//%token TOK_PREACTION +//%token TOK_POSTACTION +//%token TOK_USERINIT +//%token TOK_EMIT +//%token TOK_BUFSIZE +//%token TOK_YYTERMINATE +//%token CCE_ALNUM +//%token CCE_ALPHA +//%token CCE_BLANK +//%token CCE_CNTRL +//%token CCE_DIGIT +//%token CCE_GRAPH +//%token CCE_LOWER +//%token CCE_PRINT +//%token CCE_PUNCT +//%token CCE_SPACE +//%token CCE_UPPER +//%token CCE_XDIGIT +//%token CCE_NEG_ALNUM +//%token CCE_NEG_ALPHA +//%token CCE_NEG_BLANK +//%token CCE_NEG_CNTRL +//%token CCE_NEG_DIGIT +//%token CCE_NEG_GRAPH +//%token CCE_NEG_LOWER +//%token CCE_NEG_PRINT +//%token CCE_NEG_PUNCT +//%token CCE_NEG_SPACE +//%token CCE_NEG_UPPER +//%token CCE_NEG_XDIGIT +//%token CCL_OP_DIFF +//%token CCL_OP_UNION +//%token BEGIN_REPEAT_POSIX +//%token END_REPEAT_POSIX +//%token BEGIN_REPEAT_FLEX +//%token END_REPEAT_FLEX +//%token '=' +//%token '\n' +//%token '{' +//%token '}' +//%token '^' +//%token '<' +//%token '>' +//%token '*' +//%token ',' +//%token '$' +//%token '|' +//%token '/' +//%token '+' +//%token '?' +//%token '.' +//%token '"' +//%token '(' +//%token ')' +//%token '[' +//%token ']' +//%token '-' + +%left /*1*/ CCL_OP_DIFF CCL_OP_UNION ; + +//%start goal + +//%% + +goal : + /*YYEOF + |*/ initlex sect1 sect1end sect2 initforrule + ; + +initlex : + /*empty*/ + | top_user_code + ; + +sect1 : + sect1 startconddecl namelist1 + | sect1 options + | /*empty*/ + | error + ; + +sect1end : + SECTEND + ; + +startconddecl : + SCDECL + | XSCDECL + ; + +namelist1 : + namelist1 NAME + | NAME + | error + ; + +options : + TOK_OPTION optionlist + | user_code + ; + +optionlist : + optionlist option + | /*empty*/ + ; + +option : + TOK_OUTFILE '=' NAME + | TOK_EXTRA_TYPE '=' NAME + | TOK_PREFIX '=' NAME + | TOK_YYCLASS '=' NAME + | TOK_HEADER_FILE '=' NAME + | TOK_YYLMAX '=' TOK_NUMERIC + | TOK_YYDECL '=' NAME + | TOK_PREACTION '=' NAME + | TOK_POSTACTION '=' NAME + | TOK_BUFSIZE '=' TOK_NUMERIC + | TOK_EMIT '=' NAME + | TOK_USERINIT '=' NAME + | TOK_YYTERMINATE '=' NAME + | TOK_TABLES_FILE '=' NAME + ; + +sect2 : + sect2 scon initforrule flexrule '\n' + | sect2 scon '{' sect2 '}' + | /*empty*/ + ; + +initforrule : + /*empty*/ + ; + +flexrule : + '^' rule + | rule + | EOF_OP + | error + ; + +scon_stk_ptr : + /*empty*/ + ; + +scon : + '<' scon_stk_ptr namelist2 '>' + | '<*>' + | /*empty*/ + ; + +namelist2 : + namelist2 ',' sconname + | sconname + | error + ; + +sconname : + NAME + ; + +rule : + re2 re + | re2 re '$' + | re '$' + | re + ; + +re : + re '|' series + | series + ; + +re2 : + re '/' + ; + +series : + series singleton + | singleton + | series BEGIN_REPEAT_POSIX NUMBER ',' NUMBER END_REPEAT_POSIX + | series BEGIN_REPEAT_POSIX NUMBER ',' END_REPEAT_POSIX + | series BEGIN_REPEAT_POSIX NUMBER END_REPEAT_POSIX + ; + +singleton : + singleton '*' + | singleton '+' + | singleton '?' + | singleton BEGIN_REPEAT_FLEX NUMBER ',' NUMBER END_REPEAT_FLEX + | singleton BEGIN_REPEAT_FLEX NUMBER ',' END_REPEAT_FLEX + | singleton BEGIN_REPEAT_FLEX NUMBER END_REPEAT_FLEX + | '.' + | fullccl + | PREVCCL + | '"' string '"' + | '(' re ')' + | CHAR + ; + +fullccl : + fullccl CCL_OP_DIFF /*1L*/ braceccl + | fullccl CCL_OP_UNION /*1L*/ braceccl + | braceccl + ; + +braceccl : + '[' ccl ']' + | '[^' ccl ']' + ; + +ccl : + ccl CHAR '-' CHAR + | ccl CHAR + | ccl ccl_expr + | /*empty*/ + ; + +ccl_expr : + CCE_ALNUM + | CCE_ALPHA + | CCE_BLANK + | CCE_CNTRL + | CCE_DIGIT + | CCE_GRAPH + | CCE_LOWER + | CCE_PRINT + | CCE_PUNCT + | CCE_SPACE + | CCE_XDIGIT + | CCE_UPPER + | CCE_NEG_ALNUM + | CCE_NEG_ALPHA + | CCE_NEG_BLANK + | CCE_NEG_CNTRL + | CCE_NEG_DIGIT + | CCE_NEG_GRAPH + | CCE_NEG_PRINT + | CCE_NEG_PUNCT + | CCE_NEG_SPACE + | CCE_NEG_XDIGIT + | CCE_NEG_LOWER + | CCE_NEG_UPPER + ; + +string : + string CHAR + | /*empty*/ + ; + +//Lexer + +CCL_OP_DIFF : '{-}' ; +CCL_OP_UNION : '{+}' ; +SECTEND : 'SECTEND' ; +SCDECL : 'SCDECL' ; +XSCDECL : 'XSCDECL' ; +NAME : "[[:alpha:]_][[:alnum:]_-]*" ; +TOK_OPTION : '%option' ; +TOK_OUTFILE : '%outfile' ; +TOK_EXTRA_TYPE : '%extra_type' ; +TOK_PREFIX : '%prefix' ; +TOK_YYCLASS : '%yyclass' ; +TOK_HEADER_FILE : '%header_file' ; +TOK_YYLMAX : '%yylmax' ; +TOK_NUMERIC : '%numeric' ; +TOK_YYDECL : '%yydecl' ; +TOK_PREACTION : '%pre_action' ; +TOK_POSTACTION : '%post_action' ; +TOK_BUFSIZE : '%bufsize' ; +TOK_EMIT : '%emit' ; +TOK_USERINIT : '%userinit' ; +TOK_YYTERMINATE : '%yyterminate' ; +TOK_TABLES_FILE : '%tables_files' ; +EOF_OP : 'EOF_OP' ; +BEGIN_REPEAT_POSIX : 'BEGIN_REPEAT_POSIX' ; +NUMBER : "[[:digit:]]+" ; +END_REPEAT_POSIX : 'END_REPEAT_POSIX' ; +BEGIN_REPEAT_FLEX : 'BEGIN_REPEAT_FLEX' ; +END_REPEAT_FLEX : 'END_REPEAT_FLEX' ; +PREVCCL : 'PREVCCL' ; +CHAR : "(\\.|[^\n\]])" ; +CCE_ALNUM : '[:alnum:]' ; +CCE_ALPHA : '[:alpha:]' ; +CCE_BLANK : '[:blank:]' ; +CCE_CNTRL : '[:cntrl:]' ; +CCE_DIGIT : '[:digit:]' ; +CCE_GRAPH : '[:graph:]' ; +CCE_LOWER : '[:lower:]' ; +CCE_PRINT : '[:print:]' ; +CCE_PUNCT : '[:punct:]' ; +CCE_SPACE : '[:space:]' ; +CCE_XDIGIT : '[:xdigit:]' ; +CCE_UPPER : '[:upper:]' ; +CCE_NEG_ALNUM : '[:^alnum:]' ; +CCE_NEG_ALPHA : '[:^alpha:]' ; +CCE_NEG_BLANK : '[:^blank:]' ; +CCE_NEG_CNTRL : '[:^cntrl:]' ; +CCE_NEG_DIGIT : '[:^digit:]' ; +CCE_NEG_GRAPH : '[:^graph:]' ; +CCE_NEG_PRINT : '[:^print:]' ; +CCE_NEG_PUNCT : '[:^punct:]' ; +CCE_NEG_SPACE : '[:^space:]' ; +CCE_NEG_XDIGIT : '[:^xdigit:]' ; +CCE_NEG_LOWER : '[:^lower:]' ; +CCE_NEG_UPPER : '[:^upper:]' ; + +top_user_code : "%top{[^}]+}"; +user_code : "%{[^%]+%}" ; + +} diff --git a/playground/frege-parser.g b/playground/frege-parser.g new file mode 100644 index 0000000..f1e3197 --- /dev/null +++ b/playground/frege-parser.g @@ -0,0 +1,939 @@ +//From: https://github.com/catull/frege/blob/master/frege/compiler/grammar/Frege.y + +frege { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +//%token VARID +//%token CONID +//%token QUALIFIER +//%token DOCUMENTATION +//%token EXTENDS +//%token SUPER +//%token PACKAGE +//%token IMPORT +//%token INFIX +//%token INFIXR +//%token INFIXL +//%token NATIVE +//%token NEWTYPE +//%token DATA +//%token WHERE +//%token CLASS +//%token INSTANCE +//%token ABSTRACT +//%token TYPE +//%token TRUE +//%token FALSE +//%token IF +//%token THEN +//%token ELSE +//%token CASE +//%token OF +//%token DERIVE +//%token LET +//%token IN +//%token DO +//%token FORALL +//%token PRIVATE +//%token PROTECTED +//%token PUBLIC +//%token PURE +//%token THROWS +//%token MUTABLE +//%token INTCONST +//%token STRCONST +//%token LONGCONST +//%token FLTCONST +//%token DBLCONST +//%token DECCONST +//%token CHRCONST +//%token REGEXP +//%token BIGCONST +//%token ARROW +//%token DCOLON +//%token GETS +//%token EARROW +//%token DOTDOT +//%token LOP1 +//%token LOP2 +//%token LOP3 +//%token LOP4 +//%token LOP5 +//%token LOP6 +//%token LOP7 +//%token LOP8 +//%token LOP9 +//%token LOP10 +//%token LOP11 +//%token LOP12 +//%token LOP13 +//%token LOP14 +//%token LOP15 +//%token LOP16 +//%token ROP1 +//%token ROP2 +//%token ROP3 +//%token ROP4 +//%token ROP5 +//%token ROP6 +//%token ROP7 +//%token ROP8 +//%token ROP9 +//%token ROP10 +//%token ROP11 +//%token ROP12 +//%token ROP13 +//%token ROP14 +//%token ROP15 +//%token ROP16 +//%token NOP1 +//%token NOP2 +//%token NOP3 +//%token NOP4 +//%token NOP5 +//%token NOP6 +//%token NOP7 +//%token NOP8 +//%token NOP9 +//%token NOP10 +//%token NOP11 +//%token NOP12 +//%token NOP13 +//%token NOP14 +//%token NOP15 +//%token NOP16 +//%token NOP0 +//%token LOP0 +//%token ROP0 +//%token SOMEOP +//%token '-' +//%token ';' +//%token '{' +//%token '}' +//%token '.' +//%token '(' +//%token ')' +//%token ',' +//%token '|' +//%token '[' +//%token ']' +//%token '?' +//%token '!' +//%token '=' +//%token '\\' +//%token '_' + +%right /*1*/ SOMEOP '-' ; +%right /*2*/ ARROW ; + +//%start module + +//%% + +module : + docsO moduleclause ';' definitions + | docsO moduleclause WHERE '{' definitions '}' + | docsO '{' definitions '}' + ; +nativename : + rawnativename + ; +rawnativename : + VARID + | CONID + | PACKAGE + | VARID '.' rawnativename + | PACKAGE '.' rawnativename + | QUALIFIER rawnativename + | STRCONST + ; +modulename1 : + CONID + | varidkw '.' modulename1 + | QUALIFIER modulename1 + ; +modulename : + modulename1 + ; +docs : + DOCUMENTATION + | DOCUMENTATION docs + ; +docsO : + /*empty*/ + | docs + ; +moduleclause : + PACKAGE modulename + | PROTECTED PACKAGE modulename + | moduleclause words '(' qvarids ')' + ; +word : + VARID + ; +words : + word + | word words + ; +definitions : + definition + | definition ';' + | definition ';' definitions + ; +definition : + documentation + | topdefinition + | visibledefinition + ; +visibledefinition : + PRIVATE publicdefinition + | PROTECTED publicdefinition + | PUBLIC publicdefinition + | ABSTRACT datadef + ; +topdefinition : + import + | infix + | moduledefinition + | publicdefinition + ; +moduledefinition : + NATIVE PACKAGE typeclause interfaces wheretokens + ; +typeclause : + /*empty*/ + | TYPE tau + ; +interfaces : + /*empty*/ + | CLASS tauSC + ; +wheretokens : + WHERE '{' jtokens '}' + | WHERE '{' '}' + ; +jtoken : + VARID + | CONID + | QUALIFIER + | EXTENDS + | SUPER + | DOCUMENTATION + | PACKAGE + | IMPORT + | INFIX + | INFIXR + | INFIXL + | NATIVE + | DATA + | WHERE + | CLASS + | INSTANCE + | ABSTRACT + | TYPE + | TRUE + | FALSE + | IF + | THEN + | ELSE + | CASE + | OF + | DERIVE + | LET + | IN + | DO + | FORALL + | PRIVATE + | PROTECTED + | PUBLIC + | PURE + | THROWS + | MUTABLE + | INTCONST + | STRCONST + | LONGCONST + | FLTCONST + | DBLCONST + | CHRCONST + | ARROW /*2R*/ + | DCOLON + | GETS + | EARROW + | DOTDOT + | SOMEOP /*1R*/ + | ',' + | '|' + | '[' + | ']' + | '(' + | ')' + | '.' + | '?' + | '-' /*1R*/ + | ';' + | '!' + | '=' + | '\\' + ; +jtokens : + jtoken + | jtoken jtokens + | '{' jtokens '}' + | '{' jtokens '}' jtokens + | '{' '}' + | '{' '}' jtokens + ; +documentation : + DOCUMENTATION + ; +publicdefinition : + typedef + | datadef + | classdef + | instdef + | derivedef + | localdef + ; +localdefs : + dplocaldef + | dplocaldef ';' + | dplocaldef ';' localdefs + ; +localdef : + annotation + | nativedef + | fundef + ; +plocaldef : + localdef + | PRIVATE localdef + | PROTECTED localdef + | PUBLIC localdef + ; +dplocaldef : + documentation + | documentation dplocaldef + | plocaldef + ; +letdef : + annotation + | fundef + ; +letdefs : + letdef + | letdef ';' + | letdef ';' letdefs + ; +import : + IMPORT modulename importliste + | IMPORT modulename VARID CONID importliste + | IMPORT modulename CONID importliste + ; +importliste : + /*empty*/ + | varid '(' importspecs ')' + | '(' ')' + | '(' importspecs ')' + | PUBLIC importliste + ; +importspecs : + importspec + | importspec ',' + | importspec ',' importspecs + ; +importitem : + qvarid + | CONID '(' memspecs ')' + | CONID '(' ')' + | qconid + | operator + | unop + ; +importspec : + importitem + | importitem alias + | PUBLIC importspec + ; +memspec : + alias + | alias alias + | PUBLIC memspec + ; +memspecs : + memspec + | memspec ',' + | memspec ',' memspecs + ; +alias : + VARID + | CONID + | operator + ; +varid : + VARID + ; +varidkw : + VARID + | DATA + | TYPE + | NATIVE + | PURE + | PACKAGE + | IMPORT + ; +qvarids : + qvarop + | qvarop ',' qvarids + ; +qvarid : + QUALIFIER QUALIFIER varop + | QUALIFIER varop + | VARID + ; +qconid : + QUALIFIER QUALIFIER CONID + | QUALIFIER CONID + | CONID + ; +varop : + VARID + | unop + ; +qvarop : + QUALIFIER QUALIFIER varop + | QUALIFIER varop + | varop + | operator + ; +operator : + SOMEOP /*1R*/ + ; +unop : + '!' + | '?' + ; +fixity : + INFIX INTCONST + | INFIXL INTCONST + | INFIXR INTCONST + ; +opstring : + operator + | VARID + | '-' /*1R*/ + ; +operators : + opstring + | opstring operators + ; +infix : + fixity operators + ; +annotation : + annoitems DCOLON sigma + ; +annoitem : + varid + | '(' operator ')' + | '(' unop ')' + | '(' '-' /*1R*/ ')' + ; +annoitems : + annoitem + | annoitem ',' annoitems + ; +nativedef : + PURE impurenativedef + | impurenativedef + ; +fitem : + annoitem + | unop + | '-' /*1R*/ + | operator + ; +jitem : + nativename + | operator + | unop + ; +methodspec : + fitem jitem gargs + | fitem jitem + | fitem gargs + | fitem + ; +sigex : + sigma THROWS tauSC + | sigma + ; +sigexs : + sigex + | sigex '|' sigexs + ; +impurenativedef : + NATIVE methodspec DCOLON sigexs + ; +sigma : + forall + | rho + ; +forall : + FORALL dvars mbdot rho + ; +mbdot : + '.' + | SOMEOP /*1R*/ + ; +rho : + tapp EARROW rhofun + | rhofun + ; +rhofun : + tapp + | tapp ARROW /*2R*/ rhofun + ; +tau : + tapp + | forall + | tapp ARROW /*2R*/ tau + ; +tauSC : + tau + | tau ',' tauSC + ; +tauSB : + tau + | tau '|' tauSB + ; +tapp : + simpletypes + ; +simpletype : + tyvar + | tyname + | '(' tau ')' + | '(' tau ',' tauSC ')' + | '(' tau '|' tauSB ')' + | '[' tau ']' + ; +tyvar : + VARID + | '(' VARID DCOLON kind ')' + | '(' VARID EXTENDS tauSC ')' + | '(' EXTENDS tauSC ')' + | '(' SUPER tapp ')' + ; +tyname : + qconid + | '[' ']' + | '(' ')' + | '(' commata ')' + | '(' ARROW /*2R*/ ')' + ; +kind : + simplekind ARROW /*2R*/ kind + | simplekind + ; +simplekind : + SOMEOP /*1R*/ + | '(' kind ')' + ; +scontext : + qconid tyvar + ; +scontexts : + scontext + | scontext ',' + | scontext ',' scontexts + ; +ccontext : + scontext + | '(' scontexts ')' + ; +classdef : + CLASS ccontext EARROW CONID tyvar wheredef + | CLASS ccontext wheredef + ; +sicontext : + qconid simpletype + ; +sicontexts : + sicontext + | sicontext ',' + | sicontext ',' sicontexts + ; +icontext : + sicontext + | '(' sicontexts ')' + ; +insthead : + icontext EARROW tyname simpletype + | icontext + ; +instdef : + INSTANCE insthead wheredef + ; +derivedef : + DERIVE insthead + ; +datadef : + datainit wheredef + ; +nativepur : + PURE NATIVE + | NATIVE + ; +nativespec : + nativename + | nativename gargs + ; +gargs : + '{' tauSC '}' + | '{' '}' + ; +datainit : + DATA CONID '=' nativepur nativespec + | DATA CONID dvars '=' nativepur nativespec + | DATA CONID dvars '=' dalts + | DATA CONID '=' dalts + | DATA CONID + | NEWTYPE CONID dvars '=' dalt + | NEWTYPE CONID '=' dalt + ; +dvars : + tyvar + | tyvar dvars + ; +dalts : + dalt + | dalt '|' dalts + ; +dalt : + visdalt + | visdalt DOCUMENTATION + | DOCUMENTATION visdalt + ; +visdalt : + strictdalt + | PUBLIC strictdalt + | PRIVATE strictdalt + | PROTECTED strictdalt + ; +strictdalt : + '!' simpledalt + | '?' simpledalt + | simpledalt + ; +simpledalt : + CONID + | CONID '{' conflds '}' + | CONID contypes + ; +contypes : + strictcontype + | strictcontype contypes + ; +strictcontype : + contype + | '!' contype + | '?' contype + ; +contype : + simpletype + ; +simpletypes : + simpletype + | simpletype simpletypes + ; +conflds : + confld + | confld ',' + | confld DOCUMENTATION + | confld ',' conflds + | confld DOCUMENTATION conflds + ; +confld : + docsO fldids DCOLON sigma + ; +fldids : + fldid + | fldid ',' fldids + ; +fldid : + strictfldid + | PUBLIC strictfldid + | PRIVATE strictfldid + ; +strictfldid : + plainfldid + | '!' plainfldid + | '?' plainfldid + ; +plainfldid : + varid + ; +typedef : + TYPE CONID '=' sigma + | TYPE CONID dvars '=' sigma + ; +wheredef : + /*empty*/ + | WHERE '{' '}' + | WHERE '{' localdefs '}' + ; +wherelet : + WHERE '{' '}' + | WHERE '{' letdefs '}' + ; +fundef : + funhead '=' expr + | funhead guards + | fundef wherelet + ; +funhead : + binex + ; +literal : + TRUE + | FALSE + | CHRCONST + | STRCONST + | INTCONST + | BIGCONST + | LONGCONST + | FLTCONST + | DBLCONST + | DECCONST + | REGEXP + ; +pattern : + expr + ; +aeq : + ARROW /*2R*/ + | '=' + ; +lcqual : + gqual + | expr '=' expr + | LET '{' letdefs '}' + ; +lcquals : + lcqual + | lcqual ',' lcquals + | lcqual ',' + ; +dodefs : + lcqual + | lcqual ';' + | lcqual ';' dodefs + ; +gqual : + expr + | expr GETS expr + ; +gquals : + gqual + | gqual ',' gquals + | gqual ',' + ; +guard : + '|' gquals aeq expr + ; +guards : + guard + | guard guards + ; +calt : + pattern aeq expr + | pattern guards + | calt wherelet + ; +calts : + calt + | calt ';' calts + | calt ';' + ; +lambda : + '\\' apats lambdabody + ; +lambdabody : + lambda + | ARROW /*2R*/ expr + ; +expr : + binex DCOLON sigma + | binex + ; +thenx : + ';' THEN + | THEN + ; +elsex : + ';' ELSE + | ELSE + ; +binex : + binex SOMEOP /*1R*/ binex + | binex '-' /*1R*/ binex + | '-' /*1R*/ topex + | topex + ; +topex : + IF expr thenx expr elsex expr + | CASE expr OF '{' calts '}' + | LET '{' letdefs '}' IN expr + | lambda + | appex + ; +appex : + unex + | appex unex + ; +unex : + primary + | unop unex + ; +apats : + unex + | unex apats + ; +qualifiers : + QUALIFIER + | QUALIFIER QUALIFIER + ; +primary : + term + | DO '{' dodefs '}' + | primary '.' VARID + | primary '.' operator + | primary '.' unop + | qualifiers '{' VARID '?' '}' + | qualifiers '{' VARID '=' '}' + | qualifiers '{' VARID GETS '}' + | qualifiers '{' getfields '}' + | primary '.' '{' VARID '?' '}' + | primary '.' '{' VARID '=' '}' + | primary '.' '{' VARID GETS '}' + | primary '.' '{' getfields '}' + | primary '.' '[' expr ']' + ; +term : + qvarid + | literal + | '_' + | qconid + | qconid '{' '}' + | qconid '{' fields '}' + | '(' ')' + | '(' commata ')' + | '(' unop ')' + | '(' operator ')' + | '(' '-' /*1R*/ ')' + | '(' operator expr ')' + | '(' binex operator ')' + | '(' binex '-' /*1R*/ ')' + | '(' expr ',' exprSC ')' + | '(' expr ';' exprSS ')' + | '(' expr ')' + | '[' ']' + | '[' exprSC ']' + | '[' exprSC DOTDOT ']' + | '[' exprSC DOTDOT expr ']' + | '[' expr '|' lcquals ']' + ; +commata : + ',' + | ',' commata + ; +fields : + field + | field ',' fields + | field ',' + ; +getfields : + getfield + | getfield ',' getfields + | getfield ',' + ; +getfield : + VARID GETS expr + | VARID '=' expr + | VARID + ; +field : + varid '=' expr + | varid + ; +exprSC : + expr + | expr ',' exprSC + | expr ',' + ; +exprSS : + expr + | expr ';' exprSS + | expr ';' + ; + +//Lexer + +SOMEOP : 'SOMEOP' ; +ARROW : 'ARROW' ; +WHERE : 'WHERE' ; +VARID : 'VARID' ; +CONID : 'CONID' ; +PACKAGE : 'PACKAGE' ; +QUALIFIER : 'QUALIFIER' ; +STRCONST : 'STRCONST' ; +DOCUMENTATION : 'DOCUMENTATION' ; +PROTECTED : 'PROTECTED' ; +PRIVATE : 'PRIVATE' ; +PUBLIC : 'PUBLIC' ; +ABSTRACT : 'ABSTRACT' ; +NATIVE : 'NATIVE' ; +TYPE : 'TYPE' ; +CLASS : 'CLASS' ; +EXTENDS : 'EXTENDS' ; +SUPER : 'SUPER' ; +IMPORT : 'IMPORT' ; +INFIX : 'INFIX' ; +INFIXR : 'INFIXR' ; +INFIXL : 'INFIXL' ; +DATA : 'DATA' ; +INSTANCE : 'INSTANCE' ; +TRUE : 'TRUE' ; +FALSE : 'FALSE' ; +IF : 'IF' ; +THEN : 'THEN' ; +ELSE : 'ELSE' ; +CASE : 'CASE' ; +OF : 'OF' ; +DERIVE : 'DERIVE' ; +LET : 'LET' ; +IN : 'IN' ; +DO : 'DO' ; +FORALL : 'FORALL' ; +PURE : 'PURE' ; +THROWS : 'THROWS' ; +MUTABLE : 'MUTABLE' ; +INTCONST : 'INTCONST' ; +LONGCONST : 'LONGCONST' ; +FLTCONST : 'FLTCONST' ; +DBLCONST : 'DBLCONST' ; +CHRCONST : 'CHRCONST' ; +DCOLON : 'DCOLON' ; +GETS : 'GETS' ; +EARROW : 'EARROW' ; +DOTDOT : 'DOTDOT' ; +NEWTYPE : 'NEWTYPE' ; +BIGCONST : 'BIGCONST' ; +DECCONST : 'DECCONST' ; +REGEXP : 'REGEXP' ; + +} diff --git a/playground/ghc-parser.g b/playground/ghc-parser.g new file mode 100644 index 0000000..19e9437 --- /dev/null +++ b/playground/ghc-parser.g @@ -0,0 +1,2406 @@ +ghc { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/* +%token + '_' //-- Haskell keywords + 'as' + 'case' + 'class' + 'data' + 'default' + 'deriving' + 'else' + 'hiding' + 'if' + 'import' + 'in' + 'infix' + 'infixl' + 'infixr' + 'instance' + 'let' + 'module' + 'newtype' + 'of' + 'qualified' + 'then' + 'type' + 'where' + + 'forall' //-- GHC extension keywords + 'foreign' + 'export' + 'label' + 'dynamic' + 'safe' + 'interruptible' + 'unsafe' + 'family' + 'role' + 'stdcall' + 'ccall' + 'capi' + 'prim' + 'javascript' + 'proc' //-- for arrow notation extension + 'rec' //-- for arrow notation extension + 'group' //-- for list transform extension + 'by' //-- for list transform extension + 'using' //-- for list transform extension + 'pattern' //-- for pattern synonyms + 'static' //-- for static pointers extension + 'stock' //-- for DerivingStrategies extension + 'anyclass' //-- for DerivingStrategies extension + 'via' //-- for DerivingStrategies extension + + 'unit' + 'signature' + 'dependency' + + '{-# INLINE' //-- INLINE or INLINABLE + '{-# OPAQUE' + '{-# SPECIALISE' + '{-# SPECIALISE_INLINE' + '{-# SOURCE' + '{-# RULES' + '{-# SCC' + '{-# DEPRECATED' + '{-# WARNING' + '{-# UNPACK' + '{-# NOUNPACK' + '{-# ANN' + '{-# MINIMAL' + '{-# CTYPE' + '{-# OVERLAPPING' + '{-# OVERLAPPABLE' + '{-# OVERLAPS' + '{-# INCOHERENT' + '{-# COMPLETE' + '#-}' + + '..' //-- reserved symbols + ':' + '::' + '=' + '\\' + 'lcase' + 'lcases' + '|' + '<-' + '->' + '->.' + TIGHT_INFIX_AT + '=>' + '-' + PREFIX_TILDE + PREFIX_BANG + PREFIX_MINUS + '*' + '-<' //-- for arrow notation + '>-' //-- for arrow notation + '-<<' //-- for arrow notation + '>>-' //-- for arrow notation + '.' + PREFIX_PROJ //-- RecordDotSyntax + TIGHT_INFIX_PROJ //-- RecordDotSyntax + PREFIX_AT + PREFIX_PERCENT //-- for linear types + + '{' //-- special symbols + '}' + vocurly //-- virtual open curly (from layout) + vccurly //-- virtual close curly (from layout) + '[' + ']' + '(' + ')' + '(#' + '#)' + '(|' + '|)' + ';' + ',' + '`' + SIMPLEQUOTE //-- 'x + + VARID //-- identifiers + CONID + VARSYM + CONSYM + QVARID + QCONID + QVARSYM + QCONSYM + + + //-- QualifiedDo + DO + MDO + + IPDUPVARID //-- GHC extension + LABELVARID + + CHAR + STRING + INTEGER + RATIONAL + + PRIMCHAR + PRIMSTRING + PRIMINTEGER + PRIMWORD + PRIMINTEGER8 + PRIMINTEGER16 + PRIMINTEGER32 + PRIMINTEGER64 + PRIMWORD8 + PRIMWORD16 + PRIMWORD32 + PRIMWORD64 + PRIMFLOAT + PRIMDOUBLE + +//-- Template Haskell +'[|' +'[p|' +'[t|' +'[d|' +'|]' +'[||' +'||]' +PREFIX_DOLLAR +PREFIX_DOLLAR_DOLLAR +TH_TY_QUOTE //-- ''T +TH_QUASIQUOTE +TH_QQUASIQUOTE + +%monad +%lexer + //-- Replace 'lexer' above with 'lexerDbg' + //-- to dump the tokens fed to the parser. +%tokentype + +//-- Exported parsers +%name parseModuleNoHaddock module +%name parseSignature signature +%name parseImport importdecl +%name parseStatement e_stmt +%name parseDeclaration topdecl +%name parseExpression exp +%name parsePattern pat +%name parseTypeSignature sigdecl +%name parseStmt maybe_stmt +%name parseIdentifier identifier +%name parseType ktype +%name parseBackpack backpack +%partial parseHeader header +%% +*/ + +GHC_grammar : + module + | signature + | importdecl + | e_stmt + | topdecl + | exp + | pat + | sigdecl + | maybe_stmt + | identifier + | ktype + | backpack + | header + ; + +//----------------------------------------------------------------------------- +//-- Identifiers; one of the entry points +identifier : + qvar + | qcon + | qvarop + | qconop + | '(' '->' ')' + | '->' + ; +//----------------------------------------------------------------------------- +//-- Backpack stuff + +backpack : + implicit_top units close + | '{' units '}' + ; +units : + units ';' unit + | units ';' + | unit + ; +unit : + 'unit' pkgname 'where' unitbody + ; + +unitid : + pkgname + | pkgname '[' msubsts ']' + ; +msubsts : + msubsts ',' msubst + | msubsts ',' + | msubst + ; +msubst : + modid '=' moduleid + | modid VARSYM modid VARSYM + ; +moduleid : + VARSYM modid VARSYM + | unitid ':' modid + ; +pkgname : + STRING + | litpkgname + ; +litpkgname_segment : + VARID + | CONID + | special_id + ; +//-- Parse a minus sign regardless of whether -XLexicalNegation is turned on or off. +//-- See Note [Minus tokens] in GHC.Parser.Lexer +HYPHEN : + '-' + | PREFIX_MINUS + | VARSYM + ; + +litpkgname : + litpkgname_segment + //-- a bit of a hack, means p - b is parsed same as p-b, enough for now. + | litpkgname_segment HYPHEN litpkgname + ; +mayberns : + /*empty*/ + | '(' rns ')' + ; +rns : + rns ',' rn + | rns ',' + | rn + ; +rn : + modid 'as' modid + | modid + ; +unitbody : + '{' unitdecls '}' + | vocurly unitdecls close + ; +unitdecls : + unitdecls ';' unitdecl + | unitdecls ';' + | unitdecl + ; +unitdecl : + 'module' maybe_src modid maybemodwarning maybeexports 'where' body + //-- XXX not accurate + + | 'signature' modid maybemodwarning maybeexports 'where' body + + | 'dependency' unitid mayberns + + | 'dependency' 'signature' unitid + ; + +//----------------------------------------------------------------------------- +//-- Module Header + +//-- The place for module deprecation is really too restrictive, but if it +//-- was allowed at its natural place just before 'module', we get an ugly +//-- s/r conflict with the second alternative. Another solution would be the +//-- introduction of a new pragma DEPRECATED_MODULE, but this is not very nice, +//-- either, and DEPRECATED is only expected to be used by people who really +//-- know what they are doing. :-) + +signature : + 'signature' modid maybemodwarning maybeexports 'where' body + ; + +module : + 'module' modid maybemodwarning maybeexports 'where' body + + | body2 + ; + +missing_module_keyword : + /*empty*/ + ; + +implicit_top : + /*empty*/ + ; + +maybemodwarning : + '{-# DEPRECATED' strings '#-}' + + | '{-# WARNING' warning_category strings '#-}' + + | /*empty*/ + ; +body : + '{' top '}' + | vocurly top close + ; +body2 : + '{' top '}' + | missing_module_keyword top close + ; + +top : + semis top1 + ; + +top1 : + importdecls_semi topdecls_cs_semi + | importdecls_semi topdecls_cs + | importdecls + ; +//----------------------------------------------------------------------------- +//-- Module declaration & imports only + +header : + 'module' modid maybemodwarning maybeexports 'where' header_body + + | 'signature' modid maybemodwarning maybeexports 'where' header_body + + | header_body2 + ; + +header_body : + '{' header_top + | vocurly header_top + ; +header_body2 : + '{' header_top + | missing_module_keyword header_top + ; +header_top : + semis header_top_importdecls + ; +header_top_importdecls : + importdecls_semi + | importdecls + ; +//----------------------------------------------------------------------------- +//-- The Export List + +maybeexports : + '(' exportlist ')' + | /*empty*/ + ; +exportlist : + exportlist1 + | /*empty*/ + + //-- trailing comma: + | exportlist1 ',' + | ',' + ; +exportlist1 : + exportlist1 ',' export + + | export + ; + + //-- No longer allow things like [] and (,,,) to be exported + //-- They are built in syntax, always available +export : + maybeexportwarning qcname_ext export_subspec + | maybeexportwarning 'module' modid + | maybeexportwarning 'pattern' qcon + ; +maybeexportwarning : + '{-# DEPRECATED' strings '#-}' + + | '{-# WARNING' warning_category strings '#-}' + + | /*empty*/ + ; +export_subspec : + /*empty*/ + | '(' qcnames ')' + ; +qcnames : + /*empty*/ + | qcnames1 + ; +qcnames1 : //-- A reversed list + qcnames1 ',' qcname_ext_w_wildcard + + //-- Annotations re-added in mkImpExpSubSpec + | qcname_ext_w_wildcard + ; +//-- Variable, data constructor or wildcard +//-- or tagged type constructor +qcname_ext_w_wildcard : + qcname_ext + | '..' + ; +qcname_ext : + qcname + | 'type' oqtycon + ; +qcname : //-- Variable or type constructor + qvar //-- Things which look like functions + //-- Note: This includes record selectors but + //-- also (-.->), see #11432 + | oqtycon_no_varcon //-- see Note [Type constructors in export list] + ; +//----------------------------------------------------------------------------- +//-- Import Declarations + +//-- importdecls and topdecls must contain at least one declaration; +//-- top handles the fact that these may be optional. + +//-- One or more semicolons +semis1 : + semis1 ';' + | ';' + ; +//-- Zero or more semicolons +semis : + semis ';' + | /*empty*/ + ; +//-- No trailing semicolons, non-empty +importdecls : +importdecls + importdecls_semi importdecl + ; + +//-- May have trailing semicolons, can be empty +importdecls_semi : +importdecls_semi + importdecls_semi importdecl semis1 + + | /*empty*/ + ; +importdecl : + 'import' maybe_src maybe_safe optqualified maybe_pkg modid optqualified maybeas maybeimpspec + ; + + +maybe_src : + '{-# SOURCE' '#-}' + | /*empty*/ + ; +maybe_safe : + 'safe' + | /*empty*/ + ; +maybe_pkg : + STRING + | /*empty*/ + ; +optqualified : + 'qualified' + | /*empty*/ + ; +maybeas : + 'as' modid + | /*empty*/ + ; +maybeimpspec : + impspec + | /*empty*/ + ; +impspec : + '(' importlist ')' + | 'hiding' '(' importlist ')' + ; +importlist : + importlist1 + | /*empty*/ + //-- trailing comma: + | importlist1 ',' + | ',' + ; +importlist1 : + importlist1 ',' import + + | import + ; +import : + qcname_ext export_subspec + | 'module' modid + | 'pattern' qcon + ; +//----------------------------------------------------------------------------- +//-- Fixity Declarations + +prec : + /*empty*/ + | INTEGER + ; + +infix : + 'infix' + | 'infixl' + | 'infixr' + ; +ops : + ops ',' op + | op + ; +//----------------------------------------------------------------------------- +//-- Top-Level Declarations + +//-- No trailing semicolons, non-empty +topdecls : + topdecls_semi topdecl + ; +//-- May have trailing semicolons, can be empty +topdecls_semi : + topdecls_semi topdecl semis1 + | /*empty*/ + ; + +//----------------------------------------------------------------------------- +//-- Each topdecl accumulates prior comments +//-- No trailing semicolons, non-empty +topdecls_cs : + topdecls_cs_semi topdecl_cs + ; +//-- May have trailing semicolons, can be empty +topdecls_cs_semi : + topdecls_cs_semi topdecl_cs semis1 + | /*empty*/ + ; +//-- Each topdecl accumulates prior comments +topdecl_cs : + topdecl + ; +//----------------------------------------------------------------------------- +topdecl : + cl_decl + | ty_decl + | standalone_kind_sig + | inst_decl + | stand_alone_deriving + | role_annot + | 'default' '(' comma_types0 ')' + | 'foreign' fdecl + | '{-# DEPRECATED' deprecations '#-}' + | '{-# WARNING' warnings '#-}' + | '{-# RULES' rules '#-}' + | annotation + | decl_no_th + //-- Template Haskell Extension + //-- The $(..) form is one possible form of infixexp + //-- but we treat an arbitrary expression just as if + //-- it had a $(..) wrapped around it + | infixexp + ; +//-- Type classes +//-- +cl_decl : + 'class' tycl_hdr fds where_cls + ; + +//-- Type declarations (toplevel) +//-- +ty_decl : + //-- ordinary type synonyms + 'type' type '=' ktype + //-- Note ktype, not sigtype, on the right of '=' + //-- We allow an explicit for-all but we don't insert one + //-- in type Foo a = (b,b) + //-- Instead we just say b is out of scope + //-- + //-- Note the use of type for the head; this allows + //-- infix type constructors to be declared + + + //-- type family declarations + | 'type' 'family' type opt_tyfam_kind_sig opt_injective_info + where_type_family + //-- Note the use of type for the head; this allows + //-- infix type constructors to be declared + + + //-- ordinary data type or newtype declaration + | type_data_or_newtype capi_ctype tycl_hdr constrs maybe_derivings + + //-- We need the location on tycl_hdr in case + //-- constrs and deriving are both empty + + //-- ordinary GADT declaration + | type_data_or_newtype capi_ctype tycl_hdr opt_kind_sig + gadt_constrlist + maybe_derivings + + //-- We need the location on tycl_hdr in case + //-- constrs and deriving are both empty + + //-- data/newtype family + | 'data' 'family' type opt_datafam_kind_sig + ; + +//-- standalone kind signature +standalone_kind_sig : + 'type' sks_vars '::' sigktype + ; + +//-- See also: sig_vars +sks_vars : //-- Returned in reverse order + sks_vars ',' oqtycon + + | oqtycon + ; +inst_decl : + 'instance' overlap_pragma inst_type where_inst + + + //-- type instance declarations + | 'type' 'instance' ty_fam_inst_eqn + + + //-- data/newtype instance declaration + | data_or_newtype 'instance' capi_ctype datafam_inst_hdr constrs + maybe_derivings + + + //-- GADT instance declaration + | data_or_newtype 'instance' capi_ctype datafam_inst_hdr opt_kind_sig + gadt_constrlist + maybe_derivings + ; + +overlap_pragma : + '{-# OVERLAPPABLE' '#-}' + | '{-# OVERLAPPING' '#-}' + | '{-# OVERLAPS' '#-}' + | '{-# INCOHERENT' '#-}' + | /*empty*/ + ; +deriv_strategy_no_via : + 'stock' + | 'anyclass' + | 'newtype' + ; +deriv_strategy_via : + 'via' sigktype + ; +deriv_standalone_strategy : + 'stock' + | 'anyclass' + | 'newtype' + | deriv_strategy_via + | /*empty*/ + ; +//-- Injective type families + +opt_injective_info : + /*empty*/ + | '|' injectivity_cond + ; +injectivity_cond : + tyvarid '->' inj_varids + ; + +inj_varids : + inj_varids tyvarid + | tyvarid + ; +//-- Closed type families + +where_type_family : + /*empty*/ + | 'where' ty_fam_inst_eqn_list + ; + +ty_fam_inst_eqn_list : + '{' ty_fam_inst_eqns '}' + | vocurly ty_fam_inst_eqns close + | '{' '..' '}' + | vocurly '..' close + ; +ty_fam_inst_eqns : + ty_fam_inst_eqns ';' ty_fam_inst_eqn + + | ty_fam_inst_eqns ';' + | ty_fam_inst_eqn + | /*empty*/ + ; +ty_fam_inst_eqn : + 'forall' tv_bndrs '.' type '=' ktype + + | type '=' ktype + + //-- Note the use of type for the head; this allows + //-- infix type constructors and type patterns + ; +//-- Associated type family declarations +//-- +//-- * They have a different syntax than on the toplevel (no family special +//-- identifier). +//-- +//-- * They also need to be separate from instances; otherwise, data family +//-- declarations without a kind signature cause parsing conflicts with empty +//-- data declarations. +//-- +at_decl_cls : + //-- data family declarations, with optional 'family' keyword + 'data' opt_family type opt_datafam_kind_sig + + + //-- type family declarations, with optional 'family' keyword + //-- (can't use opt_instance because you get shift/reduce errors + | 'type' type opt_at_kind_inj_sig + + | 'type' 'family' type opt_at_kind_inj_sig + + + //-- default type instances, with optional 'instance' keyword + | 'type' ty_fam_inst_eqn + + | 'type' 'instance' ty_fam_inst_eqn + ; + +opt_family : + /*empty*/ + | 'family' + ; +opt_instance : + /*empty*/ + | 'instance' + ; +//-- Associated type instances +//-- +at_decl_inst : + //-- type instance declarations, with optional 'instance' keyword + 'type' opt_instance ty_fam_inst_eqn + //-- Note the use of type for the head; this allows + //-- infix type constructors and type patterns + + + //-- data/newtype instance declaration, with optional 'instance' keyword + | data_or_newtype opt_instance capi_ctype datafam_inst_hdr constrs maybe_derivings + + + //-- GADT instance declaration, with optional 'instance' keyword + | data_or_newtype opt_instance capi_ctype datafam_inst_hdr opt_kind_sig + gadt_constrlist + maybe_derivings + ; + +type_data_or_newtype : + 'data' + | 'newtype' + | 'type' 'data' + ; +data_or_newtype : + 'data' + | 'newtype' + ; +//-- Family result/return kind signatures + +opt_kind_sig : + | '::' kind + ; +opt_datafam_kind_sig : + | '::' kind + ; +opt_tyfam_kind_sig : + | '::' kind + | '=' tv_bndr + ; +opt_at_kind_inj_sig : + | '::' kind + | '=' tv_bndr_no_braces '|' injectivity_cond + ; + +//-- tycl_hdr parses the header of a class or data type decl, +//-- which takes the form +//-- T a b +//-- Eq a => T a +//-- (Eq a, Ord b) => T a b +//-- T Int [a] //-- for associated types +//-- Rather a lot of inlining here, else we get reduce/reduce errors +tycl_hdr : + context '=>' type + | type + ; +datafam_inst_hdr : + 'forall' tv_bndrs '.' context '=>' type + | 'forall' tv_bndrs '.' type + | context '=>' type + | type + ; + +capi_ctype : + '{-# CTYPE' STRING STRING '#-}' + + + | '{-# CTYPE' STRING '#-}' + + + | + ; +//----------------------------------------------------------------------------- +//-- Stand-alone deriving + +//-- Glasgow extension: stand-alone deriving declarations +stand_alone_deriving : + 'deriving' deriv_standalone_strategy 'instance' overlap_pragma inst_type + ; + +//----------------------------------------------------------------------------- +//-- Role annotations + +role_annot : + 'type' 'role' oqtycon maybe_roles + ; + +//-- Reversed! +maybe_roles : + /*empty*/ + | roles + ; +roles : + role + | roles role + ; +//-- read it in as a varid for better error messages +role : + VARID + | '_' + ; +//-- Pattern synonyms + +//-- Glasgow extension: pattern synonyms +pattern_synonym_decl : + 'pattern' pattern_synonym_lhs '=' pat + + + | 'pattern' pattern_synonym_lhs '<-' pat + + + | 'pattern' pattern_synonym_lhs '<-' pat where_decls + ; + +pattern_synonym_lhs : + con vars0 + | varid conop varid + | con '{' cvars1 '}' + ; +vars0 : + /*empty*/ + | varid vars0 + ; +cvars1 : + var + | var ',' cvars1 + ; +where_decls : + 'where' '{' decls '}' + | 'where' vocurly decls close + ; +pattern_synonym_sig : + 'pattern' con_list '::' sigtype + ; + +qvarcon : + qvar + | qcon + ; +//----------------------------------------------------------------------------- +//-- Nested declarations + +//-- Declaration in class bodies +//-- +decl_cls : + at_decl_cls + | decl + //-- A 'default' signature used with the generic-programming extension + | 'default' infixexp '::' sigtype + ; + +decls_cls : //-- Reversed + decls_cls ';' decl_cls + | decls_cls ';' + | decl_cls + | /*empty*/ + ; +decllist_cls + : //-- Reversed + '{' decls_cls '}' + | vocurly decls_cls close + ; +//-- Class body +//-- +where_cls : + //-- No implicit parameters + //-- May have type declarations + 'where' decllist_cls + | /*empty*/ + ; +//-- Declarations in instance bodies +//-- +decl_inst : + at_decl_inst + | decl + ; +decls_inst : //-- Reversed + decls_inst ';' decl_inst + | decls_inst ';' + | decl_inst + | /*empty*/ + ; +decllist_inst + : //-- Reversed + '{' decls_inst '}' + | vocurly decls_inst close + ; +//-- Instance body +//-- +where_inst : //-- Reversed + //-- No implicit parameters + //-- May have type declarations + 'where' decllist_inst + | /*empty*/ + ; +//-- Declarations in binding groups other than classes and instances +//-- +decls : + decls ';' decl + | decls ';' + | decl + | /*empty*/ + ; +decllist : + '{' decls '}' + | vocurly decls close + ; +//-- Binding groups other than those of class and instance declarations +//-- +binds : + //-- May have implicit parameters + //-- No type declarations + decllist + + | '{' dbinds '}' + | vocurly dbinds close + ; + +wherebinds : + //-- May have implicit parameters + //-- No type declarations + 'where' binds + | /*empty*/ + ; +//----------------------------------------------------------------------------- +//-- Transformation Rules + +rules : //-- Reversed + rules ';' rule + | rules ';' + | rule + | /*empty*/ + ; +rule : + STRING rule_activation rule_foralls infixexp '=' exp + ; + +//-- Rules can be specified to be NeverActive, unlike inline/specialize pragmas +rule_activation : + //-- See Note [//%shift: rule_activation -> /*empty*/] + /*empty*/ //%shift + | rule_explicit_activation + ; +//-- This production is used to parse the tilde syntax in pragmas such as +//-- * +//-- * +//-- * +//-- Note that it can be written either +//-- without a space [~1] (the PREFIX_TILDE case), or +//-- with a space [~ 1] (the VARSYM case). +//-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer +rule_activation_marker : + PREFIX_TILDE + | VARSYM + ; +rule_explicit_activation : //-- In brackets + '[' INTEGER ']' + | '[' rule_activation_marker INTEGER ']' + + | '[' rule_activation_marker ']' + ; + +rule_foralls : + 'forall' rule_vars '.' 'forall' rule_vars '.' + + //-- See Note [//%shift: rule_foralls -> 'forall' rule_vars '.'] + | 'forall' rule_vars '.' //%shift + //-- See Note [//%shift: rule_foralls -> /*empty*/] + | /*empty*/ //%shift + ; +rule_vars : + rule_var rule_vars + | /*empty*/ + ; +rule_var : + varid + | '(' varid '::' ctype ')' + ; + + +//----------------------------------------------------------------------------- +//-- Warnings and deprecations (c.f. rules) + +warning_category : + 'in' STRING + | /*empty*/ + ; +warnings : + warnings ';' warning + | warnings ';' + | warning + | /*empty*/ + ; +//-- SUP: TEMPORARY HACK, not checking for `module Foo' +warning : + warning_category namelist strings + ; + +deprecations : + deprecations ';' deprecation + + | deprecations ';' + | deprecation + | /*empty*/ + ; +//-- SUP: TEMPORARY HACK, not checking for `module Foo' +deprecation : + namelist strings + ; + +strings : + STRING + | '[' stringlist ']' + ; +stringlist : + stringlist ',' STRING + | STRING + | /*empty*/ + ; +//----------------------------------------------------------------------------- +//-- Annotations +annotation : + '{-# ANN' name_var aexp '#-}' + + | '{-# ANN' 'type' otycon aexp '#-}' + + | '{-# ANN' 'module' aexp '#-}' + ; +//----------------------------------------------------------------------------- +//-- Foreign import and export declarations + +fdecl : + 'import' callconv safety fspec + + | 'import' callconv fspec + + | 'export' callconv fspec + ; + +callconv : + 'stdcall' + | 'ccall' + | 'capi' + | 'prim' + | 'javascript' + ; +safety : + 'unsafe' + | 'safe' + | 'interruptible' + ; +fspec : + STRING var '::' sigtype + | var '::' sigtype + //-- if the entity string is missing, it defaults to the empty string; + //-- the meaning of an empty entity string depends on the calling + //-- convention + ; +//----------------------------------------------------------------------------- +//-- Type signatures + +opt_sig : + /*empty*/ + | '::' ctype + ; +opt_tyconsig : + /*empty*/ + | '::' gtycon + ; +//-- Like ktype, but for types that obey the forall-or-nothing rule. +//-- See Note [forall-or-nothing rule] in GHC.Hs.Type. +sigktype : + sigtype + | ctype '::' kind + ; +//-- Like ctype, but for types that obey the forall-or-nothing rule. +//-- See Note [forall-or-nothing rule] in GHC.Hs.Type. To avoid duplicating the +//-- logic in ctype here, we simply reuse the ctype production and perform +//-- surgery on the LHsType it returns to turn it into an LHsSigType. +sigtype : + ctype + ; +sig_vars : //-- Returned in reversed order + sig_vars ',' var + | var + ; +sigtypes1 : + sigtype + | sigtype ',' sigtypes1 + ; +//----------------------------------------------------------------------------- +//-- Types + +unpackedness : + '{-# UNPACK' '#-}' + | '{-# NOUNPACK' '#-}' + ; +forall_telescope : + 'forall' tv_bndrs '.' + | 'forall' tv_bndrs '->' + ; +//-- A ktype is a ctype, possibly with a kind annotation +ktype : + ctype + | ctype '::' kind + ; +//-- A ctype is a for-all type +ctype : + forall_telescope ctype + | context '=>' ctype + | ipvar '::' ctype + | type + ; +//---------------------- +//-- Notes for 'context' +//-- We parse a context as a btype so that we don't get reduce/reduce +//-- errors in ctype. The basic problem is that +//-- (Eq a, Ord a) +//-- looks so much like a tuple type. We can't tell until we find the => + +context : + btype + ; + + +type : + //-- See Note [//%shift: type -> btype] + btype //%shift + | btype '->' ctype + | btype mult '->' ctype + + | btype '->.' ctype + //-- [mu AnnLollyU $2] } + ; + +mult : + PREFIX_PERCENT atype + ; +btype : + infixtype + ; +infixtype : + //-- See Note [//%shift: infixtype -> ftype] + ftype //%shift + | ftype tyop infixtype + | unpackedness infixtype + ; +ftype : + atype + | tyop + | ftype tyarg + | ftype PREFIX_AT atype + ; +tyarg : + atype + | unpackedness atype + ; +tyop : + qtyconop + | tyvarop + | SIMPLEQUOTE qconop + | SIMPLEQUOTE varop + ; +atype : + ntgtycon //-- Not including unit tuples + //-- See Note [//%shift: atype -> tyvar] + | tyvar //%shift //-- (See Note [Unit tuples]) + | '*' + + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + | PREFIX_TILDE atype + | PREFIX_BANG atype + + | '{' fielddecls '}' + //-- Constructor sigs only + | '(' ')' + | '(' ktype ',' comma_types1 ')' + | '(#' '#)' + | '(#' comma_types1 '#)' + | '(#' bar_types2 '#)' + | '[' ktype ']' + | '(' ktype ')' + | quasiquote + | splice_untyped + //-- see Note [Promotion] for the followings + | SIMPLEQUOTE qcon_nowiredlist + | SIMPLEQUOTE '(' ktype ',' comma_types1 ')' + + | SIMPLEQUOTE '[' comma_types0 ']' + | SIMPLEQUOTE var + + //-- Two or more [ty, ty, ty] must be a promoted list type, just as + //-- if you had written '[ty, ty, ty] + //-- (One means a list type, zero means the list type constructor, + //-- so you have to quote those.) + | '[' ktype ',' comma_types1 ']' + | INTEGER + | CHAR + | STRING + | '_' + //-- Type variables are never exported, so `M.tyvar` will be rejected by the renamer. + //-- We let it pass the parser because the renamer can generate a better error message. + | QVARID + ; +//-- An inst_type is what occurs in the head of an instance decl +//-- e.g. (Foo a, Gaz b) => Wibble a b +//-- It's kept as a single type for convenience. +inst_type : + sigtype + ; +deriv_types : + sigktype + + | sigktype ',' deriv_types + ; +comma_types0 : //-- Zero or more: ty,ty,ty + comma_types1 + | /*empty*/ + ; +comma_types1 : //-- One or more: ty,ty,ty + ktype + | ktype ',' comma_types1 + ; +bar_types2 : //-- Two or more: ty|ty|ty + ktype '|' ktype + | ktype '|' bar_types2 + ; +tv_bndrs : + tv_bndr tv_bndrs + | /*empty*/ + ; +tv_bndr : + tv_bndr_no_braces + | '{' tyvar '}' + | '{' tyvar '::' kind '}' + ; +tv_bndr_no_braces : + tyvar + | '(' tyvar '::' kind ')' + ; +fds : + /*empty*/ + | '|' fds1 + ; +fds1 : + fds1 ',' fd + | fd + ; +fd : + varids0 '->' varids0 + ; +varids0 : + /*empty*/ + | varids0 tyvar + ; +//----------------------------------------------------------------------------- +//-- Kinds + +kind : + ctype + ; + + + +//----------------------------------------------------------------------------- +//-- Datatype declarations + +gadt_constrlist : //-- Returned in order + + 'where' '{' gadt_constrs '}' + | 'where' vocurly gadt_constrs close + | /*empty*/ + ; +gadt_constrs : + gadt_constr ';' gadt_constrs + + | gadt_constr + | /*empty*/ + ; +//-- We allow the following forms: +//-- C :Eq a => a -> T a +//-- C :forall a. Eq a => !a -> T a +//-- D :T a +//-- forall a. Eq a => D :T a + +gadt_constr : + //-- see Note [Difference in parsing GADT and data constructors] + //-- Returns a list because of: C,D :ty + //-- TODO:AZ capture the optSemi. Why leading? + optSemi con_list '::' sigtype + ; + + + +constrs : + '=' constrs1 + ; +constrs1 : + constrs1 '|' constr + + | constr + ; +constr : + forall context '=>' constr_stuff + + | forall constr_stuff + ; + +forall : + 'forall' tv_bndrs '.' + | /*empty*/ + ; +constr_stuff : + infixtype + ; +fielddecls : + /*empty*/ + | fielddecls1 + ; +fielddecls1 : + fielddecl ',' fielddecls1 + + | fielddecl + ; +fielddecl : + //-- A list because of f,g :Int + sig_vars '::' ctype + ; + +//-- Reversed! +maybe_derivings : + /*empty*/ + | derivings + ; +//-- A list of one or more deriving clauses at the end of a datatype +derivings : + derivings deriving //-- AZ: order? + | deriving + ; +//-- The outer Located is just to allow the caller to +//-- know the rightmost extremity of the 'deriving' clause +deriving : + 'deriving' deriv_clause_types + + + | 'deriving' deriv_strategy_no_via deriv_clause_types + + + | 'deriving' deriv_clause_types deriv_strategy_via + ; + +deriv_clause_types : + qtycon + | '(' ')' + | '(' deriv_types ')' + ; +//----------------------------------------------------------------------------- +//-- Value definitions + + + + + +decl_no_th : + sigdecl + + | infixexp opt_sig rhs + | pattern_synonym_decl + ; +decl : + decl_no_th + + //-- Why do we only allow naked declaration splices in top-level + //-- declarations and not here? Short answer: because readFail009 + //-- fails terribly with a panic in cvBindsAndSigs otherwise. + | splice_exp + ; +rhs : + '=' exp wherebinds + | gdrhs wherebinds + ; +gdrhs : + gdrhs gdrh + | gdrh + ; +gdrh : + '|' guardquals '=' exp + ; +sigdecl : + //-- See Note [Declaration/signature overlap] for why we need infixexp here + infixexp '::' sigtype + + + | var ',' sig_vars '::' sigtype + + + | infix prec ops + + + | pattern_synonym_sig + + | '{-# COMPLETE' qcon_list opt_tyconsig '#-}' + + + //-- This rule is for both INLINE and INLINABLE pragmas + | '{-# INLINE' activation qvarcon '#-}' + + | '{-# OPAQUE' qvar '#-}' + + | '{-# SCC' qvar '#-}' + + + | '{-# SCC' qvar STRING '#-}' + + + | '{-# SPECIALISE' activation qvar '::' sigtypes1 '#-}' + + + | '{-# SPECIALISE_INLINE' activation qvar '::' sigtypes1 '#-}' + + + | '{-# SPECIALISE' 'instance' inst_type '#-}' + + + //-- A minimal complete definition + | '{-# MINIMAL' name_boolformula_opt '#-}' + ; + +activation : + //-- See Note [//%shift: activation -> /*empty*/] + /*empty*/ //%shift + | explicit_activation + ; +explicit_activation : //-- In brackets + '[' INTEGER ']' + | '[' rule_activation_marker INTEGER ']' + ; + +//----------------------------------------------------------------------------- +//-- Expressions + +quasiquote : + TH_QUASIQUOTE + | TH_QQUASIQUOTE + ; +exp : + infixexp '::' ctype + + | infixexp '-<' exp + | infixexp '>-' exp + | infixexp '-<<' exp + | infixexp '>>-' exp + //-- See Note [//%shift: exp -> infixexp] + | infixexp //%shift + /// | exp_prag(exp) //-- See Note [Pragmas and operator fixity] + ; +infixexp : + exp10 + | infixexp qop exp10p //-- See Note [Pragmas and operator fixity] + + //-- AnnVal annotation for NPlusKPat, which discards the operator + ; +exp10p : + exp10 + ///| exp_prag(exp10p) //-- See Note [Pragmas and operator fixity] + ; +///exp_prag(e) : +/// prag_e e //-- See Note [Pragmas and operator fixity] + + +exp10 : + //-- See Note [//%shift: exp10 -> '-' fexp] + '-' fexp //%shift + //-- See Note [//%shift: exp10 -> fexp] + | fexp //%shift + ; +optSemi : + ';' + | /*empty*/ + ; +/* +prag_e : + '{-# SCC' STRING '#-}' + | '{-# SCC' VARID '#-}' + ; +*/ +fexp : + fexp aexp + + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + | fexp PREFIX_AT atype + + | 'static' aexp + + | aexp + ; +aexp : + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + qvar TIGHT_INFIX_AT aexp + + + + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + | PREFIX_TILDE aexp + | PREFIX_BANG aexp + | PREFIX_MINUS aexp + + | '\\' apats '->' exp + + | 'let' binds 'in' exp + ///| '\\' 'lcase' altslist(pats1) + + ///| '\\' 'lcases' altslist(apats) + + | 'if' exp optSemi 'then' exp optSemi 'else' exp + + + | 'if' ifgdpats + ///| 'case' exp 'of' altslist(pats1) + //-- QualifiedDo. + | DO stmtlist + | MDO stmtlist + | 'proc' aexp '->' exp + + + | aexp1 + ; +aexp1 : + aexp1 '{' fbinds '}' + + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + | aexp1 TIGHT_INFIX_PROJ field + + + + | aexp2 + ; +aexp2 : + qvar + | qcon + //-- See Note [//%shift: aexp2 -> ipvar] + | ipvar //%shift + | overloaded_label + | literal +//-- This will enable overloaded strings permanently. Normally the renamer turns HsString +//-- into HsOverLit when -XOverloadedStrings is on. +//-- | STRING + | INTEGER + | RATIONAL + + //-- N.B.: sections get parsed by these next two productions. + //-- This allows you to write, e.g., '(+ 3, 4 -)', which isn't + //-- correct Haskell (you'd have to write '((+ 3), (4 -))') + //-- but the less cluttered version fell out of having texps. + | '(' texp ')' + | '(' tup_exprs ')' + + //-- This case is only possible when 'OverloadedRecordDotBit' is enabled. + | '(' projection ')' + + | '(#' texp '#)' + | '(#' tup_exprs '#)' + + | '[' list ']' + | '_' + + //-- Template Haskell Extension + | splice_untyped + | splice_typed + + | SIMPLEQUOTE qvar + | SIMPLEQUOTE qcon + | TH_TY_QUOTE tyvar + | TH_TY_QUOTE gtycon + //-- See Note [//%shift: aexp2 -> TH_TY_QUOTE] + | TH_TY_QUOTE //%shift + | '[|' exp '|]' + | '[||' exp '||]' + | '[t|' ktype '|]' + | '[p|' infixexp '|]' + | '[d|' cvtopbody '|]' + | quasiquote + + //-- arrow notation extension + | '(|' aexp cmdargs '|)' + ; +projection : +projection + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parsing.Lexer + projection TIGHT_INFIX_PROJ field + + | PREFIX_PROJ field + ; +splice_exp : + splice_untyped + | splice_typed + ; +splice_untyped : + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + PREFIX_DOLLAR aexp2 + ; +splice_typed : + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + PREFIX_DOLLAR_DOLLAR aexp2 + ; + +cmdargs : + cmdargs acmd + | /*empty*/ + ; +acmd : + aexp + ; +cvtopbody : + '{' cvtopdecls0 '}' + | vocurly cvtopdecls0 close + ; +cvtopdecls0 : + topdecls_semi + | topdecls + ; +//----------------------------------------------------------------------------- +//-- Tuple expressions + +//-- "texp" is short for tuple expressions: +//-- things that can appear unparenthesized as long as they're +//-- inside parens or delimited by commas +texp : + exp + + //-- Note [Parsing sections] + //-- ~~~~~~~~~~~~~~~~~~~~~~~ + //-- We include left and right sections here, which isn't + //-- technically right according to the Haskell standard. + //-- For example (3 +, True) isn't legal. + //-- However, we want to parse bang patterns like + //-- (!x, !y) + //-- and it's convenient to do so here as a section + //-- Then when converting expr to pattern we unravel it again + //-- Meanwhile, the renamer checks that real sections appear + //-- inside parens. + | infixexp qop + + | qopm infixexp + + //-- View patterns get parenthesized above + | exp '->' texp + ; +//-- Always at least one comma or bar. +//-- Though this can parse just commas (without any expressions), it won't +//-- in practice, because (,,,) is parsed as a name. See Note [ExplicitTuple] +//-- in GHC.Hs.Expr. +tup_exprs : + texp commas_tup_tail + + | commas tup_tail + + + | texp bars + + | bars texp bars0 + ; + +//-- Always starts with commas; always follows an expr +commas_tup_tail : + commas tup_tail + ; + +//-- Always follows a comma +tup_tail : + texp commas_tup_tail + | texp + //-- See Note [//%shift: tup_tail -> /*empty*/] + | /*empty*/ //%shift + ; +//----------------------------------------------------------------------------- +//-- List expressions + +//-- The rules below are little bit contorted to keep lexps left-recursive while +//-- avoiding another shift/reduce-conflict. +//-- Never empty. +list : + texp + | lexps + | texp '..' + | texp ',' exp '..' + | texp '..' exp + | texp ',' exp '..' exp + | texp '|' flattenedpquals + ; + +lexps : + lexps ',' texp + | texp ',' texp + ; +//----------------------------------------------------------------------------- +//-- List Comprehensions + +flattenedpquals : + pquals + ; +pquals : + squals '|' pquals + + | squals + ; +squals : //-- In reverse order, because the last + //-- one can "grab" the earlier ones + squals ',' transformqual + + | squals ',' qual + + | transformqual + | qual +//-- | transformquals1 ',' '{|' pquals '|}' +//-- | '{|' pquals '|}' + ; +//-- It is possible to enable bracketing (associating) qualifier lists +//-- by uncommenting the lines with above. Due to a lack of +//-- consensus on the syntax, this feature is not being used until we +//-- get user demand. + +transformqual : + //-- Function is applied to a list of stmts *in order* + 'then' exp + | 'then' exp 'by' exp + | 'then' 'group' 'using' exp + + + | 'then' 'group' 'by' exp 'using' exp + ; + +//-- Note that 'group' is a special_id, which means that you can enable +//-- TransformListComp while still using Data.List.group. However, this +//-- introduces a shift/reduce conflict. Happy chooses to resolve the conflict +//-- in by choosing the "group by" variant, which is what we want. + +//----------------------------------------------------------------------------- +//-- Guards + +guardquals : + guardquals1 + ; +guardquals1 : + guardquals1 ',' qual + | qual + ; +//----------------------------------------------------------------------------- +//-- Case alternatives +/* +altslist(PATS) : + '{' alts(PATS) '}' + | vocurly alts(PATS) close + | '{' '}' + | vocurly close + ; +alts(PATS) : + alts1(PATS) + | ';' alts(PATS) + ; +alts1(PATS) : + alts1(PATS) ';' alt(PATS) + | alts1(PATS) ';' + | alt(PATS) + ; +alt(PATS) : + PATS alt_rhs + ; +alt_rhs : + ralt wherebinds + ; + +ralt : + '->' exp + | gdpats + ; +*/ +gdpats : + gdpats gdpat + | gdpat + ; +//-- layout for MultiWayIf doesn't begin with an open brace, because it's hard to +//-- generate the open brace in addition to the vertical bar in the lexer, and +//-- we don't need it. +ifgdpats : + '{' gdpats '}' + | gdpats close + ; +gdpat : + '|' guardquals '->' exp + ; + +//-- 'pat' recognises a pattern, including one with a bang at the top +//-- e.g. "!x" or "!(x,y)" or "C a b" etc +//-- Bangs inside are parsed as infix operator applications, so that +//-- we parse them right when bang-patterns are off +pat : + exp + ; +//-- 'pats1' does the same thing as 'pat', but returns it as a singleton +//-- list so that it can be used with a parameterized production rule +/* +pats1 : + pat + ; +*/ +bindpat : + exp + ; +apat : + aexp + ; +apats : + apat apats + | /*empty*/ + ; +//----------------------------------------------------------------------------- +//-- Statement sequences + +stmtlist : + '{' stmts '}' + | vocurly stmts close + ; +//-- do +//-- The last Stmt should be an expression, but that's hard to enforce +//-- here, because we need too much lookahead if we see do +//-- So we use BodyStmts throughout, and switch the last one over +//-- in ParseUtils.checkDo instead + +stmts : + stmts ';' stmt + + | stmts ';' + | stmt + | /*empty*/ + ; + +//-- For typing stmts at the GHCi prompt, where +//-- the input may consist of just comments. +maybe_stmt : + stmt + | + ; +//-- For GHC API. +e_stmt : + stmt + ; +stmt : + qual + | 'rec' stmtlist + ; +qual : + bindpat '<-' exp + | exp + | 'let' binds + ; +//----------------------------------------------------------------------------- +//-- Record Field Update/Construction + +fbinds : + fbinds1 + | /*empty*/ + ; +fbinds1 : + fbind ',' fbinds1 + + | fbind + | '..' + ; +fbind : + qvar '=' texp + //-- RHS is a 'texp', allowing view patterns (#6038) + //-- and, incidentally, sections. Eg + //-- f (R ) = ... + + | qvar + //-- In the punning case, use a place-holder + //-- The renamer fills in the final value + + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + //-- AZ: need to pull out the let block into a helper + | field TIGHT_INFIX_PROJ fieldToUpdate '=' texp + + + //-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + //-- AZ: need to pull out the let block into a helper + | field TIGHT_INFIX_PROJ fieldToUpdate + ; + +fieldToUpdate : +fieldToUpdate + //-- See Note [Whitespace-sensitive operator parsing] in Lexer.x + fieldToUpdate TIGHT_INFIX_PROJ field + | field + ; +//----------------------------------------------------------------------------- +//-- Implicit Parameter Bindings + +dbinds : //-- reversed + dbinds ';' dbind + + | dbinds ';' + | dbind +//-- | /*empty*/ + ; +dbind : + ipvar '=' exp + ; +ipvar : + IPDUPVARID + ; +//----------------------------------------------------------------------------- +//-- Overloaded labels + +overloaded_label : + LABELVARID + ; +//----------------------------------------------------------------------------- +//-- Warnings and deprecations + +name_boolformula_opt : + name_boolformula + | /*empty*/ + ; +name_boolformula : + name_boolformula_and + | name_boolformula_and '|' name_boolformula + ; + +name_boolformula_and : + name_boolformula_and_list + ; + +name_boolformula_and_list : + name_boolformula_atom + | name_boolformula_atom ',' name_boolformula_and_list + ; + +name_boolformula_atom : + '(' name_boolformula ')' + | name_var + ; +namelist : + name_var + | name_var ',' namelist + ; +name_var : + var + | con + ; +//----------------------------------------- +//-- Data constructors +//-- There are two different productions here as lifted list constructors +//-- are parsed differently. + +qcon_nowiredlist : + gen_qcon + | sysdcon_nolist + ; +qcon : + gen_qcon + | sysdcon + ; +gen_qcon : + qconid + | '(' qconsym ')' + ; +con : + conid + | '(' consym ')' + | sysdcon + ; +con_list : + con + | con ',' con_list + ; +qcon_list : + qcon + | qcon ',' qcon_list + ; +//-- See Note [ExplicitTuple] in GHC.Hs.Expr +sysdcon_nolist : //-- Wired in data constructors + '(' ')' + | '(' commas ')' + | '(#' '#)' + | '(#' commas '#)' + ; +//-- See Note [Empty lists] in GHC.Hs.Expr +sysdcon : + sysdcon_nolist + | '[' ']' + ; +conop : + consym + | '`' conid '`' + ; +qconop : + qconsym + | '`' qconid '`' + ; +//---------------------------------------------------------------------------- +//-- Type constructors + + +//-- See Note [Unit tuples] in GHC.Hs.Type for the distinction +//-- between gtycon and ntgtycon +gtycon : //-- A "general" qualified tycon, including unit tuples + ntgtycon + | '(' ')' + | '(#' '#)' + ; +ntgtycon : //-- A "general" qualified tycon, excluding unit tuples + oqtycon + | '(' commas ')' + | '(#' commas '#)' + | '(#' bars '#)' + | '(' '->' ')' + | '[' ']' + ; +oqtycon : //-- An "ordinary" qualified tycon; + //-- These can appear in export lists + qtycon + | '(' qtyconsym ')' + ; +oqtycon_no_varcon : //-- Type constructor which cannot be mistaken + //-- for variable constructor in export lists + //-- see Note [Type constructors in export list] + qtycon + | '(' QCONSYM ')' + | '(' CONSYM ')' + | '(' ':' ')' + ; + + +qtyconop : //-- Qualified or unqualified + //-- See Note [//%shift: qtyconop -> qtyconsym] + qtyconsym //%shift + | '`' qtycon '`' + ; +qtycon : //-- Qualified or unqualified + QCONID + | tycon + ; +tycon : //-- Unqualified + CONID + ; +qtyconsym : + QCONSYM + | QVARSYM + | tyconsym + ; +tyconsym : + CONSYM + | VARSYM + | ':' + | '-' + | '.' + ; +//-- An "ordinary" unqualified tycon. See `oqtycon` for the qualified version. +//-- These can appear in `ANN type` declarations (#19374). +otycon : + tycon + | '(' tyconsym ')' + ; +//----------------------------------------------------------------------------- +//-- Operators + +op : //-- used in infix decls + varop + | conop + | '->' + ; +varop : + varsym + | '`' varid '`' + ; +qop : //-- used in sections + qvarop + | qconop + | hole_op + ; +qopm : //-- used in sections + qvaropm + | qconop + | hole_op + ; +hole_op : //-- used in sections + '`' '_' '`' + ; +qvarop : + qvarsym + | '`' qvarid '`' + ; +qvaropm : + qvarsym_no_minus + | '`' qvarid '`' + ; +//----------------------------------------------------------------------------- +//-- Type variables + +tyvar : + tyvarid + ; +tyvarop : + '`' tyvarid '`' + ; +tyvarid : + VARID + | special_id + | 'unsafe' + | 'safe' + | 'interruptible' + //-- If this changes relative to varid, update 'checkRuleTyVarBndrNames' + //-- in GHC.Parser.PostProcess + //-- See Note [Parsing explicit foralls in Rules] + ; +//----------------------------------------------------------------------------- +//-- Variables + +var : + varid + | '(' varsym ')' + ; +qvar : + qvarid + | '(' varsym ')' + | '(' qvarsym1 ')' +//-- We've inlined qvarsym here so that the decision about +//-- whether it's a qvar or a var can be postponed until +//-- *after* we see the close paren. + ; +field : + varid + ; +qvarid : + varid + | QVARID + ; +//-- Note that 'role' and 'family' get lexed separately regardless of +//-- the use of extensions. However, because they are listed here, +//-- this is OK and they can be used as normal varids. +//-- See Note [Lexing type pseudo-keywords] in GHC.Parser.Lexer +varid : + VARID + | special_id + | 'unsafe' + | 'safe' + | 'interruptible' + | 'forall' + | 'family' + | 'role' + //-- If this changes relative to tyvarid, update 'checkRuleTyVarBndrNames' + //-- in GHC.Parser.PostProcess + //-- See Note [Parsing explicit foralls in Rules] + ; +qvarsym : + varsym + | qvarsym1 + ; +qvarsym_no_minus : + varsym_no_minus + | qvarsym1 + ; +qvarsym1 : + QVARSYM + ; +varsym : + varsym_no_minus + | '-' + ; +varsym_no_minus : //-- varsym not including '-' + VARSYM + | special_sym + ; + +//-- These special_ids are treated as keywords in various places, +//-- but as ordinary ids elsewhere. 'special_id' collects all these +//-- except 'unsafe', 'interruptible', 'forall', 'family', 'role', 'stock', and +//-- 'anyclass', whose treatment differs depending on context +special_id : +special_id + 'as' + | 'qualified' + | 'hiding' + | 'export' + | 'label' + | 'dynamic' + | 'stdcall' + | 'ccall' + | 'capi' + | 'prim' + | 'javascript' + //-- See Note [//%shift: special_id -> 'group'] + | 'group' //%shift + | 'stock' + | 'anyclass' + | 'via' + | 'unit' + | 'dependency' + | 'signature' + ; +special_sym : + '.' + | '*' + ; +//----------------------------------------------------------------------------- +//-- Data constructors + +qconid : //-- Qualified or unqualified + conid + | QCONID + ; +conid : + CONID + ; +qconsym : //-- Qualified or unqualified + consym + | QCONSYM + ; +consym : + CONSYM + + //-- ':' means only list cons + | ':' + ; + +//----------------------------------------------------------------------------- +//-- Literals + +literal : + CHAR + | STRING + | PRIMINTEGER + | PRIMWORD + | PRIMINTEGER8 + | PRIMINTEGER16 + | PRIMINTEGER32 + | PRIMINTEGER64 + | PRIMWORD8 + | PRIMWORD16 + | PRIMWORD32 + | PRIMWORD64 + | PRIMCHAR + | PRIMSTRING + | PRIMFLOAT + | PRIMDOUBLE + ; +//----------------------------------------------------------------------------- +//-- Layout + +close : + vccurly //-- context popped in lexer. + | error + ; +//----------------------------------------------------------------------------- +//-- Miscellaneous (mostly renamings) + +modid : + CONID + | QCONID + ; +commas : //-- One or more commas + commas ',' + | ',' + ; +bars0 : //-- Zero or more bars + bars + | + ; +bars : //-- One or more bars + bars '|' + | '|' + ; + +//Lexer + +VARSYM : 'VARSYM' ; +STRING : 'STRING' ; +VARID : 'VARID' ; +CONID : 'CONID' ; +PREFIX_MINUS : 'PREFIX_MINUS' ; +vocurly : 'vocurly' ; +INTEGER : 'INTEGER' ; +PREFIX_TILDE : 'PREFIX_TILDE' ; +PREFIX_PERCENT : 'PREFIX_PERCENT' ; +PREFIX_AT : 'PREFIX_AT' ; +SIMPLEQUOTE : 'SIMPLEQUOTE' ; +PREFIX_BANG : 'PREFIX_BANG' ; +CHAR : 'CHAR' ; +QVARID : 'QVARID' ; +TH_QUASIQUOTE : 'TH_QUASIQUOTE' ; +TH_QQUASIQUOTE : 'TH_QQUASIQUOTE' ; +TIGHT_INFIX_AT : 'TIGHT_INFIX_AT' ; +DO : 'DO' ; +MDO : 'MDO' ; +TIGHT_INFIX_PROJ : 'TIGHT_INFIX_PROJ' ; +RATIONAL : 'RATIONAL' ; +TH_TY_QUOTE : 'TH_TY_QUOTE' ; +PREFIX_PROJ : 'PREFIX_PROJ' ; +PREFIX_DOLLAR : 'PREFIX_DOLLAR' ; +PREFIX_DOLLAR_DOLLAR : 'PREFIX_DOLLAR_DOLLAR' ; +IPDUPVARID : 'IPDUPVARID' ; +LABELVARID : 'LABELVARID' ; +QCONSYM : 'QCONSYM' ; +CONSYM : 'CONSYM' ; +QCONID : 'QCONID' ; +QVARSYM : 'QVARSYM' ; +PRIMINTEGER : 'PRIMINTEGER' ; +PRIMWORD : 'PRIMWORD' ; +PRIMINTEGER8 : 'PRIMINTEGER8' ; +PRIMINTEGER16 : 'PRIMINTEGER16' ; +PRIMINTEGER32 : 'PRIMINTEGER32' ; +PRIMINTEGER64 : 'PRIMINTEGER64' ; +PRIMWORD8 : 'PRIMWORD8' ; +PRIMWORD16 : 'PRIMWORD16' ; +PRIMWORD32 : 'PRIMWORD32' ; +PRIMWORD64 : 'PRIMWORD64' ; +PRIMCHAR : 'PRIMCHAR' ; +PRIMSTRING : 'PRIMSTRING' ; +PRIMFLOAT : 'PRIMFLOAT' ; +PRIMDOUBLE : 'PRIMDOUBLE' ; + +vccurly : '}{' ; //-- context popped in lexer. + +} diff --git a/playground/go.g b/playground/go.g new file mode 100644 index 0000000..139f0b7 --- /dev/null +++ b/playground/go.g @@ -0,0 +1,762 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Go language grammar. + * + * The Go semicolon rules are: + * + * 1. all statements and declarations are terminated by semicolons. + * 2. semicolons can be omitted before a closing ) or }. + * 3. semicolons are inserted by the lexer before a newline + * following a specific list of tokens. + * + * Rules #1 and #2 are accomplished by writing the lists as + * semicolon-separated lists with an optional trailing semicolon. + * Rule #3 is implemented in yylex. + */ + +go { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +//%token LLITERAL +//%token LASOP +//%token LCOLAS +//%token LBREAK +//%token LCASE +//%token LCHAN +//%token LCONST +//%token LCONTINUE +//%token LDDD +//%token LDEFAULT +//%token LDEFER +//%token LELSE +//%token LFALL +//%token LFOR +//%token LFUNC +//%token LGO +//%token LGOTO +//%token LIF +//%token LIMPORT +//%token LINTERFACE +//%token LMAP +//%token LNAME +//%token LPACKAGE +//%token LRANGE +//%token LRETURN +//%token LSELECT +//%token LSTRUCT +//%token LSWITCH +//%token LTYPE +//%token LVAR +//%token LANDAND +//%token LANDNOT +//%token LBODY +//%token LCOMM +//%token LDEC +//%token LEQ +//%token LGE +//%token LGT +//%token LIGNORE +//%token LINC +//%token LLE +//%token LLSH +//%token LLT +//%token LNE +//%token LOROR +//%token LRSH +//%token '+' +//%token '-' +//%token '|' +//%token '^' +//%token '*' +//%token '/' +//%token '%' +//%token '&' +//%token NotPackage +//%token NotParen +//%token '(' +//%token ')' +//%token PreferToRightParen +//%token ';' +//%token '.' +//%token '$' +//%token '=' +//%token ':' +//%token '{' +//%token '}' +//%token '!' +//%token '~' +//%token '[' +//%token ']' +//%token '?' +//%token '@' +//%token ',' + +%left /*1*/ LCOMM ; +%left /*2*/ LOROR ; +%left /*3*/ LANDAND ; +%left /*4*/ LEQ LGE LGT LLE LLT LNE ; +%left /*5*/ '+' '-' '|' '^' ; +%left /*6*/ LANDNOT LLSH LRSH '*' '/' '%' '&' ; +%left /*7*/ NotPackage ; +%left /*8*/ LPACKAGE ; +%left /*9*/ NotParen ; +%left /*10*/ '(' ; +%left /*11*/ ')' ; +%left /*12*/ PreferToRightParen ; + +//%start file + +//%% + +file : + loadsys package imports xdcl_list + ; +package : + /*empty*/ %prec NotPackage /*7L*/ + | LPACKAGE /*8L*/ sym ';' + ; +loadsys : + import_package import_there + ; +imports : + /*empty*/ + | imports import ';' + ; +import : + LIMPORT import_stmt + | LIMPORT '(' /*10L*/ import_stmt_list osemi ')' /*11L*/ + | LIMPORT '(' /*10L*/ ')' /*11L*/ + ; +import_stmt : + import_here import_package import_there + | import_here import_there + ; +import_stmt_list : + import_stmt + | import_stmt_list ';' import_stmt + ; +import_here : + LLITERAL + | sym LLITERAL + | '.' LLITERAL + ; +import_package : + LPACKAGE /*8L*/ LNAME import_safety ';' + ; +import_safety : + /*empty*/ + | LNAME + ; +import_there : + hidden_import_list '$' '$' + ; +xdcl : + /*empty*/ + | common_dcl + | xfndcl + | non_dcl_stmt + | error + ; +common_dcl : + LVAR vardcl + | LVAR '(' /*10L*/ vardcl_list osemi ')' /*11L*/ + | LVAR '(' /*10L*/ ')' /*11L*/ + | lconst constdcl + | lconst '(' /*10L*/ constdcl osemi ')' /*11L*/ + | lconst '(' /*10L*/ constdcl ';' constdcl_list osemi ')' /*11L*/ + | lconst '(' /*10L*/ ')' /*11L*/ + | LTYPE typedcl + | LTYPE '(' /*10L*/ typedcl_list osemi ')' /*11L*/ + | LTYPE '(' /*10L*/ ')' /*11L*/ + ; +lconst : + LCONST + ; +vardcl : + dcl_name_list ntype + | dcl_name_list ntype '=' expr_list + | dcl_name_list '=' expr_list + ; +constdcl : + dcl_name_list ntype '=' expr_list + | dcl_name_list '=' expr_list + ; +constdcl1 : + constdcl + | dcl_name_list ntype + | dcl_name_list + ; +typedclname : + sym + ; +typedcl : + typedclname ntype + ; +simple_stmt : + expr + | expr LASOP expr + | expr_list '=' expr_list + | expr_list LCOLAS expr_list + | expr LINC + | expr LDEC + ; +case : + LCASE expr_or_type_list ':' + | LCASE expr_or_type_list '=' expr ':' + | LCASE expr_or_type_list LCOLAS expr ':' + | LDEFAULT ':' + ; +compound_stmt : + '{' stmt_list '}' + ; +caseblock : + case stmt_list + ; +caseblock_list : + /*empty*/ + | caseblock_list caseblock + ; +loop_body : + LBODY stmt_list '}' + ; +range_stmt : + expr_list '=' LRANGE expr + | expr_list LCOLAS LRANGE expr + | LRANGE expr + ; +for_header : + osimple_stmt ';' osimple_stmt ';' osimple_stmt + | osimple_stmt + | range_stmt + ; +for_body : + for_header loop_body + ; +for_stmt : + LFOR for_body + ; +if_header : + osimple_stmt + | osimple_stmt ';' osimple_stmt + ; +if_stmt : + LIF if_header loop_body elseif_list else + ; +elseif : + LELSE LIF if_header loop_body + ; +elseif_list : + /*empty*/ + | elseif_list elseif + ; +else : + /*empty*/ + | LELSE compound_stmt + ; +switch_stmt : + LSWITCH if_header LBODY caseblock_list '}' + ; +select_stmt : + LSELECT LBODY caseblock_list '}' + ; +expr : + uexpr + | expr LOROR /*2L*/ expr + | expr LANDAND /*3L*/ expr + | expr LEQ /*4L*/ expr + | expr LNE /*4L*/ expr + | expr LLT /*4L*/ expr + | expr LLE /*4L*/ expr + | expr LGE /*4L*/ expr + | expr LGT /*4L*/ expr + | expr '+' /*5L*/ expr + | expr '-' /*5L*/ expr + | expr '|' /*5L*/ expr + | expr '^' /*5L*/ expr + | expr '*' /*6L*/ expr + | expr '/' /*6L*/ expr + | expr '%' /*6L*/ expr + | expr '&' /*6L*/ expr + | expr LANDNOT /*6L*/ expr + | expr LLSH /*6L*/ expr + | expr LRSH /*6L*/ expr + | expr LCOMM /*1L*/ expr + ; +uexpr : + pexpr + | '*' /*6L*/ uexpr + | '&' /*6L*/ uexpr + | '+' /*5L*/ uexpr + | '-' /*5L*/ uexpr + | '!' uexpr + | '~' uexpr + | '^' /*5L*/ uexpr + | LCOMM /*1L*/ uexpr + ; +pseudocall : + pexpr '(' /*10L*/ ')' /*11L*/ + | pexpr '(' /*10L*/ expr_or_type_list ocomma ')' /*11L*/ + | pexpr '(' /*10L*/ expr_or_type_list LDDD ocomma ')' /*11L*/ + ; +pexpr_no_paren : + LLITERAL + | name + | pexpr '.' sym + | pexpr '.' '(' /*10L*/ expr_or_type ')' /*11L*/ + | pexpr '.' '(' /*10L*/ LTYPE ')' /*11L*/ + | pexpr '[' expr ']' + | pexpr '[' oexpr ':' oexpr ']' + | pexpr '[' oexpr ':' oexpr ':' oexpr ']' + | pseudocall + | convtype '(' /*10L*/ expr ocomma ')' /*11L*/ + | comptype lbrace start_complit braced_keyval_list '}' + | pexpr_no_paren '{' start_complit braced_keyval_list '}' + | '(' /*10L*/ expr_or_type ')' /*11L*/ '{' start_complit braced_keyval_list '}' + | fnliteral + ; +start_complit : + /*empty*/ + ; +keyval : + complitexpr ':' complitexpr + ; +bare_complitexpr : + expr + | '{' start_complit braced_keyval_list '}' + ; +complitexpr : + expr + | '{' start_complit braced_keyval_list '}' + ; +pexpr : + pexpr_no_paren + | '(' /*10L*/ expr_or_type ')' /*11L*/ + ; +expr_or_type : + expr + | non_expr_type %prec PreferToRightParen /*12L*/ + ; +name_or_type : + ntype + ; +lbrace : + LBODY + | '{' + ; +new_name : + sym + ; +dcl_name : + sym + ; +onew_name : + /*empty*/ + | new_name + ; +sym : + LNAME + | hidden_importsym + | '?' + ; +hidden_importsym : + '@' LLITERAL '.' LNAME + | '@' LLITERAL '.' '?' + ; +name : + sym %prec NotParen /*9L*/ + ; +labelname : + new_name + ; +dotdotdot : + LDDD + | LDDD ntype + ; +ntype : + recvchantype + | fntype + | othertype + | ptrtype + | dotname + | '(' /*10L*/ ntype ')' /*11L*/ + ; +non_expr_type : + recvchantype + | fntype + | othertype + | '*' /*6L*/ non_expr_type + ; +non_recvchantype : + fntype + | othertype + | ptrtype + | dotname + | '(' /*10L*/ ntype ')' /*11L*/ + ; +convtype : + fntype + | othertype + ; +comptype : + othertype + ; +fnret_type : + recvchantype + | fntype + | othertype + | ptrtype + | dotname + ; +dotname : + name + | name '.' sym + ; +othertype : + '[' oexpr ']' ntype + | '[' LDDD ']' ntype + | LCHAN non_recvchantype + | LCHAN LCOMM /*1L*/ ntype + | LMAP '[' ntype ']' ntype + | structtype + | interfacetype + ; +ptrtype : + '*' /*6L*/ ntype + ; +recvchantype : + LCOMM /*1L*/ LCHAN ntype + ; +structtype : + LSTRUCT lbrace structdcl_list osemi '}' + | LSTRUCT lbrace '}' + ; +interfacetype : + LINTERFACE lbrace interfacedcl_list osemi '}' + | LINTERFACE lbrace '}' + ; +xfndcl : + LFUNC fndcl fnbody + ; +fndcl : + sym '(' /*10L*/ oarg_type_list_ocomma ')' /*11L*/ fnres + | '(' /*10L*/ oarg_type_list_ocomma ')' /*11L*/ sym '(' /*10L*/ oarg_type_list_ocomma ')' /*11L*/ fnres + ; +hidden_fndcl : + hidden_pkg_importsym '(' /*10L*/ ohidden_funarg_list ')' /*11L*/ ohidden_funres + | '(' /*10L*/ hidden_funarg_list ')' /*11L*/ sym '(' /*10L*/ ohidden_funarg_list ')' /*11L*/ ohidden_funres + ; +fntype : + LFUNC '(' /*10L*/ oarg_type_list_ocomma ')' /*11L*/ fnres + ; +fnbody : + /*empty*/ + | '{' stmt_list '}' + ; +fnres : + /*empty*/ %prec NotParen /*9L*/ + | fnret_type + | '(' /*10L*/ oarg_type_list_ocomma ')' /*11L*/ + ; +fnlitdcl : + fntype + ; +fnliteral : + fnlitdcl lbrace stmt_list '}' + | fnlitdcl error + ; +xdcl_list : + /*empty*/ + | xdcl_list xdcl ';' + ; +vardcl_list : + vardcl + | vardcl_list ';' vardcl + ; +constdcl_list : + constdcl1 + | constdcl_list ';' constdcl1 + ; +typedcl_list : + typedcl + | typedcl_list ';' typedcl + ; +structdcl_list : + structdcl + | structdcl_list ';' structdcl + ; +interfacedcl_list : + interfacedcl + | interfacedcl_list ';' interfacedcl + ; +structdcl : + new_name_list ntype oliteral + | embed oliteral + | '(' /*10L*/ embed ')' /*11L*/ oliteral + | '*' /*6L*/ embed oliteral + | '(' /*10L*/ '*' /*6L*/ embed ')' /*11L*/ oliteral + | '*' /*6L*/ '(' /*10L*/ embed ')' /*11L*/ oliteral + ; +packname : + LNAME + | LNAME '.' sym + ; +embed : + packname + ; +interfacedcl : + new_name indcl + | packname + | '(' /*10L*/ packname ')' /*11L*/ + ; +indcl : + '(' /*10L*/ oarg_type_list_ocomma ')' /*11L*/ fnres + ; +arg_type : + name_or_type + | sym name_or_type + | sym dotdotdot + | dotdotdot + ; +arg_type_list : + arg_type + | arg_type_list ',' arg_type + ; +oarg_type_list_ocomma : + /*empty*/ + | arg_type_list ocomma + ; +stmt : + /*empty*/ + | compound_stmt + | common_dcl + | non_dcl_stmt + | error + ; +non_dcl_stmt : + simple_stmt + | for_stmt + | switch_stmt + | select_stmt + | if_stmt + ; +non_dcl_stmt : + labelname ':' stmt + | LFALL + | LBREAK onew_name + | LCONTINUE onew_name + | LGO pseudocall + | LDEFER pseudocall + | LGOTO new_name + | LRETURN oexpr_list + ; +stmt_list : + stmt + | stmt_list ';' stmt + ; +new_name_list : + new_name + | new_name_list ',' new_name + ; +dcl_name_list : + dcl_name + | dcl_name_list ',' dcl_name + ; +expr_list : + expr + | expr_list ',' expr + ; +expr_or_type_list : + expr_or_type + | expr_or_type_list ',' expr_or_type + ; +keyval_list : + keyval + | bare_complitexpr + | keyval_list ',' keyval + | keyval_list ',' bare_complitexpr + ; +braced_keyval_list : + /*empty*/ + | keyval_list ocomma + ; +osemi : + /*empty*/ + | ';' + ; +ocomma : + /*empty*/ + | ',' + ; +oexpr : + /*empty*/ + | expr + ; +oexpr_list : + /*empty*/ + | expr_list + ; +osimple_stmt : + /*empty*/ + | simple_stmt + ; +ohidden_funarg_list : + /*empty*/ + | hidden_funarg_list + ; +ohidden_structdcl_list : + /*empty*/ + | hidden_structdcl_list + ; +ohidden_interfacedcl_list : + /*empty*/ + | hidden_interfacedcl_list + ; +oliteral : + /*empty*/ + | LLITERAL + ; +hidden_import : + LIMPORT LNAME LLITERAL ';' + | LVAR hidden_pkg_importsym hidden_type ';' + | LCONST hidden_pkg_importsym '=' hidden_constant ';' + | LCONST hidden_pkg_importsym hidden_type '=' hidden_constant ';' + | LTYPE hidden_pkgtype hidden_type ';' + | LFUNC hidden_fndcl fnbody ';' + ; +hidden_pkg_importsym : + hidden_importsym + ; +hidden_pkgtype : + hidden_pkg_importsym + ; +hidden_type : + hidden_type_misc + | hidden_type_recv_chan + | hidden_type_func + ; +hidden_type_non_recv_chan : + hidden_type_misc + | hidden_type_func + ; +hidden_type_misc : + hidden_importsym + | LNAME + | '[' ']' hidden_type + | '[' LLITERAL ']' hidden_type + | LMAP '[' hidden_type ']' hidden_type + | LSTRUCT '{' ohidden_structdcl_list '}' + | LINTERFACE '{' ohidden_interfacedcl_list '}' + | '*' /*6L*/ hidden_type + | LCHAN hidden_type_non_recv_chan + | LCHAN '(' /*10L*/ hidden_type_recv_chan ')' /*11L*/ + | LCHAN LCOMM /*1L*/ hidden_type + ; +hidden_type_recv_chan : + LCOMM /*1L*/ LCHAN hidden_type + ; +hidden_type_func : + LFUNC '(' /*10L*/ ohidden_funarg_list ')' /*11L*/ ohidden_funres + ; +hidden_funarg : + sym hidden_type oliteral + | sym LDDD hidden_type oliteral + ; +hidden_structdcl : + sym hidden_type oliteral + ; +hidden_interfacedcl : + sym '(' /*10L*/ ohidden_funarg_list ')' /*11L*/ ohidden_funres + | hidden_type + ; +ohidden_funres : + /*empty*/ + | hidden_funres + ; +hidden_funres : + '(' /*10L*/ ohidden_funarg_list ')' /*11L*/ + | hidden_type + ; +hidden_literal : + LLITERAL + | '-' /*5L*/ LLITERAL + | sym + ; +hidden_constant : + hidden_literal + | '(' /*10L*/ hidden_literal '+' /*5L*/ hidden_literal ')' /*11L*/ + ; +hidden_import_list : + /*empty*/ + | hidden_import_list hidden_import + ; +hidden_funarg_list : + hidden_funarg + | hidden_funarg_list ',' hidden_funarg + ; +hidden_structdcl_list : + hidden_structdcl + | hidden_structdcl_list ';' hidden_structdcl + ; +hidden_interfacedcl_list : + hidden_interfacedcl + | hidden_interfacedcl_list ';' hidden_interfacedcl + ; + +//Lexer + +LCOMM : '<-' ; +LOROR : '||' ; +LANDAND : '&&' ; +LEQ : '==' ; +LGE : '>=' ; +LGT : '>' ; +LLE : '<=' ; +LLT : '<' ; +LNE : '!=' ; +LANDNOT : '&^' ; +LLSH : '<<' ; +LRSH : '>>' ; +LPACKAGE : 'package' ; +LIMPORT : 'import' ; +LLITERAL : "\"([^\"\n]|\\[^\n])*\"" ; +LLITERAL : "'([^'\n]|\\[^\n])'" ; +LLITERAL : "0[xX][a-fA-F0-9]+|[0-9]+([Ee][+-]?[0-9]+)?|[0-9]*\\.[0-9]+([Ee][+-]?[0-9]+)?" ; +LNAME : "[a-zA-Z_][a-zA-Z_0-9]*" ; +LVAR : 'var' ; +LTYPE : 'type' ; +LCONST : 'const' ; +LASOP : '=' ; +LCOLAS : ':=' ; +LINC : '++' ; +LDEC : '--' ; +LCASE : 'case' ; +LDEFAULT : 'default' ; +LBODY : 'LBODY' ; //'{' ; +LRANGE : 'range' ; +LFOR : 'for' ; +LIF : 'if' ; +LELSE : 'else' ; +LSWITCH : 'switch' ; +LSELECT : 'select' ; +LDDD : '...' ; +LCHAN : 'chan' ; +LMAP : 'map' ; +LSTRUCT : 'struct' ; +LINTERFACE : 'interface' ; +LFUNC : 'func' ; +LFALL : 'fallthrough' ; +LBREAK : 'break' ; +LCONTINUE : 'continue' ; +LGO : 'go' ; +LDEFER : 'defer' ; +LGOTO : 'goto' ; +LRETURN : 'return' ; + +} diff --git a/playground/graphql-ruby.g b/playground/graphql-ruby.g new file mode 100644 index 0000000..cc0a036 --- /dev/null +++ b/playground/graphql-ruby.g @@ -0,0 +1,537 @@ +//From: https://github.com/rmosolgo/graphql-ruby/blob/master/graphql-c_parser/ext/graphql_c_parser_ext/parser.y + +graphql_ruby { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token AMP +//%token BANG +//%token COLON +//%token DIRECTIVE +//%token DIR_SIGN +//%token ENUM +//%token ELLIPSIS +//%token EQUALS +//%token EXTEND +//%token FALSE_LITERAL +//%token FLOAT +//%token FRAGMENT +//%token IDENTIFIER +//%token INPUT +//%token IMPLEMENTS +//%token INT +//%token INTERFACE +//%token LBRACKET +//%token LCURLY +//%token LPAREN +//%token MUTATION +//%token NULL_LITERAL +//%token ON +//%token PIPE +//%token QUERY +//%token RBRACKET +//%token RCURLY +//%token REPEATABLE +//%token RPAREN +//%token SCALAR +//%token SCHEMA +//%token STRING +//%token SUBSCRIPTION +//%token TRUE_LITERAL +//%token TYPE_LITERAL +//%token UNION +//%token VAR_SIGN + + +//%start start + +//%% + +start : + /*YYEOF + |*/ document + ; + +document : + definitions_list + ; + +definitions_list : + definition + | definitions_list definition + ; + +definition : + executable_definition + | type_system_definition + | type_system_extension + ; + +executable_definition : + operation_definition + | fragment_definition + ; + +operation_definition : + operation_type operation_name_opt variable_definitions_opt directives_list_opt selection_set + | LCURLY selection_list RCURLY + | LCURLY RCURLY + ; + +operation_type : + QUERY + | MUTATION + | SUBSCRIPTION + ; + +operation_name_opt : + /*empty*/ + | name + ; + +variable_definitions_opt : + /*empty*/ + | LPAREN variable_definitions_list RPAREN + ; + +variable_definitions_list : + variable_definition + | variable_definitions_list variable_definition + ; + +variable_definition : + VAR_SIGN name COLON type default_value_opt + ; + +default_value_opt : + /*empty*/ + | EQUALS literal_value + ; + +selection_list : + selection + | selection_list selection + ; + +selection : + field + | fragment_spread + | inline_fragment + ; + +selection_set : + LCURLY selection_list RCURLY + ; + +selection_set_opt : + /*empty*/ + | selection_set + ; + +field : + name COLON name arguments_opt directives_list_opt selection_set_opt + | name arguments_opt directives_list_opt selection_set_opt + ; + +arguments_opt : + /*empty*/ + | LPAREN arguments_list RPAREN + ; + +arguments_list : + argument + | arguments_list argument + ; + +argument : + name COLON input_value + ; + +literal_value : + FLOAT + | INT + | STRING + | TRUE_LITERAL + | FALSE_LITERAL + | null_value + | enum_value + | list_value + | object_literal_value + ; + +input_value : + literal_value + | variable + | object_value + ; + +null_value : + NULL_LITERAL + ; + +variable : + VAR_SIGN name + ; + +list_value : + LBRACKET RBRACKET + | LBRACKET list_value_list RBRACKET + ; + +list_value_list : + input_value + | list_value_list input_value + ; + +enum_name : + IDENTIFIER + | FRAGMENT + | REPEATABLE + | ON + | operation_type + | schema_keyword + ; + +enum_value : + enum_name + ; + +object_value : + LCURLY object_value_list_opt RCURLY + ; + +object_value_list_opt : + /*empty*/ + | object_value_list + ; + +object_value_list : + object_value_field + | object_value_list object_value_field + ; + +object_value_field : + name COLON input_value + ; + +object_literal_value : + LCURLY object_literal_value_list_opt RCURLY + ; + +object_literal_value_list_opt : + /*empty*/ + | object_literal_value_list + ; + +object_literal_value_list : + object_literal_value_field + | object_literal_value_list object_literal_value_field + ; + +object_literal_value_field : + name COLON literal_value + ; + +directives_list_opt : + /*empty*/ + | directives_list + ; + +directives_list : + directive + | directives_list directive + ; + +directive : + DIR_SIGN name arguments_opt + ; + +name : + name_without_on + | ON + ; + +schema_keyword : + SCHEMA + | SCALAR + | TYPE_LITERAL + | IMPLEMENTS + | INTERFACE + | UNION + | ENUM + | INPUT + | DIRECTIVE + ; + +name_without_on : + IDENTIFIER + | FRAGMENT + | REPEATABLE + | TRUE_LITERAL + | FALSE_LITERAL + | operation_type + | schema_keyword + ; + +fragment_spread : + ELLIPSIS name_without_on directives_list_opt + ; + +inline_fragment : + ELLIPSIS ON type directives_list_opt selection_set + | ELLIPSIS directives_list_opt selection_set + ; + +fragment_definition : + FRAGMENT fragment_name_opt ON type directives_list_opt selection_set + ; + +fragment_name_opt : + /*empty*/ + | name_without_on + ; + +type : + nullable_type + | nullable_type BANG + ; + +nullable_type : + name + | LBRACKET type RBRACKET + ; + +type_system_definition : + schema_definition + | type_definition + | directive_definition + ; + +schema_definition : + SCHEMA directives_list_opt operation_type_definition_list_opt + ; + +operation_type_definition_list_opt : + /*empty*/ + | LCURLY operation_type_definition_list RCURLY + ; + +operation_type_definition_list : + operation_type_definition + | operation_type_definition_list operation_type_definition + ; + +operation_type_definition : + operation_type COLON name + ; + +type_definition : + scalar_type_definition + | object_type_definition + | interface_type_definition + | union_type_definition + | enum_type_definition + | input_object_type_definition + ; + +description : + STRING + ; + +description_opt : + /*empty*/ + | description + ; + +scalar_type_definition : + description_opt SCALAR name directives_list_opt + ; + +object_type_definition : + description_opt TYPE_LITERAL name implements_opt directives_list_opt field_definition_list_opt + ; + +implements_opt : + /*empty*/ + | IMPLEMENTS AMP interfaces_list + | IMPLEMENTS interfaces_list + | IMPLEMENTS legacy_interfaces_list + ; + +interfaces_list : + name + | interfaces_list AMP name + ; + +legacy_interfaces_list : + name + | legacy_interfaces_list name + ; + +input_value_definition : + description_opt name COLON type default_value_opt directives_list_opt + ; + +input_value_definition_list : + input_value_definition + | input_value_definition_list input_value_definition + ; + +arguments_definitions_opt : + /*empty*/ + | LPAREN input_value_definition_list RPAREN + ; + +field_definition : + description_opt name arguments_definitions_opt COLON type directives_list_opt + ; + +field_definition_list_opt : + /*empty*/ + | LCURLY field_definition_list RCURLY + ; + +field_definition_list : + /*empty*/ + | field_definition + | field_definition_list field_definition + ; + +interface_type_definition : + description_opt INTERFACE name implements_opt directives_list_opt field_definition_list_opt + ; + +union_members : + name + | union_members PIPE name + ; + +union_type_definition : + description_opt UNION name directives_list_opt EQUALS union_members + ; + +enum_type_definition : + description_opt ENUM name directives_list_opt LCURLY enum_value_definitions RCURLY + ; + +enum_value_definition : + description_opt enum_name directives_list_opt + ; + +enum_value_definitions : + enum_value_definition + | enum_value_definitions enum_value_definition + ; + +input_object_type_definition : + description_opt INPUT name directives_list_opt LCURLY input_value_definition_list RCURLY + ; + +directive_definition : + description_opt DIRECTIVE DIR_SIGN name arguments_definitions_opt directive_repeatable_opt ON directive_locations + ; + +directive_repeatable_opt : + /*empty*/ + | REPEATABLE + ; + +directive_locations : + name + | directive_locations PIPE name + ; + +type_system_extension : + schema_extension + | type_extension + ; + +schema_extension : + EXTEND SCHEMA directives_list_opt LCURLY operation_type_definition_list RCURLY + | EXTEND SCHEMA directives_list + ; + +type_extension : + scalar_type_extension + | object_type_extension + | interface_type_extension + | union_type_extension + | enum_type_extension + | input_object_type_extension + ; + +scalar_type_extension : + EXTEND SCALAR name directives_list + ; + +object_type_extension : + EXTEND TYPE_LITERAL name implements_opt directives_list_opt field_definition_list_opt + ; + +interface_type_extension : + EXTEND INTERFACE name implements_opt directives_list_opt field_definition_list_opt + ; + +union_type_extension : + EXTEND UNION name directives_list_opt EQUALS union_members + | EXTEND UNION name directives_list + ; + +enum_type_extension : + EXTEND ENUM name directives_list_opt LCURLY enum_value_definitions RCURLY + | EXTEND ENUM name directives_list + ; + +input_object_type_extension : + EXTEND INPUT name directives_list_opt LCURLY input_value_definition_list RCURLY + | EXTEND INPUT name directives_list + ; + +//Lexer + +LCURLY : '{' ; +RCURLY : '}' ; +QUERY : 'QUERY' ; +MUTATION : 'MUTATION' ; +SUBSCRIPTION : 'SUBSCRIPTION' ; +LPAREN : '(' ; +RPAREN : ')' ; +VAR_SIGN : 'VAR_SIGN' ; +COLON : ':' ; +EQUALS : 'EQUALS' ; +FLOAT : 'FLOAT' ; +INT : 'INT' ; +STRING : 'STRING' ; +TRUE_LITERAL : 'TRUE' ; +FALSE_LITERAL : 'FALSE' ; +NULL_LITERAL : 'NULL' ; +LBRACKET : '[' ; +RBRACKET : ']' ; +IDENTIFIER : 'IDENTIFIER' ; +FRAGMENT : 'FRAGMENT' ; +REPEATABLE : 'REPEATABLE' ; +ON : 'ON' ; +DIR_SIGN : 'DIR_SIGN' ; +SCHEMA : 'SCHEMA' ; +SCALAR : 'SCALAR' ; +TYPE_LITERAL : 'TYPE_LITERAL' ; +IMPLEMENTS : 'IMPLEMENTS' ; +INTERFACE : 'INTERFACE' ; +UNION : 'UNION' ; +ENUM : 'ENUM' ; +INPUT : 'INPUT' ; +DIRECTIVE : 'DIRECTIVE' ; +ELLIPSIS : '...' ; +BANG : 'BANG' ; +AMP : '&' ; +PIPE : '|' ; +EXTEND : 'EXTEND' ; + +} diff --git a/playground/gringo-ng.g b/playground/gringo-ng.g new file mode 100644 index 0000000..ada134b --- /dev/null +++ b/playground/gringo-ng.g @@ -0,0 +1,745 @@ +gringoNonGroundedInput { + +%whitespace "[ \t\r\n]*"; +%whitespace "%[^\n]*"; + +/*Tokens*/ +//%token END +//%token YYerror +//%token YYUNDEF +//%token ADD +//%token AND +//%token EQ +//%token AT +//%token BASE +//%token BNOT +//%token COLON +//%token COMMA +//%token CONST +//%token COUNT +//%token CUMULATIVE +//%token DOT +//%token DOTS +//%token EXTERNAL +//%token DEFINED +//%token FALSE +//%token FORGET +//%token GEQ +//%token GT +//%token IF +//%token INCLUDE +//%token INFIMUM +//%token LBRACE +//%token LBRACK +//%token LEQ +//%token LPAREN +//%token LT +//%token MAX +//%token MAXIMIZE +//%token MIN +//%token MINIMIZE +//%token MOD +//%token MUL +//%token NEQ +//%token POW +//%token QUESTION +//%token RBRACE +//%token RBRACK +//%token RPAREN +//%token SEM +//%token SHOW +//%token EDGE +//%token PROJECT +//%token HEURISTIC +//%token SHOWSIG +//%token SLASH +//%token SUB +//%token SUM +//%token SUMP +//%token SUPREMUM +//%token TRUE +//%token BLOCK +//%token UBNOT +//%token UMINUS +//%token VBAR +//%token VOLATILE +//%token WIF +//%token XOR +//%token PARSE_LP +//%token PARSE_DEF +//%token ANY +//%token UNARY +//%token BINARY +//%token LEFT +//%token RIGHT +//%token HEAD +//%token BODY +//%token DIRECTIVE +//%token THEORY +//%token SYNC +//%token NUMBER +//%token ANONYMOUS +//%token IDENTIFIER +//%token SCRIPT +//%token CODE +//%token STRING +//%token VARIABLE +//%token THEORY_OP +//%token NOT +//%token DEFAULT +//%token OVERRIDE + +%left /*1*/ DOTS ; +%left /*2*/ XOR ; +%left /*3*/ QUESTION ; +%left /*4*/ AND ; +%left /*5*/ ADD SUB ; +%left /*6*/ MOD MUL SLASH ; +%right /*7*/ POW ; +%left /*8*/ UBNOT UMINUS ; + +//%start start + +//%% + +start : + /*END + |*/ PARSE_LP program + | PARSE_DEF define SYNC + ; + +program : + program statement + | /*empty*/ + ; + +statement : + SYNC + | DOT + | error disable_theory_lexing DOT + | error disable_theory_lexing SYNC + ; + +identifier : + IDENTIFIER + | DEFAULT + | OVERRIDE + ; + +constterm : + constterm XOR /*2L*/ constterm + | constterm QUESTION /*3L*/ constterm + | constterm AND /*4L*/ constterm + | constterm ADD /*5L*/ constterm + | constterm SUB /*5L*/ constterm + | constterm MUL /*6L*/ constterm + | constterm SLASH /*6L*/ constterm + | constterm MOD /*6L*/ constterm + | constterm POW /*7R*/ constterm + | SUB /*5L*/ constterm %prec UMINUS /*8L*/ + | BNOT constterm %prec UBNOT /*8L*/ + | LPAREN RPAREN + | LPAREN COMMA RPAREN + | LPAREN consttermvec RPAREN + | LPAREN consttermvec COMMA RPAREN + | identifier LPAREN constargvec RPAREN + | AT identifier LPAREN constargvec RPAREN + | VBAR constterm VBAR + | identifier + | AT identifier + | NUMBER + | STRING + | INFIMUM + | SUPREMUM + ; + +consttermvec : + constterm + | consttermvec COMMA constterm + ; + +constargvec : + consttermvec + | /*empty*/ + ; + +term : + term DOTS /*1L*/ term + | term XOR /*2L*/ term + | term QUESTION /*3L*/ term + | term AND /*4L*/ term + | term ADD /*5L*/ term + | term SUB /*5L*/ term + | term MUL /*6L*/ term + | term SLASH /*6L*/ term + | term MOD /*6L*/ term + | term POW /*7R*/ term + | SUB /*5L*/ term %prec UMINUS /*8L*/ + | BNOT term %prec UBNOT /*8L*/ + | LPAREN tuplevec RPAREN + | identifier LPAREN argvec RPAREN + | AT identifier LPAREN argvec RPAREN + | VBAR unaryargvec VBAR + | identifier + | AT identifier + | NUMBER + | STRING + | INFIMUM + | SUPREMUM + | VARIABLE + | ANONYMOUS + ; + +unaryargvec : + term + | unaryargvec SEM term + ; + +ntermvec : + term + | ntermvec COMMA term + ; + +termvec : + ntermvec + | /*empty*/ + ; + +tuple : + ntermvec COMMA + | ntermvec + | COMMA + | /*empty*/ + ; + +tuplevec_sem : + tuple SEM + | tuplevec_sem tuple SEM + ; + +tuplevec : + tuple + | tuplevec_sem tuple + ; + +argvec : + termvec + | argvec SEM termvec + ; + +binaryargvec : + term COMMA term + | binaryargvec SEM term COMMA term + ; + +cmp : + GT + | LT + | GEQ + | LEQ + | EQ + | NEQ + ; + +atom : + identifier + | identifier LPAREN argvec RPAREN + | SUB /*5L*/ identifier + | SUB /*5L*/ identifier LPAREN argvec RPAREN + ; + +rellitvec : + cmp term + | rellitvec cmp term + ; + +literal : + TRUE + | NOT TRUE + | NOT NOT TRUE + | FALSE + | NOT FALSE + | NOT NOT FALSE + | atom + | NOT atom + | NOT NOT atom + | term rellitvec + | NOT term rellitvec + | NOT NOT term rellitvec + ; + +nlitvec : + literal + | nlitvec COMMA literal + ; + +litvec : + nlitvec + | /*empty*/ + ; + +optcondition : + COLON litvec + | /*empty*/ + ; + +aggregatefunction : + SUM + | SUMP + | MIN + | MAX + | COUNT + ; + +bodyaggrelem : + COLON litvec + | ntermvec optcondition + ; + +bodyaggrelemvec : + bodyaggrelem + | bodyaggrelemvec SEM bodyaggrelem + ; + +altbodyaggrelem : + literal optcondition + ; + +altbodyaggrelemvec : + altbodyaggrelem + | altbodyaggrelemvec SEM altbodyaggrelem + ; + +bodyaggregate : + LBRACE RBRACE + | LBRACE altbodyaggrelemvec RBRACE + | aggregatefunction LBRACE RBRACE + | aggregatefunction LBRACE bodyaggrelemvec RBRACE + ; + +upper : + term + | cmp term + | /*empty*/ + ; + +lubodyaggregate : + term bodyaggregate upper + | term cmp bodyaggregate upper + | bodyaggregate upper + | theory_atom + ; + +headaggrelemvec : + headaggrelemvec SEM termvec COLON literal optcondition + | termvec COLON literal optcondition + ; + +altheadaggrelemvec : + literal optcondition + | altheadaggrelemvec SEM literal optcondition + ; + +headaggregate : + aggregatefunction LBRACE RBRACE + | aggregatefunction LBRACE headaggrelemvec RBRACE + | LBRACE RBRACE + | LBRACE altheadaggrelemvec RBRACE + ; + +luheadaggregate : + term headaggregate upper + | term cmp headaggregate upper + | headaggregate upper + | theory_atom + ; + +conjunction : + literal COLON litvec + ; + +dsym : + SEM + | VBAR + ; + +disjunctionsep : + disjunctionsep literal COMMA + | disjunctionsep literal dsym + | disjunctionsep literal COLON SEM + | disjunctionsep literal COLON nlitvec dsym + | literal COMMA + | literal dsym + | literal COLON nlitvec dsym + | literal COLON SEM + ; + +disjunction : + disjunctionsep literal optcondition + | literal COLON litvec + ; + +bodycomma : + bodycomma literal COMMA + | bodycomma literal SEM + | bodycomma lubodyaggregate COMMA + | bodycomma lubodyaggregate SEM + | bodycomma NOT lubodyaggregate COMMA + | bodycomma NOT lubodyaggregate SEM + | bodycomma NOT NOT lubodyaggregate COMMA + | bodycomma NOT NOT lubodyaggregate SEM + | bodycomma conjunction SEM + | /*empty*/ + ; + +bodydot : + bodycomma literal DOT + | bodycomma lubodyaggregate DOT + | bodycomma NOT lubodyaggregate DOT + | bodycomma NOT NOT lubodyaggregate DOT + | bodycomma conjunction DOT + ; + +bodyconddot : + DOT + | COLON DOT + | COLON bodydot + ; + +head : + literal + | disjunction + | luheadaggregate + ; + +statement : + head DOT + | head IF DOT + | head IF bodydot + | IF bodydot + | IF DOT + ; + +optimizetuple : + COMMA ntermvec + | /*empty*/ + ; + +optimizeweight : + term AT term + | term + ; + +optimizelitvec : + literal + | optimizelitvec COMMA literal + ; + +optimizecond : + COLON optimizelitvec + | COLON + | /*empty*/ + ; + +statement : + WIF bodydot LBRACK optimizeweight optimizetuple RBRACK + | WIF DOT LBRACK optimizeweight optimizetuple RBRACK + ; + +maxelemlist : + optimizeweight optimizetuple optimizecond + | maxelemlist SEM optimizeweight optimizetuple optimizecond + ; + +minelemlist : + optimizeweight optimizetuple optimizecond + | minelemlist SEM optimizeweight optimizetuple optimizecond + ; + +statement : + MINIMIZE LBRACE RBRACE DOT + | MAXIMIZE LBRACE RBRACE DOT + | MINIMIZE LBRACE minelemlist RBRACE DOT + | MAXIMIZE LBRACE maxelemlist RBRACE DOT + | SHOWSIG identifier SLASH /*6L*/ NUMBER DOT + | SHOWSIG SUB /*5L*/ identifier SLASH /*6L*/ NUMBER DOT + | SHOW DOT + | SHOW term COLON bodydot + | SHOW term DOT + | DEFINED identifier SLASH /*6L*/ NUMBER DOT + | DEFINED SUB /*5L*/ identifier SLASH /*6L*/ NUMBER DOT + | EDGE LPAREN binaryargvec RPAREN bodyconddot + | HEURISTIC atom bodyconddot LBRACK term AT term COMMA term RBRACK + | HEURISTIC atom bodyconddot LBRACK term COMMA term RBRACK + | PROJECT identifier SLASH /*6L*/ NUMBER DOT + | PROJECT SUB /*5L*/ identifier SLASH /*6L*/ NUMBER DOT + | PROJECT atom bodyconddot + ; + +define : + identifier EQ constterm + ; + +statement : + CONST identifier EQ constterm DOT + | CONST identifier EQ constterm DOT LBRACK DEFAULT RBRACK + | CONST identifier EQ constterm DOT LBRACK OVERRIDE RBRACK + | SCRIPT LPAREN IDENTIFIER RPAREN CODE DOT + | INCLUDE STRING DOT + | INCLUDE LT identifier GT DOT + ; + +nidlist : + nidlist COMMA identifier + | identifier + ; + +idlist : + /*empty*/ + | nidlist + ; + +statement : + BLOCK identifier LPAREN idlist RPAREN DOT + | BLOCK identifier DOT + | EXTERNAL atom COLON bodydot + | EXTERNAL atom COLON DOT + | EXTERNAL atom DOT + | EXTERNAL atom COLON bodydot LBRACK term RBRACK + | EXTERNAL atom COLON DOT LBRACK term RBRACK + | EXTERNAL atom DOT LBRACK term RBRACK + ; + +theory_op : + THEORY_OP + | NOT + ; + +theory_op_list : + theory_op_list theory_op + | theory_op + ; + +theory_term : + LBRACE theory_opterm_list RBRACE + | LBRACK theory_opterm_list RBRACK + | LPAREN RPAREN + | LPAREN theory_opterm RPAREN + | LPAREN theory_opterm COMMA RPAREN + | LPAREN theory_opterm COMMA theory_opterm_nlist RPAREN + | identifier LPAREN theory_opterm_list RPAREN + | identifier + | NUMBER + | STRING + | INFIMUM + | SUPREMUM + | VARIABLE + ; + +theory_opterm : + theory_opterm theory_op_list theory_term + | theory_op_list theory_term + | theory_term + ; + +theory_opterm_nlist : + theory_opterm_nlist COMMA theory_opterm + | theory_opterm + ; + +theory_opterm_list : + theory_opterm_nlist + | /*empty*/ + ; + +theory_atom_element : + theory_opterm_nlist disable_theory_lexing optcondition + | disable_theory_lexing COLON litvec + ; + +theory_atom_element_nlist : + theory_atom_element_nlist enable_theory_lexing SEM theory_atom_element + | theory_atom_element + ; + +theory_atom_element_list : + theory_atom_element_nlist + | /*empty*/ + ; + +theory_atom_name : + identifier + | identifier LPAREN argvec RPAREN + ; + +theory_atom : + AND /*4L*/ theory_atom_name + | AND /*4L*/ theory_atom_name enable_theory_lexing LBRACE theory_atom_element_list enable_theory_lexing RBRACE disable_theory_lexing + | AND /*4L*/ theory_atom_name enable_theory_lexing LBRACE theory_atom_element_list enable_theory_lexing RBRACE theory_op theory_opterm disable_theory_lexing + ; + +theory_operator_nlist : + theory_op + | theory_operator_nlist COMMA theory_op + ; + +theory_operator_list : + theory_operator_nlist + | /*empty*/ + ; + +theory_operator_definition : + theory_op enable_theory_definition_lexing COLON NUMBER COMMA UNARY + | theory_op enable_theory_definition_lexing COLON NUMBER COMMA BINARY COMMA LEFT + | theory_op enable_theory_definition_lexing COLON NUMBER COMMA BINARY COMMA RIGHT + ; + +theory_operator_definition_nlist : + theory_operator_definition + | theory_operator_definition_nlist enable_theory_lexing SEM theory_operator_definition + ; + +theory_operator_definiton_list : + theory_operator_definition_nlist + | /*empty*/ + ; + +theory_definition_identifier : + identifier + | LEFT + | RIGHT + | UNARY + | BINARY + | HEAD + | BODY + | ANY + | DIRECTIVE + ; + +theory_term_definition : + theory_definition_identifier enable_theory_lexing LBRACE theory_operator_definiton_list enable_theory_definition_lexing RBRACE + ; + +theory_atom_type : + HEAD + | BODY + | ANY + | DIRECTIVE + ; + +theory_atom_definition : + AND /*4L*/ theory_definition_identifier SLASH /*6L*/ NUMBER COLON theory_definition_identifier COMMA enable_theory_lexing LBRACE theory_operator_list enable_theory_definition_lexing RBRACE COMMA theory_definition_identifier COMMA theory_atom_type + | AND /*4L*/ theory_definition_identifier SLASH /*6L*/ NUMBER COLON theory_definition_identifier COMMA theory_atom_type + ; + +theory_definition_nlist : + theory_definition_list SEM theory_atom_definition + | theory_definition_list SEM theory_term_definition + | theory_atom_definition + | theory_term_definition + ; + +theory_definition_list : + theory_definition_nlist + | /*empty*/ + ; + +statement : + THEORY identifier enable_theory_definition_lexing LBRACE theory_definition_list RBRACE disable_theory_lexing DOT + ; + +enable_theory_lexing : + /*empty*/ + ; + +enable_theory_definition_lexing : + /*empty*/ + ; + +disable_theory_lexing : + /*empty*/ + ; +//Lexer + +ADD : '+' ; +AND : '&' ; +EQ : '=' ; +AT : '@' ; +//BASE : '#base' ; +BNOT : '~' ; +COLON : ':' ; +COMMA : ',' ; +CONST : '#const' ; +COUNT : '#count' ; +//CUMULATIVE : '#cumulative' ; +DOT : '.' ; +DOTS : '..' ; +EXTERNAL : '#external' ; +DEFINED : '#defined' ; +FALSE : '#false' ; +//FORGET : '#forget' ; +GEQ : '>=' ; +GT : '>' ; +IF : ':-' ; +INCLUDE : '#include' ; +INFIMUM : '#inf' ; +LBRACE : '{' ; +LBRACK : '[' ; +LEQ : '<=' ; +LPAREN : '(' ; +LT : '<' ; +MAX : '#max' ; +MAXIMIZE : '#maximize' ; +MIN : '#min' ; +MINIMIZE : '#minimize' ; +MOD : '\\' ; +MUL : '*' ; +NEQ : '!=' ; +POW : '**' ; +QUESTION : '?' ; +RBRACE : '}' ; +RBRACK : ']' ; +RPAREN : ')' ; +SEM : ';' ; +SHOW : '#show' ; +EDGE : '#edge' ; +PROJECT : '#project' ; +HEURISTIC : '#heuristic' ; +SHOWSIG : '#showsig' ; +SLASH : '/' ; +SUB : '-' ; +SUM : '#sum' ; +SUMP : '#sum+' ; +SUPREMUM : '#sup' ; +TRUE : '#true' ; +BLOCK : '#program' ; +VBAR : '|' ; +//VOLATILE : '#volatile' ; +WIF : ':~' ; +XOR : '^' ; +PARSE_LP : '#program' ; +PARSE_DEF : '#define' ; +ANY : 'any' ; +UNARY : 'unary' ; +BINARY : 'binary' ; +LEFT : 'left' ; +RIGHT : 'right' ; +HEAD : 'head' ; +BODY : 'body' ; +DIRECTIVE : 'directive' ; +THEORY : '#theory' ; + +SYNC : 'EOF' ; +IDENTIFIER : "[_']*[a-z]['A-Za-z0-9_]*" ; +DEFAULT : 'default' ; +OVERRIDE : 'override' ; +NUMBER : "(0|([1-9][0-9]*))|(0x([0-9A-Fa-f]+))|(0o([1-7]+))|(0b([0-1]+))" ; +STRING : "\"[^\"\n]*\"|'[^'\n]*'" ; +VARIABLE : "[_']*[A-Z]['A-Za-z0-9_]*" ; +ANONYMOUS : '_' ; +NOT : 'not' ; +SCRIPT : '#script' ; +CODE : 'CODE' ; +THEORY_OP : "[/!<=>+\-*\\?&@|:;~\^\.]+" ; + +} \ No newline at end of file diff --git a/playground/html-parser.g b/playground/html-parser.g new file mode 100644 index 0000000..1256b3e --- /dev/null +++ b/playground/html-parser.g @@ -0,0 +1,1149 @@ +//From: https://github.com/eyoung-father/eyoung/blob/EYOUNG_R1/libdecoder/html/decode/html.y +html { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token SYM_LEX_CONTINUE +//%token SYM_TEXT +//%token SYM_TAG_START_FLAG +//%token SYM_TAG_START_FLAG2 +//%token SYM_TAG_END_FLAG +//%token SYM_TAG_END_FLAG2 +//%token SYM_EQUAL +//%token SYM_TAG_A +//%token SYM_TAG_ABBR +//%token SYM_TAG_ACRONYM +//%token SYM_TAG_ADDRESS +//%token SYM_TAG_APPLET +//%token SYM_TAG_AREA +//%token SYM_TAG_ARTICLE +//%token SYM_TAG_ASIDE +//%token SYM_TAG_AUDIO +//%token SYM_TAG_B +//%token SYM_TAG_BASE +//%token SYM_TAG_BASEFONT +//%token SYM_TAG_BDI +//%token SYM_TAG_BDO +//%token SYM_TAG_BIG +//%token SYM_TAG_BLOCKQUOTE +//%token SYM_TAG_BODY +//%token SYM_TAG_BR +//%token SYM_TAG_BUTTON +//%token SYM_TAG_CANVAS +//%token SYM_TAG_CAPTION +//%token SYM_TAG_CENTER +//%token SYM_TAG_CITE +//%token SYM_TAG_CODE +//%token SYM_TAG_COL +//%token SYM_TAG_COLGROUP +//%token SYM_TAG_COMMAND +//%token SYM_TAG_DATALIST +//%token SYM_TAG_DD +//%token SYM_TAG_DEL +//%token SYM_TAG_DETAILS +//%token SYM_TAG_DFN +//%token SYM_TAG_DIR +//%token SYM_TAG_DIV +//%token SYM_TAG_DL +//%token SYM_TAG_DT +//%token SYM_TAG_EM +//%token SYM_TAG_EMBED +//%token SYM_TAG_FIELDSET +//%token SYM_TAG_FIGCAPTION +//%token SYM_TAG_FIGURE +//%token SYM_TAG_FONT +//%token SYM_TAG_FOOTER +//%token SYM_TAG_FORM +//%token SYM_TAG_FRAME +//%token SYM_TAG_FRAMESET +//%token SYM_TAG_H1 +//%token SYM_TAG_H2 +//%token SYM_TAG_H3 +//%token SYM_TAG_H4 +//%token SYM_TAG_H5 +//%token SYM_TAG_H6 +//%token SYM_TAG_HEAD +//%token SYM_TAG_HEADER +//%token SYM_TAG_HGROUP +//%token SYM_TAG_HR +//%token SYM_TAG_HTML +//%token SYM_TAG_I +//%token SYM_TAG_IFRAME +//%token SYM_TAG_IMG +//%token SYM_TAG_INPUT +//%token SYM_TAG_INS +//%token SYM_TAG_KEYGEN +//%token SYM_TAG_KBD +//%token SYM_TAG_LABEL +//%token SYM_TAG_LEGEND +//%token SYM_TAG_LI +//%token SYM_TAG_LINK +//%token SYM_TAG_LAYER +//%token SYM_TAG_MAP +//%token SYM_TAG_MARK +//%token SYM_TAG_MENU +//%token SYM_TAG_META +//%token SYM_TAG_METER +//%token SYM_TAG_NAV +//%token SYM_TAG_NOFRAMES +//%token SYM_TAG_NOSCRIPT +//%token SYM_TAG_OBJECT +//%token SYM_TAG_OL +//%token SYM_TAG_OPTGROUP +//%token SYM_TAG_OPTION +//%token SYM_TAG_OUTPUT +//%token SYM_TAG_P +//%token SYM_TAG_PARAM +//%token SYM_TAG_PRE +//%token SYM_TAG_PROGRESS +//%token SYM_TAG_Q +//%token SYM_TAG_RP +//%token SYM_TAG_RT +//%token SYM_TAG_RUBY +//%token SYM_TAG_S +//%token SYM_TAG_U +//%token SYM_TAG_SAMP +//%token SYM_TAG_SCRIPT +//%token SYM_TAG_SECTION +//%token SYM_TAG_SELECT +//%token SYM_TAG_SMALL +//%token SYM_TAG_SOURCE +//%token SYM_TAG_SPAN +//%token SYM_TAG_STRIKE +//%token SYM_TAG_STRONG +//%token SYM_TAG_STYLE +//%token SYM_TAG_SUB +//%token SYM_TAG_SUMMARY +//%token SYM_TAG_SUP +//%token SYM_TAG_TABLE +//%token SYM_TAG_TBODY +//%token SYM_TAG_TD +//%token SYM_TAG_TH +//%token SYM_TAG_TR +//%token SYM_TAG_TT +//%token SYM_TAG_TEXTAREA +//%token SYM_TAG_TFOOT +//%token SYM_TAG_THEAD +//%token SYM_TAG_TIME +//%token SYM_TAG_TITLE +//%token SYM_TAG_UL +//%token SYM_TAG_VAR +//%token SYM_TAG_VIDEO +//%token SYM_TAG_XML +//%token SYM_TAG_BGSOUND +//%token SYM_TAG_MARQUEE +//%token SYM_TAG_USERDATA +//%token SYM_EVT_ONAFTERPRINT +//%token SYM_EVT_ONBEFOREPRINT +//%token SYM_EVT_ONBEFOREONLOAD +//%token SYM_EVT_ONBLUR +//%token SYM_EVT_ONFOCUS +//%token SYM_EVT_ONHASCHANGE +//%token SYM_EVT_ONLOAD +//%token SYM_EVT_ONMESSAGE +//%token SYM_EVT_ONOFFLINE +//%token SYM_EVT_ONONLINE +//%token SYM_EVT_ONPAGEHIDE +//%token SYM_EVT_ONPAGESHOW +//%token SYM_EVT_ONPOPSTATE +//%token SYM_EVT_ONREDO +//%token SYM_EVT_ONRESIZE +//%token SYM_EVT_ONSTORAGE +//%token SYM_EVT_ONUNDO +//%token SYM_EVT_ONUNLOAD +//%token SYM_EVT_ONCHANGE +//%token SYM_EVT_ONCONTEXTMENU +//%token SYM_EVT_ONFORMCHANGE +//%token SYM_EVT_ONFORMINPUT +//%token SYM_EVT_ONINPUT +//%token SYM_EVT_ONINVALID +//%token SYM_EVT_ONRESET +//%token SYM_EVT_ONSELECT +//%token SYM_EVT_ONSUBMIT +//%token SYM_EVT_ONKEYDOWN +//%token SYM_EVT_ONKEYPRESS +//%token SYM_EVT_ONKEYUP +//%token SYM_EVT_ONCLICK +//%token SYM_EVT_ONDBLCLICK +//%token SYM_EVT_ONDRAG +//%token SYM_EVT_ONDRAGEND +//%token SYM_EVT_ONDRAGENTER +//%token SYM_EVT_ONDRAGLEAVE +//%token SYM_EVT_ONDRAGOVER +//%token SYM_EVT_ONDRAGSTART +//%token SYM_EVT_ONDROP +//%token SYM_EVT_ONMOUSEDOWN +//%token SYM_EVT_ONMOUSEMOVE +//%token SYM_EVT_ONMOUSEOUT +//%token SYM_EVT_ONMOUSEOVER +//%token SYM_EVT_ONMOUSEUP +//%token SYM_EVT_ONMOUSEWHEEL +//%token SYM_EVT_ONSCROLL +//%token SYM_EVT_ONABORT +//%token SYM_EVT_ONCANPLAY +//%token SYM_EVT_ONCANPLAYTHROUGH +//%token SYM_EVT_ONDURATIONCHANGE +//%token SYM_EVT_ONEMPTIED +//%token SYM_EVT_ONENDED +//%token SYM_EVT_ONERROR +//%token SYM_EVT_ONLOADEDDATA +//%token SYM_EVT_ONLOADEDMETADATA +//%token SYM_EVT_ONLOADSTART +//%token SYM_EVT_ONPAUSE +//%token SYM_EVT_ONPLAY +//%token SYM_EVT_ONPLAYING +//%token SYM_EVT_ONPROGRESS +//%token SYM_EVT_ONRATECHANGE +//%token SYM_EVT_ONREADYSTATECHANGE +//%token SYM_EVT_ONSEEKED +//%token SYM_EVT_ONSEEKING +//%token SYM_EVT_ONSTALLED +//%token SYM_EVT_ONSUSPEND +//%token SYM_EVT_ONTIMEUPDATE +//%token SYM_EVT_ONVOLUMECHANGE +//%token SYM_EVT_ONWAITING +//%token SYM_EVT_ONSTART +//%token SYM_PROT_ACCESSKEY +//%token SYM_PROT_CLASS +//%token SYM_PROT_CONTENTEDITABLE +//%token SYM_PROT_CONTEXTMENU +//%token SYM_PROT_DIR +//%token SYM_PROT_DRAGGABLE +//%token SYM_PROT_HIDDEN +//%token SYM_PROT_ID +//%token SYM_PROT_ITEM +//%token SYM_PROT_ITEMPROP +//%token SYM_PROT_LANG +//%token SYM_PROT_SPELLCHECK +//%token SYM_PROT_STYLE +//%token SYM_PROT_SUBJECT +//%token SYM_PROT_TABINDEX +//%token SYM_PROT_TITLE +//%token SYM_PROT_USERDATA +//%token SYM_PROT_TEMPLATE +//%token SYM_PROT_REGISTRATIONMARK +//%token SYM_PROT_IRRELEVANT +//%token SYM_PROT_OPEN +//%token SYM_PROT_DATA +//%token SYM_PROT_NOWRAP +//%token SYM_PROT_DATETIME +//%token SYM_PROT_ROWS +//%token SYM_PROT_LIST +//%token SYM_PROT_FORMTARGETNEW +//%token SYM_PROT_AUTOFOCUSNEW +//%token SYM_PROT_ICON +//%token SYM_PROT_MAXLENGTH +//%token SYM_PROT_WIDTH +//%token SYM_PROT_ARCHIVE +//%token SYM_PROT_HREF +//%token SYM_PROT_PRELOAD +//%token SYM_PROT_MULTIPLE +//%token SYM_PROT_HREFLANG +//%token SYM_PROT_CELLSPACING +//%token SYM_PROT_COLSPAN +//%token SYM_PROT_ACTION +//%token SYM_PROT_CLASSID +//%token SYM_PROT_PATTERN +//%token SYM_PROT_COLOR +//%token SYM_PROT_HIGH +//%token SYM_PROT_PING +//%token SYM_PROT_ISMAP +//%token SYM_PROT_HTTPEQUIV +//%token SYM_PROT_HSPACE +//%token SYM_PROT_COMPACT +//%token SYM_PROT_LANGUAGE +//%token SYM_PROT_REQUIRED +//%token SYM_PROT_SPAN +//%token SYM_PROT_FORMACTIONNEW +//%token SYM_PROT_RULES +//%token SYM_PROT_AXIS +//%token SYM_PROT_METHOD +//%token SYM_PROT_BGCOLOR +//%token SYM_PROT_SHAPE +//%token SYM_PROT_USEMAP +//%token SYM_PROT_FOR +//%token SYM_PROT_SCOPED +//%token SYM_PROT_FORMACTION +//%token SYM_PROT_FORMENCTYPE +//%token SYM_PROT_FORMMETHOD +//%token SYM_PROT_FORMTARGET +//%token SYM_PROT_FORMNOVALIDATE +//%token SYM_PROT_FORMNOVALIDATENEW +//%token SYM_PROT_CONTENT +//%token SYM_PROT_INPUTMODE +//%token SYM_PROT_CITE +//%token SYM_PROT_VSPACE +//%token SYM_PROT_XMLNS +//%token SYM_PROT_CODETYPE +//%token SYM_PROT_TARGET +//%token SYM_PROT_VALUE +//%token SYM_PROT_AUTOFOCUS +//%token SYM_PROT_MEDIA +//%token SYM_PROT_COORDS +//%token SYM_PROT_PROFILE +//%token SYM_PROT_HEADERS +//%token SYM_PROT_VALUETYPE +//%token SYM_PROT_REPLACE +//%token SYM_PROT_MARGINHEIGHT +//%token SYM_PROT_BORDER +//%token SYM_PROT_FRAMEBORDER +//%token SYM_PROT_ASYNC +//%token SYM_PROT_FACE +//%token SYM_PROT_CELLPADDING +//%token SYM_PROT_STANDBY +//%token SYM_PROT_ALT +//%token SYM_PROT_ACCEPTCHARSET +//%token SYM_PROT_FORMMETHODNEW +//%token SYM_PROT_AUTOPLAY +//%token SYM_PROT_REV +//%token SYM_PROT_LOOP +//%token SYM_PROT_CODE +//%token SYM_PROT_SRC +//%token SYM_PROT_CHECKED +//%token SYM_PROT_SCROLLING +//%token SYM_PROT_SCOPE +//%token SYM_PROT_DEFER +//%token SYM_PROT_XMLSPACE +//%token SYM_PROT_CHALLENGE +//%token SYM_PROT_SCHEME +//%token SYM_PROT_DECLARE +//%token SYM_PROT_CHAR +//%token SYM_PROT_READONLY +//%token SYM_PROT_XMLLANG +//%token SYM_PROT_MAX +//%token SYM_PROT_ROWSPAN +//%token SYM_PROT_KEYTYPE +//%token SYM_PROT_AUTOCOMPLETE +//%token SYM_PROT_SELECTED +//%token SYM_PROT_CODEBASE +//%token SYM_PROT_STEP +//%token SYM_PROT_NOHREF +//%token SYM_PROT_CHARSET +//%token SYM_PROT_FORMNEW +//%token SYM_PROT_FORMENCTYPENEW +//%token SYM_PROT_REL +//%token SYM_PROT_MIN +//%token SYM_PROT_NAME +//%token SYM_PROT_TYPE +//%token SYM_PROT_NOSHADE +//%token SYM_PROT_MANIFEST +//%token SYM_PROT_ALIGN +//%token SYM_PROT_HEIGHT +//%token SYM_PROT_ACCEPT +//%token SYM_PROT_ENCTYPE +//%token SYM_PROT_DISABLED +//%token SYM_PROT_CONTROLS +//%token SYM_PROT_LONGDESC +//%token SYM_PROT_MARGINWIDTH +//%token SYM_PROT_NORESIZE +//%token SYM_PROT_COLS +//%token SYM_PROT_SIZE +//%token SYM_PROT_RADIOGROUP +//%token SYM_PROT_VALIGN +//%token SYM_PROT_OBJECT +//%token SYM_PROT_CHAROFF +//%token SYM_PROT_LOW +//%token SYM_PROT_START +//%token SYM_PROT_SUMMARY +//%token SYM_PROT_OPTIMUM +//%token SYM_PROT_ABBR +//%token SYM_PROT_FORM +//%token SYM_PROT_LABEL +//%token SYM_PROT_FRAME +//%token SYM_PROT_ALLOWSCRIPTACCESS +//%token SYM_PROT_PLACEHOLDER +//%token SYM_PROT_AUTOSUBMIT +//%token SYM_PROT_LOWSRC +//%token SYM_PROT_BACKGROUND + + +//%start html_init + +//%% + +html_init : + /*YYEOF + |*/ html_doc + ; + +html_doc : + empty + | html_doc html_tag + | html_doc html_doc_text + ; + +html_doc_text : + SYM_TEXT + ; + +empty : + /*empty*/ + ; + +html_tag : + html_tag_begin_ html_doc html_tag_finish_ + ; + +html_tag_begin_ : + SYM_TAG_START_FLAG html_tag_name_ html_tag_prot_event_list_ html_tag_begin_end_ + ; + +html_tag_begin_end_ : + SYM_TAG_END_FLAG + | SYM_TAG_END_FLAG2 + ; + +html_tag_finish_ : + empty + | SYM_TAG_START_FLAG2 html_tag_name_ html_tag_finish_end_ + ; + +html_tag_finish_end_ : + SYM_TAG_END_FLAG + | SYM_TAG_END_FLAG2 + ; + +html_tag_prot_event_list_ : + empty + | html_tag_prot_event_list_ html_tag_prot_event_ + ; + +html_tag_prot_event_ : + html_tag_prot_ + | html_tag_event_ + ; + +html_tag_prot_ : + html_tag_prot_name_ SYM_EQUAL html_tag_prot_value_ + | html_tag_prot_name_ + ; + +html_tag_prot_value_ : + SYM_TEXT + ; + +html_tag_event_ : + html_tag_event_name_ SYM_EQUAL html_tag_event_value_ + | html_tag_event_name_ + ; + +html_tag_event_value_ : + SYM_TEXT + ; + +html_tag_event_name_ : + SYM_EVT_ONAFTERPRINT + | SYM_EVT_ONBEFOREPRINT + | SYM_EVT_ONBEFOREONLOAD + | SYM_EVT_ONBLUR + | SYM_EVT_ONFOCUS + | SYM_EVT_ONHASCHANGE + | SYM_EVT_ONLOAD + | SYM_EVT_ONMESSAGE + | SYM_EVT_ONOFFLINE + | SYM_EVT_ONONLINE + | SYM_EVT_ONPAGEHIDE + | SYM_EVT_ONPAGESHOW + | SYM_EVT_ONPOPSTATE + | SYM_EVT_ONREDO + | SYM_EVT_ONRESIZE + | SYM_EVT_ONSTORAGE + | SYM_EVT_ONUNDO + | SYM_EVT_ONUNLOAD + | SYM_EVT_ONCHANGE + | SYM_EVT_ONCONTEXTMENU + | SYM_EVT_ONFORMCHANGE + | SYM_EVT_ONFORMINPUT + | SYM_EVT_ONINPUT + | SYM_EVT_ONINVALID + | SYM_EVT_ONRESET + | SYM_EVT_ONSELECT + | SYM_EVT_ONSUBMIT + | SYM_EVT_ONKEYDOWN + | SYM_EVT_ONKEYPRESS + | SYM_EVT_ONKEYUP + | SYM_EVT_ONCLICK + | SYM_EVT_ONDBLCLICK + | SYM_EVT_ONDRAG + | SYM_EVT_ONDRAGEND + | SYM_EVT_ONDRAGENTER + | SYM_EVT_ONDRAGLEAVE + | SYM_EVT_ONDRAGOVER + | SYM_EVT_ONDRAGSTART + | SYM_EVT_ONDROP + | SYM_EVT_ONMOUSEDOWN + | SYM_EVT_ONMOUSEMOVE + | SYM_EVT_ONMOUSEOUT + | SYM_EVT_ONMOUSEOVER + | SYM_EVT_ONMOUSEUP + | SYM_EVT_ONMOUSEWHEEL + | SYM_EVT_ONSCROLL + | SYM_EVT_ONABORT + | SYM_EVT_ONCANPLAY + | SYM_EVT_ONCANPLAYTHROUGH + | SYM_EVT_ONDURATIONCHANGE + | SYM_EVT_ONEMPTIED + | SYM_EVT_ONENDED + | SYM_EVT_ONERROR + | SYM_EVT_ONLOADEDDATA + | SYM_EVT_ONLOADEDMETADATA + | SYM_EVT_ONLOADSTART + | SYM_EVT_ONPAUSE + | SYM_EVT_ONPLAY + | SYM_EVT_ONPLAYING + | SYM_EVT_ONPROGRESS + | SYM_EVT_ONRATECHANGE + | SYM_EVT_ONREADYSTATECHANGE + | SYM_EVT_ONSEEKED + | SYM_EVT_ONSEEKING + | SYM_EVT_ONSTALLED + | SYM_EVT_ONSUSPEND + | SYM_EVT_ONTIMEUPDATE + | SYM_EVT_ONVOLUMECHANGE + | SYM_EVT_ONWAITING + | SYM_EVT_ONSTART + ; + +html_tag_name_ : + SYM_TAG_A + | SYM_TAG_ABBR + | SYM_TAG_ACRONYM + | SYM_TAG_ADDRESS + | SYM_TAG_APPLET + | SYM_TAG_AREA + | SYM_TAG_ARTICLE + | SYM_TAG_ASIDE + | SYM_TAG_AUDIO + | SYM_TAG_B + | SYM_TAG_BASE + | SYM_TAG_BASEFONT + | SYM_TAG_BDI + | SYM_TAG_BDO + | SYM_TAG_BIG + | SYM_TAG_BLOCKQUOTE + | SYM_TAG_BODY + | SYM_TAG_BR + | SYM_TAG_BUTTON + | SYM_TAG_CANVAS + | SYM_TAG_CAPTION + | SYM_TAG_CENTER + | SYM_TAG_CITE + | SYM_TAG_CODE + | SYM_TAG_COL + | SYM_TAG_COLGROUP + | SYM_TAG_COMMAND + | SYM_TAG_DATALIST + | SYM_TAG_DD + | SYM_TAG_DEL + | SYM_TAG_DETAILS + | SYM_TAG_DFN + | SYM_TAG_DIR + | SYM_TAG_DIV + | SYM_TAG_DL + | SYM_TAG_DT + | SYM_TAG_EM + | SYM_TAG_EMBED + | SYM_TAG_FIELDSET + | SYM_TAG_FIGCAPTION + | SYM_TAG_FIGURE + | SYM_TAG_FONT + | SYM_TAG_FOOTER + | SYM_TAG_FORM + | SYM_TAG_FRAME + | SYM_TAG_FRAMESET + | SYM_TAG_H1 + | SYM_TAG_H2 + | SYM_TAG_H3 + | SYM_TAG_H4 + | SYM_TAG_H5 + | SYM_TAG_H6 + | SYM_TAG_HEAD + | SYM_TAG_HEADER + | SYM_TAG_HGROUP + | SYM_TAG_HR + | SYM_TAG_HTML + | SYM_TAG_I + | SYM_TAG_IFRAME + | SYM_TAG_IMG + | SYM_TAG_INPUT + | SYM_TAG_INS + | SYM_TAG_KEYGEN + | SYM_TAG_KBD + | SYM_TAG_LABEL + | SYM_TAG_LEGEND + | SYM_TAG_LI + | SYM_TAG_LINK + | SYM_TAG_LAYER + | SYM_TAG_MAP + | SYM_TAG_MARK + | SYM_TAG_MENU + | SYM_TAG_META + | SYM_TAG_METER + | SYM_TAG_NAV + | SYM_TAG_NOFRAMES + | SYM_TAG_NOSCRIPT + | SYM_TAG_OBJECT + | SYM_TAG_OL + | SYM_TAG_OPTGROUP + | SYM_TAG_OPTION + | SYM_TAG_OUTPUT + | SYM_TAG_P + | SYM_TAG_PARAM + | SYM_TAG_PRE + | SYM_TAG_PROGRESS + | SYM_TAG_Q + | SYM_TAG_RP + | SYM_TAG_RT + | SYM_TAG_RUBY + | SYM_TAG_S + | SYM_TAG_U + | SYM_TAG_SAMP + | SYM_TAG_SCRIPT + | SYM_TAG_SECTION + | SYM_TAG_SELECT + | SYM_TAG_SMALL + | SYM_TAG_SOURCE + | SYM_TAG_SPAN + | SYM_TAG_STRIKE + | SYM_TAG_STRONG + | SYM_TAG_STYLE + | SYM_TAG_SUB + | SYM_TAG_SUMMARY + | SYM_TAG_SUP + | SYM_TAG_TABLE + | SYM_TAG_TBODY + | SYM_TAG_TD + | SYM_TAG_TH + | SYM_TAG_TR + | SYM_TAG_TT + | SYM_TAG_TEXTAREA + | SYM_TAG_TFOOT + | SYM_TAG_THEAD + | SYM_TAG_TIME + | SYM_TAG_TITLE + | SYM_TAG_UL + | SYM_TAG_VAR + | SYM_TAG_VIDEO + | SYM_TAG_XML + | SYM_TAG_BGSOUND + | SYM_TAG_MARQUEE + | SYM_TAG_USERDATA + ; + +html_tag_prot_name_ : + SYM_PROT_ACCESSKEY + | SYM_PROT_CLASS + | SYM_PROT_CONTENTEDITABLE + | SYM_PROT_CONTEXTMENU + | SYM_PROT_DIR + | SYM_PROT_DRAGGABLE + | SYM_PROT_HIDDEN + | SYM_PROT_ID + | SYM_PROT_ITEM + | SYM_PROT_ITEMPROP + | SYM_PROT_LANG + | SYM_PROT_SPELLCHECK + | SYM_PROT_STYLE + | SYM_PROT_SUBJECT + | SYM_PROT_TABINDEX + | SYM_PROT_TITLE + | SYM_PROT_USERDATA + | SYM_PROT_TEMPLATE + | SYM_PROT_REGISTRATIONMARK + | SYM_PROT_IRRELEVANT + | SYM_PROT_OPEN + | SYM_PROT_DATA + | SYM_PROT_NOWRAP + | SYM_PROT_DATETIME + | SYM_PROT_ROWS + | SYM_PROT_LIST + | SYM_PROT_FORMTARGETNEW + | SYM_PROT_AUTOFOCUSNEW + | SYM_PROT_ICON + | SYM_PROT_MAXLENGTH + | SYM_PROT_WIDTH + | SYM_PROT_ARCHIVE + | SYM_PROT_HREF + | SYM_PROT_PRELOAD + | SYM_PROT_MULTIPLE + | SYM_PROT_HREFLANG + | SYM_PROT_CELLSPACING + | SYM_PROT_COLSPAN + | SYM_PROT_ACTION + | SYM_PROT_CLASSID + | SYM_PROT_PATTERN + | SYM_PROT_COLOR + | SYM_PROT_HIGH + | SYM_PROT_PING + | SYM_PROT_ISMAP + | SYM_PROT_HTTPEQUIV + | SYM_PROT_HSPACE + | SYM_PROT_COMPACT + | SYM_PROT_LANGUAGE + | SYM_PROT_REQUIRED + | SYM_PROT_SPAN + | SYM_PROT_FORMACTIONNEW + | SYM_PROT_RULES + | SYM_PROT_AXIS + | SYM_PROT_METHOD + | SYM_PROT_BGCOLOR + | SYM_PROT_SHAPE + | SYM_PROT_USEMAP + | SYM_PROT_FOR + | SYM_PROT_SCOPED + | SYM_PROT_FORMENCTYPE + | SYM_PROT_FORMTARGET + | SYM_PROT_FORMMETHOD + | SYM_PROT_FORMACTION + | SYM_PROT_FORMNOVALIDATE + | SYM_PROT_FORMNOVALIDATENEW + | SYM_PROT_CONTENT + | SYM_PROT_INPUTMODE + | SYM_PROT_CITE + | SYM_PROT_VSPACE + | SYM_PROT_XMLNS + | SYM_PROT_CODETYPE + | SYM_PROT_TARGET + | SYM_PROT_VALUE + | SYM_PROT_AUTOFOCUS + | SYM_PROT_MEDIA + | SYM_PROT_COORDS + | SYM_PROT_PROFILE + | SYM_PROT_HEADERS + | SYM_PROT_VALUETYPE + | SYM_PROT_REPLACE + | SYM_PROT_MARGINHEIGHT + | SYM_PROT_BORDER + | SYM_PROT_FRAMEBORDER + | SYM_PROT_ASYNC + | SYM_PROT_FACE + | SYM_PROT_CELLPADDING + | SYM_PROT_STANDBY + | SYM_PROT_ALT + | SYM_PROT_ACCEPTCHARSET + | SYM_PROT_FORMMETHODNEW + | SYM_PROT_AUTOPLAY + | SYM_PROT_REV + | SYM_PROT_LOOP + | SYM_PROT_CODE + | SYM_PROT_SRC + | SYM_PROT_CHECKED + | SYM_PROT_SCROLLING + | SYM_PROT_SCOPE + | SYM_PROT_DEFER + | SYM_PROT_XMLSPACE + | SYM_PROT_CHALLENGE + | SYM_PROT_SCHEME + | SYM_PROT_DECLARE + | SYM_PROT_CHAR + | SYM_PROT_READONLY + | SYM_PROT_XMLLANG + | SYM_PROT_MAX + | SYM_PROT_ROWSPAN + | SYM_PROT_KEYTYPE + | SYM_PROT_AUTOCOMPLETE + | SYM_PROT_SELECTED + | SYM_PROT_CODEBASE + | SYM_PROT_STEP + | SYM_PROT_NOHREF + | SYM_PROT_CHARSET + | SYM_PROT_FORMNEW + | SYM_PROT_FORMENCTYPENEW + | SYM_PROT_REL + | SYM_PROT_MIN + | SYM_PROT_NAME + | SYM_PROT_TYPE + | SYM_PROT_NOSHADE + | SYM_PROT_MANIFEST + | SYM_PROT_ALIGN + | SYM_PROT_HEIGHT + | SYM_PROT_ACCEPT + | SYM_PROT_ENCTYPE + | SYM_PROT_DISABLED + | SYM_PROT_CONTROLS + | SYM_PROT_LONGDESC + | SYM_PROT_MARGINWIDTH + | SYM_PROT_NORESIZE + | SYM_PROT_COLS + | SYM_PROT_SIZE + | SYM_PROT_RADIOGROUP + | SYM_PROT_VALIGN + | SYM_PROT_OBJECT + | SYM_PROT_CHAROFF + | SYM_PROT_LOW + | SYM_PROT_START + | SYM_PROT_SUMMARY + | SYM_PROT_OPTIMUM + | SYM_PROT_ABBR + | SYM_PROT_FORM + | SYM_PROT_LABEL + | SYM_PROT_FRAME + | SYM_PROT_ALLOWSCRIPTACCESS + | SYM_PROT_PLACEHOLDER + | SYM_PROT_AUTOSUBMIT + | SYM_PROT_LOWSRC + | SYM_PROT_BACKGROUND + ; + +//Lexer + +SYM_TEXT : 'SYM_TEXT' ; +SYM_TAG_START_FLAG : 'SYM_TAG_START_FLAG' ; +SYM_TAG_END_FLAG : 'SYM_TAG_END_FLAG' ; +SYM_TAG_END_FLAG2 : 'SYM_TAG_END_FLAG2' ; +SYM_TAG_START_FLAG2 : 'SYM_TAG_START_FLAG2' ; +SYM_EQUAL : 'SYM_EQUAL' ; +SYM_EVT_ONAFTERPRINT : 'SYM_EVT_ONAFTERPRINT' ; +SYM_EVT_ONBEFOREPRINT : 'SYM_EVT_ONBEFOREPRINT' ; +SYM_EVT_ONBEFOREONLOAD : 'SYM_EVT_ONBEFOREONLOAD' ; +SYM_EVT_ONBLUR : 'SYM_EVT_ONBLUR' ; +SYM_EVT_ONFOCUS : 'SYM_EVT_ONFOCUS' ; +SYM_EVT_ONHASCHANGE : 'SYM_EVT_ONHASCHANGE' ; +SYM_EVT_ONLOAD : 'SYM_EVT_ONLOAD' ; +SYM_EVT_ONMESSAGE : 'SYM_EVT_ONMESSAGE' ; +SYM_EVT_ONOFFLINE : 'SYM_EVT_ONOFFLINE' ; +SYM_EVT_ONONLINE : 'SYM_EVT_ONONLINE' ; +SYM_EVT_ONPAGEHIDE : 'SYM_EVT_ONPAGEHIDE' ; +SYM_EVT_ONPAGESHOW : 'SYM_EVT_ONPAGESHOW' ; +SYM_EVT_ONPOPSTATE : 'SYM_EVT_ONPOPSTATE' ; +SYM_EVT_ONREDO : 'SYM_EVT_ONREDO' ; +SYM_EVT_ONRESIZE : 'SYM_EVT_ONRESIZE' ; +SYM_EVT_ONSTORAGE : 'SYM_EVT_ONSTORAGE' ; +SYM_EVT_ONUNDO : 'SYM_EVT_ONUNDO' ; +SYM_EVT_ONUNLOAD : 'SYM_EVT_ONUNLOAD' ; +SYM_EVT_ONCHANGE : 'SYM_EVT_ONCHANGE' ; +SYM_EVT_ONCONTEXTMENU : 'SYM_EVT_ONCONTEXTMENU' ; +SYM_EVT_ONFORMCHANGE : 'SYM_EVT_ONFORMCHANGE' ; +SYM_EVT_ONFORMINPUT : 'SYM_EVT_ONFORMINPUT' ; +SYM_EVT_ONINPUT : 'SYM_EVT_ONINPUT' ; +SYM_EVT_ONINVALID : 'SYM_EVT_ONINVALID' ; +SYM_EVT_ONRESET : 'SYM_EVT_ONRESET' ; +SYM_EVT_ONSELECT : 'SYM_EVT_ONSELECT' ; +SYM_EVT_ONSUBMIT : 'SYM_EVT_ONSUBMIT' ; +SYM_EVT_ONKEYDOWN : 'SYM_EVT_ONKEYDOWN' ; +SYM_EVT_ONKEYPRESS : 'SYM_EVT_ONKEYPRESS' ; +SYM_EVT_ONKEYUP : 'SYM_EVT_ONKEYUP' ; +SYM_EVT_ONCLICK : 'SYM_EVT_ONCLICK' ; +SYM_EVT_ONDBLCLICK : 'SYM_EVT_ONDBLCLICK' ; +SYM_EVT_ONDRAG : 'SYM_EVT_ONDRAG' ; +SYM_EVT_ONDRAGEND : 'SYM_EVT_ONDRAGEND' ; +SYM_EVT_ONDRAGENTER : 'SYM_EVT_ONDRAGENTER' ; +SYM_EVT_ONDRAGLEAVE : 'SYM_EVT_ONDRAGLEAVE' ; +SYM_EVT_ONDRAGOVER : 'SYM_EVT_ONDRAGOVER' ; +SYM_EVT_ONDRAGSTART : 'SYM_EVT_ONDRAGSTART' ; +SYM_EVT_ONDROP : 'SYM_EVT_ONDROP' ; +SYM_EVT_ONMOUSEDOWN : 'SYM_EVT_ONMOUSEDOWN' ; +SYM_EVT_ONMOUSEMOVE : 'SYM_EVT_ONMOUSEMOVE' ; +SYM_EVT_ONMOUSEOUT : 'SYM_EVT_ONMOUSEOUT' ; +SYM_EVT_ONMOUSEOVER : 'SYM_EVT_ONMOUSEOVER' ; +SYM_EVT_ONMOUSEUP : 'SYM_EVT_ONMOUSEUP' ; +SYM_EVT_ONMOUSEWHEEL : 'SYM_EVT_ONMOUSEWHEEL' ; +SYM_EVT_ONSCROLL : 'SYM_EVT_ONSCROLL' ; +SYM_EVT_ONABORT : 'SYM_EVT_ONABORT' ; +SYM_EVT_ONCANPLAY : 'SYM_EVT_ONCANPLAY' ; +SYM_EVT_ONCANPLAYTHROUGH : 'SYM_EVT_ONCANPLAYTHROUGH' ; +SYM_EVT_ONDURATIONCHANGE : 'SYM_EVT_ONDURATIONCHANGE' ; +SYM_EVT_ONEMPTIED : 'SYM_EVT_ONEMPTIED' ; +SYM_EVT_ONENDED : 'SYM_EVT_ONENDED' ; +SYM_EVT_ONERROR : 'SYM_EVT_ONERROR' ; +SYM_EVT_ONLOADEDDATA : 'SYM_EVT_ONLOADEDDATA' ; +SYM_EVT_ONLOADEDMETADATA : 'SYM_EVT_ONLOADEDMETADATA' ; +SYM_EVT_ONLOADSTART : 'SYM_EVT_ONLOADSTART' ; +SYM_EVT_ONPAUSE : 'SYM_EVT_ONPAUSE' ; +SYM_EVT_ONPLAY : 'SYM_EVT_ONPLAY' ; +SYM_EVT_ONPLAYING : 'SYM_EVT_ONPLAYING' ; +SYM_EVT_ONPROGRESS : 'SYM_EVT_ONPROGRESS' ; +SYM_EVT_ONRATECHANGE : 'SYM_EVT_ONRATECHANGE' ; +SYM_EVT_ONREADYSTATECHANGE : 'SYM_EVT_ONREADYSTATECHANGE' ; +SYM_EVT_ONSEEKED : 'SYM_EVT_ONSEEKED' ; +SYM_EVT_ONSEEKING : 'SYM_EVT_ONSEEKING' ; +SYM_EVT_ONSTALLED : 'SYM_EVT_ONSTALLED' ; +SYM_EVT_ONSUSPEND : 'SYM_EVT_ONSUSPEND' ; +SYM_EVT_ONTIMEUPDATE : 'SYM_EVT_ONTIMEUPDATE' ; +SYM_EVT_ONVOLUMECHANGE : 'SYM_EVT_ONVOLUMECHANGE' ; +SYM_EVT_ONWAITING : 'SYM_EVT_ONWAITING' ; +SYM_EVT_ONSTART : 'SYM_EVT_ONSTART' ; +SYM_TAG_A : 'SYM_TAG_A' ; +SYM_TAG_ABBR : 'SYM_TAG_ABBR' ; +SYM_TAG_ACRONYM : 'SYM_TAG_ACRONYM' ; +SYM_TAG_ADDRESS : 'SYM_TAG_ADDRESS' ; +SYM_TAG_APPLET : 'SYM_TAG_APPLET' ; +SYM_TAG_AREA : 'SYM_TAG_AREA' ; +SYM_TAG_ARTICLE : 'SYM_TAG_ARTICLE' ; +SYM_TAG_ASIDE : 'SYM_TAG_ASIDE' ; +SYM_TAG_AUDIO : 'SYM_TAG_AUDIO' ; +SYM_TAG_B : 'SYM_TAG_B' ; +SYM_TAG_BASE : 'SYM_TAG_BASE' ; +SYM_TAG_BASEFONT : 'SYM_TAG_BASEFONT' ; +SYM_TAG_BDI : 'SYM_TAG_BDI' ; +SYM_TAG_BDO : 'SYM_TAG_BDO' ; +SYM_TAG_BIG : 'SYM_TAG_BIG' ; +SYM_TAG_BLOCKQUOTE : 'SYM_TAG_BLOCKQUOTE' ; +SYM_TAG_BODY : 'SYM_TAG_BODY' ; +SYM_TAG_BR : 'SYM_TAG_BR' ; +SYM_TAG_BUTTON : 'SYM_TAG_BUTTON' ; +SYM_TAG_CANVAS : 'SYM_TAG_CANVAS' ; +SYM_TAG_CAPTION : 'SYM_TAG_CAPTION' ; +SYM_TAG_CENTER : 'SYM_TAG_CENTER' ; +SYM_TAG_CITE : 'SYM_TAG_CITE' ; +SYM_TAG_CODE : 'SYM_TAG_CODE' ; +SYM_TAG_COL : 'SYM_TAG_COL' ; +SYM_TAG_COLGROUP : 'SYM_TAG_COLGROUP' ; +SYM_TAG_COMMAND : 'SYM_TAG_COMMAND' ; +SYM_TAG_DATALIST : 'SYM_TAG_DATALIST' ; +SYM_TAG_DD : 'SYM_TAG_DD' ; +SYM_TAG_DEL : 'SYM_TAG_DEL' ; +SYM_TAG_DETAILS : 'SYM_TAG_DETAILS' ; +SYM_TAG_DFN : 'SYM_TAG_DFN' ; +SYM_TAG_DIR : 'SYM_TAG_DIR' ; +SYM_TAG_DIV : 'SYM_TAG_DIV' ; +SYM_TAG_DL : 'SYM_TAG_DL' ; +SYM_TAG_DT : 'SYM_TAG_DT' ; +SYM_TAG_EM : 'SYM_TAG_EM' ; +SYM_TAG_EMBED : 'SYM_TAG_EMBED' ; +SYM_TAG_FIELDSET : 'SYM_TAG_FIELDSET' ; +SYM_TAG_FIGCAPTION : 'SYM_TAG_FIGCAPTION' ; +SYM_TAG_FIGURE : 'SYM_TAG_FIGURE' ; +SYM_TAG_FONT : 'SYM_TAG_FONT' ; +SYM_TAG_FOOTER : 'SYM_TAG_FOOTER' ; +SYM_TAG_FORM : 'SYM_TAG_FORM' ; +SYM_TAG_FRAME : 'SYM_TAG_FRAME' ; +SYM_TAG_FRAMESET : 'SYM_TAG_FRAMESET' ; +SYM_TAG_H1 : 'SYM_TAG_H1' ; +SYM_TAG_H2 : 'SYM_TAG_H2' ; +SYM_TAG_H3 : 'SYM_TAG_H3' ; +SYM_TAG_H4 : 'SYM_TAG_H4' ; +SYM_TAG_H5 : 'SYM_TAG_H5' ; +SYM_TAG_H6 : 'SYM_TAG_H6' ; +SYM_TAG_HEAD : 'SYM_TAG_HEAD' ; +SYM_TAG_HEADER : 'SYM_TAG_HEADER' ; +SYM_TAG_HGROUP : 'SYM_TAG_HGROUP' ; +SYM_TAG_HR : 'SYM_TAG_HR' ; +SYM_TAG_HTML : 'SYM_TAG_HTML' ; +SYM_TAG_I : 'SYM_TAG_I' ; +SYM_TAG_IFRAME : 'SYM_TAG_IFRAME' ; +SYM_TAG_IMG : 'SYM_TAG_IMG' ; +SYM_TAG_INPUT : 'SYM_TAG_INPUT' ; +SYM_TAG_INS : 'SYM_TAG_INS' ; +SYM_TAG_KEYGEN : 'SYM_TAG_KEYGEN' ; +SYM_TAG_KBD : 'SYM_TAG_KBD' ; +SYM_TAG_LABEL : 'SYM_TAG_LABEL' ; +SYM_TAG_LEGEND : 'SYM_TAG_LEGEND' ; +SYM_TAG_LI : 'SYM_TAG_LI' ; +SYM_TAG_LINK : 'SYM_TAG_LINK' ; +SYM_TAG_LAYER : 'SYM_TAG_LAYER' ; +SYM_TAG_MAP : 'SYM_TAG_MAP' ; +SYM_TAG_MARK : 'SYM_TAG_MARK' ; +SYM_TAG_MENU : 'SYM_TAG_MENU' ; +SYM_TAG_META : 'SYM_TAG_META' ; +SYM_TAG_METER : 'SYM_TAG_METER' ; +SYM_TAG_NAV : 'SYM_TAG_NAV' ; +SYM_TAG_NOFRAMES : 'SYM_TAG_NOFRAMES' ; +SYM_TAG_NOSCRIPT : 'SYM_TAG_NOSCRIPT' ; +SYM_TAG_OBJECT : 'SYM_TAG_OBJECT' ; +SYM_TAG_OL : 'SYM_TAG_OL' ; +SYM_TAG_OPTGROUP : 'SYM_TAG_OPTGROUP' ; +SYM_TAG_OPTION : 'SYM_TAG_OPTION' ; +SYM_TAG_OUTPUT : 'SYM_TAG_OUTPUT' ; +SYM_TAG_P : 'SYM_TAG_P' ; +SYM_TAG_PARAM : 'SYM_TAG_PARAM' ; +SYM_TAG_PRE : 'SYM_TAG_PRE' ; +SYM_TAG_PROGRESS : 'SYM_TAG_PROGRESS' ; +SYM_TAG_Q : 'SYM_TAG_Q' ; +SYM_TAG_RP : 'SYM_TAG_RP' ; +SYM_TAG_RT : 'SYM_TAG_RT' ; +SYM_TAG_RUBY : 'SYM_TAG_RUBY' ; +SYM_TAG_S : 'SYM_TAG_S' ; +SYM_TAG_U : 'SYM_TAG_U' ; +SYM_TAG_SAMP : 'SYM_TAG_SAMP' ; +SYM_TAG_SCRIPT : 'SYM_TAG_SCRIPT' ; +SYM_TAG_SECTION : 'SYM_TAG_SECTION' ; +SYM_TAG_SELECT : 'SYM_TAG_SELECT' ; +SYM_TAG_SMALL : 'SYM_TAG_SMALL' ; +SYM_TAG_SOURCE : 'SYM_TAG_SOURCE' ; +SYM_TAG_SPAN : 'SYM_TAG_SPAN' ; +SYM_TAG_STRIKE : 'SYM_TAG_STRIKE' ; +SYM_TAG_STRONG : 'SYM_TAG_STRONG' ; +SYM_TAG_STYLE : 'SYM_TAG_STYLE' ; +SYM_TAG_SUB : 'SYM_TAG_SUB' ; +SYM_TAG_SUMMARY : 'SYM_TAG_SUMMARY' ; +SYM_TAG_SUP : 'SYM_TAG_SUP' ; +SYM_TAG_TABLE : 'SYM_TAG_TABLE' ; +SYM_TAG_TBODY : 'SYM_TAG_TBODY' ; +SYM_TAG_TD : 'SYM_TAG_TD' ; +SYM_TAG_TH : 'SYM_TAG_TH' ; +SYM_TAG_TR : 'SYM_TAG_TR' ; +SYM_TAG_TT : 'SYM_TAG_TT' ; +SYM_TAG_TEXTAREA : 'SYM_TAG_TEXTAREA' ; +SYM_TAG_TFOOT : 'SYM_TAG_TFOOT' ; +SYM_TAG_THEAD : 'SYM_TAG_THEAD' ; +SYM_TAG_TIME : 'SYM_TAG_TIME' ; +SYM_TAG_TITLE : 'SYM_TAG_TITLE' ; +SYM_TAG_UL : 'SYM_TAG_UL' ; +SYM_TAG_VAR : 'SYM_TAG_VAR' ; +SYM_TAG_VIDEO : 'SYM_TAG_VIDEO' ; +SYM_TAG_XML : 'SYM_TAG_XML' ; +SYM_TAG_BGSOUND : 'SYM_TAG_BGSOUND' ; +SYM_TAG_MARQUEE : 'SYM_TAG_MARQUEE' ; +SYM_TAG_USERDATA : 'SYM_TAG_USERDATA' ; +SYM_PROT_ACCESSKEY : 'SYM_PROT_ACCESSKEY' ; +SYM_PROT_CLASS : 'SYM_PROT_CLASS' ; +SYM_PROT_CONTENTEDITABLE : 'SYM_PROT_CONTENTEDITABLE' ; +SYM_PROT_CONTEXTMENU : 'SYM_PROT_CONTEXTMENU' ; +SYM_PROT_DIR : 'SYM_PROT_DIR' ; +SYM_PROT_DRAGGABLE : 'SYM_PROT_DRAGGABLE' ; +SYM_PROT_HIDDEN : 'SYM_PROT_HIDDEN' ; +SYM_PROT_ID : 'SYM_PROT_ID' ; +SYM_PROT_ITEM : 'SYM_PROT_ITEM' ; +SYM_PROT_ITEMPROP : 'SYM_PROT_ITEMPROP' ; +SYM_PROT_LANG : 'SYM_PROT_LANG' ; +SYM_PROT_SPELLCHECK : 'SYM_PROT_SPELLCHECK' ; +SYM_PROT_STYLE : 'SYM_PROT_STYLE' ; +SYM_PROT_SUBJECT : 'SYM_PROT_SUBJECT' ; +SYM_PROT_TABINDEX : 'SYM_PROT_TABINDEX' ; +SYM_PROT_TITLE : 'SYM_PROT_TITLE' ; +SYM_PROT_USERDATA : 'SYM_PROT_USERDATA' ; +SYM_PROT_TEMPLATE : 'SYM_PROT_TEMPLATE' ; +SYM_PROT_REGISTRATIONMARK : 'SYM_PROT_REGISTRATIONMARK' ; +SYM_PROT_IRRELEVANT : 'SYM_PROT_IRRELEVANT' ; +SYM_PROT_OPEN : 'SYM_PROT_OPEN' ; +SYM_PROT_DATA : 'SYM_PROT_DATA' ; +SYM_PROT_NOWRAP : 'SYM_PROT_NOWRAP' ; +SYM_PROT_DATETIME : 'SYM_PROT_DATETIME' ; +SYM_PROT_ROWS : 'SYM_PROT_ROWS' ; +SYM_PROT_LIST : 'SYM_PROT_LIST' ; +SYM_PROT_FORMTARGETNEW : 'SYM_PROT_FORMTARGETNEW' ; +SYM_PROT_AUTOFOCUSNEW : 'SYM_PROT_AUTOFOCUSNEW' ; +SYM_PROT_ICON : 'SYM_PROT_ICON' ; +SYM_PROT_MAXLENGTH : 'SYM_PROT_MAXLENGTH' ; +SYM_PROT_WIDTH : 'SYM_PROT_WIDTH' ; +SYM_PROT_ARCHIVE : 'SYM_PROT_ARCHIVE' ; +SYM_PROT_HREF : 'SYM_PROT_HREF' ; +SYM_PROT_PRELOAD : 'SYM_PROT_PRELOAD' ; +SYM_PROT_MULTIPLE : 'SYM_PROT_MULTIPLE' ; +SYM_PROT_HREFLANG : 'SYM_PROT_HREFLANG' ; +SYM_PROT_CELLSPACING : 'SYM_PROT_CELLSPACING' ; +SYM_PROT_COLSPAN : 'SYM_PROT_COLSPAN' ; +SYM_PROT_ACTION : 'SYM_PROT_ACTION' ; +SYM_PROT_CLASSID : 'SYM_PROT_CLASSID' ; +SYM_PROT_PATTERN : 'SYM_PROT_PATTERN' ; +SYM_PROT_COLOR : 'SYM_PROT_COLOR' ; +SYM_PROT_HIGH : 'SYM_PROT_HIGH' ; +SYM_PROT_PING : 'SYM_PROT_PING' ; +SYM_PROT_ISMAP : 'SYM_PROT_ISMAP' ; +SYM_PROT_HTTPEQUIV : 'SYM_PROT_HTTPEQUIV' ; +SYM_PROT_HSPACE : 'SYM_PROT_HSPACE' ; +SYM_PROT_COMPACT : 'SYM_PROT_COMPACT' ; +SYM_PROT_LANGUAGE : 'SYM_PROT_LANGUAGE' ; +SYM_PROT_REQUIRED : 'SYM_PROT_REQUIRED' ; +SYM_PROT_SPAN : 'SYM_PROT_SPAN' ; +SYM_PROT_FORMACTIONNEW : 'SYM_PROT_FORMACTIONNEW' ; +SYM_PROT_RULES : 'SYM_PROT_RULES' ; +SYM_PROT_AXIS : 'SYM_PROT_AXIS' ; +SYM_PROT_METHOD : 'SYM_PROT_METHOD' ; +SYM_PROT_BGCOLOR : 'SYM_PROT_BGCOLOR' ; +SYM_PROT_SHAPE : 'SYM_PROT_SHAPE' ; +SYM_PROT_USEMAP : 'SYM_PROT_USEMAP' ; +SYM_PROT_FOR : 'SYM_PROT_FOR' ; +SYM_PROT_SCOPED : 'SYM_PROT_SCOPED' ; +SYM_PROT_FORMENCTYPE : 'SYM_PROT_FORMENCTYPE' ; +SYM_PROT_FORMTARGET : 'SYM_PROT_FORMTARGET' ; +SYM_PROT_FORMMETHOD : 'SYM_PROT_FORMMETHOD' ; +SYM_PROT_FORMACTION : 'SYM_PROT_FORMACTION' ; +SYM_PROT_FORMNOVALIDATE : 'SYM_PROT_FORMNOVALIDATE' ; +SYM_PROT_FORMNOVALIDATENEW : 'SYM_PROT_FORMNOVALIDATENEW' ; +SYM_PROT_CONTENT : 'SYM_PROT_CONTENT' ; +SYM_PROT_INPUTMODE : 'SYM_PROT_INPUTMODE' ; +SYM_PROT_CITE : 'SYM_PROT_CITE' ; +SYM_PROT_VSPACE : 'SYM_PROT_VSPACE' ; +SYM_PROT_XMLNS : 'SYM_PROT_XMLNS' ; +SYM_PROT_CODETYPE : 'SYM_PROT_CODETYPE' ; +SYM_PROT_TARGET : 'SYM_PROT_TARGET' ; +SYM_PROT_VALUE : 'SYM_PROT_VALUE' ; +SYM_PROT_AUTOFOCUS : 'SYM_PROT_AUTOFOCUS' ; +SYM_PROT_MEDIA : 'SYM_PROT_MEDIA' ; +SYM_PROT_COORDS : 'SYM_PROT_COORDS' ; +SYM_PROT_PROFILE : 'SYM_PROT_PROFILE' ; +SYM_PROT_HEADERS : 'SYM_PROT_HEADERS' ; +SYM_PROT_VALUETYPE : 'SYM_PROT_VALUETYPE' ; +SYM_PROT_REPLACE : 'SYM_PROT_REPLACE' ; +SYM_PROT_MARGINHEIGHT : 'SYM_PROT_MARGINHEIGHT' ; +SYM_PROT_BORDER : 'SYM_PROT_BORDER' ; +SYM_PROT_FRAMEBORDER : 'SYM_PROT_FRAMEBORDER' ; +SYM_PROT_ASYNC : 'SYM_PROT_ASYNC' ; +SYM_PROT_FACE : 'SYM_PROT_FACE' ; +SYM_PROT_CELLPADDING : 'SYM_PROT_CELLPADDING' ; +SYM_PROT_STANDBY : 'SYM_PROT_STANDBY' ; +SYM_PROT_ALT : 'SYM_PROT_ALT' ; +SYM_PROT_ACCEPTCHARSET : 'SYM_PROT_ACCEPTCHARSET' ; +SYM_PROT_FORMMETHODNEW : 'SYM_PROT_FORMMETHODNEW' ; +SYM_PROT_AUTOPLAY : 'SYM_PROT_AUTOPLAY' ; +SYM_PROT_REV : 'SYM_PROT_REV' ; +SYM_PROT_LOOP : 'SYM_PROT_LOOP' ; +SYM_PROT_CODE : 'SYM_PROT_CODE' ; +SYM_PROT_SRC : 'SYM_PROT_SRC' ; +SYM_PROT_CHECKED : 'SYM_PROT_CHECKED' ; +SYM_PROT_SCROLLING : 'SYM_PROT_SCROLLING' ; +SYM_PROT_SCOPE : 'SYM_PROT_SCOPE' ; +SYM_PROT_DEFER : 'SYM_PROT_DEFER' ; +SYM_PROT_XMLSPACE : 'SYM_PROT_XMLSPACE' ; +SYM_PROT_CHALLENGE : 'SYM_PROT_CHALLENGE' ; +SYM_PROT_SCHEME : 'SYM_PROT_SCHEME' ; +SYM_PROT_DECLARE : 'SYM_PROT_DECLARE' ; +SYM_PROT_CHAR : 'SYM_PROT_CHAR' ; +SYM_PROT_READONLY : 'SYM_PROT_READONLY' ; +SYM_PROT_XMLLANG : 'SYM_PROT_XMLLANG' ; +SYM_PROT_MAX : 'SYM_PROT_MAX' ; +SYM_PROT_ROWSPAN : 'SYM_PROT_ROWSPAN' ; +SYM_PROT_KEYTYPE : 'SYM_PROT_KEYTYPE' ; +SYM_PROT_AUTOCOMPLETE : 'SYM_PROT_AUTOCOMPLETE' ; +SYM_PROT_SELECTED : 'SYM_PROT_SELECTED' ; +SYM_PROT_CODEBASE : 'SYM_PROT_CODEBASE' ; +SYM_PROT_STEP : 'SYM_PROT_STEP' ; +SYM_PROT_NOHREF : 'SYM_PROT_NOHREF' ; +SYM_PROT_CHARSET : 'SYM_PROT_CHARSET' ; +SYM_PROT_FORMNEW : 'SYM_PROT_FORMNEW' ; +SYM_PROT_FORMENCTYPENEW : 'SYM_PROT_FORMENCTYPENEW' ; +SYM_PROT_REL : 'SYM_PROT_REL' ; +SYM_PROT_MIN : 'SYM_PROT_MIN' ; +SYM_PROT_NAME : 'SYM_PROT_NAME' ; +SYM_PROT_TYPE : 'SYM_PROT_TYPE' ; +SYM_PROT_NOSHADE : 'SYM_PROT_NOSHADE' ; +SYM_PROT_MANIFEST : 'SYM_PROT_MANIFEST' ; +SYM_PROT_ALIGN : 'SYM_PROT_ALIGN' ; +SYM_PROT_HEIGHT : 'SYM_PROT_HEIGHT' ; +SYM_PROT_ACCEPT : 'SYM_PROT_ACCEPT' ; +SYM_PROT_ENCTYPE : 'SYM_PROT_ENCTYPE' ; +SYM_PROT_DISABLED : 'SYM_PROT_DISABLED' ; +SYM_PROT_CONTROLS : 'SYM_PROT_CONTROLS' ; +SYM_PROT_LONGDESC : 'SYM_PROT_LONGDESC' ; +SYM_PROT_MARGINWIDTH : 'SYM_PROT_MARGINWIDTH' ; +SYM_PROT_NORESIZE : 'SYM_PROT_NORESIZE' ; +SYM_PROT_COLS : 'SYM_PROT_COLS' ; +SYM_PROT_SIZE : 'SYM_PROT_SIZE' ; +SYM_PROT_RADIOGROUP : 'SYM_PROT_RADIOGROUP' ; +SYM_PROT_VALIGN : 'SYM_PROT_VALIGN' ; +SYM_PROT_OBJECT : 'SYM_PROT_OBJECT' ; +SYM_PROT_CHAROFF : 'SYM_PROT_CHAROFF' ; +SYM_PROT_LOW : 'SYM_PROT_LOW' ; +SYM_PROT_START : 'SYM_PROT_START' ; +SYM_PROT_SUMMARY : 'SYM_PROT_SUMMARY' ; +SYM_PROT_OPTIMUM : 'SYM_PROT_OPTIMUM' ; +SYM_PROT_ABBR : 'SYM_PROT_ABBR' ; +SYM_PROT_FORM : 'SYM_PROT_FORM' ; +SYM_PROT_LABEL : 'SYM_PROT_LABEL' ; +SYM_PROT_FRAME : 'SYM_PROT_FRAME' ; +SYM_PROT_ALLOWSCRIPTACCESS : 'SYM_PROT_ALLOWSCRIPTACCESS' ; +SYM_PROT_PLACEHOLDER : 'SYM_PROT_PLACEHOLDER' ; +SYM_PROT_AUTOSUBMIT : 'SYM_PROT_AUTOSUBMIT' ; +SYM_PROT_LOWSRC : 'SYM_PROT_LOWSRC' ; +SYM_PROT_BACKGROUND : 'SYM_PROT_BACKGROUND' ; + +} diff --git a/playground/httpd-parser.g b/playground/httpd-parser.g new file mode 100644 index 0000000..bb5e688 --- /dev/null +++ b/playground/httpd-parser.g @@ -0,0 +1,456 @@ +//From: https://github.com/reyk/httpd/blob/master/httpd/parse.y +httpd { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token ACCESS +//%token ALIAS +//%token AUTO +//%token BACKLOG +//%token BODY +//%token BUFFER +//%token CERTIFICATE +//%token CHROOT +//%token CIPHERS +//%token COMMON +//%token COMBINED +//%token CONNECTION +//%token DHE +//%token DIRECTORY +//%token ECDHE +//%token ERR +//%token FCGI +//%token INDEX +//%token IP +//%token KEY +//%token LIFETIME +//%token LISTEN +//%token LOCATION +//%token LOG +//%token LOGDIR +//%token MATCH +//%token MAXIMUM +//%token NO +//%token NODELAY +//%token OCSP +//%token ON +//%token PORT +//%token PREFORK +//%token PROTOCOLS +//%token REQUESTS +//%token ROOT +//%token SACK +//%token SERVER +//%token SOCKET +//%token STRIP +//%token STYLE +//%token SYSLOG +//%token TCP +//%token TICKET +//%token TIMEOUT +//%token TLS +//%token TYPE +//%token TYPES +//%token HSTS +//%token MAXAGE +//%token SUBDOMAINS +//%token DEFAULT +//%token PRELOAD +//%token REQUEST +//%token ERROR +//%token INCLUDE +//%token AUTHENTICATE +//%token WITH +//%token BLOCK +//%token DROP +//%token RETURN +//%token PASS +//%token STRING +//%token NUMBER +//%token '\n' +//%token '=' +//%token '{' +//%token '}' +//%token '/' +//%token ';' +//%token ',' + + +//%start grammar + +//%% + +grammar : + /*YYEOF + |*/ /*empty*/ + | grammar include '\n' + | grammar '\n' + | grammar varset '\n' + | grammar main '\n' + | grammar server '\n' + | grammar types '\n' + | grammar error '\n' + ; + +include : + INCLUDE STRING + ; + +varset : + STRING '=' STRING + ; + +opttls : + /*empty*/ + | TLS + ; + +main : + PREFORK NUMBER + | CHROOT STRING + | LOGDIR STRING + | DEFAULT TYPE mediastring + ; + +server : + SERVER optmatch STRING '{' optnl serveropts_l '}' + ; + +serveropts_l : + serveropts_l serveroptsl nl + | serveroptsl optnl + ; + +serveroptsl : + LISTEN ON STRING opttls port + | ALIAS optmatch STRING + | tcpip + | connection + | tls + | root + | directory + | logformat + | fastcgi + | authenticate + | filter + | LOCATION optmatch STRING '{' optnl serveropts_l '}' + | DEFAULT TYPE mediastring + | include + | hsts + ; + +hsts : + HSTS '{' optnl hstsflags_l '}' + | HSTS hstsflags + | HSTS + ; + +hstsflags_l : + hstsflags optcommanl hstsflags_l + | hstsflags optnl + ; + +hstsflags : + MAXAGE NUMBER + | SUBDOMAINS + | PRELOAD + ; + +fastcgi : + NO FCGI + | FCGI + | FCGI '{' optnl fcgiflags_l '}' + | FCGI fcgiflags + ; + +fcgiflags_l : + fcgiflags optcommanl fcgiflags_l + | fcgiflags optnl + ; + +fcgiflags : + SOCKET STRING + ; + +connection : + CONNECTION '{' optnl conflags_l '}' + | CONNECTION conflags + ; + +conflags_l : + conflags optcommanl conflags_l + | conflags optnl + ; + +conflags : + TIMEOUT timeout + | REQUEST TIMEOUT timeout + | MAXIMUM REQUESTS NUMBER + | MAXIMUM REQUEST BODY NUMBER + ; + +tls : + TLS '{' optnl tlsopts_l '}' + | TLS tlsopts + ; + +tlsopts_l : + tlsopts optcommanl tlsopts_l + | tlsopts optnl + ; + +tlsopts : + CERTIFICATE STRING + | KEY STRING + | OCSP STRING + | CIPHERS STRING + | DHE STRING + | ECDHE STRING + | PROTOCOLS STRING + | TICKET LIFETIME DEFAULT + | TICKET LIFETIME NUMBER + | NO TICKET + ; + +root : + ROOT rootflags + | ROOT '{' optnl rootflags_l '}' + ; + +rootflags_l : + rootflags optcommanl rootflags_l + | rootflags optnl + ; + +rootflags : + STRING + | STRIP NUMBER + ; + +authenticate : + NO AUTHENTICATE + | AUTHENTICATE authopts + ; + +authopts : + STRING WITH STRING + | WITH STRING + ; + +directory : + DIRECTORY dirflags + | DIRECTORY '{' optnl dirflags_l '}' + ; + +dirflags_l : + dirflags optcommanl dirflags_l + | dirflags optnl + ; + +dirflags : + INDEX STRING + | NO INDEX + | AUTO INDEX + | NO AUTO INDEX + ; + +logformat : + LOG logflags + | LOG '{' optnl logflags_l '}' + | NO LOG + ; + +logflags_l : + logflags optcommanl logflags_l + | logflags optnl + ; + +logflags : + STYLE logstyle + | SYSLOG + | NO SYSLOG + | ACCESS STRING + | ERR STRING + ; + +logstyle : + COMMON + | COMBINED + | CONNECTION + ; + +filter : + block RETURN NUMBER optstring + | block DROP + | block + | PASS + ; + +block : + BLOCK + ; + +optmatch : + /*empty*/ + | MATCH + ; + +optstring : + /*empty*/ + | STRING + ; + +tcpip : + TCP '{' optnl tcpflags_l '}' + | TCP tcpflags + ; + +tcpflags_l : + tcpflags optcommanl tcpflags_l + | tcpflags optnl + ; + +tcpflags : + SACK + | NO SACK + | NODELAY + | NO NODELAY + | BACKLOG NUMBER + | SOCKET BUFFER NUMBER + | IP STRING NUMBER + ; + +types : + TYPES '{' optnl mediaopts_l '}' + ; + +mediaopts_l : + mediaopts_l mediaoptsl nl + | mediaoptsl nl + ; + +mediaoptsl : + mediastring medianames_l optsemicolon + | include + ; + +mediastring : + STRING '/' STRING + ; + +medianames_l : + medianames_l medianamesl + | medianamesl + ; + +medianamesl : + numberstring + ; + +port : + PORT NUMBER + | PORT STRING + ; + +timeout : + NUMBER + ; + +numberstring : + NUMBER + | STRING + ; + +optsemicolon : + ';' + | /*empty*/ + ; + +optnl : + '\n' optnl + | /*empty*/ + ; + +optcommanl : + ',' optnl + | nl + ; + +nl : + '\n' optnl + ; + +//Lexer + +INCLUDE : 'include' ; +STRING : "'(\\.|[^\\'])+'" ; +TLS : 'tls' ; +PREFORK : 'prefork' ; +NUMBER : 'NUMBER' ; +CHROOT : 'chroot' ; +LOGDIR : 'logdir' ; +DEFAULT : 'default' ; +TYPE : 'type' ; +SERVER : 'server' ; +LISTEN : 'listen' ; +ON : 'on' ; +ALIAS : 'alias' ; +LOCATION : 'location' ; +HSTS : 'hsts' ; +MAXAGE : 'maxage' ; +SUBDOMAINS : 'subdomains' ; +PRELOAD : 'preload' ; +NO : 'no' ; +FCGI : 'fcgi' ; +SOCKET : 'socket' ; +CONNECTION : 'connection' ; +TIMEOUT : 'timeout' ; +REQUEST : 'request' ; +MAXIMUM : 'maximum' ; +REQUESTS : 'requests' ; +BODY : 'body' ; +CERTIFICATE : 'certificate' ; +KEY : 'key' ; +OCSP : 'ocsp' ; +CIPHERS : 'ciphers' ; +DHE : 'dhe' ; +ECDHE : 'ecdhe' ; +PROTOCOLS : 'protocols' ; +TICKET : 'ticket' ; +LIFETIME : 'lifetime' ; +ROOT : 'root' ; +STRIP : 'strip' ; +AUTHENTICATE : 'authenticate' ; +WITH : 'with' ; +DIRECTORY : 'directory' ; +INDEX : 'index' ; +AUTO : 'auto' ; +LOG : 'log' ; +STYLE : 'style' ; +SYSLOG : 'syslog' ; +ACCESS : 'access' ; +ERR : 'err' ; +COMMON : 'common' ; +COMBINED : 'combined' ; +RETURN : 'return' ; +DROP : 'drop' ; +PASS : 'pass' ; +BLOCK : 'block' ; +MATCH : 'match' ; +TCP : 'tcp' ; +SACK : 'sack' ; +NODELAY : 'nodelay' ; +BACKLOG : 'backlog' ; +BUFFER : 'buffer' ; +IP : 'ip' ; +TYPES : 'types' ; +PORT : 'port' ; + +} diff --git a/playground/ispc.g b/playground/ispc.g new file mode 100644 index 0000000..1d576d8 --- /dev/null +++ b/playground/ispc.g @@ -0,0 +1,1011 @@ +// From: https://github.com/ispc/ispc/blob/main/src/parse.yy + +cparser { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; //Withouth '\r' if the source has '\r' the lexer stop working +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token TOKEN_INT8_CONSTANT +//%token TOKEN_UINT8_CONSTANT +//%token TOKEN_INT16_CONSTANT +//%token TOKEN_UINT16_CONSTANT +//%token TOKEN_INT32_CONSTANT +//%token TOKEN_UINT32_CONSTANT +//%token TOKEN_INT64_CONSTANT +//%token TOKEN_UINT64_CONSTANT +//%token TOKEN_INT32DOTDOTDOT_CONSTANT +//%token TOKEN_UINT32DOTDOTDOT_CONSTANT +//%token TOKEN_INT64DOTDOTDOT_CONSTANT +//%token TOKEN_UINT64DOTDOTDOT_CONSTANT +//%token TOKEN_FLOAT16_CONSTANT +//%token TOKEN_FLOAT_CONSTANT +//%token TOKEN_DOUBLE_CONSTANT +//%token TOKEN_STRING_C_LITERAL +//%token TOKEN_STRING_SYCL_LITERAL +//%token TOKEN_IDENTIFIER +//%token TOKEN_STRING_LITERAL +//%token TOKEN_TYPE_NAME +//%token TOKEN_PRAGMA +//%token TOKEN_NULL +//%token TOKEN_TEMPLATE +//%token TOKEN_TEMPLATE_NAME +//%token TOKEN_TYPENAME +//%token TOKEN_PTR_OP +//%token TOKEN_INC_OP +//%token TOKEN_DEC_OP +//%token TOKEN_LEFT_OP +//%token TOKEN_RIGHT_OP +//%token TOKEN_LE_OP +//%token TOKEN_GE_OP +//%token TOKEN_EQ_OP +//%token TOKEN_NE_OP +//%token TOKEN_AND_OP +//%token TOKEN_OR_OP +//%token TOKEN_MUL_ASSIGN +//%token TOKEN_DIV_ASSIGN +//%token TOKEN_MOD_ASSIGN +//%token TOKEN_ADD_ASSIGN +//%token TOKEN_SUB_ASSIGN +//%token TOKEN_LEFT_ASSIGN +//%token TOKEN_RIGHT_ASSIGN +//%token TOKEN_AND_ASSIGN +//%token TOKEN_OR_ASSIGN +//%token TOKEN_XOR_ASSIGN +//%token TOKEN_SIZEOF +//%token TOKEN_NEW +//%token TOKEN_DELETE +//%token TOKEN_IN +//%token TOKEN_INTRINSIC_CALL +//%token TOKEN_ALLOCA +//%token TOKEN_EXTERN +//%token TOKEN_EXPORT +//%token TOKEN_STATIC +//%token TOKEN_INLINE +//%token TOKEN_NOINLINE +//%token TOKEN_VECTORCALL +//%token TOKEN_REGCALL +//%token TOKEN_TASK +//%token TOKEN_DECLSPEC +//%token TOKEN_UNIFORM +//%token TOKEN_VARYING +//%token TOKEN_TYPEDEF +//%token TOKEN_SOA +//%token TOKEN_UNMASKED +//%token TOKEN_INT +//%token TOKEN_SIGNED +//%token TOKEN_UNSIGNED +//%token TOKEN_FLOAT16 +//%token TOKEN_FLOAT +//%token TOKEN_DOUBLE +//%token TOKEN_INT8 +//%token TOKEN_INT16 +//%token TOKEN_INT64 +//%token TOKEN_CONST +//%token TOKEN_VOID +//%token TOKEN_BOOL +//%token TOKEN_UINT8 +//%token TOKEN_UINT16 +//%token TOKEN_UINT +//%token TOKEN_UINT64 +//%token TOKEN_ENUM +//%token TOKEN_STRUCT +//%token TOKEN_TRUE +//%token TOKEN_FALSE +//%token TOKEN_CASE +//%token TOKEN_DEFAULT +//%token TOKEN_IF +//%token TOKEN_ELSE +//%token TOKEN_SWITCH +//%token TOKEN_WHILE +//%token TOKEN_DO +//%token TOKEN_LAUNCH +//%token TOKEN_FOREACH +//%token TOKEN_FOREACH_TILED +//%token TOKEN_FOREACH_UNIQUE +//%token TOKEN_FOREACH_ACTIVE +//%token TOKEN_DOTDOTDOT +//%token TOKEN_FOR +//%token TOKEN_GOTO +//%token TOKEN_CONTINUE +//%token TOKEN_BREAK +//%token TOKEN_RETURN +//%token TOKEN_CIF +//%token TOKEN_CDO +//%token TOKEN_CFOR +//%token TOKEN_CWHILE +//%token TOKEN_SYNC +//%token TOKEN_PRINT +//%token TOKEN_ASSERT +//%token TOKEN_INVOKE_SYCL +//%token '(' +//%token ')' +//%token '[' +//%token ']' +//%token ',' +//%token '<' +//%token '>' +//%token '.' +//%token '&' +//%token '*' +//%token '+' +//%token '-' +//%token '~' +//%token '!' +//%token '/' +//%token '%' +//%token '^' +//%token '|' +//%token '?' +//%token ':' +//%token '=' +//%token ';' +//%token '{' +//%token '}' + +%nonassoc /*1*/ IF_WITHOUT_ELSE ; +%nonassoc /*2*/ TOKEN_ELSE ; + +//%start translation_unit + +//%% + +translation_unit : + external_declaration + | translation_unit external_declaration + //| error ';' + ; + +string_constant : + TOKEN_STRING_LITERAL + | string_constant TOKEN_STRING_LITERAL + ; + +primary_expression : + TOKEN_IDENTIFIER + | TOKEN_INT8_CONSTANT + | TOKEN_UINT8_CONSTANT + | TOKEN_INT16_CONSTANT + | TOKEN_UINT16_CONSTANT + | TOKEN_INT32_CONSTANT + | TOKEN_UINT32_CONSTANT + | TOKEN_INT64_CONSTANT + | TOKEN_UINT64_CONSTANT + | TOKEN_FLOAT16_CONSTANT + | TOKEN_FLOAT_CONSTANT + | TOKEN_DOUBLE_CONSTANT + | TOKEN_TRUE + | TOKEN_FALSE + | TOKEN_NULL + | '(' expression ')' + //| '(' error ')' + ; + +launch_expression : + TOKEN_LAUNCH postfix_expression '(' argument_expression_list ')' + | TOKEN_LAUNCH postfix_expression '(' ')' + | TOKEN_LAUNCH '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')' + | TOKEN_LAUNCH '[' assignment_expression ']' postfix_expression '(' ')' + | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ']' postfix_expression '(' argument_expression_list ')' + | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ']' postfix_expression '(' ')' + | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')' + | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' ')' + | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ',' assignment_expression ']' postfix_expression '(' argument_expression_list ')' + | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ',' assignment_expression ']' postfix_expression '(' ')' + | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')' + | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' ')' + | TOKEN_LAUNCH '<' postfix_expression '(' argument_expression_list ')' '>' + | TOKEN_LAUNCH '<' postfix_expression '(' ')' '>' + | TOKEN_LAUNCH '[' assignment_expression ']' '<' postfix_expression '(' argument_expression_list ')' '>' + | TOKEN_LAUNCH '[' assignment_expression ']' '<' postfix_expression '(' ')' '>' + ; + +invoke_sycl_expression : + TOKEN_INVOKE_SYCL '(' postfix_expression ')' + | TOKEN_INVOKE_SYCL '(' postfix_expression ',' argument_expression_list ')' + //| TOKEN_INVOKE_SYCL '(' error ')' + ; + +postfix_expression : + primary_expression + | postfix_expression '[' expression ']' + //| postfix_expression '[' error ']' + | launch_expression + | postfix_expression '.' TOKEN_IDENTIFIER + | postfix_expression TOKEN_PTR_OP TOKEN_IDENTIFIER + | postfix_expression TOKEN_INC_OP + | postfix_expression TOKEN_DEC_OP + ; + +intrinsic_name : + TOKEN_INTRINSIC_CALL + ; + +intrincall_expression : + intrinsic_name '(' argument_expression_list ')' + ; + +funcall_expression : + postfix_expression + | postfix_expression '(' ')' + | postfix_expression '(' argument_expression_list ')' + //| postfix_expression '(' error ')' + | simple_template_id '(' ')' + | simple_template_id '(' argument_expression_list ')' + //| simple_template_id '(' error ')' + ; + +argument_expression_list : + assignment_expression + | argument_expression_list ',' assignment_expression + ; + +unary_expression : + funcall_expression + | intrincall_expression + | invoke_sycl_expression + | TOKEN_INC_OP unary_expression + | TOKEN_DEC_OP unary_expression + | '&' unary_expression + | '*' unary_expression + | '+' cast_expression + | '-' cast_expression + | '~' cast_expression + | '!' cast_expression + | TOKEN_SIZEOF unary_expression + | TOKEN_SIZEOF '(' type_name ')' + | TOKEN_ALLOCA '(' assignment_expression ')' + ; + +cast_expression : + unary_expression + | '(' type_name ')' cast_expression + ; + +multiplicative_expression : + cast_expression + | multiplicative_expression '*' cast_expression + | multiplicative_expression '/' cast_expression + | multiplicative_expression '%' cast_expression + ; + +additive_expression : + multiplicative_expression + | additive_expression '+' multiplicative_expression + | additive_expression '-' multiplicative_expression + ; + +shift_expression : + additive_expression + | shift_expression TOKEN_LEFT_OP additive_expression + | shift_expression TOKEN_RIGHT_OP additive_expression + ; + +relational_expression : + shift_expression + | relational_expression '<' shift_expression + | relational_expression '>' shift_expression + | relational_expression TOKEN_LE_OP shift_expression + | relational_expression TOKEN_GE_OP shift_expression + ; + +equality_expression : + relational_expression + | equality_expression TOKEN_EQ_OP relational_expression + | equality_expression TOKEN_NE_OP relational_expression + ; + +and_expression : + equality_expression + | and_expression '&' equality_expression + ; + +exclusive_or_expression : + and_expression + | exclusive_or_expression '^' and_expression + ; + +inclusive_or_expression : + exclusive_or_expression + | inclusive_or_expression '|' exclusive_or_expression + ; + +logical_and_expression : + inclusive_or_expression + | logical_and_expression TOKEN_AND_OP inclusive_or_expression + ; + +logical_or_expression : + logical_and_expression + | logical_or_expression TOKEN_OR_OP logical_and_expression + ; + +conditional_expression : + logical_or_expression + | logical_or_expression '?' expression ':' conditional_expression + ; + +rate_qualified_new : + TOKEN_NEW + | TOKEN_UNIFORM TOKEN_NEW + | TOKEN_VARYING TOKEN_NEW + ; + +rate_qualified_type_specifier : + type_specifier + | TOKEN_UNIFORM type_specifier + | TOKEN_VARYING type_specifier + | soa_width_specifier type_specifier + ; + +new_expression : + conditional_expression + | rate_qualified_new rate_qualified_type_specifier + | rate_qualified_new rate_qualified_type_specifier '(' initializer_list ')' + | rate_qualified_new rate_qualified_type_specifier '[' expression ']' + ; + +assignment_expression : + new_expression + | unary_expression '=' assignment_expression + | unary_expression TOKEN_MUL_ASSIGN assignment_expression + | unary_expression TOKEN_DIV_ASSIGN assignment_expression + | unary_expression TOKEN_MOD_ASSIGN assignment_expression + | unary_expression TOKEN_ADD_ASSIGN assignment_expression + | unary_expression TOKEN_SUB_ASSIGN assignment_expression + | unary_expression TOKEN_LEFT_ASSIGN assignment_expression + | unary_expression TOKEN_RIGHT_ASSIGN assignment_expression + | unary_expression TOKEN_AND_ASSIGN assignment_expression + | unary_expression TOKEN_XOR_ASSIGN assignment_expression + | unary_expression TOKEN_OR_ASSIGN assignment_expression + ; + +expression : + assignment_expression + | expression ',' assignment_expression + ; + +constant_expression : + conditional_expression + ; + +declaration_statement : + declaration + ; + +declaration : + declaration_specifiers ';' + | declaration_specifiers init_declarator_list ';' + ; + +soa_width_specifier : + TOKEN_SOA '<' int_constant '>' + ; + +declspec_item : + TOKEN_IDENTIFIER + ; + +declspec_list : + declspec_item + | declspec_list ',' declspec_item + ; + +declspec_specifier : + TOKEN_DECLSPEC '(' declspec_list ')' + ; + +declaration_specifiers : + storage_class_specifier + | storage_class_specifier declaration_specifiers + | declspec_specifier + | declspec_specifier declaration_specifiers + | soa_width_specifier + | soa_width_specifier declaration_specifiers + | type_specifier + | type_specifier '<' int_constant '>' + | type_specifier declaration_specifiers + | type_qualifier + | type_qualifier declaration_specifiers + ; + +init_declarator_list : + init_declarator + | init_declarator_list ',' init_declarator + ; + +init_declarator : + declarator + | declarator '=' initializer + ; + +storage_class_specifier : + TOKEN_TYPEDEF + | TOKEN_EXTERN + | TOKEN_EXTERN TOKEN_STRING_C_LITERAL + | TOKEN_EXTERN TOKEN_STRING_SYCL_LITERAL + | TOKEN_STATIC + ; + +type_specifier : + atomic_var_type_specifier + | TOKEN_TYPE_NAME + | struct_or_union_specifier + | enum_specifier + ; + +type_specifier_list : + type_specifier + | type_specifier_list ',' type_specifier + ; + +atomic_var_type_specifier : + TOKEN_VOID + | TOKEN_BOOL + | TOKEN_INT8 + | TOKEN_UINT8 + | TOKEN_INT16 + | TOKEN_UINT16 + | TOKEN_INT + | TOKEN_UINT + | TOKEN_FLOAT16 + | TOKEN_FLOAT + | TOKEN_DOUBLE + | TOKEN_INT64 + | TOKEN_UINT64 + ; + +short_vec_specifier : + atomic_var_type_specifier '<' int_constant '>' + ; + +struct_or_union_name : + TOKEN_IDENTIFIER + | TOKEN_TYPE_NAME + ; + +struct_or_union_and_name : + struct_or_union struct_or_union_name + ; + +struct_or_union_specifier : + struct_or_union_and_name + | struct_or_union_and_name '{' struct_declaration_list '}' + | struct_or_union '{' struct_declaration_list '}' + | struct_or_union '{' '}' + | struct_or_union_and_name '{' '}' + ; + +struct_or_union : + TOKEN_STRUCT + ; + +struct_declaration_list : + struct_declaration + | struct_declaration_list struct_declaration + ; + +struct_declaration : + specifier_qualifier_list struct_declarator_list ';' + ; + +specifier_qualifier_list : + type_specifier specifier_qualifier_list + | type_specifier + | short_vec_specifier + | type_qualifier specifier_qualifier_list + ; + +struct_declarator_list : + struct_declarator + | struct_declarator_list ',' struct_declarator + ; + +struct_declarator : + declarator + ; + +enum_identifier : + TOKEN_IDENTIFIER + ; + +enum_specifier : + TOKEN_ENUM '{' enumerator_list '}' + | TOKEN_ENUM enum_identifier '{' enumerator_list '}' + | TOKEN_ENUM '{' enumerator_list ',' '}' + | TOKEN_ENUM enum_identifier '{' enumerator_list ',' '}' + | TOKEN_ENUM enum_identifier + ; + +enumerator_list : + enumerator + | enumerator_list ',' enumerator + ; + +enumerator : + enum_identifier + | enum_identifier '=' constant_expression + ; + +type_qualifier : + TOKEN_CONST + | TOKEN_UNIFORM + | TOKEN_VARYING + | TOKEN_TASK + | TOKEN_UNMASKED + | TOKEN_EXPORT + | TOKEN_INLINE + | TOKEN_NOINLINE + | TOKEN_VECTORCALL + | TOKEN_REGCALL + | TOKEN_SIGNED + | TOKEN_UNSIGNED + ; + +type_qualifier_list : + type_qualifier + | type_qualifier_list type_qualifier + ; + +declarator : + pointer direct_declarator + | reference direct_declarator + | direct_declarator + ; + +int_constant : + TOKEN_INT8_CONSTANT + | TOKEN_INT16_CONSTANT + | TOKEN_INT32_CONSTANT + | TOKEN_INT64_CONSTANT + ; + +direct_declarator : + TOKEN_IDENTIFIER + | TOKEN_TEMPLATE_NAME + | '(' declarator ')' + | direct_declarator '[' constant_expression ']' + | direct_declarator '[' ']' + //| direct_declarator '[' error ']' + | direct_declarator '(' parameter_type_list ')' + | direct_declarator '(' ')' + //| direct_declarator '(' error ')' + ; + +pointer : + '*' + | '*' type_qualifier_list + | '*' pointer + | '*' type_qualifier_list pointer + ; + +reference : + '&' + ; + +parameter_type_list : + parameter_list + ; + +parameter_list : + parameter_declaration + | parameter_list ',' parameter_declaration + //| error ',' + ; + +parameter_declaration : + declaration_specifiers declarator + | declaration_specifiers declarator '=' initializer + | declaration_specifiers abstract_declarator + | declaration_specifiers + ; + +type_name : + specifier_qualifier_list + | specifier_qualifier_list abstract_declarator + ; + +abstract_declarator : + pointer + | direct_abstract_declarator + | pointer direct_abstract_declarator + | reference + | reference direct_abstract_declarator + ; + +direct_abstract_declarator : + '(' abstract_declarator ')' + | '[' ']' + | '[' constant_expression ']' + | direct_abstract_declarator '[' ']' + | direct_abstract_declarator '[' constant_expression ']' + | '(' ')' + | '(' parameter_type_list ')' + | direct_abstract_declarator '(' ')' + | direct_abstract_declarator '(' parameter_type_list ')' + ; + +initializer : + assignment_expression + | '{' initializer_list '}' + | '{' initializer_list ',' '}' + ; + +initializer_list : + initializer + | initializer_list ',' initializer + ; + +pragma : + TOKEN_PRAGMA + ; + +attributed_statement : + pragma attributed_statement + | statement + ; + +statement : + labeled_statement + | compound_statement + | expression_statement + | selection_statement + | iteration_statement + | jump_statement + | declaration_statement + | print_statement + | assert_statement + | sync_statement + | delete_statement + | unmasked_statement + //| error ';' + ; + +labeled_statement : + goto_identifier ':' attributed_statement + | TOKEN_CASE constant_expression ':' attributed_statement + | TOKEN_DEFAULT ':' attributed_statement + ; + +start_scope : + '{' + ; + +end_scope : + '}' + ; + +compound_statement : + '{' '}' + | start_scope statement_list end_scope + ; + +statement_list : + attributed_statement + | statement_list attributed_statement + ; + +expression_statement : + ';' + | expression ';' + ; + +selection_statement : + TOKEN_IF '(' expression ')' attributed_statement %prec IF_WITHOUT_ELSE + | TOKEN_IF '(' expression ')' attributed_statement TOKEN_ELSE attributed_statement + | TOKEN_CIF '(' expression ')' attributed_statement %prec IF_WITHOUT_ELSE + | TOKEN_CIF '(' expression ')' attributed_statement TOKEN_ELSE attributed_statement + | TOKEN_SWITCH '(' expression ')' attributed_statement + ; + +for_test : + ';' + | expression ';' + ; + +for_init_statement : + expression_statement + | declaration_statement + ; + +for_scope : + TOKEN_FOR + ; + +cfor_scope : + TOKEN_CFOR + ; + +foreach_scope : + TOKEN_FOREACH + ; + +foreach_tiled_scope : + TOKEN_FOREACH_TILED + ; + +foreach_identifier : + TOKEN_IDENTIFIER + ; + +foreach_active_scope : + TOKEN_FOREACH_ACTIVE + ; + +foreach_active_identifier : + TOKEN_IDENTIFIER + ; + +integer_dotdotdot : + TOKEN_INT32DOTDOTDOT_CONSTANT + | TOKEN_UINT32DOTDOTDOT_CONSTANT + | TOKEN_INT64DOTDOTDOT_CONSTANT + | TOKEN_UINT64DOTDOTDOT_CONSTANT + ; + +foreach_dimension_specifier : + foreach_identifier '=' assignment_expression TOKEN_DOTDOTDOT assignment_expression + | foreach_identifier '=' integer_dotdotdot assignment_expression + ; + +foreach_dimension_list : + foreach_dimension_specifier + | foreach_dimension_list ',' foreach_dimension_specifier + ; + +foreach_unique_scope : + TOKEN_FOREACH_UNIQUE + ; + +foreach_unique_identifier : + TOKEN_IDENTIFIER + ; + +iteration_statement : + TOKEN_WHILE '(' expression ')' attributed_statement + | TOKEN_CWHILE '(' expression ')' attributed_statement + | TOKEN_DO attributed_statement TOKEN_WHILE '(' expression ')' ';' + | TOKEN_CDO attributed_statement TOKEN_WHILE '(' expression ')' ';' + | for_scope '(' for_init_statement for_test ')' attributed_statement + | for_scope '(' for_init_statement for_test expression ')' attributed_statement + | cfor_scope '(' for_init_statement for_test ')' attributed_statement + | cfor_scope '(' for_init_statement for_test expression ')' attributed_statement + | foreach_scope '(' foreach_dimension_list ')' attributed_statement + | foreach_tiled_scope '(' foreach_dimension_list ')' attributed_statement + | foreach_active_scope '(' foreach_active_identifier ')' attributed_statement + | foreach_unique_scope '(' foreach_unique_identifier TOKEN_IN expression ')' attributed_statement + ; + +goto_identifier : + TOKEN_IDENTIFIER + ; + +jump_statement : + TOKEN_GOTO goto_identifier ';' + | TOKEN_CONTINUE ';' + | TOKEN_BREAK ';' + | TOKEN_RETURN ';' + | TOKEN_RETURN expression ';' + ; + +sync_statement : + TOKEN_SYNC ';' + ; + +delete_statement : + TOKEN_DELETE expression ';' + ; + +unmasked_statement : + TOKEN_UNMASKED '{' statement_list '}' + ; + +print_statement : + TOKEN_PRINT '(' string_constant ')' ';' + | TOKEN_PRINT '(' string_constant ',' argument_expression_list ')' ';' + ; + +assert_statement : + TOKEN_ASSERT '(' string_constant ',' expression ')' ';' + ; + +external_declaration : + function_definition + | template_function_declaration_or_definition + | template_function_specialization + | template_function_instantiation + | TOKEN_EXTERN TOKEN_STRING_C_LITERAL '{' declaration '}' + | TOKEN_EXTERN TOKEN_STRING_SYCL_LITERAL '{' declaration '}' + | TOKEN_EXPORT '{' type_specifier_list '}' ';' + | declaration + | ';' + ; + +function_definition : + declaration_specifiers declarator compound_statement + ; + +template_type_parameter : + TOKEN_TYPENAME TOKEN_IDENTIFIER + | TOKEN_TYPENAME TOKEN_IDENTIFIER '=' type_specifier + ; + +template_int_parameter : + TOKEN_INT TOKEN_IDENTIFIER + ; + +template_parameter : + template_type_parameter + | template_int_parameter + ; + +template_parameter_list : + template_parameter + | template_parameter_list ',' template_parameter + ; + +template_head : + TOKEN_TEMPLATE '<' template_parameter_list '>' + ; + +template_declaration : + template_head declaration_specifiers declarator + ; + +template_function_declaration_or_definition : + template_declaration ';' + | template_declaration compound_statement + ; + +template_argument_list : + rate_qualified_type_specifier + | template_argument_list ',' rate_qualified_type_specifier + ; + +template_identifier : + TOKEN_TEMPLATE_NAME + ; + +simple_template_id : + template_identifier '<' template_argument_list '>' + | template_identifier + ; + +template_function_instantiation : + TOKEN_TEMPLATE declaration_specifiers simple_template_id '(' parameter_type_list ')' ';' + | TOKEN_TEMPLATE declaration_specifiers simple_template_id '(' ')' ';' + //| TOKEN_TEMPLATE declaration_specifiers simple_template_id '(' error ')' ';' + ; + +template_function_specialization : + TOKEN_TEMPLATE '<' '>' declaration_specifiers declarator ';' + | TOKEN_TEMPLATE '<' '>' declaration_specifiers declarator compound_statement + ; + +//Lexer + +TOKEN_ASSERT : 'assert' ; +TOKEN_BOOL : 'bool' ; +TOKEN_BREAK : 'break' ; +TOKEN_CASE : 'case' ; +TOKEN_CDO : 'cdo' ; +TOKEN_CFOR : 'cfor' ; +TOKEN_CIF : 'cif' ; +TOKEN_CWHILE : 'cwhile' ; +TOKEN_CONST : 'const' ; +TOKEN_CONTINUE : 'continue' ; +TOKEN_DEFAULT : 'default' ; +TOKEN_DO : 'do' ; +TOKEN_DELETE : 'delete' ; +TOKEN_DOUBLE : 'double' ; +TOKEN_ELSE : 'else' ; +TOKEN_ENUM : 'enum' ; +TOKEN_EXPORT : 'export' ; +TOKEN_EXTERN : 'extern' ; +TOKEN_FALSE : 'false' ; +TOKEN_FLOAT : 'float' ; +TOKEN_FLOAT16 : 'float16' ; +TOKEN_FOR : 'for' ; +TOKEN_FOREACH : 'foreach' ; +TOKEN_FOREACH_ACTIVE : 'foreach_active' ; +TOKEN_FOREACH_TILED : 'foreach_tiled' ; +TOKEN_FOREACH_UNIQUE : 'foreach_unique' ; +TOKEN_GOTO : 'goto' ; +TOKEN_IF : 'if' ; +TOKEN_IN : 'in' ; +TOKEN_INLINE : 'inline' ; +TOKEN_NOINLINE : 'noinline' ; +TOKEN_VECTORCALL : '__vectorcall' ; +TOKEN_REGCALL : '__regcall' ; +TOKEN_INT : 'int' ; +TOKEN_UINT : 'uint' ; +TOKEN_INT8 : 'int8' ; +TOKEN_UINT8 : 'uint8' ; +TOKEN_INT16 : 'int16' ; +TOKEN_UINT16 : 'uint16' ; +TOKEN_INT64 : 'int64' ; +TOKEN_UINT64 : 'uint64' ; +TOKEN_LAUNCH : 'launch' ; +TOKEN_INVOKE_SYCL : 'invoke_sycl' ; +TOKEN_NEW : 'new' ; +TOKEN_NULL : 'NULL' ; +TOKEN_PRINT : 'print' ; +TOKEN_RETURN : 'return' ; +TOKEN_SOA : 'soa' ; +TOKEN_SIGNED : 'signed' ; +TOKEN_SIZEOF : 'sizeof' ; +TOKEN_ALLOCA : 'alloca' ; +TOKEN_STATIC : 'static' ; +TOKEN_STRUCT : 'struct' ; +TOKEN_SWITCH : 'switch' ; +TOKEN_SYNC : 'sync' ; +TOKEN_TASK : 'task' ; +TOKEN_TEMPLATE : 'template' ; +TOKEN_TRUE : 'true' ; +TOKEN_TYPEDEF : 'typedef' ; +TOKEN_TYPENAME : 'typename' ; +TOKEN_UNIFORM : 'uniform' ; +TOKEN_UNMASKED : 'unmasked' ; +TOKEN_UNSIGNED : 'unsigned' ; +TOKEN_VARYING : 'varying' ; +TOKEN_VOID : 'void' ; +TOKEN_WHILE : 'while' ; +TOKEN_STRING_C_LITERAL : '"C"' ; +TOKEN_STRING_SYCL_LITERAL : '"SYCL"' ; +TOKEN_DOTDOTDOT : '...' ; +TOKEN_INC_OP : '++' ; +TOKEN_DEC_OP : '--' ; +TOKEN_LEFT_OP : '<<' ; +TOKEN_RIGHT_OP : '>>' ; +TOKEN_LE_OP : '<=' ; +TOKEN_GE_OP : '>=' ; +TOKEN_EQ_OP : '==' ; +TOKEN_NE_OP : '!=' ; +TOKEN_AND_OP : '&&' ; +TOKEN_OR_OP : '||' ; +TOKEN_MUL_ASSIGN : '*=' ; +TOKEN_DIV_ASSIGN : '/=' ; +TOKEN_MOD_ASSIGN : '%=' ; +TOKEN_ADD_ASSIGN : '+=' ; +TOKEN_SUB_ASSIGN : '-=' ; +TOKEN_LEFT_ASSIGN : '<<=' ; +TOKEN_RIGHT_ASSIGN : '>>=' ; +TOKEN_AND_ASSIGN : '&=' ; +TOKEN_XOR_ASSIGN : '^=' ; +TOKEN_OR_ASSIGN : '|=' ; +TOKEN_PTR_OP : '->' ; + +TOKEN_PRAGMA : '#pragma' ; +TOKEN_DECLSPEC : '__declspec' ; + + +TOKEN_STRING_LITERAL : "\"([^\"\n]|\\[^\n])*\"" ; +TOKEN_IDENTIFIER : "[a-zA-Z_][a-zA-Z_0-9]*" ; +TOKEN_INTRINSIC_CALL : "@llvm[.][.a-zA-Z_0-9]*" ; + +TOKEN_FLOAT16_CONSTANT : 'TOKEN_FLOAT16_CONSTANT' ; +TOKEN_FLOAT_CONSTANT : 'TOKEN_FLOAT_CONSTANT' ; +TOKEN_DOUBLE_CONSTANT : "[0-9]+[.][0-9]*" ; + +TOKEN_INT8_CONSTANT : 'TOKEN_INT8_CONSTANT' ; +TOKEN_UINT8_CONSTANT : 'TOKEN_UINT8_CONSTANT' ; +TOKEN_INT16_CONSTANT : 'TOKEN_INT16_CONSTANT' ; +TOKEN_UINT16_CONSTANT : 'TOKEN_UINT16_CONSTANT' ; +TOKEN_INT32_CONSTANT : 'TOKEN_INT32_CONSTANT' ; +TOKEN_UINT32_CONSTANT : "0[xX][a-fA-F0-9]+|[0-9]+" ; +TOKEN_INT64_CONSTANT : 'TOKEN_INT64_CONSTANT' ; +TOKEN_UINT64_CONSTANT : 'TOKEN_UINT64_CONSTANT' ; + +TOKEN_TYPE_NAME : 'TOKEN_TYPE_NAME' ; +TOKEN_TEMPLATE_NAME : 'TOKEN_TEMPLATE_NAME' ; +TOKEN_INT32DOTDOTDOT_CONSTANT : 'TOKEN_INT32DOTDOTDOT_CONSTANT' ; +TOKEN_UINT32DOTDOTDOT_CONSTANT : 'TOKEN_UINT32DOTDOTDOT_CONSTANT' ; +TOKEN_INT64DOTDOTDOT_CONSTANT : 'TOKEN_INT64DOTDOTDOT_CONSTANT' ; +TOKEN_UINT64DOTDOTDOT_CONSTANT : 'TOKEN_UINT64DOTDOTDOT_CONSTANT' ; + +} diff --git a/playground/iverilog-parser.g b/playground/iverilog-parser.g new file mode 100644 index 0000000..2df58a2 --- /dev/null +++ b/playground/iverilog-parser.g @@ -0,0 +1,2922 @@ +//From: https://github.com/steveicarus/iverilog/blob/master/parse.y +iverilog { + +//%error_recovery_show; +%error_recovery_off; +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token IDENTIFIER +//%token SYSTEM_IDENTIFIER +//%token STRING +//%token TIME_LITERAL +//%token TYPE_IDENTIFIER +//%token PACKAGE_IDENTIFIER +//%token DISCIPLINE_IDENTIFIER +//%token PATHPULSE_IDENTIFIER +//%token BASED_NUMBER +//%token DEC_NUMBER +//%token UNBASED_NUMBER +//%token REALTIME +//%token K_PLUS_EQ +//%token K_MINUS_EQ +//%token K_INCR +//%token K_DECR +//%token K_LE +//%token K_GE +//%token K_EG +//%token K_EQ +//%token K_NE +//%token K_CEQ +//%token K_CNE +//%token K_WEQ +//%token K_WNE +//%token K_LP +//%token K_LS +//%token K_RS +//%token K_RSS +//%token K_SG +//%token K_CONTRIBUTE +//%token K_PO_POS +//%token K_PO_NEG +//%token K_POW +//%token K_PSTAR +//%token K_STARP +//%token K_DOTSTAR +//%token K_LOR +//%token K_LAND +//%token K_NAND +//%token K_NOR +//%token K_NXOR +//%token K_TRIGGER +//%token K_NB_TRIGGER +//%token K_LEQUIV +//%token K_SCOPE_RES +//%token K_edge_descriptor +//%token K_CONSTRAINT_IMPL +//%token K_always +//%token K_and +//%token K_assign +//%token K_begin +//%token K_buf +//%token K_bufif0 +//%token K_bufif1 +//%token K_case +//%token K_casex +//%token K_casez +//%token K_cmos +//%token K_deassign +//%token K_default +//%token K_defparam +//%token K_disable +//%token K_edge +//%token K_else +//%token K_end +//%token K_endcase +//%token K_endfunction +//%token K_endmodule +//%token K_endprimitive +//%token K_endspecify +//%token K_endtable +//%token K_endtask +//%token K_event +//%token K_for +//%token K_force +//%token K_forever +//%token K_fork +//%token K_function +//%token K_highz0 +//%token K_highz1 +//%token K_if +//%token K_ifnone +//%token K_initial +//%token K_inout +//%token K_input +//%token K_integer +//%token K_join +//%token K_large +//%token K_macromodule +//%token K_medium +//%token K_module +//%token K_nand +//%token K_negedge +//%token K_nmos +//%token K_nor +//%token K_not +//%token K_notif0 +//%token K_notif1 +//%token K_or +//%token K_output +//%token K_parameter +//%token K_pmos +//%token K_posedge +//%token K_primitive +//%token K_pull0 +//%token K_pull1 +//%token K_pulldown +//%token K_pullup +//%token K_rcmos +//%token K_real +//%token K_realtime +//%token K_reg +//%token K_release +//%token K_repeat +//%token K_rnmos +//%token K_rpmos +//%token K_rtran +//%token K_rtranif0 +//%token K_rtranif1 +//%token K_scalared +//%token K_small +//%token K_specify +//%token K_specparam +//%token K_strong0 +//%token K_strong1 +//%token K_supply0 +//%token K_supply1 +//%token K_table +//%token K_task +//%token K_time +//%token K_tran +//%token K_tranif0 +//%token K_tranif1 +//%token K_tri +//%token K_tri0 +//%token K_tri1 +//%token K_triand +//%token K_trior +//%token K_trireg +//%token K_vectored +//%token K_wait +//%token K_wand +//%token K_weak0 +//%token K_weak1 +//%token K_while +//%token K_wire +//%token K_wor +//%token K_xnor +//%token K_xor +//%token K_Shold +//%token K_Snochange +//%token K_Speriod +//%token K_Srecovery +//%token K_Ssetup +//%token K_Ssetuphold +//%token K_Sskew +//%token K_Swidth +//%token KK_attribute +//%token K_bool +//%token K_logic +//%token K_automatic +//%token K_endgenerate +//%token K_generate +//%token K_genvar +//%token K_localparam +//%token K_noshowcancelled +//%token K_pulsestyle_onevent +//%token K_pulsestyle_ondetect +//%token K_showcancelled +//%token K_signed +//%token K_unsigned +//%token K_Sfullskew +//%token K_Srecrem +//%token K_Sremoval +//%token K_Stimeskew +//%token K_cell +//%token K_config +//%token K_design +//%token K_endconfig +//%token K_incdir +//%token K_include +//%token K_instance +//%token K_liblist +//%token K_library +//%token K_use +//%token K_wone +//%token K_uwire +//%token K_alias +//%token K_always_comb +//%token K_always_ff +//%token K_always_latch +//%token K_assert +//%token K_assume +//%token K_before +//%token K_bind +//%token K_bins +//%token K_binsof +//%token K_bit +//%token K_break +//%token K_byte +//%token K_chandle +//%token K_class +//%token K_clocking +//%token K_const +//%token K_constraint +//%token K_context +//%token K_continue +//%token K_cover +//%token K_covergroup +//%token K_coverpoint +//%token K_cross +//%token K_dist +//%token K_do +//%token K_endclass +//%token K_endclocking +//%token K_endgroup +//%token K_endinterface +//%token K_endpackage +//%token K_endprogram +//%token K_endproperty +//%token K_endsequence +//%token K_enum +//%token K_expect +//%token K_export +//%token K_extends +//%token K_extern +//%token K_final +//%token K_first_match +//%token K_foreach +//%token K_forkjoin +//%token K_iff +//%token K_ignore_bins +//%token K_illegal_bins +//%token K_import +//%token K_inside +//%token K_int +//%token K_interface +//%token K_intersect +//%token K_join_any +//%token K_join_none +//%token K_local +//%token K_longint +//%token K_matches +//%token K_modport +//%token K_new +//%token K_null +//%token K_package +//%token K_packed +//%token K_priority +//%token K_program +//%token K_property +//%token K_protected +//%token K_pure +//%token K_rand +//%token K_randc +//%token K_randcase +//%token K_randsequence +//%token K_ref +//%token K_return +//%token K_sequence +//%token K_shortint +//%token K_shortreal +//%token K_solve +//%token K_static +//%token K_string +//%token K_struct +//%token K_super +//%token K_tagged +//%token K_this +//%token K_throughout +//%token K_timeprecision +//%token K_timeunit +//%token K_type +//%token K_typedef +//%token K_union +//%token K_unique +//%token K_var +//%token K_virtual +//%token K_void +//%token K_wait_order +//%token K_wildcard +//%token K_with +//%token K_within +//%token K_accept_on +//%token K_checker +//%token K_endchecker +//%token K_eventually +//%token K_global +//%token K_implies +//%token K_let +//%token K_nexttime +//%token K_reject_on +//%token K_restrict +//%token K_s_always +//%token K_s_eventually +//%token K_s_nexttime +//%token K_s_until +//%token K_s_until_with +//%token K_strong +//%token K_sync_accept_on +//%token K_sync_reject_on +//%token K_unique0 +//%token K_until +//%token K_until_with +//%token K_untyped +//%token K_weak +//%token K_implements +//%token K_interconnect +//%token K_nettype +//%token K_soft +//%token K_above +//%token K_abs +//%token K_absdelay +//%token K_abstol +//%token K_access +//%token K_acos +//%token K_acosh +//%token K_ac_stim +//%token K_aliasparam +//%token K_analog +//%token K_analysis +//%token K_asin +//%token K_asinh +//%token K_atan +//%token K_atan2 +//%token K_atanh +//%token K_branch +//%token K_ceil +//%token K_connect +//%token K_connectmodule +//%token K_connectrules +//%token K_continuous +//%token K_cos +//%token K_cosh +//%token K_ddt +//%token K_ddt_nature +//%token K_ddx +//%token K_discipline +//%token K_discrete +//%token K_domain +//%token K_driver_update +//%token K_endconnectrules +//%token K_enddiscipline +//%token K_endnature +//%token K_endparamset +//%token K_exclude +//%token K_exp +//%token K_final_step +//%token K_flicker_noise +//%token K_floor +//%token K_flow +//%token K_from +//%token K_ground +//%token K_hypot +//%token K_idt +//%token K_idtmod +//%token K_idt_nature +//%token K_inf +//%token K_initial_step +//%token K_laplace_nd +//%token K_laplace_np +//%token K_laplace_zd +//%token K_laplace_zp +//%token K_last_crossing +//%token K_limexp +//%token K_ln +//%token K_log +//%token K_max +//%token K_merged +//%token K_min +//%token K_nature +//%token K_net_resolution +//%token K_noise_table +//%token K_paramset +//%token K_potential +//%token K_pow +//%token K_resolveto +//%token K_sin +//%token K_sinh +//%token K_slew +//%token K_split +//%token K_sqrt +//%token K_tan +//%token K_tanh +//%token K_timer +//%token K_transition +//%token K_units +//%token K_white_noise +//%token K_wreal +//%token K_zi_nd +//%token K_zi_np +//%token K_zi_zd +//%token K_zi_zp +//%token K_TAND +//%token K_MUL_EQ +//%token K_DIV_EQ +//%token K_MOD_EQ +//%token K_AND_EQ +//%token K_OR_EQ +//%token K_XOR_EQ +//%token K_LS_EQ +//%token K_RS_EQ +//%token K_RSS_EQ +//%token '?' +//%token ':' +//%token '|' +//%token '^' +//%token '&' +//%token '<' +//%token '>' +//%token '+' +//%token '-' +//%token '*' +//%token '/' +//%token '%' +//%token UNARY_PREC +//%token less_than_K_else +//%token '(' +//%token no_timeunits_declaration +//%token one_timeunits_declaration +//%token '}' +//%token ';' +//%token ')' +//%token '{' +//%token '[' +//%token ']' +//%token '#' +//%token ',' +//%token '=' +//%token '.' +//%token '$' +//%token '@' +//%token '~' +//%token '!' +//%token '\'' +//%token '0' +//%token '1' +//%token 'x' +//%token 'b' +//%token 'f' +//%token 'F' +//%token 'l' +//%token 'h' +//%token 'B' +//%token 'r' +//%token 'R' +//%token 'M' +//%token 'n' +//%token 'N' +//%token 'p' +//%token 'P' +//%token 'Q' +//%token 'q' +//%token '_' + +%nonassoc /*1*/ K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ ; +%nonassoc /*2*/ K_NB_TRIGGER K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ ; +%right /*3*/ K_TRIGGER K_LEQUIV ; +%right /*4*/ K_inside '?' ':' ; +%left /*5*/ K_LOR ; +%left /*6*/ K_LAND ; +%left /*7*/ '|' ; +%left /*8*/ K_NOR K_NXOR '^' ; +%left /*9*/ K_NAND '&' ; +%left /*10*/ K_EQ K_NE K_CEQ K_CNE K_WEQ K_WNE ; +%left /*11*/ K_LE K_GE '<' '>' ; +%left /*12*/ K_LS K_RS K_RSS ; +%left /*13*/ '+' '-' ; +%left /*14*/ '*' '/' '%' ; +%left /*15*/ K_POW ; +%left /*16*/ UNARY_PREC ; +%nonassoc /*17*/ less_than_K_else ; +%nonassoc /*18*/ K_else ; +%nonassoc /*19*/ '(' ; +%nonassoc /*20*/ K_exclude ; +%nonassoc /*21*/ no_timeunits_declaration ; +%nonassoc /*22*/ one_timeunits_declaration ; +%nonassoc /*23*/ K_timeprecision K_timeunit ; + +//%start source_text + +//%% + +source_text : + /*YYEOF + |*/ timeunits_declaration_opt description_list + | /*empty*/ + ; + +assert_or_assume : + K_assert + | K_assume + ; + +assertion_item : + concurrent_assertion_item + | deferred_immediate_assertion_item + ; + +assignment_pattern : + K_LP expression_list_proper '}' + | K_LP '}' + ; + +block_identifier_opt : + IDENTIFIER ':' /*4R*/ + | /*empty*/ + ; + +class_declaration : + K_virtual_opt K_class lifetime_opt identifier_name class_declaration_extends_opt ';' class_items_opt K_endclass class_declaration_endlabel_opt + ; + +class_constraint : + constraint_prototype + | constraint_declaration + ; + +identifier_name : + IDENTIFIER + | TYPE_IDENTIFIER + ; + +class_declaration_endlabel_opt : + ':' /*4R*/ identifier_name + | /*empty*/ + ; + +class_declaration_extends_opt : + K_extends ps_type_identifier argument_list_parens_opt + | /*empty*/ + ; + +class_items_opt : + class_items + | /*empty*/ + ; + +class_items : + class_items class_item + | class_item + ; + +class_item : + method_qualifier_opt K_function K_new tf_port_list_parens_opt ';' block_item_decls_opt statement_or_null_list_opt K_endfunction endnew_opt + | property_qualifier_opt data_type list_of_variable_decl_assignments ';' + | K_const class_item_qualifier_opt data_type list_of_variable_decl_assignments ';' + | property_qualifier_opt type_declaration + | method_qualifier_opt task_declaration + | method_qualifier_opt function_declaration + | K_extern method_qualifier_opt K_function K_new tf_port_list_parens_opt ';' + | K_extern method_qualifier_opt K_function data_type_or_implicit_or_void IDENTIFIER tf_port_list_parens_opt ';' + | K_extern method_qualifier_opt K_task IDENTIFIER tf_port_list_parens_opt ';' + | class_constraint + | property_qualifier_opt data_type error ';' + | property_qualifier_opt IDENTIFIER error ';' + | method_qualifier_opt K_function K_new error K_endfunction endnew_opt + | parameter_declaration + | ';' + | error ';' + ; + +class_item_qualifier : + K_static + | K_protected + | K_local + ; + +class_item_qualifier_list : + class_item_qualifier_list class_item_qualifier + | class_item_qualifier + ; + +class_item_qualifier_opt : + class_item_qualifier_list + | /*empty*/ + ; + +class_scope : + ps_type_identifier K_SCOPE_RES + ; + +class_new : + K_new argument_list_parens_opt + | class_scope K_new argument_list_parens_opt + | K_new hierarchy_identifier + ; + +concurrent_assertion_item : + block_identifier_opt concurrent_assertion_statement + ; + +concurrent_assertion_statement : + assert_or_assume K_property '(' /*19N*/ property_spec ')' statement_or_null %prec less_than_K_else /*17N*/ + | assert_or_assume K_property '(' /*19N*/ property_spec ')' K_else /*18N*/ statement_or_null + | assert_or_assume K_property '(' /*19N*/ property_spec ')' statement_or_null K_else /*18N*/ statement_or_null + | K_cover K_property '(' /*19N*/ property_spec ')' statement_or_null + | K_cover K_sequence '(' /*19N*/ property_spec ')' statement_or_null + | K_restrict K_property '(' /*19N*/ property_spec ')' ';' + | assert_or_assume K_property '(' /*19N*/ error ')' statement_or_null %prec less_than_K_else /*17N*/ + | assert_or_assume K_property '(' /*19N*/ error ')' K_else /*18N*/ statement_or_null + | assert_or_assume K_property '(' /*19N*/ error ')' statement_or_null K_else /*18N*/ statement_or_null + | K_cover K_property '(' /*19N*/ error ')' statement_or_null + | K_cover K_sequence '(' /*19N*/ error ')' statement_or_null + | K_restrict K_property '(' /*19N*/ error ')' ';' + ; + +constraint_block_item : + constraint_expression + ; + +constraint_block_item_list : + constraint_block_item_list constraint_block_item + | constraint_block_item + ; + +constraint_block_item_list_opt : + /*empty*/ + | constraint_block_item_list + ; + +constraint_declaration : + K_static_opt K_constraint IDENTIFIER '{' constraint_block_item_list_opt '}' + | K_static_opt K_constraint IDENTIFIER '{' error '}' + ; + +constraint_expression : + expression ';' + | expression K_dist '{' '}' ';' + | expression constraint_trigger + | K_if '(' /*19N*/ expression ')' constraint_set %prec less_than_K_else /*17N*/ + | K_if '(' /*19N*/ expression ')' constraint_set K_else /*18N*/ constraint_set + | K_foreach '(' /*19N*/ IDENTIFIER '[' loop_variables ']' ')' constraint_set + ; + +constraint_trigger : + K_CONSTRAINT_IMPL '{' constraint_expression_list '}' + ; + +constraint_expression_list : + constraint_expression_list constraint_expression + | constraint_expression + ; + +constraint_prototype : + K_static_opt K_constraint IDENTIFIER ';' + ; + +constraint_set : + constraint_expression + | '{' constraint_expression_list '}' + ; + +data_declaration : + attribute_list_opt data_type list_of_variable_decl_assignments ';' + | attribute_list_opt K_var data_type_or_implicit list_of_variable_decl_assignments ';' + | attribute_list_opt K_event event_variable_list ';' + | attribute_list_opt package_import_declaration + ; + +package_scope : + PACKAGE_IDENTIFIER K_SCOPE_RES + ; + +ps_type_identifier : + TYPE_IDENTIFIER + | package_scope TYPE_IDENTIFIER + ; + +packed_array_data_type : + enum_data_type + | struct_data_type + | ps_type_identifier + ; + +simple_packed_type : + integer_vector_type unsigned_signed_opt dimensions_opt + | atom_type signed_unsigned_opt + | K_time unsigned_signed_opt + ; + +data_type : + simple_packed_type + | non_integer_type + | packed_array_data_type dimensions_opt + | K_string + ; + +data_type_opt : + data_type + | /*empty*/ + ; + +scalar_vector_opt : + K_vectored + | K_scalared + | /*empty*/ + ; + +data_type_or_implicit : + data_type_or_implicit_no_opt + | /*empty*/ + ; + +data_type_or_implicit_no_opt : + data_type + | signing dimensions_opt + | scalar_vector_opt dimensions + ; + +data_type_or_implicit_or_void : + data_type_or_implicit + | K_void + ; + +deferred_immediate_assertion_item : + block_identifier_opt deferred_immediate_assertion_statement + ; + +deferred_immediate_assertion_statement : + assert_or_assume deferred_mode '(' /*19N*/ expression ')' statement_or_null %prec less_than_K_else /*17N*/ + | assert_or_assume deferred_mode '(' /*19N*/ expression ')' K_else /*18N*/ statement_or_null + | assert_or_assume deferred_mode '(' /*19N*/ expression ')' statement_or_null K_else /*18N*/ statement_or_null + | K_cover deferred_mode '(' /*19N*/ expression ')' statement_or_null + | assert_or_assume deferred_mode '(' /*19N*/ error ')' statement_or_null %prec less_than_K_else /*17N*/ + | assert_or_assume deferred_mode '(' /*19N*/ error ')' K_else /*18N*/ statement_or_null + | assert_or_assume deferred_mode '(' /*19N*/ error ')' statement_or_null K_else /*18N*/ statement_or_null + | K_cover deferred_mode '(' /*19N*/ error ')' statement_or_null + ; + +deferred_mode : + '#' DEC_NUMBER + | K_final + ; + +description : + module + | udp_primitive + | config_declaration + | nature_declaration + | package_declaration + | discipline_declaration + | package_item + | KK_attribute '(' /*19N*/ IDENTIFIER ',' STRING ',' STRING ')' + | ';' + ; + +description_list : + description + | description_list description + ; + +endnew_opt : + ':' /*4R*/ K_new + | /*empty*/ + ; + +dynamic_array_new : + K_new '[' expression ']' + | K_new '[' expression ']' '(' /*19N*/ expression ')' + ; + +for_step : + lpvalue '=' expression + | inc_or_dec_expression + | compressed_statement + ; + +for_step_opt : + for_step + | /*empty*/ + ; + +function_declaration : + K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER ';' tf_item_list_opt statement_or_null_list_opt K_endfunction label_opt + | K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER '(' /*19N*/ tf_port_list_opt ')' ';' block_item_decls_opt statement_or_null_list_opt K_endfunction label_opt + | K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction label_opt + ; + +genvar_iteration : + IDENTIFIER '=' expression + | IDENTIFIER compressed_operator expression + | IDENTIFIER K_INCR + | IDENTIFIER K_DECR + | K_INCR IDENTIFIER + | K_DECR IDENTIFIER + ; + +import_export : + K_import + | K_export + ; + +implicit_class_handle : + K_this '.' + | K_super '.' + | K_this '.' K_super '.' + ; + +class_hierarchy_identifier : + implicit_class_handle hierarchy_identifier + ; + +inc_or_dec_expression : + K_INCR lpvalue %prec UNARY_PREC /*16L*/ + | lpvalue K_INCR %prec UNARY_PREC /*16L*/ + | K_DECR lpvalue %prec UNARY_PREC /*16L*/ + | lpvalue K_DECR %prec UNARY_PREC /*16L*/ + ; + +inside_expression : + expression K_inside /*4R*/ '{' open_range_list '}' + ; + +integer_vector_type : + K_reg + | K_bit + | K_logic + | K_bool + ; + +join_keyword : + K_join + | K_join_none + | K_join_any + ; + +jump_statement : + K_break ';' + | K_continue ';' + | K_return ';' + | K_return expression ';' + ; + +lifetime : + K_automatic + | K_static + ; + +lifetime_opt : + lifetime + | /*empty*/ + ; + +loop_statement : + K_for '(' /*19N*/ lpvalue '=' expression ';' expression ';' for_step_opt ')' statement_or_null + | K_for '(' /*19N*/ ';' expression ';' for_step_opt ')' statement_or_null + | K_for '(' /*19N*/ K_var_opt data_type IDENTIFIER '=' expression ';' expression ';' for_step_opt ')' statement_or_null + | K_forever statement_or_null + | K_repeat '(' /*19N*/ expression ')' statement_or_null + | K_while '(' /*19N*/ expression ')' statement_or_null + | K_do statement_or_null K_while '(' /*19N*/ expression ')' ';' + | K_foreach '(' /*19N*/ IDENTIFIER '[' loop_variables ']' ')' statement_or_null + | K_for '(' /*19N*/ lpvalue '=' expression ';' expression ';' error ')' statement_or_null + | K_for '(' /*19N*/ lpvalue '=' expression ';' error ';' for_step_opt ')' statement_or_null + | K_for '(' /*19N*/ error ')' statement_or_null + | K_while '(' /*19N*/ error ')' statement_or_null + | K_do statement_or_null K_while '(' /*19N*/ error ')' ';' + | K_foreach '(' /*19N*/ IDENTIFIER '[' error ']' ')' statement_or_null + ; + +list_of_variable_decl_assignments : + variable_decl_assignment + | list_of_variable_decl_assignments ',' variable_decl_assignment + ; + +initializer_opt : + '=' expression + | /*empty*/ + ; + +var_decl_initializer_opt : + initializer_opt + | '=' class_new + | '=' dynamic_array_new + ; + +variable_decl_assignment : + IDENTIFIER dimensions_opt var_decl_initializer_opt + ; + +loop_variables : + loop_variables ',' IDENTIFIER + | loop_variables ',' + | IDENTIFIER + | /*empty*/ + ; + +method_qualifier : + K_virtual + | class_item_qualifier + ; + +method_qualifier_opt : + method_qualifier + | /*empty*/ + ; + +modport_declaration : + K_modport modport_item_list ';' + ; + +modport_item_list : + modport_item + | modport_item_list ',' modport_item + ; + +modport_item : + IDENTIFIER '(' /*19N*/ modport_ports_list ')' + ; + +modport_ports_list : + modport_ports_declaration + | modport_ports_list ',' modport_ports_declaration + | modport_ports_list ',' modport_simple_port + | modport_ports_list ',' modport_tf_port + | modport_ports_list ',' IDENTIFIER + | modport_ports_list ',' + ; + +modport_ports_declaration : + attribute_list_opt port_direction IDENTIFIER + | attribute_list_opt port_direction modport_simple_port + | attribute_list_opt import_export IDENTIFIER + | attribute_list_opt import_export modport_tf_port + | attribute_list_opt K_clocking IDENTIFIER + ; + +modport_simple_port : + '.' IDENTIFIER '(' /*19N*/ expression ')' + ; + +modport_tf_port : + K_task IDENTIFIER tf_port_list_parens_opt + | K_function data_type_or_implicit_or_void IDENTIFIER tf_port_list_parens_opt + ; + +non_integer_type : + K_real + | K_realtime + | K_shortreal + ; + +number : + BASED_NUMBER + | DEC_NUMBER + | DEC_NUMBER BASED_NUMBER + | UNBASED_NUMBER + | DEC_NUMBER UNBASED_NUMBER + ; + +open_range_list : + open_range_list ',' value_range + | value_range + ; + +package_declaration : + K_package lifetime_opt IDENTIFIER ';' timeunits_declaration_opt package_item_list_opt K_endpackage label_opt + ; + +module_package_import_list_opt : + /*empty*/ + | package_import_list + ; + +package_import_list : + package_import_declaration + | package_import_list package_import_declaration + ; + +package_import_declaration : + K_import package_import_item_list ';' + ; + +package_import_item : + package_scope IDENTIFIER + | package_scope TYPE_IDENTIFIER + | package_scope '*' /*14L*/ + ; + +package_import_item_list : + package_import_item_list ',' package_import_item + | package_import_item + ; + +package_export_declaration : + K_export package_export_item_list ';' + | K_export '*' /*14L*/ K_SCOPE_RES '*' /*14L*/ ';' + ; + +package_export_item : + PACKAGE_IDENTIFIER K_SCOPE_RES IDENTIFIER + | PACKAGE_IDENTIFIER K_SCOPE_RES TYPE_IDENTIFIER + | PACKAGE_IDENTIFIER K_SCOPE_RES '*' /*14L*/ + ; + +package_export_item_list : + package_export_item_list ',' package_export_item + | package_export_item + ; + +package_item : + timeunits_declaration + | parameter_declaration + | type_declaration + | function_declaration + | task_declaration + | data_declaration + | class_declaration + | package_export_declaration + ; + +package_item_list : + package_item_list package_item + | package_item + ; + +package_item_list_opt : + package_item_list + | /*empty*/ + ; + +port_direction : + K_input + | K_output + | K_inout + | K_ref + ; + +port_direction_opt : + port_direction + | /*empty*/ + ; + +procedural_assertion_statement : + block_identifier_opt concurrent_assertion_statement + | block_identifier_opt simple_immediate_assertion_statement + | block_identifier_opt deferred_immediate_assertion_statement + ; + +property_expr : + expression + ; + +property_qualifier : + class_item_qualifier + | random_qualifier + ; + +property_qualifier_opt : + property_qualifier_list + | /*empty*/ + ; + +property_qualifier_list : + property_qualifier_list property_qualifier + | property_qualifier + ; + +property_spec : + clocking_event_opt property_spec_disable_iff_opt property_expr + ; + +property_spec_disable_iff_opt : + K_disable K_iff '(' /*19N*/ expression ')' + | /*empty*/ + ; + +random_qualifier : + K_rand + | K_randc + ; + +signing : + K_signed + | K_unsigned + ; + +simple_immediate_assertion_statement : + assert_or_assume '(' /*19N*/ expression ')' statement_or_null %prec less_than_K_else /*17N*/ + | assert_or_assume '(' /*19N*/ expression ')' K_else /*18N*/ statement_or_null + | assert_or_assume '(' /*19N*/ expression ')' statement_or_null K_else /*18N*/ statement_or_null + | K_cover '(' /*19N*/ expression ')' statement_or_null + | assert_or_assume '(' /*19N*/ error ')' statement_or_null %prec less_than_K_else /*17N*/ + | assert_or_assume '(' /*19N*/ error ')' K_else /*18N*/ statement_or_null + | assert_or_assume '(' /*19N*/ error ')' statement_or_null K_else /*18N*/ statement_or_null + | K_cover '(' /*19N*/ error ')' statement_or_null + ; + +simple_type_or_string : + integer_vector_type + | non_integer_type + | atom_type + | K_time + | K_string + | ps_type_identifier + ; + +statement : + attribute_list_opt statement_item + ; + +statement_or_null : + statement + | attribute_list_opt ';' + ; + +stream_expression : + expression + ; + +stream_expression_list : + stream_expression_list ',' stream_expression + | stream_expression + ; + +stream_operator : + K_LS /*12L*/ + | K_RS /*12L*/ + ; + +streaming_concatenation : + '{' stream_operator '{' stream_expression_list '}' '}' + ; + +task_declaration : + K_task lifetime_opt IDENTIFIER ';' tf_item_list_opt statement_or_null_list_opt K_endtask label_opt + | K_task lifetime_opt IDENTIFIER '(' /*19N*/ tf_port_list_opt ')' ';' block_item_decls_opt statement_or_null_list_opt K_endtask label_opt + | K_task lifetime_opt IDENTIFIER error K_endtask label_opt + ; + +tf_port_declaration : + port_direction K_var_opt data_type_or_implicit list_of_port_identifiers ';' + ; + +tf_port_item : + port_direction_opt K_var_opt data_type_or_implicit IDENTIFIER dimensions_opt initializer_opt + | port_direction_opt K_var_opt data_type_or_implicit IDENTIFIER error + ; + +tf_port_list : + tf_port_item_list + ; + +tf_port_item_list : + tf_port_item_list ',' tf_port_item + | tf_port_item + | error ',' tf_port_item + | tf_port_item_list ',' + | tf_port_item_list ';' + ; + +timeunits_declaration : + K_timeunit /*23N*/ TIME_LITERAL ';' + | K_timeunit /*23N*/ TIME_LITERAL '/' /*14L*/ TIME_LITERAL ';' + | K_timeprecision /*23N*/ TIME_LITERAL ';' + ; + +timeunits_declaration_opt : + %prec no_timeunits_declaration /*21N*/ /*empty*/ + | timeunits_declaration %prec one_timeunits_declaration /*22N*/ + | timeunits_declaration timeunits_declaration + ; + +value_range : + expression + | '[' expression ':' /*4R*/ expression ']' + ; + +variable_dimension : + '[' expression ':' /*4R*/ expression ']' + | '[' expression ']' + | '[' ']' + | '[' '$' ']' + | '[' '$' ':' /*4R*/ expression ']' + ; + +variable_lifetime_opt : + lifetime + | /*empty*/ + ; + +attribute_list_opt : + attribute_instance_list + | /*empty*/ + ; + +attribute_instance_list : + K_PSTAR K_STARP + | K_PSTAR attribute_list K_STARP + | attribute_instance_list K_PSTAR K_STARP + | attribute_instance_list K_PSTAR attribute_list K_STARP + ; + +attribute_list : + attribute_list ',' attribute + | attribute + ; + +attribute : + IDENTIFIER initializer_opt + ; + +block_item_decl : + K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';' + | variable_lifetime_opt data_type list_of_variable_decl_assignments ';' + | variable_lifetime_opt K_reg data_type list_of_variable_decl_assignments ';' + | K_event event_variable_list ';' + | parameter_declaration + | type_declaration + | package_import_declaration + | K_var variable_lifetime_opt data_type_or_implicit error ';' + | variable_lifetime_opt data_type error ';' + | K_event error ';' + | parameter error ';' + | localparam error ';' + ; + +block_item_decls : + block_item_decl + | block_item_decls block_item_decl + ; + +block_item_decls_opt : + block_item_decls + | /*empty*/ + ; + +typedef_basic_type : + K_struct + | K_union + | K_class + ; + +type_declaration : + K_typedef data_type identifier_name dimensions_opt ';' + | K_typedef identifier_name ';' + | K_typedef typedef_basic_type identifier_name ';' + | K_typedef K_enum identifier_name ';' + | K_typedef error ';' + ; + +enum_base_type : + simple_packed_type + | ps_type_identifier dimensions_opt + | /*empty*/ + ; + +enum_data_type : + K_enum enum_base_type '{' enum_name_list '}' + ; + +enum_name_list : + enum_name + | enum_name_list ',' enum_name + ; + +pos_neg_number : + number + | '-' /*13L*/ number + ; + +enum_name : + IDENTIFIER initializer_opt + | IDENTIFIER '[' pos_neg_number ']' initializer_opt + | IDENTIFIER '[' pos_neg_number ':' /*4R*/ pos_neg_number ']' initializer_opt + ; + +packed_signing : + K_packed unsigned_signed_opt + | /*empty*/ + ; + +struct_data_type : + K_struct packed_signing '{' struct_union_member_list '}' + | K_union packed_signing '{' struct_union_member_list '}' + | K_struct packed_signing '{' error '}' + | K_union packed_signing '{' error '}' + ; + +struct_union_member_list : + struct_union_member_list struct_union_member + | struct_union_member + ; + +struct_union_member : + attribute_list_opt data_type list_of_variable_decl_assignments ';' + | error ';' + ; + +case_item : + expression_list_proper ':' /*4R*/ statement_or_null + | K_default ':' /*4R*/ statement_or_null + | K_default statement_or_null + | error ':' /*4R*/ statement_or_null + ; + +case_items : + case_items case_item + | case_item + ; + +charge_strength : + '(' /*19N*/ K_small ')' + | '(' /*19N*/ K_medium ')' + | '(' /*19N*/ K_large ')' + ; + +charge_strength_opt : + charge_strength + | /*empty*/ + ; + +defparam_assign : + hierarchy_identifier '=' expression + ; + +defparam_assign_list : + defparam_assign + | dimensions defparam_assign + | defparam_assign_list ',' defparam_assign + ; + +delay1 : + '#' delay_value_simple + | '#' '(' /*19N*/ delay_value ')' + ; + +delay3 : + '#' delay_value_simple + | '#' '(' /*19N*/ delay_value ')' + | '#' '(' /*19N*/ delay_value ',' delay_value ')' + | '#' '(' /*19N*/ delay_value ',' delay_value ',' delay_value ')' + ; + +delay3_opt : + delay3 + | /*empty*/ + ; + +delay_value_list : + delay_value + | delay_value_list ',' delay_value + ; + +delay_value : + expression + | expression ':' /*4R*/ expression ':' /*4R*/ expression + ; + +delay_value_simple : + DEC_NUMBER + | REALTIME + | IDENTIFIER + | TIME_LITERAL + ; + +optional_semicolon : + ';' + | /*empty*/ + ; + +discipline_declaration : + K_discipline IDENTIFIER optional_semicolon discipline_items K_enddiscipline + ; + +discipline_items : + discipline_items discipline_item + | discipline_item + ; + +discipline_item : + K_domain K_discrete ';' + | K_domain K_continuous ';' + | K_potential IDENTIFIER ';' + | K_flow IDENTIFIER ';' + ; + +nature_declaration : + K_nature IDENTIFIER optional_semicolon nature_items K_endnature + ; + +nature_items : + nature_items nature_item + | nature_item + ; + +nature_item : + K_units '=' STRING ';' + | K_abstol '=' expression ';' + | K_access '=' IDENTIFIER ';' + | K_idt_nature '=' IDENTIFIER ';' + | K_ddt_nature '=' IDENTIFIER ';' + ; + +config_declaration : + K_config IDENTIFIER ';' K_design lib_cell_identifiers ';' list_of_config_rule_statements K_endconfig + ; + +lib_cell_identifiers : + /*empty*/ + | lib_cell_identifiers lib_cell_id + ; + +list_of_config_rule_statements : + /*empty*/ + | list_of_config_rule_statements config_rule_statement + ; + +config_rule_statement : + K_default K_liblist list_of_libraries ';' + | K_instance hierarchy_identifier K_liblist list_of_libraries ';' + | K_instance hierarchy_identifier K_use lib_cell_id opt_config ';' + | K_cell lib_cell_id K_liblist list_of_libraries ';' + | K_cell lib_cell_id K_use lib_cell_id opt_config ';' + ; + +opt_config : + /*empty*/ + | ':' /*4R*/ K_config + ; + +lib_cell_id : + IDENTIFIER + | IDENTIFIER '.' IDENTIFIER + ; + +list_of_libraries : + /*empty*/ + | list_of_libraries IDENTIFIER + ; + +drive_strength : + '(' /*19N*/ dr_strength0 ',' dr_strength1 ')' + | '(' /*19N*/ dr_strength1 ',' dr_strength0 ')' + | '(' /*19N*/ dr_strength0 ',' K_highz1 ')' + | '(' /*19N*/ dr_strength1 ',' K_highz0 ')' + | '(' /*19N*/ K_highz1 ',' dr_strength0 ')' + | '(' /*19N*/ K_highz0 ',' dr_strength1 ')' + ; + +drive_strength_opt : + drive_strength + | /*empty*/ + ; + +dr_strength0 : + K_supply0 + | K_strong0 + | K_pull0 + | K_weak0 + ; + +dr_strength1 : + K_supply1 + | K_strong1 + | K_pull1 + | K_weak1 + ; + +clocking_event_opt : + event_control + | /*empty*/ + ; + +event_control : + '@' hierarchy_identifier + | '@' '(' /*19N*/ event_expression_list ')' + | '@' '(' /*19N*/ error ')' + ; + +event_expression_list : + event_expression + | event_expression_list K_or event_expression + | event_expression_list ',' event_expression + ; + +event_expression : + K_posedge expression + | K_negedge expression + | K_edge expression + | expression + ; + +branch_probe_expression : + IDENTIFIER '(' /*19N*/ IDENTIFIER ',' IDENTIFIER ')' + | IDENTIFIER '(' /*19N*/ IDENTIFIER ')' + ; + +expression : + expr_primary_or_typename + | inc_or_dec_expression + | inside_expression + | '+' /*13L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '-' /*13L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '~' attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '&' /*9L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '!' attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '|' /*7L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '^' /*8L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '~' '&' /*9L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '~' '|' /*7L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '~' '^' /*8L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | K_NAND /*9L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | K_NOR /*8L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | K_NXOR /*8L*/ attribute_list_opt expr_primary %prec UNARY_PREC /*16L*/ + | '!' error %prec UNARY_PREC /*16L*/ + | '^' /*8L*/ error %prec UNARY_PREC /*16L*/ + | expression '^' /*8L*/ attribute_list_opt expression + | expression K_POW /*15L*/ attribute_list_opt expression + | expression '*' /*14L*/ attribute_list_opt expression + | expression '/' /*14L*/ attribute_list_opt expression + | expression '%' /*14L*/ attribute_list_opt expression + | expression '+' /*13L*/ attribute_list_opt expression + | expression '-' /*13L*/ attribute_list_opt expression + | expression '&' /*9L*/ attribute_list_opt expression + | expression '|' /*7L*/ attribute_list_opt expression + | expression K_NAND /*9L*/ attribute_list_opt expression + | expression K_NOR /*8L*/ attribute_list_opt expression + | expression K_NXOR /*8L*/ attribute_list_opt expression + | expression '<' /*11L*/ attribute_list_opt expression + | expression '>' /*11L*/ attribute_list_opt expression + | expression K_LS /*12L*/ attribute_list_opt expression + | expression K_RS /*12L*/ attribute_list_opt expression + | expression K_RSS /*12L*/ attribute_list_opt expression + | expression K_EQ /*10L*/ attribute_list_opt expression + | expression K_CEQ /*10L*/ attribute_list_opt expression + | expression K_WEQ /*10L*/ attribute_list_opt expression + | expression K_LE /*11L*/ attribute_list_opt expression + | expression K_GE /*11L*/ attribute_list_opt expression + | expression K_NE /*10L*/ attribute_list_opt expression + | expression K_CNE /*10L*/ attribute_list_opt expression + | expression K_WNE /*10L*/ attribute_list_opt expression + | expression K_LOR /*5L*/ attribute_list_opt expression + | expression K_LAND /*6L*/ attribute_list_opt expression + | expression K_TRIGGER /*3R*/ attribute_list_opt expression + | expression K_LEQUIV /*3R*/ attribute_list_opt expression + | expression '?' /*4R*/ attribute_list_opt expression ':' /*4R*/ expression + ; + +expr_mintypmax : + expression + | expression ':' /*4R*/ expression ':' /*4R*/ expression + ; + +expression_list_with_nuls : + expression_list_with_nuls ',' expression + | expression + | /*empty*/ + | expression_list_with_nuls ',' + ; + +argument_list_parens : + '(' /*19N*/ expression_list_with_nuls ')' + ; + +argument_list_parens_opt : + argument_list_parens + | /*empty*/ + ; + +expression_list_proper : + expression_list_proper ',' expression + | expression + ; + +expr_primary_or_typename : + expr_primary + | data_type + ; + +expr_primary : + number + | REALTIME + | STRING + | TIME_LITERAL + | SYSTEM_IDENTIFIER + | hierarchy_identifier + | hierarchy_identifier '.' K_and + | hierarchy_identifier '.' K_or + | hierarchy_identifier '.' K_unique + | hierarchy_identifier '.' K_xor + | package_scope hierarchy_identifier + | hierarchy_identifier attribute_list_opt argument_list_parens + | class_hierarchy_identifier argument_list_parens + | SYSTEM_IDENTIFIER '(' /*19N*/ expression_list_proper ')' + | package_scope hierarchy_identifier argument_list_parens + | SYSTEM_IDENTIFIER '(' /*19N*/ ')' + | K_this + | class_hierarchy_identifier + | K_acos '(' /*19N*/ expression ')' + | K_acosh '(' /*19N*/ expression ')' + | K_asin '(' /*19N*/ expression ')' + | K_asinh '(' /*19N*/ expression ')' + | K_atan '(' /*19N*/ expression ')' + | K_atanh '(' /*19N*/ expression ')' + | K_atan2 '(' /*19N*/ expression ',' expression ')' + | K_ceil '(' /*19N*/ expression ')' + | K_cos '(' /*19N*/ expression ')' + | K_cosh '(' /*19N*/ expression ')' + | K_exp '(' /*19N*/ expression ')' + | K_floor '(' /*19N*/ expression ')' + | K_hypot '(' /*19N*/ expression ',' expression ')' + | K_ln '(' /*19N*/ expression ')' + | K_log '(' /*19N*/ expression ')' + | K_pow '(' /*19N*/ expression ',' expression ')' + | K_sin '(' /*19N*/ expression ')' + | K_sinh '(' /*19N*/ expression ')' + | K_sqrt '(' /*19N*/ expression ')' + | K_tan '(' /*19N*/ expression ')' + | K_tanh '(' /*19N*/ expression ')' + | K_abs '(' /*19N*/ expression ')' + | K_max '(' /*19N*/ expression ',' expression ')' + | K_min '(' /*19N*/ expression ',' expression ')' + | '(' /*19N*/ expr_mintypmax ')' + | '{' expression_list_proper '}' + | '{' expression '{' expression_list_proper '}' '}' + | '{' expression '{' expression_list_proper '}' error '}' + | '{' '}' + | expr_primary '\'' '(' /*19N*/ expression ')' + | simple_type_or_string '\'' '(' /*19N*/ expression ')' + | signing '\'' '(' /*19N*/ expression ')' + | assignment_pattern + | streaming_concatenation + | K_null + ; + +tf_item_list_opt : + tf_item_list + | /*empty*/ + ; + +tf_item_list : + tf_item_declaration + | tf_item_list tf_item_declaration + ; + +tf_item_declaration : + tf_port_declaration + | block_item_decl + ; + +gate_instance : + IDENTIFIER '(' /*19N*/ port_conn_expression_list_with_nuls ')' + | IDENTIFIER dimensions '(' /*19N*/ port_conn_expression_list_with_nuls ')' + | '(' /*19N*/ port_conn_expression_list_with_nuls ')' + | IDENTIFIER dimensions + | IDENTIFIER '(' /*19N*/ port_name_list ')' + | IDENTIFIER dimensions '(' /*19N*/ port_name_list ')' + | IDENTIFIER '(' /*19N*/ error ')' + | IDENTIFIER dimensions '(' /*19N*/ error ')' + ; + +gate_instance_list : + gate_instance_list ',' gate_instance + | gate_instance + ; + +gatetype : + K_and + | K_nand + | K_or + | K_nor + | K_xor + | K_xnor + | K_buf + | K_bufif0 + | K_bufif1 + | K_not + | K_notif0 + | K_notif1 + ; + +switchtype : + K_nmos + | K_rnmos + | K_pmos + | K_rpmos + | K_cmos + | K_rcmos + | K_tran + | K_rtran + | K_tranif0 + | K_tranif1 + | K_rtranif0 + | K_rtranif1 + ; + +hierarchy_identifier : + IDENTIFIER + | hierarchy_identifier '.' IDENTIFIER + | hierarchy_identifier '[' expression ']' + | hierarchy_identifier '[' '$' ']' + | hierarchy_identifier '[' expression ':' /*4R*/ expression ']' + | hierarchy_identifier '[' expression K_PO_POS expression ']' + | hierarchy_identifier '[' expression K_PO_NEG expression ']' + ; + +list_of_identifiers : + IDENTIFIER + | list_of_identifiers ',' IDENTIFIER + ; + +list_of_port_identifiers : + IDENTIFIER dimensions_opt + | list_of_port_identifiers ',' IDENTIFIER dimensions_opt + ; + +list_of_variable_port_identifiers : + IDENTIFIER dimensions_opt initializer_opt + | list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt initializer_opt + ; + +list_of_ports : + port_opt + | list_of_ports ',' port_opt + ; + +list_of_port_declarations : + port_declaration + | list_of_port_declarations ',' port_declaration + | list_of_port_declarations ',' attribute_list_opt IDENTIFIER dimensions_opt initializer_opt + | list_of_port_declarations ',' + | list_of_port_declarations ';' + ; + +port_declaration : + attribute_list_opt port_direction net_type_or_var_opt data_type_or_implicit IDENTIFIER dimensions_opt initializer_opt + | attribute_list_opt net_type_or_var data_type_or_implicit IDENTIFIER dimensions_opt initializer_opt + | attribute_list_opt data_type_or_implicit_no_opt IDENTIFIER dimensions_opt initializer_opt + | attribute_list_opt port_direction K_wreal IDENTIFIER + ; + +unsigned_signed_opt : + K_signed + | K_unsigned + | /*empty*/ + ; + +signed_unsigned_opt : + K_signed + | K_unsigned + | /*empty*/ + ; + +atom_type : + K_byte + | K_shortint + | K_int + | K_longint + | K_integer + ; + +lpvalue : + hierarchy_identifier + | class_hierarchy_identifier + | '{' expression_list_proper '}' + | streaming_concatenation + ; + +cont_assign : + lpvalue '=' expression + ; + +cont_assign_list : + cont_assign_list ',' cont_assign + | cont_assign + ; + +module : + attribute_list_opt module_start lifetime_opt IDENTIFIER module_package_import_list_opt module_parameter_port_list_opt module_port_list_opt module_attribute_foreign ';' timeunits_declaration_opt module_item_list_opt module_end label_opt + ; + +module_start : + K_module + | K_macromodule + | K_program + | K_interface + ; + +module_end : + K_endmodule + | K_endprogram + | K_endinterface + ; + +label_opt : + ':' /*4R*/ IDENTIFIER + | /*empty*/ + ; + +module_attribute_foreign : + K_PSTAR IDENTIFIER K_integer IDENTIFIER '=' STRING ';' K_STARP + | /*empty*/ + ; + +module_port_list_opt : + '(' /*19N*/ list_of_ports ')' + | '(' /*19N*/ list_of_port_declarations ')' + | /*empty*/ + | '(' /*19N*/ error ')' + ; + +module_parameter_port_list_opt : + /*empty*/ + | '#' '(' /*19N*/ module_parameter_port_list ')' + ; + +type_param : + K_type + ; + +module_parameter : + parameter param_type parameter_assign + | localparam param_type parameter_assign + ; + +module_parameter_port_list : + module_parameter + | data_type_opt parameter_assign + | type_param parameter_assign + | module_parameter_port_list ',' module_parameter + | module_parameter_port_list ',' data_type_opt parameter_assign + | module_parameter_port_list ',' type_param parameter_assign + ; + +module_item : + module + | attribute_list_opt net_type data_type_or_implicit delay3_opt net_variable_list ';' + | attribute_list_opt K_wreal delay3 net_variable_list ';' + | attribute_list_opt K_wreal net_variable_list ';' + | attribute_list_opt net_type data_type_or_implicit delay3_opt net_decl_assigns ';' + | attribute_list_opt net_type data_type_or_implicit drive_strength net_decl_assigns ';' + | attribute_list_opt K_wreal net_decl_assigns ';' + | K_trireg charge_strength_opt dimensions_opt delay3_opt list_of_identifiers ';' + | attribute_list_opt port_direction net_type_or_var data_type_or_implicit list_of_port_identifiers ';' + | attribute_list_opt port_direction K_wreal list_of_port_identifiers ';' + | attribute_list_opt K_inout data_type_or_implicit list_of_port_identifiers ';' + | attribute_list_opt K_input data_type_or_implicit list_of_port_identifiers ';' + | attribute_list_opt K_output data_type_or_implicit list_of_variable_port_identifiers ';' + | attribute_list_opt port_direction net_type_or_var data_type_or_implicit error ';' + | attribute_list_opt K_inout data_type_or_implicit error ';' + | attribute_list_opt K_input data_type_or_implicit error ';' + | attribute_list_opt K_output data_type_or_implicit error ';' + | K_let IDENTIFIER let_port_list_opt '=' expression ';' + | DISCIPLINE_IDENTIFIER list_of_identifiers ';' + | attribute_list_opt block_item_decl + | K_defparam defparam_assign_list ';' + | attribute_list_opt gatetype gate_instance_list ';' + | attribute_list_opt gatetype delay3 gate_instance_list ';' + | attribute_list_opt gatetype drive_strength gate_instance_list ';' + | attribute_list_opt gatetype drive_strength delay3 gate_instance_list ';' + | attribute_list_opt switchtype gate_instance_list ';' + | attribute_list_opt switchtype delay3 gate_instance_list ';' + | K_pullup gate_instance_list ';' + | K_pulldown gate_instance_list ';' + | K_pullup '(' /*19N*/ dr_strength1 ')' gate_instance_list ';' + | K_pullup '(' /*19N*/ dr_strength1 ',' dr_strength0 ')' gate_instance_list ';' + | K_pullup '(' /*19N*/ dr_strength0 ',' dr_strength1 ')' gate_instance_list ';' + | K_pulldown '(' /*19N*/ dr_strength0 ')' gate_instance_list ';' + | K_pulldown '(' /*19N*/ dr_strength1 ',' dr_strength0 ')' gate_instance_list ';' + | K_pulldown '(' /*19N*/ dr_strength0 ',' dr_strength1 ')' gate_instance_list ';' + | attribute_list_opt IDENTIFIER parameter_value_opt gate_instance_list ';' + | attribute_list_opt IDENTIFIER parameter_value_opt error ';' + | K_assign drive_strength_opt delay3_opt cont_assign_list ';' + | attribute_list_opt K_always statement_item + | attribute_list_opt K_always_comb statement_item + | attribute_list_opt K_always_ff statement_item + | attribute_list_opt K_always_latch statement_item + | attribute_list_opt K_initial statement_item + | attribute_list_opt K_final statement_item + | attribute_list_opt K_analog analog_statement + | attribute_list_opt assertion_item + | timeunits_declaration + | class_declaration + | task_declaration + | function_declaration + | K_generate generate_item_list_opt K_endgenerate + | K_genvar list_of_identifiers ';' + | K_for '(' /*19N*/ K_genvar_opt IDENTIFIER '=' expression ';' expression ';' genvar_iteration ')' generate_block + | generate_if generate_block K_else /*18N*/ generate_block + | generate_if generate_block %prec less_than_K_else /*17N*/ + | K_case '(' /*19N*/ expression ')' generate_case_items K_endcase + | SYSTEM_IDENTIFIER argument_list_parens_opt ';' + | modport_declaration + | attribute_list_opt K_specparam specparam_decl ';' + | K_specify specify_item_list_opt K_endspecify + | K_specify error K_endspecify + | error ';' + | K_assign error '=' expression ';' + | K_assign error ';' + | K_function error K_endfunction label_opt + | KK_attribute '(' /*19N*/ IDENTIFIER ',' STRING ',' STRING ')' ';' + | KK_attribute '(' /*19N*/ error ')' ';' + | ';' + ; + +let_port_list_opt : + '(' /*19N*/ let_port_list ')' + | '(' /*19N*/ ')' + | /*empty*/ + ; + +let_port_list : + let_port_item + | let_port_list ',' let_port_item + ; + +let_port_item : + attribute_list_opt let_formal_type IDENTIFIER dimensions_opt initializer_opt + ; + +let_formal_type : + data_type_or_implicit + | K_untyped + ; + +module_item_list : + module_item_list module_item + | module_item + ; + +module_item_list_opt : + module_item_list + | /*empty*/ + ; + +generate_if : + K_if '(' /*19N*/ expression ')' + ; + +generate_case_items : + generate_case_items generate_case_item + | generate_case_item + ; + +generate_case_item : + expression_list_proper ':' /*4R*/ generate_block + | K_default ':' /*4R*/ generate_block + ; + +generate_item : + module_item + | K_begin generate_item_list_opt K_end + | K_begin ':' /*4R*/ IDENTIFIER generate_item_list_opt K_end + ; + +generate_item_list : + generate_item_list generate_item + | generate_item + ; + +generate_item_list_opt : + generate_item_list + | /*empty*/ + ; + +generate_block : + module_item + | K_begin label_opt generate_item_list_opt K_end label_opt + ; + +net_decl_assign : + IDENTIFIER '=' expression + ; + +net_decl_assigns : + net_decl_assigns ',' net_decl_assign + | net_decl_assign + ; + +net_type : + K_wire + | K_tri + | K_tri1 + | K_supply0 + | K_wand + | K_triand + | K_tri0 + | K_supply1 + | K_wor + | K_trior + | K_wone + | K_uwire + ; + +net_type_opt : + net_type + | /*empty*/ + ; + +net_type_or_var : + net_type + | K_var + ; + +net_type_or_var_opt : + net_type_opt + | K_var + ; + +param_type : + data_type_or_implicit + | type_param + ; + +parameter : + K_parameter + ; + +localparam : + K_localparam + ; + +parameter_declaration : + parameter_or_localparam param_type parameter_assign_list ';' + ; + +parameter_or_localparam : + parameter + | localparam + ; + +parameter_assign_list : + parameter_assign + | parameter_assign_list ',' parameter_assign + ; + +parameter_assign : + IDENTIFIER initializer_opt parameter_value_ranges_opt + ; + +parameter_value_ranges_opt : + parameter_value_ranges + | /*empty*/ + ; + +parameter_value_ranges : + parameter_value_ranges parameter_value_range + | parameter_value_range + ; + +parameter_value_range : + from_exclude '[' value_range_expression ':' /*4R*/ value_range_expression ']' + | from_exclude '[' value_range_expression ':' /*4R*/ value_range_expression ')' + | from_exclude '(' /*19N*/ value_range_expression ':' /*4R*/ value_range_expression ']' + | from_exclude '(' /*19N*/ value_range_expression ':' /*4R*/ value_range_expression ')' + | K_exclude /*20N*/ expression + ; + +value_range_expression : + expression + | K_inf + | '+' /*13L*/ K_inf + | '-' /*13L*/ K_inf + ; + +from_exclude : + K_from + | K_exclude /*20N*/ + ; + +parameter_value_opt : + '#' '(' /*19N*/ expression_list_with_nuls ')' + | '#' '(' /*19N*/ parameter_value_byname_list ')' + | '#' DEC_NUMBER + | '#' REALTIME + | '#' error + | /*empty*/ + ; + +parameter_value_byname : + '.' IDENTIFIER '(' /*19N*/ expression ')' + | '.' IDENTIFIER '(' /*19N*/ ')' + ; + +parameter_value_byname_list : + parameter_value_byname + | parameter_value_byname_list ',' parameter_value_byname + ; + +port : + port_reference + | '.' IDENTIFIER '(' /*19N*/ port_reference ')' + | '{' port_reference_list '}' + | '.' IDENTIFIER '(' /*19N*/ '{' port_reference_list '}' ')' + ; + +port_opt : + port + | /*empty*/ + ; + +port_name : + attribute_list_opt '.' IDENTIFIER '(' /*19N*/ expression ')' + | attribute_list_opt '.' IDENTIFIER '(' /*19N*/ error ')' + | attribute_list_opt '.' IDENTIFIER '(' /*19N*/ ')' + | attribute_list_opt '.' IDENTIFIER + | K_DOTSTAR + ; + +port_name_list : + port_name_list ',' port_name + | port_name + ; + +port_conn_expression_list_with_nuls : + port_conn_expression_list_with_nuls ',' attribute_list_opt expression + | attribute_list_opt expression + | /*empty*/ + | port_conn_expression_list_with_nuls ',' + ; + +port_reference : + IDENTIFIER + | IDENTIFIER '[' expression ':' /*4R*/ expression ']' + | IDENTIFIER '[' expression ']' + | IDENTIFIER '[' error ']' + ; + +port_reference_list : + port_reference + | port_reference_list ',' port_reference + ; + +dimensions_opt : + /*empty*/ + | dimensions + ; + +dimensions : + variable_dimension + | dimensions variable_dimension + ; + +net_variable : + IDENTIFIER dimensions_opt + ; + +net_variable_list : + net_variable + | net_variable_list ',' net_variable + ; + +event_variable : + IDENTIFIER dimensions_opt + ; + +event_variable_list : + event_variable + | event_variable_list ',' event_variable + ; + +specify_item : + K_specparam specparam_decl ';' + | specify_simple_path_decl ';' + | specify_edge_path_decl ';' + | K_if '(' /*19N*/ expression ')' specify_simple_path_decl ';' + | K_if '(' /*19N*/ expression ')' specify_edge_path_decl ';' + | K_ifnone specify_simple_path_decl ';' + | K_ifnone specify_edge_path_decl ';' + | K_Sfullskew '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' delay_value ',' delay_value fullskew_opt_args ')' ';' + | K_Shold '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' + | K_Snochange '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' delay_value ',' delay_value spec_notifier_opt ')' ';' + | K_Speriod '(' /*19N*/ spec_reference_event ',' delay_value spec_notifier_opt ')' ';' + | K_Srecovery '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' + | K_Srecrem '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' expr_mintypmax ',' expr_mintypmax recrem_opt_args ')' ';' + | K_Sremoval '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' + | K_Ssetup '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' + | K_Ssetuphold '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' expr_mintypmax ',' expr_mintypmax setuphold_opt_args ')' ';' + | K_Sskew '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' delay_value spec_notifier_opt ')' ';' + | K_Stimeskew '(' /*19N*/ spec_reference_event ',' spec_reference_event ',' delay_value timeskew_opt_args ')' ';' + | K_Swidth '(' /*19N*/ spec_reference_event ',' delay_value ',' expression spec_notifier_opt ')' ';' + | K_Swidth '(' /*19N*/ spec_reference_event ',' delay_value ')' ';' + | K_pulsestyle_onevent specify_path_identifiers ';' + | K_pulsestyle_ondetect specify_path_identifiers ';' + | K_showcancelled specify_path_identifiers ';' + | K_noshowcancelled specify_path_identifiers ';' + ; + +specify_item_list : + specify_item + | specify_item_list specify_item + ; + +specify_item_list_opt : + /*empty*/ + | specify_item_list + ; + +specify_edge_path_decl : + specify_edge_path '=' '(' /*19N*/ delay_value_list ')' + | specify_edge_path '=' delay_value_simple + ; + +edge_operator : + K_posedge + | K_negedge + ; + +specify_edge_path : + '(' /*19N*/ specify_path_identifiers spec_polarity K_EG '(' /*19N*/ specify_path_identifiers polarity_operator expression ')' ')' + | '(' /*19N*/ edge_operator specify_path_identifiers spec_polarity K_EG '(' /*19N*/ specify_path_identifiers polarity_operator expression ')' ')' + | '(' /*19N*/ specify_path_identifiers spec_polarity K_SG '(' /*19N*/ specify_path_identifiers polarity_operator expression ')' ')' + | '(' /*19N*/ edge_operator specify_path_identifiers spec_polarity K_SG '(' /*19N*/ specify_path_identifiers polarity_operator expression ')' ')' + ; + +polarity_operator : + K_PO_POS + | K_PO_NEG + | ':' /*4R*/ + ; + +specify_simple_path_decl : + specify_simple_path '=' '(' /*19N*/ delay_value_list ')' + | specify_simple_path '=' delay_value_simple + | specify_simple_path '=' '(' /*19N*/ error ')' + ; + +specify_simple_path : + '(' /*19N*/ specify_path_identifiers spec_polarity K_EG specify_path_identifiers ')' + | '(' /*19N*/ specify_path_identifiers spec_polarity K_SG specify_path_identifiers ')' + | '(' /*19N*/ error ')' + ; + +specify_path_identifiers : + IDENTIFIER + | IDENTIFIER '[' expr_primary ']' + | IDENTIFIER '[' expr_primary polarity_operator expr_primary ']' + | specify_path_identifiers ',' IDENTIFIER + | specify_path_identifiers ',' IDENTIFIER '[' expr_primary ']' + | specify_path_identifiers ',' IDENTIFIER '[' expr_primary polarity_operator expr_primary ']' + ; + +specparam : + IDENTIFIER '=' expr_mintypmax + | PATHPULSE_IDENTIFIER '=' expression + | PATHPULSE_IDENTIFIER '=' '(' /*19N*/ expression ',' expression ')' + ; + +specparam_list : + specparam + | specparam_list ',' specparam + ; + +specparam_decl : + specparam_list + | dimensions specparam_list + ; + +spec_polarity : + '+' /*13L*/ + | '-' /*13L*/ + | /*empty*/ + ; + +spec_reference_event : + hierarchy_identifier + | hierarchy_identifier K_TAND expression + | K_posedge hierarchy_identifier + | K_negedge hierarchy_identifier + | K_posedge hierarchy_identifier K_TAND expression + | K_negedge hierarchy_identifier K_TAND expression + | K_edge '[' edge_descriptor_list ']' hierarchy_identifier + | K_edge '[' edge_descriptor_list ']' hierarchy_identifier K_TAND expression + ; + +edge_descriptor_list : + edge_descriptor_list ',' K_edge_descriptor + | K_edge_descriptor + ; + +setuphold_opt_args : + setuphold_recrem_opt_notifier + | /*empty*/ + ; + +recrem_opt_args : + setuphold_recrem_opt_notifier + | /*empty*/ + ; + +setuphold_recrem_opt_notifier : + ',' + | ',' hierarchy_identifier + | ',' setuphold_recrem_opt_timestamp_cond + | ',' hierarchy_identifier setuphold_recrem_opt_timestamp_cond + ; + +setuphold_recrem_opt_timestamp_cond : + ',' + | ',' expression + | ',' setuphold_recrem_opt_timecheck_cond + | ',' expression setuphold_recrem_opt_timecheck_cond + ; + +setuphold_recrem_opt_timecheck_cond : + ',' + | ',' expression + | ',' setuphold_recrem_opt_delayed_reference + | ',' expression setuphold_recrem_opt_delayed_reference + ; + +setuphold_recrem_opt_delayed_reference : + ',' + | ',' hierarchy_identifier + | ',' setuphold_recrem_opt_delayed_data + | ',' hierarchy_identifier setuphold_recrem_opt_delayed_data + ; + +setuphold_recrem_opt_delayed_data : + ',' + | ',' hierarchy_identifier + ; + +timeskew_opt_args : + timeskew_fullskew_opt_notifier + | /*empty*/ + ; + +fullskew_opt_args : + timeskew_fullskew_opt_notifier + | /*empty*/ + ; + +timeskew_fullskew_opt_notifier : + ',' + | ',' hierarchy_identifier + | ',' timeskew_fullskew_opt_event_based_flag + | ',' hierarchy_identifier timeskew_fullskew_opt_event_based_flag + ; + +timeskew_fullskew_opt_event_based_flag : + ',' + | ',' expression + | ',' timeskew_fullskew_opt_remain_active_flag + | ',' expression timeskew_fullskew_opt_remain_active_flag + ; + +timeskew_fullskew_opt_remain_active_flag : + ',' + | ',' expression + ; + +spec_notifier_opt : + /*empty*/ + | spec_notifier + ; + +spec_notifier : + ',' + | ',' hierarchy_identifier + ; + +subroutine_call : + hierarchy_identifier argument_list_parens_opt + | class_hierarchy_identifier argument_list_parens_opt + | SYSTEM_IDENTIFIER argument_list_parens_opt + | hierarchy_identifier '(' /*19N*/ error ')' + ; + +statement_item : + K_assign lpvalue '=' expression ';' + | K_deassign lpvalue ';' + | K_force lpvalue '=' expression ';' + | K_release lpvalue ';' + | K_begin label_opt block_item_decls_opt statement_or_null_list_opt K_end label_opt + | K_fork label_opt block_item_decls_opt statement_or_null_list_opt join_keyword label_opt + | K_disable hierarchy_identifier ';' + | K_disable K_fork ';' + | K_TRIGGER /*3R*/ hierarchy_identifier ';' + | K_TRIGGER /*3R*/ package_scope hierarchy_identifier + | K_NB_TRIGGER /*2N*/ hierarchy_identifier ';' + | K_NB_TRIGGER /*2N*/ delay1 hierarchy_identifier ';' + | K_NB_TRIGGER /*2N*/ event_control hierarchy_identifier ';' + | K_NB_TRIGGER /*2N*/ K_repeat '(' /*19N*/ expression ')' event_control hierarchy_identifier ';' + | procedural_assertion_statement + | loop_statement + | jump_statement + | unique_priority K_case '(' /*19N*/ expression ')' case_items K_endcase + | unique_priority K_casex '(' /*19N*/ expression ')' case_items K_endcase + | unique_priority K_casez '(' /*19N*/ expression ')' case_items K_endcase + | unique_priority K_case '(' /*19N*/ expression ')' error K_endcase + | unique_priority K_casex '(' /*19N*/ expression ')' error K_endcase + | unique_priority K_casez '(' /*19N*/ expression ')' error K_endcase + | K_if '(' /*19N*/ expression ')' statement_or_null %prec less_than_K_else /*17N*/ + | K_if '(' /*19N*/ expression ')' statement_or_null K_else /*18N*/ statement_or_null + | K_if '(' /*19N*/ error ')' statement_or_null %prec less_than_K_else /*17N*/ + | K_if '(' /*19N*/ error ')' statement_or_null K_else /*18N*/ statement_or_null + | compressed_statement ';' + | inc_or_dec_expression ';' + | delay1 statement_or_null + | event_control statement_or_null + | '@' '*' /*14L*/ statement_or_null + | '@' '(' /*19N*/ '*' /*14L*/ ')' statement_or_null + | lpvalue '=' expression ';' + | error '=' expression ';' + | lpvalue K_LE /*11L*/ expression ';' + | error K_LE /*11L*/ expression ';' + | lpvalue '=' delay1 expression ';' + | lpvalue K_LE /*11L*/ delay1 expression ';' + | lpvalue '=' event_control expression ';' + | lpvalue '=' K_repeat '(' /*19N*/ expression ')' event_control expression ';' + | lpvalue K_LE /*11L*/ event_control expression ';' + | lpvalue K_LE /*11L*/ K_repeat '(' /*19N*/ expression ')' event_control expression ';' + | lpvalue '=' dynamic_array_new ';' + | lpvalue '=' class_new ';' + | K_wait '(' /*19N*/ expression ')' statement_or_null + | K_wait K_fork ';' + | K_void '\'' '(' /*19N*/ subroutine_call ')' ';' + | subroutine_call ';' + | hierarchy_identifier K_with '{' constraint_block_item_list_opt '}' ';' + | implicit_class_handle K_new argument_list_parens_opt ';' + | error ';' + ; + +compressed_operator : + K_PLUS_EQ /*1N*/ + | K_MINUS_EQ /*1N*/ + | K_MUL_EQ /*1N*/ + | K_DIV_EQ /*1N*/ + | K_MOD_EQ /*1N*/ + | K_AND_EQ /*1N*/ + | K_OR_EQ /*1N*/ + | K_XOR_EQ /*2N*/ + | K_LS_EQ /*2N*/ + | K_RS_EQ /*2N*/ + | K_RSS_EQ /*2N*/ + ; + +compressed_statement : + lpvalue compressed_operator expression + ; + +statement_or_null_list_opt : + statement_or_null_list + | /*empty*/ + ; + +statement_or_null_list : + statement_or_null_list statement_or_null + | statement_or_null + ; + +analog_statement : + branch_probe_expression K_CONTRIBUTE expression ';' + ; + +tf_port_list_opt : + tf_port_list + | /*empty*/ + ; + +tf_port_list_parens_opt : + '(' /*19N*/ tf_port_list_opt ')' + | /*empty*/ + ; + +udp_body : + K_table udp_entry_list K_endtable + | K_table K_endtable + | K_table error K_endtable + ; + +udp_entry_list : + udp_comb_entry_list + | udp_sequ_entry_list + ; + +udp_comb_entry : + udp_input_list ':' /*4R*/ udp_output_sym ';' + ; + +udp_comb_entry_list : + udp_comb_entry + | udp_comb_entry_list udp_comb_entry + ; + +udp_sequ_entry_list : + udp_sequ_entry + | udp_sequ_entry_list udp_sequ_entry + ; + +udp_sequ_entry : + udp_input_list ':' /*4R*/ udp_input_sym ':' /*4R*/ udp_output_sym ';' + ; + +udp_initial : + K_initial IDENTIFIER '=' number ';' + ; + +udp_init_opt : + udp_initial + | /*empty*/ + ; + +udp_input_list : + udp_input_sym + | udp_input_list udp_input_sym + ; + +udp_input_sym : + '0' + | '1' + | 'x' + | '?' /*4R*/ + | 'b' + | '*' /*14L*/ + | '%' /*14L*/ + | 'f' + | 'F' + | 'l' + | 'h' + | 'B' + | 'r' + | 'R' + | 'M' + | 'n' + | 'N' + | 'p' + | 'P' + | 'Q' + | 'q' + | '_' + | '+' /*13L*/ + | DEC_NUMBER + ; + +udp_output_sym : + '0' + | '1' + | 'x' + | '-' /*13L*/ + | DEC_NUMBER + ; + +udp_port_decl : + K_input list_of_identifiers ';' + | K_output IDENTIFIER ';' + | K_reg IDENTIFIER ';' + | K_output K_reg IDENTIFIER ';' + ; + +udp_port_decls : + udp_port_decl + | udp_port_decls udp_port_decl + ; + +udp_port_list : + IDENTIFIER + | udp_port_list ',' IDENTIFIER + ; + +udp_reg_opt : + K_reg + | /*empty*/ + ; + +udp_input_declaration_list : + K_input IDENTIFIER + | udp_input_declaration_list ',' K_input IDENTIFIER + ; + +udp_primitive : + K_primitive IDENTIFIER '(' /*19N*/ udp_port_list ')' ';' udp_port_decls udp_init_opt udp_body K_endprimitive label_opt + | K_primitive IDENTIFIER '(' /*19N*/ K_output udp_reg_opt IDENTIFIER initializer_opt ',' udp_input_declaration_list ')' ';' udp_body K_endprimitive label_opt + ; + +unique_priority : + /*empty*/ + | K_unique + | K_unique0 + | K_priority + ; + +K_genvar_opt : + K_genvar + | /*empty*/ + ; + +K_static_opt : + K_static + | /*empty*/ + ; + +K_virtual_opt : + K_virtual + | /*empty*/ + ; + +K_var_opt : + K_var + | /*empty*/ + ; + +//Lexer + +K_PLUS_EQ : '+=' ; +K_MINUS_EQ : '-=' ; +K_MUL_EQ : '*=' ; +K_DIV_EQ : '/=' ; +K_MOD_EQ : '%=' ; +K_AND_EQ : '&=' ; +K_OR_EQ : '|=' ; +K_NB_TRIGGER : 'K_NB_TRIGGER' ; +K_XOR_EQ : 'K_XOR_EQ' ; +K_LS_EQ : '<<=' ; +K_RS_EQ : '>>=' ; +K_RSS_EQ : 'K_RSS_EQ' ; +K_TRIGGER : 'K_TRIGGER' ; +K_LEQUIV : 'K_LEQUIV' ; +K_inside : 'inside' ; +K_LOR : '||' ; +K_LAND : '&&' ; +K_NOR : 'K_NOR' ; +K_NXOR : 'K_NXOR' ; +K_NAND : 'K_NAND' ; +K_EQ : '==' ; +K_NE : '!=' ; +K_CEQ : 'K_CEQ' ; +K_CNE : 'K_CNE' ; +K_WEQ : 'K_WEQ' ; +K_WNE : 'K_WNE' ; +K_LE : '<=' ; +K_GE : '>=' ; +K_LS : 'K_LS' ; +K_RS : 'K_RS' ; +K_RSS : 'K_RSS' ; +K_POW : 'K_POW' ; +K_else : 'else' ; +K_exclude : 'exclude' ; +K_timeprecision : 'timeprecision' ; +K_timeunit : 'timeunit' ; +K_assert : 'assert' ; +K_assume : 'assume' ; +K_LP : 'K_LP' ; +IDENTIFIER : "[a-zA-Z_][a-zA-Z_0-9]*" ; +K_class : 'class' ; +K_endclass : 'endclass' ; +TYPE_IDENTIFIER : 'TYPE_IDENTIFIER' ; +K_extends : 'extends' ; +K_function : 'function' ; +K_new : 'new' ; +K_endfunction : 'endfunction' ; +K_const : 'const' ; +K_extern : 'extern' ; +K_task : 'task' ; +K_static : 'static' ; +K_protected : 'protected' ; +K_local : 'local' ; +K_SCOPE_RES : 'K_SCOPE_RES' ; +K_property : 'property' ; +K_cover : 'cover' ; +K_sequence : 'sequence' ; +K_restrict : 'restrict' ; +K_constraint : 'constraint' ; +K_dist : 'dist' ; +K_if : 'if' ; +K_foreach : 'foreach' ; +K_CONSTRAINT_IMPL : 'K_CONSTRAINT_IMPL' ; +K_var : 'var' ; +K_event : 'event' ; +PACKAGE_IDENTIFIER : 'PACKAGE_IDENTIFIER' ; +K_time : 'time' ; +K_string : 'string' ; +K_vectored : 'vectored' ; +K_scalared : 'scalared' ; +K_void : 'void' ; +DEC_NUMBER : "[0-9]+" ; +K_final : 'final' ; +KK_attribute : 'KK_attribute' ; +STRING : "\"(\\.|[^\\\"])+\"" ; +K_INCR : '++' ; +K_DECR : '--' ; +K_import : 'import' ; +K_export : 'export' ; +K_this : 'this' ; +K_super : 'super' ; +K_reg : 'reg' ; +K_bit : 'bit' ; +K_logic : 'logic' ; +K_bool : 'bool' ; +K_join : 'join' ; +K_join_none : 'join_none' ; +K_join_any : 'join_any' ; +K_break : 'break' ; +K_continue : 'continue' ; +K_return : 'return' ; +K_automatic : 'automatic' ; +K_for : 'for' ; +K_forever : 'forever' ; +K_repeat : 'repeat' ; +K_while : 'while' ; +K_do : 'do' ; +K_virtual : 'virtual' ; +K_modport : 'modport' ; +K_clocking : 'clocking' ; +K_real : 'real' ; +K_realtime : 'realtime' ; +K_shortreal : 'shortreal' ; +BASED_NUMBER : 'BASED_NUMBER' ; +UNBASED_NUMBER : 'UNBASED_NUMBER' ; +K_package : 'package' ; +K_endpackage : 'endpackage' ; +K_input : 'input' ; +K_output : 'output' ; +K_inout : 'inout' ; +K_ref : 'ref' ; +K_disable : 'disable' ; +K_iff : 'iff' ; +K_rand : 'rand' ; +K_randc : 'randc' ; +K_signed : 'signed' ; +K_unsigned : 'unsigned' ; +K_endtask : 'endtask' ; +TIME_LITERAL : 'TIME_LITERAL' ; +K_PSTAR : 'K_PSTAR' ; +K_STARP : 'K_STARP' ; +K_struct : 'struct' ; +K_union : 'union' ; +K_typedef : 'typedef' ; +K_enum : 'enum' ; +K_packed : 'packed' ; +K_default : 'default' ; +K_small : 'small' ; +K_medium : 'medium' ; +K_large : 'large' ; +REALTIME : 'REALTIME' ; +K_discipline : 'discipline' ; +K_enddiscipline : 'enddiscipline' ; +K_domain : 'domain' ; +K_discrete : 'discrete' ; +K_continuous : 'continuous' ; +K_potential : 'potential' ; +K_flow : 'flow' ; +K_nature : 'nature' ; +K_endnature : 'endnature' ; +K_units : 'units' ; +K_abstol : 'abstol' ; +K_access : 'access' ; +K_idt_nature : 'idt_nature' ; +K_ddt_nature : 'ddt_nature' ; +K_config : 'config' ; +K_design : 'design' ; +K_endconfig : 'endconfig' ; +K_liblist : 'liblist' ; +K_instance : 'instance' ; +K_use : 'use' ; +K_cell : 'cell' ; +K_highz1 : 'highz1' ; +K_highz0 : 'highz0' ; +K_supply0 : 'supply0' ; +K_strong0 : 'strong0' ; +K_pull0 : 'pull0' ; +K_weak0 : 'weak0' ; +K_supply1 : 'supply1' ; +K_strong1 : 'strong1' ; +K_pull1 : 'pull1' ; +K_weak1 : 'weak1' ; +K_or : 'or' ; +K_posedge : 'posedge' ; +K_negedge : 'negedge' ; +K_edge : 'edge' ; +SYSTEM_IDENTIFIER : 'SYSTEM_IDENTIFIER' ; +K_and : 'and' ; +K_unique : 'unique' ; +K_xor : 'xor' ; +K_acos : 'acos' ; +K_acosh : 'acosh' ; +K_asin : 'asin' ; +K_asinh : 'asinh' ; +K_atan : 'atan' ; +K_atanh : 'atanh' ; +K_atan2 : 'atan2' ; +K_ceil : 'ceil' ; +K_cos : 'cos' ; +K_cosh : 'cosh' ; +K_exp : 'exp' ; +K_floor : 'floor' ; +K_hypot : 'hypot' ; +K_ln : 'ln' ; +K_log : 'log' ; +K_pow : 'pow' ; +K_sin : 'sin' ; +K_sinh : 'sinh' ; +K_sqrt : 'sqrt' ; +K_tan : 'tan' ; +K_tanh : 'tanh' ; +K_abs : 'abs' ; +K_max : 'max' ; +K_min : 'min' ; +K_null : 'null' ; +K_nand : 'nand' ; +K_nor : 'nor' ; +K_xnor : 'xnor' ; +K_buf : 'buf' ; +K_bufif0 : 'bufif0' ; +K_bufif1 : 'bufif1' ; +K_not : 'not' ; +K_notif0 : 'notif0' ; +K_notif1 : 'notif1' ; +K_nmos : 'nmos' ; +K_rnmos : 'rnmos' ; +K_pmos : 'pmos' ; +K_rpmos : 'rpmos' ; +K_cmos : 'cmos' ; +K_rcmos : 'rcmos' ; +K_tran : 'tran' ; +K_rtran : 'rtran' ; +K_tranif0 : 'tranif0' ; +K_tranif1 : 'tranif1' ; +K_rtranif0 : 'rtranif0' ; +K_rtranif1 : 'rtranif1' ; +K_PO_POS : 'K_PO_POS' ; +K_PO_NEG : 'K_PO_NEG' ; +K_wreal : 'wreal' ; +K_byte : 'byte' ; +K_shortint : 'shortint' ; +K_int : 'int' ; +K_longint : 'longint' ; +K_integer : 'integer' ; +K_module : 'module' ; +K_macromodule : 'macromodule' ; +K_program : 'program' ; +K_interface : 'interface' ; +K_endmodule : 'endmodule' ; +K_endprogram : 'endprogram' ; +K_endinterface : 'endinterface' ; +K_type : 'type' ; +K_trireg : 'trireg' ; +K_let : 'let' ; +DISCIPLINE_IDENTIFIER : 'DISCIPLINE_IDENTIFIER' ; +K_defparam : 'defparam' ; +K_pullup : 'pullup' ; +K_pulldown : 'pulldown' ; +K_assign : 'assign' ; +K_always : 'always' ; +K_always_comb : 'always_comb' ; +K_always_ff : 'always_ff' ; +K_always_latch : 'always_latch' ; +K_initial : 'initial' ; +K_analog : 'analog' ; +K_generate : 'generate' ; +K_endgenerate : 'endgenerate' ; +K_genvar : 'genvar' ; +K_case : 'case' ; +K_endcase : 'endcase' ; +K_specparam : 'specparam' ; +K_specify : 'specify' ; +K_endspecify : 'endspecify' ; +K_untyped : 'untyped' ; +K_begin : 'begin' ; +K_end : 'end' ; +K_wire : 'wire' ; +K_tri : 'tri' ; +K_tri1 : 'tri1' ; +K_wand : 'wand' ; +K_triand : 'triand' ; +K_tri0 : 'tri0' ; +K_wor : 'wor' ; +K_trior : 'trior' ; +K_wone : 'wone' ; +K_uwire : 'uwire' ; +K_parameter : 'parameter' ; +K_localparam : 'localparam' ; +K_inf : 'inf' ; +K_from : 'from' ; +K_DOTSTAR : 'K_DOTSTAR' ; +K_ifnone : 'ifnone' ; +K_Sfullskew : 'K_Sfullskew' ; +K_Shold : 'K_Shold' ; +K_Snochange : 'K_Snochange' ; +K_Speriod : 'K_Speriod' ; +K_Srecovery : 'K_Srecovery' ; +K_Srecrem : 'K_Srecrem' ; +K_Sremoval : 'K_Sremoval' ; +K_Ssetup : 'K_Ssetup' ; +K_Ssetuphold : 'K_Ssetuphold' ; +K_Sskew : 'K_Sskew' ; +K_Stimeskew : 'K_Stimeskew' ; +K_Swidth : 'K_Swidth' ; +K_pulsestyle_onevent : 'pulsestyle_onevent' ; +K_pulsestyle_ondetect : 'pulsestyle_ondetect' ; +K_showcancelled : 'showcancelled' ; +K_noshowcancelled : 'noshowcancelled' ; +K_EG : 'K_EG' ; +K_SG : 'K_SG' ; +PATHPULSE_IDENTIFIER : 'PATHPULSE_IDENTIFIER' ; +K_TAND : 'K_TAND' ; +K_edge_descriptor : 'edge_descriptor' ; +K_deassign : 'deassign' ; +K_force : 'force' ; +K_release : 'release' ; +K_fork : 'fork' ; +K_casex : 'casex' ; +K_casez : 'casez' ; +K_wait : 'wait' ; +K_with : 'with' ; +K_CONTRIBUTE : 'K_CONTRIBUTE' ; +K_table : 'table' ; +K_endtable : 'endtable' ; +K_primitive : 'primitive' ; +K_endprimitive : 'endprimitive' ; +K_unique0 : 'unique0' ; +K_priority : 'priority' ; + +} diff --git a/playground/java11.g b/playground/java11.g new file mode 100644 index 0000000..2d96477 --- /dev/null +++ b/playground/java11.g @@ -0,0 +1,682 @@ +//From: chaperon-3.0-final + +Java11 { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +//%token ABSTRACT +//%token BOOLEAN +//%token BREAK +//%token BYTE +//%token BYVALUE +//%token CASE +//%token CAST +//%token CATCH +//%token CHAR +//%token CLASS +//%token CONST +//%token CONTINUE +//%token DEFAULT +//%token DO +//%token DOUBLE +//%token ELSE +//%token EXTENDS +//%token FINAL +//%token FINALLY +//%token FLOAT +//%token FOR +//%token FUTURE +//%token GENERIC +//%token GOTO +//%token IF +//%token IMPLEMENTS +//%token IMPORT +//%token INNER +//%token INSTANCEOF +//%token INT +//%token INTERFACE +//%token LONG +//%token NATIVE +//%token NEW +//%token JNULL +//%token OPERATOR +//%token OUTER +//%token PACKAGE +//%token PRIVATE +//%token PROTECTED +//%token PUBLIC +//%token REST +//%token RETURN +//%token SHORT +//%token STATIC +//%token SUPER +//%token SWITCH +//%token SYNCHRONIZED +//%token THIS +//%token THROW +//%token THROWS +//%token TRANSIENT +//%token TRY +//%token VAR +//%token VOID +//%token VOLATILE +//%token WHILE +//%token OP_INC +//%token OP_DEC +//%token OP_SHL +//%token OP_SHR +//%token OP_SHRR +//%token OP_GE +//%token OP_LE +//%token OP_EQ +//%token OP_NE +//%token OP_LAND +//%token OP_LOR +//%token OP_DIM +//%token ASS_MUL +//%token ASS_DIV +//%token ASS_MOD +//%token ASS_ADD +//%token ASS_SUB +//%token ASS_SHL +//%token ASS_SHR +//%token ASS_SHRR +//%token ASS_AND +//%token ASS_XOR +//%token ASS_OR +//%token IDENTIFIER +//%token LITERAL +//%token BOOLLIT +//%token ',' +//%token ';' +//%token '.' +//%token '*' +//%token '{' +//%token '}' +//%token '=' +//%token '(' +//%token ')' +//%token ':' +//%token '[' +//%token ']' +//%token '~' +//%token '!' +//%token '+' +//%token '-' +//%token '/' +//%token '%' +//%token '<' +//%token '>' +//%token '&' +//%token '^' +//%token '|' +//%token '?' + +%nonassoc /*1*/ IF_WITHOUT_ELSE ; +%nonassoc /*2*/ ELSE ; + +//%start CompilationUnit + +//%% + +CompilationUnit : + ProgramFile + ; + +TypeSpecifier : + TypeName + | TypeName Dims + ; +TypeName : + PrimitiveType + | QualifiedName + ; +ClassNameList : + QualifiedName + | ClassNameList ',' QualifiedName + ; +PrimitiveType : + BOOLEAN + | CHAR + | BYTE + | SHORT + | INT + | LONG + | FLOAT + | DOUBLE + | VOID + ; +SemiColons : + ';' + | SemiColons ';' + ; +ProgramFile : + PackageStatement ImportStatements TypeDeclarations + | PackageStatement ImportStatements + | PackageStatement TypeDeclarations + | ImportStatements TypeDeclarations + | PackageStatement + | ImportStatements + | TypeDeclarations + ; +PackageStatement : + PACKAGE QualifiedName SemiColons + ; +TypeDeclarations : + TypeDeclarationOptSemi + | TypeDeclarations TypeDeclarationOptSemi + ; +TypeDeclarationOptSemi : + TypeDeclaration + | TypeDeclaration SemiColons + ; +ImportStatements : + ImportStatement + | ImportStatements ImportStatement + ; +ImportStatement : + IMPORT QualifiedName SemiColons + | IMPORT QualifiedName '.' '*' SemiColons + ; +QualifiedName : + IDENTIFIER + | QualifiedName '.' IDENTIFIER + ; +TypeDeclaration : + ClassHeader '{' FieldDeclarations '}' + | ClassHeader '{' '}' + ; +ClassHeader : + Modifiers ClassWord IDENTIFIER Extends Interfaces + | Modifiers ClassWord IDENTIFIER Extends + | Modifiers ClassWord IDENTIFIER Interfaces + | ClassWord IDENTIFIER Extends Interfaces + | Modifiers ClassWord IDENTIFIER + | ClassWord IDENTIFIER Extends + | ClassWord IDENTIFIER Interfaces + | ClassWord IDENTIFIER + ; +Modifiers : + Modifier + | Modifiers Modifier + ; +Modifier : + ABSTRACT + | FINAL + | PUBLIC + | PROTECTED + | PRIVATE + | STATIC + | TRANSIENT + | VOLATILE + | NATIVE + | SYNCHRONIZED + ; +ClassWord : + CLASS + | INTERFACE + ; +Interfaces : + IMPLEMENTS ClassNameList + ; +FieldDeclarations : + FieldDeclarationOptSemi + | FieldDeclarations FieldDeclarationOptSemi + ; +FieldDeclarationOptSemi : + FieldDeclaration + | FieldDeclaration SemiColons + ; +FieldDeclaration : + FieldVariableDeclaration ';' + | MethodDeclaration + | ConstructorDeclaration + | StaticInitializer + | NonStaticInitializer + | TypeDeclaration + ; +FieldVariableDeclaration : + Modifiers TypeSpecifier VariableDeclarators + | TypeSpecifier VariableDeclarators + ; +VariableDeclarators : + VariableDeclarator + | VariableDeclarators ',' VariableDeclarator + ; +VariableDeclarator : + DeclaratorName + | DeclaratorName '=' VariableInitializer + ; +VariableInitializer : + Expression + | '{' '}' + | '{' ArrayInitializers '}' + ; +ArrayInitializers : + VariableInitializer + | ArrayInitializers ',' VariableInitializer + | ArrayInitializers ',' + ; +MethodDeclaration : + Modifiers TypeSpecifier MethodDeclarator Throws MethodBody + | Modifiers TypeSpecifier MethodDeclarator MethodBody + | TypeSpecifier MethodDeclarator Throws MethodBody + | TypeSpecifier MethodDeclarator MethodBody + ; +MethodDeclarator : + DeclaratorName '(' ParameterList ')' + | DeclaratorName '(' ')' + | MethodDeclarator OP_DIM + ; +ParameterList : + Parameter + | ParameterList ',' Parameter + ; +Parameter : + TypeSpecifier DeclaratorName + | FINAL TypeSpecifier DeclaratorName + ; +DeclaratorName : + IDENTIFIER + | DeclaratorName OP_DIM + ; +Throws : + THROWS ClassNameList + ; +MethodBody : + Block + | ';' + ; +ConstructorDeclaration : + Modifiers ConstructorDeclarator Throws Block + | Modifiers ConstructorDeclarator Block + | ConstructorDeclarator Throws Block + | ConstructorDeclarator Block + ; +ConstructorDeclarator : + IDENTIFIER '(' ParameterList ')' + | IDENTIFIER '(' ')' + ; +StaticInitializer : + STATIC Block + ; +NonStaticInitializer : + Block + ; +Extends : + EXTENDS TypeName + | Extends ',' TypeName + ; +Block : + '{' LocalVariableDeclarationsAndStatements '}' + | '{' '}' + ; +LocalVariableDeclarationsAndStatements : + LocalVariableDeclarationOrStatement + | LocalVariableDeclarationsAndStatements LocalVariableDeclarationOrStatement + ; +LocalVariableDeclarationOrStatement : + LocalVariableDeclarationStatement + | Statement + ; +LocalVariableDeclarationStatement : + TypeSpecifier VariableDeclarators ';' + | FINAL TypeSpecifier VariableDeclarators ';' + ; +Statement : + EmptyStatement + | LabelStatement + | ExpressionStatement ';' + | SelectionStatement + | IterationStatement + | JumpStatement + | GuardingStatement + | Block + ; +EmptyStatement : + ';' + ; +LabelStatement : + IDENTIFIER ':' + | CASE ConstantExpression ':' + | DEFAULT ':' + ; +ExpressionStatement : + Expression + ; +SelectionStatement : + IF '(' Expression ')' Statement %prec IF_WITHOUT_ELSE + | IF '(' Expression ')' Statement ELSE Statement + | SWITCH '(' Expression ')' Block + ; +IterationStatement : + WHILE '(' Expression ')' Statement + | DO Statement WHILE '(' Expression ')' ';' + | FOR '(' ForInit ForExpr ForIncr ')' Statement + | FOR '(' ForInit ForExpr ')' Statement + ; +ForInit : + ExpressionStatements ';' + | LocalVariableDeclarationStatement + | ';' + ; +ForExpr : + Expression ';' + | ';' + ; +ForIncr : + ExpressionStatements + ; +ExpressionStatements : + ExpressionStatement + | ExpressionStatements ',' ExpressionStatement + ; +JumpStatement : + BREAK IDENTIFIER ';' + | BREAK ';' + | CONTINUE IDENTIFIER ';' + | CONTINUE ';' + | RETURN Expression ';' + | RETURN ';' + | THROW Expression ';' + ; +GuardingStatement : + SYNCHRONIZED '(' Expression ')' Statement + | TRY Block Finally + | TRY Block Catches + | TRY Block Catches Finally + ; +Catches : + Catch + | Catches Catch + ; +Catch : + CatchHeader Block + ; +CatchHeader : + CATCH '(' TypeSpecifier IDENTIFIER ')' + | CATCH '(' TypeSpecifier ')' + ; +Finally : + FINALLY Block + ; +PrimaryExpression : + QualifiedName + | NotJustName + ; +NotJustName : + SpecialName + | NewAllocationExpression + | ComplexPrimary + ; +ComplexPrimary : + '(' Expression ')' + | ComplexPrimaryNoParenthesis + ; +ComplexPrimaryNoParenthesis : + LITERAL + | BOOLLIT + | ArrayAccess + | FieldAccess + | MethodCall + ; +ArrayAccess : + QualifiedName '[' Expression ']' + | ComplexPrimary '[' Expression ']' + ; +FieldAccess : + NotJustName '.' IDENTIFIER + | RealPostfixExpression '.' IDENTIFIER + | QualifiedName '.' THIS + | QualifiedName '.' CLASS + | PrimitiveType '.' CLASS + ; +MethodCall : + MethodAccess '(' ArgumentList ')' + | MethodAccess '(' ')' + ; +MethodAccess : + ComplexPrimaryNoParenthesis + | SpecialName + | QualifiedName + ; +SpecialName : + THIS + | SUPER + | JNULL + ; +ArgumentList : + Expression + | ArgumentList ',' Expression + ; +NewAllocationExpression : + PlainNewAllocationExpression + | QualifiedName '.' PlainNewAllocationExpression + ; +PlainNewAllocationExpression : + ArrayAllocationExpression + | ClassAllocationExpression + | ArrayAllocationExpression '{' '}' + | ClassAllocationExpression '{' '}' + | ArrayAllocationExpression '{' ArrayInitializers '}' + | ClassAllocationExpression '{' FieldDeclarations '}' + ; +ClassAllocationExpression : + NEW TypeName '(' ArgumentList ')' + | NEW TypeName '(' ')' + ; +ArrayAllocationExpression : + NEW TypeName DimExprs Dims + | NEW TypeName DimExprs + | NEW TypeName Dims + ; +DimExprs : + DimExpr + | DimExprs DimExpr + ; +DimExpr : + '[' Expression ']' + ; +Dims : + OP_DIM + | Dims OP_DIM + ; +PostfixExpression : + PrimaryExpression + | RealPostfixExpression + ; +RealPostfixExpression : + PostfixExpression OP_INC + | PostfixExpression OP_DEC + ; +UnaryExpression : + OP_INC UnaryExpression + | OP_DEC UnaryExpression + | ArithmeticUnaryOperator CastExpression + | LogicalUnaryExpression + ; +LogicalUnaryExpression : + PostfixExpression + | LogicalUnaryOperator UnaryExpression + ; +LogicalUnaryOperator : + '~' + | '!' + ; +ArithmeticUnaryOperator : + '+' + | '-' + ; +CastExpression : + UnaryExpression + | '(' PrimitiveTypeExpression ')' CastExpression + | '(' ClassTypeExpression ')' CastExpression + | '(' Expression ')' LogicalUnaryExpression + ; +PrimitiveTypeExpression : + PrimitiveType + | PrimitiveType Dims + ; +ClassTypeExpression : + QualifiedName Dims + ; +MultiplicativeExpression : + CastExpression + | MultiplicativeExpression '*' CastExpression + | MultiplicativeExpression '/' CastExpression + | MultiplicativeExpression '%' CastExpression + ; +AdditiveExpression : + MultiplicativeExpression + | AdditiveExpression '+' MultiplicativeExpression + | AdditiveExpression '-' MultiplicativeExpression + ; +ShiftExpression : + AdditiveExpression + | ShiftExpression OP_SHL AdditiveExpression + | ShiftExpression OP_SHR AdditiveExpression + | ShiftExpression OP_SHRR AdditiveExpression + ; +RelationalExpression : + ShiftExpression + | RelationalExpression '<' ShiftExpression + | RelationalExpression '>' ShiftExpression + | RelationalExpression OP_LE ShiftExpression + | RelationalExpression OP_GE ShiftExpression + | RelationalExpression INSTANCEOF TypeSpecifier + ; +EqualityExpression : + RelationalExpression + | EqualityExpression OP_EQ RelationalExpression + | EqualityExpression OP_NE RelationalExpression + ; +AndExpression : + EqualityExpression + | AndExpression '&' EqualityExpression + ; +ExclusiveOrExpression : + AndExpression + | ExclusiveOrExpression '^' AndExpression + ; +InclusiveOrExpression : + ExclusiveOrExpression + | InclusiveOrExpression '|' ExclusiveOrExpression + ; +ConditionalAndExpression : + InclusiveOrExpression + | ConditionalAndExpression OP_LAND InclusiveOrExpression + ; +ConditionalOrExpression : + ConditionalAndExpression + | ConditionalOrExpression OP_LOR ConditionalAndExpression + ; +ConditionalExpression : + ConditionalOrExpression + | ConditionalOrExpression '?' Expression ':' ConditionalExpression + ; +AssignmentExpression : + ConditionalExpression + | UnaryExpression AssignmentOperator AssignmentExpression + ; +AssignmentOperator : + '=' + | ASS_MUL + | ASS_DIV + | ASS_MOD + | ASS_ADD + | ASS_SUB + | ASS_SHL + | ASS_SHR + | ASS_SHRR + | ASS_AND + | ASS_XOR + | ASS_OR + ; +Expression : + AssignmentExpression + ; +ConstantExpression : + ConditionalExpression + ; + +//Lexer + +BOOLEAN : 'boolean' ; +CHAR : 'char' ; +BYTE : 'byte' ; +SHORT : 'short' ; +INT : 'int' ; +LONG : 'long' ; +FLOAT : 'float' ; +DOUBLE : 'double' ; +VOID : 'void' ; +PACKAGE : 'package' ; +IMPORT : 'import' ; +IDENTIFIER : "[a-zA-Z_][a-zA-Z_0-9]*" ; +ABSTRACT : 'abstract' ; +FINAL : 'final' ; +PUBLIC : 'public' ; +PROTECTED : 'protected' ; +PRIVATE : 'private' ; +STATIC : 'static' ; +TRANSIENT : 'transient' ; +VOLATILE : 'volatile' ; +NATIVE : 'native' ; +SYNCHRONIZED : 'synchronized' ; +CLASS : 'class' ; +INTERFACE : 'interface' ; +IMPLEMENTS : 'implements' ; +OP_DIM : '[]' ; +THROWS : 'throws' ; +EXTENDS : 'extends' ; +CASE : 'case' ; +DEFAULT : 'default' ; +IF : 'if' ; +ELSE : 'else' ; +SWITCH : 'switch' ; +WHILE : 'while' ; +DO : 'do' ; +FOR : 'for' ; +BREAK : 'break' ; +CONTINUE : 'continue' ; +RETURN : 'return' ; +THROW : 'throw' ; +TRY : 'try' ; +CATCH : 'catch' ; +FINALLY : 'finally' ; +LITERAL : "\"([^\"\n]|\\[^\n])*\"" ; +LITERAL : "'([^'\n]|\\[^\n])'" ; +LITERAL : "0[xX][a-fA-F0-9]+|[0-9]+([Ee][+-]?[0-9]+)?|[0-9]*\\.[0-9]+([Ee][+-]?[0-9]+)?" ; +BOOLLIT : 'true' | 'false' ; +THIS : 'this' ; +SUPER : 'super' ; +JNULL : 'null' ; +NEW : 'new' ; +OP_INC : '++' ; +OP_DEC : '--' ; +OP_SHL : '<<' ; +OP_SHR : '>>' ; +OP_SHRR : '>>>' ; +OP_LE : '<=' ; +OP_GE : '>=' ; +INSTANCEOF : 'instanceof' ; +OP_EQ : '==' ; +OP_NE : '!=' ; +OP_LAND : '&&' ; +OP_LOR : '||' ; +ASS_MUL : '*=' ; +ASS_DIV : '/=' ; +ASS_MOD : '%=' ; +ASS_ADD : '+=' ; +ASS_SUB : '-=' ; +ASS_SHL : '<<=' ; +ASS_SHR : '>>=' ; +ASS_SHRR : '>>>=' ; +ASS_AND : '&=' ; +ASS_XOR : '^=' ; +ASS_OR : '|=' ; + +} diff --git a/playground/javascript-core.g b/playground/javascript-core.g new file mode 100644 index 0000000..5a92edc --- /dev/null +++ b/playground/javascript-core.g @@ -0,0 +1,1149 @@ +JavaScriptCore { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +//%token NULLTOKEN +//%token TRUETOKEN +//%token FALSETOKEN +//%token BREAK +//%token CASE +//%token DEFAULT +//%token FOR +//%token NEW +//%token VAR +//%token CONSTTOKEN +//%token CONTINUE +//%token FUNCTION +//%token RETURN +//%token VOIDTOKEN +//%token DELETETOKEN +//%token IF +//%token THISTOKEN +//%token DO +//%token WHILE +//%token INTOKEN +//%token INSTANCEOF +//%token TYPEOF +//%token SWITCH +//%token WITH +//%token RESERVED +//%token THROW +//%token TRY +//%token CATCH +//%token FINALLY +//%token DEBUGGER +//%token IF_WITHOUT_ELSE +//%token ELSE +//%token EQEQ +//%token NE +//%token STREQ +//%token STRNEQ +//%token LE +//%token GE +//%token OR +//%token AND +//%token PLUSPLUS +//%token MINUSMINUS +//%token LSHIFT +//%token RSHIFT +//%token URSHIFT +//%token PLUSEQUAL +//%token MINUSEQUAL +//%token MULTEQUAL +//%token DIVEQUAL +//%token LSHIFTEQUAL +//%token RSHIFTEQUAL +//%token URSHIFTEQUAL +//%token ANDEQUAL +//%token MODEQUAL +//%token XOREQUAL +//%token OREQUAL +//%token OPENBRACE +//%token CLOSEBRACE +//%token NUMBER +//%token IDENT +//%token STRING +//%token AUTOPLUSPLUS +//%token AUTOMINUSMINUS +//%token '/' +//%token ':' +//%token '(' +//%token ')' +//%token ',' +//%token '[' +//%token ']' +//%token '.' +//%token '+' +//%token '-' +//%token '~' +//%token '!' +//%token '*' +//%token '%' +//%token '<' +//%token '>' +//%token '&' +//%token '^' +//%token '|' +//%token '?' +//%token '=' +//%token ';' + +%nonassoc /*1*/ IF_WITHOUT_ELSE ; +%nonassoc /*2*/ ELSE ; + +//%start Program + +//%% + +Program : + /*empty*/ + | SourceElements + ; + +Literal : + NULLTOKEN + | TRUETOKEN + | FALSETOKEN + | NUMBER + | STRING + | '/' + | DIVEQUAL + ; +Property : + IDENT ':' AssignmentExpr + | STRING ':' AssignmentExpr + | NUMBER ':' AssignmentExpr + | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE + | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE + ; +PropertyList : + Property + | PropertyList ',' Property + ; +PrimaryExpr : + PrimaryExprNoBrace + | OPENBRACE CLOSEBRACE + | OPENBRACE PropertyList CLOSEBRACE + | OPENBRACE PropertyList ',' CLOSEBRACE + ; +PrimaryExprNoBrace : + THISTOKEN + | Literal + | ArrayLiteral + | IDENT + | '(' Expr ')' + ; +ArrayLiteral : + '[' ElisionOpt ']' + | '[' ElementList ']' + | '[' ElementList ',' ElisionOpt ']' + ; +ElementList : + ElisionOpt AssignmentExpr + | ElementList ',' ElisionOpt AssignmentExpr + ; +ElisionOpt : + /*empty*/ + | Elision + ; +Elision : + ',' + | Elision ',' + ; +MemberExpr : + PrimaryExpr + | FunctionExpr + | MemberExpr '[' Expr ']' + | MemberExpr '.' IDENT + | NEW MemberExpr Arguments + ; +MemberExprNoBF : + PrimaryExprNoBrace + | MemberExprNoBF '[' Expr ']' + | MemberExprNoBF '.' IDENT + | NEW MemberExpr Arguments + ; +NewExpr : + MemberExpr + | NEW NewExpr + ; +NewExprNoBF : + MemberExprNoBF + | NEW NewExpr + ; +CallExpr : + MemberExpr Arguments + | CallExpr Arguments + | CallExpr '[' Expr ']' + | CallExpr '.' IDENT + ; +CallExprNoBF : + MemberExprNoBF Arguments + | CallExprNoBF Arguments + | CallExprNoBF '[' Expr ']' + | CallExprNoBF '.' IDENT + ; +Arguments : + '(' ')' + | '(' ArgumentList ')' + ; +ArgumentList : + AssignmentExpr + | ArgumentList ',' AssignmentExpr + ; +LeftHandSideExpr : + NewExpr + | CallExpr + ; +LeftHandSideExprNoBF : + NewExprNoBF + | CallExprNoBF + ; +PostfixExpr : + LeftHandSideExpr + | LeftHandSideExpr PLUSPLUS + | LeftHandSideExpr MINUSMINUS + ; +PostfixExprNoBF : + LeftHandSideExprNoBF + | LeftHandSideExprNoBF PLUSPLUS + | LeftHandSideExprNoBF MINUSMINUS + ; +UnaryExprCommon : + DELETETOKEN UnaryExpr + | VOIDTOKEN UnaryExpr + | TYPEOF UnaryExpr + | PLUSPLUS UnaryExpr + | AUTOPLUSPLUS UnaryExpr + | MINUSMINUS UnaryExpr + | AUTOMINUSMINUS UnaryExpr + | '+' UnaryExpr + | '-' UnaryExpr + | '~' UnaryExpr + | '!' UnaryExpr + ; +UnaryExpr : + PostfixExpr + | UnaryExprCommon + ; +UnaryExprNoBF : + PostfixExprNoBF + | UnaryExprCommon + ; +MultiplicativeExpr : + UnaryExpr + | MultiplicativeExpr '*' UnaryExpr + | MultiplicativeExpr '/' UnaryExpr + | MultiplicativeExpr '%' UnaryExpr + ; +MultiplicativeExprNoBF : + UnaryExprNoBF + | MultiplicativeExprNoBF '*' UnaryExpr + | MultiplicativeExprNoBF '/' UnaryExpr + | MultiplicativeExprNoBF '%' UnaryExpr + ; +AdditiveExpr : + MultiplicativeExpr + | AdditiveExpr '+' MultiplicativeExpr + | AdditiveExpr '-' MultiplicativeExpr + ; +AdditiveExprNoBF : + MultiplicativeExprNoBF + | AdditiveExprNoBF '+' MultiplicativeExpr + | AdditiveExprNoBF '-' MultiplicativeExpr + ; +ShiftExpr : + AdditiveExpr + | ShiftExpr LSHIFT AdditiveExpr + | ShiftExpr RSHIFT AdditiveExpr + | ShiftExpr URSHIFT AdditiveExpr + ; +ShiftExprNoBF : + AdditiveExprNoBF + | ShiftExprNoBF LSHIFT AdditiveExpr + | ShiftExprNoBF RSHIFT AdditiveExpr + | ShiftExprNoBF URSHIFT AdditiveExpr + ; +RelationalExpr : + ShiftExpr + | RelationalExpr '<' ShiftExpr + | RelationalExpr '>' ShiftExpr + | RelationalExpr LE ShiftExpr + | RelationalExpr GE ShiftExpr + | RelationalExpr INSTANCEOF ShiftExpr + | RelationalExpr INTOKEN ShiftExpr + ; +RelationalExprNoIn : + ShiftExpr + | RelationalExprNoIn '<' ShiftExpr + | RelationalExprNoIn '>' ShiftExpr + | RelationalExprNoIn LE ShiftExpr + | RelationalExprNoIn GE ShiftExpr + | RelationalExprNoIn INSTANCEOF ShiftExpr + ; +RelationalExprNoBF : + ShiftExprNoBF + | RelationalExprNoBF '<' ShiftExpr + | RelationalExprNoBF '>' ShiftExpr + | RelationalExprNoBF LE ShiftExpr + | RelationalExprNoBF GE ShiftExpr + | RelationalExprNoBF INSTANCEOF ShiftExpr + | RelationalExprNoBF INTOKEN ShiftExpr + ; +EqualityExpr : + RelationalExpr + | EqualityExpr EQEQ RelationalExpr + | EqualityExpr NE RelationalExpr + | EqualityExpr STREQ RelationalExpr + | EqualityExpr STRNEQ RelationalExpr + ; +EqualityExprNoIn : + RelationalExprNoIn + | EqualityExprNoIn EQEQ RelationalExprNoIn + | EqualityExprNoIn NE RelationalExprNoIn + | EqualityExprNoIn STREQ RelationalExprNoIn + | EqualityExprNoIn STRNEQ RelationalExprNoIn + ; +EqualityExprNoBF : + RelationalExprNoBF + | EqualityExprNoBF EQEQ RelationalExpr + | EqualityExprNoBF NE RelationalExpr + | EqualityExprNoBF STREQ RelationalExpr + | EqualityExprNoBF STRNEQ RelationalExpr + ; +BitwiseANDExpr : + EqualityExpr + | BitwiseANDExpr '&' EqualityExpr + ; +BitwiseANDExprNoIn : + EqualityExprNoIn + | BitwiseANDExprNoIn '&' EqualityExprNoIn + ; +BitwiseANDExprNoBF : + EqualityExprNoBF + | BitwiseANDExprNoBF '&' EqualityExpr + ; +BitwiseXORExpr : + BitwiseANDExpr + | BitwiseXORExpr '^' BitwiseANDExpr + ; +BitwiseXORExprNoIn : + BitwiseANDExprNoIn + | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn + ; +BitwiseXORExprNoBF : + BitwiseANDExprNoBF + | BitwiseXORExprNoBF '^' BitwiseANDExpr + ; +BitwiseORExpr : + BitwiseXORExpr + | BitwiseORExpr '|' BitwiseXORExpr + ; +BitwiseORExprNoIn : + BitwiseXORExprNoIn + | BitwiseORExprNoIn '|' BitwiseXORExprNoIn + ; +BitwiseORExprNoBF : + BitwiseXORExprNoBF + | BitwiseORExprNoBF '|' BitwiseXORExpr + ; +LogicalANDExpr : + BitwiseORExpr + | LogicalANDExpr AND BitwiseORExpr + ; +LogicalANDExprNoIn : + BitwiseORExprNoIn + | LogicalANDExprNoIn AND BitwiseORExprNoIn + ; +LogicalANDExprNoBF : + BitwiseORExprNoBF + | LogicalANDExprNoBF AND BitwiseORExpr + ; +LogicalORExpr : + LogicalANDExpr + | LogicalORExpr OR LogicalANDExpr + ; +LogicalORExprNoIn : + LogicalANDExprNoIn + | LogicalORExprNoIn OR LogicalANDExprNoIn + ; +LogicalORExprNoBF : + LogicalANDExprNoBF + | LogicalORExprNoBF OR LogicalANDExpr + ; +ConditionalExpr : + LogicalORExpr + | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr + ; +ConditionalExprNoIn : + LogicalORExprNoIn + | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn + ; +ConditionalExprNoBF : + LogicalORExprNoBF + | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr + ; +AssignmentExpr : + ConditionalExpr + | LeftHandSideExpr AssignmentOperator AssignmentExpr + ; +AssignmentExprNoIn : + ConditionalExprNoIn + | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn + ; +AssignmentExprNoBF : + ConditionalExprNoBF + | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr + ; +AssignmentOperator : + '=' + | PLUSEQUAL + | MINUSEQUAL + | MULTEQUAL + | DIVEQUAL + | LSHIFTEQUAL + | RSHIFTEQUAL + | URSHIFTEQUAL + | ANDEQUAL + | XOREQUAL + | OREQUAL + | MODEQUAL + ; +Expr : + AssignmentExpr + | Expr ',' AssignmentExpr + ; +ExprNoIn : + AssignmentExprNoIn + | ExprNoIn ',' AssignmentExprNoIn + ; +ExprNoBF : + AssignmentExprNoBF + | ExprNoBF ',' AssignmentExpr + ; +Statement : + Block + | VariableStatement + | ConstStatement + | FunctionDeclaration + | EmptyStatement + | ExprStatement + | IfStatement + | IterationStatement + | ContinueStatement + | BreakStatement + | ReturnStatement + | WithStatement + | SwitchStatement + | LabelledStatement + | ThrowStatement + | TryStatement + | DebuggerStatement + ; +Block : + OPENBRACE CLOSEBRACE + | OPENBRACE SourceElements CLOSEBRACE + ; +VariableStatement : + VAR VariableDeclarationList ';' + //| VAR VariableDeclarationList error + ; +VariableDeclarationList : + IDENT + | IDENT Initializer + | VariableDeclarationList ',' IDENT + | VariableDeclarationList ',' IDENT Initializer + ; +VariableDeclarationListNoIn : + IDENT + | IDENT InitializerNoIn + | VariableDeclarationListNoIn ',' IDENT + | VariableDeclarationListNoIn ',' IDENT InitializerNoIn + ; +ConstStatement : + CONSTTOKEN ConstDeclarationList ';' + //| CONSTTOKEN ConstDeclarationList error + ; +ConstDeclarationList : + ConstDeclaration + | ConstDeclarationList ',' ConstDeclaration + ; +ConstDeclaration : + IDENT + | IDENT Initializer + ; +Initializer : + '=' AssignmentExpr + ; +InitializerNoIn : + '=' AssignmentExprNoIn + ; +EmptyStatement : + ';' + ; +ExprStatement : + ExprNoBF ';' + | ExprNoBF error + ; +IfStatement : + IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE /*1N*/ + | IF '(' Expr ')' Statement ELSE /*2N*/ Statement + ; +IterationStatement : + DO Statement WHILE '(' Expr ')' ';' + | DO Statement WHILE '(' Expr ')' error + | WHILE '(' Expr ')' Statement + | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement + | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement + | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement + | FOR '(' VAR IDENT INTOKEN Expr ')' Statement + | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement + ; +ExprOpt : + /*empty*/ + | Expr + ; +ExprNoInOpt : + /*empty*/ + | ExprNoIn + ; +ContinueStatement : + CONTINUE ';' + //| CONTINUE error + | CONTINUE IDENT ';' + //| CONTINUE IDENT error + ; +BreakStatement : + BREAK ';' + //| BREAK error + | BREAK IDENT ';' + //| BREAK IDENT error + ; +ReturnStatement : + RETURN ';' + //| RETURN error + | RETURN Expr ';' + //| RETURN Expr error + ; +WithStatement : + WITH '(' Expr ')' Statement + ; +SwitchStatement : + SWITCH '(' Expr ')' CaseBlock + ; +CaseBlock : + OPENBRACE CaseClausesOpt CLOSEBRACE + | OPENBRACE CaseClausesOpt DefaultClause CaseClausesOpt CLOSEBRACE + ; +CaseClausesOpt : + /*empty*/ + | CaseClauses + ; +CaseClauses : + CaseClause + | CaseClauses CaseClause + ; +CaseClause : + CASE Expr ':' + | CASE Expr ':' SourceElements + ; +DefaultClause : + DEFAULT ':' + | DEFAULT ':' SourceElements + ; +LabelledStatement : + IDENT ':' Statement + ; +ThrowStatement : + THROW Expr ';' + //| THROW Expr error + ; +TryStatement : + TRY Block FINALLY Block + | TRY Block CATCH '(' IDENT ')' Block + | TRY Block CATCH '(' IDENT ')' Block FINALLY Block + ; +DebuggerStatement : + DEBUGGER ';' + //| DEBUGGER error + ; +FunctionDeclaration : + FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE + | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE + ; +FunctionExpr : + FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE + | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE + | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE + | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE + ; +FormalParameterList : + IDENT + | FormalParameterList ',' IDENT + ; +FunctionBody : + /*empty*/ + | SourceElements_NoNode + ; +SourceElements : + Statement + | SourceElements Statement + ; +Literal_NoNode : + NULLTOKEN + | TRUETOKEN + | FALSETOKEN + | NUMBER + | STRING + | '/' + | DIVEQUAL + ; +Property_NoNode : + IDENT ':' AssignmentExpr_NoNode + | STRING ':' AssignmentExpr_NoNode + | NUMBER ':' AssignmentExpr_NoNode + | IDENT IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | IDENT IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + ; +PropertyList_NoNode : + Property_NoNode + | PropertyList_NoNode ',' Property_NoNode + ; +PrimaryExpr_NoNode : + PrimaryExprNoBrace_NoNode + | OPENBRACE CLOSEBRACE + | OPENBRACE PropertyList_NoNode CLOSEBRACE + | OPENBRACE PropertyList_NoNode ',' CLOSEBRACE + ; +PrimaryExprNoBrace_NoNode : + THISTOKEN + | Literal_NoNode + | ArrayLiteral_NoNode + | IDENT + | '(' Expr_NoNode ')' + ; +ArrayLiteral_NoNode : + '[' ElisionOpt_NoNode ']' + | '[' ElementList_NoNode ']' + | '[' ElementList_NoNode ',' ElisionOpt_NoNode ']' + ; +ElementList_NoNode : + ElisionOpt_NoNode AssignmentExpr_NoNode + | ElementList_NoNode ',' ElisionOpt_NoNode AssignmentExpr_NoNode + ; +ElisionOpt_NoNode : + /*empty*/ + | Elision_NoNode + ; +Elision_NoNode : + ',' + | Elision_NoNode ',' + ; +MemberExpr_NoNode : + PrimaryExpr_NoNode + | FunctionExpr_NoNode + | MemberExpr_NoNode '[' Expr_NoNode ']' + | MemberExpr_NoNode '.' IDENT + | NEW MemberExpr_NoNode Arguments_NoNode + ; +MemberExprNoBF_NoNode : + PrimaryExprNoBrace_NoNode + | MemberExprNoBF_NoNode '[' Expr_NoNode ']' + | MemberExprNoBF_NoNode '.' IDENT + | NEW MemberExpr_NoNode Arguments_NoNode + ; +NewExpr_NoNode : + MemberExpr_NoNode + | NEW NewExpr_NoNode + ; +NewExprNoBF_NoNode : + MemberExprNoBF_NoNode + | NEW NewExpr_NoNode + ; +CallExpr_NoNode : + MemberExpr_NoNode Arguments_NoNode + | CallExpr_NoNode Arguments_NoNode + | CallExpr_NoNode '[' Expr_NoNode ']' + | CallExpr_NoNode '.' IDENT + ; +CallExprNoBF_NoNode : + MemberExprNoBF_NoNode Arguments_NoNode + | CallExprNoBF_NoNode Arguments_NoNode + | CallExprNoBF_NoNode '[' Expr_NoNode ']' + | CallExprNoBF_NoNode '.' IDENT + ; +Arguments_NoNode : + '(' ')' + | '(' ArgumentList_NoNode ')' + ; +ArgumentList_NoNode : + AssignmentExpr_NoNode + | ArgumentList_NoNode ',' AssignmentExpr_NoNode + ; +LeftHandSideExpr_NoNode : + NewExpr_NoNode + | CallExpr_NoNode + ; +LeftHandSideExprNoBF_NoNode : + NewExprNoBF_NoNode + | CallExprNoBF_NoNode + ; +PostfixExpr_NoNode : + LeftHandSideExpr_NoNode + | LeftHandSideExpr_NoNode PLUSPLUS + | LeftHandSideExpr_NoNode MINUSMINUS + ; +PostfixExprNoBF_NoNode : + LeftHandSideExprNoBF_NoNode + | LeftHandSideExprNoBF_NoNode PLUSPLUS + | LeftHandSideExprNoBF_NoNode MINUSMINUS + ; +UnaryExprCommon_NoNode : + DELETETOKEN UnaryExpr_NoNode + | VOIDTOKEN UnaryExpr_NoNode + | TYPEOF UnaryExpr_NoNode + | PLUSPLUS UnaryExpr_NoNode + | AUTOPLUSPLUS UnaryExpr_NoNode + | MINUSMINUS UnaryExpr_NoNode + | AUTOMINUSMINUS UnaryExpr_NoNode + | '+' UnaryExpr_NoNode + | '-' UnaryExpr_NoNode + | '~' UnaryExpr_NoNode + | '!' UnaryExpr_NoNode + ; +UnaryExpr_NoNode : + PostfixExpr_NoNode + | UnaryExprCommon_NoNode + ; +UnaryExprNoBF_NoNode : + PostfixExprNoBF_NoNode + | UnaryExprCommon_NoNode + ; +MultiplicativeExpr_NoNode : + UnaryExpr_NoNode + | MultiplicativeExpr_NoNode '*' UnaryExpr_NoNode + | MultiplicativeExpr_NoNode '/' UnaryExpr_NoNode + | MultiplicativeExpr_NoNode '%' UnaryExpr_NoNode + ; +MultiplicativeExprNoBF_NoNode : + UnaryExprNoBF_NoNode + | MultiplicativeExprNoBF_NoNode '*' UnaryExpr_NoNode + | MultiplicativeExprNoBF_NoNode '/' UnaryExpr_NoNode + | MultiplicativeExprNoBF_NoNode '%' UnaryExpr_NoNode + ; +AdditiveExpr_NoNode : + MultiplicativeExpr_NoNode + | AdditiveExpr_NoNode '+' MultiplicativeExpr_NoNode + | AdditiveExpr_NoNode '-' MultiplicativeExpr_NoNode + ; +AdditiveExprNoBF_NoNode : + MultiplicativeExprNoBF_NoNode + | AdditiveExprNoBF_NoNode '+' MultiplicativeExpr_NoNode + | AdditiveExprNoBF_NoNode '-' MultiplicativeExpr_NoNode + ; +ShiftExpr_NoNode : + AdditiveExpr_NoNode + | ShiftExpr_NoNode LSHIFT AdditiveExpr_NoNode + | ShiftExpr_NoNode RSHIFT AdditiveExpr_NoNode + | ShiftExpr_NoNode URSHIFT AdditiveExpr_NoNode + ; +ShiftExprNoBF_NoNode : + AdditiveExprNoBF_NoNode + | ShiftExprNoBF_NoNode LSHIFT AdditiveExpr_NoNode + | ShiftExprNoBF_NoNode RSHIFT AdditiveExpr_NoNode + | ShiftExprNoBF_NoNode URSHIFT AdditiveExpr_NoNode + ; +RelationalExpr_NoNode : + ShiftExpr_NoNode + | RelationalExpr_NoNode '<' ShiftExpr_NoNode + | RelationalExpr_NoNode '>' ShiftExpr_NoNode + | RelationalExpr_NoNode LE ShiftExpr_NoNode + | RelationalExpr_NoNode GE ShiftExpr_NoNode + | RelationalExpr_NoNode INSTANCEOF ShiftExpr_NoNode + | RelationalExpr_NoNode INTOKEN ShiftExpr_NoNode + ; +RelationalExprNoIn_NoNode : + ShiftExpr_NoNode + | RelationalExprNoIn_NoNode '<' ShiftExpr_NoNode + | RelationalExprNoIn_NoNode '>' ShiftExpr_NoNode + | RelationalExprNoIn_NoNode LE ShiftExpr_NoNode + | RelationalExprNoIn_NoNode GE ShiftExpr_NoNode + | RelationalExprNoIn_NoNode INSTANCEOF ShiftExpr_NoNode + ; +RelationalExprNoBF_NoNode : + ShiftExprNoBF_NoNode + | RelationalExprNoBF_NoNode '<' ShiftExpr_NoNode + | RelationalExprNoBF_NoNode '>' ShiftExpr_NoNode + | RelationalExprNoBF_NoNode LE ShiftExpr_NoNode + | RelationalExprNoBF_NoNode GE ShiftExpr_NoNode + | RelationalExprNoBF_NoNode INSTANCEOF ShiftExpr_NoNode + | RelationalExprNoBF_NoNode INTOKEN ShiftExpr_NoNode + ; +EqualityExpr_NoNode : + RelationalExpr_NoNode + | EqualityExpr_NoNode EQEQ RelationalExpr_NoNode + | EqualityExpr_NoNode NE RelationalExpr_NoNode + | EqualityExpr_NoNode STREQ RelationalExpr_NoNode + | EqualityExpr_NoNode STRNEQ RelationalExpr_NoNode + ; +EqualityExprNoIn_NoNode : + RelationalExprNoIn_NoNode + | EqualityExprNoIn_NoNode EQEQ RelationalExprNoIn_NoNode + | EqualityExprNoIn_NoNode NE RelationalExprNoIn_NoNode + | EqualityExprNoIn_NoNode STREQ RelationalExprNoIn_NoNode + | EqualityExprNoIn_NoNode STRNEQ RelationalExprNoIn_NoNode + ; +EqualityExprNoBF_NoNode : + RelationalExprNoBF_NoNode + | EqualityExprNoBF_NoNode EQEQ RelationalExpr_NoNode + | EqualityExprNoBF_NoNode NE RelationalExpr_NoNode + | EqualityExprNoBF_NoNode STREQ RelationalExpr_NoNode + | EqualityExprNoBF_NoNode STRNEQ RelationalExpr_NoNode + ; +BitwiseANDExpr_NoNode : + EqualityExpr_NoNode + | BitwiseANDExpr_NoNode '&' EqualityExpr_NoNode + ; +BitwiseANDExprNoIn_NoNode : + EqualityExprNoIn_NoNode + | BitwiseANDExprNoIn_NoNode '&' EqualityExprNoIn_NoNode + ; +BitwiseANDExprNoBF_NoNode : + EqualityExprNoBF_NoNode + | BitwiseANDExprNoBF_NoNode '&' EqualityExpr_NoNode + ; +BitwiseXORExpr_NoNode : + BitwiseANDExpr_NoNode + | BitwiseXORExpr_NoNode '^' BitwiseANDExpr_NoNode + ; +BitwiseXORExprNoIn_NoNode : + BitwiseANDExprNoIn_NoNode + | BitwiseXORExprNoIn_NoNode '^' BitwiseANDExprNoIn_NoNode + ; +BitwiseXORExprNoBF_NoNode : + BitwiseANDExprNoBF_NoNode + | BitwiseXORExprNoBF_NoNode '^' BitwiseANDExpr_NoNode + ; +BitwiseORExpr_NoNode : + BitwiseXORExpr_NoNode + | BitwiseORExpr_NoNode '|' BitwiseXORExpr_NoNode + ; +BitwiseORExprNoIn_NoNode : + BitwiseXORExprNoIn_NoNode + | BitwiseORExprNoIn_NoNode '|' BitwiseXORExprNoIn_NoNode + ; +BitwiseORExprNoBF_NoNode : + BitwiseXORExprNoBF_NoNode + | BitwiseORExprNoBF_NoNode '|' BitwiseXORExpr_NoNode + ; +LogicalANDExpr_NoNode : + BitwiseORExpr_NoNode + | LogicalANDExpr_NoNode AND BitwiseORExpr_NoNode + ; +LogicalANDExprNoIn_NoNode : + BitwiseORExprNoIn_NoNode + | LogicalANDExprNoIn_NoNode AND BitwiseORExprNoIn_NoNode + ; +LogicalANDExprNoBF_NoNode : + BitwiseORExprNoBF_NoNode + | LogicalANDExprNoBF_NoNode AND BitwiseORExpr_NoNode + ; +LogicalORExpr_NoNode : + LogicalANDExpr_NoNode + | LogicalORExpr_NoNode OR LogicalANDExpr_NoNode + ; +LogicalORExprNoIn_NoNode : + LogicalANDExprNoIn_NoNode + | LogicalORExprNoIn_NoNode OR LogicalANDExprNoIn_NoNode + ; +LogicalORExprNoBF_NoNode : + LogicalANDExprNoBF_NoNode + | LogicalORExprNoBF_NoNode OR LogicalANDExpr_NoNode + ; +ConditionalExpr_NoNode : + LogicalORExpr_NoNode + | LogicalORExpr_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode + ; +ConditionalExprNoIn_NoNode : + LogicalORExprNoIn_NoNode + | LogicalORExprNoIn_NoNode '?' AssignmentExprNoIn_NoNode ':' AssignmentExprNoIn_NoNode + ; +ConditionalExprNoBF_NoNode : + LogicalORExprNoBF_NoNode + | LogicalORExprNoBF_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode + ; +AssignmentExpr_NoNode : + ConditionalExpr_NoNode + | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode + ; +AssignmentExprNoIn_NoNode : + ConditionalExprNoIn_NoNode + | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExprNoIn_NoNode + ; +AssignmentExprNoBF_NoNode : + ConditionalExprNoBF_NoNode + | LeftHandSideExprNoBF_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode + ; +AssignmentOperator_NoNode : + '=' + | PLUSEQUAL + | MINUSEQUAL + | MULTEQUAL + | DIVEQUAL + | LSHIFTEQUAL + | RSHIFTEQUAL + | URSHIFTEQUAL + | ANDEQUAL + | XOREQUAL + | OREQUAL + | MODEQUAL + ; +Expr_NoNode : + AssignmentExpr_NoNode + | Expr_NoNode ',' AssignmentExpr_NoNode + ; +ExprNoIn_NoNode : + AssignmentExprNoIn_NoNode + | ExprNoIn_NoNode ',' AssignmentExprNoIn_NoNode + ; +ExprNoBF_NoNode : + AssignmentExprNoBF_NoNode + | ExprNoBF_NoNode ',' AssignmentExpr_NoNode + ; +Statement_NoNode : + Block_NoNode + | VariableStatement_NoNode + | ConstStatement_NoNode + | FunctionDeclaration_NoNode + | EmptyStatement_NoNode + | ExprStatement_NoNode + | IfStatement_NoNode + | IterationStatement_NoNode + | ContinueStatement_NoNode + | BreakStatement_NoNode + | ReturnStatement_NoNode + | WithStatement_NoNode + | SwitchStatement_NoNode + | LabelledStatement_NoNode + | ThrowStatement_NoNode + | TryStatement_NoNode + | DebuggerStatement_NoNode + ; +Block_NoNode : + OPENBRACE CLOSEBRACE + | OPENBRACE SourceElements_NoNode CLOSEBRACE + ; +VariableStatement_NoNode : + VAR VariableDeclarationList_NoNode ';' + //| VAR VariableDeclarationList_NoNode error + ; +VariableDeclarationList_NoNode : + IDENT + | IDENT Initializer_NoNode + | VariableDeclarationList_NoNode ',' IDENT + | VariableDeclarationList_NoNode ',' IDENT Initializer_NoNode + ; +VariableDeclarationListNoIn_NoNode : + IDENT + | IDENT InitializerNoIn_NoNode + | VariableDeclarationListNoIn_NoNode ',' IDENT + | VariableDeclarationListNoIn_NoNode ',' IDENT InitializerNoIn_NoNode + ; +ConstStatement_NoNode : + CONSTTOKEN ConstDeclarationList_NoNode ';' + //| CONSTTOKEN ConstDeclarationList_NoNode error + ; +ConstDeclarationList_NoNode : + ConstDeclaration_NoNode + | ConstDeclarationList_NoNode ',' ConstDeclaration_NoNode + ; +ConstDeclaration_NoNode : + IDENT + | IDENT Initializer_NoNode + ; +Initializer_NoNode : + '=' AssignmentExpr_NoNode + ; +InitializerNoIn_NoNode : + '=' AssignmentExprNoIn_NoNode + ; +EmptyStatement_NoNode : + ';' + ; +ExprStatement_NoNode : + ExprNoBF_NoNode ';' + //| ExprNoBF_NoNode error + ; +IfStatement_NoNode : + IF '(' Expr_NoNode ')' Statement_NoNode %prec IF_WITHOUT_ELSE /*1N*/ + | IF '(' Expr_NoNode ')' Statement_NoNode ELSE /*2N*/ Statement_NoNode + ; +IterationStatement_NoNode : + DO Statement_NoNode WHILE '(' Expr_NoNode ')' ';' + //| DO Statement_NoNode WHILE '(' Expr_NoNode ')' error + | WHILE '(' Expr_NoNode ')' Statement_NoNode + | FOR '(' ExprNoInOpt_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode + | FOR '(' VAR VariableDeclarationListNoIn_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode + | FOR '(' LeftHandSideExpr_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode + | FOR '(' VAR IDENT INTOKEN Expr_NoNode ')' Statement_NoNode + | FOR '(' VAR IDENT InitializerNoIn_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode + ; +ExprOpt_NoNode : + /*empty*/ + | Expr_NoNode + ; +ExprNoInOpt_NoNode : + /*empty*/ + | ExprNoIn_NoNode + ; +ContinueStatement_NoNode : + CONTINUE ';' + //| CONTINUE error + | CONTINUE IDENT ';' + //| CONTINUE IDENT error + ; +BreakStatement_NoNode : + BREAK ';' + //| BREAK error + | BREAK IDENT ';' + //| BREAK IDENT error + ; +ReturnStatement_NoNode : + RETURN ';' + //| RETURN error + | RETURN Expr_NoNode ';' + //| RETURN Expr_NoNode error + ; +WithStatement_NoNode : + WITH '(' Expr_NoNode ')' Statement_NoNode + ; +SwitchStatement_NoNode : + SWITCH '(' Expr_NoNode ')' CaseBlock_NoNode + ; +CaseBlock_NoNode : + OPENBRACE CaseClausesOpt_NoNode CLOSEBRACE + | OPENBRACE CaseClausesOpt_NoNode DefaultClause_NoNode CaseClausesOpt_NoNode CLOSEBRACE + ; +CaseClausesOpt_NoNode : + /*empty*/ + | CaseClauses_NoNode + ; +CaseClauses_NoNode : + CaseClause_NoNode + | CaseClauses_NoNode CaseClause_NoNode + ; +CaseClause_NoNode : + CASE Expr_NoNode ':' + | CASE Expr_NoNode ':' SourceElements_NoNode + ; +DefaultClause_NoNode : + DEFAULT ':' + | DEFAULT ':' SourceElements_NoNode + ; +LabelledStatement_NoNode : + IDENT ':' Statement_NoNode + ; +ThrowStatement_NoNode : + THROW Expr_NoNode ';' + //| THROW Expr_NoNode error + ; +TryStatement_NoNode : + TRY Block_NoNode FINALLY Block_NoNode + | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode + | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode FINALLY Block_NoNode + ; +DebuggerStatement_NoNode : + DEBUGGER ';' + //| DEBUGGER error + ; +FunctionDeclaration_NoNode : + FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + ; +FunctionExpr_NoNode : + FUNCTION '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | FUNCTION '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE + ; +FormalParameterList_NoNode : + IDENT + | FormalParameterList_NoNode ',' IDENT + ; +FunctionBody_NoNode : + /*empty*/ + | SourceElements_NoNode + ; +SourceElements_NoNode : + Statement_NoNode + | SourceElements_NoNode Statement_NoNode + ; + +//Lexer + +ELSE : 'else' ; +NULLTOKEN : 'null' ; +TRUETOKEN : 'true' ; +FALSETOKEN : 'false' ; +NUMBER : "0[xX][a-fA-F0-9]+|[0-9]+([Ee][+-]?[0-9]+)?|[0-9]*\\.[0-9]+([Ee][+-]?[0-9]+)?" ; +STRING : "\"[^\"\n]*\"|'[^'\n]*'" ; +DIVEQUAL : '/=' ; +IDENT : "[a-zA-Z_$][a-zA-Z_0-9]*" ; +OPENBRACE : '{' ; +CLOSEBRACE : '}' ; +THISTOKEN : 'this' ; +NEW : 'new' ; +PLUSPLUS : '++' ; +MINUSMINUS : '--' ; +DELETETOKEN : 'delete' ; +VOIDTOKEN : 'void' ; +TYPEOF : 'typeof' ; +AUTOPLUSPLUS : 'AUTOPLUSPLUS' ; +AUTOMINUSMINUS : 'AUTOMINUSMINUS' ; +LSHIFT : '<<' ; +RSHIFT : '>>' ; +URSHIFT : '>>>' ; +LE : '<=' ; +GE : '>=' ; +INSTANCEOF : 'instanceof' ; +INTOKEN : 'in' ; +EQEQ : '==' ; +NE : '!=' ; +STREQ : '===' ; +STRNEQ : '!==' ; +AND : '&&' ; +OR : '||' ; +PLUSEQUAL : '+=' ; +MINUSEQUAL : '-=' ; +MULTEQUAL : '*=' ; +LSHIFTEQUAL : '<<=' ; +RSHIFTEQUAL : '>>=' ; +URSHIFTEQUAL : '>>>=' ; +ANDEQUAL : '&=' ; +XOREQUAL : '^=' ; +OREQUAL : '|=' ; +MODEQUAL : '%=' ; +VAR : 'var' ; +CONSTTOKEN : 'const' ; +IF : 'if' ; +DO : 'do' ; +WHILE : 'while' ; +FOR : 'for' ; +CONTINUE : 'continue' ; +BREAK : 'break' ; +RETURN : 'return' ; +WITH : 'with' ; +SWITCH : 'switch' ; +CASE : 'case' ; +DEFAULT : 'default' ; +THROW : 'throw' ; +TRY : 'try' ; +FINALLY : 'finally' ; +CATCH : 'catch' ; +DEBUGGER : 'debugger' ; +FUNCTION : 'function' ; + +} \ No newline at end of file diff --git a/playground/jscript-parser.g b/playground/jscript-parser.g new file mode 100644 index 0000000..c4d3bc2 --- /dev/null +++ b/playground/jscript-parser.g @@ -0,0 +1,708 @@ +//From: https://github.com/ValveSoftware/wine/blob/cd165953c8b379a78418711f07417022e503c81b/dlls/jscript/parser.y + +jscript { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token kBREAK +//%token kCASE +//%token kCATCH +//%token kCONST +//%token kCONTINUE +//%token kDEFAULT +//%token kDELETE +//%token kDO +//%token kELSE +//%token kFUNCTION +//%token kIF +//%token kFINALLY +//%token kFOR +//%token kGET +//%token kIN +//%token kLET +//%token kSET +//%token kINSTANCEOF +//%token kNEW +//%token kNULL +//%token kRETURN +//%token kSWITCH +//%token kTHIS +//%token kTHROW +//%token kTRUE +//%token kFALSE +//%token kTRY +//%token kTYPEOF +//%token kVAR +//%token kVOID +//%token kWHILE +//%token kWITH +//%token tANDAND +//%token tOROR +//%token tINC +//%token tDEC +//%token tHTMLCOMMENT +//%token kDIVEQ +//%token kDCOL +//%token tIdentifier +//%token tAssignOper +//%token tEqOper +//%token tShiftOper +//%token tRelOper +//%token tNumericLiteral +//%token tBooleanLiteral +//%token tStringLiteral +//%token LOWER_THAN_ELSE +//%token ':' +//%token '{' +//%token '}' +//%token ',' +//%token '=' +//%token ';' +//%token '?' +//%token '|' +//%token '^' +//%token '&' +//%token '+' +//%token '-' +//%token '*' +//%token '/' +//%token '%' +//%token '~' +//%token '!' +//%token '[' +//%token ']' +//%token '.' +//%token '(' +//%token ')' + +%nonassoc /*1*/ LOWER_THAN_ELSE ; +%nonassoc /*2*/ kELSE kIN kINSTANCEOF ':' ; +%nonassoc /*3*/ kGET kLET kSET ; + +//%start Script + +//%% + +Script : + /*YYEOF + |*/ ScriptBody HtmlComment + ; + +ScriptBody : + StatementList_opt + ; + +HtmlComment : + tHTMLCOMMENT + | /*empty*/ + ; + +FunctionStatementList : + StatementList_opt + ; + +FunctionExpression : + kFUNCTION left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + | kFUNCTION Identifier left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + | kFUNCTION Identifier kDCOL Identifier left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + ; + +FunctionBody : + FunctionStatementList + ; + +FormalParameterList : + Identifier + | FormalParameterList ',' Identifier + ; + +FormalParameterList_opt : + /*empty*/ + | FormalParameterList + ; + +Statement : + Block + | VariableStatement + | EmptyStatement + | FunctionExpression + | ExpressionStatement + | IfStatement + | IterationStatement + | ContinueStatement + | BreakStatement + | ReturnStatement + | WithStatement + | LabelledStatement + | SwitchStatement + | ThrowStatement + | TryStatement + ; + +Declaration : + LexicalDeclaration + ; + +StatementListItem : + Statement + | Declaration + ; + +StatementList : + StatementListItem + | StatementList StatementListItem + ; + +StatementList_opt : + /*empty*/ + | StatementList + ; + +Block : + '{' StatementList '}' + | '{' '}' + ; + +LexicalDeclaration : + kLET /*3N*/ VariableDeclarationList semicolon_opt + | kCONST VariableDeclarationList semicolon_opt + ; + +LexicalDeclarationNoIn : + kLET /*3N*/ VariableDeclarationListNoIn semicolon_opt + | kCONST VariableDeclarationListNoIn semicolon_opt + ; + +VariableStatement : + kVAR VariableDeclarationList semicolon_opt + ; + +VariableDeclarationList : + VariableDeclaration + | VariableDeclarationList ',' VariableDeclaration + ; + +VariableDeclarationListNoIn : + VariableDeclarationNoIn + | VariableDeclarationListNoIn ',' VariableDeclarationNoIn + ; + +VariableDeclaration : + Identifier Initialiser_opt + ; + +VariableDeclarationNoIn : + Identifier InitialiserNoIn_opt + ; + +Initialiser_opt : + /*empty*/ + | Initialiser + ; + +Initialiser : + '=' AssignmentExpression + ; + +InitialiserNoIn_opt : + /*empty*/ + | InitialiserNoIn + ; + +InitialiserNoIn : + '=' AssignmentExpressionNoIn + ; + +EmptyStatement : + ';' + ; + +ExpressionStatement : + Expression semicolon_opt + ; + +IfStatement : + kIF left_bracket Expression_err right_bracket Statement kELSE /*2N*/ Statement + | kIF left_bracket Expression_err right_bracket Statement %prec LOWER_THAN_ELSE /*1N*/ + ; + +IterationStatement : + kDO Statement kWHILE left_bracket Expression_err right_bracket semicolon_opt + | kWHILE left_bracket Expression_err right_bracket Statement + | kFOR left_bracket ExpressionNoIn_opt semicolon Expression_opt semicolon Expression_opt right_bracket Statement + | kFOR left_bracket kVAR VariableDeclarationListNoIn semicolon Expression_opt semicolon Expression_opt right_bracket Statement + | kFOR left_bracket LeftHandSideExpression kIN /*2N*/ Expression_err right_bracket Statement + | kFOR left_bracket kVAR VariableDeclarationNoIn kIN /*2N*/ Expression_err right_bracket Statement + | kFOR left_bracket LexicalDeclarationNoIn Expression_opt semicolon Expression_opt right_bracket Statement + ; + +ContinueStatement : + kCONTINUE Identifier_opt semicolon_opt + ; + +BreakStatement : + kBREAK Identifier_opt semicolon_opt + ; + +ReturnStatement : + kRETURN Expression_opt semicolon_opt + ; + +WithStatement : + kWITH left_bracket Expression right_bracket Statement + ; + +LabelledStatement : + tIdentifier ':' /*2N*/ Statement + | kGET /*3N*/ ':' /*2N*/ Statement + | kSET /*3N*/ ':' /*2N*/ Statement + | kLET /*3N*/ ':' /*2N*/ Statement + ; + +SwitchStatement : + kSWITCH left_bracket Expression right_bracket CaseBlock + ; + +CaseBlock : + '{' CaseClausules_opt '}' + | '{' CaseClausules_opt DefaultClausule CaseClausules_opt '}' + ; + +CaseClausules_opt : + /*empty*/ + | CaseClausules + ; + +CaseClausules : + CaseClausule + | CaseClausules CaseClausule + ; + +CaseClausule : + kCASE Expression ':' /*2N*/ StatementList_opt + ; + +DefaultClausule : + kDEFAULT ':' /*2N*/ StatementList_opt + ; + +ThrowStatement : + kTHROW Expression semicolon_opt + ; + +TryStatement : + kTRY Block Catch + | kTRY Block Finally + | kTRY Block Catch Finally + ; + +Catch : + kCATCH left_bracket Identifier right_bracket Block + ; + +Finally : + kFINALLY Block + ; + +Expression_opt : + /*empty*/ + | Expression + ; + +Expression_err : + Expression + | error + ; + +Expression : + AssignmentExpression + | Expression ',' AssignmentExpression + ; + +ExpressionNoIn_opt : + /*empty*/ + | ExpressionNoIn + ; + +ExpressionNoIn : + AssignmentExpressionNoIn + | ExpressionNoIn ',' AssignmentExpressionNoIn + ; + +AssignOper : + tAssignOper + | kDIVEQ + ; + +AssignmentExpression : + ConditionalExpression + | LeftHandSideExpression '=' AssignmentExpression + | LeftHandSideExpression AssignOper AssignmentExpression + ; + +AssignmentExpressionNoIn : + ConditionalExpressionNoIn + | LeftHandSideExpression '=' AssignmentExpressionNoIn + | LeftHandSideExpression AssignOper AssignmentExpressionNoIn + ; + +ConditionalExpression : + LogicalORExpression + | LogicalORExpression '?' AssignmentExpression ':' /*2N*/ AssignmentExpression + ; + +ConditionalExpressionNoIn : + LogicalORExpressionNoIn + | LogicalORExpressionNoIn '?' AssignmentExpressionNoIn ':' /*2N*/ AssignmentExpressionNoIn + ; + +LogicalORExpression : + LogicalANDExpression + | LogicalORExpression tOROR LogicalANDExpression + ; + +LogicalORExpressionNoIn : + LogicalANDExpressionNoIn + | LogicalORExpressionNoIn tOROR LogicalANDExpressionNoIn + ; + +LogicalANDExpression : + BitwiseORExpression + | LogicalANDExpression tANDAND BitwiseORExpression + ; + +LogicalANDExpressionNoIn : + BitwiseORExpressionNoIn + | LogicalANDExpressionNoIn tANDAND BitwiseORExpressionNoIn + ; + +BitwiseORExpression : + BitwiseXORExpression + | BitwiseORExpression '|' BitwiseXORExpression + ; + +BitwiseORExpressionNoIn : + BitwiseXORExpressionNoIn + | BitwiseORExpressionNoIn '|' BitwiseXORExpressionNoIn + ; + +BitwiseXORExpression : + BitwiseANDExpression + | BitwiseXORExpression '^' BitwiseANDExpression + ; + +BitwiseXORExpressionNoIn : + BitwiseANDExpressionNoIn + | BitwiseXORExpressionNoIn '^' BitwiseANDExpressionNoIn + ; + +BitwiseANDExpression : + EqualityExpression + | BitwiseANDExpression '&' EqualityExpression + ; + +BitwiseANDExpressionNoIn : + EqualityExpressionNoIn + | BitwiseANDExpressionNoIn '&' EqualityExpressionNoIn + ; + +EqualityExpression : + RelationalExpression + | EqualityExpression tEqOper RelationalExpression + ; + +EqualityExpressionNoIn : + RelationalExpressionNoIn + | EqualityExpressionNoIn tEqOper RelationalExpressionNoIn + ; + +RelationalExpression : + ShiftExpression + | RelationalExpression tRelOper ShiftExpression + | RelationalExpression kINSTANCEOF /*2N*/ ShiftExpression + | RelationalExpression kIN /*2N*/ ShiftExpression + ; + +RelationalExpressionNoIn : + ShiftExpression + | RelationalExpressionNoIn tRelOper ShiftExpression + | RelationalExpressionNoIn kINSTANCEOF /*2N*/ ShiftExpression + ; + +ShiftExpression : + AdditiveExpression + | ShiftExpression tShiftOper AdditiveExpression + ; + +AdditiveExpression : + MultiplicativeExpression + | AdditiveExpression '+' MultiplicativeExpression + | AdditiveExpression '-' MultiplicativeExpression + ; + +MultiplicativeExpression : + UnaryExpression + | MultiplicativeExpression '*' UnaryExpression + | MultiplicativeExpression '/' UnaryExpression + | MultiplicativeExpression '%' UnaryExpression + ; + +UnaryExpression : + PostfixExpression + | kDELETE UnaryExpression + | kVOID UnaryExpression + | kTYPEOF UnaryExpression + | tINC UnaryExpression + | tDEC UnaryExpression + | '+' UnaryExpression + | '-' UnaryExpression + | '~' UnaryExpression + | '!' UnaryExpression + ; + +PostfixExpression : + LeftHandSideExpression + | LeftHandSideExpression tINC + | LeftHandSideExpression tDEC + ; + +LeftHandSideExpression : + NewExpression + | CallExpression + ; + +NewExpression : + MemberExpression + | kNEW NewExpression + ; + +MemberExpression : + PrimaryExpression + | FunctionExpression + | MemberExpression '[' Expression ']' + | MemberExpression '.' IdentifierName + | kNEW MemberExpression Arguments + ; + +CallExpression : + MemberExpression Arguments + | CallExpression Arguments + | CallExpression '[' Expression ']' + | CallExpression '.' IdentifierName + ; + +Arguments : + '(' ')' + | '(' ArgumentList ')' + ; + +ArgumentList : + AssignmentExpression + | ArgumentList ',' AssignmentExpression + ; + +PrimaryExpression : + kTHIS + | Identifier + | Literal + | ArrayLiteral + | ObjectLiteral + | '(' Expression ')' + ; + +ArrayLiteral : + '[' ']' + | '[' Elision ']' + | '[' ElementList ']' + | '[' ElementList ',' Elision_opt ']' + ; + +ElementList : + Elision_opt AssignmentExpression + | ElementList ',' Elision_opt AssignmentExpression + ; + +Elision : + ',' + | Elision ',' + ; + +Elision_opt : + /*empty*/ + | Elision + ; + +ObjectLiteral : + '{' '}' + | '{' PropertyNameAndValueList '}' + | '{' PropertyNameAndValueList ',' '}' + ; + +PropertyNameAndValueList : + PropertyDefinition + | PropertyNameAndValueList ',' PropertyDefinition + ; + +PropertyDefinition : + PropertyName ':' /*2N*/ AssignmentExpression + | kGET /*3N*/ PropertyName GetterSetterMethod + | kSET /*3N*/ PropertyName GetterSetterMethod + ; + +GetterSetterMethod : + left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + ; + +PropertyName : + IdentifierName + | tStringLiteral + | tNumericLiteral + ; + +Identifier_opt : + /*empty*/ + | Identifier + ; + +Identifier : + tIdentifier + | ES5Keyword + ; + +IdentifierName : + tIdentifier + | ReservedAsIdentifier + ; + +ReservedAsIdentifier : + kBREAK + | kCASE + | kCATCH + | kCONST + | kCONTINUE + | kDEFAULT + | kDELETE + | kDO + | kELSE /*2N*/ + | kFALSE + | kFINALLY + | kFOR + | kFUNCTION + | kIF + | kIN /*2N*/ + | kINSTANCEOF /*2N*/ + | kNEW + | kNULL + | kRETURN + | kSWITCH + | kTHIS + | kTHROW + | kTRUE + | kTRY + | kTYPEOF + | kVAR + | kVOID + | kWHILE + | kWITH + | ES5Keyword + ; + +ES5Keyword : + kGET /*3N*/ + | kLET /*3N*/ + | kSET /*3N*/ + ; + +Literal : + kNULL + | BooleanLiteral + | tNumericLiteral + | tStringLiteral + | '/' + | kDIVEQ + ; + +BooleanLiteral : + kTRUE + | kFALSE + | tBooleanLiteral + ; + +semicolon_opt : + ';' + | error + ; + +left_bracket : + '(' + | error + ; + +right_bracket : + ')' + | error + ; + +semicolon : + ';' + | error + ; + +//Lexer + +kELSE : 'kELSE' ; +kIN : 'kIN' ; +kINSTANCEOF : 'kINSTANCEOF' ; +kGET : 'kGET' ; +kLET : 'kLET' ; +kSET : 'kSET' ; +tHTMLCOMMENT : 'tHTMLCOMMENT' ; +kFUNCTION : 'kFUNCTION' ; +kDCOL : 'kDCOL' ; +kCONST : 'kCONST' ; +kVAR : 'kVAR' ; +kIF : 'kIF' ; +kDO : 'kDO' ; +kWHILE : 'kWHILE' ; +kFOR : 'kFOR' ; +kCONTINUE : 'kCONTINUE' ; +kBREAK : 'kBREAK' ; +kRETURN : 'kRETURN' ; +kWITH : 'kWITH' ; +tIdentifier : 'tIdentifier' ; +kSWITCH : 'kSWITCH' ; +kCASE : 'kCASE' ; +kDEFAULT : 'kDEFAULT' ; +kTHROW : 'kTHROW' ; +kTRY : 'kTRY' ; +kCATCH : 'kCATCH' ; +kFINALLY : 'kFINALLY' ; +tAssignOper : 'tAssignOper' ; +kDIVEQ : 'kDIVEQ' ; +tOROR : 'tOROR' ; +tANDAND : 'tANDAND' ; +tEqOper : 'tEqOper' ; +tRelOper : 'tRelOper' ; +tShiftOper : 'tShiftOper' ; +kDELETE : 'kDELETE' ; +kVOID : 'kVOID' ; +kTYPEOF : 'kTYPEOF' ; +tINC : 'tINC' ; +tDEC : 'tDEC' ; +kNEW : 'kNEW' ; +kTHIS : 'kTHIS' ; +tStringLiteral : 'tStringLiteral' ; +tNumericLiteral : 'tNumericLiteral' ; +kFALSE : 'kFALSE' ; +kNULL : 'kNULL' ; +kTRUE : 'kTRUE' ; +tBooleanLiteral : 'tBooleanLiteral' ; + +} diff --git a/playground/json3.g b/playground/json3.g new file mode 100644 index 0000000..fb09a60 --- /dev/null +++ b/playground/json3.g @@ -0,0 +1,61 @@ +// /usr/bin/time /home/mingo/dev/c/A_grammars/lalr/test-grammar-nb/dist/Release/GNU-Linux/test-grammar-nb -g json2.g -i BytecodeList.json +// /usr/bin/time /home/mingo/dev/c/A_grammars/lalr/test-grammar-nb/dist/Release/GNU-Linux/test-grammar-nb -g json2.g -i /home/mingo/dev/c/A_grammars/tree-sitter/tree-sitter-dart/src/grammar.json +json { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + + document: object | array [document] + ; + + value: + 'null' [value] + | 'true' [value] + | 'false' [value] + | integer [value] + | real [value] + | string [value] + | array [value] + | object [value] + ; + + object: + '{' kv_list '}' [object] + ; + + array: + '[' value_list ']' [array] + ; + + value_list : + /*empty*/ + | value + | value_list ',' value + ; + + kv_list: + /*empty*/ + | key_val + | kv_list ',' key_val + ; + + key_val: + string ':' value [key_val] + ; + + integer: + "(\+|\-)?[0-9]+" + ; + + real: + "(\+|\-)?[0-9]+(\.[0-9]+)?((e|E)(\+|\-)?[0-9]+)?" + ; + + string: + //"[\"](\\[\"\\\\]|[^\"\n])*[\"]" + //| "['](\\['\\\\]|[^'\n])*[']" + "\"(\\[\"\\]|[^\"\n])*\"|'(\\['\\]|[^'\n])*'" + ; +} diff --git a/playground/json5.g b/playground/json5.g new file mode 100644 index 0000000..dcee565 --- /dev/null +++ b/playground/json5.g @@ -0,0 +1,127 @@ +//Based on: https://github.com/Joakker/tree-sitter-json5 +json5 { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\r\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +file : + object + | array + ; + +object : + LCURLY kv_list comma_opt RCURLY + ; + +comma_opt: + /*empty*/ + | COMMA + ; + +kv_list : + /*emty*/ + | member + | kv_list COMMA member + ; + +member : + name COLON _value + ; + +name : + string + | identifier + ; + +array : + LBRACK value_list comma_opt RBRACK + ; + +value_list : + /*empty*/ + | _value + | value_list COMMA _value + ; + +string : + string_dq + | string_sq + ; + +number : + num_sign_opt _number + ; + +num_sign_opt: + /*empty*/ + | num_sign + ; + +_number : + _number_hex + | _number_zd + | _number_d + | _number_infinity + | _number_nan + ; + +_value : + object + | array + | number + | string + | NULL + | TRUE + | FALSE + ; + +identifier : + //[\$_\p{L}] ( [\$_\p{L}] | [0-9] ) * + "[a-zA-Z_][a-zA-Z_0-9]*" + ; + +string_dq : + "\"((\\[\"\\bfnrtv\n])|[^\"\\])*\"" + ; + +string_sq : + "'((\\['\\bfnrtv\n])|[^'\\])*'" + ; + +num_sign: + "\+|\-" + ; + +_number_hex : + "0[xX][0-9a-fA-F]+" + ; + +_number_zd : + "(0|[1-9][0-9]*)(\.[0-9]*)?([eE][+-]?[0-9]+)?" + ; + +_number_d : + "\.[0-9]*([eE][+-]?[0-9]+)?" + ; + +_number_infinity: + 'Infinity' + ; + +_number_nan: + 'NaN' + ; + +NULL : 'null' ; +TRUE : 'true' ; +FALSE : 'false' ; +LBRACK : '[' ; +RBRACK : ']' ; +LCURLY : '{' ; +RCURLY : '}' ; +COMMA : ',' ; +COLON : ':' ; + +} diff --git a/playground/lalr.g b/playground/lalr.g new file mode 100644 index 0000000..1b86bf9 --- /dev/null +++ b/playground/lalr.g @@ -0,0 +1,119 @@ +lalr { + //%error_recovery_off; + //%error_recovery_show; + %whitespace "[ \t\r\n]*"; + %whitespace "//[^\n]*"; + //%whitespace "/\*[^*]+\*/"; + %whitespace "/\\*:C_MultilineComment:"; + + match_grammar: + match_identifier '{' match_statements '}' + ; + + match_identifier: + "[a-zA-Z_][a-zA-Z_0-9]*" + ; + + match_statements: + match_statement + | match_statements match_statement + ; + + match_statement: + match_associativity_statement + | match_whitespace_statement + | match_case_insensitive_statement + | match_error_recovery_statement + | match_production_statement + ; + + match_associativity_statement: + match_associativity match_symbols ';' + ; + + match_whitespace_statement: + '%whitespace' match_regex ';' + ; + + match_case_insensitive_statement: + '%case_insensitive' ';' + ; + + match_error_recovery_statement: + '%error_recovery_off' ';' + |'%error_recovery_show' ';' + ; + + match_production_statement: + match_identifier ':' match_expressions ';' + ; + + match_associativity: + '%left' + | '%right' + | none_assoc + | '%precedence' + ; + + none_assoc: + '%none' + | '%nonassoc' + ; + + match_symbols: + match_symbol + | match_symbols match_symbol + ; + + match_symbol: + match_error + | match_literal + | match_regex + | match_identifier + ; + + match_error: + 'error' + ; + + match_literal: + "'(\\.|[^'\n])+'" + ; + + match_regex: + "\"(\\.|[^\"\n])+\"" + ; + + match_expressions: + match_expression + | match_expressions match_expression_or + ; + + match_expression_or: + '|' match_expression + ; + + match_expression: + match_symbols_opt match_precedence match_action + ; + + match_symbols_opt: + /*empty*/ + | match_symbols + ; + + match_precedence: + /*empty*/ + | prec_tag match_symbol + ; + + prec_tag: + '%precedence' + | '%prec' + ; + + match_action: + /*empty*/ + | '[' match_identifier ']' + ; +} diff --git a/playground/lsl_ext.g b/playground/lsl_ext.g new file mode 100644 index 0000000..5acb3d2 --- /dev/null +++ b/playground/lsl_ext.g @@ -0,0 +1,415 @@ +//From: https://github.com/riej/lsl_ext/blob/master/parser/parser.y + +lsl_ext { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +//%whitespace "/\*.+\*/"; ////!!!!<<< this makes lalr enter an endless loop +%whitespace "/\*:C_MultilineComment:"; + +//%token COMMENT +//%token C_STYLE_COMMENT +//%token INTEGER +//%token FLOAT +//%token STRING +//%token KEY +//%token VECTOR +//%token ROTATION +//%token LIST +//%token INTEGER_CONSTANT +//%token FLOAT_CONSTANT +//%token STRING_CONSTANT +//%token IDENTIFIER +//%token DEFAULT +//%token STATE +//%token JUMP +//%token RETURN +//%token IF +//%token ELSE +//%token FOR +//%token DO +//%token WHILE +//%token INC_OP +//%token DEC_OP +//%token ADD_ASSIGN +//%token SUB_ASSIGN +//%token MUL_ASSIGN +//%token DIV_ASSIGN +//%token MOD_ASSIGN +//%token EQ +//%token NEQ +//%token LEQ +//%token GEQ +//%token BOOLEAN_AND +//%token BOOLEAN_OR +//%token SHIFT_LEFT +//%token SHIFT_RIGHT +//%token ARRAY_BRACES +//%token BOOLEAN +//%token TRUE +//%token FALSE +//%token INCLUDE +//%token PRAGMA +//%token STRUCT +//%token SWITCH +//%token CASE +//%token BREAK +//%token CONTINUE +//%token CONST +//%token DELETE +//%token '{' +//%token '@' +//%token '-' +//%token '!' +//%token '~' +//%token '(' +//%token '<' +//%token '[' +//%token '#' +//%token LOWER_THAN_ELSE +//%token '=' +//%token '|' +//%token '^' +//%token '&' +//%token '>' +//%token '+' +//%token '*' +//%token '/' +//%token '%' +//%token LIST_ITEM_PREC +//%token INITIALIZER +//%token '}' +//%token ',' +//%token ';' +//%token ')' +//%token ':' +//%token '.' +//%token ']' + +%nonassoc /*1*/ LOWER_THAN_ELSE ; +%nonassoc /*2*/ ELSE ; +%nonassoc /*3*/ INTEGER_CONSTANT FLOAT_CONSTANT ; +%right /*4*/ ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN '=' ; +%left /*5*/ BOOLEAN_AND BOOLEAN_OR ; +%left /*6*/ '|' ; +%left /*7*/ '^' ; +%left /*8*/ '&' ; +%left /*9*/ EQ NEQ ; +%left /*10*/ LEQ GEQ '<' '>' ; +%left /*11*/ SHIFT_LEFT SHIFT_RIGHT ; +%left /*12*/ '-' '+' ; +%left /*13*/ '*' '/' '%' ; +%right /*14*/ INC_OP DEC_OP '!' '~' ; +%right /*15*/ '[' ; //LIST_ITEM_PREC ; +%nonassoc /*16*/ INITIALIZER ; + +//%start lscript_program + +//%% + +lscript_program : + globals states + | globals + | states + ; +globals : + global + | preproc + | globals preproc + | globals global + ; +preproc : + '#' INCLUDE STRING_CONSTANT + | '#' PRAGMA IDENTIFIER + ; +global : + variable_declaration + | function + | struct + | empty_statement + ; +identifier : + IDENTIFIER + ; +typename : + INTEGER + | FLOAT + | STRING + | KEY + | VECTOR + | ROTATION + | LIST + | BOOLEAN + ; +constant : + INTEGER_CONSTANT /*3N*/ + | FLOAT_CONSTANT /*3N*/ + | STRING_CONSTANT + | TRUE + | FALSE + ; +pre_variable : + identifier + | identifier '=' /*4R*/ expression + | identifier '{' '}' + | identifier '{' struct_expression_variables '}' + ; +pre_variables : + pre_variable + | pre_variables ',' pre_variable + ; +variable_declaration : + typename pre_variables ';' + | identifier pre_variables ';' + | identifier ARRAY_BRACES pre_variables ';' + | CONST pre_variables ';' + ; +variable_declarations : + variable_declaration + | variable_declarations variable_declaration + ; +struct : + STRUCT identifier '{' variable_declarations '}' + ; +function : + identifier '(' ')' block_statement + | typename identifier '(' ')' block_statement + | identifier '(' function_arguments ')' block_statement + | typename identifier '(' function_arguments ')' block_statement + ; +function_arguments : + function_argument + | function_argument ',' function_arguments + ; +function_argument : + typename identifier + | identifier identifier + ; +event : + identifier '(' ')' block_statement + | identifier '(' function_arguments ')' block_statement + ; +events : + event + | event events + ; +states : + default_state + | default_state other_states + ; +other_states : + state + | state other_states + ; +default_state : + DEFAULT '{' events '}' + | DEFAULT '{' '}' + ; +state : + STATE identifier '{' events '}' + | STATE identifier '{' '}' + ; +block_statement : + '{' '}' + | '{' statements '}' + ; +statements : + statement + | variable_declaration + | statements statement + | statements variable_declaration + ; +empty_statement : + ';' + ; +statement : + empty_statement + | STATE identifier ';' + | STATE DEFAULT ';' + | '@' identifier ';' + | JUMP identifier ';' + | RETURN expression ';' + | RETURN ';' + | expression ';' + | block_statement + | IF '(' expression ')' statement %prec LOWER_THAN_ELSE /*1N*/ + | IF '(' expression ')' statement ELSE /*2N*/ statement + | FOR '(' for_expression_list ';' expression ';' for_expression_list ')' statement + | FOR '(' for_expression_list ';' ';' for_expression_list ')' statement + | DO statement WHILE '(' expression ')' ';' + | WHILE '(' expression ')' statement + | SWITCH '(' expression ')' block_statement + | CASE next_for_expression_list ':' + | DEFAULT ':' + | BREAK ';' + | CONTINUE ';' + ; +for_expression_list : + /*empty*/ + | next_for_expression_list + ; +next_for_expression_list : + expression + | expression ',' next_for_expression_list + ; +lvalue_identifiers : + identifier + | identifier '.' identifier + ; +list_item_expression : + lvalue_identifiers '[' /*15R*/ expression ']' + | lvalue_identifiers '[' /*15R*/ expression ',' expression ']' + ; +lvalue : + lvalue_identifiers + | list_item_expression + | lvalue_identifiers '[' /*15R*/ expression ']' '.' identifier + ; +expression : + unary_expression + | typecast_expression + | lvalue '=' /*4R*/ expression + | lvalue ADD_ASSIGN /*4R*/ expression + | lvalue SUB_ASSIGN /*4R*/ expression + | lvalue MUL_ASSIGN /*4R*/ expression + | lvalue DIV_ASSIGN /*4R*/ expression + | lvalue MOD_ASSIGN /*4R*/ expression + | expression EQ /*9L*/ expression + | expression NEQ /*9L*/ expression + | expression LEQ /*10L*/ expression + | expression GEQ /*10L*/ expression + | expression '<' /*10L*/ expression + | expression '>' /*10L*/ expression + | expression '+' /*12L*/ expression + | expression '-' /*12L*/ expression + | expression '*' /*13L*/ expression + | expression '/' /*13L*/ expression + | expression '%' /*13L*/ expression + | expression '&' /*8L*/ expression + | expression '|' /*6L*/ expression + | expression '^' /*7L*/ expression + | expression BOOLEAN_AND /*5L*/ expression + | expression BOOLEAN_OR /*5L*/ expression + | expression SHIFT_LEFT /*11L*/ expression + | expression SHIFT_RIGHT /*11L*/ expression + ; +unary_expression : + '-' /*12L*/ expression + | '!' /*14R*/ expression + | '~' /*14R*/ expression + | INC_OP /*14R*/ lvalue + | DEC_OP /*14R*/ lvalue + | DELETE list_item_expression + | unary_postfix_expression + | '#' unary_expression + | '(' expression ')' + ; +typecast_expression : + '(' typename ')' unary_expression + ; +unary_postfix_expression : + '<' /*10L*/ expression ',' expression ',' expression '>' /*10L*/ %prec INITIALIZER /*16N*/ + | '<' /*10L*/ expression ',' expression ',' expression ',' expression '>' /*10L*/ %prec INITIALIZER /*16N*/ + | ARRAY_BRACES %prec INITIALIZER /*16N*/ + | '[' /*15R*/ list_values ']' %prec INITIALIZER /*16N*/ + | struct_expression %prec INITIALIZER /*16N*/ + | lvalue + | lvalue INC_OP /*14R*/ + | lvalue DEC_OP /*14R*/ + | identifier '(' ')' + | identifier '(' list_values ')' + | constant + ; +list_values : + expression + | expression ',' list_values + ; +struct_expression : + identifier '{' '}' + | identifier '{' struct_expression_variables '}' + ; +struct_expression_variables : + struct_expression_variable + | struct_expression_variable ',' struct_expression_variables + ; +struct_expression_variable : + identifier ':' expression + ; + +//Lexer + +//"\([^"]+\)":\s*\(\w[^,]+\), +INTEGER : 'integer' ; +INTEGER : 'int' ; +FLOAT : 'float' ; +STRING : 'string' ; +KEY : 'key' ; +VECTOR : 'vector' ; +ROTATION : 'rotation' ; +ROTATION : 'quaternion' ; +LIST : 'list' ; + +DEFAULT : 'default' ; +STATE : 'state' ; + +JUMP : 'jump' ; +RETURN : 'return' ; +IF : 'if' ; +ELSE : 'else' ; +FOR : 'for' ; +DO : 'do' ; +WHILE : 'while' ; + +INC_OP : '++' ; +DEC_OP : '--' ; + +ADD_ASSIGN : '+=' ; +SUB_ASSIGN : '-=' ; +MUL_ASSIGN : '*=' ; +DIV_ASSIGN : '/=' ; +MOD_ASSIGN : '%=' ; + +EQ : '==' ; +NEQ : '!=' ; +LEQ : '<=' ; +GEQ : '>=' ; + +BOOLEAN_AND : '&&' ; +BOOLEAN_OR : '||' ; + +SHIFT_LEFT : '<<' ; +SHIFT_RIGHT : '>>' ; + +BOOLEAN : 'boolean' ; +TRUE : 'true' ; +FALSE : 'false' ; +TRUE : 'TRUE' ; +FALSE : 'FALSE' ; + +INCLUDE : 'include' ; +PRAGMA : 'pragma' ; + +STRUCT : 'struct' ; + +ARRAY_BRACES : '[]' ; + +SWITCH : 'switch' ; +CASE : 'case' ; +BREAK : 'break' ; +CONTINUE : 'continue' ; + +CONST : 'const' ; + +DELETE : 'delete' ; + +IDENTIFIER : "[A-Z_a-z][A-Z_a-z0-9]*" ; +INTEGER_CONSTANT : "[0-9]+" ; +FLOAT_CONSTANT : "([0-9]+\.[0-9]*|\.[0-9]+)([Ee](\+|\-)?[0-9]+)?" ; +STRING_CONSTANT : "\"(\\.|[^\"\n])*\"" ; + +//COMMENT : "//[^\n]*"; +//C_STYLE_COMMENT : "/\*.+\*/" ; +//C_STYLE_COMMENT : "/\*[^*]+\*/" ; + +} diff --git a/playground/lua.g b/playground/lua.g new file mode 100644 index 0000000..9f3e60a --- /dev/null +++ b/playground/lua.g @@ -0,0 +1,372 @@ +// /home/mingo/dev/c/A_grammars/lalr/lalr-nb/dist/Release/GNU-Linux/lalr-nb lua.g + +lua { +%whitespace "([ \t\r\n]*)|(\-\-[^\n]*)"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token AND +//%token BREAK +//%token DO +//%token ELSE +//%token ELSEIF +//%token END +//%token FALSE +//%token FOR +//%token FUNCTION +//%token IF +//%token IN +//%token LOCAL +//%token NIL +//%token NOT +//%token OR +//%token REPEAT +//%token RETURN +//%token THEN +//%token TRUE +//%token UNTIL +//%token WHILE +//%token CONCAT +//%token ELLIPSES +//%token EQ +//%token GE +//%token LE +//%token NE +//%token SPECIAL +//%token SPECIAL_CONST +//%token SPECIAL_NUMBER +//%token NUMBER +//%token STRING +//%token IDENTIFIER +//%token '<' +//%token '>' +//%token '+' +//%token '-' +//%token '*' +//%token '/' +//%token '%' +//%token UNARY_OPERATOR +//%token '^' +//%token ';' +//%token '=' +//%token ',' +//%token ':' +//%token '.' +//%token '(' +//%token ')' +//%token '#' +//%token '[' +//%token ']' +//%token '{' +//%token '}' + +//declared to eliminate/silence the 2 shift reduce +%left '(' ; +%left IDENTIFIER ; +%left STRING ; + +%left /*1*/ OR ; +%left /*2*/ AND ; +%left /*3*/ GE LE '<' '>' ; +%left /*4*/ EQ NE ; +%right /*5*/ CONCAT ; +%left /*6*/ '+' '-' ; +%left /*7*/ '*' '/' '%' ; +%left /*8*/ UNARY_OPERATOR ; +%right /*9*/ '^' ; + +//%start file + +//%% + +file : + opt_block + ; + +opt_block : + opt_block_statements + ; + +opt_block_statements : + /*empty*/ + | last_statement + | statement_list + | statement_list last_statement + ; + +class_1_statement : + nobr_function_call + ; + +class_2_statement : + br_function_call + ; + +class_3_statement : + nobr_statement opt_special + | nobr_statement ';' opt_special + | nobr_function_call ';' + ; + +class_4_statement : + br_statement + | br_statement ';' + | br_function_call ';' + ; + +statement_list : + statement_list_1 + | statement_list_2 + | statement_list_3 + | statement_list_4 + ; + +statement_list_1 : + class_1_statement + | statement_list_1 class_1_statement + | statement_list_2 class_1_statement + | statement_list_3 class_1_statement + | statement_list_4 class_1_statement + ; + +statement_list_2 : + class_2_statement + | statement_list_3 class_2_statement + | statement_list_4 class_2_statement + ; + +statement_list_3 : + class_3_statement + | statement_list_1 class_3_statement + | statement_list_2 class_3_statement + | statement_list_3 class_3_statement + | statement_list_4 class_3_statement + ; + +statement_list_4 : + class_4_statement + | statement_list_3 class_4_statement + | statement_list_4 class_4_statement + ; + +nobr_statement : + nobr_variable_list '=' expression_list + | DO opt_block END + | WHILE expression DO opt_block END + | REPEAT opt_block UNTIL expression + | IF expression THEN opt_block opt_elseif_block_list opt_else_block END + | FOR IDENTIFIER '=' expression ',' expression DO opt_block END + | FOR IDENTIFIER '=' expression ',' expression ',' expression DO opt_block END + | FOR identifier_list IN expression_list DO opt_block END + | FUNCTION func_name_list function_body + | FUNCTION func_name_list ':' IDENTIFIER function_body + | LOCAL FUNCTION IDENTIFIER function_body + | LOCAL identifier_list + | LOCAL identifier_list '=' expression_list + | IDENTIFIER STRING + ; + +br_statement : + br_variable_list '=' expression_list + ; + +opt_elseif_block_list : + /*empty*/ + | elseif_block_list + ; + +elseif_block_list : + elseif_block + | elseif_block_list elseif_block + ; + +elseif_block : + ELSEIF expression THEN opt_block + ; + +opt_else_block : + /*empty*/ + | ELSE opt_block + ; + +last_statement : + RETURN opt_semicolon + | RETURN expression_list opt_semicolon + | BREAK opt_semicolon + ; + +nobr_variable_list : + nobr_variable + | nobr_variable_list ',' nobr_variable + | nobr_variable_list ',' br_variable + ; + +br_variable_list : + br_variable + | br_variable_list ',' nobr_variable + | br_variable_list ',' br_variable + ; + +func_name_list : + IDENTIFIER + | func_name_list '.' IDENTIFIER + ; + +expression : + NIL + | FALSE + | TRUE + | NUMBER + | STRING + | ELLIPSES + | FUNCTION function_body + | nobr_prefix_expression %prec '(' + | '(' expression ')' + | table_constructor + | expression CONCAT /*5R*/ expression + | expression '+' /*6L*/ expression + | expression '-' /*6L*/ expression + | expression '*' /*7L*/ expression + | expression '/' /*7L*/ expression + | expression '^' /*9R*/ expression + | expression '%' /*7L*/ expression + | expression '<' /*3L*/ expression + | expression LE /*3L*/ expression + | expression '>' /*3L*/ expression + | expression GE /*3L*/ expression + | expression EQ /*4L*/ expression + | expression NE /*4L*/ expression + | expression AND /*2L*/ expression + | expression OR /*1L*/ expression + | NOT expression %precedence UNARY_OPERATOR /*8L*/ + | '-' /*6L*/ expression %precedence UNARY_OPERATOR /*8L*/ + | '#' expression %precedence UNARY_OPERATOR /*8L*/ + ; + +expression_list : + expression + | expression_list ',' expression + ; + +nobr_prefix_expression : + nobr_variable + | nobr_function_call + ; + +nobr_variable : + IDENTIFIER + | nobr_prefix_expression '[' expression ']' + | nobr_prefix_expression '.' IDENTIFIER + ; + +br_variable : + '(' expression ')' '[' expression ']' + | '(' expression ')' '.' IDENTIFIER + ; + +nobr_function_call : + nobr_prefix_expression arguments + | nobr_prefix_expression ':' IDENTIFIER arguments + ; + +br_function_call : + '(' expression ')' arguments + | '(' expression ')' ':' IDENTIFIER arguments + ; + +arguments : + '(' ')' + | '(' expression_list ')' + | table_constructor + | STRING + ; + +function_body : + '(' opt_parameter_list ')' opt_block END + ; + +opt_parameter_list : + /*empty*/ + | ELLIPSES + | identifier_list + | identifier_list ',' ELLIPSES + ; + +table_constructor : + '{' '}' + | '{' field_list opt_field_separator '}' + ; + +field_list : + field + | field_list field_separator field + ; + +field : + '[' expression ']' '=' expression + | IDENTIFIER '=' expression + | expression + ; + +opt_semicolon : + /*empty*/ + | ';' + ; + +field_separator : + ',' + | ';' + ; + +opt_field_separator : + /*empty*/ + | field_separator + ; + +identifier_list : + IDENTIFIER + | identifier_list ',' IDENTIFIER + ; + +opt_special : + /*empty*/ + | SPECIAL + ; + +// Tokens +//\("[^"]+"\)\s+{ TOKEN(\([^)]+\)); } +AND : 'and' ; +BREAK : 'break' ; +DO : 'do' ; +ELSE : 'else' ; +ELSEIF : 'elseif' ; +END : 'end' ; +FALSE : 'false' ; +FOR : 'for' ; +FUNCTION : 'function' ; +IF : 'if' ; +IN : 'in' ; +LOCAL : 'local' ; +NIL : 'nil' ; +NOT : 'not' ; +OR : 'or' ; +REPEAT : 'repeat' ; +RETURN : 'return' ; +THEN : 'then' ; +TRUE : 'true' ; +UNTIL : 'until' ; +WHILE : 'while' ; +CONCAT : '..' ; +ELLIPSES : '...' ; +EQ : '==' ; +GE : '>=' ; +LE : '<=' ; +NE : '~=' ; + +IDENTIFIER : "[a-zA-Z_][a-zA-Z_0-9]*" ; +NUMBER : "0[xX][a-fA-F0-9]+|[0-9]+([Ee][+-]?[0-9]+)?|[0-9]*\\.[0-9]+([Ee][+-]?[0-9]+)?" ; +STRING : "\"[^\"\n]*\"|'[^'\n]*'" ; +SPECIAL : '--@' ; +} \ No newline at end of file diff --git a/playground/php-8.2.g b/playground/php-8.2.g new file mode 100644 index 0000000..30b1dac --- /dev/null +++ b/playground/php-8.2.g @@ -0,0 +1,1440 @@ +php { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token END +//%token YYerror +//%token YYUNDEF +//%token PREC_ARROW_FUNCTION +//%token '=' +//%token '?' +//%token ':' +//%token '|' +//%token '^' +//%token '<' +//%token '>' +//%token '.' +//%token '+' +//%token '-' +//%token '*' +//%token '/' +//%token '%' +//%token '!' +//%token '~' +//%token '@' +//%token T_NOELSE +//%token T_LNUMBER +//%token T_DNUMBER +//%token T_STRING +//%token T_NAME_FULLY_QUALIFIED +//%token T_NAME_RELATIVE +//%token T_NAME_QUALIFIED +//%token T_VARIABLE +//%token T_INLINE_HTML +//%token T_ENCAPSED_AND_WHITESPACE +//%token T_CONSTANT_ENCAPSED_STRING +//%token T_STRING_VARNAME +//%token T_NUM_STRING +//%token T_INCLUDE +//%token T_INCLUDE_ONCE +//%token T_EVAL +//%token T_REQUIRE +//%token T_REQUIRE_ONCE +//%token T_LOGICAL_OR +//%token T_LOGICAL_XOR +//%token T_LOGICAL_AND +//%token T_PRINT +//%token T_YIELD +//%token T_YIELD_FROM +//%token T_INSTANCEOF +//%token T_NEW +//%token T_CLONE +//%token T_EXIT +//%token T_IF +//%token T_ELSEIF +//%token T_ELSE +//%token T_ENDIF +//%token T_ECHO +//%token T_DO +//%token T_WHILE +//%token T_ENDWHILE +//%token T_FOR +//%token T_ENDFOR +//%token T_FOREACH +//%token T_ENDFOREACH +//%token T_DECLARE +//%token T_ENDDECLARE +//%token T_AS +//%token T_SWITCH +//%token T_ENDSWITCH +//%token T_CASE +//%token T_DEFAULT +//%token T_MATCH +//%token T_BREAK +//%token T_CONTINUE +//%token T_GOTO +//%token T_FUNCTION +//%token T_FN +//%token T_CONST +//%token T_RETURN +//%token T_TRY +//%token T_CATCH +//%token T_FINALLY +//%token T_THROW +//%token T_USE +//%token T_INSTEADOF +//%token T_GLOBAL +//%token T_STATIC +//%token T_ABSTRACT +//%token T_FINAL +//%token T_PRIVATE +//%token T_PROTECTED +//%token T_PUBLIC +//%token T_READONLY +//%token T_VAR +//%token T_UNSET +//%token T_ISSET +//%token T_EMPTY +//%token T_HALT_COMPILER +//%token T_CLASS +//%token T_TRAIT +//%token T_INTERFACE +//%token T_ENUM +//%token T_EXTENDS +//%token T_IMPLEMENTS +//%token T_NAMESPACE +//%token T_LIST +//%token T_ARRAY +//%token T_CALLABLE +//%token T_LINE +//%token T_FILE +//%token T_DIR +//%token T_CLASS_C +//%token T_TRAIT_C +//%token T_METHOD_C +//%token T_FUNC_C +//%token T_NS_C +//%token T_ATTRIBUTE +//%token T_PLUS_EQUAL +//%token T_MINUS_EQUAL +//%token T_MUL_EQUAL +//%token T_DIV_EQUAL +//%token T_CONCAT_EQUAL +//%token T_MOD_EQUAL +//%token T_AND_EQUAL +//%token T_OR_EQUAL +//%token T_XOR_EQUAL +//%token T_SL_EQUAL +//%token T_SR_EQUAL +//%token T_COALESCE_EQUAL +//%token T_BOOLEAN_OR +//%token T_BOOLEAN_AND +//%token T_IS_EQUAL +//%token T_IS_NOT_EQUAL +//%token T_IS_IDENTICAL +//%token T_IS_NOT_IDENTICAL +//%token T_IS_SMALLER_OR_EQUAL +//%token T_IS_GREATER_OR_EQUAL +//%token T_SPACESHIP +//%token T_SL +//%token T_SR +//%token T_INC +//%token T_DEC +//%token T_INT_CAST +//%token T_DOUBLE_CAST +//%token T_STRING_CAST +//%token T_ARRAY_CAST +//%token T_OBJECT_CAST +//%token T_BOOL_CAST +//%token T_UNSET_CAST +//%token T_OBJECT_OPERATOR +//%token T_NULLSAFE_OBJECT_OPERATOR +//%token T_DOUBLE_ARROW +//%token T_COMMENT +//%token T_DOC_COMMENT +//%token T_OPEN_TAG +//%token T_OPEN_TAG_WITH_ECHO +//%token T_CLOSE_TAG +//%token T_WHITESPACE +//%token T_START_HEREDOC +//%token T_END_HEREDOC +//%token T_DOLLAR_OPEN_CURLY_BRACES +//%token T_CURLY_OPEN +//%token T_PAAMAYIM_NEKUDOTAYIM +//%token T_NS_SEPARATOR +//%token T_ELLIPSIS +//%token T_COALESCE +//%token T_POW +//%token T_POW_EQUAL +//%token T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG +//%token T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG +//%token T_BAD_CHARACTER +//%token T_ERROR +//%token ',' +//%token ']' +//%token '(' +//%token ')' +//%token ';' +//%token '{' +//%token '}' +//%token '[' +//%token '`' +//%token '"' +//%token '$' + +%precedence /*1*/ T_THROW ; +%precedence /*2*/ PREC_ARROW_FUNCTION ; +%precedence /*3*/ T_INCLUDE T_INCLUDE_ONCE T_REQUIRE T_REQUIRE_ONCE ; +%left /*4*/ T_LOGICAL_OR ; +%left /*5*/ T_LOGICAL_XOR ; +%left /*6*/ T_LOGICAL_AND ; +%precedence /*7*/ T_PRINT ; +%precedence /*8*/ T_YIELD ; +%precedence /*9*/ T_DOUBLE_ARROW ; +%precedence /*10*/ T_YIELD_FROM ; +%precedence /*11*/ '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_COALESCE_EQUAL T_POW_EQUAL ; +%left /*12*/ '?' ':' ; +%right /*13*/ T_COALESCE ; +%left /*14*/ T_BOOLEAN_OR ; +%left /*15*/ T_BOOLEAN_AND ; +%left /*16*/ '|' ; +%left /*17*/ '^' ; +%left /*18*/ T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG ; +%nonassoc /*19*/ T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP ; +%nonassoc /*20*/ '<' '>' T_IS_SMALLER_OR_EQUAL T_IS_GREATER_OR_EQUAL ; +%left /*21*/ '.' ; +%left /*22*/ T_SL T_SR ; +%left /*23*/ '+' '-' ; +%left /*24*/ '*' '/' '%' ; +%precedence /*25*/ '!' ; +%precedence /*26*/ T_INSTANCEOF ; +%precedence /*27*/ '~' '@' T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST ; +%right /*28*/ T_POW ; +%precedence /*29*/ T_CLONE ; +%precedence /*30*/ T_NOELSE ; +%precedence /*31*/ T_ELSEIF ; +%precedence /*32*/ T_ELSE ; + +//%start start + +//%% + +start : + /*END + |*/ top_statement_list + ; + +reserved_non_modifiers : + T_INCLUDE /*3P*/ + | T_INCLUDE_ONCE /*3P*/ + | T_EVAL + | T_REQUIRE /*3P*/ + | T_REQUIRE_ONCE /*3P*/ + | T_LOGICAL_OR /*4L*/ + | T_LOGICAL_XOR /*5L*/ + | T_LOGICAL_AND /*6L*/ + | T_INSTANCEOF /*26P*/ + | T_NEW + | T_CLONE /*29P*/ + | T_EXIT + | T_IF + | T_ELSEIF /*31P*/ + | T_ELSE /*32P*/ + | T_ENDIF + | T_ECHO + | T_DO + | T_WHILE + | T_ENDWHILE + | T_FOR + | T_ENDFOR + | T_FOREACH + | T_ENDFOREACH + | T_DECLARE + | T_ENDDECLARE + | T_AS + | T_TRY + | T_CATCH + | T_FINALLY + | T_THROW /*1P*/ + | T_USE + | T_INSTEADOF + | T_GLOBAL + | T_VAR + | T_UNSET + | T_ISSET + | T_EMPTY + | T_CONTINUE + | T_GOTO + | T_FUNCTION + | T_CONST + | T_RETURN + | T_PRINT /*7P*/ + | T_YIELD /*8P*/ + | T_LIST + | T_SWITCH + | T_ENDSWITCH + | T_CASE + | T_DEFAULT + | T_BREAK + | T_ARRAY + | T_CALLABLE + | T_EXTENDS + | T_IMPLEMENTS + | T_NAMESPACE + | T_TRAIT + | T_INTERFACE + | T_CLASS + | T_CLASS_C + | T_TRAIT_C + | T_FUNC_C + | T_METHOD_C + | T_LINE + | T_FILE + | T_DIR + | T_NS_C + | T_FN + | T_MATCH + | T_ENUM + ; + +semi_reserved : + reserved_non_modifiers + | T_STATIC + | T_ABSTRACT + | T_FINAL + | T_PRIVATE + | T_PROTECTED + | T_PUBLIC + | T_READONLY + ; + +ampersand : + T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ + | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ + ; + +identifier : + T_STRING + | semi_reserved + ; + +top_statement_list : + top_statement_list top_statement + | /*empty*/ + ; + +namespace_declaration_name : + identifier + | T_NAME_QUALIFIED + ; + +namespace_name : + T_STRING + | T_NAME_QUALIFIED + ; + +legacy_namespace_name : + namespace_name + | T_NAME_FULLY_QUALIFIED + ; + +name : + T_STRING + | T_NAME_QUALIFIED + | T_NAME_FULLY_QUALIFIED + | T_NAME_RELATIVE + ; + +attribute_decl : + class_name + | class_name argument_list + ; + +attribute_group : + attribute_decl + | attribute_group ',' attribute_decl + ; + +attribute : + T_ATTRIBUTE attribute_group possible_comma ']' + ; + +attributes : + attribute + | attributes attribute + ; + +attributed_statement : + function_declaration_statement + | class_declaration_statement + | trait_declaration_statement + | interface_declaration_statement + | enum_declaration_statement + ; + +top_statement : + statement + | attributed_statement + | attributes attributed_statement + | T_HALT_COMPILER '(' ')' ';' + | T_NAMESPACE namespace_declaration_name ';' + | T_NAMESPACE namespace_declaration_name '{' top_statement_list '}' + | T_NAMESPACE '{' top_statement_list '}' + | T_USE mixed_group_use_declaration ';' + | T_USE use_type group_use_declaration ';' + | T_USE use_declarations ';' + | T_USE use_type use_declarations ';' + | T_CONST const_list ';' + ; + +use_type : + T_FUNCTION + | T_CONST + ; + +group_use_declaration : + legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations possible_comma '}' + ; + +mixed_group_use_declaration : + legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations possible_comma '}' + ; + +possible_comma : + /*empty*/ + | ',' + ; + +inline_use_declarations : + inline_use_declarations ',' inline_use_declaration + | inline_use_declaration + ; + +unprefixed_use_declarations : + unprefixed_use_declarations ',' unprefixed_use_declaration + | unprefixed_use_declaration + ; + +use_declarations : + use_declarations ',' use_declaration + | use_declaration + ; + +inline_use_declaration : + unprefixed_use_declaration + | use_type unprefixed_use_declaration + ; + +unprefixed_use_declaration : + namespace_name + | namespace_name T_AS T_STRING + ; + +use_declaration : + legacy_namespace_name + | legacy_namespace_name T_AS T_STRING + ; + +const_list : + const_list ',' const_decl + | const_decl + ; + +inner_statement_list : + inner_statement_list inner_statement + | /*empty*/ + ; + +inner_statement : + statement + | attributed_statement + | attributes attributed_statement + | T_HALT_COMPILER '(' ')' ';' + ; + +statement : + '{' inner_statement_list '}' + | if_stmt + | alt_if_stmt + | T_WHILE '(' expr ')' while_statement + | T_DO statement T_WHILE '(' expr ')' ';' + | T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement + | T_SWITCH '(' expr ')' switch_case_list + | T_BREAK optional_expr ';' + | T_CONTINUE optional_expr ';' + | T_RETURN optional_expr ';' + | T_GLOBAL global_var_list ';' + | T_STATIC static_var_list ';' + | T_ECHO echo_expr_list ';' + | T_INLINE_HTML + | expr ';' + | T_UNSET '(' unset_variables possible_comma ')' ';' + | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement + | T_FOREACH '(' expr T_AS foreach_variable T_DOUBLE_ARROW /*9P*/ foreach_variable ')' foreach_statement + | T_DECLARE '(' const_list ')' declare_statement + | ';' + | T_TRY '{' inner_statement_list '}' catch_list finally_statement + | T_GOTO T_STRING ';' + | T_STRING ':' /*12L*/ + ; + +catch_list : + /*empty*/ + | catch_list T_CATCH '(' catch_name_list optional_variable ')' '{' inner_statement_list '}' + ; + +catch_name_list : + class_name + | catch_name_list '|' /*16L*/ class_name + ; + +optional_variable : + /*empty*/ + | T_VARIABLE + ; + +finally_statement : + /*empty*/ + | T_FINALLY '{' inner_statement_list '}' + ; + +unset_variables : + unset_variable + | unset_variables ',' unset_variable + ; + +unset_variable : + variable + ; + +function_name : + T_STRING + | T_READONLY + ; + +function_declaration_statement : + function returns_ref function_name backup_doc_comment '(' parameter_list ')' return_type backup_fn_flags '{' inner_statement_list '}' backup_fn_flags + ; + +is_reference : + /*empty*/ + | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ + ; + +is_variadic : + /*empty*/ + | T_ELLIPSIS + ; + +class_declaration_statement : + class_modifiers T_CLASS T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' + | T_CLASS T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' + ; + +class_modifiers : + class_modifier + | class_modifiers class_modifier + ; + +class_modifier : + T_ABSTRACT + | T_FINAL + | T_READONLY + ; + +trait_declaration_statement : + T_TRAIT T_STRING backup_doc_comment '{' class_statement_list '}' + ; + +interface_declaration_statement : + T_INTERFACE T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}' + ; + +enum_declaration_statement : + T_ENUM T_STRING enum_backing_type implements_list backup_doc_comment '{' class_statement_list '}' + ; + +enum_backing_type : + /*empty*/ + | ':' /*12L*/ type_expr + ; + +enum_case : + T_CASE backup_doc_comment identifier enum_case_expr ';' + ; + +enum_case_expr : + /*empty*/ + | '=' /*11P*/ expr + ; + +extends_from : + /*empty*/ + | T_EXTENDS class_name + ; + +interface_extends_list : + /*empty*/ + | T_EXTENDS class_name_list + ; + +implements_list : + /*empty*/ + | T_IMPLEMENTS class_name_list + ; + +foreach_variable : + variable + | ampersand variable + | T_LIST '(' array_pair_list ')' + | '[' array_pair_list ']' + ; + +for_statement : + statement + | ':' /*12L*/ inner_statement_list T_ENDFOR ';' + ; + +foreach_statement : + statement + | ':' /*12L*/ inner_statement_list T_ENDFOREACH ';' + ; + +declare_statement : + statement + | ':' /*12L*/ inner_statement_list T_ENDDECLARE ';' + ; + +switch_case_list : + '{' case_list '}' + | '{' ';' case_list '}' + | ':' /*12L*/ case_list T_ENDSWITCH ';' + | ':' /*12L*/ ';' case_list T_ENDSWITCH ';' + ; + +case_list : + /*empty*/ + | case_list T_CASE expr case_separator inner_statement_list + | case_list T_DEFAULT case_separator inner_statement_list + ; + +case_separator : + ':' /*12L*/ + | ';' + ; + +match : + T_MATCH '(' expr ')' '{' match_arm_list '}' + ; + +match_arm_list : + /*empty*/ + | non_empty_match_arm_list possible_comma + ; + +non_empty_match_arm_list : + match_arm + | non_empty_match_arm_list ',' match_arm + ; + +match_arm : + match_arm_cond_list possible_comma T_DOUBLE_ARROW /*9P*/ expr + | T_DEFAULT possible_comma T_DOUBLE_ARROW /*9P*/ expr + ; + +match_arm_cond_list : + expr + | match_arm_cond_list ',' expr + ; + +while_statement : + statement + | ':' /*12L*/ inner_statement_list T_ENDWHILE ';' + ; + +if_stmt_without_else : + T_IF '(' expr ')' statement + | if_stmt_without_else T_ELSEIF /*31P*/ '(' expr ')' statement + ; + +if_stmt : + if_stmt_without_else %prec T_NOELSE /*30P*/ + | if_stmt_without_else T_ELSE /*32P*/ statement + ; + +alt_if_stmt_without_else : + T_IF '(' expr ')' ':' /*12L*/ inner_statement_list + | alt_if_stmt_without_else T_ELSEIF /*31P*/ '(' expr ')' ':' /*12L*/ inner_statement_list + ; + +alt_if_stmt : + alt_if_stmt_without_else T_ENDIF ';' + | alt_if_stmt_without_else T_ELSE /*32P*/ ':' /*12L*/ inner_statement_list T_ENDIF ';' + ; + +parameter_list : + non_empty_parameter_list possible_comma + | /*empty*/ + ; + +non_empty_parameter_list : + attributed_parameter + | non_empty_parameter_list ',' attributed_parameter + ; + +attributed_parameter : + attributes parameter + | parameter + ; + +optional_property_modifiers : + /*empty*/ + | optional_property_modifiers property_modifier + ; + +property_modifier : + T_PUBLIC + | T_PROTECTED + | T_PRIVATE + | T_READONLY + ; + +parameter : + optional_property_modifiers optional_type_without_static is_reference is_variadic T_VARIABLE backup_doc_comment + | optional_property_modifiers optional_type_without_static is_reference is_variadic T_VARIABLE backup_doc_comment '=' /*11P*/ expr + ; + +optional_type_without_static : + /*empty*/ + | type_expr_without_static + ; + +type_expr : + type + | '?' /*12L*/ type + | union_type + | intersection_type + ; + +type : + type_without_static + | T_STATIC + ; + +union_type_element : + type + | '(' intersection_type ')' + ; + +union_type : + union_type_element '|' /*16L*/ union_type_element + | union_type '|' /*16L*/ union_type_element + ; + +intersection_type : + type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ type + | intersection_type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ type + ; + +type_expr_without_static : + type_without_static + | '?' /*12L*/ type_without_static + | union_type_without_static + | intersection_type_without_static + ; + +type_without_static : + T_ARRAY + | T_CALLABLE + | name + ; + +union_type_without_static_element : + type_without_static + | '(' intersection_type_without_static ')' + ; + +union_type_without_static : + union_type_without_static_element '|' /*16L*/ union_type_without_static_element + | union_type_without_static '|' /*16L*/ union_type_without_static_element + ; + +intersection_type_without_static : + type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ type_without_static + | intersection_type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ type_without_static + ; + +return_type : + /*empty*/ + | ':' /*12L*/ type_expr + ; + +argument_list : + '(' ')' + | '(' non_empty_argument_list possible_comma ')' + | '(' T_ELLIPSIS ')' + ; + +non_empty_argument_list : + argument + | non_empty_argument_list ',' argument + ; + +argument : + expr + | identifier ':' /*12L*/ expr + | T_ELLIPSIS expr + ; + +global_var_list : + global_var_list ',' global_var + | global_var + ; + +global_var : + simple_variable + ; + +static_var_list : + static_var_list ',' static_var + | static_var + ; + +static_var : + T_VARIABLE + | T_VARIABLE '=' /*11P*/ expr + ; + +class_statement_list : + class_statement_list class_statement + | /*empty*/ + ; + +attributed_class_statement : + variable_modifiers optional_type_without_static property_list ';' + | method_modifiers T_CONST class_const_list ';' + | method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')' return_type backup_fn_flags method_body backup_fn_flags + | enum_case + ; + +class_statement : + attributed_class_statement + | attributes attributed_class_statement + | T_USE class_name_list trait_adaptations + ; + +class_name_list : + class_name + | class_name_list ',' class_name + ; + +trait_adaptations : + ';' + | '{' '}' + | '{' trait_adaptation_list '}' + ; + +trait_adaptation_list : + trait_adaptation + | trait_adaptation_list trait_adaptation + ; + +trait_adaptation : + trait_precedence ';' + | trait_alias ';' + ; + +trait_precedence : + absolute_trait_method_reference T_INSTEADOF class_name_list + ; + +trait_alias : + trait_method_reference T_AS T_STRING + | trait_method_reference T_AS reserved_non_modifiers + | trait_method_reference T_AS member_modifier identifier + | trait_method_reference T_AS member_modifier + ; + +trait_method_reference : + identifier + | absolute_trait_method_reference + ; + +absolute_trait_method_reference : + class_name T_PAAMAYIM_NEKUDOTAYIM identifier + ; + +method_body : + ';' + | '{' inner_statement_list '}' + ; + +variable_modifiers : + non_empty_member_modifiers + | T_VAR + ; + +method_modifiers : + /*empty*/ + | non_empty_member_modifiers + ; + +non_empty_member_modifiers : + member_modifier + | non_empty_member_modifiers member_modifier + ; + +member_modifier : + T_PUBLIC + | T_PROTECTED + | T_PRIVATE + | T_STATIC + | T_ABSTRACT + | T_FINAL + | T_READONLY + ; + +property_list : + property_list ',' property + | property + ; + +property : + T_VARIABLE backup_doc_comment + | T_VARIABLE '=' /*11P*/ expr backup_doc_comment + ; + +class_const_list : + class_const_list ',' class_const_decl + | class_const_decl + ; + +class_const_decl : + identifier '=' /*11P*/ expr backup_doc_comment + ; + +const_decl : + T_STRING '=' /*11P*/ expr backup_doc_comment + ; + +echo_expr_list : + echo_expr_list ',' echo_expr + | echo_expr + ; + +echo_expr : + expr + ; + +for_exprs : + /*empty*/ + | non_empty_for_exprs + ; + +non_empty_for_exprs : + non_empty_for_exprs ',' expr + | expr + ; + +anonymous_class : + T_CLASS ctor_arguments extends_from implements_list backup_doc_comment '{' class_statement_list '}' + ; + +new_expr : + T_NEW class_name_reference ctor_arguments + | T_NEW anonymous_class + | T_NEW attributes anonymous_class + ; + +expr : + variable + | T_LIST '(' array_pair_list ')' '=' /*11P*/ expr + | '[' array_pair_list ']' '=' /*11P*/ expr + | variable '=' /*11P*/ expr + | variable '=' /*11P*/ ampersand variable + | T_CLONE /*29P*/ expr + | variable T_PLUS_EQUAL /*11P*/ expr + | variable T_MINUS_EQUAL /*11P*/ expr + | variable T_MUL_EQUAL /*11P*/ expr + | variable T_POW_EQUAL /*11P*/ expr + | variable T_DIV_EQUAL /*11P*/ expr + | variable T_CONCAT_EQUAL /*11P*/ expr + | variable T_MOD_EQUAL /*11P*/ expr + | variable T_AND_EQUAL /*11P*/ expr + | variable T_OR_EQUAL /*11P*/ expr + | variable T_XOR_EQUAL /*11P*/ expr + | variable T_SL_EQUAL /*11P*/ expr + | variable T_SR_EQUAL /*11P*/ expr + | variable T_COALESCE_EQUAL /*11P*/ expr + | variable T_INC + | T_INC variable + | variable T_DEC + | T_DEC variable + | expr T_BOOLEAN_OR /*14L*/ expr + | expr T_BOOLEAN_AND /*15L*/ expr + | expr T_LOGICAL_OR /*4L*/ expr + | expr T_LOGICAL_AND /*6L*/ expr + | expr T_LOGICAL_XOR /*5L*/ expr + | expr '|' /*16L*/ expr + | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ expr + | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG /*18L*/ expr + | expr '^' /*17L*/ expr + | expr '.' /*21L*/ expr + | expr '+' /*23L*/ expr + | expr '-' /*23L*/ expr + | expr '*' /*24L*/ expr + | expr T_POW /*28R*/ expr + | expr '/' /*24L*/ expr + | expr '%' /*24L*/ expr + | expr T_SL /*22L*/ expr + | expr T_SR /*22L*/ expr + | '+' /*23L*/ expr %prec '~' /*27P*/ + | '-' /*23L*/ expr %prec '~' /*27P*/ + | '!' /*25P*/ expr + | '~' /*27P*/ expr + | expr T_IS_IDENTICAL /*19N*/ expr + | expr T_IS_NOT_IDENTICAL /*19N*/ expr + | expr T_IS_EQUAL /*19N*/ expr + | expr T_IS_NOT_EQUAL /*19N*/ expr + | expr '<' /*20N*/ expr + | expr T_IS_SMALLER_OR_EQUAL /*20N*/ expr + | expr '>' /*20N*/ expr + | expr T_IS_GREATER_OR_EQUAL /*20N*/ expr + | expr T_SPACESHIP /*19N*/ expr + | expr T_INSTANCEOF /*26P*/ class_name_reference + | '(' expr ')' + | new_expr + | expr '?' /*12L*/ expr ':' /*12L*/ expr + | expr '?' /*12L*/ ':' /*12L*/ expr + | expr T_COALESCE /*13R*/ expr + | internal_functions_in_yacc + | T_INT_CAST /*27P*/ expr + | T_DOUBLE_CAST /*27P*/ expr + | T_STRING_CAST /*27P*/ expr + | T_ARRAY_CAST /*27P*/ expr + | T_OBJECT_CAST /*27P*/ expr + | T_BOOL_CAST /*27P*/ expr + | T_UNSET_CAST /*27P*/ expr + | T_EXIT exit_expr + | '@' /*27P*/ expr + | scalar + | '`' backticks_expr '`' + | T_PRINT /*7P*/ expr + | T_YIELD /*8P*/ + | T_YIELD /*8P*/ expr + | T_YIELD /*8P*/ expr T_DOUBLE_ARROW /*9P*/ expr + | T_YIELD_FROM /*10P*/ expr + | T_THROW /*1P*/ expr + | inline_function + | attributes inline_function + | T_STATIC inline_function + | attributes T_STATIC inline_function + | match + ; + +inline_function : + function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type backup_fn_flags '{' inner_statement_list '}' backup_fn_flags + | fn returns_ref backup_doc_comment '(' parameter_list ')' return_type T_DOUBLE_ARROW /*9P*/ backup_fn_flags backup_lex_pos expr backup_fn_flags + ; + +fn : + T_FN + ; + +function : + T_FUNCTION + ; + +backup_doc_comment : + /*empty*/ + ; + +backup_fn_flags : + %prec PREC_ARROW_FUNCTION /*2P*/ /*empty*/ + ; + +backup_lex_pos : + /*empty*/ + ; + +returns_ref : + /*empty*/ + | ampersand + ; + +lexical_vars : + /*empty*/ + | T_USE '(' lexical_var_list possible_comma ')' + ; + +lexical_var_list : + lexical_var_list ',' lexical_var + | lexical_var + ; + +lexical_var : + T_VARIABLE + | ampersand T_VARIABLE + ; + +function_call : + name argument_list + | T_READONLY argument_list + | class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list + | callable_expr argument_list + ; + +class_name : + T_STATIC + | name + ; + +class_name_reference : + class_name + | new_variable + | '(' expr ')' + ; + +exit_expr : + /*empty*/ + | '(' optional_expr ')' + ; + +backticks_expr : + /*empty*/ + | T_ENCAPSED_AND_WHITESPACE + | encaps_list + ; + +ctor_arguments : + /*empty*/ + | argument_list + ; + +dereferenceable_scalar : + T_ARRAY '(' array_pair_list ')' + | '[' array_pair_list ']' + | T_CONSTANT_ENCAPSED_STRING + | '"' encaps_list '"' + ; + +scalar : + T_LNUMBER + | T_DNUMBER + | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC + | T_START_HEREDOC T_END_HEREDOC + | T_START_HEREDOC encaps_list T_END_HEREDOC + | dereferenceable_scalar + | constant + | class_constant + ; + +constant : + name + | T_LINE + | T_FILE + | T_DIR + | T_TRAIT_C + | T_METHOD_C + | T_FUNC_C + | T_NS_C + | T_CLASS_C + ; + +class_constant : + class_name T_PAAMAYIM_NEKUDOTAYIM identifier + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM identifier + ; + +optional_expr : + /*empty*/ + | expr + ; + +variable_class_name : + fully_dereferenceable + ; + +fully_dereferenceable : + variable + | '(' expr ')' + | dereferenceable_scalar + | class_constant + ; + +array_object_dereferenceable : + fully_dereferenceable + | constant + ; + +callable_expr : + callable_variable + | '(' expr ')' + | dereferenceable_scalar + ; + +callable_variable : + simple_variable + | array_object_dereferenceable '[' optional_expr ']' + | array_object_dereferenceable '{' expr '}' + | array_object_dereferenceable T_OBJECT_OPERATOR property_name argument_list + | array_object_dereferenceable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list + | function_call + ; + +variable : + callable_variable + | static_member + | array_object_dereferenceable T_OBJECT_OPERATOR property_name + | array_object_dereferenceable T_NULLSAFE_OBJECT_OPERATOR property_name + ; + +simple_variable : + T_VARIABLE + | '$' '{' expr '}' + | '$' simple_variable + ; + +static_member : + class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable + ; + +new_variable : + simple_variable + | new_variable '[' optional_expr ']' + | new_variable '{' expr '}' + | new_variable T_OBJECT_OPERATOR property_name + | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name + | class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable + | new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable + ; + +member_name : + identifier + | '{' expr '}' + | simple_variable + ; + +property_name : + T_STRING + | '{' expr '}' + | simple_variable + ; + +array_pair_list : + non_empty_array_pair_list + ; + +possible_array_pair : + /*empty*/ + | array_pair + ; + +non_empty_array_pair_list : + non_empty_array_pair_list ',' possible_array_pair + | possible_array_pair + ; + +array_pair : + expr T_DOUBLE_ARROW /*9P*/ expr + | expr + | expr T_DOUBLE_ARROW /*9P*/ ampersand variable + | ampersand variable + | T_ELLIPSIS expr + | expr T_DOUBLE_ARROW /*9P*/ T_LIST '(' array_pair_list ')' + | T_LIST '(' array_pair_list ')' + ; + +encaps_list : + encaps_list encaps_var + | encaps_list T_ENCAPSED_AND_WHITESPACE + | encaps_var + | T_ENCAPSED_AND_WHITESPACE encaps_var + ; + +encaps_var : + T_VARIABLE + | T_VARIABLE '[' encaps_var_offset ']' + | T_VARIABLE T_OBJECT_OPERATOR T_STRING + | T_VARIABLE T_NULLSAFE_OBJECT_OPERATOR T_STRING + | T_DOLLAR_OPEN_CURLY_BRACES expr '}' + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' + | T_CURLY_OPEN variable '}' + ; + +encaps_var_offset : + T_STRING + | T_NUM_STRING + | '-' /*23L*/ T_NUM_STRING + | T_VARIABLE + ; + +internal_functions_in_yacc : + T_ISSET '(' isset_variables possible_comma ')' + | T_EMPTY '(' expr ')' + | T_INCLUDE /*3P*/ expr + | T_INCLUDE_ONCE /*3P*/ expr + | T_EVAL '(' expr ')' + | T_REQUIRE /*3P*/ expr + | T_REQUIRE_ONCE /*3P*/ expr + ; + +isset_variables : + isset_variable + | isset_variables ',' isset_variable + ; + +isset_variable : + expr + ; + +//Lexer + +T_THROW : 'throw' ; +T_INCLUDE : 'include' ; +T_INCLUDE_ONCE : 'include_once' ; +T_REQUIRE : 'require' ; +T_REQUIRE_ONCE : 'require_once' ; +T_LOGICAL_OR : '||' ; +T_LOGICAL_XOR : 'LOGICAL_XOR' ; +T_LOGICAL_AND : '&&' ; +T_PRINT : 'print' ; +T_YIELD : 'yield' ; +T_DOUBLE_ARROW : '=>' ; +T_YIELD_FROM : 'YIELD_FROM' ; +T_PLUS_EQUAL : '+=' ; +T_MINUS_EQUAL : '-=' ; +T_MUL_EQUAL : '*=' ; +T_DIV_EQUAL : '/=' ; +T_CONCAT_EQUAL : 'CONCAT_EQUAL' ; +T_MOD_EQUAL : '%=' ; +T_AND_EQUAL : '&=' ; +T_OR_EQUAL : '|=' ; +T_XOR_EQUAL : 'XOR_EQUAL' ; +T_SL_EQUAL : '<<=' ; +T_SR_EQUAL : '>>=' ; +T_COALESCE_EQUAL : 'COALESCE_EQUAL' ; +T_POW_EQUAL : 'POW_EQUAL' ; +T_COALESCE : 'COALESCE' ; +T_BOOLEAN_OR : 'BOOLEAN_OR' ; +T_BOOLEAN_AND : 'BOOLEAN_AND' ; +T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG : 'AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG' ; +T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG : 'AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG' ; +T_IS_EQUAL : '==' ; +T_IS_NOT_EQUAL : '!=' ; +T_IS_IDENTICAL : '===' ; +T_IS_NOT_IDENTICAL : '!==' ; +T_SPACESHIP : '<=>' ; +T_IS_SMALLER_OR_EQUAL : '<=' ; +T_IS_GREATER_OR_EQUAL : '>=' ; +T_SL : '<<' ; +T_SR : '>>' ; +T_INSTANCEOF : 'instanceof' ; +T_INT_CAST : 'INT_CAST' ; +T_DOUBLE_CAST : 'DOUBLE_CAST' ; +T_STRING_CAST : 'STRING_CAST' ; +T_ARRAY_CAST : 'ARRAY_CAST' ; +T_OBJECT_CAST : 'OBJECT_CAST' ; +T_BOOL_CAST : 'BOOL_CAST' ; +T_UNSET_CAST : 'UNSET_CAST' ; +T_POW : 'POW' ; +T_CLONE : 'clone' ; +T_ELSEIF : 'elseif' ; +T_ELSE : 'else' ; +T_EVAL : 'eval' ; +T_NEW : 'new' ; +T_EXIT : 'exit' ; +T_IF : 'if' ; +T_ENDIF : 'endif' ; +T_ECHO : 'echo' ; +T_DO : 'do' ; +T_WHILE : 'while' ; +T_ENDWHILE : 'endwhile' ; +T_FOR : 'for' ; +T_ENDFOR : 'endfor' ; +T_FOREACH : 'foreach' ; +T_ENDFOREACH : 'endforeach' ; +T_DECLARE : 'declare' ; +T_ENDDECLARE : 'enddeclare' ; +T_AS : 'as' ; +T_TRY : 'try' ; +T_CATCH : 'catch' ; +T_FINALLY : 'finally' ; +T_USE : 'use' ; +T_INSTEADOF : 'insteadof' ; +T_GLOBAL : 'global' ; +T_VAR : 'var' ; +T_UNSET : 'unset' ; +T_ISSET : 'isset' ; +T_EMPTY : 'empty' ; +T_CONTINUE : 'continue' ; +T_GOTO : 'goto' ; +T_FUNCTION : 'function' ; +T_CONST : 'const' ; +T_RETURN : 'return' ; +T_LIST : 'list' ; +T_SWITCH : 'switch' ; +T_ENDSWITCH : 'endswitch' ; +T_CASE : 'case' ; +T_DEFAULT : 'default' ; +T_BREAK : 'break' ; +T_ARRAY : 'array' ; +T_CALLABLE : 'callable' ; +T_EXTENDS : 'extends' ; +T_IMPLEMENTS : 'implements' ; +T_NAMESPACE : 'namespace' ; +T_TRAIT : 'trait' ; +T_INTERFACE : 'interface' ; +T_CLASS : 'class' ; +T_CLASS_C : 'CLASS_C' ; +T_TRAIT_C : 'TRAIT_C' ; +T_FUNC_C : 'FUNC_C' ; +T_METHOD_C : 'METHOD_C' ; +T_LINE : 'LINE' ; +T_FILE : 'FILE' ; +T_DIR : 'DIR' ; +T_NS_C : 'NS_C' ; +T_FN : 'fn' ; +T_MATCH : 'match' ; +T_ENUM : 'enum' ; +T_STATIC : 'static' ; +T_ABSTRACT : 'abstract' ; +T_FINAL : 'final' ; +T_PRIVATE : 'private' ; +T_PROTECTED : 'protected' ; +T_PUBLIC : 'public' ; +T_READONLY : 'readonly' ; +T_STRING : "[a-zA-Z_][a-zA-Z_0-9]*" ; +T_NAME_QUALIFIED : 'NAME_QUALIFIED' ; +T_NAME_FULLY_QUALIFIED : 'NAME_FULLY_QUALIFIED' ; +T_NAME_RELATIVE : 'NAME_RELATIVE' ; +T_ATTRIBUTE : 'attribute' ; +T_HALT_COMPILER : 'HALT_COMPILER' ; +T_NS_SEPARATOR : 'NS_SEPARATOR' ; +T_INLINE_HTML : 'INLINE_HTML' ; +T_VARIABLE : 'VARIABLE' ; +T_ELLIPSIS : '...' ; +T_PAAMAYIM_NEKUDOTAYIM : 'PAAMAYIM_NEKUDOTAYIM' ; +T_INC : '++' ; +T_DEC : '--' ; +T_ENCAPSED_AND_WHITESPACE : 'ENCAPSED_AND_WHITESPACE' ; +T_CONSTANT_ENCAPSED_STRING : 'CONSTANT_ENCAPSED_STRING' ; +T_LNUMBER : 'LNUMBER' ; +T_DNUMBER : 'DNUMBER' ; +T_START_HEREDOC : 'START_HEREDOC' ; +T_END_HEREDOC : 'END_HEREDOC' ; +T_OBJECT_OPERATOR : 'OBJECT_OPERATOR' ; +T_NULLSAFE_OBJECT_OPERATOR : 'NULLSAFE_OBJECT_OPERATOR' ; +T_DOLLAR_OPEN_CURLY_BRACES : '${' ; +T_STRING_VARNAME : 'STRING_VARNAME' ; +T_CURLY_OPEN : '{' ; +T_NUM_STRING : 'NUM_STRING' ; + +} \ No newline at end of file diff --git a/playground/postgresql-16-nc.g b/playground/postgresql-16-nc.g new file mode 100644 index 0000000..f8cbc71 --- /dev/null +++ b/playground/postgresql-16-nc.g @@ -0,0 +1,6487 @@ +/* +/usr/bin/time /home/mingo/dev/c/A_grammars/lalr/lalr-nb/dist/Release/GNU-Linux/lalr-nb postgresql.g -p + +/usr/bin/time /home/mingo/dev/c/A_grammars/lalr/lalr-nb/dist/Release/GNU-Linux/lalr-nb postgresql.g > /dev/null + +32 bits +64.89user 0.54system 1:08.52elapsed 95%CPU (0avgtext+0avgdata 1076272maxresident)k +0inputs+0outputs (0major+268598minor)pagefaults 0swaps + +64 bits +66.48user 0.75system 1:07.25elapsed 99%CPU (0avgtext+0avgdata 1621820maxresident)k +0inputs+0outputs (0major+404808minor)pagefaults 0swaps +*/ + +postgresql { + +%whitespace "[ \t\r\n]*"; +%whitespace "\-\-[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +%case_insensitive ; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token IDENT +//%token UIDENT +//%token FCONST +//%token SCONST +//%token USCONST +//%token BCONST +//%token XCONST +//%token Op +//%token ICONST +//%token PARAM +//%token TYPECAST +//%token DOT_DOT +//%token COLON_EQUALS +//%token EQUALS_GREATER +//%token LESS_EQUALS +//%token GREATER_EQUALS +//%token NOT_EQUALS +//%token ABORT_P +//%token ABSENT +//%token ABSOLUTE_P +//%token ACCESS +//%token ACTION +//%token ADD_P +//%token ADMIN +//%token AFTER +//%token AGGREGATE +//%token ALL +//%token ALSO +//%token ALTER +//%token ALWAYS +//%token ANALYSE +//%token ANALYZE +//%token AND +//%token ANY +//%token ARRAY +//%token AS +//%token ASC +//%token ASENSITIVE +//%token ASSERTION +//%token ASSIGNMENT +//%token ASYMMETRIC +//%token ATOMIC +//%token AT +//%token ATTACH +//%token ATTRIBUTE +//%token AUTHORIZATION +//%token BACKWARD +//%token BEFORE +//%token BEGIN_P +//%token BETWEEN +//%token BIGINT +//%token BINARY +//%token BIT +//%token BOOLEAN_P +//%token BOTH +//%token BREADTH +//%token BY +//%token CACHE +//%token CALL +//%token CALLED +//%token CASCADE +//%token CASCADED +//%token CASE +//%token CAST +//%token CATALOG_P +//%token CHAIN +//%token CHAR_P +//%token CHARACTER +//%token CHARACTERISTICS +//%token CHECK +//%token CHECKPOINT +//%token CLASS +//%token CLOSE +//%token CLUSTER +//%token COALESCE +//%token COLLATE +//%token COLLATION +//%token COLUMN +//%token COLUMNS +//%token COMMENT +//%token COMMENTS +//%token COMMIT +//%token COMMITTED +//%token COMPRESSION +//%token CONCURRENTLY +//%token CONFIGURATION +//%token CONFLICT +//%token CONNECTION +//%token CONSTRAINT +//%token CONSTRAINTS +//%token CONTENT_P +//%token CONTINUE_P +//%token CONVERSION_P +//%token COPY +//%token COST +//%token CREATE +//%token CROSS +//%token CSV +//%token CUBE +//%token CURRENT_P +//%token CURRENT_CATALOG +//%token CURRENT_DATE +//%token CURRENT_ROLE +//%token CURRENT_SCHEMA +//%token CURRENT_TIME +//%token CURRENT_TIMESTAMP +//%token CURRENT_USER +//%token CURSOR +//%token CYCLE +//%token DATA_P +//%token DATABASE +//%token DAY_P +//%token DEALLOCATE +//%token DEC +//%token DECIMAL_P +//%token DECLARE +//%token DEFAULT +//%token DEFAULTS +//%token DEFERRABLE +//%token DEFERRED +//%token DEFINER +//%token DELETE_P +//%token DELIMITER +//%token DELIMITERS +//%token DEPENDS +//%token DEPTH +//%token DESC +//%token DETACH +//%token DICTIONARY +//%token DISABLE_P +//%token DISCARD +//%token DISTINCT +//%token DO +//%token DOCUMENT_P +//%token DOMAIN_P +//%token DOUBLE_P +//%token DROP +//%token EACH +//%token ELSE +//%token ENABLE_P +//%token ENCODING +//%token ENCRYPTED +//%token END_P +//%token ENUM_P +//%token ESCAPE +//%token EVENT +//%token EXCEPT +//%token EXCLUDE +//%token EXCLUDING +//%token EXCLUSIVE +//%token EXECUTE +//%token EXISTS +//%token EXPLAIN +//%token EXPRESSION +//%token EXTENSION +//%token EXTERNAL +//%token EXTRACT +//%token FALSE_P +//%token FAMILY +//%token FETCH +//%token FILTER +//%token FINALIZE +//%token FIRST_P +//%token FLOAT_P +//%token FOLLOWING +//%token FOR +//%token FORCE +//%token FOREIGN +//%token FORMAT +//%token FORWARD +//%token FREEZE +//%token FROM +//%token FULL +//%token FUNCTION +//%token FUNCTIONS +//%token GENERATED +//%token GLOBAL +//%token GRANT +//%token GRANTED +//%token GREATEST +//%token GROUP_P +//%token GROUPING +//%token GROUPS +//%token HANDLER +//%token HAVING +//%token HEADER_P +//%token HOLD +//%token HOUR_P +//%token IDENTITY_P +//%token IF_P +//%token ILIKE +//%token IMMEDIATE +//%token IMMUTABLE +//%token IMPLICIT_P +//%token IMPORT_P +//%token IN_P +//%token INCLUDE +//%token INCLUDING +//%token INCREMENT +//%token INDENT +//%token INDEX +//%token INDEXES +//%token INHERIT +//%token INHERITS +//%token INITIALLY +//%token INLINE_P +//%token INNER_P +//%token INOUT +//%token INPUT_P +//%token INSENSITIVE +//%token INSERT +//%token INSTEAD +//%token INT_P +//%token INTEGER +//%token INTERSECT +//%token INTERVAL +//%token INTO +//%token INVOKER +//%token IS +//%token ISNULL +//%token ISOLATION +//%token JOIN +//%token JSON +//%token JSON_ARRAY +//%token JSON_ARRAYAGG +//%token JSON_OBJECT +//%token JSON_OBJECTAGG +//%token KEY +//%token KEYS +//%token LABEL +//%token LANGUAGE +//%token LARGE_P +//%token LAST_P +//%token LATERAL_P +//%token LEADING +//%token LEAKPROOF +//%token LEAST +//%token LEFT +//%token LEVEL +//%token LIKE +//%token LIMIT +//%token LISTEN +//%token LOAD +//%token LOCAL +//%token LOCALTIME +//%token LOCALTIMESTAMP +//%token LOCATION +//%token LOCK_P +//%token LOCKED +//%token LOGGED +//%token MAPPING +//%token MATCH +//%token MATCHED +//%token MATERIALIZED +//%token MAXVALUE +//%token MERGE +//%token METHOD +//%token MINUTE_P +//%token MINVALUE +//%token MODE +//%token MONTH_P +//%token MOVE +//%token NAME_P +//%token NAMES +//%token NATIONAL +//%token NATURAL +//%token NCHAR +//%token NEW +//%token NEXT +//%token NFC +//%token NFD +//%token NFKC +//%token NFKD +//%token NO +//%token NONE +//%token NORMALIZE +//%token NORMALIZED +//%token NOT +//%token NOTHING +//%token NOTIFY +//%token NOTNULL +//%token NOWAIT +//%token NULL_P +//%token NULLIF +//%token NULLS_P +//%token NUMERIC +//%token OBJECT_P +//%token OF +//%token OFF +//%token OFFSET +//%token OIDS +//%token OLD +//%token ON +//%token ONLY +//%token OPERATOR +//%token OPTION +//%token OPTIONS +//%token OR +//%token ORDER +//%token ORDINALITY +//%token OTHERS +//%token OUT_P +//%token OUTER_P +//%token OVER +//%token OVERLAPS +//%token OVERLAY +//%token OVERRIDING +//%token OWNED +//%token OWNER +//%token PARALLEL +//%token PARAMETER +//%token PARSER +//%token PARTIAL +//%token PARTITION +//%token PASSING +//%token PASSWORD +//%token PLACING +//%token PLANS +//%token POLICY +//%token POSITION +//%token PRECEDING +//%token PRECISION +//%token PRESERVE +//%token PREPARE +//%token PREPARED +//%token PRIMARY +//%token PRIOR +//%token PRIVILEGES +//%token PROCEDURAL +//%token PROCEDURE +//%token PROCEDURES +//%token PROGRAM +//%token PUBLICATION +//%token QUOTE +//%token RANGE +//%token READ +//%token REAL +//%token REASSIGN +//%token RECHECK +//%token RECURSIVE +//%token REF_P +//%token REFERENCES +//%token REFERENCING +//%token REFRESH +//%token REINDEX +//%token RELATIVE_P +//%token RELEASE +//%token RENAME +//%token REPEATABLE +//%token REPLACE +//%token REPLICA +//%token RESET +//%token RESTART +//%token RESTRICT +//%token RETURN +//%token RETURNING +//%token RETURNS +//%token REVOKE +//%token RIGHT +//%token ROLE +//%token ROLLBACK +//%token ROLLUP +//%token ROUTINE +//%token ROUTINES +//%token ROW +//%token ROWS +//%token RULE +//%token SAVEPOINT +//%token SCALAR +//%token SCHEMA +//%token SCHEMAS +//%token SCROLL +//%token SEARCH +//%token SECOND_P +//%token SECURITY +//%token SELECT +//%token SEQUENCE +//%token SEQUENCES +//%token SERIALIZABLE +//%token SERVER +//%token SESSION +//%token SESSION_USER +//%token SET +//%token SETS +//%token SETOF +//%token SHARE +//%token SHOW +//%token SIMILAR +//%token SIMPLE +//%token SKIP +//%token SMALLINT +//%token SNAPSHOT +//%token SOME +//%token SQL_P +//%token STABLE +//%token STANDALONE_P +//%token START +//%token STATEMENT +//%token STATISTICS +//%token STDIN +//%token STDOUT +//%token STORAGE +//%token STORED +//%token STRICT_P +//%token STRIP_P +//%token SUBSCRIPTION +//%token SUBSTRING +//%token SUPPORT +//%token SYMMETRIC +//%token SYSID +//%token SYSTEM_P +//%token SYSTEM_USER +//%token TABLE +//%token TABLES +//%token TABLESAMPLE +//%token TABLESPACE +//%token TEMP +//%token TEMPLATE +//%token TEMPORARY +//%token TEXT_P +//%token THEN +//%token TIES +//%token TIME +//%token TIMESTAMP +//%token TO +//%token TRAILING +//%token TRANSACTION +//%token TRANSFORM +//%token TREAT +//%token TRIGGER +//%token TRIM +//%token TRUE_P +//%token TRUNCATE +//%token TRUSTED +//%token TYPE_P +//%token TYPES_P +//%token UESCAPE +//%token UNBOUNDED +//%token UNCOMMITTED +//%token UNENCRYPTED +//%token UNION +//%token UNIQUE +//%token UNKNOWN +//%token UNLISTEN +//%token UNLOGGED +//%token UNTIL +//%token UPDATE +//%token USER +//%token USING +//%token VACUUM +//%token VALID +//%token VALIDATE +//%token VALIDATOR +//%token VALUE_P +//%token VALUES +//%token VARCHAR +//%token VARIADIC +//%token VARYING +//%token VERBOSE +//%token VERSION_P +//%token VIEW +//%token VIEWS +//%token VOLATILE +//%token WHEN +//%token WHERE +//%token WHITESPACE_P +//%token WINDOW +//%token WITH +//%token WITHIN +//%token WITHOUT +//%token WORK +//%token WRAPPER +//%token WRITE +//%token XML_P +//%token XMLATTRIBUTES +//%token XMLCONCAT +//%token XMLELEMENT +//%token XMLEXISTS +//%token XMLFOREST +//%token XMLNAMESPACES +//%token XMLPARSE +//%token XMLPI +//%token XMLROOT +//%token XMLSERIALIZE +//%token XMLTABLE +//%token YEAR_P +//%token YES_P +//%token ZONE +//%token FORMAT_LA +//%token NOT_LA +//%token NULLS_LA +//%token WITH_LA +//%token WITHOUT_LA +//%token MODE_TYPE_NAME +//%token MODE_PLPGSQL_EXPR +//%token MODE_PLPGSQL_ASSIGN1 +//%token MODE_PLPGSQL_ASSIGN2 +//%token MODE_PLPGSQL_ASSIGN3 +//%token '<' +//%token '>' +//%token '=' +//%token '+' +//%token '-' +//%token '*' +//%token '/' +//%token '%' +//%token '^' +//%token UMINUS +//%token '[' +//%token ']' +//%token '(' +//%token ')' +//%token '.' +//%token ';' +//%token ',' +//%token ':' + +%nonassoc /*1*/ SET ; +%left /*2*/ EXCEPT UNION ; +%left /*3*/ INTERSECT ; +%left /*4*/ OR ; +%left /*5*/ AND ; +%right /*6*/ NOT ; +%nonassoc /*7*/ IS ISNULL NOTNULL ; +%nonassoc /*8*/ LESS_EQUALS GREATER_EQUALS NOT_EQUALS '<' '>' '=' ; +%nonassoc /*9*/ BETWEEN ILIKE IN_P LIKE SIMILAR NOT_LA ; +%nonassoc /*10*/ ESCAPE ; +%nonassoc /*11*/ JSON UNIQUE ; +%nonassoc /*12*/ KEYS OBJECT_P SCALAR VALUE_P ; +%nonassoc /*13*/ WITH WITHOUT ; +%nonassoc /*14*/ UNBOUNDED ; +%nonassoc /*15*/ IDENT CUBE FOLLOWING GROUPS PARTITION PRECEDING RANGE ROLLUP ROWS ; +%left /*16*/ Op OPERATOR ; +%left /*17*/ '+' '-' ; +%left /*18*/ '*' '/' '%' ; +%left /*19*/ '^' ; +%left /*20*/ AT ; +%left /*21*/ COLLATE ; +%right /*22*/ UMINUS ; +%left /*23*/ '[' ']' ; +%left /*24*/ '(' ')' ; +%left /*25*/ TYPECAST ; +%left /*26*/ '.' ; +%left /*27*/ CROSS FULL INNER_P JOIN LEFT NATURAL RIGHT ; + +//%start parse_toplevel + +//%% + +parse_toplevel : + /*YYEOF + |*/ stmtmulti + | MODE_TYPE_NAME Typename + | MODE_PLPGSQL_EXPR PLpgSQL_Expr + | MODE_PLPGSQL_ASSIGN1 PLAssignStmt + | MODE_PLPGSQL_ASSIGN2 PLAssignStmt + | MODE_PLPGSQL_ASSIGN3 PLAssignStmt + ; + +stmtmulti : + stmtmulti ';' toplevel_stmt + | toplevel_stmt + ; + +toplevel_stmt : + stmt + | TransactionStmtLegacy + ; + +stmt : + AlterEventTrigStmt + | AlterCollationStmt + | AlterDatabaseStmt + | AlterDatabaseSetStmt + | AlterDefaultPrivilegesStmt + | AlterDomainStmt + | AlterEnumStmt + | AlterExtensionStmt + | AlterExtensionContentsStmt + | AlterFdwStmt + | AlterForeignServerStmt + | AlterFunctionStmt + | AlterGroupStmt + | AlterObjectDependsStmt + | AlterObjectSchemaStmt + | AlterOwnerStmt + | AlterOperatorStmt + | AlterTypeStmt + | AlterPolicyStmt + | AlterSeqStmt + | AlterSystemStmt + | AlterTableStmt + | AlterTblSpcStmt + | AlterCompositeTypeStmt + | AlterPublicationStmt + | AlterRoleSetStmt + | AlterRoleStmt + | AlterSubscriptionStmt + | AlterStatsStmt + | AlterTSConfigurationStmt + | AlterTSDictionaryStmt + | AlterUserMappingStmt + | AnalyzeStmt + | CallStmt + | CheckPointStmt + | ClosePortalStmt + | ClusterStmt + | CommentStmt + | ConstraintsSetStmt + | CopyStmt + | CreateAmStmt + | CreateAsStmt + | CreateAssertionStmt + | CreateCastStmt + | CreateConversionStmt + | CreateDomainStmt + | CreateExtensionStmt + | CreateFdwStmt + | CreateForeignServerStmt + | CreateForeignTableStmt + | CreateFunctionStmt + | CreateGroupStmt + | CreateMatViewStmt + | CreateOpClassStmt + | CreateOpFamilyStmt + | CreatePublicationStmt + | AlterOpFamilyStmt + | CreatePolicyStmt + | CreatePLangStmt + | CreateSchemaStmt + | CreateSeqStmt + | CreateStmt + | CreateSubscriptionStmt + | CreateStatsStmt + | CreateTableSpaceStmt + | CreateTransformStmt + | CreateTrigStmt + | CreateEventTrigStmt + | CreateRoleStmt + | CreateUserStmt + | CreateUserMappingStmt + | CreatedbStmt + | DeallocateStmt + | DeclareCursorStmt + | DefineStmt + | DeleteStmt + | DiscardStmt + | DoStmt + | DropCastStmt + | DropOpClassStmt + | DropOpFamilyStmt + | DropOwnedStmt + | DropStmt + | DropSubscriptionStmt + | DropTableSpaceStmt + | DropTransformStmt + | DropRoleStmt + | DropUserMappingStmt + | DropdbStmt + | ExecuteStmt + | ExplainStmt + | FetchStmt + | GrantStmt + | GrantRoleStmt + | ImportForeignSchemaStmt + | IndexStmt + | InsertStmt + | ListenStmt + | RefreshMatViewStmt + | LoadStmt + | LockStmt + | MergeStmt + | NotifyStmt + | PrepareStmt + | ReassignOwnedStmt + | ReindexStmt + | RemoveAggrStmt + | RemoveFuncStmt + | RemoveOperStmt + | RenameStmt + | RevokeStmt + | RevokeRoleStmt + | RuleStmt + | SecLabelStmt + | SelectStmt + | TransactionStmt + | TruncateStmt + | UnlistenStmt + | UpdateStmt + | VacuumStmt + | VariableResetStmt + | VariableSetStmt + | VariableShowStmt + | ViewStmt + | /*empty*/ + ; + +opt_single_name : + ColId + | /*empty*/ + ; + +opt_qualified_name : + any_name + | /*empty*/ + ; + +opt_concurrently : + CONCURRENTLY + | /*empty*/ + ; + +opt_drop_behavior : + CASCADE + | RESTRICT + | /*empty*/ + ; + +CallStmt : + CALL func_application + ; + +CreateRoleStmt : + CREATE ROLE RoleId opt_with OptRoleList + ; + +opt_with : + WITH /*13N*/ + | WITH_LA + | /*empty*/ + ; + +OptRoleList : + OptRoleList CreateOptRoleElem + | /*empty*/ + ; + +AlterOptRoleList : + AlterOptRoleList AlterOptRoleElem + | /*empty*/ + ; + +AlterOptRoleElem : + PASSWORD Sconst + | PASSWORD NULL_P + | ENCRYPTED PASSWORD Sconst + | UNENCRYPTED PASSWORD Sconst + | INHERIT + | CONNECTION LIMIT SignedIconst + | VALID UNTIL Sconst + | USER role_list + | IDENT /*15N*/ + ; + +CreateOptRoleElem : + AlterOptRoleElem + | SYSID Iconst + | ADMIN role_list + | ROLE role_list + | IN_P /*9N*/ ROLE role_list + | IN_P /*9N*/ GROUP_P role_list + ; + +CreateUserStmt : + CREATE USER RoleId opt_with OptRoleList + ; + +AlterRoleStmt : + ALTER ROLE RoleSpec opt_with AlterOptRoleList + | ALTER USER RoleSpec opt_with AlterOptRoleList + ; + +opt_in_database : + /*empty*/ + | IN_P /*9N*/ DATABASE name + ; + +AlterRoleSetStmt : + ALTER ROLE RoleSpec opt_in_database SetResetClause + | ALTER ROLE ALL opt_in_database SetResetClause + | ALTER USER RoleSpec opt_in_database SetResetClause + | ALTER USER ALL opt_in_database SetResetClause + ; + +DropRoleStmt : + DROP ROLE role_list + | DROP ROLE IF_P EXISTS role_list + | DROP USER role_list + | DROP USER IF_P EXISTS role_list + | DROP GROUP_P role_list + | DROP GROUP_P IF_P EXISTS role_list + ; + +CreateGroupStmt : + CREATE GROUP_P RoleId opt_with OptRoleList + ; + +AlterGroupStmt : + ALTER GROUP_P RoleSpec add_drop USER role_list + ; + +add_drop : + ADD_P + | DROP + ; + +CreateSchemaStmt : + CREATE SCHEMA opt_single_name AUTHORIZATION RoleSpec OptSchemaEltList + | CREATE SCHEMA ColId OptSchemaEltList + | CREATE SCHEMA IF_P NOT /*6R*/ EXISTS opt_single_name AUTHORIZATION RoleSpec OptSchemaEltList + | CREATE SCHEMA IF_P NOT /*6R*/ EXISTS ColId OptSchemaEltList + ; + +OptSchemaEltList : + OptSchemaEltList schema_stmt + | /*empty*/ + ; + +schema_stmt : + CreateStmt + | IndexStmt + | CreateSeqStmt + | CreateTrigStmt + | GrantStmt + | ViewStmt + ; + +VariableSetStmt : + SET /*1N*/ set_rest + | SET /*1N*/ LOCAL set_rest + | SET /*1N*/ SESSION set_rest + ; + +set_rest : + TRANSACTION transaction_mode_list + | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list + | set_rest_more + ; + +generic_set : + var_name TO var_list + | var_name '=' /*8N*/ var_list + | var_name TO DEFAULT + | var_name '=' /*8N*/ DEFAULT + ; + +set_rest_more : + generic_set + | var_name FROM CURRENT_P + | TIME ZONE zone_value + | CATALOG_P Sconst + | SCHEMA Sconst + | NAMES opt_encoding + | ROLE NonReservedWord_or_Sconst + | SESSION AUTHORIZATION NonReservedWord_or_Sconst + | SESSION AUTHORIZATION DEFAULT + | XML_P OPTION document_or_content + | TRANSACTION SNAPSHOT Sconst + ; + +var_name : + ColId + | var_name '.' /*26L*/ ColId + ; + +var_list : + var_value + | var_list ',' var_value + ; + +var_value : + opt_boolean_or_string + | NumericOnly + ; + +iso_level : + READ UNCOMMITTED + | READ COMMITTED + | REPEATABLE READ + | SERIALIZABLE + ; + +opt_boolean_or_string : + TRUE_P + | FALSE_P + | ON + | NonReservedWord_or_Sconst + ; + +zone_value : + Sconst + | IDENT /*15N*/ + | ConstInterval Sconst opt_interval + | ConstInterval '(' /*24L*/ Iconst ')' /*24L*/ Sconst + | NumericOnly + | DEFAULT + | LOCAL + ; + +opt_encoding : + Sconst + | DEFAULT + | /*empty*/ + ; + +NonReservedWord_or_Sconst : + NonReservedWord + | Sconst + ; + +VariableResetStmt : + RESET reset_rest + ; + +reset_rest : + generic_reset + | TIME ZONE + | TRANSACTION ISOLATION LEVEL + | SESSION AUTHORIZATION + ; + +generic_reset : + var_name + | ALL + ; + +SetResetClause : + SET /*1N*/ set_rest + | VariableResetStmt + ; + +FunctionSetResetClause : + SET /*1N*/ set_rest_more + | VariableResetStmt + ; + +VariableShowStmt : + SHOW var_name + | SHOW TIME ZONE + | SHOW TRANSACTION ISOLATION LEVEL + | SHOW SESSION AUTHORIZATION + | SHOW ALL + ; + +ConstraintsSetStmt : + SET /*1N*/ CONSTRAINTS constraints_set_list constraints_set_mode + ; + +constraints_set_list : + ALL + | qualified_name_list + ; + +constraints_set_mode : + DEFERRED + | IMMEDIATE + ; + +CheckPointStmt : + CHECKPOINT + ; + +DiscardStmt : + DISCARD ALL + | DISCARD TEMP + | DISCARD TEMPORARY + | DISCARD PLANS + | DISCARD SEQUENCES + ; + +AlterTableStmt : + ALTER TABLE relation_expr alter_table_cmds + | ALTER TABLE IF_P EXISTS relation_expr alter_table_cmds + | ALTER TABLE relation_expr partition_cmd + | ALTER TABLE IF_P EXISTS relation_expr partition_cmd + | ALTER TABLE ALL IN_P /*9N*/ TABLESPACE name SET /*1N*/ TABLESPACE name opt_nowait + | ALTER TABLE ALL IN_P /*9N*/ TABLESPACE name OWNED BY role_list SET /*1N*/ TABLESPACE name opt_nowait + | ALTER INDEX qualified_name alter_table_cmds + | ALTER INDEX IF_P EXISTS qualified_name alter_table_cmds + | ALTER INDEX qualified_name index_partition_cmd + | ALTER INDEX ALL IN_P /*9N*/ TABLESPACE name SET /*1N*/ TABLESPACE name opt_nowait + | ALTER INDEX ALL IN_P /*9N*/ TABLESPACE name OWNED BY role_list SET /*1N*/ TABLESPACE name opt_nowait + | ALTER SEQUENCE qualified_name alter_table_cmds + | ALTER SEQUENCE IF_P EXISTS qualified_name alter_table_cmds + | ALTER VIEW qualified_name alter_table_cmds + | ALTER VIEW IF_P EXISTS qualified_name alter_table_cmds + | ALTER MATERIALIZED VIEW qualified_name alter_table_cmds + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name alter_table_cmds + | ALTER MATERIALIZED VIEW ALL IN_P /*9N*/ TABLESPACE name SET /*1N*/ TABLESPACE name opt_nowait + | ALTER MATERIALIZED VIEW ALL IN_P /*9N*/ TABLESPACE name OWNED BY role_list SET /*1N*/ TABLESPACE name opt_nowait + | ALTER FOREIGN TABLE relation_expr alter_table_cmds + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr alter_table_cmds + ; + +alter_table_cmds : + alter_table_cmd + | alter_table_cmds ',' alter_table_cmd + ; + +partition_cmd : + ATTACH PARTITION /*15N*/ qualified_name PartitionBoundSpec + | DETACH PARTITION /*15N*/ qualified_name opt_concurrently + | DETACH PARTITION /*15N*/ qualified_name FINALIZE + ; + +index_partition_cmd : + ATTACH PARTITION /*15N*/ qualified_name + ; + +alter_table_cmd : + ADD_P columnDef + | ADD_P IF_P NOT /*6R*/ EXISTS columnDef + | ADD_P COLUMN columnDef + | ADD_P COLUMN IF_P NOT /*6R*/ EXISTS columnDef + | ALTER opt_column ColId alter_column_default + | ALTER opt_column ColId DROP NOT /*6R*/ NULL_P + | ALTER opt_column ColId SET /*1N*/ NOT /*6R*/ NULL_P + | ALTER opt_column ColId DROP EXPRESSION + | ALTER opt_column ColId DROP EXPRESSION IF_P EXISTS + | ALTER opt_column ColId SET /*1N*/ STATISTICS SignedIconst + | ALTER opt_column Iconst SET /*1N*/ STATISTICS SignedIconst + | ALTER opt_column ColId SET /*1N*/ reloptions + | ALTER opt_column ColId RESET reloptions + | ALTER opt_column ColId SET /*1N*/ column_storage + | ALTER opt_column ColId SET /*1N*/ column_compression + | ALTER opt_column ColId ADD_P GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList + | ALTER opt_column ColId alter_identity_column_option_list + | ALTER opt_column ColId DROP IDENTITY_P + | ALTER opt_column ColId DROP IDENTITY_P IF_P EXISTS + | DROP opt_column IF_P EXISTS ColId opt_drop_behavior + | DROP opt_column ColId opt_drop_behavior + | ALTER opt_column ColId opt_set_data TYPE_P Typename opt_collate_clause alter_using + | ALTER opt_column ColId alter_generic_options + | ADD_P TableConstraint + | ALTER CONSTRAINT name ConstraintAttributeSpec + | VALIDATE CONSTRAINT name + | DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior + | DROP CONSTRAINT name opt_drop_behavior + | SET /*1N*/ WITHOUT /*13N*/ OIDS + | CLUSTER ON name + | SET /*1N*/ WITHOUT /*13N*/ CLUSTER + | SET /*1N*/ LOGGED + | SET /*1N*/ UNLOGGED + | ENABLE_P TRIGGER name + | ENABLE_P ALWAYS TRIGGER name + | ENABLE_P REPLICA TRIGGER name + | ENABLE_P TRIGGER ALL + | ENABLE_P TRIGGER USER + | DISABLE_P TRIGGER name + | DISABLE_P TRIGGER ALL + | DISABLE_P TRIGGER USER + | ENABLE_P RULE name + | ENABLE_P ALWAYS RULE name + | ENABLE_P REPLICA RULE name + | DISABLE_P RULE name + | INHERIT qualified_name + | NO INHERIT qualified_name + | OF any_name + | NOT /*6R*/ OF + | OWNER TO RoleSpec + | SET /*1N*/ ACCESS METHOD name + | SET /*1N*/ TABLESPACE name + | SET /*1N*/ reloptions + | RESET reloptions + | REPLICA IDENTITY_P replica_identity + | ENABLE_P ROW LEVEL SECURITY + | DISABLE_P ROW LEVEL SECURITY + | FORCE ROW LEVEL SECURITY + | NO FORCE ROW LEVEL SECURITY + | alter_generic_options + ; + +alter_column_default : + SET /*1N*/ DEFAULT a_expr + | DROP DEFAULT + ; + +opt_collate_clause : + COLLATE /*21L*/ any_name + | /*empty*/ + ; + +alter_using : + USING a_expr + | /*empty*/ + ; + +replica_identity : + NOTHING + | FULL /*27L*/ + | DEFAULT + | USING INDEX name + ; + +reloptions : + '(' /*24L*/ reloption_list ')' /*24L*/ + ; + +opt_reloptions : + WITH /*13N*/ reloptions + | /*empty*/ + ; + +reloption_list : + reloption_elem + | reloption_list ',' reloption_elem + ; + +reloption_elem : + ColLabel '=' /*8N*/ def_arg + | ColLabel + | ColLabel '.' /*26L*/ ColLabel '=' /*8N*/ def_arg + | ColLabel '.' /*26L*/ ColLabel + ; + +alter_identity_column_option_list : + alter_identity_column_option + | alter_identity_column_option_list alter_identity_column_option + ; + +alter_identity_column_option : + RESTART + | RESTART opt_with NumericOnly + | SET /*1N*/ SeqOptElem + | SET /*1N*/ GENERATED generated_when + ; + +PartitionBoundSpec : + FOR VALUES WITH /*13N*/ '(' /*24L*/ hash_partbound ')' /*24L*/ + | FOR VALUES IN_P /*9N*/ '(' /*24L*/ expr_list ')' /*24L*/ + | FOR VALUES FROM '(' /*24L*/ expr_list ')' /*24L*/ TO '(' /*24L*/ expr_list ')' /*24L*/ + | DEFAULT + ; + +hash_partbound_elem : + NonReservedWord Iconst + ; + +hash_partbound : + hash_partbound_elem + | hash_partbound ',' hash_partbound_elem + ; + +AlterCompositeTypeStmt : + ALTER TYPE_P any_name alter_type_cmds + ; + +alter_type_cmds : + alter_type_cmd + | alter_type_cmds ',' alter_type_cmd + ; + +alter_type_cmd : + ADD_P ATTRIBUTE TableFuncElement opt_drop_behavior + | DROP ATTRIBUTE IF_P EXISTS ColId opt_drop_behavior + | DROP ATTRIBUTE ColId opt_drop_behavior + | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_collate_clause opt_drop_behavior + ; + +ClosePortalStmt : + CLOSE cursor_name + | CLOSE ALL + ; + +CopyStmt : + COPY opt_binary qualified_name opt_column_list copy_from opt_program copy_file_name copy_delimiter opt_with copy_options where_clause + | COPY '(' /*24L*/ PreparableStmt ')' /*24L*/ TO opt_program copy_file_name opt_with copy_options + ; + +copy_from : + FROM + | TO + ; + +opt_program : + PROGRAM + | /*empty*/ + ; + +copy_file_name : + Sconst + | STDIN + | STDOUT + ; + +copy_options : + copy_opt_list + | '(' /*24L*/ copy_generic_opt_list ')' /*24L*/ + ; + +copy_opt_list : + copy_opt_list copy_opt_item + | /*empty*/ + ; + +copy_opt_item : + BINARY + | FREEZE + | DELIMITER opt_as Sconst + | NULL_P opt_as Sconst + | CSV + | HEADER_P + | QUOTE opt_as Sconst + | ESCAPE /*10N*/ opt_as Sconst + | FORCE QUOTE columnList + | FORCE QUOTE '*' /*18L*/ + | FORCE NOT /*6R*/ NULL_P columnList + | FORCE NULL_P columnList + | ENCODING Sconst + ; + +opt_binary : + BINARY + | /*empty*/ + ; + +copy_delimiter : + opt_using DELIMITERS Sconst + | /*empty*/ + ; + +opt_using : + USING + | /*empty*/ + ; + +copy_generic_opt_list : + copy_generic_opt_elem + | copy_generic_opt_list ',' copy_generic_opt_elem + ; + +copy_generic_opt_elem : + ColLabel copy_generic_opt_arg + ; + +copy_generic_opt_arg : + opt_boolean_or_string + | NumericOnly + | '*' /*18L*/ + | '(' /*24L*/ copy_generic_opt_arg_list ')' /*24L*/ + | /*empty*/ + ; + +copy_generic_opt_arg_list : + copy_generic_opt_arg_list_item + | copy_generic_opt_arg_list ',' copy_generic_opt_arg_list_item + ; + +copy_generic_opt_arg_list_item : + opt_boolean_or_string + ; + +CreateStmt : + CREATE OptTemp TABLE qualified_name '(' /*24L*/ OptTableElementList ')' /*24L*/ OptInherit OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS qualified_name '(' /*24L*/ OptTableElementList ')' /*24L*/ OptInherit OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE qualified_name OF any_name OptTypedTableElementList OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS qualified_name OF any_name OptTypedTableElementList OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE qualified_name PARTITION /*15N*/ OF qualified_name OptTypedTableElementList PartitionBoundSpec OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS qualified_name PARTITION /*15N*/ OF qualified_name OptTypedTableElementList PartitionBoundSpec OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + ; + +OptTemp : + TEMPORARY + | TEMP + | LOCAL TEMPORARY + | LOCAL TEMP + | GLOBAL TEMPORARY + | GLOBAL TEMP + | UNLOGGED + | /*empty*/ + ; + +OptTableElementList : + TableElementList + | /*empty*/ + ; + +OptTypedTableElementList : + '(' /*24L*/ TypedTableElementList ')' /*24L*/ + | /*empty*/ + ; + +TableElementList : + TableElement + | TableElementList ',' TableElement + ; + +TypedTableElementList : + TypedTableElement + | TypedTableElementList ',' TypedTableElement + ; + +TableElement : + columnDef + | TableLikeClause + | TableConstraint + ; + +TypedTableElement : + columnOptions + | TableConstraint + ; + +columnDef : + ColId Typename opt_column_storage opt_column_compression create_generic_options ColQualList + ; + +columnOptions : + ColId ColQualList + | ColId WITH /*13N*/ OPTIONS ColQualList + ; + +column_compression : + COMPRESSION ColId + | COMPRESSION DEFAULT + ; + +opt_column_compression : + column_compression + | /*empty*/ + ; + +column_storage : + STORAGE ColId + | STORAGE DEFAULT + ; + +opt_column_storage : + column_storage + | /*empty*/ + ; + +ColQualList : + ColQualList ColConstraint + | /*empty*/ + ; + +ColConstraint : + CONSTRAINT name ColConstraintElem + | ColConstraintElem + | ConstraintAttr + | COLLATE /*21L*/ any_name + ; + +ColConstraintElem : + NOT /*6R*/ NULL_P + | NULL_P + | UNIQUE /*11N*/ opt_unique_null_treatment opt_definition OptConsTableSpace + | PRIMARY KEY opt_definition OptConsTableSpace + | CHECK '(' /*24L*/ a_expr ')' /*24L*/ opt_no_inherit + | DEFAULT b_expr + | GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList + | GENERATED generated_when AS '(' /*24L*/ a_expr ')' /*24L*/ STORED + | REFERENCES qualified_name opt_column_list key_match key_actions + ; + +opt_unique_null_treatment : + NULLS_P DISTINCT + | NULLS_P NOT /*6R*/ DISTINCT + | /*empty*/ + ; + +generated_when : + ALWAYS + | BY DEFAULT + ; + +ConstraintAttr : + DEFERRABLE + | NOT /*6R*/ DEFERRABLE + | INITIALLY DEFERRED + | INITIALLY IMMEDIATE + ; + +TableLikeClause : + LIKE /*9N*/ qualified_name TableLikeOptionList + ; + +TableLikeOptionList : + TableLikeOptionList INCLUDING TableLikeOption + | TableLikeOptionList EXCLUDING TableLikeOption + | /*empty*/ + ; + +TableLikeOption : + COMMENTS + | COMPRESSION + | CONSTRAINTS + | DEFAULTS + | IDENTITY_P + | GENERATED + | INDEXES + | STATISTICS + | STORAGE + | ALL + ; + +TableConstraint : + CONSTRAINT name ConstraintElem + | ConstraintElem + ; + +ConstraintElem : + CHECK '(' /*24L*/ a_expr ')' /*24L*/ ConstraintAttributeSpec + | UNIQUE /*11N*/ opt_unique_null_treatment '(' /*24L*/ columnList ')' /*24L*/ opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec + | UNIQUE /*11N*/ ExistingIndex ConstraintAttributeSpec + | PRIMARY KEY '(' /*24L*/ columnList ')' /*24L*/ opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec + | PRIMARY KEY ExistingIndex ConstraintAttributeSpec + | EXCLUDE access_method_clause '(' /*24L*/ ExclusionConstraintList ')' /*24L*/ opt_c_include opt_definition OptConsTableSpace OptWhereClause ConstraintAttributeSpec + | FOREIGN KEY '(' /*24L*/ columnList ')' /*24L*/ REFERENCES qualified_name opt_column_list key_match key_actions ConstraintAttributeSpec + ; + +opt_no_inherit : + NO INHERIT + | /*empty*/ + ; + +opt_column_list : + '(' /*24L*/ columnList ')' /*24L*/ + | /*empty*/ + ; + +columnList : + columnElem + | columnList ',' columnElem + ; + +columnElem : + ColId + ; + +opt_c_include : + INCLUDE '(' /*24L*/ columnList ')' /*24L*/ + | /*empty*/ + ; + +key_match : + MATCH FULL /*27L*/ + | MATCH PARTIAL + | MATCH SIMPLE + | /*empty*/ + ; + +ExclusionConstraintList : + ExclusionConstraintElem + | ExclusionConstraintList ',' ExclusionConstraintElem + ; + +ExclusionConstraintElem : + index_elem WITH /*13N*/ any_operator + | index_elem WITH /*13N*/ OPERATOR /*16L*/ '(' /*24L*/ any_operator ')' /*24L*/ + ; + +OptWhereClause : + WHERE '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +key_actions : + key_update + | key_delete + | key_update key_delete + | key_delete key_update + | /*empty*/ + ; + +key_update : + ON UPDATE key_action + ; + +key_delete : + ON DELETE_P key_action + ; + +key_action : + NO ACTION + | RESTRICT + | CASCADE + | SET /*1N*/ NULL_P opt_column_list + | SET /*1N*/ DEFAULT opt_column_list + ; + +OptInherit : + INHERITS '(' /*24L*/ qualified_name_list ')' /*24L*/ + | /*empty*/ + ; + +OptPartitionSpec : + PartitionSpec + | /*empty*/ + ; + +PartitionSpec : + PARTITION /*15N*/ BY ColId '(' /*24L*/ part_params ')' /*24L*/ + ; + +part_params : + part_elem + | part_params ',' part_elem + ; + +part_elem : + ColId opt_collate opt_qualified_name + | func_expr_windowless opt_collate opt_qualified_name + | '(' /*24L*/ a_expr ')' /*24L*/ opt_collate opt_qualified_name + ; + +table_access_method_clause : + USING name + | /*empty*/ + ; + +OptWith : + WITH /*13N*/ reloptions + | WITHOUT /*13N*/ OIDS + | /*empty*/ + ; + +OnCommitOption : + ON COMMIT DROP + | ON COMMIT DELETE_P ROWS /*15N*/ + | ON COMMIT PRESERVE ROWS /*15N*/ + | /*empty*/ + ; + +OptTableSpace : + TABLESPACE name + | /*empty*/ + ; + +OptConsTableSpace : + USING INDEX TABLESPACE name + | /*empty*/ + ; + +ExistingIndex : + USING INDEX name + ; + +CreateStatsStmt : + CREATE STATISTICS opt_qualified_name opt_name_list ON stats_params FROM from_list + | CREATE STATISTICS IF_P NOT /*6R*/ EXISTS any_name opt_name_list ON stats_params FROM from_list + ; + +stats_params : + stats_param + | stats_params ',' stats_param + ; + +stats_param : + ColId + | func_expr_windowless + | '(' /*24L*/ a_expr ')' /*24L*/ + ; + +AlterStatsStmt : + ALTER STATISTICS any_name SET /*1N*/ STATISTICS SignedIconst + | ALTER STATISTICS IF_P EXISTS any_name SET /*1N*/ STATISTICS SignedIconst + ; + +CreateAsStmt : + CREATE OptTemp TABLE create_as_target AS SelectStmt opt_with_data + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS create_as_target AS SelectStmt opt_with_data + ; + +create_as_target : + qualified_name opt_column_list table_access_method_clause OptWith OnCommitOption OptTableSpace + ; + +opt_with_data : + WITH /*13N*/ DATA_P + | WITH /*13N*/ NO DATA_P + | /*empty*/ + ; + +CreateMatViewStmt : + CREATE OptNoLog MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data + | CREATE OptNoLog MATERIALIZED VIEW IF_P NOT /*6R*/ EXISTS create_mv_target AS SelectStmt opt_with_data + ; + +create_mv_target : + qualified_name opt_column_list table_access_method_clause opt_reloptions OptTableSpace + ; + +OptNoLog : + UNLOGGED + | /*empty*/ + ; + +RefreshMatViewStmt : + REFRESH MATERIALIZED VIEW opt_concurrently qualified_name opt_with_data + ; + +CreateSeqStmt : + CREATE OptTemp SEQUENCE qualified_name OptSeqOptList + | CREATE OptTemp SEQUENCE IF_P NOT /*6R*/ EXISTS qualified_name OptSeqOptList + ; + +AlterSeqStmt : + ALTER SEQUENCE qualified_name SeqOptList + | ALTER SEQUENCE IF_P EXISTS qualified_name SeqOptList + ; + +OptSeqOptList : + SeqOptList + | /*empty*/ + ; + +OptParenthesizedSeqOptList : + '(' /*24L*/ SeqOptList ')' /*24L*/ + | /*empty*/ + ; + +SeqOptList : + SeqOptElem + | SeqOptList SeqOptElem + ; + +SeqOptElem : + AS SimpleTypename + | CACHE NumericOnly + | CYCLE + | NO CYCLE + | INCREMENT opt_by NumericOnly + | MAXVALUE NumericOnly + | MINVALUE NumericOnly + | NO MAXVALUE + | NO MINVALUE + | OWNED BY any_name + | SEQUENCE NAME_P any_name + | START opt_with NumericOnly + | RESTART + | RESTART opt_with NumericOnly + ; + +opt_by : + BY + | /*empty*/ + ; + +NumericOnly : + FCONST + | '+' /*17L*/ FCONST + | '-' /*17L*/ FCONST + | SignedIconst + ; + +NumericOnly_list : + NumericOnly + | NumericOnly_list ',' NumericOnly + ; + +CreatePLangStmt : + CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE name + | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE name HANDLER handler_name opt_inline_handler opt_validator + ; + +opt_trusted : + TRUSTED + | /*empty*/ + ; + +handler_name : + name + | name attrs + ; + +opt_inline_handler : + INLINE_P handler_name + | /*empty*/ + ; + +validator_clause : + VALIDATOR handler_name + | NO VALIDATOR + ; + +opt_validator : + validator_clause + | /*empty*/ + ; + +opt_procedural : + PROCEDURAL + | /*empty*/ + ; + +CreateTableSpaceStmt : + CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst opt_reloptions + ; + +OptTableSpaceOwner : + OWNER RoleSpec + | /*empty*/ + ; + +DropTableSpaceStmt : + DROP TABLESPACE name + | DROP TABLESPACE IF_P EXISTS name + ; + +CreateExtensionStmt : + CREATE EXTENSION name opt_with create_extension_opt_list + | CREATE EXTENSION IF_P NOT /*6R*/ EXISTS name opt_with create_extension_opt_list + ; + +create_extension_opt_list : + create_extension_opt_list create_extension_opt_item + | /*empty*/ + ; + +create_extension_opt_item : + SCHEMA name + | VERSION_P NonReservedWord_or_Sconst + | FROM NonReservedWord_or_Sconst + | CASCADE + ; + +AlterExtensionStmt : + ALTER EXTENSION name UPDATE alter_extension_opt_list + ; + +alter_extension_opt_list : + alter_extension_opt_list alter_extension_opt_item + | /*empty*/ + ; + +alter_extension_opt_item : + TO NonReservedWord_or_Sconst + ; + +AlterExtensionContentsStmt : + ALTER EXTENSION name add_drop object_type_name name + | ALTER EXTENSION name add_drop object_type_any_name any_name + | ALTER EXTENSION name add_drop AGGREGATE aggregate_with_argtypes + | ALTER EXTENSION name add_drop CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ + | ALTER EXTENSION name add_drop DOMAIN_P Typename + | ALTER EXTENSION name add_drop FUNCTION function_with_argtypes + | ALTER EXTENSION name add_drop OPERATOR /*16L*/ operator_with_argtypes + | ALTER EXTENSION name add_drop OPERATOR /*16L*/ CLASS any_name USING name + | ALTER EXTENSION name add_drop OPERATOR /*16L*/ FAMILY any_name USING name + | ALTER EXTENSION name add_drop PROCEDURE function_with_argtypes + | ALTER EXTENSION name add_drop ROUTINE function_with_argtypes + | ALTER EXTENSION name add_drop TRANSFORM FOR Typename LANGUAGE name + | ALTER EXTENSION name add_drop TYPE_P Typename + ; + +CreateFdwStmt : + CREATE FOREIGN DATA_P WRAPPER name opt_fdw_options create_generic_options + ; + +fdw_option : + HANDLER handler_name + | NO HANDLER + | VALIDATOR handler_name + | NO VALIDATOR + ; + +fdw_options : + fdw_option + | fdw_options fdw_option + ; + +opt_fdw_options : + fdw_options + | /*empty*/ + ; + +AlterFdwStmt : + ALTER FOREIGN DATA_P WRAPPER name opt_fdw_options alter_generic_options + | ALTER FOREIGN DATA_P WRAPPER name fdw_options + ; + +create_generic_options : + OPTIONS '(' /*24L*/ generic_option_list ')' /*24L*/ + | /*empty*/ + ; + +generic_option_list : + generic_option_elem + | generic_option_list ',' generic_option_elem + ; + +alter_generic_options : + OPTIONS '(' /*24L*/ alter_generic_option_list ')' /*24L*/ + ; + +alter_generic_option_list : + alter_generic_option_elem + | alter_generic_option_list ',' alter_generic_option_elem + ; + +alter_generic_option_elem : + generic_option_elem + | SET /*1N*/ generic_option_elem + | ADD_P generic_option_elem + | DROP generic_option_name + ; + +generic_option_elem : + generic_option_name generic_option_arg + ; + +generic_option_name : + ColLabel + ; + +generic_option_arg : + Sconst + ; + +CreateForeignServerStmt : + CREATE SERVER name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options + | CREATE SERVER IF_P NOT /*6R*/ EXISTS name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options + ; + +opt_type : + TYPE_P Sconst + | /*empty*/ + ; + +foreign_server_version : + VERSION_P Sconst + | VERSION_P NULL_P + ; + +opt_foreign_server_version : + foreign_server_version + | /*empty*/ + ; + +AlterForeignServerStmt : + ALTER SERVER name foreign_server_version alter_generic_options + | ALTER SERVER name foreign_server_version + | ALTER SERVER name alter_generic_options + ; + +CreateForeignTableStmt : + CREATE FOREIGN TABLE qualified_name '(' /*24L*/ OptTableElementList ')' /*24L*/ OptInherit SERVER name create_generic_options + | CREATE FOREIGN TABLE IF_P NOT /*6R*/ EXISTS qualified_name '(' /*24L*/ OptTableElementList ')' /*24L*/ OptInherit SERVER name create_generic_options + | CREATE FOREIGN TABLE qualified_name PARTITION /*15N*/ OF qualified_name OptTypedTableElementList PartitionBoundSpec SERVER name create_generic_options + | CREATE FOREIGN TABLE IF_P NOT /*6R*/ EXISTS qualified_name PARTITION /*15N*/ OF qualified_name OptTypedTableElementList PartitionBoundSpec SERVER name create_generic_options + ; + +ImportForeignSchemaStmt : + IMPORT_P FOREIGN SCHEMA name import_qualification FROM SERVER name INTO name create_generic_options + ; + +import_qualification_type : + LIMIT TO + | EXCEPT /*2L*/ + ; + +import_qualification : + import_qualification_type '(' /*24L*/ relation_expr_list ')' /*24L*/ + | /*empty*/ + ; + +CreateUserMappingStmt : + CREATE USER MAPPING FOR auth_ident SERVER name create_generic_options + | CREATE USER MAPPING IF_P NOT /*6R*/ EXISTS FOR auth_ident SERVER name create_generic_options + ; + +auth_ident : + RoleSpec + | USER + ; + +DropUserMappingStmt : + DROP USER MAPPING FOR auth_ident SERVER name + | DROP USER MAPPING IF_P EXISTS FOR auth_ident SERVER name + ; + +AlterUserMappingStmt : + ALTER USER MAPPING FOR auth_ident SERVER name alter_generic_options + ; + +CreatePolicyStmt : + CREATE POLICY name ON qualified_name RowSecurityDefaultPermissive RowSecurityDefaultForCmd RowSecurityDefaultToRole RowSecurityOptionalExpr RowSecurityOptionalWithCheck + ; + +AlterPolicyStmt : + ALTER POLICY name ON qualified_name RowSecurityOptionalToRole RowSecurityOptionalExpr RowSecurityOptionalWithCheck + ; + +RowSecurityOptionalExpr : + USING '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +RowSecurityOptionalWithCheck : + WITH /*13N*/ CHECK '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +RowSecurityDefaultToRole : + TO role_list + | /*empty*/ + ; + +RowSecurityOptionalToRole : + TO role_list + | /*empty*/ + ; + +RowSecurityDefaultPermissive : + AS IDENT /*15N*/ + | /*empty*/ + ; + +RowSecurityDefaultForCmd : + FOR row_security_cmd + | /*empty*/ + ; + +row_security_cmd : + ALL + | SELECT + | INSERT + | UPDATE + | DELETE_P + ; + +CreateAmStmt : + CREATE ACCESS METHOD name TYPE_P am_type HANDLER handler_name + ; + +am_type : + INDEX + | TABLE + ; + +CreateTrigStmt : + CREATE opt_or_replace TRIGGER name TriggerActionTime TriggerEvents ON qualified_name TriggerReferencing TriggerForSpec TriggerWhen EXECUTE FUNCTION_or_PROCEDURE func_name '(' /*24L*/ TriggerFuncArgs ')' /*24L*/ + | CREATE opt_or_replace CONSTRAINT TRIGGER name AFTER TriggerEvents ON qualified_name OptConstrFromTable ConstraintAttributeSpec FOR EACH ROW TriggerWhen EXECUTE FUNCTION_or_PROCEDURE func_name '(' /*24L*/ TriggerFuncArgs ')' /*24L*/ + ; + +TriggerActionTime : + BEFORE + | AFTER + | INSTEAD OF + ; + +TriggerEvents : + TriggerOneEvent + | TriggerEvents OR /*4L*/ TriggerOneEvent + ; + +TriggerOneEvent : + INSERT + | DELETE_P + | UPDATE + | UPDATE OF columnList + | TRUNCATE + ; + +TriggerReferencing : + REFERENCING TriggerTransitions + | /*empty*/ + ; + +TriggerTransitions : + TriggerTransition + | TriggerTransitions TriggerTransition + ; + +TriggerTransition : + TransitionOldOrNew TransitionRowOrTable opt_as TransitionRelName + ; + +TransitionOldOrNew : + NEW + | OLD + ; + +TransitionRowOrTable : + TABLE + | ROW + ; + +TransitionRelName : + ColId + ; + +TriggerForSpec : + FOR TriggerForOptEach TriggerForType + | /*empty*/ + ; + +TriggerForOptEach : + EACH + | /*empty*/ + ; + +TriggerForType : + ROW + | STATEMENT + ; + +TriggerWhen : + WHEN '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +FUNCTION_or_PROCEDURE : + FUNCTION + | PROCEDURE + ; + +TriggerFuncArgs : + TriggerFuncArg + | TriggerFuncArgs ',' TriggerFuncArg + | /*empty*/ + ; + +TriggerFuncArg : + Iconst + | FCONST + | Sconst + | ColLabel + ; + +OptConstrFromTable : + FROM qualified_name + | /*empty*/ + ; + +ConstraintAttributeSpec : + /*empty*/ + | ConstraintAttributeSpec ConstraintAttributeElem + ; + +ConstraintAttributeElem : + NOT /*6R*/ DEFERRABLE + | DEFERRABLE + | INITIALLY IMMEDIATE + | INITIALLY DEFERRED + | NOT /*6R*/ VALID + | NO INHERIT + ; + +CreateEventTrigStmt : + CREATE EVENT TRIGGER name ON ColLabel EXECUTE FUNCTION_or_PROCEDURE func_name '(' /*24L*/ ')' /*24L*/ + | CREATE EVENT TRIGGER name ON ColLabel WHEN event_trigger_when_list EXECUTE FUNCTION_or_PROCEDURE func_name '(' /*24L*/ ')' /*24L*/ + ; + +event_trigger_when_list : + event_trigger_when_item + | event_trigger_when_list AND /*5L*/ event_trigger_when_item + ; + +event_trigger_when_item : + ColId IN_P /*9N*/ '(' /*24L*/ event_trigger_value_list ')' /*24L*/ + ; + +event_trigger_value_list : + SCONST + | event_trigger_value_list ',' SCONST + ; + +AlterEventTrigStmt : + ALTER EVENT TRIGGER name enable_trigger + ; + +enable_trigger : + ENABLE_P + | ENABLE_P REPLICA + | ENABLE_P ALWAYS + | DISABLE_P + ; + +CreateAssertionStmt : + CREATE ASSERTION any_name CHECK '(' /*24L*/ a_expr ')' /*24L*/ ConstraintAttributeSpec + ; + +DefineStmt : + CREATE opt_or_replace AGGREGATE func_name aggr_args definition + | CREATE opt_or_replace AGGREGATE func_name old_aggr_definition + | CREATE OPERATOR /*16L*/ any_operator definition + | CREATE TYPE_P any_name definition + | CREATE TYPE_P any_name + | CREATE TYPE_P any_name AS '(' /*24L*/ OptTableFuncElementList ')' /*24L*/ + | CREATE TYPE_P any_name AS ENUM_P '(' /*24L*/ opt_enum_val_list ')' /*24L*/ + | CREATE TYPE_P any_name AS RANGE /*15N*/ definition + | CREATE TEXT_P SEARCH PARSER any_name definition + | CREATE TEXT_P SEARCH DICTIONARY any_name definition + | CREATE TEXT_P SEARCH TEMPLATE any_name definition + | CREATE TEXT_P SEARCH CONFIGURATION any_name definition + | CREATE COLLATION any_name definition + | CREATE COLLATION IF_P NOT /*6R*/ EXISTS any_name definition + | CREATE COLLATION any_name FROM any_name + | CREATE COLLATION IF_P NOT /*6R*/ EXISTS any_name FROM any_name + ; + +definition : + '(' /*24L*/ def_list ')' /*24L*/ + ; + +def_list : + def_elem + | def_list ',' def_elem + ; + +def_elem : + ColLabel '=' /*8N*/ def_arg + | ColLabel + ; + +def_arg : + func_type + | reserved_keyword + | qual_all_Op + | NumericOnly + | Sconst + | NONE + ; + +old_aggr_definition : + '(' /*24L*/ old_aggr_list ')' /*24L*/ + ; + +old_aggr_list : + old_aggr_elem + | old_aggr_list ',' old_aggr_elem + ; + +old_aggr_elem : + IDENT /*15N*/ '=' /*8N*/ def_arg + ; + +opt_enum_val_list : + enum_val_list + | /*empty*/ + ; + +enum_val_list : + Sconst + | enum_val_list ',' Sconst + ; + +AlterEnumStmt : + ALTER TYPE_P any_name ADD_P VALUE_P /*12N*/ opt_if_not_exists Sconst + | ALTER TYPE_P any_name ADD_P VALUE_P /*12N*/ opt_if_not_exists Sconst BEFORE Sconst + | ALTER TYPE_P any_name ADD_P VALUE_P /*12N*/ opt_if_not_exists Sconst AFTER Sconst + | ALTER TYPE_P any_name RENAME VALUE_P /*12N*/ Sconst TO Sconst + ; + +opt_if_not_exists : + IF_P NOT /*6R*/ EXISTS + | /*empty*/ + ; + +CreateOpClassStmt : + CREATE OPERATOR /*16L*/ CLASS any_name opt_default FOR TYPE_P Typename USING name opt_opfamily AS opclass_item_list + ; + +opclass_item_list : + opclass_item + | opclass_item_list ',' opclass_item + ; + +opclass_item : + OPERATOR /*16L*/ Iconst any_operator opclass_purpose opt_recheck + | OPERATOR /*16L*/ Iconst operator_with_argtypes opclass_purpose opt_recheck + | FUNCTION Iconst function_with_argtypes + | FUNCTION Iconst '(' /*24L*/ type_list ')' /*24L*/ function_with_argtypes + | STORAGE Typename + ; + +opt_default : + DEFAULT + | /*empty*/ + ; + +opt_opfamily : + FAMILY any_name + | /*empty*/ + ; + +opclass_purpose : + FOR SEARCH + | FOR ORDER BY any_name + | /*empty*/ + ; + +opt_recheck : + RECHECK + | /*empty*/ + ; + +CreateOpFamilyStmt : + CREATE OPERATOR /*16L*/ FAMILY any_name USING name + ; + +AlterOpFamilyStmt : + ALTER OPERATOR /*16L*/ FAMILY any_name USING name ADD_P opclass_item_list + | ALTER OPERATOR /*16L*/ FAMILY any_name USING name DROP opclass_drop_list + ; + +opclass_drop_list : + opclass_drop + | opclass_drop_list ',' opclass_drop + ; + +opclass_drop : + OPERATOR /*16L*/ Iconst '(' /*24L*/ type_list ')' /*24L*/ + | FUNCTION Iconst '(' /*24L*/ type_list ')' /*24L*/ + ; + +DropOpClassStmt : + DROP OPERATOR /*16L*/ CLASS any_name USING name opt_drop_behavior + | DROP OPERATOR /*16L*/ CLASS IF_P EXISTS any_name USING name opt_drop_behavior + ; + +DropOpFamilyStmt : + DROP OPERATOR /*16L*/ FAMILY any_name USING name opt_drop_behavior + | DROP OPERATOR /*16L*/ FAMILY IF_P EXISTS any_name USING name opt_drop_behavior + ; + +DropOwnedStmt : + DROP OWNED BY role_list opt_drop_behavior + ; + +ReassignOwnedStmt : + REASSIGN OWNED BY role_list TO RoleSpec + ; + +DropStmt : + DROP object_type_any_name IF_P EXISTS any_name_list opt_drop_behavior + | DROP object_type_any_name any_name_list opt_drop_behavior + | DROP drop_type_name IF_P EXISTS name_list opt_drop_behavior + | DROP drop_type_name name_list opt_drop_behavior + | DROP object_type_name_on_any_name name ON any_name opt_drop_behavior + | DROP object_type_name_on_any_name IF_P EXISTS name ON any_name opt_drop_behavior + | DROP TYPE_P type_name_list opt_drop_behavior + | DROP TYPE_P IF_P EXISTS type_name_list opt_drop_behavior + | DROP DOMAIN_P type_name_list opt_drop_behavior + | DROP DOMAIN_P IF_P EXISTS type_name_list opt_drop_behavior + | DROP INDEX CONCURRENTLY any_name_list opt_drop_behavior + | DROP INDEX CONCURRENTLY IF_P EXISTS any_name_list opt_drop_behavior + ; + +object_type_any_name : + TABLE + | SEQUENCE + | VIEW + | MATERIALIZED VIEW + | INDEX + | FOREIGN TABLE + | COLLATION + | CONVERSION_P + | STATISTICS + | TEXT_P SEARCH PARSER + | TEXT_P SEARCH DICTIONARY + | TEXT_P SEARCH TEMPLATE + | TEXT_P SEARCH CONFIGURATION + ; + +object_type_name : + drop_type_name + | DATABASE + | ROLE + | SUBSCRIPTION + | TABLESPACE + ; + +drop_type_name : + ACCESS METHOD + | EVENT TRIGGER + | EXTENSION + | FOREIGN DATA_P WRAPPER + | opt_procedural LANGUAGE + | PUBLICATION + | SCHEMA + | SERVER + ; + +object_type_name_on_any_name : + POLICY + | RULE + | TRIGGER + ; + +any_name_list : + any_name + | any_name_list ',' any_name + ; + +any_name : + ColId + | ColId attrs + ; + +attrs : + '.' /*26L*/ attr_name + | attrs '.' /*26L*/ attr_name + ; + +type_name_list : + Typename + | type_name_list ',' Typename + ; + +TruncateStmt : + TRUNCATE opt_table relation_expr_list opt_restart_seqs opt_drop_behavior + ; + +opt_restart_seqs : + CONTINUE_P IDENTITY_P + | RESTART IDENTITY_P + | /*empty*/ + ; + +CommentStmt : + COMMENT ON object_type_any_name any_name IS /*7N*/ comment_text + | COMMENT ON COLUMN any_name IS /*7N*/ comment_text + | COMMENT ON object_type_name name IS /*7N*/ comment_text + | COMMENT ON TYPE_P Typename IS /*7N*/ comment_text + | COMMENT ON DOMAIN_P Typename IS /*7N*/ comment_text + | COMMENT ON AGGREGATE aggregate_with_argtypes IS /*7N*/ comment_text + | COMMENT ON FUNCTION function_with_argtypes IS /*7N*/ comment_text + | COMMENT ON OPERATOR /*16L*/ operator_with_argtypes IS /*7N*/ comment_text + | COMMENT ON CONSTRAINT name ON any_name IS /*7N*/ comment_text + | COMMENT ON CONSTRAINT name ON DOMAIN_P any_name IS /*7N*/ comment_text + | COMMENT ON object_type_name_on_any_name name ON any_name IS /*7N*/ comment_text + | COMMENT ON PROCEDURE function_with_argtypes IS /*7N*/ comment_text + | COMMENT ON ROUTINE function_with_argtypes IS /*7N*/ comment_text + | COMMENT ON TRANSFORM FOR Typename LANGUAGE name IS /*7N*/ comment_text + | COMMENT ON OPERATOR /*16L*/ CLASS any_name USING name IS /*7N*/ comment_text + | COMMENT ON OPERATOR /*16L*/ FAMILY any_name USING name IS /*7N*/ comment_text + | COMMENT ON LARGE_P OBJECT_P /*12N*/ NumericOnly IS /*7N*/ comment_text + | COMMENT ON CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ IS /*7N*/ comment_text + ; + +comment_text : + Sconst + | NULL_P + ; + +SecLabelStmt : + SECURITY LABEL opt_provider ON object_type_any_name any_name IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON COLUMN any_name IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON object_type_name name IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON TYPE_P Typename IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON DOMAIN_P Typename IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON AGGREGATE aggregate_with_argtypes IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON FUNCTION function_with_argtypes IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON LARGE_P OBJECT_P /*12N*/ NumericOnly IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON PROCEDURE function_with_argtypes IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON ROUTINE function_with_argtypes IS /*7N*/ security_label + ; + +opt_provider : + FOR NonReservedWord_or_Sconst + | /*empty*/ + ; + +security_label : + Sconst + | NULL_P + ; + +FetchStmt : + FETCH fetch_args + | MOVE fetch_args + ; + +fetch_args : + cursor_name + | from_in cursor_name + | NEXT opt_from_in cursor_name + | PRIOR opt_from_in cursor_name + | FIRST_P opt_from_in cursor_name + | LAST_P opt_from_in cursor_name + | ABSOLUTE_P SignedIconst opt_from_in cursor_name + | RELATIVE_P SignedIconst opt_from_in cursor_name + | SignedIconst opt_from_in cursor_name + | ALL opt_from_in cursor_name + | FORWARD opt_from_in cursor_name + | FORWARD SignedIconst opt_from_in cursor_name + | FORWARD ALL opt_from_in cursor_name + | BACKWARD opt_from_in cursor_name + | BACKWARD SignedIconst opt_from_in cursor_name + | BACKWARD ALL opt_from_in cursor_name + ; + +from_in : + FROM + | IN_P /*9N*/ + ; + +opt_from_in : + from_in + | /*empty*/ + ; + +GrantStmt : + GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option opt_granted_by + ; + +RevokeStmt : + REVOKE privileges ON privilege_target FROM grantee_list opt_granted_by opt_drop_behavior + | REVOKE GRANT OPTION FOR privileges ON privilege_target FROM grantee_list opt_granted_by opt_drop_behavior + ; + +privileges : + privilege_list + | ALL + | ALL PRIVILEGES + | ALL '(' /*24L*/ columnList ')' /*24L*/ + | ALL PRIVILEGES '(' /*24L*/ columnList ')' /*24L*/ + ; + +privilege_list : + privilege + | privilege_list ',' privilege + ; + +privilege : + SELECT opt_column_list + | REFERENCES opt_column_list + | CREATE opt_column_list + | ALTER SYSTEM_P + | ColId opt_column_list + ; + +parameter_name_list : + parameter_name + | parameter_name_list ',' parameter_name + ; + +parameter_name : + ColId + | parameter_name '.' /*26L*/ ColId + ; + +privilege_target : + qualified_name_list + | TABLE qualified_name_list + | SEQUENCE qualified_name_list + | FOREIGN DATA_P WRAPPER name_list + | FOREIGN SERVER name_list + | FUNCTION function_with_argtypes_list + | PROCEDURE function_with_argtypes_list + | ROUTINE function_with_argtypes_list + | DATABASE name_list + | DOMAIN_P any_name_list + | LANGUAGE name_list + | LARGE_P OBJECT_P /*12N*/ NumericOnly_list + | PARAMETER parameter_name_list + | SCHEMA name_list + | TABLESPACE name_list + | TYPE_P any_name_list + | ALL TABLES IN_P /*9N*/ SCHEMA name_list + | ALL SEQUENCES IN_P /*9N*/ SCHEMA name_list + | ALL FUNCTIONS IN_P /*9N*/ SCHEMA name_list + | ALL PROCEDURES IN_P /*9N*/ SCHEMA name_list + | ALL ROUTINES IN_P /*9N*/ SCHEMA name_list + ; + +grantee_list : + grantee + | grantee_list ',' grantee + ; + +grantee : + RoleSpec + | GROUP_P RoleSpec + ; + +opt_grant_grant_option : + WITH /*13N*/ GRANT OPTION + | /*empty*/ + ; + +GrantRoleStmt : + GRANT privilege_list TO role_list opt_granted_by + | GRANT privilege_list TO role_list WITH /*13N*/ grant_role_opt_list opt_granted_by + ; + +RevokeRoleStmt : + REVOKE privilege_list FROM role_list opt_granted_by opt_drop_behavior + | REVOKE ColId OPTION FOR privilege_list FROM role_list opt_granted_by opt_drop_behavior + ; + +grant_role_opt_list : + grant_role_opt_list ',' grant_role_opt + | grant_role_opt + ; + +grant_role_opt : + ColLabel grant_role_opt_value + ; + +grant_role_opt_value : + OPTION + | TRUE_P + | FALSE_P + ; + +opt_granted_by : + GRANTED BY RoleSpec + | /*empty*/ + ; + +AlterDefaultPrivilegesStmt : + ALTER DEFAULT PRIVILEGES DefACLOptionList DefACLAction + ; + +DefACLOptionList : + DefACLOptionList DefACLOption + | /*empty*/ + ; + +DefACLOption : + IN_P /*9N*/ SCHEMA name_list + | FOR ROLE role_list + | FOR USER role_list + ; + +DefACLAction : + GRANT privileges ON defacl_privilege_target TO grantee_list opt_grant_grant_option + | REVOKE privileges ON defacl_privilege_target FROM grantee_list opt_drop_behavior + | REVOKE GRANT OPTION FOR privileges ON defacl_privilege_target FROM grantee_list opt_drop_behavior + ; + +defacl_privilege_target : + TABLES + | FUNCTIONS + | ROUTINES + | SEQUENCES + | TYPES_P + | SCHEMAS + ; + +IndexStmt : + CREATE opt_unique INDEX opt_concurrently opt_single_name ON relation_expr access_method_clause '(' /*24L*/ index_params ')' /*24L*/ opt_include opt_unique_null_treatment opt_reloptions OptTableSpace where_clause + | CREATE opt_unique INDEX opt_concurrently IF_P NOT /*6R*/ EXISTS name ON relation_expr access_method_clause '(' /*24L*/ index_params ')' /*24L*/ opt_include opt_unique_null_treatment opt_reloptions OptTableSpace where_clause + ; + +opt_unique : + UNIQUE /*11N*/ + | /*empty*/ + ; + +access_method_clause : + USING name + | /*empty*/ + ; + +index_params : + index_elem + | index_params ',' index_elem + ; + +index_elem_options : + opt_collate opt_qualified_name opt_asc_desc opt_nulls_order + | opt_collate any_name reloptions opt_asc_desc opt_nulls_order + ; + +index_elem : + ColId index_elem_options + | func_expr_windowless index_elem_options + | '(' /*24L*/ a_expr ')' /*24L*/ index_elem_options + ; + +opt_include : + INCLUDE '(' /*24L*/ index_including_params ')' /*24L*/ + | /*empty*/ + ; + +index_including_params : + index_elem + | index_including_params ',' index_elem + ; + +opt_collate : + COLLATE /*21L*/ any_name + | /*empty*/ + ; + +opt_asc_desc : + ASC + | DESC + | /*empty*/ + ; + +opt_nulls_order : + NULLS_LA FIRST_P + | NULLS_LA LAST_P + | /*empty*/ + ; + +CreateFunctionStmt : + CREATE opt_or_replace FUNCTION func_name func_args_with_defaults RETURNS func_return opt_createfunc_opt_list opt_routine_body + | CREATE opt_or_replace FUNCTION func_name func_args_with_defaults RETURNS TABLE '(' /*24L*/ table_func_column_list ')' /*24L*/ opt_createfunc_opt_list opt_routine_body + | CREATE opt_or_replace FUNCTION func_name func_args_with_defaults opt_createfunc_opt_list opt_routine_body + | CREATE opt_or_replace PROCEDURE func_name func_args_with_defaults opt_createfunc_opt_list opt_routine_body + ; + +opt_or_replace : + OR /*4L*/ REPLACE + | /*empty*/ + ; + +func_args : + '(' /*24L*/ func_args_list ')' /*24L*/ + | '(' /*24L*/ ')' /*24L*/ + ; + +func_args_list : + func_arg + | func_args_list ',' func_arg + ; + +function_with_argtypes_list : + function_with_argtypes + | function_with_argtypes_list ',' function_with_argtypes + ; + +function_with_argtypes : + func_name func_args + | type_func_name_keyword + | ColId + | ColId indirection + ; + +func_args_with_defaults : + '(' /*24L*/ func_args_with_defaults_list ')' /*24L*/ + | '(' /*24L*/ ')' /*24L*/ + ; + +func_args_with_defaults_list : + func_arg_with_default + | func_args_with_defaults_list ',' func_arg_with_default + ; + +func_arg : + arg_class param_name func_type + | param_name arg_class func_type + | param_name func_type + | arg_class func_type + | func_type + ; + +arg_class : + IN_P /*9N*/ + | OUT_P + | INOUT + | IN_P /*9N*/ OUT_P + | VARIADIC + ; + +param_name : + type_function_name + ; + +func_return : + func_type + ; + +func_type : + Typename + | type_function_name attrs '%' /*18L*/ TYPE_P + | SETOF type_function_name attrs '%' /*18L*/ TYPE_P + ; + +func_arg_with_default : + func_arg + | func_arg DEFAULT a_expr + | func_arg '=' /*8N*/ a_expr + ; + +aggr_arg : + func_arg + ; + +aggr_args : + '(' /*24L*/ '*' /*18L*/ ')' /*24L*/ + | '(' /*24L*/ aggr_args_list ')' /*24L*/ + | '(' /*24L*/ ORDER BY aggr_args_list ')' /*24L*/ + | '(' /*24L*/ aggr_args_list ORDER BY aggr_args_list ')' /*24L*/ + ; + +aggr_args_list : + aggr_arg + | aggr_args_list ',' aggr_arg + ; + +aggregate_with_argtypes : + func_name aggr_args + ; + +aggregate_with_argtypes_list : + aggregate_with_argtypes + | aggregate_with_argtypes_list ',' aggregate_with_argtypes + ; + +opt_createfunc_opt_list : + createfunc_opt_list + | /*empty*/ + ; + +createfunc_opt_list : + createfunc_opt_item + | createfunc_opt_list createfunc_opt_item + ; + +common_func_opt_item : + CALLED ON NULL_P INPUT_P + | RETURNS NULL_P ON NULL_P INPUT_P + | STRICT_P + | IMMUTABLE + | STABLE + | VOLATILE + | EXTERNAL SECURITY DEFINER + | EXTERNAL SECURITY INVOKER + | SECURITY DEFINER + | SECURITY INVOKER + | LEAKPROOF + | NOT /*6R*/ LEAKPROOF + | COST NumericOnly + | ROWS /*15N*/ NumericOnly + | SUPPORT any_name + | FunctionSetResetClause + | PARALLEL ColId + ; + +createfunc_opt_item : + AS func_as + | LANGUAGE NonReservedWord_or_Sconst + | TRANSFORM transform_type_list + | WINDOW + | common_func_opt_item + ; + +func_as : + Sconst + | Sconst ',' Sconst + ; + +ReturnStmt : + RETURN a_expr + ; + +opt_routine_body : + ReturnStmt + | BEGIN_P ATOMIC routine_body_stmt_list END_P + | /*empty*/ + ; + +routine_body_stmt_list : + routine_body_stmt_list routine_body_stmt ';' + | /*empty*/ + ; + +routine_body_stmt : + stmt + | ReturnStmt + ; + +transform_type_list : + FOR TYPE_P Typename + | transform_type_list ',' FOR TYPE_P Typename + ; + +opt_definition : + WITH /*13N*/ definition + | /*empty*/ + ; + +table_func_column : + param_name func_type + ; + +table_func_column_list : + table_func_column + | table_func_column_list ',' table_func_column + ; + +AlterFunctionStmt : + ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict + | ALTER PROCEDURE function_with_argtypes alterfunc_opt_list opt_restrict + | ALTER ROUTINE function_with_argtypes alterfunc_opt_list opt_restrict + ; + +alterfunc_opt_list : + common_func_opt_item + | alterfunc_opt_list common_func_opt_item + ; + +opt_restrict : + RESTRICT + | /*empty*/ + ; + +RemoveFuncStmt : + DROP FUNCTION function_with_argtypes_list opt_drop_behavior + | DROP FUNCTION IF_P EXISTS function_with_argtypes_list opt_drop_behavior + | DROP PROCEDURE function_with_argtypes_list opt_drop_behavior + | DROP PROCEDURE IF_P EXISTS function_with_argtypes_list opt_drop_behavior + | DROP ROUTINE function_with_argtypes_list opt_drop_behavior + | DROP ROUTINE IF_P EXISTS function_with_argtypes_list opt_drop_behavior + ; + +RemoveAggrStmt : + DROP AGGREGATE aggregate_with_argtypes_list opt_drop_behavior + | DROP AGGREGATE IF_P EXISTS aggregate_with_argtypes_list opt_drop_behavior + ; + +RemoveOperStmt : + DROP OPERATOR /*16L*/ operator_with_argtypes_list opt_drop_behavior + | DROP OPERATOR /*16L*/ IF_P EXISTS operator_with_argtypes_list opt_drop_behavior + ; + +oper_argtypes : + '(' /*24L*/ Typename ')' /*24L*/ + | '(' /*24L*/ Typename ',' Typename ')' /*24L*/ + | '(' /*24L*/ NONE ',' Typename ')' /*24L*/ + | '(' /*24L*/ Typename ',' NONE ')' /*24L*/ + ; + +any_operator : + all_Op + | ColId '.' /*26L*/ any_operator + ; + +operator_with_argtypes_list : + operator_with_argtypes + | operator_with_argtypes_list ',' operator_with_argtypes + ; + +operator_with_argtypes : + any_operator oper_argtypes + ; + +DoStmt : + DO dostmt_opt_list + ; + +dostmt_opt_list : + dostmt_opt_item + | dostmt_opt_list dostmt_opt_item + ; + +dostmt_opt_item : + Sconst + | LANGUAGE NonReservedWord_or_Sconst + ; + +CreateCastStmt : + CREATE CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ WITH /*13N*/ FUNCTION function_with_argtypes cast_context + | CREATE CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ WITHOUT /*13N*/ FUNCTION cast_context + | CREATE CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ WITH /*13N*/ INOUT cast_context + ; + +cast_context : + AS IMPLICIT_P + | AS ASSIGNMENT + | /*empty*/ + ; + +DropCastStmt : + DROP CAST opt_if_exists '(' /*24L*/ Typename AS Typename ')' /*24L*/ opt_drop_behavior + ; + +opt_if_exists : + IF_P EXISTS + | /*empty*/ + ; + +CreateTransformStmt : + CREATE opt_or_replace TRANSFORM FOR Typename LANGUAGE name '(' /*24L*/ transform_element_list ')' /*24L*/ + ; + +transform_element_list : + FROM SQL_P WITH /*13N*/ FUNCTION function_with_argtypes ',' TO SQL_P WITH /*13N*/ FUNCTION function_with_argtypes + | TO SQL_P WITH /*13N*/ FUNCTION function_with_argtypes ',' FROM SQL_P WITH /*13N*/ FUNCTION function_with_argtypes + | FROM SQL_P WITH /*13N*/ FUNCTION function_with_argtypes + | TO SQL_P WITH /*13N*/ FUNCTION function_with_argtypes + ; + +DropTransformStmt : + DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_drop_behavior + ; + +ReindexStmt : + REINDEX opt_reindex_option_list reindex_target_relation opt_concurrently qualified_name + | REINDEX opt_reindex_option_list SCHEMA opt_concurrently name + | REINDEX opt_reindex_option_list reindex_target_all opt_concurrently opt_single_name + ; + +reindex_target_relation : + INDEX + | TABLE + ; + +reindex_target_all : + SYSTEM_P + | DATABASE + ; + +opt_reindex_option_list : + '(' /*24L*/ utility_option_list ')' /*24L*/ + | /*empty*/ + ; + +AlterTblSpcStmt : + ALTER TABLESPACE name SET /*1N*/ reloptions + | ALTER TABLESPACE name RESET reloptions + ; + +RenameStmt : + ALTER AGGREGATE aggregate_with_argtypes RENAME TO name + | ALTER COLLATION any_name RENAME TO name + | ALTER CONVERSION_P any_name RENAME TO name + | ALTER DATABASE name RENAME TO name + | ALTER DOMAIN_P any_name RENAME TO name + | ALTER DOMAIN_P any_name RENAME CONSTRAINT name TO name + | ALTER FOREIGN DATA_P WRAPPER name RENAME TO name + | ALTER FUNCTION function_with_argtypes RENAME TO name + | ALTER GROUP_P RoleId RENAME TO RoleId + | ALTER opt_procedural LANGUAGE name RENAME TO name + | ALTER OPERATOR /*16L*/ CLASS any_name USING name RENAME TO name + | ALTER OPERATOR /*16L*/ FAMILY any_name USING name RENAME TO name + | ALTER POLICY name ON qualified_name RENAME TO name + | ALTER POLICY IF_P EXISTS name ON qualified_name RENAME TO name + | ALTER PROCEDURE function_with_argtypes RENAME TO name + | ALTER PUBLICATION name RENAME TO name + | ALTER ROUTINE function_with_argtypes RENAME TO name + | ALTER SCHEMA name RENAME TO name + | ALTER SERVER name RENAME TO name + | ALTER SUBSCRIPTION name RENAME TO name + | ALTER TABLE relation_expr RENAME TO name + | ALTER TABLE IF_P EXISTS relation_expr RENAME TO name + | ALTER SEQUENCE qualified_name RENAME TO name + | ALTER SEQUENCE IF_P EXISTS qualified_name RENAME TO name + | ALTER VIEW qualified_name RENAME TO name + | ALTER VIEW IF_P EXISTS qualified_name RENAME TO name + | ALTER MATERIALIZED VIEW qualified_name RENAME TO name + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME TO name + | ALTER INDEX qualified_name RENAME TO name + | ALTER INDEX IF_P EXISTS qualified_name RENAME TO name + | ALTER FOREIGN TABLE relation_expr RENAME TO name + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME TO name + | ALTER TABLE relation_expr RENAME opt_column name TO name + | ALTER TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name + | ALTER VIEW qualified_name RENAME opt_column name TO name + | ALTER VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name + | ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name + | ALTER TABLE relation_expr RENAME CONSTRAINT name TO name + | ALTER TABLE IF_P EXISTS relation_expr RENAME CONSTRAINT name TO name + | ALTER FOREIGN TABLE relation_expr RENAME opt_column name TO name + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name + | ALTER RULE name ON qualified_name RENAME TO name + | ALTER TRIGGER name ON qualified_name RENAME TO name + | ALTER EVENT TRIGGER name RENAME TO name + | ALTER ROLE RoleId RENAME TO RoleId + | ALTER USER RoleId RENAME TO RoleId + | ALTER TABLESPACE name RENAME TO name + | ALTER STATISTICS any_name RENAME TO name + | ALTER TEXT_P SEARCH PARSER any_name RENAME TO name + | ALTER TEXT_P SEARCH DICTIONARY any_name RENAME TO name + | ALTER TEXT_P SEARCH TEMPLATE any_name RENAME TO name + | ALTER TEXT_P SEARCH CONFIGURATION any_name RENAME TO name + | ALTER TYPE_P any_name RENAME TO name + | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name opt_drop_behavior + ; + +opt_column : + COLUMN + | /*empty*/ + ; + +opt_set_data : + SET /*1N*/ DATA_P + | /*empty*/ + ; + +AlterObjectDependsStmt : + ALTER FUNCTION function_with_argtypes opt_no DEPENDS ON EXTENSION name + | ALTER PROCEDURE function_with_argtypes opt_no DEPENDS ON EXTENSION name + | ALTER ROUTINE function_with_argtypes opt_no DEPENDS ON EXTENSION name + | ALTER TRIGGER name ON qualified_name opt_no DEPENDS ON EXTENSION name + | ALTER MATERIALIZED VIEW qualified_name opt_no DEPENDS ON EXTENSION name + | ALTER INDEX qualified_name opt_no DEPENDS ON EXTENSION name + ; + +opt_no : + NO + | /*empty*/ + ; + +AlterObjectSchemaStmt : + ALTER AGGREGATE aggregate_with_argtypes SET /*1N*/ SCHEMA name + | ALTER COLLATION any_name SET /*1N*/ SCHEMA name + | ALTER CONVERSION_P any_name SET /*1N*/ SCHEMA name + | ALTER DOMAIN_P any_name SET /*1N*/ SCHEMA name + | ALTER EXTENSION name SET /*1N*/ SCHEMA name + | ALTER FUNCTION function_with_argtypes SET /*1N*/ SCHEMA name + | ALTER OPERATOR /*16L*/ operator_with_argtypes SET /*1N*/ SCHEMA name + | ALTER OPERATOR /*16L*/ CLASS any_name USING name SET /*1N*/ SCHEMA name + | ALTER OPERATOR /*16L*/ FAMILY any_name USING name SET /*1N*/ SCHEMA name + | ALTER PROCEDURE function_with_argtypes SET /*1N*/ SCHEMA name + | ALTER ROUTINE function_with_argtypes SET /*1N*/ SCHEMA name + | ALTER TABLE relation_expr SET /*1N*/ SCHEMA name + | ALTER TABLE IF_P EXISTS relation_expr SET /*1N*/ SCHEMA name + | ALTER STATISTICS any_name SET /*1N*/ SCHEMA name + | ALTER TEXT_P SEARCH PARSER any_name SET /*1N*/ SCHEMA name + | ALTER TEXT_P SEARCH DICTIONARY any_name SET /*1N*/ SCHEMA name + | ALTER TEXT_P SEARCH TEMPLATE any_name SET /*1N*/ SCHEMA name + | ALTER TEXT_P SEARCH CONFIGURATION any_name SET /*1N*/ SCHEMA name + | ALTER SEQUENCE qualified_name SET /*1N*/ SCHEMA name + | ALTER SEQUENCE IF_P EXISTS qualified_name SET /*1N*/ SCHEMA name + | ALTER VIEW qualified_name SET /*1N*/ SCHEMA name + | ALTER VIEW IF_P EXISTS qualified_name SET /*1N*/ SCHEMA name + | ALTER MATERIALIZED VIEW qualified_name SET /*1N*/ SCHEMA name + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name SET /*1N*/ SCHEMA name + | ALTER FOREIGN TABLE relation_expr SET /*1N*/ SCHEMA name + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr SET /*1N*/ SCHEMA name + | ALTER TYPE_P any_name SET /*1N*/ SCHEMA name + ; + +AlterOperatorStmt : + ALTER OPERATOR /*16L*/ operator_with_argtypes SET /*1N*/ '(' /*24L*/ operator_def_list ')' /*24L*/ + ; + +operator_def_list : + operator_def_elem + | operator_def_list ',' operator_def_elem + ; + +operator_def_elem : + ColLabel '=' /*8N*/ NONE + | ColLabel '=' /*8N*/ operator_def_arg + ; + +operator_def_arg : + func_type + | reserved_keyword + | qual_all_Op + | NumericOnly + | Sconst + ; + +AlterTypeStmt : + ALTER TYPE_P any_name SET /*1N*/ '(' /*24L*/ operator_def_list ')' /*24L*/ + ; + +AlterOwnerStmt : + ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec + | ALTER COLLATION any_name OWNER TO RoleSpec + | ALTER CONVERSION_P any_name OWNER TO RoleSpec + | ALTER DATABASE name OWNER TO RoleSpec + | ALTER DOMAIN_P any_name OWNER TO RoleSpec + | ALTER FUNCTION function_with_argtypes OWNER TO RoleSpec + | ALTER opt_procedural LANGUAGE name OWNER TO RoleSpec + | ALTER LARGE_P OBJECT_P /*12N*/ NumericOnly OWNER TO RoleSpec + | ALTER OPERATOR /*16L*/ operator_with_argtypes OWNER TO RoleSpec + | ALTER OPERATOR /*16L*/ CLASS any_name USING name OWNER TO RoleSpec + | ALTER OPERATOR /*16L*/ FAMILY any_name USING name OWNER TO RoleSpec + | ALTER PROCEDURE function_with_argtypes OWNER TO RoleSpec + | ALTER ROUTINE function_with_argtypes OWNER TO RoleSpec + | ALTER SCHEMA name OWNER TO RoleSpec + | ALTER TYPE_P any_name OWNER TO RoleSpec + | ALTER TABLESPACE name OWNER TO RoleSpec + | ALTER STATISTICS any_name OWNER TO RoleSpec + | ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO RoleSpec + | ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO RoleSpec + | ALTER FOREIGN DATA_P WRAPPER name OWNER TO RoleSpec + | ALTER SERVER name OWNER TO RoleSpec + | ALTER EVENT TRIGGER name OWNER TO RoleSpec + | ALTER PUBLICATION name OWNER TO RoleSpec + | ALTER SUBSCRIPTION name OWNER TO RoleSpec + ; + +CreatePublicationStmt : + CREATE PUBLICATION name opt_definition + | CREATE PUBLICATION name FOR ALL TABLES opt_definition + | CREATE PUBLICATION name FOR pub_obj_list opt_definition + ; + +PublicationObjSpec : + TABLE relation_expr opt_column_list OptWhereClause + | TABLES IN_P /*9N*/ SCHEMA ColId + | TABLES IN_P /*9N*/ SCHEMA CURRENT_SCHEMA + | ColId opt_column_list OptWhereClause + | ColId indirection opt_column_list OptWhereClause + | extended_relation_expr opt_column_list OptWhereClause + | CURRENT_SCHEMA + ; + +pub_obj_list : + PublicationObjSpec + | pub_obj_list ',' PublicationObjSpec + ; + +AlterPublicationStmt : + ALTER PUBLICATION name SET /*1N*/ definition + | ALTER PUBLICATION name ADD_P pub_obj_list + | ALTER PUBLICATION name SET /*1N*/ pub_obj_list + | ALTER PUBLICATION name DROP pub_obj_list + ; + +CreateSubscriptionStmt : + CREATE SUBSCRIPTION name CONNECTION Sconst PUBLICATION name_list opt_definition + ; + +AlterSubscriptionStmt : + ALTER SUBSCRIPTION name SET /*1N*/ definition + | ALTER SUBSCRIPTION name CONNECTION Sconst + | ALTER SUBSCRIPTION name REFRESH PUBLICATION opt_definition + | ALTER SUBSCRIPTION name ADD_P PUBLICATION name_list opt_definition + | ALTER SUBSCRIPTION name DROP PUBLICATION name_list opt_definition + | ALTER SUBSCRIPTION name SET /*1N*/ PUBLICATION name_list opt_definition + | ALTER SUBSCRIPTION name ENABLE_P + | ALTER SUBSCRIPTION name DISABLE_P + | ALTER SUBSCRIPTION name SKIP definition + ; + +DropSubscriptionStmt : + DROP SUBSCRIPTION name opt_drop_behavior + | DROP SUBSCRIPTION IF_P EXISTS name opt_drop_behavior + ; + +RuleStmt : + CREATE opt_or_replace RULE name AS ON event TO qualified_name where_clause DO opt_instead RuleActionList + ; + +RuleActionList : + NOTHING + | RuleActionStmt + | '(' /*24L*/ RuleActionMulti ')' /*24L*/ + ; + +RuleActionMulti : + RuleActionMulti ';' RuleActionStmtOrEmpty + | RuleActionStmtOrEmpty + ; + +RuleActionStmt : + SelectStmt + | InsertStmt + | UpdateStmt + | DeleteStmt + | NotifyStmt + ; + +RuleActionStmtOrEmpty : + RuleActionStmt + | /*empty*/ + ; + +event : + SELECT + | UPDATE + | DELETE_P + | INSERT + ; + +opt_instead : + INSTEAD + | ALSO + | /*empty*/ + ; + +NotifyStmt : + NOTIFY ColId notify_payload + ; + +notify_payload : + ',' Sconst + | /*empty*/ + ; + +ListenStmt : + LISTEN ColId + ; + +UnlistenStmt : + UNLISTEN ColId + | UNLISTEN '*' /*18L*/ + ; + +TransactionStmt : + ABORT_P opt_transaction opt_transaction_chain + | START TRANSACTION transaction_mode_list_or_empty + | COMMIT opt_transaction opt_transaction_chain + | ROLLBACK opt_transaction opt_transaction_chain + | SAVEPOINT ColId + | RELEASE SAVEPOINT ColId + | RELEASE ColId + | ROLLBACK opt_transaction TO SAVEPOINT ColId + | ROLLBACK opt_transaction TO ColId + | PREPARE TRANSACTION Sconst + | COMMIT PREPARED Sconst + | ROLLBACK PREPARED Sconst + ; + +TransactionStmtLegacy : + BEGIN_P opt_transaction transaction_mode_list_or_empty + | END_P opt_transaction opt_transaction_chain + ; + +opt_transaction : + WORK + | TRANSACTION + | /*empty*/ + ; + +transaction_mode_item : + ISOLATION LEVEL iso_level + | READ ONLY + | READ WRITE + | DEFERRABLE + | NOT /*6R*/ DEFERRABLE + ; + +transaction_mode_list : + transaction_mode_item + | transaction_mode_list ',' transaction_mode_item + | transaction_mode_list transaction_mode_item + ; + +transaction_mode_list_or_empty : + transaction_mode_list + | /*empty*/ + ; + +opt_transaction_chain : + AND /*5L*/ CHAIN + | AND /*5L*/ NO CHAIN + | /*empty*/ + ; + +ViewStmt : + CREATE OptTemp VIEW qualified_name opt_column_list opt_reloptions AS SelectStmt opt_check_option + | CREATE OR /*4L*/ REPLACE OptTemp VIEW qualified_name opt_column_list opt_reloptions AS SelectStmt opt_check_option + | CREATE OptTemp RECURSIVE VIEW qualified_name '(' /*24L*/ columnList ')' /*24L*/ opt_reloptions AS SelectStmt opt_check_option + | CREATE OR /*4L*/ REPLACE OptTemp RECURSIVE VIEW qualified_name '(' /*24L*/ columnList ')' /*24L*/ opt_reloptions AS SelectStmt opt_check_option + ; + +opt_check_option : + WITH /*13N*/ CHECK OPTION + | WITH /*13N*/ CASCADED CHECK OPTION + | WITH /*13N*/ LOCAL CHECK OPTION + | /*empty*/ + ; + +LoadStmt : + LOAD file_name + ; + +CreatedbStmt : + CREATE DATABASE name opt_with createdb_opt_list + ; + +createdb_opt_list : + createdb_opt_items + | /*empty*/ + ; + +createdb_opt_items : + createdb_opt_item + | createdb_opt_items createdb_opt_item + ; + +createdb_opt_item : + createdb_opt_name opt_equal NumericOnly + | createdb_opt_name opt_equal opt_boolean_or_string + | createdb_opt_name opt_equal DEFAULT + ; + +createdb_opt_name : + IDENT /*15N*/ + | CONNECTION LIMIT + | ENCODING + | LOCATION + | OWNER + | TABLESPACE + | TEMPLATE + ; + +opt_equal : + '=' /*8N*/ + | /*empty*/ + ; + +AlterDatabaseStmt : + ALTER DATABASE name WITH /*13N*/ createdb_opt_list + | ALTER DATABASE name createdb_opt_list + | ALTER DATABASE name SET /*1N*/ TABLESPACE name + | ALTER DATABASE name REFRESH COLLATION VERSION_P + ; + +AlterDatabaseSetStmt : + ALTER DATABASE name SetResetClause + ; + +DropdbStmt : + DROP DATABASE name + | DROP DATABASE IF_P EXISTS name + | DROP DATABASE name opt_with '(' /*24L*/ drop_option_list ')' /*24L*/ + | DROP DATABASE IF_P EXISTS name opt_with '(' /*24L*/ drop_option_list ')' /*24L*/ + ; + +drop_option_list : + drop_option + | drop_option_list ',' drop_option + ; + +drop_option : + FORCE + ; + +AlterCollationStmt : + ALTER COLLATION any_name REFRESH VERSION_P + ; + +AlterSystemStmt : + ALTER SYSTEM_P SET /*1N*/ generic_set + | ALTER SYSTEM_P RESET generic_reset + ; + +CreateDomainStmt : + CREATE DOMAIN_P any_name opt_as Typename ColQualList + ; + +AlterDomainStmt : + ALTER DOMAIN_P any_name alter_column_default + | ALTER DOMAIN_P any_name DROP NOT /*6R*/ NULL_P + | ALTER DOMAIN_P any_name SET /*1N*/ NOT /*6R*/ NULL_P + | ALTER DOMAIN_P any_name ADD_P TableConstraint + | ALTER DOMAIN_P any_name DROP CONSTRAINT name opt_drop_behavior + | ALTER DOMAIN_P any_name DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior + | ALTER DOMAIN_P any_name VALIDATE CONSTRAINT name + ; + +opt_as : + AS + | /*empty*/ + ; + +AlterTSDictionaryStmt : + ALTER TEXT_P SEARCH DICTIONARY any_name definition + ; + +AlterTSConfigurationStmt : + ALTER TEXT_P SEARCH CONFIGURATION any_name ADD_P MAPPING FOR name_list any_with any_name_list + | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list any_with any_name_list + | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING REPLACE any_name any_with any_name + | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list REPLACE any_name any_with any_name + | ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING FOR name_list + | ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING IF_P EXISTS FOR name_list + ; + +any_with : + WITH /*13N*/ + | WITH_LA + ; + +CreateConversionStmt : + CREATE opt_default CONVERSION_P any_name FOR Sconst TO Sconst FROM any_name + ; + +ClusterStmt : + CLUSTER opt_verbose qualified_name cluster_index_specification + | CLUSTER '(' /*24L*/ utility_option_list ')' /*24L*/ qualified_name cluster_index_specification + | CLUSTER opt_verbose + | CLUSTER opt_verbose name ON qualified_name + ; + +cluster_index_specification : + USING name + | /*empty*/ + ; + +VacuumStmt : + VACUUM opt_full opt_freeze opt_verbose opt_analyze opt_vacuum_relation_list + | VACUUM '(' /*24L*/ utility_option_list ')' /*24L*/ opt_vacuum_relation_list + ; + +AnalyzeStmt : + analyze_keyword opt_verbose opt_vacuum_relation_list + | analyze_keyword '(' /*24L*/ utility_option_list ')' /*24L*/ opt_vacuum_relation_list + ; + +utility_option_list : + utility_option_elem + | utility_option_list ',' utility_option_elem + ; + +analyze_keyword : + ANALYZE + | ANALYSE + ; + +utility_option_elem : + utility_option_name utility_option_arg + ; + +utility_option_name : + NonReservedWord + | analyze_keyword + | FORMAT_LA + ; + +utility_option_arg : + opt_boolean_or_string + | NumericOnly + | /*empty*/ + ; + +opt_analyze : + analyze_keyword + | /*empty*/ + ; + +opt_verbose : + VERBOSE + | /*empty*/ + ; + +opt_full : + FULL /*27L*/ + | /*empty*/ + ; + +opt_freeze : + FREEZE + | /*empty*/ + ; + +opt_name_list : + '(' /*24L*/ name_list ')' /*24L*/ + | /*empty*/ + ; + +vacuum_relation : + qualified_name opt_name_list + ; + +vacuum_relation_list : + vacuum_relation + | vacuum_relation_list ',' vacuum_relation + ; + +opt_vacuum_relation_list : + vacuum_relation_list + | /*empty*/ + ; + +ExplainStmt : + EXPLAIN ExplainableStmt + | EXPLAIN analyze_keyword opt_verbose ExplainableStmt + | EXPLAIN VERBOSE ExplainableStmt + | EXPLAIN '(' /*24L*/ utility_option_list ')' /*24L*/ ExplainableStmt + ; + +ExplainableStmt : + SelectStmt + | InsertStmt + | UpdateStmt + | DeleteStmt + | MergeStmt + | DeclareCursorStmt + | CreateAsStmt + | CreateMatViewStmt + | RefreshMatViewStmt + | ExecuteStmt + ; + +PrepareStmt : + PREPARE name prep_type_clause AS PreparableStmt + ; + +prep_type_clause : + '(' /*24L*/ type_list ')' /*24L*/ + | /*empty*/ + ; + +PreparableStmt : + SelectStmt + | InsertStmt + | UpdateStmt + | DeleteStmt + | MergeStmt + ; + +ExecuteStmt : + EXECUTE name execute_param_clause + | CREATE OptTemp TABLE create_as_target AS EXECUTE name execute_param_clause opt_with_data + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS create_as_target AS EXECUTE name execute_param_clause opt_with_data + ; + +execute_param_clause : + '(' /*24L*/ expr_list ')' /*24L*/ + | /*empty*/ + ; + +DeallocateStmt : + DEALLOCATE name + | DEALLOCATE PREPARE name + | DEALLOCATE ALL + | DEALLOCATE PREPARE ALL + ; + +InsertStmt : + opt_with_clause INSERT INTO insert_target insert_rest opt_on_conflict returning_clause + ; + +insert_target : + qualified_name + | qualified_name AS ColId + ; + +insert_rest : + SelectStmt + | OVERRIDING override_kind VALUE_P /*12N*/ SelectStmt + | '(' /*24L*/ insert_column_list ')' /*24L*/ SelectStmt + | '(' /*24L*/ insert_column_list ')' /*24L*/ OVERRIDING override_kind VALUE_P /*12N*/ SelectStmt + | DEFAULT VALUES + ; + +override_kind : + USER + | SYSTEM_P + ; + +insert_column_list : + insert_column_item + | insert_column_list ',' insert_column_item + ; + +insert_column_item : + ColId opt_indirection + ; + +opt_on_conflict : + ON CONFLICT opt_conf_expr DO UPDATE SET /*1N*/ set_clause_list where_clause + | ON CONFLICT opt_conf_expr DO NOTHING + | /*empty*/ + ; + +opt_conf_expr : + '(' /*24L*/ index_params ')' /*24L*/ where_clause + | ON CONSTRAINT name + | /*empty*/ + ; + +returning_clause : + RETURNING target_list + | /*empty*/ + ; + +DeleteStmt : + opt_with_clause DELETE_P FROM relation_expr_opt_alias using_clause where_or_current_clause returning_clause + ; + +using_clause : + USING from_list + | /*empty*/ + ; + +LockStmt : + LOCK_P opt_table relation_expr_list opt_lock opt_nowait + ; + +opt_lock : + IN_P /*9N*/ lock_type MODE + | /*empty*/ + ; + +lock_type : + ACCESS SHARE + | ROW SHARE + | ROW EXCLUSIVE + | SHARE UPDATE EXCLUSIVE + | SHARE + | SHARE ROW EXCLUSIVE + | EXCLUSIVE + | ACCESS EXCLUSIVE + ; + +opt_nowait : + NOWAIT + | /*empty*/ + ; + +opt_nowait_or_skip : + NOWAIT + | SKIP LOCKED + | /*empty*/ + ; + +UpdateStmt : + opt_with_clause UPDATE relation_expr_opt_alias SET /*1N*/ set_clause_list from_clause where_or_current_clause returning_clause + ; + +set_clause_list : + set_clause + | set_clause_list ',' set_clause + ; + +set_clause : + set_target '=' /*8N*/ a_expr + | '(' /*24L*/ set_target_list ')' /*24L*/ '=' /*8N*/ a_expr + ; + +set_target : + ColId opt_indirection + ; + +set_target_list : + set_target + | set_target_list ',' set_target + ; + +MergeStmt : + opt_with_clause MERGE INTO relation_expr_opt_alias USING table_ref ON a_expr merge_when_list + ; + +merge_when_list : + merge_when_clause + | merge_when_list merge_when_clause + ; + +merge_when_clause : + WHEN MATCHED opt_merge_when_condition THEN merge_update + | WHEN MATCHED opt_merge_when_condition THEN merge_delete + | WHEN NOT /*6R*/ MATCHED opt_merge_when_condition THEN merge_insert + | WHEN MATCHED opt_merge_when_condition THEN DO NOTHING + | WHEN NOT /*6R*/ MATCHED opt_merge_when_condition THEN DO NOTHING + ; + +opt_merge_when_condition : + AND /*5L*/ a_expr + | /*empty*/ + ; + +merge_update : + UPDATE SET /*1N*/ set_clause_list + ; + +merge_delete : + DELETE_P + ; + +merge_insert : + INSERT merge_values_clause + | INSERT OVERRIDING override_kind VALUE_P /*12N*/ merge_values_clause + | INSERT '(' /*24L*/ insert_column_list ')' /*24L*/ merge_values_clause + | INSERT '(' /*24L*/ insert_column_list ')' /*24L*/ OVERRIDING override_kind VALUE_P /*12N*/ merge_values_clause + | INSERT DEFAULT VALUES + ; + +merge_values_clause : + VALUES '(' /*24L*/ expr_list ')' /*24L*/ + ; + +DeclareCursorStmt : + DECLARE cursor_name cursor_options CURSOR opt_hold FOR SelectStmt + ; + +cursor_name : + name + ; + +cursor_options : + /*empty*/ + | cursor_options NO SCROLL + | cursor_options SCROLL + | cursor_options BINARY + | cursor_options ASENSITIVE + | cursor_options INSENSITIVE + ; + +opt_hold : + /*empty*/ + | WITH /*13N*/ HOLD + | WITHOUT /*13N*/ HOLD + ; + +SelectStmt : + select_no_parens %prec UMINUS /*22R*/ + | select_with_parens %prec UMINUS /*22R*/ + ; + +select_with_parens : + '(' /*24L*/ select_no_parens ')' /*24L*/ + | '(' /*24L*/ select_with_parens ')' /*24L*/ + ; + +select_no_parens : + simple_select + | select_clause sort_clause + | select_clause opt_sort_clause for_locking_clause opt_select_limit + | select_clause opt_sort_clause select_limit opt_for_locking_clause + | with_clause select_clause + | with_clause select_clause sort_clause + | with_clause select_clause opt_sort_clause for_locking_clause opt_select_limit + | with_clause select_clause opt_sort_clause select_limit opt_for_locking_clause + ; + +select_clause : + simple_select + | select_with_parens + ; + +simple_select : + SELECT opt_all_clause opt_target_list into_clause from_clause where_clause group_clause having_clause window_clause + | SELECT distinct_clause target_list into_clause from_clause where_clause group_clause having_clause window_clause + | values_clause + | TABLE relation_expr + | select_clause UNION /*2L*/ set_quantifier select_clause + | select_clause INTERSECT /*3L*/ set_quantifier select_clause + | select_clause EXCEPT /*2L*/ set_quantifier select_clause + ; + +with_clause : + WITH /*13N*/ cte_list + | WITH_LA cte_list + | WITH /*13N*/ RECURSIVE cte_list + ; + +cte_list : + common_table_expr + | cte_list ',' common_table_expr + ; + +common_table_expr : + name opt_name_list AS opt_materialized '(' /*24L*/ PreparableStmt ')' /*24L*/ opt_search_clause opt_cycle_clause + ; + +opt_materialized : + MATERIALIZED + | NOT /*6R*/ MATERIALIZED + | /*empty*/ + ; + +opt_search_clause : + SEARCH DEPTH FIRST_P BY columnList SET /*1N*/ ColId + | SEARCH BREADTH FIRST_P BY columnList SET /*1N*/ ColId + | /*empty*/ + ; + +opt_cycle_clause : + CYCLE columnList SET /*1N*/ ColId TO AexprConst DEFAULT AexprConst USING ColId + | CYCLE columnList SET /*1N*/ ColId USING ColId + | /*empty*/ + ; + +opt_with_clause : + with_clause + | /*empty*/ + ; + +into_clause : + INTO OptTempTableName + | /*empty*/ + ; + +OptTempTableName : + TEMPORARY opt_table qualified_name + | TEMP opt_table qualified_name + | LOCAL TEMPORARY opt_table qualified_name + | LOCAL TEMP opt_table qualified_name + | GLOBAL TEMPORARY opt_table qualified_name + | GLOBAL TEMP opt_table qualified_name + | UNLOGGED opt_table qualified_name + | TABLE qualified_name + | qualified_name + ; + +opt_table : + TABLE + | /*empty*/ + ; + +set_quantifier : + ALL + | DISTINCT + | /*empty*/ + ; + +distinct_clause : + DISTINCT + | DISTINCT ON '(' /*24L*/ expr_list ')' /*24L*/ + ; + +opt_all_clause : + ALL + | /*empty*/ + ; + +opt_distinct_clause : + distinct_clause + | opt_all_clause + ; + +opt_sort_clause : + sort_clause + | /*empty*/ + ; + +sort_clause : + ORDER BY sortby_list + ; + +sortby_list : + sortby + | sortby_list ',' sortby + ; + +sortby : + a_expr USING qual_all_Op opt_nulls_order + | a_expr opt_asc_desc opt_nulls_order + ; + +select_limit : + limit_clause offset_clause + | offset_clause limit_clause + | limit_clause + | offset_clause + ; + +opt_select_limit : + select_limit + | /*empty*/ + ; + +limit_clause : + LIMIT select_limit_value + | LIMIT select_limit_value ',' select_offset_value + | FETCH first_or_next select_fetch_first_value row_or_rows ONLY + | FETCH first_or_next select_fetch_first_value row_or_rows WITH /*13N*/ TIES + | FETCH first_or_next row_or_rows ONLY + | FETCH first_or_next row_or_rows WITH /*13N*/ TIES + ; + +offset_clause : + OFFSET select_offset_value + | OFFSET select_fetch_first_value row_or_rows + ; + +select_limit_value : + a_expr + | ALL + ; + +select_offset_value : + a_expr + ; + +select_fetch_first_value : + c_expr + | '+' /*17L*/ I_or_F_const + | '-' /*17L*/ I_or_F_const + ; + +I_or_F_const : + Iconst + | FCONST + ; + +row_or_rows : + ROW + | ROWS /*15N*/ + ; + +first_or_next : + FIRST_P + | NEXT + ; + +group_clause : + GROUP_P BY set_quantifier group_by_list + | /*empty*/ + ; + +group_by_list : + group_by_item + | group_by_list ',' group_by_item + ; + +group_by_item : + a_expr + | empty_grouping_set + | cube_clause + | rollup_clause + | grouping_sets_clause + ; + +empty_grouping_set : + '(' /*24L*/ ')' /*24L*/ + ; + +rollup_clause : + ROLLUP /*15N*/ '(' /*24L*/ expr_list ')' /*24L*/ + ; + +cube_clause : + CUBE /*15N*/ '(' /*24L*/ expr_list ')' /*24L*/ + ; + +grouping_sets_clause : + GROUPING SETS '(' /*24L*/ group_by_list ')' /*24L*/ + ; + +having_clause : + HAVING a_expr + | /*empty*/ + ; + +for_locking_clause : + for_locking_items + | FOR READ ONLY + ; + +opt_for_locking_clause : + for_locking_clause + | /*empty*/ + ; + +for_locking_items : + for_locking_item + | for_locking_items for_locking_item + ; + +for_locking_item : + for_locking_strength locked_rels_list opt_nowait_or_skip + ; + +for_locking_strength : + FOR UPDATE + | FOR NO KEY UPDATE + | FOR SHARE + | FOR KEY SHARE + ; + +locked_rels_list : + OF qualified_name_list + | /*empty*/ + ; + +values_clause : + VALUES '(' /*24L*/ expr_list ')' /*24L*/ + | values_clause ',' '(' /*24L*/ expr_list ')' /*24L*/ + ; + +from_clause : + FROM from_list + | /*empty*/ + ; + +from_list : + table_ref + | from_list ',' table_ref + ; + +table_ref : + relation_expr opt_alias_clause + | relation_expr opt_alias_clause tablesample_clause + | func_table func_alias_clause + | LATERAL_P func_table func_alias_clause + | xmltable opt_alias_clause + | LATERAL_P xmltable opt_alias_clause + | select_with_parens opt_alias_clause + | LATERAL_P select_with_parens opt_alias_clause + | joined_table + | '(' /*24L*/ joined_table ')' /*24L*/ alias_clause + ; + +joined_table : + '(' /*24L*/ joined_table ')' /*24L*/ + | table_ref CROSS /*27L*/ JOIN /*27L*/ table_ref + | table_ref join_type JOIN /*27L*/ table_ref join_qual + | table_ref JOIN /*27L*/ table_ref join_qual + | table_ref NATURAL /*27L*/ join_type JOIN /*27L*/ table_ref + | table_ref NATURAL /*27L*/ JOIN /*27L*/ table_ref + ; + +alias_clause : + AS ColId '(' /*24L*/ name_list ')' /*24L*/ + | AS ColId + | ColId '(' /*24L*/ name_list ')' /*24L*/ + | ColId + ; + +opt_alias_clause : + alias_clause + | /*empty*/ + ; + +opt_alias_clause_for_join_using : + AS ColId + | /*empty*/ + ; + +func_alias_clause : + alias_clause + | AS '(' /*24L*/ TableFuncElementList ')' /*24L*/ + | AS ColId '(' /*24L*/ TableFuncElementList ')' /*24L*/ + | ColId '(' /*24L*/ TableFuncElementList ')' /*24L*/ + | /*empty*/ + ; + +join_type : + FULL /*27L*/ opt_outer + | LEFT /*27L*/ opt_outer + | RIGHT /*27L*/ opt_outer + | INNER_P /*27L*/ + ; + +opt_outer : + OUTER_P + | /*empty*/ + ; + +join_qual : + USING '(' /*24L*/ name_list ')' /*24L*/ opt_alias_clause_for_join_using + | ON a_expr + ; + +relation_expr : + qualified_name + | extended_relation_expr + ; + +extended_relation_expr : + qualified_name '*' /*18L*/ + | ONLY qualified_name + | ONLY '(' /*24L*/ qualified_name ')' /*24L*/ + ; + +relation_expr_list : + relation_expr + | relation_expr_list ',' relation_expr + ; + +relation_expr_opt_alias : + relation_expr %prec UMINUS /*22R*/ + | relation_expr ColId + | relation_expr AS ColId + ; + +tablesample_clause : + TABLESAMPLE func_name '(' /*24L*/ expr_list ')' /*24L*/ opt_repeatable_clause + ; + +opt_repeatable_clause : + REPEATABLE '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +func_table : + func_expr_windowless opt_ordinality + | ROWS /*15N*/ FROM '(' /*24L*/ rowsfrom_list ')' /*24L*/ opt_ordinality + ; + +rowsfrom_item : + func_expr_windowless opt_col_def_list + ; + +rowsfrom_list : + rowsfrom_item + | rowsfrom_list ',' rowsfrom_item + ; + +opt_col_def_list : + AS '(' /*24L*/ TableFuncElementList ')' /*24L*/ + | /*empty*/ + ; + +opt_ordinality : + WITH_LA ORDINALITY + | /*empty*/ + ; + +where_clause : + WHERE a_expr + | /*empty*/ + ; + +where_or_current_clause : + WHERE a_expr + | WHERE CURRENT_P OF cursor_name + | /*empty*/ + ; + +OptTableFuncElementList : + TableFuncElementList + | /*empty*/ + ; + +TableFuncElementList : + TableFuncElement + | TableFuncElementList ',' TableFuncElement + ; + +TableFuncElement : + ColId Typename opt_collate_clause + ; + +xmltable : + XMLTABLE '(' /*24L*/ c_expr xmlexists_argument COLUMNS xmltable_column_list ')' /*24L*/ + | XMLTABLE '(' /*24L*/ XMLNAMESPACES '(' /*24L*/ xml_namespace_list ')' /*24L*/ ',' c_expr xmlexists_argument COLUMNS xmltable_column_list ')' /*24L*/ + ; + +xmltable_column_list : + xmltable_column_el + | xmltable_column_list ',' xmltable_column_el + ; + +xmltable_column_el : + ColId Typename + | ColId Typename xmltable_column_option_list + | ColId FOR ORDINALITY + ; + +xmltable_column_option_list : + xmltable_column_option_el + | xmltable_column_option_list xmltable_column_option_el + ; + +xmltable_column_option_el : + IDENT /*15N*/ b_expr + | DEFAULT b_expr + | NOT /*6R*/ NULL_P + | NULL_P + ; + +xml_namespace_list : + xml_namespace_el + | xml_namespace_list ',' xml_namespace_el + ; + +xml_namespace_el : + b_expr AS ColLabel + | DEFAULT b_expr + ; + +Typename : + SimpleTypename opt_array_bounds + | SETOF SimpleTypename opt_array_bounds + | SimpleTypename ARRAY '[' /*23L*/ Iconst ']' /*23L*/ + | SETOF SimpleTypename ARRAY '[' /*23L*/ Iconst ']' /*23L*/ + | SimpleTypename ARRAY + | SETOF SimpleTypename ARRAY + ; + +opt_array_bounds : + opt_array_bounds '[' /*23L*/ ']' /*23L*/ + | opt_array_bounds '[' /*23L*/ Iconst ']' /*23L*/ + | /*empty*/ + ; + +SimpleTypename : + GenericType + | Numeric + | Bit + | Character + | ConstDatetime + | ConstInterval opt_interval + | ConstInterval '(' /*24L*/ Iconst ')' /*24L*/ + ; + +ConstTypename : + Numeric + | ConstBit + | ConstCharacter + | ConstDatetime + ; + +GenericType : + type_function_name opt_type_modifiers + | type_function_name attrs opt_type_modifiers + ; + +opt_type_modifiers : + '(' /*24L*/ expr_list ')' /*24L*/ + | /*empty*/ + ; + +Numeric : + INT_P + | INTEGER + | SMALLINT + | BIGINT + | REAL + | FLOAT_P opt_float + | DOUBLE_P PRECISION + | DECIMAL_P opt_type_modifiers + | DEC opt_type_modifiers + | NUMERIC opt_type_modifiers + | BOOLEAN_P + ; + +opt_float : + '(' /*24L*/ Iconst ')' /*24L*/ + | /*empty*/ + ; + +Bit : + BitWithLength + | BitWithoutLength + ; + +ConstBit : + BitWithLength + | BitWithoutLength + ; + +BitWithLength : + BIT opt_varying '(' /*24L*/ expr_list ')' /*24L*/ + ; + +BitWithoutLength : + BIT opt_varying + ; + +Character : + CharacterWithLength + | CharacterWithoutLength + ; + +ConstCharacter : + CharacterWithLength + | CharacterWithoutLength + ; + +CharacterWithLength : + character '(' /*24L*/ Iconst ')' /*24L*/ + ; + +CharacterWithoutLength : + character + ; + +character : + CHARACTER opt_varying + | CHAR_P opt_varying + | VARCHAR + | NATIONAL CHARACTER opt_varying + | NATIONAL CHAR_P opt_varying + | NCHAR opt_varying + ; + +opt_varying : + VARYING + | /*empty*/ + ; + +ConstDatetime : + TIMESTAMP '(' /*24L*/ Iconst ')' /*24L*/ opt_timezone + | TIMESTAMP opt_timezone + | TIME '(' /*24L*/ Iconst ')' /*24L*/ opt_timezone + | TIME opt_timezone + ; + +ConstInterval : + INTERVAL + ; + +opt_timezone : + WITH_LA TIME ZONE + | WITHOUT_LA TIME ZONE + | /*empty*/ + ; + +opt_interval : + YEAR_P + | MONTH_P + | DAY_P + | HOUR_P + | MINUTE_P + | interval_second + | YEAR_P TO MONTH_P + | DAY_P TO HOUR_P + | DAY_P TO MINUTE_P + | DAY_P TO interval_second + | HOUR_P TO MINUTE_P + | HOUR_P TO interval_second + | MINUTE_P TO interval_second + | /*empty*/ + ; + +interval_second : + SECOND_P + | SECOND_P '(' /*24L*/ Iconst ')' /*24L*/ + ; + +a_expr : + c_expr + | a_expr TYPECAST /*25L*/ Typename + | a_expr COLLATE /*21L*/ any_name + | a_expr AT /*20L*/ TIME ZONE a_expr %prec AT /*20L*/ + | '+' /*17L*/ a_expr %prec UMINUS /*22R*/ + | '-' /*17L*/ a_expr %prec UMINUS /*22R*/ + | a_expr '+' /*17L*/ a_expr + | a_expr '-' /*17L*/ a_expr + | a_expr '*' /*18L*/ a_expr + | a_expr '/' /*18L*/ a_expr + | a_expr '%' /*18L*/ a_expr + | a_expr '^' /*19L*/ a_expr + | a_expr '<' /*8N*/ a_expr + | a_expr '>' /*8N*/ a_expr + | a_expr '=' /*8N*/ a_expr + | a_expr LESS_EQUALS /*8N*/ a_expr + | a_expr GREATER_EQUALS /*8N*/ a_expr + | a_expr NOT_EQUALS /*8N*/ a_expr + | a_expr qual_Op a_expr %prec Op /*16L*/ + | qual_Op a_expr %prec Op /*16L*/ + | a_expr AND /*5L*/ a_expr + | a_expr OR /*4L*/ a_expr + | NOT /*6R*/ a_expr + | NOT_LA /*9N*/ a_expr %prec NOT /*6R*/ + | a_expr LIKE /*9N*/ a_expr + | a_expr LIKE /*9N*/ a_expr ESCAPE /*10N*/ a_expr %prec LIKE /*9N*/ + | a_expr NOT_LA /*9N*/ LIKE /*9N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr NOT_LA /*9N*/ LIKE /*9N*/ a_expr ESCAPE /*10N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr ILIKE /*9N*/ a_expr + | a_expr ILIKE /*9N*/ a_expr ESCAPE /*10N*/ a_expr %prec ILIKE /*9N*/ + | a_expr NOT_LA /*9N*/ ILIKE /*9N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr NOT_LA /*9N*/ ILIKE /*9N*/ a_expr ESCAPE /*10N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr SIMILAR /*9N*/ TO a_expr %prec SIMILAR /*9N*/ + | a_expr SIMILAR /*9N*/ TO a_expr ESCAPE /*10N*/ a_expr %prec SIMILAR /*9N*/ + | a_expr NOT_LA /*9N*/ SIMILAR /*9N*/ TO a_expr %prec NOT_LA /*9N*/ + | a_expr NOT_LA /*9N*/ SIMILAR /*9N*/ TO a_expr ESCAPE /*10N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr IS /*7N*/ NULL_P %prec IS /*7N*/ + | a_expr ISNULL /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ NULL_P %prec IS /*7N*/ + | a_expr NOTNULL /*7N*/ + | row OVERLAPS row + | a_expr IS /*7N*/ TRUE_P %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ TRUE_P %prec IS /*7N*/ + | a_expr IS /*7N*/ FALSE_P %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ FALSE_P %prec IS /*7N*/ + | a_expr IS /*7N*/ UNKNOWN %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ UNKNOWN %prec IS /*7N*/ + | a_expr IS /*7N*/ DISTINCT FROM a_expr %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ DISTINCT FROM a_expr %prec IS /*7N*/ + | a_expr BETWEEN /*9N*/ opt_asymmetric b_expr AND /*5L*/ a_expr %prec BETWEEN /*9N*/ + | a_expr NOT_LA /*9N*/ BETWEEN /*9N*/ opt_asymmetric b_expr AND /*5L*/ a_expr %prec NOT_LA /*9N*/ + | a_expr BETWEEN /*9N*/ SYMMETRIC b_expr AND /*5L*/ a_expr %prec BETWEEN /*9N*/ + | a_expr NOT_LA /*9N*/ BETWEEN /*9N*/ SYMMETRIC b_expr AND /*5L*/ a_expr %prec NOT_LA /*9N*/ + | a_expr IN_P /*9N*/ in_expr + | a_expr NOT_LA /*9N*/ IN_P /*9N*/ in_expr %prec NOT_LA /*9N*/ + | a_expr subquery_Op sub_type select_with_parens %prec Op /*16L*/ + | a_expr subquery_Op sub_type '(' /*24L*/ a_expr ')' /*24L*/ %prec Op /*16L*/ + | UNIQUE /*11N*/ opt_unique_null_treatment select_with_parens + | a_expr IS /*7N*/ DOCUMENT_P %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ DOCUMENT_P %prec IS /*7N*/ + | a_expr IS /*7N*/ NORMALIZED %prec IS /*7N*/ + | a_expr IS /*7N*/ unicode_normal_form NORMALIZED %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ NORMALIZED %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ unicode_normal_form NORMALIZED %prec IS /*7N*/ + | a_expr IS /*7N*/ json_predicate_type_constraint json_key_uniqueness_constraint_opt %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ json_predicate_type_constraint json_key_uniqueness_constraint_opt %prec IS /*7N*/ + | DEFAULT + ; + +b_expr : + c_expr + | b_expr TYPECAST /*25L*/ Typename + | '+' /*17L*/ b_expr %prec UMINUS /*22R*/ + | '-' /*17L*/ b_expr %prec UMINUS /*22R*/ + | b_expr '+' /*17L*/ b_expr + | b_expr '-' /*17L*/ b_expr + | b_expr '*' /*18L*/ b_expr + | b_expr '/' /*18L*/ b_expr + | b_expr '%' /*18L*/ b_expr + | b_expr '^' /*19L*/ b_expr + | b_expr '<' /*8N*/ b_expr + | b_expr '>' /*8N*/ b_expr + | b_expr '=' /*8N*/ b_expr + | b_expr LESS_EQUALS /*8N*/ b_expr + | b_expr GREATER_EQUALS /*8N*/ b_expr + | b_expr NOT_EQUALS /*8N*/ b_expr + | b_expr qual_Op b_expr %prec Op /*16L*/ + | qual_Op b_expr %prec Op /*16L*/ + | b_expr IS /*7N*/ DISTINCT FROM b_expr %prec IS /*7N*/ + | b_expr IS /*7N*/ NOT /*6R*/ DISTINCT FROM b_expr %prec IS /*7N*/ + | b_expr IS /*7N*/ DOCUMENT_P %prec IS /*7N*/ + | b_expr IS /*7N*/ NOT /*6R*/ DOCUMENT_P %prec IS /*7N*/ + ; + +c_expr : + columnref + | AexprConst + | PARAM opt_indirection + | '(' /*24L*/ a_expr ')' /*24L*/ opt_indirection + | case_expr + | func_expr + | select_with_parens %prec UMINUS /*22R*/ + | select_with_parens indirection + | EXISTS select_with_parens + | ARRAY select_with_parens + | ARRAY array_expr + | explicit_row + | implicit_row + | GROUPING '(' /*24L*/ expr_list ')' /*24L*/ + ; + +func_application : + func_name '(' /*24L*/ ')' /*24L*/ + | func_name '(' /*24L*/ func_arg_list opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ VARIADIC func_arg_expr opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ ALL func_arg_list opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ DISTINCT func_arg_list opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ '*' /*18L*/ ')' /*24L*/ + ; + +func_expr : + func_application within_group_clause filter_clause over_clause + | json_aggregate_func filter_clause over_clause + | func_expr_common_subexpr + ; + +func_expr_windowless : + func_application + | func_expr_common_subexpr + | json_aggregate_func + ; + +func_expr_common_subexpr : + COLLATION FOR '(' /*24L*/ a_expr ')' /*24L*/ + | CURRENT_DATE + | CURRENT_TIME + | CURRENT_TIME '(' /*24L*/ Iconst ')' /*24L*/ + | CURRENT_TIMESTAMP + | CURRENT_TIMESTAMP '(' /*24L*/ Iconst ')' /*24L*/ + | LOCALTIME + | LOCALTIME '(' /*24L*/ Iconst ')' /*24L*/ + | LOCALTIMESTAMP + | LOCALTIMESTAMP '(' /*24L*/ Iconst ')' /*24L*/ + | CURRENT_ROLE + | CURRENT_USER + | SESSION_USER + | SYSTEM_USER + | USER + | CURRENT_CATALOG + | CURRENT_SCHEMA + | CAST '(' /*24L*/ a_expr AS Typename ')' /*24L*/ + | EXTRACT '(' /*24L*/ extract_list ')' /*24L*/ + | NORMALIZE '(' /*24L*/ a_expr ')' /*24L*/ + | NORMALIZE '(' /*24L*/ a_expr ',' unicode_normal_form ')' /*24L*/ + | OVERLAY '(' /*24L*/ overlay_list ')' /*24L*/ + | OVERLAY '(' /*24L*/ func_arg_list_opt ')' /*24L*/ + | POSITION '(' /*24L*/ position_list ')' /*24L*/ + | SUBSTRING '(' /*24L*/ substr_list ')' /*24L*/ + | SUBSTRING '(' /*24L*/ func_arg_list_opt ')' /*24L*/ + | TREAT '(' /*24L*/ a_expr AS Typename ')' /*24L*/ + | TRIM '(' /*24L*/ BOTH trim_list ')' /*24L*/ + | TRIM '(' /*24L*/ LEADING trim_list ')' /*24L*/ + | TRIM '(' /*24L*/ TRAILING trim_list ')' /*24L*/ + | TRIM '(' /*24L*/ trim_list ')' /*24L*/ + | NULLIF '(' /*24L*/ a_expr ',' a_expr ')' /*24L*/ + | COALESCE '(' /*24L*/ expr_list ')' /*24L*/ + | GREATEST '(' /*24L*/ expr_list ')' /*24L*/ + | LEAST '(' /*24L*/ expr_list ')' /*24L*/ + | XMLCONCAT '(' /*24L*/ expr_list ')' /*24L*/ + | XMLELEMENT '(' /*24L*/ NAME_P ColLabel ')' /*24L*/ + | XMLELEMENT '(' /*24L*/ NAME_P ColLabel ',' xml_attributes ')' /*24L*/ + | XMLELEMENT '(' /*24L*/ NAME_P ColLabel ',' expr_list ')' /*24L*/ + | XMLELEMENT '(' /*24L*/ NAME_P ColLabel ',' xml_attributes ',' expr_list ')' /*24L*/ + | XMLEXISTS '(' /*24L*/ c_expr xmlexists_argument ')' /*24L*/ + | XMLFOREST '(' /*24L*/ xml_attribute_list ')' /*24L*/ + | XMLPARSE '(' /*24L*/ document_or_content a_expr xml_whitespace_option ')' /*24L*/ + | XMLPI '(' /*24L*/ NAME_P ColLabel ')' /*24L*/ + | XMLPI '(' /*24L*/ NAME_P ColLabel ',' a_expr ')' /*24L*/ + | XMLROOT '(' /*24L*/ a_expr ',' xml_root_version opt_xml_root_standalone ')' /*24L*/ + | XMLSERIALIZE '(' /*24L*/ document_or_content a_expr AS SimpleTypename xml_indent_option ')' /*24L*/ + | JSON_OBJECT '(' /*24L*/ func_arg_list ')' /*24L*/ + | JSON_OBJECT '(' /*24L*/ json_name_and_value_list json_object_constructor_null_clause_opt json_key_uniqueness_constraint_opt json_output_clause_opt ')' /*24L*/ + | JSON_OBJECT '(' /*24L*/ json_output_clause_opt ')' /*24L*/ + | JSON_ARRAY '(' /*24L*/ json_value_expr_list json_array_constructor_null_clause_opt json_output_clause_opt ')' /*24L*/ + | JSON_ARRAY '(' /*24L*/ select_no_parens json_format_clause_opt json_output_clause_opt ')' /*24L*/ + | JSON_ARRAY '(' /*24L*/ json_output_clause_opt ')' /*24L*/ + ; + +xml_root_version : + VERSION_P a_expr + | VERSION_P NO VALUE_P /*12N*/ + ; + +opt_xml_root_standalone : + ',' STANDALONE_P YES_P + | ',' STANDALONE_P NO + | ',' STANDALONE_P NO VALUE_P /*12N*/ + | /*empty*/ + ; + +xml_attributes : + XMLATTRIBUTES '(' /*24L*/ xml_attribute_list ')' /*24L*/ + ; + +xml_attribute_list : + xml_attribute_el + | xml_attribute_list ',' xml_attribute_el + ; + +xml_attribute_el : + a_expr AS ColLabel + | a_expr + ; + +document_or_content : + DOCUMENT_P + | CONTENT_P + ; + +xml_indent_option : + INDENT + | NO INDENT + | /*empty*/ + ; + +xml_whitespace_option : + PRESERVE WHITESPACE_P + | STRIP_P WHITESPACE_P + | /*empty*/ + ; + +xmlexists_argument : + PASSING c_expr + | PASSING c_expr xml_passing_mech + | PASSING xml_passing_mech c_expr + | PASSING xml_passing_mech c_expr xml_passing_mech + ; + +xml_passing_mech : + BY REF_P + | BY VALUE_P /*12N*/ + ; + +within_group_clause : + WITHIN GROUP_P '(' /*24L*/ sort_clause ')' /*24L*/ + | /*empty*/ + ; + +filter_clause : + FILTER '(' /*24L*/ WHERE a_expr ')' /*24L*/ + | /*empty*/ + ; + +window_clause : + WINDOW window_definition_list + | /*empty*/ + ; + +window_definition_list : + window_definition + | window_definition_list ',' window_definition + ; + +window_definition : + ColId AS window_specification + ; + +over_clause : + OVER window_specification + | OVER ColId + | /*empty*/ + ; + +window_specification : + '(' /*24L*/ opt_existing_window_name opt_partition_clause opt_sort_clause opt_frame_clause ')' /*24L*/ + ; + +opt_existing_window_name : + ColId + | %prec Op /*16L*/ /*empty*/ + ; + +opt_partition_clause : + PARTITION /*15N*/ BY expr_list + | /*empty*/ + ; + +opt_frame_clause : + RANGE /*15N*/ frame_extent opt_window_exclusion_clause + | ROWS /*15N*/ frame_extent opt_window_exclusion_clause + | GROUPS /*15N*/ frame_extent opt_window_exclusion_clause + | /*empty*/ + ; + +frame_extent : + frame_bound + | BETWEEN /*9N*/ frame_bound AND /*5L*/ frame_bound + ; + +frame_bound : + UNBOUNDED /*14N*/ PRECEDING /*15N*/ + | UNBOUNDED /*14N*/ FOLLOWING /*15N*/ + | CURRENT_P ROW + | a_expr PRECEDING /*15N*/ + | a_expr FOLLOWING /*15N*/ + ; + +opt_window_exclusion_clause : + EXCLUDE CURRENT_P ROW + | EXCLUDE GROUP_P + | EXCLUDE TIES + | EXCLUDE NO OTHERS + | /*empty*/ + ; + +row : + ROW '(' /*24L*/ expr_list ')' /*24L*/ + | ROW '(' /*24L*/ ')' /*24L*/ + | '(' /*24L*/ expr_list ',' a_expr ')' /*24L*/ + ; + +explicit_row : + ROW '(' /*24L*/ expr_list ')' /*24L*/ + | ROW '(' /*24L*/ ')' /*24L*/ + ; + +implicit_row : + '(' /*24L*/ expr_list ',' a_expr ')' /*24L*/ + ; + +sub_type : + ANY + | SOME + | ALL + ; + +all_Op : + Op /*16L*/ + | MathOp + ; + +MathOp : + '+' /*17L*/ + | '-' /*17L*/ + | '*' /*18L*/ + | '/' /*18L*/ + | '%' /*18L*/ + | '^' /*19L*/ + | '<' /*8N*/ + | '>' /*8N*/ + | '=' /*8N*/ + | LESS_EQUALS /*8N*/ + | GREATER_EQUALS /*8N*/ + | NOT_EQUALS /*8N*/ + ; + +qual_Op : + Op /*16L*/ + | OPERATOR /*16L*/ '(' /*24L*/ any_operator ')' /*24L*/ + ; + +qual_all_Op : + all_Op + | OPERATOR /*16L*/ '(' /*24L*/ any_operator ')' /*24L*/ + ; + +subquery_Op : + all_Op + | OPERATOR /*16L*/ '(' /*24L*/ any_operator ')' /*24L*/ + | LIKE /*9N*/ + | NOT_LA /*9N*/ LIKE /*9N*/ + | ILIKE /*9N*/ + | NOT_LA /*9N*/ ILIKE /*9N*/ + ; + +expr_list : + a_expr + | expr_list ',' a_expr + ; + +func_arg_list : + func_arg_expr + | func_arg_list ',' func_arg_expr + ; + +func_arg_expr : + a_expr + | param_name COLON_EQUALS a_expr + | param_name EQUALS_GREATER a_expr + ; + +func_arg_list_opt : + func_arg_list + | /*empty*/ + ; + +type_list : + Typename + | type_list ',' Typename + ; + +array_expr : + '[' /*23L*/ expr_list ']' /*23L*/ + | '[' /*23L*/ array_expr_list ']' /*23L*/ + | '[' /*23L*/ ']' /*23L*/ + ; + +array_expr_list : + array_expr + | array_expr_list ',' array_expr + ; + +extract_list : + extract_arg FROM a_expr + ; + +extract_arg : + IDENT /*15N*/ + | YEAR_P + | MONTH_P + | DAY_P + | HOUR_P + | MINUTE_P + | SECOND_P + | Sconst + ; + +unicode_normal_form : + NFC + | NFD + | NFKC + | NFKD + ; + +overlay_list : + a_expr PLACING a_expr FROM a_expr FOR a_expr + | a_expr PLACING a_expr FROM a_expr + ; + +position_list : + b_expr IN_P /*9N*/ b_expr + ; + +substr_list : + a_expr FROM a_expr FOR a_expr + | a_expr FOR a_expr FROM a_expr + | a_expr FROM a_expr + | a_expr FOR a_expr + | a_expr SIMILAR /*9N*/ a_expr ESCAPE /*10N*/ a_expr + ; + +trim_list : + a_expr FROM expr_list + | FROM expr_list + | expr_list + ; + +in_expr : + select_with_parens + | '(' /*24L*/ expr_list ')' /*24L*/ + ; + +case_expr : + CASE case_arg when_clause_list case_default END_P + ; + +when_clause_list : + when_clause + | when_clause_list when_clause + ; + +when_clause : + WHEN a_expr THEN a_expr + ; + +case_default : + ELSE a_expr + | /*empty*/ + ; + +case_arg : + a_expr + | /*empty*/ + ; + +columnref : + ColId + | ColId indirection + ; + +indirection_el : + '.' /*26L*/ attr_name + | '.' /*26L*/ '*' /*18L*/ + | '[' /*23L*/ a_expr ']' /*23L*/ + | '[' /*23L*/ opt_slice_bound ':' opt_slice_bound ']' /*23L*/ + ; + +opt_slice_bound : + a_expr + | /*empty*/ + ; + +indirection : + indirection_el + | indirection indirection_el + ; + +opt_indirection : + /*empty*/ + | opt_indirection indirection_el + ; + +opt_asymmetric : + ASYMMETRIC + | /*empty*/ + ; + +json_value_expr : + a_expr json_format_clause_opt + ; + +json_format_clause_opt : + FORMAT_LA JSON /*11N*/ json_encoding_clause_opt + | /*empty*/ + ; + +json_encoding_clause_opt : + ENCODING name + | /*empty*/ + ; + +json_output_clause_opt : + RETURNING Typename json_format_clause_opt + | /*empty*/ + ; + +json_predicate_type_constraint : + JSON /*11N*/ + | JSON /*11N*/ VALUE_P /*12N*/ + | JSON /*11N*/ ARRAY + | JSON /*11N*/ OBJECT_P /*12N*/ + | JSON /*11N*/ SCALAR /*12N*/ + ; + +json_key_uniqueness_constraint_opt : + WITH /*13N*/ UNIQUE /*11N*/ KEYS /*12N*/ + | WITH /*13N*/ UNIQUE /*11N*/ + | WITHOUT /*13N*/ UNIQUE /*11N*/ KEYS /*12N*/ + | WITHOUT /*13N*/ UNIQUE /*11N*/ + | %prec KEYS /*12N*/ /*empty*/ + ; + +json_name_and_value_list : + json_name_and_value + | json_name_and_value_list ',' json_name_and_value + ; + +json_name_and_value : + c_expr VALUE_P /*12N*/ json_value_expr + | a_expr ':' json_value_expr + ; + +json_object_constructor_null_clause_opt : + NULL_P ON NULL_P + | ABSENT ON NULL_P + | /*empty*/ + ; + +json_array_constructor_null_clause_opt : + NULL_P ON NULL_P + | ABSENT ON NULL_P + | /*empty*/ + ; + +json_value_expr_list : + json_value_expr + | json_value_expr_list ',' json_value_expr + ; + +json_aggregate_func : + JSON_OBJECTAGG '(' /*24L*/ json_name_and_value json_object_constructor_null_clause_opt json_key_uniqueness_constraint_opt json_output_clause_opt ')' /*24L*/ + | JSON_ARRAYAGG '(' /*24L*/ json_value_expr json_array_aggregate_order_by_clause_opt json_array_constructor_null_clause_opt json_output_clause_opt ')' /*24L*/ + ; + +json_array_aggregate_order_by_clause_opt : + ORDER BY sortby_list + | /*empty*/ + ; + +opt_target_list : + target_list + | /*empty*/ + ; + +target_list : + target_el + | target_list ',' target_el + ; + +target_el : + a_expr AS ColLabel + | a_expr BareColLabel + | a_expr + | '*' /*18L*/ + ; + +qualified_name_list : + qualified_name + | qualified_name_list ',' qualified_name + ; + +qualified_name : + ColId + | ColId indirection + ; + +name_list : + name + | name_list ',' name + ; + +name : + ColId + ; + +attr_name : + ColLabel + ; + +file_name : + Sconst + ; + +func_name : + type_function_name + | ColId indirection + ; + +AexprConst : + Iconst + | FCONST + | Sconst + | BCONST + | XCONST + | func_name Sconst + | func_name '(' /*24L*/ func_arg_list opt_sort_clause ')' /*24L*/ Sconst + | ConstTypename Sconst + | ConstInterval Sconst opt_interval + | ConstInterval '(' /*24L*/ Iconst ')' /*24L*/ Sconst + | TRUE_P + | FALSE_P + | NULL_P + ; + +Iconst : + ICONST + ; + +Sconst : + SCONST + ; + +SignedIconst : + Iconst + | '+' /*17L*/ Iconst + | '-' /*17L*/ Iconst + ; + +RoleId : + RoleSpec + ; + +RoleSpec : + NonReservedWord + | CURRENT_ROLE + | CURRENT_USER + | SESSION_USER + ; + +role_list : + RoleSpec + | role_list ',' RoleSpec + ; + +PLpgSQL_Expr : + opt_distinct_clause opt_target_list from_clause where_clause group_clause having_clause window_clause opt_sort_clause opt_select_limit opt_for_locking_clause + ; + +PLAssignStmt : + plassign_target opt_indirection plassign_equals PLpgSQL_Expr + ; + +plassign_target : + ColId + | PARAM + ; + +plassign_equals : + COLON_EQUALS + | '=' /*8N*/ + ; + +ColId : + IDENT /*15N*/ + | unreserved_keyword + | col_name_keyword + ; + +type_function_name : + IDENT /*15N*/ + | unreserved_keyword + | type_func_name_keyword + ; + +NonReservedWord : + IDENT /*15N*/ + | unreserved_keyword + | col_name_keyword + | type_func_name_keyword + ; + +ColLabel : + IDENT /*15N*/ + | unreserved_keyword + | col_name_keyword + | type_func_name_keyword + | reserved_keyword + ; + +BareColLabel : + IDENT /*15N*/ + | bare_label_keyword + ; + +unreserved_keyword : + ABORT_P + | ABSENT + | ABSOLUTE_P + | ACCESS + | ACTION + | ADD_P + | ADMIN + | AFTER + | AGGREGATE + | ALSO + | ALTER + | ALWAYS + | ASENSITIVE + | ASSERTION + | ASSIGNMENT + | AT /*20L*/ + | ATOMIC + | ATTACH + | ATTRIBUTE + | BACKWARD + | BEFORE + | BEGIN_P + | BREADTH + | BY + | CACHE + | CALL + | CALLED + | CASCADE + | CASCADED + | CATALOG_P + | CHAIN + | CHARACTERISTICS + | CHECKPOINT + | CLASS + | CLOSE + | CLUSTER + | COLUMNS + | COMMENT + | COMMENTS + | COMMIT + | COMMITTED + | COMPRESSION + | CONFIGURATION + | CONFLICT + | CONNECTION + | CONSTRAINTS + | CONTENT_P + | CONTINUE_P + | CONVERSION_P + | COPY + | COST + | CSV + | CUBE /*15N*/ + | CURRENT_P + | CURSOR + | CYCLE + | DATA_P + | DATABASE + | DAY_P + | DEALLOCATE + | DECLARE + | DEFAULTS + | DEFERRED + | DEFINER + | DELETE_P + | DELIMITER + | DELIMITERS + | DEPENDS + | DEPTH + | DETACH + | DICTIONARY + | DISABLE_P + | DISCARD + | DOCUMENT_P + | DOMAIN_P + | DOUBLE_P + | DROP + | EACH + | ENABLE_P + | ENCODING + | ENCRYPTED + | ENUM_P + | ESCAPE /*10N*/ + | EVENT + | EXCLUDE + | EXCLUDING + | EXCLUSIVE + | EXECUTE + | EXPLAIN + | EXPRESSION + | EXTENSION + | EXTERNAL + | FAMILY + | FILTER + | FINALIZE + | FIRST_P + | FOLLOWING /*15N*/ + | FORCE + | FORMAT + | FORWARD + | FUNCTION + | FUNCTIONS + | GENERATED + | GLOBAL + | GRANTED + | GROUPS /*15N*/ + | HANDLER + | HEADER_P + | HOLD + | HOUR_P + | IDENTITY_P + | IF_P + | IMMEDIATE + | IMMUTABLE + | IMPLICIT_P + | IMPORT_P + | INCLUDE + | INCLUDING + | INCREMENT + | INDENT + | INDEX + | INDEXES + | INHERIT + | INHERITS + | INLINE_P + | INPUT_P + | INSENSITIVE + | INSERT + | INSTEAD + | INVOKER + | ISOLATION + | JSON /*11N*/ + | KEY + | KEYS /*12N*/ + | LABEL + | LANGUAGE + | LARGE_P + | LAST_P + | LEAKPROOF + | LEVEL + | LISTEN + | LOAD + | LOCAL + | LOCATION + | LOCK_P + | LOCKED + | LOGGED + | MAPPING + | MATCH + | MATCHED + | MATERIALIZED + | MAXVALUE + | MERGE + | METHOD + | MINUTE_P + | MINVALUE + | MODE + | MONTH_P + | MOVE + | NAME_P + | NAMES + | NEW + | NEXT + | NFC + | NFD + | NFKC + | NFKD + | NO + | NORMALIZED + | NOTHING + | NOTIFY + | NOWAIT + | NULLS_P + | OBJECT_P /*12N*/ + | OF + | OFF + | OIDS + | OLD + | OPERATOR /*16L*/ + | OPTION + | OPTIONS + | ORDINALITY + | OTHERS + | OVER + | OVERRIDING + | OWNED + | OWNER + | PARALLEL + | PARAMETER + | PARSER + | PARTIAL + | PARTITION /*15N*/ + | PASSING + | PASSWORD + | PLANS + | POLICY + | PRECEDING /*15N*/ + | PREPARE + | PREPARED + | PRESERVE + | PRIOR + | PRIVILEGES + | PROCEDURAL + | PROCEDURE + | PROCEDURES + | PROGRAM + | PUBLICATION + | QUOTE + | RANGE /*15N*/ + | READ + | REASSIGN + | RECHECK + | RECURSIVE + | REF_P + | REFERENCING + | REFRESH + | REINDEX + | RELATIVE_P + | RELEASE + | RENAME + | REPEATABLE + | REPLACE + | REPLICA + | RESET + | RESTART + | RESTRICT + | RETURN + | RETURNS + | REVOKE + | ROLE + | ROLLBACK + | ROLLUP /*15N*/ + | ROUTINE + | ROUTINES + | ROWS /*15N*/ + | RULE + | SAVEPOINT + | SCALAR /*12N*/ + | SCHEMA + | SCHEMAS + | SCROLL + | SEARCH + | SECOND_P + | SECURITY + | SEQUENCE + | SEQUENCES + | SERIALIZABLE + | SERVER + | SESSION + | SET /*1N*/ + | SETS + | SHARE + | SHOW + | SIMPLE + | SKIP + | SNAPSHOT + | SQL_P + | STABLE + | STANDALONE_P + | START + | STATEMENT + | STATISTICS + | STDIN + | STDOUT + | STORAGE + | STORED + | STRICT_P + | STRIP_P + | SUBSCRIPTION + | SUPPORT + | SYSID + | SYSTEM_P + | TABLES + | TABLESPACE + | TEMP + | TEMPLATE + | TEMPORARY + | TEXT_P + | TIES + | TRANSACTION + | TRANSFORM + | TRIGGER + | TRUNCATE + | TRUSTED + | TYPE_P + | TYPES_P + | UESCAPE + | UNBOUNDED /*14N*/ + | UNCOMMITTED + | UNENCRYPTED + | UNKNOWN + | UNLISTEN + | UNLOGGED + | UNTIL + | UPDATE + | VACUUM + | VALID + | VALIDATE + | VALIDATOR + | VALUE_P /*12N*/ + | VARYING + | VERSION_P + | VIEW + | VIEWS + | VOLATILE + | WHITESPACE_P + | WITHIN + | WITHOUT /*13N*/ + | WORK + | WRAPPER + | WRITE + | XML_P + | YEAR_P + | YES_P + | ZONE + ; + +col_name_keyword : + BETWEEN /*9N*/ + | BIGINT + | BIT + | BOOLEAN_P + | CHAR_P + | CHARACTER + | COALESCE + | DEC + | DECIMAL_P + | EXISTS + | EXTRACT + | FLOAT_P + | GREATEST + | GROUPING + | INOUT + | INT_P + | INTEGER + | INTERVAL + | JSON_ARRAY + | JSON_ARRAYAGG + | JSON_OBJECT + | JSON_OBJECTAGG + | LEAST + | NATIONAL + | NCHAR + | NONE + | NORMALIZE + | NULLIF + | NUMERIC + | OUT_P + | OVERLAY + | POSITION + | PRECISION + | REAL + | ROW + | SETOF + | SMALLINT + | SUBSTRING + | TIME + | TIMESTAMP + | TREAT + | TRIM + | VALUES + | VARCHAR + | XMLATTRIBUTES + | XMLCONCAT + | XMLELEMENT + | XMLEXISTS + | XMLFOREST + | XMLNAMESPACES + | XMLPARSE + | XMLPI + | XMLROOT + | XMLSERIALIZE + | XMLTABLE + ; + +type_func_name_keyword : + AUTHORIZATION + | BINARY + | COLLATION + | CONCURRENTLY + | CROSS /*27L*/ + | CURRENT_SCHEMA + | FREEZE + | FULL /*27L*/ + | ILIKE /*9N*/ + | INNER_P /*27L*/ + | IS /*7N*/ + | ISNULL /*7N*/ + | JOIN /*27L*/ + | LEFT /*27L*/ + | LIKE /*9N*/ + | NATURAL /*27L*/ + | NOTNULL /*7N*/ + | OUTER_P + | OVERLAPS + | RIGHT /*27L*/ + | SIMILAR /*9N*/ + | TABLESAMPLE + | VERBOSE + ; + +reserved_keyword : + ALL + | ANALYSE + | ANALYZE + | AND /*5L*/ + | ANY + | ARRAY + | AS + | ASC + | ASYMMETRIC + | BOTH + | CASE + | CAST + | CHECK + | COLLATE /*21L*/ + | COLUMN + | CONSTRAINT + | CREATE + | CURRENT_CATALOG + | CURRENT_DATE + | CURRENT_ROLE + | CURRENT_TIME + | CURRENT_TIMESTAMP + | CURRENT_USER + | DEFAULT + | DEFERRABLE + | DESC + | DISTINCT + | DO + | ELSE + | END_P + | EXCEPT /*2L*/ + | FALSE_P + | FETCH + | FOR + | FOREIGN + | FROM + | GRANT + | GROUP_P + | HAVING + | IN_P /*9N*/ + | INITIALLY + | INTERSECT /*3L*/ + | INTO + | LATERAL_P + | LEADING + | LIMIT + | LOCALTIME + | LOCALTIMESTAMP + | NOT /*6R*/ + | NULL_P + | OFFSET + | ON + | ONLY + | OR /*4L*/ + | ORDER + | PLACING + | PRIMARY + | REFERENCES + | RETURNING + | SELECT + | SESSION_USER + | SOME + | SYMMETRIC + | SYSTEM_USER + | TABLE + | THEN + | TO + | TRAILING + | TRUE_P + | UNION /*2L*/ + | UNIQUE /*11N*/ + | USER + | USING + | VARIADIC + | WHEN + | WHERE + | WINDOW + | WITH /*13N*/ + ; + +bare_label_keyword : + ABORT_P + | ABSENT + | ABSOLUTE_P + | ACCESS + | ACTION + | ADD_P + | ADMIN + | AFTER + | AGGREGATE + | ALL + | ALSO + | ALTER + | ALWAYS + | ANALYSE + | ANALYZE + | AND /*5L*/ + | ANY + | ASC + | ASENSITIVE + | ASSERTION + | ASSIGNMENT + | ASYMMETRIC + | AT /*20L*/ + | ATOMIC + | ATTACH + | ATTRIBUTE + | AUTHORIZATION + | BACKWARD + | BEFORE + | BEGIN_P + | BETWEEN /*9N*/ + | BIGINT + | BINARY + | BIT + | BOOLEAN_P + | BOTH + | BREADTH + | BY + | CACHE + | CALL + | CALLED + | CASCADE + | CASCADED + | CASE + | CAST + | CATALOG_P + | CHAIN + | CHARACTERISTICS + | CHECK + | CHECKPOINT + | CLASS + | CLOSE + | CLUSTER + | COALESCE + | COLLATE /*21L*/ + | COLLATION + | COLUMN + | COLUMNS + | COMMENT + | COMMENTS + | COMMIT + | COMMITTED + | COMPRESSION + | CONCURRENTLY + | CONFIGURATION + | CONFLICT + | CONNECTION + | CONSTRAINT + | CONSTRAINTS + | CONTENT_P + | CONTINUE_P + | CONVERSION_P + | COPY + | COST + | CROSS /*27L*/ + | CSV + | CUBE /*15N*/ + | CURRENT_P + | CURRENT_CATALOG + | CURRENT_DATE + | CURRENT_ROLE + | CURRENT_SCHEMA + | CURRENT_TIME + | CURRENT_TIMESTAMP + | CURRENT_USER + | CURSOR + | CYCLE + | DATA_P + | DATABASE + | DEALLOCATE + | DEC + | DECIMAL_P + | DECLARE + | DEFAULT + | DEFAULTS + | DEFERRABLE + | DEFERRED + | DEFINER + | DELETE_P + | DELIMITER + | DELIMITERS + | DEPENDS + | DEPTH + | DESC + | DETACH + | DICTIONARY + | DISABLE_P + | DISCARD + | DISTINCT + | DO + | DOCUMENT_P + | DOMAIN_P + | DOUBLE_P + | DROP + | EACH + | ELSE + | ENABLE_P + | ENCODING + | ENCRYPTED + | END_P + | ENUM_P + | ESCAPE /*10N*/ + | EVENT + | EXCLUDE + | EXCLUDING + | EXCLUSIVE + | EXECUTE + | EXISTS + | EXPLAIN + | EXPRESSION + | EXTENSION + | EXTERNAL + | EXTRACT + | FALSE_P + | FAMILY + | FINALIZE + | FIRST_P + | FLOAT_P + | FOLLOWING /*15N*/ + | FORCE + | FOREIGN + | FORMAT + | FORWARD + | FREEZE + | FULL /*27L*/ + | FUNCTION + | FUNCTIONS + | GENERATED + | GLOBAL + | GRANTED + | GREATEST + | GROUPING + | GROUPS /*15N*/ + | HANDLER + | HEADER_P + | HOLD + | IDENTITY_P + | IF_P + | ILIKE /*9N*/ + | IMMEDIATE + | IMMUTABLE + | IMPLICIT_P + | IMPORT_P + | IN_P /*9N*/ + | INCLUDE + | INCLUDING + | INCREMENT + | INDENT + | INDEX + | INDEXES + | INHERIT + | INHERITS + | INITIALLY + | INLINE_P + | INNER_P /*27L*/ + | INOUT + | INPUT_P + | INSENSITIVE + | INSERT + | INSTEAD + | INT_P + | INTEGER + | INTERVAL + | INVOKER + | IS /*7N*/ + | ISOLATION + | JOIN /*27L*/ + | JSON /*11N*/ + | JSON_ARRAY + | JSON_ARRAYAGG + | JSON_OBJECT + | JSON_OBJECTAGG + | KEY + | KEYS /*12N*/ + | LABEL + | LANGUAGE + | LARGE_P + | LAST_P + | LATERAL_P + | LEADING + | LEAKPROOF + | LEAST + | LEFT /*27L*/ + | LEVEL + | LIKE /*9N*/ + | LISTEN + | LOAD + | LOCAL + | LOCALTIME + | LOCALTIMESTAMP + | LOCATION + | LOCK_P + | LOCKED + | LOGGED + | MAPPING + | MATCH + | MATCHED + | MATERIALIZED + | MAXVALUE + | MERGE + | METHOD + | MINVALUE + | MODE + | MOVE + | NAME_P + | NAMES + | NATIONAL + | NATURAL /*27L*/ + | NCHAR + | NEW + | NEXT + | NFC + | NFD + | NFKC + | NFKD + | NO + | NONE + | NORMALIZE + | NORMALIZED + | NOT /*6R*/ + | NOTHING + | NOTIFY + | NOWAIT + | NULL_P + | NULLIF + | NULLS_P + | NUMERIC + | OBJECT_P /*12N*/ + | OF + | OFF + | OIDS + | OLD + | ONLY + | OPERATOR /*16L*/ + | OPTION + | OPTIONS + | OR /*4L*/ + | ORDINALITY + | OTHERS + | OUT_P + | OUTER_P + | OVERLAY + | OVERRIDING + | OWNED + | OWNER + | PARALLEL + | PARAMETER + | PARSER + | PARTIAL + | PARTITION /*15N*/ + | PASSING + | PASSWORD + | PLACING + | PLANS + | POLICY + | POSITION + | PRECEDING /*15N*/ + | PREPARE + | PREPARED + | PRESERVE + | PRIMARY + | PRIOR + | PRIVILEGES + | PROCEDURAL + | PROCEDURE + | PROCEDURES + | PROGRAM + | PUBLICATION + | QUOTE + | RANGE /*15N*/ + | READ + | REAL + | REASSIGN + | RECHECK + | RECURSIVE + | REF_P + | REFERENCES + | REFERENCING + | REFRESH + | REINDEX + | RELATIVE_P + | RELEASE + | RENAME + | REPEATABLE + | REPLACE + | REPLICA + | RESET + | RESTART + | RESTRICT + | RETURN + | RETURNS + | REVOKE + | RIGHT /*27L*/ + | ROLE + | ROLLBACK + | ROLLUP /*15N*/ + | ROUTINE + | ROUTINES + | ROW + | ROWS /*15N*/ + | RULE + | SAVEPOINT + | SCALAR /*12N*/ + | SCHEMA + | SCHEMAS + | SCROLL + | SEARCH + | SECURITY + | SELECT + | SEQUENCE + | SEQUENCES + | SERIALIZABLE + | SERVER + | SESSION + | SESSION_USER + | SET /*1N*/ + | SETOF + | SETS + | SHARE + | SHOW + | SIMILAR /*9N*/ + | SIMPLE + | SKIP + | SMALLINT + | SNAPSHOT + | SOME + | SQL_P + | STABLE + | STANDALONE_P + | START + | STATEMENT + | STATISTICS + | STDIN + | STDOUT + | STORAGE + | STORED + | STRICT_P + | STRIP_P + | SUBSCRIPTION + | SUBSTRING + | SUPPORT + | SYMMETRIC + | SYSID + | SYSTEM_P + | SYSTEM_USER + | TABLE + | TABLES + | TABLESAMPLE + | TABLESPACE + | TEMP + | TEMPLATE + | TEMPORARY + | TEXT_P + | THEN + | TIES + | TIME + | TIMESTAMP + | TRAILING + | TRANSACTION + | TRANSFORM + | TREAT + | TRIGGER + | TRIM + | TRUE_P + | TRUNCATE + | TRUSTED + | TYPE_P + | TYPES_P + | UESCAPE + | UNBOUNDED /*14N*/ + | UNCOMMITTED + | UNENCRYPTED + | UNIQUE /*11N*/ + | UNKNOWN + | UNLISTEN + | UNLOGGED + | UNTIL + | UPDATE + | USER + | USING + | VACUUM + | VALID + | VALIDATE + | VALIDATOR + | VALUE_P /*12N*/ + | VALUES + | VARCHAR + | VARIADIC + | VERBOSE + | VERSION_P + | VIEW + | VIEWS + | VOLATILE + | WHEN + | WHITESPACE_P + | WORK + | WRAPPER + | WRITE + | XML_P + | XMLATTRIBUTES + | XMLCONCAT + | XMLELEMENT + | XMLEXISTS + | XMLFOREST + | XMLNAMESPACES + | XMLPARSE + | XMLPI + | XMLROOT + | XMLSERIALIZE + | XMLTABLE + | YES_P + | ZONE + ; + +// Tokens + +/* + * List of keyword (name, token-value, category, bare-label-status) entries. + * + * Note: gen_keywordlist.pl requires the entries to appear in ASCII order. + */ + + //PG_KEYWORD("\([^"]+\)", \(\w[^,]+\),.+ +/* name, value, category, is-bare-label */ +ABORT_P : 'ABORT' ; +ABSENT : 'ABSENT' ; +ABSOLUTE_P : 'ABSOLUTE' ; +ACCESS : 'ACCESS' ; +ACTION : 'ACTION' ; +ADD_P : 'ADD' ; +ADMIN : 'ADMIN' ; +AFTER : 'AFTER' ; +AGGREGATE : 'AGGREGATE' ; +ALL : 'ALL' ; +ALSO : 'ALSO' ; +ALTER : 'ALTER' ; +ALWAYS : 'ALWAYS' ; +ANALYSE : 'ANALYSE' ; +ANALYZE : 'ANALYZE' ; +AND : 'AND' ; +ANY : 'ANY' ; +ARRAY : 'ARRAY' ; +AS : 'AS' ; +ASC : 'ASC' ; +ASENSITIVE : 'ASENSITIVE' ; +ASSERTION : 'ASSERTION' ; +ASSIGNMENT : 'ASSIGNMENT' ; +ASYMMETRIC : 'ASYMMETRIC' ; +AT : 'AT' ; +ATOMIC : 'ATOMIC' ; +ATTACH : 'ATTACH' ; +ATTRIBUTE : 'ATTRIBUTE' ; +AUTHORIZATION : 'AUTHORIZATION' ; +BACKWARD : 'BACKWARD' ; +BEFORE : 'BEFORE' ; +BEGIN_P : 'BEGIN' ; +BETWEEN : 'BETWEEN' ; +BIGINT : 'BIGINT' ; +BINARY : 'BINARY' ; +BIT : 'BIT' ; +BOOLEAN_P : 'BOOLEAN' ; +BOTH : 'BOTH' ; +BREADTH : 'BREADTH' ; +BY : 'BY' ; +CACHE : 'CACHE' ; +CALL : 'CALL' ; +CALLED : 'CALLED' ; +CASCADE : 'CASCADE' ; +CASCADED : 'CASCADED' ; +CASE : 'CASE' ; +CAST : 'CAST' ; +CATALOG_P : 'CATALOG' ; +CHAIN : 'CHAIN' ; +CHAR_P : 'CHAR' ; +CHARACTER : 'CHARACTER' ; +CHARACTERISTICS : 'CHARACTERISTICS' ; +CHECK : 'CHECK' ; +CHECKPOINT : 'CHECKPOINT' ; +CLASS : 'CLASS' ; +CLOSE : 'CLOSE' ; +CLUSTER : 'CLUSTER' ; +COALESCE : 'COALESCE' ; +COLLATE : 'COLLATE' ; +COLLATION : 'COLLATION' ; +COLUMN : 'COLUMN' ; +COLUMNS : 'COLUMNS' ; +COMMENT : 'COMMENT' ; +COMMENTS : 'COMMENTS' ; +COMMIT : 'COMMIT' ; +COMMITTED : 'COMMITTED' ; +COMPRESSION : 'COMPRESSION' ; +CONCURRENTLY : 'CONCURRENTLY' ; +CONFIGURATION : 'CONFIGURATION' ; +CONFLICT : 'CONFLICT' ; +CONNECTION : 'CONNECTION' ; +CONSTRAINT : 'CONSTRAINT' ; +CONSTRAINTS : 'CONSTRAINTS' ; +CONTENT_P : 'CONTENT' ; +CONTINUE_P : 'CONTINUE' ; +CONVERSION_P : 'CONVERSION' ; +COPY : 'COPY' ; +COST : 'COST' ; +CREATE : 'CREATE' ; +CROSS : 'CROSS' ; +CSV : 'CSV' ; +CUBE : 'CUBE' ; +CURRENT_P : 'CURRENT' ; +CURRENT_CATALOG : 'CURRENT_CATALOG' ; +CURRENT_DATE : 'CURRENT_DATE' ; +CURRENT_ROLE : 'CURRENT_ROLE' ; +CURRENT_SCHEMA : 'CURRENT_SCHEMA' ; +CURRENT_TIME : 'CURRENT_TIME' ; +CURRENT_TIMESTAMP : 'CURRENT_TIMESTAMP' ; +CURRENT_USER : 'CURRENT_USER' ; +CURSOR : 'CURSOR' ; +CYCLE : 'CYCLE' ; +DATA_P : 'DATA' ; +DATABASE : 'DATABASE' ; +DAY_P : 'DAY' ; +DEALLOCATE : 'DEALLOCATE' ; +DEC : 'DEC' ; +DECIMAL_P : 'DECIMAL' ; +DECLARE : 'DECLARE' ; +DEFAULT : 'DEFAULT' ; +DEFAULTS : 'DEFAULTS' ; +DEFERRABLE : 'DEFERRABLE' ; +DEFERRED : 'DEFERRED' ; +DEFINER : 'DEFINER' ; +DELETE_P : 'DELETE' ; +DELIMITER : 'DELIMITER' ; +DELIMITERS : 'DELIMITERS' ; +DEPENDS : 'DEPENDS' ; +DEPTH : 'DEPTH' ; +DESC : 'DESC' ; +DETACH : 'DETACH' ; +DICTIONARY : 'DICTIONARY' ; +DISABLE_P : 'DISABLE' ; +DISCARD : 'DISCARD' ; +DISTINCT : 'DISTINCT' ; +DO : 'DO' ; +DOCUMENT_P : 'DOCUMENT' ; +DOMAIN_P : 'DOMAIN' ; +DOUBLE_P : 'DOUBLE' ; +DROP : 'DROP' ; +EACH : 'EACH' ; +ELSE : 'ELSE' ; +ENABLE_P : 'ENABLE' ; +ENCODING : 'ENCODING' ; +ENCRYPTED : 'ENCRYPTED' ; +END_P : 'END' ; +ENUM_P : 'ENUM' ; +ESCAPE : 'ESCAPE' ; +EVENT : 'EVENT' ; +EXCEPT : 'EXCEPT' ; +EXCLUDE : 'EXCLUDE' ; +EXCLUDING : 'EXCLUDING' ; +EXCLUSIVE : 'EXCLUSIVE' ; +EXECUTE : 'EXECUTE' ; +EXISTS : 'EXISTS' ; +EXPLAIN : 'EXPLAIN' ; +EXPRESSION : 'EXPRESSION' ; +EXTENSION : 'EXTENSION' ; +EXTERNAL : 'EXTERNAL' ; +EXTRACT : 'EXTRACT' ; +FALSE_P : 'FALSE' ; +FAMILY : 'FAMILY' ; +FETCH : 'FETCH' ; +FILTER : 'FILTER' ; +FINALIZE : 'FINALIZE' ; +FIRST_P : 'FIRST' ; +FLOAT_P : 'FLOAT' ; +FOLLOWING : 'FOLLOWING' ; +FOR : 'FOR' ; +FORCE : 'FORCE' ; +FOREIGN : 'FOREIGN' ; +FORMAT : 'FORMAT' ; +FORWARD : 'FORWARD' ; +FREEZE : 'FREEZE' ; +FROM : 'FROM' ; +FULL : 'FULL' ; +FUNCTION : 'FUNCTION' ; +FUNCTIONS : 'FUNCTIONS' ; +GENERATED : 'GENERATED' ; +GLOBAL : 'GLOBAL' ; +GRANT : 'GRANT' ; +GRANTED : 'GRANTED' ; +GREATEST : 'GREATEST' ; +GROUP_P : 'GROUP' ; +GROUPING : 'GROUPING' ; +GROUPS : 'GROUPS' ; +HANDLER : 'HANDLER' ; +HAVING : 'HAVING' ; +HEADER_P : 'HEADER' ; +HOLD : 'HOLD' ; +HOUR_P : 'HOUR' ; +IDENTITY_P : 'IDENTITY' ; +IF_P : 'IF' ; +ILIKE : 'ILIKE' ; +IMMEDIATE : 'IMMEDIATE' ; +IMMUTABLE : 'IMMUTABLE' ; +IMPLICIT_P : 'IMPLICIT' ; +IMPORT_P : 'IMPORT' ; +IN_P : 'IN' ; +INCLUDE : 'INCLUDE' ; +INCLUDING : 'INCLUDING' ; +INCREMENT : 'INCREMENT' ; +INDENT : 'INDENT' ; +INDEX : 'INDEX' ; +INDEXES : 'INDEXES' ; +INHERIT : 'INHERIT' ; +INHERITS : 'INHERITS' ; +INITIALLY : 'INITIALLY' ; +INLINE_P : 'INLINE' ; +INNER_P : 'INNER' ; +INOUT : 'INOUT' ; +INPUT_P : 'INPUT' ; +INSENSITIVE : 'INSENSITIVE' ; +INSERT : 'INSERT' ; +INSTEAD : 'INSTEAD' ; +INT_P : 'INT' ; +INTEGER : 'INTEGER' ; +INTERSECT : 'INTERSECT' ; +INTERVAL : 'INTERVAL' ; +INTO : 'INTO' ; +INVOKER : 'INVOKER' ; +IS : 'IS' ; +ISNULL : 'ISNULL' ; +ISOLATION : 'ISOLATION' ; +JOIN : 'JOIN' ; +JSON : 'JSON' ; +JSON_ARRAY : 'JSON_ARRAY' ; +JSON_ARRAYAGG : 'JSON_ARRAYAGG' ; +JSON_OBJECT : 'JSON_OBJECT' ; +JSON_OBJECTAGG : 'JSON_OBJECTAGG' ; +KEY : 'KEY' ; +KEYS : 'KEYS' ; +LABEL : 'LABEL' ; +LANGUAGE : 'LANGUAGE' ; +LARGE_P : 'LARGE' ; +LAST_P : 'LAST' ; +LATERAL_P : 'LATERAL' ; +LEADING : 'LEADING' ; +LEAKPROOF : 'LEAKPROOF' ; +LEAST : 'LEAST' ; +LEFT : 'LEFT' ; +LEVEL : 'LEVEL' ; +LIKE : 'LIKE' ; +LIMIT : 'LIMIT' ; +LISTEN : 'LISTEN' ; +LOAD : 'LOAD' ; +LOCAL : 'LOCAL' ; +LOCALTIME : 'LOCALTIME' ; +LOCALTIMESTAMP : 'LOCALTIMESTAMP' ; +LOCATION : 'LOCATION' ; +LOCK_P : 'LOCK' ; +LOCKED : 'LOCKED' ; +LOGGED : 'LOGGED' ; +MAPPING : 'MAPPING' ; +MATCH : 'MATCH' ; +MATCHED : 'MATCHED' ; +MATERIALIZED : 'MATERIALIZED' ; +MAXVALUE : 'MAXVALUE' ; +MERGE : 'MERGE' ; +METHOD : 'METHOD' ; +MINUTE_P : 'MINUTE' ; +MINVALUE : 'MINVALUE' ; +MODE : 'MODE' ; +MONTH_P : 'MONTH' ; +MOVE : 'MOVE' ; +NAME_P : 'NAME' ; +NAMES : 'NAMES' ; +NATIONAL : 'NATIONAL' ; +NATURAL : 'NATURAL' ; +NCHAR : 'NCHAR' ; +NEW : 'NEW' ; +NEXT : 'NEXT' ; +NFC : 'NFC' ; +NFD : 'NFD' ; +NFKC : 'NFKC' ; +NFKD : 'NFKD' ; +NO : 'NO' ; +NONE : 'NONE' ; +NORMALIZE : 'NORMALIZE' ; +NORMALIZED : 'NORMALIZED' ; +NOT : 'NOT' ; +NOTHING : 'NOTHING' ; +NOTIFY : 'NOTIFY' ; +NOTNULL : 'NOTNULL' ; +NOWAIT : 'NOWAIT' ; +NULL_P : 'NULL' ; +NULLIF : 'NULLIF' ; +NULLS_P : 'NULLS' ; +NUMERIC : 'NUMERIC' ; +OBJECT_P : 'OBJECT' ; +OF : 'OF' ; +OFF : 'OFF' ; +OFFSET : 'OFFSET' ; +OIDS : 'OIDS' ; +OLD : 'OLD' ; +ON : 'ON' ; +ONLY : 'ONLY' ; +OPERATOR : 'OPERATOR' ; +OPTION : 'OPTION' ; +OPTIONS : 'OPTIONS' ; +OR : 'OR' ; +ORDER : 'ORDER' ; +ORDINALITY : 'ORDINALITY' ; +OTHERS : 'OTHERS' ; +OUT_P : 'OUT' ; +OUTER_P : 'OUTER' ; +OVER : 'OVER' ; +OVERLAPS : 'OVERLAPS' ; +OVERLAY : 'OVERLAY' ; +OVERRIDING : 'OVERRIDING' ; +OWNED : 'OWNED' ; +OWNER : 'OWNER' ; +PARALLEL : 'PARALLEL' ; +PARAMETER : 'PARAMETER' ; +PARSER : 'PARSER' ; +PARTIAL : 'PARTIAL' ; +PARTITION : 'PARTITION' ; +PASSING : 'PASSING' ; +PASSWORD : 'PASSWORD' ; +PLACING : 'PLACING' ; +PLANS : 'PLANS' ; +POLICY : 'POLICY' ; +POSITION : 'POSITION' ; +PRECEDING : 'PRECEDING' ; +PRECISION : 'PRECISION' ; +PREPARE : 'PREPARE' ; +PREPARED : 'PREPARED' ; +PRESERVE : 'PRESERVE' ; +PRIMARY : 'PRIMARY' ; +PRIOR : 'PRIOR' ; +PRIVILEGES : 'PRIVILEGES' ; +PROCEDURAL : 'PROCEDURAL' ; +PROCEDURE : 'PROCEDURE' ; +PROCEDURES : 'PROCEDURES' ; +PROGRAM : 'PROGRAM' ; +PUBLICATION : 'PUBLICATION' ; +QUOTE : 'QUOTE' ; +RANGE : 'RANGE' ; +READ : 'READ' ; +REAL : 'REAL' ; +REASSIGN : 'REASSIGN' ; +RECHECK : 'RECHECK' ; +RECURSIVE : 'RECURSIVE' ; +REF_P : 'REF' ; +REFERENCES : 'REFERENCES' ; +REFERENCING : 'REFERENCING' ; +REFRESH : 'REFRESH' ; +REINDEX : 'REINDEX' ; +RELATIVE_P : 'RELATIVE' ; +RELEASE : 'RELEASE' ; +RENAME : 'RENAME' ; +REPEATABLE : 'REPEATABLE' ; +REPLACE : 'REPLACE' ; +REPLICA : 'REPLICA' ; +RESET : 'RESET' ; +RESTART : 'RESTART' ; +RESTRICT : 'RESTRICT' ; +RETURN : 'RETURN' ; +RETURNING : 'RETURNING' ; +RETURNS : 'RETURNS' ; +REVOKE : 'REVOKE' ; +RIGHT : 'RIGHT' ; +ROLE : 'ROLE' ; +ROLLBACK : 'ROLLBACK' ; +ROLLUP : 'ROLLUP' ; +ROUTINE : 'ROUTINE' ; +ROUTINES : 'ROUTINES' ; +ROW : 'ROW' ; +ROWS : 'ROWS' ; +RULE : 'RULE' ; +SAVEPOINT : 'SAVEPOINT' ; +SCALAR : 'SCALAR' ; +SCHEMA : 'SCHEMA' ; +SCHEMAS : 'SCHEMAS' ; +SCROLL : 'SCROLL' ; +SEARCH : 'SEARCH' ; +SECOND_P : 'SECOND' ; +SECURITY : 'SECURITY' ; +SELECT : 'SELECT' ; +SEQUENCE : 'SEQUENCE' ; +SEQUENCES : 'SEQUENCES' ; +SERIALIZABLE : 'SERIALIZABLE' ; +SERVER : 'SERVER' ; +SESSION : 'SESSION' ; +SESSION_USER : 'SESSION_USER' ; +SET : 'SET' ; +SETOF : 'SETOF' ; +SETS : 'SETS' ; +SHARE : 'SHARE' ; +SHOW : 'SHOW' ; +SIMILAR : 'SIMILAR' ; +SIMPLE : 'SIMPLE' ; +SKIP : 'SKIP' ; +SMALLINT : 'SMALLINT' ; +SNAPSHOT : 'SNAPSHOT' ; +SOME : 'SOME' ; +SQL_P : 'SQL' ; +STABLE : 'STABLE' ; +STANDALONE_P : 'STANDALONE' ; +START : 'START' ; +STATEMENT : 'STATEMENT' ; +STATISTICS : 'STATISTICS' ; +STDIN : 'STDIN' ; +STDOUT : 'STDOUT' ; +STORAGE : 'STORAGE' ; +STORED : 'STORED' ; +STRICT_P : 'STRICT' ; +STRIP_P : 'STRIP' ; +SUBSCRIPTION : 'SUBSCRIPTION' ; +SUBSTRING : 'SUBSTRING' ; +SUPPORT : 'SUPPORT' ; +SYMMETRIC : 'SYMMETRIC' ; +SYSID : 'SYSID' ; +SYSTEM_P : 'SYSTEM' ; +SYSTEM_USER : 'SYSTEM_USER' ; +TABLE : 'TABLE' ; +TABLES : 'TABLES' ; +TABLESAMPLE : 'TABLESAMPLE' ; +TABLESPACE : 'TABLESPACE' ; +TEMP : 'TEMP' ; +TEMPLATE : 'TEMPLATE' ; +TEMPORARY : 'TEMPORARY' ; +TEXT_P : 'TEXT' ; +THEN : 'THEN' ; +TIES : 'TIES' ; +TIME : 'TIME' ; +TIMESTAMP : 'TIMESTAMP' ; +TO : 'TO' ; +TRAILING : 'TRAILING' ; +TRANSACTION : 'TRANSACTION' ; +TRANSFORM : 'TRANSFORM' ; +TREAT : 'TREAT' ; +TRIGGER : 'TRIGGER' ; +TRIM : 'TRIM' ; +TRUE_P : 'TRUE' ; +TRUNCATE : 'TRUNCATE' ; +TRUSTED : 'TRUSTED' ; +TYPE_P : 'TYPE' ; +TYPES_P : 'TYPES' ; +UESCAPE : 'UESCAPE' ; +UNBOUNDED : 'UNBOUNDED' ; +UNCOMMITTED : 'UNCOMMITTED' ; +UNENCRYPTED : 'UNENCRYPTED' ; +UNION : 'UNION' ; +UNIQUE : 'UNIQUE' ; +UNKNOWN : 'UNKNOWN' ; +UNLISTEN : 'UNLISTEN' ; +UNLOGGED : 'UNLOGGED' ; +UNTIL : 'UNTIL' ; +UPDATE : 'UPDATE' ; +USER : 'USER' ; +USING : 'USING' ; +VACUUM : 'VACUUM' ; +VALID : 'VALID' ; +VALIDATE : 'VALIDATE' ; +VALIDATOR : 'VALIDATOR' ; +VALUE_P : 'VALUE' ; +VALUES : 'VALUES' ; +VARCHAR : 'VARCHAR' ; +VARIADIC : 'VARIADIC' ; +VARYING : 'VARYING' ; +VERBOSE : 'VERBOSE' ; +VERSION_P : 'VERSION' ; +VIEW : 'VIEW' ; +VIEWS : 'VIEWS' ; +VOLATILE : 'VOLATILE' ; +WHEN : 'WHEN' ; +WHERE : 'WHERE' ; +WHITESPACE_P : 'WHITESPACE' ; +WINDOW : 'WINDOW' ; +WITH : 'WITH' ; +WITHIN : 'WITHIN' ; +WITHOUT : 'WITHOUT' ; +WORK : 'WORK' ; +WRAPPER : 'WRAPPER' ; +WRITE : 'WRITE' ; +XML_P : 'XML' ; +XMLATTRIBUTES : 'XMLATTRIBUTES' ; +XMLCONCAT : 'XMLCONCAT' ; +XMLELEMENT : 'XMLELEMENT' ; +XMLEXISTS : 'XMLEXISTS' ; +XMLFOREST : 'XMLFOREST' ; +XMLNAMESPACES : 'XMLNAMESPACES' ; +XMLPARSE : 'XMLPARSE' ; +XMLPI : 'XMLPI' ; +XMLROOT : 'XMLROOT' ; +XMLSERIALIZE : 'XMLSERIALIZE' ; +XMLTABLE : 'XMLTABLE' ; +YEAR_P : 'YEAR' ; +YES_P : 'YES' ; +ZONE : 'ZONE' ; + + +LESS_EQUALS : '<=' ; +GREATER_EQUALS : '>=' ; +NOT_EQUALS : "!=|<>" ; +COLON_EQUALS : ':=' ; +EQUALS_GREATER : ' =>' ; +TYPECAST : '::' ; +//DOT_DOT : '..' ; + +IDENT : "[A-Za-z\200-\377_][A-Za-z\200-\377_0-9\$]*" ; +FCONST : "(([0-9]*\.[0-9]+)|([0-9]+\.[0-9]*))" ; +SCONST : "\"(\\[\"\\]|[^\"\n])*\"|'(\\['\\]|[^'\n])*'|\$\$[^\$]+\$\$" ; +BCONST : 'BCONST' ; +XCONST : 'XCONST' ; +ICONST : "[0-9]+" ; +PARAM : "\$[0-9]+"; + +MODE_TYPE_NAME : 'MODE_TYPE_NAME' ; +MODE_PLPGSQL_EXPR : 'MODE_PLPGSQL_EXPR' ; +MODE_PLPGSQL_ASSIGN1 : 'MODE_PLPGSQL_ASSIGN1' ; +MODE_PLPGSQL_ASSIGN2 : 'MODE_PLPGSQL_ASSIGN2' ; +MODE_PLPGSQL_ASSIGN3 : 'MODE_PLPGSQL_ASSIGN3' ; + +FORMAT_LA : 'FROMAT_LA' ; +WITH_LA : 'WITH_LA' ; +WITHOUT_LA : 'WITHOUT_LA' ; +NULLS_LA : 'NULLS_LA'; +NOT_LA : 'NOT_LA' ; +Op : 'Op' ; + +} \ No newline at end of file diff --git a/playground/postgresql-16.g b/playground/postgresql-16.g new file mode 100644 index 0000000..7c9257a --- /dev/null +++ b/playground/postgresql-16.g @@ -0,0 +1,6485 @@ +/* +/usr/bin/time /home/mingo/dev/c/A_grammars/lalr/lalr-nb/dist/Release/GNU-Linux/lalr-nb postgresql.g -p + +/usr/bin/time /home/mingo/dev/c/A_grammars/lalr/lalr-nb/dist/Release/GNU-Linux/lalr-nb postgresql.g > /dev/null + +32 bits +64.89user 0.54system 1:08.52elapsed 95%CPU (0avgtext+0avgdata 1076272maxresident)k +0inputs+0outputs (0major+268598minor)pagefaults 0swaps + +64 bits +66.48user 0.75system 1:07.25elapsed 99%CPU (0avgtext+0avgdata 1621820maxresident)k +0inputs+0outputs (0major+404808minor)pagefaults 0swaps +*/ + +postgresql { + +%whitespace "[ \t\r\n]*"; +%whitespace "\-\-[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token IDENT +//%token UIDENT +//%token FCONST +//%token SCONST +//%token USCONST +//%token BCONST +//%token XCONST +//%token Op +//%token ICONST +//%token PARAM +//%token TYPECAST +//%token DOT_DOT +//%token COLON_EQUALS +//%token EQUALS_GREATER +//%token LESS_EQUALS +//%token GREATER_EQUALS +//%token NOT_EQUALS +//%token ABORT_P +//%token ABSENT +//%token ABSOLUTE_P +//%token ACCESS +//%token ACTION +//%token ADD_P +//%token ADMIN +//%token AFTER +//%token AGGREGATE +//%token ALL +//%token ALSO +//%token ALTER +//%token ALWAYS +//%token ANALYSE +//%token ANALYZE +//%token AND +//%token ANY +//%token ARRAY +//%token AS +//%token ASC +//%token ASENSITIVE +//%token ASSERTION +//%token ASSIGNMENT +//%token ASYMMETRIC +//%token ATOMIC +//%token AT +//%token ATTACH +//%token ATTRIBUTE +//%token AUTHORIZATION +//%token BACKWARD +//%token BEFORE +//%token BEGIN_P +//%token BETWEEN +//%token BIGINT +//%token BINARY +//%token BIT +//%token BOOLEAN_P +//%token BOTH +//%token BREADTH +//%token BY +//%token CACHE +//%token CALL +//%token CALLED +//%token CASCADE +//%token CASCADED +//%token CASE +//%token CAST +//%token CATALOG_P +//%token CHAIN +//%token CHAR_P +//%token CHARACTER +//%token CHARACTERISTICS +//%token CHECK +//%token CHECKPOINT +//%token CLASS +//%token CLOSE +//%token CLUSTER +//%token COALESCE +//%token COLLATE +//%token COLLATION +//%token COLUMN +//%token COLUMNS +//%token COMMENT +//%token COMMENTS +//%token COMMIT +//%token COMMITTED +//%token COMPRESSION +//%token CONCURRENTLY +//%token CONFIGURATION +//%token CONFLICT +//%token CONNECTION +//%token CONSTRAINT +//%token CONSTRAINTS +//%token CONTENT_P +//%token CONTINUE_P +//%token CONVERSION_P +//%token COPY +//%token COST +//%token CREATE +//%token CROSS +//%token CSV +//%token CUBE +//%token CURRENT_P +//%token CURRENT_CATALOG +//%token CURRENT_DATE +//%token CURRENT_ROLE +//%token CURRENT_SCHEMA +//%token CURRENT_TIME +//%token CURRENT_TIMESTAMP +//%token CURRENT_USER +//%token CURSOR +//%token CYCLE +//%token DATA_P +//%token DATABASE +//%token DAY_P +//%token DEALLOCATE +//%token DEC +//%token DECIMAL_P +//%token DECLARE +//%token DEFAULT +//%token DEFAULTS +//%token DEFERRABLE +//%token DEFERRED +//%token DEFINER +//%token DELETE_P +//%token DELIMITER +//%token DELIMITERS +//%token DEPENDS +//%token DEPTH +//%token DESC +//%token DETACH +//%token DICTIONARY +//%token DISABLE_P +//%token DISCARD +//%token DISTINCT +//%token DO +//%token DOCUMENT_P +//%token DOMAIN_P +//%token DOUBLE_P +//%token DROP +//%token EACH +//%token ELSE +//%token ENABLE_P +//%token ENCODING +//%token ENCRYPTED +//%token END_P +//%token ENUM_P +//%token ESCAPE +//%token EVENT +//%token EXCEPT +//%token EXCLUDE +//%token EXCLUDING +//%token EXCLUSIVE +//%token EXECUTE +//%token EXISTS +//%token EXPLAIN +//%token EXPRESSION +//%token EXTENSION +//%token EXTERNAL +//%token EXTRACT +//%token FALSE_P +//%token FAMILY +//%token FETCH +//%token FILTER +//%token FINALIZE +//%token FIRST_P +//%token FLOAT_P +//%token FOLLOWING +//%token FOR +//%token FORCE +//%token FOREIGN +//%token FORMAT +//%token FORWARD +//%token FREEZE +//%token FROM +//%token FULL +//%token FUNCTION +//%token FUNCTIONS +//%token GENERATED +//%token GLOBAL +//%token GRANT +//%token GRANTED +//%token GREATEST +//%token GROUP_P +//%token GROUPING +//%token GROUPS +//%token HANDLER +//%token HAVING +//%token HEADER_P +//%token HOLD +//%token HOUR_P +//%token IDENTITY_P +//%token IF_P +//%token ILIKE +//%token IMMEDIATE +//%token IMMUTABLE +//%token IMPLICIT_P +//%token IMPORT_P +//%token IN_P +//%token INCLUDE +//%token INCLUDING +//%token INCREMENT +//%token INDENT +//%token INDEX +//%token INDEXES +//%token INHERIT +//%token INHERITS +//%token INITIALLY +//%token INLINE_P +//%token INNER_P +//%token INOUT +//%token INPUT_P +//%token INSENSITIVE +//%token INSERT +//%token INSTEAD +//%token INT_P +//%token INTEGER +//%token INTERSECT +//%token INTERVAL +//%token INTO +//%token INVOKER +//%token IS +//%token ISNULL +//%token ISOLATION +//%token JOIN +//%token JSON +//%token JSON_ARRAY +//%token JSON_ARRAYAGG +//%token JSON_OBJECT +//%token JSON_OBJECTAGG +//%token KEY +//%token KEYS +//%token LABEL +//%token LANGUAGE +//%token LARGE_P +//%token LAST_P +//%token LATERAL_P +//%token LEADING +//%token LEAKPROOF +//%token LEAST +//%token LEFT +//%token LEVEL +//%token LIKE +//%token LIMIT +//%token LISTEN +//%token LOAD +//%token LOCAL +//%token LOCALTIME +//%token LOCALTIMESTAMP +//%token LOCATION +//%token LOCK_P +//%token LOCKED +//%token LOGGED +//%token MAPPING +//%token MATCH +//%token MATCHED +//%token MATERIALIZED +//%token MAXVALUE +//%token MERGE +//%token METHOD +//%token MINUTE_P +//%token MINVALUE +//%token MODE +//%token MONTH_P +//%token MOVE +//%token NAME_P +//%token NAMES +//%token NATIONAL +//%token NATURAL +//%token NCHAR +//%token NEW +//%token NEXT +//%token NFC +//%token NFD +//%token NFKC +//%token NFKD +//%token NO +//%token NONE +//%token NORMALIZE +//%token NORMALIZED +//%token NOT +//%token NOTHING +//%token NOTIFY +//%token NOTNULL +//%token NOWAIT +//%token NULL_P +//%token NULLIF +//%token NULLS_P +//%token NUMERIC +//%token OBJECT_P +//%token OF +//%token OFF +//%token OFFSET +//%token OIDS +//%token OLD +//%token ON +//%token ONLY +//%token OPERATOR +//%token OPTION +//%token OPTIONS +//%token OR +//%token ORDER +//%token ORDINALITY +//%token OTHERS +//%token OUT_P +//%token OUTER_P +//%token OVER +//%token OVERLAPS +//%token OVERLAY +//%token OVERRIDING +//%token OWNED +//%token OWNER +//%token PARALLEL +//%token PARAMETER +//%token PARSER +//%token PARTIAL +//%token PARTITION +//%token PASSING +//%token PASSWORD +//%token PLACING +//%token PLANS +//%token POLICY +//%token POSITION +//%token PRECEDING +//%token PRECISION +//%token PRESERVE +//%token PREPARE +//%token PREPARED +//%token PRIMARY +//%token PRIOR +//%token PRIVILEGES +//%token PROCEDURAL +//%token PROCEDURE +//%token PROCEDURES +//%token PROGRAM +//%token PUBLICATION +//%token QUOTE +//%token RANGE +//%token READ +//%token REAL +//%token REASSIGN +//%token RECHECK +//%token RECURSIVE +//%token REF_P +//%token REFERENCES +//%token REFERENCING +//%token REFRESH +//%token REINDEX +//%token RELATIVE_P +//%token RELEASE +//%token RENAME +//%token REPEATABLE +//%token REPLACE +//%token REPLICA +//%token RESET +//%token RESTART +//%token RESTRICT +//%token RETURN +//%token RETURNING +//%token RETURNS +//%token REVOKE +//%token RIGHT +//%token ROLE +//%token ROLLBACK +//%token ROLLUP +//%token ROUTINE +//%token ROUTINES +//%token ROW +//%token ROWS +//%token RULE +//%token SAVEPOINT +//%token SCALAR +//%token SCHEMA +//%token SCHEMAS +//%token SCROLL +//%token SEARCH +//%token SECOND_P +//%token SECURITY +//%token SELECT +//%token SEQUENCE +//%token SEQUENCES +//%token SERIALIZABLE +//%token SERVER +//%token SESSION +//%token SESSION_USER +//%token SET +//%token SETS +//%token SETOF +//%token SHARE +//%token SHOW +//%token SIMILAR +//%token SIMPLE +//%token SKIP +//%token SMALLINT +//%token SNAPSHOT +//%token SOME +//%token SQL_P +//%token STABLE +//%token STANDALONE_P +//%token START +//%token STATEMENT +//%token STATISTICS +//%token STDIN +//%token STDOUT +//%token STORAGE +//%token STORED +//%token STRICT_P +//%token STRIP_P +//%token SUBSCRIPTION +//%token SUBSTRING +//%token SUPPORT +//%token SYMMETRIC +//%token SYSID +//%token SYSTEM_P +//%token SYSTEM_USER +//%token TABLE +//%token TABLES +//%token TABLESAMPLE +//%token TABLESPACE +//%token TEMP +//%token TEMPLATE +//%token TEMPORARY +//%token TEXT_P +//%token THEN +//%token TIES +//%token TIME +//%token TIMESTAMP +//%token TO +//%token TRAILING +//%token TRANSACTION +//%token TRANSFORM +//%token TREAT +//%token TRIGGER +//%token TRIM +//%token TRUE_P +//%token TRUNCATE +//%token TRUSTED +//%token TYPE_P +//%token TYPES_P +//%token UESCAPE +//%token UNBOUNDED +//%token UNCOMMITTED +//%token UNENCRYPTED +//%token UNION +//%token UNIQUE +//%token UNKNOWN +//%token UNLISTEN +//%token UNLOGGED +//%token UNTIL +//%token UPDATE +//%token USER +//%token USING +//%token VACUUM +//%token VALID +//%token VALIDATE +//%token VALIDATOR +//%token VALUE_P +//%token VALUES +//%token VARCHAR +//%token VARIADIC +//%token VARYING +//%token VERBOSE +//%token VERSION_P +//%token VIEW +//%token VIEWS +//%token VOLATILE +//%token WHEN +//%token WHERE +//%token WHITESPACE_P +//%token WINDOW +//%token WITH +//%token WITHIN +//%token WITHOUT +//%token WORK +//%token WRAPPER +//%token WRITE +//%token XML_P +//%token XMLATTRIBUTES +//%token XMLCONCAT +//%token XMLELEMENT +//%token XMLEXISTS +//%token XMLFOREST +//%token XMLNAMESPACES +//%token XMLPARSE +//%token XMLPI +//%token XMLROOT +//%token XMLSERIALIZE +//%token XMLTABLE +//%token YEAR_P +//%token YES_P +//%token ZONE +//%token FORMAT_LA +//%token NOT_LA +//%token NULLS_LA +//%token WITH_LA +//%token WITHOUT_LA +//%token MODE_TYPE_NAME +//%token MODE_PLPGSQL_EXPR +//%token MODE_PLPGSQL_ASSIGN1 +//%token MODE_PLPGSQL_ASSIGN2 +//%token MODE_PLPGSQL_ASSIGN3 +//%token '<' +//%token '>' +//%token '=' +//%token '+' +//%token '-' +//%token '*' +//%token '/' +//%token '%' +//%token '^' +//%token UMINUS +//%token '[' +//%token ']' +//%token '(' +//%token ')' +//%token '.' +//%token ';' +//%token ',' +//%token ':' + +%nonassoc /*1*/ SET ; +%left /*2*/ EXCEPT UNION ; +%left /*3*/ INTERSECT ; +%left /*4*/ OR ; +%left /*5*/ AND ; +%right /*6*/ NOT ; +%nonassoc /*7*/ IS ISNULL NOTNULL ; +%nonassoc /*8*/ LESS_EQUALS GREATER_EQUALS NOT_EQUALS '<' '>' '=' ; +%nonassoc /*9*/ BETWEEN ILIKE IN_P LIKE SIMILAR NOT_LA ; +%nonassoc /*10*/ ESCAPE ; +%nonassoc /*11*/ JSON UNIQUE ; +%nonassoc /*12*/ KEYS OBJECT_P SCALAR VALUE_P ; +%nonassoc /*13*/ WITH WITHOUT ; +%nonassoc /*14*/ UNBOUNDED ; +%nonassoc /*15*/ IDENT CUBE FOLLOWING GROUPS PARTITION PRECEDING RANGE ROLLUP ROWS ; +%left /*16*/ Op OPERATOR ; +%left /*17*/ '+' '-' ; +%left /*18*/ '*' '/' '%' ; +%left /*19*/ '^' ; +%left /*20*/ AT ; +%left /*21*/ COLLATE ; +%right /*22*/ UMINUS ; +%left /*23*/ '[' ']' ; +%left /*24*/ '(' ')' ; +%left /*25*/ TYPECAST ; +%left /*26*/ '.' ; +%left /*27*/ CROSS FULL INNER_P JOIN LEFT NATURAL RIGHT ; + +//%start parse_toplevel + +//%% + +parse_toplevel : + /*YYEOF + |*/ stmtmulti + | MODE_TYPE_NAME Typename + | MODE_PLPGSQL_EXPR PLpgSQL_Expr + | MODE_PLPGSQL_ASSIGN1 PLAssignStmt + | MODE_PLPGSQL_ASSIGN2 PLAssignStmt + | MODE_PLPGSQL_ASSIGN3 PLAssignStmt + ; + +stmtmulti : + stmtmulti ';' toplevel_stmt + | toplevel_stmt + ; + +toplevel_stmt : + stmt + | TransactionStmtLegacy + ; + +stmt : + AlterEventTrigStmt + | AlterCollationStmt + | AlterDatabaseStmt + | AlterDatabaseSetStmt + | AlterDefaultPrivilegesStmt + | AlterDomainStmt + | AlterEnumStmt + | AlterExtensionStmt + | AlterExtensionContentsStmt + | AlterFdwStmt + | AlterForeignServerStmt + | AlterFunctionStmt + | AlterGroupStmt + | AlterObjectDependsStmt + | AlterObjectSchemaStmt + | AlterOwnerStmt + | AlterOperatorStmt + | AlterTypeStmt + | AlterPolicyStmt + | AlterSeqStmt + | AlterSystemStmt + | AlterTableStmt + | AlterTblSpcStmt + | AlterCompositeTypeStmt + | AlterPublicationStmt + | AlterRoleSetStmt + | AlterRoleStmt + | AlterSubscriptionStmt + | AlterStatsStmt + | AlterTSConfigurationStmt + | AlterTSDictionaryStmt + | AlterUserMappingStmt + | AnalyzeStmt + | CallStmt + | CheckPointStmt + | ClosePortalStmt + | ClusterStmt + | CommentStmt + | ConstraintsSetStmt + | CopyStmt + | CreateAmStmt + | CreateAsStmt + | CreateAssertionStmt + | CreateCastStmt + | CreateConversionStmt + | CreateDomainStmt + | CreateExtensionStmt + | CreateFdwStmt + | CreateForeignServerStmt + | CreateForeignTableStmt + | CreateFunctionStmt + | CreateGroupStmt + | CreateMatViewStmt + | CreateOpClassStmt + | CreateOpFamilyStmt + | CreatePublicationStmt + | AlterOpFamilyStmt + | CreatePolicyStmt + | CreatePLangStmt + | CreateSchemaStmt + | CreateSeqStmt + | CreateStmt + | CreateSubscriptionStmt + | CreateStatsStmt + | CreateTableSpaceStmt + | CreateTransformStmt + | CreateTrigStmt + | CreateEventTrigStmt + | CreateRoleStmt + | CreateUserStmt + | CreateUserMappingStmt + | CreatedbStmt + | DeallocateStmt + | DeclareCursorStmt + | DefineStmt + | DeleteStmt + | DiscardStmt + | DoStmt + | DropCastStmt + | DropOpClassStmt + | DropOpFamilyStmt + | DropOwnedStmt + | DropStmt + | DropSubscriptionStmt + | DropTableSpaceStmt + | DropTransformStmt + | DropRoleStmt + | DropUserMappingStmt + | DropdbStmt + | ExecuteStmt + | ExplainStmt + | FetchStmt + | GrantStmt + | GrantRoleStmt + | ImportForeignSchemaStmt + | IndexStmt + | InsertStmt + | ListenStmt + | RefreshMatViewStmt + | LoadStmt + | LockStmt + | MergeStmt + | NotifyStmt + | PrepareStmt + | ReassignOwnedStmt + | ReindexStmt + | RemoveAggrStmt + | RemoveFuncStmt + | RemoveOperStmt + | RenameStmt + | RevokeStmt + | RevokeRoleStmt + | RuleStmt + | SecLabelStmt + | SelectStmt + | TransactionStmt + | TruncateStmt + | UnlistenStmt + | UpdateStmt + | VacuumStmt + | VariableResetStmt + | VariableSetStmt + | VariableShowStmt + | ViewStmt + | /*empty*/ + ; + +opt_single_name : + ColId + | /*empty*/ + ; + +opt_qualified_name : + any_name + | /*empty*/ + ; + +opt_concurrently : + CONCURRENTLY + | /*empty*/ + ; + +opt_drop_behavior : + CASCADE + | RESTRICT + | /*empty*/ + ; + +CallStmt : + CALL func_application + ; + +CreateRoleStmt : + CREATE ROLE RoleId opt_with OptRoleList + ; + +opt_with : + WITH /*13N*/ + | WITH_LA + | /*empty*/ + ; + +OptRoleList : + OptRoleList CreateOptRoleElem + | /*empty*/ + ; + +AlterOptRoleList : + AlterOptRoleList AlterOptRoleElem + | /*empty*/ + ; + +AlterOptRoleElem : + PASSWORD Sconst + | PASSWORD NULL_P + | ENCRYPTED PASSWORD Sconst + | UNENCRYPTED PASSWORD Sconst + | INHERIT + | CONNECTION LIMIT SignedIconst + | VALID UNTIL Sconst + | USER role_list + | IDENT /*15N*/ + ; + +CreateOptRoleElem : + AlterOptRoleElem + | SYSID Iconst + | ADMIN role_list + | ROLE role_list + | IN_P /*9N*/ ROLE role_list + | IN_P /*9N*/ GROUP_P role_list + ; + +CreateUserStmt : + CREATE USER RoleId opt_with OptRoleList + ; + +AlterRoleStmt : + ALTER ROLE RoleSpec opt_with AlterOptRoleList + | ALTER USER RoleSpec opt_with AlterOptRoleList + ; + +opt_in_database : + /*empty*/ + | IN_P /*9N*/ DATABASE name + ; + +AlterRoleSetStmt : + ALTER ROLE RoleSpec opt_in_database SetResetClause + | ALTER ROLE ALL opt_in_database SetResetClause + | ALTER USER RoleSpec opt_in_database SetResetClause + | ALTER USER ALL opt_in_database SetResetClause + ; + +DropRoleStmt : + DROP ROLE role_list + | DROP ROLE IF_P EXISTS role_list + | DROP USER role_list + | DROP USER IF_P EXISTS role_list + | DROP GROUP_P role_list + | DROP GROUP_P IF_P EXISTS role_list + ; + +CreateGroupStmt : + CREATE GROUP_P RoleId opt_with OptRoleList + ; + +AlterGroupStmt : + ALTER GROUP_P RoleSpec add_drop USER role_list + ; + +add_drop : + ADD_P + | DROP + ; + +CreateSchemaStmt : + CREATE SCHEMA opt_single_name AUTHORIZATION RoleSpec OptSchemaEltList + | CREATE SCHEMA ColId OptSchemaEltList + | CREATE SCHEMA IF_P NOT /*6R*/ EXISTS opt_single_name AUTHORIZATION RoleSpec OptSchemaEltList + | CREATE SCHEMA IF_P NOT /*6R*/ EXISTS ColId OptSchemaEltList + ; + +OptSchemaEltList : + OptSchemaEltList schema_stmt + | /*empty*/ + ; + +schema_stmt : + CreateStmt + | IndexStmt + | CreateSeqStmt + | CreateTrigStmt + | GrantStmt + | ViewStmt + ; + +VariableSetStmt : + SET /*1N*/ set_rest + | SET /*1N*/ LOCAL set_rest + | SET /*1N*/ SESSION set_rest + ; + +set_rest : + TRANSACTION transaction_mode_list + | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list + | set_rest_more + ; + +generic_set : + var_name TO var_list + | var_name '=' /*8N*/ var_list + | var_name TO DEFAULT + | var_name '=' /*8N*/ DEFAULT + ; + +set_rest_more : + generic_set + | var_name FROM CURRENT_P + | TIME ZONE zone_value + | CATALOG_P Sconst + | SCHEMA Sconst + | NAMES opt_encoding + | ROLE NonReservedWord_or_Sconst + | SESSION AUTHORIZATION NonReservedWord_or_Sconst + | SESSION AUTHORIZATION DEFAULT + | XML_P OPTION document_or_content + | TRANSACTION SNAPSHOT Sconst + ; + +var_name : + ColId + | var_name '.' /*26L*/ ColId + ; + +var_list : + var_value + | var_list ',' var_value + ; + +var_value : + opt_boolean_or_string + | NumericOnly + ; + +iso_level : + READ UNCOMMITTED + | READ COMMITTED + | REPEATABLE READ + | SERIALIZABLE + ; + +opt_boolean_or_string : + TRUE_P + | FALSE_P + | ON + | NonReservedWord_or_Sconst + ; + +zone_value : + Sconst + | IDENT /*15N*/ + | ConstInterval Sconst opt_interval + | ConstInterval '(' /*24L*/ Iconst ')' /*24L*/ Sconst + | NumericOnly + | DEFAULT + | LOCAL + ; + +opt_encoding : + Sconst + | DEFAULT + | /*empty*/ + ; + +NonReservedWord_or_Sconst : + NonReservedWord + | Sconst + ; + +VariableResetStmt : + RESET reset_rest + ; + +reset_rest : + generic_reset + | TIME ZONE + | TRANSACTION ISOLATION LEVEL + | SESSION AUTHORIZATION + ; + +generic_reset : + var_name + | ALL + ; + +SetResetClause : + SET /*1N*/ set_rest + | VariableResetStmt + ; + +FunctionSetResetClause : + SET /*1N*/ set_rest_more + | VariableResetStmt + ; + +VariableShowStmt : + SHOW var_name + | SHOW TIME ZONE + | SHOW TRANSACTION ISOLATION LEVEL + | SHOW SESSION AUTHORIZATION + | SHOW ALL + ; + +ConstraintsSetStmt : + SET /*1N*/ CONSTRAINTS constraints_set_list constraints_set_mode + ; + +constraints_set_list : + ALL + | qualified_name_list + ; + +constraints_set_mode : + DEFERRED + | IMMEDIATE + ; + +CheckPointStmt : + CHECKPOINT + ; + +DiscardStmt : + DISCARD ALL + | DISCARD TEMP + | DISCARD TEMPORARY + | DISCARD PLANS + | DISCARD SEQUENCES + ; + +AlterTableStmt : + ALTER TABLE relation_expr alter_table_cmds + | ALTER TABLE IF_P EXISTS relation_expr alter_table_cmds + | ALTER TABLE relation_expr partition_cmd + | ALTER TABLE IF_P EXISTS relation_expr partition_cmd + | ALTER TABLE ALL IN_P /*9N*/ TABLESPACE name SET /*1N*/ TABLESPACE name opt_nowait + | ALTER TABLE ALL IN_P /*9N*/ TABLESPACE name OWNED BY role_list SET /*1N*/ TABLESPACE name opt_nowait + | ALTER INDEX qualified_name alter_table_cmds + | ALTER INDEX IF_P EXISTS qualified_name alter_table_cmds + | ALTER INDEX qualified_name index_partition_cmd + | ALTER INDEX ALL IN_P /*9N*/ TABLESPACE name SET /*1N*/ TABLESPACE name opt_nowait + | ALTER INDEX ALL IN_P /*9N*/ TABLESPACE name OWNED BY role_list SET /*1N*/ TABLESPACE name opt_nowait + | ALTER SEQUENCE qualified_name alter_table_cmds + | ALTER SEQUENCE IF_P EXISTS qualified_name alter_table_cmds + | ALTER VIEW qualified_name alter_table_cmds + | ALTER VIEW IF_P EXISTS qualified_name alter_table_cmds + | ALTER MATERIALIZED VIEW qualified_name alter_table_cmds + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name alter_table_cmds + | ALTER MATERIALIZED VIEW ALL IN_P /*9N*/ TABLESPACE name SET /*1N*/ TABLESPACE name opt_nowait + | ALTER MATERIALIZED VIEW ALL IN_P /*9N*/ TABLESPACE name OWNED BY role_list SET /*1N*/ TABLESPACE name opt_nowait + | ALTER FOREIGN TABLE relation_expr alter_table_cmds + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr alter_table_cmds + ; + +alter_table_cmds : + alter_table_cmd + | alter_table_cmds ',' alter_table_cmd + ; + +partition_cmd : + ATTACH PARTITION /*15N*/ qualified_name PartitionBoundSpec + | DETACH PARTITION /*15N*/ qualified_name opt_concurrently + | DETACH PARTITION /*15N*/ qualified_name FINALIZE + ; + +index_partition_cmd : + ATTACH PARTITION /*15N*/ qualified_name + ; + +alter_table_cmd : + ADD_P columnDef + | ADD_P IF_P NOT /*6R*/ EXISTS columnDef + | ADD_P COLUMN columnDef + | ADD_P COLUMN IF_P NOT /*6R*/ EXISTS columnDef + | ALTER opt_column ColId alter_column_default + | ALTER opt_column ColId DROP NOT /*6R*/ NULL_P + | ALTER opt_column ColId SET /*1N*/ NOT /*6R*/ NULL_P + | ALTER opt_column ColId DROP EXPRESSION + | ALTER opt_column ColId DROP EXPRESSION IF_P EXISTS + | ALTER opt_column ColId SET /*1N*/ STATISTICS SignedIconst + | ALTER opt_column Iconst SET /*1N*/ STATISTICS SignedIconst + | ALTER opt_column ColId SET /*1N*/ reloptions + | ALTER opt_column ColId RESET reloptions + | ALTER opt_column ColId SET /*1N*/ column_storage + | ALTER opt_column ColId SET /*1N*/ column_compression + | ALTER opt_column ColId ADD_P GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList + | ALTER opt_column ColId alter_identity_column_option_list + | ALTER opt_column ColId DROP IDENTITY_P + | ALTER opt_column ColId DROP IDENTITY_P IF_P EXISTS + | DROP opt_column IF_P EXISTS ColId opt_drop_behavior + | DROP opt_column ColId opt_drop_behavior + | ALTER opt_column ColId opt_set_data TYPE_P Typename opt_collate_clause alter_using + | ALTER opt_column ColId alter_generic_options + | ADD_P TableConstraint + | ALTER CONSTRAINT name ConstraintAttributeSpec + | VALIDATE CONSTRAINT name + | DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior + | DROP CONSTRAINT name opt_drop_behavior + | SET /*1N*/ WITHOUT /*13N*/ OIDS + | CLUSTER ON name + | SET /*1N*/ WITHOUT /*13N*/ CLUSTER + | SET /*1N*/ LOGGED + | SET /*1N*/ UNLOGGED + | ENABLE_P TRIGGER name + | ENABLE_P ALWAYS TRIGGER name + | ENABLE_P REPLICA TRIGGER name + | ENABLE_P TRIGGER ALL + | ENABLE_P TRIGGER USER + | DISABLE_P TRIGGER name + | DISABLE_P TRIGGER ALL + | DISABLE_P TRIGGER USER + | ENABLE_P RULE name + | ENABLE_P ALWAYS RULE name + | ENABLE_P REPLICA RULE name + | DISABLE_P RULE name + | INHERIT qualified_name + | NO INHERIT qualified_name + | OF any_name + | NOT /*6R*/ OF + | OWNER TO RoleSpec + | SET /*1N*/ ACCESS METHOD name + | SET /*1N*/ TABLESPACE name + | SET /*1N*/ reloptions + | RESET reloptions + | REPLICA IDENTITY_P replica_identity + | ENABLE_P ROW LEVEL SECURITY + | DISABLE_P ROW LEVEL SECURITY + | FORCE ROW LEVEL SECURITY + | NO FORCE ROW LEVEL SECURITY + | alter_generic_options + ; + +alter_column_default : + SET /*1N*/ DEFAULT a_expr + | DROP DEFAULT + ; + +opt_collate_clause : + COLLATE /*21L*/ any_name + | /*empty*/ + ; + +alter_using : + USING a_expr + | /*empty*/ + ; + +replica_identity : + NOTHING + | FULL /*27L*/ + | DEFAULT + | USING INDEX name + ; + +reloptions : + '(' /*24L*/ reloption_list ')' /*24L*/ + ; + +opt_reloptions : + WITH /*13N*/ reloptions + | /*empty*/ + ; + +reloption_list : + reloption_elem + | reloption_list ',' reloption_elem + ; + +reloption_elem : + ColLabel '=' /*8N*/ def_arg + | ColLabel + | ColLabel '.' /*26L*/ ColLabel '=' /*8N*/ def_arg + | ColLabel '.' /*26L*/ ColLabel + ; + +alter_identity_column_option_list : + alter_identity_column_option + | alter_identity_column_option_list alter_identity_column_option + ; + +alter_identity_column_option : + RESTART + | RESTART opt_with NumericOnly + | SET /*1N*/ SeqOptElem + | SET /*1N*/ GENERATED generated_when + ; + +PartitionBoundSpec : + FOR VALUES WITH /*13N*/ '(' /*24L*/ hash_partbound ')' /*24L*/ + | FOR VALUES IN_P /*9N*/ '(' /*24L*/ expr_list ')' /*24L*/ + | FOR VALUES FROM '(' /*24L*/ expr_list ')' /*24L*/ TO '(' /*24L*/ expr_list ')' /*24L*/ + | DEFAULT + ; + +hash_partbound_elem : + NonReservedWord Iconst + ; + +hash_partbound : + hash_partbound_elem + | hash_partbound ',' hash_partbound_elem + ; + +AlterCompositeTypeStmt : + ALTER TYPE_P any_name alter_type_cmds + ; + +alter_type_cmds : + alter_type_cmd + | alter_type_cmds ',' alter_type_cmd + ; + +alter_type_cmd : + ADD_P ATTRIBUTE TableFuncElement opt_drop_behavior + | DROP ATTRIBUTE IF_P EXISTS ColId opt_drop_behavior + | DROP ATTRIBUTE ColId opt_drop_behavior + | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_collate_clause opt_drop_behavior + ; + +ClosePortalStmt : + CLOSE cursor_name + | CLOSE ALL + ; + +CopyStmt : + COPY opt_binary qualified_name opt_column_list copy_from opt_program copy_file_name copy_delimiter opt_with copy_options where_clause + | COPY '(' /*24L*/ PreparableStmt ')' /*24L*/ TO opt_program copy_file_name opt_with copy_options + ; + +copy_from : + FROM + | TO + ; + +opt_program : + PROGRAM + | /*empty*/ + ; + +copy_file_name : + Sconst + | STDIN + | STDOUT + ; + +copy_options : + copy_opt_list + | '(' /*24L*/ copy_generic_opt_list ')' /*24L*/ + ; + +copy_opt_list : + copy_opt_list copy_opt_item + | /*empty*/ + ; + +copy_opt_item : + BINARY + | FREEZE + | DELIMITER opt_as Sconst + | NULL_P opt_as Sconst + | CSV + | HEADER_P + | QUOTE opt_as Sconst + | ESCAPE /*10N*/ opt_as Sconst + | FORCE QUOTE columnList + | FORCE QUOTE '*' /*18L*/ + | FORCE NOT /*6R*/ NULL_P columnList + | FORCE NULL_P columnList + | ENCODING Sconst + ; + +opt_binary : + BINARY + | /*empty*/ + ; + +copy_delimiter : + opt_using DELIMITERS Sconst + | /*empty*/ + ; + +opt_using : + USING + | /*empty*/ + ; + +copy_generic_opt_list : + copy_generic_opt_elem + | copy_generic_opt_list ',' copy_generic_opt_elem + ; + +copy_generic_opt_elem : + ColLabel copy_generic_opt_arg + ; + +copy_generic_opt_arg : + opt_boolean_or_string + | NumericOnly + | '*' /*18L*/ + | '(' /*24L*/ copy_generic_opt_arg_list ')' /*24L*/ + | /*empty*/ + ; + +copy_generic_opt_arg_list : + copy_generic_opt_arg_list_item + | copy_generic_opt_arg_list ',' copy_generic_opt_arg_list_item + ; + +copy_generic_opt_arg_list_item : + opt_boolean_or_string + ; + +CreateStmt : + CREATE OptTemp TABLE qualified_name '(' /*24L*/ OptTableElementList ')' /*24L*/ OptInherit OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS qualified_name '(' /*24L*/ OptTableElementList ')' /*24L*/ OptInherit OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE qualified_name OF any_name OptTypedTableElementList OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS qualified_name OF any_name OptTypedTableElementList OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE qualified_name PARTITION /*15N*/ OF qualified_name OptTypedTableElementList PartitionBoundSpec OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS qualified_name PARTITION /*15N*/ OF qualified_name OptTypedTableElementList PartitionBoundSpec OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace + ; + +OptTemp : + TEMPORARY + | TEMP + | LOCAL TEMPORARY + | LOCAL TEMP + | GLOBAL TEMPORARY + | GLOBAL TEMP + | UNLOGGED + | /*empty*/ + ; + +OptTableElementList : + TableElementList + | /*empty*/ + ; + +OptTypedTableElementList : + '(' /*24L*/ TypedTableElementList ')' /*24L*/ + | /*empty*/ + ; + +TableElementList : + TableElement + | TableElementList ',' TableElement + ; + +TypedTableElementList : + TypedTableElement + | TypedTableElementList ',' TypedTableElement + ; + +TableElement : + columnDef + | TableLikeClause + | TableConstraint + ; + +TypedTableElement : + columnOptions + | TableConstraint + ; + +columnDef : + ColId Typename opt_column_storage opt_column_compression create_generic_options ColQualList + ; + +columnOptions : + ColId ColQualList + | ColId WITH /*13N*/ OPTIONS ColQualList + ; + +column_compression : + COMPRESSION ColId + | COMPRESSION DEFAULT + ; + +opt_column_compression : + column_compression + | /*empty*/ + ; + +column_storage : + STORAGE ColId + | STORAGE DEFAULT + ; + +opt_column_storage : + column_storage + | /*empty*/ + ; + +ColQualList : + ColQualList ColConstraint + | /*empty*/ + ; + +ColConstraint : + CONSTRAINT name ColConstraintElem + | ColConstraintElem + | ConstraintAttr + | COLLATE /*21L*/ any_name + ; + +ColConstraintElem : + NOT /*6R*/ NULL_P + | NULL_P + | UNIQUE /*11N*/ opt_unique_null_treatment opt_definition OptConsTableSpace + | PRIMARY KEY opt_definition OptConsTableSpace + | CHECK '(' /*24L*/ a_expr ')' /*24L*/ opt_no_inherit + | DEFAULT b_expr + | GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList + | GENERATED generated_when AS '(' /*24L*/ a_expr ')' /*24L*/ STORED + | REFERENCES qualified_name opt_column_list key_match key_actions + ; + +opt_unique_null_treatment : + NULLS_P DISTINCT + | NULLS_P NOT /*6R*/ DISTINCT + | /*empty*/ + ; + +generated_when : + ALWAYS + | BY DEFAULT + ; + +ConstraintAttr : + DEFERRABLE + | NOT /*6R*/ DEFERRABLE + | INITIALLY DEFERRED + | INITIALLY IMMEDIATE + ; + +TableLikeClause : + LIKE /*9N*/ qualified_name TableLikeOptionList + ; + +TableLikeOptionList : + TableLikeOptionList INCLUDING TableLikeOption + | TableLikeOptionList EXCLUDING TableLikeOption + | /*empty*/ + ; + +TableLikeOption : + COMMENTS + | COMPRESSION + | CONSTRAINTS + | DEFAULTS + | IDENTITY_P + | GENERATED + | INDEXES + | STATISTICS + | STORAGE + | ALL + ; + +TableConstraint : + CONSTRAINT name ConstraintElem + | ConstraintElem + ; + +ConstraintElem : + CHECK '(' /*24L*/ a_expr ')' /*24L*/ ConstraintAttributeSpec + | UNIQUE /*11N*/ opt_unique_null_treatment '(' /*24L*/ columnList ')' /*24L*/ opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec + | UNIQUE /*11N*/ ExistingIndex ConstraintAttributeSpec + | PRIMARY KEY '(' /*24L*/ columnList ')' /*24L*/ opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec + | PRIMARY KEY ExistingIndex ConstraintAttributeSpec + | EXCLUDE access_method_clause '(' /*24L*/ ExclusionConstraintList ')' /*24L*/ opt_c_include opt_definition OptConsTableSpace OptWhereClause ConstraintAttributeSpec + | FOREIGN KEY '(' /*24L*/ columnList ')' /*24L*/ REFERENCES qualified_name opt_column_list key_match key_actions ConstraintAttributeSpec + ; + +opt_no_inherit : + NO INHERIT + | /*empty*/ + ; + +opt_column_list : + '(' /*24L*/ columnList ')' /*24L*/ + | /*empty*/ + ; + +columnList : + columnElem + | columnList ',' columnElem + ; + +columnElem : + ColId + ; + +opt_c_include : + INCLUDE '(' /*24L*/ columnList ')' /*24L*/ + | /*empty*/ + ; + +key_match : + MATCH FULL /*27L*/ + | MATCH PARTIAL + | MATCH SIMPLE + | /*empty*/ + ; + +ExclusionConstraintList : + ExclusionConstraintElem + | ExclusionConstraintList ',' ExclusionConstraintElem + ; + +ExclusionConstraintElem : + index_elem WITH /*13N*/ any_operator + | index_elem WITH /*13N*/ OPERATOR /*16L*/ '(' /*24L*/ any_operator ')' /*24L*/ + ; + +OptWhereClause : + WHERE '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +key_actions : + key_update + | key_delete + | key_update key_delete + | key_delete key_update + | /*empty*/ + ; + +key_update : + ON UPDATE key_action + ; + +key_delete : + ON DELETE_P key_action + ; + +key_action : + NO ACTION + | RESTRICT + | CASCADE + | SET /*1N*/ NULL_P opt_column_list + | SET /*1N*/ DEFAULT opt_column_list + ; + +OptInherit : + INHERITS '(' /*24L*/ qualified_name_list ')' /*24L*/ + | /*empty*/ + ; + +OptPartitionSpec : + PartitionSpec + | /*empty*/ + ; + +PartitionSpec : + PARTITION /*15N*/ BY ColId '(' /*24L*/ part_params ')' /*24L*/ + ; + +part_params : + part_elem + | part_params ',' part_elem + ; + +part_elem : + ColId opt_collate opt_qualified_name + | func_expr_windowless opt_collate opt_qualified_name + | '(' /*24L*/ a_expr ')' /*24L*/ opt_collate opt_qualified_name + ; + +table_access_method_clause : + USING name + | /*empty*/ + ; + +OptWith : + WITH /*13N*/ reloptions + | WITHOUT /*13N*/ OIDS + | /*empty*/ + ; + +OnCommitOption : + ON COMMIT DROP + | ON COMMIT DELETE_P ROWS /*15N*/ + | ON COMMIT PRESERVE ROWS /*15N*/ + | /*empty*/ + ; + +OptTableSpace : + TABLESPACE name + | /*empty*/ + ; + +OptConsTableSpace : + USING INDEX TABLESPACE name + | /*empty*/ + ; + +ExistingIndex : + USING INDEX name + ; + +CreateStatsStmt : + CREATE STATISTICS opt_qualified_name opt_name_list ON stats_params FROM from_list + | CREATE STATISTICS IF_P NOT /*6R*/ EXISTS any_name opt_name_list ON stats_params FROM from_list + ; + +stats_params : + stats_param + | stats_params ',' stats_param + ; + +stats_param : + ColId + | func_expr_windowless + | '(' /*24L*/ a_expr ')' /*24L*/ + ; + +AlterStatsStmt : + ALTER STATISTICS any_name SET /*1N*/ STATISTICS SignedIconst + | ALTER STATISTICS IF_P EXISTS any_name SET /*1N*/ STATISTICS SignedIconst + ; + +CreateAsStmt : + CREATE OptTemp TABLE create_as_target AS SelectStmt opt_with_data + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS create_as_target AS SelectStmt opt_with_data + ; + +create_as_target : + qualified_name opt_column_list table_access_method_clause OptWith OnCommitOption OptTableSpace + ; + +opt_with_data : + WITH /*13N*/ DATA_P + | WITH /*13N*/ NO DATA_P + | /*empty*/ + ; + +CreateMatViewStmt : + CREATE OptNoLog MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data + | CREATE OptNoLog MATERIALIZED VIEW IF_P NOT /*6R*/ EXISTS create_mv_target AS SelectStmt opt_with_data + ; + +create_mv_target : + qualified_name opt_column_list table_access_method_clause opt_reloptions OptTableSpace + ; + +OptNoLog : + UNLOGGED + | /*empty*/ + ; + +RefreshMatViewStmt : + REFRESH MATERIALIZED VIEW opt_concurrently qualified_name opt_with_data + ; + +CreateSeqStmt : + CREATE OptTemp SEQUENCE qualified_name OptSeqOptList + | CREATE OptTemp SEQUENCE IF_P NOT /*6R*/ EXISTS qualified_name OptSeqOptList + ; + +AlterSeqStmt : + ALTER SEQUENCE qualified_name SeqOptList + | ALTER SEQUENCE IF_P EXISTS qualified_name SeqOptList + ; + +OptSeqOptList : + SeqOptList + | /*empty*/ + ; + +OptParenthesizedSeqOptList : + '(' /*24L*/ SeqOptList ')' /*24L*/ + | /*empty*/ + ; + +SeqOptList : + SeqOptElem + | SeqOptList SeqOptElem + ; + +SeqOptElem : + AS SimpleTypename + | CACHE NumericOnly + | CYCLE + | NO CYCLE + | INCREMENT opt_by NumericOnly + | MAXVALUE NumericOnly + | MINVALUE NumericOnly + | NO MAXVALUE + | NO MINVALUE + | OWNED BY any_name + | SEQUENCE NAME_P any_name + | START opt_with NumericOnly + | RESTART + | RESTART opt_with NumericOnly + ; + +opt_by : + BY + | /*empty*/ + ; + +NumericOnly : + FCONST + | '+' /*17L*/ FCONST + | '-' /*17L*/ FCONST + | SignedIconst + ; + +NumericOnly_list : + NumericOnly + | NumericOnly_list ',' NumericOnly + ; + +CreatePLangStmt : + CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE name + | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE name HANDLER handler_name opt_inline_handler opt_validator + ; + +opt_trusted : + TRUSTED + | /*empty*/ + ; + +handler_name : + name + | name attrs + ; + +opt_inline_handler : + INLINE_P handler_name + | /*empty*/ + ; + +validator_clause : + VALIDATOR handler_name + | NO VALIDATOR + ; + +opt_validator : + validator_clause + | /*empty*/ + ; + +opt_procedural : + PROCEDURAL + | /*empty*/ + ; + +CreateTableSpaceStmt : + CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst opt_reloptions + ; + +OptTableSpaceOwner : + OWNER RoleSpec + | /*empty*/ + ; + +DropTableSpaceStmt : + DROP TABLESPACE name + | DROP TABLESPACE IF_P EXISTS name + ; + +CreateExtensionStmt : + CREATE EXTENSION name opt_with create_extension_opt_list + | CREATE EXTENSION IF_P NOT /*6R*/ EXISTS name opt_with create_extension_opt_list + ; + +create_extension_opt_list : + create_extension_opt_list create_extension_opt_item + | /*empty*/ + ; + +create_extension_opt_item : + SCHEMA name + | VERSION_P NonReservedWord_or_Sconst + | FROM NonReservedWord_or_Sconst + | CASCADE + ; + +AlterExtensionStmt : + ALTER EXTENSION name UPDATE alter_extension_opt_list + ; + +alter_extension_opt_list : + alter_extension_opt_list alter_extension_opt_item + | /*empty*/ + ; + +alter_extension_opt_item : + TO NonReservedWord_or_Sconst + ; + +AlterExtensionContentsStmt : + ALTER EXTENSION name add_drop object_type_name name + | ALTER EXTENSION name add_drop object_type_any_name any_name + | ALTER EXTENSION name add_drop AGGREGATE aggregate_with_argtypes + | ALTER EXTENSION name add_drop CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ + | ALTER EXTENSION name add_drop DOMAIN_P Typename + | ALTER EXTENSION name add_drop FUNCTION function_with_argtypes + | ALTER EXTENSION name add_drop OPERATOR /*16L*/ operator_with_argtypes + | ALTER EXTENSION name add_drop OPERATOR /*16L*/ CLASS any_name USING name + | ALTER EXTENSION name add_drop OPERATOR /*16L*/ FAMILY any_name USING name + | ALTER EXTENSION name add_drop PROCEDURE function_with_argtypes + | ALTER EXTENSION name add_drop ROUTINE function_with_argtypes + | ALTER EXTENSION name add_drop TRANSFORM FOR Typename LANGUAGE name + | ALTER EXTENSION name add_drop TYPE_P Typename + ; + +CreateFdwStmt : + CREATE FOREIGN DATA_P WRAPPER name opt_fdw_options create_generic_options + ; + +fdw_option : + HANDLER handler_name + | NO HANDLER + | VALIDATOR handler_name + | NO VALIDATOR + ; + +fdw_options : + fdw_option + | fdw_options fdw_option + ; + +opt_fdw_options : + fdw_options + | /*empty*/ + ; + +AlterFdwStmt : + ALTER FOREIGN DATA_P WRAPPER name opt_fdw_options alter_generic_options + | ALTER FOREIGN DATA_P WRAPPER name fdw_options + ; + +create_generic_options : + OPTIONS '(' /*24L*/ generic_option_list ')' /*24L*/ + | /*empty*/ + ; + +generic_option_list : + generic_option_elem + | generic_option_list ',' generic_option_elem + ; + +alter_generic_options : + OPTIONS '(' /*24L*/ alter_generic_option_list ')' /*24L*/ + ; + +alter_generic_option_list : + alter_generic_option_elem + | alter_generic_option_list ',' alter_generic_option_elem + ; + +alter_generic_option_elem : + generic_option_elem + | SET /*1N*/ generic_option_elem + | ADD_P generic_option_elem + | DROP generic_option_name + ; + +generic_option_elem : + generic_option_name generic_option_arg + ; + +generic_option_name : + ColLabel + ; + +generic_option_arg : + Sconst + ; + +CreateForeignServerStmt : + CREATE SERVER name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options + | CREATE SERVER IF_P NOT /*6R*/ EXISTS name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options + ; + +opt_type : + TYPE_P Sconst + | /*empty*/ + ; + +foreign_server_version : + VERSION_P Sconst + | VERSION_P NULL_P + ; + +opt_foreign_server_version : + foreign_server_version + | /*empty*/ + ; + +AlterForeignServerStmt : + ALTER SERVER name foreign_server_version alter_generic_options + | ALTER SERVER name foreign_server_version + | ALTER SERVER name alter_generic_options + ; + +CreateForeignTableStmt : + CREATE FOREIGN TABLE qualified_name '(' /*24L*/ OptTableElementList ')' /*24L*/ OptInherit SERVER name create_generic_options + | CREATE FOREIGN TABLE IF_P NOT /*6R*/ EXISTS qualified_name '(' /*24L*/ OptTableElementList ')' /*24L*/ OptInherit SERVER name create_generic_options + | CREATE FOREIGN TABLE qualified_name PARTITION /*15N*/ OF qualified_name OptTypedTableElementList PartitionBoundSpec SERVER name create_generic_options + | CREATE FOREIGN TABLE IF_P NOT /*6R*/ EXISTS qualified_name PARTITION /*15N*/ OF qualified_name OptTypedTableElementList PartitionBoundSpec SERVER name create_generic_options + ; + +ImportForeignSchemaStmt : + IMPORT_P FOREIGN SCHEMA name import_qualification FROM SERVER name INTO name create_generic_options + ; + +import_qualification_type : + LIMIT TO + | EXCEPT /*2L*/ + ; + +import_qualification : + import_qualification_type '(' /*24L*/ relation_expr_list ')' /*24L*/ + | /*empty*/ + ; + +CreateUserMappingStmt : + CREATE USER MAPPING FOR auth_ident SERVER name create_generic_options + | CREATE USER MAPPING IF_P NOT /*6R*/ EXISTS FOR auth_ident SERVER name create_generic_options + ; + +auth_ident : + RoleSpec + | USER + ; + +DropUserMappingStmt : + DROP USER MAPPING FOR auth_ident SERVER name + | DROP USER MAPPING IF_P EXISTS FOR auth_ident SERVER name + ; + +AlterUserMappingStmt : + ALTER USER MAPPING FOR auth_ident SERVER name alter_generic_options + ; + +CreatePolicyStmt : + CREATE POLICY name ON qualified_name RowSecurityDefaultPermissive RowSecurityDefaultForCmd RowSecurityDefaultToRole RowSecurityOptionalExpr RowSecurityOptionalWithCheck + ; + +AlterPolicyStmt : + ALTER POLICY name ON qualified_name RowSecurityOptionalToRole RowSecurityOptionalExpr RowSecurityOptionalWithCheck + ; + +RowSecurityOptionalExpr : + USING '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +RowSecurityOptionalWithCheck : + WITH /*13N*/ CHECK '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +RowSecurityDefaultToRole : + TO role_list + | /*empty*/ + ; + +RowSecurityOptionalToRole : + TO role_list + | /*empty*/ + ; + +RowSecurityDefaultPermissive : + AS IDENT /*15N*/ + | /*empty*/ + ; + +RowSecurityDefaultForCmd : + FOR row_security_cmd + | /*empty*/ + ; + +row_security_cmd : + ALL + | SELECT + | INSERT + | UPDATE + | DELETE_P + ; + +CreateAmStmt : + CREATE ACCESS METHOD name TYPE_P am_type HANDLER handler_name + ; + +am_type : + INDEX + | TABLE + ; + +CreateTrigStmt : + CREATE opt_or_replace TRIGGER name TriggerActionTime TriggerEvents ON qualified_name TriggerReferencing TriggerForSpec TriggerWhen EXECUTE FUNCTION_or_PROCEDURE func_name '(' /*24L*/ TriggerFuncArgs ')' /*24L*/ + | CREATE opt_or_replace CONSTRAINT TRIGGER name AFTER TriggerEvents ON qualified_name OptConstrFromTable ConstraintAttributeSpec FOR EACH ROW TriggerWhen EXECUTE FUNCTION_or_PROCEDURE func_name '(' /*24L*/ TriggerFuncArgs ')' /*24L*/ + ; + +TriggerActionTime : + BEFORE + | AFTER + | INSTEAD OF + ; + +TriggerEvents : + TriggerOneEvent + | TriggerEvents OR /*4L*/ TriggerOneEvent + ; + +TriggerOneEvent : + INSERT + | DELETE_P + | UPDATE + | UPDATE OF columnList + | TRUNCATE + ; + +TriggerReferencing : + REFERENCING TriggerTransitions + | /*empty*/ + ; + +TriggerTransitions : + TriggerTransition + | TriggerTransitions TriggerTransition + ; + +TriggerTransition : + TransitionOldOrNew TransitionRowOrTable opt_as TransitionRelName + ; + +TransitionOldOrNew : + NEW + | OLD + ; + +TransitionRowOrTable : + TABLE + | ROW + ; + +TransitionRelName : + ColId + ; + +TriggerForSpec : + FOR TriggerForOptEach TriggerForType + | /*empty*/ + ; + +TriggerForOptEach : + EACH + | /*empty*/ + ; + +TriggerForType : + ROW + | STATEMENT + ; + +TriggerWhen : + WHEN '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +FUNCTION_or_PROCEDURE : + FUNCTION + | PROCEDURE + ; + +TriggerFuncArgs : + TriggerFuncArg + | TriggerFuncArgs ',' TriggerFuncArg + | /*empty*/ + ; + +TriggerFuncArg : + Iconst + | FCONST + | Sconst + | ColLabel + ; + +OptConstrFromTable : + FROM qualified_name + | /*empty*/ + ; + +ConstraintAttributeSpec : + /*empty*/ + | ConstraintAttributeSpec ConstraintAttributeElem + ; + +ConstraintAttributeElem : + NOT /*6R*/ DEFERRABLE + | DEFERRABLE + | INITIALLY IMMEDIATE + | INITIALLY DEFERRED + | NOT /*6R*/ VALID + | NO INHERIT + ; + +CreateEventTrigStmt : + CREATE EVENT TRIGGER name ON ColLabel EXECUTE FUNCTION_or_PROCEDURE func_name '(' /*24L*/ ')' /*24L*/ + | CREATE EVENT TRIGGER name ON ColLabel WHEN event_trigger_when_list EXECUTE FUNCTION_or_PROCEDURE func_name '(' /*24L*/ ')' /*24L*/ + ; + +event_trigger_when_list : + event_trigger_when_item + | event_trigger_when_list AND /*5L*/ event_trigger_when_item + ; + +event_trigger_when_item : + ColId IN_P /*9N*/ '(' /*24L*/ event_trigger_value_list ')' /*24L*/ + ; + +event_trigger_value_list : + SCONST + | event_trigger_value_list ',' SCONST + ; + +AlterEventTrigStmt : + ALTER EVENT TRIGGER name enable_trigger + ; + +enable_trigger : + ENABLE_P + | ENABLE_P REPLICA + | ENABLE_P ALWAYS + | DISABLE_P + ; + +CreateAssertionStmt : + CREATE ASSERTION any_name CHECK '(' /*24L*/ a_expr ')' /*24L*/ ConstraintAttributeSpec + ; + +DefineStmt : + CREATE opt_or_replace AGGREGATE func_name aggr_args definition + | CREATE opt_or_replace AGGREGATE func_name old_aggr_definition + | CREATE OPERATOR /*16L*/ any_operator definition + | CREATE TYPE_P any_name definition + | CREATE TYPE_P any_name + | CREATE TYPE_P any_name AS '(' /*24L*/ OptTableFuncElementList ')' /*24L*/ + | CREATE TYPE_P any_name AS ENUM_P '(' /*24L*/ opt_enum_val_list ')' /*24L*/ + | CREATE TYPE_P any_name AS RANGE /*15N*/ definition + | CREATE TEXT_P SEARCH PARSER any_name definition + | CREATE TEXT_P SEARCH DICTIONARY any_name definition + | CREATE TEXT_P SEARCH TEMPLATE any_name definition + | CREATE TEXT_P SEARCH CONFIGURATION any_name definition + | CREATE COLLATION any_name definition + | CREATE COLLATION IF_P NOT /*6R*/ EXISTS any_name definition + | CREATE COLLATION any_name FROM any_name + | CREATE COLLATION IF_P NOT /*6R*/ EXISTS any_name FROM any_name + ; + +definition : + '(' /*24L*/ def_list ')' /*24L*/ + ; + +def_list : + def_elem + | def_list ',' def_elem + ; + +def_elem : + ColLabel '=' /*8N*/ def_arg + | ColLabel + ; + +def_arg : + func_type + | reserved_keyword + | qual_all_Op + | NumericOnly + | Sconst + | NONE + ; + +old_aggr_definition : + '(' /*24L*/ old_aggr_list ')' /*24L*/ + ; + +old_aggr_list : + old_aggr_elem + | old_aggr_list ',' old_aggr_elem + ; + +old_aggr_elem : + IDENT /*15N*/ '=' /*8N*/ def_arg + ; + +opt_enum_val_list : + enum_val_list + | /*empty*/ + ; + +enum_val_list : + Sconst + | enum_val_list ',' Sconst + ; + +AlterEnumStmt : + ALTER TYPE_P any_name ADD_P VALUE_P /*12N*/ opt_if_not_exists Sconst + | ALTER TYPE_P any_name ADD_P VALUE_P /*12N*/ opt_if_not_exists Sconst BEFORE Sconst + | ALTER TYPE_P any_name ADD_P VALUE_P /*12N*/ opt_if_not_exists Sconst AFTER Sconst + | ALTER TYPE_P any_name RENAME VALUE_P /*12N*/ Sconst TO Sconst + ; + +opt_if_not_exists : + IF_P NOT /*6R*/ EXISTS + | /*empty*/ + ; + +CreateOpClassStmt : + CREATE OPERATOR /*16L*/ CLASS any_name opt_default FOR TYPE_P Typename USING name opt_opfamily AS opclass_item_list + ; + +opclass_item_list : + opclass_item + | opclass_item_list ',' opclass_item + ; + +opclass_item : + OPERATOR /*16L*/ Iconst any_operator opclass_purpose opt_recheck + | OPERATOR /*16L*/ Iconst operator_with_argtypes opclass_purpose opt_recheck + | FUNCTION Iconst function_with_argtypes + | FUNCTION Iconst '(' /*24L*/ type_list ')' /*24L*/ function_with_argtypes + | STORAGE Typename + ; + +opt_default : + DEFAULT + | /*empty*/ + ; + +opt_opfamily : + FAMILY any_name + | /*empty*/ + ; + +opclass_purpose : + FOR SEARCH + | FOR ORDER BY any_name + | /*empty*/ + ; + +opt_recheck : + RECHECK + | /*empty*/ + ; + +CreateOpFamilyStmt : + CREATE OPERATOR /*16L*/ FAMILY any_name USING name + ; + +AlterOpFamilyStmt : + ALTER OPERATOR /*16L*/ FAMILY any_name USING name ADD_P opclass_item_list + | ALTER OPERATOR /*16L*/ FAMILY any_name USING name DROP opclass_drop_list + ; + +opclass_drop_list : + opclass_drop + | opclass_drop_list ',' opclass_drop + ; + +opclass_drop : + OPERATOR /*16L*/ Iconst '(' /*24L*/ type_list ')' /*24L*/ + | FUNCTION Iconst '(' /*24L*/ type_list ')' /*24L*/ + ; + +DropOpClassStmt : + DROP OPERATOR /*16L*/ CLASS any_name USING name opt_drop_behavior + | DROP OPERATOR /*16L*/ CLASS IF_P EXISTS any_name USING name opt_drop_behavior + ; + +DropOpFamilyStmt : + DROP OPERATOR /*16L*/ FAMILY any_name USING name opt_drop_behavior + | DROP OPERATOR /*16L*/ FAMILY IF_P EXISTS any_name USING name opt_drop_behavior + ; + +DropOwnedStmt : + DROP OWNED BY role_list opt_drop_behavior + ; + +ReassignOwnedStmt : + REASSIGN OWNED BY role_list TO RoleSpec + ; + +DropStmt : + DROP object_type_any_name IF_P EXISTS any_name_list opt_drop_behavior + | DROP object_type_any_name any_name_list opt_drop_behavior + | DROP drop_type_name IF_P EXISTS name_list opt_drop_behavior + | DROP drop_type_name name_list opt_drop_behavior + | DROP object_type_name_on_any_name name ON any_name opt_drop_behavior + | DROP object_type_name_on_any_name IF_P EXISTS name ON any_name opt_drop_behavior + | DROP TYPE_P type_name_list opt_drop_behavior + | DROP TYPE_P IF_P EXISTS type_name_list opt_drop_behavior + | DROP DOMAIN_P type_name_list opt_drop_behavior + | DROP DOMAIN_P IF_P EXISTS type_name_list opt_drop_behavior + | DROP INDEX CONCURRENTLY any_name_list opt_drop_behavior + | DROP INDEX CONCURRENTLY IF_P EXISTS any_name_list opt_drop_behavior + ; + +object_type_any_name : + TABLE + | SEQUENCE + | VIEW + | MATERIALIZED VIEW + | INDEX + | FOREIGN TABLE + | COLLATION + | CONVERSION_P + | STATISTICS + | TEXT_P SEARCH PARSER + | TEXT_P SEARCH DICTIONARY + | TEXT_P SEARCH TEMPLATE + | TEXT_P SEARCH CONFIGURATION + ; + +object_type_name : + drop_type_name + | DATABASE + | ROLE + | SUBSCRIPTION + | TABLESPACE + ; + +drop_type_name : + ACCESS METHOD + | EVENT TRIGGER + | EXTENSION + | FOREIGN DATA_P WRAPPER + | opt_procedural LANGUAGE + | PUBLICATION + | SCHEMA + | SERVER + ; + +object_type_name_on_any_name : + POLICY + | RULE + | TRIGGER + ; + +any_name_list : + any_name + | any_name_list ',' any_name + ; + +any_name : + ColId + | ColId attrs + ; + +attrs : + '.' /*26L*/ attr_name + | attrs '.' /*26L*/ attr_name + ; + +type_name_list : + Typename + | type_name_list ',' Typename + ; + +TruncateStmt : + TRUNCATE opt_table relation_expr_list opt_restart_seqs opt_drop_behavior + ; + +opt_restart_seqs : + CONTINUE_P IDENTITY_P + | RESTART IDENTITY_P + | /*empty*/ + ; + +CommentStmt : + COMMENT ON object_type_any_name any_name IS /*7N*/ comment_text + | COMMENT ON COLUMN any_name IS /*7N*/ comment_text + | COMMENT ON object_type_name name IS /*7N*/ comment_text + | COMMENT ON TYPE_P Typename IS /*7N*/ comment_text + | COMMENT ON DOMAIN_P Typename IS /*7N*/ comment_text + | COMMENT ON AGGREGATE aggregate_with_argtypes IS /*7N*/ comment_text + | COMMENT ON FUNCTION function_with_argtypes IS /*7N*/ comment_text + | COMMENT ON OPERATOR /*16L*/ operator_with_argtypes IS /*7N*/ comment_text + | COMMENT ON CONSTRAINT name ON any_name IS /*7N*/ comment_text + | COMMENT ON CONSTRAINT name ON DOMAIN_P any_name IS /*7N*/ comment_text + | COMMENT ON object_type_name_on_any_name name ON any_name IS /*7N*/ comment_text + | COMMENT ON PROCEDURE function_with_argtypes IS /*7N*/ comment_text + | COMMENT ON ROUTINE function_with_argtypes IS /*7N*/ comment_text + | COMMENT ON TRANSFORM FOR Typename LANGUAGE name IS /*7N*/ comment_text + | COMMENT ON OPERATOR /*16L*/ CLASS any_name USING name IS /*7N*/ comment_text + | COMMENT ON OPERATOR /*16L*/ FAMILY any_name USING name IS /*7N*/ comment_text + | COMMENT ON LARGE_P OBJECT_P /*12N*/ NumericOnly IS /*7N*/ comment_text + | COMMENT ON CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ IS /*7N*/ comment_text + ; + +comment_text : + Sconst + | NULL_P + ; + +SecLabelStmt : + SECURITY LABEL opt_provider ON object_type_any_name any_name IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON COLUMN any_name IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON object_type_name name IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON TYPE_P Typename IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON DOMAIN_P Typename IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON AGGREGATE aggregate_with_argtypes IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON FUNCTION function_with_argtypes IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON LARGE_P OBJECT_P /*12N*/ NumericOnly IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON PROCEDURE function_with_argtypes IS /*7N*/ security_label + | SECURITY LABEL opt_provider ON ROUTINE function_with_argtypes IS /*7N*/ security_label + ; + +opt_provider : + FOR NonReservedWord_or_Sconst + | /*empty*/ + ; + +security_label : + Sconst + | NULL_P + ; + +FetchStmt : + FETCH fetch_args + | MOVE fetch_args + ; + +fetch_args : + cursor_name + | from_in cursor_name + | NEXT opt_from_in cursor_name + | PRIOR opt_from_in cursor_name + | FIRST_P opt_from_in cursor_name + | LAST_P opt_from_in cursor_name + | ABSOLUTE_P SignedIconst opt_from_in cursor_name + | RELATIVE_P SignedIconst opt_from_in cursor_name + | SignedIconst opt_from_in cursor_name + | ALL opt_from_in cursor_name + | FORWARD opt_from_in cursor_name + | FORWARD SignedIconst opt_from_in cursor_name + | FORWARD ALL opt_from_in cursor_name + | BACKWARD opt_from_in cursor_name + | BACKWARD SignedIconst opt_from_in cursor_name + | BACKWARD ALL opt_from_in cursor_name + ; + +from_in : + FROM + | IN_P /*9N*/ + ; + +opt_from_in : + from_in + | /*empty*/ + ; + +GrantStmt : + GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option opt_granted_by + ; + +RevokeStmt : + REVOKE privileges ON privilege_target FROM grantee_list opt_granted_by opt_drop_behavior + | REVOKE GRANT OPTION FOR privileges ON privilege_target FROM grantee_list opt_granted_by opt_drop_behavior + ; + +privileges : + privilege_list + | ALL + | ALL PRIVILEGES + | ALL '(' /*24L*/ columnList ')' /*24L*/ + | ALL PRIVILEGES '(' /*24L*/ columnList ')' /*24L*/ + ; + +privilege_list : + privilege + | privilege_list ',' privilege + ; + +privilege : + SELECT opt_column_list + | REFERENCES opt_column_list + | CREATE opt_column_list + | ALTER SYSTEM_P + | ColId opt_column_list + ; + +parameter_name_list : + parameter_name + | parameter_name_list ',' parameter_name + ; + +parameter_name : + ColId + | parameter_name '.' /*26L*/ ColId + ; + +privilege_target : + qualified_name_list + | TABLE qualified_name_list + | SEQUENCE qualified_name_list + | FOREIGN DATA_P WRAPPER name_list + | FOREIGN SERVER name_list + | FUNCTION function_with_argtypes_list + | PROCEDURE function_with_argtypes_list + | ROUTINE function_with_argtypes_list + | DATABASE name_list + | DOMAIN_P any_name_list + | LANGUAGE name_list + | LARGE_P OBJECT_P /*12N*/ NumericOnly_list + | PARAMETER parameter_name_list + | SCHEMA name_list + | TABLESPACE name_list + | TYPE_P any_name_list + | ALL TABLES IN_P /*9N*/ SCHEMA name_list + | ALL SEQUENCES IN_P /*9N*/ SCHEMA name_list + | ALL FUNCTIONS IN_P /*9N*/ SCHEMA name_list + | ALL PROCEDURES IN_P /*9N*/ SCHEMA name_list + | ALL ROUTINES IN_P /*9N*/ SCHEMA name_list + ; + +grantee_list : + grantee + | grantee_list ',' grantee + ; + +grantee : + RoleSpec + | GROUP_P RoleSpec + ; + +opt_grant_grant_option : + WITH /*13N*/ GRANT OPTION + | /*empty*/ + ; + +GrantRoleStmt : + GRANT privilege_list TO role_list opt_granted_by + | GRANT privilege_list TO role_list WITH /*13N*/ grant_role_opt_list opt_granted_by + ; + +RevokeRoleStmt : + REVOKE privilege_list FROM role_list opt_granted_by opt_drop_behavior + | REVOKE ColId OPTION FOR privilege_list FROM role_list opt_granted_by opt_drop_behavior + ; + +grant_role_opt_list : + grant_role_opt_list ',' grant_role_opt + | grant_role_opt + ; + +grant_role_opt : + ColLabel grant_role_opt_value + ; + +grant_role_opt_value : + OPTION + | TRUE_P + | FALSE_P + ; + +opt_granted_by : + GRANTED BY RoleSpec + | /*empty*/ + ; + +AlterDefaultPrivilegesStmt : + ALTER DEFAULT PRIVILEGES DefACLOptionList DefACLAction + ; + +DefACLOptionList : + DefACLOptionList DefACLOption + | /*empty*/ + ; + +DefACLOption : + IN_P /*9N*/ SCHEMA name_list + | FOR ROLE role_list + | FOR USER role_list + ; + +DefACLAction : + GRANT privileges ON defacl_privilege_target TO grantee_list opt_grant_grant_option + | REVOKE privileges ON defacl_privilege_target FROM grantee_list opt_drop_behavior + | REVOKE GRANT OPTION FOR privileges ON defacl_privilege_target FROM grantee_list opt_drop_behavior + ; + +defacl_privilege_target : + TABLES + | FUNCTIONS + | ROUTINES + | SEQUENCES + | TYPES_P + | SCHEMAS + ; + +IndexStmt : + CREATE opt_unique INDEX opt_concurrently opt_single_name ON relation_expr access_method_clause '(' /*24L*/ index_params ')' /*24L*/ opt_include opt_unique_null_treatment opt_reloptions OptTableSpace where_clause + | CREATE opt_unique INDEX opt_concurrently IF_P NOT /*6R*/ EXISTS name ON relation_expr access_method_clause '(' /*24L*/ index_params ')' /*24L*/ opt_include opt_unique_null_treatment opt_reloptions OptTableSpace where_clause + ; + +opt_unique : + UNIQUE /*11N*/ + | /*empty*/ + ; + +access_method_clause : + USING name + | /*empty*/ + ; + +index_params : + index_elem + | index_params ',' index_elem + ; + +index_elem_options : + opt_collate opt_qualified_name opt_asc_desc opt_nulls_order + | opt_collate any_name reloptions opt_asc_desc opt_nulls_order + ; + +index_elem : + ColId index_elem_options + | func_expr_windowless index_elem_options + | '(' /*24L*/ a_expr ')' /*24L*/ index_elem_options + ; + +opt_include : + INCLUDE '(' /*24L*/ index_including_params ')' /*24L*/ + | /*empty*/ + ; + +index_including_params : + index_elem + | index_including_params ',' index_elem + ; + +opt_collate : + COLLATE /*21L*/ any_name + | /*empty*/ + ; + +opt_asc_desc : + ASC + | DESC + | /*empty*/ + ; + +opt_nulls_order : + NULLS_LA FIRST_P + | NULLS_LA LAST_P + | /*empty*/ + ; + +CreateFunctionStmt : + CREATE opt_or_replace FUNCTION func_name func_args_with_defaults RETURNS func_return opt_createfunc_opt_list opt_routine_body + | CREATE opt_or_replace FUNCTION func_name func_args_with_defaults RETURNS TABLE '(' /*24L*/ table_func_column_list ')' /*24L*/ opt_createfunc_opt_list opt_routine_body + | CREATE opt_or_replace FUNCTION func_name func_args_with_defaults opt_createfunc_opt_list opt_routine_body + | CREATE opt_or_replace PROCEDURE func_name func_args_with_defaults opt_createfunc_opt_list opt_routine_body + ; + +opt_or_replace : + OR /*4L*/ REPLACE + | /*empty*/ + ; + +func_args : + '(' /*24L*/ func_args_list ')' /*24L*/ + | '(' /*24L*/ ')' /*24L*/ + ; + +func_args_list : + func_arg + | func_args_list ',' func_arg + ; + +function_with_argtypes_list : + function_with_argtypes + | function_with_argtypes_list ',' function_with_argtypes + ; + +function_with_argtypes : + func_name func_args + | type_func_name_keyword + | ColId + | ColId indirection + ; + +func_args_with_defaults : + '(' /*24L*/ func_args_with_defaults_list ')' /*24L*/ + | '(' /*24L*/ ')' /*24L*/ + ; + +func_args_with_defaults_list : + func_arg_with_default + | func_args_with_defaults_list ',' func_arg_with_default + ; + +func_arg : + arg_class param_name func_type + | param_name arg_class func_type + | param_name func_type + | arg_class func_type + | func_type + ; + +arg_class : + IN_P /*9N*/ + | OUT_P + | INOUT + | IN_P /*9N*/ OUT_P + | VARIADIC + ; + +param_name : + type_function_name + ; + +func_return : + func_type + ; + +func_type : + Typename + | type_function_name attrs '%' /*18L*/ TYPE_P + | SETOF type_function_name attrs '%' /*18L*/ TYPE_P + ; + +func_arg_with_default : + func_arg + | func_arg DEFAULT a_expr + | func_arg '=' /*8N*/ a_expr + ; + +aggr_arg : + func_arg + ; + +aggr_args : + '(' /*24L*/ '*' /*18L*/ ')' /*24L*/ + | '(' /*24L*/ aggr_args_list ')' /*24L*/ + | '(' /*24L*/ ORDER BY aggr_args_list ')' /*24L*/ + | '(' /*24L*/ aggr_args_list ORDER BY aggr_args_list ')' /*24L*/ + ; + +aggr_args_list : + aggr_arg + | aggr_args_list ',' aggr_arg + ; + +aggregate_with_argtypes : + func_name aggr_args + ; + +aggregate_with_argtypes_list : + aggregate_with_argtypes + | aggregate_with_argtypes_list ',' aggregate_with_argtypes + ; + +opt_createfunc_opt_list : + createfunc_opt_list + | /*empty*/ + ; + +createfunc_opt_list : + createfunc_opt_item + | createfunc_opt_list createfunc_opt_item + ; + +common_func_opt_item : + CALLED ON NULL_P INPUT_P + | RETURNS NULL_P ON NULL_P INPUT_P + | STRICT_P + | IMMUTABLE + | STABLE + | VOLATILE + | EXTERNAL SECURITY DEFINER + | EXTERNAL SECURITY INVOKER + | SECURITY DEFINER + | SECURITY INVOKER + | LEAKPROOF + | NOT /*6R*/ LEAKPROOF + | COST NumericOnly + | ROWS /*15N*/ NumericOnly + | SUPPORT any_name + | FunctionSetResetClause + | PARALLEL ColId + ; + +createfunc_opt_item : + AS func_as + | LANGUAGE NonReservedWord_or_Sconst + | TRANSFORM transform_type_list + | WINDOW + | common_func_opt_item + ; + +func_as : + Sconst + | Sconst ',' Sconst + ; + +ReturnStmt : + RETURN a_expr + ; + +opt_routine_body : + ReturnStmt + | BEGIN_P ATOMIC routine_body_stmt_list END_P + | /*empty*/ + ; + +routine_body_stmt_list : + routine_body_stmt_list routine_body_stmt ';' + | /*empty*/ + ; + +routine_body_stmt : + stmt + | ReturnStmt + ; + +transform_type_list : + FOR TYPE_P Typename + | transform_type_list ',' FOR TYPE_P Typename + ; + +opt_definition : + WITH /*13N*/ definition + | /*empty*/ + ; + +table_func_column : + param_name func_type + ; + +table_func_column_list : + table_func_column + | table_func_column_list ',' table_func_column + ; + +AlterFunctionStmt : + ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict + | ALTER PROCEDURE function_with_argtypes alterfunc_opt_list opt_restrict + | ALTER ROUTINE function_with_argtypes alterfunc_opt_list opt_restrict + ; + +alterfunc_opt_list : + common_func_opt_item + | alterfunc_opt_list common_func_opt_item + ; + +opt_restrict : + RESTRICT + | /*empty*/ + ; + +RemoveFuncStmt : + DROP FUNCTION function_with_argtypes_list opt_drop_behavior + | DROP FUNCTION IF_P EXISTS function_with_argtypes_list opt_drop_behavior + | DROP PROCEDURE function_with_argtypes_list opt_drop_behavior + | DROP PROCEDURE IF_P EXISTS function_with_argtypes_list opt_drop_behavior + | DROP ROUTINE function_with_argtypes_list opt_drop_behavior + | DROP ROUTINE IF_P EXISTS function_with_argtypes_list opt_drop_behavior + ; + +RemoveAggrStmt : + DROP AGGREGATE aggregate_with_argtypes_list opt_drop_behavior + | DROP AGGREGATE IF_P EXISTS aggregate_with_argtypes_list opt_drop_behavior + ; + +RemoveOperStmt : + DROP OPERATOR /*16L*/ operator_with_argtypes_list opt_drop_behavior + | DROP OPERATOR /*16L*/ IF_P EXISTS operator_with_argtypes_list opt_drop_behavior + ; + +oper_argtypes : + '(' /*24L*/ Typename ')' /*24L*/ + | '(' /*24L*/ Typename ',' Typename ')' /*24L*/ + | '(' /*24L*/ NONE ',' Typename ')' /*24L*/ + | '(' /*24L*/ Typename ',' NONE ')' /*24L*/ + ; + +any_operator : + all_Op + | ColId '.' /*26L*/ any_operator + ; + +operator_with_argtypes_list : + operator_with_argtypes + | operator_with_argtypes_list ',' operator_with_argtypes + ; + +operator_with_argtypes : + any_operator oper_argtypes + ; + +DoStmt : + DO dostmt_opt_list + ; + +dostmt_opt_list : + dostmt_opt_item + | dostmt_opt_list dostmt_opt_item + ; + +dostmt_opt_item : + Sconst + | LANGUAGE NonReservedWord_or_Sconst + ; + +CreateCastStmt : + CREATE CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ WITH /*13N*/ FUNCTION function_with_argtypes cast_context + | CREATE CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ WITHOUT /*13N*/ FUNCTION cast_context + | CREATE CAST '(' /*24L*/ Typename AS Typename ')' /*24L*/ WITH /*13N*/ INOUT cast_context + ; + +cast_context : + AS IMPLICIT_P + | AS ASSIGNMENT + | /*empty*/ + ; + +DropCastStmt : + DROP CAST opt_if_exists '(' /*24L*/ Typename AS Typename ')' /*24L*/ opt_drop_behavior + ; + +opt_if_exists : + IF_P EXISTS + | /*empty*/ + ; + +CreateTransformStmt : + CREATE opt_or_replace TRANSFORM FOR Typename LANGUAGE name '(' /*24L*/ transform_element_list ')' /*24L*/ + ; + +transform_element_list : + FROM SQL_P WITH /*13N*/ FUNCTION function_with_argtypes ',' TO SQL_P WITH /*13N*/ FUNCTION function_with_argtypes + | TO SQL_P WITH /*13N*/ FUNCTION function_with_argtypes ',' FROM SQL_P WITH /*13N*/ FUNCTION function_with_argtypes + | FROM SQL_P WITH /*13N*/ FUNCTION function_with_argtypes + | TO SQL_P WITH /*13N*/ FUNCTION function_with_argtypes + ; + +DropTransformStmt : + DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_drop_behavior + ; + +ReindexStmt : + REINDEX opt_reindex_option_list reindex_target_relation opt_concurrently qualified_name + | REINDEX opt_reindex_option_list SCHEMA opt_concurrently name + | REINDEX opt_reindex_option_list reindex_target_all opt_concurrently opt_single_name + ; + +reindex_target_relation : + INDEX + | TABLE + ; + +reindex_target_all : + SYSTEM_P + | DATABASE + ; + +opt_reindex_option_list : + '(' /*24L*/ utility_option_list ')' /*24L*/ + | /*empty*/ + ; + +AlterTblSpcStmt : + ALTER TABLESPACE name SET /*1N*/ reloptions + | ALTER TABLESPACE name RESET reloptions + ; + +RenameStmt : + ALTER AGGREGATE aggregate_with_argtypes RENAME TO name + | ALTER COLLATION any_name RENAME TO name + | ALTER CONVERSION_P any_name RENAME TO name + | ALTER DATABASE name RENAME TO name + | ALTER DOMAIN_P any_name RENAME TO name + | ALTER DOMAIN_P any_name RENAME CONSTRAINT name TO name + | ALTER FOREIGN DATA_P WRAPPER name RENAME TO name + | ALTER FUNCTION function_with_argtypes RENAME TO name + | ALTER GROUP_P RoleId RENAME TO RoleId + | ALTER opt_procedural LANGUAGE name RENAME TO name + | ALTER OPERATOR /*16L*/ CLASS any_name USING name RENAME TO name + | ALTER OPERATOR /*16L*/ FAMILY any_name USING name RENAME TO name + | ALTER POLICY name ON qualified_name RENAME TO name + | ALTER POLICY IF_P EXISTS name ON qualified_name RENAME TO name + | ALTER PROCEDURE function_with_argtypes RENAME TO name + | ALTER PUBLICATION name RENAME TO name + | ALTER ROUTINE function_with_argtypes RENAME TO name + | ALTER SCHEMA name RENAME TO name + | ALTER SERVER name RENAME TO name + | ALTER SUBSCRIPTION name RENAME TO name + | ALTER TABLE relation_expr RENAME TO name + | ALTER TABLE IF_P EXISTS relation_expr RENAME TO name + | ALTER SEQUENCE qualified_name RENAME TO name + | ALTER SEQUENCE IF_P EXISTS qualified_name RENAME TO name + | ALTER VIEW qualified_name RENAME TO name + | ALTER VIEW IF_P EXISTS qualified_name RENAME TO name + | ALTER MATERIALIZED VIEW qualified_name RENAME TO name + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME TO name + | ALTER INDEX qualified_name RENAME TO name + | ALTER INDEX IF_P EXISTS qualified_name RENAME TO name + | ALTER FOREIGN TABLE relation_expr RENAME TO name + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME TO name + | ALTER TABLE relation_expr RENAME opt_column name TO name + | ALTER TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name + | ALTER VIEW qualified_name RENAME opt_column name TO name + | ALTER VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name + | ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name + | ALTER TABLE relation_expr RENAME CONSTRAINT name TO name + | ALTER TABLE IF_P EXISTS relation_expr RENAME CONSTRAINT name TO name + | ALTER FOREIGN TABLE relation_expr RENAME opt_column name TO name + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name + | ALTER RULE name ON qualified_name RENAME TO name + | ALTER TRIGGER name ON qualified_name RENAME TO name + | ALTER EVENT TRIGGER name RENAME TO name + | ALTER ROLE RoleId RENAME TO RoleId + | ALTER USER RoleId RENAME TO RoleId + | ALTER TABLESPACE name RENAME TO name + | ALTER STATISTICS any_name RENAME TO name + | ALTER TEXT_P SEARCH PARSER any_name RENAME TO name + | ALTER TEXT_P SEARCH DICTIONARY any_name RENAME TO name + | ALTER TEXT_P SEARCH TEMPLATE any_name RENAME TO name + | ALTER TEXT_P SEARCH CONFIGURATION any_name RENAME TO name + | ALTER TYPE_P any_name RENAME TO name + | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name opt_drop_behavior + ; + +opt_column : + COLUMN + | /*empty*/ + ; + +opt_set_data : + SET /*1N*/ DATA_P + | /*empty*/ + ; + +AlterObjectDependsStmt : + ALTER FUNCTION function_with_argtypes opt_no DEPENDS ON EXTENSION name + | ALTER PROCEDURE function_with_argtypes opt_no DEPENDS ON EXTENSION name + | ALTER ROUTINE function_with_argtypes opt_no DEPENDS ON EXTENSION name + | ALTER TRIGGER name ON qualified_name opt_no DEPENDS ON EXTENSION name + | ALTER MATERIALIZED VIEW qualified_name opt_no DEPENDS ON EXTENSION name + | ALTER INDEX qualified_name opt_no DEPENDS ON EXTENSION name + ; + +opt_no : + NO + | /*empty*/ + ; + +AlterObjectSchemaStmt : + ALTER AGGREGATE aggregate_with_argtypes SET /*1N*/ SCHEMA name + | ALTER COLLATION any_name SET /*1N*/ SCHEMA name + | ALTER CONVERSION_P any_name SET /*1N*/ SCHEMA name + | ALTER DOMAIN_P any_name SET /*1N*/ SCHEMA name + | ALTER EXTENSION name SET /*1N*/ SCHEMA name + | ALTER FUNCTION function_with_argtypes SET /*1N*/ SCHEMA name + | ALTER OPERATOR /*16L*/ operator_with_argtypes SET /*1N*/ SCHEMA name + | ALTER OPERATOR /*16L*/ CLASS any_name USING name SET /*1N*/ SCHEMA name + | ALTER OPERATOR /*16L*/ FAMILY any_name USING name SET /*1N*/ SCHEMA name + | ALTER PROCEDURE function_with_argtypes SET /*1N*/ SCHEMA name + | ALTER ROUTINE function_with_argtypes SET /*1N*/ SCHEMA name + | ALTER TABLE relation_expr SET /*1N*/ SCHEMA name + | ALTER TABLE IF_P EXISTS relation_expr SET /*1N*/ SCHEMA name + | ALTER STATISTICS any_name SET /*1N*/ SCHEMA name + | ALTER TEXT_P SEARCH PARSER any_name SET /*1N*/ SCHEMA name + | ALTER TEXT_P SEARCH DICTIONARY any_name SET /*1N*/ SCHEMA name + | ALTER TEXT_P SEARCH TEMPLATE any_name SET /*1N*/ SCHEMA name + | ALTER TEXT_P SEARCH CONFIGURATION any_name SET /*1N*/ SCHEMA name + | ALTER SEQUENCE qualified_name SET /*1N*/ SCHEMA name + | ALTER SEQUENCE IF_P EXISTS qualified_name SET /*1N*/ SCHEMA name + | ALTER VIEW qualified_name SET /*1N*/ SCHEMA name + | ALTER VIEW IF_P EXISTS qualified_name SET /*1N*/ SCHEMA name + | ALTER MATERIALIZED VIEW qualified_name SET /*1N*/ SCHEMA name + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name SET /*1N*/ SCHEMA name + | ALTER FOREIGN TABLE relation_expr SET /*1N*/ SCHEMA name + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr SET /*1N*/ SCHEMA name + | ALTER TYPE_P any_name SET /*1N*/ SCHEMA name + ; + +AlterOperatorStmt : + ALTER OPERATOR /*16L*/ operator_with_argtypes SET /*1N*/ '(' /*24L*/ operator_def_list ')' /*24L*/ + ; + +operator_def_list : + operator_def_elem + | operator_def_list ',' operator_def_elem + ; + +operator_def_elem : + ColLabel '=' /*8N*/ NONE + | ColLabel '=' /*8N*/ operator_def_arg + ; + +operator_def_arg : + func_type + | reserved_keyword + | qual_all_Op + | NumericOnly + | Sconst + ; + +AlterTypeStmt : + ALTER TYPE_P any_name SET /*1N*/ '(' /*24L*/ operator_def_list ')' /*24L*/ + ; + +AlterOwnerStmt : + ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec + | ALTER COLLATION any_name OWNER TO RoleSpec + | ALTER CONVERSION_P any_name OWNER TO RoleSpec + | ALTER DATABASE name OWNER TO RoleSpec + | ALTER DOMAIN_P any_name OWNER TO RoleSpec + | ALTER FUNCTION function_with_argtypes OWNER TO RoleSpec + | ALTER opt_procedural LANGUAGE name OWNER TO RoleSpec + | ALTER LARGE_P OBJECT_P /*12N*/ NumericOnly OWNER TO RoleSpec + | ALTER OPERATOR /*16L*/ operator_with_argtypes OWNER TO RoleSpec + | ALTER OPERATOR /*16L*/ CLASS any_name USING name OWNER TO RoleSpec + | ALTER OPERATOR /*16L*/ FAMILY any_name USING name OWNER TO RoleSpec + | ALTER PROCEDURE function_with_argtypes OWNER TO RoleSpec + | ALTER ROUTINE function_with_argtypes OWNER TO RoleSpec + | ALTER SCHEMA name OWNER TO RoleSpec + | ALTER TYPE_P any_name OWNER TO RoleSpec + | ALTER TABLESPACE name OWNER TO RoleSpec + | ALTER STATISTICS any_name OWNER TO RoleSpec + | ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO RoleSpec + | ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO RoleSpec + | ALTER FOREIGN DATA_P WRAPPER name OWNER TO RoleSpec + | ALTER SERVER name OWNER TO RoleSpec + | ALTER EVENT TRIGGER name OWNER TO RoleSpec + | ALTER PUBLICATION name OWNER TO RoleSpec + | ALTER SUBSCRIPTION name OWNER TO RoleSpec + ; + +CreatePublicationStmt : + CREATE PUBLICATION name opt_definition + | CREATE PUBLICATION name FOR ALL TABLES opt_definition + | CREATE PUBLICATION name FOR pub_obj_list opt_definition + ; + +PublicationObjSpec : + TABLE relation_expr opt_column_list OptWhereClause + | TABLES IN_P /*9N*/ SCHEMA ColId + | TABLES IN_P /*9N*/ SCHEMA CURRENT_SCHEMA + | ColId opt_column_list OptWhereClause + | ColId indirection opt_column_list OptWhereClause + | extended_relation_expr opt_column_list OptWhereClause + | CURRENT_SCHEMA + ; + +pub_obj_list : + PublicationObjSpec + | pub_obj_list ',' PublicationObjSpec + ; + +AlterPublicationStmt : + ALTER PUBLICATION name SET /*1N*/ definition + | ALTER PUBLICATION name ADD_P pub_obj_list + | ALTER PUBLICATION name SET /*1N*/ pub_obj_list + | ALTER PUBLICATION name DROP pub_obj_list + ; + +CreateSubscriptionStmt : + CREATE SUBSCRIPTION name CONNECTION Sconst PUBLICATION name_list opt_definition + ; + +AlterSubscriptionStmt : + ALTER SUBSCRIPTION name SET /*1N*/ definition + | ALTER SUBSCRIPTION name CONNECTION Sconst + | ALTER SUBSCRIPTION name REFRESH PUBLICATION opt_definition + | ALTER SUBSCRIPTION name ADD_P PUBLICATION name_list opt_definition + | ALTER SUBSCRIPTION name DROP PUBLICATION name_list opt_definition + | ALTER SUBSCRIPTION name SET /*1N*/ PUBLICATION name_list opt_definition + | ALTER SUBSCRIPTION name ENABLE_P + | ALTER SUBSCRIPTION name DISABLE_P + | ALTER SUBSCRIPTION name SKIP definition + ; + +DropSubscriptionStmt : + DROP SUBSCRIPTION name opt_drop_behavior + | DROP SUBSCRIPTION IF_P EXISTS name opt_drop_behavior + ; + +RuleStmt : + CREATE opt_or_replace RULE name AS ON event TO qualified_name where_clause DO opt_instead RuleActionList + ; + +RuleActionList : + NOTHING + | RuleActionStmt + | '(' /*24L*/ RuleActionMulti ')' /*24L*/ + ; + +RuleActionMulti : + RuleActionMulti ';' RuleActionStmtOrEmpty + | RuleActionStmtOrEmpty + ; + +RuleActionStmt : + SelectStmt + | InsertStmt + | UpdateStmt + | DeleteStmt + | NotifyStmt + ; + +RuleActionStmtOrEmpty : + RuleActionStmt + | /*empty*/ + ; + +event : + SELECT + | UPDATE + | DELETE_P + | INSERT + ; + +opt_instead : + INSTEAD + | ALSO + | /*empty*/ + ; + +NotifyStmt : + NOTIFY ColId notify_payload + ; + +notify_payload : + ',' Sconst + | /*empty*/ + ; + +ListenStmt : + LISTEN ColId + ; + +UnlistenStmt : + UNLISTEN ColId + | UNLISTEN '*' /*18L*/ + ; + +TransactionStmt : + ABORT_P opt_transaction opt_transaction_chain + | START TRANSACTION transaction_mode_list_or_empty + | COMMIT opt_transaction opt_transaction_chain + | ROLLBACK opt_transaction opt_transaction_chain + | SAVEPOINT ColId + | RELEASE SAVEPOINT ColId + | RELEASE ColId + | ROLLBACK opt_transaction TO SAVEPOINT ColId + | ROLLBACK opt_transaction TO ColId + | PREPARE TRANSACTION Sconst + | COMMIT PREPARED Sconst + | ROLLBACK PREPARED Sconst + ; + +TransactionStmtLegacy : + BEGIN_P opt_transaction transaction_mode_list_or_empty + | END_P opt_transaction opt_transaction_chain + ; + +opt_transaction : + WORK + | TRANSACTION + | /*empty*/ + ; + +transaction_mode_item : + ISOLATION LEVEL iso_level + | READ ONLY + | READ WRITE + | DEFERRABLE + | NOT /*6R*/ DEFERRABLE + ; + +transaction_mode_list : + transaction_mode_item + | transaction_mode_list ',' transaction_mode_item + | transaction_mode_list transaction_mode_item + ; + +transaction_mode_list_or_empty : + transaction_mode_list + | /*empty*/ + ; + +opt_transaction_chain : + AND /*5L*/ CHAIN + | AND /*5L*/ NO CHAIN + | /*empty*/ + ; + +ViewStmt : + CREATE OptTemp VIEW qualified_name opt_column_list opt_reloptions AS SelectStmt opt_check_option + | CREATE OR /*4L*/ REPLACE OptTemp VIEW qualified_name opt_column_list opt_reloptions AS SelectStmt opt_check_option + | CREATE OptTemp RECURSIVE VIEW qualified_name '(' /*24L*/ columnList ')' /*24L*/ opt_reloptions AS SelectStmt opt_check_option + | CREATE OR /*4L*/ REPLACE OptTemp RECURSIVE VIEW qualified_name '(' /*24L*/ columnList ')' /*24L*/ opt_reloptions AS SelectStmt opt_check_option + ; + +opt_check_option : + WITH /*13N*/ CHECK OPTION + | WITH /*13N*/ CASCADED CHECK OPTION + | WITH /*13N*/ LOCAL CHECK OPTION + | /*empty*/ + ; + +LoadStmt : + LOAD file_name + ; + +CreatedbStmt : + CREATE DATABASE name opt_with createdb_opt_list + ; + +createdb_opt_list : + createdb_opt_items + | /*empty*/ + ; + +createdb_opt_items : + createdb_opt_item + | createdb_opt_items createdb_opt_item + ; + +createdb_opt_item : + createdb_opt_name opt_equal NumericOnly + | createdb_opt_name opt_equal opt_boolean_or_string + | createdb_opt_name opt_equal DEFAULT + ; + +createdb_opt_name : + IDENT /*15N*/ + | CONNECTION LIMIT + | ENCODING + | LOCATION + | OWNER + | TABLESPACE + | TEMPLATE + ; + +opt_equal : + '=' /*8N*/ + | /*empty*/ + ; + +AlterDatabaseStmt : + ALTER DATABASE name WITH /*13N*/ createdb_opt_list + | ALTER DATABASE name createdb_opt_list + | ALTER DATABASE name SET /*1N*/ TABLESPACE name + | ALTER DATABASE name REFRESH COLLATION VERSION_P + ; + +AlterDatabaseSetStmt : + ALTER DATABASE name SetResetClause + ; + +DropdbStmt : + DROP DATABASE name + | DROP DATABASE IF_P EXISTS name + | DROP DATABASE name opt_with '(' /*24L*/ drop_option_list ')' /*24L*/ + | DROP DATABASE IF_P EXISTS name opt_with '(' /*24L*/ drop_option_list ')' /*24L*/ + ; + +drop_option_list : + drop_option + | drop_option_list ',' drop_option + ; + +drop_option : + FORCE + ; + +AlterCollationStmt : + ALTER COLLATION any_name REFRESH VERSION_P + ; + +AlterSystemStmt : + ALTER SYSTEM_P SET /*1N*/ generic_set + | ALTER SYSTEM_P RESET generic_reset + ; + +CreateDomainStmt : + CREATE DOMAIN_P any_name opt_as Typename ColQualList + ; + +AlterDomainStmt : + ALTER DOMAIN_P any_name alter_column_default + | ALTER DOMAIN_P any_name DROP NOT /*6R*/ NULL_P + | ALTER DOMAIN_P any_name SET /*1N*/ NOT /*6R*/ NULL_P + | ALTER DOMAIN_P any_name ADD_P TableConstraint + | ALTER DOMAIN_P any_name DROP CONSTRAINT name opt_drop_behavior + | ALTER DOMAIN_P any_name DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior + | ALTER DOMAIN_P any_name VALIDATE CONSTRAINT name + ; + +opt_as : + AS + | /*empty*/ + ; + +AlterTSDictionaryStmt : + ALTER TEXT_P SEARCH DICTIONARY any_name definition + ; + +AlterTSConfigurationStmt : + ALTER TEXT_P SEARCH CONFIGURATION any_name ADD_P MAPPING FOR name_list any_with any_name_list + | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list any_with any_name_list + | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING REPLACE any_name any_with any_name + | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list REPLACE any_name any_with any_name + | ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING FOR name_list + | ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING IF_P EXISTS FOR name_list + ; + +any_with : + WITH /*13N*/ + | WITH_LA + ; + +CreateConversionStmt : + CREATE opt_default CONVERSION_P any_name FOR Sconst TO Sconst FROM any_name + ; + +ClusterStmt : + CLUSTER opt_verbose qualified_name cluster_index_specification + | CLUSTER '(' /*24L*/ utility_option_list ')' /*24L*/ qualified_name cluster_index_specification + | CLUSTER opt_verbose + | CLUSTER opt_verbose name ON qualified_name + ; + +cluster_index_specification : + USING name + | /*empty*/ + ; + +VacuumStmt : + VACUUM opt_full opt_freeze opt_verbose opt_analyze opt_vacuum_relation_list + | VACUUM '(' /*24L*/ utility_option_list ')' /*24L*/ opt_vacuum_relation_list + ; + +AnalyzeStmt : + analyze_keyword opt_verbose opt_vacuum_relation_list + | analyze_keyword '(' /*24L*/ utility_option_list ')' /*24L*/ opt_vacuum_relation_list + ; + +utility_option_list : + utility_option_elem + | utility_option_list ',' utility_option_elem + ; + +analyze_keyword : + ANALYZE + | ANALYSE + ; + +utility_option_elem : + utility_option_name utility_option_arg + ; + +utility_option_name : + NonReservedWord + | analyze_keyword + | FORMAT_LA + ; + +utility_option_arg : + opt_boolean_or_string + | NumericOnly + | /*empty*/ + ; + +opt_analyze : + analyze_keyword + | /*empty*/ + ; + +opt_verbose : + VERBOSE + | /*empty*/ + ; + +opt_full : + FULL /*27L*/ + | /*empty*/ + ; + +opt_freeze : + FREEZE + | /*empty*/ + ; + +opt_name_list : + '(' /*24L*/ name_list ')' /*24L*/ + | /*empty*/ + ; + +vacuum_relation : + qualified_name opt_name_list + ; + +vacuum_relation_list : + vacuum_relation + | vacuum_relation_list ',' vacuum_relation + ; + +opt_vacuum_relation_list : + vacuum_relation_list + | /*empty*/ + ; + +ExplainStmt : + EXPLAIN ExplainableStmt + | EXPLAIN analyze_keyword opt_verbose ExplainableStmt + | EXPLAIN VERBOSE ExplainableStmt + | EXPLAIN '(' /*24L*/ utility_option_list ')' /*24L*/ ExplainableStmt + ; + +ExplainableStmt : + SelectStmt + | InsertStmt + | UpdateStmt + | DeleteStmt + | MergeStmt + | DeclareCursorStmt + | CreateAsStmt + | CreateMatViewStmt + | RefreshMatViewStmt + | ExecuteStmt + ; + +PrepareStmt : + PREPARE name prep_type_clause AS PreparableStmt + ; + +prep_type_clause : + '(' /*24L*/ type_list ')' /*24L*/ + | /*empty*/ + ; + +PreparableStmt : + SelectStmt + | InsertStmt + | UpdateStmt + | DeleteStmt + | MergeStmt + ; + +ExecuteStmt : + EXECUTE name execute_param_clause + | CREATE OptTemp TABLE create_as_target AS EXECUTE name execute_param_clause opt_with_data + | CREATE OptTemp TABLE IF_P NOT /*6R*/ EXISTS create_as_target AS EXECUTE name execute_param_clause opt_with_data + ; + +execute_param_clause : + '(' /*24L*/ expr_list ')' /*24L*/ + | /*empty*/ + ; + +DeallocateStmt : + DEALLOCATE name + | DEALLOCATE PREPARE name + | DEALLOCATE ALL + | DEALLOCATE PREPARE ALL + ; + +InsertStmt : + opt_with_clause INSERT INTO insert_target insert_rest opt_on_conflict returning_clause + ; + +insert_target : + qualified_name + | qualified_name AS ColId + ; + +insert_rest : + SelectStmt + | OVERRIDING override_kind VALUE_P /*12N*/ SelectStmt + | '(' /*24L*/ insert_column_list ')' /*24L*/ SelectStmt + | '(' /*24L*/ insert_column_list ')' /*24L*/ OVERRIDING override_kind VALUE_P /*12N*/ SelectStmt + | DEFAULT VALUES + ; + +override_kind : + USER + | SYSTEM_P + ; + +insert_column_list : + insert_column_item + | insert_column_list ',' insert_column_item + ; + +insert_column_item : + ColId opt_indirection + ; + +opt_on_conflict : + ON CONFLICT opt_conf_expr DO UPDATE SET /*1N*/ set_clause_list where_clause + | ON CONFLICT opt_conf_expr DO NOTHING + | /*empty*/ + ; + +opt_conf_expr : + '(' /*24L*/ index_params ')' /*24L*/ where_clause + | ON CONSTRAINT name + | /*empty*/ + ; + +returning_clause : + RETURNING target_list + | /*empty*/ + ; + +DeleteStmt : + opt_with_clause DELETE_P FROM relation_expr_opt_alias using_clause where_or_current_clause returning_clause + ; + +using_clause : + USING from_list + | /*empty*/ + ; + +LockStmt : + LOCK_P opt_table relation_expr_list opt_lock opt_nowait + ; + +opt_lock : + IN_P /*9N*/ lock_type MODE + | /*empty*/ + ; + +lock_type : + ACCESS SHARE + | ROW SHARE + | ROW EXCLUSIVE + | SHARE UPDATE EXCLUSIVE + | SHARE + | SHARE ROW EXCLUSIVE + | EXCLUSIVE + | ACCESS EXCLUSIVE + ; + +opt_nowait : + NOWAIT + | /*empty*/ + ; + +opt_nowait_or_skip : + NOWAIT + | SKIP LOCKED + | /*empty*/ + ; + +UpdateStmt : + opt_with_clause UPDATE relation_expr_opt_alias SET /*1N*/ set_clause_list from_clause where_or_current_clause returning_clause + ; + +set_clause_list : + set_clause + | set_clause_list ',' set_clause + ; + +set_clause : + set_target '=' /*8N*/ a_expr + | '(' /*24L*/ set_target_list ')' /*24L*/ '=' /*8N*/ a_expr + ; + +set_target : + ColId opt_indirection + ; + +set_target_list : + set_target + | set_target_list ',' set_target + ; + +MergeStmt : + opt_with_clause MERGE INTO relation_expr_opt_alias USING table_ref ON a_expr merge_when_list + ; + +merge_when_list : + merge_when_clause + | merge_when_list merge_when_clause + ; + +merge_when_clause : + WHEN MATCHED opt_merge_when_condition THEN merge_update + | WHEN MATCHED opt_merge_when_condition THEN merge_delete + | WHEN NOT /*6R*/ MATCHED opt_merge_when_condition THEN merge_insert + | WHEN MATCHED opt_merge_when_condition THEN DO NOTHING + | WHEN NOT /*6R*/ MATCHED opt_merge_when_condition THEN DO NOTHING + ; + +opt_merge_when_condition : + AND /*5L*/ a_expr + | /*empty*/ + ; + +merge_update : + UPDATE SET /*1N*/ set_clause_list + ; + +merge_delete : + DELETE_P + ; + +merge_insert : + INSERT merge_values_clause + | INSERT OVERRIDING override_kind VALUE_P /*12N*/ merge_values_clause + | INSERT '(' /*24L*/ insert_column_list ')' /*24L*/ merge_values_clause + | INSERT '(' /*24L*/ insert_column_list ')' /*24L*/ OVERRIDING override_kind VALUE_P /*12N*/ merge_values_clause + | INSERT DEFAULT VALUES + ; + +merge_values_clause : + VALUES '(' /*24L*/ expr_list ')' /*24L*/ + ; + +DeclareCursorStmt : + DECLARE cursor_name cursor_options CURSOR opt_hold FOR SelectStmt + ; + +cursor_name : + name + ; + +cursor_options : + /*empty*/ + | cursor_options NO SCROLL + | cursor_options SCROLL + | cursor_options BINARY + | cursor_options ASENSITIVE + | cursor_options INSENSITIVE + ; + +opt_hold : + /*empty*/ + | WITH /*13N*/ HOLD + | WITHOUT /*13N*/ HOLD + ; + +SelectStmt : + select_no_parens %prec UMINUS /*22R*/ + | select_with_parens %prec UMINUS /*22R*/ + ; + +select_with_parens : + '(' /*24L*/ select_no_parens ')' /*24L*/ + | '(' /*24L*/ select_with_parens ')' /*24L*/ + ; + +select_no_parens : + simple_select + | select_clause sort_clause + | select_clause opt_sort_clause for_locking_clause opt_select_limit + | select_clause opt_sort_clause select_limit opt_for_locking_clause + | with_clause select_clause + | with_clause select_clause sort_clause + | with_clause select_clause opt_sort_clause for_locking_clause opt_select_limit + | with_clause select_clause opt_sort_clause select_limit opt_for_locking_clause + ; + +select_clause : + simple_select + | select_with_parens + ; + +simple_select : + SELECT opt_all_clause opt_target_list into_clause from_clause where_clause group_clause having_clause window_clause + | SELECT distinct_clause target_list into_clause from_clause where_clause group_clause having_clause window_clause + | values_clause + | TABLE relation_expr + | select_clause UNION /*2L*/ set_quantifier select_clause + | select_clause INTERSECT /*3L*/ set_quantifier select_clause + | select_clause EXCEPT /*2L*/ set_quantifier select_clause + ; + +with_clause : + WITH /*13N*/ cte_list + | WITH_LA cte_list + | WITH /*13N*/ RECURSIVE cte_list + ; + +cte_list : + common_table_expr + | cte_list ',' common_table_expr + ; + +common_table_expr : + name opt_name_list AS opt_materialized '(' /*24L*/ PreparableStmt ')' /*24L*/ opt_search_clause opt_cycle_clause + ; + +opt_materialized : + MATERIALIZED + | NOT /*6R*/ MATERIALIZED + | /*empty*/ + ; + +opt_search_clause : + SEARCH DEPTH FIRST_P BY columnList SET /*1N*/ ColId + | SEARCH BREADTH FIRST_P BY columnList SET /*1N*/ ColId + | /*empty*/ + ; + +opt_cycle_clause : + CYCLE columnList SET /*1N*/ ColId TO AexprConst DEFAULT AexprConst USING ColId + | CYCLE columnList SET /*1N*/ ColId USING ColId + | /*empty*/ + ; + +opt_with_clause : + with_clause + | /*empty*/ + ; + +into_clause : + INTO OptTempTableName + | /*empty*/ + ; + +OptTempTableName : + TEMPORARY opt_table qualified_name + | TEMP opt_table qualified_name + | LOCAL TEMPORARY opt_table qualified_name + | LOCAL TEMP opt_table qualified_name + | GLOBAL TEMPORARY opt_table qualified_name + | GLOBAL TEMP opt_table qualified_name + | UNLOGGED opt_table qualified_name + | TABLE qualified_name + | qualified_name + ; + +opt_table : + TABLE + | /*empty*/ + ; + +set_quantifier : + ALL + | DISTINCT + | /*empty*/ + ; + +distinct_clause : + DISTINCT + | DISTINCT ON '(' /*24L*/ expr_list ')' /*24L*/ + ; + +opt_all_clause : + ALL + | /*empty*/ + ; + +opt_distinct_clause : + distinct_clause + | opt_all_clause + ; + +opt_sort_clause : + sort_clause + | /*empty*/ + ; + +sort_clause : + ORDER BY sortby_list + ; + +sortby_list : + sortby + | sortby_list ',' sortby + ; + +sortby : + a_expr USING qual_all_Op opt_nulls_order + | a_expr opt_asc_desc opt_nulls_order + ; + +select_limit : + limit_clause offset_clause + | offset_clause limit_clause + | limit_clause + | offset_clause + ; + +opt_select_limit : + select_limit + | /*empty*/ + ; + +limit_clause : + LIMIT select_limit_value + | LIMIT select_limit_value ',' select_offset_value + | FETCH first_or_next select_fetch_first_value row_or_rows ONLY + | FETCH first_or_next select_fetch_first_value row_or_rows WITH /*13N*/ TIES + | FETCH first_or_next row_or_rows ONLY + | FETCH first_or_next row_or_rows WITH /*13N*/ TIES + ; + +offset_clause : + OFFSET select_offset_value + | OFFSET select_fetch_first_value row_or_rows + ; + +select_limit_value : + a_expr + | ALL + ; + +select_offset_value : + a_expr + ; + +select_fetch_first_value : + c_expr + | '+' /*17L*/ I_or_F_const + | '-' /*17L*/ I_or_F_const + ; + +I_or_F_const : + Iconst + | FCONST + ; + +row_or_rows : + ROW + | ROWS /*15N*/ + ; + +first_or_next : + FIRST_P + | NEXT + ; + +group_clause : + GROUP_P BY set_quantifier group_by_list + | /*empty*/ + ; + +group_by_list : + group_by_item + | group_by_list ',' group_by_item + ; + +group_by_item : + a_expr + | empty_grouping_set + | cube_clause + | rollup_clause + | grouping_sets_clause + ; + +empty_grouping_set : + '(' /*24L*/ ')' /*24L*/ + ; + +rollup_clause : + ROLLUP /*15N*/ '(' /*24L*/ expr_list ')' /*24L*/ + ; + +cube_clause : + CUBE /*15N*/ '(' /*24L*/ expr_list ')' /*24L*/ + ; + +grouping_sets_clause : + GROUPING SETS '(' /*24L*/ group_by_list ')' /*24L*/ + ; + +having_clause : + HAVING a_expr + | /*empty*/ + ; + +for_locking_clause : + for_locking_items + | FOR READ ONLY + ; + +opt_for_locking_clause : + for_locking_clause + | /*empty*/ + ; + +for_locking_items : + for_locking_item + | for_locking_items for_locking_item + ; + +for_locking_item : + for_locking_strength locked_rels_list opt_nowait_or_skip + ; + +for_locking_strength : + FOR UPDATE + | FOR NO KEY UPDATE + | FOR SHARE + | FOR KEY SHARE + ; + +locked_rels_list : + OF qualified_name_list + | /*empty*/ + ; + +values_clause : + VALUES '(' /*24L*/ expr_list ')' /*24L*/ + | values_clause ',' '(' /*24L*/ expr_list ')' /*24L*/ + ; + +from_clause : + FROM from_list + | /*empty*/ + ; + +from_list : + table_ref + | from_list ',' table_ref + ; + +table_ref : + relation_expr opt_alias_clause + | relation_expr opt_alias_clause tablesample_clause + | func_table func_alias_clause + | LATERAL_P func_table func_alias_clause + | xmltable opt_alias_clause + | LATERAL_P xmltable opt_alias_clause + | select_with_parens opt_alias_clause + | LATERAL_P select_with_parens opt_alias_clause + | joined_table + | '(' /*24L*/ joined_table ')' /*24L*/ alias_clause + ; + +joined_table : + '(' /*24L*/ joined_table ')' /*24L*/ + | table_ref CROSS /*27L*/ JOIN /*27L*/ table_ref + | table_ref join_type JOIN /*27L*/ table_ref join_qual + | table_ref JOIN /*27L*/ table_ref join_qual + | table_ref NATURAL /*27L*/ join_type JOIN /*27L*/ table_ref + | table_ref NATURAL /*27L*/ JOIN /*27L*/ table_ref + ; + +alias_clause : + AS ColId '(' /*24L*/ name_list ')' /*24L*/ + | AS ColId + | ColId '(' /*24L*/ name_list ')' /*24L*/ + | ColId + ; + +opt_alias_clause : + alias_clause + | /*empty*/ + ; + +opt_alias_clause_for_join_using : + AS ColId + | /*empty*/ + ; + +func_alias_clause : + alias_clause + | AS '(' /*24L*/ TableFuncElementList ')' /*24L*/ + | AS ColId '(' /*24L*/ TableFuncElementList ')' /*24L*/ + | ColId '(' /*24L*/ TableFuncElementList ')' /*24L*/ + | /*empty*/ + ; + +join_type : + FULL /*27L*/ opt_outer + | LEFT /*27L*/ opt_outer + | RIGHT /*27L*/ opt_outer + | INNER_P /*27L*/ + ; + +opt_outer : + OUTER_P + | /*empty*/ + ; + +join_qual : + USING '(' /*24L*/ name_list ')' /*24L*/ opt_alias_clause_for_join_using + | ON a_expr + ; + +relation_expr : + qualified_name + | extended_relation_expr + ; + +extended_relation_expr : + qualified_name '*' /*18L*/ + | ONLY qualified_name + | ONLY '(' /*24L*/ qualified_name ')' /*24L*/ + ; + +relation_expr_list : + relation_expr + | relation_expr_list ',' relation_expr + ; + +relation_expr_opt_alias : + relation_expr %prec UMINUS /*22R*/ + | relation_expr ColId + | relation_expr AS ColId + ; + +tablesample_clause : + TABLESAMPLE func_name '(' /*24L*/ expr_list ')' /*24L*/ opt_repeatable_clause + ; + +opt_repeatable_clause : + REPEATABLE '(' /*24L*/ a_expr ')' /*24L*/ + | /*empty*/ + ; + +func_table : + func_expr_windowless opt_ordinality + | ROWS /*15N*/ FROM '(' /*24L*/ rowsfrom_list ')' /*24L*/ opt_ordinality + ; + +rowsfrom_item : + func_expr_windowless opt_col_def_list + ; + +rowsfrom_list : + rowsfrom_item + | rowsfrom_list ',' rowsfrom_item + ; + +opt_col_def_list : + AS '(' /*24L*/ TableFuncElementList ')' /*24L*/ + | /*empty*/ + ; + +opt_ordinality : + WITH_LA ORDINALITY + | /*empty*/ + ; + +where_clause : + WHERE a_expr + | /*empty*/ + ; + +where_or_current_clause : + WHERE a_expr + | WHERE CURRENT_P OF cursor_name + | /*empty*/ + ; + +OptTableFuncElementList : + TableFuncElementList + | /*empty*/ + ; + +TableFuncElementList : + TableFuncElement + | TableFuncElementList ',' TableFuncElement + ; + +TableFuncElement : + ColId Typename opt_collate_clause + ; + +xmltable : + XMLTABLE '(' /*24L*/ c_expr xmlexists_argument COLUMNS xmltable_column_list ')' /*24L*/ + | XMLTABLE '(' /*24L*/ XMLNAMESPACES '(' /*24L*/ xml_namespace_list ')' /*24L*/ ',' c_expr xmlexists_argument COLUMNS xmltable_column_list ')' /*24L*/ + ; + +xmltable_column_list : + xmltable_column_el + | xmltable_column_list ',' xmltable_column_el + ; + +xmltable_column_el : + ColId Typename + | ColId Typename xmltable_column_option_list + | ColId FOR ORDINALITY + ; + +xmltable_column_option_list : + xmltable_column_option_el + | xmltable_column_option_list xmltable_column_option_el + ; + +xmltable_column_option_el : + IDENT /*15N*/ b_expr + | DEFAULT b_expr + | NOT /*6R*/ NULL_P + | NULL_P + ; + +xml_namespace_list : + xml_namespace_el + | xml_namespace_list ',' xml_namespace_el + ; + +xml_namespace_el : + b_expr AS ColLabel + | DEFAULT b_expr + ; + +Typename : + SimpleTypename opt_array_bounds + | SETOF SimpleTypename opt_array_bounds + | SimpleTypename ARRAY '[' /*23L*/ Iconst ']' /*23L*/ + | SETOF SimpleTypename ARRAY '[' /*23L*/ Iconst ']' /*23L*/ + | SimpleTypename ARRAY + | SETOF SimpleTypename ARRAY + ; + +opt_array_bounds : + opt_array_bounds '[' /*23L*/ ']' /*23L*/ + | opt_array_bounds '[' /*23L*/ Iconst ']' /*23L*/ + | /*empty*/ + ; + +SimpleTypename : + GenericType + | Numeric + | Bit + | Character + | ConstDatetime + | ConstInterval opt_interval + | ConstInterval '(' /*24L*/ Iconst ')' /*24L*/ + ; + +ConstTypename : + Numeric + | ConstBit + | ConstCharacter + | ConstDatetime + ; + +GenericType : + type_function_name opt_type_modifiers + | type_function_name attrs opt_type_modifiers + ; + +opt_type_modifiers : + '(' /*24L*/ expr_list ')' /*24L*/ + | /*empty*/ + ; + +Numeric : + INT_P + | INTEGER + | SMALLINT + | BIGINT + | REAL + | FLOAT_P opt_float + | DOUBLE_P PRECISION + | DECIMAL_P opt_type_modifiers + | DEC opt_type_modifiers + | NUMERIC opt_type_modifiers + | BOOLEAN_P + ; + +opt_float : + '(' /*24L*/ Iconst ')' /*24L*/ + | /*empty*/ + ; + +Bit : + BitWithLength + | BitWithoutLength + ; + +ConstBit : + BitWithLength + | BitWithoutLength + ; + +BitWithLength : + BIT opt_varying '(' /*24L*/ expr_list ')' /*24L*/ + ; + +BitWithoutLength : + BIT opt_varying + ; + +Character : + CharacterWithLength + | CharacterWithoutLength + ; + +ConstCharacter : + CharacterWithLength + | CharacterWithoutLength + ; + +CharacterWithLength : + character '(' /*24L*/ Iconst ')' /*24L*/ + ; + +CharacterWithoutLength : + character + ; + +character : + CHARACTER opt_varying + | CHAR_P opt_varying + | VARCHAR + | NATIONAL CHARACTER opt_varying + | NATIONAL CHAR_P opt_varying + | NCHAR opt_varying + ; + +opt_varying : + VARYING + | /*empty*/ + ; + +ConstDatetime : + TIMESTAMP '(' /*24L*/ Iconst ')' /*24L*/ opt_timezone + | TIMESTAMP opt_timezone + | TIME '(' /*24L*/ Iconst ')' /*24L*/ opt_timezone + | TIME opt_timezone + ; + +ConstInterval : + INTERVAL + ; + +opt_timezone : + WITH_LA TIME ZONE + | WITHOUT_LA TIME ZONE + | /*empty*/ + ; + +opt_interval : + YEAR_P + | MONTH_P + | DAY_P + | HOUR_P + | MINUTE_P + | interval_second + | YEAR_P TO MONTH_P + | DAY_P TO HOUR_P + | DAY_P TO MINUTE_P + | DAY_P TO interval_second + | HOUR_P TO MINUTE_P + | HOUR_P TO interval_second + | MINUTE_P TO interval_second + | /*empty*/ + ; + +interval_second : + SECOND_P + | SECOND_P '(' /*24L*/ Iconst ')' /*24L*/ + ; + +a_expr : + c_expr + | a_expr TYPECAST /*25L*/ Typename + | a_expr COLLATE /*21L*/ any_name + | a_expr AT /*20L*/ TIME ZONE a_expr %prec AT /*20L*/ + | '+' /*17L*/ a_expr %prec UMINUS /*22R*/ + | '-' /*17L*/ a_expr %prec UMINUS /*22R*/ + | a_expr '+' /*17L*/ a_expr + | a_expr '-' /*17L*/ a_expr + | a_expr '*' /*18L*/ a_expr + | a_expr '/' /*18L*/ a_expr + | a_expr '%' /*18L*/ a_expr + | a_expr '^' /*19L*/ a_expr + | a_expr '<' /*8N*/ a_expr + | a_expr '>' /*8N*/ a_expr + | a_expr '=' /*8N*/ a_expr + | a_expr LESS_EQUALS /*8N*/ a_expr + | a_expr GREATER_EQUALS /*8N*/ a_expr + | a_expr NOT_EQUALS /*8N*/ a_expr + | a_expr qual_Op a_expr %prec Op /*16L*/ + | qual_Op a_expr %prec Op /*16L*/ + | a_expr AND /*5L*/ a_expr + | a_expr OR /*4L*/ a_expr + | NOT /*6R*/ a_expr + | NOT_LA /*9N*/ a_expr %prec NOT /*6R*/ + | a_expr LIKE /*9N*/ a_expr + | a_expr LIKE /*9N*/ a_expr ESCAPE /*10N*/ a_expr %prec LIKE /*9N*/ + | a_expr NOT_LA /*9N*/ LIKE /*9N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr NOT_LA /*9N*/ LIKE /*9N*/ a_expr ESCAPE /*10N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr ILIKE /*9N*/ a_expr + | a_expr ILIKE /*9N*/ a_expr ESCAPE /*10N*/ a_expr %prec ILIKE /*9N*/ + | a_expr NOT_LA /*9N*/ ILIKE /*9N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr NOT_LA /*9N*/ ILIKE /*9N*/ a_expr ESCAPE /*10N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr SIMILAR /*9N*/ TO a_expr %prec SIMILAR /*9N*/ + | a_expr SIMILAR /*9N*/ TO a_expr ESCAPE /*10N*/ a_expr %prec SIMILAR /*9N*/ + | a_expr NOT_LA /*9N*/ SIMILAR /*9N*/ TO a_expr %prec NOT_LA /*9N*/ + | a_expr NOT_LA /*9N*/ SIMILAR /*9N*/ TO a_expr ESCAPE /*10N*/ a_expr %prec NOT_LA /*9N*/ + | a_expr IS /*7N*/ NULL_P %prec IS /*7N*/ + | a_expr ISNULL /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ NULL_P %prec IS /*7N*/ + | a_expr NOTNULL /*7N*/ + | row OVERLAPS row + | a_expr IS /*7N*/ TRUE_P %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ TRUE_P %prec IS /*7N*/ + | a_expr IS /*7N*/ FALSE_P %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ FALSE_P %prec IS /*7N*/ + | a_expr IS /*7N*/ UNKNOWN %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ UNKNOWN %prec IS /*7N*/ + | a_expr IS /*7N*/ DISTINCT FROM a_expr %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ DISTINCT FROM a_expr %prec IS /*7N*/ + | a_expr BETWEEN /*9N*/ opt_asymmetric b_expr AND /*5L*/ a_expr %prec BETWEEN /*9N*/ + | a_expr NOT_LA /*9N*/ BETWEEN /*9N*/ opt_asymmetric b_expr AND /*5L*/ a_expr %prec NOT_LA /*9N*/ + | a_expr BETWEEN /*9N*/ SYMMETRIC b_expr AND /*5L*/ a_expr %prec BETWEEN /*9N*/ + | a_expr NOT_LA /*9N*/ BETWEEN /*9N*/ SYMMETRIC b_expr AND /*5L*/ a_expr %prec NOT_LA /*9N*/ + | a_expr IN_P /*9N*/ in_expr + | a_expr NOT_LA /*9N*/ IN_P /*9N*/ in_expr %prec NOT_LA /*9N*/ + | a_expr subquery_Op sub_type select_with_parens %prec Op /*16L*/ + | a_expr subquery_Op sub_type '(' /*24L*/ a_expr ')' /*24L*/ %prec Op /*16L*/ + | UNIQUE /*11N*/ opt_unique_null_treatment select_with_parens + | a_expr IS /*7N*/ DOCUMENT_P %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ DOCUMENT_P %prec IS /*7N*/ + | a_expr IS /*7N*/ NORMALIZED %prec IS /*7N*/ + | a_expr IS /*7N*/ unicode_normal_form NORMALIZED %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ NORMALIZED %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ unicode_normal_form NORMALIZED %prec IS /*7N*/ + | a_expr IS /*7N*/ json_predicate_type_constraint json_key_uniqueness_constraint_opt %prec IS /*7N*/ + | a_expr IS /*7N*/ NOT /*6R*/ json_predicate_type_constraint json_key_uniqueness_constraint_opt %prec IS /*7N*/ + | DEFAULT + ; + +b_expr : + c_expr + | b_expr TYPECAST /*25L*/ Typename + | '+' /*17L*/ b_expr %prec UMINUS /*22R*/ + | '-' /*17L*/ b_expr %prec UMINUS /*22R*/ + | b_expr '+' /*17L*/ b_expr + | b_expr '-' /*17L*/ b_expr + | b_expr '*' /*18L*/ b_expr + | b_expr '/' /*18L*/ b_expr + | b_expr '%' /*18L*/ b_expr + | b_expr '^' /*19L*/ b_expr + | b_expr '<' /*8N*/ b_expr + | b_expr '>' /*8N*/ b_expr + | b_expr '=' /*8N*/ b_expr + | b_expr LESS_EQUALS /*8N*/ b_expr + | b_expr GREATER_EQUALS /*8N*/ b_expr + | b_expr NOT_EQUALS /*8N*/ b_expr + | b_expr qual_Op b_expr %prec Op /*16L*/ + | qual_Op b_expr %prec Op /*16L*/ + | b_expr IS /*7N*/ DISTINCT FROM b_expr %prec IS /*7N*/ + | b_expr IS /*7N*/ NOT /*6R*/ DISTINCT FROM b_expr %prec IS /*7N*/ + | b_expr IS /*7N*/ DOCUMENT_P %prec IS /*7N*/ + | b_expr IS /*7N*/ NOT /*6R*/ DOCUMENT_P %prec IS /*7N*/ + ; + +c_expr : + columnref + | AexprConst + | PARAM opt_indirection + | '(' /*24L*/ a_expr ')' /*24L*/ opt_indirection + | case_expr + | func_expr + | select_with_parens %prec UMINUS /*22R*/ + | select_with_parens indirection + | EXISTS select_with_parens + | ARRAY select_with_parens + | ARRAY array_expr + | explicit_row + | implicit_row + | GROUPING '(' /*24L*/ expr_list ')' /*24L*/ + ; + +func_application : + func_name '(' /*24L*/ ')' /*24L*/ + | func_name '(' /*24L*/ func_arg_list opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ VARIADIC func_arg_expr opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ ALL func_arg_list opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ DISTINCT func_arg_list opt_sort_clause ')' /*24L*/ + | func_name '(' /*24L*/ '*' /*18L*/ ')' /*24L*/ + ; + +func_expr : + func_application within_group_clause filter_clause over_clause + | json_aggregate_func filter_clause over_clause + | func_expr_common_subexpr + ; + +func_expr_windowless : + func_application + | func_expr_common_subexpr + | json_aggregate_func + ; + +func_expr_common_subexpr : + COLLATION FOR '(' /*24L*/ a_expr ')' /*24L*/ + | CURRENT_DATE + | CURRENT_TIME + | CURRENT_TIME '(' /*24L*/ Iconst ')' /*24L*/ + | CURRENT_TIMESTAMP + | CURRENT_TIMESTAMP '(' /*24L*/ Iconst ')' /*24L*/ + | LOCALTIME + | LOCALTIME '(' /*24L*/ Iconst ')' /*24L*/ + | LOCALTIMESTAMP + | LOCALTIMESTAMP '(' /*24L*/ Iconst ')' /*24L*/ + | CURRENT_ROLE + | CURRENT_USER + | SESSION_USER + | SYSTEM_USER + | USER + | CURRENT_CATALOG + | CURRENT_SCHEMA + | CAST '(' /*24L*/ a_expr AS Typename ')' /*24L*/ + | EXTRACT '(' /*24L*/ extract_list ')' /*24L*/ + | NORMALIZE '(' /*24L*/ a_expr ')' /*24L*/ + | NORMALIZE '(' /*24L*/ a_expr ',' unicode_normal_form ')' /*24L*/ + | OVERLAY '(' /*24L*/ overlay_list ')' /*24L*/ + | OVERLAY '(' /*24L*/ func_arg_list_opt ')' /*24L*/ + | POSITION '(' /*24L*/ position_list ')' /*24L*/ + | SUBSTRING '(' /*24L*/ substr_list ')' /*24L*/ + | SUBSTRING '(' /*24L*/ func_arg_list_opt ')' /*24L*/ + | TREAT '(' /*24L*/ a_expr AS Typename ')' /*24L*/ + | TRIM '(' /*24L*/ BOTH trim_list ')' /*24L*/ + | TRIM '(' /*24L*/ LEADING trim_list ')' /*24L*/ + | TRIM '(' /*24L*/ TRAILING trim_list ')' /*24L*/ + | TRIM '(' /*24L*/ trim_list ')' /*24L*/ + | NULLIF '(' /*24L*/ a_expr ',' a_expr ')' /*24L*/ + | COALESCE '(' /*24L*/ expr_list ')' /*24L*/ + | GREATEST '(' /*24L*/ expr_list ')' /*24L*/ + | LEAST '(' /*24L*/ expr_list ')' /*24L*/ + | XMLCONCAT '(' /*24L*/ expr_list ')' /*24L*/ + | XMLELEMENT '(' /*24L*/ NAME_P ColLabel ')' /*24L*/ + | XMLELEMENT '(' /*24L*/ NAME_P ColLabel ',' xml_attributes ')' /*24L*/ + | XMLELEMENT '(' /*24L*/ NAME_P ColLabel ',' expr_list ')' /*24L*/ + | XMLELEMENT '(' /*24L*/ NAME_P ColLabel ',' xml_attributes ',' expr_list ')' /*24L*/ + | XMLEXISTS '(' /*24L*/ c_expr xmlexists_argument ')' /*24L*/ + | XMLFOREST '(' /*24L*/ xml_attribute_list ')' /*24L*/ + | XMLPARSE '(' /*24L*/ document_or_content a_expr xml_whitespace_option ')' /*24L*/ + | XMLPI '(' /*24L*/ NAME_P ColLabel ')' /*24L*/ + | XMLPI '(' /*24L*/ NAME_P ColLabel ',' a_expr ')' /*24L*/ + | XMLROOT '(' /*24L*/ a_expr ',' xml_root_version opt_xml_root_standalone ')' /*24L*/ + | XMLSERIALIZE '(' /*24L*/ document_or_content a_expr AS SimpleTypename xml_indent_option ')' /*24L*/ + | JSON_OBJECT '(' /*24L*/ func_arg_list ')' /*24L*/ + | JSON_OBJECT '(' /*24L*/ json_name_and_value_list json_object_constructor_null_clause_opt json_key_uniqueness_constraint_opt json_output_clause_opt ')' /*24L*/ + | JSON_OBJECT '(' /*24L*/ json_output_clause_opt ')' /*24L*/ + | JSON_ARRAY '(' /*24L*/ json_value_expr_list json_array_constructor_null_clause_opt json_output_clause_opt ')' /*24L*/ + | JSON_ARRAY '(' /*24L*/ select_no_parens json_format_clause_opt json_output_clause_opt ')' /*24L*/ + | JSON_ARRAY '(' /*24L*/ json_output_clause_opt ')' /*24L*/ + ; + +xml_root_version : + VERSION_P a_expr + | VERSION_P NO VALUE_P /*12N*/ + ; + +opt_xml_root_standalone : + ',' STANDALONE_P YES_P + | ',' STANDALONE_P NO + | ',' STANDALONE_P NO VALUE_P /*12N*/ + | /*empty*/ + ; + +xml_attributes : + XMLATTRIBUTES '(' /*24L*/ xml_attribute_list ')' /*24L*/ + ; + +xml_attribute_list : + xml_attribute_el + | xml_attribute_list ',' xml_attribute_el + ; + +xml_attribute_el : + a_expr AS ColLabel + | a_expr + ; + +document_or_content : + DOCUMENT_P + | CONTENT_P + ; + +xml_indent_option : + INDENT + | NO INDENT + | /*empty*/ + ; + +xml_whitespace_option : + PRESERVE WHITESPACE_P + | STRIP_P WHITESPACE_P + | /*empty*/ + ; + +xmlexists_argument : + PASSING c_expr + | PASSING c_expr xml_passing_mech + | PASSING xml_passing_mech c_expr + | PASSING xml_passing_mech c_expr xml_passing_mech + ; + +xml_passing_mech : + BY REF_P + | BY VALUE_P /*12N*/ + ; + +within_group_clause : + WITHIN GROUP_P '(' /*24L*/ sort_clause ')' /*24L*/ + | /*empty*/ + ; + +filter_clause : + FILTER '(' /*24L*/ WHERE a_expr ')' /*24L*/ + | /*empty*/ + ; + +window_clause : + WINDOW window_definition_list + | /*empty*/ + ; + +window_definition_list : + window_definition + | window_definition_list ',' window_definition + ; + +window_definition : + ColId AS window_specification + ; + +over_clause : + OVER window_specification + | OVER ColId + | /*empty*/ + ; + +window_specification : + '(' /*24L*/ opt_existing_window_name opt_partition_clause opt_sort_clause opt_frame_clause ')' /*24L*/ + ; + +opt_existing_window_name : + ColId + | %prec Op /*16L*/ /*empty*/ + ; + +opt_partition_clause : + PARTITION /*15N*/ BY expr_list + | /*empty*/ + ; + +opt_frame_clause : + RANGE /*15N*/ frame_extent opt_window_exclusion_clause + | ROWS /*15N*/ frame_extent opt_window_exclusion_clause + | GROUPS /*15N*/ frame_extent opt_window_exclusion_clause + | /*empty*/ + ; + +frame_extent : + frame_bound + | BETWEEN /*9N*/ frame_bound AND /*5L*/ frame_bound + ; + +frame_bound : + UNBOUNDED /*14N*/ PRECEDING /*15N*/ + | UNBOUNDED /*14N*/ FOLLOWING /*15N*/ + | CURRENT_P ROW + | a_expr PRECEDING /*15N*/ + | a_expr FOLLOWING /*15N*/ + ; + +opt_window_exclusion_clause : + EXCLUDE CURRENT_P ROW + | EXCLUDE GROUP_P + | EXCLUDE TIES + | EXCLUDE NO OTHERS + | /*empty*/ + ; + +row : + ROW '(' /*24L*/ expr_list ')' /*24L*/ + | ROW '(' /*24L*/ ')' /*24L*/ + | '(' /*24L*/ expr_list ',' a_expr ')' /*24L*/ + ; + +explicit_row : + ROW '(' /*24L*/ expr_list ')' /*24L*/ + | ROW '(' /*24L*/ ')' /*24L*/ + ; + +implicit_row : + '(' /*24L*/ expr_list ',' a_expr ')' /*24L*/ + ; + +sub_type : + ANY + | SOME + | ALL + ; + +all_Op : + Op /*16L*/ + | MathOp + ; + +MathOp : + '+' /*17L*/ + | '-' /*17L*/ + | '*' /*18L*/ + | '/' /*18L*/ + | '%' /*18L*/ + | '^' /*19L*/ + | '<' /*8N*/ + | '>' /*8N*/ + | '=' /*8N*/ + | LESS_EQUALS /*8N*/ + | GREATER_EQUALS /*8N*/ + | NOT_EQUALS /*8N*/ + ; + +qual_Op : + Op /*16L*/ + | OPERATOR /*16L*/ '(' /*24L*/ any_operator ')' /*24L*/ + ; + +qual_all_Op : + all_Op + | OPERATOR /*16L*/ '(' /*24L*/ any_operator ')' /*24L*/ + ; + +subquery_Op : + all_Op + | OPERATOR /*16L*/ '(' /*24L*/ any_operator ')' /*24L*/ + | LIKE /*9N*/ + | NOT_LA /*9N*/ LIKE /*9N*/ + | ILIKE /*9N*/ + | NOT_LA /*9N*/ ILIKE /*9N*/ + ; + +expr_list : + a_expr + | expr_list ',' a_expr + ; + +func_arg_list : + func_arg_expr + | func_arg_list ',' func_arg_expr + ; + +func_arg_expr : + a_expr + | param_name COLON_EQUALS a_expr + | param_name EQUALS_GREATER a_expr + ; + +func_arg_list_opt : + func_arg_list + | /*empty*/ + ; + +type_list : + Typename + | type_list ',' Typename + ; + +array_expr : + '[' /*23L*/ expr_list ']' /*23L*/ + | '[' /*23L*/ array_expr_list ']' /*23L*/ + | '[' /*23L*/ ']' /*23L*/ + ; + +array_expr_list : + array_expr + | array_expr_list ',' array_expr + ; + +extract_list : + extract_arg FROM a_expr + ; + +extract_arg : + IDENT /*15N*/ + | YEAR_P + | MONTH_P + | DAY_P + | HOUR_P + | MINUTE_P + | SECOND_P + | Sconst + ; + +unicode_normal_form : + NFC + | NFD + | NFKC + | NFKD + ; + +overlay_list : + a_expr PLACING a_expr FROM a_expr FOR a_expr + | a_expr PLACING a_expr FROM a_expr + ; + +position_list : + b_expr IN_P /*9N*/ b_expr + ; + +substr_list : + a_expr FROM a_expr FOR a_expr + | a_expr FOR a_expr FROM a_expr + | a_expr FROM a_expr + | a_expr FOR a_expr + | a_expr SIMILAR /*9N*/ a_expr ESCAPE /*10N*/ a_expr + ; + +trim_list : + a_expr FROM expr_list + | FROM expr_list + | expr_list + ; + +in_expr : + select_with_parens + | '(' /*24L*/ expr_list ')' /*24L*/ + ; + +case_expr : + CASE case_arg when_clause_list case_default END_P + ; + +when_clause_list : + when_clause + | when_clause_list when_clause + ; + +when_clause : + WHEN a_expr THEN a_expr + ; + +case_default : + ELSE a_expr + | /*empty*/ + ; + +case_arg : + a_expr + | /*empty*/ + ; + +columnref : + ColId + | ColId indirection + ; + +indirection_el : + '.' /*26L*/ attr_name + | '.' /*26L*/ '*' /*18L*/ + | '[' /*23L*/ a_expr ']' /*23L*/ + | '[' /*23L*/ opt_slice_bound ':' opt_slice_bound ']' /*23L*/ + ; + +opt_slice_bound : + a_expr + | /*empty*/ + ; + +indirection : + indirection_el + | indirection indirection_el + ; + +opt_indirection : + /*empty*/ + | opt_indirection indirection_el + ; + +opt_asymmetric : + ASYMMETRIC + | /*empty*/ + ; + +json_value_expr : + a_expr json_format_clause_opt + ; + +json_format_clause_opt : + FORMAT_LA JSON /*11N*/ json_encoding_clause_opt + | /*empty*/ + ; + +json_encoding_clause_opt : + ENCODING name + | /*empty*/ + ; + +json_output_clause_opt : + RETURNING Typename json_format_clause_opt + | /*empty*/ + ; + +json_predicate_type_constraint : + JSON /*11N*/ + | JSON /*11N*/ VALUE_P /*12N*/ + | JSON /*11N*/ ARRAY + | JSON /*11N*/ OBJECT_P /*12N*/ + | JSON /*11N*/ SCALAR /*12N*/ + ; + +json_key_uniqueness_constraint_opt : + WITH /*13N*/ UNIQUE /*11N*/ KEYS /*12N*/ + | WITH /*13N*/ UNIQUE /*11N*/ + | WITHOUT /*13N*/ UNIQUE /*11N*/ KEYS /*12N*/ + | WITHOUT /*13N*/ UNIQUE /*11N*/ + | %prec KEYS /*12N*/ /*empty*/ + ; + +json_name_and_value_list : + json_name_and_value + | json_name_and_value_list ',' json_name_and_value + ; + +json_name_and_value : + c_expr VALUE_P /*12N*/ json_value_expr + | a_expr ':' json_value_expr + ; + +json_object_constructor_null_clause_opt : + NULL_P ON NULL_P + | ABSENT ON NULL_P + | /*empty*/ + ; + +json_array_constructor_null_clause_opt : + NULL_P ON NULL_P + | ABSENT ON NULL_P + | /*empty*/ + ; + +json_value_expr_list : + json_value_expr + | json_value_expr_list ',' json_value_expr + ; + +json_aggregate_func : + JSON_OBJECTAGG '(' /*24L*/ json_name_and_value json_object_constructor_null_clause_opt json_key_uniqueness_constraint_opt json_output_clause_opt ')' /*24L*/ + | JSON_ARRAYAGG '(' /*24L*/ json_value_expr json_array_aggregate_order_by_clause_opt json_array_constructor_null_clause_opt json_output_clause_opt ')' /*24L*/ + ; + +json_array_aggregate_order_by_clause_opt : + ORDER BY sortby_list + | /*empty*/ + ; + +opt_target_list : + target_list + | /*empty*/ + ; + +target_list : + target_el + | target_list ',' target_el + ; + +target_el : + a_expr AS ColLabel + | a_expr BareColLabel + | a_expr + | '*' /*18L*/ + ; + +qualified_name_list : + qualified_name + | qualified_name_list ',' qualified_name + ; + +qualified_name : + ColId + | ColId indirection + ; + +name_list : + name + | name_list ',' name + ; + +name : + ColId + ; + +attr_name : + ColLabel + ; + +file_name : + Sconst + ; + +func_name : + type_function_name + | ColId indirection + ; + +AexprConst : + Iconst + | FCONST + | Sconst + | BCONST + | XCONST + | func_name Sconst + | func_name '(' /*24L*/ func_arg_list opt_sort_clause ')' /*24L*/ Sconst + | ConstTypename Sconst + | ConstInterval Sconst opt_interval + | ConstInterval '(' /*24L*/ Iconst ')' /*24L*/ Sconst + | TRUE_P + | FALSE_P + | NULL_P + ; + +Iconst : + ICONST + ; + +Sconst : + SCONST + ; + +SignedIconst : + Iconst + | '+' /*17L*/ Iconst + | '-' /*17L*/ Iconst + ; + +RoleId : + RoleSpec + ; + +RoleSpec : + NonReservedWord + | CURRENT_ROLE + | CURRENT_USER + | SESSION_USER + ; + +role_list : + RoleSpec + | role_list ',' RoleSpec + ; + +PLpgSQL_Expr : + opt_distinct_clause opt_target_list from_clause where_clause group_clause having_clause window_clause opt_sort_clause opt_select_limit opt_for_locking_clause + ; + +PLAssignStmt : + plassign_target opt_indirection plassign_equals PLpgSQL_Expr + ; + +plassign_target : + ColId + | PARAM + ; + +plassign_equals : + COLON_EQUALS + | '=' /*8N*/ + ; + +ColId : + IDENT /*15N*/ + | unreserved_keyword + | col_name_keyword + ; + +type_function_name : + IDENT /*15N*/ + | unreserved_keyword + | type_func_name_keyword + ; + +NonReservedWord : + IDENT /*15N*/ + | unreserved_keyword + | col_name_keyword + | type_func_name_keyword + ; + +ColLabel : + IDENT /*15N*/ + | unreserved_keyword + | col_name_keyword + | type_func_name_keyword + | reserved_keyword + ; + +BareColLabel : + IDENT /*15N*/ + | bare_label_keyword + ; + +unreserved_keyword : + ABORT_P + | ABSENT + | ABSOLUTE_P + | ACCESS + | ACTION + | ADD_P + | ADMIN + | AFTER + | AGGREGATE + | ALSO + | ALTER + | ALWAYS + | ASENSITIVE + | ASSERTION + | ASSIGNMENT + | AT /*20L*/ + | ATOMIC + | ATTACH + | ATTRIBUTE + | BACKWARD + | BEFORE + | BEGIN_P + | BREADTH + | BY + | CACHE + | CALL + | CALLED + | CASCADE + | CASCADED + | CATALOG_P + | CHAIN + | CHARACTERISTICS + | CHECKPOINT + | CLASS + | CLOSE + | CLUSTER + | COLUMNS + | COMMENT + | COMMENTS + | COMMIT + | COMMITTED + | COMPRESSION + | CONFIGURATION + | CONFLICT + | CONNECTION + | CONSTRAINTS + | CONTENT_P + | CONTINUE_P + | CONVERSION_P + | COPY + | COST + | CSV + | CUBE /*15N*/ + | CURRENT_P + | CURSOR + | CYCLE + | DATA_P + | DATABASE + | DAY_P + | DEALLOCATE + | DECLARE + | DEFAULTS + | DEFERRED + | DEFINER + | DELETE_P + | DELIMITER + | DELIMITERS + | DEPENDS + | DEPTH + | DETACH + | DICTIONARY + | DISABLE_P + | DISCARD + | DOCUMENT_P + | DOMAIN_P + | DOUBLE_P + | DROP + | EACH + | ENABLE_P + | ENCODING + | ENCRYPTED + | ENUM_P + | ESCAPE /*10N*/ + | EVENT + | EXCLUDE + | EXCLUDING + | EXCLUSIVE + | EXECUTE + | EXPLAIN + | EXPRESSION + | EXTENSION + | EXTERNAL + | FAMILY + | FILTER + | FINALIZE + | FIRST_P + | FOLLOWING /*15N*/ + | FORCE + | FORMAT + | FORWARD + | FUNCTION + | FUNCTIONS + | GENERATED + | GLOBAL + | GRANTED + | GROUPS /*15N*/ + | HANDLER + | HEADER_P + | HOLD + | HOUR_P + | IDENTITY_P + | IF_P + | IMMEDIATE + | IMMUTABLE + | IMPLICIT_P + | IMPORT_P + | INCLUDE + | INCLUDING + | INCREMENT + | INDENT + | INDEX + | INDEXES + | INHERIT + | INHERITS + | INLINE_P + | INPUT_P + | INSENSITIVE + | INSERT + | INSTEAD + | INVOKER + | ISOLATION + | JSON /*11N*/ + | KEY + | KEYS /*12N*/ + | LABEL + | LANGUAGE + | LARGE_P + | LAST_P + | LEAKPROOF + | LEVEL + | LISTEN + | LOAD + | LOCAL + | LOCATION + | LOCK_P + | LOCKED + | LOGGED + | MAPPING + | MATCH + | MATCHED + | MATERIALIZED + | MAXVALUE + | MERGE + | METHOD + | MINUTE_P + | MINVALUE + | MODE + | MONTH_P + | MOVE + | NAME_P + | NAMES + | NEW + | NEXT + | NFC + | NFD + | NFKC + | NFKD + | NO + | NORMALIZED + | NOTHING + | NOTIFY + | NOWAIT + | NULLS_P + | OBJECT_P /*12N*/ + | OF + | OFF + | OIDS + | OLD + | OPERATOR /*16L*/ + | OPTION + | OPTIONS + | ORDINALITY + | OTHERS + | OVER + | OVERRIDING + | OWNED + | OWNER + | PARALLEL + | PARAMETER + | PARSER + | PARTIAL + | PARTITION /*15N*/ + | PASSING + | PASSWORD + | PLANS + | POLICY + | PRECEDING /*15N*/ + | PREPARE + | PREPARED + | PRESERVE + | PRIOR + | PRIVILEGES + | PROCEDURAL + | PROCEDURE + | PROCEDURES + | PROGRAM + | PUBLICATION + | QUOTE + | RANGE /*15N*/ + | READ + | REASSIGN + | RECHECK + | RECURSIVE + | REF_P + | REFERENCING + | REFRESH + | REINDEX + | RELATIVE_P + | RELEASE + | RENAME + | REPEATABLE + | REPLACE + | REPLICA + | RESET + | RESTART + | RESTRICT + | RETURN + | RETURNS + | REVOKE + | ROLE + | ROLLBACK + | ROLLUP /*15N*/ + | ROUTINE + | ROUTINES + | ROWS /*15N*/ + | RULE + | SAVEPOINT + | SCALAR /*12N*/ + | SCHEMA + | SCHEMAS + | SCROLL + | SEARCH + | SECOND_P + | SECURITY + | SEQUENCE + | SEQUENCES + | SERIALIZABLE + | SERVER + | SESSION + | SET /*1N*/ + | SETS + | SHARE + | SHOW + | SIMPLE + | SKIP + | SNAPSHOT + | SQL_P + | STABLE + | STANDALONE_P + | START + | STATEMENT + | STATISTICS + | STDIN + | STDOUT + | STORAGE + | STORED + | STRICT_P + | STRIP_P + | SUBSCRIPTION + | SUPPORT + | SYSID + | SYSTEM_P + | TABLES + | TABLESPACE + | TEMP + | TEMPLATE + | TEMPORARY + | TEXT_P + | TIES + | TRANSACTION + | TRANSFORM + | TRIGGER + | TRUNCATE + | TRUSTED + | TYPE_P + | TYPES_P + | UESCAPE + | UNBOUNDED /*14N*/ + | UNCOMMITTED + | UNENCRYPTED + | UNKNOWN + | UNLISTEN + | UNLOGGED + | UNTIL + | UPDATE + | VACUUM + | VALID + | VALIDATE + | VALIDATOR + | VALUE_P /*12N*/ + | VARYING + | VERSION_P + | VIEW + | VIEWS + | VOLATILE + | WHITESPACE_P + | WITHIN + | WITHOUT /*13N*/ + | WORK + | WRAPPER + | WRITE + | XML_P + | YEAR_P + | YES_P + | ZONE + ; + +col_name_keyword : + BETWEEN /*9N*/ + | BIGINT + | BIT + | BOOLEAN_P + | CHAR_P + | CHARACTER + | COALESCE + | DEC + | DECIMAL_P + | EXISTS + | EXTRACT + | FLOAT_P + | GREATEST + | GROUPING + | INOUT + | INT_P + | INTEGER + | INTERVAL + | JSON_ARRAY + | JSON_ARRAYAGG + | JSON_OBJECT + | JSON_OBJECTAGG + | LEAST + | NATIONAL + | NCHAR + | NONE + | NORMALIZE + | NULLIF + | NUMERIC + | OUT_P + | OVERLAY + | POSITION + | PRECISION + | REAL + | ROW + | SETOF + | SMALLINT + | SUBSTRING + | TIME + | TIMESTAMP + | TREAT + | TRIM + | VALUES + | VARCHAR + | XMLATTRIBUTES + | XMLCONCAT + | XMLELEMENT + | XMLEXISTS + | XMLFOREST + | XMLNAMESPACES + | XMLPARSE + | XMLPI + | XMLROOT + | XMLSERIALIZE + | XMLTABLE + ; + +type_func_name_keyword : + AUTHORIZATION + | BINARY + | COLLATION + | CONCURRENTLY + | CROSS /*27L*/ + | CURRENT_SCHEMA + | FREEZE + | FULL /*27L*/ + | ILIKE /*9N*/ + | INNER_P /*27L*/ + | IS /*7N*/ + | ISNULL /*7N*/ + | JOIN /*27L*/ + | LEFT /*27L*/ + | LIKE /*9N*/ + | NATURAL /*27L*/ + | NOTNULL /*7N*/ + | OUTER_P + | OVERLAPS + | RIGHT /*27L*/ + | SIMILAR /*9N*/ + | TABLESAMPLE + | VERBOSE + ; + +reserved_keyword : + ALL + | ANALYSE + | ANALYZE + | AND /*5L*/ + | ANY + | ARRAY + | AS + | ASC + | ASYMMETRIC + | BOTH + | CASE + | CAST + | CHECK + | COLLATE /*21L*/ + | COLUMN + | CONSTRAINT + | CREATE + | CURRENT_CATALOG + | CURRENT_DATE + | CURRENT_ROLE + | CURRENT_TIME + | CURRENT_TIMESTAMP + | CURRENT_USER + | DEFAULT + | DEFERRABLE + | DESC + | DISTINCT + | DO + | ELSE + | END_P + | EXCEPT /*2L*/ + | FALSE_P + | FETCH + | FOR + | FOREIGN + | FROM + | GRANT + | GROUP_P + | HAVING + | IN_P /*9N*/ + | INITIALLY + | INTERSECT /*3L*/ + | INTO + | LATERAL_P + | LEADING + | LIMIT + | LOCALTIME + | LOCALTIMESTAMP + | NOT /*6R*/ + | NULL_P + | OFFSET + | ON + | ONLY + | OR /*4L*/ + | ORDER + | PLACING + | PRIMARY + | REFERENCES + | RETURNING + | SELECT + | SESSION_USER + | SOME + | SYMMETRIC + | SYSTEM_USER + | TABLE + | THEN + | TO + | TRAILING + | TRUE_P + | UNION /*2L*/ + | UNIQUE /*11N*/ + | USER + | USING + | VARIADIC + | WHEN + | WHERE + | WINDOW + | WITH /*13N*/ + ; + +bare_label_keyword : + ABORT_P + | ABSENT + | ABSOLUTE_P + | ACCESS + | ACTION + | ADD_P + | ADMIN + | AFTER + | AGGREGATE + | ALL + | ALSO + | ALTER + | ALWAYS + | ANALYSE + | ANALYZE + | AND /*5L*/ + | ANY + | ASC + | ASENSITIVE + | ASSERTION + | ASSIGNMENT + | ASYMMETRIC + | AT /*20L*/ + | ATOMIC + | ATTACH + | ATTRIBUTE + | AUTHORIZATION + | BACKWARD + | BEFORE + | BEGIN_P + | BETWEEN /*9N*/ + | BIGINT + | BINARY + | BIT + | BOOLEAN_P + | BOTH + | BREADTH + | BY + | CACHE + | CALL + | CALLED + | CASCADE + | CASCADED + | CASE + | CAST + | CATALOG_P + | CHAIN + | CHARACTERISTICS + | CHECK + | CHECKPOINT + | CLASS + | CLOSE + | CLUSTER + | COALESCE + | COLLATE /*21L*/ + | COLLATION + | COLUMN + | COLUMNS + | COMMENT + | COMMENTS + | COMMIT + | COMMITTED + | COMPRESSION + | CONCURRENTLY + | CONFIGURATION + | CONFLICT + | CONNECTION + | CONSTRAINT + | CONSTRAINTS + | CONTENT_P + | CONTINUE_P + | CONVERSION_P + | COPY + | COST + | CROSS /*27L*/ + | CSV + | CUBE /*15N*/ + | CURRENT_P + | CURRENT_CATALOG + | CURRENT_DATE + | CURRENT_ROLE + | CURRENT_SCHEMA + | CURRENT_TIME + | CURRENT_TIMESTAMP + | CURRENT_USER + | CURSOR + | CYCLE + | DATA_P + | DATABASE + | DEALLOCATE + | DEC + | DECIMAL_P + | DECLARE + | DEFAULT + | DEFAULTS + | DEFERRABLE + | DEFERRED + | DEFINER + | DELETE_P + | DELIMITER + | DELIMITERS + | DEPENDS + | DEPTH + | DESC + | DETACH + | DICTIONARY + | DISABLE_P + | DISCARD + | DISTINCT + | DO + | DOCUMENT_P + | DOMAIN_P + | DOUBLE_P + | DROP + | EACH + | ELSE + | ENABLE_P + | ENCODING + | ENCRYPTED + | END_P + | ENUM_P + | ESCAPE /*10N*/ + | EVENT + | EXCLUDE + | EXCLUDING + | EXCLUSIVE + | EXECUTE + | EXISTS + | EXPLAIN + | EXPRESSION + | EXTENSION + | EXTERNAL + | EXTRACT + | FALSE_P + | FAMILY + | FINALIZE + | FIRST_P + | FLOAT_P + | FOLLOWING /*15N*/ + | FORCE + | FOREIGN + | FORMAT + | FORWARD + | FREEZE + | FULL /*27L*/ + | FUNCTION + | FUNCTIONS + | GENERATED + | GLOBAL + | GRANTED + | GREATEST + | GROUPING + | GROUPS /*15N*/ + | HANDLER + | HEADER_P + | HOLD + | IDENTITY_P + | IF_P + | ILIKE /*9N*/ + | IMMEDIATE + | IMMUTABLE + | IMPLICIT_P + | IMPORT_P + | IN_P /*9N*/ + | INCLUDE + | INCLUDING + | INCREMENT + | INDENT + | INDEX + | INDEXES + | INHERIT + | INHERITS + | INITIALLY + | INLINE_P + | INNER_P /*27L*/ + | INOUT + | INPUT_P + | INSENSITIVE + | INSERT + | INSTEAD + | INT_P + | INTEGER + | INTERVAL + | INVOKER + | IS /*7N*/ + | ISOLATION + | JOIN /*27L*/ + | JSON /*11N*/ + | JSON_ARRAY + | JSON_ARRAYAGG + | JSON_OBJECT + | JSON_OBJECTAGG + | KEY + | KEYS /*12N*/ + | LABEL + | LANGUAGE + | LARGE_P + | LAST_P + | LATERAL_P + | LEADING + | LEAKPROOF + | LEAST + | LEFT /*27L*/ + | LEVEL + | LIKE /*9N*/ + | LISTEN + | LOAD + | LOCAL + | LOCALTIME + | LOCALTIMESTAMP + | LOCATION + | LOCK_P + | LOCKED + | LOGGED + | MAPPING + | MATCH + | MATCHED + | MATERIALIZED + | MAXVALUE + | MERGE + | METHOD + | MINVALUE + | MODE + | MOVE + | NAME_P + | NAMES + | NATIONAL + | NATURAL /*27L*/ + | NCHAR + | NEW + | NEXT + | NFC + | NFD + | NFKC + | NFKD + | NO + | NONE + | NORMALIZE + | NORMALIZED + | NOT /*6R*/ + | NOTHING + | NOTIFY + | NOWAIT + | NULL_P + | NULLIF + | NULLS_P + | NUMERIC + | OBJECT_P /*12N*/ + | OF + | OFF + | OIDS + | OLD + | ONLY + | OPERATOR /*16L*/ + | OPTION + | OPTIONS + | OR /*4L*/ + | ORDINALITY + | OTHERS + | OUT_P + | OUTER_P + | OVERLAY + | OVERRIDING + | OWNED + | OWNER + | PARALLEL + | PARAMETER + | PARSER + | PARTIAL + | PARTITION /*15N*/ + | PASSING + | PASSWORD + | PLACING + | PLANS + | POLICY + | POSITION + | PRECEDING /*15N*/ + | PREPARE + | PREPARED + | PRESERVE + | PRIMARY + | PRIOR + | PRIVILEGES + | PROCEDURAL + | PROCEDURE + | PROCEDURES + | PROGRAM + | PUBLICATION + | QUOTE + | RANGE /*15N*/ + | READ + | REAL + | REASSIGN + | RECHECK + | RECURSIVE + | REF_P + | REFERENCES + | REFERENCING + | REFRESH + | REINDEX + | RELATIVE_P + | RELEASE + | RENAME + | REPEATABLE + | REPLACE + | REPLICA + | RESET + | RESTART + | RESTRICT + | RETURN + | RETURNS + | REVOKE + | RIGHT /*27L*/ + | ROLE + | ROLLBACK + | ROLLUP /*15N*/ + | ROUTINE + | ROUTINES + | ROW + | ROWS /*15N*/ + | RULE + | SAVEPOINT + | SCALAR /*12N*/ + | SCHEMA + | SCHEMAS + | SCROLL + | SEARCH + | SECURITY + | SELECT + | SEQUENCE + | SEQUENCES + | SERIALIZABLE + | SERVER + | SESSION + | SESSION_USER + | SET /*1N*/ + | SETOF + | SETS + | SHARE + | SHOW + | SIMILAR /*9N*/ + | SIMPLE + | SKIP + | SMALLINT + | SNAPSHOT + | SOME + | SQL_P + | STABLE + | STANDALONE_P + | START + | STATEMENT + | STATISTICS + | STDIN + | STDOUT + | STORAGE + | STORED + | STRICT_P + | STRIP_P + | SUBSCRIPTION + | SUBSTRING + | SUPPORT + | SYMMETRIC + | SYSID + | SYSTEM_P + | SYSTEM_USER + | TABLE + | TABLES + | TABLESAMPLE + | TABLESPACE + | TEMP + | TEMPLATE + | TEMPORARY + | TEXT_P + | THEN + | TIES + | TIME + | TIMESTAMP + | TRAILING + | TRANSACTION + | TRANSFORM + | TREAT + | TRIGGER + | TRIM + | TRUE_P + | TRUNCATE + | TRUSTED + | TYPE_P + | TYPES_P + | UESCAPE + | UNBOUNDED /*14N*/ + | UNCOMMITTED + | UNENCRYPTED + | UNIQUE /*11N*/ + | UNKNOWN + | UNLISTEN + | UNLOGGED + | UNTIL + | UPDATE + | USER + | USING + | VACUUM + | VALID + | VALIDATE + | VALIDATOR + | VALUE_P /*12N*/ + | VALUES + | VARCHAR + | VARIADIC + | VERBOSE + | VERSION_P + | VIEW + | VIEWS + | VOLATILE + | WHEN + | WHITESPACE_P + | WORK + | WRAPPER + | WRITE + | XML_P + | XMLATTRIBUTES + | XMLCONCAT + | XMLELEMENT + | XMLEXISTS + | XMLFOREST + | XMLNAMESPACES + | XMLPARSE + | XMLPI + | XMLROOT + | XMLSERIALIZE + | XMLTABLE + | YES_P + | ZONE + ; + +// Tokens + +/* + * List of keyword (name, token-value, category, bare-label-status) entries. + * + * Note: gen_keywordlist.pl requires the entries to appear in ASCII order. + */ + + //PG_KEYWORD("\([^"]+\)", \(\w[^,]+\),.+ +/* name, value, category, is-bare-label */ +ABORT_P : "[aA][bB][oO][rR][tT]" ; +ABSENT : "[aA][bB][sS][eE][nN][tT]" ; +ABSOLUTE_P : "[aA][bB][sS][oO][lL][uU][tT][eE]" ; +ACCESS : "[aA][cC][cC][eE][sS][sS]" ; +ACTION : "[aA][cC][tT][iI][oO][nN]" ; +ADD_P : "[aA][dD][dD]" ; +ADMIN : "[aA][dD][mM][iI][nN]" ; +AFTER : "[aA][fF][tT][eE][rR]" ; +AGGREGATE : "[aA][gG][gG][rR][eE][gG][aA][tT][eE]" ; +ALL : "[aA][lL][lL]" ; +ALSO : "[aA][lL][sS][oO]" ; +ALTER : "[aA][lL][tT][eE][rR]" ; +ALWAYS : "[aA][lL][wW][aA][yY][sS]" ; +ANALYSE : "[aA][nN][aA][lL][yY][sS][eE]" ; +ANALYZE : "[aA][nN][aA][lL][yY][zZ][eE]" ; +AND : "[aA][nN][dD]" ; +ANY : "[aA][nN][yY]" ; +ARRAY : "[aA][rR][rR][aA][yY]" ; +AS : "[aA][sS]" ; +ASC : "[aA][sS][cC]" ; +ASENSITIVE : "[aA][sS][eE][nN][sS][iI][tT][iI][vV][eE]" ; +ASSERTION : "[aA][sS][sS][eE][rR][tT][iI][oO][nN]" ; +ASSIGNMENT : "[aA][sS][sS][iI][gG][nN][mM][eE][nN][tT]" ; +ASYMMETRIC : "[aA][sS][yY][mM][mM][eE][tT][rR][iI][cC]" ; +AT : "[aA][tT]" ; +ATOMIC : "[aA][tT][oO][mM][iI][cC]" ; +ATTACH : "[aA][tT][tT][aA][cC][hH]" ; +ATTRIBUTE : "[aA][tT][tT][rR][iI][bB][uU][tT][eE]" ; +AUTHORIZATION : "[aA][uU][tT][hH][oO][rR][iI][zZ][aA][tT][iI][oO][nN]" ; +BACKWARD : "[bB][aA][cC][kK][wW][aA][rR][dD]" ; +BEFORE : "[bB][eE][fF][oO][rR][eE]" ; +BEGIN_P : "[bB][eE][gG][iI][nN]" ; +BETWEEN : "[bB][eE][tT][wW][eE][eE][nN]" ; +BIGINT : "[bB][iI][gG][iI][nN][tT]" ; +BINARY : "[bB][iI][nN][aA][rR][yY]" ; +BIT : "[bB][iI][tT]" ; +BOOLEAN_P : "[bB][oO][oO][lL][eE][aA][nN]" ; +BOTH : "[bB][oO][tT][hH]" ; +BREADTH : "[bB][rR][eE][aA][dD][tT][hH]" ; +BY : "[bB][yY]" ; +CACHE : "[cC][aA][cC][hH][eE]" ; +CALL : "[cC][aA][lL][lL]" ; +CALLED : "[cC][aA][lL][lL][eE][dD]" ; +CASCADE : "[cC][aA][sS][cC][aA][dD][eE]" ; +CASCADED : "[cC][aA][sS][cC][aA][dD][eE][dD]" ; +CASE : "[cC][aA][sS][eE]" ; +CAST : "[cC][aA][sS][tT]" ; +CATALOG_P : "[cC][aA][tT][aA][lL][oO][gG]" ; +CHAIN : "[cC][hH][aA][iI][nN]" ; +CHAR_P : "[cC][hH][aA][rR]" ; +CHARACTER : "[cC][hH][aA][rR][aA][cC][tT][eE][rR]" ; +CHARACTERISTICS : "[cC][hH][aA][rR][aA][cC][tT][eE][rR][iI][sS][tT][iI][cC][sS]" ; +CHECK : "[cC][hH][eE][cC][kK]" ; +CHECKPOINT : "[cC][hH][eE][cC][kK][pP][oO][iI][nN][tT]" ; +CLASS : "[cC][lL][aA][sS][sS]" ; +CLOSE : "[cC][lL][oO][sS][eE]" ; +CLUSTER : "[cC][lL][uU][sS][tT][eE][rR]" ; +COALESCE : "[cC][oO][aA][lL][eE][sS][cC][eE]" ; +COLLATE : "[cC][oO][lL][lL][aA][tT][eE]" ; +COLLATION : "[cC][oO][lL][lL][aA][tT][iI][oO][nN]" ; +COLUMN : "[cC][oO][lL][uU][mM][nN]" ; +COLUMNS : "[cC][oO][lL][uU][mM][nN][sS]" ; +COMMENT : "[cC][oO][mM][mM][eE][nN][tT]" ; +COMMENTS : "[cC][oO][mM][mM][eE][nN][tT][sS]" ; +COMMIT : "[cC][oO][mM][mM][iI][tT]" ; +COMMITTED : "[cC][oO][mM][mM][iI][tT][tT][eE][dD]" ; +COMPRESSION : "[cC][oO][mM][pP][rR][eE][sS][sS][iI][oO][nN]" ; +CONCURRENTLY : "[cC][oO][nN][cC][uU][rR][rR][eE][nN][tT][lL][yY]" ; +CONFIGURATION : "[cC][oO][nN][fF][iI][gG][uU][rR][aA][tT][iI][oO][nN]" ; +CONFLICT : "[cC][oO][nN][fF][lL][iI][cC][tT]" ; +CONNECTION : "[cC][oO][nN][nN][eE][cC][tT][iI][oO][nN]" ; +CONSTRAINT : "[cC][oO][nN][sS][tT][rR][aA][iI][nN][tT]" ; +CONSTRAINTS : "[cC][oO][nN][sS][tT][rR][aA][iI][nN][tT][sS]" ; +CONTENT_P : "[cC][oO][nN][tT][eE][nN][tT]" ; +CONTINUE_P : "[cC][oO][nN][tT][iI][nN][uU][eE]" ; +CONVERSION_P : "[cC][oO][nN][vV][eE][rR][sS][iI][oO][nN]" ; +COPY : "[cC][oO][pP][yY]" ; +COST : "[cC][oO][sS][tT]" ; +CREATE : "[cC][rR][eE][aA][tT][eE]" ; +CROSS : "[cC][rR][oO][sS][sS]" ; +CSV : "[cC][sS][vV]" ; +CUBE : "[cC][uU][bB][eE]" ; +CURRENT_P : "[cC][uU][rR][rR][eE][nN][tT]" ; +CURRENT_CATALOG : "[cC][uU][rR][rR][eE][nN][tT][__][cC][aA][tT][aA][lL][oO][gG]" ; +CURRENT_DATE : "[cC][uU][rR][rR][eE][nN][tT][__][dD][aA][tT][eE]" ; +CURRENT_ROLE : "[cC][uU][rR][rR][eE][nN][tT][__][rR][oO][lL][eE]" ; +CURRENT_SCHEMA : "[cC][uU][rR][rR][eE][nN][tT][__][sS][cC][hH][eE][mM][aA]" ; +CURRENT_TIME : "[cC][uU][rR][rR][eE][nN][tT][__][tT][iI][mM][eE]" ; +CURRENT_TIMESTAMP : "[cC][uU][rR][rR][eE][nN][tT][__][tT][iI][mM][eE][sS][tT][aA][mM][pP]" ; +CURRENT_USER : "[cC][uU][rR][rR][eE][nN][tT][__][uU][sS][eE][rR]" ; +CURSOR : "[cC][uU][rR][sS][oO][rR]" ; +CYCLE : "[cC][yY][cC][lL][eE]" ; +DATA_P : "[dD][aA][tT][aA]" ; +DATABASE : "[dD][aA][tT][aA][bB][aA][sS][eE]" ; +DAY_P : "[dD][aA][yY]" ; +DEALLOCATE : "[dD][eE][aA][lL][lL][oO][cC][aA][tT][eE]" ; +DEC : "[dD][eE][cC]" ; +DECIMAL_P : "[dD][eE][cC][iI][mM][aA][lL]" ; +DECLARE : "[dD][eE][cC][lL][aA][rR][eE]" ; +DEFAULT : "[dD][eE][fF][aA][uU][lL][tT]" ; +DEFAULTS : "[dD][eE][fF][aA][uU][lL][tT][sS]" ; +DEFERRABLE : "[dD][eE][fF][eE][rR][rR][aA][bB][lL][eE]" ; +DEFERRED : "[dD][eE][fF][eE][rR][rR][eE][dD]" ; +DEFINER : "[dD][eE][fF][iI][nN][eE][rR]" ; +DELETE_P : "[dD][eE][lL][eE][tT][eE]" ; +DELIMITER : "[dD][eE][lL][iI][mM][iI][tT][eE][rR]" ; +DELIMITERS : "[dD][eE][lL][iI][mM][iI][tT][eE][rR][sS]" ; +DEPENDS : "[dD][eE][pP][eE][nN][dD][sS]" ; +DEPTH : "[dD][eE][pP][tT][hH]" ; +DESC : "[dD][eE][sS][cC]" ; +DETACH : "[dD][eE][tT][aA][cC][hH]" ; +DICTIONARY : "[dD][iI][cC][tT][iI][oO][nN][aA][rR][yY]" ; +DISABLE_P : "[dD][iI][sS][aA][bB][lL][eE]" ; +DISCARD : "[dD][iI][sS][cC][aA][rR][dD]" ; +DISTINCT : "[dD][iI][sS][tT][iI][nN][cC][tT]" ; +DO : "[dD][oO]" ; +DOCUMENT_P : "[dD][oO][cC][uU][mM][eE][nN][tT]" ; +DOMAIN_P : "[dD][oO][mM][aA][iI][nN]" ; +DOUBLE_P : "[dD][oO][uU][bB][lL][eE]" ; +DROP : "[dD][rR][oO][pP]" ; +EACH : "[eE][aA][cC][hH]" ; +ELSE : "[eE][lL][sS][eE]" ; +ENABLE_P : "[eE][nN][aA][bB][lL][eE]" ; +ENCODING : "[eE][nN][cC][oO][dD][iI][nN][gG]" ; +ENCRYPTED : "[eE][nN][cC][rR][yY][pP][tT][eE][dD]" ; +END_P : "[eE][nN][dD]" ; +ENUM_P : "[eE][nN][uU][mM]" ; +ESCAPE : "[eE][sS][cC][aA][pP][eE]" ; +EVENT : "[eE][vV][eE][nN][tT]" ; +EXCEPT : "[eE][xX][cC][eE][pP][tT]" ; +EXCLUDE : "[eE][xX][cC][lL][uU][dD][eE]" ; +EXCLUDING : "[eE][xX][cC][lL][uU][dD][iI][nN][gG]" ; +EXCLUSIVE : "[eE][xX][cC][lL][uU][sS][iI][vV][eE]" ; +EXECUTE : "[eE][xX][eE][cC][uU][tT][eE]" ; +EXISTS : "[eE][xX][iI][sS][tT][sS]" ; +EXPLAIN : "[eE][xX][pP][lL][aA][iI][nN]" ; +EXPRESSION : "[eE][xX][pP][rR][eE][sS][sS][iI][oO][nN]" ; +EXTENSION : "[eE][xX][tT][eE][nN][sS][iI][oO][nN]" ; +EXTERNAL : "[eE][xX][tT][eE][rR][nN][aA][lL]" ; +EXTRACT : "[eE][xX][tT][rR][aA][cC][tT]" ; +FALSE_P : "[fF][aA][lL][sS][eE]" ; +FAMILY : "[fF][aA][mM][iI][lL][yY]" ; +FETCH : "[fF][eE][tT][cC][hH]" ; +FILTER : "[fF][iI][lL][tT][eE][rR]" ; +FINALIZE : "[fF][iI][nN][aA][lL][iI][zZ][eE]" ; +FIRST_P : "[fF][iI][rR][sS][tT]" ; +FLOAT_P : "[fF][lL][oO][aA][tT]" ; +FOLLOWING : "[fF][oO][lL][lL][oO][wW][iI][nN][gG]" ; +FOR : "[fF][oO][rR]" ; +FORCE : "[fF][oO][rR][cC][eE]" ; +FOREIGN : "[fF][oO][rR][eE][iI][gG][nN]" ; +FORMAT : "[fF][oO][rR][mM][aA][tT]" ; +FORWARD : "[fF][oO][rR][wW][aA][rR][dD]" ; +FREEZE : "[fF][rR][eE][eE][zZ][eE]" ; +FROM : "[fF][rR][oO][mM]" ; +FULL : "[fF][uU][lL][lL]" ; +FUNCTION : "[fF][uU][nN][cC][tT][iI][oO][nN]" ; +FUNCTIONS : "[fF][uU][nN][cC][tT][iI][oO][nN][sS]" ; +GENERATED : "[gG][eE][nN][eE][rR][aA][tT][eE][dD]" ; +GLOBAL : "[gG][lL][oO][bB][aA][lL]" ; +GRANT : "[gG][rR][aA][nN][tT]" ; +GRANTED : "[gG][rR][aA][nN][tT][eE][dD]" ; +GREATEST : "[gG][rR][eE][aA][tT][eE][sS][tT]" ; +GROUP_P : "[gG][rR][oO][uU][pP]" ; +GROUPING : "[gG][rR][oO][uU][pP][iI][nN][gG]" ; +GROUPS : "[gG][rR][oO][uU][pP][sS]" ; +HANDLER : "[hH][aA][nN][dD][lL][eE][rR]" ; +HAVING : "[hH][aA][vV][iI][nN][gG]" ; +HEADER_P : "[hH][eE][aA][dD][eE][rR]" ; +HOLD : "[hH][oO][lL][dD]" ; +HOUR_P : "[hH][oO][uU][rR]" ; +IDENTITY_P : "[iI][dD][eE][nN][tT][iI][tT][yY]" ; +IF_P : "[iI][fF]" ; +ILIKE : "[iI][lL][iI][kK][eE]" ; +IMMEDIATE : "[iI][mM][mM][eE][dD][iI][aA][tT][eE]" ; +IMMUTABLE : "[iI][mM][mM][uU][tT][aA][bB][lL][eE]" ; +IMPLICIT_P : "[iI][mM][pP][lL][iI][cC][iI][tT]" ; +IMPORT_P : "[iI][mM][pP][oO][rR][tT]" ; +IN_P : "[iI][nN]" ; +INCLUDE : "[iI][nN][cC][lL][uU][dD][eE]" ; +INCLUDING : "[iI][nN][cC][lL][uU][dD][iI][nN][gG]" ; +INCREMENT : "[iI][nN][cC][rR][eE][mM][eE][nN][tT]" ; +INDENT : "[iI][nN][dD][eE][nN][tT]" ; +INDEX : "[iI][nN][dD][eE][xX]" ; +INDEXES : "[iI][nN][dD][eE][xX][eE][sS]" ; +INHERIT : "[iI][nN][hH][eE][rR][iI][tT]" ; +INHERITS : "[iI][nN][hH][eE][rR][iI][tT][sS]" ; +INITIALLY : "[iI][nN][iI][tT][iI][aA][lL][lL][yY]" ; +INLINE_P : "[iI][nN][lL][iI][nN][eE]" ; +INNER_P : "[iI][nN][nN][eE][rR]" ; +INOUT : "[iI][nN][oO][uU][tT]" ; +INPUT_P : "[iI][nN][pP][uU][tT]" ; +INSENSITIVE : "[iI][nN][sS][eE][nN][sS][iI][tT][iI][vV][eE]" ; +INSERT : "[iI][nN][sS][eE][rR][tT]" ; +INSTEAD : "[iI][nN][sS][tT][eE][aA][dD]" ; +INT_P : "[iI][nN][tT]" ; +INTEGER : "[iI][nN][tT][eE][gG][eE][rR]" ; +INTERSECT : "[iI][nN][tT][eE][rR][sS][eE][cC][tT]" ; +INTERVAL : "[iI][nN][tT][eE][rR][vV][aA][lL]" ; +INTO : "[iI][nN][tT][oO]" ; +INVOKER : "[iI][nN][vV][oO][kK][eE][rR]" ; +IS : "[iI][sS]" ; +ISNULL : "[iI][sS][nN][uU][lL][lL]" ; +ISOLATION : "[iI][sS][oO][lL][aA][tT][iI][oO][nN]" ; +JOIN : "[jJ][oO][iI][nN]" ; +JSON : "[jJ][sS][oO][nN]" ; +JSON_ARRAY : "[jJ][sS][oO][nN][__][aA][rR][rR][aA][yY]" ; +JSON_ARRAYAGG : "[jJ][sS][oO][nN][__][aA][rR][rR][aA][yY][aA][gG][gG]" ; +JSON_OBJECT : "[jJ][sS][oO][nN][__][oO][bB][jJ][eE][cC][tT]" ; +JSON_OBJECTAGG : "[jJ][sS][oO][nN][__][oO][bB][jJ][eE][cC][tT][aA][gG][gG]" ; +KEY : "[kK][eE][yY]" ; +KEYS : "[kK][eE][yY][sS]" ; +LABEL : "[lL][aA][bB][eE][lL]" ; +LANGUAGE : "[lL][aA][nN][gG][uU][aA][gG][eE]" ; +LARGE_P : "[lL][aA][rR][gG][eE]" ; +LAST_P : "[lL][aA][sS][tT]" ; +LATERAL_P : "[lL][aA][tT][eE][rR][aA][lL]" ; +LEADING : "[lL][eE][aA][dD][iI][nN][gG]" ; +LEAKPROOF : "[lL][eE][aA][kK][pP][rR][oO][oO][fF]" ; +LEAST : "[lL][eE][aA][sS][tT]" ; +LEFT : "[lL][eE][fF][tT]" ; +LEVEL : "[lL][eE][vV][eE][lL]" ; +LIKE : "[lL][iI][kK][eE]" ; +LIMIT : "[lL][iI][mM][iI][tT]" ; +LISTEN : "[lL][iI][sS][tT][eE][nN]" ; +LOAD : "[lL][oO][aA][dD]" ; +LOCAL : "[lL][oO][cC][aA][lL]" ; +LOCALTIME : "[lL][oO][cC][aA][lL][tT][iI][mM][eE]" ; +LOCALTIMESTAMP : "[lL][oO][cC][aA][lL][tT][iI][mM][eE][sS][tT][aA][mM][pP]" ; +LOCATION : "[lL][oO][cC][aA][tT][iI][oO][nN]" ; +LOCK_P : "[lL][oO][cC][kK]" ; +LOCKED : "[lL][oO][cC][kK][eE][dD]" ; +LOGGED : "[lL][oO][gG][gG][eE][dD]" ; +MAPPING : "[mM][aA][pP][pP][iI][nN][gG]" ; +MATCH : "[mM][aA][tT][cC][hH]" ; +MATCHED : "[mM][aA][tT][cC][hH][eE][dD]" ; +MATERIALIZED : "[mM][aA][tT][eE][rR][iI][aA][lL][iI][zZ][eE][dD]" ; +MAXVALUE : "[mM][aA][xX][vV][aA][lL][uU][eE]" ; +MERGE : "[mM][eE][rR][gG][eE]" ; +METHOD : "[mM][eE][tT][hH][oO][dD]" ; +MINUTE_P : "[mM][iI][nN][uU][tT][eE]" ; +MINVALUE : "[mM][iI][nN][vV][aA][lL][uU][eE]" ; +MODE : "[mM][oO][dD][eE]" ; +MONTH_P : "[mM][oO][nN][tT][hH]" ; +MOVE : "[mM][oO][vV][eE]" ; +NAME_P : "[nN][aA][mM][eE]" ; +NAMES : "[nN][aA][mM][eE][sS]" ; +NATIONAL : "[nN][aA][tT][iI][oO][nN][aA][lL]" ; +NATURAL : "[nN][aA][tT][uU][rR][aA][lL]" ; +NCHAR : "[nN][cC][hH][aA][rR]" ; +NEW : "[nN][eE][wW]" ; +NEXT : "[nN][eE][xX][tT]" ; +NFC : "[nN][fF][cC]" ; +NFD : "[nN][fF][dD]" ; +NFKC : "[nN][fF][kK][cC]" ; +NFKD : "[nN][fF][kK][dD]" ; +NO : "[nN][oO]" ; +NONE : "[nN][oO][nN][eE]" ; +NORMALIZE : "[nN][oO][rR][mM][aA][lL][iI][zZ][eE]" ; +NORMALIZED : "[nN][oO][rR][mM][aA][lL][iI][zZ][eE][dD]" ; +NOT : "[nN][oO][tT]" ; +NOTHING : "[nN][oO][tT][hH][iI][nN][gG]" ; +NOTIFY : "[nN][oO][tT][iI][fF][yY]" ; +NOTNULL : "[nN][oO][tT][nN][uU][lL][lL]" ; +NOWAIT : "[nN][oO][wW][aA][iI][tT]" ; +NULL_P : "[nN][uU][lL][lL]" ; +NULLIF : "[nN][uU][lL][lL][iI][fF]" ; +NULLS_P : "[nN][uU][lL][lL][sS]" ; +NUMERIC : "[nN][uU][mM][eE][rR][iI][cC]" ; +OBJECT_P : "[oO][bB][jJ][eE][cC][tT]" ; +OF : "[oO][fF]" ; +OFF : "[oO][fF][fF]" ; +OFFSET : "[oO][fF][fF][sS][eE][tT]" ; +OIDS : "[oO][iI][dD][sS]" ; +OLD : "[oO][lL][dD]" ; +ON : "[oO][nN]" ; +ONLY : "[oO][nN][lL][yY]" ; +OPERATOR : "[oO][pP][eE][rR][aA][tT][oO][rR]" ; +OPTION : "[oO][pP][tT][iI][oO][nN]" ; +OPTIONS : "[oO][pP][tT][iI][oO][nN][sS]" ; +OR : "[oO][rR]" ; +ORDER : "[oO][rR][dD][eE][rR]" ; +ORDINALITY : "[oO][rR][dD][iI][nN][aA][lL][iI][tT][yY]" ; +OTHERS : "[oO][tT][hH][eE][rR][sS]" ; +OUT_P : "[oO][uU][tT]" ; +OUTER_P : "[oO][uU][tT][eE][rR]" ; +OVER : "[oO][vV][eE][rR]" ; +OVERLAPS : "[oO][vV][eE][rR][lL][aA][pP][sS]" ; +OVERLAY : "[oO][vV][eE][rR][lL][aA][yY]" ; +OVERRIDING : "[oO][vV][eE][rR][rR][iI][dD][iI][nN][gG]" ; +OWNED : "[oO][wW][nN][eE][dD]" ; +OWNER : "[oO][wW][nN][eE][rR]" ; +PARALLEL : "[pP][aA][rR][aA][lL][lL][eE][lL]" ; +PARAMETER : "[pP][aA][rR][aA][mM][eE][tT][eE][rR]" ; +PARSER : "[pP][aA][rR][sS][eE][rR]" ; +PARTIAL : "[pP][aA][rR][tT][iI][aA][lL]" ; +PARTITION : "[pP][aA][rR][tT][iI][tT][iI][oO][nN]" ; +PASSING : "[pP][aA][sS][sS][iI][nN][gG]" ; +PASSWORD : "[pP][aA][sS][sS][wW][oO][rR][dD]" ; +PLACING : "[pP][lL][aA][cC][iI][nN][gG]" ; +PLANS : "[pP][lL][aA][nN][sS]" ; +POLICY : "[pP][oO][lL][iI][cC][yY]" ; +POSITION : "[pP][oO][sS][iI][tT][iI][oO][nN]" ; +PRECEDING : "[pP][rR][eE][cC][eE][dD][iI][nN][gG]" ; +PRECISION : "[pP][rR][eE][cC][iI][sS][iI][oO][nN]" ; +PREPARE : "[pP][rR][eE][pP][aA][rR][eE]" ; +PREPARED : "[pP][rR][eE][pP][aA][rR][eE][dD]" ; +PRESERVE : "[pP][rR][eE][sS][eE][rR][vV][eE]" ; +PRIMARY : "[pP][rR][iI][mM][aA][rR][yY]" ; +PRIOR : "[pP][rR][iI][oO][rR]" ; +PRIVILEGES : "[pP][rR][iI][vV][iI][lL][eE][gG][eE][sS]" ; +PROCEDURAL : "[pP][rR][oO][cC][eE][dD][uU][rR][aA][lL]" ; +PROCEDURE : "[pP][rR][oO][cC][eE][dD][uU][rR][eE]" ; +PROCEDURES : "[pP][rR][oO][cC][eE][dD][uU][rR][eE][sS]" ; +PROGRAM : "[pP][rR][oO][gG][rR][aA][mM]" ; +PUBLICATION : "[pP][uU][bB][lL][iI][cC][aA][tT][iI][oO][nN]" ; +QUOTE : "[qQ][uU][oO][tT][eE]" ; +RANGE : "[rR][aA][nN][gG][eE]" ; +READ : "[rR][eE][aA][dD]" ; +REAL : "[rR][eE][aA][lL]" ; +REASSIGN : "[rR][eE][aA][sS][sS][iI][gG][nN]" ; +RECHECK : "[rR][eE][cC][hH][eE][cC][kK]" ; +RECURSIVE : "[rR][eE][cC][uU][rR][sS][iI][vV][eE]" ; +REF_P : "[rR][eE][fF]" ; +REFERENCES : "[rR][eE][fF][eE][rR][eE][nN][cC][eE][sS]" ; +REFERENCING : "[rR][eE][fF][eE][rR][eE][nN][cC][iI][nN][gG]" ; +REFRESH : "[rR][eE][fF][rR][eE][sS][hH]" ; +REINDEX : "[rR][eE][iI][nN][dD][eE][xX]" ; +RELATIVE_P : "[rR][eE][lL][aA][tT][iI][vV][eE]" ; +RELEASE : "[rR][eE][lL][eE][aA][sS][eE]" ; +RENAME : "[rR][eE][nN][aA][mM][eE]" ; +REPEATABLE : "[rR][eE][pP][eE][aA][tT][aA][bB][lL][eE]" ; +REPLACE : "[rR][eE][pP][lL][aA][cC][eE]" ; +REPLICA : "[rR][eE][pP][lL][iI][cC][aA]" ; +RESET : "[rR][eE][sS][eE][tT]" ; +RESTART : "[rR][eE][sS][tT][aA][rR][tT]" ; +RESTRICT : "[rR][eE][sS][tT][rR][iI][cC][tT]" ; +RETURN : "[rR][eE][tT][uU][rR][nN]" ; +RETURNING : "[rR][eE][tT][uU][rR][nN][iI][nN][gG]" ; +RETURNS : "[rR][eE][tT][uU][rR][nN][sS]" ; +REVOKE : "[rR][eE][vV][oO][kK][eE]" ; +RIGHT : "[rR][iI][gG][hH][tT]" ; +ROLE : "[rR][oO][lL][eE]" ; +ROLLBACK : "[rR][oO][lL][lL][bB][aA][cC][kK]" ; +ROLLUP : "[rR][oO][lL][lL][uU][pP]" ; +ROUTINE : "[rR][oO][uU][tT][iI][nN][eE]" ; +ROUTINES : "[rR][oO][uU][tT][iI][nN][eE][sS]" ; +ROW : "[rR][oO][wW]" ; +ROWS : "[rR][oO][wW][sS]" ; +RULE : "[rR][uU][lL][eE]" ; +SAVEPOINT : "[sS][aA][vV][eE][pP][oO][iI][nN][tT]" ; +SCALAR : "[sS][cC][aA][lL][aA][rR]" ; +SCHEMA : "[sS][cC][hH][eE][mM][aA]" ; +SCHEMAS : "[sS][cC][hH][eE][mM][aA][sS]" ; +SCROLL : "[sS][cC][rR][oO][lL][lL]" ; +SEARCH : "[sS][eE][aA][rR][cC][hH]" ; +SECOND_P : "[sS][eE][cC][oO][nN][dD]" ; +SECURITY : "[sS][eE][cC][uU][rR][iI][tT][yY]" ; +SELECT : "[sS][eE][lL][eE][cC][tT]" ; +SEQUENCE : "[sS][eE][qQ][uU][eE][nN][cC][eE]" ; +SEQUENCES : "[sS][eE][qQ][uU][eE][nN][cC][eE][sS]" ; +SERIALIZABLE : "[sS][eE][rR][iI][aA][lL][iI][zZ][aA][bB][lL][eE]" ; +SERVER : "[sS][eE][rR][vV][eE][rR]" ; +SESSION : "[sS][eE][sS][sS][iI][oO][nN]" ; +SESSION_USER : "[sS][eE][sS][sS][iI][oO][nN][__][uU][sS][eE][rR]" ; +SET : "[sS][eE][tT]" ; +SETOF : "[sS][eE][tT][oO][fF]" ; +SETS : "[sS][eE][tT][sS]" ; +SHARE : "[sS][hH][aA][rR][eE]" ; +SHOW : "[sS][hH][oO][wW]" ; +SIMILAR : "[sS][iI][mM][iI][lL][aA][rR]" ; +SIMPLE : "[sS][iI][mM][pP][lL][eE]" ; +SKIP : "[sS][kK][iI][pP]" ; +SMALLINT : "[sS][mM][aA][lL][lL][iI][nN][tT]" ; +SNAPSHOT : "[sS][nN][aA][pP][sS][hH][oO][tT]" ; +SOME : "[sS][oO][mM][eE]" ; +SQL_P : "[sS][qQ][lL]" ; +STABLE : "[sS][tT][aA][bB][lL][eE]" ; +STANDALONE_P : "[sS][tT][aA][nN][dD][aA][lL][oO][nN][eE]" ; +START : "[sS][tT][aA][rR][tT]" ; +STATEMENT : "[sS][tT][aA][tT][eE][mM][eE][nN][tT]" ; +STATISTICS : "[sS][tT][aA][tT][iI][sS][tT][iI][cC][sS]" ; +STDIN : "[sS][tT][dD][iI][nN]" ; +STDOUT : "[sS][tT][dD][oO][uU][tT]" ; +STORAGE : "[sS][tT][oO][rR][aA][gG][eE]" ; +STORED : "[sS][tT][oO][rR][eE][dD]" ; +STRICT_P : "[sS][tT][rR][iI][cC][tT]" ; +STRIP_P : "[sS][tT][rR][iI][pP]" ; +SUBSCRIPTION : "[sS][uU][bB][sS][cC][rR][iI][pP][tT][iI][oO][nN]" ; +SUBSTRING : "[sS][uU][bB][sS][tT][rR][iI][nN][gG]" ; +SUPPORT : "[sS][uU][pP][pP][oO][rR][tT]" ; +SYMMETRIC : "[sS][yY][mM][mM][eE][tT][rR][iI][cC]" ; +SYSID : "[sS][yY][sS][iI][dD]" ; +SYSTEM_P : "[sS][yY][sS][tT][eE][mM]" ; +SYSTEM_USER : "[sS][yY][sS][tT][eE][mM][__][uU][sS][eE][rR]" ; +TABLE : "[tT][aA][bB][lL][eE]" ; +TABLES : "[tT][aA][bB][lL][eE][sS]" ; +TABLESAMPLE : "[tT][aA][bB][lL][eE][sS][aA][mM][pP][lL][eE]" ; +TABLESPACE : "[tT][aA][bB][lL][eE][sS][pP][aA][cC][eE]" ; +TEMP : "[tT][eE][mM][pP]" ; +TEMPLATE : "[tT][eE][mM][pP][lL][aA][tT][eE]" ; +TEMPORARY : "[tT][eE][mM][pP][oO][rR][aA][rR][yY]" ; +TEXT_P : "[tT][eE][xX][tT]" ; +THEN : "[tT][hH][eE][nN]" ; +TIES : "[tT][iI][eE][sS]" ; +TIME : "[tT][iI][mM][eE]" ; +TIMESTAMP : "[tT][iI][mM][eE][sS][tT][aA][mM][pP]" ; +TO : "[tT][oO]" ; +TRAILING : "[tT][rR][aA][iI][lL][iI][nN][gG]" ; +TRANSACTION : "[tT][rR][aA][nN][sS][aA][cC][tT][iI][oO][nN]" ; +TRANSFORM : "[tT][rR][aA][nN][sS][fF][oO][rR][mM]" ; +TREAT : "[tT][rR][eE][aA][tT]" ; +TRIGGER : "[tT][rR][iI][gG][gG][eE][rR]" ; +TRIM : "[tT][rR][iI][mM]" ; +TRUE_P : "[tT][rR][uU][eE]" ; +TRUNCATE : "[tT][rR][uU][nN][cC][aA][tT][eE]" ; +TRUSTED : "[tT][rR][uU][sS][tT][eE][dD]" ; +TYPE_P : "[tT][yY][pP][eE]" ; +TYPES_P : "[tT][yY][pP][eE][sS]" ; +UESCAPE : "[uU][eE][sS][cC][aA][pP][eE]" ; +UNBOUNDED : "[uU][nN][bB][oO][uU][nN][dD][eE][dD]" ; +UNCOMMITTED : "[uU][nN][cC][oO][mM][mM][iI][tT][tT][eE][dD]" ; +UNENCRYPTED : "[uU][nN][eE][nN][cC][rR][yY][pP][tT][eE][dD]" ; +UNION : "[uU][nN][iI][oO][nN]" ; +UNIQUE : "[uU][nN][iI][qQ][uU][eE]" ; +UNKNOWN : "[uU][nN][kK][nN][oO][wW][nN]" ; +UNLISTEN : "[uU][nN][lL][iI][sS][tT][eE][nN]" ; +UNLOGGED : "[uU][nN][lL][oO][gG][gG][eE][dD]" ; +UNTIL : "[uU][nN][tT][iI][lL]" ; +UPDATE : "[uU][pP][dD][aA][tT][eE]" ; +USER : "[uU][sS][eE][rR]" ; +USING : "[uU][sS][iI][nN][gG]" ; +VACUUM : "[vV][aA][cC][uU][uU][mM]" ; +VALID : "[vV][aA][lL][iI][dD]" ; +VALIDATE : "[vV][aA][lL][iI][dD][aA][tT][eE]" ; +VALIDATOR : "[vV][aA][lL][iI][dD][aA][tT][oO][rR]" ; +VALUE_P : "[vV][aA][lL][uU][eE]" ; +VALUES : "[vV][aA][lL][uU][eE][sS]" ; +VARCHAR : "[vV][aA][rR][cC][hH][aA][rR]" ; +VARIADIC : "[vV][aA][rR][iI][aA][dD][iI][cC]" ; +VARYING : "[vV][aA][rR][yY][iI][nN][gG]" ; +VERBOSE : "[vV][eE][rR][bB][oO][sS][eE]" ; +VERSION_P : "[vV][eE][rR][sS][iI][oO][nN]" ; +VIEW : "[vV][iI][eE][wW]" ; +VIEWS : "[vV][iI][eE][wW][sS]" ; +VOLATILE : "[vV][oO][lL][aA][tT][iI][lL][eE]" ; +WHEN : "[wW][hH][eE][nN]" ; +WHERE : "[wW][hH][eE][rR][eE]" ; +WHITESPACE_P : "[wW][hH][iI][tT][eE][sS][pP][aA][cC][eE]" ; +WINDOW : "[wW][iI][nN][dD][oO][wW]" ; +WITH : "[wW][iI][tT][hH]" ; +WITHIN : "[wW][iI][tT][hH][iI][nN]" ; +WITHOUT : "[wW][iI][tT][hH][oO][uU][tT]" ; +WORK : "[wW][oO][rR][kK]" ; +WRAPPER : "[wW][rR][aA][pP][pP][eE][rR]" ; +WRITE : "[wW][rR][iI][tT][eE]" ; +XML_P : "[xX][mM][lL]" ; +XMLATTRIBUTES : "[xX][mM][lL][aA][tT][tT][rR][iI][bB][uU][tT][eE][sS]" ; +XMLCONCAT : "[xX][mM][lL][cC][oO][nN][cC][aA][tT]" ; +XMLELEMENT : "[xX][mM][lL][eE][lL][eE][mM][eE][nN][tT]" ; +XMLEXISTS : "[xX][mM][lL][eE][xX][iI][sS][tT][sS]" ; +XMLFOREST : "[xX][mM][lL][fF][oO][rR][eE][sS][tT]" ; +XMLNAMESPACES : "[xX][mM][lL][nN][aA][mM][eE][sS][pP][aA][cC][eE][sS]" ; +XMLPARSE : "[xX][mM][lL][pP][aA][rR][sS][eE]" ; +XMLPI : "[xX][mM][lL][pP][iI]" ; +XMLROOT : "[xX][mM][lL][rR][oO][oO][tT]" ; +XMLSERIALIZE : "[xX][mM][lL][sS][eE][rR][iI][aA][lL][iI][zZ][eE]" ; +XMLTABLE : "[xX][mM][lL][tT][aA][bB][lL][eE]" ; +YEAR_P : "[yY][eE][aA][rR]" ; +YES_P : "[yY][eE][sS]" ; +ZONE : "[zZ][oO][nN][eE]" ; + + +LESS_EQUALS : '<=' ; +GREATER_EQUALS : '>=' ; +NOT_EQUALS : "!=|<>" ; +COLON_EQUALS : ':=' ; +EQUALS_GREATER : ' =>' ; +TYPECAST : '::' ; +//DOT_DOT : '..' ; + +IDENT : "[A-Za-z\200-\377_][A-Za-z\200-\377_0-9\$]*" ; +FCONST : "(([0-9]*\.[0-9]+)|([0-9]+\.[0-9]*))" ; +SCONST : "\"(\\[\"\\]|[^\"\n])*\"|'(\\['\\]|[^'\n])*'|\$\$[^\$]+\$\$" ; +BCONST : 'BCONST' ; +XCONST : 'XCONST' ; +ICONST : "[0-9]+" ; +PARAM : "\$[0-9]+"; + +MODE_TYPE_NAME : 'MODE_TYPE_NAME' ; +MODE_PLPGSQL_EXPR : 'MODE_PLPGSQL_EXPR' ; +MODE_PLPGSQL_ASSIGN1 : 'MODE_PLPGSQL_ASSIGN1' ; +MODE_PLPGSQL_ASSIGN2 : 'MODE_PLPGSQL_ASSIGN2' ; +MODE_PLPGSQL_ASSIGN3 : 'MODE_PLPGSQL_ASSIGN3' ; + +FORMAT_LA : 'FROMAT_LA' ; +WITH_LA : 'WITH_LA' ; +WITHOUT_LA : 'WITHOUT_LA' ; +NULLS_LA : 'NULLS_LA'; +NOT_LA : 'NOT_LA' ; +Op : 'Op' ; + +} \ No newline at end of file diff --git a/playground/prelude.carbon b/playground/prelude.carbon new file mode 100644 index 0000000..bc0bbab --- /dev/null +++ b/playground/prelude.carbon @@ -0,0 +1,736 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +package Carbon api; + +// ---------------------- +// Conversion interfaces. +// ---------------------- + +// Explicitly convert `Self` to `T`. +interface As(T:! type) { + fn Convert[self: Self]() -> T; +} + +// Implicitly convert `Self` to `T`. +interface ImplicitAs(T:! type) { + extends As(T); +} + +// TODO: This should be private. +interface __EqualConverter { + let T:! type; + fn Convert(t: T) -> Self; +} +fn __EqualConvert[T:! type](t: T, U:! __EqualConverter where .T = T) -> U { + return U.Convert(t); +} +impl forall [U:! type] U as __EqualConverter where .T = U { + fn Convert(u: U) -> U { return u; } +} + +__match_first { + // Pick up implicit conversions that are built into the compiler. + // TODO: Split these into individual categories and implement as many as we can + // in the prelude. + impl forall [U:! type, template T:! __intrinsic_implicit_as(U)] T as ImplicitAs(U) { + fn Convert[self: Self]() -> U { return __intrinsic_implicit_as_convert(self, U); } + } + + // Every type implicitly converts to single-step-equal types. + impl forall [T:! type, U:! type where .Self == T] T as ImplicitAs(U) { + fn Convert[self: Self]() -> U { return __EqualConvert(self, U); } + } + + // A tuple implicitly converts to another tuple if all its elements do. + // TODO: Simplify this once we have variadics. + // TODO: Should these be final? + impl forall [U1:! type, T1:! ImplicitAs(U1)] + (T1,) as ImplicitAs((U1,)) { + fn Convert[self: Self]() -> (U1,) { + let (v1: T1,) = self; + return (v1.Convert(),); + } + } + impl forall [U1:! type, U2:! type, T1:! ImplicitAs(U1), T2:! ImplicitAs(U2)] + (T1, T2) as ImplicitAs((U1, U2)) { + fn Convert[self: Self]() -> (U1, U2) { + let (v1: T1, v2: T2) = self; + return (v1.Convert(), v2.Convert()); + } + } + impl forall [U1:! type, U2:! type, U3:! type, + T1:! ImplicitAs(U1), T2:! ImplicitAs(U2), T3:! ImplicitAs(U3)] + (T1, T2, T3) as ImplicitAs((U1, U2, U3)) { + fn Convert[self: Self]() -> (U1, U2, U3) { + let (v1: T1, v2: T2, v3: T3) = self; + return (v1.Convert(), v2.Convert(), v3.Convert()); + } + } + + // A tuple explicitly converts to another tuple if all its elements do. Note + // that this fully overlaps with the previous set of impls for the case where + // an implicit conversion is possible. + impl forall [U1:! type, T1:! As(U1)] + (T1,) as As((U1,)) { + fn Convert[self: Self]() -> (U1,) { + let (v1: T1,) = self; + return (v1.Convert(),); + } + } + impl forall [U1:! type, U2:! type, T1:! As(U1), T2:! As(U2)] + (T1, T2) as As((U1, U2)) { + fn Convert[self: Self]() -> (U1, U2) { + let (v1: T1, v2: T2) = self; + return (v1.Convert(), v2.Convert()); + } + } + impl forall [U1:! type, U2:! type, U3:! type, + T1:! As(U1), T2:! As(U2), T3:! As(U3)] + (T1, T2, T3) as As((U1, U2, U3)) { + fn Convert[self: Self]() -> (U1, U2, U3) { + let (v1: T1, v2: T2, v3: T3) = self; + return (v1.Convert(), v2.Convert(), v3.Convert()); + } + } +} + +// ---------------------- +// Comparison interfaces. +// ---------------------- + +// ---------------------- +// EQUAL +// ---------------------- + +interface EqWith(U:! type) { + fn Equal[self: Self](other: U) -> bool; + fn NotEqual[self: Self](other: U) -> bool; +} + +constraint Eq { + extends EqWith(Self); +} + +// TODO: Simplify this once we have variadics +impl forall [T2:! type, U2:! type, T1:! EqWith(T2), U1:! EqWith(U2)] + (T1, U1) as EqWith((T2, U2)) { + fn Equal[self: Self](other: (T2, U2)) -> bool { + let (l1: T1, l2: U1) = self; + let (r1: T2, r2: U2) = other; + return l1 == r1 and l2 == r2; + } + fn NotEqual[self: Self](other: (T2, U2)) -> bool { + let (l1: T1, l2: U1) = self; + let (r1: T2, r2: U2) = other; + return l1 != r1 or l2 != r2; + } +} + +impl bool as EqWith(Self) { + fn Equal[self: Self](other: Self) -> bool { + return if self then other else not other; + } + fn NotEqual[self: Self](other: Self) -> bool { + return if self then not other else other; + } +} + +impl i32 as EqWith(Self) { + fn Equal[self: Self](other: Self) -> bool { + return __intrinsic_int_eq(self, other); + } + + fn NotEqual[self: Self](other: Self) -> bool { + return not __intrinsic_int_eq(self, other); + } +} + +impl String as EqWith(Self) { + fn Equal[self: Self](other: Self) -> bool { + return __intrinsic_str_eq(self, other); + } + + fn NotEqual[self: Self](other: Self) -> bool { + return not __intrinsic_str_eq(self, other); + } +} + +// ---------------------- +// COMPARE +// ---------------------- + +choice Ordering { + Less, + Equivalent, + Greater, + Incomparable +} + +// TODO: Per the design, this should be named `OrderedWith`. +interface CompareWith(U:! type) { + fn Compare[self: Self](u: U) -> Ordering; + // TODO: Add `default fn` for Less, LessOrEquivalent, Greater, and GreaterOrEquivalent once it's available. +} +constraint Ordered { + extends CompareWith(Self); +} + +impl i32 as CompareWith(Self) { + fn Compare[self: Self](other: Self) -> Ordering { + var comp: i32 = __intrinsic_int_compare(self, other); + if (comp == -1) { + return Ordering.Less; + } + if (comp == 0) { + return Ordering.Equivalent; + } + if (comp == 1) { + return Ordering.Greater; + } + return Ordering.Incomparable; + + } +} + +impl String as CompareWith(Self) { + fn Compare[self: Self](other: Self) -> Ordering { + var comp: i32 = __intrinsic_str_compare(self, other); + if (comp == -1) { + return Ordering.Less; + } + if (comp == 0) { + return Ordering.Equivalent; + } + if (comp == 1) { + return Ordering.Greater; + } + return Ordering.Incomparable; + } +} + +interface LessWith(U:! type) { + fn Less[self: Self](other: U) -> bool; +} + +interface LessEqWith(U:! type) { + fn LessEq[self: Self](other: U) -> bool; +} + +interface GreaterWith(U:! type) { + fn Greater[self: Self](other: U) -> bool; +} + +interface GreaterEqWith(U:! type) { + fn GreaterEq[self: Self](other: U) -> bool; +} + +impl i32 as LessWith(Self) { + fn Less[self: Self](other: Self) -> bool { + var comp: Ordering = self.(CompareWith(i32).Compare)(other); + match (comp) { + case Ordering.Less => { + return true; + } + } + return false; + } +} + +impl String as LessWith(Self) { + fn Less[self: Self](other: Self) -> bool { + var comp: Ordering = self.(CompareWith(String).Compare)(other); + match(comp){ + case Ordering.Less => { + return true; + } + } + return false; + } +} + +impl i32 as LessEqWith(Self) { + fn LessEq[self: Self](other: Self) -> bool { + var comp: Ordering = self.(CompareWith(i32).Compare)(other); + match(comp){ + case Ordering.Less => { + return true; + } + case Ordering.Equivalent => { + return true; + } + } + return false; + } +} + +impl String as LessEqWith(Self) { + fn LessEq[self: Self](other: Self) -> bool { + var comp: Ordering = self.(CompareWith(String).Compare)(other); + match(comp){ + case Ordering.Less => { + return true; + } + case Ordering.Equivalent => { + return true; + } + } + return false; + } +} + +impl i32 as GreaterWith(Self) { + fn Greater[self: Self](other: Self) -> bool { + var comp: Ordering = self.(CompareWith(i32).Compare)(other); + match(comp){ + case Ordering.Greater => { + return true; + } + } + return false; + } +} + +impl String as GreaterWith(Self) { + fn Greater[self: Self](other: Self) -> bool { + var comp: Ordering = self.(CompareWith(String).Compare)(other); + match(comp){ + case Ordering.Greater => { + return true; + } + } + return false; + } +} + +impl i32 as GreaterEqWith(Self) { + fn GreaterEq[self: Self](other: Self) -> bool { + var comp: Ordering = self.(CompareWith(i32).Compare)(other); + match(comp){ + case Ordering.Greater => { + return true; + } + case Ordering.Equivalent => { + return true; + } + } + return false; + } +} + +impl String as GreaterEqWith(Self) { + fn GreaterEq[self: Self](other: Self) -> bool { + var comp: Ordering = self.(CompareWith(String).Compare)(other); + match(comp){ + case Ordering.Greater => { + return true; + } + case Ordering.Equivalent => { + return true; + } + } + return false; + } +} + +// ---------------------- +// Arithmetic interfaces. +// ---------------------- + +interface Negate { + // TODO: = Self + let Result:! type; + fn Op[self: Self]() -> Result; +} + +interface AddWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint Add { + extends AddWith(Self) where .Result = Self; +} + +interface SubWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint Sub { + extends SubWith(Self) where .Result = Self; +} + +interface MulWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint Mul { + extends MulWith(Self) where .Result = Self; +} + +interface DivWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint Div { + extends DivWith(Self) where .Result = Self; +} + +interface ModWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint Mod { + extends ModWith(Self) where .Result = Self; +} + +// Note, these impls use the builtin addition for i32. +external impl i32 as Negate where .Result = i32 { + fn Op[self: i32]() -> i32 { return -self; } +} +external impl i32 as AddWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { return self + other; } +} +external impl i32 as SubWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { return self - other; } +} +external impl i32 as MulWith(i32) where .Result = i32 { + //fn Op[self: i32](other: i32) -> i32 { return self * other; } +} +external impl i32 as DivWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { return self / other; } +} +external impl i32 as ModWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { return self % other; } +} + +// --------------------------------- +// Bitwise and bit-shift interfaces. +// --------------------------------- + +// Unary `^`. +interface BitComplement { + // TODO: = Self + let Result:! type; + fn Op[self: Self]() -> Result; +} + +// Binary `&`. +interface BitAndWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint BitAnd { + extends BitAndWith(Self) where .Result = Self; +} + +// Binary `|`. +interface BitOrWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint BitOr { + extends BitOrWith(Self) where .Result = Self; +} + +// Binary `^`. +interface BitXorWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint BitXor { + extends BitXorWith(Self) where .Result = Self; +} + +// Binary `<<`. +interface LeftShiftWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint LeftShift { + extends LeftShiftWith(Self) where .Result = Self; +} + +// Binary `>>`. +interface RightShiftWith(U:! type) { + // TODO: = Self + let Result:! type; + fn Op[self: Self](other: U) -> Result; +} +constraint RightShift { + extends RightShiftWith(Self) where .Result = Self; +} + +external impl i32 as BitComplement where .Result = i32 { + fn Op[self: i32]() -> i32 { + return __intrinsic_int_bit_complement(self); + } +} +external impl i32 as BitAndWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { + return __intrinsic_int_bit_and(self, other); + } +} +external impl i32 as BitOrWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { + return __intrinsic_int_bit_or(self, other); + } +} +external impl i32 as BitXorWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { + return __intrinsic_int_bit_xor(self, other); + } +} +external impl i32 as LeftShiftWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { + return __intrinsic_int_left_shift(self, other); + } +} +external impl i32 as RightShiftWith(i32) where .Result = i32 { + fn Op[self: i32](other: i32) -> i32 { + return __intrinsic_int_right_shift(self, other); + } +} + +// ----------------------------------- +// Assignment and compound assignment. +// ----------------------------------- + +interface AssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint Assign { extends AssignWith(Self); } + +interface AddAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint AddAssign { extends AddAssignWith(Self); } + +interface SubAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint SubAssign { extends SubAssignWith(Self); } + +interface MulAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint MulAssign { extends MulAssignWith(Self); } + +interface DivAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint DivAssign { extends DivAssignWith(Self); } + +interface ModAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint ModAssign { extends ModAssignWith(Self); } + +interface BitAndAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint BitAssignAnd { extends BitAndAssignWith(Self); } + +interface BitOrAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint BitAssignOr { extends BitOrAssignWith(Self); } + +interface BitXorAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint BitAssignXor { extends BitXorAssignWith(Self); } + +interface LeftShiftAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint LeftShiftAssign { extends LeftShiftAssignWith(Self); } + +interface RightShiftAssignWith(U:! type) { + fn Op[addr self: Self*](other: U); +} +constraint RightShiftAssign { extends RightShiftAssignWith(Self); } + +// TODO: This is temporary, and should eventually be replaced by +// something more fine-grained. Not all class types should be +// assignable. +impl forall [T:! type, U:! ImplicitAs(T)] + T as AssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = other.Convert(); + } +} + +// TODO: Should `AddWith(U) & AssignWith(.Self.(AddWith(U).Result))` work? +impl forall [U:! type, T:! AddWith(U) where .Self is AssignWith(.Self.Result)] + T as AddAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self + other; + } +} + +impl forall [U:! type, T:! SubWith(U) where .Self is AssignWith(.Self.Result)] + T as SubAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self - other; + } +} + +impl forall [U:! type, T:! MulWith(U) where .Self is AssignWith(.Self.Result)] + T as MulAssignWith(U) { + fn Op[addr self: Self*](other: U) { + //*self = *self * other; + } +} + +impl forall [U:! type, T:! DivWith(U) where .Self is AssignWith(.Self.Result)] + T as DivAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self / other; + } +} + +impl forall [U:! type, T:! ModWith(U) where .Self is AssignWith(.Self.Result)] + T as ModAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self % other; + } +} + +impl forall [U:! type, T:! BitAndWith(U) where .Self is AssignWith(.Self.Result)] + T as BitAndAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self & other; + } +} + +impl forall [U:! type, T:! BitOrWith(U) where .Self is AssignWith(.Self.Result)] + T as BitOrAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self | other; + } +} + +impl forall [U:! type, T:! BitXorWith(U) where .Self is AssignWith(.Self.Result)] + T as BitXorAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self ^ other; + } +} + +impl forall [U:! type, T:! LeftShiftWith(U) where .Self is AssignWith(.Self.Result)] + T as LeftShiftAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self << other; + } +} + +impl forall [U:! type, T:! RightShiftWith(U) where .Self is AssignWith(.Self.Result)] + T as RightShiftAssignWith(U) { + fn Op[addr self: Self*](other: U) { + *self = *self >> other; + } +} + +// ------------------------ +// Increment and decrement. +// ------------------------ + +interface Inc { + fn Op[addr self: Self*](); +} +interface Dec { + fn Op[addr self: Self*](); +} + +impl i32 as Inc { + fn Op[addr self: Self*]() { + *self = *self + 1; + } +} +impl i32 as Dec { + fn Op[addr self: Self*]() { + *self = *self - 1; + } +} + +// ------------------------ +// Miscellaneous utilities. +// ------------------------ + +// Note that Print is experimental, and not part of an accepted proposal, but +// is included here for printing state in tests. +// TODO: Remove Print special casing once we have variadics or overloads. +// fn Print(format_str: String) { +// __intrinsic_print(format_str); +// } + +fn Assert(condition: bool, message: String){ + __intrinsic_assert(condition, message); +} + +fn Rand(low: i32, high: i32) -> i32{ + return __intrinsic_rand(low,high); +} + +//------------------------- +// Optional. +//------------------------- +choice OptionalElement(T:! type) { + None, + Element(T) +} + +class Optional(T:! type) { + fn CreateEmpty() -> Optional(T) { + return {.element = OptionalElement(T).None}; + } + fn Create(value: T) -> Optional(T) { + return {.element = OptionalElement(T).Element(value)}; + } + + fn HasValue[self: Self]() -> bool { + match(self.element) { + case OptionalElement(T).None => { return false; } + } + return true; + } + + fn Get[self: Self]() -> T { + match(self.element) { + case OptionalElement(T).Element(x: T) => { + return x; + } + } + Assert(false, "Attempted to unwrap empty Optional"); + // TODO: Drop uninitialized variable & return when we can flag unreachable paths. + var y: T; + return y; + } + + var element: OptionalElement(T); +} + +//------------------------- +// Heap. +//------------------------- + +class Heap { + fn New[T:! type, self: Self](x : T) -> T* { + return __intrinsic_new(x); + } + fn Delete[T:! type, self: Self](p : T*) { + __intrinsic_delete(p); + } +} + +var heap: Heap = {}; diff --git a/playground/rust.g b/playground/rust.g new file mode 100644 index 0000000..e463c3c --- /dev/null +++ b/playground/rust.g @@ -0,0 +1,1858 @@ +//From: https://github.com/bleibig/rust-grammar.git + +rust { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +//%token YYEOF +//%token YYerror +//%token YYUNDEF +//%token SHL +//%token SHR +//%token LE +//%token EQEQ +//%token NE +//%token GE +//%token ANDAND +//%token OROR +//%token SHLEQ +//%token SHREQ +//%token MINUSEQ +//%token ANDEQ +//%token OREQ +//%token PLUSEQ +//%token STAREQ +//%token SLASHEQ +//%token CARETEQ +//%token PERCENTEQ +//%token DOTDOT +//%token DOTDOTDOT +//%token MOD_SEP +//%token RARROW +//%token LARROW +//%token FAT_ARROW +//%token LIT_BYTE +//%token LIT_CHAR +//%token LIT_INTEGER +//%token LIT_FLOAT +//%token LIT_STR +//%token LIT_STR_RAW +//%token LIT_BYTE_STR +//%token LIT_BYTE_STR_RAW +//%token IDENT +//%token UNDERSCORE +//%token LIFETIME +//%token SELF +//%token STATIC +//%token ABSTRACT +//%token ALIGNOF +//%token AS +//%token BECOME +//%token BREAK +//%token CATCH +//%token CRATE +//%token DO +//%token ELSE +//%token ENUM +//%token EXTERN +//%token FALSE +//%token FINAL +//%token FN +//%token FOR +//%token IF +//%token IMPL +//%token IN +//%token LET +//%token LOOP +//%token MACRO +//%token MATCH +//%token MOD +//%token MOVE +//%token MUT +//%token OFFSETOF +//%token OVERRIDE +//%token PRIV +//%token PUB +//%token PURE +//%token REF +//%token RETURN +//%token SIZEOF +//%token STRUCT +//%token SUPER +//%token UNION +//%token UNSIZED +//%token TRUE +//%token TRAIT +//%token TYPE +//%token UNSAFE +//%token VIRTUAL +//%token YIELD +//%token DEFAULT +//%token USE +//%token WHILE +//%token CONTINUE +//%token PROC +//%token BOX +//%token CONST +//%token WHERE +//%token TYPEOF +//%token INNER_DOC_COMMENT +//%token OUTER_DOC_COMMENT +//%token SHEBANG +//%token SHEBANG_LINE +//%token STATIC_LIFETIME +//%token PRECLOW +//%token LAMBDA +//%token SHIFTPLUS +//%token ':' +//%token FORTYPE +//%token '?' +//%token '=' +//%token '<' +//%token '>' +//%token '|' +//%token '^' +//%token '&' +//%token '+' +//%token '-' +//%token '*' +//%token '/' +//%token '%' +//%token '!' +//%token '{' +//%token '[' +//%token '(' +//%token '.' +//%token RANGE +//%token ']' +//%token '#' +//%token ')' +//%token ',' +//%token ';' +//%token '}' +//%token '@' +//%token '~' +//%token '$' + +%precedence /*1*/ PRECLOW ; +%precedence /*2*/ LAMBDA ; +%precedence /*3*/ SELF ; +%precedence /*4*/ MUT ; +%precedence /*5*/ IDENT ; +%precedence /*6*/ CATCH ; +%precedence /*7*/ DEFAULT ; +%precedence /*8*/ UNION ; +%precedence /*9*/ SHIFTPLUS ; +%precedence /*10*/ MOD_SEP ; +%precedence /*11*/ RARROW ':' ; +%precedence /*12*/ FORTYPE ; +%precedence /*13*/ FOR ; +%precedence /*14*/ '?' ; +%precedence /*15*/ BOX ; +%nonassoc /*16*/ DOTDOT ; +%precedence /*17*/ RETURN YIELD ; +%right /*18*/ SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ '=' ; +%right /*19*/ LARROW ; +%left /*20*/ OROR ; +%left /*21*/ ANDAND ; +%left /*22*/ EQEQ NE ; +%left /*23*/ LE GE '<' '>' ; +%left /*24*/ '|' ; +%left /*25*/ '^' ; +%left /*26*/ '&' ; +%left /*27*/ SHL SHR ; +%left /*28*/ '+' '-' ; +%precedence /*29*/ AS ; +%left /*30*/ '*' '/' '%' ; +%precedence /*31*/ '!' ; +%precedence /*32*/ '{' '[' '(' '.' ; +%precedence /*33*/ RANGE ; + +//%start crate + +//%% + +crate : + /*YYEOF + |*/ maybe_shebang inner_attrs maybe_mod_items + | maybe_shebang maybe_mod_items + ; + +maybe_shebang : + SHEBANG_LINE + | /*empty*/ + ; + +maybe_inner_attrs : + inner_attrs + | /*empty*/ + ; + +inner_attrs : + inner_attr + | inner_attrs inner_attr + ; + +inner_attr : + SHEBANG '[' /*32P*/ meta_item ']' + | INNER_DOC_COMMENT + ; + +maybe_outer_attrs : + outer_attrs + | /*empty*/ + ; + +outer_attrs : + outer_attr + | outer_attrs outer_attr + ; + +outer_attr : + '#' '[' /*32P*/ meta_item ']' + | OUTER_DOC_COMMENT + ; + +meta_item : + ident + | ident '=' /*18R*/ lit + | ident '(' /*32P*/ meta_seq ')' + | ident '(' /*32P*/ meta_seq ',' ')' + ; + +meta_seq : + /*empty*/ + | meta_item + | meta_seq MOD_SEP /*10P*/ meta_item + | meta_seq ',' meta_item + ; + +maybe_mod_items : + mod_items + | /*empty*/ + ; + +mod_items : + mod_item + | mod_items mod_item + ; + +attrs_and_vis : + maybe_outer_attrs visibility + ; + +mod_item : + attrs_and_vis item + ; + +item : + stmt_item + | item_macro + ; + +stmt_item : + item_static + | item_const + | item_type + | block_item + | view_item + ; + +item_static : + STATIC ident ':' /*11P*/ ty '=' /*18R*/ expr ';' + | STATIC MUT /*4P*/ ident ':' /*11P*/ ty '=' /*18R*/ expr ';' + ; + +item_const : + CONST ident ':' /*11P*/ ty '=' /*18R*/ expr ';' + ; + +item_macro : + path_expr '!' /*31P*/ maybe_ident parens_delimited_token_trees ';' + | path_expr '!' /*31P*/ maybe_ident braces_delimited_token_trees + | path_expr '!' /*31P*/ maybe_ident brackets_delimited_token_trees ';' + ; + +view_item : + use_item + | extern_fn_item + | EXTERN CRATE ident ';' + | EXTERN CRATE ident AS /*29P*/ ident ';' + ; + +extern_fn_item : + EXTERN maybe_abi item_fn + ; + +use_item : + USE view_path ';' + ; + +view_path : + path_no_types_allowed + | path_no_types_allowed MOD_SEP /*10P*/ '{' /*32P*/ '}' + | MOD_SEP /*10P*/ '{' /*32P*/ '}' + | path_no_types_allowed MOD_SEP /*10P*/ '{' /*32P*/ idents_or_self '}' + | MOD_SEP /*10P*/ '{' /*32P*/ idents_or_self '}' + | path_no_types_allowed MOD_SEP /*10P*/ '{' /*32P*/ idents_or_self ',' '}' + | MOD_SEP /*10P*/ '{' /*32P*/ idents_or_self ',' '}' + | path_no_types_allowed MOD_SEP /*10P*/ '*' /*30L*/ + | MOD_SEP /*10P*/ '*' /*30L*/ + | '*' /*30L*/ + | '{' /*32P*/ '}' + | '{' /*32P*/ idents_or_self '}' + | '{' /*32P*/ idents_or_self ',' '}' + | path_no_types_allowed AS /*29P*/ ident + ; + +block_item : + item_fn + | item_unsafe_fn + | item_mod + | item_foreign_mod + | item_struct + | item_enum + | item_union + | item_trait + | item_impl + ; + +maybe_ty_ascription : + ':' /*11P*/ ty_sum + | /*empty*/ + ; + +maybe_init_expr : + '=' /*18R*/ expr + | /*empty*/ + ; + +item_struct : + STRUCT ident generic_params maybe_where_clause struct_decl_args + | STRUCT ident generic_params struct_tuple_args maybe_where_clause ';' + | STRUCT ident generic_params maybe_where_clause ';' + ; + +struct_decl_args : + '{' /*32P*/ struct_decl_fields '}' + | '{' /*32P*/ struct_decl_fields ',' '}' + ; + +struct_tuple_args : + '(' /*32P*/ struct_tuple_fields ')' + | '(' /*32P*/ struct_tuple_fields ',' ')' + ; + +struct_decl_fields : + struct_decl_field + | struct_decl_fields ',' struct_decl_field + | /*empty*/ + ; + +struct_decl_field : + attrs_and_vis ident ':' /*11P*/ ty_sum + ; + +struct_tuple_fields : + struct_tuple_field + | struct_tuple_fields ',' struct_tuple_field + | /*empty*/ + ; + +struct_tuple_field : + attrs_and_vis ty_sum + ; + +item_enum : + ENUM ident generic_params maybe_where_clause '{' /*32P*/ enum_defs '}' + | ENUM ident generic_params maybe_where_clause '{' /*32P*/ enum_defs ',' '}' + ; + +enum_defs : + enum_def + | enum_defs ',' enum_def + | /*empty*/ + ; + +enum_def : + attrs_and_vis ident enum_args + ; + +enum_args : + '{' /*32P*/ struct_decl_fields '}' + | '{' /*32P*/ struct_decl_fields ',' '}' + | '(' /*32P*/ maybe_ty_sums ')' + | '=' /*18R*/ expr + | /*empty*/ + ; + +item_union : + UNION /*8P*/ ident generic_params maybe_where_clause '{' /*32P*/ struct_decl_fields '}' + | UNION /*8P*/ ident generic_params maybe_where_clause '{' /*32P*/ struct_decl_fields ',' '}' + ; + +item_mod : + MOD ident ';' + | MOD ident '{' /*32P*/ maybe_mod_items '}' + | MOD ident '{' /*32P*/ inner_attrs maybe_mod_items '}' + ; + +item_foreign_mod : + EXTERN maybe_abi '{' /*32P*/ maybe_foreign_items '}' + | EXTERN maybe_abi '{' /*32P*/ inner_attrs maybe_foreign_items '}' + ; + +maybe_abi : + str + | /*empty*/ + ; + +maybe_foreign_items : + foreign_items + | /*empty*/ + ; + +foreign_items : + foreign_item + | foreign_items foreign_item + ; + +foreign_item : + attrs_and_vis STATIC item_foreign_static + | attrs_and_vis item_foreign_fn + | attrs_and_vis UNSAFE item_foreign_fn + | attrs_and_vis TYPE item_foreign_type + ; + +item_foreign_static : + maybe_mut ident ':' /*11P*/ ty ';' + ; + +item_foreign_fn : + FN ident generic_params fn_decl_allow_variadic maybe_where_clause ';' + ; + +item_foreign_type : + ident generic_params ';' + ; + +fn_decl_allow_variadic : + fn_params_allow_variadic ret_ty + ; + +fn_params_allow_variadic : + '(' /*32P*/ ')' + | '(' /*32P*/ params ')' + | '(' /*32P*/ params ',' ')' + | '(' /*32P*/ params ',' DOTDOTDOT ')' + ; + +visibility : + PUB %prec PRECLOW /*1P*/ + | PUB '(' /*32P*/ pub_param ')' + | CRATE + | /*empty*/ + ; + +pub_param : + SELF /*3P*/ + | SUPER + | CRATE + ; + +idents_or_self : + ident_or_self + | idents_or_self AS /*29P*/ ident + | idents_or_self MOD_SEP /*10P*/ ident + | idents_or_self ',' ident_or_self + ; + +ident_or_self : + ident + | SELF /*3P*/ + ; + +item_type : + TYPE ident generic_params maybe_where_clause '=' /*18R*/ ty_sum ';' + ; + +for_sized : + FOR /*13P*/ '?' /*14P*/ ident + | FOR /*13P*/ ident '?' /*14P*/ + | /*empty*/ + ; + +item_trait : + maybe_unsafe TRAIT ident generic_params for_sized maybe_ty_param_bounds maybe_where_clause '{' /*32P*/ maybe_trait_items '}' + ; + +maybe_trait_items : + trait_items + | /*empty*/ + ; + +trait_items : + trait_item + | trait_items trait_item + ; + +trait_item : + trait_const + | trait_type + | trait_method + | maybe_outer_attrs item_macro + ; + +trait_const : + maybe_outer_attrs CONST ident maybe_ty_ascription maybe_const_default ';' + ; + +maybe_const_default : + '=' /*18R*/ expr + | /*empty*/ + ; + +trait_type : + maybe_outer_attrs TYPE ty_param ';' + ; + +maybe_unsafe : + UNSAFE + | /*empty*/ + ; + +maybe_default_maybe_unsafe : + DEFAULT /*7P*/ UNSAFE + | DEFAULT /*7P*/ + | UNSAFE + | /*empty*/ + ; + +trait_method : + type_method + | method + ; + +type_method : + maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' + | maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' + | maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' + ; + +method : + maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block + | maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block + | maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block + ; + +impl_method : + attrs_and_vis maybe_default maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block + | attrs_and_vis maybe_default CONST maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block + | attrs_and_vis maybe_default maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block + ; + +item_impl : + maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' /*32P*/ maybe_inner_attrs maybe_impl_items '}' + | maybe_default_maybe_unsafe IMPL generic_params '(' /*32P*/ ty ')' maybe_where_clause '{' /*32P*/ maybe_inner_attrs maybe_impl_items '}' + | maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR /*13P*/ ty_sum maybe_where_clause '{' /*32P*/ maybe_inner_attrs maybe_impl_items '}' + | maybe_default_maybe_unsafe IMPL generic_params '!' /*31P*/ trait_ref FOR /*13P*/ ty_sum maybe_where_clause '{' /*32P*/ maybe_inner_attrs maybe_impl_items '}' + | maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR /*13P*/ DOTDOT /*16N*/ '{' /*32P*/ '}' + | maybe_default_maybe_unsafe IMPL generic_params '!' /*31P*/ trait_ref FOR /*13P*/ DOTDOT /*16N*/ '{' /*32P*/ '}' + ; + +maybe_impl_items : + impl_items + | /*empty*/ + ; + +impl_items : + impl_item + | impl_item impl_items + ; + +impl_item : + impl_method + | attrs_and_vis item_macro + | impl_const + | impl_type + ; + +maybe_default : + DEFAULT /*7P*/ + | /*empty*/ + ; + +impl_const : + attrs_and_vis maybe_default item_const + ; + +impl_type : + attrs_and_vis maybe_default TYPE ident generic_params '=' /*18R*/ ty_sum ';' + ; + +item_fn : + FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block + | CONST FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block + ; + +item_unsafe_fn : + UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block + | CONST UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block + | UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block + ; + +fn_decl : + fn_params ret_ty + ; + +fn_decl_with_self : + fn_params_with_self ret_ty + ; + +fn_decl_with_self_allow_anon_params : + fn_anon_params_with_self ret_ty + ; + +fn_params : + '(' /*32P*/ maybe_params ')' + ; + +fn_anon_params : + '(' /*32P*/ anon_param anon_params_allow_variadic_tail ')' + | '(' /*32P*/ ')' + ; + +fn_params_with_self : + '(' /*32P*/ maybe_mut SELF /*3P*/ maybe_ty_ascription maybe_comma_params ')' + | '(' /*32P*/ '&' /*26L*/ maybe_mut SELF /*3P*/ maybe_ty_ascription maybe_comma_params ')' + | '(' /*32P*/ '&' /*26L*/ lifetime maybe_mut SELF /*3P*/ maybe_ty_ascription maybe_comma_params ')' + | '(' /*32P*/ maybe_params ')' + ; + +fn_anon_params_with_self : + '(' /*32P*/ maybe_mut SELF /*3P*/ maybe_ty_ascription maybe_comma_anon_params ')' + | '(' /*32P*/ '&' /*26L*/ maybe_mut SELF /*3P*/ maybe_ty_ascription maybe_comma_anon_params ')' + | '(' /*32P*/ '&' /*26L*/ lifetime maybe_mut SELF /*3P*/ maybe_ty_ascription maybe_comma_anon_params ')' + | '(' /*32P*/ maybe_anon_params ')' + ; + +maybe_params : + params + | params ',' + | /*empty*/ + ; + +params : + param + | params ',' param + ; + +param : + pat ':' /*11P*/ ty_sum + ; + +inferrable_params : + inferrable_param + | inferrable_params ',' inferrable_param + ; + +inferrable_param : + pat maybe_ty_ascription + ; + +maybe_comma_params : + ',' + | ',' params + | ',' params ',' + | /*empty*/ + ; + +maybe_comma_anon_params : + ',' + | ',' anon_params + | ',' anon_params ',' + | /*empty*/ + ; + +maybe_anon_params : + anon_params + | anon_params ',' + | /*empty*/ + ; + +anon_params : + anon_param + | anon_params ',' anon_param + ; + +anon_param : + named_arg ':' /*11P*/ ty + | ty + ; + +anon_params_allow_variadic_tail : + ',' DOTDOTDOT + | ',' anon_param anon_params_allow_variadic_tail + | /*empty*/ + ; + +named_arg : + ident + | UNDERSCORE + | '&' /*26L*/ ident + | '&' /*26L*/ UNDERSCORE + | ANDAND /*21L*/ ident + | ANDAND /*21L*/ UNDERSCORE + | MUT /*4P*/ ident + ; + +ret_ty : + RARROW /*11P*/ '!' /*31P*/ + | RARROW /*11P*/ ty + | %prec IDENT /*5P*/ /*empty*/ + ; + +generic_params : + '<' /*23L*/ '>' /*23L*/ + | '<' /*23L*/ lifetimes '>' /*23L*/ + | '<' /*23L*/ lifetimes ',' '>' /*23L*/ + | '<' /*23L*/ lifetimes SHR /*27L*/ + | '<' /*23L*/ lifetimes ',' SHR /*27L*/ + | '<' /*23L*/ lifetimes ',' ty_params '>' /*23L*/ + | '<' /*23L*/ lifetimes ',' ty_params ',' '>' /*23L*/ + | '<' /*23L*/ lifetimes ',' ty_params SHR /*27L*/ + | '<' /*23L*/ lifetimes ',' ty_params ',' SHR /*27L*/ + | '<' /*23L*/ ty_params '>' /*23L*/ + | '<' /*23L*/ ty_params ',' '>' /*23L*/ + | '<' /*23L*/ ty_params SHR /*27L*/ + | '<' /*23L*/ ty_params ',' SHR /*27L*/ + | /*empty*/ + ; + +maybe_where_clause : + /*empty*/ + | where_clause + ; + +where_clause : + WHERE where_predicates + | WHERE where_predicates ',' + ; + +where_predicates : + where_predicate + | where_predicates ',' where_predicate + ; + +where_predicate : + maybe_for_lifetimes lifetime ':' /*11P*/ bounds + | maybe_for_lifetimes ty ':' /*11P*/ ty_param_bounds + ; + +maybe_for_lifetimes : + FOR /*13P*/ '<' /*23L*/ lifetimes '>' /*23L*/ + | %prec FORTYPE /*12P*/ /*empty*/ + ; + +ty_params : + ty_param + | ty_params ',' ty_param + ; + +path_no_types_allowed : + ident + | MOD_SEP /*10P*/ ident + | SELF /*3P*/ + | MOD_SEP /*10P*/ SELF /*3P*/ + | SUPER + | MOD_SEP /*10P*/ SUPER + | CRATE + | path_no_types_allowed MOD_SEP /*10P*/ ident + ; + +path_generic_args_without_colons : + ident %prec IDENT /*5P*/ + | ident generic_args %prec IDENT /*5P*/ + | ident '(' /*32P*/ maybe_ty_sums ')' ret_ty %prec IDENT /*5P*/ + | path_generic_args_without_colons MOD_SEP /*10P*/ ident %prec IDENT /*5P*/ + | path_generic_args_without_colons MOD_SEP /*10P*/ ident generic_args %prec IDENT /*5P*/ + | path_generic_args_without_colons MOD_SEP /*10P*/ ident '(' /*32P*/ maybe_ty_sums ')' ret_ty %prec IDENT /*5P*/ + ; + +generic_args : + '<' /*23L*/ generic_values '>' /*23L*/ + | '<' /*23L*/ generic_values SHR /*27L*/ + | '<' /*23L*/ generic_values GE /*23L*/ + | '<' /*23L*/ generic_values SHREQ /*18R*/ + | SHL /*27L*/ ty_qualified_path_and_generic_values '>' /*23L*/ + | SHL /*27L*/ ty_qualified_path_and_generic_values SHR /*27L*/ + | SHL /*27L*/ ty_qualified_path_and_generic_values GE /*23L*/ + | SHL /*27L*/ ty_qualified_path_and_generic_values SHREQ /*18R*/ + ; + +generic_values : + maybe_ty_sums_and_or_bindings + ; + +maybe_ty_sums_and_or_bindings : + ty_sums + | ty_sums ',' + | ty_sums ',' bindings + | bindings + | bindings ',' + | /*empty*/ + ; + +maybe_bindings : + ',' bindings + | /*empty*/ + ; + +pat : + UNDERSCORE + | '&' /*26L*/ pat + | '&' /*26L*/ MUT /*4P*/ pat + | ANDAND /*21L*/ pat + | '(' /*32P*/ ')' + | '(' /*32P*/ pat_tup ')' + | '[' /*32P*/ pat_vec ']' + | lit_or_path + | lit_or_path DOTDOTDOT lit_or_path + | path_expr '{' /*32P*/ pat_struct '}' + | path_expr '(' /*32P*/ ')' + | path_expr '(' /*32P*/ pat_tup ')' + | path_expr '!' /*31P*/ maybe_ident delimited_token_trees + | binding_mode ident + | ident '@' pat + | binding_mode ident '@' pat + | BOX /*15P*/ pat + | '<' /*23L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident + | SHL /*27L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident + ; + +pats_or : + pat + | pats_or '|' /*24L*/ pat + ; + +binding_mode : + REF + | REF MUT /*4P*/ + | MUT /*4P*/ + ; + +lit_or_path : + path_expr + | lit + | '-' /*28L*/ lit + ; + +pat_field : + ident + | binding_mode ident + | BOX /*15P*/ ident + | BOX /*15P*/ binding_mode ident + | ident ':' /*11P*/ pat + | binding_mode ident ':' /*11P*/ pat + | LIT_INTEGER ':' /*11P*/ pat + ; + +pat_fields : + pat_field + | pat_fields ',' pat_field + ; + +pat_struct : + pat_fields + | pat_fields ',' + | pat_fields ',' DOTDOT /*16N*/ + | DOTDOT /*16N*/ + | /*empty*/ + ; + +pat_tup : + pat_tup_elts + | pat_tup_elts ',' + | pat_tup_elts DOTDOT /*16N*/ + | pat_tup_elts ',' DOTDOT /*16N*/ + | pat_tup_elts DOTDOT /*16N*/ ',' pat_tup_elts + | pat_tup_elts DOTDOT /*16N*/ ',' pat_tup_elts ',' + | pat_tup_elts ',' DOTDOT /*16N*/ ',' pat_tup_elts + | pat_tup_elts ',' DOTDOT /*16N*/ ',' pat_tup_elts ',' + | DOTDOT /*16N*/ ',' pat_tup_elts + | DOTDOT /*16N*/ ',' pat_tup_elts ',' + | DOTDOT /*16N*/ + ; + +pat_tup_elts : + pat + | pat_tup_elts ',' pat + ; + +pat_vec : + pat_vec_elts + | pat_vec_elts ',' + | pat_vec_elts DOTDOT /*16N*/ + | pat_vec_elts ',' DOTDOT /*16N*/ + | pat_vec_elts DOTDOT /*16N*/ ',' pat_vec_elts + | pat_vec_elts DOTDOT /*16N*/ ',' pat_vec_elts ',' + | pat_vec_elts ',' DOTDOT /*16N*/ ',' pat_vec_elts + | pat_vec_elts ',' DOTDOT /*16N*/ ',' pat_vec_elts ',' + | DOTDOT /*16N*/ ',' pat_vec_elts + | DOTDOT /*16N*/ ',' pat_vec_elts ',' + | DOTDOT /*16N*/ + | /*empty*/ + ; + +pat_vec_elts : + pat + | pat_vec_elts ',' pat + ; + +ty : + ty_prim + | ty_closure + | '<' /*23L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident + | SHL /*27L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident + | '(' /*32P*/ ty_sums ')' + | '(' /*32P*/ ty_sums ',' ')' + | '(' /*32P*/ ')' + ; + +ty_prim : + path_generic_args_without_colons %prec IDENT /*5P*/ + | MOD_SEP /*10P*/ path_generic_args_without_colons %prec IDENT /*5P*/ + | SELF /*3P*/ MOD_SEP /*10P*/ path_generic_args_without_colons %prec IDENT /*5P*/ + | path_generic_args_without_colons '!' /*31P*/ maybe_ident delimited_token_trees %prec IDENT /*5P*/ + | MOD_SEP /*10P*/ path_generic_args_without_colons '!' /*31P*/ maybe_ident delimited_token_trees %prec IDENT /*5P*/ + | BOX /*15P*/ ty + | '*' /*30L*/ maybe_mut_or_const ty + | '&' /*26L*/ ty + | '&' /*26L*/ MUT /*4P*/ ty + | ANDAND /*21L*/ ty + | ANDAND /*21L*/ MUT /*4P*/ ty + | '&' /*26L*/ lifetime maybe_mut ty + | ANDAND /*21L*/ lifetime maybe_mut ty + | '[' /*32P*/ ty ']' + | '[' /*32P*/ ty ',' DOTDOT /*16N*/ expr ']' + | '[' /*32P*/ ty ';' expr ']' + | TYPEOF '(' /*32P*/ expr ')' + | UNDERSCORE + | ty_bare_fn + | for_in_type + ; + +ty_bare_fn : + FN ty_fn_decl + | UNSAFE FN ty_fn_decl + | EXTERN maybe_abi FN ty_fn_decl + | UNSAFE EXTERN maybe_abi FN ty_fn_decl + ; + +ty_fn_decl : + generic_params fn_anon_params ret_ty + ; + +ty_closure : + UNSAFE '|' /*24L*/ anon_params '|' /*24L*/ maybe_bounds ret_ty + | '|' /*24L*/ anon_params '|' /*24L*/ maybe_bounds ret_ty + | UNSAFE OROR /*20L*/ maybe_bounds ret_ty + | OROR /*20L*/ maybe_bounds ret_ty + ; + +for_in_type : + FOR /*13P*/ '<' /*23L*/ maybe_lifetimes '>' /*23L*/ for_in_type_suffix + ; + +for_in_type_suffix : + ty_bare_fn + | trait_ref + | ty_closure + ; + +maybe_mut : + MUT /*4P*/ + | %prec MUT /*4P*/ /*empty*/ + ; + +maybe_mut_or_const : + MUT /*4P*/ + | CONST + | /*empty*/ + ; + +ty_qualified_path_and_generic_values : + ty_qualified_path maybe_bindings + | ty_qualified_path ',' ty_sums maybe_bindings + ; + +ty_qualified_path : + ty_sum AS /*29P*/ trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident + | ty_sum AS /*29P*/ trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident '+' /*28L*/ ty_param_bounds + ; + +maybe_ty_sums : + ty_sums + | ty_sums ',' + | /*empty*/ + ; + +ty_sums : + ty_sum + | ty_sums ',' ty_sum + ; + +ty_sum : + ty_sum_elt + | ty_sum '+' /*28L*/ ty_sum_elt + ; + +ty_sum_elt : + ty + | lifetime + ; + +ty_prim_sum : + ty_prim_sum_elt + | ty_prim_sum '+' /*28L*/ ty_prim_sum_elt + ; + +ty_prim_sum_elt : + ty_prim + | lifetime + ; + +maybe_ty_param_bounds : + ':' /*11P*/ ty_param_bounds + | /*empty*/ + ; + +ty_param_bounds : + boundseq + | /*empty*/ + ; + +boundseq : + polybound + | boundseq '+' /*28L*/ polybound + ; + +polybound : + FOR /*13P*/ '<' /*23L*/ maybe_lifetimes '>' /*23L*/ bound + | bound + | '?' /*14P*/ FOR /*13P*/ '<' /*23L*/ maybe_lifetimes '>' /*23L*/ bound + | '?' /*14P*/ bound + ; + +bindings : + binding + | bindings ',' binding + ; + +binding : + ident '=' /*18R*/ ty + ; + +ty_param : + maybe_const ident maybe_ty_param_bounds maybe_ty_default + | maybe_const ident '?' /*14P*/ ident maybe_ty_param_bounds maybe_ty_default + ; + +maybe_const : + CONST + | /*empty*/ + ; + +maybe_bounds : + ':' /*11P*/ bounds %prec SHIFTPLUS /*9P*/ + | %prec SHIFTPLUS /*9P*/ /*empty*/ + ; + +bounds : + bound + | bounds '+' /*28L*/ bound + ; + +bound : + lifetime + | trait_ref + ; + +maybe_ltbounds : + ':' /*11P*/ ltbounds %prec SHIFTPLUS /*9P*/ + | /*empty*/ + ; + +ltbounds : + lifetime + | ltbounds '+' /*28L*/ lifetime + ; + +maybe_ty_default : + '=' /*18R*/ ty_sum + | /*empty*/ + ; + +maybe_lifetimes : + lifetimes + | lifetimes ',' + | /*empty*/ + ; + +lifetimes : + lifetime_and_bounds + | lifetimes ',' lifetime_and_bounds + ; + +lifetime_and_bounds : + LIFETIME maybe_ltbounds + | STATIC_LIFETIME + ; + +lifetime : + LIFETIME + | STATIC_LIFETIME + ; + +trait_ref : + path_generic_args_without_colons %prec IDENT /*5P*/ + | MOD_SEP /*10P*/ path_generic_args_without_colons %prec IDENT /*5P*/ + ; + +inner_attrs_and_block : + '{' /*32P*/ maybe_inner_attrs maybe_stmts '}' + ; + +block : + '{' /*32P*/ maybe_stmts '}' + ; + +maybe_stmts : + stmts + | stmts nonblock_expr + | nonblock_expr + | /*empty*/ + ; + +stmts : + stmt + | stmts stmt + ; + +stmt : + maybe_outer_attrs let + | stmt_item + | PUB stmt_item + | outer_attrs stmt_item + | outer_attrs PUB stmt_item + | full_block_expr + | maybe_outer_attrs block + | nonblock_expr ';' + | outer_attrs nonblock_expr ';' + | ';' + ; + +maybe_exprs : + exprs + | exprs ',' + | /*empty*/ + ; + +maybe_expr : + expr + | /*empty*/ + ; + +exprs : + expr + | exprs ',' expr + ; + +path_expr : + path_generic_args_with_colons + | MOD_SEP /*10P*/ path_generic_args_with_colons + | SELF /*3P*/ MOD_SEP /*10P*/ path_generic_args_with_colons + ; + +path_generic_args_with_colons : + ident + | SUPER + | path_generic_args_with_colons MOD_SEP /*10P*/ ident + | path_generic_args_with_colons MOD_SEP /*10P*/ SUPER + | path_generic_args_with_colons MOD_SEP /*10P*/ generic_args + ; + +macro_expr : + path_expr '!' /*31P*/ maybe_ident parens_delimited_token_trees + | path_expr '!' /*31P*/ maybe_ident brackets_delimited_token_trees + ; + +nonblock_expr : + lit + | path_expr %prec IDENT /*5P*/ + | SELF /*3P*/ + | macro_expr + | path_expr '{' /*32P*/ struct_expr_fields '}' + | nonblock_expr '?' /*14P*/ + | nonblock_expr '.' /*32P*/ path_generic_args_with_colons + | nonblock_expr '.' /*32P*/ LIT_INTEGER + | nonblock_expr '[' /*32P*/ maybe_expr ']' + | nonblock_expr '(' /*32P*/ maybe_exprs ')' + | '[' /*32P*/ vec_expr ']' + | '(' /*32P*/ maybe_exprs ')' + | CONTINUE + | CONTINUE lifetime + | RETURN /*17P*/ + | RETURN /*17P*/ expr + | BREAK + | BREAK lifetime + | YIELD /*17P*/ + | YIELD /*17P*/ expr + | nonblock_expr LARROW /*19R*/ expr + | nonblock_expr '=' /*18R*/ expr + | nonblock_expr SHLEQ /*18R*/ expr + | nonblock_expr SHREQ /*18R*/ expr + | nonblock_expr MINUSEQ /*18R*/ expr + | nonblock_expr ANDEQ /*18R*/ expr + | nonblock_expr OREQ /*18R*/ expr + | nonblock_expr PLUSEQ /*18R*/ expr + | nonblock_expr STAREQ /*18R*/ expr + | nonblock_expr SLASHEQ /*18R*/ expr + | nonblock_expr CARETEQ /*18R*/ expr + | nonblock_expr PERCENTEQ /*18R*/ expr + | nonblock_expr OROR /*20L*/ expr + | nonblock_expr ANDAND /*21L*/ expr + | nonblock_expr EQEQ /*22L*/ expr + | nonblock_expr NE /*22L*/ expr + | nonblock_expr '<' /*23L*/ expr + | nonblock_expr '>' /*23L*/ expr + | nonblock_expr LE /*23L*/ expr + | nonblock_expr GE /*23L*/ expr + | nonblock_expr '|' /*24L*/ expr + | nonblock_expr '^' /*25L*/ expr + | nonblock_expr '&' /*26L*/ expr + | nonblock_expr SHL /*27L*/ expr + | nonblock_expr SHR /*27L*/ expr + | nonblock_expr '+' /*28L*/ expr + | nonblock_expr '-' /*28L*/ expr + | nonblock_expr '*' /*30L*/ expr + | nonblock_expr '/' /*30L*/ expr + | nonblock_expr '%' /*30L*/ expr + | nonblock_expr DOTDOT /*16N*/ + | nonblock_expr DOTDOT /*16N*/ expr + | DOTDOT /*16N*/ expr + | DOTDOT /*16N*/ + | nonblock_expr AS /*29P*/ ty + | nonblock_expr ':' /*11P*/ ty + | BOX /*15P*/ expr + | expr_qualified_path + | nonblock_prefix_expr + ; + +expr : + lit + | path_expr %prec IDENT /*5P*/ + | SELF /*3P*/ + | macro_expr + | path_expr '{' /*32P*/ struct_expr_fields '}' + | expr '?' /*14P*/ + | expr '.' /*32P*/ path_generic_args_with_colons + | expr '.' /*32P*/ LIT_INTEGER + | expr '[' /*32P*/ maybe_expr ']' + | expr '(' /*32P*/ maybe_exprs ')' + | '(' /*32P*/ maybe_exprs ')' + | '[' /*32P*/ vec_expr ']' + | CONTINUE + | CONTINUE ident + | RETURN /*17P*/ + | RETURN /*17P*/ expr + | BREAK + | BREAK ident + | YIELD /*17P*/ + | YIELD /*17P*/ expr + | expr LARROW /*19R*/ expr + | expr '=' /*18R*/ expr + | expr SHLEQ /*18R*/ expr + | expr SHREQ /*18R*/ expr + | expr MINUSEQ /*18R*/ expr + | expr ANDEQ /*18R*/ expr + | expr OREQ /*18R*/ expr + | expr PLUSEQ /*18R*/ expr + | expr STAREQ /*18R*/ expr + | expr SLASHEQ /*18R*/ expr + | expr CARETEQ /*18R*/ expr + | expr PERCENTEQ /*18R*/ expr + | expr OROR /*20L*/ expr + | expr ANDAND /*21L*/ expr + | expr EQEQ /*22L*/ expr + | expr NE /*22L*/ expr + | expr '<' /*23L*/ expr + | expr '>' /*23L*/ expr + | expr LE /*23L*/ expr + | expr GE /*23L*/ expr + | expr '|' /*24L*/ expr + | expr '^' /*25L*/ expr + | expr '&' /*26L*/ expr + | expr SHL /*27L*/ expr + | expr SHR /*27L*/ expr + | expr '+' /*28L*/ expr + | expr '-' /*28L*/ expr + | expr '*' /*30L*/ expr + | expr '/' /*30L*/ expr + | expr '%' /*30L*/ expr + | expr DOTDOT /*16N*/ + | expr DOTDOT /*16N*/ expr + | DOTDOT /*16N*/ expr + | DOTDOT /*16N*/ + | expr AS /*29P*/ ty + | expr ':' /*11P*/ ty + | BOX /*15P*/ expr + | expr_qualified_path + | block_expr + | block + | nonblock_prefix_expr + ; + +expr_nostruct : + lit + | path_expr %prec IDENT /*5P*/ + | SELF /*3P*/ + | macro_expr + | expr_nostruct '?' /*14P*/ + | expr_nostruct '.' /*32P*/ path_generic_args_with_colons + | expr_nostruct '.' /*32P*/ LIT_INTEGER + | expr_nostruct '[' /*32P*/ maybe_expr ']' + | expr_nostruct '(' /*32P*/ maybe_exprs ')' + | '[' /*32P*/ vec_expr ']' + | '(' /*32P*/ maybe_exprs ')' + | CONTINUE + | CONTINUE ident + | RETURN /*17P*/ + | RETURN /*17P*/ expr + | BREAK + | BREAK ident + | YIELD /*17P*/ + | YIELD /*17P*/ expr + | expr_nostruct LARROW /*19R*/ expr_nostruct + | expr_nostruct '=' /*18R*/ expr_nostruct + | expr_nostruct SHLEQ /*18R*/ expr_nostruct + | expr_nostruct SHREQ /*18R*/ expr_nostruct + | expr_nostruct MINUSEQ /*18R*/ expr_nostruct + | expr_nostruct ANDEQ /*18R*/ expr_nostruct + | expr_nostruct OREQ /*18R*/ expr_nostruct + | expr_nostruct PLUSEQ /*18R*/ expr_nostruct + | expr_nostruct STAREQ /*18R*/ expr_nostruct + | expr_nostruct SLASHEQ /*18R*/ expr_nostruct + | expr_nostruct CARETEQ /*18R*/ expr_nostruct + | expr_nostruct PERCENTEQ /*18R*/ expr_nostruct + | expr_nostruct OROR /*20L*/ expr_nostruct + | expr_nostruct ANDAND /*21L*/ expr_nostruct + | expr_nostruct EQEQ /*22L*/ expr_nostruct + | expr_nostruct NE /*22L*/ expr_nostruct + | expr_nostruct '<' /*23L*/ expr_nostruct + | expr_nostruct '>' /*23L*/ expr_nostruct + | expr_nostruct LE /*23L*/ expr_nostruct + | expr_nostruct GE /*23L*/ expr_nostruct + | expr_nostruct '|' /*24L*/ expr_nostruct + | expr_nostruct '^' /*25L*/ expr_nostruct + | expr_nostruct '&' /*26L*/ expr_nostruct + | expr_nostruct SHL /*27L*/ expr_nostruct + | expr_nostruct SHR /*27L*/ expr_nostruct + | expr_nostruct '+' /*28L*/ expr_nostruct + | expr_nostruct '-' /*28L*/ expr_nostruct + | expr_nostruct '*' /*30L*/ expr_nostruct + | expr_nostruct '/' /*30L*/ expr_nostruct + | expr_nostruct '%' /*30L*/ expr_nostruct + | expr_nostruct DOTDOT /*16N*/ %prec RANGE /*33P*/ + | expr_nostruct DOTDOT /*16N*/ expr_nostruct + | DOTDOT /*16N*/ expr_nostruct + | DOTDOT /*16N*/ + | expr_nostruct AS /*29P*/ ty + | expr_nostruct ':' /*11P*/ ty + | BOX /*15P*/ expr + | expr_qualified_path + | block_expr + | block + | nonblock_prefix_expr_nostruct + ; + +nonblock_prefix_expr_nostruct : + '-' /*28L*/ expr_nostruct + | '!' /*31P*/ expr_nostruct + | '*' /*30L*/ expr_nostruct + | '&' /*26L*/ maybe_mut expr_nostruct + | ANDAND /*21L*/ maybe_mut expr_nostruct + | lambda_expr_nostruct + | MOVE lambda_expr_nostruct + ; + +nonblock_prefix_expr : + '-' /*28L*/ expr + | '!' /*31P*/ expr + | '*' /*30L*/ expr + | '&' /*26L*/ maybe_mut expr + | ANDAND /*21L*/ maybe_mut expr + | lambda_expr + | MOVE lambda_expr + ; + +expr_qualified_path : + '<' /*23L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident maybe_qpath_params + | SHL /*27L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident + | SHL /*27L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident generic_args maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident + | SHL /*27L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident generic_args + | SHL /*27L*/ ty_sum maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident generic_args maybe_as_trait_ref '>' /*23L*/ MOD_SEP /*10P*/ ident generic_args + ; + +maybe_qpath_params : + MOD_SEP /*10P*/ generic_args + | /*empty*/ + ; + +maybe_as_trait_ref : + AS /*29P*/ trait_ref + | /*empty*/ + ; + +lambda_expr : + OROR /*20L*/ ret_ty expr %prec LAMBDA /*2P*/ + | '|' /*24L*/ '|' /*24L*/ ret_ty expr %prec LAMBDA /*2P*/ + | '|' /*24L*/ inferrable_params '|' /*24L*/ ret_ty expr %prec LAMBDA /*2P*/ + | '|' /*24L*/ inferrable_params OROR /*20L*/ lambda_expr_no_first_bar %prec LAMBDA /*2P*/ + ; + +lambda_expr_no_first_bar : + '|' /*24L*/ ret_ty expr %prec LAMBDA /*2P*/ + | inferrable_params '|' /*24L*/ ret_ty expr %prec LAMBDA /*2P*/ + | inferrable_params OROR /*20L*/ lambda_expr_no_first_bar %prec LAMBDA /*2P*/ + ; + +lambda_expr_nostruct : + OROR /*20L*/ expr_nostruct %prec LAMBDA /*2P*/ + | '|' /*24L*/ '|' /*24L*/ ret_ty expr_nostruct %prec LAMBDA /*2P*/ + | '|' /*24L*/ inferrable_params '|' /*24L*/ expr_nostruct %prec LAMBDA /*2P*/ + | '|' /*24L*/ inferrable_params OROR /*20L*/ lambda_expr_nostruct_no_first_bar %prec LAMBDA /*2P*/ + ; + +lambda_expr_nostruct_no_first_bar : + '|' /*24L*/ ret_ty expr_nostruct %prec LAMBDA /*2P*/ + | inferrable_params '|' /*24L*/ ret_ty expr_nostruct %prec LAMBDA /*2P*/ + | inferrable_params OROR /*20L*/ lambda_expr_nostruct_no_first_bar %prec LAMBDA /*2P*/ + ; + +vec_expr : + maybe_exprs + | exprs ';' expr + ; + +struct_expr_fields : + field_inits + | field_inits ',' + | maybe_field_inits default_field_init + | /*empty*/ + ; + +maybe_field_inits : + field_inits + | field_inits ',' + | /*empty*/ + ; + +field_inits : + field_init + | field_inits ',' field_init + ; + +field_init : + ident + | ident ':' /*11P*/ expr + | LIT_INTEGER ':' /*11P*/ expr + ; + +default_field_init : + DOTDOT /*16N*/ expr + ; + +block_expr : + expr_match + | expr_if + | expr_if_let + | expr_while + | expr_while_let + | expr_loop + | expr_for + | UNSAFE block + | path_expr '!' /*31P*/ maybe_ident braces_delimited_token_trees + ; + +full_block_expr : + block_expr + | block_expr_dot + ; + +block_expr_dot : + block_expr '.' /*32P*/ path_generic_args_with_colons %prec IDENT /*5P*/ + | block_expr_dot '.' /*32P*/ path_generic_args_with_colons %prec IDENT /*5P*/ + | block_expr '.' /*32P*/ path_generic_args_with_colons '[' /*32P*/ maybe_expr ']' + | block_expr_dot '.' /*32P*/ path_generic_args_with_colons '[' /*32P*/ maybe_expr ']' + | block_expr '.' /*32P*/ path_generic_args_with_colons '(' /*32P*/ maybe_exprs ')' + | block_expr_dot '.' /*32P*/ path_generic_args_with_colons '(' /*32P*/ maybe_exprs ')' + | block_expr '.' /*32P*/ LIT_INTEGER + | block_expr_dot '.' /*32P*/ LIT_INTEGER + ; + +expr_match : + MATCH expr_nostruct '{' /*32P*/ '}' + | MATCH expr_nostruct '{' /*32P*/ match_clauses '}' + | MATCH expr_nostruct '{' /*32P*/ match_clauses nonblock_match_clause '}' + | MATCH expr_nostruct '{' /*32P*/ nonblock_match_clause '}' + ; + +match_clauses : + match_clause + | match_clauses match_clause + ; + +match_clause : + nonblock_match_clause ',' + | block_match_clause + | block_match_clause ',' + ; + +nonblock_match_clause : + maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr + | maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr_dot + ; + +block_match_clause : + maybe_outer_attrs pats_or maybe_guard FAT_ARROW block + | maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr + ; + +maybe_guard : + IF expr_nostruct + | /*empty*/ + ; + +expr_if : + IF expr_nostruct block + | IF expr_nostruct block ELSE block_or_if + ; + +expr_if_let : + IF LET pat '=' /*18R*/ expr_nostruct block + | IF LET pat '=' /*18R*/ expr_nostruct block ELSE block_or_if + ; + +block_or_if : + block + | expr_if + | expr_if_let + ; + +expr_while : + maybe_label WHILE expr_nostruct block + ; + +expr_while_let : + maybe_label WHILE LET pat '=' /*18R*/ expr_nostruct block + ; + +expr_loop : + maybe_label LOOP block + ; + +expr_for : + maybe_label FOR /*13P*/ pat IN expr_nostruct block + ; + +maybe_label : + lifetime ':' /*11P*/ + | /*empty*/ + ; + +let : + LET pat maybe_ty_ascription maybe_init_expr ';' + ; + +lit : + LIT_BYTE + | LIT_CHAR + | LIT_INTEGER + | LIT_FLOAT + | TRUE + | FALSE + | str + ; + +str : + LIT_STR + | LIT_STR_RAW + | LIT_BYTE_STR + | LIT_BYTE_STR_RAW + ; + +maybe_ident : + /*empty*/ + | ident + ; + +ident : + IDENT /*5P*/ + | CATCH /*6P*/ + | DEFAULT /*7P*/ + | UNION /*8P*/ + ; + +unpaired_token : + SHL /*27L*/ + | SHR /*27L*/ + | LE /*23L*/ + | EQEQ /*22L*/ + | NE /*22L*/ + | GE /*23L*/ + | ANDAND /*21L*/ + | OROR /*20L*/ + | LARROW /*19R*/ + | SHLEQ /*18R*/ + | SHREQ /*18R*/ + | MINUSEQ /*18R*/ + | ANDEQ /*18R*/ + | OREQ /*18R*/ + | PLUSEQ /*18R*/ + | STAREQ /*18R*/ + | SLASHEQ /*18R*/ + | CARETEQ /*18R*/ + | PERCENTEQ /*18R*/ + | DOTDOT /*16N*/ + | DOTDOTDOT + | MOD_SEP /*10P*/ + | RARROW /*11P*/ + | FAT_ARROW + | LIT_BYTE + | LIT_CHAR + | LIT_INTEGER + | LIT_FLOAT + | LIT_STR + | LIT_STR_RAW + | LIT_BYTE_STR + | LIT_BYTE_STR_RAW + | IDENT /*5P*/ + | UNDERSCORE + | LIFETIME + | SELF /*3P*/ + | STATIC + | ABSTRACT + | ALIGNOF + | AS /*29P*/ + | BECOME + | BREAK + | CATCH /*6P*/ + | CRATE + | DEFAULT /*7P*/ + | DO + | ELSE + | ENUM + | EXTERN + | FALSE + | FINAL + | FN + | FOR /*13P*/ + | IF + | IMPL + | IN + | LET + | LOOP + | MACRO + | MATCH + | MOD + | MOVE + | MUT /*4P*/ + | OFFSETOF + | OVERRIDE + | PRIV + | PUB + | PURE + | REF + | RETURN /*17P*/ + | STRUCT + | SIZEOF + | SUPER + | TRUE + | TRAIT + | TYPE + | UNION /*8P*/ + | UNSAFE + | UNSIZED + | USE + | VIRTUAL + | WHILE + | YIELD /*17P*/ + | CONTINUE + | PROC + | BOX /*15P*/ + | CONST + | WHERE + | TYPEOF + | INNER_DOC_COMMENT + | OUTER_DOC_COMMENT + | SHEBANG + | STATIC_LIFETIME + | ';' + | ',' + | '.' /*32P*/ + | '@' + | '#' + | '~' + | ':' /*11P*/ + | '$' + | '=' /*18R*/ + | '?' /*14P*/ + | '!' /*31P*/ + | '<' /*23L*/ + | '>' /*23L*/ + | '-' /*28L*/ + | '&' /*26L*/ + | '|' /*24L*/ + | '+' /*28L*/ + | '*' /*30L*/ + | '/' /*30L*/ + | '^' /*25L*/ + | '%' /*30L*/ + ; + +token_trees : + /*empty*/ + | token_trees token_tree + ; + +token_tree : + delimited_token_trees + | unpaired_token + ; + +delimited_token_trees : + parens_delimited_token_trees + | braces_delimited_token_trees + | brackets_delimited_token_trees + ; + +parens_delimited_token_trees : + '(' /*32P*/ token_trees ')' + ; + +braces_delimited_token_trees : + '{' /*32P*/ token_trees '}' + ; + +brackets_delimited_token_trees : + '[' /*32P*/ token_trees ']' + ; + +//Lexer + + +SELF : 'self' ; +CATCH : 'catch' ; +DEFAULT : 'default' ; +UNION : 'union' ; +MOD_SEP : '::' ; +RARROW : '->' ; +FOR : 'for' ; +BOX : 'box' ; +DOTDOT : '..' ; +RETURN : 'return' ; +YIELD : 'yield' ; +SHLEQ : '<<=' ; +SHREQ : '>>=' ; +MINUSEQ : '-=' ; +ANDEQ : '&=' ; +OREQ : '|=' ; +PLUSEQ : '+=' ; +STAREQ : '*=' ; +SLASHEQ : '/=' ; +CARETEQ : '^=' ; +PERCENTEQ : '%=' ; +LARROW : '<-' ; +OROR : '||' ; +ANDAND : '&&' ; +EQEQ : '==' ; +NE : '!=' ; +LE : '<=' ; +GE : '>=' ; +SHL : '<<' ; +SHR : '>>' ; +AS : 'as' ; +SHEBANG : '#!' ; +SHEBANG_LINE : "#![^\n]+" ; +INNER_DOC_COMMENT : "///[^\n]*" ; +OUTER_DOC_COMMENT : "//![^\n]*" ; +STATIC : 'static' ; +CONST : 'const' ; +EXTERN : 'extern' ; +CRATE : 'crate' ; +USE : 'use' ; +STRUCT : 'struct' ; +ENUM : 'enum' ; +MOD : 'mod' ; +UNSAFE : 'unsafe' ; +TYPE : 'type' ; +FN : 'fn' ; +DOTDOTDOT : '...' ; +PUB : 'pub' ; +SUPER : 'super' ; +TRAIT : 'trait' ; +IMPL : 'impl' ; +UNDERSCORE : '_' ; +WHERE : 'where' ; +REF : 'ref' ; +LIT_INTEGER : "0x[0-9a-fA-F_]+|0o[0-7_]+|0b[01_]+|[0-9][0-9_]*|[0-9][0-9_]*\.(\.|[a-zA-Z])" ; +TYPEOF : 'typeof' ; +LIFETIME : '\'' IDENT ; +STATIC_LIFETIME : '\'static' ; +CONTINUE : 'continue' ; +BREAK : 'break' ; +MOVE : 'move' ; +MATCH : 'match' ; +FAT_ARROW : '=>' ; +IF : 'if' ; +ELSE : 'else' ; +LET : 'let' ; +WHILE : 'while' ; +LOOP : 'loop' ; +IN : 'in' ; +LIT_BYTE : "b'([^'\n]|\\[^\n])'" ; +LIT_CHAR : "'([^'\n]|\\[^\n])'" ; +LIT_FLOAT : "[0-9][0-9_]*\.[0-9_]*([eE][-\+]?[0-9_]+)?|[0-9][0-9_]*(\.[0-9_]*)?[eE][-\+]?[0-9_]+" ; +TRUE : 'true' ; +FALSE : 'false' ; +LIT_STR : "\"([^\"\n]|\\[^\n])*\"" ; +LIT_STR_RAW : 'LIT_STR_RAW' ; +LIT_BYTE_STR : 'LIT_BYTE_STR' ; +LIT_BYTE_STR_RAW : 'LIT_BYTE_STR_RAW' ; +ABSTRACT : 'abstract' ; +ALIGNOF : 'alignof' ; +BECOME : 'become' ; +DO : 'do' ; +FINAL : 'final' ; +MACRO : 'macro' ; +OFFSETOF : 'offsetof' ; +OVERRIDE : 'override' ; +PRIV : 'priv' ; +PURE : 'pure' ; +SIZEOF : 'sizeof' ; +UNSIZED : 'unsized' ; +VIRTUAL : 'virtual' ; +PROC : 'proc' ; +MUT : 'mut' ; //When commenting this we get lots of shift/reduce conflicts instead of a missing definition +IDENT : "[a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]*" ; + +// +// TODO: parse generic parameter that end in ">>" +// + +} diff --git a/playground/tameparser.g b/playground/tameparser.g new file mode 100644 index 0000000..383bf79 --- /dev/null +++ b/playground/tameparser.g @@ -0,0 +1,404 @@ +// From: https://github.com/Logicalshift/TameParse/blob/master/TameParse/Language/definition.tp +/// +/// Parser Language Definition +/// +/// Created by Andrew Hunter on 21/05/2011 +/// + +tameparse { + +%whitespace "[ \t\r\n]*"; +%whitespace "//[^\n]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + + +/// The grammar itself + +// +// The top-level definitions +// + +Parser_Language : + TopLevel_Block_zm + ; + +TopLevel_Block_zm : + TopLevel_Block + | TopLevel_Block_zm TopLevel_Block + | /*empty*/ + ; + +TopLevel_Block : + Language_Block + | Import_Block + | Parser_Block + | Test_Block + ; + +Language_Block : + language identifier Language_Inherits_zo '{' Language_Definition_zm '}' + ; + +Import_Block : + import string + ; + +Language_Inherits_zo : + Language_Inherits + | /*empty*/ + ; + +Language_Inherits : + ':' identifier + ; + +// +// The language block +// + +Language_Definition_zm : + Language_Definition + | Language_Definition_zm Language_Definition + | /*empty*/ + ; + +Language_Definition : + Lexer_Symbols_Definition + | Lexer_Definition + | Ignore_Definition + | Keywords_Definition + | Grammar_Definition + | Precedence_Definition + ; + +// +// Basic language items +// + +Lexer_Symbols_Definition : + Lexer_Symbols_Modifier_zm lexer_symbols '{' Lexeme_Definition_zm '}' + ; + +Lexer_Definition : + Lexer_Modifier_zm lexer '{' Lexeme_Definition_zm '}' + ; + +Ignore_Definition : + ignore '{' Keyword_Definition_zm '}' + ; + +Keywords_Definition : + Lexer_Modifier_zm keywords '{' Keyword_Definition_zm '}' + ; + +Lexer_Modifier_zm : + Lexer_Modifier + | Lexer_Modifier_zm Lexer_Modifier + | /*eempty*/ + ; + +Lexer_Modifier : + weak + | case sensitive + | case insensitive + ; + +Lexer_Symbols_Modifier_zm : + Lexer_Symbols_Modifier + | Lexer_Symbols_Modifier_zm Lexer_Symbols_Modifier + | /*empty*/ + ; + +Lexer_Symbols_Modifier : + case sensitive + | case insensitive + ; + +Keyword_Definition_zm : + Keyword_Definition + | Keyword_Definition_zm Keyword_Definition + | /*empty*/ + ; + +Keyword_Definition : + identifier + | Lexeme_Definition + ; + +Lexeme_Definition_zm : + Lexeme_Definition + | Lexer_Definition_zm Lexeme_Definition + | /*empty*/ + ; + +Lexer_Definition_zm : + Lexer_Definition + | Lexer_Definition_zm Lexer_Definition + | /*empty*/ + ; + +Lexeme_Definition : + identifier Assign_sym LX_rhs + | replace identifier '=' LX_rhs + | identifier '=' identifier '.' identifier + ; + +Assign_sym : + '=' + | "|=" + ; + +LX_rhs : + regex + | string + | character + ; + +// +// Defining grammars +// + +Grammar_Definition : + grammar '{' Nonterminal_Definition_zm '}' + ; + +Nonterminal_Definition_zm : + Nonterminal_Definition + | Nonterminal_Definition_zm Nonterminal_Definition + | /*empty*/ + ; + +Nonterminal_Definition : + nonterminal Assign_sym Production OrProduction_zm + | replace nonterminal '=' Production OrProduction_zm + ; + +OrProduction_zm : + OrProduction + | OrProduction_zm OrProduction + | /*empty*/ + ; + +OrProduction : + '|' Production + ; + +// Top level is just a simple EBNF term, as the '|' operator creates a new production at this point +Production : + Simple_Ebnf_Item_zm + ; + +Ebnf_Item : + Simple_Ebnf_Item_zm + | Simple_Ebnf_Item_zm '|' Ebnf_Item + ; + +Simple_Ebnf_Item_zm : + Simple_Ebnf_Item + | Simple_Ebnf_Item_zm Simple_Ebnf_Item + | /*empty*/ + ; + +Simple_Ebnf_Item : + Nonterminal Semantic_Specification_zo + | Terminal Semantic_Specification_zo + | Guard Semantic_Specification_zo + | Simple_Ebnf_Item '*' Semantic_Specification_zo + | Simple_Ebnf_Item '+' Semantic_Specification_zo + | Simple_Ebnf_Item '?' Semantic_Specification_zo + | '(' Ebnf_Item ')' Semantic_Specification_zo + ; + +Guard : + "[=>" Ebnf_Item ']' + | "[=>" '[' can_clash ']' Ebnf_Item ']' + ; + +Nonterminal : + nonterminal + | identifier '.' nonterminal + ; + +Terminal : + Basic_Terminal + | identifier '.' Basic_Terminal + ; + +Basic_Terminal : + identifier + | string + | character + ; + +// +// Semantics +// + +Semantic_Specification_zo : + Semantic_Specification + | /*empty*/ + ; + +Semantic_Specification : + '[' Semantic_Item Comma_Semantic_Item_zm ']' + ; + +Comma_Semantic_Item_zm : + Comma_Semantic_Item + | Comma_Semantic_Item_zm Comma_Semantic_Item + | /*empty*/ + ; + +Comma_Semantic_Item : + ',' Semantic_Item + ; + +Semantic_Item : + identifier + | conflict '=' shift + | conflict '=' reduce + | conflict '=' weak reduce + ; + +// +// Defining precedence +// + +Precedence_Definition : + precedence '{' Precedence_Item_zm '}' + ; + +Precedence_Item_zm : + Precedence_Item + | Precedence_Item_zm Precedence_Item + | /*empty*/ + ; + +Precedence_Item : + left Equal_Precedence_Items + | right Equal_Precedence_Items + | non_associative Equal_Precedence_Items + | non_assoc Equal_Precedence_Items + ; + +Equal_Precedence_Items : + Simple_Ebnf_Item + | '{' Simple_Ebnf_Item_zm '}' + ; + +// +// The parser declaration block +// + +Parser_Block : + parser identifier ':' identifier '{' Parser_StartSymbol_zo '}' + ; + +Parser_StartSymbol_zo : + Parser_StartSymbol + | /*empty*/ + ; + +Parser_StartSymbol : + Nonterminal + ; + +// +// Test definition block +// + +Test_Block : + test identifier '{' Test_Definition_zm '}' + ; + +Test_Definition_zm : + Test_Definition + | Test_Definition_zm Test_Definition + | /*empty*/ + ; + +Test_Definition : + Nonterminal '=' Test_Specification_om + | Nonterminal "!=" Test_Specification_om + | Nonterminal from Test_Specification_om + ; + +Test_Specification_om : + Test_Specification + | Test_Specification_om Test_Specification + ; + +Test_Specification : + string + | identifier '(' string ')' + ; + + +//Tokens + +/// Symbols used by the lexer + +// Commonly used character sets +//letter : "[a-zA-Z_-]" ; // /({unicode-letter}|{unicode-punctuation-dash}|{unicode-punctuation-connector})/ +//digit : "[0-9]" ; // /{unicode-number}/ +//alphanumeric : letter | digit ; // /({letter}|{digit})/ +//whitespace = /{unicode-separator}|[\t]/ +//anycharacter = /[^\n\r]/ + +// Characters valid in regular expressions and strings +//first_re_char : "[^/\*]|(\\/)" ; +//regex_char : "[^/]|(\\/)" ; +//string_char : "[^\"]|(\\\")" ; + +// Identifiers, regular expressions +identifier : "[a-zA-Z_-][a-zA-Z_0-9-]*" ; +regex : "/([^/\*]|(\\/))([^/]|(\\/))*/" ; // /\/{first-re-char}{regex-char}*\// + +/// Lexical symbols +//identifier = /{identifier}/ +nonterminal : "<[a-zA-Z_-][a-zA-Z_0-9-]*>" ; // /\<{identifier}\>/ +//regex = /{regex}/ +string : "\"([^\"]|(\\\"))*\"" ; // /"{string-char}*"/ +character : "'(.|\\.)'" ; // /'(.|\\.)'/ + +/// Ignored symbols +//newline = /[\n\r]+/ +//whitespace = /{whitespace}+/ +//comment = /\/\/({anycharacter}*)/ +//c-comment = /\/\*([^*]|\*[^\/])*\*\// + +/// Keywords +/// (We use very few keywords, to extend the range of identifiers available) + +/// Weak keywords +/// Declared here to suppress warnings +language : 'language' ; +import : 'import' ; +lexer_symbols : 'lexer-symbols' ; +lexer : 'lexer' ; +ignore : 'ignore' ; +weak : 'weak' ; +keywords : 'keywords' ; +grammar : 'grammar' ; +replace : 'replace' ; +parser : 'parser' ; +test : 'test' ; +from : 'from' ; +case : 'case' ; +sensitive : 'sensitive' ; +insensitive : 'insensitive' ; +precedence : 'precedence' ; + +left : 'left' ; +right : 'right' ; +non_associative : 'non-associative' ; +non_assoc : 'non-assoc' ; + +conflict : 'conflict' ; +shift : 'shift' ; +reduce : 'reduce' ; + +can_clash : 'can-clash' ; + +} \ No newline at end of file diff --git a/playground/test.adb b/playground/test.adb new file mode 100644 index 0000000..d1a53a1 --- /dev/null +++ b/playground/test.adb @@ -0,0 +1,125 @@ +-- $Header: /cf/ua/arcadia/alex-ayacc/ayacc/src/RCS/ayacc.a,v 1.1 88/08/08 12:07:07 arcadia Exp $ +--************************************************************************ +-- ayacc +-- version 1.1 +-- +--*********************************************************************** +-- +-- Arcadia Project +-- Department of Information and Computer Science +-- University of California +-- Irvine, California 92717 +-- +-- Copyright (c) 1990 Regents of the University of California. +-- All rights reserved. +-- +-- The primary authors of ayacc were David Taback and Deepak Tolani. +-- Enhancements were made by Ronald J. Schmalz. +-- Further enhancements were made by Yidong Chen. +-- +-- Send requests for ayacc information to ayacc-info@ics.uci.edu +-- Send bug reports for ayacc to ayacc-bugs@ics.uci.edu +-- +-- Redistribution and use in source and binary forms are permitted +-- provided that the above copyright notice and this paragraph are +-- duplicated in all such forms and that any documentation, +-- advertising materials, and other materials related to such +-- distribution and use acknowledge that the software was developed +-- by the University of California, Irvine. The name of the +-- University may not be used to endorse or promote products derived +-- from this software without specific prior written permission. +-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +-- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +-- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +-- Module : ayacc.ada +-- Component of : ayacc +-- Version : 1.2 +-- Date : 11/21/86 12:28:24 +-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxayacc.ada + +-- $Header: /cf/ua/arcadia/alex-ayacc/ayacc/src/RCS/ayacc.a,v 1.1 88/08/08 12:07:07 arcadia Exp $ +-- $Log: ayacc.a,v $ +--Revision 1.1 88/08/08 12:07:07 arcadia +--Initial revision +-- +-- Revision 0.1 86/04/01 15:04:07 ada +-- This version fixes some minor bugs with empty grammars +-- and $$ expansion. It also uses vads5.1b enhancements +-- such as pragma inline. +-- +-- +-- Revision 0.0 86/02/19 19:00:49 ada +-- +-- These files comprise the initial version of Ayacc +-- designed and implemented by David Taback and Deepak Tolani. +-- Ayacc has been compiled and tested under the Verdix Ada compiler +-- version 4.06 on a vax 11/750 running Unix 4.2BSD. +-- + +with Source_File, Ayacc_File_Names, Options, Parser, Parse_Template_File, Tokens_File, Output_File, Parse_Table, Text_Io, +-- u_env, -- For getting the command line arguments + +Symbol_Table, -- Used for statistics only +Rule_Table; -- Used for statistics only + +-- UMASS CODES : +with Error_Report_File; +-- END OF UMASS CODES. + +procedure Ayacc is + + -- Rcs_ID : constant String := "$Header: /cf/ua/arcadia/alex-ayacc/ayacc/src/RCS/ayacc.a,v 1.1 88/08/08 12:07:07 arcadia Exp $"; + + use Text_Io; + procedure Print_Statistics is separate; + +begin + + Options.Get_Arguments; + Parse_Template_File.Cleanup; + + Source_File.Open; + + Parser.Parse_Declarations; + Parser.Parse_Rules; + Parse_Table.Make_Parse_Table; + Output_File.Make_Output_File; + Tokens_File.Complete_Tokens_Package; + +-- UMASS CODES : +-- Generate the error report file if the codes +-- of error recovery extension should be generated. + if Options.Error_Recovery_Extension then + Error_Report_File.Write_File; + end if; +-- END OF UMASS CODES. + + Source_File.Close; + Tokens_File.Close; + + if Options.Interface_To_C then + Tokens_File.Make_C_Lex_Package; + end if; + + Print_Statistics; + Parse_Template_File.Cleanup; + +exception + + when Ayacc_File_Names.Illegal_File_Name => + Put_Line ("Ayacc: Illegal Filename."); + + when Options.Illegal_Option => + null; + + when Parser.Syntax_Error => -- Error has already been reported. + Source_File.Close; + Parse_Template_File.Cleanup; + + when Text_Io.Name_Error | Text_Io.Use_Error => + null; -- Error has already been reported. + + when others => + Put_Line ("Ayacc: Internal Error, Please Submit an LCR."); +end Ayacc; \ No newline at end of file diff --git a/playground/test.bc b/playground/test.bc new file mode 100644 index 0000000..0d840cf --- /dev/null +++ b/playground/test.bc @@ -0,0 +1,53 @@ +/* + This is a program to determine the distribution of digits in the + fraction part of PI. It will look at the first scale digits. + + The results are left in the global variable digits. + digits[0] is the number of 0's in PI. + + This program requires the math library. +*/ + +define pi () { + auto ix, pi, save_scale, work; + + save_scale = scale; + scale += 5; + print "\n\nCalculating PI to ",scale," digits. Please wait . . ."; + pi = 4*a(1); + scale -= 5; + work = pi; + + print "\nCounting digits. . ."; + for (ix = 0; ix < 10; ix++) digits[ix] = 0; + + /* Extract the One's digit from pi. */ + scale = 0; + one_digit = work / 1; + + for (ix = save_scale; ix > 0; ix--) { + + /* Remove the One's digit and multiply by 10. */ + scale = ix; + work = (work - one_digit) / 1 * 10; + + /* Extract the One's digit. */ + scale = 0; + one_digit = work / 1; + + digits[one_digit] += 1; + } + + /* Restore the scale. */ + scale = save_scale; + + /* Report. */ + print "\n\n" + print "PI to ", scale, " digits is:\n", pi/1, "\n\n" + print "The frequency of the digits are:\n" + for (ix = 0; ix < 10; ix++) { + print " ", ix, " - ", digits[ix], " times\n" + } + + print "\n\n" +} diff --git a/playground/test.c b/playground/test.c new file mode 100644 index 0000000..b3161a8 --- /dev/null +++ b/playground/test.c @@ -0,0 +1,112 @@ +int yywrap() +{ + return(1); +} + + +void comment() +{ + char c, c1; + +loop: + while ((c = input()) != '*' && c != 0) + putchar(c); + + if ((c1 = input()) != '/' && c != 0) + { + unput(c1); + goto loop; + } + + if (c != 0) + putchar(c1); +} + +int column = 0; + +void count() +{ + int i; + + for (i = 0; yytext[i] != '\0'; i++) + if (yytext[i] == '\n') + column = 0; + else if (yytext[i] == '\t') + column += 8 - (column % 8); + else + column++; + + ECHO; +} + +extern char yytext[]; +extern int column; +int yyparse(void); +int yylex (void); +void yyerror(const char *s) +{ + fflush(stdout); + printf("\n%*s\n%*s\n", column, "^", column, s); +} + +typedef int YYINT; +static const int yylhs[] = { -1, + 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 8, 8, 10, 10, + 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, + 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 5, 5, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 2, 2, 22, 23, 23, 24, 24, 24, 24, + 24, 24, 25, 25, 29, 29, 26, 26, 26, 26, + 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 32, 32, 32, 34, 34, 35, 35, + 36, 37, 37, 37, 37, 38, 38, 39, 39, 39, + 33, 33, 33, 40, 40, 41, 41, 28, 28, 30, + 30, 43, 43, 43, 43, 43, 43, 43, 42, 42, + 42, 42, 46, 46, 44, 44, 47, 47, 48, 48, + 48, 45, 45, 9, 9, 49, 49, 49, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 31, 31, 31, + 51, 51, 52, 52, 53, 53, 53, 54, 54, 54, + 56, 56, 56, 56, 55, 55, 55, 60, 60, 60, + 61, 61, 61, 62, 57, 57, 57, 57, 64, 64, + 63, 63, 58, 58, 59, 59, 59, 59, 59, 0, + 0, 65, 65, 66, 66, 66, 66, +}; + +static const char *const yyname[] = { + +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +"'!'",0,0,0,"'%'","'&'",0,"'('","')'","'*'","'+'","','","'-'","'.'","'/'",0,0,0, +0,0,0,0,0,0,0,"':'","';'","'<'","'='","'>'","'?'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,"'['",0,"']'","'^'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,"'{'","'|'","'}'","'~'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"IDENTIFIER", +"CONSTANT","STRING_LITERAL","SIZEOF","PTR_OP","INC_OP","DEC_OP","LEFT_OP", +"RIGHT_OP","LE_OP","GE_OP","EQ_OP","NE_OP","AND_OP","OR_OP","MUL_ASSIGN", +"DIV_ASSIGN","MOD_ASSIGN","ADD_ASSIGN","SUB_ASSIGN","LEFT_ASSIGN", +"RIGHT_ASSIGN","AND_ASSIGN","XOR_ASSIGN","OR_ASSIGN","TYPE_NAME","TYPEDEF", +"EXTERN","STATIC","AUTO","REGISTER","CHAR","SHORT","INT","LONG","SIGNED", +"UNSIGNED","FLOAT","DOUBLE","CONST","VOLATILE","VOID","STRUCT","UNION","ENUM", +"ELLIPSIS","CASE","DEFAULT","IF","ELSE","SWITCH","WHILE","DO","FOR","GOTO", +"CONTINUE","BREAK","RETURN",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,"illegal-symbol", +}; + +typedef struct { + unsigned stacksize; + int *s_base; + int *s_mark; + int *s_last; + int *l_base; + int *l_mark; +} YYSTACKDATA; + +void main() +{ + yyparse(); +} diff --git a/playground/test.clingo b/playground/test.clingo new file mode 100644 index 0000000..780eef8 --- /dev/null +++ b/playground/test.clingo @@ -0,0 +1,35 @@ +#program base. +dir(-1,0;1,0;0,-1;0,1). + +stop( DX, DY,X, Y ) :- barrier(X,Y,DX,DY). +stop(-DX,-DY,X+DX,Y+DY) :- stop(DX,DY,X,Y). + +#external target(R,X,Y) : available_target(R,M,X,Y). +#external pos(R,X,Y,0) : dim(X), dim(Y), robot(R). + +#program trans(t). + +1 { move(R,DX,DY,t) : robot(R), dir(DX,DY) } 1. + +halt(DX,DY,X-DX,Y-DY,t) :- pos(_,X,Y,t-1), dir(DX,DY), dim(X-DX), dim(Y-DY), not stop(-DX,-DY,X,Y). + +goto(R,DX,DY,X,Y,t) :- pos(R,X,Y,t-1), dir(DX,DY). +goto(R,DX,DY,X+DX,Y+DY,t) :- goto(R,DX,DY,X,Y,t), dim(X+DX), dim(Y+DY), not stop(DX,DY,X,Y), not halt(DX,DY,X,Y,t). + +pos(R,X,Y,t) :- move(R,DX,DY,t), goto(R,DX,DY,X,Y,t), not goto(R,DX,DY,X+DX,Y+DY,t). +pos(R,X,Y,t) :- pos(R,X,Y,t-1), not move(R,_,_,t). + +:- move(R,DX,DY,t-1), not goon(t-1), not move(R,DX,DY,t). + +#program state(t). + +goon(t) :- target(R,X,Y), not pos(R,X,Y,t). +#minimize{ 1,t : goon(t) }. + +#program check(t). + +#external horizon(t). + +:- goon(t), horizon(t). + +#show move/4. diff --git a/playground/test.cpp b/playground/test.cpp new file mode 100644 index 0000000..e598db9 --- /dev/null +++ b/playground/test.cpp @@ -0,0 +1,209 @@ +/* + * Tiny self-contained version of the PCG Random Number Generation for C++ + * put together from pieces of the much larger C/C++ codebase. + * Wenzel Jakob, February 2015 + * + * The PCG random number generator was developed by Melissa O'Neill + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * For additional information about the PCG random number generation scheme, + * including its license and other licensing options, visit + * + * http://www.pcg-random.org + */ + +//#ifndef __PCG32_H +//#define __PCG32_H 1 + +//#define PCG32_DEFAULT_STATE 0x853c49e6748fea9bULL +//#define PCG32_DEFAULT_STREAM 0xda3e39cb94b95bdbULL +//#define PCG32_MULT 0x5851f42d4c957f2dULL + +//#include +//#include +//#include +//#include + +/// PCG32 Pseudorandom number generator +struct pcg32 { + /// Initialize the pseudorandom number generator with default seed + pcg32() : state(PCG32_DEFAULT_STATE), inc(PCG32_DEFAULT_STREAM) {} + + /// Initialize the pseudorandom number generator with the \ref seed() function + pcg32(uint64_t initstate, uint64_t initseq = 1u) { seed(initstate, initseq); } + + /** + * \brief Seed the pseudorandom number generator + * + * Specified in two parts: a state initializer and a sequence selection + * constant (a.k.a. stream id) + */ + void seed(uint64_t initstate, uint64_t initseq = 1) { + state = 0U; + inc = (initseq << 1u) | 1u; + nextUInt(); + state += initstate; + nextUInt(); + } + + /// Generate a uniformly distributed unsigned 32-bit random number + uint32_t nextUInt() { + uint64_t oldstate = state; + state = oldstate * PCG32_MULT + inc; + uint32_t xorshifted = (uint32_t) (((oldstate >> 18u) ^ oldstate) >> 27u); + uint32_t rot = (uint32_t) (oldstate >> 59u); + return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31)); + } + + /// Generate a uniformly distributed number, r, where 0 <= r < bound + uint32_t nextUInt(uint32_t bound) { + // To avoid bias, we need to make the range of the RNG a multiple of + // bound, which we do by dropping output less than a threshold. + // A naive scheme to calculate the threshold would be to do + // + // uint32_t threshold = 0x100000000ull % bound; + // + // but 64-bit div/mod is slower than 32-bit div/mod (especially on + // 32-bit platforms). In essence, we do + // + // uint32_t threshold = (0x100000000ull-bound) % bound; + // + // because this version will calculate the same modulus, but the LHS + // value is less than 2^32. + + uint32_t threshold = (~bound+1u) % bound; + + // Uniformity guarantees that this loop will terminate. In practice, it + // should usually terminate quickly; on average (assuming all bounds are + // equally likely), 82.25% of the time, we can expect it to require just + // one iteration. In the worst case, someone passes a bound of 2^31 + 1 + // (i.e., 2147483649), which invalidates almost 50% of the range. In + // practice, bounds are typically small and only a tiny amount of the range + // is eliminated. + for (;;) { + uint32_t r = nextUInt(); + if (r >= threshold) + return r % bound; + } + } + + /// Generate a single precision floating point value on the interval [0, 1) + float nextFloat() { + /* Trick from MTGP: generate an uniformly distributed + single precision number in [1,2) and subtract 1. */ + union { + uint32_t u; + float f; + } x; + x.u = (nextUInt() >> 9) | 0x3f800000u; + return x.f - 1.0f; + } + + /** + * \brief Generate a double precision floating point value on the interval [0, 1) + * + * \remark Since the underlying random number generator produces 32 bit output, + * only the first 32 mantissa bits will be filled (however, the resolution is still + * finer than in \ref nextFloat(), which only uses 23 mantissa bits) + */ + double nextDouble() { + /* Trick from MTGP: generate an uniformly distributed + double precision number in [1,2) and subtract 1. */ + union { + uint64_t u; + double d; + } x; + x.u = ((uint64_t) nextUInt() << 20) | 0x3ff0000000000000ULL; + return x.d - 1.0; + } + + /** + * \brief Multi-step advance function (jump-ahead, jump-back) + * + * The method used here is based on Brown, "Random Number Generation + * with Arbitrary Stride", Transactions of the American Nuclear + * Society (Nov. 1994). The algorithm is very similar to fast + * exponentiation. + */ + void advance(int64_t delta_) { + uint64_t + cur_mult = PCG32_MULT, + cur_plus = inc, + acc_mult = 1u, + acc_plus = 0u; + + /* Even though delta is an unsigned integer, we can pass a signed + integer to go backwards, it just goes "the long way round". */ + uint64_t delta = (uint64_t) delta_; + + while (delta > 0) { + if (delta & 1) { + acc_mult *= cur_mult; + acc_plus = acc_plus * cur_mult + cur_plus; + } + cur_plus = (cur_mult + 1) * cur_plus; + cur_mult *= cur_mult; + delta /= 2; + } + state = acc_mult * state + acc_plus; + } + + /** + * \brief Draw uniformly distributed permutation and permute the + * given STL container + * + * From: Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2 + */ + template void shuffle(Iterator begin, Iterator end) { + for (Iterator it = end - 1; it > begin; --it) + std::iter_swap(it, begin + nextUInt((uint32_t) (it - begin + 1))); + } + + /// Compute the distance between two PCG32 pseudorandom number generators + int64_t operator-(const pcg32 &other) const { + assert(inc == other.inc); + + uint64_t + cur_mult = PCG32_MULT, + cur_plus = inc, + cur_state = other.state, + the_bit = 1u, + distance = 0u; + + while (state != cur_state) { + if ((state & the_bit) != (cur_state & the_bit)) { + cur_state = cur_state * cur_mult + cur_plus; + distance |= the_bit; + } + assert((state & the_bit) == (cur_state & the_bit)); + the_bit <<= 1; + cur_plus = (cur_mult + 1ULL) * cur_plus; + cur_mult *= cur_mult; + } + + return (int64_t) distance; + } + + /// Equality operator + bool operator==(const pcg32 &other) const { return state == other.state && inc == other.inc; } + + /// Inequality operator + bool operator!=(const pcg32 &other) const { return state != other.state || inc != other.inc; } + + uint64_t state; // RNG state. All values are possible. + uint64_t inc; // Controls which RNG sequence (stream) is selected. Must *always* be odd. +}; + +//#endif // __PCG32_H diff --git a/playground/test.cql b/playground/test.cql new file mode 100644 index 0000000..bcc404a --- /dev/null +++ b/playground/test.cql @@ -0,0 +1,2558 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +-- basic test table with an auto inc field +create table foo( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL +); + +-- second test table with combination of fields +@attribute(bar_is_good=1) +create table bar( + id INTEGER NOT NULL PRIMARY KEY, + @attribute(collossal_cave='xyzzy') + name TEXT, + rate LONG INT, + type INTEGER, + size REAL @create(2) +); + +-- test view that reads from the test tables +create view baz as select id, name, type from bar; + +-- declare variables of the basic types +declare i0_nullable int; +declare i1_nullable int; +declare r0_nullable real; +declare l0_nullable long integer; +declare l1_nullable long integer; +declare b0_nullable bool; +declare t0_nullable text; + +-- same types but not null variant +declare i2 int not null; +declare r2 real not null; +declare l2 long integer not null; +declare b2 bool not null; +declare t2 text not null; + +-- TEST: assign eveything not null +-- Note: semantic analysis verifies no chance of +-- assigning nullable to not nullable +-- + i2 = 1; +set i2 := 1; + +-- TEST: assign rhs not null +-- + cql_set_notnull(i1_nullable, 88); +set i1_nullable := 88; + +-- TEST: assign everything nullable +-- + cql_set_nullable(i0_nullable, i1_nullable.is_null, i1_nullable.value); +set i0_nullable := i1_nullable; + +-- TEST: assign NULL to nullable string +-- + cql_set_string_ref(&t0_nullable, NULL); +set t0_nullable := null; + +-- + cql_set_string_ref(&t0_nullable, t2); +set t0_nullable := t2; + +-- TEST: simple unary operators +-- + i2 = - - 1; +set i2 := - -1; + +-- + cql_set_notnull(i0_nullable, - i2); +set i0_nullable := -i2; + +-- + cql_set_null(i0_nullable); +set i0_nullable := -null; + +-- + cql_set_nullable(i1_nullable, i0_nullable.is_null, - i0_nullable.value); +set i1_nullable := -i0_nullable; + +-- + cql_set_notnull(r0_nullable, 2.2%); +set r0_nullable := 2.2; + +-- + r2 = 3.5%; +set r2 := 3.5; + +-- + cql_set_nullable(_tmp_n_bool_1, i0_nullable.is_null, ! i0_nullable.value); +-- + cql_set_nullable(_tmp_n_bool_0, _tmp_n_bool_1.is_null, ! _tmp_n_bool_1.value); +-- + cql_set_nullable(i1_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i1_nullable := NOT NOT i0_nullable; + +-- + i2 = ! ! b2; +set i2 := NOT NOT b2; + +-- TEST: not null arithmetic +-- + i2 = 1 * 3 + 5; +set i2 := 1 * 3 + 5; + +-- TEST: everything in sight is nullable +-- + cql_combine_nullables(_tmp_n_double_0, r0_nullable.is_null, i1_nullable.is_null, r0_nullable.value * i1_nullable.value); +-- + cql_set_nullable(i0_nullable, _tmp_n_double_0.is_null, _tmp_n_double_0.value); +set i0_nullable := r0_nullable * i1_nullable; + +-- TEST: right operand is not null +-- + cql_set_nullable(_tmp_n_double_0, r0_nullable.is_null, r0_nullable.value * i2); +-- + cql_set_nullable(i0_nullable, _tmp_n_double_0.is_null, _tmp_n_double_0.value); +set i0_nullable := r0_nullable * i2; + +-- TEST: left operand is not null +-- + cql_set_nullable(i0_nullable, i1_nullable.is_null, 12 * i1_nullable.value); +set i0_nullable := 12 * i1_nullable; + +-- TEST: an operaand is actually null +-- + cql_set_null(i0_nullable); +set i0_nullable := null * i1_nullable; + +-- TEST: make sure the stacking is working correctly +-- + cql_combine_nullables(_tmp_n_double_1, %, r0_nullable.value * i1_nullable.value); +-- + cql_combine_nullables(_tmp_n_double_2, %, r0_nullable.value * i1_nullable.value); +-- + cql_combine_nullables(_tmp_n_double_0, %, _tmp_n_double_1.value + _tmp_n_double_2.value); +-- + cql_set_nullable(i0_nullable, _tmp_n_double_0.is_null, _tmp_n_double_0.value); +set i0_nullable := r0_nullable * i1_nullable + r0_nullable * i1_nullable; + +-- TEST: a more complex stacking example +-- + cql_combine_nullables(_tmp_n_double_2, %, r0_nullable.value * i1_nullable.value); +-- + cql_combine_nullables(_tmp_n_double_3, %, r0_nullable.value * i0_nullable.value); +-- + cql_combine_nullables(_tmp_n_double_1, %, _tmp_n_double_2.value + _tmp_n_double_3.value); +-- + cql_combine_nullables(_tmp_n_double_0, %, _tmp_n_double_1.value + r0_nullable.value); +-- + cql_set_nullable(i0_nullable, _tmp_n_double_0.is_null, _tmp_n_double_0.value); +set i0_nullable := (r0_nullable * i1_nullable + r0_nullable * i0_nullable) + r0_nullable; + +-- TEST: string assignment -- nasty string +-- + cql_set_string_ref(&t2, _literal%This_is_a_test_); +set t2 := "This is a \" \\ test '' \n \" "; + +-- TEST: call an external procedure (type not known) +-- + printf("Hello, world\n"); +call printf("Hello, world\n"); + +-- TEST: logical AND with short circuit +-- + i2 = r2 && l2; +set i2 := r2 and l2; + +-- helper methods for the next test +declare function side_effect1() integer; +declare function side_effect2() integer; + +-- TEST: the operands have side effects, the short circuit must not +-- do the evaluation of the side effect for the second arg if the first +-- returns false. This is the trickiest case because ti looks like it's +-- safe to use the (x && y) form because the operands are non-null. +-- it isn't though because there was expression work to get to the non-null +-- state. The Coalesce is important to this test for that reason. +-- + do { +-- + _tmp_n_int_3 = side_effect1(); +-- + if (!_tmp_n_int_3.is_null) { +-- + _tmp_int_2 = _tmp_n_int_3.value; +-- + break; +-- + } +-- + _tmp_int_2 = 7; +-- + } while (0); +-- + if (!(_tmp_int_2)) { +-- + _tmp_bool_0 = 0; +-- + } +-- + else { +-- + _tmp_n_int_2 = side_effect2(); +-- + if (!_tmp_n_int_2.is_null) { +-- + _tmp_int_1 = _tmp_n_int_2.value; +-- + break; +-- + } +-- + _tmp_int_1 = 5; +-- + } while (0); +-- + _tmp_bool_0 = !!(_tmp_int_1); +-- + } +-- + i2 = _tmp_bool_0; +set i2 := coalesce(side_effect1(), 7) and coalesce(side_effect2(), 5); + +-- TEST: trival NULL on AND +-- + cql_set_null(_tmp_n_bool_0); +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := NULL and NULL; + +-- TEST: logical AND with nullables +-- + if (cql_is_nullable_false(i0_nullable.is_null, i0_nullable.value)) +-- + if (cql_is_nullable_false(i1_nullable.is_null, i1_nullable.value)) +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i0_nullable and i1_nullable; + +-- TEST: logical AND with constant nulls +-- + if (cql_is_nullable_false(i1_nullable.is_null, i1_nullable.value)) +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := NULL and i1_nullable; + +-- TEST: logical AND with constant nulls +-- + if (cql_is_nullable_false(i0_nullable.is_null, i0_nullable.value)) +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i0_nullable and NULL; + +-- TEST: logical OR with short circuit +-- + i2 = r2 || l2; +set i2 := r2 or l2; + +-- TEST: complex side effect, looks safe but it isn't because of codegen +-- + do { +-- + _tmp_n_int_3 = side_effect1(); +-- + if (!_tmp_n_int_3.is_null) { +-- + _tmp_int_2 = _tmp_n_int_3.value; +-- + break; +-- + } +-- + _tmp_int_2 = 7; +-- + } while (0); +-- + if (_tmp_int_2) { +-- + _tmp_bool_0 = 1; +-- + } +-- + else { +-- + do { +-- + _tmp_n_int_2 = side_effect2(); +-- + if (!_tmp_n_int_2.is_null) { +-- + _tmp_int_1 = _tmp_n_int_2.value; +-- + break; +-- + } +-- + _tmp_int_1 = 5; +-- + } while (0); +-- + _tmp_bool_0 = !!(_tmp_int_1); +-- + } +-- + i2 = _tmp_bool_0; +set i2 := coalesce(side_effect1(), 7) or coalesce(side_effect2(), 5); + +-- TEST: trival NULL on OR +-- + cql_set_null(_tmp_n_bool_0); +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := NULL or NULL; + +-- TEST: logical OR with nullables +-- + cql_is_nullable_true(i0_nullable.is_null, i0_nullable.value) +-- + cql_is_nullable_true(i1_nullable.is_null, i1_nullable.value) +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i0_nullable or i1_nullable; + +-- TEST: logical OR with constant nulls +-- + cql_is_nullable_true(i1_nullable.is_null, i1_nullable.value) +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := NULL or i1_nullable; + +-- TEST: logical OR with constant nulls +-- + cql_is_nullable_true(i0_nullable.is_null, i0_nullable.value) +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i0_nullable or NULL; + +-- TEST: is null basic test +-- + i2 = 1; +set i2 := null is null; + +-- TEST: is null test non-null subexpression +-- + i2 = 0; +set i2 := (1+2*3) is null; + +-- TEST: is null test general case +-- + cql_combine_nullables(_tmp_n_int_0, i0_nullable.is_null, i1_nullable.is_null, i0_nullable.value + i1_nullable.value); +-- + i2 = _tmp_n_int_0.is_null; +set i2 := (i0_nullable + i1_nullable) is null; + +-- TEST: is not null basic test +-- + i2 = !1; +set i2 := null is not null; + +-- TEST: is not null test non-null subexpression +-- + i2 = 1; +set i2 := (1+2*3) is not null; + +-- TEST: is not null test general case +-- + cql_combine_nullables(_tmp_n_int_0, i0_nullable.is_null, i1_nullable.is_null, i0_nullable.value + i1_nullable.value); +-- + i2 = !_tmp_n_int_0.is_null; +set i2 := (i0_nullable + i1_nullable) is not null; + +-- TEST: complex if/else pattern +-- Note: of interest because the embedded nullable +-- comparison requires statements to compute +-- + if (1) { +-- + i2 = 1; +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_0, i0_nullable.is_null, i1_nullable.is_null, i0_nullable.value == i1_nullable.value); +-- + if (cql_is_nullable_true(_tmp_n_bool_0.is_null, _tmp_n_bool_0.value)) { +-- + i2 = 2; +-- + } +-- + else { +-- + i2 = 3; +-- + } +-- + } +-- +4 { +-- +4 } +-- +2 else { +if 1 then + set i2 := 1; +else if i0_nullable == i1_nullable then + set i2 := 2; +else + set i2 := 3; +end if; + +-- TEST: complex if/else pattern, embedded logical operation +-- Note: of interest because the embedded logical requires +-- statements to compute +-- validating the bits are are unique to this construct +-- + if (cql_is_nullable_true(i0_nullable.is_null, i0_nullable.value)) { +-- + if (cql_is_nullable_true(i1_nullable.is_null, i1_nullable.value)) { +-- + if (cql_is_nullable_true(_tmp_n_bool_0.is_null, _tmp_n_bool_0.value)) { +if 1 then + set i2 := 1; +else if i0_nullable or i1_nullable then + set i2 := 2; +else + set i2 := 3; +end if; + +-- TEST: simple procedure with external call +-- + void test(cql_int32 i) { +-- + if (i) { +-- + puts("true"); +create procedure test(i integer not null) +begin + if i then + call puts('true'); + end if; +end; + +-- TEST: simple between +-- + SET b2 := BETWEEN REWRITE _between_0_ := 1 CHECK (_between_0_ >= 0 AND _between_0_ <= 3); +-- + _between_0_ = 1; +-- + b2 = _between_0_ >= 0 && _between_0_ <= 3; +set b2 := 1 between 0 and 3; + +-- TEST: between with some nullables +-- + SET i0_nullable := BETWEEN REWRITE _between_1_ := i1_nullable CHECK (_between_1_ >= i0_nullable AND _between_1_ <= r2); +-- + cql_set_nullable(_between_1_, i1_nullable.is_null, i1_nullable.value); +-- + cql_combine_nullables(_tmp_n_bool_2, _between_1_.is_null, i0_nullable.is_null, _between_1_.value >= i0_nullable.value); +-- + if (cql_is_nullable_false(_tmp_n_bool_2.is_null, _tmp_n_bool_2.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + cql_set_nullable(_tmp_n_bool_1, _between_1_.is_null, _between_1_.value <= r2); +-- + if (cql_is_nullable_false(_tmp_n_bool_1.is_null, _tmp_n_bool_1.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_0, _tmp_n_bool_2.is_null, _tmp_n_bool_1.is_null, 1); +-- + } +-- + } +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i1_nullable between i0_nullable and r2; + +-- TEST: between with different nullables +-- + SET i0_nullable := BETWEEN REWRITE _between_2_ := i1_nullable CHECK (_between_2_ >= r2 AND _between_2_ <= i0_nullable); +-- + cql_set_nullable(_between_2_, i1_nullable.is_null, i1_nullable.value); +-- + cql_set_nullable(_tmp_n_bool_2, _between_2_.is_null, _between_2_.value >= r2); +-- + if (cql_is_nullable_false(_tmp_n_bool_2.is_null, _tmp_n_bool_2.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_1, _between_2_.is_null, i0_nullable.is_null, _between_2_.value <= i0_nullable.value); +-- + if (cql_is_nullable_false(_tmp_n_bool_1.is_null, _tmp_n_bool_1.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_0, _tmp_n_bool_2.is_null, _tmp_n_bool_1.is_null, 1); +-- + } +-- + } +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i1_nullable between r2 and i0_nullable; + +-- TEST: simple not between +-- + SET b2 := BETWEEN REWRITE _between_3_ := 1 CHECK (_between_3_ < 0 OR _between_3_ > 3); +-- + _between_3_ = 1; +-- + b2 = _between_3_ < 0 || _between_3_ > 3; +set b2 := 1 not between 0 and 3; + +-- TEST: not between with some nullables +-- + SET i0_nullable := BETWEEN REWRITE _between_4_ := i1_nullable CHECK (_between_4_ < i0_nullable OR _between_4_ > r2); +-- + cql_set_nullable(_between_4_, i1_nullable.is_null, i1_nullable.value); +-- + cql_combine_nullables(_tmp_n_bool_2, _between_4_.is_null, i0_nullable.is_null, _between_4_.value < i0_nullable.value); +-- + if (cql_is_nullable_true(_tmp_n_bool_2.is_null, _tmp_n_bool_2.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + cql_set_nullable(_tmp_n_bool_1, _between_4_.is_null, _between_4_.value > r2); +-- + if (cql_is_nullable_true(_tmp_n_bool_1.is_null, _tmp_n_bool_1.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_0, _tmp_n_bool_2.is_null, _tmp_n_bool_1.is_null, 0); +-- + } +-- + } +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i1_nullable not between i0_nullable and r2; + +-- TEST: not between with different nullables +-- + SET i0_nullable := BETWEEN REWRITE _between_5_ := i1_nullable CHECK (_between_5_ < r2 OR _between_5_ > i0_nullable); +-- + cql_set_nullable(_between_5_, i1_nullable.is_null, i1_nullable.value); +-- + cql_set_nullable(_tmp_n_bool_2, _between_5_.is_null, _between_5_.value < r2); +-- + if (cql_is_nullable_true(_tmp_n_bool_2.is_null, _tmp_n_bool_2.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_1, _between_5_.is_null, i0_nullable.is_null, _between_5_.value > i0_nullable.value); +-- + if (cql_is_nullable_true(_tmp_n_bool_1.is_null, _tmp_n_bool_1.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_0, _tmp_n_bool_2.is_null, _tmp_n_bool_1.is_null, 0); +-- + } +-- + } +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i1_nullable not between r2 and i0_nullable; + +-- TEST: out parameter test +-- + void out_test(cql_int32 *_Nonnull i, cql_nullable_int32 *_Nonnull ii) { +-- + *i = i2; +-- + cql_set_nullable(*ii, i0_nullable.is_null, i0_nullable.value); +-- + } +create procedure out_test(out i integer not null, out ii integer) +begin + set i := i2; + set ii := i0_nullable; +end; + +-- TEST: force a cql_int64 variable to be pushed on the scratch stack +-- + cql_nullable_int64 longint_var; +declare longint_var long integer; + +-- + cql_combine_nullables(_tmp_n_int64_1, l0_nullable.is_null, l1_nullable.is_null, l0_nullable.value + l1_nullable.value); +-- + cql_set_nullable(longint_var, _tmp_n_int64_1.is_null, _tmp_n_int64_1.value * 5); +set longint_var := (l0_nullable + l1_nullable) * 5; + +-- TEST: make a cursor +-- + _rc_ = cql_prepare(_db_, &foo_cursor, +-- + "SELECT id, ? " +-- + "FROM foo " +-- + "WHERE id = ?" +-- + cql_multibind(&_rc_, _db_, &foo_cursor, 2, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, i2, +-- + CQL_DATA_TYPE_INT32, &i0_nullable); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +declare foo_cursor cursor for select id, i2 from foo where id = i0_nullable; + +-- TEST: fetch a cursor +-- + _rc_ = sqlite3_step(foo_cursor); +-- + _rc_ = sqlite3_step(foo_cursor); +-- + _foo_cursor_has_row_ = _rc_ == SQLITE_ROW; +-- + cql_multifetch(_rc_, foo_cursor, 2, +-- + CQL_DATA_TYPE_INT32, &i0_nullable, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, &i2); +-- + if (_rc_ != SQLITE_ROW && _rc_ != SQLITE_DONE) goto cql_cleanup; +fetch foo_cursor into i0_nullable, i2; + +-- TEST: test elementary cursor on select with no tables, still round trips through sqlite +declare col1 integer; +declare col2 real not null; +-- + _rc_ = cql_prepare(_db_, &basic_cursor, +declare basic_cursor cursor for select 1, 2.5; +open basic_cursor; +-- + cql_multifetch(_rc_, basic_cursor, 2, +-- + CQL_DATA_TYPE_INT32, &col1, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_DOUBLE, &col2); +fetch basic_cursor into col1, col2; +-- + cql_finalize_stmt(_db_, &basic_cursor); +close basic_cursor; + +-- TEST: the most expensive way to swap two variables ever :) +declare arg1 integer not null; +declare arg2 integer not null; +set arg1 := 7; +set arg2 := 11; +-- + _rc_ = cql_prepare(_db_, &exchange_cursor, +-- + cql_multibind(&_rc_, _db_, &exchange_cursor, 2, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, arg2, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, arg1); +declare exchange_cursor cursor for select arg2, arg1; +open exchange_cursor; +-- + cql_multifetch(_rc_, exchange_cursor, 2, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, &arg1, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, &arg2); +fetch exchange_cursor into arg1, arg2; +-- + cql_finalize_stmt(_db_, &exchange_cursor); +close exchange_cursor; + +-- TEST: simple nested select +-- + _rc_ = cql_prepare(_db_, &_temp_stmt, +-- + "SELECT ? + 1" +-- + cql_multibind(&_rc_, _db_, &_temp_stmt, 1, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, i2); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +-- + _rc_ = sqlite3_step(_temp_stmt); +-- + if (_rc_ != SQLITE_ROW) goto cql_cleanup; +-- + i2 = sqlite3_column_int(_temp_stmt, 0); +-- + cql_finalize_stmt(_db_, &_temp_stmt); +set i2 := (select i2+1); + +-- TEST: nested select with nullable +-- validate just the different bit +-- + cql_multibind(&_rc_, _db_, &_temp_stmt, 1, +-- + CQL_DATA_TYPE_INT32, &i0_nullable); +set i0_nullable := (select i0_nullable+1); + +-- TEST: tricky quoted text +-- this validates that the C escaping works right when making SQL +-- + "DELETE FROM bar WHERE name LIKE '\\\\ \" \\n'" +delete from bar where name like '\\ " \n'; + +-- TEST: binding an out parameter +-- + cql_multibind(&_rc_, _db_, &_temp_stmt, 1, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, *foo); +create procedure outparm_test(out foo integer not null) +begin + set foo := 1; + delete from bar where id = foo; +end; + +-- TEST: a simple stored proc that throws +-- + if (_rc_ != SQLITE_OK) goto catch_start_1; +-- + goto catch_end_1; +-- + catch_start_1: { +-- + printf("error\n"); +-- + cql_best_error(&_rc_); +-- + goto cql_cleanup; +-- + catch_end_1: +-- + _rc_ = SQLITE_OK; +-- + cql_cleanup: +create procedure throwing() +begin + begin try + delete from bar; + end try; + begin catch + call printf("error\n"); + throw; + end catch; +end; + +-- TEST: a simple case expression +-- + do { +-- + if (1) { +-- + i2 = 100; +-- + break; +-- + } +-- + if (2) { +-- + i2 = 200; +-- + break; +-- + } +-- + i2 = 300; +-- + } while (0); +set i2 := case when 1 then 100 when 2 then 200 when null then 500 else 300 end; + +-- TEST: a simple in expression +-- + do { +-- + _tmp_int_% = 3; +-- + _tmp_bool_0 = 1; +-- + if (_tmp_int_% == 1) break; +-- + if (_tmp_int_% == 2) break; +-- + if (_tmp_int_% == 4) break; +-- + _tmp_bool_0 = 0; +-- + } while (0); +-- + i2 = _tmp_bool_0; +set i2 := 3 in (1, 2, null, 4); + +-- TEST: in with nullables +-- + do { +-- + cql_set_nullable(_tmp_n_int_%, i1_nullable.is_null, i1_nullable.value); +-- + if (_tmp_n_int_%.is_null) { +-- + cql_set_null(_tmp_n_bool_0); +-- + break; +-- + } +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + if (_tmp_n_int_%.value == 1) break; +-- + if (_tmp_n_int_%.value == 2) break; +-- + if (cql_is_nullable_true(b0_nullable.is_null, _tmp_n_int_%.value == b0_nullable.value)) break; +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } while (0); +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i1_nullable in (1, 2, null, b0_nullable); + +-- TEST: a simple not in expression +-- + do { +-- + _tmp_int_% = 3; +-- + _tmp_bool_0 = 0; +-- + if (_tmp_int_% == 1) break; +-- + if (_tmp_int_% == 2) break; +-- + if (_tmp_int_% == 4) break; +-- + _tmp_bool_0 = 1; +-- + } while (0); +-- + i2 = _tmp_bool_0; +set i2 := 3 not in (1, 2, null, 4); + +-- TEST: not in with nullables +-- + do { +-- + cql_set_nullable(_tmp_n_int_%, i1_nullable.is_null, i1_nullable.value); +-- + if (_tmp_n_int_%.is_null) { +-- + cql_set_null(_tmp_n_bool_0); +-- + break; +-- + } +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + if (_tmp_n_int_%.value == 1) break; +-- + if (_tmp_n_int_%.value == 2) break; +-- + if (cql_is_nullable_true(b0_nullable.is_null, _tmp_n_int_%.value == b0_nullable.value)) break; +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } while (0); +-- + cql_set_nullable(i0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set i0_nullable := i1_nullable not in (1, 2, null, b0_nullable); + +-- TEST: between with strings +-- + SET b2 := BETWEEN REWRITE _between_6_ := 'b' CHECK (_between_6_ >= 'a' AND _between_6_ <= 'c'); +-- + cql_set_string_ref(&_between_6_, _literal_2_b_); +-- + b2 = cql_string_compare(_between_6_, _literal_4_a_) >= 0 && cql_string_compare(_between_6_, _literal_3_c_) <= 0; +set b2 := 'b' between 'a' and 'c'; + +-- TEST: between with nullable strings right +-- + SET b0_nullable := BETWEEN REWRITE _between_7_ := 'b' CHECK (_between_7_ >= 'a' AND _between_7_ <= t0_nullable); +-- + cql_set_string_ref(&_between_7_, _literal_2_b_); +-- + if (!(cql_string_compare(_between_7_, _literal_4_a_) >= 0)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_1, !_between_7_, !t0_nullable, cql_string_compare(_between_7_, t0_nullable) <= 0); +-- + if (cql_is_nullable_false(_tmp_n_bool_1.is_null, _tmp_n_bool_1.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + cql_set_nullable(_tmp_n_bool_0, _tmp_n_bool_1.is_null, 1); +-- + } +-- + } +-- + cql_set_nullable(b0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set b0_nullable := 'b' between 'a' and t0_nullable; + +-- TEST: between with nullable strings left +-- + SET b0_nullable := BETWEEN REWRITE _between_8_ := 'b' CHECK (_between_8_ >= t0_nullable AND _between_8_ <= 'c'); +-- + cql_set_string_ref(&_between_8_, _literal_2_b_); +-- + cql_combine_nullables(_tmp_n_bool_2, !_between_8_, !t0_nullable, cql_string_compare(_between_8_, t0_nullable) >= 0); +-- + if (cql_is_nullable_false(_tmp_n_bool_2.is_null, _tmp_n_bool_2.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + if (!(cql_string_compare(_between_8_, _literal_3_c_) <= 0)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + cql_set_nullable(_tmp_n_bool_0, _tmp_n_bool_2.is_null, 1); +-- + } +-- + } +-- + cql_set_nullable(b0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set b0_nullable := 'b' between t0_nullable and 'c'; + +-- TEST: between with nullable strings null operand +-- + SET b0_nullable := BETWEEN REWRITE _between_9_ := 'b' CHECK (_between_9_ >= NULL AND _between_9_ <= 'c'); +-- + cql_set_string_ref(&_between_9_, _literal_2_b_); +-- + cql_set_null(_tmp_n_bool_2); +-- + if (cql_is_nullable_false(_tmp_n_bool_2.is_null, _tmp_n_bool_2.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + if (!(cql_string_compare(_between_9_, _literal_3_c_) <= 0)) { +-- + cql_set_notnull(_tmp_n_bool_0, 0); +-- + } +-- + else { +-- + cql_set_nullable(_tmp_n_bool_0, _tmp_n_bool_2.is_null, 1); +-- + } +-- + } +-- + cql_set_nullable(b0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set b0_nullable := 'b' between null and 'c'; + +-- TEST: not between with strings +-- + SET b2 := BETWEEN REWRITE _between_10_ := 'b' CHECK (_between_10_ < 'a' OR _between_10_ > 'c'); +-- + cql_set_string_ref(&_between_10_, _literal_2_b_); +-- + b2 = cql_string_compare(_between_10_, _literal_4_a_) < 0 || cql_string_compare(_between_10_, _literal_3_c_) > 0; +set b2 := 'b' not between 'a' and 'c'; + +-- TEST: not between with nullable strings right +-- + SET b0_nullable := BETWEEN REWRITE _between_11_ := 'b' CHECK (_between_11_ < 'a' OR _between_11_ > t0_nullable); +-- + cql_set_string_ref(&_between_11_, _literal_2_b_); +-- + if (cql_string_compare(_between_11_, _literal_4_a_) < 0) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + cql_combine_nullables(_tmp_n_bool_1, !_between_11_, !t0_nullable, cql_string_compare(_between_11_, t0_nullable) > 0); +-- + if (cql_is_nullable_true(_tmp_n_bool_1.is_null, _tmp_n_bool_1.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + cql_set_nullable(_tmp_n_bool_0, _tmp_n_bool_1.is_null, 0); +-- + } +-- + } +-- + cql_set_nullable(b0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set b0_nullable := 'b' not between 'a' and t0_nullable; + +-- TEST: not between with nullable strings left +-- + SET b0_nullable := BETWEEN REWRITE _between_12_ := 'b' CHECK (_between_12_ < t0_nullable OR _between_12_ > 'c'); +-- + cql_set_string_ref(&_between_12_, _literal_2_b_); +-- + cql_combine_nullables(_tmp_n_bool_2, !_between_12_, !t0_nullable, cql_string_compare(_between_12_, t0_nullable) < 0); +-- + if (cql_is_nullable_true(_tmp_n_bool_2.is_null, _tmp_n_bool_2.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + if (cql_string_compare(_between_12_, _literal_3_c_) > 0) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + cql_set_nullable(_tmp_n_bool_0, _tmp_n_bool_2.is_null, 0); +-- + } +-- + } +-- + cql_set_nullable(b0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set b0_nullable := 'b' not between t0_nullable and 'c'; + +-- TEST: not between with nullable strings null operand +-- verify rewrite +-- + SET b0_nullable := BETWEEN REWRITE _between_13_ := 'b' CHECK (_between_13_ < NULL OR _between_13_ > 'c'); +-- + cql_set_string_ref(&_between_%, _literal_%_b_); +-- + cql_set_null(_tmp_n_bool_2); +-- + if (cql_is_nullable_true(_tmp_n_bool_2.is_null, _tmp_n_bool_2.value)) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + if (cql_string_compare(_between_%_, _literal_3_c_) > 0) { +-- + cql_set_notnull(_tmp_n_bool_0, 1); +-- + } +-- + else { +-- + cql_set_nullable(_tmp_n_bool_0, _tmp_n_bool_2.is_null, 0); +-- + } +-- + } +-- + cql_set_nullable(b0_nullable, _tmp_n_bool_0.is_null, _tmp_n_bool_0.value); +set b0_nullable := 'b' not between null and 'c'; + +-- TEST: this procedure will have a structured semantic type +-- + cql_string_literal(with_result_set_stored_procedure_name, "with_result_set"); +-- + cql_code with_result_set(sqlite3 *_Nonnull _db_, sqlite3_stmt *_Nullable *_Nonnull _result_) { +-- + #define with_result_set_refs_offset cql_offsetof(with_result_set_row, name) // count = 1 +-- + cql_int32 with_result_set_get_id(with_result_set_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + cql_string_ref _Nullable with_result_set_get_name(with_result_set_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + cql_bool with_result_set_get_rate_is_null(with_result_set_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + cql_int64 with_result_set_get_rate_value(with_result_set_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + cql_int32 with_result_set_get_type_value(with_result_set_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + cql_int32 with_result_set_result_count(with_result_set_result_set_ref _Nonnull result_set) { +-- + CQL_WARN_UNUSED cql_code with_result_set_fetch_results(sqlite3 *_Nonnull _db_, with_result_set_result_set_ref _Nullable *_Nonnull result_set) { +-- + if (_rc_ == SQLITE_OK && !*_result_) _rc_ = SQLITE_ERROR; +create procedure with_result_set() +begin + select * from bar; +end; + +-- TEST: grabs values from a view that is backed by a table +-- + cql_code select_from_view(sqlite3 *_Nonnull _db_, sqlite3_stmt *_Nullable *_Nonnull _result_) { +-- - .refs_count = 0, +-- - .refs_offset = 0, +-- + cql_int32 select_from_view_get_id(select_from_view_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + cql_bool select_from_view_get_type_is_null(select_from_view_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + cql_int32 select_from_view_get_type_value(select_from_view_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + cql_int32 select_from_view_result_count(select_from_view_result_set_ref _Nonnull result_set) { +-- + CQL_WARN_UNUSED cql_code select_from_view_fetch_results(sqlite3 *_Nonnull _db_, select_from_view_result_set_ref _Nullable *_Nonnull result_set) { +create proc select_from_view() +begin + select id, type from baz; +end; + +-- TEST: create dml for a view +-- + "CREATE VIEW MyView AS " +-- + "SELECT 1 AS f1, 2 AS f2, 3 AS f3" +create procedure make_view() +begin + create view MyView as select 1 as f1, 2 as f2, 3 as f3; +end; + +-- TEST: code gen a simple create index statement +-- + "CREATE INDEX index_1 ON bar (id)" +create procedure make_index() +begin + create index index_1 on bar(id); +end; + +-- TEST: create a proc with reader logic with more than one arg +-- + cql_code get_data(sqlite3 *_Nonnull _db_, sqlite3_stmt *_Nullable *_Nonnull _result_, cql_string_ref _Nonnull name_, cql_int32 id_) { +create procedure get_data(name_ text not null, id_ integer not null) +begin + select * from bar where id = id_ and name = name_; +end; + +-- TEST: create a proc that uses the new cursor fetch strategy +-- then bind values from those implicit variables in a CQL statement +-- and also bind the _has_rows auto local as well +-- validate auto variable management +-- + #define easy_fetch_C_refs_offset cql_offsetof(easy_fetch_C_row, name) // count = 1 +-- + easy_fetch_C_row C_ = { ._refs_count_ = 1, ._refs_offset_ = easy_fetch_C_refs_offset }; +-- + sqlite3_stmt *C2 = NULL; +-- + cql_bool _C2_has_row_ = 0; +-- + C_._has_row_ = _rc_ == SQLITE_ROW; +-- + cql_multifetch(_rc_, C, 5, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, &C_.id, +-- + CQL_DATA_TYPE_STRING, &C_.name, +-- + CQL_DATA_TYPE_INT64, &C_.rate, +-- + CQL_DATA_TYPE_INT32, &C_.type, +-- + CQL_DATA_TYPE_DOUBLE, &C_.size); +-- + cql_multibind(&_rc_, _db_, &C2, 2, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_BOOL, C_._has_row_, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, C_.id); +-- + cql_finalize_stmt(_db_, &C); +-- + cql_teardown_row(C_); +-- + cql_finalize_stmt(_db_, &C2); +create proc easy_fetch() +begin + declare C cursor for select * from bar; + fetch C; + call printf("%d %s\n", C.id, C.name); + declare C2 cursor for select * from bar where C and id = C.id; +end; + +-- TEST: safe not nullable assignment +-- + i2 = i0_nullable.value; +-- + i2 = 3; +set i2 := ifnull(i0_nullable, 3); + +-- TEST: this works too, but the result might be nullable +-- + do { +-- + if (!i0_nullable.is_null) { +-- + cql_set_notnull(i0_nullable, i0_nullable.value); +-- + break; +-- + } +-- + cql_set_nullable(i0_nullable, i1_nullable.is_null, i1_nullable.value); +-- + } while (0); +set i0_nullable := ifnull(i0_nullable, i1_nullable); + +-- TEST: create a proc that takes a nullable int and pass it a nullable int +-- this forces the case where the variable for the int has to be +-- reconstituted from the .value field +create proc copy_int(a int, out b int) +begin + set b := a; +end; + +-- + copy_int(i0_nullable, &i1_nullable); +call copy_int(i0_nullable, i1_nullable); + +-- TEST: try out last_insert_rowid() +-- + cql_set_notnull(row, sqlite3_last_insert_rowid(_db_)); +-- - cql_cleanup +create proc insert_rowid_reader() +begin + declare row long integer; + set row := last_insert_rowid(); +end; + +-- TEST: try out printf expression +declare s text not null; +-- + _printf_result = sqlite3_mprintf("%d and %d", 1, 2); +-- + cql_string_release(s); +-- + s = cql_string_ref_new(_printf_result); +set s := printf('%d and %d', 1, 2); + +-- + _printf_result = sqlite3_mprintf("%d and %d", 3, 4) +-- + cql_string_release(s); +-- + s = cql_string_ref_new(_printf_result); +set s := printf('%d and %d', 3, 4); + +-- TEST: make sure that we use the canonical name for 's' in codegen not 'S'. Even though S is legal. +-- + cql_set_string_ref(&s, _literal%x_); +set S := 'x'; + +-- TEST: declare proc and call it +-- + /* +-- + DECLARE PROC xyzzy (id INTEGER) (A INTEGER NOT NULL); +-- + */ +declare proc xyzzy(id integer) ( A integer not null ); + +-- + _rc_ = xyzzy(_db_, &xyzzy_cursor, _tmp_n_int_%); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +create proc xyzzy_test() +begin + declare xyzzy_cursor cursor for call xyzzy(1); +end; + +-- TEST: declare a simple proc with no dml +-- + /* +-- + DECLARE PROC plugh (id INTEGER); +-- + */ +declare proc plugh(id integer); + +-- TEST: create a proc that returns a mix of possible types +-- in a select +create proc complex_return() +begin + select cast(1 as bool) as _bool, + 2 as _integer, + cast(3 as long integer) as _longint, + 3.0 as _real, + 'xxx' as _text, + cast(null as bool) as _nullable_bool; +end; + +-- TEST: create a proc with a nested select within an in statement for hierarchical queries +create proc hierarchical_query(rate_ long integer not null, limit_ integer not null, offset_ integer not null) +begin + select * + from foo + where id in ( + select id + from bar + where rate = rate_ + order by name + limit limit_ + offset offset_ + ) + order by id; +end; + +-- TEST: create a proc with a nested select within a not in statement for hierarchical queries +create proc hierarchical_unmatched_query(rate_ long integer not null, limit_ integer not null, offset_ integer not null) +begin + select * + from foo + where id not in ( + select id + from bar + where rate = rate_ + order by name + limit limit_ + offset offset_ + ) + order by id; +end; + +-- TEST: create a proc with a compound select union form +create proc union_select() +begin + select 1 as A union select 2 as A; +end; + +-- TEST: create a proc with a compound select union all form +create proc union_all_select() +begin + select 1 as A union all select 2 as A; +end; + +-- TEST: create a valid union using not null columns and nullable matching +create proc union_all_with_nullable() +begin + select nullable('foo') as name + union all + select name from bar; +end; + +-- TEST: create a simple with statement +create proc with_stmt_using_cursor() +begin + declare C cursor for + with X(a,b,c) as (select 1,2,3) + select * from X; + fetch C; +end; + +-- TEST: with statement top level +create proc with_stmt() +begin + with X(a,b,c) as (select 1,2,3) select * from X; +end; + +-- TEST: with recursive statement top level +create proc with_recursive_stmt() +begin + with recursive X(a,b,c) as (select 1,2,3 union all select 4,5,6) select * from X; +end; + +-- TEST: parent procedure +create proc parent_proc() +begin + select 1 as one, 2 as two, 3 as three; +end; + +-- TEST: child procedure +create proc parent_proc_child() +begin + select 4 as four, 5 as five, 6 as six; +end; + +-- TEST: fetch nullable output parameter +-- + _C_has_row_ = _rc_ == SQLITE_ROW; +-- + cql_multifetch(_rc_, C, 1, +-- + CQL_DATA_TYPE_INT32, output); +-- + if (_rc_ != SQLITE_ROW && _rc_ != SQLITE_DONE) goto cql_cleanup; +-- + *result = _C_has_row_; +create proc outint_nullable(out output integer, out result bool not null) +begin + declare C cursor for select 1; + fetch C into output; + set result := C; +END; + +-- TEST: fetch not null output parameter +-- + cql_bool _C_has_row_ = 0; +-- + _C_has_row_ = _rc_ == SQLITE_ROW; +-- + cql_multifetch(_rc_, C, 1, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, output); +-- + if (_rc_ != SQLITE_ROW && _rc_ != SQLITE_DONE) goto cql_cleanup; +-- + *result = _C_has_row_; +create proc outint_notnull(out output integer not null, out result bool not null) +begin + declare C cursor for select 1; + fetch C into output; + set result := C; +END; + +declare function simple_func(int1 integer) real; +declare result real; + +-- TEST: call external function +-- + cql_set_notnull(_tmp_n_int_2, 2); +-- + result = simple_func(_tmp_n_int_2); +set result := simple_func(2); + +-- TEST: call external function +-- + cql_set_notnull(_tmp_n_int_3, 1); +-- + _tmp_n_double_1 = simple_func(_tmp_n_int_3); +-- + cql_set_nullable(_tmp_n_int_2, _tmp_n_double_1.is_null, _tmp_n_double_1.value); +-- + result = simple_func(_tmp_n_int_2); +set result := simple_func(simple_func(1)); + +declare function text_func(int1 integer, int2 integer not null) text not null; +declare text_result text; + +-- TEST: call external text function +-- + cql_set_notnull(_tmp_n_int_2, 123); +-- + cql_set_string_ref(&_tmp_text_0, text_func(_tmp_n_int_2, 456)); +-- + cql_set_string_ref(&text_result, _tmp_text_0); +set text_result := text_func(123, 456); + +-- TEST: create object variable +-- + cql_object_ref obj_var = NULL; +declare obj_var object; + +-- TEST: assign null to object variable +-- + cql_set_object_ref(&obj_var, NULL); +set obj_var := null; + +-- TEST: declare not null object +-- + cql_object_ref obj_var2 = NULL; +declare obj_var2 object not null; + +-- TEST: assign var to object variable +-- + cql_set_object_ref(&obj_var, obj_var2); +set obj_var := obj_var2; + +-- TEST: object comparison +-- + cql_combine_nullables(b0_nullable, !obj_var, !obj_var, obj_var == obj_var); +set b0_nullable := obj_var == obj_var; + +-- TEST: object variable in IN clause +-- + if (cql_is_nullable_true(!obj_var, _tmp_n_object_% == obj_var)) break; +-- + if (cql_is_nullable_true(!obj_var, _tmp_n_object_% == obj_var)) break; +set b0_nullable := obj_var in (obj_var, obj_var); + +-- TEST: object variable in IN clause +-- + if (_tmp_object_2 == obj_var2) break; +set b2 := obj_var2 in (obj_var2, obj_var2); + +-- TEST: object variable in NOT IN clause +-- + if (cql_is_nullable_true(!obj_var, _tmp_n_object_% == obj_var)) break; +-- + if (cql_is_nullable_true(!obj_var, _tmp_n_object_% == obj_var)) break; +set b0_nullable := obj_var not in (obj_var, obj_var); + +-- TEST: object variable in NOT IN clause +-- + if (_tmp_object_2 == obj_var2) break; +set b2 := obj_var2 not in (obj_var2, obj_var2); + +-- TEST: proc with object args +-- + void obj_proc(cql_object_ref _Nullable *_Nonnull an_object) +create proc obj_proc(out an_object object) +begin + set an_object := null; +end; + +-- TEST: case statement with objects +-- + if (cql_is_nullable_true(!obj_var, _tmp_n_object_1 == obj_var)) +set i2 := case obj_var when obj_var then 1 else 2 end; + +-- TEST: case statement with returning objects +-- + cql_set_object_ref(&obj_var, obj_var2); +-- + cql_set_object_ref(&obj_var, NULL); +set obj_var := case 1 when 1 then obj_var2 else null end; + +declare function obj_func() object; + +-- TEST: function invocation with object function +-- + cql_set_object_ref(&obj_var, obj_func()); +set obj_var := obj_func(); + +declare function obj_func_create() create object; + +-- TEST: function invocation with creater object function +-- + cql_object_release(obj_var); +-- + obj_var = obj_func_create(); +set obj_var := obj_func_create(); + +declare function text_func_create() create text; + +-- TEST: function invocation with creater text function +-- cql_string_release(_tmp_n_text_0); +-- _tmp_n_text_0 = text_func_create(); +set text_result := text_func_create(); + +-- TEST: unused temp in unary not emitted +-- - cql_int32 _tmp_int_0 = 0; +-- - cql_int32 _tmp_int_1 = 0; +-- + o = i.value; +-- + o = - 1; +create proc unused_temp(i integer, out o integer not null) +begin + set o := coalesce(i, -1); +end; + +-- TEST: echo something to the output +-- + Garbonzo +-- + chick pea +@echo c, "int Garbonzo; // a chick pea\n"; + +-- TEST: echo all the escape characters that are supported +-- + // +-- + '%' +@echo c, "//\/'\a\b\f\t\v'\r\n"; + +-- TEST: insert or replace form +-- + "INSERT OR REPLACE INTO bar(id, type) VALUES(1, 5)" +insert or replace into bar(id, type) values (1,5); + +-- TEST: insert default from +-- + "INSERT INTO foo DEFAULT VALUES" +insert into foo default values; + +-- TEST: insert from stored procedure +-- + "INSERT INTO bar(id, type) VALUES(?, ?)" +-- + cql_code insert_values(sqlite3 *_Nonnull _db_, cql_int32 id_, cql_nullable_int32 type_) { +create proc insert_values(id_ integer not null, type_ integer) +begin + insert into bar(id, type) values (id_, type_); +end; + +-- TEST: alter table add column +-- + _rc_ = cql_exec(_db_, +-- + "ALTER TABLE bar ADD COLUMN size REAL" +create proc alter_table_test() +begin + alter table bar add column size real; +end; + +-- TEST: drop table +-- + _rc_ = cql_exec(_db_, +-- + "DROP TABLE IF EXISTS bar" +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +-- + _rc_ = SQLITE_OK; +create proc drop_table_test() +begin + drop table if exists bar; +end; + +-- TEST: use a procedure to get a result set +-- + cql_code uses_proc_for_result(sqlite3 *_Nonnull _db_, sqlite3_stmt *_Nullable *_Nonnull _result_) +-- + *_result_ = NULL; +-- + _rc_ = with_result_set(_db_, &*_result_); +create procedure uses_proc_for_result() +begin + call with_result_set(); +end; + +-- TEST: declare a void func +declare function voidfunc() integer; + +-- TEST: use a select exists clause +-- + "SELECT EXISTS (SELECT * " +-- + "FROM bar)" +set b2 := (select exists(select * from bar)); + +-- TEST: for expand of select * columns from whole result +-- + _rc_ = cql_prepare(_db_, &expanded_select, +-- + "SELECT id, name, rate, type, size " +-- + "FROM bar" +declare expanded_select cursor for select * from bar; + +-- TEST: for expand of select * columns from table +-- + "SELECT bar.id, bar.name, bar.rate, bar.type, bar.size " +-- + "FROM bar" +declare table_expanded_select cursor for select bar.* from bar; + +-- TEST: use a long literal +-- + l2 = 3147483647L; +set l2 := 3147483647L; + +-- TEST: use a long literal +-- + l2 = 3147483647L; +set l2 := 3147483647; + +-- TEST: use drop index in a proc +-- + "DROP INDEX index_1" +create proc index_dropper() +begin + drop index index_1; +end; + +-- TEST: simple DML statements for schema_util cg +-- +2 "INSERT INTO foo(id) VALUES(NULL)" +-- + "UPDATE bar " +-- + "SET name = 'bar' " +-- + "DELETE FROM foo WHERE id = 1" +create proc misc_dml_proc() +begin + insert into foo values(NULL); + insert into foo(id) values(NULL); + update bar set name = 'bar' where name = 'baz'; + delete from foo where id = 1; +end; + +-- TEST: use dummy data +-- + INSERT INTO bar(id, name, rate, type, size) VALUES(_seed_, printf('name_%d', _seed_), _seed_, _seed_, _seed_) +-- + @DUMMY_SEED(123) @DUMMY_DEFAULTS @DUMMY_NULLABLES; +-- + _seed_ = 123; +-- + "INSERT INTO bar(id, name, rate, type, size) VALUES(?, printf('name_%d', ?), ?, ?, ?)" +-- + cql_multibind(&_rc_, _db_, &_temp_stmt, 5, +-- +4 CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, _seed_, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, _seed_); +create proc dummy_user() +begin + insert into bar () values () @dummy_seed(123) @dummy_nullables @dummy_defaults; +end; + +create proc proc_with_out_arg(out foo text) +begin + set foo := 'x'; +end; + +-- TEST: the incoming arg must be nulled +-- when we call proc_with_out_arg we have to release the out arg before we call it or leak +-- (note: run tests verify this too) +-- bar is local and it is forced to null to start +-- + cql_string_ref bar = NULL; +-- foo is the out arg, we clobber it to a safe value +-- + *(void **)foo = NULL; +-- foo is set to something useful +-- + cql_set_string_ref(&*foo, _literal_%x_%); +-- we have to release the something useful before we make the call +-- + cql_set_string_ref(&*foo, NULL); +-- + proc_with_out_arg(foo); +-- we have to release bar before we make the call +-- + cql_set_string_ref(&bar, NULL); +-- + proc_with_out_arg(&bar); +create proc calls_out_proc(out foo text) +begin + set foo := 'x'; + declare bar text; + call proc_with_out_arg(foo); + call proc_with_out_arg(bar); +end; + +-- TEST: create blob variable +-- + cql_blob_ref blob_var = NULL; +declare blob_var blob; + +-- TEST: create blob variable2 +-- + cql_blob_ref blob_var2 = NULL; +declare blob_var2 blob not null; + +-- TEST: assign null to blob variable +-- + cql_set_blob_ref(&blob_var, NULL); +set blob_var := null; + +-- TEST: assign var to blob variable +-- + cql_set_blob_ref(&blob_var, blob_var2); +set blob_var := blob_var2; + +-- TEST: blob comparison +-- + cql_combine_nullables(b0_nullable, !blob_var, !blob_var, blob_var == blob_var); +set b0_nullable := blob_var == blob_var; + +-- TEST: blob variable in IN clause +-- + if (cql_is_nullable_true(!blob_var, _tmp_n_blob_% == blob_var)) break; +-- + if (cql_is_nullable_true(!blob_var, _tmp_n_blob_% == blob_var)) break; +set b0_nullable := blob_var in (blob_var, blob_var); + +-- TEST: blob variable in IN clause +-- + if (_tmp_blob_2 == blob_var2) break; +set b2 := blob_var2 in (blob_var, blob_var2); + +-- TEST: blob variable in NOT IN clause +-- + if (cql_is_nullable_true(!blob_var, _tmp_n_blob_% == blob_var)) break; +-- + if (cql_is_nullable_true(!blob_var, _tmp_n_blob_% == blob_var)) break; +set b0_nullable := blob_var not in (blob_var, blob_var); + +-- TEST: blob variable in NOT IN clause +-- + if (_tmp_blob_2 == blob_var2) break; +set b2 := blob_var2 not in (blob_var, blob_var2); + +-- TEST: proc with blob args +-- + void blob_proc(cql_blob_ref _Nullable *_Nonnull a_blob) +create proc blob_proc(out a_blob blob) +begin + set a_blob := null; +end; + +-- TEST: case statement with blobs +-- + if (cql_is_nullable_true(!blob_var, _tmp_n_blob_1 == blob_var)) +set i2 := case blob_var when blob_var then 1 else 2 end; + +-- TEST: case statement with returning blobs +-- + cql_set_blob_ref(&blob_var, blob_var2); +-- + cql_set_blob_ref(&blob_var, NULL); +set blob_var := case 1 when 1 then blob_var2 else null end; + +declare function blob_func() blob; + +-- TEST: function invocation with blob function +-- + cql_set_blob_ref(&blob_var, blob_func()); +set blob_var := blob_func(); + +declare function blob_func_create() create blob; + +-- TEST: function invocation with creater blob function +-- + cql_blob_release(blob_var); +-- + blob_var = blob_func_create(); +set blob_var := blob_func_create(); + +-- make a table with blobs in it +create table blob_table ( + blob_id integer not null, + b_notnull blob not null, + b_nullable blob +); + +-- TEST: fetch a nullable blob +-- + cql_column_nullable_blob_ref(_temp_stmt, 0, &blob_var); +set blob_var := (select b_nullable from blob_table where blob_id = 1); + +-- TEST: fetch a not null blob +-- + cql_column_blob_ref(_temp_stmt, 0, &_tmp_blob_0); +set blob_var := (select b_notnull from blob_table where blob_id = 1); + +-- some not null blob object we can use +declare blob_var_notnull blob not null; + +-- TEST: bind a nullable blob and a not null blob +-- + INSERT INTO blob_table(blob_id, b_nullable, b_notnull) VALUES(0, blob_var, blob_var_notnull); +-- + "INSERT INTO blob_table(blob_id, b_nullable, b_notnull) VALUES(0, ?, ?)" +-- + cql_multibind(&_rc_, _db_, &_temp_stmt, 2, +-- + CQL_DATA_TYPE_BLOB, blob_var, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_BLOB, blob_var_notnull); +insert into blob_table(blob_id, b_nullable, b_notnull) values(0, blob_var, blob_var_notnull); + +-- TEST: a result set that includes blobs +create proc blob_returner() +begin + select * from blob_table; +end; + +-- TEST: forcing null set of object temporary by having no else case +-- + cql_set_object_ref(&obj_var, NULL); +set obj_var := case when 1 then obj_var end; + +-- TEST: force a proc with no arg list +-- + void voidproc(void) { +create proc voidproc() +begin + declare unused int; +end; + +-- TEST: create an output struct proc +-- + #define out_cursor_proc_C_refs_offset cql_offsetof(out_cursor_proc_C_row, name) // count = 3 +-- + memset(_result_, 0, sizeof(*_result_)); +-- + out_cursor_proc_C_row C_ = { ._refs_count_ = 3, ._refs_offset_ = out_cursor_proc_C_refs_offset }; +-- + _result_->_has_row_ = C_._has_row_; +-- + _result_->id = C_.id; +-- + cql_set_string_ref(&_result_->name, C_.name); +-- + _result_->rate = C_.rate; +-- + _result_->type = C_.type; +-- + _result_->size = C_.size; +-- + cql_set_string_ref(&_result_->extra1, C_.extra1); +-- + cql_set_string_ref(&_result_->extra2, C_.extra2); +create proc out_cursor_proc() +begin + declare C cursor for select bar.*, 'xyzzy' extra1, 'plugh' extra2 from bar; + fetch C; + out C; +end; + +-- TEST: fetch from an output struct proc +-- + #define read_cursor_proc_C_refs_offset cql_offsetof(read_cursor_proc_C_row, name) // count = 3 +-- + read_cursor_proc_C_row C_ = { ._refs_count_ = 3, ._refs_offset_ = read_cursor_proc_C_refs_offset }; +-- +2 cql_teardown_row(C_); +-- +1 _rc_ = out_cursor_proc(_db_, (out_cursor_proc_row *)&C_); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +create proc read_cursor_proc() +begin + declare C cursor fetch from call out_cursor_proc(); +end; + +-- TEST: declare a cursor and do a fetch as separate actions +-- +1 declare_cursor_then_fetch_from_proc_C_row C_ = { ._refs_count_ = 3, ._refs_offset_ = declare_cursor_then_fetch_from_proc_C_refs_offset }; +-- +2 cql_teardown_row(C_); +-- +1 _rc_ = out_cursor_proc(_db_, (out_cursor_proc_row *)&C_); +create proc declare_cursor_then_fetch_from_proc() +begin + declare C cursor like out_cursor_proc; + fetch C from call out_cursor_proc(); +end; + +-- TEST: proc decl with out args +-- + DECLARE PROC fetcher_proc () OUT (a INTEGER, b TEXT); +declare proc fetcher_proc() out (a integer, b text); + +-- TEST: All void all day +-- + DECLARE PROC totally_void_proc (); +declare proc totally_void_proc(); + +-- TEST: call out proc like a function +-- + SET i2 := outparm_test(); +-- + _rc_ = outparm_test(_db_, &i2); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +set i2 := outparm_test(); + +declare proc compute(in a_ integer not null, out b_ integer not null); + +-- TEST: call out proc like a function, this one has args +-- + compute(1, &_tmp_int_1); +-- + compute(_tmp_int_1, &i2); +set i2 := compute(compute(1)); + +-- a dml method +declare proc dml_compute(in a_ integer not null, out b_ integer not null) USING TRANSACTION; + +-- TEST: call out proc like a function, this one has args and uses the db +-- + _rc_ = dml_compute(_db_, 1, &_tmp_int_1); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +-- + _rc_ = dml_compute(_db_, _tmp_int_1, &i2); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +set i2 := dml_compute(dml_compute(1)); + +-- TEST: write the result of a proc-as-func call to an out variable +-- + _rc_ = dml_compute(_db_, 1, &*a_); +create proc dml_user(out a_ integer not null) +begin + set a_ := dml_compute(1); +end; + +-- a test table for the following case +create table threads ( + thread_key long int not null +); + +-- TEST: nested subquery in a proc +-- this forces the msys_schema_utils to run over an atypical table_factor +-- + _rc_ = cql_prepare(_db_, _result_, +-- + "SELECT thread_key " +-- + "FROM (SELECT thread_key " +-- + "FROM threads) AS T" +create procedure thread_theme_info_list(thread_key_ LONG INT NOT NULL) +begin + select * + from (select thread_key from threads) T; +end; + +-- TEST: value cursor fetch +-- + _seed_ = 123; +-- + C_._has_row_ = 1; +-- + C_.id = _seed_; +-- + char *_printf_result = sqlite3_mprintf("name_%d", _seed_); +-- + cql_string_release(_tmp_text_0); +-- + _tmp_text_0 = cql_string_ref_new(_printf_result); +-- + sqlite3_free(_printf_result); +-- + cql_set_string_ref(&C_.name, _tmp_text_0); +-- + cql_set_notnull(C_.rate, _seed_); +-- + cql_set_notnull(C_.type, _seed_); +-- + cql_set_notnull(C_.size, _seed_); +-- This should not be a dml proc, it doesn't actually use the db +-- + fetch_values_dummy(void) +-- - _rc_ +-- - cql_cleanup +create proc fetch_values_dummy() +begin + declare C cursor like select * from bar; + fetch C() from values() @dummy_seed(123) @dummy_nullables; +end; + +-- TEST: c style literal +-- + SET x := "\"Testing\" \\''"; +create proc c_literal(out x text) +begin + set x := "\"Testing\" \\''"; +end; + +-- TEST: no cleanup label needed proc +-- - cql_cleanup +-- + if (_rc_ != SQLITE_OK) goto catch_start +-- + catch_start%: +create proc no_cleanup_label_needed_proc() +begin + begin try + declare C cursor for select 1 as N; + fetch C; + end try; + begin catch + declare x integer; + end catch; +end; + +-- TEST: no code after the last label +-- begin try and begin catch implyl dml proc +-- + cql_code no_code_after_catch(sqlite3 *_Nonnull _db_) +create proc no_code_after_catch() +begin + begin try + @attribute(foo) -- just messing with the tree + declare x integer; + end try; + begin catch + @attribute(bar) -- just messing with the tree + declare y integer; + end catch; +end; + +-- TEST: void cursor fetcher +-- + void out_no_db(out_no_db_row *_Nonnull _result_) { +-- + memset(_result_, 0, sizeof(*_result_)); +-- + out_no_db_C_row C_ = { 0 }; +-- + C_._has_row_ = 1; +-- + C_.A = 3; +-- + C_.B = 12; +-- + _result_->_has_row_ = C_._has_row_; +-- + _result_->A = C_.A; +-- + _result_->B = C_.B; +create proc out_no_db() +begin + declare C cursor like select 1 A, 2.5 B; + fetch C(A,B) from values(3,12); + out C; +end; + +-- TEST: declare cursor like cursor +-- + declare_cursor_like_cursor_C0_row C0_ = { 0 }; +-- + declare_cursor_like_cursor_C1_row C1_ = { 0 }; +-- + memset(_result_, 0, sizeof(*_result_)); +-- + _C1_._has_row_ = 1; +-- + C1_.A = 3; +-- + C1_.B = 12; +-- + _result_->_has_row_ = C1_._has_row_; +-- + _result_->A = C1_.A; +-- + _result_->B = C1_.B; +create proc declare_cursor_like_cursor() +begin + declare C0 cursor like select 1 A, 2.5 B; + declare C1 cursor like C0; + fetch C1(A,B) from values(3,12); + out C1; +end; + +-- TEST: declare cursor like proc +-- + void declare_cursor_like_proc(declare_cursor_like_proc_row *_Nonnull _result_) { +-- + memset(_result_, 0, sizeof(*_result_)); +-- + _result_->_has_row_ = C_._has_row_; +-- + _result_->_refs_count_ = 1; +-- + _result_->_refs_offset_ = declare_cursor_like_proc_refs_offset; +-- + _result_->a = C_.a; +-- + cql_set_string_ref(&_result_->b, C_.b); +-- + cql_teardown_row(C_); +-- - Error +create proc declare_cursor_like_proc() +begin + declare C cursor like fetcher_proc; + out C; +end; + +-- TEST: declare a cursor like a table +-- + void declare_cursor_like_table(declare_cursor_like_table_row *_Nonnull _result_) { +-- + declare_cursor_like_table_C_row C_ = { ._refs_count_ = 1, ._refs_offset_ = declare_cursor_like_table_C_refs_offset }; +-- + memset(_result_, 0, sizeof(*_result_)); +-- + _result_->_has_row_ = C_._has_row_; +-- + _result_->_refs_offset_ = declare_cursor_like_table_refs_offset; +-- + _result_->id = C_.id; +-- + cql_set_string_ref(&_result_->name, C_.name); +-- + _result_->rate = C_.rate; +-- + _result_->type = C_.type; +-- + _result_->size = C_.size; +-- + cql_teardown_row(C_); +-- - Error +create proc declare_cursor_like_table() +begin + declare C cursor like bar; + out C; +end; + +-- TEST: declare a cursor like a view +-- + void declare_cursor_like_view_fetch_results( declare_cursor_like_view_result_set_ref _Nullable *_Nonnull result_set) { +-- + declare_cursor_like_view_C_row C_ = { 0 }; +-- + _result_->_has_row_ = C_._has_row_; +-- + _result_->f1 = C_.f1; +-- + _result_->f2 = C_.f2; +-- + _result_->f3 = C_.f3; +-- - Error +create proc declare_cursor_like_view() +begin + declare C cursor like MyView; + out C; +end; + +-- TEST: stress case for quote management +-- the backslash must be preserved in a regular sql string and then escaped +-- the newlines in the c string are turned into newline characters in the SQL string +-- but they have to be escaped due to being embedded in a c string +-- the ones with a leading space are the echoed sql, the strings are not C escaped there +-- so this checks both paths +-- + DELETE FROM bar WHERE name LIKE "\n\n"; +-- + "DELETE FROM bar WHERE name LIKE '\n\n'" +-- + DELETE FROM bar WHERE name = ' '' \n '' \'; +-- + "DELETE FROM bar WHERE name = ' '' \\n '' \\'" +-- + DELETE FROM bar WHERE name <> "'"; +-- + "DELETE FROM bar WHERE name <> ''''" +-- + DELETE FROM bar WHERE name >= '\'; +-- + "DELETE FROM bar WHERE name >= '\\'" +create proc weird_quoting() +begin + delete from bar where name like "\n\n"; + -- the newline looking thing is NOT an escape sequence it's a pain in the ass... + delete from bar where name = ' '' \n '' \'; + -- lots of transforms required to get this right + delete from bar where name != "\'"; + -- another tricky case + delete from bar where name >= '\'; +end; + +-- TEST: create a table with a long integer autoinc column +-- this requires the workaround of downgradeing the long to int +-- note: sqlite integers can hold 64 bits so they are already "long" +-- + id LONG_INT PRIMARY KEY AUTOINCREMENT, +-- + "id INTEGER PRIMARY KEY AUTOINCREMENT, " +create proc long_auto_table_maker() +begin + create table long_int_autoinc ( + id long primary key autoincrement, + name text + ); +end; + +declare proc blob_out(out x blob); + +-- TEST: force a blob variable to be cleared to null before a proc cll +-- call on out parameter. This is important because the blob +-- might be holding a value and the out arg is assume to be junk +-- + cql_blob_ref b = NULL; +-- + cql_set_blob_ref(&b, NULL); +-- + blob_out(&b); +-- + cql_blob_release(b); +create proc blob_call1() +begin + declare b blob; + call blob_out(b); +end; + +-- TEST: force a blob variable to be cleared to null before a function +-- call on out parameter. This is important because the blob +-- might be holding a value and the out arg is assume to be junk +-- + cql_blob_ref b = NULL; +-- + cql_set_blob_ref(&b, NULL); +-- + blob_out(&b); +-- + cql_blob_release(b); +create proc blob_call2() +begin + declare b blob; + set b := blob_out(); -- use function call syntax should be the same +end; + +-- TEST: forces us to set a blob to null via else. This is not the store code path +-- + cql_set_blob_ref(&b, b1); +-- + cql_set_blob_ref(&b, NULL); +create proc blob_no_else() +begin + declare b blob; + declare b1 blob; + set b := case b when b then b1 end; +end; + +-- TEST: use with-insert form +-- + _rc_ = cql_exec(_db_, +-- + "WITH " +-- + "x (a) AS (SELECT 111) " +-- + "INSERT INTO foo(id) VALUES(ifnull(( SELECT a " +-- + "FROM x ), 0))"); +with x(a) as (select 111) +insert into foo values ( ifnull((select a from x), 0)); + +-- TEST: use insert from select (put this in a proc to force the schema utils to walk it) +-- + "WITH " +-- + "x (a) AS (SELECT 111) " +-- + "INSERT INTO foo(id) SELECT a " +-- + "FROM x" +create proc with_inserter() +begin + with x(a) as (select 111) + insert into foo select * from x; +end; + +declare select func SqlUserFunc(id integer) real not null; + +-- TEST: invoke a declared user function +-- + _rc_ = cql_prepare(_db_, &_temp_stmt, +-- + "SELECT SqlUserFunc(123)" +set r2 := (select SqlUserFunc(123)); + +-- TEST: multiple rewrites complex arg filter +-- +-- Note: we're doing something that's legal but not really very useful here just to force the codegen. +-- the out_arg should still be present in the args (and we check it here plus the code is required to compile) +-- and we have to be able to correctly code gen two different like args cases in different locations. +-- It's hard to think of a real use case for this but I want to make sure the rewriter doesn't screw it up. +-- +-- + cql_code multi_rewrite(sqlite3 *_Nonnull _db_, +-- + cql_int32 blob_id_, cql_blob_ref _Nonnull b_notnull_, cql_blob_ref _Nullable b_nullable_, +-- + cql_int32 id_, cql_string_ref _Nullable name_, cql_nullable_int64 rate_, cql_nullable_int32 type_, +-- + cql_nullable_double size_, cql_int32 *_Nonnull out_arg) +-- + "INSERT INTO blob_table(blob_id, b_notnull, b_nullable) VALUES(?, ?, ?)" +-- + cql_multibind(&_rc_, _db_, &_temp_stmt, 3, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, blob_id_, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_BLOB, b_notnull_, +-- + CQL_DATA_TYPE_BLOB, b_nullable_); +create proc multi_rewrite(like blob_table, like bar, out out_arg integer not null) +begin + insert into blob_table from arguments; + set out_arg := 1; +end; + +-- TEST: fetch to a cursor from another cursor +-- + C1_._has_row_ = C0_._has_row_; +-- + C1_.A = C0_.A; +-- + cql_set_string_ref(&C1_.B, C0_.B); +create proc fetch_to_cursor_from_cursor() +begin + declare C0 cursor like select 1 A, "foo" B; + declare C1 cursor like C0; + fetch C0 from values (2, "bar"); + fetch C1 from C0; + out C1; +end; + +-- TEST loop statement cursor with autofetch +-- + sqlite3_stmt *C = NULL; +-- + loop_statement_cursor_C_row C_ = { 0 }; +-- + "SELECT 1" +-- + C_._has_row_ = _rc_ == SQLITE_ROW; +-- + if (_rc_ != SQLITE_ROW && _rc_ != SQLITE_DONE) goto cql_cleanup; +-- + if (!C_._has_row_) break +create proc loop_statement_cursor() +begin + declare C cursor for select 1 A; + loop fetch C + begin + call printf("%d\n", C.A); + end; +end; + +-- TEST loop statement cursor with autofetch +-- + sqlite3_stmt *C = NULL; +-- + cql_bool _C_has_row_ = 0; +-- + cql_int32 A_ = 0; +-- + "SELECT 1" +-- + _C_has_row_ = _rc_ == SQLITE_ROW; +-- + if (_rc_ != SQLITE_ROW && _rc_ != SQLITE_DONE) goto cql_cleanup; +-- + if (!_C_has_row_) break +create proc loop_statement_not_auto_cursor() +begin + declare C cursor for select 1 A; + declare A_ integer not null; + loop fetch C into A_ + begin + call printf("%d\n", A_); + end; +end; + +-- TEST: ensure cursors work outside of a proc +-- _rc_ = cql_prepare(_db_, &global_cursor, +-- "SELECT 1 AS a, 2 AS b" +declare global_cursor cursor for select 1 a, 2 b; + +-- TEST: fetch from global cursor +-- + _rc_ = sqlite3_step(global_cursor); +-- + global_cursor_._has_row_ = _rc_ == SQLITE_ROW; +fetch global_cursor; + +-- TEST: use like in an expression +-- + i2 = cql_string_like(_literal_%_x_, _literal_%_y_) == 0; +set i2 := 'x' LIKE 'y'; + +-- TEST: use not like in an expression +-- + i2 = cql_string_like(_literal_%_x_, _literal_%_y_) != 0; +set i2 := 'x' NOT LIKE 'y'; + +-- TEST: use like in a SQL statement +-- + _rc_ = cql_prepare(_db_, &_temp_stmt, +-- + "SELECT 'x' LIKE 'y'" +set i2 := (select 'x' LIKE 'y'); + +-- TEST: use not like in a SQL statement +-- + _rc_ = cql_prepare(_db_, &_temp_stmt, +-- + "SELECT 'x' NOT LIKE 'y'" +set i2 := (select 'x' NOT LIKE 'y'); + +-- TEST: use match in a SQL statement +-- + _rc_ = cql_prepare(_db_, &_temp_stmt, +-- + "SELECT 'x' MATCH 'y'" +set i2 := (select 'x' MATCH 'y'); + +-- TEST: use glob in a SQL statement +-- + _rc_ = cql_prepare(_db_, &_temp_stmt, +-- + "SELECT 'x' GLOB 'y'" +set i2 := (select 'x' GLOB 'y'); + +-- TEST: use lot of bitwise operators +-- NOTE the SQL order of ops is different... +-- no parens used here +-- + SET i2 := 1 << 2 | 1 << 4 & 1 >> 8; +-- in Sqlite binary math operators all bind equal and left to right so the above is the same as +-- SET i2 := (((((1 << 2) | 1) << 4) & 1) >> 8); +-- in C that becomes +-- because i C << and >> are stronger than | and & +-- + i2 = ((1 << 2 | 1) << 4 & 1) >> 8; +set i2 := 1 << 2 | 1 << 4 & 1 >> 8; + +-- TEST: now maybe what you expected to see. Force the issue with parens +-- + SET i2 := 1 << 2 | (1 << 4) & (1 >> 8); +-- Still not what you expected... remember | and & are EQUAL in sql +-- so the above was parsed left to right... +-- + i2 = (1 << 2 | 1 << 4) & 1 >> 8; +set i2 := (1 << 2) | (1 << 4) & (1 >> 8); + +-- TEST: this is really the normal thing +-- some parens were redunant, removed... +-- + SET i2 := 1 << 2 | (1 << 4 & (1 >> 8)); +-- now this is the usual C order of ops and no parens are in the C +-- + i2 = 1 << 2 | 1 << 4 & 1 >> 8; +set i2 := (1 << 2) | ((1 << 4) & (1 >> 8)); + +-- TEST: force a high binding ~ +-- nothing weird here, ~ binds very strong in both languages +-- + i2 = 1 | ~ i2; +set i2 := 1 | ~i2; + +-- TEST: create a trigger, force the dml +-- + _rc_ = cql_exec(_db_, +-- + "CREATE TEMP TRIGGER IF NOT EXISTS trigger1 " +-- + "BEFORE DELETE ON bar " +-- + "FOR EACH ROW " +-- + "WHEN old.id > 7 " +-- + "BEGIN " +-- + "SELECT old.id; " +-- + "END" +create proc make_trigger() +begin + create temp trigger if not exists trigger1 + before delete on bar + for each row + when old.id > 7 + begin + select old.id; + end; +end; + +-- TEST: IS patterns +-- + b = 1 == 1; +-- + b = cql_string_equal(_literal_%_x_, _literal_%_x_); +-- + b = cql_string_equal(_literal_%_x_, _literal_%_y_); +-- + b = !!(1 + (3 == 4)); +-- + cql_set_notnull(i, 1); +-- + cql_set_notnull(j, 2); +-- + b = ((i.is_null == j.is_null) && (j.is_null || i.value == j.value)) +create proc is_test() +begin + declare b bool not null; + set b := 1 is 1; + set b := 'x' is 'x'; + set b := 'x' is 'y'; + set b := 1 + (3 is 4); + + declare i integer; + declare j integer; + set i := 1; + set j := 2; + + set b := i is j; +end; + +-- TEST: IS NOT patterns +-- + b = 1 != 1; +-- + b = !cql_string_equal(_literal_%_x_, _literal_%_x_); +-- + b = !cql_string_equal(_literal_%_x_, _literal_%_y_); +-- + b = !!(1 + (3 != 4)); +-- + cql_set_notnull(i, 1); +-- + cql_set_notnull(j, 2); +-- + b = !((i.is_null == j.is_null) && (j.is_null || i.value == j.value)) +create proc is_not_test() +begin + declare b bool not null; + set b := 1 is not 1; + set b := 'x' is not 'x'; + set b := 'x' is not 'y'; + set b := 1 + (3 is not 4); + + declare i integer; + declare j integer; + set i := 1; + set j := 2; + + set b := i is not j; +end; + +-- TEST: null on lhs of IN +-- + cql_set_null(*b); +create proc in_test(x integer, out b bool) +begin + set b := NULL IN (1); +end; + +-- TEST: null on lhs of NOT IN +-- + cql_set_null(*b); +create proc not_in_test(x integer, out b bool) +begin + set b := NULL NOT IN (1); +end; + +-- TEST: drop a trigger (both flavors) +-- +1 "DROP TRIGGER IF EXISTS trigger1" +-- +1 "DROP TRIGGER trigger1" +create proc drop_trigger_test() +begin + drop trigger if exists trigger1; + drop trigger trigger1; +end; + +-- TEST: create proc with a single-column identity attribute +-- + static cql_uint16 simple_identity_identity_columns[] = { 1, +@attribute(cql:identity=(id)) +create proc simple_identity() +begin + select 1 as id, 2 as data; +end; + +-- TEST: create proc with a multi-column identity attribute +-- + static cql_uint16 complex_identity_identity_columns[] = { 2, +@attribute(cql:identity=(col1, col2)) +create proc complex_identity() +begin + select 1 as col1, 2 as col2, 3 as data; +end; + +-- TEST: create proc with a out cursor and identity column +-- + static cql_uint16 out_cursor_identity_identity_columns[] = { 1, +@attribute(cql:identity=(id)) +create proc out_cursor_identity() +begin + declare C cursor for select 1 as id, 2 as data; + fetch C; + out C; +end; + +create table radioactive( + id integer not null, + data text @sensitive +); + +-- TEST: create a proc that reducts some sensitive data +-- + CREATE PROC radioactive_proc () +create proc radioactive_proc() +begin + select * from radioactive; +end; + +-- TEST: with delete form +-- + _rc_ = cql_exec(_db_, +-- + "WITH " +-- + "x (a) AS (SELECT 111) " +-- + "DELETE FROM foo WHERE id IN (SELECT a " +-- + "FROM x)"); +create proc with_deleter() +begin + with x(a) as (select 111) + delete from foo where id in (select * from x); +end; + +-- TEST: with update form +-- + _rc_ = cql_exec(_db_, +-- + "WITH " +-- + "x (a) AS (SELECT 111) " +-- + "UPDATE bar " +-- + "SET name = 'xyzzy' " +-- + "WHERE id IN (SELECT a " +-- + "FROM x)"); +create proc with_updater() +begin + with x(a) as (select 111) + update bar set name = 'xyzzy' where id in (select * from x); +end; + +create temp table table1( id integer); +create temp table table2( id integer); + +-- TEST: autodrop attribute +-- + .autodrop_tables = "table1\0table2\0", +@attribute(cql:autodrop=(table1, table2)) +create proc autodropper() +begin + select 1 a, 2 b; +end; + +-- TEST: base fragment attribute +-- - base_fragment +@attribute(cql:base_fragment=core) +create proc base_fragment(id_ integer not null) +begin +with + core(x,y,z) as (select id,name,rate from bar where id = id_) +select * from core; +end; + +-- TEST: make sure that the name of the cursor is canonicalized +-- There should be no references to the version with the wrong case +-- + simple_cursor_proc_A_CURSOR_row A_CURSOR_ = { 0 }; +-- + A_CURSOR_._has_row_ = 1; +-- + A_CURSOR_.id = 1; +-- + _result_->_has_row_ = A_CURSOR_._has_row_; +-- + _result_->id = A_CURSOR_.id; +create procedure simple_cursor_proc() +begin + declare A_CURSOR cursor like select 1 id; + fetch a_cursor (id) from values(1); + out a_cursor; +end; + +-- TEST: force codegen to include (and ignore) the enforcement directives +-- these have no output so there's nothing to verify really +-- we just verify that we did not echo the comment for these +-- thereby causing the need for the global proc for no reason +-- - @enforce +@enforce_strict foreign key on update; +@enforce_normal foreign key on delete; + +-- TEST: force codegen to include (and ignore) the schema region directives +-- these have no output so there's nothing to verify really +-- we just verify that we did not echo the comment for these +-- thereby causing the need for the global proc for no reason +-- - @declare +-- - @begin +-- - @end +-- - schema +-- - region +@declare_schema_region root_region; +@begin_schema_region root_region; +@end_schema_region; + +-- TEST: select with redundant cast and alias +-- + "SELECT (5), T.xyzzy " +-- + "FROM (SELECT 1 AS xyzzy) AS T"); +create proc redundant_cast() +begin + select CAST(5 as integer) plugh, T.xyzzy five from (select 1 xyzzy) as T; +end; + +-- TEST: select with alias in view +-- + "CREATE VIEW alias_preserved AS " +-- + "SELECT (5) AS plugh, T.xyzzy AS five " +-- + "FROM (SELECT 1 AS xyzzy) AS T"); +create proc view_creator() +begin + create view alias_preserved as + select CAST(5 as integer) plugh, T.xyzzy five from (select 1 xyzzy) as T; +end; + +create table switch_account_badges(badge_count integer); +create table unread_pending_threads(unread_pending_thread_count integer); + +-- TEST: nested select table should not have column aliases removed +-- + "SELECT SUM(A.unread_pending_thread_count), SUM(A.switch_account_badge_count) " +-- + "FROM (SELECT P.unread_pending_thread_count AS unread_pending_thread_count, 0 AS switch_account_badge_count " +-- + "FROM unread_pending_threads AS P " +-- + "UNION ALL " +-- + "SELECT 0 AS unread_pending_thread_count, S.badge_count AS switch_account_badge_count " +-- + "FROM switch_account_badges AS S) AS A"); +CREATE PROC settings_info () +BEGIN + declare C cursor for + SELECT SUM(A.unread_pending_thread_count) AS unread_pending_thread_count, + SUM(A.switch_account_badge_count) AS switch_account_badge_count + FROM (SELECT P.unread_pending_thread_count AS unread_pending_thread_count, 0 AS switch_account_badge_count + FROM unread_pending_threads AS P + UNION ALL + SELECT 0 AS unread_pending_thread_count, S.badge_count AS switch_account_badge_count + FROM switch_account_badges AS S) AS A; +END; + +-- TEST: try to use a WITH_SELECT form in a select expression +-- + _rc_ = cql_prepare(_db_, &_temp_stmt, +-- + "WITH " +-- + "threads2 (count) AS (SELECT 1) " +-- + "SELECT COUNT(*) " +-- + "FROM threads2"); +create proc use_with_select() +begin + declare x integer; + SET x := (WITH threads2 (count) AS (SELECT 1 foo) SELECT COUNT(*) FROM threads2); +end; + +-- declare a simple table-valued function +declare select function ReadFromRowset(rowset Object) (id integer); + +-- TEST: use a table valued function that consumes an object +-- + cql_multibind(&_rc_, _db_, &C, 1, +-- + CQL_DATA_TYPE_OBJECT, rowset); +create proc rowset_object_reader(rowset Object) +begin + declare C cursor for select * from ReadFromRowset(rowset); +end; + +-- TEST: codegen upsert statement with update statement +-- + "INSERT INTO foo(id) SELECT id " +-- + "FROM bar " +-- + "WHERE 1 " +-- + "ON CONFLICT (id) DO UPDATE " +-- + "SET id = 10 " +-- + "WHERE id <> 10" +-- + cql_code upsert_do_something(sqlite3 *_Nonnull _db_) { +create proc upsert_do_something() +BEGIN + insert into foo select id from bar where 1 on conflict(id) do update set id=10 where id != 10; +END; + +-- TEST: codegen with upsert statement form +-- + cql_code with_upsert_form(sqlite3 *_Nonnull _db_) { +-- + "WITH " +-- + "names (id) AS (VALUES(1), (5), (3), (12)) " +-- + "INSERT INTO foo(id) SELECT id " +-- + "FROM names " +-- + "WHERE 1 " +-- + "ON CONFLICT (id) DO UPDATE " +-- + "SET id = 10 " +-- + "WHERE id <> 10"); +create proc with_upsert_form() +BEGIN + with names(id) as (values (1), (5), (3), (12)) + insert into foo select id from names where 1 on conflict(id) do update set id = 10 where id != 10; +END; + +-- TEST: codegen upsert statement with do nothing +-- + "INSERT INTO foo(id) VALUES(?) " +-- + "ON CONFLICT DO NOTHING" +-- + cql_code upsert_do_nothing(sqlite3 *_Nonnull _db_, cql_int32 id_) { +create proc upsert_do_nothing(id_ integer not null) +BEGIN + insert into foo(id) values(id_) on conflict do nothing; +END; + +-- TEST: codegen with-insert with a seed +-- + _seed_ = 1337; +-- + _rc_ = cql_exec(_db_, +-- + "WITH " +-- + "foo (id) AS (SELECT 1 AS id) " +-- + "INSERT INTO bar(id) VALUES(ifnull(( SELECT id " +-- + "FROM foo ), 0))"); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +with foo(id) as (select 1 id) +insert into bar(id) +values (ifnull((select id from foo), 0)) +@dummy_seed(1337); + +-- TEST: codegen upsert with a seed +-- + _seed_ = 1338; +-- + _rc_ = cql_exec(_db_, +-- + "INSERT INTO bar(id) VALUES(1) " +-- + "ON CONFLICT (id) DO UPDATE " +-- + "SET id = 10"); +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +insert into bar(id) values(1) @dummy_seed(1338) +on conflict(id) do +update set id=10; + +-- TEST: set up a couple of out cursor procs (body not needed) +declare procedure p1() out (id integer not null, t text); +declare procedure p2() out (id integer not null, t text) using transaction; + +-- TEST: this test forces several out cursors to go into the symbol table +-- the idea is that it reveals any cases where a temporary pointer is +-- stored into the symbol table as was the case with the temporary +-- row data for each cursor. The test is this: is c2 properly emitted? +-- + use_many_out_cursors_c1_row c1_ = { ._refs_count_ = 1, ._refs_offset_ = use_many_out_cursors_c1_refs_offset }; +-- + use_many_out_cursors_c2_row c2_ = { ._refs_count_ = 1, ._refs_offset_ = use_many_out_cursors_c2_refs_offset }; +-- +1 p1((p1_row *)&c1_); +-- +1 _rc_ = p2(_db_, (p2_row *)&c2_); +-- +2 cql_teardown_row(c1_); +-- +2 cql_teardown_row(c2_); +create procedure use_many_out_cursors() +begin + declare c1 cursor fetch from call p1(); + declare c2 cursor fetch from call p2(); +end; + +-- TEST: each fetch forces the declaration of the cursor storage if it has +-- not already been declared. In this case the third branch of the if +-- must find that p1 and p2 row data are already declare and not duplicate +-- the declarations. +-- +1 fetch_many_times_C_row C_ = { ._refs_count_ = 1, ._refs_offset_ = fetch_many_times_C_refs_offset }; +-- +2 p1((p1_row *)&C_); +-- +2 _rc_ = p2(_db_, (p2_row *)&C_); +-- +5 cql_teardown_row(C_); +create procedure fetch_many_times(arg bool not null) +begin + declare C cursor like p1; + if arg == 1 then + fetch C from call p1(); + else if arg == 2 then + fetch C from call p2(); + else + fetch C from call p1(); + fetch C from call p2(); + end if; +end; + +-- TEST: create a result set from rows values +-- + void out_union_two_fetch_results(out_union_two_result_set_ref _Nullable *_Nonnull _result_set_) { +-- + cql_profile_start(CRC_out_union_two, &out_union_two_perf_index); +-- + cql_bytebuf _rows_; +-- + cql_bytebuf_open(&_rows_); +-- +2 cql_retain_row(C_); +-- +2 if (C_._has_row_) cql_bytebuf_append(&_rows_, (const void *)&C_, sizeof(C_)); +-- + cql_results_from_data(SQLITE_OK, &_rows_, &out_union_two_info, (cql_result_set_ref *)_result_set_); +-- + cql_teardown_row(C_); +create proc out_union_two() +begin + declare C cursor like select 1 x, '2' y; + fetch C from values(1, "y"); + out union C; + out union C; +end; + +-- TEST: read back the two rows from the above +-- + CQL_WARN_UNUSED cql_code out_union_reader(sqlite3 *_Nonnull _db_) { +-- + out_union_two_result_set_ref c_result_set_ = NULL; +-- + cql_int32 c_row_num_ = 0; +-- + cql_int32 c_row_count_ = 0; +-- + out_union_reader_c_row c_ = { ._refs_count_ = 1, ._refs_offset_ = out_union_reader_c_refs_offset }; +-- + out_union_two_fetch_results(&c_result_set_); +-- + c_row_num_ = c_row_count_ = -1; +-- + c_row_count_ = cql_result_set_get_count((cql_result_set_ref)c_result_set_); +-- + for (;;) { +-- + C_row_num_++; +-- + C_._has_row_ = C_row_num_ < C_row_count_; +-- + cql_copyoutrow((cql_result_set_ref)C_result_set_, C_row_num_, 2, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, &C_.x, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_STRING, &C_.y); +-- NOT PRESENT !! +-- - if (_rc_ != SQLITE_ROW && _rc_ != SQLITE_DONE) goto cql_cleanup; +-- + if (!C_._has_row_) break; +-- + } +-- + cql_object_release(c_result_set_); +-- + cql_teardown_row(c_); +-- + return _rc_; +create proc out_union_reader() +begin + declare c cursor for call out_union_two(); + loop fetch C + begin + call printf("%d %s\n", C.x, C.y); + end; +end; + +-- TEST: create a result set from selected rows +-- + cql_bytebuf _rows_; +-- + cql_bytebuf_open(&_rows_); +-- +2 cql_retain_row(C_); +-- +2 if (C_._has_row_) cql_bytebuf_append(&_rows_, (const void *)&C_, sizeof(C_)); +-- + cql_results_from_data(_rc_, &_rows_, &out_union_from_select_info, (cql_result_set_ref *)_result_set_); +-- + cql_teardown_row(C_); +create proc out_union_from_select() +begin + declare C cursor for select 1 x, '2' y; + fetch C; + out union C; + out union C; +end; + +-- TEST: reading from out union again, this time a DML proc (uses select) +-- slightly different call path +-- + _rc_ = out_union_from_select_fetch_results(_db_, &c_result_set_); +-- + c_row_num_ = c_row_count_ = -1; +-- + if (_rc_ != SQLITE_OK) goto cql_cleanup; +-- + c_row_count_ = cql_result_set_get_count((cql_result_set_ref)c_result_set_); +create proc out_union_dml_reader() +begin + declare c cursor for call out_union_from_select(); + loop fetch C + begin + call printf("%d %s\n", C.x, C.y); + end; +end; + + +-- This just sets up a call to a procedure that takes two integers +create proc out_union_values(a integer not null, b integer not null) +begin + declare x cursor like select 1 x, 2 y; + fetch x from values(a,b); + out union x; +end; + +-- TEST: we need to be able to call the above proc, this requires +-- the args be emitted correctly, with a comma (!) +-- + out_union_values_fetch_results(&C_result_set_, a, b); +-- + C_row_num_ = C_row_count_ = -1; +-- + C_row_count_ = cql_result_set_get_count((cql_result_set_ref)C_result_set_); +-- + C_row_num_++; +-- + C_._has_row_ = C_row_num_ < C_row_count_; +-- + cql_copyoutrow((cql_result_set_ref)C_result_set_, C_row_num_, 2, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, &C_.x, +-- + CQL_DATA_TYPE_NOT_NULL | CQL_DATA_TYPE_INT32, &C_.y); +create proc read_out_union_values(a integer not null, b integer not null) +begin + declare C cursor for call out_union_values(a,b); + fetch C; +end; + +-- TEST: generate a compound select statement in an expression (this is a legal form) +-- + _rc_ = cql_prepare(_db_, &_temp_stmt, +-- + "SELECT 1 " +-- + "WHERE 0 " +-- + "UNION " +-- + "SELECT 2 " +-- + "LIMIT 1"); +create proc compound_select_expr() +begin + declare x integer; + set x := (select 1 where 0 union select 2 limit 1); +end; + +-- TEST: generate window function invocation +-- + "SELECT id, " +-- + "row_number() OVER () " +-- + "FROM foo"); +create proc window_function_invocation() +begin + select id, row_number() over () as row_num from foo; +end; + +-- TEST: update some of the cursor columns +-- + if (C_._has_row_) { +-- + C_.x = 2; +-- + } +create proc update_cursor() +begin + declare C cursor like select 1 x, 2 y; + update cursor C(x) from values (2); +end; + +-- TEST: make sure decl output is correct for DML out union +-- + DECLARE PROC out_union_with_dml (id INTEGER) OUT UNION (id INTEGER NOT NULL) USING TRANSACTION; +declare proc out_union_with_dml(id integer) out union (id integer not null) using transaction; + +-- TEST: make sure decl output is correct for non-DML out union +-- + DECLARE PROC out_union_no_dml (id INTEGER) OUT UNION (id INTEGER NOT NULL); +declare proc out_union_no_dml(id integer) out union (id integer not null); + +-- TEST: emit goto cql_cleanup in case of return +-- + goto cql_cleanup; // return +-- + cql_cleanup: +create proc use_return() +begin + begin try + select 1 x; + end try; + begin catch + return; + end catch; +end; + +-- TEST: emit goto cql_cleanup in case of return, force the label even if not +-- used for any other error processing +-- + goto cql_cleanup; // return +-- + cql_cleanup: +create proc use_return_no_error_flow() +begin + if 1 then + return; + end if; +end; + +-- TEST: empty proc body +-- + CREATE PROC empty_proc () +-- + BEGIN +-- + END; +-- + void empty_proc(void) { +-- + cql_cleanup: +-- + ; // label requires some statement +-- + } +create proc empty_proc() +begin +end; + +-- TEST: empty body parts, all statment list types +-- nothing really to validate here; if any of the empty cases +-- are not handled it will crash. If the blocks are badly shaped +-- it won't compile. Can't think of anything that isn't redundant here +-- + CREATE PROC empty_blocks () +create proc empty_blocks() +begin + if 1 then + end if; + + if 2 then + else + end if; + + if 3 then + else if 4 + then + else + end if; + + while 1 + begin + end; + + declare c cursor for select 1 x; + loop fetch c + begin + end; + + begin try + end try; + begin catch + end catch; +end; + +-- This proc illustrates a case where we need to put the ; +-- after the catch label so that there is a statement. Note +-- the problem is that two catches end in a row. The fact that +-- the bodies of the functions are empty changes nothing. It only +-- matters that we had end catch and then end some other block +-- so empty statement lists are not required to make this issue happen +-- + CQL_WARN_UNUSED cql_code tail_catch(sqlite3 *_Nonnull _db_) { +-- +2 // try +-- + goto catch_end_6; +-- + goto catch_end_7; +-- mandatory ; after this label +-- + catch_end_7:; +-- + catch_end_6:; +create proc tail_catch() +begin + begin try + end try; + begin catch + begin try + end try; + begin catch + end catch; + end catch; +end; + +-- TEST: the SQL output will include an escaped quote '' +-- this used to fool us into thinking we had left quoted mode +-- and so later characters would not be correctly escaped in the output +-- in particular the newline would get messed up because we thought +-- it was a line break in non-quoted SQL which can be replaced with a space +-- note the newline is escaped and present +-- + "INSERT INTO bar(id, name) VALUES(1, 'it''s high noon\r\n\f\b\t\v')"); +create proc pretty_print_with_quote() +begin + insert into bar(id, name) values(1, "it's high noon\r\n\f\b\t\v"); +end; + +-- TEST: string literal with hex forms +-- + "INSERT INTO bar(id, name) VALUES(1, '\x01\x02\xa1\x1bg')"); +create proc hex_quote() +begin + insert into bar(id, name) values(1, "\x01\x02\xA1\x1b\x00\xg"); +end; + +-- TEST: no getters generated for this function +-- getters go into the .h stream and there's no test hook for that +-- but this can be verified by checking the .ref for the header file manually +-- We verify that we are still generating the data types (only the getters are suppressed) +-- + CQL_DATA_TYPE_INT32 | CQL_DATA_TYPE_NOT_NULL, // id +-- + CQL_DATA_TYPE_STRING, // name +-- + CQL_DATA_TYPE_INT64, // rate +-- + CQL_DATA_TYPE_INT32, // type +-- + CQL_DATA_TYPE_DOUBLE, // size +@attribute(cql:suppress_getters) +create proc lotsa_columns_no_getters() +begin + select * from bar; +end; + +-- TEST: make sure that _rc_ is set to SQLITE_OK when we return +-- + _rc_ = SQLITE_OK; // clean up any SQLITE_ROW value or other non-error +-- + goto cql_cleanup; // return +create proc early_out_rc_cleared(out x integer) +begin + declare C cursor for select 1 x; + fetch C; + if C then + return; + end if; +end; + +create table ext_test_table ( + f1 integer not null, + f2 integer not null, + f3 integer not null +); + +-- TEST: define a base fragment, no output for this +-- - get +-- - set +-- - void +-- - return +@attribute(cql:base_fragment=frag_test) +create proc baseline() +begin + with + frag_test(*) as (select 1 id) + select * from frag_test; +end; + +-- TEST: extension creates getters for the base columns and the new columns it added +-- + cql_int32 ext_get_id(frag_test_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + return frag_test_get_id(result_set, row); +-- + cql_bool ext_get_f2_is_null(frag_test_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + return __PRIVATE__frag_test_get_f2_is_null(result_set, row); +-- + cql_int32 ext_get_f2_value(frag_test_result_set_ref _Nonnull result_set, cql_int32 row) { +-- + return __PRIVATE__frag_test_get_f2_value(result_set, row); +-- + cql_int32 ext_result_count(frag_test_result_set_ref _Nonnull result_set) { +-- + return cql_result_set_get_count((cql_result_set_ref)result_set); +@attribute(cql:extension_fragment=frag_test) +create proc ext() +begin + with + frag_test(*) as (select 1 id), + ext(*) as (select frag_test.*, f2 from frag_test left outer join ext_test_table on f1 = id) + select * from ext; +end; + +-- TEST: another extension, this one should not include anything about f2, it doesn't "know" about that column +-- - f2 +@attribute(cql:extension_fragment=frag_test) +create proc ext2() +begin + with + frag_test(*) as (select 1 id), + ext2(*) as (select frag_test.*, f3 from frag_test left outer join ext_test_table on f1 = id) + select * from ext2; +end; + +-------------------------------------------------------------------- +-------------------- add new tests before this point --------------- +-------------------------------------------------------------------- +create proc end_proc() begin declare x integer; end; +-- TEST: end marker -- this is the last test +-- + cql_nullable_int32 end_marker; +-- + cql_code cql_startup(sqlite3 *_Nonnull _db_) +declare end_marker integer; +-------------------------------------------------------------------- diff --git a/playground/test.flex b/playground/test.flex new file mode 100644 index 0000000..a3c4735 --- /dev/null +++ b/playground/test.flex @@ -0,0 +1,58 @@ + // An example of using the flex C++ scanner class. + +%option C++ noyywrap + +%{ +int mylineno = 0; +%} + +string \"[^\n"]+\" + +ws [ \t]+ + +alpha [A-Za-z] +dig [0-9] +name ({alpha}|{dig}|\$)({alpha}|{dig}|\_|\.|\-|\/|\$)* +num1 [-+]?{dig}+\.?([eE][-+]?{dig}+)? +num2 [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)? +number {num1}|{num2} + +%% + +{ws} /* skip blanks and tabs */ + +"/*" { + int c; + + while((c = yyinput()) != 0) + { + if(c == '\n') + ++mylineno; + + else if(c == '*') + { + if((c = yyinput()) == '/') + break; + else + unput(c); + } + } + } + +{number} std::cout << "number " << YYText() << '\n'; + +\n mylineno++; + +{name} std::cout << "name " << YYText() << '\n'; + +{string} std::cout << "string " << YYText() << '\n'; + +%% + +int main( int /* argc */, char** /* argv */ ) + { + FlexLexer* lexer = new yyFlexLexer; + while(lexer->yylex() != 0) + ; + return 0; + } diff --git a/playground/test.go b/playground/test.go new file mode 100644 index 0000000..3617493 --- /dev/null +++ b/playground/test.go @@ -0,0 +1,2712 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go tool yacc go.y +//go:generate go run mkbuiltin.go runtime unsafe + +package gc + +import ( + "bytes" + "cmd/internal/obj" + "flag" + "fmt" + "io" + "log" + "os" + "path" + "strconv" + "strings" + "unicode" + "unicode/utf8" +) + +var yyprev int + +var yylast int + +var imported_unsafe bool + +var ( + goos string + goarch string + goroot string + buildid string +) + +var ( + Debug_append int + Debug_panic int + Debug_slice int + Debug_wb int +) + +// Debug arguments. +// These can be specified with the -d flag, as in "-d nil" +// to set the debug_checknil variable. In general the list passed +// to -d can be comma-separated. +var debugtab = []struct { + name string + val *int +}{ + {"append", &Debug_append}, // print information about append compilation + {"disablenil", &Disable_checknil}, // disable nil checks + {"gcprog", &Debug_gcprog}, // print dump of GC programs + {"nil", &Debug_checknil}, // print information about nil checks + {"panic", &Debug_panic}, // do not hide any compiler panic + {"slice", &Debug_slice}, // print information about slice compilation + {"typeassert", &Debug_typeassert}, // print information about type assertion inlining + {"wb", &Debug_wb}, // print information about write barriers + {"export", &Debug_export}, // print export data +} + +const ( + EOF = -1 +) + +func usage() { + fmt.Printf("usage: compile [options] file.go...\n") + obj.Flagprint(1) + Exit(2) +} + +func hidePanic() { + if Debug_panic == 0 && nsavederrors+nerrors > 0 { + // If we've already complained about things + // in the program, don't bother complaining + // about a panic too; let the user clean up + // the code and try again. + if err := recover(); err != nil { + errorexit() + } + } +} + +func doversion() { + p := obj.Expstring() + if p == "X:none" { + p = "" + } + sep := "" + if p != "" { + sep = " " + } + fmt.Printf("compile version %s%s%s\n", obj.Getgoversion(), sep, p) + os.Exit(0) +} + +func Main() { + defer hidePanic() + + // Allow GOARCH=thearch.thestring or GOARCH=thearch.thestringsuffix, + // but not other values. + p := obj.Getgoarch() + + if !strings.HasPrefix(p, Thearch.Thestring) { + log.Fatalf("cannot use %cg with GOARCH=%s", Thearch.Thechar, p) + } + goarch = p + + Thearch.Linkarchinit() + Ctxt = obj.Linknew(Thearch.Thelinkarch) + Ctxt.Diag = Yyerror + Ctxt.Bso = &bstdout + bstdout = *obj.Binitw(os.Stdout) + + localpkg = mkpkg("") + localpkg.Prefix = "\"\"" + + // pseudo-package, for scoping + builtinpkg = mkpkg("go.builtin") + + builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin + + // pseudo-package, accessed by import "unsafe" + unsafepkg = mkpkg("unsafe") + + unsafepkg.Name = "unsafe" + + // real package, referred to by generated runtime calls + Runtimepkg = mkpkg("runtime") + + Runtimepkg.Name = "runtime" + + // pseudo-packages used in symbol tables + gostringpkg = mkpkg("go.string") + + gostringpkg.Name = "go.string" + gostringpkg.Prefix = "go.string" // not go%2estring + + itabpkg = mkpkg("go.itab") + + itabpkg.Name = "go.itab" + itabpkg.Prefix = "go.itab" // not go%2eitab + + weaktypepkg = mkpkg("go.weak.type") + + weaktypepkg.Name = "go.weak.type" + weaktypepkg.Prefix = "go.weak.type" // not go%2eweak%2etype + + typelinkpkg = mkpkg("go.typelink") + typelinkpkg.Name = "go.typelink" + typelinkpkg.Prefix = "go.typelink" // not go%2etypelink + + trackpkg = mkpkg("go.track") + + trackpkg.Name = "go.track" + trackpkg.Prefix = "go.track" // not go%2etrack + + typepkg = mkpkg("type") + + typepkg.Name = "type" + + goroot = obj.Getgoroot() + goos = obj.Getgoos() + + Nacl = goos == "nacl" + if Nacl { + flag_largemodel = 1 + } + + outfile = "" + obj.Flagcount("+", "compiling runtime", &compiling_runtime) + obj.Flagcount("%", "debug non-static initializers", &Debug['%']) + obj.Flagcount("A", "for bootstrapping, allow 'any' type", &Debug['A']) + obj.Flagcount("B", "disable bounds checking", &Debug['B']) + obj.Flagstr("D", "set relative `path` for local imports", &localimport) + obj.Flagcount("E", "debug symbol export", &Debug['E']) + obj.Flagfn1("I", "add `directory` to import search path", addidir) + obj.Flagcount("K", "debug missing line numbers", &Debug['K']) + obj.Flagcount("L", "use full (long) path in error messages", &Debug['L']) + obj.Flagcount("M", "debug move generation", &Debug['M']) + obj.Flagcount("N", "disable optimizations", &Debug['N']) + obj.Flagcount("P", "debug peephole optimizer", &Debug['P']) + obj.Flagcount("R", "debug register optimizer", &Debug['R']) + obj.Flagcount("S", "print assembly listing", &Debug['S']) + obj.Flagfn0("V", "print compiler version", doversion) + obj.Flagcount("W", "debug parse tree after type checking", &Debug['W']) + obj.Flagstr("asmhdr", "write assembly header to `file`", &asmhdr) + obj.Flagstr("buildid", "record `id` as the build id in the export metadata", &buildid) + obj.Flagcount("complete", "compiling complete package (no C or assembly)", &pure_go) + obj.Flagstr("d", "print debug information about items in `list`", &debugstr) + obj.Flagcount("e", "no limit on number of errors reported", &Debug['e']) + obj.Flagcount("f", "debug stack frames", &Debug['f']) + obj.Flagcount("g", "debug code generation", &Debug['g']) + obj.Flagcount("h", "halt on error", &Debug['h']) + obj.Flagcount("i", "debug line number stack", &Debug['i']) + obj.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap) + obj.Flagstr("installsuffix", "set pkg directory `suffix`", &flag_installsuffix) + obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j']) + obj.Flagcount("l", "disable inlining", &Debug['l']) + obj.Flagcount("live", "debug liveness analysis", &debuglive) + obj.Flagcount("m", "print optimization decisions", &Debug['m']) + obj.Flagcount("msan", "build code compatible with C/C++ memory sanitizer", &flag_msan) + obj.Flagcount("newexport", "use new export format", &newexport) // TODO(gri) remove eventually (issue 13241) + obj.Flagcount("oldparser", "use old parser", &oldparser) // TODO(gri) remove eventually (issue 13240) + obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports) + obj.Flagstr("o", "write output to `file`", &outfile) + obj.Flagstr("p", "set expected package import `path`", &myimportpath) + obj.Flagcount("pack", "write package file instead of object file", &writearchive) + obj.Flagcount("r", "debug generated wrappers", &Debug['r']) + obj.Flagcount("race", "enable race detector", &flag_race) + obj.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s']) + obj.Flagstr("trimpath", "remove `prefix` from recorded source file paths", &Ctxt.LineHist.TrimPathPrefix) + obj.Flagcount("u", "reject unsafe code", &safemode) + obj.Flagcount("v", "increase debug verbosity", &Debug['v']) + obj.Flagcount("w", "debug type checking", &Debug['w']) + use_writebarrier = 1 + obj.Flagcount("wb", "enable write barrier", &use_writebarrier) + obj.Flagcount("x", "debug lexer", &Debug['x']) + obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y']) + var flag_shared int + var flag_dynlink bool + switch Thearch.Thechar { + case '5', '6', '7', '8', '9': + obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared) + } + if Thearch.Thechar == '6' { + obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel) + } + switch Thearch.Thechar { + case '5', '6', '7', '8', '9': + flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries") + } + obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile) + obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile) + obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate) + obj.Flagparse(usage) + + if flag_dynlink { + flag_shared = 1 + } + Ctxt.Flag_shared = int32(flag_shared) + Ctxt.Flag_dynlink = flag_dynlink + + Ctxt.Debugasm = int32(Debug['S']) + Ctxt.Debugvlog = int32(Debug['v']) + + if flag.NArg() < 1 { + usage() + } + + startProfile() + + if flag_race != 0 { + racepkg = mkpkg("runtime/race") + racepkg.Name = "race" + } + if flag_msan != 0 { + msanpkg = mkpkg("runtime/msan") + msanpkg.Name = "msan" + } + if flag_race != 0 && flag_msan != 0 { + log.Fatal("can not use both -race and -msan") + } else if flag_race != 0 || flag_msan != 0 { + instrumenting = true + } + + // parse -d argument + if debugstr != "" { + Split: + for _, name := range strings.Split(debugstr, ",") { + if name == "" { + continue + } + val := 1 + if i := strings.Index(name, "="); i >= 0 { + var err error + val, err = strconv.Atoi(name[i+1:]) + if err != nil { + log.Fatalf("invalid debug value %v", name) + } + name = name[:i] + } + for _, t := range debugtab { + if t.name == name { + if t.val != nil { + *t.val = val + continue Split + } + } + } + log.Fatalf("unknown debug key -d %s\n", name) + } + } + + // enable inlining. for now: + // default: inlining on. (debug['l'] == 1) + // -l: inlining off (debug['l'] == 0) + // -ll, -lll: inlining on again, with extra debugging (debug['l'] > 1) + if Debug['l'] <= 1 { + Debug['l'] = 1 - Debug['l'] + } + + Thearch.Betypeinit() + if Widthptr == 0 { + Fatalf("betypeinit failed") + } + + lexinit() + typeinit() + lexinit1() + // TODO(rsc): Restore yytinit? + + blockgen = 1 + dclcontext = PEXTERN + nerrors = 0 + lexlineno = 1 + const BOM = 0xFEFF + + // Uncomment the line below to temporarily switch the compiler back + // to the yacc-based parser. Short-term work-around for issues with + // the new recursive-descent parser for which setting -oldparser is + // not sufficient. + // TODO(gri) remove this eventually (issue 13240) + // + // oldparser = 1 + + for _, infile = range flag.Args() { + if trace && Debug['x'] != 0 && oldparser == 0 { + fmt.Printf("--- %s ---\n", infile) + } + + linehistpush(infile) + + curio.infile = infile + var err error + curio.bin, err = obj.Bopenr(infile) + if err != nil { + fmt.Printf("open %s: %v\n", infile, err) + errorexit() + } + + curio.peekc = 0 + curio.peekc1 = 0 + curio.nlsemi = false + curio.eofnl = false + curio.last = 0 + + // Skip initial BOM if present. + if obj.Bgetrune(curio.bin) != BOM { + obj.Bungetrune(curio.bin) + } + + block = 1 + iota_ = -1000000 + + imported_unsafe = false + + yyparse() + if nsyntaxerrors != 0 { + errorexit() + } + + linehistpop() + if curio.bin != nil { + obj.Bterm(curio.bin) + } + } + + testdclstack() + mkpackage(localpkg.Name) // final import not used checks + lexfini() + + typecheckok = true + if Debug['f'] != 0 { + frame(1) + } + + // Process top-level declarations in phases. + + // Phase 1: const, type, and names and types of funcs. + // This will gather all the information about types + // and methods but doesn't depend on any of it. + defercheckwidth() + + for l := xtop; l != nil; l = l.Next { + if l.N.Op != ODCL && l.N.Op != OAS && l.N.Op != OAS2 { + typecheck(&l.N, Etop) + } + } + + // Phase 2: Variable assignments. + // To check interface assignments, depends on phase 1. + for l := xtop; l != nil; l = l.Next { + if l.N.Op == ODCL || l.N.Op == OAS || l.N.Op == OAS2 { + typecheck(&l.N, Etop) + } + } + resumecheckwidth() + + // Phase 3: Type check function bodies. + for l := xtop; l != nil; l = l.Next { + if l.N.Op == ODCLFUNC || l.N.Op == OCLOSURE { + Curfn = l.N + decldepth = 1 + saveerrors() + typechecklist(l.N.Nbody, Etop) + checkreturn(l.N) + if nerrors != 0 { + l.N.Nbody = nil // type errors; do not compile + } + } + } + + // Phase 4: Decide how to capture closed variables. + // This needs to run before escape analysis, + // because variables captured by value do not escape. + for l := xtop; l != nil; l = l.Next { + if l.N.Op == ODCLFUNC && l.N.Func.Closure != nil { + Curfn = l.N + capturevars(l.N) + } + } + + Curfn = nil + + if nsavederrors+nerrors != 0 { + errorexit() + } + + // Phase 5: Inlining + if Debug['l'] > 1 { + // Typecheck imported function bodies if debug['l'] > 1, + // otherwise lazily when used or re-exported. + for _, n := range importlist { + if n.Func.Inl != nil { + saveerrors() + typecheckinl(n) + } + } + + if nsavederrors+nerrors != 0 { + errorexit() + } + } + + if Debug['l'] != 0 { + // Find functions that can be inlined and clone them before walk expands them. + visitBottomUp(xtop, func(list []*Node, recursive bool) { + // TODO: use a range statement here if the order does not matter + for i := len(list) - 1; i >= 0; i-- { + n := list[i] + if n.Op == ODCLFUNC { + caninl(n) + inlcalls(n) + } + } + }) + } + + // Phase 6: Escape analysis. + // Required for moving heap allocations onto stack, + // which in turn is required by the closure implementation, + // which stores the addresses of stack variables into the closure. + // If the closure does not escape, it needs to be on the stack + // or else the stack copier will not update it. + // Large values are also moved off stack in escape analysis; + // because large values may contain pointers, it must happen early. + escapes(xtop) + + // Phase 7: Transform closure bodies to properly reference captured variables. + // This needs to happen before walk, because closures must be transformed + // before walk reaches a call of a closure. + for l := xtop; l != nil; l = l.Next { + if l.N.Op == ODCLFUNC && l.N.Func.Closure != nil { + Curfn = l.N + transformclosure(l.N) + } + } + + Curfn = nil + + // Phase 8: Compile top level functions. + for l := xtop; l != nil; l = l.Next { + if l.N.Op == ODCLFUNC { + funccompile(l.N) + } + } + + if nsavederrors+nerrors == 0 { + fninit(xtop) + } + + if compiling_runtime != 0 { + checknowritebarrierrec() + } + + // Phase 9: Check external declarations. + for i, n := range externdcl { + if n.Op == ONAME { + typecheck(&externdcl[i], Erv) + } + } + + if nerrors+nsavederrors != 0 { + errorexit() + } + + dumpobj() + + if asmhdr != "" { + dumpasmhdr() + } + + if nerrors+nsavederrors != 0 { + errorexit() + } + + Flusherrors() +} + +var importMap = map[string]string{} + +func addImportMap(s string) { + if strings.Count(s, "=") != 1 { + log.Fatal("-importmap argument must be of the form source=actual") + } + i := strings.Index(s, "=") + source, actual := s[:i], s[i+1:] + if source == "" || actual == "" { + log.Fatal("-importmap argument must be of the form source=actual; source and actual must be non-empty") + } + importMap[source] = actual +} + +func saveerrors() { + nsavederrors += nerrors + nerrors = 0 +} + +func arsize(b *obj.Biobuf, name string) int { + var buf [ArhdrSize]byte + if _, err := io.ReadFull(b, buf[:]); err != nil { + return -1 + } + aname := strings.Trim(string(buf[0:16]), " ") + if !strings.HasPrefix(aname, name) { + return -1 + } + asize := strings.Trim(string(buf[48:58]), " ") + i, _ := strconv.Atoi(asize) + return i +} + +func skiptopkgdef(b *obj.Biobuf) bool { + // archive header + p := obj.Brdline(b, '\n') + if p == "" { + return false + } + if obj.Blinelen(b) != 8 { + return false + } + if p != "!\n" { + return false + } + + // symbol table may be first; skip it + sz := arsize(b, "__.GOSYMDEF") + + if sz >= 0 { + obj.Bseek(b, int64(sz), 1) + } else { + obj.Bseek(b, 8, 0) + } + + // package export block is next + sz = arsize(b, "__.PKGDEF") + + if sz <= 0 { + return false + } + return true +} + +func addidir(dir string) { + if dir == "" { + return + } + + var pp **Idir + for pp = &idirs; *pp != nil; pp = &(*pp).link { + } + *pp = new(Idir) + (*pp).link = nil + (*pp).dir = dir +} + +// is this path a local name? begins with ./ or ../ or / +func islocalname(name string) bool { + return strings.HasPrefix(name, "/") || + Ctxt.Windows != 0 && len(name) >= 3 && isAlpha(int(name[0])) && name[1] == ':' && name[2] == '/' || + strings.HasPrefix(name, "./") || name == "." || + strings.HasPrefix(name, "../") || name == ".." +} + +func findpkg(name string) (file string, ok bool) { + if islocalname(name) { + if safemode != 0 || nolocalimports != 0 { + return "", false + } + + // try .a before .6. important for building libraries: + // if there is an array.6 in the array.a library, + // want to find all of array.a, not just array.6. + file = fmt.Sprintf("%s.a", name) + if _, err := os.Stat(file); err == nil { + return file, true + } + file = fmt.Sprintf("%s.o", name) + if _, err := os.Stat(file); err == nil { + return file, true + } + return "", false + } + + // local imports should be canonicalized already. + // don't want to see "encoding/../encoding/base64" + // as different from "encoding/base64". + if q := path.Clean(name); q != name { + Yyerror("non-canonical import path %q (should be %q)", name, q) + return "", false + } + + for p := idirs; p != nil; p = p.link { + file = fmt.Sprintf("%s/%s.a", p.dir, name) + if _, err := os.Stat(file); err == nil { + return file, true + } + file = fmt.Sprintf("%s/%s.o", p.dir, name) + if _, err := os.Stat(file); err == nil { + return file, true + } + } + + if goroot != "" { + suffix := "" + suffixsep := "" + if flag_installsuffix != "" { + suffixsep = "_" + suffix = flag_installsuffix + } else if flag_race != 0 { + suffixsep = "_" + suffix = "race" + } else if flag_msan != 0 { + suffixsep = "_" + suffix = "msan" + } + + file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", goroot, goos, goarch, suffixsep, suffix, name) + if _, err := os.Stat(file); err == nil { + return file, true + } + file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.o", goroot, goos, goarch, suffixsep, suffix, name) + if _, err := os.Stat(file); err == nil { + return file, true + } + } + + return "", false +} + +func fakeimport() { + importpkg = mkpkg("fake") + cannedimports("fake.o", "$$\n") +} + +// TODO(gri) line argument doesn't appear to be used +func importfile(f *Val, line int) { + if _, ok := f.U.(string); !ok { + Yyerror("import statement not a string") + fakeimport() + return + } + + if len(f.U.(string)) == 0 { + Yyerror("import path is empty") + fakeimport() + return + } + + if isbadimport(f.U.(string)) { + fakeimport() + return + } + + // The package name main is no longer reserved, + // but we reserve the import path "main" to identify + // the main package, just as we reserve the import + // path "math" to identify the standard math package. + if f.U.(string) == "main" { + Yyerror("cannot import \"main\"") + errorexit() + } + + if myimportpath != "" && f.U.(string) == myimportpath { + Yyerror("import %q while compiling that package (import cycle)", f.U.(string)) + errorexit() + } + + if f.U.(string) == "unsafe" { + if safemode != 0 { + Yyerror("cannot import package unsafe") + errorexit() + } + + importpkg = mkpkg(f.U.(string)) + cannedimports("unsafe.o", unsafeimport) + imported_unsafe = true + return + } + + path_ := f.U.(string) + + if mapped, ok := importMap[path_]; ok { + path_ = mapped + } + + if islocalname(path_) { + if path_[0] == '/' { + Yyerror("import path cannot be absolute path") + fakeimport() + return + } + + prefix := Ctxt.Pathname + if localimport != "" { + prefix = localimport + } + cleanbuf := prefix + cleanbuf += "/" + cleanbuf += path_ + cleanbuf = path.Clean(cleanbuf) + path_ = cleanbuf + + if isbadimport(path_) { + fakeimport() + return + } + } + + file, found := findpkg(path_) + if !found { + Yyerror("can't find import: %q", f.U.(string)) + errorexit() + } + + importpkg = mkpkg(path_) + + // If we already saw that package, feed a dummy statement + // to the lexer to avoid parsing export data twice. + if importpkg.Imported { + tag := "" + if importpkg.Safe { + tag = "safe" + } + + p := fmt.Sprintf("package %s %s\n$$\n", importpkg.Name, tag) + cannedimports(file, p) + return + } + + importpkg.Imported = true + + var err error + var imp *obj.Biobuf + imp, err = obj.Bopenr(file) + if err != nil { + Yyerror("can't open import: %q: %v", f.U.(string), err) + errorexit() + } + + if strings.HasSuffix(file, ".a") { + if !skiptopkgdef(imp) { + Yyerror("import %s: not a package file", file) + errorexit() + } + } + + // check object header + p := obj.Brdstr(imp, '\n', 1) + + if p != "empty archive" { + if !strings.HasPrefix(p, "go object ") { + Yyerror("import %s: not a go object file", file) + errorexit() + } + + q := fmt.Sprintf("%s %s %s %s", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) + if p[10:] != q { + Yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q) + errorexit() + } + } + + // assume files move (get installed) + // so don't record the full path. + linehistpragma(file[len(file)-len(path_)-2:]) // acts as #pragma lib + + // In the importfile, if we find: + // $$\n (old format): position the input right after $$\n and return + // $$B\n (new format): import directly, then feed the lexer a dummy statement + + // look for $$ + var c int + for { + c = obj.Bgetc(imp) + if c < 0 { + break + } + if c == '$' { + c = obj.Bgetc(imp) + if c == '$' || c < 0 { + break + } + } + } + + // get character after $$ + if c >= 0 { + c = obj.Bgetc(imp) + } + + switch c { + case '\n': + // old export format + pushedio = curio + + curio.bin = imp + curio.peekc = 0 + curio.peekc1 = 0 + curio.infile = file + curio.nlsemi = false + typecheckok = true + + if oldparser == 0 { + push_parser() + } + + case 'B': + // new export format + obj.Bgetc(imp) // skip \n after $$B + Import(imp) + + // continue as if the package was imported before (see above) + tag := "" + if importpkg.Safe { + tag = "safe" + } + p := fmt.Sprintf("package %s %s\n$$\n", importpkg.Name, tag) + cannedimports(file, p) + + default: + Yyerror("no import in %q", f.U.(string)) + } +} + +func unimportfile() { + if oldparser == 0 { + pop_parser() + } + + if curio.bin != nil { + obj.Bterm(curio.bin) + curio.bin = nil + } else { + lexlineno-- // re correct sys.6 line number + } + + curio = pushedio + + pushedio.bin = nil + incannedimport = 0 + typecheckok = false +} + +func cannedimports(file string, cp string) { + lexlineno++ // if sys.6 is included on line 1, + + pushedio = curio + + curio.bin = nil + curio.peekc = 0 + curio.peekc1 = 0 + curio.infile = file + curio.cp = cp + curio.nlsemi = false + curio.importsafe = false + + typecheckok = true + incannedimport = 1 + + if oldparser == 0 { + push_parser() + } +} + +func isSpace(c int) bool { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' +} + +func isAlpha(c int) bool { + return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' +} + +func isDigit(c int) bool { + return '0' <= c && c <= '9' +} +func isAlnum(c int) bool { + return isAlpha(c) || isDigit(c) +} + +func plan9quote(s string) string { + if s == "" { + return "''" + } + for _, c := range s { + if c <= ' ' || c == '\'' { + return "'" + strings.Replace(s, "'", "''", -1) + "'" + } + } + return s +} + +func isfrog(c int) bool { + // complain about possibly invisible control characters + if c < ' ' { + return !isSpace(c) // exclude good white space + } + + if 0x7f <= c && c <= 0xa0 { // DEL, unicode block including unbreakable space. + return true + } + return false +} + +type Loophack struct { + next *Loophack + v bool +} + +var _yylex_lstk *Loophack + +func _yylex(yylval *yySymType) int32 { + var c1 int + var escflag int + var v int64 + var cp *bytes.Buffer + var s *Sym + var h *Loophack + var str string + + prevlineno = lineno + +l0: + c := getc() + if isSpace(c) { + if c == '\n' && curio.nlsemi { + ungetc(c) + if Debug['x'] != 0 { + fmt.Printf("lex: implicit semi\n") + } + return ';' + } + + goto l0 + } + + lineno = lexlineno // start of token + + if c >= utf8.RuneSelf { + // all multibyte runes are alpha + cp = &lexbuf + cp.Reset() + + goto talph + } + + if isAlpha(c) { + cp = &lexbuf + cp.Reset() + goto talph + } + + if isDigit(c) { + cp = &lexbuf + cp.Reset() + if c != '0' { + for { + cp.WriteByte(byte(c)) + c = getc() + if isDigit(c) { + continue + } + if c == '.' { + goto casedot + } + if c == 'e' || c == 'E' || c == 'p' || c == 'P' { + goto caseep + } + if c == 'i' { + goto casei + } + goto ncu + } + } + + cp.WriteByte(byte(c)) + c = getc() + if c == 'x' || c == 'X' { + for { + cp.WriteByte(byte(c)) + c = getc() + if isDigit(c) { + continue + } + if c >= 'a' && c <= 'f' { + continue + } + if c >= 'A' && c <= 'F' { + continue + } + if lexbuf.Len() == 2 { + Yyerror("malformed hex constant") + } + if c == 'p' { + goto caseep + } + goto ncu + } + } + + if c == 'p' { // 0p begins floating point zero + goto caseep + } + + c1 = 0 + for { + if !isDigit(c) { + break + } + if c < '0' || c > '7' { + c1 = 1 // not octal + } + cp.WriteByte(byte(c)) + c = getc() + } + + if c == '.' { + goto casedot + } + if c == 'e' || c == 'E' { + goto caseep + } + if c == 'i' { + goto casei + } + if c1 != 0 { + Yyerror("malformed octal constant") + } + goto ncu + } + + switch c { + case EOF: + lineno = prevlineno + ungetc(EOF) + return -1 + + case '_': + cp = &lexbuf + cp.Reset() + goto talph + + case '.': + c1 = getc() + if isDigit(c1) { + cp = &lexbuf + cp.Reset() + cp.WriteByte(byte(c)) + c = c1 + goto casedot + } + + if c1 == '.' { + c1 = getc() + if c1 == '.' { + c = LDDD + goto lx + } + + ungetc(c1) + c1 = '.' + } + + // "..." + case '"': + lexbuf.Reset() + lexbuf.WriteString(`""`) + + cp = &strbuf + cp.Reset() + + for { + if escchar('"', &escflag, &v) { + break + } + if v < utf8.RuneSelf || escflag != 0 { + cp.WriteByte(byte(v)) + } else { + cp.WriteRune(rune(v)) + } + } + + goto strlit + + // `...` + case '`': + lexbuf.Reset() + lexbuf.WriteString("``") + + cp = &strbuf + cp.Reset() + + for { + c = int(getr()) + if c == '\r' { + continue + } + if c == EOF { + Yyerror("eof in string") + break + } + + if c == '`' { + break + } + cp.WriteRune(rune(c)) + } + + goto strlit + + // '.' + case '\'': + if escchar('\'', &escflag, &v) { + Yyerror("empty character literal or unescaped ' in character literal") + v = '\'' + } + + if !escchar('\'', &escflag, &v) { + Yyerror("missing '") + ungetc(int(v)) + } + + x := new(Mpint) + yylval.val.U = x + Mpmovecfix(x, v) + x.Rune = true + if Debug['x'] != 0 { + fmt.Printf("lex: codepoint literal\n") + } + litbuf = "string literal" + return LLITERAL + + case '/': + c1 = getc() + if c1 == '*' { + nl := false + for { + c = int(getr()) + if c == '\n' { + nl = true + } + for c == '*' { + c = int(getr()) + if c == '/' { + if nl { + ungetc('\n') + } + goto l0 + } + + if c == '\n' { + nl = true + } + } + + if c == EOF { + Yyerror("eof in comment") + errorexit() + } + } + } + + if c1 == '/' { + c = getlinepragma() + for { + if c == '\n' || c == EOF { + ungetc(c) + goto l0 + } + + c = int(getr()) + } + } + + if c1 == '=' { + c = int(ODIV) + goto asop + } + + case ':': + c1 = getc() + if c1 == '=' { + c = int(LCOLAS) + yylval.i = int(lexlineno) + goto lx + } + + case '*': + c1 = getc() + if c1 == '=' { + c = int(OMUL) + goto asop + } + + case '%': + c1 = getc() + if c1 == '=' { + c = int(OMOD) + goto asop + } + + case '+': + c1 = getc() + if c1 == '+' { + c = int(LINC) + goto lx + } + + if c1 == '=' { + c = int(OADD) + goto asop + } + + case '-': + c1 = getc() + if c1 == '-' { + c = int(LDEC) + goto lx + } + + if c1 == '=' { + c = int(OSUB) + goto asop + } + + case '>': + c1 = getc() + if c1 == '>' { + c = int(LRSH) + c1 = getc() + if c1 == '=' { + c = int(ORSH) + goto asop + } + + break + } + + if c1 == '=' { + c = int(LGE) + goto lx + } + + c = int(LGT) + + case '<': + c1 = getc() + if c1 == '<' { + c = int(LLSH) + c1 = getc() + if c1 == '=' { + c = int(OLSH) + goto asop + } + + break + } + + if c1 == '=' { + c = int(LLE) + goto lx + } + + if c1 == '-' { + c = int(LCOMM) + goto lx + } + + c = int(LLT) + + case '=': + c1 = getc() + if c1 == '=' { + c = int(LEQ) + goto lx + } + + case '!': + c1 = getc() + if c1 == '=' { + c = int(LNE) + goto lx + } + + case '&': + c1 = getc() + if c1 == '&' { + c = int(LANDAND) + goto lx + } + + if c1 == '^' { + c = int(LANDNOT) + c1 = getc() + if c1 == '=' { + c = int(OANDNOT) + goto asop + } + + break + } + + if c1 == '=' { + c = int(OAND) + goto asop + } + + case '|': + c1 = getc() + if c1 == '|' { + c = int(LOROR) + goto lx + } + + if c1 == '=' { + c = int(OOR) + goto asop + } + + case '^': + c1 = getc() + if c1 == '=' { + c = int(OXOR) + goto asop + } + + // clumsy dance: + // to implement rule that disallows + // if T{1}[0] { ... } + // but allows + // if (T{1}[0]) { ... } + // the block bodies for if/for/switch/select + // begin with an LBODY token, not '{'. + // + // when we see the keyword, the next + // non-parenthesized '{' becomes an LBODY. + // loophack is normally false. + // a keyword sets it to true. + // parens push loophack onto a stack and go back to false. + // a '{' with loophack == true becomes LBODY and disables loophack. + // + // I said it was clumsy. + // + // We only need the loophack when running with -oldparser. + case '(', '[': + if oldparser != 0 && (loophack || _yylex_lstk != nil) { + h = new(Loophack) + if h == nil { + Flusherrors() + Yyerror("out of memory") + errorexit() + } + + h.v = loophack + h.next = _yylex_lstk + _yylex_lstk = h + loophack = false + } + + goto lx + + case ')', ']': + if oldparser != 0 && _yylex_lstk != nil { + h = _yylex_lstk + loophack = h.v + _yylex_lstk = h.next + } + + goto lx + + case '{': + if oldparser != 0 && loophack { + if Debug['x'] != 0 { + fmt.Printf("%v lex: LBODY\n", Ctxt.Line(int(lexlineno))) + } + loophack = false + return LBODY + } + + goto lx + + default: + goto lx + } + + ungetc(c1) + +lx: + if c > 0xff { + if Debug['x'] != 0 { + fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lexlineno)), lexname(c)) + } + } else { + if Debug['x'] != 0 { + fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lexlineno)), c) + } + } + if isfrog(c) { + Yyerror("illegal character 0x%x", uint(c)) + goto l0 + } + + if importpkg == nil && (c == '#' || c == '$' || c == '?' || c == '@' || c == '\\') { + Yyerror("%s: unexpected %c", "syntax error", c) + goto l0 + } + + return int32(c) + +asop: + yylval.i = c // rathole to hold which asop + if Debug['x'] != 0 { + fmt.Printf("lex: TOKEN ASOP %c\n", c) + } + return LASOP + + // cp is set to lexbuf and some + // prefix has been stored +talph: + for { + if c >= utf8.RuneSelf { + ungetc(c) + r := rune(getr()) + + // 0xb7 · is used for internal names + if !unicode.IsLetter(r) && !unicode.IsDigit(r) && (importpkg == nil || r != 0xb7) { + Yyerror("invalid identifier character U+%04x", r) + } + if cp.Len() == 0 && unicode.IsDigit(r) { + Yyerror("identifier cannot begin with digit U+%04x", r) + } + cp.WriteRune(r) + } else if !isAlnum(c) && c != '_' { + break + } else { + cp.WriteByte(byte(c)) + } + c = getc() + } + + cp = nil + ungetc(c) + + s = LookupBytes(lexbuf.Bytes()) + switch s.Lexical { + case LIGNORE: + goto l0 + + case LFOR, LIF, LSWITCH, LSELECT: + if oldparser != 0 { + loophack = true // see comment about loophack above + } + } + + if Debug['x'] != 0 { + fmt.Printf("lex: %s %s\n", s, lexname(int(s.Lexical))) + } + yylval.sym = s + return int32(s.Lexical) + +ncu: + cp = nil + ungetc(c) + + str = lexbuf.String() + yylval.val.U = new(Mpint) + mpatofix(yylval.val.U.(*Mpint), str) + if yylval.val.U.(*Mpint).Ovf { + Yyerror("overflow in constant") + Mpmovecfix(yylval.val.U.(*Mpint), 0) + } + + if Debug['x'] != 0 { + fmt.Printf("lex: integer literal\n") + } + litbuf = "literal " + str + return LLITERAL + +casedot: + for { + cp.WriteByte(byte(c)) + c = getc() + if !isDigit(c) { + break + } + } + + if c == 'i' { + goto casei + } + if c != 'e' && c != 'E' { + goto caseout + } + +caseep: + if importpkg == nil && (c == 'p' || c == 'P') { + // p is allowed in .a/.o imports, + // but not in .go sources. See #9036. + Yyerror("malformed floating point constant") + } + cp.WriteByte(byte(c)) + c = getc() + if c == '+' || c == '-' { + cp.WriteByte(byte(c)) + c = getc() + } + + if !isDigit(c) { + Yyerror("malformed floating point constant exponent") + } + for isDigit(c) { + cp.WriteByte(byte(c)) + c = getc() + } + + if c == 'i' { + goto casei + } + goto caseout + + // imaginary constant +casei: + cp = nil + + str = lexbuf.String() + yylval.val.U = new(Mpcplx) + Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0) + mpatoflt(&yylval.val.U.(*Mpcplx).Imag, str) + if yylval.val.U.(*Mpcplx).Imag.Val.IsInf() { + Yyerror("overflow in imaginary constant") + Mpmovecflt(&yylval.val.U.(*Mpcplx).Imag, 0.0) + } + + if Debug['x'] != 0 { + fmt.Printf("lex: imaginary literal\n") + } + litbuf = "literal " + str + return LLITERAL + +caseout: + cp = nil + ungetc(c) + + str = lexbuf.String() + yylval.val.U = newMpflt() + mpatoflt(yylval.val.U.(*Mpflt), str) + if yylval.val.U.(*Mpflt).Val.IsInf() { + Yyerror("overflow in float constant") + Mpmovecflt(yylval.val.U.(*Mpflt), 0.0) + } + + if Debug['x'] != 0 { + fmt.Printf("lex: floating literal\n") + } + litbuf = "literal " + str + return LLITERAL + +strlit: + yylval.val.U = internString(cp.Bytes()) + if Debug['x'] != 0 { + fmt.Printf("lex: string literal\n") + } + litbuf = "string literal" + return LLITERAL +} + +var internedStrings = map[string]string{} + +func internString(b []byte) string { + s, ok := internedStrings[string(b)] // string(b) here doesn't allocate + if ok { + return s + } + s = string(b) + internedStrings[s] = s + return s +} + +func more(pp *string) bool { + p := *pp + for p != "" && isSpace(int(p[0])) { + p = p[1:] + } + *pp = p + return p != "" +} + +// read and interpret syntax that looks like +// //line parse.y:15 +// as a discontinuity in sequential line numbers. +// the next line of input comes from parse.y:15 +func getlinepragma() int { + var cmd, verb, name string + + c := int(getr()) + if c == 'g' { + cp := &lexbuf + cp.Reset() + cp.WriteByte('g') // already read + for { + c = int(getr()) + if c == EOF || c >= utf8.RuneSelf { + return c + } + if c == '\n' { + break + } + cp.WriteByte(byte(c)) + } + cp = nil + + text := strings.TrimSuffix(lexbuf.String(), "\r") + + if strings.HasPrefix(text, "go:cgo_") { + pragcgo(text) + } + + cmd = text + verb = cmd + if i := strings.Index(verb, " "); i >= 0 { + verb = verb[:i] + } + + if verb == "go:linkname" { + if !imported_unsafe { + Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"") + } + f := strings.Fields(cmd) + if len(f) != 3 { + Yyerror("usage: //go:linkname localname linkname") + return c + } + + Lookup(f[1]).Linkname = f[2] + return c + } + + if verb == "go:nointerface" && obj.Fieldtrack_enabled != 0 { + nointerface = true + return c + } + + if verb == "go:noescape" { + noescape = true + return c + } + + if verb == "go:norace" { + norace = true + return c + } + + if verb == "go:nosplit" { + nosplit = true + return c + } + + if verb == "go:noinline" { + noinline = true + return c + } + + if verb == "go:systemstack" { + if compiling_runtime == 0 { + Yyerror("//go:systemstack only allowed in runtime") + } + systemstack = true + return c + } + + if verb == "go:nowritebarrier" { + if compiling_runtime == 0 { + Yyerror("//go:nowritebarrier only allowed in runtime") + } + nowritebarrier = true + return c + } + + if verb == "go:nowritebarrierrec" { + if compiling_runtime == 0 { + Yyerror("//go:nowritebarrierrec only allowed in runtime") + } + nowritebarrierrec = true + nowritebarrier = true // Implies nowritebarrier + return c + } + return c + } + if c != 'l' { + return c + } + for i := 1; i < 5; i++ { + c = int(getr()) + if c != int("line "[i]) { + return c + } + } + + cp := &lexbuf + cp.Reset() + linep := 0 + for { + c = int(getr()) + if c == EOF { + return c + } + if c == '\n' { + break + } + if c == ' ' { + continue + } + if c == ':' { + linep = cp.Len() + 1 + } + cp.WriteByte(byte(c)) + } + + cp = nil + + if linep == 0 { + return c + } + text := strings.TrimSuffix(lexbuf.String(), "\r") + n := 0 + for _, c := range text[linep:] { + if c < '0' || c > '9' { + goto out + } + n = n*10 + int(c) - '0' + if n > 1e8 { + Yyerror("line number out of range") + errorexit() + } + } + + if n <= 0 { + return c + } + + name = text[:linep-1] + linehistupdate(name, n) + return c + +out: + return c +} + +func getimpsym(pp *string) string { + more(pp) // skip spaces + p := *pp + if p == "" || p[0] == '"' { + return "" + } + i := 0 + for i < len(p) && !isSpace(int(p[i])) && p[i] != '"' { + i++ + } + sym := p[:i] + *pp = p[i:] + return sym +} + +func getquoted(pp *string) (string, bool) { + more(pp) // skip spaces + p := *pp + if p == "" || p[0] != '"' { + return "", false + } + p = p[1:] + i := strings.Index(p, `"`) + if i < 0 { + return "", false + } + *pp = p[i+1:] + return p[:i], true +} + +// Copied nearly verbatim from the C compiler's #pragma parser. +// TODO: Rewrite more cleanly once the compiler is written in Go. +func pragcgo(text string) { + var q string + + if i := strings.Index(text, " "); i >= 0 { + text, q = text[:i], text[i:] + } + + verb := text[3:] // skip "go:" + + if verb == "cgo_dynamic_linker" || verb == "dynlinker" { + p, ok := getquoted(&q) + if !ok { + Yyerror("usage: //go:cgo_dynamic_linker \"path\"") + return + } + pragcgobuf += fmt.Sprintf("cgo_dynamic_linker %v\n", plan9quote(p)) + return + + } + + if verb == "dynexport" { + verb = "cgo_export_dynamic" + } + if verb == "cgo_export_static" || verb == "cgo_export_dynamic" { + local := getimpsym(&q) + var remote string + if local == "" { + goto err2 + } + if !more(&q) { + pragcgobuf += fmt.Sprintf("%s %v\n", verb, plan9quote(local)) + return + } + + remote = getimpsym(&q) + if remote == "" { + goto err2 + } + pragcgobuf += fmt.Sprintf("%s %v %v\n", verb, plan9quote(local), plan9quote(remote)) + return + + err2: + Yyerror("usage: //go:%s local [remote]", verb) + return + } + + if verb == "cgo_import_dynamic" || verb == "dynimport" { + var ok bool + local := getimpsym(&q) + var p string + var remote string + if local == "" { + goto err3 + } + if !more(&q) { + pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v\n", plan9quote(local)) + return + } + + remote = getimpsym(&q) + if remote == "" { + goto err3 + } + if !more(&q) { + pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v\n", plan9quote(local), plan9quote(remote)) + return + } + + p, ok = getquoted(&q) + if !ok { + goto err3 + } + pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v %v\n", plan9quote(local), plan9quote(remote), plan9quote(p)) + return + + err3: + Yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]") + return + } + + if verb == "cgo_import_static" { + local := getimpsym(&q) + if local == "" || more(&q) { + Yyerror("usage: //go:cgo_import_static local") + return + } + pragcgobuf += fmt.Sprintf("cgo_import_static %v\n", plan9quote(local)) + return + + } + + if verb == "cgo_ldflag" { + p, ok := getquoted(&q) + if !ok { + Yyerror("usage: //go:cgo_ldflag \"arg\"") + return + } + pragcgobuf += fmt.Sprintf("cgo_ldflag %v\n", plan9quote(p)) + return + + } +} + +type yy struct{} + +func (yy) Lex(v *yySymType) int { + return int(yylex(v)) +} + +func (yy) Error(msg string) { + Yyerror("%s", msg) +} + +var oldparser int // if set, theparser is used (otherwise we use the recursive-descent parser) +var theparser yyParser +var parsing bool + +func yyparse() { + parsing = true + if oldparser != 0 { + theparser = yyNewParser() + theparser.Parse(yy{}) + } else { + parse_file() + } + parsing = false +} + +func yylex(yylval *yySymType) int32 { + lx := int(_yylex(yylval)) + + if curio.nlsemi && lx == EOF { + // Treat EOF as "end of line" for the purposes + // of inserting a semicolon. + lx = ';' + } + + switch lx { + case LNAME, + LLITERAL, + LBREAK, + LCONTINUE, + LFALL, + LRETURN, + LINC, + LDEC, + ')', + '}', + ']': + curio.nlsemi = true + + default: + curio.nlsemi = false + } + + // Track last two tokens returned by yylex. + yyprev = yylast + + yylast = lx + return int32(lx) +} + +func getc() int { + c := curio.peekc + if c != 0 { + curio.peekc = curio.peekc1 + curio.peekc1 = 0 + goto check + } + + if curio.bin == nil { + if len(curio.cp) == 0 { + c = 0 + } else { + c = int(curio.cp[0]) + curio.cp = curio.cp[1:] + } + } else { + loop: + c = obj.Bgetc(curio.bin) + // recognize BOM (U+FEFF): UTF-8 encoding is 0xef 0xbb 0xbf + if c == 0xef { + buf, err := curio.bin.Peek(2) + if err != nil { + yyerrorl(int(lexlineno), "illegal UTF-8 sequence ef % x followed by read error (%v)", string(buf), err) + errorexit() + } + if buf[0] == 0xbb && buf[1] == 0xbf { + yyerrorl(int(lexlineno), "Unicode (UTF-8) BOM in middle of file") + + // consume BOM bytes + obj.Bgetc(curio.bin) + obj.Bgetc(curio.bin) + goto loop + } + } + } + +check: + switch c { + case 0: + if curio.bin != nil { + Yyerror("illegal NUL byte") + break + } + fallthrough + + // insert \n at EOF + case EOF: + if curio.eofnl || curio.last == '\n' { + return EOF + } + curio.eofnl = true + c = '\n' + fallthrough + + case '\n': + if pushedio.bin == nil { + lexlineno++ + } + } + + curio.last = c + return c +} + +func ungetc(c int) { + curio.peekc1 = curio.peekc + curio.peekc = c + if c == '\n' && pushedio.bin == nil { + lexlineno-- + } +} + +func getr() int32 { + var buf [utf8.UTFMax]byte + + for i := 0; ; i++ { + c := getc() + if i == 0 && c < utf8.RuneSelf { + return int32(c) + } + buf[i] = byte(c) + if i+1 == len(buf) || utf8.FullRune(buf[:i+1]) { + r, w := utf8.DecodeRune(buf[:i+1]) + if r == utf8.RuneError && w == 1 { + lineno = lexlineno + // The string conversion here makes a copy for passing + // to fmt.Printf, so that buf itself does not escape and can + // be allocated on the stack. + Yyerror("illegal UTF-8 sequence % x", string(buf[:i+1])) + } + return int32(r) + } + } +} + +func escchar(e int, escflg *int, val *int64) bool { + *escflg = 0 + + c := int(getr()) + switch c { + case EOF: + Yyerror("eof in string") + return true + + case '\n': + Yyerror("newline in string") + return true + + case '\\': + break + + default: + if c == e { + return true + } + *val = int64(c) + return false + } + + u := 0 + c = int(getr()) + var i int + switch c { + case 'x': + *escflg = 1 // it's a byte + i = 2 + goto hex + + case 'u': + i = 4 + u = 1 + goto hex + + case 'U': + i = 8 + u = 1 + goto hex + + case '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7': + *escflg = 1 // it's a byte + l := int64(c) - '0' + for i := 2; i > 0; i-- { + c = getc() + if c >= '0' && c <= '7' { + l = l*8 + int64(c) - '0' + continue + } + + Yyerror("non-octal character in escape sequence: %c", c) + ungetc(c) + } + + if l > 255 { + Yyerror("octal escape value > 255: %d", l) + } + + *val = l + return false + + case 'a': + c = '\a' + case 'b': + c = '\b' + case 'f': + c = '\f' + case 'n': + c = '\n' + case 'r': + c = '\r' + case 't': + c = '\t' + case 'v': + c = '\v' + case '\\': + c = '\\' + + default: + if c != e { + Yyerror("unknown escape sequence: %c", c) + } + } + + *val = int64(c) + return false + +hex: + l := int64(0) + for ; i > 0; i-- { + c = getc() + if c >= '0' && c <= '9' { + l = l*16 + int64(c) - '0' + continue + } + + if c >= 'a' && c <= 'f' { + l = l*16 + int64(c) - 'a' + 10 + continue + } + + if c >= 'A' && c <= 'F' { + l = l*16 + int64(c) - 'A' + 10 + continue + } + + Yyerror("non-hex character in escape sequence: %c", c) + ungetc(c) + break + } + + if u != 0 && (l > utf8.MaxRune || (0xd800 <= l && l < 0xe000)) { + Yyerror("invalid Unicode code point in escape sequence: %#x", l) + l = utf8.RuneError + } + + *val = l + return false +} + +var syms = []struct { + name string + lexical int + etype EType + op Op +}{ + // basic types + {"int8", LNAME, TINT8, OXXX}, + {"int16", LNAME, TINT16, OXXX}, + {"int32", LNAME, TINT32, OXXX}, + {"int64", LNAME, TINT64, OXXX}, + {"uint8", LNAME, TUINT8, OXXX}, + {"uint16", LNAME, TUINT16, OXXX}, + {"uint32", LNAME, TUINT32, OXXX}, + {"uint64", LNAME, TUINT64, OXXX}, + {"float32", LNAME, TFLOAT32, OXXX}, + {"float64", LNAME, TFLOAT64, OXXX}, + {"complex64", LNAME, TCOMPLEX64, OXXX}, + {"complex128", LNAME, TCOMPLEX128, OXXX}, + {"bool", LNAME, TBOOL, OXXX}, + {"string", LNAME, TSTRING, OXXX}, + {"any", LNAME, TANY, OXXX}, + {"break", LBREAK, Txxx, OXXX}, + {"case", LCASE, Txxx, OXXX}, + {"chan", LCHAN, Txxx, OXXX}, + {"const", LCONST, Txxx, OXXX}, + {"continue", LCONTINUE, Txxx, OXXX}, + {"default", LDEFAULT, Txxx, OXXX}, + {"else", LELSE, Txxx, OXXX}, + {"defer", LDEFER, Txxx, OXXX}, + {"fallthrough", LFALL, Txxx, OXXX}, + {"for", LFOR, Txxx, OXXX}, + {"func", LFUNC, Txxx, OXXX}, + {"go", LGO, Txxx, OXXX}, + {"goto", LGOTO, Txxx, OXXX}, + {"if", LIF, Txxx, OXXX}, + {"import", LIMPORT, Txxx, OXXX}, + {"interface", LINTERFACE, Txxx, OXXX}, + {"map", LMAP, Txxx, OXXX}, + {"package", LPACKAGE, Txxx, OXXX}, + {"range", LRANGE, Txxx, OXXX}, + {"return", LRETURN, Txxx, OXXX}, + {"select", LSELECT, Txxx, OXXX}, + {"struct", LSTRUCT, Txxx, OXXX}, + {"switch", LSWITCH, Txxx, OXXX}, + {"type", LTYPE, Txxx, OXXX}, + {"var", LVAR, Txxx, OXXX}, + {"append", LNAME, Txxx, OAPPEND}, + {"cap", LNAME, Txxx, OCAP}, + {"close", LNAME, Txxx, OCLOSE}, + {"complex", LNAME, Txxx, OCOMPLEX}, + {"copy", LNAME, Txxx, OCOPY}, + {"delete", LNAME, Txxx, ODELETE}, + {"imag", LNAME, Txxx, OIMAG}, + {"len", LNAME, Txxx, OLEN}, + {"make", LNAME, Txxx, OMAKE}, + {"new", LNAME, Txxx, ONEW}, + {"panic", LNAME, Txxx, OPANIC}, + {"print", LNAME, Txxx, OPRINT}, + {"println", LNAME, Txxx, OPRINTN}, + {"real", LNAME, Txxx, OREAL}, + {"recover", LNAME, Txxx, ORECOVER}, + {"notwithstanding", LIGNORE, Txxx, OXXX}, + {"thetruthofthematter", LIGNORE, Txxx, OXXX}, + {"despiteallobjections", LIGNORE, Txxx, OXXX}, + {"whereas", LIGNORE, Txxx, OXXX}, + {"insofaras", LIGNORE, Txxx, OXXX}, +} + +// lexinit initializes known symbols and the basic types. +func lexinit() { + for _, s := range syms { + lex := s.lexical + s1 := Lookup(s.name) + s1.Lexical = uint16(lex) + + if etype := s.etype; etype != Txxx { + if int(etype) >= len(Types) { + Fatalf("lexinit: %s bad etype", s.name) + } + s2 := Pkglookup(s.name, builtinpkg) + t := Types[etype] + if t == nil { + t = typ(etype) + t.Sym = s2 + + if etype != TANY && etype != TSTRING { + dowidth(t) + } + Types[etype] = t + } + + s2.Lexical = LNAME + s2.Def = typenod(t) + s2.Def.Name = new(Name) + continue + } + + // TODO(marvin): Fix Node.EType type union. + if etype := s.op; etype != OXXX { + s2 := Pkglookup(s.name, builtinpkg) + s2.Lexical = LNAME + s2.Def = Nod(ONAME, nil, nil) + s2.Def.Sym = s2 + s2.Def.Etype = EType(etype) + } + } + + // logically, the type of a string literal. + // types[TSTRING] is the named type string + // (the type of x in var x string or var x = "hello"). + // this is the ideal form + // (the type of x in const x = "hello"). + idealstring = typ(TSTRING) + + idealbool = typ(TBOOL) + + s := Pkglookup("true", builtinpkg) + s.Def = Nodbool(true) + s.Def.Sym = Lookup("true") + s.Def.Name = new(Name) + s.Def.Type = idealbool + + s = Pkglookup("false", builtinpkg) + s.Def = Nodbool(false) + s.Def.Sym = Lookup("false") + s.Def.Name = new(Name) + s.Def.Type = idealbool + + s = Lookup("_") + s.Block = -100 + s.Def = Nod(ONAME, nil, nil) + s.Def.Sym = s + Types[TBLANK] = typ(TBLANK) + s.Def.Type = Types[TBLANK] + nblank = s.Def + + s = Pkglookup("_", builtinpkg) + s.Block = -100 + s.Def = Nod(ONAME, nil, nil) + s.Def.Sym = s + Types[TBLANK] = typ(TBLANK) + s.Def.Type = Types[TBLANK] + + Types[TNIL] = typ(TNIL) + s = Pkglookup("nil", builtinpkg) + var v Val + v.U = new(NilVal) + s.Def = nodlit(v) + s.Def.Sym = s + s.Def.Name = new(Name) +} + +func lexinit1() { + // t = interface { Error() string } + rcvr := typ(TSTRUCT) + + rcvr.Type = typ(TFIELD) + rcvr.Type.Type = Ptrto(typ(TSTRUCT)) + rcvr.Funarg = true + in := typ(TSTRUCT) + in.Funarg = true + out := typ(TSTRUCT) + out.Type = typ(TFIELD) + out.Type.Type = Types[TSTRING] + out.Funarg = true + f := typ(TFUNC) + *getthis(f) = rcvr + *Getoutarg(f) = out + *getinarg(f) = in + f.Thistuple = 1 + f.Intuple = 0 + f.Outnamed = false + f.Outtuple = 1 + t := typ(TINTER) + t.Type = typ(TFIELD) + t.Type.Sym = Lookup("Error") + t.Type.Type = f + + // error type + s := Lookup("error") + + s.Lexical = LNAME + s1 := Pkglookup("error", builtinpkg) + errortype = t + errortype.Sym = s1 + s1.Lexical = LNAME + s1.Def = typenod(errortype) + + // byte alias + s = Lookup("byte") + + s.Lexical = LNAME + s1 = Pkglookup("byte", builtinpkg) + bytetype = typ(TUINT8) + bytetype.Sym = s1 + s1.Lexical = LNAME + s1.Def = typenod(bytetype) + s1.Def.Name = new(Name) + + // rune alias + s = Lookup("rune") + + s.Lexical = LNAME + s1 = Pkglookup("rune", builtinpkg) + runetype = typ(TINT32) + runetype.Sym = s1 + s1.Lexical = LNAME + s1.Def = typenod(runetype) + s1.Def.Name = new(Name) +} + +func lexfini() { + for i := range syms { + lex := syms[i].lexical + if lex != LNAME { + continue + } + s := Lookup(syms[i].name) + s.Lexical = uint16(lex) + + etype := syms[i].etype + if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil { + s.Def = typenod(Types[etype]) + s.Def.Name = new(Name) + s.Origpkg = builtinpkg + } + + // TODO(marvin): Fix Node.EType type union. + etype = EType(syms[i].op) + if etype != EType(OXXX) && s.Def == nil { + s.Def = Nod(ONAME, nil, nil) + s.Def.Sym = s + s.Def.Etype = etype + s.Origpkg = builtinpkg + } + } + + // backend-specific builtin types (e.g. int). + for i := range Thearch.Typedefs { + s := Lookup(Thearch.Typedefs[i].Name) + if s.Def == nil { + s.Def = typenod(Types[Thearch.Typedefs[i].Etype]) + s.Def.Name = new(Name) + s.Origpkg = builtinpkg + } + } + + // there's only so much table-driven we can handle. + // these are special cases. + if s := Lookup("byte"); s.Def == nil { + s.Def = typenod(bytetype) + s.Def.Name = new(Name) + s.Origpkg = builtinpkg + } + + if s := Lookup("error"); s.Def == nil { + s.Def = typenod(errortype) + s.Def.Name = new(Name) + s.Origpkg = builtinpkg + } + + if s := Lookup("rune"); s.Def == nil { + s.Def = typenod(runetype) + s.Def.Name = new(Name) + s.Origpkg = builtinpkg + } + + if s := Lookup("nil"); s.Def == nil { + var v Val + v.U = new(NilVal) + s.Def = nodlit(v) + s.Def.Sym = s + s.Def.Name = new(Name) + s.Origpkg = builtinpkg + } + + if s := Lookup("iota"); s.Def == nil { + s.Def = Nod(OIOTA, nil, nil) + s.Def.Sym = s + s.Origpkg = builtinpkg + } + + if s := Lookup("true"); s.Def == nil { + s.Def = Nodbool(true) + s.Def.Sym = s + s.Def.Name = new(Name) + s.Origpkg = builtinpkg + } + + if s := Lookup("false"); s.Def == nil { + s.Def = Nodbool(false) + s.Def.Sym = s + s.Def.Name = new(Name) + s.Origpkg = builtinpkg + } + + nodfp = Nod(ONAME, nil, nil) + nodfp.Type = Types[TINT32] + nodfp.Xoffset = 0 + nodfp.Class = PPARAM + nodfp.Sym = Lookup(".fp") +} + +var lexn = map[int]string{ + LANDAND: "ANDAND", + LANDNOT: "ANDNOT", + LASOP: "ASOP", + LBREAK: "BREAK", + LCASE: "CASE", + LCHAN: "CHAN", + LCOLAS: "COLAS", + LCOMM: "<-", + LCONST: "CONST", + LCONTINUE: "CONTINUE", + LDDD: "...", + LDEC: "DEC", + LDEFAULT: "DEFAULT", + LDEFER: "DEFER", + LELSE: "ELSE", + LEQ: "EQ", + LFALL: "FALL", + LFOR: "FOR", + LFUNC: "FUNC", + LGE: "GE", + LGO: "GO", + LGOTO: "GOTO", + LGT: "GT", + LIF: "IF", + LIMPORT: "IMPORT", + LINC: "INC", + LINTERFACE: "INTERFACE", + LLE: "LE", + LLITERAL: "LITERAL", + LLSH: "LSH", + LLT: "LT", + LMAP: "MAP", + LNAME: "NAME", + LNE: "NE", + LOROR: "OROR", + LPACKAGE: "PACKAGE", + LRANGE: "RANGE", + LRETURN: "RETURN", + LRSH: "RSH", + LSELECT: "SELECT", + LSTRUCT: "STRUCT", + LSWITCH: "SWITCH", + LTYPE: "TYPE", + LVAR: "VAR", +} + +func lexname(lex int) string { + if s, ok := lexn[lex]; ok { + return s + } + return fmt.Sprintf("LEX-%d", lex) +} + +var yytfix = map[string]string{ + "$end": "EOF", + "LASOP": "op=", + "LBREAK": "break", + "LCASE": "case", + "LCHAN": "chan", + "LCOLAS": ":=", + "LCONST": "const", + "LCONTINUE": "continue", + "LDDD": "...", + "LDEFAULT": "default", + "LDEFER": "defer", + "LELSE": "else", + "LFALL": "fallthrough", + "LFOR": "for", + "LFUNC": "func", + "LGO": "go", + "LGOTO": "goto", + "LIF": "if", + "LIMPORT": "import", + "LINTERFACE": "interface", + "LMAP": "map", + "LNAME": "name", + "LPACKAGE": "package", + "LRANGE": "range", + "LRETURN": "return", + "LSELECT": "select", + "LSTRUCT": "struct", + "LSWITCH": "switch", + "LTYPE": "type", + "LVAR": "var", + "LANDAND": "&&", + "LANDNOT": "&^", + "LBODY": "{", + "LCOMM": "<-", + "LDEC": "--", + "LINC": "++", + "LEQ": "==", + "LGE": ">=", + "LGT": ">", + "LLE": "<=", + "LLT": "<", + "LLSH": "<<", + "LRSH": ">>", + "LOROR": "||", + "LNE": "!=", + // spell out to avoid confusion with punctuation in error messages + "';'": "semicolon or newline", + "','": "comma", +} + +func init() { + yyErrorVerbose = true + + for i, s := range yyToknames { + // Apply yytfix if possible. + if fix, ok := yytfix[s]; ok { + yyToknames[i] = fix + } else if len(s) == 3 && s[0] == '\'' && s[2] == '\'' { + // Turn 'x' into x. + yyToknames[i] = s[1:2] + } + } +} + +func pkgnotused(lineno int, path string, name string) { + // If the package was imported with a name other than the final + // import path element, show it explicitly in the error message. + // Note that this handles both renamed imports and imports of + // packages containing unconventional package declarations. + // Note that this uses / always, even on Windows, because Go import + // paths always use forward slashes. + elem := path + if i := strings.LastIndex(elem, "/"); i >= 0 { + elem = elem[i+1:] + } + if name == "" || elem == name { + yyerrorl(int(lineno), "imported and not used: %q", path) + } else { + yyerrorl(int(lineno), "imported and not used: %q as %s", path, name) + } +} + +func mkpackage(pkgname string) { + if localpkg.Name == "" { + if pkgname == "_" { + Yyerror("invalid package name _") + } + localpkg.Name = pkgname + } else { + if pkgname != localpkg.Name { + Yyerror("package %s; expected %s", pkgname, localpkg.Name) + } + for _, s := range localpkg.Syms { + if s.Def == nil { + continue + } + if s.Def.Op == OPACK { + // throw away top-level package name leftover + // from previous file. + // leave s->block set to cause redeclaration + // errors if a conflicting top-level name is + // introduced by a different file. + if !s.Def.Used && nsyntaxerrors == 0 { + pkgnotused(int(s.Def.Lineno), s.Def.Name.Pkg.Path, s.Name) + } + s.Def = nil + continue + } + + if s.Def.Sym != s { + // throw away top-level name left over + // from previous import . "x" + if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 { + pkgnotused(int(s.Def.Name.Pack.Lineno), s.Def.Name.Pack.Name.Pkg.Path, "") + s.Def.Name.Pack.Used = true + } + + s.Def = nil + continue + } + } + } + + if outfile == "" { + p := infile + if i := strings.LastIndex(p, "/"); i >= 0 { + p = p[i+1:] + } + if Ctxt.Windows != 0 { + if i := strings.LastIndex(p, `\`); i >= 0 { + p = p[i+1:] + } + } + if i := strings.LastIndex(p, "."); i >= 0 { + p = p[:i] + } + suffix := ".o" + if writearchive > 0 { + suffix = ".a" + } + outfile = p + suffix + } +} diff --git a/playground/test.ispc b/playground/test.ispc new file mode 100644 index 0000000..4bd5fe3 --- /dev/null +++ b/playground/test.ispc @@ -0,0 +1,24 @@ +/* + Copyright (c) 2010-2023, Intel Corporation + + SPDX-License-Identifier: BSD-3-Clause +*/ + + +export void simple(uniform float vin[], uniform float vout[], + uniform int count) { + foreach (index = 0 ... count) { + // Load the appropriate input value for this program instance. + float v = vin[index]; + + // Do an arbitrary little computation, but at least make the + // computation dependent on the value being processed + if (v < 3.) + v = v * v; + else + v = sqrt(v); + + // And write the result to the output array. + vout[index] = v; + } +} diff --git a/playground/test.java b/playground/test.java new file mode 100644 index 0000000..17b43b0 --- /dev/null +++ b/playground/test.java @@ -0,0 +1,466 @@ +/* + * Copyright (C) Chaperon. All rights reserved. + * ------------------------------------------------------------------------- + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE file. + */ + +package net.sourceforge.chaperon.model.grammar; + +import java.io.Serializable; +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Vector; + +import net.sourceforge.chaperon.common.IntegerList; +import net.sourceforge.chaperon.model.Violations; +import net.sourceforge.chaperon.model.symbol.Symbol; +import net.sourceforge.chaperon.model.symbol.SymbolList; +import net.sourceforge.chaperon.model.symbol.SymbolSet; +import net.sourceforge.chaperon.model.symbol.Nonterminal; +import net.sourceforge.chaperon.model.symbol.Terminal; + +/** + * This class contains a grammar for building a parser table + * + * @author Stephan Michels + * @version CVS $Id: test3.java,v 1.3 2003/01/21 22:37:19 benedikta Exp $ + */ +public class Grammar implements Serializable, Cloneable +{ + // Start symbol + private Nonterminal startsymbol = null; + + // Productions + private Vector productions = new Vector(); + + private Hashtable priorities = new Hashtable(); + private Hashtable associativities = new Hashtable(); + + private String location = null; + + /** + * Creates a empty grammar + */ + public Grammar() + { + } + + /** + * Add a production to this list + * + * @param production Production, which should added + * + * @return Index of the production in this list + */ + public int addProduction(Production production) + { + if (production==null) + throw new NullPointerException(); + + productions.addElement(production); + return productions.size() - 1; + } + + /** + * Add a list of productions + * + * @param list Array of productions + */ + public void addProduction(Production[] list) + { + for (int i = 0; i < list.length; i++) + { + try + { + addProduction((Production)list[i].clone()); + } catch (CloneNotSupportedException cnse) + { + throw new IllegalArgumentException("Could not clone token:"+cnse.getMessage()); + } + } + } + + /** + * Removes a production by an index from this list + * + * @param index Index of the production, which should be removed + */ + public void removeProduction(int index) + { + productions.removeElementAt(index); + } + + /** + * Set a production by an index + * + * @param index The index, at which the production be inserted + * @param production Production + */ + public void setProduction(int index, + Production production) + throws IndexOutOfBoundsException + { + if ((index < 0) || (index > productions.size())) + throw new IndexOutOfBoundsException(); + productions.setElementAt(production, index); + } + + /** + * Return a production giving by an index + * + * @param index Index of the Production + * + * @return Production + */ + public Production getProduction(int index) throws IndexOutOfBoundsException + { + if ((index < 0) || (index > productions.size())) + throw new IndexOutOfBoundsException(); + + return (Production) productions.elementAt(index); + } + + /** + * Returns all production for given non terminal symbol + * + * @param ntsymbol Non terminal symbol + * + * @return List of indices from found productions + */ + public IntegerList getProductionList(Symbol ntsymbol) + { + IntegerList list = new IntegerList(); + int i; + + for (i = 0; i < getProductionCount(); i++) + { + if (getProduction(i).getSymbol().equals(ntsymbol)) + list.add(i); + } + return list; + } + + /** + * Returns the count of productions in the list + * + * @return Count of productions + */ + public int getProductionCount() + { + return productions.size(); + } + + /** + * Return the index of a production + * + * @param production Production + * + * @return Index of the Production + */ + public int indexOf(Production production) + { + for (int i = 0; i < productions.size(); i++) + if (((Production) productions.elementAt(i)).equals(production)) + return i; + return -1; + } + + /** + * Return the index of the next production, which found + * by a non terminal symbol + * + * @param ntsymbol Non terminal symbol + * + * @return Production, which found + */ + public int indexOf(Symbol ntsymbol) + { + for (int i = 0; i < productions.size(); i++) + if (((Production) productions.elementAt(i)).getSymbol().equals(ntsymbol)) + return i; + return -1; + } + + /** + * If the list contains a production + * + * @param production Production + * + * @return True, if the list contains the production + */ + public boolean contains(Production production) + { + return (indexOf(production) != -1); + } + + /** + * If the list contains a production with a special symbol + * + * @param ntsymbol Non terminal symbol + * + * @return True, if the list contains a production with the symbol + */ + public boolean contains(Symbol ntsymbol) + { + return (indexOf(ntsymbol) != -1); + } + + /** + * Removes all productions from this list + */ + public void removeAllProduction() + { + productions.removeAllElements(); + } + + /** + * Returns a enumeration of the productions + * in this list. + * + * @return Enumeration of the productions + */ + public Enumeration enumerateProduction() + { + return productions.elements(); + } + + /** + * Returns the content of this list + * + * @return Array of the tokens + */ + public Production[] getProduction() + { + int size = productions.size(); + Production[] mArray = new Production[size]; + + for (int index = 0; index < size; index++) + mArray[index] = (Production) productions.elementAt(index); + return mArray; + } + + /** + * Replace the content of this list by the content of an array + * + * + * @param productionArray + */ + public void setProduction(Production[] productionArray) + { + productions.removeAllElements(); + for (int i = 0; i < productionArray.length; i++) + productions.addElement(productionArray[i]); + } + + public void setPriority(Terminal terminal, int priority) + { + if (terminal==null) + throw new NullPointerException(); + + priorities.put(terminal, new Integer(priority)); + } + + public int getPriority(Terminal terminal) + { + Integer priority = (Integer)priorities.get(terminal); + if (priority==null) + return 0; + return priority.intValue(); + } + + public int getPriority(Production production) + { + if (!contains(production)) + return 0; + + if (production.getPrecedence() != null) + return getPriority(production.getPrecedence()); + + SymbolList definition = production.getDefinition(); + for (int i = definition.getSymbolCount() - 1; i >= 0; i--) + if (definition.getSymbol(i) instanceof Terminal) + { + int priority = getPriority((Terminal)definition.getSymbol(i)); + if (priority==0) + return getProductionCount()-indexOf(production); + return priority; + } + + return getProductionCount()-indexOf(production); + } + + public void setAssociativity(Terminal terminal, Associativity assoc) + { + if (terminal==null) + throw new NullPointerException(); + + associativities.put(terminal, assoc); + } + + public Associativity getAssociativity(Terminal terminal) + { + Associativity assoc = (Associativity)associativities.get(terminal); + if (assoc==null) + return Associativity.NONASSOC; + return assoc; + } + + public Associativity getAssociativity(Production production) + { + if (!contains(production)) + return Associativity.NONASSOC; + + if (production.getPrecedence() != null) + return getAssociativity(production.getPrecedence()); + + SymbolList definition = production.getDefinition(); + for (int i = definition.getSymbolCount() - 1; i >= 0; i--) + if (definition.getSymbol(i) instanceof Terminal) + return getAssociativity((Terminal)definition.getSymbol(i)); + + return Associativity.NONASSOC; + } + + /** + * Return all used symbols in this grammar + * + * @return Set of symbols + */ + public SymbolSet getSymbols() + { + SymbolSet set = new SymbolSet(); + + for (int i = 0; i < getProductionCount(); i++) + set.addSymbol(getProduction(i).getSymbols()); + return set; + } + + /** + * Set the a symbol a start symbol + * + * @param startsymbol + */ + public void setStartSymbol(Nonterminal startsymbol) + { + this.startsymbol = startsymbol; + } + + /** + * Returns the start symbol + * + * @return Start symbol + */ + public Nonterminal getStartSymbol() + { + return startsymbol; + } + + /** + * Set the location from the input source. + * + * @param location Location in the input source. + */ + public void setLocation(String location) + { + this.location = location; + } + + /** + * Returns the location from the input source. + * + * @return Location in the input source. + */ + public String getLocation() + { + return location; + } + + /** + * This method validates the grammer + * + * @return Return a list of violations, if this + * object isn't correct + */ + public Violations validate() + { + Violations violations = new Violations(); + if (startsymbol==null) + violations.addViolation("Start symbol is not defined", location); + + if (getProductionCount() <= 0) + violations.addViolation("No productions are defined", location); + + for (Enumeration e = productions.elements(); e.hasMoreElements() ;) + violations.addViolations(((Production)e.nextElement()).validate()); + + SymbolSet ntsymbols = getSymbols().getNonterminals(); + for (int i = 0; i < ntsymbols.getSymbolCount(); i++) + if (!contains(ntsymbols.getSymbol(i))) + violations.addViolation("Nonterminal symbol \"" + ntsymbols.getSymbol(i) + "\"" + + "is not defined through a production", location); + + return violations; + } + + /* + * + * + * @return + */ + public String toString() + { + StringBuffer buffer = new StringBuffer(); + + buffer.append(super.toString()); + buffer.append("\n"); + + buffer.append("Terminal symbols:\n"); + SymbolSet tsymbols = getSymbols().getTerminals(); + for (int i = 0; i < tsymbols.getSymbolCount(); i++) + { + buffer.append(String.valueOf(i)); + buffer.append(".Terminal: "); + buffer.append(tsymbols.getSymbol(i)); + buffer.append(" Priority="); + buffer.append(String.valueOf(getPriority((Terminal)tsymbols.getSymbol(i)))); + buffer.append(" Associativity="); + buffer.append(String.valueOf(getAssociativity((Terminal)tsymbols.getSymbol(i)))); + buffer.append("\n"); + } + + buffer.append("Produktions:\n"); + for (int i = 0; i < getProductionCount(); i++) + { + buffer.append(String.valueOf(i)); + buffer.append(".Production: "); + buffer.append(getProduction(i).toString()); + buffer.append("\n"); + } + + buffer.append("\n"); + + return buffer.toString(); + } + + /** + * Creates a clone of a grammar. + * + * @return + * + * @throws CloneNotSupportedException + */ + public Object clone() throws CloneNotSupportedException + { + Grammar clone = new Grammar(); + + clone.startsymbol = startsymbol; + for (int i = 0; i < productions.size(); i++) + clone.addProduction((Production) ((Production) productions.elementAt(i)).clone()); + + clone.location = location; + + return clone; + } +} diff --git a/playground/test.js.txt b/playground/test.js.txt new file mode 100644 index 0000000..9d7c2fa --- /dev/null +++ b/playground/test.js.txt @@ -0,0 +1,195 @@ +/* +From https://eli.thegreenplace.net/2013/07/16/hand-written-lexer-in-javascript-compared-to-the-regex-based-ones +*/ + +// To parse with JavascriptCore grammar I needed to add semicolomns at the end of assignements + +'use strict'; + +var Lexer = exports.Lexer = function() { + this.pos = 0; + this.buf = null; + this.buflen = 0; + + // Operator table, mapping operator -> token name + this.optable = { + '+': 'PLUS', + '-': 'MINUS', + '*': 'MULTIPLY', + '.': 'PERIOD', + '\\': 'BACKSLASH', + ':': 'COLON', + '%': 'PERCENT', + '|': 'PIPE', + '!': 'EXCLAMATION', + '?': 'QUESTION', + '#': 'POUND', + '&': 'AMPERSAND', + ';': 'SEMI', + ',': 'COMMA', + '(': 'L_PAREN', + ')': 'R_PAREN', + '<': 'L_ANG', + '>': 'R_ANG', + '{': 'L_BRACE', + '}': 'R_BRACE', + '[': 'L_BRACKET', + ']': 'R_BRACKET', + '=': 'EQUALS' + }; +}; + +// Initialize the Lexer's buffer. This resets the lexer's internal +// state and subsequent tokens will be returned starting with the +// beginning of the new buffer. +Lexer.prototype.input = function(buf) { + this.pos = 0; + this.buf = buf; + this.buflen = buf.length; +}; + +// Get the next token from the current buffer. A token is an object with +// the following properties: +// - name: name of the pattern that this token matched (taken from rules). +// - value: actual string value of the token. +// - pos: offset in the current buffer where the token starts. +// +// If there are no more tokens in the buffer, returns null. In case of +// an error throws Error. +Lexer.prototype.token = function() { + this._skipnontokens(); + if (this.pos >= this.buflen) { + return null; + } + + // The char at this.pos is part of a real token. Figure out which. + var c = this.buf.charAt(this.pos); + + // '/' is treated specially, because it starts a comment if followed by + // another '/'. If not followed by another '/', it's the DIVIDE + // operator. + if (c === '/') { + var next_c = this.buf.charAt(this.pos + 1); + if (next_c === '/') { + return this._process_comment(); + } else { + return {name: 'DIVIDE', value: '/', pos: this.pos++}; + } + } else { + // Look it up in the table of operators + var op = this.optable[c]; + if (op !== undefined) { + return {name: op, value: c, pos: this.pos++}; + } else { + // Not an operator - so it's the beginning of another token. + if (Lexer._isalpha(c)) { + return this._process_identifier(); + } else if (Lexer._isdigit(c)) { + return this._process_number(); + } else if (c === '"') { + return this._process_quote(); + } else { + throw Error('Token error at ' + this.pos); + } + } + } +}; + +Lexer._isnewline = function(c) { + return c === '\r' || c === '\n'; +}; + +Lexer._isdigit = function(c) { + return c >= '0' && c <= '9'; +}; + +Lexer._isalpha = function(c) { + return (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c === '_' || c === '$'; +}; + +Lexer._isalphanum = function(c) { + return (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c === '_' || c === '$'; +}; + +Lexer.prototype._process_number = function() { + var endpos = this.pos + 1; + while (endpos < this.buflen && + Lexer._isdigit(this.buf.charAt(endpos))) { + endpos++; + } + + var tok = { + name: 'NUMBER', + value: this.buf.substring(this.pos, endpos), + pos: this.pos + }; + this.pos = endpos; + return tok; +}; + +Lexer.prototype._process_comment = function() { + var endpos = this.pos + 2; + // Skip until the end of the line + var c = this.buf.charAt(this.pos + 2); + while (endpos < this.buflen && + !Lexer._isnewline(this.buf.charAt(endpos))) { + endpos++; + } + + var tok = { + name: 'COMMENT', + value: this.buf.substring(this.pos, endpos), + pos: this.pos + }; + this.pos = endpos + 1; + return tok; +}; + +Lexer.prototype._process_identifier = function() { + var endpos = this.pos + 1; + while (endpos < this.buflen && + Lexer._isalphanum(this.buf.charAt(endpos))) { + endpos++; + } + + var tok = { + name: 'IDENTIFIER', + value: this.buf.substring(this.pos, endpos), + pos: this.pos + }; + this.pos = endpos; + return tok; +}; + +Lexer.prototype._process_quote = function() { + // this.pos points at the opening quote. Find the ending quote. + var end_index = this.buf.indexOf('"', this.pos + 1); + + if (end_index === -1) { + throw Error('Unterminated quote at ' + this.pos); + } else { + var tok = { + name: 'QUOTE', + value: this.buf.substring(this.pos, end_index + 1), + pos: this.pos + }; + this.pos = end_index + 1; + return tok; + } +}; + +Lexer.prototype._skipnontokens = function() { + while (this.pos < this.buflen) { + var c = this.buf.charAt(this.pos); + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') { + this.pos++; + } else { + break; + } + } +}; diff --git a/playground/test.json.txt b/playground/test.json.txt new file mode 100644 index 0000000..3203359 --- /dev/null +++ b/playground/test.json.txt @@ -0,0 +1,162 @@ +[ + { + "section" : "Bytecodes", "emitInHFile" : true, "emitInASMFile" : true, "macroNameComponent" : "BYTECODE", + "bytecodes" : [ + { "name" : "op_enter", "length" : 1 }, + { "name" : "op_create_activation", "length" : 2 }, + { "name" : "op_touch_entry", "length" : 1 }, + { "name" : "op_init_lazy_reg", "length" : 2 }, + { "name" : "op_create_arguments", "length" : 2 }, + { "name" : "op_create_this", "length" : 4 }, + { "name" : "op_get_callee", "length" : 3 }, + { "name" : "op_to_this", "length" : 3 }, + { "name" : "op_new_object", "length" : 4 }, + { "name" : "op_new_array", "length" : 5 }, + { "name" : "op_new_array_with_size", "length" : 4 }, + { "name" : "op_new_array_buffer", "length" : 5 }, + { "name" : "op_new_regexp", "length" : 3 }, + { "name" : "op_mov", "length" : 3 }, + { "name" : "op_captured_mov", "length" : 4 }, + { "name" : "op_not", "length" : 3 }, + { "name" : "op_eq", "length" : 4 }, + { "name" : "op_eq_null", "length" : 3 }, + { "name" : "op_neq", "length" : 4 }, + { "name" : "op_neq_null", "length" : 3 }, + { "name" : "op_stricteq", "length" : 4 }, + { "name" : "op_nstricteq", "length" : 4 }, + { "name" : "op_less", "length" : 4 }, + { "name" : "op_lesseq", "length" : 4 }, + { "name" : "op_greater", "length" : 4 }, + { "name" : "op_greatereq", "length" : 4 }, + { "name" : "op_inc", "length" : 2 }, + { "name" : "op_dec", "length" : 2 }, + { "name" : "op_to_number", "length" : 3 }, + { "name" : "op_negate", "length" : 3 }, + { "name" : "op_add", "length" : 5 }, + { "name" : "op_mul", "length" : 5 }, + { "name" : "op_div", "length" : 5 }, + { "name" : "op_mod", "length" : 4 }, + { "name" : "op_sub", "length" : 5 }, + { "name" : "op_lshift", "length" : 4 }, + { "name" : "op_rshift", "length" : 4 }, + { "name" : "op_urshift", "length" : 4 }, + { "name" : "op_unsigned", "length" : 3 }, + { "name" : "op_bitand", "length" : 5 }, + { "name" : "op_bitxor", "length" : 5 }, + { "name" : "op_bitor", "length" : 5 }, + { "name" : "op_check_has_instance", "length" : 5 }, + { "name" : "op_instanceof", "length" : 4 }, + { "name" : "op_typeof", "length" : 3 }, + { "name" : "op_is_undefined", "length" : 3 }, + { "name" : "op_is_boolean", "length" : 3 }, + { "name" : "op_is_number", "length" : 3 }, + { "name" : "op_is_string", "length" : 3 }, + { "name" : "op_is_object", "length" : 3 }, + { "name" : "op_is_function", "length" : 3 }, + { "name" : "op_in", "length" : 4 }, + { "name" : "op_init_global_const_nop", "length" : 5 }, + { "name" : "op_init_global_const", "length" : 5 }, + { "name" : "op_get_by_id", "length" : 9 }, + { "name" : "op_get_by_id_out_of_line", "length" : 9 }, + { "name" : "op_get_array_length", "length" : 9 }, + { "name" : "op_get_arguments_length", "length" : 4 }, + { "name" : "op_put_by_id", "length" : 9 }, + { "name" : "op_put_by_id_out_of_line", "length" : 9 }, + { "name" : "op_put_by_id_transition_direct", "length" : 9 }, + { "name" : "op_put_by_id_transition_direct_out_of_line", "length" : 9 }, + { "name" : "op_put_by_id_transition_normal", "length" : 9 }, + { "name" : "op_put_by_id_transition_normal_out_of_line", "length" : 9 }, + { "name" : "op_del_by_id", "length" : 4 }, + { "name" : "op_get_by_val", "length" : 6 }, + { "name" : "op_get_argument_by_val", "length" : 6 }, + { "name" : "op_get_by_pname", "length" : 7 }, + { "name" : "op_put_by_val", "length" : 5 }, + { "name" : "op_put_by_val_direct", "length" : 5 }, + { "name" : "op_del_by_val", "length" : 4 }, + { "name" : "op_put_by_index", "length" : 4 }, + { "name" : "op_put_getter_setter", "length" : 5 }, + { "name" : "op_jmp", "length" : 2 }, + { "name" : "op_jtrue", "length" : 3 }, + { "name" : "op_jfalse", "length" : 3 }, + { "name" : "op_jeq_null", "length" : 3 }, + { "name" : "op_jneq_null", "length" : 3 }, + { "name" : "op_jneq_ptr", "length" : 4 }, + { "name" : "op_jless", "length" : 4 }, + { "name" : "op_jlesseq", "length" : 4 }, + { "name" : "op_jgreater", "length" : 4 }, + { "name" : "op_jgreatereq", "length" : 4 }, + { "name" : "op_jnless", "length" : 4 }, + { "name" : "op_jnlesseq", "length" : 4 }, + { "name" : "op_jngreater", "length" : 4 }, + { "name" : "op_jngreatereq", "length" : 4 }, + { "name" : "op_loop_hint", "length" : 1 }, + { "name" : "op_switch_imm", "length" : 4 }, + { "name" : "op_switch_char", "length" : 4 }, + { "name" : "op_switch_string", "length" : 4 }, + { "name" : "op_new_func", "length" : 4 }, + { "name" : "op_new_captured_func", "length" : 4 }, + { "name" : "op_new_func_exp", "length" : 3 }, + { "name" : "op_call", "length" : 9 }, + { "name" : "op_call_eval", "length" : 9 }, + { "name" : "op_call_varargs", "length" : 9 }, + { "name" : "op_tear_off_activation", "length" : 2 }, + { "name" : "op_tear_off_arguments", "length" : 3 }, + { "name" : "op_ret", "length" : 2 }, + { "name" : "op_ret_object_or_this", "length" : 3 }, + { "name" : "op_construct", "length" : 9 }, + { "name" : "op_strcat", "length" : 4 }, + { "name" : "op_to_primitive", "length" : 3 }, + { "name" : "op_get_pnames", "length" : 6 }, + { "name" : "op_next_pname", "length" : 7 }, + { "name" : "op_resolve_scope", "length" : 6 }, + { "name" : "op_get_from_scope", "length" : 8 }, + { "name" : "op_put_to_scope", "length" : 7 }, + { "name" : "op_push_with_scope", "length" : 2 }, + { "name" : "op_pop_scope", "length" : 1 }, + { "name" : "op_push_name_scope", "length" : 4 }, + { "name" : "op_catch", "length" : 2 }, + { "name" : "op_throw", "length" : 2 }, + { "name" : "op_throw_static_error", "length" : 3 }, + { "name" : "op_debug", "length" : 3 }, + { "name" : "op_profile_will_call", "length" : 2 }, + { "name" : "op_profile_did_call", "length" : 2 }, + { "name" : "op_end", "length" : 2 } + ] + }, + { + "section" : "NativeHelpers", "emitInHFile" : true, "emitInASMFile" : true, "defaultLength" : 1, + "macroNameComponent" : "BYTECODE_HELPER", "emitDefineID" : true, + "bytecodes" : [ + { "name" : "llint_program_prologue" }, + { "name" : "llint_eval_prologue" }, + { "name" : "llint_function_for_call_prologue" }, + { "name" : "llint_function_for_construct_prologue" }, + { "name" : "llint_function_for_call_arity_check" }, + { "name" : "llint_function_for_construct_arity_check" }, + { "name" : "llint_generic_return_point" }, + { "name" : "llint_throw_from_slow_path_trampoline" }, + { "name" : "llint_throw_during_call_trampoline" }, + { "name" : "llint_native_call_trampoline" }, + { "name" : "llint_native_construct_trampoline" } + ] + }, + { + "section" : "CLoopHelpers", "emitInHFile" : true, "emitInASMFile" : false, "defaultLength" : 1, + "macroNameComponent" : "CLOOP_BYTECODE_HELPER", + "bytecodes" : [ + { "name" : "llint_c_loop_init" }, + { "name" : "getHostCallReturnValue" }, + { "name" : "llint_return_to_host" }, + { "name" : "llint_call_to_javascript" }, + { "name" : "llint_call_to_native_function" }, + { "name" : "handleUncaughtException" }, + { "name" : "llint_cloop_did_return_from_js_1" }, + { "name" : "llint_cloop_did_return_from_js_2" }, + { "name" : "llint_cloop_did_return_from_js_3" }, + { "name" : "llint_cloop_did_return_from_js_4" }, + { "name" : "llint_cloop_did_return_from_js_5" }, + { "name" : "llint_cloop_did_return_from_js_6" }, + { "name" : "llint_cloop_did_return_from_js_7" } + ] + } +] diff --git a/playground/test.json5.txt b/playground/test.json5.txt new file mode 100644 index 0000000..0e72c64 --- /dev/null +++ b/playground/test.json5.txt @@ -0,0 +1,12 @@ +{ + // comments + unquoted: 'and you can quote me on that', + singleQuotes: 'I can use "double quotes" here', + lineBreaks: "Look, Mom! \ +No \\n's!", + hexadecimal: 0xdecaf, + leadingDecimalPoint: .8675309, andTrailing: 8675309., + positiveSign: +1, + trailingComma: 'in objects', andIn: ['arrays',], + "backwardsCompatible": "with JSON", +} diff --git a/playground/test.lsl b/playground/test.lsl new file mode 100644 index 0000000..b120636 --- /dev/null +++ b/playground/test.lsl @@ -0,0 +1,711 @@ +//From: https://github.com/riej/OpenCollar/blob/master/src/collar/oc_dialog.lsl +// This file is part of OpenCollar. +// Copyright (c) 2007 - 2017 Schmobag Hogfather, Nandana Singh, +// Cleo Collins, Satomi Ahn, Joy Stipe, Wendy Starfall, littlemousy, +// Romka Swallowtail, Garvin Twine et al. +// Licensed under the GPLv2. See LICENSE for full details. +string g_sScriptVersion="7.3"; +integer LINK_CMD_DEBUG=1999; + + +//an adaptation of Schmobag Hogfather's SchmoDialog script + +//MESSAGE MAP +integer CMD_ZERO = 0; +integer CMD_OWNER = 500; +integer CMD_TRUSTED = 501; +integer CMD_GROUP = 502; +integer CMD_WEARER = 503; +//integer CMD_EVERYONE = 504; +//integer CMD_RLV_RELAY = 507; +//integer CMD_SAFEWORD = 510; +//integer CMD_RELAY_SAFEWORD = 511; +//integer CMD_BLOCKED = 520; + +integer NOTIFY = 1002; +integer NOTIFY_OWNERS=1003; +integer SAY = 1004; +integer LINK_SAVE = LINK_SET; // = 5; +integer LINK_UPDATE = -10; +integer REBOOT = -1000; +integer LOADPIN = -1904; +integer LM_SETTING_SAVE = 2000; +//integer LM_SETTING_REQUEST = 2001; +integer LM_SETTING_RESPONSE = 2002; +integer LM_SETTING_DELETE = 2003; +//integer LM_SETTING_EMPTY = 2004; + +//integer MENUNAME_REQUEST = 3000; +//integer MENUNAME_RESPONSE = 3001; +//integer MENUNAME_REMOVE = 3003; + +//integer RLV_CMD = 6000; +//integer RLV_REFRESH = 6001;//RLV plugins should reinstate their restrictions upon receiving this message. +//integer RLV_CLEAR = 6002;//RLV plugins should clear their restriction lists upon receiving this message. +//integer RLV_VERSION = 6003; //RLV Plugins can recieve the used rl viewer version upon receiving this message.. + +//integer RLV_OFF = 6100; // send to inform plugins that RLV is disabled now, no message or key needed +//integer RLV_ON = 6101; // send to inform plugins that RLV is enabled now, no message or key needed + +//integer ANIM_START = 7000;//send this with the name of an anim in the string part of the message to play the anim +//integer ANIM_STOP = 7001;//send this with the name of an anim in the string part of the message to stop the anim + +integer DIALOG = -9000; +integer DIALOG_RESPONSE = -9001; +integer DIALOG_TIMEOUT = -9002; +integer SENSORDIALOG = -9003; +//integer FIND_AGENT = -9005; + +integer g_iPagesize = 12; +string MORE = "►"; +string PREV = "◄"; +string UPMENU = "BACK"; // string to identify the UPMENU button in the utility lButtons +//string SWAPBTN = "swap"; +//string SYNCBTN = "sync"; +string BLANK = "-"; +integer g_iTimeOut = 300; +integer g_iReapeat = 5;//how often the timer will go off, in seconds + +list g_lMenus;//11-strided list in form listenChan, dialogid, listener, starttime, recipient, prompt, list buttons, utility buttons, currentpage, button digits, auth level +//where "list buttons" means the big list of choices presented to the user +//and "page buttons" means utility buttons that will appear on every page, such as one saying "go up one level" +//and "currentpage" is an integer meaning which page of the menu the user is currently viewing + +list g_lRemoteMenus; +integer g_iStrideLength = 12; + +// List of user keys who opt-out of chat-spammage, ie chose "off" +list MRSBUN = []; // blatant monty python reference - list of those who do not like spam +string SPAMSWITCH = "verbose"; // lowercase chat-command token + +key g_kWearer; +string g_sSettingToken = "dialog_"; +string g_sGlobalToken = "global_"; +integer g_iListenChan=1; +string g_sPrefix; +string g_sDeviceType = "collar"; +string g_sDeviceName; +string g_sWearerName; +list g_lOwners; + +list g_lSensorDetails; +integer g_bSensorLock; +integer g_iSensorTimeout; +integer g_iSelectAviMenu; //added to show URIs in menus june 2015 Otto(garvin.twine) +integer g_iColorMenu; + +list g_lColors = [ +"Red",<1.00000, 0.00000, 0.00000>, +"Green",<0.00000, 1.00000, 0.00000>, +"Blue",<0.00000, 0.50196, 1.00000>, +"Yellow",<1.00000, 1.00000, 0.00000>, +"Pink",<1.00000, 0.50588, 0.62353>, +"Brown",<0.24314, 0.14902, 0.07059>, +"Purple",<0.62353, 0.29020, 0.71765>, +"Black",<0.00000, 0.00000, 0.00000>, +"White",<1.00000, 1.00000, 1.00000>, +"Barbie",<0.91373, 0.00000, 0.34510>, +"Orange",<0.96078, 0.60784, 0.00000>, +"Toad",<0.25098, 0.25098, 0.00000>, +"Khaki",<0.62745, 0.50196, 0.38824>, +"Pool",<0.14902, 0.88235, 0.94510>, +"Blood",<0.42353, 0.00000, 0.00000>, +"Gray",<0.70588, 0.70588, 0.70588>, +"Anthracite",<0.08627, 0.08627, 0.08627>, +"Midnight",<0.00000, 0.10588, 0.21176> +]; + + +/*integer g_iProfiled=1; +Debug(string sStr) { + //if you delete the first // from the preceeding and following lines, + // profiling is off, debug is off, and the compiler will remind you to + // remove the debug calls from the code, we're back to production mode + if (!g_iProfiled){ + g_iProfiled=1; + llScriptProfiler(1); + } + llOwnerSay(llGetScriptName() + "(min free:"+(string)(llGetMemoryLimit()-llGetSPMaxMemory())+")["+(string)llGetFreeMemory()+"] :\n" + sStr); +}*/ + + +string NameURI(key kID){ + return "secondlife:///app/agent/"+(string)kID+"/about"; +} + +string SubstitudeVars(string sMsg) { + if (~llSubStringIndex(sMsg, "%NOACCESS")) + sMsg = llDumpList2String(llParseStringKeepNulls(sMsg, ["%NOACCESS%"], []), "Access Denied"); + if (~llSubStringIndex(sMsg, "%PREFIX%")) + sMsg = llDumpList2String(llParseStringKeepNulls((sMsg = "") + sMsg, ["%PREFIX%"], []), g_sPrefix); + if (~llSubStringIndex(sMsg, "%CHANNEL%")) + sMsg = llDumpList2String(llParseStringKeepNulls((sMsg = "") + sMsg, ["%CHANNEL%"], []), (string)g_iListenChan); + if (~llSubStringIndex(sMsg, "%DEVICETYPE%")) + sMsg = llDumpList2String(llParseStringKeepNulls((sMsg = "") + sMsg, ["%DEVICETYPE%"], []), g_sDeviceType); + if (~llSubStringIndex(sMsg, "%WEARERNAME%")) + sMsg = llDumpList2String(llParseStringKeepNulls((sMsg = "") + sMsg, ["%WEARERNAME%"], []), g_sWearerName); + + return sMsg; +} + +Notify(key kID, string sMsg, integer iAlsoNotifyWearer) { + if ((key)kID){ + sMsg = SubstitudeVars(sMsg); + string sObjectName = llGetObjectName(); + if (g_sDeviceName != sObjectName) llSetObjectName(g_sDeviceName); + if (kID == g_kWearer) llOwnerSay(sMsg); + else { + if (llGetAgentSize(kID)) llRegionSayTo(kID,0,sMsg); + else llInstantMessage(kID, sMsg); + if (iAlsoNotifyWearer) llOwnerSay(sMsg); + } + llSetObjectName(sObjectName); + }//else Debug("something went wrong in Notify, Msg: \""+sMsg+"\" is missing an ID to be sent to."); +} + +NotifyOwners(string sMsg, string comments) { + integer n; + integer iStop = llGetListLength(g_lOwners); + for (; n < iStop; ++n) { + key kAv = (key)llList2String(g_lOwners, n); + if (comments=="ignoreNearby") { + //we don't want to bother the owner if he/she is right there, so check distance + vector vOwnerPos = (vector)llList2String(llGetObjectDetails(kAv, [OBJECT_POS]), 0); + if (vOwnerPos == ZERO_VECTOR || llVecDist(vOwnerPos, llGetPos()) > 20.0) {//vOwnerPos will be ZERO_VECTOR if not in sim + //Debug("notifying " + (string)kAv); + //Debug("Sending notify to "+(string)kAv); + Notify(kAv, sMsg,FALSE); + //} else { + //Debug("Not sending notify to "+(string)kAv); + } + } else { + //Debug("Sending notify to "+(string)kAv); + Notify(kAv, sMsg,FALSE); + } + } +} + +Say(string sMsg, integer iWhisper) { + sMsg = SubstitudeVars(sMsg); + string sObjectName = llGetObjectName(); + llSetObjectName(""); + if (iWhisper) llWhisper(0,"/me "+sMsg); + else llSay(0, sMsg); + llSetObjectName(sObjectName); +} + +Dialog(key kRecipient, string sPrompt, list lMenuItems, list lUtilityButtons, integer iPage, key kID, integer iWithNums, integer iAuth,string extraInfo) +{ + //calculate page start and end + integer iNumitems = llGetListLength(lMenuItems); + integer iStart = 0; + integer iMyPageSize = g_iPagesize - llGetListLength(lUtilityButtons); + if (g_iSelectAviMenu) { //we have to reduce buttons due to text length limitations we reach with URI + iMyPageSize = iMyPageSize-3; // june 2015 Otto(garvin.twine) + if (iNumitems == 8) iMyPageSize = iMyPageSize-1; + //special cases again are 7 or 8 avis where we have to reduce "active" buttons again + else if (iNumitems == 7) iMyPageSize = iMyPageSize-2; + } + string sPagerPrompt; + if (iNumitems > iMyPageSize) { + iMyPageSize=iMyPageSize-2;//we'll use two slots for the MORE and PREV button, so shrink the page accordingly + + integer numPages=(iNumitems-1)/iMyPageSize; + if (iPage>numPages)iPage=0; + else if (iPage<0) iPage=numPages; + + iStart = iPage * iMyPageSize; + //multi page menu + sPagerPrompt = sPagerPrompt + "\nPage "+(string)(iPage+1)+"/"+(string)(numPages+1); + } + integer iEnd = iStart + iMyPageSize - 1; + if (iEnd >= iNumitems) iEnd = iNumitems - 1; + integer iPagerPromptLen = GetStringBytes(sPagerPrompt); + //Debug("start at "+(string)iStart+", end at "+(string)iEnd); + + //if we've been told to, calculate numbering from buttons supplied, inlined ButtonDigits function + if (iWithNums == -1) { + integer iNumButtons=llGetListLength(lMenuItems); + iWithNums=llStringLength((string)iNumButtons); + //if ( iNumButtons < 10 ) iWithNums = 1; + //else if (iNumButtons < 100) iWithNums = 2; + //else if (iNumButtons < 1000) iWithNums = 3; // more than 100 is unlikely, considering the size of a LM + while (iNumButtons--) { + if (GetStringBytes(llList2String(lMenuItems,iNumButtons))>18) { + jump longButtonName; //one of the options is too long for a button, thats all we need to know. + } + } + iWithNums=0; + @longButtonName; + } + //Debug("numbered list:"+(string)iWithNums); + // create list of buttons to use, and number them if needed + string sNumberedButtons; + integer iNBPromptlen; + list lButtons; //list of buttons to be used in the dialog, sliced by page and maybe with numbers added, not the lMenuItems we were supplied + if (iWithNums) { // put numbers in front of buttons: "00 Button1", "01 Button2", ... + integer iCur; + sNumberedButtons="\n"; //let's make this a linebreak instead + for (iCur = iStart; iCur <= iEnd; iCur++) { + string sButton = llList2String(lMenuItems, iCur); + if ((key)sButton) { + //fixme: inlined single use key2name function + if (g_iSelectAviMenu) sButton = NameURI((key)sButton); + else if (llGetDisplayName((key)sButton)) sButton=llGetDisplayName((key)sButton); + else sButton=llKey2Name((key)sButton); + } + //inlined single use Integer2String function + string sButtonNumber = (string)iCur; + + while (llStringLength(sButtonNumber) iMyPageSize) lButtons = llList2List(lMenuItems, iStart, iEnd); + else lButtons = lMenuItems; + //Debug("buttons:"+llDumpList2String(lButtons,",")); + sPrompt = SubstitudeVars(sPrompt); + //make a prompt small enough to fit in the 512 limit for dialogs, prepare overflow for chat message + integer iPromptlen=GetStringBytes(sPrompt); + string sThisPrompt; + string sThisChat; + if (iPromptlen + iNBPromptlen + iPagerPromptLen < 512) //we can fit it all in the dialog + sThisPrompt = sPrompt + sNumberedButtons + sPagerPrompt ; + else if (iPromptlen + iPagerPromptLen < 512) { //we can fit in the whole prompt and pager info, but not the buttons list + if (iPromptlen + iPagerPromptLen < 459) { + sThisPrompt = sPrompt + "\nPlease check nearby chat for button descriptions.\n" + sPagerPrompt; + } else + sThisPrompt = sPrompt + sPagerPrompt; + sThisChat = sNumberedButtons; + } else { //can't fit prompt and pager, so send truncated prompt, pager and chat full prompt and button list + sThisPrompt=TruncateString(sPrompt,510-iPagerPromptLen)+sPagerPrompt; + sThisChat = sPrompt+sNumberedButtons; + } + //Debug("prompt:"+sThisPrompt); + //unless asked not to, chat anything that wouldn't fit to menu user + if (! ~llListFindList(MRSBUN, [kRecipient])){ + integer iRemainingChatLen; + while ((iRemainingChatLen=llStringLength(sThisChat))){ //capture and compare in one go + if(iRemainingChatLen<1015) { + Notify(kRecipient,sThisChat,FALSE); //if its short enough, IM it in one chunk + sThisChat=""; + } else { + string sMessageChunk=TruncateString(sPrompt,1015); + Notify(kRecipient,sMessageChunk,FALSE); + sThisChat=llGetSubString(sThisChat,llStringLength(sMessageChunk),-1); + } + } + } + //Debug("chat prompt:"+sThisChat); + integer iChan=llRound(llFrand(10000000)) + 100000; + while (~llListFindList(g_lMenus, [iChan])) iChan=llRound(llFrand(10000000)) + 100000; + integer iListener = llListen(iChan, "", kRecipient, ""); + //LED ON + llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_FULLBRIGHT,ALL_SIDES,TRUE,PRIM_BUMP_SHINY,ALL_SIDES,PRIM_SHINY_NONE,PRIM_BUMP_NONE,PRIM_GLOW,ALL_SIDES,0.4]); + //send dialog to viewer + if (llGetListLength(lMenuItems+lUtilityButtons)){ + list lNavButtons; + if (iNumitems > iMyPageSize) lNavButtons=[PREV,MORE]; + llDialog(kRecipient, sThisPrompt, PrettyButtons(lButtons, lUtilityButtons, lNavButtons), iChan); + } + else llTextBox(kRecipient, sThisPrompt, iChan); + //LED OFF + llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_FULLBRIGHT,ALL_SIDES,FALSE,PRIM_BUMP_SHINY,ALL_SIDES,PRIM_SHINY_HIGH,PRIM_BUMP_NONE,PRIM_GLOW,ALL_SIDES,0.0]); + //set dialog timeout + llSetTimerEvent(g_iReapeat); + integer ts = llGetUnixTime() + g_iTimeOut; + + //write entry in tracking list + g_lMenus += [iChan, kID, iListener, ts, kRecipient, sPrompt, llDumpList2String(lMenuItems, "|"), llDumpList2String(lUtilityButtons, "|"), iPage, iWithNums, iAuth,extraInfo]; + //Debug("Made Dialog"); +} + +integer GetStringBytes(string sStr) { + sStr = llEscapeURL(sStr); + integer l = llStringLength(sStr); + list lAtoms = llParseStringKeepNulls(sStr, ["%"], []); + return l - 2 * llGetListLength(lAtoms) + 2; +} + +string TruncateString(string sStr, integer iBytes) { + sStr = llEscapeURL(sStr); + integer j = 0; + string sOut; + integer l = llStringLength(sStr); + for (; j < l; j++) { + string c = llGetSubString(sStr, j, j); + if (c == "%") { + if (iBytes >= 2) { + sOut += llGetSubString(sStr, j, j+2); + j += 2; + iBytes -= 2; + } + } else if (iBytes >= 1) { + sOut += c; + iBytes --; + } + } + return llUnescapeURL(sOut); +} + +list PrettyButtons(list lOptions, list lUtilityButtons, list iPagebuttons) { //returns a list formatted to that "options" will start in the top left of a dialog, and "utilitybuttons" will start in the bottom right + list lSpacers; + list lCombined = lOptions + lUtilityButtons + iPagebuttons; + while (llGetListLength(lCombined) % 3 != 0 && llGetListLength(lCombined) < 12) { + lSpacers += [BLANK]; + lCombined = lOptions + lSpacers + lUtilityButtons + iPagebuttons; + } + // check if a UPBUTTON is present and remove it for the moment + integer u = llListFindList(lCombined, [UPMENU]); + if (u != -1) lCombined = llDeleteSubList(lCombined, u, u); + + list lOut = llList2List(lCombined, 9, 11); + lOut += llList2List(lCombined, 6, 8); + lOut += llList2List(lCombined, 3, 5); + lOut += llList2List(lCombined, 0, 2); + //make sure we move UPMENU to the lower right corner + if (u != -1) lOut = llListInsertList(lOut, [UPMENU], 2); + + return lOut; +} + +RemoveMenuStride(integer iIndex) { //fixme: duplicates entire global lMenu list + //tell this function the menu you wish to remove, identified by list index + //it will close the listener, remove the menu's entry from the list, and return the new list + //should be called in the listen event, and on menu timeout + integer iListener = llList2Integer(g_lMenus, iIndex + 2); + llListenRemove(iListener); + g_lMenus=llDeleteSubList(g_lMenus, iIndex, iIndex + g_iStrideLength - 1); +} + +CleanList() { + //Debug("cleaning list"); + //loop through menus and remove any whose timeouts are in the past + //start at end of list and loop down so that indices don't get messed up as we remove items + integer iLength = llGetListLength(g_lMenus); + integer n; + integer iNow = llGetUnixTime(); + for (n = iLength - g_iStrideLength; n >= 0; n -= g_iStrideLength) { + integer iDieTime = llList2Integer(g_lMenus, n + 3); + //Debug("dietime: " + (string)iDieTime); + if (iNow > iDieTime) { + //Debug("menu timeout"); + key kID = llList2Key(g_lMenus, n + 1); + llMessageLinked(LINK_ALL_OTHERS, DIALOG_TIMEOUT, "", kID); + RemoveMenuStride(n); + } + } + if (g_iSensorTimeout>iNow){ //sensor took too long to return. Ignore it, and do the next in the list + g_lSensorDetails=llDeleteSubList(g_lSensorDetails,0,3); + if (llGetListLength(g_lSensorDetails)>0) dequeueSensor(); + } +} + +ClearUser(key kRCPT) { + //find any strides belonging to user and remove them + integer iIndex = llListFindList(g_lMenus, [kRCPT]); + while (~iIndex) { + //Debug("removed stride for " + (string)kRCPT); + RemoveMenuStride(iIndex -4); + //g_lMenus = llDeleteSubList(g_lMenus, iIndex - 4, iIndex - 5 + g_iStrideLength); + iIndex = llListFindList(g_lMenus, [kRCPT]); + } + //Debug(llDumpList2String(g_lMenus, ",")); +} + +UserCommand(integer iNum, string sStr, key kID) { + if (iNum == CMD_GROUP) return; + list lParams = llParseString2List(llToLower(sStr), ["="], []); + string sToken = llList2String(lParams, 0); + string sValue = llList2String(lParams, 1); + if (sToken == SPAMSWITCH) {// add/rem user to verbose=off list + integer i = llListFindList(MRSBUN, [kID]); + if (sValue == "off") { + if (~i) return; // already in list + MRSBUN += [kID]; + Notify(kID,"Verbose Feature activated for you.",FALSE); + } else if (~i) { + MRSBUN = llDeleteSubList(MRSBUN, i, i); + Notify(kID,"Verbose Feature de-activated for you.",FALSE); + } else return; // not in list to start with + if (!llGetListLength(MRSBUN)) llMessageLinked(LINK_SAVE, LM_SETTING_DELETE, g_sSettingToken + SPAMSWITCH, ""); + else llMessageLinked(LINK_SAVE, LM_SETTING_SAVE, g_sSettingToken + SPAMSWITCH + "=" + llList2CSV(MRSBUN), ""); + } +} + +dequeueSensor() { + //get sStr of first set of sensor details, unpack it and run the apropriate sensor + //Debug((string)llGetListLength(g_lSensorDetails)); + list lParams = llParseStringKeepNulls(llList2String(g_lSensorDetails,2), ["|"], []); + //sensor information is encoded in the first 5 fields of the lButtons list, ready to feed to the sensor command, + list lSensorInfo = llParseStringKeepNulls(llList2String(lParams, 3), ["`"], []); + /* Debug("Running sensor with\n"+ + llList2String(lSensorInfo,0)+"\n"+ + llList2String(lSensorInfo,1)+"\n"+ + (string)llList2Integer(lSensorInfo,2)+"\n"+ + (string)llList2Float(lSensorInfo,3)+"\n"+ + (string)llList2Float(lSensorInfo,4) + );*/ + + if (llList2Integer(lSensorInfo,2) == (integer)AGENT) g_iSelectAviMenu = TRUE; + else g_iSelectAviMenu = FALSE; + llSensor(llList2String(lSensorInfo,0),(key)llList2String(lSensorInfo,1),llList2Integer(lSensorInfo,2),llList2Float(lSensorInfo,3),llList2Float(lSensorInfo,4)); + g_iSensorTimeout=llGetUnixTime()+10; + llSetTimerEvent(g_iReapeat); +} + +default { + on_rez(integer iParam) { + llResetScript(); + } + + state_entry() { + if (llGetStartParameter()==825) llSetRemoteScriptAccessPin(0); + g_kWearer=llGetOwner(); + g_sPrefix = llToLower(llGetSubString(llKey2Name(llGetOwner()), 0,1)); + g_sWearerName = NameURI(g_kWearer); + g_sDeviceName = llList2String(llGetLinkPrimitiveParams(1,[PRIM_DESC]),0); + if (g_sDeviceName == "" || g_sDeviceName =="(No Description)") + g_sDeviceName = llList2String(llGetLinkPrimitiveParams(1,[PRIM_NAME]),0); + llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NAME,g_sDeviceName]); + //Debug("Starting"); + } + + sensor(integer num_detected){ + //get sensot request info from list + list lSensorInfo=llList2List(g_lSensorDetails,0,3); + g_lSensorDetails=llDeleteSubList(g_lSensorDetails,0,3); + + list lParams=llParseStringKeepNulls(llList2String(lSensorInfo,2), ["|"], []); + list lButtons = llParseStringKeepNulls(llList2String(lParams, 3), ["`"], []); + //sensor information is encoded in the first 5 fields of the lButtons list, we've run the sensor so we don't need that now. + //6th field is "find" information + //7th is boolean, 0 for return a dialog, 1 for return the first matching name + string sFind=llList2String(lButtons,5); + //Debug(sFind); + integer bReturnFirstMatch=llList2Integer(lButtons,6); + lButtons=[]; + integer i; + for (; i 0) + dequeueSensor(); + else g_bSensorLock=FALSE; + g_iSelectAviMenu = FALSE; + return; + } + + } + } + @next; + //pack buttons back into a ` delimited list, and put it back into lParams + string sButtons=llDumpList2String(lButtons,"`"); + lParams=llListReplaceList(lParams,[sButtons],3,3); + //fake fresh dialog call with our new buttons in place, using the rest of the information we were sent + llMessageLinked(LINK_THIS,DIALOG,llDumpList2String(lParams,"|"),(key)llList2String(lSensorInfo,3)); + //if we have more sensors to run, run another one now, else unlock subsys and quite + if (llGetListLength(g_lSensorDetails) > 0) + dequeueSensor(); + else g_bSensorLock=FALSE; + } + + no_sensor() { + list lSensorInfo=llList2List(g_lSensorDetails,0,3); + g_lSensorDetails=llDeleteSubList(g_lSensorDetails,0,3); + + list lParams=llParseStringKeepNulls(llList2String(lSensorInfo,2), ["|"], []); + lParams=llListReplaceList(lParams,[""],3,3); + //fake fresh dialog call with our new buttons in place, using the rest of the information we were sent + llMessageLinked(LINK_THIS,DIALOG,llDumpList2String(lParams,"|"),(key)llList2String(lSensorInfo,3)); + //if we have more sensors to run, run another one now, else unlock subsys and quit + if (llGetListLength(g_lSensorDetails) > 0) + dequeueSensor(); + else { + g_iSelectAviMenu = FALSE; + g_bSensorLock=FALSE; + } + } + + link_message(integer iSender, integer iNum, string sStr, key kID) { + if (iNum == SENSORDIALOG){ + //first, store all incoming parameters in a global sensor details list + //test for locked sensor subsystem + //if subsys locked, do nothing + //if subsys open, run sensor with first set of details in the list, and set timeout + // Debug(sStr); + g_lSensorDetails+=[iSender, iNum, sStr, kID]; + if (! g_bSensorLock){ + g_bSensorLock=TRUE; + dequeueSensor(); + } + } else if (iNum == DIALOG) { + //give a dialog with the options on the button labels + //str will be pipe-delimited list with rcpt|prompt|page|backtick-delimited-list-buttons|backtick-delimited-utility-buttons|auth + //Debug("DIALOG:"+sStr); + if (iSender != llGetLinkNumber()) g_iSelectAviMenu = FALSE; + list lParams = llParseStringKeepNulls(sStr, ["|"], []); + key kRCPT = llGetOwnerKey((key)llList2String(lParams, 0)); + integer iIndex = llListFindList(g_lRemoteMenus, [kRCPT]); + if (~iIndex) { + if (llKey2Name(kRCPT)=="") { //if recipient is not in the sim. Inlined single use InSim(kRCPT) function + llHTTPRequest(llList2String(g_lRemoteMenus, iIndex+1), [HTTP_METHOD, "POST"], sStr+"|"+(string)kID); + return; + } else g_lRemoteMenus = llListReplaceList(g_lRemoteMenus, [], iIndex, iIndex+1); + } + string sPrompt = llList2String(lParams, 1); + integer iPage = (integer)llList2String(lParams, 2); + if (iPage < 0 ) { + g_iSelectAviMenu = TRUE; + iPage = 0; + } + list lButtons = llParseString2List(llList2String(lParams, 3), ["`"], []); + if (llList2String(lButtons,0) == "colormenu please") { + lButtons = llList2ListStrided(g_lColors,0,-1,2); + g_iColorMenu = TRUE; + } + integer iDigits=-1; //iDigits==-1 means Dialog should run idigits on the buttons + list ubuttons = llParseString2List(llList2String(lParams, 4), ["`"], []); + integer iAuth = CMD_ZERO; + if (llGetListLength(lParams)>=6) iAuth = llList2Integer(lParams, 5); + //first clean out any strides already in place for that user. prevents having lots of listens open if someone uses the menu several times while sat + ClearUser(kRCPT); + Dialog(kRCPT, sPrompt, lButtons, ubuttons, iPage, kID, iDigits, iAuth,""); + } + else if (llGetSubString(sStr, 0, 10) == "remotemenu:") { + if (iNum == CMD_OWNER || iNum == CMD_TRUSTED) { + string sCmd = llGetSubString(sStr, 11, -1); + //Debug("dialog cmd:" + sCmd); + if (llGetSubString(sCmd, 0, 3) == "url:") { + integer iIndex = llListFindList(g_lRemoteMenus, [kID]); + if (~iIndex) + g_lRemoteMenus = llListReplaceList(g_lRemoteMenus, [kID, llGetSubString(sCmd, 4, -1)], iIndex, iIndex+1); + else + g_lRemoteMenus += [kID, llGetSubString(sCmd, 4, -1)]; + llMessageLinked(LINK_ALL_OTHERS, iNum, "menu", kID); + } else if (llGetSubString(sCmd, 0, 2) == "off") { + integer iIndex = llListFindList(g_lRemoteMenus, [kID]); + if (~iIndex) + g_lRemoteMenus = llListReplaceList(g_lRemoteMenus, [], iIndex, iIndex+1); + } + else if (llGetSubString(sCmd, 0, 8) == "response:") { + list lParams = llParseString2List(llGetSubString(sCmd, 9, -1), ["|"], []); + //llMessageLinked(LINK_SET, DIALOG_RESPONSE, (string)kAv + "|" + sMessage + "|" + (string)iPage, kMenuID); + llMessageLinked(LINK_ALL_OTHERS, DIALOG_RESPONSE, llList2String(lParams, 0) + "|" + llList2String(lParams, 1) + "|" + llList2String(lParams, 2), llList2String(lParams, 3)); + } else if (llGetSubString(sCmd, 0, 7) == "timeout:") + llMessageLinked(LINK_ALL_OTHERS, DIALOG_TIMEOUT, "", llGetSubString(sCmd, 8, -1)); + } + } + else if (iNum >= CMD_OWNER && iNum <= CMD_WEARER) UserCommand(iNum, sStr, kID); + else if (iNum == LM_SETTING_RESPONSE) { + list lParams = llParseString2List(sStr, ["="], []); + string sToken = llList2String(lParams, 0); + string sValue = llList2String(lParams, 1); + if (sToken == g_sSettingToken + SPAMSWITCH) MRSBUN = llParseString2List(sValue, [","], []); + else if (sToken == g_sGlobalToken+"DeviceType") g_sDeviceType = sValue; + else if (sToken == g_sGlobalToken+"DeviceName") { + g_sDeviceName = sValue; + llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NAME,g_sDeviceName]); + } else if (sToken == g_sGlobalToken+"WearerName") { + if (llSubStringIndex(sValue, "secondlife:///app/agent")) + g_sWearerName = "["+NameURI(g_kWearer)+" " + sValue + "]"; + else g_sWearerName = sValue; + } else if (sToken == g_sGlobalToken+"prefix"){ + if (sValue != "") g_sPrefix=sValue; + } else if (sToken == g_sGlobalToken+"channel") g_iListenChan = (integer)sValue; + else if (sToken == "auth_owner") + g_lOwners = llParseString2List(sValue, [","], []); + } else if (iNum == LOADPIN && sStr == llGetScriptName()) { + integer iPin = (integer)llFrand(99999.0)+1; + llSetRemoteScriptAccessPin(iPin); + llMessageLinked(iSender, LOADPIN, (string)iPin+"@"+llGetScriptName(),llGetKey()); + } else if (iNum == NOTIFY) Notify(kID,llGetSubString(sStr,1,-1),(integer)llGetSubString(sStr,0,0)); + else if (iNum == SAY) Say(llGetSubString(sStr,1,-1),(integer)llGetSubString(sStr,0,0)); + else if (iNum == LINK_UPDATE) { + if (sStr == "LINK_SAVE") LINK_SAVE = iSender; + else if (sStr == "LINK_REQUEST") llMessageLinked(LINK_ALL_OTHERS,LINK_UPDATE,"LINK_DIALOG",""); + } else if (iNum==NOTIFY_OWNERS) NotifyOwners(sStr,(string)kID); + else if (iNum == REBOOT && sStr == "reboot") llResetScript(); + else if(iNum == LINK_CMD_DEBUG){ + integer onlyver=0; + if(sStr == "ver")onlyver=1; + llInstantMessage(kID, llGetScriptName() +" SCRIPT VERSION: "+g_sScriptVersion); + if(onlyver)return; // basically this command was: versions + } + } + + listen(integer iChan, string sName, key kID, string sMessage) { + integer iMenuIndex = llListFindList(g_lMenus, [iChan]); + if (~iMenuIndex) { + key kMenuID = llList2Key(g_lMenus, iMenuIndex + 1); + key kAv = llList2Key(g_lMenus, iMenuIndex + 4); + string sPrompt = llList2String(g_lMenus, iMenuIndex + 5); + // SA: null strings should not be kept for dialog buttons + list items = llParseString2List(llList2String(g_lMenus, iMenuIndex + 6), ["|"], []); + list ubuttons = llParseString2List(llList2String(g_lMenus, iMenuIndex + 7), ["|"], []); + integer iPage = llList2Integer(g_lMenus, iMenuIndex + 8); + integer iDigits = llList2Integer(g_lMenus, iMenuIndex + 9); + integer iAuth = llList2Integer(g_lMenus, iMenuIndex + 10); + string sExtraInfo = llList2String(g_lMenus, iMenuIndex + 11); + + RemoveMenuStride(iMenuIndex); + + if (sMessage == MORE) Dialog(kID, sPrompt, items, ubuttons, ++iPage, kMenuID, iDigits, iAuth,sExtraInfo); + else if (sMessage == PREV) Dialog(kID, sPrompt, items, ubuttons, --iPage, kMenuID, iDigits, iAuth, sExtraInfo); + else if (sMessage == BLANK) Dialog(kID, sPrompt, items, ubuttons, iPage, kMenuID, iDigits, iAuth, sExtraInfo); + else { + g_iSelectAviMenu = FALSE; + string sAnswer; + integer iIndex = llListFindList(ubuttons, [sMessage]); + if (iDigits && !~iIndex) { + integer iBIndex = (integer) llGetSubString(sMessage, 0, iDigits); + sAnswer = llList2String(items, iBIndex); + } else if (g_iColorMenu) { + integer iColorIndex =llListFindList(llList2ListStrided(g_lColors,0,-1,2),[sMessage]); + if (~iColorIndex) sAnswer = llList2String(llList2ListStrided(llDeleteSubList(g_lColors,0,0),0,-1,2),iColorIndex); + else sAnswer = sMessage; + g_iColorMenu = FALSE; + } else sAnswer = sMessage; + if (sAnswer == "") sAnswer = " "; //to have an answer to deal with send " " + llMessageLinked(LINK_ALL_OTHERS, DIALOG_RESPONSE, (string)kAv + "|" + sAnswer + "|" + (string)iPage + "|" + (string)iAuth, kMenuID); + } + } + } + + timer() { + CleanList(); + //if list is empty after that, then stop timer + if (!llGetListLength(g_lMenus) && !llGetListLength(g_lSensorDetails)) { + //Debug("no active dialogs, stopping timer"); + g_iSelectAviMenu = FALSE; + llSetTimerEvent(0.0); + } + } + + changed(integer iChange){ + if (iChange & CHANGED_OWNER) llResetScript(); +/* + if (iChange & CHANGED_REGION) { + if (g_iProfiled){ + llScriptProfiler(1); + Debug("profiling restarted"); + } + } +*/ + } +} diff --git a/playground/test.lua b/playground/test.lua new file mode 100644 index 0000000..50c0260 --- /dev/null +++ b/playground/test.lua @@ -0,0 +1,87 @@ +package.path = './model/?.lua;./ometa/?.lua;./lib/?.lua;./?.lua;' .. package.path + +local utils = require 'utils' +local Types = require 'types' +local Any, Array = Types.Any, Types.Array + +local OMeta = require 'ometa' +local Model = require 'ometa_abstractsyntax' +local Grammar = require 'ometa_lua_grammar'.OMetaInLuaGrammar + +local alt = {'reference'} + +local OMetaToLuaTranslator = require('ometa_ast2lua_ast_' .. alt[1]) +local ToSourceTranslator = require 'lua_ast2source' + +local function parseFile(path) + return utils.measure( + function() + return Grammar.block:matchFile(path) + end + ) +end + +local function translateTree(tree) + return utils.measure( + function() + return OMetaToLuaTranslator.toLuaAst(tree) + end + ) +end + +local function generateSourceTrans(tree) + return utils.measure( + function() + return ToSourceTranslator.trans:matchMixed(tree) + end + ) +end + +local function generateSourceDirect(tree) + return utils.measure( + function() + return tree:toLuaSource() + end + ) +end + +local function compileFile(name) + print('----------------------------') + print('compilation: ' .. name) + local ometaAst, pt = parseFile(name) + print(string.format('source2ast: %.3f', pt)) + --utils.writeFile(name .. '.oast', tostring(ometaAst)) + local luaAst, tt = translateTree(ometaAst) + print(string.format('ometa2lua: %.3f', tt)) + --utils.writeFile(name .. '.last', tostring(luaAst)) + local luaSource, t2t = +-- generateSourceDirect(luaAst) + generateSourceTrans(luaAst) + print(string.format('ast2source: %.3f', t2t)) + utils.writeFile(name:sub(1, -5) .. '.lua', luaSource) + return pt + tt + t2t +end + +local libs = {'commons','grammar_commons','binary_commons','auxiliary','lua_grammar','lua52_grammar','ometa_grammar','ometa_lua_grammar','ometa_ast2lua_ast_' .. alt[1],'lua_ast2source'} + +return { + parseFile = parseFile, + translateTree = translateTree, + generateSource = generateSourceTrans, + compileFile = compileFile; + + build = function() + local t = 0 + for l = 1, #libs do +-- t = t + compileFile('./ometa/' .. libs[l]) + local pass, res = pcall(compileFile, './ometa/' .. libs[l] .. '.lpp') + if not pass then + print(res) + else + t = t + res + end + end + print('----------------------------') + print(string.format('total: %.3f', t)) + end; +} diff --git a/playground/test.parse_gen b/playground/test.parse_gen new file mode 100644 index 0000000..8667a50 --- /dev/null +++ b/playground/test.parse_gen @@ -0,0 +1,271 @@ +/coderequires /{ + #include "regular.h" +/} + +/code /{ + #include + #include "regular_lex.h" + + static void yyerror(char const* msg, reg_nfa* out, void* scanner); + static int yyparse(reg_nfa* out, void* scanner); + static int init_node(reg_nfa_table* table) { + unsigned int* p = malloc((sizeof *p) * 16); + if (p == NULL) return 1; + int res = 0; + DYNARR_CHK(table->node_cnt, table->node_cap, table->nodes, res); + if (res) {free(p); return 1;} + table->nodes[table->node_cnt].lambda = (reg_nfa_lam){.paths=p,.cnt=0,.cap=16}; + for (size_t i = 0; i < (1 << CHAR_BIT); ++i) { + table->nodes[table->node_cnt].tran[i] = UINT_MAX; + } + ++(table->node_cnt); + return 0; + } + + static int add_path(reg_nfa_node* node, unsigned int goal) { + int res = 0; + DYNARR_CHK(node->lambda.cnt, node->lambda.cap, node->lambda.paths, res); + if (res) return 1; + node->lambda.paths[node->lambda.cnt] = goal; + ++(node->lambda.cnt); + return 0; + } +/} + +/parseparam out +/parseparam scanner +/lexparam scanner + +/token tokpipe 1 +/token tokkleene 2 +/token tokplus 3 +/token tokopen 4 +/token tokclose 5 +/token tokchar 6 +/token tokdot 7 +/token tokdash 8 + +/nterm NTRE +/nterm NTALT +/nterm NTALTLIST +/nterm NTSEQ +/nterm NTSEQLIST +/nterm NTATOM +/nterm NTATOMMOD +/nterm NTNUCLEUS +/nterm NTCHARRNG + +/start NTRE + +%% + +NTRE: + NTALT /{out->specials = $1;/} + ; + +NTALT: + NTSEQ NTALTLIST /{ + if ($2 == NULL) { + $0 = $1; + } else { + if (init_node(&(out->table))) exit(1); + if (init_node(&(out->table))) exit(1); + if (add_path(&(out->table.nodes[out->table.node_cnt - 2]), $1.start)) exit(1); + if (add_path(&(out->table.nodes[$1.end]), out->table.node_cnt - 1)) exit(1); + struct reg_link* curr = $2; + while (curr != NULL) { + struct reg_link* tmp = curr; + if (add_path(&(out->table.nodes[out->table.node_cnt - 2]), tmp->sub.start)) exit(1); + if (add_path(&(out->table.nodes[tmp->sub.end]), out->table.node_cnt - 1)) exit(1); + curr = tmp->next; + free(tmp); + } + $0.start = out->table.node_cnt - 2; + $0.end = out->table.node_cnt - 1; + } + /} + ; + +NTALTLIST: + tokpipe NTSEQ NTALTLIST /{ + struct reg_link* top = malloc(sizeof *top); + if (top == NULL) exit(1); + top->next = $3; + top->sub = $2; + $0 = top; + /} + | /empty /{$0 = NULL;/} + ; + +NTSEQ: + NTATOM NTSEQLIST /{ + if ($2 == NULL) { + $0 = $1; + } else { + if (init_node(&(out->table))) exit(1); + if (init_node(&(out->table))) exit(1); + if (add_path(&(out->table.nodes[out->table.node_cnt - 2]), $1.start)) exit(1); + unsigned int save = $1.end; + struct reg_link* curr = $2; + while (curr != NULL) { + struct reg_link* tmp = curr; + if (add_path(&(out->table.nodes[save]), tmp->sub.start)) exit(1); + save = tmp->sub.end; + curr = tmp->next; + free(tmp); + } + if (add_path(&(out->table.nodes[save]), out->table.node_cnt - 1)) exit(1); + $0.start = out->table.node_cnt - 2; + $0.end = out->table.node_cnt - 1; + } + /} + | /empty /{ + if (init_node(&(out->table))) exit(1); + if (init_node(&(out->table))) exit(1); + if (add_path(&(out->table.nodes[out->table.node_cnt - 2]), out->table.node_cnt - 1)) exit(1); + $0.start = out->table.node_cnt - 2; + $0.end = out->table.node_cnt - 1; + /} + ; + +NTSEQLIST: + NTATOM NTSEQLIST /{ + struct reg_link* top = malloc(sizeof *top); + top->next = $2; + top->sub = $1; + $0 = top; + /} + | /empty /{$0 = NULL;/} + ; + +NTATOM: + NTNUCLEUS NTATOMMOD /{ + if ($2 == MOD_NONE) { + $0 = $1; + } else { + if (init_node(&(out->table))) exit(1); + if (init_node(&(out->table))) exit(1); + if (add_path(&(out->table.nodes[out->table.node_cnt - 2]), $1.start)) exit(1); + if (add_path(&(out->table.nodes[$1.end]), out->table.node_cnt - 1)) exit(1); + if (add_path(&(out->table.nodes[$1.end]), $1.start)) exit(1); + if ($2 == MOD_KLEENE) { + if (add_path(&(out->table.nodes[$1.start]), $1.end)) exit(1); + } + $0.start = out->table.node_cnt - 2; + $0.end = out->table.node_cnt - 1; + } + /} + ; + +NTATOMMOD: + tokkleene /{$0 = MOD_KLEENE;/} + | tokplus /{$0 = MOD_PLUS;/} + | /empty /{$0 = MOD_NONE;/} + ; + +NTNUCLEUS: + tokopen NTALT tokclose /{$0 = $2;/} + | tokchar NTCHARRNG /{ + if (init_node(&(out->table))) exit(1); + if (init_node(&(out->table))) exit(1); + if ($2.type == RNG_NONE) { + out->table.nodes[out->table.node_cnt - 2].tran[(unsigned char)$1] = out->table.node_cnt - 1; + } else { + if ((unsigned char)$1 > (unsigned char)($2.top)) exit(1); + for (size_t i = (unsigned char)$1; i <= (unsigned char)($2.top); ++i) { + out->table.nodes[out->table.node_cnt - 2].tran[i] = out->table.node_cnt - 1; + } + } + $0.start = out->table.node_cnt - 2; + $0.end = out->table.node_cnt - 1; + /} + | tokdot /{ + if (init_node(&(out->table))) exit(1); + if (init_node(&(out->table))) exit(1); + for (size_t i = 0; i < (1 << CHAR_BIT); ++i) { + out->table.nodes[out->table.node_cnt - 2].tran[i] = out->table.node_cnt - 1; + } + $0.start = out->table.node_cnt - 2; + $0.end = out->table.node_cnt - 1; + /} + ; + +NTCHARRNG: + tokdash tokchar /{ + $0.type = RNG_TOP; + $0.top = $2; + /} + | /empty /{$0.type = RNG_NONE;/} + ; + +%% + +void yyerror(char const* msg, reg_nfa* out, void* scanner) { + (void)out; + (void)scanner; + fprintf(stderr, "%s\n", msg); +} + +static void write_reg(FILE* restrict out, reg_nfa const* restrict r) { + _Bool* table = malloc((sizeof *table) * r->table.node_cnt); + fputs("+----++", out); + for (size_t i = 0; i < (1 << CHAR_BIT); ++i) fputs("-----+", out); + fputs("\n| T ||", out); + for (size_t i = 0; i < (1 << CHAR_BIT); ++i) { + if (i >= 32 && i <= 126) fprintf(out, " %c |", (char)i); + else fprintf(out, "<%3zu>|", i); + } + fputs("\n+----++", out); + for (size_t i = 0; i < (1 << CHAR_BIT); ++i) fputs("-----+", out); + fputs("\n+----++", out); + for (size_t i = 0; i < (1 << CHAR_BIT); ++i) fputs("-----+", out); + for (size_t i = 0; i < r->table.node_cnt; ++i) { + fprintf(out, "\n|%c%3zu||", r->specials.end == i ? '+' : (r->specials.start == i ? 'S' : ' '), i); + for (size_t j = 0; j < (1 << CHAR_BIT); ++j) { + if (r->table.nodes[i].tran[j] == UINT_MAX) { + fprintf(out, " E |"); + } else { + fprintf(out, " %3u |", r->table.nodes[i].tran[j]); + } + } + fputs("\n+----++", out); + for (size_t i = 0; i < (1 << CHAR_BIT); ++i) fputs("-----+", out); + } + fputs("\n\n+----++", out); + for (size_t i = 0; i < r->table.node_cnt; ++i) fputs("----+", out); + fputs("\n| L ||", out); + for (size_t i = 0; i < r->table.node_cnt; ++i) { + fprintf(out, "%c%3zu|", r->specials.end == i ? '+' : (r->specials.start == i ? 'S' : ' '), i); + } + fputs("\n+----++", out); + for (size_t i = 0; i < r->table.node_cnt; ++i) fputs("----+", out); + fputs("\n+----++", out); + for (size_t i = 0; i < r->table.node_cnt; ++i) fputs("----+", out); + for (size_t i = 0; i < r->table.node_cnt; ++i) { + for (size_t j = 0; j < r->table.node_cnt; ++j) table[j] = 0; + for (size_t j = 0; j < r->table.nodes[i].lambda.cnt; ++j) table[r->table.nodes[i].lambda.paths[j]] = 1; + fprintf(out, "\n|%c%3zu||", r->specials.end == i ? '+' : (r->specials.start == i ? 'S' : ' '), i); + for (size_t j = 0; j < r->table.node_cnt; ++j) { + fprintf(out, " %c |", table[j] ? '*' : ' '); + } + fputs("\n+----++", out); + for (size_t i = 0; i < r->table.node_cnt; ++i) fputs("----+", out); + } + fputc('\n', out); +} + +int main(void) { + void* scanner = init_scanner(stdin); + if (scanner == NULL) return 1; + reg_nfa out; + out.table.nodes = malloc((sizeof *(out.table.nodes)) * 16); + out.table.node_cnt = 0; + out.table.node_cap = 16; + int res = yyparse(&out, scanner); + fini_scanner(scanner); + if (res == 0) { + write_reg(stdout, &out); + fputc('\n', stdout); + } + return res; +} diff --git a/playground/test.php b/playground/test.php new file mode 100644 index 0000000..8f84d64 --- /dev/null +++ b/playground/test.php @@ -0,0 +1,422 @@ +0)) { + $im=$re*$im*2+$imc; + $re=$re2-$im2+$rec; + $re2=$re*$re; + $im2=$im*$im; + $color=$color-1; + } + if ( $color==0 ) { + print "_"; + } else { + print "#"; + } + } + print "
    "; + flush(); + } +} + +/****/ + +function mandel2() { + $b = " .:,;!/>)|&IH%*#"; + //float r, i, z, Z, t, c, C; + for ($y=30; printf("\n"), $C = $y*0.1 - 1.5, $y--;){ + for ($x=0; $c = $x*0.04 - 2, $z=0, $Z=0, $x++ < 75;){ + for ($r=$c, $i=$C, $k=0; $t = $z*$z - $Z*$Z + $r, $Z = 2*$z*$Z + $i, $z=$t, $k<5000; $k++) + if ($z*$z + $Z*$Z > 500000) break; + echo $b[$k%16]; + } + } +} + +/****/ + +function Ack($m, $n){ + if($m == 0) return $n+1; + if($n == 0) return Ack($m-1, 1); + return Ack($m - 1, Ack($m, ($n - 1))); +} + +function ackermann($n) { + $r = Ack(3,$n); + print "Ack(3,$n): $r\n"; +} + +/****/ + +function ary($n) { + for ($i=0; $i<$n; $i++) { + $X[$i] = $i; + } + for ($i=$n-1; $i>=0; $i--) { + $Y[$i] = $X[$i]; + } + $last = $n-1; + print "$Y[$last]\n"; +} + +/****/ + +function ary2($n) { + for ($i=0; $i<$n;) { + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + $X[$i] = $i; ++$i; + } + for ($i=$n-1; $i>=0;) { + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + $Y[$i] = $X[$i]; --$i; + } + $last = $n-1; + print "$Y[$last]\n"; +} + +/****/ + +function ary3($n) { + for ($i=0; $i<$n; $i++) { + $X[$i] = $i + 1; + $Y[$i] = 0; + } + for ($k=0; $k<1000; $k++) { + for ($i=$n-1; $i>=0; $i--) { + $Y[$i] += $X[$i]; + } + } + $last = $n-1; + print "$Y[0] $Y[$last]\n"; +} + +/****/ + +function fibo_r($n){ + return(($n < 2) ? 1 : fibo_r($n - 2) + fibo_r($n - 1)); +} + +function fibo($n) { + $r = fibo_r($n); + print "$r\n"; +} + +/****/ + +function hash1($n) { + for ($i = 1; $i <= $n; $i++) { + $X[dechex($i)] = $i; + } + $c = 0; + for ($i = $n; $i > 0; $i--) { + if ($X[dechex($i)]) { $c++; } + } + print "$c\n"; +} + +/****/ + +function hash2($n) { + for ($i = 0; $i < $n; $i++) { + $hash1["foo_$i"] = $i; + $hash2["foo_$i"] = 0; + } + for ($i = $n; $i > 0; $i--) { + foreach($hash1 as $key => $value) $hash2[$key] += $value; + } + $first = "foo_0"; + $last = "foo_".($n-1); + print "$hash1[$first] $hash1[$last] $hash2[$first] $hash2[$last]\n"; +} + +/****/ + +function gen_random ($n) { + global $LAST; + return( ($n * ($LAST = ($LAST * IA + IC) % IM)) / IM ); +} + +function heapsort_r($n, &$ra) { + $l = ($n >> 1) + 1; + $ir = $n; + + while (1) { + if ($l > 1) { + $rra = $ra[--$l]; + } else { + $rra = $ra[$ir]; + $ra[$ir] = $ra[1]; + if (--$ir == 1) { + $ra[1] = $rra; + return; + } + } + $i = $l; + $j = $l << 1; + while ($j <= $ir) { + if (($j < $ir) && ($ra[$j] < $ra[$j+1])) { + $j++; + } + if ($rra < $ra[$j]) { + $ra[$i] = $ra[$j]; + $j += ($i = $j); + } else { + $j = $ir + 1; + } + } + $ra[$i] = $rra; + } +} + +function heapsort($N) { + global $LAST; + + define("IM", 139968); + define("IA", 3877); + define("IC", 29573); + + $LAST = 42; + for ($i=1; $i<=$N; $i++) { + $ary[$i] = gen_random(1); + } + heapsort_r($N, $ary); + printf("%.10f\n", $ary[$N]); +} + +/****/ + +function mkmatrix ($rows, $cols) { + $count = 1; + $mx = array(); + for ($i=0; $i<$rows; $i++) { + for ($j=0; $j<$cols; $j++) { + $mx[$i][$j] = $count++; + } + } + return($mx); +} + +function mmult ($rows, $cols, $m1, $m2) { + $m3 = array(); + for ($i=0; $i<$rows; $i++) { + for ($j=0; $j<$cols; $j++) { + $x = 0; + for ($k=0; $k<$cols; $k++) { + $x += $m1[$i][$k] * $m2[$k][$j]; + } + $m3[$i][$j] = $x; + } + } + return($m3); +} + +function matrix($n) { + $SIZE = 30; + $m1 = mkmatrix($SIZE, $SIZE); + $m2 = mkmatrix($SIZE, $SIZE); + while ($n--) { + $mm = mmult($SIZE, $SIZE, $m1, $m2); + } + print "{$mm[0][0]} {$mm[2][3]} {$mm[3][2]} {$mm[4][4]}\n"; +} + +/****/ + +function nestedloop($n) { + $x = 0; + for ($a=0; $a<$n; $a++) + for ($b=0; $b<$n; $b++) + for ($c=0; $c<$n; $c++) + for ($d=0; $d<$n; $d++) + for ($e=0; $e<$n; $e++) + for ($f=0; $f<$n; $f++) + $x++; + print "$x\n"; +} + +/****/ + +function sieve($n) { + $count = 0; + while ($n-- > 0) { + $count = 0; + $flags = range (0,8192); + for ($i=2; $i<8193; $i++) { + if ($flags[$i] > 0) { + for ($k=$i+$i; $k <= 8192; $k+=$i) { + $flags[$k] = 0; + } + $count++; + } + } + } + print "Count: $count\n"; +} + +/****/ + +function strcat($n) { + $str = ""; + while ($n-- > 0) { + $str .= "hello\n"; + } + $len = strlen($str); + print "$len\n"; +} + +/*****/ + +function gethrtime() +{ + $hrtime = hrtime(); + return (($hrtime[0]*1000000000 + $hrtime[1]) / 1000000000); +} + +function start_test() +{ + ob_start(); + return gethrtime(); +} + +function end_test($start, $name) +{ + global $total; + $end = gethrtime(); + ob_end_clean(); + $total += $end-$start; + $num = number_format($end-$start,3); + $pad = str_repeat(" ", 24-strlen($name)-strlen($num)); + + echo $name.$pad.$num."\n"; + ob_start(); + return gethrtime(); +} + +function total() +{ + global $total; + $pad = str_repeat("-", 24); + echo $pad."\n"; + $num = number_format($total,3); + $pad = str_repeat(" ", 24-strlen("Total")-strlen($num)); + echo "Total".$pad.$num."\n"; +} + +$t0 = $t = start_test(); +simple(); +$t = end_test($t, "simple"); +simplecall(); +$t = end_test($t, "simplecall"); +simpleucall(); +$t = end_test($t, "simpleucall"); +simpleudcall(); +$t = end_test($t, "simpleudcall"); +mandel(); +$t = end_test($t, "mandel"); +mandel2(); +$t = end_test($t, "mandel2"); +ackermann(7); +$t = end_test($t, "ackermann(7)"); +ary(50000); +$t = end_test($t, "ary(50000)"); +ary2(50000); +$t = end_test($t, "ary2(50000)"); +ary3(2000); +$t = end_test($t, "ary3(2000)"); +fibo(30); +$t = end_test($t, "fibo(30)"); +hash1(50000); +$t = end_test($t, "hash1(50000)"); +hash2(500); +$t = end_test($t, "hash2(500)"); +heapsort(20000); +$t = end_test($t, "heapsort(20000)"); +matrix(20); +$t = end_test($t, "matrix(20)"); +nestedloop(12); +$t = end_test($t, "nestedloop(12)"); +sieve(30); +$t = end_test($t, "sieve(30)"); +strcat(200000); +$t = end_test($t, "strcat(200000)"); +total(); +?> diff --git a/playground/test.rs b/playground/test.rs new file mode 100644 index 0000000..50c381f --- /dev/null +++ b/playground/test.rs @@ -0,0 +1,188 @@ +// +// Here I've added a space in generic parameter that end in ">>" to allow parse it +// +#![allow(unused_must_use)] + +extern crate syntax; +extern crate rustc; +extern crate serialize; +extern crate getopts; +extern crate rustc_trans; +extern crate rustc_driver; + +use getopts::{optflag,getopts}; + +use std::io; +use std::os; +use std::io::Reader; +use std::string::String; +use serialize::json; +use serialize::json::{Json}; +use syntax::diagnostics::registry; + +use rustc::session; +use rustc::session::config; +use rustc::session::config::Input; + +use rustc_driver::driver; + +fn filter_json(j: &mut json::Json) { + let mut replace = None; + + match *j { + Json::Object(ref mut ob) => { + // remove + ob.remove(&String::from_str("span")); + ob.remove(&String::from_str("id")); + let mut kv : Option<(String,Vec)> = None; + match ob.get(&String::from_str("node")) { + Some(&Json::Object(ref ob2)) => { + match (ob2.get(&String::from_str("variant")), + ob2.get(&String::from_str("fields"))) { + (Some(&Json::String(ref s)), Some(&Json::Array(ref ls))) => { + kv = Some((s.clone(), ls.clone())); + } + _ => () + } + } + _ => () + } + match kv { + None => (), + Some((k, v)) => { + ob.remove(&String::from_str("node")); + ob.insert(k, Json::Array(v)); + } + } + for (_, v) in ob.iter_mut() { + filter_json(v); + } + } + Json::Array(ref mut ls) => { + for v in ls.iter_mut() { + filter_json(v) + } + if ls.len() == 1 { + replace = Some(ls.as_slice()[0].clone()) + } + } + _ => () + } + match replace { + None => (), + Some(jj) => *j = jj + } +} + +static INDENT_STEP: int = 4; + +fn print_indent(indent: int) { + let mut out = io::stdout(); + for i in range(0, indent) { + if i % INDENT_STEP == 0 { + out.write_str("|"); + } else { + out.write_str(" "); + } + } +} + +fn print_sexp(indent: int, j: &json::Json) { + let mut out = io::stdout(); + + match *j { + + Json::Object(ref ob) => { + { + for (k, v) in ob.iter() { + print_indent(indent); + out.write_str("("); + out.write_str(k.as_slice()); + out.write_str("\n"); + print_sexp(indent + INDENT_STEP, v); + print_indent(indent); + out.write_str(")\n"); + } + } + } + Json::Array(ref ls) => { + print_indent(indent); + out.write_str("(\n"); + for v in ls.iter() { + print_sexp(indent + INDENT_STEP, v); + } + print_indent(indent); + out.write_str(")\n"); + } + Json::String(ref s) => { + print_indent(indent); + out.write_str(s.as_slice()); + out.write_str("\n"); + } + Json::Null => { + print_indent(indent); + out.write_str("\n"); + } + Json::Boolean(true) => { + print_indent(indent); + out.write_str("true\n"); + } + Json::Boolean(false) => { + print_indent(indent); + out.write_str("false\n"); + } + Json::I64(n) => { + print_indent(indent); + out.write_str(n.to_string().as_slice()); + out.write_str("\n"); + } + Json::U64(n) => { + print_indent(indent); + out.write_str(n.to_string().as_slice()); + out.write_str("\n"); + } + Json::F64(n) => { + print_indent(indent); + out.write_str(n.to_string().as_slice()); + out.write_str("\n"); + } + } +} + +fn main() { + + let args = os::args().into_iter().collect:: >(); + let opts = [ optflag("j", "", "dump output in JSON, not sexp") ]; + let matches = match getopts(args.tail(), &opts) { + Ok(m) => { m } + Err(f) => { panic!(f) } + }; + let dump_json = matches.opt_present("j"); + + match io::stdin().read_to_string() { + Ok(text) => { + let opt = config::basic_options(); + let sess = session::build_session(opt, None, + registry::Registry::new(&rustc::DIAGNOSTICS)); + let cfg = config::build_configuration(&sess); + let input = Input::Str(text); + let cr = driver::phase_1_parse_input(&sess, cfg, &input); + + // JSON-ify, meaning "encode then re-parse as just json", ugh. + let ast_str = json::encode(&cr.module); + let chars = ast_str.as_slice().chars().collect:: >(); + let mut b = json::Builder::new(chars.into_iter()); + let mut j = b.build().ok().unwrap(); + + filter_json(&mut j); + if dump_json { + println!("{}", j.pretty()); + } else { + print_sexp(0, &j); + } + }, + Err(ioerr) => { + panic!("I/O Error: {}", ioerr.desc); + } + } +} diff --git a/playground/test.sql b/playground/test.sql new file mode 100644 index 0000000..8045b48 --- /dev/null +++ b/playground/test.sql @@ -0,0 +1,2430 @@ +SELECT a,b,c from mytable; + +---- + +CREATE SCHEMA TESTLIBPQ2; +SET search_path = TESTLIBPQ2; +CREATE TABLE TBL1 (i int4); +CREATE TABLE TBL2 (i int4); +CREATE RULE r1 AS ON INSERT TO TBL1 DO + (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2); + + +--- + +-- database: presto; groups: tpch; tables: lineitem,part +SELECT sum(l_extendedprice * (1 - l_discount)) AS revenue +FROM lineitem, + part +WHERE ( + p_partkey = l_partkey + AND p_brand = 'Brand#12' + AND p_container IN ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') + AND l_quantity >= 1 AND l_quantity <= 1 + 10 + AND p_size BETWEEN 1 AND 5 + AND l_shipmode IN ('AIR', 'AIR REG') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR ( + p_partkey = l_partkey + AND p_brand = 'Brand#23' + AND p_container IN ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') + AND l_quantity >= 10 AND l_quantity <= 10 + 10 + AND p_size BETWEEN 1 AND 10 + AND l_shipmode IN ('AIR', 'AIR REG') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR ( + p_partkey = l_partkey + AND p_brand = 'Brand#34' + AND p_container IN ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') + AND l_quantity >= 20 AND l_quantity <= 20 + 10 + AND p_size BETWEEN 1 AND 15 + AND l_shipmode IN ('AIR', 'AIR REG') + AND l_shipinstruct = 'DELIVER IN PERSON' + ); + +---- + +-- +-- Copyright © 2016-2023 The Thingsboard Authors +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +CREATE TABLE IF NOT EXISTS tb_schema_settings +( + schema_version bigint NOT NULL, + CONSTRAINT tb_schema_settings_pkey PRIMARY KEY (schema_version) +); + +CREATE OR REPLACE PROCEDURE insert_tb_schema_settings() + LANGUAGE plpgsql AS +$$ +BEGIN + IF (SELECT COUNT(*) FROM tb_schema_settings) = 0 THEN + INSERT INTO tb_schema_settings (schema_version) VALUES (3003000); + END IF; +END; +$$; + +call insert_tb_schema_settings(); + +CREATE TABLE IF NOT EXISTS admin_settings ( + id uuid NOT NULL CONSTRAINT admin_settings_pkey PRIMARY KEY, + tenant_id uuid NOT NULL, + created_time bigint NOT NULL, + json_value varchar, + key varchar(255) +); + +CREATE TABLE IF NOT EXISTS alarm ( + id uuid NOT NULL CONSTRAINT alarm_pkey PRIMARY KEY, + created_time bigint NOT NULL, + ack_ts bigint, + clear_ts bigint, + additional_info varchar, + end_ts bigint, + originator_id uuid, + originator_type integer, + propagate boolean, + severity varchar(255), + start_ts bigint, + assign_ts bigint DEFAULT 0, + assignee_id uuid, + tenant_id uuid, + customer_id uuid, + propagate_relation_types varchar, + type varchar(255), + propagate_to_owner boolean, + propagate_to_tenant boolean, + acknowledged boolean, + cleared boolean +); + +CREATE TABLE IF NOT EXISTS alarm_comment ( + id uuid NOT NULL, + created_time bigint NOT NULL, + alarm_id uuid NOT NULL, + user_id uuid, + type varchar(255) NOT NULL, + comment varchar(10000), + CONSTRAINT fk_alarm_comment_alarm_id FOREIGN KEY (alarm_id) REFERENCES alarm(id) ON DELETE CASCADE +) PARTITION BY RANGE (created_time); + +CREATE TABLE IF NOT EXISTS entity_alarm ( + tenant_id uuid NOT NULL, + entity_type varchar(32), + entity_id uuid NOT NULL, + created_time bigint NOT NULL, + alarm_type varchar(255) NOT NULL, + customer_id uuid, + alarm_id uuid, + CONSTRAINT entity_alarm_pkey PRIMARY KEY (entity_id, alarm_id), + CONSTRAINT fk_entity_alarm_id FOREIGN KEY (alarm_id) REFERENCES alarm(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS audit_log ( + id uuid NOT NULL, + created_time bigint NOT NULL, + tenant_id uuid, + customer_id uuid, + entity_id uuid, + entity_type varchar(255), + entity_name varchar(255), + user_id uuid, + user_name varchar(255), + action_type varchar(255), + action_data varchar(1000000), + action_status varchar(255), + action_failure_details varchar(1000000) +) PARTITION BY RANGE (created_time); + +CREATE TABLE IF NOT EXISTS attribute_kv ( + entity_type varchar(255), + entity_id uuid, + attribute_type varchar(255), + attribute_key varchar(255), + bool_v boolean, + str_v varchar(10000000), + long_v bigint, + dbl_v double precision, + json_v json, + last_update_ts bigint, + CONSTRAINT attribute_kv_pkey PRIMARY KEY (entity_type, entity_id, attribute_type, attribute_key) +); + +CREATE TABLE IF NOT EXISTS component_descriptor ( + id uuid NOT NULL CONSTRAINT component_descriptor_pkey PRIMARY KEY, + created_time bigint NOT NULL, + actions varchar(255), + clazz varchar UNIQUE, + configuration_descriptor varchar, + name varchar(255), + scope varchar(255), + search_text varchar(255), + type varchar(255), + clustering_mode varchar(255) +); + +CREATE TABLE IF NOT EXISTS customer ( + id uuid NOT NULL CONSTRAINT customer_pkey PRIMARY KEY, + created_time bigint NOT NULL, + additional_info varchar, + address varchar, + address2 varchar, + city varchar(255), + country varchar(255), + email varchar(255), + phone varchar(255), + search_text varchar(255), + state varchar(255), + tenant_id uuid, + title varchar(255), + zip varchar(255), + external_id uuid, + CONSTRAINT customer_external_id_unq_key UNIQUE (tenant_id, external_id) +); + +CREATE TABLE IF NOT EXISTS dashboard ( + id uuid NOT NULL CONSTRAINT dashboard_pkey PRIMARY KEY, + created_time bigint NOT NULL, + configuration varchar, + assigned_customers varchar(1000000), + search_text varchar(255), + tenant_id uuid, + title varchar(255), + mobile_hide boolean DEFAULT false, + mobile_order int, + image varchar(1000000), + external_id uuid, + CONSTRAINT dashboard_external_id_unq_key UNIQUE (tenant_id, external_id) +); + +CREATE TABLE IF NOT EXISTS rule_chain ( + id uuid NOT NULL CONSTRAINT rule_chain_pkey PRIMARY KEY, + created_time bigint NOT NULL, + additional_info varchar, + configuration varchar(10000000), + name varchar(255), + type varchar(255), + first_rule_node_id uuid, + root boolean, + debug_mode boolean, + search_text varchar(255), + tenant_id uuid, + external_id uuid, + CONSTRAINT rule_chain_external_id_unq_key UNIQUE (tenant_id, external_id) +); + +CREATE TABLE IF NOT EXISTS rule_node ( + id uuid NOT NULL CONSTRAINT rule_node_pkey PRIMARY KEY, + created_time bigint NOT NULL, + rule_chain_id uuid, + additional_info varchar, + configuration varchar(10000000), + type varchar(255), + name varchar(255), + debug_mode boolean, + singleton_mode boolean, + search_text varchar(255), + external_id uuid +); + +CREATE TABLE IF NOT EXISTS rule_node_state ( + id uuid NOT NULL CONSTRAINT rule_node_state_pkey PRIMARY KEY, + created_time bigint NOT NULL, + rule_node_id uuid NOT NULL, + entity_type varchar(32) NOT NULL, + entity_id uuid NOT NULL, + state_data varchar(16384) NOT NULL, + CONSTRAINT rule_node_state_unq_key UNIQUE (rule_node_id, entity_id), + CONSTRAINT fk_rule_node_state_node_id FOREIGN KEY (rule_node_id) REFERENCES rule_node(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS ota_package ( + id uuid NOT NULL CONSTRAINT ota_package_pkey PRIMARY KEY, + created_time bigint NOT NULL, + tenant_id uuid NOT NULL, + device_profile_id uuid , + type varchar(32) NOT NULL, + title varchar(255) NOT NULL, + version varchar(255) NOT NULL, + tag varchar(255), + url varchar(255), + file_name varchar(255), + content_type varchar(255), + checksum_algorithm varchar(32), + checksum varchar(1020), + data oid, + data_size bigint, + additional_info varchar, + search_text varchar(255), + CONSTRAINT ota_package_tenant_title_version_unq_key UNIQUE (tenant_id, title, version) +); + +CREATE TABLE IF NOT EXISTS queue ( + id uuid NOT NULL CONSTRAINT queue_pkey PRIMARY KEY, + created_time bigint NOT NULL, + tenant_id uuid, + name varchar(255), + topic varchar(255), + poll_interval int, + partitions int, + consumer_per_partition boolean, + pack_processing_timeout bigint, + submit_strategy varchar(255), + processing_strategy varchar(255), + additional_info varchar +); + +CREATE TABLE IF NOT EXISTS asset_profile ( + id uuid NOT NULL CONSTRAINT asset_profile_pkey PRIMARY KEY, + created_time bigint NOT NULL, + name varchar(255), + image varchar(1000000), + description varchar, + search_text varchar(255), + is_default boolean, + tenant_id uuid, + default_rule_chain_id uuid, + default_dashboard_id uuid, + default_queue_name varchar(255), + default_edge_rule_chain_id uuid, + external_id uuid, + CONSTRAINT asset_profile_name_unq_key UNIQUE (tenant_id, name), + CONSTRAINT asset_profile_external_id_unq_key UNIQUE (tenant_id, external_id), + CONSTRAINT fk_default_rule_chain_asset_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id), + CONSTRAINT fk_default_dashboard_asset_profile FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id), + CONSTRAINT fk_default_edge_rule_chain_asset_profile FOREIGN KEY (default_edge_rule_chain_id) REFERENCES rule_chain(id) + ); + +CREATE TABLE IF NOT EXISTS asset ( + id uuid NOT NULL CONSTRAINT asset_pkey PRIMARY KEY, + created_time bigint NOT NULL, + additional_info varchar, + customer_id uuid, + asset_profile_id uuid NOT NULL, + name varchar(255), + label varchar(255), + search_text varchar(255), + tenant_id uuid, + type varchar(255), + external_id uuid, + CONSTRAINT asset_name_unq_key UNIQUE (tenant_id, name), + CONSTRAINT asset_external_id_unq_key UNIQUE (tenant_id, external_id), + CONSTRAINT fk_asset_profile FOREIGN KEY (asset_profile_id) REFERENCES asset_profile(id) +); + +CREATE TABLE IF NOT EXISTS device_profile ( + id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY, + created_time bigint NOT NULL, + name varchar(255), + type varchar(255), + image varchar(1000000), + transport_type varchar(255), + provision_type varchar(255), + profile_data jsonb, + description varchar, + search_text varchar(255), + is_default boolean, + tenant_id uuid, + firmware_id uuid, + software_id uuid, + default_rule_chain_id uuid, + default_dashboard_id uuid, + default_queue_name varchar(255), + provision_device_key varchar, + default_edge_rule_chain_id uuid, + external_id uuid, + CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name), + CONSTRAINT device_provision_key_unq_key UNIQUE (provision_device_key), + CONSTRAINT device_profile_external_id_unq_key UNIQUE (tenant_id, external_id), + CONSTRAINT fk_default_rule_chain_device_profile FOREIGN KEY (default_rule_chain_id) REFERENCES rule_chain(id), + CONSTRAINT fk_default_dashboard_device_profile FOREIGN KEY (default_dashboard_id) REFERENCES dashboard(id), + CONSTRAINT fk_firmware_device_profile FOREIGN KEY (firmware_id) REFERENCES ota_package(id), + CONSTRAINT fk_software_device_profile FOREIGN KEY (software_id) REFERENCES ota_package(id), + CONSTRAINT fk_default_edge_rule_chain_device_profile FOREIGN KEY (default_edge_rule_chain_id) REFERENCES rule_chain(id) +); + +DO +$$ + BEGIN + IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'fk_device_profile_ota_package') THEN + ALTER TABLE ota_package + ADD CONSTRAINT fk_device_profile_ota_package + FOREIGN KEY (device_profile_id) REFERENCES device_profile (id) + ON DELETE CASCADE; + END IF; + END; +$$; + +-- We will use one-to-many relation in the first release and extend this feature in case of user requests +-- CREATE TABLE IF NOT EXISTS device_profile_firmware ( +-- device_profile_id uuid NOT NULL, +-- firmware_id uuid NOT NULL, +-- CONSTRAINT device_profile_firmware_unq_key UNIQUE (device_profile_id, firmware_id), +-- CONSTRAINT fk_device_profile_firmware_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id) ON DELETE CASCADE, +-- CONSTRAINT fk_device_profile_firmware_firmware FOREIGN KEY (firmware_id) REFERENCES firmware(id) ON DELETE CASCADE, +-- ); + +CREATE TABLE IF NOT EXISTS device ( + id uuid NOT NULL CONSTRAINT device_pkey PRIMARY KEY, + created_time bigint NOT NULL, + additional_info varchar, + customer_id uuid, + device_profile_id uuid NOT NULL, + device_data jsonb, + type varchar(255), + name varchar(255), + label varchar(255), + search_text varchar(255), + tenant_id uuid, + firmware_id uuid, + software_id uuid, + external_id uuid, + CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name), + CONSTRAINT device_external_id_unq_key UNIQUE (tenant_id, external_id), + CONSTRAINT fk_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id), + CONSTRAINT fk_firmware_device FOREIGN KEY (firmware_id) REFERENCES ota_package(id), + CONSTRAINT fk_software_device FOREIGN KEY (software_id) REFERENCES ota_package(id) +); + +CREATE TABLE IF NOT EXISTS device_credentials ( + id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY, + created_time bigint NOT NULL, + credentials_id varchar, + credentials_type varchar(255), + credentials_value varchar, + device_id uuid, + CONSTRAINT device_credentials_id_unq_key UNIQUE (credentials_id), + CONSTRAINT device_credentials_device_id_unq_key UNIQUE (device_id) +); + +CREATE TABLE IF NOT EXISTS rule_node_debug_event ( + id uuid NOT NULL, + tenant_id uuid NOT NULL , + ts bigint NOT NULL, + entity_id uuid NOT NULL, + service_id varchar, + e_type varchar, + e_entity_id uuid, + e_entity_type varchar, + e_msg_id uuid, + e_msg_type varchar, + e_data_type varchar, + e_relation_type varchar, + e_data varchar, + e_metadata varchar, + e_error varchar +) PARTITION BY RANGE (ts); + +CREATE TABLE IF NOT EXISTS rule_chain_debug_event ( + id uuid NOT NULL, + tenant_id uuid NOT NULL, + ts bigint NOT NULL, + entity_id uuid NOT NULL, + service_id varchar NOT NULL, + e_message varchar, + e_error varchar +) PARTITION BY RANGE (ts); + +CREATE TABLE IF NOT EXISTS stats_event ( + id uuid NOT NULL, + tenant_id uuid NOT NULL, + ts bigint NOT NULL, + entity_id uuid NOT NULL, + service_id varchar NOT NULL, + e_messages_processed bigint NOT NULL, + e_errors_occurred bigint NOT NULL +) PARTITION BY RANGE (ts); + +CREATE TABLE IF NOT EXISTS lc_event ( + id uuid NOT NULL, + tenant_id uuid NOT NULL, + ts bigint NOT NULL, + entity_id uuid NOT NULL, + service_id varchar NOT NULL, + e_type varchar NOT NULL, + e_success boolean NOT NULL, + e_error varchar +) PARTITION BY RANGE (ts); + +CREATE TABLE IF NOT EXISTS error_event ( + id uuid NOT NULL, + tenant_id uuid NOT NULL, + ts bigint NOT NULL, + entity_id uuid NOT NULL, + service_id varchar NOT NULL, + e_method varchar NOT NULL, + e_error varchar +) PARTITION BY RANGE (ts); + +CREATE TABLE IF NOT EXISTS relation ( + from_id uuid, + from_type varchar(255), + to_id uuid, + to_type varchar(255), + relation_type_group varchar(255), + relation_type varchar(255), + additional_info varchar, + CONSTRAINT relation_pkey PRIMARY KEY (from_id, from_type, relation_type_group, relation_type, to_id, to_type) +); + +CREATE TABLE IF NOT EXISTS tb_user ( + id uuid NOT NULL CONSTRAINT tb_user_pkey PRIMARY KEY, + created_time bigint NOT NULL, + additional_info varchar, + authority varchar(255), + customer_id uuid, + email varchar(255) UNIQUE, + first_name varchar(255), + last_name varchar(255), + phone varchar(255), + search_text varchar(255), + tenant_id uuid +); + +CREATE TABLE IF NOT EXISTS tenant_profile ( + id uuid NOT NULL CONSTRAINT tenant_profile_pkey PRIMARY KEY, + created_time bigint NOT NULL, + name varchar(255), + profile_data jsonb, + description varchar, + search_text varchar(255), + is_default boolean, + isolated_tb_core boolean, + isolated_tb_rule_engine boolean, + CONSTRAINT tenant_profile_name_unq_key UNIQUE (name) +); + +CREATE TABLE IF NOT EXISTS tenant ( + id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY, + created_time bigint NOT NULL, + additional_info varchar, + tenant_profile_id uuid NOT NULL, + address varchar, + address2 varchar, + city varchar(255), + country varchar(255), + email varchar(255), + phone varchar(255), + region varchar(255), + search_text varchar(255), + state varchar(255), + title varchar(255), + zip varchar(255), + CONSTRAINT fk_tenant_profile FOREIGN KEY (tenant_profile_id) REFERENCES tenant_profile(id) +); + +CREATE TABLE IF NOT EXISTS user_credentials ( + id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY, + created_time bigint NOT NULL, + activate_token varchar(255) UNIQUE, + enabled boolean, + password varchar(255), + reset_token varchar(255) UNIQUE, + user_id uuid UNIQUE, + additional_info varchar DEFAULT '{}' +); + +CREATE TABLE IF NOT EXISTS widget_type ( + id uuid NOT NULL CONSTRAINT widget_type_pkey PRIMARY KEY, + created_time bigint NOT NULL, + alias varchar(255), + bundle_alias varchar(255), + descriptor varchar(1000000), + name varchar(255), + tenant_id uuid, + image varchar(1000000), + description varchar(255) +); + +CREATE TABLE IF NOT EXISTS widgets_bundle ( + id uuid NOT NULL CONSTRAINT widgets_bundle_pkey PRIMARY KEY, + created_time bigint NOT NULL, + alias varchar(255), + search_text varchar(255), + tenant_id uuid, + title varchar(255), + image varchar(1000000), + description varchar(255), + external_id uuid, + CONSTRAINT widgets_bundle_external_id_unq_key UNIQUE (tenant_id, external_id) +); + +CREATE TABLE IF NOT EXISTS entity_view ( + id uuid NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, + created_time bigint NOT NULL, + entity_id uuid, + entity_type varchar(255), + tenant_id uuid, + customer_id uuid, + type varchar(255), + name varchar(255), + keys varchar(10000000), + start_ts bigint, + end_ts bigint, + search_text varchar(255), + additional_info varchar, + external_id uuid, + CONSTRAINT entity_view_external_id_unq_key UNIQUE (tenant_id, external_id) +); + +CREATE TABLE IF NOT EXISTS ts_kv_latest +( + entity_id uuid NOT NULL, + key int NOT NULL, + ts bigint NOT NULL, + bool_v boolean, + str_v varchar(10000000), + long_v bigint, + dbl_v double precision, + json_v json, + CONSTRAINT ts_kv_latest_pkey PRIMARY KEY (entity_id, key) +); + +CREATE TABLE IF NOT EXISTS ts_kv_dictionary +( + key varchar(255) NOT NULL, + key_id serial UNIQUE, + CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) +); + +CREATE TABLE IF NOT EXISTS oauth2_params ( + id uuid NOT NULL CONSTRAINT oauth2_params_pkey PRIMARY KEY, + enabled boolean, + tenant_id uuid, + created_time bigint NOT NULL +); + +CREATE TABLE IF NOT EXISTS oauth2_registration ( + id uuid NOT NULL CONSTRAINT oauth2_registration_pkey PRIMARY KEY, + oauth2_params_id uuid NOT NULL, + created_time bigint NOT NULL, + additional_info varchar, + client_id varchar(255), + client_secret varchar(2048), + authorization_uri varchar(255), + token_uri varchar(255), + scope varchar(255), + platforms varchar(255), + user_info_uri varchar(255), + user_name_attribute_name varchar(255), + jwk_set_uri varchar(255), + client_authentication_method varchar(255), + login_button_label varchar(255), + login_button_icon varchar(255), + allow_user_creation boolean, + activate_user boolean, + type varchar(31), + basic_email_attribute_key varchar(31), + basic_first_name_attribute_key varchar(31), + basic_last_name_attribute_key varchar(31), + basic_tenant_name_strategy varchar(31), + basic_tenant_name_pattern varchar(255), + basic_customer_name_pattern varchar(255), + basic_default_dashboard_name varchar(255), + basic_always_full_screen boolean, + custom_url varchar(255), + custom_username varchar(255), + custom_password varchar(255), + custom_send_token boolean, + CONSTRAINT fk_registration_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS oauth2_domain ( + id uuid NOT NULL CONSTRAINT oauth2_domain_pkey PRIMARY KEY, + oauth2_params_id uuid NOT NULL, + created_time bigint NOT NULL, + domain_name varchar(255), + domain_scheme varchar(31), + CONSTRAINT fk_domain_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE, + CONSTRAINT oauth2_domain_unq_key UNIQUE (oauth2_params_id, domain_name, domain_scheme) +); + +CREATE TABLE IF NOT EXISTS oauth2_mobile ( + id uuid NOT NULL CONSTRAINT oauth2_mobile_pkey PRIMARY KEY, + oauth2_params_id uuid NOT NULL, + created_time bigint NOT NULL, + pkg_name varchar(255), + app_secret varchar(2048), + CONSTRAINT fk_mobile_oauth2_params FOREIGN KEY (oauth2_params_id) REFERENCES oauth2_params(id) ON DELETE CASCADE, + CONSTRAINT oauth2_mobile_unq_key UNIQUE (oauth2_params_id, pkg_name) +); + +CREATE TABLE IF NOT EXISTS oauth2_client_registration_template ( + id uuid NOT NULL CONSTRAINT oauth2_client_registration_template_pkey PRIMARY KEY, + created_time bigint NOT NULL, + additional_info varchar, + provider_id varchar(255), + authorization_uri varchar(255), + token_uri varchar(255), + scope varchar(255), + user_info_uri varchar(255), + user_name_attribute_name varchar(255), + jwk_set_uri varchar(255), + client_authentication_method varchar(255), + type varchar(31), + basic_email_attribute_key varchar(31), + basic_first_name_attribute_key varchar(31), + basic_last_name_attribute_key varchar(31), + basic_tenant_name_strategy varchar(31), + basic_tenant_name_pattern varchar(255), + basic_customer_name_pattern varchar(255), + basic_default_dashboard_name varchar(255), + basic_always_full_screen boolean, + comment varchar, + login_button_icon varchar(255), + login_button_label varchar(255), + help_link varchar(255), + CONSTRAINT oauth2_template_provider_id_unq_key UNIQUE (provider_id) +); + +-- Deprecated +CREATE TABLE IF NOT EXISTS oauth2_client_registration_info ( + id uuid NOT NULL CONSTRAINT oauth2_client_registration_info_pkey PRIMARY KEY, + enabled boolean, + created_time bigint NOT NULL, + additional_info varchar, + client_id varchar(255), + client_secret varchar(255), + authorization_uri varchar(255), + token_uri varchar(255), + scope varchar(255), + user_info_uri varchar(255), + user_name_attribute_name varchar(255), + jwk_set_uri varchar(255), + client_authentication_method varchar(255), + login_button_label varchar(255), + login_button_icon varchar(255), + allow_user_creation boolean, + activate_user boolean, + type varchar(31), + basic_email_attribute_key varchar(31), + basic_first_name_attribute_key varchar(31), + basic_last_name_attribute_key varchar(31), + basic_tenant_name_strategy varchar(31), + basic_tenant_name_pattern varchar(255), + basic_customer_name_pattern varchar(255), + basic_default_dashboard_name varchar(255), + basic_always_full_screen boolean, + custom_url varchar(255), + custom_username varchar(255), + custom_password varchar(255), + custom_send_token boolean +); + +-- Deprecated +CREATE TABLE IF NOT EXISTS oauth2_client_registration ( + id uuid NOT NULL CONSTRAINT oauth2_client_registration_pkey PRIMARY KEY, + created_time bigint NOT NULL, + domain_name varchar(255), + domain_scheme varchar(31), + client_registration_info_id uuid +); + +CREATE TABLE IF NOT EXISTS api_usage_state ( + id uuid NOT NULL CONSTRAINT usage_record_pkey PRIMARY KEY, + created_time bigint NOT NULL, + tenant_id uuid, + entity_type varchar(32), + entity_id uuid, + transport varchar(32), + db_storage varchar(32), + re_exec varchar(32), + js_exec varchar(32), + email_exec varchar(32), + sms_exec varchar(32), + alarm_exec varchar(32), + CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) +); + +CREATE TABLE IF NOT EXISTS resource ( + id uuid NOT NULL CONSTRAINT resource_pkey PRIMARY KEY, + created_time bigint NOT NULL, + tenant_id uuid NOT NULL, + title varchar(255) NOT NULL, + resource_type varchar(32) NOT NULL, + resource_key varchar(255) NOT NULL, + search_text varchar(255), + file_name varchar(255) NOT NULL, + data varchar, + CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_key) +); + +CREATE TABLE IF NOT EXISTS edge ( + id uuid NOT NULL CONSTRAINT edge_pkey PRIMARY KEY, + created_time bigint NOT NULL, + additional_info varchar, + customer_id uuid, + root_rule_chain_id uuid, + type varchar(255), + name varchar(255), + label varchar(255), + routing_key varchar(255), + secret varchar(255), + search_text varchar(255), + tenant_id uuid, + CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name), + CONSTRAINT edge_routing_key_unq_key UNIQUE (routing_key) +); + +CREATE TABLE IF NOT EXISTS edge_event ( + id uuid NOT NULL, + created_time bigint NOT NULL, + edge_id uuid, + edge_event_type varchar(255), + edge_event_uid varchar(255), + entity_id uuid, + edge_event_action varchar(255), + body varchar(10000000), + tenant_id uuid, + ts bigint NOT NULL +) PARTITION BY RANGE(created_time); + +CREATE TABLE IF NOT EXISTS rpc ( + id uuid NOT NULL CONSTRAINT rpc_pkey PRIMARY KEY, + created_time bigint NOT NULL, + tenant_id uuid NOT NULL, + device_id uuid NOT NULL, + expiration_time bigint NOT NULL, + request varchar(10000000) NOT NULL, + response varchar(10000000), + additional_info varchar(10000000), + status varchar(255) NOT NULL +); + +CREATE OR REPLACE FUNCTION to_uuid(IN entity_id varchar, OUT uuid_id uuid) AS +$$ +BEGIN + uuid_id := substring(entity_id, 8, 8) || '-' || substring(entity_id, 4, 4) || '-1' || substring(entity_id, 1, 3) || + '-' || substring(entity_id, 16, 4) || '-' || substring(entity_id, 20, 12); +END; +$$ LANGUAGE plpgsql; + + +CREATE OR REPLACE PROCEDURE cleanup_edge_events_by_ttl(IN ttl bigint, INOUT deleted bigint) + LANGUAGE plpgsql AS +$$ +DECLARE + ttl_ts bigint; + ttl_deleted_count bigint DEFAULT 0; +BEGIN + IF ttl > 0 THEN + ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - ttl::bigint * 1000)::bigint; + EXECUTE format( + 'WITH deleted AS (DELETE FROM edge_event WHERE ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', ttl_ts) into ttl_deleted_count; + END IF; + RAISE NOTICE 'Edge events removed by ttl: %', ttl_deleted_count; + deleted := ttl_deleted_count; +END +$$; + + +CREATE TABLE IF NOT EXISTS user_auth_settings ( + id uuid NOT NULL CONSTRAINT user_auth_settings_pkey PRIMARY KEY, + created_time bigint NOT NULL, + user_id uuid UNIQUE NOT NULL CONSTRAINT fk_user_auth_settings_user_id REFERENCES tb_user(id), + two_fa_settings varchar +); + +CREATE TABLE IF NOT EXISTS notification_target ( + id UUID NOT NULL CONSTRAINT notification_target_pkey PRIMARY KEY, + created_time BIGINT NOT NULL, + tenant_id UUID NOT NULL, + name VARCHAR(255) NOT NULL, + configuration VARCHAR(10000) NOT NULL, + CONSTRAINT uq_notification_target_name UNIQUE (tenant_id, name) +); + +CREATE TABLE IF NOT EXISTS notification_template ( + id UUID NOT NULL CONSTRAINT notification_template_pkey PRIMARY KEY, + created_time BIGINT NOT NULL, + tenant_id UUID NOT NULL, + name VARCHAR(255) NOT NULL, + notification_type VARCHAR(50) NOT NULL, + configuration VARCHAR(10000000) NOT NULL, + CONSTRAINT uq_notification_template_name UNIQUE (tenant_id, name) +); + +CREATE TABLE IF NOT EXISTS notification_rule ( + id UUID NOT NULL CONSTRAINT notification_rule_pkey PRIMARY KEY, + created_time BIGINT NOT NULL, + tenant_id UUID NOT NULL, + name VARCHAR(255) NOT NULL, + template_id UUID NOT NULL CONSTRAINT fk_notification_rule_template_id REFERENCES notification_template(id), + trigger_type VARCHAR(50) NOT NULL, + trigger_config VARCHAR(1000) NOT NULL, + recipients_config VARCHAR(10000) NOT NULL, + additional_config VARCHAR(255), + CONSTRAINT uq_notification_rule_name UNIQUE (tenant_id, name) +); + +CREATE TABLE IF NOT EXISTS notification_request ( + id UUID NOT NULL CONSTRAINT notification_request_pkey PRIMARY KEY, + created_time BIGINT NOT NULL, + tenant_id UUID NOT NULL, + targets VARCHAR(10000) NOT NULL, + template_id UUID, + template VARCHAR(10000000), + info VARCHAR(1000), + additional_config VARCHAR(1000), + originator_entity_id UUID, + originator_entity_type VARCHAR(32), + rule_id UUID NULL, + status VARCHAR(32), + stats VARCHAR(10000) +); + +CREATE TABLE IF NOT EXISTS notification ( + id UUID NOT NULL, + created_time BIGINT NOT NULL, + request_id UUID NULL CONSTRAINT fk_notification_request_id REFERENCES notification_request(id) ON DELETE CASCADE, + recipient_id UUID NOT NULL CONSTRAINT fk_notification_recipient_id REFERENCES tb_user(id) ON DELETE CASCADE, + type VARCHAR(50) NOT NULL, + subject VARCHAR(255), + body VARCHAR(1000) NOT NULL, + additional_config VARCHAR(1000), + status VARCHAR(32) +) PARTITION BY RANGE (created_time); + +CREATE TABLE IF NOT EXISTS user_settings ( + user_id uuid NOT NULL, + type VARCHAR(50) NOT NULL, + settings varchar(10000), + CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES tb_user(id) ON DELETE CASCADE, + CONSTRAINT user_settings_pkey PRIMARY KEY (user_id, type) +); + +---- + +-- 初始化 +begin; +CREATE EXTENSION IF NOT EXISTS pg_stat_statements; + +create schema IF NOT EXISTS __rds_pg_stats__; +set search_path=__rds_pg_stats__,public,pg_catalog; + +-- 全局, pg_db_role_setting +create table snap_pg_db_role_setting as select 1::int8 snap_id, now() snap_ts, * from pg_db_role_setting; + +-- 全局, 表空间占用 +create table snap_pg_tbs_size as select 1::int8 snap_id, now() snap_ts, spcname, pg_tablespace_location(oid), pg_size_pretty(pg_tablespace_size(oid)) from pg_tablespace where spcname<>'pg_global' order by pg_tablespace_size(oid) desc; + +-- 全局, 数据库空间占用 +create table snap_pg_db_size as select 1::int8 snap_id, now() snap_ts, datname, pg_size_pretty(pg_database_size(oid)) from pg_database order by pg_database_size(oid) desc; + +-- 全局, 当前活跃度 +create table snap_pg_stat_activity as select 1::int8 snap_id, now() snap_ts, state, count(*) from pg_stat_activity group by 1,2,3; + +-- 全局, 总剩余连接数 +create table snap_pg_conn_stats as select 1::int8 snap_id, now() snap_ts, max_conn,used,res_for_super,max_conn-used-res_for_super res_for_normal from (select count(*) used from pg_stat_activity) t1,(select setting::int res_for_super from pg_settings where name=$$superuser_reserved_connections$$) t2,(select setting::int max_conn from pg_settings where name=$$max_connections$$) t3; + +-- 全局, 用户连接数限制 +create table snap_pg_role_conn_limit as select 1::int8 snap_id, now() snap_ts, a.rolname,a.rolconnlimit,b.connects from pg_roles a,(select usename,count(*) connects from pg_stat_activity group by usename) b where a.rolname=b.usename order by b.connects desc; + +-- 全局, 数据库连接限制 +create table snap_pg_db_conn_limit as select 1::int8 snap_id, now() snap_ts, a.datname, a.datconnlimit, b.connects from pg_database a,(select datname,count(*) connects from pg_stat_activity group by datname) b where a.datname=b.datname order by b.connects desc; + +-- 全局, TOP CPU TIME 10 SQL +create table snap_pg_cputime_topsql as select 1::int8 snap_id, now() snap_ts, c.rolname,b.datname,a.total_time/a.calls per_call_time,a.* from pg_stat_statements a,pg_database b,pg_roles c where a.userid=c.oid and a.dbid=b.oid order by a.total_time desc limit 10; + +-- 全局, 数据库统计信息, 回滚比例, 命中比例, 数据块读写时间, 死锁, 复制冲突 +--create table snap_pg_stat_database as select 1::int8 snap_id, now() snap_ts, datname,round(100*(xact_rollback::numeric/(case when xact_commit > 0 then xact_commit else 1 end + xact_rollback)),2)||$$ %$$ rollback_ratio, round(100*(blks_hit::numeric/(case when blks_read>0 then blks_read else 1 end + blks_hit)),2)||$$ %$$ hit_ratio, blk_read_time, blk_write_time, conflicts, deadlocks from pg_stat_database; + +-- 全局, 检查点, bgwriter 统计信息 +create table snap_pg_stat_bgwriter as select 1::int8 snap_id, now() snap_ts, * from pg_stat_bgwriter; + +-- 全局, archiver 统计信息 +create table snap_pg_stat_archiver as select 1::int8 snap_id, now() snap_ts,coalesce(pg_walfile_name(pg_current_wal_insert_lsn()),'-') as now_insert_xlog_file, * from pg_stat_archiver; + +-- 全局, 数据库年龄 +create table snap_pg_database_age as select 1::int8 snap_id, now() snap_ts, datname,age(datfrozenxid),2^31-age(datfrozenxid) age_remain from pg_database order by age(datfrozenxid) desc; + +-- 全局, 长事务, 2PC +create table snap_pg_long_xact as select 1::int8 snap_id, now() snap_ts, datname,usename,query,xact_start,now()-xact_start xact_duration,query_start,now()-query_start query_duration,state from pg_stat_activity where state<>$$idle$$ and (backend_xid is not null or backend_xmin is not null) and now()-xact_start > interval $$30 min$$ order by xact_start; + +create table snap_pg_long_2pc as select 1::int8 snap_id, now() snap_ts, name,statement,prepare_time,now()-prepare_time duration,parameter_types,from_sql from pg_prepared_statements where now()-prepare_time > interval $$30 min$$ order by prepare_time; + +-- 全局, 用户密码到期时间 +create table snap_pg_user_deadline as select 1::int8 snap_id, now() snap_ts, rolname,rolvaliduntil from pg_roles order by rolvaliduntil; + +-- 库级, 快照清单 +create table snap_list (id serial8 primary key, snap_ts timestamp, snap_level text); +insert into snap_list (snap_ts, snap_level) values (now(), 'database'); + +-- 库级, pg_stat_statements +create table snap_pg_stat_statements as select 1::int8 snap_id, now() snap_ts, * from pg_stat_statements; + +-- 库级, 对象空间占用柱状图 +create table snap_pg_rel_space_bucket as select 1::int8 snap_id, now() snap_ts, current_database(), buk this_buk_no, cnt rels_in_this_buk, pg_size_pretty(min) buk_min, pg_size_pretty(max) buk_max from +( + select row_number() over (partition by buk order by tsize), tsize, buk, min(tsize) over (partition by buk),max(tsize) over (partition by buk), count(*) over (partition by buk) cnt from + ( + select pg_relation_size(a.oid) tsize, width_bucket(pg_relation_size(a.oid),tmin-1,tmax+1,10) buk from + ( + select min(pg_relation_size(a.oid)) tmin, max(pg_relation_size(a.oid)) tmax from pg_class a, pg_namespace c where a.relnamespace=c.oid and nspname --!~ $$^pg_$$ and nspname<>$$information_schema$$ + ) t, pg_class a, pg_namespace c where a.relnamespace=c.oid and nspname --!~ $$^pg_$$ and nspname<>$$information_schema$$ + ) t +) t where row_number=1; + +-- 库级, 数据库对象空间前5000 +create table snap_pg_db_rel_size as select 1::int8 snap_id, now() snap_ts, current_database(),b.nspname,c.relname,c.relkind,pg_relation_size(c.oid),a.seq_scan,a.seq_tup_read,a.idx_scan,a.idx_tup_fetch,a.n_tup_ins,a.n_tup_upd,a.n_tup_del,a.n_tup_hot_upd,a.n_live_tup,a.n_dead_tup from pg_stat_all_tables a, pg_class c,pg_namespace b where c.relnamespace=b.oid and c.relkind=$$r$$ and a.relid=c.oid order by pg_relation_size(c.oid) desc limit 5000; + +-- 库级, pg_statio_all_tables +create table snap_pg_statio_all_tables as select 1::int8 snap_id, now() snap_ts, current_database(),* from pg_statio_all_tables; + +-- 库级, pg_statio_all_indexes +create table snap_pg_statio_all_indexes as select 1::int8 snap_id, now() snap_ts, current_database(),* from pg_statio_all_indexes; + +-- 库级, 索引数超过4并且SIZE大于10MB的表 +create table snap_pg_many_indexes_rel as select 1::int8 snap_id, now() snap_ts, current_database(), t2.nspname, t1.relname, pg_relation_size(t1.oid), t3.idx_cnt from pg_class t1, pg_namespace t2, (select indrelid,count(*) idx_cnt from pg_index group by 1 having count(*)>4) t3 where t1.oid=t3.indrelid and t1.relnamespace=t2.oid and pg_relation_size(t1.oid)/1024/1024.0>10 order by t3.idx_cnt desc; + +-- 库级, 上次快照以来未使用,或者使用较少的索引 +--create table snap_pg_notused_indexes as select 1::int8 snap_id, now() snap_ts, current_database(),t2.schemaname,t2.relname,t2.indexrelname,t2.idx_scan,t2.idx_tup_read,t2.idx_tup_fetch,pg_relation_size(indexrelid) from pg_stat_all_tables t1,pg_stat_all_indexes t2 where t1.relid=t2.relid and t2.idx_scan<10 and t2.schemaname not in ($$pg_toast$$,$$pg_catalog$$) and indexrelid not in (select conindid from pg_constraint where contype in ($$p$$,$$u$$,$$f$$)) and pg_relation_size(indexrelid)>65536 order by pg_relation_size(indexrelid) desc; + +-- 库级, 表膨胀前10 +create table snap_pg_table_bloat as select 1::int8 snap_id, now() snap_ts, + current_database() AS db, schemaname, tablename, reltuples::bigint AS tups, relpages::bigint AS pages, otta, + ROUND(CASE WHEN otta=0 OR sml.relpages=0 OR sml.relpages=otta THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS tbloat, + CASE WHEN relpages < otta THEN 0 ELSE relpages::bigint - otta END AS wastedpages, + CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::bigint END AS wastedbytes, + --CASE WHEN relpages < otta THEN $$0 bytes$$::text ELSE (bs*(relpages-otta))::bigint || $$ bytes$$ END AS wastedsize, + iname, ituples::bigint AS itups, ipages::bigint AS ipages, iotta, + ROUND(CASE WHEN iotta=0 OR ipages=0 OR ipages=iotta THEN 0.0 ELSE ipages/iotta::numeric END,1) AS ibloat, + CASE WHEN ipages < iotta THEN 0 ELSE ipages::bigint - iotta END AS wastedipages, + CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes, + --CASE WHEN ipages < iotta THEN $$0 bytes$$ ELSE (bs*(ipages-iotta))::bigint || $$ bytes$$ END AS wastedisize, + CASE WHEN relpages < otta THEN + CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta::bigint) END + ELSE CASE WHEN ipages < iotta THEN bs*(relpages-otta::bigint) + ELSE bs*(relpages-otta::bigint + ipages-iotta::bigint) END + END AS totalwastedbytes +FROM ( + SELECT + nn.nspname AS schemaname, + cc.relname AS tablename, + COALESCE(cc.reltuples,0) AS reltuples, + COALESCE(cc.relpages,0) AS relpages, + COALESCE(bs,0) AS bs, + COALESCE(CEIL((cc.reltuples*((datahdr+ma- + (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)),0) AS otta, + COALESCE(c2.relname,$$?$$) AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages, + COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols + FROM + pg_class cc + JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname <> $$information_schema$$ + LEFT JOIN + ( + SELECT + ma,bs,foo.nspname,foo.relname, + (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr, + (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2 + FROM ( + SELECT + ns.nspname, tbl.relname, hdr, ma, bs, + SUM((1-coalesce(null_frac,0))*coalesce(avg_width, 2048)) AS datawidth, + MAX(coalesce(null_frac,0)) AS maxfracsum, + hdr+( + SELECT 1+count(*)/8 + FROM pg_stats s2 + WHERE null_frac<>0 AND s2.schemaname = ns.nspname AND s2.tablename = tbl.relname + ) AS nullhdr + FROM pg_attribute att + JOIN pg_class tbl ON att.attrelid = tbl.oid + JOIN pg_namespace ns ON ns.oid = tbl.relnamespace + LEFT JOIN pg_stats s ON s.schemaname=ns.nspname + AND s.tablename = tbl.relname + AND s.inherited=false + AND s.attname=att.attname, + ( + SELECT + (SELECT current_setting($$block_size$$)::numeric) AS bs, + CASE WHEN SUBSTRING(SPLIT_PART(v, $$ $$, 2) FROM $$#"[0-9]+.[0-9]+#"%$$ for $$#$$) + IN ($$8.0$$,$$8.1$$,$$8.2$$) THEN 27 ELSE 23 END AS hdr --, + --CASE WHEN v ~ $$mingw32$$ OR v ~ $$64-bit$$ THEN 8 ELSE 4 END AS ma + FROM (SELECT version() AS v) AS foo + ) AS constants + WHERE att.attnum > 0 AND tbl.relkind=$$r$$ + GROUP BY 1,2,3,4,5 + ) AS foo + ) AS rs + ON cc.relname = rs.relname AND nn.nspname = rs.nspname + LEFT JOIN pg_index i ON indrelid = cc.oid + LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid +) AS sml order by wastedbytes desc limit 10; + +-- 库级, 索引膨胀前10 +create table snap_pg_index_bloat as select 1::int8 snap_id, now() snap_ts, + current_database() AS db, schemaname, tablename, reltuples::bigint AS tups, relpages::bigint AS pages, otta, + ROUND(CASE WHEN otta=0 OR sml.relpages=0 OR sml.relpages=otta THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS tbloat, + CASE WHEN relpages < otta THEN 0 ELSE relpages::bigint - otta END AS wastedpages, + CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::bigint END AS wastedbytes, + --CASE WHEN relpages < otta THEN $$0 bytes$$::text ELSE (bs*(relpages-otta))::bigint || $$ bytes$$ END AS wastedsize, + iname, ituples::bigint AS itups, ipages::bigint AS ipages, iotta, + ROUND(CASE WHEN iotta=0 OR ipages=0 OR ipages=iotta THEN 0.0 ELSE ipages/iotta::numeric END,1) AS ibloat, + CASE WHEN ipages < iotta THEN 0 ELSE ipages::bigint - iotta END AS wastedipages, + CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes, + --CASE WHEN ipages < iotta THEN $$0 bytes$$ ELSE (bs*(ipages-iotta))::bigint || $$ bytes$$ END AS wastedisize, + CASE WHEN relpages < otta THEN + CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta::bigint) END + ELSE CASE WHEN ipages < iotta THEN bs*(relpages-otta::bigint) + ELSE bs*(relpages-otta::bigint + ipages-iotta::bigint) END + END AS totalwastedbytes +FROM ( + SELECT + nn.nspname AS schemaname, + cc.relname AS tablename, + COALESCE(cc.reltuples,0) AS reltuples, + COALESCE(cc.relpages,0) AS relpages, + COALESCE(bs,0) AS bs, + COALESCE(CEIL((cc.reltuples*((datahdr+ma- + (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)),0) AS otta, + COALESCE(c2.relname,$$?$$) AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages, + COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols + FROM + pg_class cc + JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname <> $$information_schema$$ + LEFT JOIN + ( + SELECT + ma,bs,foo.nspname,foo.relname, + (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr, + (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2 + FROM ( + SELECT + ns.nspname, tbl.relname, hdr, ma, bs, + SUM((1-coalesce(null_frac,0))*coalesce(avg_width, 2048)) AS datawidth, + MAX(coalesce(null_frac,0)) AS maxfracsum, + hdr+( + SELECT 1+count(*)/8 + FROM pg_stats s2 + WHERE null_frac<>0 AND s2.schemaname = ns.nspname AND s2.tablename = tbl.relname + ) AS nullhdr + FROM pg_attribute att + JOIN pg_class tbl ON att.attrelid = tbl.oid + JOIN pg_namespace ns ON ns.oid = tbl.relnamespace + LEFT JOIN pg_stats s ON s.schemaname=ns.nspname + AND s.tablename = tbl.relname + AND s.inherited=false + AND s.attname=att.attname, + ( + SELECT + (SELECT current_setting($$block_size$$)::numeric) AS bs, + CASE WHEN SUBSTRING(SPLIT_PART(v, $$ $$, 2) FROM $$#"[0-9]+.[0-9]+#"%$$ for $$#$$) + IN ($$8.0$$,$$8.1$$,$$8.2$$) THEN 27 ELSE 23 END AS hdr --, + --CASE WHEN v ~ $$mingw32$$ OR v ~ $$64-bit$$ THEN 8 ELSE 4 END AS ma + FROM (SELECT version() AS v) AS foo + ) AS constants + WHERE att.attnum > 0 AND tbl.relkind=$$r$$ + GROUP BY 1,2,3,4,5 + ) AS foo + ) AS rs + ON cc.relname = rs.relname AND nn.nspname = rs.nspname + LEFT JOIN pg_index i ON indrelid = cc.oid + LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid +) AS sml order by wastedibytes desc limit 10; + +-- 库级, 垃圾数据前十 +--create table snap_pg_dead_tup as select 1::int8 snap_id, now() snap_ts, current_database(),schemaname,relname,n_dead_tup from pg_stat_all_tables where n_live_tup>0 and n_dead_tup/n_live_tup>0.2 and schemaname not in ($$pg_toast$$,$$pg_catalog$$) order by n_dead_tup desc limit 10; + +-- 库级, 表年龄前100 +create table snap_pg_rel_age as select 1::int8 snap_id, now() snap_ts, current_database(),rolname,nspname,relkind,relname,age(relfrozenxid),2^31-age(relfrozenxid) age_remain from pg_roles t1 join pg_class t2 on t1.oid=t2.relowner join pg_namespace t3 on t2.relnamespace=t3.oid where t2.relkind in ($$t$$,$$r$$) order by age(relfrozenxid) desc limit 100; + + +-- 库级, unlogged table 和 哈希索引 +create table snap_pg_unlogged_table as select 1::int8 snap_id, now() snap_ts, current_database(),t3.rolname,t2.nspname,t1.relname from pg_class t1,pg_namespace t2,pg_roles t3 where t1.relnamespace=t2.oid and t1.relowner=t3.oid and t1.relpersistence=$$u$$; + +--create table snap_pg_hash_idx as select 1::int8 snap_id, now() snap_ts, current_database(),pg_get_indexdef(oid) from pg_class where relkind=$$i$$ and pg_get_indexdef(oid) ~ $$USING hash$$; + +-- 库级, 剩余可使用次数不足1000万次的序列检查 + create or replace function sequence_stats(OUT v_datname name, OUT v_role name, OUT v_nspname name, OUT v_relname name, OUT v_times_remain int8) returns setof record as $$ + declare + begin + v_datname := current_database(); +-- for v_role,v_nspname,v_relname in select rolname,nspname,relname from pg_roles t1 , pg_class t2 , pg_namespace t3 where t1.oid=t2.relowner and t2.relnamespace=t3.oid and t2.relkind='S' + select (seqmax-seqmin)/seqincrement from pg_catalog.pg_sequence into v_times_remain; +-- LOOP +-- execute 'select (9223372036854775807-last_value)/increment_by from "'||v_nspname||'"."'||v_relname||'" where not is_cycled' into v_times_remain; +-- return next; +-- end loop; + end; + $$ language plpgsql; + + create table snap_pg_seq_deadline as select 1::int8 snap_id, now() snap_ts, * from sequence_stats() where v_times_remain is not null and v_times_remain < 10240000 order by v_times_remain limit 10; + +-- 库级, 清理未引用的大对象 +create table snap_pg_vacuumlo as select 1::int8 snap_id, now() snap_ts, current_database(), 1::int8 as lo_bloat; + +create or replace function vacuumlo(i_snapid int8) returns void as $$ +declare + los oid[]; + lo oid; + v_nspname name; + v_relname name; + v_attname name; + v_bloat int8; +begin + SELECT array_agg(oid) into los FROM pg_largeobject_metadata; + + if los is not null and array_length(los,1) > 0 then + for v_nspname,v_relname,v_attname in + SELECT s.nspname, c.relname, a.attname + FROM pg_class c, pg_attribute a, pg_namespace s, pg_type t + WHERE a.attnum > 0 AND NOT a.attisdropped + AND a.attrelid = c.oid + AND a.atttypid = t.oid + AND c.relnamespace = s.oid + AND t.typname in ('oid', 'lo') + AND c.relkind in ('r', 'm') + AND s.nspname !~ '^pg_' + loop + for lo in execute format('SELECT %I FROM %I.%I', quote_ident(v_attname), quote_ident(v_nspname), quote_ident(v_relname)) loop + los := array_remove(los, lo); + end loop; + end loop; + end if; + + if los is not null and array_length(los,1) > 0 then + select sum(current_setting('block_size')::int8) into v_bloat from pg_largeobject where loid = any(los); + + insert into snap_pg_vacuumlo select i_snapid, now() snap_ts, current_database(), v_bloat; + raise notice 'lo bloats: %', pg_size_pretty(v_bloat); + + raise notice 'begin vacuumlo. %', clock_timestamp(); + perform lo_unlink(o) from unnest(los) t(o); + raise notice 'end vacuumlo. %', clock_timestamp(); + end if; +end; +$$ language plpgsql strict; + +-- 库级, 锁等待 +create table snap_pg_waiting as +with t_wait as +(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid, +a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a, +transactionid,b.query,b.xact_start,b.query_start,b.usename,b.datname + from pg_locks a,pg_stat_activity b where a.pid=b.pid and not a.granted), +t_run as +(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple, +a.classid,a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid, +a,transactionid,b.query,b.xact_start,b.query_start, +b.usename,b.datname from pg_locks a,pg_stat_activity b where +a.pid=b.pid and a.granted) +select +1::int8 snap_id, now() snap_ts, +r.locktype, r.mode r_mode,r.usename r_user,r.datname r_db, +r.relation::regclass,r.pid r_pid, +r.page r_page,r.tuple r_tuple,r.xact_start r_xact_start, +r.query_start r_query_start, +now()-r.query_start r_locktime,r.query r_query,w.mode w_mode, +w.pid w_pid,w.page w_page, +w.tuple w_tuple,w.xact_start w_xact_start,w.query_start w_query_start, +now()-w.query_start w_locktime,w.query w_query +from t_wait w,t_run r where + r.locktype is not distinct from w.locktype and + r.database is not distinct from w.database and + r.relation is not distinct from w.relation and + r.page is not distinct from w.page and + r.tuple is not distinct from w.tuple and + r.classid is not distinct from w.classid and + r.objid is not distinct from w.objid and + r.objsubid is not distinct from w.objsubid and + r.transactionid is not distinct from w.transactionid and + r.pid <> w.pid + order by + (( case w.mode + when 'INVALID' then 0 + when 'AccessShareLock' then 1 + when 'RowShareLock' then 2 + when 'RowExclusiveLock' then 3 + when 'ShareUpdateExclusiveLock' then 4 + when 'ShareLock' then 5 + when 'ShareRowExclusiveLock' then 6 + when 'ExclusiveLock' then 7 + when 'AccessExclusiveLock' then 8 + else 0 + end ) + + ( case r.mode + when 'INVALID' then 0 + when 'AccessShareLock' then 1 + when 'RowShareLock' then 2 + when 'RowExclusiveLock' then 3 + when 'ShareUpdateExclusiveLock' then 4 + when 'ShareLock' then 5 + when 'ShareRowExclusiveLock' then 6 + when 'ExclusiveLock' then 7 + when 'AccessExclusiveLock' then 8 + else 0 + end )) desc,r.xact_start; + +-- 打快照函数 +--create or replace function snap_global(erase_stats boolean default true) returns void as $_$ +--declare +-- snap_id int8; +-- ts timestamp := clock_timestamp(); +-- +--begin +--set search_path=__rds_pg_stats__,public,pg_catalog; +-- +---- 库级, 快照清单 +--raise notice '%', ts; +--insert into snap_list (snap_ts, snap_level) values (ts, 'global') returning id into snap_id; +-- +---- 全局, pg_db_role_setting +--insert into snap_pg_db_role_setting select snap_id, ts snap_ts, * from pg_db_role_setting; +-- +---- 全局, 表空间占用 +--insert into snap_pg_tbs_size select snap_id, ts snap_ts, spcname, case when pg_tablespace_location(oid)='' then '-' else pg_tablespace_location(oid) end, pg_size_pretty(pg_tablespace_size(oid)) from pg_tablespace where spcname<>'pg_global' order by pg_tablespace_size(oid) desc; +-- +---- 全局, 数据库空间占用 +--insert into snap_pg_db_size select snap_id, ts snap_ts, datname, pg_size_pretty(pg_database_size(oid)) from pg_database order by pg_database_size(oid) desc; +-- +---- 全局, 当前活跃度 +--insert into snap_pg_stat_activity select snap_id, ts snap_ts, state, count(*) from pg_stat_activity group by 1,2,3; +-- +---- 全局, 总剩余连接数 +----insert into snap_pg_conn_stats select snap_id, ts snap_ts, max_conn,used,res_for_super,max_conn-used-res_for_super res_for_normal from (select count(*) used from pg_stat_activity) t1,(select setting::int res_for_super from pg_settings where name=$$superuser_reserved_connections$$) t2,(select setting::int max_conn from pg_settings where name=$$max_connections$$) t3; +-- +---- 全局, 用户连接数限制 +--insert into snap_pg_role_conn_limit select snap_id, ts snap_ts, a.rolname,a.rolconnlimit,b.connects from pg_roles a,(select usename,count(*) connects from pg_stat_activity group by usename) b where a.rolname=b.usename order by b.connects desc; +-- +---- 全局, 数据库连接限制 +--insert into snap_pg_db_conn_limit select snap_id, ts snap_ts, a.datname, a.datconnlimit, b.connects from pg_database a,(select datname,count(*) connects from pg_stat_activity group by datname) b where a.datname=b.datname order by b.connects desc; +-- +---- 全局, TOP CPUTIME 10 SQL +--insert into snap_pg_cputime_topsql select snap_id, ts snap_ts, c.rolname,b.datname,a.total_time/a.calls per_call_time,a.* from pg_stat_statements a,pg_database b,pg_roles c where a.userid=c.oid and a.dbid=b.oid order by a.total_time desc limit 10; +-- +---- 全局, 数据库统计信息, 回滚比例, 命中比例, 数据块读写时间, 死锁, 复制冲突 +--insert into snap_pg_stat_database select snap_id, ts snap_ts, datname,round(100*(xact_rollback::numeric/(case when xact_commit > 0 then xact_commit else 1 end + xact_rollback)),2)||$$ %$$ rollback_ratio, round(100*(blks_hit::numeric/(case when blks_read>0 then blks_read else 1 end + blks_hit)),2)||$$ %$$ hit_ratio, blk_read_time, blk_write_time, conflicts, deadlocks from pg_stat_database; +-- +---- 全局, 检查点, bgwriter 统计信息 +--insert into snap_pg_stat_bgwriter select snap_id, ts snap_ts, * from pg_stat_bgwriter; +-- +---- 全局, archiver 统计信息 +--insert into snap_pg_stat_archiver select snap_id, ts snap_ts, coalesce(pg_walfile_name(pg_current_wal_insert_lsn()),'-') as now_insert_xlog_file, * from pg_stat_archiver; +-- +---- 全局, 数据库年龄 +--insert into snap_pg_database_age select snap_id, ts snap_ts, datname,age(datfrozenxid),2^31-age(datfrozenxid) age_remain from pg_database order by age(datfrozenxid) desc; +-- +---- 全局, 长事务, 2PC +--insert into snap_pg_long_xact select snap_id, ts snap_ts, datname,usename,query,xact_start,ts-xact_start xact_duration,query_start,ts-query_start query_duration,state from pg_stat_activity where state<>$$idle$$ and (backend_xid is not null or backend_xmin is not null) and ts-xact_start > interval $$30 min$$ order by xact_start; +-- +--insert into snap_pg_long_2pc select snap_id, ts snap_ts, name,statement,prepare_time,ts-prepare_time,parameter_types,from_sql from pg_prepared_statements where ts-prepare_time > interval $$30 min$$ order by prepare_time; +-- +---- 全局, 用户密码到期时间 +--insert into snap_pg_user_deadline select snap_id, ts snap_ts, rolname,rolvaliduntil from pg_roles order by rolvaliduntil; +-- +---- 重置统计信息 +--if erase_stats then +-- perform pg_stat_reset_shared('bgwriter'); +-- perform pg_stat_reset_shared('archiver'); +-- perform pg_stat_statements_reset(); +--end if; +-- +--reset search_path; +--end; +--$_$ language plpgsql strict; + + +--create or replace function snap_database(erase_stats boolean default true) returns void as $_$ +--declare +-- snap_id int8; +-- ts timestamp := clock_timestamp(); +-- +--begin +--set search_path=__rds_pg_stats__,public,pg_catalog; +-- +---- 库级, 快照清单 +--raise notice '%', ts; +--insert into snap_list (snap_ts, snap_level) values (ts, 'database') returning id into snap_id; +-- +---- 库级, pg_stat_statements +--insert into snap_pg_stat_statements select snap_id, ts snap_ts, * from pg_stat_statements; +-- +---- 库级, 对象空间占用柱状图 +--insert into snap_pg_rel_space_bucket select snap_id, ts snap_ts, current_database(), buk this_buk_no, cnt rels_in_this_buk, pg_size_pretty(min) buk_min, pg_size_pretty(max) buk_max from +--( +-- select row_number() over (partition by buk order by tsize), tsize, buk, min(tsize) over (partition by buk),max(tsize) over (partition by buk), count(*) over (partition by buk) cnt from +-- ( +-- select pg_relation_size(a.oid) tsize, width_bucket(pg_relation_size(a.oid),tmin-1,tmax+1,10) buk from +-- ( +-- select min(pg_relation_size(a.oid)) tmin, max(pg_relation_size(a.oid)) tmax from pg_class a, pg_namespace c where a.relnamespace=c.oid and nspname !~ $$^pg_$$ and nspname<>$$information_schema$$ +-- ) t, pg_class a, pg_namespace c where a.relnamespace=c.oid and nspname !~ $$^pg_$$ and nspname<>$$information_schema$$ +-- ) t +--) t where row_number=1; +-- +---- 库级, 空间占用前5000的表 +--insert into snap_pg_db_rel_size select snap_id, ts snap_ts, current_database(),b.nspname,c.relname,c.relkind,pg_relation_size(c.oid),a.seq_scan,a.seq_tup_read,a.idx_scan,a.idx_tup_fetch,a.n_tup_ins,a.n_tup_upd,a.n_tup_del,a.n_tup_hot_upd,a.n_live_tup,a.n_dead_tup from pg_stat_all_tables a, pg_class c,pg_namespace b where c.relnamespace=b.oid and c.relkind=$$r$$ and a.relid=c.oid order by pg_relation_size(c.oid) desc limit 5000; +-- +---- 库级, pg_statio_all_tables +--insert into snap_pg_statio_all_tables select snap_id, ts snap_ts, current_database(),* from pg_statio_all_tables; +-- +---- 库级, pg_statio_all_indexes +--insert into snap_pg_statio_all_indexes select snap_id, ts snap_ts, current_database(),* from pg_statio_all_indexes; +-- +---- 库级, 索引数超过4并且SIZE大于10MB的表 +--insert into snap_pg_many_indexes_rel select snap_id, ts snap_ts, current_database(), t2.nspname, t1.relname, pg_relation_size(t1.oid), t3.idx_cnt from pg_class t1, pg_namespace t2, (select indrelid,count(*) idx_cnt from pg_index group by 1 having count(*)>4) t3 where t1.oid=t3.indrelid and t1.relnamespace=t2.oid and pg_relation_size(t1.oid)/1024/1024.0>10 order by t3.idx_cnt desc; +-- +---- 库级, 上次巡检以来未使用,或者使用较少的索引 +--insert into snap_pg_notused_indexes select snap_id, ts snap_ts, current_database(),t2.schemaname,t2.relname,t2.indexrelname,t2.idx_scan,t2.idx_tup_read,t2.idx_tup_fetch,pg_relation_size(indexrelid) from pg_stat_all_tables t1,pg_stat_all_indexes t2 where t1.relid=t2.relid and t2.idx_scan<10 and t2.schemaname not in ($$pg_toast$$,$$pg_catalog$$) and indexrelid not in (select conindid from pg_constraint where contype in ($$p$$,$$u$$,$$f$$)) and pg_relation_size(indexrelid)>65536 order by pg_relation_size(indexrelid) desc; +-- +---- 库级, 表膨胀前10 +--insert into snap_pg_table_bloat select snap_id, ts snap_ts, +-- current_database() AS db, schemaname, tablename, reltuples::bigint AS tups, relpages::bigint AS pages, otta, +-- ROUND(CASE WHEN otta=0 OR sml.relpages=0 OR sml.relpages=otta THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS tbloat, +-- CASE WHEN relpages < otta THEN 0 ELSE relpages::bigint - otta END AS wastedpages, +-- CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::bigint END AS wastedbytes, +-- CASE WHEN relpages < otta THEN $$0 bytes$$::text ELSE (bs*(relpages-otta))::bigint || $$ bytes$$ END AS wastedsize, +-- iname, ituples::bigint AS itups, ipages::bigint AS ipages, iotta, +-- ROUND(CASE WHEN iotta=0 OR ipages=0 OR ipages=iotta THEN 0.0 ELSE ipages/iotta::numeric END,1) AS ibloat, +-- CASE WHEN ipages < iotta THEN 0 ELSE ipages::bigint - iotta END AS wastedipages, +-- CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes, +-- CASE WHEN ipages < iotta THEN $$0 bytes$$ ELSE (bs*(ipages-iotta))::bigint || $$ bytes$$ END AS wastedisize, +-- CASE WHEN relpages < otta THEN +-- CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta::bigint) END +-- ELSE CASE WHEN ipages < iotta THEN bs*(relpages-otta::bigint) +-- ELSE bs*(relpages-otta::bigint + ipages-iotta::bigint) END +-- END AS totalwastedbytes +--FROM ( +-- SELECT +-- nn.nspname AS schemaname, +-- cc.relname AS tablename, +-- COALESCE(cc.reltuples,0) AS reltuples, +-- COALESCE(cc.relpages,0) AS relpages, +-- COALESCE(bs,0) AS bs, +-- COALESCE(CEIL((cc.reltuples*((datahdr+ma- +-- (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)),0) AS otta, +-- COALESCE(c2.relname,$$?$$) AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages, +-- COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols +-- FROM +-- pg_class cc +-- JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname <> $$information_schema$$ +-- LEFT JOIN +-- ( +-- SELECT +-- ma,bs,foo.nspname,foo.relname, +-- (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr, +-- (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2 +-- FROM ( +-- SELECT +-- ns.nspname, tbl.relname, hdr, ma, bs, +-- SUM((1-coalesce(null_frac,0))*coalesce(avg_width, 2048)) AS datawidth, +-- MAX(coalesce(null_frac,0)) AS maxfracsum, +-- hdr+( +-- SELECT 1+count(*)/8 +-- FROM pg_stats s2 +-- WHERE null_frac<>0 AND s2.schemaname = ns.nspname AND s2.tablename = tbl.relname +-- ) AS nullhdr +-- FROM pg_attribute att +-- JOIN pg_class tbl ON att.attrelid = tbl.oid +-- JOIN pg_namespace ns ON ns.oid = tbl.relnamespace +-- LEFT JOIN pg_stats s ON s.schemaname=ns.nspname +-- AND s.tablename = tbl.relname +-- AND s.inherited=false +-- AND s.attname=att.attname, +-- ( +-- SELECT +-- (SELECT current_setting($$block_size$$)::numeric) AS bs, +-- CASE WHEN SUBSTRING(SPLIT_PART(v, $$ $$, 2) FROM $$#"[0-9]+.[0-9]+#"%$$ for $$#$$) +-- IN ($$8.0$$,$$8.1$$,$$8.2$$) THEN 27 ELSE 23 END AS hdr, +-- CASE WHEN v ~ $$mingw32$$ OR v ~ $$64-bit$$ THEN 8 ELSE 4 END AS ma +-- FROM (SELECT version() AS v) AS foo +-- ) AS constants +-- WHERE att.attnum > 0 AND tbl.relkind=$$r$$ +-- GROUP BY 1,2,3,4,5 +-- ) AS foo +-- ) AS rs +-- ON cc.relname = rs.relname AND nn.nspname = rs.nspname +-- LEFT JOIN pg_index i ON indrelid = cc.oid +-- LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid +--) AS sml order by wastedbytes desc limit 10; +-- +---- 库级, 索引膨胀前10 +--insert into snap_pg_index_bloat select snap_id, ts snap_ts, +-- current_database() AS db, schemaname, tablename, reltuples::bigint AS tups, relpages::bigint AS pages, otta, +-- ROUND(CASE WHEN otta=0 OR sml.relpages=0 OR sml.relpages=otta THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS tbloat, +-- CASE WHEN relpages < otta THEN 0 ELSE relpages::bigint - otta END AS wastedpages, +-- CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::bigint END AS wastedbytes, +-- CASE WHEN relpages < otta THEN $$0 bytes$$::text ELSE (bs*(relpages-otta))::bigint || $$ bytes$$ END AS wastedsize, +-- iname, ituples::bigint AS itups, ipages::bigint AS ipages, iotta, +-- ROUND(CASE WHEN iotta=0 OR ipages=0 OR ipages=iotta THEN 0.0 ELSE ipages/iotta::numeric END,1) AS ibloat, +-- CASE WHEN ipages < iotta THEN 0 ELSE ipages::bigint - iotta END AS wastedipages, +-- CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes, +-- CASE WHEN ipages < iotta THEN $$0 bytes$$ ELSE (bs*(ipages-iotta))::bigint || $$ bytes$$ END AS wastedisize, +-- CASE WHEN relpages < otta THEN +-- CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta::bigint) END +-- ELSE CASE WHEN ipages < iotta THEN bs*(relpages-otta::bigint) +-- ELSE bs*(relpages-otta::bigint + ipages-iotta::bigint) END +-- END AS totalwastedbytes +--FROM ( +-- SELECT +-- nn.nspname AS schemaname, +-- cc.relname AS tablename, +-- COALESCE(cc.reltuples,0) AS reltuples, +-- COALESCE(cc.relpages,0) AS relpages, +-- COALESCE(bs,0) AS bs, +-- COALESCE(CEIL((cc.reltuples*((datahdr+ma- +-- (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)),0) AS otta, +-- COALESCE(c2.relname,$$?$$) AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages, +-- COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols +-- FROM +-- pg_class cc +-- JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname <> $$information_schema$$ +-- LEFT JOIN +-- ( +-- SELECT +-- ma,bs,foo.nspname,foo.relname, +-- (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr, +-- (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2 +-- FROM ( +-- SELECT +-- ns.nspname, tbl.relname, hdr, ma, bs, +-- SUM((1-coalesce(null_frac,0))*coalesce(avg_width, 2048)) AS datawidth, +-- MAX(coalesce(null_frac,0)) AS maxfracsum, +-- hdr+( +-- SELECT 1+count(*)/8 +-- FROM pg_stats s2 +-- WHERE null_frac<>0 AND s2.schemaname = ns.nspname AND s2.tablename = tbl.relname +-- ) AS nullhdr +-- FROM pg_attribute att +-- JOIN pg_class tbl ON att.attrelid = tbl.oid +-- JOIN pg_namespace ns ON ns.oid = tbl.relnamespace +-- LEFT JOIN pg_stats s ON s.schemaname=ns.nspname +-- AND s.tablename = tbl.relname +-- AND s.inherited=false +-- AND s.attname=att.attname, +-- ( +-- SELECT +-- (SELECT current_setting($$block_size$$)::numeric) AS bs, +-- CASE WHEN SUBSTRING(SPLIT_PART(v, $$ $$, 2) FROM $$#"[0-9]+.[0-9]+#"%$$ for $$#$$) +-- IN ($$8.0$$,$$8.1$$,$$8.2$$) THEN 27 ELSE 23 END AS hdr, +-- CASE WHEN v ~ $$mingw32$$ OR v ~ $$64-bit$$ THEN 8 ELSE 4 END AS ma +-- FROM (SELECT version() AS v) AS foo +-- ) AS constants +-- WHERE att.attnum > 0 AND tbl.relkind=$$r$$ +-- GROUP BY 1,2,3,4,5 +-- ) AS foo +-- ) AS rs +-- ON cc.relname = rs.relname AND nn.nspname = rs.nspname +-- LEFT JOIN pg_index i ON indrelid = cc.oid +-- LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid +--) AS sml order by wastedibytes desc limit 10; +-- +---- 库级, 垃圾数据前十 +--insert into snap_pg_dead_tup select snap_id, ts snap_ts, current_database(),schemaname,relname,n_dead_tup from pg_stat_all_tables where n_live_tup>0 and (n_dead_tup/n_live_tup)>0.2 and schemaname not in ($$pg_toast$$,$$pg_catalog$$) order by n_dead_tup desc limit 10; +-- +---- 库级, 表年龄前100 +--insert into snap_pg_rel_age select snap_id, ts snap_ts, current_database(),rolname,nspname,relkind,relname,age(relfrozenxid),2^31-age(relfrozenxid) age_remain from pg_roles t1 join pg_class t2 on t1.oid=t2.relowner join pg_namespace t3 on t2.relnamespace=t3.oid where t2.relkind in ($$t$$,$$r$$) order by age(relfrozenxid) desc limit 100; +-- +-- +---- 库级, unlogged table 和 哈希索引 +--insert into snap_pg_unlogged_table select snap_id, ts snap_ts, current_database(),t3.rolname,t2.nspname,t1.relname from pg_class t1,pg_namespace t2,pg_roles t3 where t1.relnamespace=t2.oid and t1.relowner=t3.oid and t1.relpersistence=$$u$$; +-- +--insert into snap_pg_hash_idx select snap_id, ts snap_ts, current_database(),pg_get_indexdef(oid) from pg_class where relkind=$$i$$ and pg_get_indexdef(oid) ~ $$USING hash$$; +-- +---- 库级, 剩余可使用次数不足1000万次的序列检查 +--insert into snap_pg_seq_deadline select snap_id, ts snap_ts, * from sequence_stats() where v_times_remain is not null and v_times_remain < 10240000 order by v_times_remain limit 10; +-- +---- 库级, 清理未引用的大对象 +--perform vacuumlo(snap_id) ; +-- +---- 库级, 锁等待 +--insert into snap_pg_waiting +--with t_wait as +--(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid, +--a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a, +--transactionid,b.query,b.xact_start,b.query_start,b.usename,b.datname +-- from pg_locks a,pg_stat_activity b where a.pid=b.pid and not a.granted), +--t_run as +--(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple, +--a.classid,a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid, +--a,transactionid,b.query,b.xact_start,b.query_start, +--b.usename,b.datname from pg_locks a,pg_stat_activity b where +--a.pid=b.pid and a.granted) +--select +--snap_id, ts snap_ts, +--r.locktype, r.mode r_mode,r.usename r_user,r.datname r_db, +--r.relation::regclass,r.pid r_pid, +--r.page r_page,r.tuple r_tuple,r.xact_start r_xact_start, +--r.query_start r_query_start, +--ts-r.query_start r_locktime,r.query r_query,w.mode w_mode, +--w.pid w_pid,w.page w_page, +--w.tuple w_tuple,w.xact_start w_xact_start,w.query_start w_query_start, +--ts-w.query_start w_locktime,w.query w_query +--from t_wait w,t_run r where +-- r.locktype is not distinct from w.locktype and +-- r.database is not distinct from w.database and +-- r.relation is not distinct from w.relation and +-- r.page is not distinct from w.page and +-- r.tuple is not distinct from w.tuple and +-- r.classid is not distinct from w.classid and +-- r.objid is not distinct from w.objid and +-- r.objsubid is not distinct from w.objsubid and +-- r.transactionid is not distinct from w.transactionid and +-- r.pid <> w.pid +-- order by +-- (( case w.mode +-- when 'INVALID' then 0 +-- when 'AccessShareLock' then 1 +-- when 'RowShareLock' then 2 +-- when 'RowExclusiveLock' then 3 +-- when 'ShareUpdateExclusiveLock' then 4 +-- when 'ShareLock' then 5 +-- when 'ShareRowExclusiveLock' then 6 +-- when 'ExclusiveLock' then 7 +-- when 'AccessExclusiveLock' then 8 +-- else 0 +-- end ) + +-- ( case r.mode +-- when 'INVALID' then 0 +-- when 'AccessShareLock' then 1 +-- when 'RowShareLock' then 2 +-- when 'RowExclusiveLock' then 3 +-- when 'ShareUpdateExclusiveLock' then 4 +-- when 'ShareLock' then 5 +-- when 'ShareRowExclusiveLock' then 6 +-- when 'ExclusiveLock' then 7 +-- when 'AccessExclusiveLock' then 8 +-- else 0 +-- end )) desc,r.xact_start; +-- +---- 重置统计信息 +--if erase_stats then +-- perform pg_stat_reset(); +--end if; +-- +--reset search_path; +--end; +--$_$ language plpgsql strict; + +-- 清理快照函数 + +-- 清理库级、全局快照 +-- 3种清理快照的方法 + +create or replace function snap_delete_data(i_snap_id int8) returns void as $$ +declare +begin + set search_path=__rds_pg_stats__,public,pg_catalog; + + delete from snap_list where id=i_snap_id; + delete from snap_pg_conn_stats where snap_id=i_snap_id; + delete from snap_pg_cputime_topsql where snap_id=i_snap_id; + delete from snap_pg_database_age where snap_id=i_snap_id; + delete from snap_pg_db_conn_limit where snap_id=i_snap_id; + delete from snap_pg_db_rel_size where snap_id=i_snap_id; + delete from snap_pg_db_role_setting where snap_id=i_snap_id; + delete from snap_pg_db_size where snap_id=i_snap_id; + delete from snap_pg_dead_tup where snap_id=i_snap_id; + delete from snap_pg_hash_idx where snap_id=i_snap_id; + delete from snap_pg_index_bloat where snap_id=i_snap_id; + delete from snap_pg_long_2pc where snap_id=i_snap_id; + delete from snap_pg_long_xact where snap_id=i_snap_id; + delete from snap_pg_many_indexes_rel where snap_id=i_snap_id; + delete from snap_pg_notused_indexes where snap_id=i_snap_id; + delete from snap_pg_rel_age where snap_id=i_snap_id; + delete from snap_pg_rel_space_bucket where snap_id=i_snap_id; + delete from snap_pg_role_conn_limit where snap_id=i_snap_id; + delete from snap_pg_seq_deadline where snap_id=i_snap_id; + delete from snap_pg_stat_activity where snap_id=i_snap_id; + delete from snap_pg_stat_archiver where snap_id=i_snap_id; + delete from snap_pg_stat_bgwriter where snap_id=i_snap_id; + delete from snap_pg_stat_database where snap_id=i_snap_id; + delete from snap_pg_stat_statements where snap_id=i_snap_id; + delete from snap_pg_statio_all_indexes where snap_id=i_snap_id; + delete from snap_pg_statio_all_tables where snap_id=i_snap_id; + delete from snap_pg_table_bloat where snap_id=i_snap_id; + delete from snap_pg_tbs_size where snap_id=i_snap_id; + delete from snap_pg_unlogged_table where snap_id=i_snap_id; + delete from snap_pg_user_deadline where snap_id=i_snap_id; + delete from snap_pg_vacuumlo where snap_id=i_snap_id; + delete from snap_pg_waiting where snap_id=i_snap_id; + + reset search_path; +end; +$$ language plpgsql strict; + +-- 删除指定snap_id以前的快照数据 +create or replace function snap_delete(i_snap_id int8) returns void as $$ +declare + v_snap_id int8; +begin + set search_path=__rds_pg_stats__,public,pg_catalog; + + for v_snap_id in select id from snap_list where id=1'; + reset search_path; + return; + end if; + + for v_snap_id in select id from snap_list where id < (select id from snap_list order by id desc limit 1 offset 2) order by id + loop + perform snap_delete_data(v_snap_id); + end loop; + + reset search_path; + +end; +$$ language plpgsql strict; + + + +-- 生成诊断报告函数 +-- 生成全局报告 +-- 指定ID范围 + +--create or replace function snap_report_global(i_begin_id int8, i_end_id int8, i_level text default 'global') returns setof text as $$ +-- +--declare +-- v_begin_ts timestamp; +-- v_end_ts timestamp; +-- res text[]; +-- tmp text; +-- version text := '9.4'; +--begin +-- set search_path=__rds_pg_stats__,public,pg_catalog; +-- +-- +---- 判断 ID 是否存在 +--perform 1 from snap_list where id = i_begin_id and snap_level=i_level ; +--if not found then +-- raise notice '% snapshot begin_id : % not exist.', i_level, i_begin_id; +-- reset search_path; +-- return; +--end if; +-- +--perform 1 from snap_list where id = i_end_id and snap_level=i_level ; +--if not found then +-- raise notice '% snapshot end_id : % not exist.', i_level, i_end_id; +-- reset search_path; +-- return; +--end if; +-- +---- 生成报告时间段, 如果没有前序快照, 默认往前加1小时 +--select snap_ts into v_begin_ts from snap_list where id=i_begin_id and t1.snap_id<=i_end_id order by datname,rolname,snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '## 二、数据库空间使用分析'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 1. 表空间在该时段的变化情况'); +--res := array_append(res, ' '); +--res := array_append(res, 'tablespace | tbs_location | snap_ts | size'); +--res := array_append(res, '---|---|---|---'); +--for tmp in select coalesce(spcname,'-')||' | ```'||coalesce(pg_tablespace_location,'-')||'``` | ```'||snap_ts||'``` | '||coalesce(pg_size_pretty,'-') from snap_pg_tbs_size where snap_id >=i_begin_id and snap_id<=i_end_id order by spcname,pg_tablespace_location,snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '注意检查表空间所在文件系统的剩余空间, (默认表空间在$PGDATA/base目录下), IOPS分配是否均匀, OS的sysstat包可以观察IO使用率. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 2. 数据库在该时段的变化情况'); +--res := array_append(res, ' '); +--res := array_append(res, 'database | snap_ts | size'); +--res := array_append(res, '---|---|---'); +--for tmp in select '```'||coalesce(datname,'-')||'``` | ```'||snap_ts||'``` | '||coalesce(pg_size_pretty,'-') from snap_pg_db_size where snap_id >=i_begin_id and snap_id<=i_end_id order by datname, snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '注意检查数据库的大小, 是否需要清理历史数据. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '## 三、数据库连接分析'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 1. 活跃度在该时段的变化'); +--res := array_append(res, ' '); +--res := array_append(res, 'state | snap_ts | connections'); +--res := array_append(res, '---|---|---'); +--for tmp in select coalesce(state,'-')||' | ```'||snap_ts||'``` | '||coalesce(count,-1) from snap_pg_stat_activity where snap_id >=i_begin_id and snap_id<=i_end_id order by state, snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '如果active状态很多, 说明数据库比较繁忙. 如果idle in transaction很多, 说明业务逻辑设计可能有问题. 如果idle很多, 可能使用了连接池, 并且可能没有自动回收连接到连接池的最小连接数. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 2. 剩余连接数在该时段的变化'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | max_enabled_connections | used | res_for_super | res_for_normal'); +--res := array_append(res, '---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | '||coalesce(max_conn,-1)||' | '||coalesce(used,-1)||' | '||coalesce(res_for_super,-1)||' | '||coalesce(res_for_normal,-1) from snap_pg_conn_stats where snap_id >=i_begin_id and snap_id<=i_end_id order by snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '给超级用户和普通用户设置足够的连接, 以免不能登录数据库. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 3. 用户连接数限制在该时段的变化'); +--res := array_append(res, ' '); +--res := array_append(res, 'rolename | snap_ts | conn_limit | connects'); +--res := array_append(res, '---|---|---|---'); +--for tmp in select '```'||coalesce(rolname,'-')||'``` | ```'||snap_ts||'``` | '||coalesce(rolconnlimit,-1)||' | '||coalesce(connects,-1) from snap_pg_role_conn_limit where snap_id >=i_begin_id and snap_id<=i_end_id order by rolname, snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '给用户设置足够的连接数, alter role ... CONNECTION LIMIT . '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 4. 数据库连接限制在该时段的变化'); +--res := array_append(res, ' '); +--res := array_append(res, 'database | snap_ts | conn_limit | connects'); +--res := array_append(res, '---|---|---|---'); +--for tmp in select '```'||coalesce(datname,'-')||'``` | ```'||snap_ts||'``` | '||coalesce(datconnlimit,-1)||' | '||coalesce(connects,-1) from snap_pg_db_conn_limit where snap_id >=i_begin_id and snap_id<=i_end_id order by datname, snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '给数据库设置足够的连接数, alter database ... CONNECTION LIMIT . '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '## 四、数据库性能分析'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 1. TOP 10 SQL : total_cpu_time'); +--res := array_append(res, ' '); +-- +-- +---- res := array_append(res, 'rolename | database | calls | total_ms | min_ms | max_ms | mean_ms | stddev_ms | rows | shared_blks_hit | shared_blks_read | shared_blks_dirtied | shared_blks_written | local_blks_hit | local_blks_read | local_blks_dirtied | shared_blks_written | temp_blks_read | temp_blks_written | blk_read_time | blk_write_time | query'); +-- +---- res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---'); +-- +---- for tmp in select '```'||coalesce(rolname,'-')||'``` | ```'||coalesce(datname,'-')||'``` | '||coalesce(sum(calls),-1)||' | '||coalesce(sum(total_time),-1)||' | '||coalesce(avg(min_time),-1)||' | '||coalesce(avg(max_time),-1)||' | '||coalesce(avg(mean_time),-1)||' | '||coalesce(avg(stddev_time),-1)||' | '||coalesce(sum(rows),-1)||' | '||coalesce(sum(shared_blks_hit),-1)||' | '||coalesce(sum(shared_blks_read),-1)||' | '||coalesce(sum(shared_blks_dirtied),-1)||' | '||coalesce(sum(shared_blks_written),-1)||' | '||coalesce(sum(local_blks_hit),-1)||' | '||coalesce(sum(local_blks_read),-1)||' | '||coalesce(sum(local_blks_dirtied),-1)||' | '||coalesce(sum(local_blks_written),-1)||' | '||coalesce(sum(temp_blks_read),-1)||' | '||coalesce(sum(temp_blks_written),-1)||' | '||coalesce(sum(blk_read_time),-1)||' | '||coalesce(sum(blk_write_time),-1)||' | ```'||coalesce(replace(regexp_replace(query,'\n',' ','g'), '|', '|'),'-')||'```' from snap_pg_cputime_topsql where snap_id >=i_begin_id and snap_id<=i_end_id group by rolname,datname,query order by sum(total_time) desc nulls last limit 10 +-- +--res := array_append(res, 'rolename | database | calls | total_ms | rows | shared_blks_hit | shared_blks_read | shared_blks_dirtied | shared_blks_written | local_blks_hit | local_blks_read | local_blks_dirtied | shared_blks_written | temp_blks_read | temp_blks_written | blk_read_time | blk_write_time | query'); +-- +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---'); +-- +--for tmp in select '```'||coalesce(rolname,'-')||'``` | ```'||coalesce(datname,'-')||'``` | '||coalesce(sum(calls),-1)||' | '||coalesce(sum(total_time),-1)||' | '||coalesce(sum(rows),-1)||' | '||coalesce(sum(shared_blks_hit),-1)||' | '||coalesce(sum(shared_blks_read),-1)||' | '||coalesce(sum(shared_blks_dirtied),-1)||' | '||coalesce(sum(shared_blks_written),-1)||' | '||coalesce(sum(local_blks_hit),-1)||' | '||coalesce(sum(local_blks_read),-1)||' | '||coalesce(sum(local_blks_dirtied),-1)||' | '||coalesce(sum(local_blks_written),-1)||' | '||coalesce(sum(temp_blks_read),-1)||' | '||coalesce(sum(temp_blks_written),-1)||' | '||coalesce(sum(blk_read_time),-1)||' | '||coalesce(sum(blk_write_time),-1)||' | ```'||coalesce(replace(regexp_replace(query,'\n',' ','g'), '|', '|'),'-')||'```' from snap_pg_cputime_topsql where snap_id >=i_begin_id and snap_id<=i_end_id group by rolname,datname,query order by sum(total_time) desc nulls last limit 10 +-- +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '从最耗时的SQL开始, 检查SQL是否有优化空间, 配合auto_explain插件在csvlog中观察LONG SQL的执行计划是否正确. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 2. 数据库统计信息, 回滚比例, 命中比例, 数据块读写时间, 死锁, 复制冲突 在该时段的变化'); +--res := array_append(res, ' '); +--res := array_append(res, 'database | snap_ts | rollback_ratio | hit_ratio | blk_read_time | blk_write_time | conflicts | deadlocks'); +--res := array_append(res, '---|---|---|---|---|---|---|---'); +--for tmp in select '```'||coalesce(datname,'-')||'``` | ```'||snap_ts||'``` | '||coalesce(rollback_ratio,'-1')||' | '||coalesce(hit_ratio,'-1')||' | '||coalesce(blk_read_time,-1)||' | '||coalesce(blk_write_time,-1)||' | '||coalesce(conflicts,-1)||' | '||coalesce(deadlocks,-1) from snap_pg_stat_database where snap_id >=i_begin_id and snap_id<=i_end_id order by datname, snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '回滚比例大说明业务逻辑可能有问题, 命中率小说明shared_buffer要加大, 数据块读写时间长说明块设备的IO性能要提升, 死锁次数多说明业务逻辑有问题, 复制冲突次数多说明备库可能在跑LONG SQL. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 3. 检查点, bgwriter 统计信息'); +--res := array_append(res, ' '); +--res := array_append(res, 'checkpoints_timed | checkpoints_req | checkpoint_write_time | checkpoint_sync_time | buffers_checkpoint | buffers_clean | maxwritten_clean | buffers_backend | buffers_backend_fsync | buffers_alloc'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---'); +--for tmp in select coalesce(sum(checkpoints_timed),-1)||' | '||coalesce(sum(checkpoints_req),-1)||' | '||coalesce(sum(checkpoint_write_time),-1)||' | '||coalesce(sum(checkpoint_sync_time),-1)||' | '||coalesce(sum(buffers_checkpoint),-1)||' | '||coalesce(sum(buffers_clean),-1)||' | '||coalesce(sum(maxwritten_clean),-1)||' | '||coalesce(sum(buffers_backend),-1)||' | '||coalesce(sum(buffers_backend_fsync),-1)||' | '||coalesce(sum(buffers_alloc),-1) from snap_pg_stat_bgwriter where snap_id >=i_begin_id and snap_id<=i_end_id +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 说明'); +--res := array_append(res, ' '); +--res := array_append(res, 'checkpoints_timed , 统计周期内, 发生了多少次调度检查点. '); +--res := array_append(res, ' '); +--res := array_append(res, 'checkpoints_req , 统计周期内, 发生了多少次人为执行检查点. '); +--res := array_append(res, ' '); +--res := array_append(res, 'checkpoint_write_time , 检查点过程中, write系统调用的耗时ms. '); +--res := array_append(res, ' '); +--res := array_append(res, 'checkpoint_sync_time , 检查点过程中, fsync系统调用的耗时ms. '); +--res := array_append(res, ' '); +--res := array_append(res, 'buffers_checkpoint , 检查点过程中, ckpt进程写出(write)了多少buffer pages. '); +--res := array_append(res, ' '); +--res := array_append(res, 'buffers_clean , 统计周期内, bgwriter进程写出(write)了多少buffer pages. '); +--res := array_append(res, ' '); +--res := array_append(res, 'maxwritten_clean , 统计周期内, bgwriter被打断了多少次(由于write的pages超过一个bgwriter调度周期内的阈值). '); +--res := array_append(res, ' '); +--res := array_append(res, 'buffers_backend , 统计周期内, 有多少pages是被backend process直接write out的. '); +--res := array_append(res, ' '); +--res := array_append(res, 'buffers_backend_fsync , 统计周期内, 有多少pages是被backend process直接fsync的. '); +--res := array_append(res, ' '); +--res := array_append(res, 'buffers_alloc , 统计周期内, 指派了多少个pages. '); +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, 'checkpoint_write_time多说明检查点持续时间长, 检查点过程中产生了较多的脏页. '); +--res := array_append(res, ' '); +--res := array_append(res, 'checkpoint_sync_time代表检查点开始时的shared buffer中的脏页被同步到磁盘的时间, 如果时间过长, 并且数据库在检查点时性能较差, 考虑一下提升块设备的IOPS能力. '); +--res := array_append(res, ' '); +--res := array_append(res, 'buffers_backend_fsync太多说明需要加大shared buffer 或者 减小bgwriter_delay参数. '); +--res := array_append(res, ' '); +--res := array_append(res, 'maxwritten_clean太多说明需要减小调大bgwriter_lru_maxpages和bgwriter_lru_multiplier参数. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 4. 归档统计信息'); +--res := array_append(res, ' '); +--res := array_append(res, 'archived_count | last_archived_wal | last_archived_time | failed_count | last_failed_wal | last_failed_time | now_insert_xlog_file'); +--res := array_append(res, '---|---|---|---|---|---|---'); +--for tmp in select coalesce(archived_count,-1)||' | '||coalesce(last_archived_wal,'-')||' | ```'||coalesce(last_archived_time,'1970-01-01')||'``` | '||coalesce(failed_count,-1)||' | '||coalesce(last_failed_wal,'-')||' | ```'||coalesce(last_failed_time,'1970-01-01')||'``` | '||coalesce(now_insert_xlog_file,'-') from snap_pg_stat_archiver where snap_id=i_end_id +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, 'last_archived_wal和now_insert_xlog_file相差很多, 说明失败的归档很多, 或者归档慢, 需要检查原因(IO\CPU\网络等). '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '## 五、数据库年龄分析'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 1. 数据库年龄在该时段的变化'); +--res := array_append(res, ' '); +--res := array_append(res, 'database | snap_ts | age | age_remain'); +--res := array_append(res, '---|---|---|---'); +--for tmp in select '```'||coalesce(datname,'-')||'``` | ```'||snap_ts||'``` | '||coalesce(age,-1)||' | '||coalesce(age_remain,-1) from snap_pg_database_age where snap_id >=i_begin_id and snap_id<=i_end_id order by datname,snap_ts +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '正常情况下, 数据库的年龄应该小于vacuum_freeze_table_age, 如果剩余年龄小于2亿, 建议人为干预, 将LONG SQL或事务杀掉后, 执行vacuum freeze. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 2. 长事务, 2PC'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | database | user | query | xact_start | xact_duration | query_start | query_duration | state'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(datname,'-')||'``` | ```'||coalesce(usename,'-')||'``` | ```'||coalesce(replace(regexp_replace(query,'\n',' ','g'), '|', '|'),'-')||'``` | ```'||coalesce(xact_start,'1970-01-01')||'``` | ```'||coalesce(xact_duration,'0 s')||'``` | ```'||coalesce(query_start,'1970-01-01')||'``` | ```'||coalesce(query_duration,'0 s')||'``` | '||coalesce(state,'-') from snap_pg_long_xact where snap_id >=i_begin_id and snap_id<=i_end_id order by snap_ts,datname,usename,query +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | name | statement | prepare_time | duration | parameter_types | from_sql'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(name,'-')||'``` | ```'||coalesce(replace(regexp_replace(statement,'\n',' ','g'), '|', '|'),'-')||'``` | ```'||coalesce(prepare_time,'1970-01-01')||'``` | ```'||coalesce(duration,'0 s')||'``` | '||coalesce(parameter_types::text,'-')||' | '||coalesce(from_sql,'false') from snap_pg_long_2pc where snap_id >=i_begin_id and snap_id<=i_end_id order by snap_ts,prepare_time,name,statement +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '长事务过程中产生的垃圾, 无法回收, 建议不要在数据库中运行LONG SQL, 或者错开DML高峰时间去运行LONG SQL. 2PC事务一定要记得尽快结束掉, 否则可能会导致数据库膨胀. '); +--res := array_append(res, ' '); +--res := array_append(res, '参考: https://github.com/digoal/blog/blob/master/201504/20150429_02.md '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '## 六、数据库安全或潜在风险分析'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 1. 用户密码到期时间'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | rolname | rolvaliduntil'); +--res := array_append(res, '---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(rolname,'-')||'``` | ```'||coalesce(rolvaliduntil,'9999-01-01')||'```' from snap_pg_user_deadline where snap_id=i_end_id order by snap_ts,rolname +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '到期后, 用户将无法登陆, 记得修改密码, 同时将密码到期时间延长到某个时间或无限时间, alter role ... VALID UNTIL ''$timestamp''. '); +--res := array_append(res, ' '); +-- +--reset search_path; +--return query select t from unnest(res) t1(t); +-- +--end; +--$$ language plpgsql strict; + + + + + +-- 生成库级报告 + + +-- 指定ID范围 +--create or replace function snap_report_database(i_begin_id int8, i_end_id int8, i_level text default 'database') returns setof text as $$ +-- +--declare +-- v_begin_ts timestamp; +-- v_end_ts timestamp; +-- res text[]; +-- tmp text; +-- version text := '9.4'; +--begin +-- set search_path=__rds_pg_stats__,public,pg_catalog; +-- +---- 判断 ID 是否存在 +--perform 1 from snap_list where id = i_begin_id and snap_level=i_level ; +--if not found then +-- raise notice '% snapshot begin_id : % not exist.', i_level, i_begin_id; +-- reset search_path; +-- return; +--end if; +-- +--perform 1 from snap_list where id = i_end_id and snap_level=i_level ; +--if not found then +-- raise notice '% snapshot end_id : % not exist.', i_level, i_end_id; +-- reset search_path; +-- return; +--end if; +-- +---- 生成报告时间段, 如果没有前序快照, 默认往前加1小时 +--select snap_ts into v_begin_ts from snap_list where id=i_begin_id and snap_id<=i_end_id and dbid=(select oid from pg_database where datname=current_database()) group by query order by sum(total_time) desc nulls last limit 10 +-- +--res := array_append(res, 'calls | total_ms | rows | shared_blks_hit | shared_blks_read | shared_blks_dirtied | shared_blks_written | local_blks_hit | local_blks_read | local_blks_dirtied | shared_blks_written | temp_blks_read | temp_blks_written | blk_read_time | blk_write_time | query'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---'); +--for tmp in select coalesce(sum(calls),-1)||' | '||coalesce(sum(total_time),-1)||' | '||coalesce(sum(rows),-1)||' | '||coalesce(sum(shared_blks_hit),-1)||' | '||coalesce(sum(shared_blks_read),-1)||' | '||coalesce(sum(shared_blks_dirtied),-1)||' | '||coalesce(sum(shared_blks_written),-1)||' | '||coalesce(sum(local_blks_hit),-1)||' | '||coalesce(sum(local_blks_read),-1)||' | '||coalesce(sum(local_blks_dirtied),-1)||' | '||coalesce(sum(local_blks_written),-1)||' | '||coalesce(sum(temp_blks_read),-1)||' | '||coalesce(sum(temp_blks_written),-1)||' | '||coalesce(sum(blk_read_time),-1)||' | '||coalesce(sum(blk_write_time),-1)||' | ```'||coalesce(replace(regexp_replace(query,'\n',' ','g'), '|', '|'),'-')||'```' from snap_pg_stat_statements where snap_id >=i_begin_id and snap_id<=i_end_id and dbid=(select oid from pg_database where datname=current_database()) group by query order by sum(total_time) desc nulls last limit 10 +-- +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '检查SQL是否有优化空间, 配合auto_explain插件在csvlog中观察LONG SQL的执行计划是否正确. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 2. TOP 10 size 表统计信息'); +--res := array_append(res, ' '); +--res := array_append(res, 'current_database | nspname | relname | relkind | pg_relation_size | seq_scan | seq_tup_read | idx_scan | idx_tup_fetch | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd | n_live_tup | n_dead_tup'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||coalesce(current_database,'-')||'``` | ```'||coalesce(nspname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | '||coalesce(relkind,'-')||' | '||coalesce(pg_size_pretty(avg(pg_relation_size)),'-')||' | '||coalesce(sum(seq_scan),-1)||' | '||coalesce(sum(seq_tup_read),-1)||' | '||coalesce(sum(idx_scan),-1)||' | '||coalesce(sum(idx_tup_fetch),-1)||' | '||coalesce(sum(n_tup_ins),-1)||' | '||coalesce(sum(n_tup_upd),-1)||' | '||coalesce(sum(n_tup_del),-1)||' | '||coalesce(sum(n_tup_hot_upd),-1)||' | '||coalesce(avg(n_live_tup),-1)||' | '||coalesce(avg(n_dead_tup),-1) from snap_pg_db_rel_size where snap_id >=i_begin_id and snap_id<=i_end_id group by current_database,nspname,relname,relkind order by avg(pg_relation_size) desc nulls last limit 10 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 说明'); +--res := array_append(res, ' '); +--res := array_append(res, 'seq_scan, 全表扫描次数 '); +--res := array_append(res, ' '); +--res := array_append(res, 'seq_tup_read, 全表扫描实际一共读取了多少条记录, 如果平均每次读取的记录数不多, 可能是limit语句造成的 '); +--res := array_append(res, ' '); +--res := array_append(res, 'idx_scan, 索引扫描次数 '); +--res := array_append(res, ' '); +--res := array_append(res, 'idx_tup_fetch, 索引扫描实际获取的记录数, 如果平均每次读取记录数很多, 说明数据库倾向使用索引扫描, 建议观察随机IO的性能看情况调整 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_tup_ins, 统计周期内, 插入了多少条记录 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_tup_upd, 统计周期内, 更新了多少条记录 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_tup_hot_upd, 统计周期内, HOT更新(指更新后的记录依旧在当前PAGE)了多少条记录 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_live_tup, 该表有多少可用数据 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_dead_tup, 该表有多少垃圾数据 '); +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '经验值: 单表超过10GB, 并且这个表需要频繁更新 或 删除+插入的话, 建议对表根据业务逻辑进行合理拆分后获得更好的性能, 以及便于对膨胀索引进行维护; 如果是只读的表, 建议适当结合SQL语句进行优化. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 3. 全表扫描统计 , 平均实际扫描记录数排名前10的表'); +--res := array_append(res, ' '); +--res := array_append(res, 'current_database | nspname | relname | relkind | pg_relation_size | seq_scan | seq_tup_read | idx_scan | idx_tup_fetch | n_tup_ins | n_tup_upd | n_tup_del | n_tup_hot_upd | n_live_tup | n_dead_tup'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||coalesce(current_database,'-')||'``` | ```'||coalesce(nspname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | '||coalesce(relkind,'-')||' | '||coalesce(pg_size_pretty(avg(pg_relation_size)),'-')||' | '||coalesce(sum(seq_scan),-1)||' | '||coalesce(sum(seq_tup_read),-1)||' | '||coalesce(sum(idx_scan),-1)||' | '||coalesce(sum(idx_tup_fetch),-1)||' | '||coalesce(sum(n_tup_ins),-1)||' | '||coalesce(sum(n_tup_upd),-1)||' | '||coalesce(sum(n_tup_del),-1)||' | '||coalesce(sum(n_tup_hot_upd),-1)||' | '||coalesce(avg(n_live_tup),-1)||' | '||coalesce(avg(n_dead_tup),-1) from snap_pg_db_rel_size where snap_id >=i_begin_id and snap_id<=i_end_id group by current_database,nspname,relname,relkind order by avg(case when seq_tup_read=0 then 1 else seq_tup_read end/case when seq_scan=0 then 1 else seq_scan end) desc nulls last limit 10 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 说明'); +--res := array_append(res, ' '); +--res := array_append(res, 'seq_scan, 全表扫描次数 '); +--res := array_append(res, ' '); +--res := array_append(res, 'seq_tup_read, 全表扫描实际一共读取了多少条记录, 如果平均每次读取的记录数不多, 可能是limit语句造成的 '); +--res := array_append(res, ' '); +--res := array_append(res, 'idx_scan, 索引扫描次数 '); +--res := array_append(res, ' '); +--res := array_append(res, 'idx_tup_fetch, 索引扫描实际获取的记录数, 如果平均每次读取记录数很多, 说明数据库倾向使用索引扫描, 建议观察随机IO的性能看情况调整 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_tup_ins, 统计周期内, 插入了多少条记录 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_tup_upd, 统计周期内, 更新了多少条记录 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_tup_hot_upd, 统计周期内, HOT更新(指更新后的记录依旧在当前PAGE)了多少条记录 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_live_tup, 该表有多少可用数据 '); +--res := array_append(res, ' '); +--res := array_append(res, 'n_dead_tup, 该表有多少垃圾数据 '); +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '平均扫描的记录数如果很多, 建议找到SQL, 并针对性的创建索引(统计分析需求除外). '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 4. 未命中buffer , 热表统计'); +--res := array_append(res, ' '); +--res := array_append(res, 'current_database | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||coalesce(current_database,'-')||'``` | ```'||coalesce(schemaname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | '||coalesce(sum(heap_blks_read),-1)||' | '||coalesce(sum(heap_blks_hit),-1)||' | '||coalesce(sum(idx_blks_read),-1)||' | '||coalesce(sum(idx_blks_hit),-1)||' | '||coalesce(sum(toast_blks_read),-1)||' | '||coalesce(sum(toast_blks_hit),-1)||' | '||coalesce(sum(tidx_blks_read),-1)||' | '||coalesce(sum(tidx_blks_hit),-1) from snap_pg_statio_all_tables where snap_id >=i_begin_id and snap_id<=i_end_id group by current_database,schemaname,relname order by sum(heap_blks_read+idx_blks_read+toast_blks_read+tidx_blks_read) desc nulls last limit 10 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '如果热表的命中率很低, 说明需要增加shared buffer, 添加内存. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 5. 未命中&命中buffer , 热表统计'); +--res := array_append(res, ' '); +--res := array_append(res, 'current_database | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||coalesce(current_database,'-')||'``` | ```'||coalesce(schemaname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | '||coalesce(sum(heap_blks_read),-1)||' | '||coalesce(sum(heap_blks_hit),-1)||' | '||coalesce(sum(idx_blks_read),-1)||' | '||coalesce(sum(idx_blks_hit),-1)||' | '||coalesce(sum(toast_blks_read),-1)||' | '||coalesce(sum(toast_blks_hit),-1)||' | '||coalesce(sum(tidx_blks_read),-1)||' | '||coalesce(sum(tidx_blks_hit),-1) from snap_pg_statio_all_tables where snap_id >=i_begin_id and snap_id<=i_end_id group by current_database,schemaname,relname order by sum(heap_blks_hit+idx_blks_hit+toast_blks_hit+tidx_blks_hit+heap_blks_read+idx_blks_read+toast_blks_read+tidx_blks_read) desc nulls last limit 10 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '如果热表的命中率很低, 说明需要增加shared buffer, 添加内存. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 6. 未命中 , 热索引统计'); +--res := array_append(res, ' '); +--res := array_append(res, 'current_database | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit'); +--res := array_append(res, '---|---|---|---|---|---'); +--for tmp in select '```'||coalesce(current_database,'-')||'``` | ```'||coalesce(schemaname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | ```'||coalesce(indexrelname,'-')||'``` | '||coalesce(sum(idx_blks_read),-1)||' | '||coalesce(sum(idx_blks_hit),-1) from snap_pg_statio_all_indexes where snap_id >=i_begin_id and snap_id<=i_end_id group by current_database,schemaname,relname,indexrelname order by sum(idx_blks_read) desc nulls last limit 10 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '如果热索引的命中率很低, 说明需要增加shared buffer, 添加内存. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 7. 未命中&命中buffer , 热索引统计'); +--res := array_append(res, ' '); +--res := array_append(res, 'current_database | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit'); +--res := array_append(res, '---|---|---|---|---|---'); +--for tmp in select '```'||coalesce(current_database,'-')||'``` | ```'||coalesce(schemaname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | ```'||coalesce(indexrelname,'-')||'``` | '||coalesce(sum(idx_blks_read),-1)||' | '||coalesce(sum(idx_blks_hit),-1) from snap_pg_statio_all_indexes where snap_id >=i_begin_id and snap_id<=i_end_id group by current_database,schemaname,relname,indexrelname order by sum(idx_blks_read+idx_blks_hit) desc nulls last limit 10 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '如果热索引的命中率很低, 说明需要增加shared buffer, 添加内存. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 8. 上次巡检以来未使用,或者使用较少的索引'); +--res := array_append(res, ' '); +--res := array_append(res, 'current_database | schemaname | relname | indexrelname | idx_scan | idx_tup_read | idx_tup_fetch | pg_size_pretty'); +--res := array_append(res, '---|---|---|---|---|---'); +--for tmp in select '```'||coalesce(current_database,'-')||'``` | ```'||coalesce(schemaname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | ```'||coalesce(indexrelname,'-')||'``` | '||coalesce(sum(idx_scan),-1)||' | '||coalesce(sum(idx_tup_read),-1)||' | '||coalesce(sum(idx_tup_fetch),-1)||' | '||coalesce(pg_size_pretty(avg(pg_relation_size)),'-') from snap_pg_notused_indexes where snap_id >=i_begin_id and snap_id<=i_end_id group by current_database,schemaname,relname,indexrelname order by sum(idx_scan) nulls last limit 10 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '建议和应用开发人员确认后, 删除不需要的索引. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 9. 索引数超过4并且SIZE大于10MB的表'); +--res := array_append(res, ' '); +--res := array_append(res, 'current_database | schemaname | relname | pg_size_pretty | idx_cnt'); +--res := array_append(res, '---|---|---|---|---'); +--for tmp in select '```'||coalesce(current_database,'-')||'``` | ```'||coalesce(nspname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | '||coalesce(pg_size_pretty(avg(pg_relation_size)),'-')||' | '||coalesce(max(idx_cnt),-1) from snap_pg_many_indexes_rel where snap_id >=i_begin_id and snap_id<=i_end_id group by current_database,nspname,relname order by max(idx_cnt) desc nulls last limit 20 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '索引数量太多, 影响表的增删改性能, 建议检查是否有不需要的索引. '); +--res := array_append(res, ' '); +--res := array_append(res, '建议检查pg_stat_all_tables(n_tup_ins,n_tup_upd,n_tup_del,n_tup_hot_upd), 如果确实非常频繁, 建议检查哪些索引是不需要的. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '## 二、数据库空间使用分析'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 1. 用户对象占用空间的柱状图'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | current_database | this_buk_no | rels_in_this_buk | buk_min | buk_max'); +--res := array_append(res, '---|---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(current_database,'-')||'``` | '||coalesce(this_buk_no,-1)||' | '||coalesce(rels_in_this_buk,-1)||' | '||coalesce(buk_min,'-')||' | '||coalesce(buk_max,'-') from snap_pg_rel_space_bucket where snap_id >=i_begin_id and snap_id<=i_end_id order by snap_ts,current_database,this_buk_no nulls last +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '纵览用户对象大小的柱状分布图, 单容量超过10GB的对象(指排除TOAST的空间还超过10GB),建议分区, 目前建议使用pg_pathman插件. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '## 三、数据库垃圾分析'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 1. 表膨胀分析'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | db | schemaname | tablename | tups | pages | otta | tbloat | wastedpages | wastedbytes | wastedsize | iname | itups | ipages | iotta | ibloat | wastedipages | wastedibytes | wastedisize | totalwastedbytes'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(db,'-')||'``` | ```'||coalesce(schemaname,'-')||'``` | ```'||coalesce(tablename,'-')||'``` | '||coalesce(tups,-1)||' | '||coalesce(pages,-1)||' | '||coalesce(otta,-1)||' | '||coalesce(tbloat,-1)||' | '||coalesce(wastedpages,-1)||' | '||coalesce(wastedbytes,-1)||' | '||coalesce(wastedsize,'-')||' | '||coalesce(iname,'-')||' | '||coalesce(itups,-1)||' | '||coalesce(ipages,-1)||' | '||coalesce(iotta,-1)||' | '||coalesce(ibloat,-1)||' | '||coalesce(wastedipages,-1)||' | '||coalesce(wastedibytes,-1)||' | '||coalesce(wastedisize,'-')||' | '||coalesce(totalwastedbytes,-1) from snap_pg_table_bloat where snap_id=i_end_id order by wastedbytes desc nulls last +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '根据浪费的字节数, 设置合适的autovacuum_vacuum_scale_factor, 大表如果频繁的有更新或删除和插入操作, 建议设置较小的autovacuum_vacuum_scale_factor来降低浪费空间. '); +--res := array_append(res, ' '); +--res := array_append(res, '同时还需要打开autovacuum, 根据服务器的内存大小, CPU核数, 设置足够大的autovacuum_work_mem 或 autovacuum_max_workers 或 maintenance_work_mem, 以及足够小的 autovacuum_naptime. '); +--res := array_append(res, ' '); +--res := array_append(res, '同时还需要分析是否对大数据库使用了逻辑备份pg_dump, 系统中是否经常有长SQL, 长事务. 这些都有可能导致膨胀. '); +--res := array_append(res, ' '); +--res := array_append(res, '使用pg_reorg或者vacuum full可以回收膨胀的空间. '); +--res := array_append(res, ' '); +--res := array_append(res, '参考: https://github.com/digoal/blog/blob/master/201504/20150429_02.md. '); +--res := array_append(res, ' '); +--res := array_append(res, 'otta评估出的表实际需要页数, iotta评估出的索引实际需要页数. '); +--res := array_append(res, ' '); +--res := array_append(res, 'bs数据库的块大小. '); +--res := array_append(res, ' '); +--res := array_append(res, 'tbloat表膨胀倍数, ibloat索引膨胀倍数, wastedpages表浪费了多少个数据块, wastedipages索引浪费了多少个数据块. '); +--res := array_append(res, ' '); +--res := array_append(res, 'wastedbytes表浪费了多少字节, wastedibytes索引浪费了多少字节. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 2. 索引膨胀分析'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | db | schemaname | tablename | tups | pages | otta | tbloat | wastedpages | wastedbytes | wastedsize | iname | itups | ipages | iotta | ibloat | wastedipages | wastedibytes | wastedisize | totalwastedbytes'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(db,'-')||'``` | ```'||coalesce(schemaname,'-')||'``` | ```'||coalesce(tablename,'-')||'``` | '||coalesce(tups,-1)||' | '||coalesce(pages,-1)||' | '||coalesce(otta,-1)||' | '||coalesce(tbloat,-1)||' | '||coalesce(wastedpages,-1)||' | '||coalesce(wastedbytes,-1)||' | '||coalesce(wastedsize,'-')||' | '||coalesce(iname,'-')||' | '||coalesce(itups,-1)||' | '||coalesce(ipages,-1)||' | '||coalesce(iotta,-1)||' | '||coalesce(ibloat,-1)||' | '||coalesce(wastedipages,-1)||' | '||coalesce(wastedibytes,-1)||' | '||coalesce(wastedisize,'-')||' | '||coalesce(totalwastedbytes,-1) from snap_pg_index_bloat where snap_id=i_end_id order by wastedibytes desc nulls last +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '如果索引膨胀太大, 会影响性能, 建议重建索引, create index CONCURRENTLY ... . '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 3. 垃圾记录 TOP 10 表分析'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | database | schemaname | tablename | n_dead_tup'); +--res := array_append(res, '---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(current_database,'-')||'``` | ```'||coalesce(schemaname,'-')||'``` | ```'||coalesce(relname,'-')||'``` | '||coalesce(sum(n_dead_tup),-1) from snap_pg_dead_tup where snap_id >=i_begin_id and snap_id<=i_end_id group by snap_ts,current_database,schemaname,relname order by sum(n_dead_tup) desc nulls last limit 10 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '通常垃圾过多, 可能是因为无法回收垃圾, 或者回收垃圾的进程繁忙或没有及时唤醒, 或者没有开启autovacuum, 或在短时间内产生了大量的垃圾. '); +--res := array_append(res, ' '); +--res := array_append(res, '可以等待autovacuum进行处理, 或者手工执行vacuum table. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 4. 未引用的大对象分析'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | database | pg_size_pretty'); +--res := array_append(res, '---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(current_database,'-')||'``` | '||coalesce(pg_size_pretty(lo_bloat),'-') from snap_pg_vacuumlo where snap_id=i_end_id +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '如果大对象没有被引用时, 建议删除, 否则就类似于内存泄露, 使用vacuumlo可以删除未被引用的大对象, 例如: vacuumlo -l 1000 $db -w或者我写的调用vacuumlo()函数. '); +--res := array_append(res, ' '); +--res := array_append(res, '应用开发时, 注意及时删除不需要使用的大对象, 使用lo_unlink 或 驱动对应的API. '); +--res := array_append(res, ' '); +--res := array_append(res, '参考 http://www.postgresql.org/docs/9.4/static/largeobjects.html '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '## 四、数据库安全或潜在风险分析'); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 1. 表年龄前100'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | database | rolname | nspname | relkind | relname | age | age_remain'); +--res := array_append(res, '---|---|---|---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(current_database,'-')||'``` | ```'||coalesce(rolname,'-')||'``` | ```'||coalesce(nspname,'-')||'``` | '||coalesce(relkind,'-')||' | ```'||coalesce(relname,'-')||'``` | '||coalesce(age,-1)||' | '||coalesce(age_remain,-1) from snap_pg_rel_age where snap_id=i_end_id and age_remain<500000000 order by age desc nulls last limit 100 +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '表的年龄正常情况下应该小于vacuum_freeze_table_age, 如果剩余年龄小于2亿, 建议人为干预, 将LONG SQL或事务杀掉后, 执行vacuum freeze. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 2. unlogged table和hash index'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | database | rolname | nspname | relname'); +--res := array_append(res, '---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(current_database,'-')||'``` | ```'||coalesce(rolname,'-')||'``` | ```'||coalesce(nspname,'-')||'``` | ```'||coalesce(relname,'-')||'```' from snap_pg_unlogged_table where snap_id=i_end_id +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | database | idx'); +--res := array_append(res, '---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(current_database,'-')||'``` | ```'||coalesce(pg_get_indexdef,'-')||'```' from snap_pg_hash_idx where snap_id=i_end_id +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, 'unlogged table和hash index不记录XLOG, 无法使用流复制或者log shipping的方式复制到standby节点, 如果在standby节点执行某些SQL, 可能导致报错或查不到数据. '); +--res := array_append(res, ' '); +--res := array_append(res, '在数据库CRASH后无法修复unlogged table和hash index, 不建议使用. '); +--res := array_append(res, ' '); +--res := array_append(res, 'PITR对unlogged table和hash index也不起作用. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 3. 剩余可使用次数不足1000万次的序列检查'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | database | rolname | nspname | relname | times_remain'); +--res := array_append(res, '---|---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | ```'||coalesce(v_datname,'-')||'``` | ```'||coalesce(v_role,'-')||'``` | ```'||coalesce(v_nspname,'-')||'``` | ```'||coalesce(v_relname,'-')||'``` | '||coalesce(v_times_remain,-1) from snap_pg_seq_deadline where snap_id=i_end_id +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '序列剩余使用次数到了之后, 将无法使用, 报错, 请开发人员关注. '); +--res := array_append(res, ' '); +-- +--res := array_append(res, '### 4. 锁等待分析'); +--res := array_append(res, ' '); +--res := array_append(res, 'snap_ts | locktype | r_mode | r_user | r_db | relation | r_pid | r_page | r_tuple | r_xact_start | r_query_start | r_locktime | r_query | w_mode | w_pid | w_page | w_tuple | w_xact_start | w_query_start | w_locktime | w_query'); +--res := array_append(res, '---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---'); +--for tmp in select '```'||snap_ts||'``` | '||coalesce(locktype,'-')||' | '||coalesce(r_mode,'-')||' | ```'||coalesce(r_user,'-')||'``` | ```'||coalesce(r_db,'-')||'``` | '||coalesce(relation,-1)||' | '||coalesce(r_pid,-1)||' | '||coalesce(r_page,-1)||' | '||coalesce(r_tuple,-1)||' | ```'||coalesce(r_xact_start,'1970-01-01')||'``` | ```'||coalesce(r_query_start,'1970-01-01')||'``` | ```'||coalesce(r_locktime,'0 s')||'``` | ```'||coalesce(replace(regexp_replace(r_query,'\n',' ','g'), '|', '|'),'-')||'``` | '||coalesce(w_mode,'-')||' | '||coalesce(w_pid,-1)||' | '||coalesce(w_page,-1)||' | '||coalesce(w_tuple,-1)||' | ```'||coalesce(w_xact_start,'1970-01-01')||'``` | ```'||coalesce(w_query_start,'1970-01-01')||'``` | ```'||coalesce(w_locktime,'0 s')||'``` | ```'||coalesce(replace(regexp_replace(w_query,'\n',' ','g'), '|', '|'),'-')||'```' from snap_pg_waiting where snap_id>=i_begin_id and snap_id<=i_end_id order by snap_ts,w_locktime desc nulls last +--loop +-- res := array_append(res, tmp); +--end loop; +--res := array_append(res, ' '); +--res := array_append(res, '#### 建议'); +--res := array_append(res, ' '); +--res := array_append(res, '锁等待状态, 反映业务逻辑的问题或者SQL性能有问题, 建议深入排查持锁的SQL. '); +--res := array_append(res, ' '); +-- +--reset search_path; +--return query select t from unnest(res) t1(t); +--end; +--$$ language plpgsql strict; + + + + + +reset search_path; +end; + diff --git a/playground/test.tameparser b/playground/test.tameparser new file mode 100644 index 0000000..45e7b98 --- /dev/null +++ b/playground/test.tameparser @@ -0,0 +1,221 @@ +/// +/// Parser Language Definition +/// +/// Created by Andrew Hunter on 21/05/2011 +/// + +language ParserLanguage { + /// Symbols used by the lexer + lexer-symbols { + // Commonly used character sets + letter = /({unicode-letter}|{unicode-punctuation-dash}|{unicode-punctuation-connector})/ + digit = /{unicode-number}/ + alphanumeric = /({letter}|{digit})/ + whitespace = /{unicode-separator}|[\t]/ + anycharacter = /[^\n\r]/ + + // Characters valid in regular expressions and strings + first-re-char = /[^\/\*]|(\\\/)/ + regex-char = /[^\/]|(\\\/)/ + string-char = /[^"]|(\\")/ + + // Identifiers, regular expressions + identifier = /{letter}{alphanumeric}*/ + regex = /\/{first-re-char}{regex-char}*\// + } + + /// Lexical symbols + lexer { + identifier = /{identifier}/ + nonterminal = /\<{identifier}\>/ + regex = /{regex}/ + string = /"{string-char}*"/ + character = /'(.|\\.)'/ + } + + /// Ignored symbols + ignore { + newline = /[\n\r]+/ + whitespace = /{whitespace}+/ + comment = /\/\/({anycharacter}*)/ + c-comment = /\/\*([^*]|\*[^\/])*\*\// + } + + /// Keywords + /// (We use very few keywords, to extend the range of identifiers available) + keywords { + } + + /// Weak keywords + /// Declared here to suppress warnings + weak keywords { + language + import + lexer-symbols + lexer + ignore + weak + keywords + grammar + replace + parser + test + from + case + sensitive + insensitive + precedence + + left + right + non-associative + non-assoc + + conflict + shift + reduce + + can-clash + } + + /// The grammar itself + grammar { + + // + // The top-level definitions + // + + = ()* + + = + | + | + | + + = language identifier[name] ()? '{' ()* '}' + + = import string[filename] + + = ':' identifier[inherit-from] + + // + // The language block + // + + = + | + | + | + | + | + + // + // Basic language items + // + + = *[modifiers] lexer-symbols '{' ()*[definitions] '}' + + = [=> * lexer] *[modifiers] lexer '{' ()*[definitions] '}' + + = ignore '{' ()*[definitions] '}' + + = [=> * keywords] *[modifiers] keywords '{' ()*[definitions] '}' + + = weak + | case sensitive + | case insensitive + + = case sensitive + | case insensitive + + = identifier[literal] + | [lexeme] + + = identifier[name] ('=' | "|=") (regex | string | character) + | [=> replace identifier '='] replace identifier[name] '=' (regex | string | character) + | identifier[name] '=' identifier[source-language] '.' identifier[source-name] + + // + // Defining grammars + // + + = grammar '{' ()*[nonterminals] '}' + + = [=> nonterminal ('=' | "|=")] nonterminal ('=' | "|=") ('|' )* + | [=> replace nonterminal '='] replace nonterminal '=' ('|' )* + + // Top level is just a simple EBNF term, as the '|' operator creates a new production at this point + = ()*[items] + + = ()*[items] + | ()*[items] '|' [or-item] + + = ? + | ? + | ? + | '*' ? + | '+' ? + | '?' ? + | '(' ')' ? + + = "[=>" ']' + | "[=>" '[' can-clash ']' ']' + + = nonterminal + | identifier[source-language] '.' nonterminal + + = + | identifier[source-language] '.' + + = identifier[lexeme-name] + | string + | character + + // + // Semantics + // + + = '[' [first-item] (',' )*[more-items] ']' + + = identifier[name] + | conflict '=' shift + | conflict '=' reduce + | conflict '=' weak reduce + + // + // Defining precedence + // + + = precedence '{' *[items] '}' + + = left + | right + | non-associative + | non-assoc + + = + | '{' *[terminals] '}' + + // + // The parser declaration block + // + + = parser identifier[name] ':' identifier[language-name] '{' ()+[start-symbols] '}' + + = + + // + // Test definition block + // + + = test identifier[language-name] '{' *[tests] '}' + + = '=' + + | "!=" + + | from + + + = string + | [=> identifier '('] identifier '(' string ')' + + } +} \ No newline at end of file diff --git a/playground/test.tm b/playground/test.tm new file mode 100644 index 0000000..5c43633 --- /dev/null +++ b/playground/test.tm @@ -0,0 +1,501 @@ +# syntax: lalr1 generator source grammar + +# Copyright 2002-2020 Evgeny Gryaznov +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +language tm(go); + +lang = "tm" +package = "github.com/inspirer/textmapper/parsers/tm" +eventBased = true +eventFields = true +cancellable = true +eventAST = true +writeBison = true +tokenColumn = true +fileNode = "File" +reportTokens = [invalid_token, multilineComment, comment, templates] + +:: lexer + +%s initial, afterID, afterColonOrEq, afterGT; + +reClass = /\[([^\n\r\]\\]|\\.)*\]/ +reFirst = /[^\n\r\*\[\\\/]|\\.|{reClass}/ +reChar = /{reFirst}|\*/ + +scon: /"([^\n\\"]|\\.)*"/ +icon: /-?[0-9]+/ + +templates: /%%/ (space) { l.rewind(len(l.source)) } +whitespace: /[\n\r\t ]+/ (space) +comment: /(#|\/\/)[^\r\n]*/ (space) + +commentChars = /([^*]|\*+[^*\/])*\**/ +multilineComment: /\/\*{commentChars}\*\// (space) + +'%': /%/ +'::': /::/ +'|': /\|/ +'||': /\|\|/ +'=': /=/ +'==': /==/ +'!=': /!=/ +';': /;/ +'.': /\./ +',': /,/ +':': /:/ +'[': /\[/ +']': /\]/ +'(': /\(/ +'(?=': /\(\?=/ +# TODO overlaps with ID +'->': /->/ +')': /\)/ +'}': /\}/ +'<': /': />/ +'*': /\*/ +'+': /+/ +'+=': /+=/ +'?': /?/ +'!': /!/ +'~': /~/ +'&': /&/ +'&&': /&&/ +'$': /$/ +'@': /@/ + +#xerror: +invalid_token: + +ID: /[a-zA-Z_]([a-zA-Z_\-0-9]*[a-zA-Z_0-9])?|'([^\n\\']|\\.)*'/ (class) + +'as': /as/ +'false': /false/ +'import': /import/ +'separator': /separator/ +'set': /set/ +'true': /true/ + +# Soft keywords. + +'assert': /assert/ +'brackets': /brackets/ +'class': /class/ +'empty': /empty/ +'expect': /expect/ +'expect-rr': /expect-rr/ +'explicit': /explicit/ +'extend': /extend/ +'flag': /flag/ +'generate': /generate/ +'global': /global/ +'inject': /inject/ +'inline': /inline/ +'input': /input/ +'interface': /interface/ +'lalr': /lalr/ +'language': /language/ +'layout': /layout/ +'left': /left/ +'lexer': /lexer/ +'lookahead': /lookahead/ +'no-eoi': /no-eoi/ +'nonassoc': /nonassoc/ +'nonempty': /nonempty/ +'param': /param/ +'parser': /parser/ +'prec': /prec/ +'right': /right/ +'s': /s/ +'shift': /shift/ +'space': /space/ +'x': /x/ + + +code: /\{/ /* We skip the rest in a post-processing action. */ + + +'{': /\{/ + + +regexp: /\/{reFirst}{reChar}*\// + + +'/': /\// + +:: parser + +%input file, nonterm; + +%flag OrSyntaxError = false; + +# Basic nonterminals. + +identifier -> Identifier: + ID + +# Soft keywords + | 'brackets' | 'inline' | 'prec' | 'shift' | 'input' + | 'left' | 'right' | 'nonassoc' | 'generate' | 'assert' | 'empty' + | 'nonempty' | 'global' | 'explicit' | 'lookahead' | 'param' | 'flag' + | 'no-eoi' | 's' | 'x' | 'expect' | 'expect-rr' + | 'class' | 'interface' | 'space' | 'extend' | 'inject' + | 'layout' | 'language' | 'lalr' | 'lexer' | 'parser' + + # Keywords + | [Keywords] ('true' | 'false' | 'separator' | 'as' | 'import' | 'set') +; + +integer_literal -> IntegerLiteral: + icon ; + +string_literal -> StringLiteral: + scon ; + +boolean_literal -> BooleanLiteral: + 'true' + | 'false' +; + +%interface Literal; + +literal -> Literal: + string_literal + | integer_literal + | boolean_literal +; + +pattern -> Pattern: + regexp ; + +command -> Command: + code ; + +syntax_problem -> SyntaxProblem: + xerror ; + +file -> File: + header imports=import_* options=option* syntax_problem? lexer=lexer_section? parser=parser_section? ; + +header -> Header: + 'language' name=identifier<+Keywords> ('(' target=identifier<+Keywords> ')')? ';' ; + +lexer_section -> LexerSection: + '::' .recoveryScope 'lexer' lexer_parts ; + +parser_section -> ParserSection: + '::' .recoveryScope 'parser' grammar_parts ; + +import_ -> Import: + 'import' alias=identifier? path=string_literal ';' ; + +option -> Option: + key=identifier '=' value=expression ; + +symref -> Symref: + [Args] name=identifier args=args? + | [!Args] name=identifier +; + +rawType -> RawType: + code ; + +lexer_parts: + lexer_part + | lexer_parts lexer_part<+OrSyntaxError> +; + +%interface LexerPart; + +lexer_part -> LexerPart: + named_pattern + | lexeme + | lexer_directive + | start_conditions_scope + | [OrSyntaxError] syntax_problem +; + +named_pattern -> NamedPattern: + name=identifier '=' pattern ; + +start_conditions_scope -> StartConditionsScope: + start_conditions '{' .recoveryScope lexer_parts '}' ; + +start_conditions -> StartConditions: + '<' '*' '>' + | '<' (stateref separator ',')+ '>' +; + +lexeme -> Lexeme: + start_conditions? name=identifier rawTypeopt reportClause? ':' + (pattern priority=integer_literal? attrs=lexeme_attrs? command? | attrs=lexeme_attrs)? ; + +lexeme_attrs -> LexemeAttrs: + '(' lexeme_attribute ')' ; + +lexeme_attribute -> LexemeAttribute: + 'class' + | 'space' + | 'layout' +; + +lexer_directive -> LexerPart: + '%' 'brackets' opening=symref<~Args> closing=symref<~Args> ';' -> DirectiveBrackets + | '%' 's' states=(lexer_state separator ',')+ ';' -> InclusiveStartConds + | '%' 'x' states=(lexer_state separator ',')+ ';' -> ExclusiveStartConds +; + +stateref -> Stateref: + name=identifier ; + +lexer_state -> LexerState: + name=identifier ; + +grammar_parts: + grammar_part + | grammar_parts grammar_part<+OrSyntaxError> +; + +%interface GrammarPart; + +grammar_part -> GrammarPart: + nonterm + | template_param + | directive + | [OrSyntaxError] syntax_problem +; + +nonterm -> Nonterm: + annotations? name=identifier params=nonterm_params? rawType? reportClause? ':' rules ';' + | ('extend' -> Extend) name=identifier reportClause? ':' rules ';' +; + +assoc -> Assoc: + 'left' + | 'right' + | 'nonassoc' +; + +param_modifier -> ParamModifier: + 'explicit' + | 'global' + | 'lookahead' +; + +template_param -> GrammarPart: + '%' modifier=param_modifier? param_type name=identifier ('=' param_value)? ';' -> TemplateParam +; + +directive -> GrammarPart: + '%' assoc symbols=references ';' -> DirectivePrio + | '%' 'input' inputRefs=(inputref separator ',')+ ';' -> DirectiveInput + | '%' 'interface' ids=(identifier separator ',')+ ';' -> DirectiveInterface + | '%' 'assert' ('empty' -> Empty | 'nonempty' -> NonEmpty) rhsSet ';' -> DirectiveAssert + | '%' 'generate' name=identifier '=' rhsSet ';' -> DirectiveSet + | '%' 'expect' integer_literal ';' -> DirectiveExpect + | '%' 'expect-rr' integer_literal ';' -> DirectiveExpectRR + | '%' 'inject' symref<~Args> reportClause ';' -> DirectiveInject +; + +inputref -> Inputref: + reference=symref<~Args> ('no-eoi' -> NoEoi)? ; + +references: + symref<~Args> + | references symref<~Args> +; + +rules: + rule0 + | rules '|' rule0 +; + +%interface Rule0; + +rule0 -> Rule0: + predicate? rhsParts? rhsSuffix? reportClause? -> Rule + | syntax_problem +; + +predicate -> Predicate: + '[' predicate_expression ']' ; + +rhsSuffix -> RhsSuffix: + '%' ('prec' -> Name) symref<~Args> + | '%' ('shift' -> Name) symref<~Args> +; + +reportClause -> ReportClause: + '->' action=identifier ('/' flags=(identifier separator ',')+)? reportAs? ; + +reportAs -> ReportAs: + 'as' identifier ; + +rhsParts: + rhsPart + | rhsParts rhsPart<+OrSyntaxError> +; + +%interface RhsPart; + +rhsPart -> RhsPart: + rhsAnnotated + | command + | rhsStateMarker + | rhsLookahead + | [OrSyntaxError] syntax_problem +; + +rhsLookahead -> RhsLookahead: + '(?=' predicates=(lookahead_predicate separator '&')+ ')' ; + +lookahead_predicate -> LookaheadPredicate: + ('!' -> Not)? symref<~Args> ; + +rhsStateMarker -> StateMarker: + '.' name=identifier ; + +rhsAnnotated -> RhsPart: + rhsAssignment + | annotations inner=rhsAssignment -> RhsAnnotated +; + +rhsAssignment -> RhsPart: + rhsOptional + | id=identifier '=' inner=rhsOptional -> RhsAssignment + | id=identifier '+=' inner=rhsOptional -> RhsPlusAssignment +; + +rhsOptional -> RhsPart: + rhsCast + | inner=rhsCast '?' -> RhsOptional +; + +rhsCast -> RhsPart: + rhsPrimary + | inner=rhsPrimary 'as' target=symref<+Args> -> RhsCast + | inner=rhsPrimary 'as' literal -> RhsAsLiteral /* TODO remove */ +; + +listSeparator -> ListSeparator: + 'separator' separator_=references ; + +rhsPrimary -> RhsPart: + reference=symref<+Args> -> RhsSymbol + | '(' .recoveryScope rules ')' -> RhsNested + | '(' .recoveryScope ruleParts=rhsParts listSeparator ')' '+' -> RhsPlusList + | '(' .recoveryScope ruleParts=rhsParts listSeparator ')' '*' -> RhsStarList + | inner=rhsPrimary '+' -> RhsPlusQuantifier + | inner=rhsPrimary '*' -> RhsStarQuantifier + | '$' '(' .recoveryScope rules ')' -> RhsIgnored + | rhsSet +; + +rhsSet -> RhsSet: + 'set' '(' .recoveryScope expr=setExpression ')' ; + +%interface SetExpression; + +setPrimary -> SetExpression: + operator=identifier? symbol=symref<+Args> -> SetSymbol + | '(' inner=setExpression ')' -> SetCompound + | '~' inner=setPrimary -> SetComplement +; + +%left '|'; +%left '&'; + +setExpression -> SetExpression: + setPrimary + | left=setExpression '|' right=setExpression -> SetOr + | left=setExpression '&' right=setExpression -> SetAnd +; + +annotations -> Annotations: + annotation+ ; + +%interface Annotation; + +annotation -> Annotation: + '@' name=identifier ('=' expression)? -> AnnotationImpl + | '@' syntax_problem +; + +/* Nonterminal parameters */ + +nonterm_params -> NontermParams: + '<' list=(nonterm_param separator ',')+ '>' ; + +%interface NontermParam; + +nonterm_param -> NontermParam: + param_ref + | param_type=identifier name=identifier ('=' param_value)? -> InlineParameter +; + +param_ref -> ParamRef: + identifier ; + +args -> SymrefArgs: + '<' arg_list=(argument separator ',')* '>' ; + +%interface Argument; + +argument -> Argument: + name=param_ref (':' val=param_value)? -> ArgumentVal + | '+' name=param_ref -> ArgumentTrue + | '~' name=param_ref -> ArgumentFalse +; + +param_type -> ParamType: + 'flag' + | 'param' +; + +%interface ParamValue; + +param_value -> ParamValue: + literal + | param_ref +; + +predicate_primary -> PredicateExpression: + param_ref + | '!' param_ref -> PredicateNot + | param_ref '==' literal -> PredicateEq + | param_ref '!=' literal -> PredicateNotEq +; + +%left '||'; +%left '&&'; + +%interface PredicateExpression; + +predicate_expression -> PredicateExpression: + predicate_primary + | left=predicate_expression '&&' right=predicate_expression -> PredicateAnd + | left=predicate_expression '||' right=predicate_expression -> PredicateOr +; + +%interface Expression; + +expression -> Expression: + literal + | symref<+Args> + | '[' (expression separator ',')+? ','? ']' -> Array + | syntax_problem +; + diff --git a/playground/test.vl b/playground/test.vl new file mode 100644 index 0000000..15cc811 --- /dev/null +++ b/playground/test.vl @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1999 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + /* + * This example program simulates a 16x1 ram, and is used as an + * example for using VCD output and waveform viewers. + * + * Like any other Verilog simulation, compile this program with the + * command: + * + * iverilog show_vcd.vl + * + * This will generate the show_vcd command in the current directory. + * When you run the command, you will see the output from all the + * calls to $display, but also there will be a dump file ``show_vcd.vcd''. + * The name of this file is set by the statement: + * + * $dumpfile("show_vcd.vcd"); + * + * in the main module. The output file uses the standard VCD file format + * so can be viewed using off-the-shelf waveform viewers. The remaining + * steps describe how to use GTKWave to view the file. If you are using + * a different viewer, see the documentation for that tool. + * + * To view the output generated by running show_vcd, start the GTKWave + * viewer with the command: + * + * gtkwave show_vcd.vcd + * + * The GTKWave program will display its main window, and show in a small + * status box (upper left corner) that it succeeded in loading the dump + * file. However, there are no waveforms displayed yet. Select signals to + * add to the waveform display using the menu selection: + * + * "Search --> Signal Search Tree" + * + * This will bring up a dialog box that shows in directory tree format + * the signals of the program. Select the signals you wish to view, and + * click one of the buttons on the bottom of the dialog box to display + * the selected signals in the waveform window. Click "Exit" on the box + * to get rid of it. + * + * The magic that makes all this work is contained in the $dumpfile and + * $dumpvars system tasks. The $dumpfile task tells the simulation where + * to write the VCD output. This task must be called once before the + * $dumpvars task is called. + * + * The $dumpvars task tells the simulation what variables to write to + * the VCD output. The first parameter is how far to descend while + * scanning a scope, and the remaining parameters are signals or scope + * names to include in the dump. If a scope name is given, all the + * signals within the scope are dumped. If a wire or register name is + * given, that signal is included. + */ + +module ram16x1 (q, d, a, we, wclk); + output q; + input d; + input [3:0] a; + input we; + input wclk; + + reg mem[15:0]; + + assign q = mem[a]; + always @(posedge wclk) if (we) mem[a] = d; + +endmodule /* ram16x1 */ + +module main; + wire q; + reg d; + reg [3:0] a; + reg we, wclk; + + ram16x1 r1 (q, d, a, we, wclk); + + initial begin + $dumpfile("show_vcd.vcd"); + $dumpvars(1, main.r1); + wclk = 0; + we = 1; + for (a = 0 ; a < 4'hf ; a = a + 1) begin + d = a[0]; + #1 wclk = 1; + #1 wclk = 0; + $display("r1[%x] == %b", a, q); + end + + for (a = 0 ; a < 4'hf ; a = a + 1) + #1 if (q !== a[0]) begin + $display("FAILED -- mem[%h] !== %b", a, a[0]); + $finish; + end + + $display("PASSED"); + end +endmodule /* main */ diff --git a/playground/test.xml.txt b/playground/test.xml.txt new file mode 100644 index 0000000..5cb0ad4 --- /dev/null +++ b/playground/test.xml.txt @@ -0,0 +1,6 @@ + + + + + + diff --git a/playground/textmapper.g b/playground/textmapper.g new file mode 100644 index 0000000..e2fb530 --- /dev/null +++ b/playground/textmapper.g @@ -0,0 +1,764 @@ +textmapper { + +//%error_recovery_show; +//%error_recovery_off; +%whitespace "[ \t\r\n]*"; +%whitespace "#[^\n\r]*"; +//%whitespace "/\*[^*]+\*/"; +%whitespace "/\*:C_MultilineComment:"; + +/*Tokens*/ +/* +%token YYEOF +%token YYerror +%token YYUNDEF +%token OR +%token AND +%token OROR +%token ANDAND +%token INVALID_TOKEN +%token SCON +%token ICON +%token TEMPLATES +%token WHITESPACE +%token COMMENT +%token MULTILINECOMMENT +%token REM +%token COLONCOLON +%token ASSIGN +%token ASSIGNASSIGN +%token EXCLASSIGN +%token SEMICOLON +%token DOT +%token COMMA +%token COLON +%token LBRACK +%token RBRACK +%token LPAREN +%token LPARENQUESTASSIGN +%token MINUSGT +%token RPAREN +%token RBRACE +%token LT +%token GT +%token MULT +%token PLUS +%token PLUSASSIGN +%token QUEST +%token EXCL +%token TILDE +%token DOLLAR +%token ATSIGN +%token ERROR +%token ID +%token AS +%token FALSE +%token IMPORT +%token SEPARATOR +%token SET +%token TRUE +%token ASSERT +%token BRACKETS +%token CLASS +%token EMPTY +%token EXPECT +%token EXPECTMINUSRR +%token EXPLICIT +%token EXTEND +%token FLAG +%token GENERATE +%token GLOBAL +%token INJECT +%token INLINE +%token INPUT +%token INTERFACE +%token LALR +%token LANGUAGE +%token LAYOUT +%token LEFT +%token LEXER +%token LOOKAHEAD +%token NOMINUSEOI +%token NONASSOC +%token NONEMPTY +%token PARAM +%token PARSER +%token PREC +%token RIGHT +%token CHAR_S +%token SHIFT +%token SPACE +%token CHAR_X +%token CODE +%token LBRACE +%token REGEXP +%token DIV +%token YY_PARSE_file +%token YY_PARSE_nonterm +*/ + +%left /*1*/ OR ; +%left /*2*/ AND ; +%left /*3*/ OROR ; +%left /*4*/ ANDAND ; + +//%start file + +//%% + +YY_PARSE_file : + file //YYEOF + ; +/* +YY_PARSE_nonterm : + nonterm //YYEOF + ; +*/ +identifier : + ID + | BRACKETS + | INLINE + | PREC + | SHIFT + | INPUT + | LEFT + | RIGHT + | NONASSOC + | GENERATE + | ASSERT + | EMPTY + | NONEMPTY + | GLOBAL + | EXPLICIT + | LOOKAHEAD + | PARAM + | FLAG + | NOMINUSEOI + | REM_CHAR_S + | REM_CHAR_X + | EXPECT + | EXPECTMINUSRR + | CLASS + | INTERFACE + | SPACE + | EXTEND + | INJECT + | LAYOUT + | LANGUAGE + | LALR + | LEXER + | PARSER + ; + +identifier_Keywords : + identifier + | TRUE + | FALSE + | SEPARATOR + | AS + | IMPORT + | SET + ; + +integer_literal : + ICON + ; + +string_literal : + SCON + ; + +boolean_literal : + TRUE + | FALSE + ; + +literal : + string_literal + | integer_literal + | boolean_literal + ; + +pattern : + REGEXP + ; + +command : + CODE + ; + +syntax_problem : + ERROR + ; + +file : + header import__optlist option_optlist syntax_problem lexer_section parser_section + | header import__optlist option_optlist syntax_problem lexer_section + | header import__optlist option_optlist syntax_problem parser_section + | header import__optlist option_optlist syntax_problem + | header import__optlist option_optlist lexer_section parser_section + | header import__optlist option_optlist lexer_section + | header import__optlist option_optlist parser_section + | header import__optlist option_optlist + ; + +import__optlist : + import__optlist import_ + | /*empty*/ + ; + +option_optlist : + option_optlist option + | /*empty*/ + ; + +header : + LANGUAGE identifier_Keywords LPAREN identifier_Keywords RPAREN SEMICOLON + | LANGUAGE identifier_Keywords SEMICOLON + ; + +lexer_section : + COLONCOLON LEXER lexer_parts + ; + +parser_section : + COLONCOLON PARSER grammar_parts + ; + +import_ : + IMPORT identifier string_literal SEMICOLON + | IMPORT string_literal SEMICOLON + ; + +option : + identifier ASSIGN expression + ; + +symref : + identifier + ; + +symref_Args : + identifier args + | identifier + ; + +rawType : + CODE + ; + +lexer_parts : + lexer_part + | lexer_parts lexer_part_OrSyntaxError + ; + +lexer_part : + named_pattern + | lexeme + | lexer_directive + | start_conditions_scope + ; + +lexer_part_OrSyntaxError : + named_pattern + | lexeme + | lexer_directive + | start_conditions_scope + | syntax_problem + ; + +named_pattern : + identifier ASSIGN pattern + ; + +start_conditions_scope : + start_conditions LBRACE lexer_parts RBRACE + ; + +start_conditions : + LT MULT GT + | LT stateref_list_Comma_separated GT + ; + +stateref_list_Comma_separated : + stateref_list_Comma_separated COMMA stateref + | stateref + ; + +lexeme : + start_conditions identifier rawTypeopt reportClause COLON pattern integer_literal lexeme_attrs command + | start_conditions identifier rawTypeopt reportClause COLON pattern integer_literal lexeme_attrs + | start_conditions identifier rawTypeopt reportClause COLON pattern integer_literal command + | start_conditions identifier rawTypeopt reportClause COLON pattern integer_literal + | start_conditions identifier rawTypeopt reportClause COLON pattern lexeme_attrs command + | start_conditions identifier rawTypeopt reportClause COLON pattern lexeme_attrs + | start_conditions identifier rawTypeopt reportClause COLON pattern command + | start_conditions identifier rawTypeopt reportClause COLON pattern + | start_conditions identifier rawTypeopt reportClause COLON lexeme_attrs + | start_conditions identifier rawTypeopt reportClause COLON + | start_conditions identifier rawTypeopt COLON pattern integer_literal lexeme_attrs command + | start_conditions identifier rawTypeopt COLON pattern integer_literal lexeme_attrs + | start_conditions identifier rawTypeopt COLON pattern integer_literal command + | start_conditions identifier rawTypeopt COLON pattern integer_literal + | start_conditions identifier rawTypeopt COLON pattern lexeme_attrs command + | start_conditions identifier rawTypeopt COLON pattern lexeme_attrs + | start_conditions identifier rawTypeopt COLON pattern command + | start_conditions identifier rawTypeopt COLON pattern + | start_conditions identifier rawTypeopt COLON lexeme_attrs + | start_conditions identifier rawTypeopt COLON + | identifier rawTypeopt reportClause COLON pattern integer_literal lexeme_attrs command + | identifier rawTypeopt reportClause COLON pattern integer_literal lexeme_attrs + | identifier rawTypeopt reportClause COLON pattern integer_literal command + | identifier rawTypeopt reportClause COLON pattern integer_literal + | identifier rawTypeopt reportClause COLON pattern lexeme_attrs command + | identifier rawTypeopt reportClause COLON pattern lexeme_attrs + | identifier rawTypeopt reportClause COLON pattern command + | identifier rawTypeopt reportClause COLON pattern + | identifier rawTypeopt reportClause COLON lexeme_attrs + | identifier rawTypeopt reportClause COLON + | identifier rawTypeopt COLON pattern integer_literal lexeme_attrs command + | identifier rawTypeopt COLON pattern integer_literal lexeme_attrs + | identifier rawTypeopt COLON pattern integer_literal command + | identifier rawTypeopt COLON pattern integer_literal + | identifier rawTypeopt COLON pattern lexeme_attrs command + | identifier rawTypeopt COLON pattern lexeme_attrs + | identifier rawTypeopt COLON pattern command + | identifier rawTypeopt COLON pattern + | identifier rawTypeopt COLON lexeme_attrs + | identifier rawTypeopt COLON + ; + +lexeme_attrs : + LPAREN lexeme_attribute RPAREN + ; + +lexeme_attribute : + CLASS + | SPACE + | LAYOUT + ; + +lexer_directive : + REM BRACKETS symref symref SEMICOLON + | REM_CHAR_S lexer_state_list_Comma_separated SEMICOLON + | REM_CHAR_X lexer_state_list_Comma_separated SEMICOLON + ; + +lexer_state_list_Comma_separated : + lexer_state_list_Comma_separated COMMA lexer_state + | lexer_state + ; + +stateref : + identifier + ; + +lexer_state : + identifier + ; + +grammar_parts : + grammar_part + | grammar_parts grammar_part_OrSyntaxError + ; + +grammar_part : + nonterm + | template_param + | directive + ; + +grammar_part_OrSyntaxError : + nonterm + | template_param + | directive + | syntax_problem + ; + +nonterm : + annotations identifier nonterm_params rawType reportClause COLON rules SEMICOLON + | annotations identifier nonterm_params rawType COLON rules SEMICOLON + | annotations identifier nonterm_params reportClause COLON rules SEMICOLON + | annotations identifier nonterm_params COLON rules SEMICOLON + | annotations identifier rawType reportClause COLON rules SEMICOLON + | annotations identifier rawType COLON rules SEMICOLON + | annotations identifier reportClause COLON rules SEMICOLON + | annotations identifier COLON rules SEMICOLON + | identifier nonterm_params rawType reportClause COLON rules SEMICOLON + | identifier nonterm_params rawType COLON rules SEMICOLON + | identifier nonterm_params reportClause COLON rules SEMICOLON + | identifier nonterm_params COLON rules SEMICOLON + | identifier rawType reportClause COLON rules SEMICOLON + | identifier rawType COLON rules SEMICOLON + | identifier reportClause COLON rules SEMICOLON + | identifier COLON rules SEMICOLON + | EXTEND identifier reportClause COLON rules SEMICOLON + | EXTEND identifier COLON rules SEMICOLON + ; + +assoc : + LEFT + | RIGHT + | NONASSOC + ; + +param_modifier : + EXPLICIT + | GLOBAL + | LOOKAHEAD + ; + +template_param : + REM param_modifier param_type identifier ASSIGN param_value SEMICOLON + | REM param_modifier param_type identifier SEMICOLON + | REM param_type identifier ASSIGN param_value SEMICOLON + | REM param_type identifier SEMICOLON + ; + +directive : + REM assoc references SEMICOLON + | REM INPUT inputref_list_Comma_separated SEMICOLON + | REM INTERFACE identifier_list_Comma_separated SEMICOLON + | REM ASSERT EMPTY rhsSet SEMICOLON + | REM ASSERT NONEMPTY rhsSet SEMICOLON + | REM GENERATE identifier ASSIGN rhsSet SEMICOLON + | REM EXPECT integer_literal SEMICOLON + | REM EXPECTMINUSRR integer_literal SEMICOLON + | REM INJECT symref reportClause SEMICOLON + ; + +identifier_list_Comma_separated : + identifier_list_Comma_separated COMMA identifier + | identifier + ; + +inputref_list_Comma_separated : + inputref_list_Comma_separated COMMA inputref + | inputref + ; + +inputref : + symref NOMINUSEOI + | symref + ; + +references : + symref + | references symref + ; + +rules : + rule0 + | rules OR /*1L*/ rule0 + ; + +rule0 : + predicate rhsParts rhsSuffix reportClause + | predicate rhsParts rhsSuffix + | predicate rhsParts reportClause + | predicate rhsParts + | predicate rhsSuffix reportClause + | predicate rhsSuffix + | predicate reportClause + | predicate + | rhsParts rhsSuffix reportClause + | rhsParts rhsSuffix + | rhsParts reportClause + | rhsParts + | rhsSuffix reportClause + | rhsSuffix + | reportClause + | /*empty*/ + | syntax_problem + ; + +predicate : + LBRACK predicate_expression RBRACK + ; + +rhsSuffix : + REM PREC symref + | REM SHIFT symref + ; + +reportClause : + MINUSGT identifier DIV identifier_list_Comma_separated reportAs + | MINUSGT identifier DIV identifier_list_Comma_separated + | MINUSGT identifier reportAs + | MINUSGT identifier + ; + +reportAs : + AS identifier + ; + +rhsParts : + rhsPart + | rhsParts rhsPart_OrSyntaxError + ; + +rhsPart : + rhsAnnotated + | command + | rhsStateMarker + | rhsLookahead + ; + +rhsPart_OrSyntaxError : + rhsAnnotated + | command + | rhsStateMarker + | rhsLookahead + | syntax_problem + ; + +lookahead_predicate_list_And_separated : + lookahead_predicate_list_And_separated AND /*2L*/ lookahead_predicate + | lookahead_predicate + ; + +rhsLookahead : + LPARENQUESTASSIGN lookahead_predicate_list_And_separated RPAREN + ; + +lookahead_predicate : + EXCL symref + | symref + ; + +rhsStateMarker : + DOT identifier + ; + +rhsAnnotated : + rhsAssignment + | annotations rhsAssignment + ; + +rhsAssignment : + rhsOptional + | identifier ASSIGN rhsOptional + | identifier PLUSASSIGN rhsOptional + ; + +rhsOptional : + rhsCast + | rhsCast QUEST + ; + +rhsCast : + rhsPrimary + | rhsPrimary AS symref_Args + | rhsPrimary AS literal + ; + +listSeparator : + SEPARATOR references + ; + +rhsPrimary : + symref_Args + | LPAREN rules RPAREN + | LPAREN rhsParts listSeparator RPAREN PLUS + | LPAREN rhsParts listSeparator RPAREN MULT + | rhsPrimary PLUS + | rhsPrimary MULT + | DOLLAR LPAREN rules RPAREN + | rhsSet + ; + +rhsSet : + SET LPAREN setExpression RPAREN + ; + +setPrimary : + identifier symref_Args + | symref_Args + | LPAREN setExpression RPAREN + | TILDE setPrimary + ; + +setExpression : + setPrimary + | setExpression OR /*1L*/ setExpression + | setExpression AND /*2L*/ setExpression + ; + +annotation_list : + annotation_list annotation + | annotation + ; + +annotations : + annotation_list + ; + +annotation : + ATSIGN identifier ASSIGN expression + | ATSIGN identifier + | ATSIGN syntax_problem + ; + +nonterm_param_list_Comma_separated : + nonterm_param_list_Comma_separated COMMA nonterm_param + | nonterm_param + ; + +nonterm_params : + LT nonterm_param_list_Comma_separated GT + ; + +nonterm_param : + param_ref + | identifier identifier ASSIGN param_value + | identifier identifier + ; + +param_ref : + identifier + ; + +args : + LT argument_list_Comma_separatedopt GT + ; + +argument_list_Comma_separated : + argument_list_Comma_separated COMMA argument + | argument + ; + +argument_list_Comma_separatedopt : + argument_list_Comma_separated + | /*empty*/ + ; + +argument : + param_ref COLON param_value + | param_ref + | PLUS param_ref + | TILDE param_ref + ; + +param_type : + FLAG + | PARAM + ; + +param_value : + literal + | param_ref + ; + +predicate_primary : + param_ref + | EXCL param_ref + | param_ref ASSIGNASSIGN literal + | param_ref EXCLASSIGN literal + ; + +predicate_expression : + predicate_primary + | predicate_expression ANDAND /*4L*/ predicate_expression + | predicate_expression OROR /*3L*/ predicate_expression + ; + +expression : + literal + | symref_Args + | LBRACK expression_list_Comma_separated COMMA RBRACK + | LBRACK expression_list_Comma_separated RBRACK + | LBRACK COMMA RBRACK + | LBRACK RBRACK + | syntax_problem + ; + +expression_list_Comma_separated : + expression_list_Comma_separated COMMA expression + | expression + ; + +rawTypeopt : + rawType + | /*empty*/ + ; + +//Lexer + +OR : '|' ; +AND : '&' ; +OROR : '||' ; +ANDAND : '&&' ; +ID : "[a-zA-Z_]([a-zA-Z_\-0-9]*[a-zA-Z_0-9])?|'([^\n\\']|\\.)*'" ; +BRACKETS : 'brackets' ; +INLINE : 'inline' ; +PREC : 'prec' ; +SHIFT : 'shift' ; +INPUT : 'input' ; +LEFT : 'left' ; +RIGHT : 'right' ; +NONASSOC : 'nonassoc' ; +GENERATE : 'generate' ; +ASSERT : 'assert' ; +EMPTY : 'empty' ; +NONEMPTY : 'nonempty' ; +GLOBAL : 'global' ; +EXPLICIT : 'explicit' ; +LOOKAHEAD : 'lookahead' ; +PARAM : 'param' ; +FLAG : 'flag' ; +NOMINUSEOI : 'no-eoi' ; +REM_CHAR_S : '%s' ; +REM_CHAR_X : 'x' ; +EXPECT : 'expect' ; +EXPECTMINUSRR : 'expect-rr' ; +CLASS : 'class' ; +INTERFACE : 'interface' ; +SPACE : 'space' ; +EXTEND : 'extend' ; +INJECT : 'inject' ; +LAYOUT : 'layout' ; +LANGUAGE : 'language' ; +LALR : 'lalr' ; +LEXER : 'lexer' ; +PARSER : 'parser' ; +TRUE : 'true' ; +FALSE : 'false' ; +SEPARATOR : 'separator' ; +AS : 'as' ; +IMPORT : 'import' ; +SET : 'set' ; +ICON : "\-?[0-9]+" ; +SCON : "\"(\\.|[^\"\n])*\"" ; +REGEXP : "/(\\.|[^/\n])+/" ; +CODE : "{[^}]*}" ; +ERROR : 'xerror' ; //TODO fix bug with 'error' as reserved keyword +LPAREN : '(' ; +RPAREN : ')' ; +SEMICOLON : ';' ; +COLONCOLON : '::' ; +ASSIGN : '=' ; +LBRACE : '{' ; +RBRACE : '}' ; +LT : '<' ; +MULT : '*' ; +GT : '>' ; +COMMA : ',' ; +COLON : ':' ; +REM : '%' ; +LBRACK : '[' ; +RBRACK : ']' ; +MINUSGT : '->' ; +DIV : '/' ; +LPARENQUESTASSIGN : '(?=' ; +EXCL : '!' ; +DOT : '.' ; +PLUSASSIGN : '+=' ; +QUEST : '?' ; +PLUS : '+' ; +DOLLAR : '$' ; +TILDE : '~' ; +ATSIGN : '@=' ; +ASSIGNASSIGN : '==' ; +EXCLASSIGN : '!=' ; + +} diff --git a/playground/xml.g b/playground/xml.g new file mode 100644 index 0000000..b6481fd --- /dev/null +++ b/playground/xml.g @@ -0,0 +1,13 @@ +xml { + %whitespace "[ \t\r\n]*"; + %left '<' '>'; + %left name; + document: prolog element [document]; + prolog: "<\?xml" attributes "\?>" | ; + elements: elements element [add_element] | element [create_element] | %precedence '<'; + element: '<' name attributes '/>' [short_element] | '<' name attributes '>' elements '' [long_element]; + attributes: attributes attribute [add_attribute] | attribute [create_attribute] | %precedence name; + attribute: name '=' value [attribute]; + name: "[A-Za-z_:][A-Za-z0-9_:\.-]*"; + value: "\"(\\.|[^\"\n])*\"|'(\\.|[^'\n])*'"; +} From d5231dc5e7fedb21e6652628eaa1b060c811f6ca Mon Sep 17 00:00:00 2001 From: mingodad Date: Tue, 14 Nov 2023 15:18:11 +0100 Subject: [PATCH 39/40] Update code --- playground/lalr_playground.cpp | 73 +++++++++++++++++++------------- playground/lalr_playground.js | 1 + playground/lalr_playground.wasm | Bin 0 -> 161193 bytes src/lalr/Grammar.cpp | 66 +++++++++++++++++++++++------ src/lalr/Grammar.hpp | 6 +-- src/lalr/GrammarCompiler.cpp | 16 +++++-- src/lalr/GrammarCompiler.hpp | 2 +- src/lalr/GrammarGenerator.cpp | 68 +++++++++++++++++++++++------ src/lalr/GrammarGenerator.hpp | 8 +++- src/lalr/GrammarParser.cpp | 16 ++++--- src/lalr/GrammarParser.hpp | 1 + src/lalr/Parser.ipp | 8 +++- src/lalr/ParserStateMachine.hpp | 6 ++- 13 files changed, 196 insertions(+), 75 deletions(-) create mode 100644 playground/lalr_playground.js create mode 100755 playground/lalr_playground.wasm diff --git a/playground/lalr_playground.cpp b/playground/lalr_playground.cpp index 1c8bd71..f188ad9 100644 --- a/playground/lalr_playground.cpp +++ b/playground/lalr_playground.cpp @@ -26,37 +26,52 @@ typedef unsigned char mychar_t; struct C_MultLineCommentLexer { - static lalr::PositionIterator string_lexer( const lalr::PositionIterator& begin, + static lalr::PositionIterator string_lexer( const lalr::PositionIterator& begin, const lalr::PositionIterator& end, std::basic_string* lexeme, const void** /*symbol*/ ) - { - LALR_ASSERT( lexeme ); + { + LALR_ASSERT( lexeme ); - lexeme->clear(); - //printf("C_MultLineCommentLexer : %s\n", lexeme->c_str()); + lexeme->clear(); + //printf("C_MultLineCommentLexer : %s\n", lexeme->c_str()); - bool done = false; - lalr::PositionIterator i = begin; - while ( i != end && !done) - { - switch( *i ) - { - case '*': - ++i; - if(i != end && *i == '/') done = true; - continue; - break; - } - ++i; - } - if ( i != end ) - { - LALR_ASSERT( *i == '/' ); - ++i; - } - return i; - } + bool done = false; + int nested = 0; + lalr::PositionIterator i = begin; + while ( i != end && !done) + { + switch( *i ) + { + case '*': + ++i; + if(i != end && *i == '/') + { + if(nested == 0) done = true; + else --nested; + } + continue; + break; + case '/': + ++i; + if(i != end && *i == '*') + { + ++nested; + ++i; + continue; + } + break; + + } + ++i; + } + if ( i != end ) + { + LALR_ASSERT( *i == '/' && nested == 0); + ++i; + } + return i; + } }; @@ -193,7 +208,7 @@ static void print_parsetree( const ParseTreeUserData& ast, int level ) } } -extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLexer, int generate_ebnf, int generate_yacc, int generate_parsetree) +extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLexer, int generate_ebnf, int generate_yacc, int generate_yacc_html, int generate_parsetree) { int err = 0; // currently, zero is always returned; result codes for each part // are sent to JS via set_result() @@ -216,7 +231,7 @@ extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLe lalr::GrammarCompiler compiler; lalr::ErrorPolicy error_policy; - int errors = compiler.compile( grammar, grammar + strlen(grammar), &error_policy, generate_ebnf, generate_yacc); + int errors = compiler.compile( grammar, grammar + strlen(grammar), &error_policy, generate_ebnf, generate_yacc, generate_yacc_html); if (errors != 0) { fprintf(stderr, "Error compiling grammar. " @@ -225,7 +240,7 @@ extern "C" int parse(const char *grammar, const unsigned char *input, int dumpLe goto done; } else { - if(generate_ebnf || generate_yacc) { + if(generate_ebnf || generate_yacc || generate_yacc_html) { err = -3; parse_result = 0; goto done; diff --git a/playground/lalr_playground.js b/playground/lalr_playground.js new file mode 100644 index 0000000..862acb8 --- /dev/null +++ b/playground/lalr_playground.js @@ -0,0 +1 @@ +var Module=typeof Module!="undefined"?Module:{};var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");if(ENVIRONMENT_IS_WORKER){scriptDirectory=nodePath.dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}process.on("uncaughtException",ex=>{if(ex!=="unwind"&&!(ex instanceof ExitStatus)&&!(ex.context instanceof ExitStatus)){throw ex}});var nodeMajor=process.versions.node.split(".")[0];if(nodeMajor<15){process.on("unhandledRejection",reason=>{throw reason})}quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};Module["inspect"]=()=>"[Emscripten Module object]"}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="lalr_playground.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}catch(err){abort(err)}}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(binaryFile)){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()}).catch(()=>getBinary(binaryFile))}else{if(readAsync){return new Promise((resolve,reject)=>{readAsync(binaryFile,response=>resolve(new Uint8Array(response)),reject)})}}}return Promise.resolve().then(()=>getBinary(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>{return WebAssembly.instantiate(binary,imports)}).then(instance=>{return instance}).then(receiver,reason=>{err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}else{return instantiateArrayBuffer(binaryFile,imports,callback)}}function createWasm(){var info={"env":wasmImports,"wasi_snapshot_preview1":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["memory"];updateMemoryViews();wasmTable=Module["asm"]["__indirect_function_table"];addOnInit(Module["asm"]["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return exports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}function switch_output(which){output=UTF8ToString(which)}function set_result(which,value){result_name=UTF8ToString(which);result[result_name]=value}function showDiffTime(title){const now=(new Date).getTime();const diff_time=now-parse_start_time;outputs.parse_time+=UTF8ToString(title)+" -> Time taken : "+diff_time+"ms
    \n";parse_start_time=now}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){callbacks.shift()(Module)}}var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heapOrArray,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function ___assert_fail(condition,filename,line,func){abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast}function _abort(){abort("")}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function getHeapMax(){return 2147483648}function emscripten_realloc_buffer(size){var b=wasmMemory.buffer;var pages=size-b.byteLength+65535>>>16;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret}};function _fd_close(fd){return 52}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){return 70}var printCharBuffers=[null,[],[]];function printChar(stream,curr){var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0}function getCFunc(ident){var func=Module["_"+ident];return func}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function stringToUTF8OnStack(str){var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},"array":arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;itype==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return function(){return ccall(ident,returnType,argTypes,arguments,opts)}}var wasmImports={"__assert_fail":___assert_fail,"__cxa_throw":___cxa_throw,"abort":_abort,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_resize_heap":_emscripten_resize_heap,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"set_result":set_result,"showDiffTime":showDiffTime,"switch_output":switch_output};var asm=createWasm();var ___wasm_call_ctors=function(){return(___wasm_call_ctors=Module["asm"]["__wasm_call_ctors"]).apply(null,arguments)};var _parse=Module["_parse"]=function(){return(_parse=Module["_parse"]=Module["asm"]["parse"]).apply(null,arguments)};var ___errno_location=function(){return(___errno_location=Module["asm"]["__errno_location"]).apply(null,arguments)};var stackSave=function(){return(stackSave=Module["asm"]["stackSave"]).apply(null,arguments)};var stackRestore=function(){return(stackRestore=Module["asm"]["stackRestore"]).apply(null,arguments)};var stackAlloc=function(){return(stackAlloc=Module["asm"]["stackAlloc"]).apply(null,arguments)};var ___cxa_increment_exception_refcount=function(){return(___cxa_increment_exception_refcount=Module["asm"]["__cxa_increment_exception_refcount"]).apply(null,arguments)};var ___cxa_is_pointer_type=function(){return(___cxa_is_pointer_type=Module["asm"]["__cxa_is_pointer_type"]).apply(null,arguments)};var dynCall_jiji=Module["dynCall_jiji"]=function(){return(dynCall_jiji=Module["dynCall_jiji"]=Module["asm"]["dynCall_jiji"]).apply(null,arguments)};var ___start_em_js=Module["___start_em_js"]=15252;var ___stop_em_js=Module["___stop_em_js"]=15628;Module["ccall"]=ccall;Module["cwrap"]=cwrap;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); diff --git a/playground/lalr_playground.wasm b/playground/lalr_playground.wasm new file mode 100755 index 0000000000000000000000000000000000000000..d5c5d9860f5db94ef3a91034396cb871e3a7ac8f GIT binary patch literal 161193 zcmeFa3%q4lUFW$U=XLKnx9TLRBsZy&+V@aGAyp7G6if_KD?=&?Nk~3D&NSM5rV^4u za&JgdkA#OdRbW7+ZJSo?#`e+J&^<~Un^9B*97+XS9*$9YDX;JpMeP^^W-!Qnf4~3Q z=bU@1Di5T!oe81t*?aA^*W>^G|JQ%5U0i$k1!Ykb<&TwTUQ-?|uBndlr#xC7y{0~@ zOa0}h#}EJWb8b6v)6IoN(N^GD6mrq`Q@>sxed*EirSTe13jXzuevh7WRejIV@_VkS zsB!d~L4Jpx+SiNf2dZIx;HKM__V2&;@Zkf8j_iNlwKv>Y^i?+8zyG=yUAzCt^AFwp z!lHJq!!Nwy$aT-(fAg(JZn^bHQK)S3@PQ-y4;?ss>y1Z>QU#;K&%gPF&$!`v&-?Zp zUT`4loO$2{hp#(y!!1V++_e7%2VQX9Eic~x+#9~DsLy)gwTExmfB2?rZ{eLI`)@gP z;I*SqDQC`%qxMYk$wr0RBxqU!dj#s&0H_B(aa>la18s_R~l z8bz-h4a;FUptY(V&_FRPi<(>h^~$K4_o(=Bf)zw=<*bj+W`JSH7$>GEBb%zeT;J{5s z_8)lBbq8*7ONS0T@4B0Bz3E8tx$?|h>+t?tZoc8BBL@!cKl0*R4itY|j;??4P5-lo zyL!Xw4aM!%!oLQZsT_XCd&~Egk2>%B${#3SQ$Ff{+x}1AR&IaP_Lr3}*U!q1M{WP* z@<+?j_B+a7Dc@2)YWx3L{sMQuSiZUZCGLK%{C+?C`SQP%Z!dqXd`Ee_{PlAC@06eA z;b`>7<@P@*xBqE*e|cZ|#d7~X4EB~UryWIZO za`BaaJ@|527v)g@zN0LUHbqnHtS+6Dsa$KyLwl-Abzg8lIM~_C(=s)b7U}5bVN+aG zJf-TyE4wD;o@$#a?5VcsNAI1tx~Ce0%VT9(9es3>#%q&mN6}PGc|ozc+FQ}!&T2fV zJ4c(k+Z5xarOG8Vy|dafsrM~;I9Jo_SIdLGYwA?e>XxQfBgLqsZd0YrtI0j?IIRPa zFX6pvcd_~0A&Gpe7q_Ob7?>>0RQaRKNG&JCIr(a-<={50cm0mqxL>C&kW?yLF)zJNy<4w##-OajG z`%G^uwF5}*qB^mQazhtj&0PSBfQ`GT#+%#$gFn|D6*N2?9_y6#QATyFb5&rrsm35d zcx|fHm0ELa%EPHXcyR}aFi~GM#Y!cpSCqEb6xDl$*4>3V21MoRihx?KPAa{$FQ zwnVqIRHyGbIO(M01qGCM(%#ic_wuD8+F+OgrgCT1*#mvi?#^nkry9i72-L;Z80w0v zEusk5Ti#PG$JI8`qsy8-RTEb`_EbCKYUiG6XI$;tQ|*eY^Y&Ed#nt(Hs`KOOse7uY z#?^&;stcLf-Zjr`FQnXbuhfiq+_`G0TsQhMbpiq%AkcI)a{;YRoy+FHru(%?=kmFt z4UjZUA#}kH=vEgLRb15<6p+aJUfR*r^l@r@G&StOsEgroBsJ9D(D)o1RdzqX=iULR%*?zT44cmIwIzI=8RuNM_Gl_9WEdDK z##<&u!(D#rfzo^-mKdMz;kGx!NeSPc+ensNvXz=k1#JaGr^PvzE;jHRqQ?Bj%x3(S z7U8$yOAK0|B-tqrU@(Bdkl8#0OyZIJs5IjQiRcMD6VxNgTc@Lkf#J(ue*0kUU^>R{ zi`1H$sCXYnGi4OUDf3$!_88`ui{U-!Su8b%P`P)@OW;|p(x#-lI2G;`69Q#XmVbb5 zs`KMIRnv<7X~mivooV@k%M*>PF;Or*5n&<}J?0yw7eFo;?5vsZB@*1Fjbe~c$$Im!^2JyoSsR{mW)W&v%mpSU6pgz*)|0+}mqc7J80(A z|Iy#Q<(07BYrgCO^wOB3p@yK}%eEqO>)R&fZ4-&|EYpu3PUS)P3Yw^oKu>S~a}-E1mQ+9`6bW1_&jO>f4S? zy3&n;HT54CrD+Cbt40zIO1303LW&vO< ztQ~xQs*a?0-XBOo7k7+oR#L{>7Sa!s)%|J9dI>a8m!NCP@s z5gvtww`KkE%3?^`(WH9`6MKV)f%FxWnWKh}NM`t>O}vn{KsKTgcS?DeX5Sb*f&*11I#{h;Vow)#c z4^EF&@bI~5JC|5aecnEo%g4~f;I{9Y6l=GM#EVoOSxeuxI-CsVA(?fR$T<}&YV8~b zRNl5m%Y(H2lC4LikpsFdAbU-D6(g*{aBos-Ou(~VDMq#Roq*qKdLp~@4Ywg{;3JIO zeOrNfZ!3LN3Pq^83HS3~E8&)2@XHNED#1Hs$3@VgM6~NIMnd zvqAdNeWHbxo~C3_$sUA4!Fj88dvInt!;An%)o*%h8cex{ zPd7e0s;lD_D44oTkQrUFg!d+x^N&taN1`827@sYY;;+b?p5VOv(^OaLj`1NHI%(%B zw?j=VPfk-aCV$&4Hif8-Ynuc@Os2DW9K;L}>x`i@>8|bz?->>a`kGaU?+K)#p0C_0 zF+-WvjY%#4oh1bwRZ-%Cis^l$P1cB=Au1sL{UZ!M2K^hoR4~JJ%?95dcX2gAAyGCAiu;ff)3PCTL0sdr?MctC67&ytPhx6C=9c;GsVA zQ}wHuGj%VEsgH?n)^3(o}_=| zMzPWzE$XKl4O(b76-M0*%18@nrw+cU_Ub=CXp|L*R-sP#DhUU`I=c(az~I9SCvUJ*iivaN(0Y!`#7 z1((c3K}s4s%sOBYvN~RpVdIxDY+4m_!b=Po$)Sb-Vbc>K%Ux0k2Q?<`-{B87lBPL$p_H4Ai+)PkaGld^yaKRtF1gO3$1x2~oqLc{>JWIP!C-9#X%!(cx8mEv&~5xX(hke9CqD&>A4 zKlUWzpyhk2EMwc7{rhST+e)4%vX5d$EjLme*;SOz#zQB)6hA@sKcJGA6q7;ZYj#ye zDm0o+Z29WhbAk7%AOpLa8rXDU13N-~Ab$v~nIt%yp&EG0z&6IwrrR|%+k~Q@Dm{jO zCou`78A=i1wx(1_Q*Ki>wiO1e_O=FSmvI$GCOr=dqf~OngEFm&UFdmPc1ML7318TZ zEW(ULsGuuWy1=k2v)R^UWuc9kC@W27p+rwtHY3QJKzUft0xZlRs6_`FZT2Wkvh+uL z$dM@ZVDMB$eR5wJlYqh<9Ga~e*p6tC>5@zIvCt3w>7P0kTRx~gLvvF{wLlQ{EenSY zZc9;_Z?;Y97Lsx#VFDPIu>=VaQw4|_xHHF+sL?_ir!CC_jK>>WS95(kG*z>pX$4aX ztD3ajbJ|=slW!5Tf_Ob3WRxG^(TP%f{0Od{6`&>&6GS?dVvtl8NZ=#nj+~J20_EM$ zktmuF5-p}A3hqn|r7cgBs8A;7Sj`Fz_6YSOY{=l-zEY|q+!m2&0f~m!Qij)pEorYs zqxHMnnof{t*#dSwiNa>`pu;g0i6T%kiAosLNK2vxBueup(K1LBS`mp>kZ3g}(Ly9z zibVATiBb#t&LoPtk7aLZXK9~1&}j37HGKgjlc-CHu?Q%gAW@I01&aJZg%Qw*(9j@A ziC*SONhFG-5x~}w5?;B(6B9&~8lWlB(Li+6J%Nspxy#vIF&%*tI6spMJ=%p90C}J# z4HFn+D${1+3aKV0fe3&v2$kS2tbVgTWX@RM`7r`GA`T%1p-QYLv-DKEwN$o25K8S4 znVC`<;5S0&1R*4((J4B`Pj=4qLl2qCAjBz^l~5U$(22gW1fi!(;QXY55CGHHk%|2S zF)nECXY!(F0jnji@{|%V2Z^%;B=jmZ0(qGSLjrbM^0EZ%gan-HK*P*4( z8dZ>&$JBbP(#j?;FWxK$dEtbfKwb(e38|V@HzXBeX&U{4xE4)Ziz2Q{#1&O7q`J+b zh%201(@G{T>L8>j&%}k)590EJYD!$7Zar}kwcSWuS~&^YCaykxpCpJS z3Y&(onowsC5X54L3JCBs0wQK$111bUVLYN&qGzc-!FPzes+G5<7=CeB_O;AF#DZIb zyRx$h0ZVeo#G4eWD_u{$JV*`Me*jS!b`6;h;mO200TJ(_+FP}O0h~W3xz0xH>rL5+ z{LEsPGaIoVHX;sV7RMo@86c3p6{BZTw!SrN zq;K1W5bd>j9;fCL3tTiuPgAkag{eG!&CLk%lPGHroj_)Drx3 z!0=b#n9#zMN3>@BK*kyi4^-G_tT}4aY%tcWI7~NLf3}JP;(8dinpN*qi_UDdPH;f$ zP{`3)XRTrUTb;5BCKg1n!)3CbPHL@*P89raYKbB{6f_9EoW(1*iL@#uoJ$fh9uV$3zM z6{43DZqW&!ubgOsI?>WALPH3i5RBkgCa;ZQimUNyLT=a_RV%~W9mx&( zEh##JrvsFXwhqW z`xosL;!!?uGE6$|im_&Xd;8KcUuYSfB9Bq}QW1LG3+Ux?6M5@NWSq`@p>5K0vi1u!dJRV5((ZfIK+0+Rp zkG~B{Q&;i~MiUGuN%RF1Jt+!9A#SM|tqkg@h0nq;CwF+Lvlf`E7I4KE}#jQxZ zw&7-JQ&m*uaQqmV5WGO(dU0!0HpB5_CyQE6E>;$?P@!p_;^h$amN$f%IA|6WEmyoT zE?IOa#ye%JFrGoWTfQh^RYp8Wi{it6Gq^zAtSm|p4btXAVxA%IEb@#rCjR##q}D)# z5Nde=lA?PCG#H;oG%-0Xs4t&lN8_Ju@v|j^-^a0~c^krnsKVgVe@Sk@+lJqpmVV4Fr&=rdkqbk3kD1ZP}QNQr=E z(G2amLSHM;mw-RgMD{K9*EPw+bCXPeFn*l-ReJ<(nw}AjDAT<43*oBgd#&U<@1DTT$lEVElyi>&^H{6V@y4vDhVuc@NIT zxGaXRE2U%Pc_5y1j@u!L{1UJLJNTPF*xJY(CM{&8toAapa=fe+ zf%M^5YIu`^R*TaXG>qYRAb1ZC@tP)Z%lL`%Va+ip1ZU(C7r%O%E_Q0{o$(XKzgq(RkKUc3e|LLv{4deU zLc^nQ`NmJ66=CW27E5nvv9w9Ezq42!FYE8{9BwrmrXI8F=!anpALm)8_y1+|Bzp&L z)QZmd{{|oAp)sXK@VP`u8bu5&SC?$7($ea9Ct9Bd6f?Ho^ACMO^&{(VFgHHU8gckr zr5$wP5FOzy5ifDD;JO^Q^Urb= zHZ)8dP1BP^V&NquQcn^|Tp)S7*mTC<;-2s-sZVHRZ88*PpeU9ntkp0G`Kk70;eOR1 zns2MoPsv7DV-*0Ywjin2Z>3rX4kXMSqK(it&tZB54^pi=m1=#Y+VmBq!c3|yuuu^( zEZ(y~>nn7+l)1>iOMlLNjXM4+i? z4va%Tu=8JCD6#n4-SpsWZ$X=At6&#O3lfk z)eI@r0vs$E3pp6AnCbQ9Tk+OgmE+9m7N4?erz*#*nKJ1hD-~-28!;#`2ULi;ft=}# zFdZ|Ih9N6h3QygvZHNF6!Di%Cw48|vC}Jlrf_a(_tNb*n#6af+*~T`yDonfLSBL zM*!~v7|X%|TZXnGmqp`#K0iSIdVV0tYZ^n2DMM-hcDI!250~jbn9^Fx`b4MfWy-1y zi$IJhYv&7OsW80s$M5^GZ&5nI=lB&YL{fSTBv{J=%`l`{{ue*@zH_eHIth-~TUuT3 zr=2%uGp2_zvhzl9JxC`LECi{4#A&9s8bRBc8j*e*QgHC1&k#FdQo?Z;6k8?U`V@sh zxq#rz1RLG(NRmL7keEXzCd*kX7%N^>XK13H@i!3s4EwSjpG7PSB^uuj`ravYhj$y&B!m+`9WRF}+Q!x3DFPA=EXNw0I@T>qas$^JH`&_kg>2WuZEf9cs*6-t*0~<+ z;4Pzl2kOCTk61IUPX44W&ri~lq##WW9&JY zsh5`4b`?b^!(Lieh*jle-?ZFJkh3KoS#k6hedkWao|I0R?OwJbO$lu3eTeZYdVzfa z>(wEVpWz@b7SV+h`O;nf5tzg~x1+wZIzQO-sq)=}Cq+awqq$cXl``I?rn@cmbSp%2 z&`T9zQwS-OO*a!w4=;r91T&wJh=V5D7$8OB7%z_OH?aN^RN@|Y&?D+V8&)dlgLHq# zkj~57NUmWdPo_j7i&4=Q%#G()jK2|TX3o!0Omhvhk~o25J&j7WZ^pK>i*`6mUcp&C zyJFIj?Z`C}nfAutEKPF-7}#ArO{>2fx*=#tbtL}<#gpTGWJj~4O%RAjy3=f)#uy>B zWkAc1%>X|Z!Gr`{wgluMfR(j`1e9^wDx9lmu$W0eCdG5uihn4Y^5hb5ab5!Ad6A4E z6676AK&`5xXr!%_MGDb!Pv08RyaWvGqM=CwLgBLet;f;Qk|u2F5b&fY5P?6qOUm_S zRr=e3mF;_}zk`@QYGs5^b=$r78NEz%p~oew=t_g^T|D|WbzUpzm3=8W`x zRr;^t*JPjO=QfuM%DKLabgd5YD$#pzB$F({Kqkm_XO({TcL8;}vsxVs6T*|=FspLB zO82L1;kBp$Kr1RBY^9y{ zkwdPR^dDdzSoQIqUcd^)d7=j;(LiX_CQr#B0d!Pb4sBnoyKUHm)g|~uGT|@_6i(AC zWVmTPzzgjnorIcp09<2N%gAnUrTL-|ryzM#l|JM7zDe`-3|C0((GUqbbVv$BlgUP^ z(}#B&1@ATro|Zmo45an9o*zAuh^n^67~6!Aij^KjWjGl+jA92~m@;mA&)k{~9o`56 zLquP}OCJFA3CD{!>y?T&q>kJ)yhqbU0}mra3c>*$?aHaE$cKfk^e>u6ZY!AlKUQx*F3=TC&S`YA`S-R&QSgH%I<^f5Elx&M<81Z|m zyUX+k#O6?~_$QkcGj#E>Dt*|+$JBuo>Pe9D>MH&6X}tPs)fuK{JZ1#aqqcWr`Z*?) ze&Gp1&)qG0pbA6pTm24#!))DShm7(&f#ZL=)AJ2jE)%T+maL@$%{tSkamXquK`kb# zz}Cch?Te!6#h~H%3xF5)LF>gO|6Na=+Ey>J#s8Efvp1T6fZC??mOiu1p^@;9h5VF4#ApHcp%M#k$*u?H%l)U)X~f zk@^++JF@1sYqJLk^guO~C7`P~4grjX%p8+?cTuD#>?5=y!!D2Gt}?yhaopUcVSv3D z-TP%ldYpHb=|AJ$q&xK-C|eZ8qqoSE$5wcA{(Tb}n0Jaq-sCBX7NX)ibA{t&dWS0< zkIqg4p(~VB+h@sg1yjY$V%2v$K(`3 zTP$HU8mcO|UVpC1k_O(T!wG+!p%H z#9GvV+OenFn||05Y3~~HIUdh*&$`i~!snzAq&ChV8Vf>}K@>I_LX8S7fi|FoZIv{sU=V9zeh^gd+BrT$RFm%ILd1MmMM41&LPmYOl~F%bJ4_?V!|JSl zSaFt6Ekwt}wO70;r@gbZ$IARbbrT^WJmW~SW3K5x|MMGVCXVoNu;5g2i_&(Yu0*`p z09ij*PYOxOD5#H4HTUs3#-rBe*}~>+3Tx^9?HZGGIx}hlQ`XFLMa$+lqUu_ynksg{tZk~wg4LD}R2mkt3T!H# z1m(sQa?`Tiu+{99tCs;c1}RdNZmADw*y*>*W)shUCD$cU1Nt#ip%<7)hEt|ymAa4=jt;nL5V!nG9IY-b7;wNZip2g;b1rej1X zkW5%M`*d6}55_9$^bOOXlkw992(=C&#MV;v&7k*Uq&!t7=Ed(?Epx`XW zcKjjg!8HhWKO>OL9BRX^9RCqBDu%C}g#ipb{UI)GFQ1?W?VThD5RVZ%N954+pJE<$ z%0Ym5Lje-}qZ=nR&bf4_+<)+&0qZL}%Uns_V$4IdWQ(ZESedjrp|%smOgREYcD}Eg zyfIrYa=f~OK1}w0ZyPi1M&t?~zVEpOIiedPhQ;XcDd?S_Qw~ddIS)%deE9lk)o{as zr5H_(;KN7V2OnS^FJlvDA3lOsqTL!~MUpiAu7EzN25}B%k?l{9S;mE2V>0j8A^_=d zXFc!3*E1g;wxtEM8VccL!LsPkJ(0*lyW&Qc3NTcI8q^hoVQ`Gm8@uYgLN0J?hf=K{ z3IX$3IH8&ig~a#RMDCWAnhGaM4!O$@ZDzx2wYS=68A!&%B%hYBmSmzBZQq^`U0dfdyWMf%Rd}_E!aDrq8Ev7A*G}M zlB)1xd8>Z+ZAFSGW`GMHCeEY-jT3WH{F=y;#M`9nV-R>zvM)NITvjWP!G2Bln8v2yJVC^$pd=)SS#vz%+%_IU>NE?~T z3R6=$YPl2`Y2`uT$NRSvt5MRdy;X<#3;LUHu!2NU2&UA2pbUaF${4`D$zUtwG({T0 z3{Vf!SZ~mx%mSnoYH89}sz@^s(x|k8G6nP~Tj^bo6NPB35kv!93ao*ejH!$w2Qg5D z!W6z%0FCu-vioQzV`}!6uZ$^Q8B@M8rhMh|DtzVhDtzVhDtr}UQJ4bN`~bpC9$sM; zrf6OqlUW_~fjmV>>cA8UhcX*b5a2Sy7Dm&Q5kNKoGs|%Ye2l(Fxa}Vaw-i5V*$Y2$h;r zbeI{gg|?HW8G^o&pchXdXD~z{`EOv8_ez!$m`Yi&3pUkEMu`0F?AsZCR5@wmkEt~*E4-BPC-U`Ze3!1O@rMO*j|D)fwhUn>$&W0Bpc%YuQi zbY!OHPOpoQpb;iSf%u^dvuP_UiMju>E*CQ;4QS0w1V!pi+t^{wwF{>b#+=ke7eog` zZpbk0vIYrBjW0X#eWp=C0NC4MXtj1Y;J8vsr9|#}TwXjxT0<`hgN%PZWvoU6ttdd| zlA7>5FhryS7=>36>zL|ncjo%g#Hu9c^~r2g6h(ox&Y_dn_x27an!!W4KCR0}9)`K6 z{XuP)l*ihD`7n2B$AB?~c8e|z#=K&|9uk57GFFQuWdZ+~)`2evg6P5JJYX@|$lyGy zpXh^*Oll5_31!%~B`3g4Msi6Mwp26INY|o}q9uq}rC0?}Fn-ya5O`lgtrcm?XgKLJ^wr0~9cdpkg zYCo_D-x@{IqB??I+AN^AL1&zfVt}B_FXzxLpxV7^t4AuWMdBQ3q;jlklN&q12S$Iy z3BZbM3E3~0=d_m1^Ta7t<@$O~){#=cZ17OMwC^jOW)o%X56o9Y{PLC8{9TU~ec9#O zkv%}0GBZgpJPyGgU4Q|Ry%KM-BU2QENBJhKrgEYL|Ml19lMI>0 znZQEwqz51?O&+<%Yyi=EAUm^zys4PAI6}t^;2HwANa#A4`gq;z-_5Nk;Un5pidtML zb1JT!O6A^2!pdb@kBz6ws=zgw`a??|JcdWLS44^e;bJ741BBbj;z+Q*WOCS^pkA)A z94_oisEGDtr{w9?!e-sht4yQthgH=Tb2XSJV8oO@onu zme9YbtSVARKq;a*n?8h^L?$$+HnoWvYSq$nn=tV)sa?lbV8Cla^j|+wrW@o9HIi=2 z>;`6pz^U>aDiKd*d=o-5rrSIJ3$0U zx$_TX`Ece3*k=$OZDX@$nQKVAnEv`{>0h6bPD}sx-Gx_P|HZfIemuS30u923^e_jO zh;q@B9y zD6D-LBBN7~83+n)Zh-olgX8BIP*V9p32GdzK~6RN9I1<0V{Y4?YKJ4G z4bwAp=1O`7KWc)mEFc*He8d|X0z-C;K)>*l27?rH7uF`!5H->OFF2FrB=ajB^7i~h zh1E(};YLGrifzr*Ae?qO4=^=g0qj*(THPLjAg}lj=FPfU8Q=n|dSUbre`?IugYx=q zZXMLu`_zwt$PEfdP!ajA%M89kyww@=Ba{9U73iy=11Ld;S^310aUlnZw=x}F9E>|z zV7e24$R&e6CBdJ$RP&}_gK8;FoGKBXv+p${6ReheY!wHRz6+0b6OZVOqvb#r6`S>KvIC;y5Sp&>cRtLljYH zoaR28psEgYQsh+~+Qjg@9H3Dpb6?Vdf@EF%(sH`JOm~>o(ieZTNUz+IzA623-2a!j ze|&rY)(iD`SHAtZiZnyd3Gk%XJV|W(D^>c^ir7|=L9FLF2Td?)SpilD)n0@>!$EZb zHW9dBgX{q2ln8FT{GB>hZy+xo|SP@sV^Fg!N zo-f>Hhqy_w;Ae3^n^mwC{=!Xl%GB=zkEqjuoghI%0+|fG3kumdYG<8Dz1jkB%#TFs z#*}qS9nOS8T4JhTq*Y<@%3X^M1QIwz;lk*Zdk*WYGkRq$6Nc2S#EZ~NdaMv)uUlJgoX3t`u`%hK%FZ|xSS+I*Ut-b`0<+_dnFl1) zIn9M2MZm-o9TEh0UeBaJ!s=oCUg4&akh*>qE}E9*WrshHBdoMhAxkxtVkIE%z!B@DZo{)AFoKm2N-rhPM#?BV=@ zV&)X{MafvfM^xX&c=>5;m*!HF39J8D zLVm~|Di~KX#SSfbQ?Vf1deOB|glOcyNKR`T}l`4*?1~ZUHPDy^%y9$|Azrz~$xiW=X zM=|}^<9EyKRY$|3GF-V9Q zN)u(nt}|Nxn_cPGwxlPgpFPLHf%p1$Prhvl+jQ{S-?NM^hEFyXEBRWK<_>m-iWCFQ z3OQB}Ehs>a$5#)pT^GOh<`6yFVT)&nE(=? z`A!f?bA$@?!r`H`vlp>qP&%|-b;Pi8DcMyUUmUVDQn+Qb04`zdSFk+%6!@LuO`WnRYB;hA-HWNiw}NngmLx+NyvxxaD#wr|ro65g z=vY5;9G03C6Pwiy6)6_fE_+Zz-3U-RI#qDM;+90n(~v3g1G^-*7l4K*_e}!9y2&x4 zrsK)A69ei>s$`U!ARrE4&HtTF^f4vhLh3!h{|Y_pVo!U@LX8h_h8y!B`#fRo+v`xo z8zCtjf%tU?l>E2Z5PDcjc?gEcYzSD#ZB=Mb)qtl)O?5#EDK4YcU!Uk4A3ulHwsn9Z zV!}roL;^*pQ<8KXGZD~1*+!Jlij8t1M$FTqyrs2uD3@ALW1>W32t)x(=2H=EDe%XI zJR#GRp@J_fwJ{bYyE}?JUM;Dz+-Bnf-jFS)?tB16(pFjcwea3Dx$mFG~X zAVbJQ&Hz?HmoGL=%8WS)1bLJ|fR7X~3Y0815b3nFP+GDg43;WF_-Zug%aY)sd|8tj zodL5o*%)RQ=icIDsy2gA;%s+Uv6(140!D+7iqbyS9Z*H&9gMk3%|8CH(9^x_(D3Ka zoUWEGsG2m)!}xFN0x}(lDQ8x*Qi!rab!jF!4@Ls!vp$+agw8YJF>{=)qADs%`lWl? ziW2+}@RT*v6Q2IJ>AN^?Cp^t9+xhlRXJ|-p135K4>)O<#oJ4$aFw&|@aYraiI1B(= zSuQB##2aF6e#hS#|K=betpX7G>4Wd_`JF(Cy&u|wwl>kCnbj8u zEli^zyqw(_Tiaf>Vo1o09Oz(39Or~YlN$rL?I<$vEn1YpL6ZLhkIH|6%Fw=sNg;3$ z?@^Q*p;4sAhK`knwuWzNgc>ib2_dV)DbCT~0}(#Y6pU^9*?LkVlS<7XI$7N3N8UiC zfT5CPHt{9GBCLy#7W?GMpfA!#i%U3BR6;ovP1Yq9TkuJAi)ag=mW{<|#{Ue|0C$EU z`pNuf8>_X`ZN6#9v>6{On@+CEU6{}at$1SUTHkBwO(&>uj#Y+qwxE|X zpb;l5x0mVDJ6J4yHltLa8;$X31|G7k@!wM084KdY9*n;laiK~kQcdX%XO(AZ@Ko> zHImH^v>{n9s4E_Mck`A2siJ_7lq|RA-&}q z(Mu+_-L&jS4`0Y|6>)v{b0S_kj<+I z2a2a1LaYn}1bJKQ6-pj!mNaK|t9GIA*sQHdKMhMuYDEHspDaM+r!%W8K&FFH4X`jT zM5eKjux@}s2oc3X6jz-Ik#(^UC3j6-$C(guzgiGiEJS()9d0IiAR*!?r-vpXf;lfC zg0Pej!P1)(BH#`oV%ZL0bp|Lu(0G;JW*V2U|KEcoO}8wKij>}Yo*Zn4cO#cox z;Wu)a;Og3Vk0E87mZrzwfhDWz^UYLl24jvT_DyaJVGI%EJ;?4>ysHjicYe%BC=*>@ zJy|?-G04<036L)5-#~YPaJ&yFu}THAISJjJt}(8sJ2tJ&=nfUR*wUTUC3KgC0Z9n7 zJO1YNG`GGplfEV|I$VDcfWCK#420l=+Vj2LlfztiA8!?gd#m;&m8GN2r}F_ zFkXh6mO795P@cDxIT-L@X8^RJjr5B1wDb96Y@*#B5fGm*@bT$=oG z>U@D$R{4B^wBfvg^cOzU;6GOBuG8oG{7=*Scl=Kp)BiEOf0*YP{DyW$hV#@9dlhJX zr}yJ#eQD}v*+CZQN6?ob2(plsER8wA9N@Evp)$SD4e-}gQTAvDl}XL81o_k|lFep; z5QR~Y)Ee337%6u0%1XK=AMq?tlhz>vXKB!fN@NqjPOVMQJ4g$adRGJ-{}QFe=|^bE z>COm=5kykNU64#CF$wY%ZDebT=z2Q{?F3_fbR?4ip3n2ca*)$EGYO!#zJL-Yff`{c#wI}@lOVa$dZU2j8x$zwWhGgu4H*RYq4USjPK6@${UGRS`0kS3 zlz~I#dsgYc>9|3LDL2T8v1FLZeJa!Ec!GDt2kJDZBhvL;;hD-6a~%?;W=X#Qwi~St zm7wjNsX$gr4$0I}8n$gmgyAGkn80ykxP3sbXxCsZs&JC0%wzTfhz68v%MYzN2RHIe z!=HNXo^n}Jxr?vt;LKw|>|lXAV%|`a)k`{`g_T^SAJXykvkNS5lAhJ^YIR;D(gPNL zl*!$0<%_UpttVKzs@KpBKT=uXEqkVXlz4n?le1@?B80Vbr1u- z{MC*G3L;oXJZBCx6D^23SdKEu*~|mfbkN&X=<};OKbS_9|JhBy@$Q1G?d#V8Sc$$H z0369tk?AoHV6UdP0PX~U+q6lodM(RrnL{3Y$i_lUm#da^%#BkFIZ!3NUuUEmzhf+? zT4b7!fI>!yylS00$~Q?bdL==SYn}q7+3muD3a3M1vk1u&@At^^UjMM6B^W0)Y}ze)fE(76|S5T^v8? z7~&QruunFF1yvqDj|b!LGGz3JJSiFH&EX}lA~!})@r~4+#|vcgAb7bj(4siV99p#P=E2ai_u-&ruh8NX zFrEYU0w92E%mTkzxnoA|qa#DH^tZyh_|HZhKsW{1`T@4Z43JZTODp?S?z@jSYSs4A$TH3Yy;`Z(B4RUcFLYDDI@~f zK&rWDj#SB<`tO27@zw@JB1aw!m02;&RLz{ULJYUkYCThAX*ET`*GpQ>amBRlEUg|v z@52+Fdmjcp_K2MjOtf~#POvOyr6+8GW;4`^M)%f65WkjKW59F>%1|%FXbBanme+pu zde#Ie7D=%+{@uvG7lbS$*D6bLJ|7ZAEqkDTB*{0tW(M0S)`LfP@f#yM)nC;jmsawM zKg(XBRbZvCrB_KL;gUf)z8R*(O2h=jkl_zmH%eHN+V$V@EgX5gbAk!P+$@Js z6f0YBbr=-#h@B6sljW6j(37K;Gn;DVtfpQ;0^lV9!GlKOoInPIQouNT3 zHfQM7)0scD$SWkXlO&`q=)XA|j@ptD-V&p!VM6hPLBazrMoH-_Ao!*F8TiwqS_ka& zm;s*$VeoT4>kSfqblY@T{HXTQBY+@YA{&?PWa{yhY*vgT;&8hQZM0QH&Q~@W6zz{D zSZAeLy5mXd?laSUW%{Mfa%Gvj0${Qf>0Cnl!saw2t}Voa^d#xcU{)eF%rYhY@(vUg zlVSP088E!s;@usCESi%%(?DbG%@Ck&JJ@J~8EA{KlqD-+8UQMPegNmH7huVXLRdAi zouHbfu=0?^0RgFZ3I15EP;xAwaYYKAWigF7LG)COI6>5nkRYl?*pHPP!MbctS0jNM zND^oS`j*LfVldk)|R``v~E2`&uFU;N630h1Y|Bnnh;z!YxeP@fs$87ZZrmx%vs z0i1CzNtkR=f`W}8XqrO6*9^4(WzZ}t8b?f$A3@&*dQ3rKy3lKv!pRuG<3pJYaGi{x zo-@oQy%~ZSM9$l;FA;JeD4s&EoF@+%3$hEQL7moF4Mp-SU^|Z0O{SH-#ab zp~7j{)iQ`St&C}!o_9Fo)U3BT{7KWy!pc|@ACnvz1bIQuB5tjP3#xHipAxhbp|N-# z9}#sRS&zWpdL5wvE71!to_YeOV!n3br=kf@94bPx1x?^ndg6qcka3$cRm3bb0e$j8 z+(wqku-Vk;6v*ZbNVDIt3Cns(a!7NX5aftG5OIcNvswEjH%?aTiA>g(=Repq*>haN z2buv^;c$GbkQTEl$G1XDI_Z9VGr$}+XK8~rtACOcLqWvr|0H)hnb?U6b-O~jDX(Xq z#Zv+!ENY6Hur^qasHW+&>&_&X(=}a>P*RVA!dNfrPESA!IfV>B=lzI=w2sNWe%M5S zSYuf6)eET|#&;HtXqdC_NuXh+X;9eG)%b<+cYKRP$kJ{;70r({&XVA;WFZ;SmIrlP zO0Y$of)LwXur5kkAAInfR@IKjx0zzcFT~y<&K2U?I-ogQ)Nyumj){xBQB-~1oVBvt z3|G!+2R|F_nRI%la}D&#fbc^=)Q0vqsrSa(7}49AlUZctN}D!+7dC=9wN)9^#V!m0 z2BdA(kcqC2&sh3~w9OF@ti2t~33O=*&qiaMHnT&*wYIilh+KveatUbH1GZYKvA(u+ z@WGd09Pt&aXv{;}fi%b^ z_dgvC{>Zf8M}N~j{P46Oclkw{^e0_XG;#0r{v+S4CciMf|HIwsO=qR8>27ZnOS!>M zPM?$gAYax2Sg(Ipgsodqa`{&14?9P~;0S-T&7^SQB89xTlOPjMVwEbMEWq)Y0k$Qz zX+eS>;zZwAKUw@p+-rSYR!faE3JX$#22ziY>a6N=y2HMbDCF$2hjwHkDfy|ui5 zWCyy>N&;7XR_>Dpc^z&^3-I&YvCUc@AfRMKD?-)8_op$#g=PzA!`G3~Sv03f3Sg7494d6;#0|JX z*mU^eAqQlQ^s56EPLu4G-UXXTk7X_PI^wns12DfY$AGS^U@T(PlD5o9uC*ONBU0ve z2t@?QKlb~|MCRR@$tgI^o18q%c2yUl-hyX@u?0^WibZ3aG^eA4dRtLgC1bZB51sABs& zHVxSG8DY!Luat$yQlCIuH-;52Z1W35?TAv(Uf8A&iSbk~@C?bW4?TI&s^JCkq16Ki zJT>$0HL|VpdpuJRwp};d(JX0Hyo$CVB;g<%%O-RRlC+G1WtiPw*r8oRL1{q88ACZJ z0r;bcp1g)aP(u2^Yba{XXUjWiNW?&Dm$CtiIR0J&Bfu%9Tg)V!@lfp)?qG3A?#xOViI2D z?(1wGQ8^8Zp1m;o`T?4Fwk~>q{w$V)%ySE)ug8eOj@G(p2P;XKLyl-{CbUu9K^x=i zgeyERVzgLP$`cSL`$ie2dWRnwrLquVwvLa3dZ;f!HxON>Ojcff z1eKDpT;#bF+^7;?L)KnuNkm4;BUVZR0%VcZc^_15gWE^pNa>ZTfGI_axpNEw6N_Wm z+`V)kkNbSGCBLELT5IGP=O*dIvw`)S`A#BG^9xd)hXrl>ya$G&gmHXa8^W@em0_EY zSq&~kLc@$WS%x{-;w8Z@uV7Kzv`#O1g`6e>YcWaX--upt&(v^T3kYqSL>fgjIVfLb zFcxi53r52__k=guT3|FBoobruRNX*&pk5yv8osq3pLF0v5U1{nsY}fUN{9%V*miyh znO5jmHFL~VBg}|KV;a#X7eUafThDPBQoGbo#BD9n(GRs9e^ z(of?b7Qsp_f>pVKc=bGrv^d!|Dv0wPIX$|R3>?mTD_NTqju~KHo6MAsAT`A!1_^D+ zDJUh0cOZQn@f38l1&rw_xX0*3N#aId8Z^}3Nx7NXWan5fv_#1~G?DQF36{hTH83EG z3t4xxcGk~(9wgM!>@g00){ny>t&@(!UtpvDbR1Bb#0d)?P#oh3>J8EnGtG^or*WX7 zy@n@Zs6cm6mwvop%VgCOAQj%Zrg6_##M!pWbI&e+7kCSSYuBe?TJ)Rq)Kg{Z!D^sk z0b0Vf;0A%j3-c@I^TO+dm2>LObLf0sPrGf`92yB(q+|UFp3XhX>C!JhZ=Scd>9X$he-E&Ck4K&9<33m3%*QXA{@C?b^S9F*CbnUY_*vwK zZ6Ztju`18_ z#|3tTCn3{Ao2#kM(yLTO`&bU%Z1!;_B{AAG=oe*GR~_$5R1unVEsZZ>+kiy-?m|nh z@)$@jB8G{SN7_@$M|Gma1DL*)N;_})Rea)#^?>Oc!`z6L-PGFbU6z&m(YU&7`(ilb z^wNDA))rPD54NwzU<6S#0S5c!r z{#ecVPmlH&&FdXS3%3j${bYD+mI^&$z_HAo6}%sBgtuM-)?Hv-RhvRG`#+lA2L?XX-hV9^ zxbg3bfeSMR3|{O|%+)yzi0HMw$rymmcFI(Bm6KwC#%36}5Dd7nbr@(%Pl^FnA6jCV z_A|x6>o|C19R{dSrF^{S9$Hn}$F2+Ud5xO9b#n>h>2 zqH)%XJx-0R(8!z+Q*0cR-LZ{>qJ^)+pwMj^ls;S-((R5qy=NY?Z<*f5^W)R|!0hi# z@8kLVr}x3tpKb5oQI-9f^lNH4Y{az9>=S}bxc*7$;ewuW0>mTy#K{A~I*x{r+wp;S zLYb;p_`F)j^}=n58=q04XfS#}b>fkm(o>pQii8mb2#5`70SSesaEd}i%4gOta*>Dq zB|jQXh;A=eME*1e92u(0Ya=Uonr*1rXd>zu?;h_ioKobkyd|cf|4$SjV~Q%$2=J#p zJB0n^;x_uV2gTM?jbVJ4N%#!pH}}hN2H+y7rZfrVV zQThaq>6k-$2b$n%q1t1K9Qi{7^p-PoxI#Zd7b-(T<}1Dhsknky#5f7GjUlcuUjW}- z@mbkjuY$6k2!9b0(8tK*sl8;*7E)tQoQ%7Rsm9$Se?V& zp@i2|vMEZy0vX2L)Jwnrjm;uS-GG4)#iMJP_#&)Ev<~q zLIV(xR=QPxM;jP`YCu2ZP&!zn*$^ejhYW3&nK}KI`9faJuCne=J-SM(+nTSRRa5h29!AM%nR!GNTCJl|z2+W?c&T0d{ zT32OPh2rP%s>1K>=U1=+m7V}+xjoWaM1@E`n9yez@-Qz*aBv;q;FPYAi@K_t)6|t3 zfkIE+2oG~3gJ=W>(|a^0&O_8g794C5Yns1Nr4Pn(9&(8l$={vc|K3w||H@N76MNl9W6<;D`O~HIhFFH1ywI-)@zz1pqqIXU4MKe@phmHck z!qYw+!l_3nQ4GnM9ehri-W+Hl_QWgjqgv&&$1P%TPxHxuWRHo5c{$_4t3AZSc&`^{ z&=Nsx-}7pZhNuGBFjF)Pa*r+#|yOv;SR`Q1P?CZ(3FhCM0Bb;G2P ztD2N#z(3@im|)__N5QbW)HzoM)&Q)6F9FpmM;{%EA|mF3NYZh|Rwo4ju45s_d47b- zLq8x`q}PMoJx3nazWDB#DKL8nBo3Vch00gKBi=Q68`RN?|DnyeOvZ|b6HdG03q z7!^e98Iy?VMV!p;2ZWHVY9?JJ)*!R?`KQY3xdj?Tkx7PvKc#E&nC8J06kFGcS{;Ai z7Ac%x;xIc27f!v_5^c?4ArOSeWc8v{M>I+^!0yrKmIk)fP7$#uk&+of?n#IAL4&Rb zr1UOS>&QNRMLnJpFelJIf08!0`Dtt9Fi(-Bz^S9{YK}=Ji^eCEFwKfiI8VhJYmk{6 z7dJ@J)TlWBtp15TiL)T&9B6Vy6P;10f^)+eE~u3$=8+mGIBGGljM)wK;qH2 zz82(a0v*f3X0qmOkGHlI^F6uB*nd>IVyP$NKvnV( z*c4}}2|H`D61$29eSTN^;F;+M%jq%cpK`&!JavIm9c=$fLV-bD8>m^8`HWEN6XkIe!Ws5{J8BB7-aPt3lec2=q`C`PE!dL4`$w9*dvOr33*nQ=Yj5 ziSv5}k2=pf81ObppTg)cGt(q;EsPEzZykeJiVxo<87N3B0R+5A;V?{(3acZJc5Y~x zq3edWprcGYG?GH{&=we)Wq=c~bzbtv;mJCN zvE8LY*dnKAYh$Yg1KU#u6MiGTpnnFx5oTV#o3 zaiXK3b*gtmuS%4#IDv{GL|T$K5y5!}T4Ar4Bd?S@Nm%tg(`3jE$&L^D{7WqLed_G= z=SBLyNHKifla=uFg!CDoj+!F>i6ar>_Nz}y|86;bp0Dis{+yyIG+;(fh6_I({b=o; zNlc%-FrN5lODnE^rSfM^XHI|*+_Ajs#X(sJflQ}dATdVqv5uBSLq(DMAQi%ow3FqE zc@E8FH6klM@P}J1&EyRMMkU(GN{q+CVEELW$ESlzl?JB^K60mipbAk|Izf+|AYITO zARqkAVI6e)m=fVx4N9sB*L?<#?V(~>aePlek9hl37Of~{_-}45H!1YdkZrxANPqp< zjSDX=fKK|G^N74EfVZ>H`fGOH(np*`L@MO$&`NIPgL{)vy}KyV$EhO^nUl*4T5SM^^HsJ|W+8E=1y^xC_%q`5Q#2L@&=3SIQ)+f;-AoM0{ra5|4a+#*_9kq*v?` z^kf5+8p!VH$ycOT+c?ol5U=0}N|2@l8M@SpgeN+hOL%g(LIIxX6UN_-wHyCQ45U{* zHk{85L8Vr;Zv5pHlQ#w*Eh;t3AT1%JcANt0X{cg8_D8gZF%mUto3Tb|`=9>ir@RB? zF;@3YM)IzEn)L-hpFT^$AKigikFz#ENiT>UzL>bK_|I}NT5P`dU*uw)6EWAw7jtoM zees{?;{N(#hN2$9=zJR=b7gbFFaPH;eF=mGmq57>jFC0e#Ds7!5__LCI zj!0jJFz%-G^T{IpO)-86jr@9%J`z{wr3=O{89h!d&3fRAbik>F8A?|WL#4^&Sr8=u znt`fVA10eC*7;(v}4*+!{>OAfg9<_W5lmk`5Yb1 z7thhreDU4PNHowwB{%Zi#%QMH^&})v1o`~dW3j~)F%7ygjJ_tC z8EqFxXm02aL$?4C${-SP97N*MPi6cTCzdMnQXEsAyTm_((y!;@(b@|x_Mw0YSM}sXdx{^9h?}0w8C~OL##?% z38f*fY=}uPQGzf+8%W|vvPu#m%>=Od(ogfciUHVsu|S|=xN5%m-dqg*%ooQgmIl~- zv7oL-0N8wS9td)1zEn`dxv^y+Aidpkh*|PMlLv+m%GL1sYLSkWKnMrDMlVRO7zk)T z0m0gkzU5{Cg!xiQ1r-B?`Qksx#QXfjK$tIXYeO~j#R8ey1_<-Tc_08`zEnWq zJ_Es@ashRr6i*>zQ%KXZuzpkzc(2)7w$2rC6rracDlFRBZGeSPtZ8h3g*ZsX8(<+h zqv8#)keqp#un=Jf{!HSweY)w+OdKMNQyB{@>8p~aEnuebP>lAcOdTS(pb*wR_#kfP z5+OhjL?p8ZBIfpqU^9Cn4b(mncxF$evf3wt(Cmqho^789NV6va=oo=$X729|e?{}cw2&fa9&%uk^;Vn?>9r)D3{&j>(b1cshMsaR=`PWw90Q%edD zjh4`(^jt$sowp*brA_>)T7OgAvlf*Vh z(J7uJZN>UH0m6UpK*Najz$u7%C5yF(C(HgSlg$R&Yf18<$+7_L39>9W_+iQQlhfWG zJ-95x4{PR)0Km1BHd*N{rXfOZ)5(bPXC6LL&XeAHqMRq!^+Y-UWIa*-{Rz3BIVn-5 zuRexI6XYf1{nXMfJ0>FnXH$wRO>s1!?KmehrLev>no{>cZ7K$E^M;L#3l#&k`C>^r z6$7&QVyRyh!^HE&ZS4)Fl$cw!H`r2W3Y9LbZ$oNA#fwvgx+npt=>2Y+>;Ng<`}pzq zXn_Flc%(n$@jr(vxnOlWTxP`(nu?IiD|Q83PoaR}`d`!b((@h?*Z;vzER~^xINBW^ z!2*eh2>}*$*yV!MK*9yHGqSz*IE`9xhx*DBAf7ch0m&Eb^Xcnbz;0Dv;PE}!ZK`L+ zgwYA4vV8Y+R>FL)W`O9qXn`u_Fv1Y)!yew~b;_^@6ENszVUKF4NGS6S3op+ntK*o@ zH0)vEBPoRnb{JNB^`8c;?XX{bEIM9r3oAOL>0EbTlUAR^7 z=cVV4&KRbjdWw>8e}q#sBVG6RegB&2{inPg`bTH?dsP3Y>hvjpGX{>rLdAVCf+KWg zTtrx^=@A^$5^qX9%M=XN|2hDwiwp=N=)N5W98JO4-+>X9&1 zEWOGWPmhG59M*g!3>ER}N5W7!aQ{dcDzEcB5{4S(=!Jt9|6_)shy^LQH4Q@%zEK#8 zd^cpgt_kWoXzApaX&7qy++nDf{QZZaUZMdG{-MH9tO>N?DUHHGxsFeDArwXekwRhj zJihA)&@@%Y@g^eZ7w|NoPK-(32Jx`9^ts2i=`IROX{F5H$srm^CR(npJX%-&5AQBi zn{8iRAMzDxgVPA4gHW8z#D`}TFD(r#4z*gU((B%>BY-05_EfJroW~sKj5uB8&4TS` zijR7Cf5#t3CX%i6gt$)rn2AQ{e81 zjlxGzVQB1qC%RQbH9Z)<&`XJ=eMFdXdfU zu#T?$Jy&1(d#=9nZV6xcd#=9n_gsDD@3~e=>*3b1#k{|ik$6BHmO7qnY6w4{4Qk8d z6K}#J)r&)pl@K`L=$lPS1075j!8LpJlwQm-?dFD8frAc(^*bvIfiAs71d~0F`YtPb zV~$VsO+tODZ4?r?;N+w%iSe)c`x{`u{kcrv}6YIbP{@LN8Ksw8m3XZZhXEc87 z#Y>pb-nx`QI2z}*j>m=D?Kt}^It{fdd*VUE(<7aKFdr}0LX^Y1PiV&ms3LwZX1nL{ zgrSLeGbt@OM1U8rQL>b21+s1zp;xN*v?cNn^+lNVr!6@yFDff9>giK3w5Tl32R&^m zC-*X{lbp6h6Vua{j4qwFB#P1y05l`5_UdL?s}cD`Aw~wEoh|BwP<`W&Ia+2YS=H|; z?FsIjeg#Hbbpt`X?1Pi^t8LsMCYpf(d?r=Z7D@8vQ-%0mI1Ez){I7VuCgSvv2zAW0 zTDHj_sbKs9AkrtDPuf6E-?XSO`~*0TzKbun7%mS7jD+V;IJD}21Td1exDkxGXdaA< z?W)EPSLtPOcv7rt{K)h^RyAHTyZ5TbPgdy*Ue)kN>h5O=k)@7%%k&@P*w#3v^^5I2 zTT{dY!+fwF$2{ujPmzpv(JCWYg5g<^OxX+{SB-pNn4|{hclwKH6brGN#!t6YA!(Oa zkT1%AueG6#V1b%rw~N*pVIu8luJ-D`kV9lHOEPf=9^1gQ_ihrRy2B zSVl$pMN0}c?t04(J9n5d6y0ywqw4f}QV6&UHdjiJwkl0`{vsf%+$7*Y?QKSq>PqZI zMwtJ=3SMQLJJhc2EcfE(VL_onuXzyYQ4L)g-%3uONhZYp36e=b*oGXkfYR61%8UA^ z5KxW9Rq>6qt^*WW&U`S*#8!4xt-i|_;>lk)n~5g|#dde8Bp-MNsIz$T6}j^gPbZ$} zMoQyMJoPq;C&;K3Pz4C}^-MtJqB+hQHp5-T*?|I)F0eE;u3wk)dgn8}1XSascJ*%tIHoK+RuP!!(&c ziI8@t6qvu%GChg#duOMa1=C~#)6YpyBAikn8(&(X-ZrW^OE>c9(lBL2eBMvW5JER< z=Vsp`C+r~~og^08;nP86y2vE)NdxmHmT@m@YaxrZo!p3b#Y+G|x*GTyErMsOQ4t0v zSsy~!*WrKIEIRy8-M61?0nCDSKKzeah*+s`N=8tg*;G&0Vg$CHP(Kd;^PBUB|1lb? zX{@ebj22-&Iugt?i=YB1$~Adgr(iMor+b#^@yg&mk>bAZA05Tr{trQMoJbCz3FQ+= ztpVK+gW{CNq5A*-ptz7}QiAB(bkEN9GS%^he;lIi75@-~7U#TtjfA%N|3yM8PY`W# z=`8MADTrW3DQW$V*+#V;W8TyH||d_?`Wz!E^1zRyS}lDV=mPMc--i8pE}BqPVzo=HXM0l zDbW}2S1S~UVdpJ_W2Yh$;N8w-(VLJLd%4EEh)+DRof)Cb zDGxvmjI$wDLua=*Mh;->E2dLz9JlJaA}fJQ@(Uenix7&46 zau>?hle=a!vdza=hzQ%V@BM^<#xNTn+QrEmCl1tf%JAn0%DJQ`8)$V$)13|!3-=U! zDM~o?K%p^qUlSDg#eRByoJtq>Z*A|tP;*SZJWVDewkN#FkG7dY7 zfa2xz`F5mejiyr{&5a^O$(RP z)a=zt49lzWD8CHxta}+FfnWyR@u7I{o`^FRw31OCj8lJ7eb5p}?wt1PE3)9nqJEno z+snumok8+w&7~Z}$gB2AhAbNt_6wW7YVF$!j|vkj z?b?hYmx#y_Kk`))r_ul*kpFYL^kJSqsnVAnCVFMf_ZgV3PuZ<>J}(FHa%L}9KgmIq`bhI^^i3se2`CE5y}y`>OOQF(TbTUsDO!_%!~G_(BIPEDa_(irv$-Affw|(6S#j^OL&MjXK9oe< z>wxXf>I%*)Q7{!e>Wc5Z#!nO9BU2;_LY(My^m;FFsEDTNe2b2bQKA2AG`xtC)V+Lau>btM=`-;FiST zDS|O*B#LQT%5!ulxC#MburNk79U#$Qq6_zg0`^@@jP5W21k|sgJ4WE{ zeEg!&%!oIlF6M1K@YJ~Qky@FoV~C}w3RJ{=EPmZGNHzd6)}{yp%yS3}*)&7W3~knc zJP<0UAQk`x6Btz>+^WL}W_UWWv6G?b?+&wviXzBV#Q%4t2vB6oF-?`B5&{eHdl{S5!?bgUXbgRh0=6OHo8MPUbjz5ZHe z0MR|wG5Xc-eg7|eZv$r8S=IUOz0avSb-t>1RaaM6cXh}GTU5DYxbBV)HSQ6o2Ciy#5w*g``hp!QXSjDuQ0&>)Go9e6Y< zj19&J$Q@ga7$pPu_h0MX`<(jf?tB5G(4@}(ct6+oTJL(_Ey(iwCXEB>dy73U+5}@B zL!iD?g8Kw^=q2Ez`XkQ$`cVzP!Cvc2@}2;NaoEXel2m(+_Vipe2!t4fu8%obcQ} zhOaIb=pet$d??-Mks4M5hsxHx7ZBag=l_I(F4C7TtXg529S)`cH6rk^YCO^|t-D9t z94M(_47%anmP>#SrQ;oxpktmV4a=2k0R)D>OsRT{twG_Dwt-xLFg(5+g>#fo&I>c@ z31r$Nj*!%lhCkV@(T^|X*V)F%YG~mvIs&qdt2Hp(GTO&Me%=?e;!6k!3eDviHWi(J z`xk6z*7|Hq9(CKNZKJoNlKeOty(L((?yVB3Wd*dfe|z2Ahw8VaSFC%hZP?V+NyXaf z*D1J9p%_AY)ox|zOYjQ~8z3i0r$xv8>?;HgP@(KR^0oLcMqqTVs?pyg>`Y&U;tG)Z zHBgYl@y7x%pcS&#faQ5`}_Q$p87zG+TN6!Sb z=2HclOZ_Y%ePZ>Jiw0l!@ zylMBD(4jpM4wjA3F=YIWB;HUSZbYRKEH3ZX0c}`!BXnq+qmODMbPVfmgpMJBfsA$i z4o8Kpv+nIEXLZkv%It}8)>`?DHVD68AyHCY_Dk84jd8i#wbua2ooj)t!n7!t_#d;-CV)v*XbC# zHCpEP&q#_o3Ttyx9BPV?*s*=HkC97?38k`%E>RvQa=xV5p+ zJ+rZ}5gGn{5oO7c4CTOx{!*hq+3A-@V*6KacFQiWEbTp5+GT4+rfFiPscd~t>Mly6LB{w46;ixtu+~KG;lA*(vk)Z1&?675)o7cS^ zj=8_V+aViIZt!+kcgqHEzg)wL!@}3~J1Y05&M5bvY-W3CEwd?{^4*cS++BOpB{@4i zR`W!0MxH3d6YK_ABg`KMm#aByAe+e zXS5Md3}wJZJTV;eMm#a3&5d|s*zZO>F&y(oJn?rm)o;WTLuhQo6T>mX5$iZ+=>jreIeU$|)>)Q3AfJnLhUC^JON?e2fOZz-ok+{KAG-C@nfzcJe9&tY;(x zPT>0S(=)0Hgb@HetH3GY>^gATF1pLS(nc*VHEhc$BfMUFlI{oTE#hh2TUSzgiwV5$ zt&29jMcuD^>xxxxQTOZK4(p=s*S+;Hg6g8~*S#IqMcuD^>t?L#qVCtd9gYfhzwT{p z84~RV1eAj3V4l!_518s2_eV>ze2z;|-j<@g?fi;C51h1PlvfMJZ4#4|f`=|6Ol<49 z5rOMb_wHw|M;+OxLfyLw$ekH=R&Z0)`P{=X9XmWq@0zPK?FL&}P-2c3A*Y@zEX?XK)eQ}!=Nxq-gBeleNV0x4X zHeJy=Tuh5QX7$r6`-GjQ8`oeyMw%#iRhj# za-n;gRVwy>)8Je&t<8DUdy=P@vn%qH`}1X&#b&*nDf5tAgM{F^Ss&MZ>lC>P&?-q&`m?K;E&6h)pIf#Ov0atlUA6|Zwo2C0?E>Guf~>l%fK4*&K|=Uw zc7b*Lz8dOli+Nt;Hl7^m%bcxlGMOdKw3|PZ5K~`FO7VorQl`s>Q}&L7%UQjc)yFYO zLpDs!UfG|t{j7YVR$b0ki*EWRElV-ks|MODJ?qPFy<&EMvZd%LL$hNrj*D-TEWYuH zh+?u{eCu(?Qc07aS!W8yF`G{nv%d1Cp(#A2v1B8yP_5>`S&Lfk9qxs^ybkwx2fF;v?0JEHHW@)JWf2(&DbEX09z~ zlqbWLzSO18b08Md9_Al~PZTeGO|nc%Q1AmkJ?aQS)51fM$0gVv%dfn$l)K@|VHImI^M!T8t_Jqb37M8^-&~eQ z&8aju1zDnj@nV@$$};U@J=kYwq~<1kWgmL+9%PKr3@>cWzA{CsP7%HovMaA6Wi31Ia~`mwXD zq#t7?{m7YD(vR3mdIeI=f`$EvKdg%g?DbQB&of9Qfd=Yn@721(J`nD0#TwS0u4T;j z!;g3^c$Y_S>Xd9AQo3-s<=gYEdUT>wV)BRgcb1Shq~?)VI0^nIkw=hYqO(vqZ$xZA zc|~7Q;K_qp*SPW~dCS2ncs#8!^yFwT&ifsa{L)c zf?%Gsv<(tS!~}y#+>i3nLlOCD{YoG|`(T-{F!Koa;ofIzj4U7Yler~_Rfu_q_R&p zV=t$h8ZTypB|RLe#&l#jrZsJmP!gwl)CR~fEwyd-KBH?&Uv|ta?{GzHP2}Zxy5m|Fv5Ro)1ZLOs zQ>a@{l$)gAll)4P-qXsoo8l;^4sA6PoV=xS3oTd7Wm5dybmLs+zmj*9^N? zm7x6E-eqybabvqKc-uYNW*j4a6 zyS%iY17!z6)X?%G_FvVZ+kb7a)0SBTtUUjJi&*}0hw@7<%&zmR>n_Y*>Q^sSECUQ& zuPLdkm+>56-=Nofl1uj|ukot``;&iH3G?{tqTT*#d%o|*68X|~XSV393|qVcv-RhyNvo5Runnk)(4`?1wjpS{7cR~xY} zp?2ndgxK@*mPy$6hGkrCRJ!bsly^K(EDE-5;q>_o3a?GP7D0x{6zp!4tzeH96bw2X zk}(i%;vZ0sX9kkFpbdiR;d=eK!EW{>7s@MT(BG*xc)o~AC=6}=y0NwVq5-g*gymP z#lCHJ&=79WNRxpLXID9;M@89l0-w?ZDLO8fsVP#oouO_gP^qowGo^V{a~01lWLDRffCBbog1IIzK(BcVV>;0_(|$;kO$0 zs-x^K1k_tZtYI=7|G4l;EOdy@9qI|p37uxKRWw-dzyTA4#{`$Qp+>lbEN{@C>q|@% zY(X2C<6L7QBV6;xVy)ig6p_G-THb0X`qofM*#c_Kez{+C%VmM7ahE{1vbaFSR^tc8 z(XK79eLUnn{BE?nm$~-Ab{-xEE(qO`sYaOlRBbA@Z#VLsqy{tu781pKw5^K)U#~wR z1q*oTV~|}`B~nQJl~eO2taOg#N`q4(*bev;1=86F!Ls{CA`Cc~B!m4R*p>(uf^haF+2Hf5cSW!sLq8(wxb_Oz(GVsQhTh4!1>hI|d=cLagQ{qA~smZT%I< zYRb;Mk|oorlE2&0prP2%ps^eK6AhZ`f$AM9(Fzo9iqy=YnX=)qwKchhc#+10Kp<4Q z8`{*!%7n+snBFLmTnHVzT-4PCS4=xP(Q)r-&DY;P@-xs zee@aAQDLK=ivdff+l0++E@Di)BoLo14 z&xVgQ!-JC+0DAbl^!kfg_?*B0)$i8*pV#*fU99^r)%P?<{nt0bPd!cb4I-j$MjHjo zBI5u~QeMXIgwCa$V0oQZ1}OqP_#g>W;Xk6$FzfOwnSiEa%4SjYspA(v_8fKfca8AZ zT^s7JJx})!*Y`iZSNEUcL#7kZ~d3n+~3g% z@ALQf?bpQrOBR0553snOuon-Gr_}>*;K!Qb{dV|(Ys!UkN(gKbMpVSd_zMC`;7U$N zYZX(a>0ev&XaT4xD`e~>EgwxmDgZr*#w=&r>*RdPSv7~Mhd_ucaD%s`noE39%f_}P zO+X>4Cdq?uu_)OjRW%@`g|S(S8agz#&}DR6&^3dSpM6V%UC#Y9F)90uB8!7b>B>eF zJ{Sx-OAs@EZzTjrC62% zVg?+0u9$8N=#H?I>jIOBtv$&;2@WXi;-&l$aFTXFY_d6K2uL4+Q-y64r70^ z4^9H^Dp#=^V^KMi>I>OkM8?>wF{c>gCD=jyTr8E!36T94GXoq^+2b0rIu=TaA1?9y zL5#AiTs_LV1!9B+{A3(#og%rp?BC?86{^=~&y2=&Poj1zZLN!|U?{!0*WQ>YSApsc zqi6R6e~TSU1Iz?*nPCAg(^<(Cm%V{6wsuCi=tGToU+f6U_n@oHR(vUP(6Aln?Z#mV zw_oe3;+hz#pBkBbo1I{IOUOb7htwQAer};pu&D@D7VR^BAP22-k~JsR-55f{|%mADdft z6>W$NIk3jX-WM9-*V~4`W6zeH`f_y-K+wF1XR%FR%v#9@Gx1>y4Ya>{ppg|sEe;P8 z4aV~r673>i0-VwG1e^`np&Pv8Bh6|cE+F4I7VotlWRzqOq^(`h3_nG=ZMEsv02Po% zQBDD1nF%tLcrXWB^207d&BE7yMQ;B2w`u_gW(BvALBEHQY?U1(YfD5!VOT7$*kDeAn=`4Fu^SM6MuCzp)&?Y_ zvu~#4#phrWNic&LIZdZYcG#v+ndT{mn52Weru-_*Bz~JE8%6nUNFVMX#zXsuCWEABq2)M3n zFDy7%=*qENmy*(}X&4 z(O{c+!vCoh|3)_MxpM3SseZBjAeP+@`M+C>oubxAyK{m{UYzg1u{#klaJV%s+@CMD z9qcz586zO5_8bn+^gy)SU$GpIrX@e&BPVNHbmb^0QD#*Z>ejv1^CQf_08|Au;ZcLh z)BuU2naSs*KMII5Sm?Y8yPKD?V|doFv%5NgO@2MaOiYObiay6Csis{+ZBWqcqGnKs5N&lBgE z0rD~dSJKDsZY<6#rX@-u1xae*qPJD+6;?-uUjf$;VjX>XbN%vWK~4nUQl;1Ua~S3| zRN5UYAv5&ywf+)e{8|ZbRl+Y|In0iTz(HVvE~Od)SnCTc>Gdt~HL~*-UhC1VJc6ks zO^c^l;IXwS;wRQhOW{*WzQW{-J!Pcv;mh)C3yZNr7ZTBCf{k!I^^o&W9L6F)Y;uOg z2^AnHO=>npFbp1DRrCh3+X=(XD02Y@*CZ|VB0gu87!&Y3DiRmdrf2dM#$vt#i}TCn zwDJ{Z5b9I3G0!SSm9H>`qghwk!DXGVFkPHyR?>Oi-L$>aV)l9FQ-H!=k-H{^!PPC#hQ~|sSuW=hOPd%3&_XnE3_nt?ElYJm6I5nM<$5SEW;nWm$s;%}$ByIYkfsf$ z)Godp{7l?R5Gft3`9BpJZiqnz^`p9shOy`&;Q+vDM;X^j6R{$DTAy!_wIZQ~iJ{f~ zo`5Mi)I*y`nPqW4sX7JA+u=_x4ZkuM-pn~BJH&Iv4nou4%aAdvl88iR=%?o(1^f}> z#f}bY=_Hvcz(NINVN&qV)Z<76dsJ0ORDl^SvPfE))T~jbxZBv3$*Yo zq(3t#pu~ZpU6`$rT4h*BjcA;gAmYt`B8x&;N{l447t7G#c&}3DHt;=S_^DIO7rTTc z%ORKifO^x=dF?urv-}j%BX`GEo{sH!xgXJus znYQR8>rx{|mY@y>9OxKZph5=fj8S(aKt+?VsW3IF@MbQ_p#xQsP`d>Kx-m>VW-}HC zTR2Gy10g*i5yj5>v#^Y<&F{4gh#wqU7pW*Vs0P9}y`YpxDIFwtcSlMED_c`QsFje!l>roL#*!^pOuoCV)e)6SaNB+<3>q$tuj6q0YGY)a9>^Qjf-aq-v zi}{Ls_$_`>Pu>&M4i^G4ED1QZAO7So@7_gvoyA3C6~(W1-ms__~NvO%qj-wo)^3Jk?O_GZtGe!Y0R^GeW862@x`%YP!%OwzJQgqRK=?n00Eh zlz-3>Sz6GrFS6`Jvh-Jwih+BY}ec^QrOo*VDbj1LueD)KF;4{mGU(+Y2OspLi-BtA&!0t$L*v_WKA zv=yp@wbU`l0v+q3Rkx+IJ{qXH4cF!>E4yK!s;w{`Qf?Tdi)7TJBP`&niOy-jbcW!7 z!s0WsV;LOl^*F<|L;4cNikkj{1**R|7QRqR+H1^S5)}Qe>F~#+j9cyOo@IVZw#+R%eGD*QUF97fIaP))nv=WGfo`W7z-nU zQ8%CnkdB#U4|O}Pz+O|dp8xYFDv)eNqg%{*Uek|h{tik;s%JpmI(BQv zV#Uh%cj6b_52^J%)sPj0V6p3m((p+;3|Xut&fw<;-?U&{Aiq|SwK%XaznW8wcZa+J z{9~^%BMHKJBI?1hK_m3Mx#;I*r1nV{{gbum#~E;w&7|kG*dv;i!mqnuZUWyHnUO4& z%dLQX=Kc+6TpDaAB&X$o!<=X~Co>5emP(#Ou*d=;@4+1RZEgvzaonkmA0WpawTlRqQLfnc+|31=E?sE(Sdugb{Xn zX?6pREir4Ye^IX`MJEf1)9z#@$p{n>Q&_7T-uzrS@P9BKek_;y5`{;^!cMx}F1ZW- z`e2}?txFWzDS+%$n;vt}Rdi*xkBAOey{rEg+a;~ddl#J9=B5Fif3V*N^icR}$&2*J zgleL-ra<*)#$+%9SjFWSJVfwZZ-F;rhwxTXP7z#n)b23cTNEYHL%lANtGJTZ1zoQKzCLKvmQf*HRh zW}N3wSRPd$p%=dRam9@}%H>MJ+j@qMf>ksZ*l!h9wus_hfwUxG9OpBkf!ngaPsj$3 zEUTuWNjkIWnO)5lJDJ*WHf*BPyl98$iBHI;$AEQ5095nZrBc1Y)3j@9`(UuqEEVJC zJ-%Eq@L4u_LVZ2iv?+p}+DR2BYqPxBW_hzzqV#q#^+E|2aiZbi z@p(+=n?CPXj?8~;g}Xfb;)@2qU*CK9<#YADM-WLy`9+T?{>r@;L3~&JU@b>^1oHXe zkNpckw>?h*$xEu+HMuft-l}mV;`=zu)q7i0eDy6LL7;7};CUGp{B~FH+iL}nN~{#T z0%o(QgBh}DX_3g+vi5SWj=_zFbdgsOIc-lRTq;6K49Z0FbXUTdfHW47ILS&fzO#jQ zZFQb|t#-U2CK%*I_&h;5_Umg$!GP^OgM|M`pkiTEB zU9e8yXD82$?Jip`*`o8R!PCQGs4=~nKc)$ZkQPrbo*vR`<_9hG zf;OiOWiSp|R-7-1jgBe-@U@Qp);iKY!WG50(pe z77LdZx8A8S%ob(U_tT1}dEZP(>+h;J6zAp;&T>CP$j2PAy)p?O#!F{}!lmot&0W)jsXJT;LsiEvce@`pPX7|Bz z2J5VuwHg_7#f<1JR}A=>Vv6BE z$@kpSC0L&ZKrBKRTR?!#n}8Hv_5g_mpcRDJeD2X$DzG5u!>${V>Jvqw@3uCJNpnQT zif4M@D<|gFuqGABwRGoi^L8b=i+m3uK=8jJ8Eb=n^LdsyZ#ocvOx5GI>-NY}G|M`; zMv={%HvHT|9@1a@Q?s7eKU3%R&&=n~563QG8vxrs<$Ph1Y07SPNjxV^o?)@@wkKgf zLeZ~=H4`5F1p5bw1~3SY&5+AF!#A|;5pniF7*Hf4`ecjwQXGXymksA}Jl0ydHI9d@ zWyZ4;vQI@+F|BdC(eOsSK$WbZ04AlNiF1ENa?Kr z0v*L{cmi(LCYl{VdI+qDPm$ux2!J(ZEH@4mJ&%_6hM6n8jJl`R-lEE%~L5mD7%FVRQJBnGP7VQR z56QSd{A3N})j%a!x9y-U=OO4e$38EIfihvAgiOPJp#|Z2ExM?C7CkI*X3|-i@XyG< z3kiYuvsaNlFfsbio*PDFF!od3&oQsb;(X1^kijS3?CJSd*g{8oTQKXVoA8upgzW(Y zLs!utO7F5ZIDlc-XdAoGxf+PK!CO|kil<2q>#5aK7DRm$X2A8nk^2SiFCMwSg!@a# z9AM}Oad4=a${%5HLbMOP7?9SdMxi3!;oTLakMzuHMg|cn9M|jJR++pbMm4Owd!QXr zUYU1`R31o^>rt^o`&Z&iD4qlps93a5Hi@W$Gdy0iKhfd`SO0E*avlm!->p>Y`rq!8 zR{Ya6eBO=X<1f(tpVjyN{x8z-fXDHE`1yMOm-YQ^R{pDSp4Y$I?pgDEgN1a%ADY&^ zwYtZI1N~p(oJ}q0Jjic2)n0Oar$>zkbes*F&zSl|cz{=5OY_UwGP;m`sD%N-@7*o? z@(r(7$QqvZ;scVF2KdE;ZbO{at;8#V0vG{m@(tTmzeOF$go2N4e~@G<(UN*umD0N= z8%dh6_K^+r1$zBp7)XBT;QBw2|E=*YWDjt;KS_L6pSHbqOmII%^k{$bKpV-2%c#Sq z*cU_K!CGOAleXmA3f1Svc3#D9b5vRNL9rcI+s-|Q!5<}T-?K~m^xE)-Cd2iiC?@BZ zR;s7rGn8gNGF{2g=+_^mT3Xl8lA>jzgM&r*ijJxZqH&@XpyvmK1GT0*QEb03`w*`cp1NDV zEVaE~zev3k#JWd6nn1J!V0K<8H0h%WpJ;29TyAIe!2}X=7yy+m7N!p-+^e>r&K3Q# z@O%$>8S>~yKA0e^UYLD~0wUl06wF}EpO1$be5rjE{jsU|0>-0VsoI5ncYEoAjKVaD z`K(2FgtqvSTYG_trp6Lr!gH&%K-0c0m)1{mS*WQ6I+j?VB@)vvq+890UCR1`K{&w| zCN5E-`xuQ}Fblo`#ZL^$b;UNnQszS~q%*&Fw$Qja-xPXZOAJd4eqOnnpVdH`e(y;!J^3HNpa6cdh?T+cqdq zYJk@10f@0x%-{{6wLyDADA5a+jnS@#65X=AJQ?va>3FeoQLL6?eO^|=6hTqA0%|El zi~y#Q-NZlnA=APuGZ+~}SY%MCO;1y>d{<0(svyDOR7X7H&X5f@SeeA-jOYosykL== zCN1MDBAb&p~fy0V}y#Y7sGB?ImpU64%2yfrA`5*gGk zS-Xq`QnOjXUUo_P4jjj`3Fn>2kPQEBVU#V1*pk{gCO!j_NrX6zL>&MiiZy}Ees&C> z{L)AmYgy{9b_rQ5Krli)mlaEiScWVmNe@do=%wnq5p`XMe#8a23lws^m{le8(YkY) zT{@T9k$~bdb;GQN!(#qQ2fZ-6D{>taOPNuwv%m+%IAnp4xp1-(_lbASL#+7gP2w+a z&G@U}xHgY^R4n!;3|3g|kYGi@`~}wXDm7%iiA(L}LiXvFt;;gUQ!VvoylA9FiVe8P z%dU|YxeS<G%U+Q(|BK;1~kOs6%}lb)x$r2PQzbJ2x>*2%uZ`s z3$0^AXdSP*SxkNg_-YY=aqux7CqVn85QFB~t(}M}_@0#}s3{8SRRkh=DcR#xfb1Dk z0sGxIls&7cxOf{;aP$3q1Y1xTp9Mn@jgB|Kj3FI^*?^Z zo)}K+{lm_VSJS%doTsI2h9jhTd^m}_s&*HXcXnzU^LE3UHbU7!G$)$jm+l9};RJ`X zl;JQ|&7N-f_k2vQ`O0GKmHlV!41YbHH^VXevYA8(p@NTHpremWa9@}mYlbiVj#@aT z<6ZnQg8gVS{H{GdI($qr*pX)V(f?Paj|?B9%1$@J2dwnzMr`DQZ04fIsYdvWjqX(S zcu%qmf!GLdx6&v5v8)Q6bhKMeUwDs?j(gPHN+bN2`_$h`Yyo0Kq@HNR(VZARMxh*Q z#L*oaKGs~S(H+&}Zuq+npLx@#qyth2c+tFlG7Y^p9z6pT#=7HYbSw=;5%T(cmLNsb zGH_1l!&anQ>(3$m+2_UbAJ*4JIh{%8&A1l1dw7XM@P}%TlV~2`S3REKS0Brg$z~c< zzPCrvWtXlbFUEh7>KVJa?6S;EqwlARl#HrM6fw5DT{(M2MpKkp_$E%R54&dv)W!QJ zU<7{eo+uNkR6DRK3o3Fwr zlgZfSK)@uN8ci+M*!TFz6GqOWH6Ijt|^(X~3th+c`nrm6U6=p1fA9bc-Fk-qO zT&zJr^9nF(fGjbxcOOexV<6_BOmRTV&6HNiX-wLTQPjr$cG*7L3!NVUk%)}k**eb0 z;ig5E2d?PP>cufb{q4YOIqZ6Qxb*7&Ha)(B^5F=FR|3!@ljbTiM=wKU8cUEn4pS_8 z(UjiB&;c?(Bc`%Vd5knH-Hv4Y@lj+Eo?obKwL#>K2Ygd6xhh3Nsci8Extk7c` zCHaq_&}<^!9-fx0j&SQ&6a9zOW@ffeI<_8e;SK+-d*dDGTdH?i2P5EO%aih3F;J95 zsI6AEWSs&mzV4f7xt$eh{`EHA_r%#4*hr-Uf$hD*}<1xlaQT7M$U+vuths#}!+ zk&3O*gPk9M>H}5hiW_iZxS@%SaTBmI?$g1lM?MDv?&XT>d&lYd0X^mI9jHiud%K16 zPP+ABX%e*B5mLhn3K@zqvr73BJmQ7zv@55BD|@k!t$;LHKSJI~nT${eNXaol zy!c5OV|52y(Uuxm;9Iv9%yFEt#qYy(^w z_FkB&gbCz_lbM+$b`asnO!C@U!o!T7{y7}E)d{0TvR zMNfHakhiyjJkNli!BW;g*ZJ$xYAAPkOq7Q;3Lf)xR(v`P!Q0@%+c@!@C@Q2$7wF>MUICf7J2d&L73mu7U8!e zHoe#_waX)veu-k2{SX|Qv*5!u2JHUilrDJrY5lV4I3DPkJ*pjNbpKvjj@=)#PBgyb zv0bMldVa4U&+jq5x;{bfRCKx;`E6;qZNL$w`k3X!p5)dE=mk>MJR7vHaN?t_iyBA3 z7U5~QCVch+3LKHQ$N*Y$kS-u%wLn>m6*nH?GvP|w`7ypnorOPmrkcwr%~--0NZ8Oh zsk93lK#Vm2S(ZJOg?E_$d`iU&jm?LI5Vj+3gbiv`ULfcDnBksM^!0qOUE+-JJaE$I zl%H(;;LxtaPg3EBmro{s1b)PMjVCbS&{)WhOyIBpf=64V{5nbiiBS7sTYOZ}@bFiq z?vMkxOFn>Y7<3S_GS2#Wbu2O8Uodw`tJVl+CEUa%LJ2l8Q_DZZBqgR2=3}WFM(4W& zs46V@*Q^z*Rh0D&JXk#dZLz3FF#beGAQE{{3B2wXno~%+tAGL(pmCa{*H7m^uBo$giJu9LGM7uOSSTeffmOu zF&O*6gJvMF9=6$&fN-=bh2RLC-cFNoRmuabILONbeBjB@Vtr~=EvwIYQb;qklI$VA8qrNe#y5@C9LSuOeFd;Eg z<>~C|PcQ~U65vh!6t9QklR9y)3rjp7Lo? zx5!JvMta>zOr0naCVD^EhuEwEm}0c}C{yUPQmZ3oVt2c?5Mob%wh=z&xvg$6f3Chi z+xz1mNz}k!jfEB4dJ|6h19p~m1J zcSOC4yMmt$;39}X{?G@>c7%}(KDIqtOzH_!ggLIU4b{pW#TYWnm_!4Ga4fmSfyz)G z26B6nuMh$)x+`jtWFdR0oGudMEb61v5otuXG{(on0lU}-vLs#JINlH@M2W-OHZe(_XR_%+;u)9_0;l3@i}IEonasxOj=lM$EiF!d^H>#=}DtA>o^n;9hU zkDxd)3W`q)6erez0updgAbh$N6zZiF56GkJC8A42)*smQt@=(C%>Bw&Dt|?yTd3$N z=F7z%N_i@?wD?b?yU`N))dol}# zp}~p;k?{E&-FL8;F=QymMBHKy8DmyQ;+o^IQ|+*;?_ALG)%CUA*^~?Ggm%60)E6-G#?RP(R>|@adg`^v9I_Rv#ds))vvR!n9EztIYaXC z_=?KPlh!A9?TPt{PseL}g1({>^t;ma=i)1}W%`@MS7goQEWV;du8gXu&{wqh%3W9= z%NRhb97P<&hau4dlkRjH9mUg}8}S$%MW-(b$a8WO-y(Cx!zW(no7qv+$v*7w_=oB! zeqN}@^nFmjn7pU>HAfMgx}$gsTKGrhD1It};^ZhO%uzhK1{8?JC)ZJwL1nI@LVbI1 z9q}W>8$0B4{en`M;yW`%syqo&I<9293j?X#Bb|=UGh$uDrQe!b_EUJz({mlKNhXR} z-?F34Hk1v&YDt8297K_4pd=KomR8gQNkNu~7W0WZF~`%IRW5QVf5lUB=Iq0aRy#It zACK)S`NbP=7Zy12^p@K1vm6>*Z|zvFlP3_4tO$f-6HC#zTWfp9CC&SY3%fZ=PAUyQ zC8NBrHK<0(cf_hR$CbM4d!D+kSB72RGwfQKrOcYdA9=VS>$s}X}F&()c85IO<7ZcC;kq*C}JJZDFyIC4|;+ z2|A?)D?KZ@WYhbk5I>_djd*9G@HSA4AfMPVn~Pn}#&CL~t(Q zOl8TWtFmM=&yvYTvSc`iX>FDadEWwjO#hZYgBY{5K4b)n#sYs&S(XgMMCa!a_lvo? zaZN@8CWf>w@kNO(S_!C+!fN6dwJrIj0exBW3#UJk?8?7MOMa?~yF6CL5Ms!) zik02|gkoi5t7Bzv`^OY3TQU1%m{+kPZ!$ZuQLOB4+1ef}JCS-`#R-)@Ypm>88uKcS zsrcDrWp+H`=CQIT89!g|SlK_6yo$FQ<$MEUWu8|-=IG;zl|5;B6&z6TL}O*&%Bw)$ z;3qzjyo%-~c@=Mx&?0Phv6!IdQqh?oyC9IASEMbqkKAMhw--7eMtMM#-CZcL%r|c9%$fMO zSoL^U^?28+$8*(Vb}`qDZuFF05t0*+H%Mge!E zesN^~SXuP}W7GJk)AzkiMY zyh7{o*v_N^i-rjuj2GmsCHc>#7F;cLQ!1U0i(Z))P22d{D#r9N!mM$C3%XhGpF;$6 znZ;f;r>Ggh*qO4apE>26kPNOVHdRB3I!)UZI-}*HaT?%L(eF|696{u)7+c5=l}-6f z84I!8T^!@Q`N{h+|=3mlw6?8F;aq5S-)O??yU8TRJ#kwL2%EVQ8&v7 z7qWL(!G#wF7eVcefXO!nOyPjpy*XftCl@dRV(uUvbC6VfLpKNM8jy_XOZ1{+Ha)-n zdEtXw!};N({&C&aw{K{q<8@lK@ZT(n9SCGvJa~DD&|E6B@Y~1V_;K60^Ko6M0FewU zz!$r2F2|q)D1i_|Gf-eRUn_}q^x>n7bn8;Pn8w(UN#=E#i7%SeFe=LeKXa6V*k%fQ z*Ardxk?LYhG(r8P!FYk^#^)~~WbT*CtZ3+`5yNS^g(rk;Z9vs6Br;}i*{7=xApms& z7Z=pB4X89J5)y?QgERdB>{Jk&FlI>D#cf&^h-yRanoTWE!A)+Ws$UIeRApA zh*s5A>_Z}j0W{!%24c7ShAitGZu}sk=m0^O-HEODgh!s0Z_Ow{sU++cFcOXrLFgrc z&jllyU`abFG=++_SE<9qIeZPA7{K8|)|557o+W*AE_ZV=*-8Q{iQh9E5yg2a6MO_> zTyRiKY)U6iveYlA@qseX%ITq;oTBrLLBA{>_I)X0Ch-tIsX`uB9)6!q`yy9-@iEcP zScC|oLvB$?hfN&|r#o6<>{M^C9ZdBwo_&u#(_d!tX?L5jW*eV`0?{X^>3(1=oj5FT zWB{c;R#4)_(~cTKbW>c()qcU(o(s_?4iM*>1=r1zQG@Fu-IFl5{fP!-f`Y+G@^hV+ z5GXW7^8~^&3J%5_bUpeHS{?UX*hKjD<;n4+#s5+kRp?(pwEh!j!F3#aqZp$P#!F50O}G3U?Ax(48bBW# zNKJ<4T*(>vtt;qM@jKEZ;Y~3?>xCR|%h_*LCs1O}wRK`-0FKnjgm*IGoe-SU+1TVE zb6{hked=s{V}Aj^ar{@>@tSGKM#jzc+Hq?rkg!^*;39}rLq@vOjn98%U?Z(CtS<3BT!|W9TvrSfV=s;7oG_eEPVc52G>29C?@ko#n}9nsIJGw-^&Pm@>M8 z5=slU8yX6ROcBqz`m#%ew>oLX<{9%@?+VtK|jqzGK=3AW`!n^xG=r#-jA zO#a>!_E^23a{IP)i|kyKixHsuT>H;PWTKV9M8gXD;e#vE$?RfimJk3FkP2e$Kp;pN z2j`xmtf|9SFvNpdgQlSk(Vq4k@e8Twv(yMR>FOa(vngk^M0&fw6dg5f`Foi=-ACTP)#2b$7gO~8rKpRPveXAY&c*I zOk;ZRMalH0vZp=Yf`APtE5=0^W}k8;f@nHHfX($Jz~qM{pbZk#>Dhk0RC;pc4w>5X z9d%Vtb{2|tg@#?zRc2JixW9*~I=!(Kr_kO$njP)3?#6^RHh?D2;WF~guowhj% zB$dxh46FVjLADyDV-0cWkfYbI@(6mZ;Cei6z{(9H6K!@vEAFFtV^JwGE*Py?bW4#6 zd{~gC{+vZ+t)>-=igT{$qhQ6G=&%iV(-bhhNt!lfO^@=Xi31?RD=}WWo;Nj`$eZHZ zVo7I3ZqAWs<45}nhwb$PxL23iie`$`3mxRxIQDiLI6_A~$e`PwTwP@LqANmVAeXx` zIfM+;dHb!KWT%axSi}s<*hvRt`b5ZB_zS&0*q^Z%SnL@Po#*6Qd(QiZc+UY6>CSFY zaaoW0xfz|DqFLq{n5Ew`knUCU-Es>Hzw+gA!6ntZfO`zjqK`-%(+G5DsB~RYo=Y<)=ayyt(kUZTQlv-wr1Lu zZOybR+nSlVIie5%owD(W`~~@NV+LTp`KjoY@$vzFw$%Gj59z7kVTY7*))asd>!nPH zovn$mfZ%0nCR{Z)vCY|qYpR+iT=5}l;hIJJmyvBETw^^bOM(RfzYks(S4%;-2oQC@ z76)uR|7l7~nk-zD5p1fZ$qoJ#8S^s9H^~L`E9M-nv0+ssd##5?j8l+qYUHIC`Ly;V zH#lAM>}3}r`}kP2^(29YtXWJp5mU9S8_Fm3C>zFxCh1FrH5u3(FV{18qR3W6t3E6f zT(AW^C|%4zul3T`NEaJ2fMzLokK5>vh}K%+1JA`*e&>$Z%Wc+S&*Kp1xX_&$(NCHYM-MbMYObtN9HJt5F4}%1onZkIqZ3Xi&JO4w zEIFck+XJE*a*=?EE=OpDtiCXnBH3xnIm{t0wBv}+ z8%mfzI_xDy!`x@AKf=|-e%_pgW4m*X#n3U_+`lgi$L-_Y;maRO^x%W_gX4R2|DUV- z{CG+&Z{>?wc))9Y$XfaH`u>A>U)1_a{lHuKAJx4=;IWaPZ&X`#y^&w2?!Sk9I|kjf1G+a4GaiE@M!>uunR^iCrZ`^jSgLu zjT;rwiHm$*{8p#jUsN%> zQsE-F4GVb=ZsTVLCgTUQ4ZDMjiLvmfCzCFEkyxh$?if)Vv>bczb>KBxO|H?nOzxZ? z-WRNs_}8?OaMyDg5ZGlv1Oe$Bfrs8P1_lo6da=m!31`;2Rgu%d$n4OZrT z%<;m2!Wz@aQAkpt(A(%4NUpDdza-#-k8_b@`~U5sJ}CF|3dbxC3j(g<83;0$l25ZN z2Tn!;LszjuU!l9cP~W+V9}svI$N7P=tFe&Ad|*fs+PHciFmVp7qKG`9I!`FCO*H0y ziNI#cMmQ{i)=;zfKkD|lQOB{g%!c+{qq64!wB_X5JTCEhT+9#HmexUj?iDhiZdrYp zbNH70!I2u5BQ=i8#h<1Ji_nF(r#t@ds;c#?kCzVyB47whc)NrP;soq$%5LCO zY9y0>ax8q+cdM&~L4&4fbTsTS!5oo3iY!^cFOwi(i9jA2O9V1cppq;4TTLop3$r8a z8V<8eG*o!V!Xa`Chy!8}zFSHZs_~f;6wp!*M0P;~b1I>hxSbBOf>Zl4iPjtGDCeBC}X-c}#p3vYeChVlpX z{Qto2|FF9Mc;*r9+}6$Ak`X2nh{>!J1l%Dl<%vNfr}tQ*rARI=l-!n`r9W^l4A9K) zWGT&juaT(cnj&|ZvT^G;nk-t1!wj)yIF#$0TO2c3%o`aVbm-!80JqRJEQp8{8R4!= zFk`*Q_LDMHqh@=^5IB00hbVl=&SR|jlsUGa8{2^DE}4Ofg9XLkntJPjtMnRs#eA#qU-1SZYF@tK*a^hya^@v6eG!?n)U2X1eU~ z(iEX^7aMo+BTuYq+~I4D(^#d*j-~F|0Avh@)O>c?=xEL8bAq*3urMh-8Y6BzIbcuB zdqa73<_h?tcRI4@&qA2)a{rN@bz_Ar7-S7Hg5^;E=t^A1 zuV*MBU~_{~5gJ8?qAtZQ(R$PSEcPT2;Lgk6hf%6xT7=7B4=sJ$7!Zl7)%05Q>?m;` zL=Xa}$VK%hKq1Hsk|rKK1EMjC7Zx3=LvB1JLckSmKpDb|1}nUPCUryRy-lWmN4Wd0)VmM!=xAdWG4DfcDf zR<@=B23Ucmd18Zp))3p9l=@)kWe!Gy2H6Q2yzGw6|5M6IWmxHkI~^`+>#M`B*k}hW z`15QM<}are2>2oSD6+vA?NWb+<$F6Tk4<9x6AQ_38kX6GcwG}Qm3tgAl}9yRhbHH^ zgS_}Ym`pj&EuWCxIbNNQr@H|joJFkYe2+(8#W`}a^@B-iRXjGtnfADAEUa_dj|X9g zwd~4*uy$oZSi7WmY*iG{qZp&KsOpQBi~3A&UjBrUqhjypf@-D7nZ*ya(R3g5+et zEBPT_LdBZ-F{2bwte?qdfeIrAbias!fNLa%wh;ppgeHXK@%qa~z@qZ^M#;g#8CG(H z9607}EjcJ((NDo}a?l4T4}Z=BrV8e3%T1cBcUn5i@D)>BD#yK{bsb9E-_^w5oCAJ-Ee7MkvTX)ss)NPl7(N2 z%$Me6lvoG5ME7UXQdJXkfT)28T(_M6Gdnzzcq)PaB%vSsKbz_5prUMX97ZXQvxOA9 zFJc+kEK&<863$yLx5SVlex<%;d5$5)t_2Sin;H!%>UeX>TPYZqII`@|7*eD(xFgbT zAw@+GSBDf$(2k1)iKCr4q^N)|mUcf`DcVEF*+ORK+6es;HtR_suA(IxaDKh@S(? zh|mTD&<_ze{p@8`i~yn>8?~TV2SH#9AllN%Fo4Ko3m~%9L2jIule-Ehf^)?Y`Bvc7 z#1TD!SY`?sRv|>Jn$h?n!NyJFha_T%2-n6BCuOi~7(cv5;JlD^FhlKi{9w1R=%Kmb ze<&VlvBL3iU!t(#r|s_p_V-i#RY9<{SqyQr=FhoNCM&DR7M(B_&Dli@ny{|(6F6wnvDZdXyEe*b>w!cWwOJHwechsr z7=Vg05^NleGEOVJc!*#lYG-8RLtBxkr=MJ$jBTIZgKVe8!B;62KqHH-`Bn3N;G71m5N-aS15a#PDaW zWBuWS@x=7EXVNO)_!zzdewaW{MkwFZw{mAEQS_2DAm-M9g@(oP7!vVf;T8??J-8I8 z%Ep244mO{%ZwJJ*!?)}>kca^F9|IGCg3Z8fr z8VFb4Ub7!WpI`S4cn#C_O>L$lXYA&9#1AQ#EOi8q_|fJ#%o4)mX{e6)QLMJEr)5z) z;z#jQOMDb!q#`qxpA`ise5-|^2!HNl=zB*-ArNOcvyd3 zjG~f3Z~W%SdRi5tcsyB8S`-=$Q7A~jqsJ1Wz^(wMn35KvQ2Np85CxebRn`+O#~HJp z;`iU8le8+g%1ogrHR~y!l(kuiqPszeg2?+OAqtB@XeCBPMq?0bl9=EDi$Oe|BqoSE z$R_+oB{3~3{P1KZF`d0Z6Q=*jl9)hqo$(=Vl*(y-6DBcj9A4P!;e{CwFRV#ok}q)P z@B+E#lFrQ86^K^BETCpdOmI);exbZYG>9iL0Uu9dLV1iPF;&WAn8ZXCB{4~P)JaT& zw=Jkx&$f{$CNZH!#L{&V6Y4__7C)7P7F`=@kqxq!*n)r;bWYhzxMKexvzJ(vGV~Eb z8_8bM5k%k0UK)Pr=E=!k`e3upURt$$B5Uu=8B7-Mj2TRrPZ+LGT?Uh_Pp(^m*dT++ z78_(vV4rE}0WVKW4;y4KDVI4e$ybX}Wy6-EDsxm8AtWb%#7z3i9<`8>2Nn?xhy>CT zBp#woieQ1)Ws@qQitH(D(nf8Qjv<`ux;mP~Y*NM9AbRgvyN+a&D)^5y0k)M*>S9Eu zDyAv;(d6_pMg^mT%hY9)Vwz%;%EM{8Kl{{4pX<7E~D021^g(EqD(3ZG!)Pqw|zkaaydLdv!VT1 zXgEcm1}Xj$9@3tT_GHDF?YIMpfY??2)y1u%MfU8{FZuhz`559%^96j1Mn2_ScwSg}YP!cZKK!^A=wq&7UzHG>GGpbDdZuMI90q1nJeHwc&^_mC*q*a9g$fVrifl zV2DRW?Zta!7S219D)6iw>5)@yELGH=l^AmJR9x{$b{T5<1rZyg_G4Alo=1_O8(KS{ zh5hYYIc>(qt1V($eu?`kGriRuiOLW*w+J++S&{6j zc4C4LL#_mXu8idDnQ^pT8AscdakO0-N86Rf>g~#6^>KS;rdYlDRvNkqT2AoM69www zFpGza0)!EMK{6jn7ou+;2hl>JArhX8j0b(Ps%-P$_*fw?V3etV1f8Qo>SKiju2w}3 zzB&W6IqF2KU0SJO3cgIkMGWyP`Obyy2*PbMc%w!*=4pj+s^zw-!^I5o7ehGaZbbNa zg>Xrv@u3VWS(hOdza9qpdn_V?L>b;Otw&2rzF|<}M%qw!hWgY{--t*QvK5bU)Qb?1 zSe}~N#&B1TDCuFI+XaMb)N>V4&s9V{R}uAGMbvW@QO{LGJy(YMxIPn64y~L6uGRsTmT9V361PxPW zB%@NdHN&zM#B0S|8tsT-z)+=7D*5LbmG~P@gwQW?MBM>9Kh+6<50_~+%&1g=3yG;H zw|p51K5DBYws2Q=fhfQ3R}KyxT2B{sRgfyRV zmzl&8>m_SzVsyzm%1kYZf`ZMKtn+Hgnw@CQLXb~np;pC0*rt(z&bVX^9FdvP@`Q0x zfTKHOoO4*R_DFUcXiKfJMCyzKHY;}1l`)Pzi|d;_GsdxJaeb3##yIvYu5a?p7-!QZ zYpu-zbBRv$P@Nr(joREID?Bay)ShVE#a;HcA1k^QHCFB3Ibsy6#*n;otPXp?&95^r zpj_pViLkJ?AY)NmzGJmAMhO9;I{73mM>*e5IKPKmgOMf$d6X`Qs57lK`Hu)(o$Kz2<_$W ze;#iAiK|LQYP;Np8A({^D;{GQ2^?xLqC+lCrSW}r5>?I)5hq2G^i@$UNL|Fj@tHrd z!Yo}WPEIZTKr1GfV{u#ztLr6YpyrkyPAQT7<|DAq)gY5sB_wGaJvH^Rs=L8}Y{shV zW3sh8Sw?CMb&~@)=$U1!;Z`5Q4yvU?Hq18c*g7I@>;^LAWQuNFtg{+GrK(Rz?Om7Y=ocrQ$XtQO@YRxaq;m zc%~#xM(cwCMe9SPV}oVpdYw5IMrS^d zI0EY$^HCHhbL71Z4qm9o7hO3s`-M~g7Y|vqutvSl8Cn_|&Ehug|Io8$rSb6*+1xBP zs5QP!b{EI)B_R@O16h0nl;rm#j(bt#o0p`Frds2>mo&b|y(F`s(W(+r3`qn>$lOps z{=9ifwZ;eGv6fv$Q<-PcROTw0%3MWLnX70ja}`Zxu1w>LAhdbNz(wD+mt+W591760 zk4vHy`qM^8D3gtl<|$z-Moj)@QtiU@O_^*6^(2nCE0g`8e*ZTa$ci`-R~z%ttzszM!cd-T#Ye2Ug`wPn#HnzGGS-CxYKFpax^k^Kk5pX4P*9A7 z01PGaILpRiXQ)*hq1;udctov@@W_|5v<=t=ZR2P&(#Kv^q%T(Rh!^JNt>}bYm1#nV zI?Adfv{ho2$ydT-!4&hYW`GFR_dV7u;ImVaw|vHj3+Xrdrb+X6>eNb$`5B z!@WM2*p8R*v0mRVMqA@C=7`u9&A)m56SR|_G^byIMmBjZ9j>Tmy z5GKM0W#iDNO-D0t^2DNq%#WE04-_My6(i$z!@1RDphL-pfkJU0sR^qu6<%Y(Nuwbk z#n`-=Fr2=LRFqpi#tv9Nt0-YZn!GxZvQr3(jmQ{4m!zfb3{fkOn2f8Wv{OLWQ;3cg zfI`f<;EcGMLc9)m8QNDGR7=zk1w;yAcYyO9J@{TxBcM^QIt7D-Js|NoS|btb2q0>- z1~?mlXdsdZnMd>uWvG865B0S7UTwQePSve!HCl!9KM$15~#v0lx^Q^x&SlZG2JojnRV#WHfjP zy^dei%OKF56sWa8Q)+LRno}7N=gEGw)Z%q#D;E%gh9K0K4Q&K$9Bgo(;#AuiY*rR$ z0_6~P;q-&a!TIiZ5>7vqbUDX~U0Dqww_qcAq+uE>WpN;&<#~!0@H|b_L-r>431(VX z8nLf z85au&XAB0@zJ!~5$^Ub zht5^qCXc#p?%9`+k9U7vyj7pT#SnSUSt;hv;9~Sn1#a%-hk9J z6rEfg;^l`M2QvF-%`*bM=`H20{MYT2JKHJ6NmWvXpyNe-HWVwUdHBjcK~fvkqS{uT znROANyBE-NRE!E6LI7SlaWy^$=cwQzVBkZRWAn=;hCWp03>A6-2{W&V7tlt6v6_yc zWB5=G>yYHV7wv(zCepR&j9wwihIw*S2nE|Rd4W}v;o|NTZPW2GhfFgoJNm2Hon_Ey zh@hh&j{ZG2s&cq{5MDDF3>tpAL!!NnMS3TRgvG6Qf*BnOj_-2z)ig%()s_LKahW6@|NGG+hySB(YeW*BzVw#g zprLN}qq0Gn%1ND2$z042yAP%g$5?qv!a_c~lZWv5eIV}MGy^2GJ{Imxm-x$v3A`vk zXy*5z0uOOiAoh@ebPbd+4^FsDzzIKxu$P+$Ac9u-*Eca%lFUR`dbL;jSl{f>=}};3 z6m2>(ILg6A={AbzoQxPiMc&upm?Eo9$J7N2tx&MWT1?0}67#5u-BV4FZ(Y%&!pn2BhH)EdG?)(QV4D_k(23B1PEst` ze~%etMnpJY>$f__SKScyO$%I^H2m1_HaYMzVLsGEduk2l8t~eC<)Ekf?CbaXh4eB9 zNRL+3wCJW2z8wqJj&5zMMk@}KGpyr4mEJ)3GOQr|J3?h!BPX;m*jA_tqDQNoM;hAO zp%HEa5c0;flSK%yPm5|=+xTy*M3+asaGw+vg`Q|hr-XF}TVvsZv%_Ab6OoIp%RKA_ zOjahP)+e;BG5^i9)bU~*`G&oJ&7h+V;R3jlFgtsaBs^Ql?Pv>-D)A^CPPDU_WHm;3 z)o_fo*G{y<_y%dA;u}tqkAw1_LF#ZfNkv%=IHEQylfOFDFVY0e_x<7gSKAbTx@;Yh zyH7^NG!F=;JIFz(u)K>8MSw!lK`VSESq=xa`BYUIlqhHajZ5J-9!i#&FC{>a&YZ0} z%p@jSVP0@(UBN!pX(1RC$;HGl6=s9|BnzwWRrUM@^+Fr~I*t}@}OkS?meUN~!X-gjZ-B z!JtiM%~vz|rNMS=lWB3@3?gTB7a|-a8(nbf^4{2V>-!kdj>{Tqy6*yz2i`2l&=njx zMS3KuP_38O8 zgtMcV$?rwlceOnoXpv;W`M6GOkXjCvfuX9a??sSy`40dh0J=S*X5C`PwKhJTxlxUd zlO`oq54-*_G)Tegz`8a&_LD0I9Z17ft8m8LzWSV^HD97wI3% z5$L=&qecFD$+XyFAkzl}L~w;_SOcNyOK-X4Lz~-z}1`wpPcv)NfVQdOqgW49J~D6s7P>KLTuVs&mfsNdKg$t z>Q-B;TcqKzQG8zuDPDUtSRsmM}V2#G@I$yo^<$GJ7ef8N_ zyJVACqEPkxW1NWX9n-DDzwSYb==;^pR{CodTcQ0{kNk@vu};{?l49anV2KkNAzDmq zKF$J7AwyeyMlS;DlH?*#*DZ7&Dlpek=q>aV6BcLDZi2H}Bp4doz$-;tw5SC=#JA>x zwS)M!BNRFE#$`37rmQ->5x+?34U(~Eofr34HvlBmk(Xp0ztxq>(J&x5F}OaQ4R@E) z9mXygUYSi#^O_dq+5!Qjggw+SJODDsLsIDbp1=}+3kZnGj~rPVhrB2Nk8t!}RFF%yL5Pv~2vb_YFu+Ta;mWViA#p%!E1$MC* zXh23T3l98fY(1PNQeW8qM+6M7z`N^(VLFQ`5CAY(R^q9mej|33*r5!QseZRN`+a@UCD& z*ddDy6-W6kmK(&?rIbjqR{#}vhzH5AnwqEh)D?s6vX*yL0gXq#mi)(&>whW|3<7i5=0quY}{9?yHQ(Rmk zA_Kvv$I7%0-25AcgZd$kp|uXeGK=c0cR>Xm!^#p9t^3$*PNWv3fde-wwyJfE9^?CQ7!&6m1JnvZ{4D{O|R3lKdZ-utoY_ zK^cQei#F&{3>DTGit)RD*5>eU@4x^5Z|?kq>pHIczW6~9z#~OSsuW7J>e~9=+ zQIrUQATLRff<%E3K`B&Z<>lew0(ip1dynrufTT@XbfwX#P1-6`^_Qzooy0ThbflSd zrZY*Wp0UQAW||rQ;dtC>J#|~9lZl-~ah%wR6vv7B`JTP^-G^V6+D_uW!Q$@SJ-d7M z?Ade9p51$I_{+`xVa`E)T97+OZ%WvXpJ!LEy+n_Tk}#F;LD{s0_uvF-1Daadj%T-$ zx!Cqr@7?RqijK@c6>J2b7P#m zj<^bT>M)Go;3z$HVgJZMXxmNHhx4GXLwk1ytc5s65)#7G-{!tZ*g*%|LdUm-$Ri?W z^N#SY=fbX%%$1(tj_`Ng+1@+p2Bw^fX<64rU(|EDp&5iV7TacqZ;)BVa(^Mn)G>z5 zLTn3oMLkGS7EmmV%qrdm(HOVPm0)L4q=VX2-r-lfR-@lFV_XGEKXAu3I>4t+NIry3 zLr*7UJ<<6)WwrF!N?1F>>>;N2{V+q1;=+wLqRbLXyzHVl7UA;tm3u?%b$hl{M%wn0 z4F6)^&a>G25bqXtiY4LsxFtKOK(c(1gpB9k$D*#QDI4wrM)az*l_L4w`g93pF7o%rL3p3uYbM z3x`yUBRgOlc#;(O0-o%u0H&7>GSiqG+Z*i1B551mD)qQj=wl zUkn6EpQQKX^U=bGSXUKkA&Jx(?Bc6bUA>)cFs#IRoBSUgkc2H9@k@slc-)>`YVMp* z7XuqF*)b6*vr)(A%r(OF6H;|7NiA#1i`3hNB!dO0)rEg@U)W;SnRr$Mf^M=#8d%VI z;mTA3x6PZjRzilE;)r@RMMV2baf?Vo`J=iXg%>)|w(zZ-MRbq$7#a9bkh(C7SPI5u z+T~+LCa)2Y`w4maI^fi#ue<0g)ltDmrugf*f>?1?%w1-rWq+?#AseBSQUl# z60E`QU-|;lRcvE|b@wkx)ZQAliaTZ8VUOJAjW4P2^;4}udyUa9)3i3Zc((+%Yvz|6 zG&a9X=*fA_?x?Bvz7E+}|18G$oiGn>E&p1wh0V5`*D`n|5`Sl>IVDj@zvgW#=Y~&W z#WCg@J%&NGGXGH>q)9L`t?d(taqZ6K^x4gha8RoSa0Lgt-pHMWL=skBR3W5zkXU)fj zcXYDX#(|VBTj*^|b~ry^5zyBbF9Y7bIreK>h^7Sqt`z1nN)W3=E>)^@J!YlH#;vfaac~CYI#wh3{LxW zQ_~+f-e;L$1&&Ybkw#51Nw8>pF{$xKAGnvSq9lRk4J{^HxnHI?PwixT($a=sd4tvc zFTUq6-O!D&B#T~h60)2~s(stN)YoRRxF!7Dd)lcC-*&S8`92Gq$8Wvd%Ns>K{=Do} z5~K62zU?mut$<-tyamm)`q}<+FZ168t$GzHP!G0sww??>_dX+(R*B)ODqrd4h)1uT zlCmn>;;I+}Ro+UKIvdmaioNqLXjhfIn3O7mF2-4d#nmyW8nIU0^yuI2m)KKyt3eR0 z9_ZWJ5o|rx5|2hge1=vob~0WJTFH|sVf+0emWJAXFTD8Dm+^6Aws9W&O2sKo_f9^7YWdrjMZe8!WGqI`^{WD_@2zi8ga%<4gFU=1ER<`TkPnEt-j+J=T;hN znap44AP;i}vq0O^t>JggfN5DWKS0laZb6@!;%Z5rDSZKj4Ptfg35UIzg*uOca_iL5 zkN>742R+{c>YsN{ki)`m40>)PljePyLH%uQ=jyQ8vMB-xmPp) zCZ*=Kz0QlGHj6;tcIrk-8Nsw-+O1Qz?IPL#(p6~bDAw*?Tuk~fMY|uCRt<~VQDHo0 zJ@;_bRK&LjzS}0MH};o%PI$z736UlXSj}K9RBGOaHRP`|#oqTE7ss7^BY1GaU`SIHP$B$Wz=qOWL<9QMt7!!G*k~&7!Vg&}^R{94K17v86 zYyre9qa#X*|IcQSrfv3pA*lH8Tx=Fvsg+swjqSg51pswbql=4CEpIMF&Mc=F9F^Ss&e-Mu*cHef^r0#D=B% zI7}mh#bOjEhPz)puG0~ocx{8b0prtXYp}2PGJK zBUOwb?8f(L?DQ7s2S5XJDCATfweV*A7QXnZQ?lGq4~W4TB=BcL-!kAHP`#nKhqyb! zTHSknIrn!+)-lqH2N+Z>qeMUUD;f_SvE8BY5!=%>&DOLv$!p)1m`BS4b$Z0B!fwf$zaBhSlXA0fQ&J= zM)kHmKPp_}B7o368!>-clU}mD+dNQzjN&~lWLw!#hjAogAVDYZS`sC+SB_MH%t*)| zz}IbPs8Ct0SN6mtG32|g!`jNs+|Z+WjM64;d8+O}TIfWeJw2gHG%6y`_gh3(9R+9h z(~izT@@5v-MygQYpXn9@)$yyNjF&?e0I%J6Y>400m!r@r$S9N()wP5#{gF%h+-m-# zkXIig8-(S6>kN0x2n1hN(BIKIN`+(q^8P_DX3fvayKwXbIo3HYcp7NL?tdKJmUgkBiQuv*KcW87=Z#TTepexNM5A z%@z(839okH#R&xT$VMbMs?hGMQ$re+q#=fdyVt*KB=FBeU{<`>B0s0yMw}y_ zrUNydHJBn6b}@6Tp$m1IdYc#L?U@Tq)|64=-g&&Bl?|kk3z9=D8!sCz8wBRKQhF@K z)8Q+6eN$iq%hB%U8T$V&O4SyERASdpJHtt{3uVmkYv}0YbvW1S@tV3w}0|$vp z$Y?&Ox5frdw2;!KE_*bFhX5pZG}oD*svs=|Igq~E&{|8&jpgwuxkhuwm@3F{B@~4i zA65sl@1zunWVfgMp7f$}Q)>Vkq}D*p1TqR>3965^H#K+?Yt9;_%r2s& zOcQD_y`T9N|D27-Yct!6L4H77!#u@T2K!@aY2=SUM!UoCkhZc9AB$9AVWu0F95VvG zr-HujDvL-8P_8diwI{8N+vIrcG;ZtknhXfk7RaMJJlgOGqF<`WrVG=9(`JxTDViCY z3f=&c#*h|@wIEiBq2LkVEFma(1cL3L0GFd0@ne{31Zz7YiT1J%GVM4IV0TAsalHkF zGIk;d&eldhl<;z$a&i%T?=JoSC->_AtAVZdd-T?9t(rhH)7Qe02grr9;;mD`%P+}} zx^*Y-NY(QKdznOUWHP_E^f4FS?9BY_M+bWQKDoF5-hKNI9K7$);Lzy9W5>r&oP6d} z&t`w_GdG_9tb5)CH(c-;_i0y)>e*baR?Zi4^}=eQe%<94qx@2KzFf@~mMg_VzEIEB zqv~>@lq+WER+N&fN9)Se>epPPuw1EM5312Zbj{7JELYBR9k?$Dg5k@<#D*{5H+-4+ z!0@&EhOY%A<>uzHwd>2X4KB`8g{Eq?hG>EBME@g#Wc2QKS z73QLBTxnFzfoXm*SIy-aUs`EU9jH>hFke`k>c=8mDc1`1Lb=pjzz@b|IW|CPhPbU> z&6ScW7NQb(FwoU#ZY3YB$xHF6FrE=O0Z^XLR;p!SJqpIXaXjJHAmP?vUw>`i5Fw~l zqP+T33)ZlD08N6l@}OJ_X3O=(0N!7&xdv_vWmvONk4RH{p0Lf`Pg+jrNdmJ_bMtX2 zSR!hwv{0HWFA|D&^P29n_#RpqO+Q?5Eg!`13l+Jt|vMOD|B`MG&Y zxKc!C3agO~Ov=V?IakjwHr-#8EIOTVxfcUfhg?F86$4lwR`xv=iluU(iBhBiK%#1B z`H#d&=_sT##O15tnX5X)geH5iP|Ynbb3cbH;}Vswxaf)-92}}u^Fzg4u{w0lLrgdL z_7$q6`xNyY6HMp`VKCx>xE@s zYRvcz`EmW8&Kq*A^o(Z5=2?dFrcIvnf~8y?%&)^JZgFb>Yc!_w7KOLS^|bJOuw}zB zpKO`G6~awKT#uEtYa_cpC+_TwY1j=lH<5R%f=2uGnZBF}j7!xh+Pq#H8+P0OzWnUT%{7x zn`)Fp&B|y=RhNtNno}@^nr^)$78tgIByxQ*3Z%+SLIqOgL3th-+Em7ivjh`AsbX8B z8ZBT_RkMilD&j^&^U%#H!nO%O+73dmEJJu1JlRSP)5DoP;iEpec4dW(=G-+YrCbRG zR&t-BXl^ztn#lG8Ev;&FwMa}sak9j{2T3WOoyDLtPHxh}O{#G-I>!pum#RjvAx1>Q zhN_9l;wn)^>-D!aliCLfWNNc|zMIWqf3B2FRb1}9Ub)@h{+7{g%X-;HCK#> zq)4Z$+(3F)e5A}WpmYP z4&dl23bnLQUo_Af2HGN)EB|WcMOUb0O@WeEE95a;rGUBNA2yyCm_E$ALTTO==iPd1 zyF5=?US?&XREx~WTaDat8PTJjk4Ed)E72%ZJi0cT>d;YX_~mF6(yTCXT;pSY)vgq&14!N}ixDUo6*Fs*#f&U9IKIL@R|##Pz4%tA95JR#iA@pNYLV@3jJ8$n2<{(C5$(_vJi{Sb=>RvQ%+{et>!SN<7u5=sTQwi zXIThDesVV_3|?J?Piqxr_BX}7O$d*g{Z}g2F`FU08$^gWMzS#Hu%`C)HJ(yjo2gn|8x5sr#Sc>O@ z{y7c3jk{T+>2zh1mdOxBTy15Rwd<^_=VslC27NA9&uQ(poO97^X+C=`>ud?&p7~kV zKR3$XGySz^?VlSM8RhR8?w)nejN0@VRqWbaVWCjBXd0_XNLU)H+^A}?6$HGG<%*@1 zWlPJK>eZsfW{bJflEt7;Wzk|b6c)Q$uFhE`SF9}N6mvi0o_3erPrIkwlkSq6aTnba zZrWXNQ{j|*+?{uixkufkd&He{lT&A<5+_b^?d~2L3K+M*?uJJW-+$zRqYplGEH|5n zrs1j6XC}_N3Eme#fv3aMr_%y$)!1my6?WEEg;yaF6f% zBQ|BZT`2 zhY2HY*bNP-SL%`08naQbT8OUB1vwOGyzsdUcQmU%eP1A8Lbh(NMKIv{Im$ zN}euPuKN`t{(%VfTVVP4p@nfVn5N!0F;}Puu}0e$z+8bUMTwV!JgmFqp`HS#;7lPW z_BW_Opxn?w(+LNMT=&qyOXVeGsgH+Ej+&wA#;(RlV}y{;soR$jr|lHNBmW}}5d34pq&B0%-VEDBYVtkj8n zpM=*G4YTT8M8EDB(^D6;eocd$> zvzC=cp@Ve%Igr7%SDFLD7(sZGo8HEEvOlUAP-NutS`}Cn-wxuv;T<{Pg8jHT^e3r) zpy3s0I6)e-0nq>9T+G)S%D`6Y@Fp!OXJZ?hNCV>wa=2o1djWBN;_}4B?9_!b z6InVsd0~ovY=9dJHUm>7BH5)2k4;P&6RjVPtfp*A?1axYk&*-BO{})Dlqz1soF9dy zttT5+aEW|uqQT75kDt159wJO-8S2L;r^53w6_7MqJ?%d*2-P4My&YCwI+D^8 zj0Gcy9|FegO$r2Q+};_P*$wUK-Ykp3xZu-=h|WiXsmag ze<~H5O%zWi!2Sa&l8!`be)v&DfUpiVVNi=XP6dpVab8+@ql9iM;zzZ?Jn`+Anen(3 za1YeSXlgvsgR#H8!RXekd8sA)<6+b=Nm~vkW9!jvsPZ+XdsB0C(ClbBZ%USBEXIVk zC@rNoo)}FjX~{K!-cnhU)HHvZ%BSWJEC;?dgh^Aj8Lfl9wlz8F6x(dlu`Z0N(5_fm zF4SvdD|l9H3x(ayYJGfkbU6o|=wg$d(V%~G+F0;WYl8wl)06VfkFUV@X|qyhzcuibyw29+WtI$(xMyCDgQYjL*Tcu=_htn? zr2ZyW{OE0LR%qQI`}K&8mPCyg4(Ld&!1fOGXYDQ{YwFm4t*yw|e{H~i1AfS(8Z_KOtZgk@t{|(<18fb~ z@GK<-8hi20sJXuWTAw*CZg4(lXsEx*rxw^o$Ed$(sh}mrXfSc{;)RQ(1|BvTI@mvV za42vWC(b;1dO~}i!Po#_hzqFJA1eqfYMy?JrFzEaU{IME?C-{8XN{lWCaF4b)HyIt z&E4)GNI*K)-14!RBvOlNw%a|)x=Z`I=srIWgZ>JqPx;N5-?yfy|54!6bKQ=ARM^#D z>9Xz-3C2d%(qRJyTtrEoAMTF5U2?~zu2d^5ZRWb*8#(Y4FnZf*VZvnxjc#22H-<&|@aT4W4o zV<{-i9oHl>=baM9+3q@oHV4aPHgv&V7^cn}jbD{w+bj_xC&3#kHG| zA?zURBuvfJ@6TorA0E!4R`BJr3sz^JinB+!oG0Tp4xjT5nHf=YVrnLP%v`tWHgdxI<)P0HcFHrtV+&@d%CkQ3d|2gTWsN)}TJx(}4e(N1{i|`}b zeV_0H!uJT@CA>@ceZqGLzfFDLB7BN+f1kSMxqh4bRjw8CON1ifDZ(YfMM5v(6NGyR zdkA+Ceu{7h;da6nobVa?(GSjxTvurKuZaH; z8lNTaDB&PsJ0S;6u95cy;RN9p0?!kRJ_B@cUKZsnU_;XvUH40NaB5DrIbjs5&|A z+3#3mFGj34GMw_MG2h__*RU=w^BjlAvg`sz^+*uLp_?mVB({- zM%V1O_Yh-AjNuX+xjP9(+MH*W==bUXW6pIq;V#16ggu0h5$+*;obU-kJWEHIrHSA6 zsE5hQ z(sXm;eNFPn;HL5JDNnMaxUGn4$=0zGyyqsgBDb|54gzX$C#zL&Ya0-d)e z)RuHI(YOh%9%vSTDY5R~lvr*{68tr{3*WrF&7(9A>GX|del=3VWN%!Sj_ zkFCOQr{TB9#BXA{El~3O_BVr3%wr4CP(1bxX!9Zf&{QcRP2SgChTN{YNgxfeb zk8a>MBa8c+Z4F)!Kb40)Ke5SYzjxy6++lPkDF+FNRL8XA=(l5U4Bbl**a#u%`WCY6 zu$NWMvh2+4!v9C&>?eRA+~)PhZ$Lot+g`4pg5Hv8TjKNAEM9(sO&cG+OaCR;DqQtj zyk9!B+ue27UAo0O(GSDL8@#%be``1SZQa{li|fjucDp(<%I{Dal?;FD+m83b8nhMY z-l^oB*n+N0$z3vJZgJtyf5&B7cJR;u*E^)+P0_oq9g51lChtEAriVHOvy0?*{WD98 zOOO7-4+L`?_5Gg9d|Y;s8Aq<`HbrG5@h7w3?z``H;a32Xc~f|L6C1G2B~gh?gvdpk~hl=x$WnfkHx#49&; z#?Q_*`EmO@z<-rCXX=NCH$DGH9m460z^Og`zQ>h?6bFSI$AwgOWTaSL!1o-2Dfl)bNm;mL%**vrYe7l&|LmW?w=z3G@%IWjTpzT5*Ph16Q1V% zE#K#BX#>)symbol_type() == SYMBOL_TERMINAL) { if(sym->lexeme_type() == LEXEME_LITERAL) @@ -331,7 +331,12 @@ static void ouptputTerminal(const GrammarSymbol *sym) printf("\"%s\"", sym->lexeme().c_str()); } else - printf("%s", sym->lexeme().c_str()); + { + if(asHtml) + printf("%s", sym->lexeme().c_str(), sym->lexeme().c_str()); + else + printf("%s", sym->lexeme().c_str()); + } } static bool isTerminalRegex(const GrammarSymbol *symbol) @@ -340,11 +345,37 @@ static bool isTerminalRegex(const GrammarSymbol *symbol) && symbol->lexeme_type() == LexemeType::LEXEME_REGULAR_EXPRESSION; } +static bool isTerminalOrRegex(const GrammarSymbol *symbol) +{ + return symbol->symbol_type() == SymbolType::SYMBOL_TERMINAL + || symbol->lexeme_type() == LexemeType::LEXEME_REGULAR_EXPRESSION; +} + static bool isTerminal(const GrammarSymbol *symbol) { return symbol->symbol_type() == SymbolType::SYMBOL_TERMINAL; } +static bool IsTerminalProduction(const GrammarSymbol *symbol, const GrammarProduction* production, bool hasMoreProductions) +{ + return (isTerminalRegex(symbol) + || (!hasMoreProductions && production->length() == 1 && isTerminal(production->symbol_by_position(0)))); + +} + +static bool isProductionTerminal(const GrammarSymbol *symbol) +{ + if(isTerminalOrRegex(symbol)) return true; + if(symbol->symbol_type() == SymbolType::SYMBOL_NON_TERMINAL) + { + if(symbol->productions().size() == 1) + { + return isTerminalOrRegex(symbol->productions()[0]->symbol_by_position(0)); + } + } + return false; +} + void Grammar::genEBNF() { printf( @@ -409,8 +440,9 @@ void Grammar::genEBNF() printf("\n\n// end EBNF\n"); } -void Grammar::genYACC() +void Grammar::genYACC(bool asHtml) { + if(asHtml) printf("\nYacc HTML linked for %s\n
    \n", identifier().c_str());
         const char *prefix = "";
         printf(
                 "//\n"
    @@ -431,8 +463,7 @@ void Grammar::genYACC()
             bool hasMoreProductions = same_production || (production_next != productions().end() && production_next->get()->symbol() == curr_symbol);
             if(!same_production)
             {
    -            if( isTerminalRegex(curr_symbol)
    -                        || (!hasMoreProductions && production->length() == 1 && isTerminal(production->symbol_by_position(0))) )
    +            if(IsTerminalProduction(curr_symbol, production, hasMoreProductions))
                 {
                     printf("%%token %s ;\n", curr_symbol->lexeme().c_str());
                 }
    @@ -516,8 +547,7 @@ void Grammar::genYACC()
             bool same_production = last_production_symbol && last_production_symbol == curr_symbol;
             vector>::const_iterator production_next = (i+1);
             bool hasMoreProductions = same_production || (production_next != productions().end() && production_next->get()->symbol() == curr_symbol);
    -        if (isTerminalRegex(curr_symbol)
    -                    || (!hasMoreProductions && production->length() == 1 && isTerminal(production->symbol_by_position(0))))
    +        if(IsTerminalProduction(curr_symbol, production, hasMoreProductions))
             {
                 continue;
             }
    @@ -538,7 +568,11 @@ void Grammar::genYACC()
                 {
                     printf("\n%s\t;", prefix);
                 }
    -            printf("\n\n%s%s%s :\n%s\t", prefix, sym_prefix, sym_name, prefix);
    +            printf("\n\n%s%s", prefix, sym_prefix);
    +            if(asHtml)
    +                printf("%s :\n%s\t", sym_name, sym_name, prefix);
    +            else
    +                printf("%s :\n%s\t", sym_name, prefix);
             }
             if(production->length() > 0) {
                 for(int elm=0; elm < production->length(); ++elm) {
    @@ -548,7 +582,7 @@ void Grammar::genYACC()
                         printf("\n%s\t| ", prefix);
                     }
                     else printf(" ");
    -                ouptputTerminal(sym);
    +                ouptputTerminal(sym, asHtml ? !isProductionTerminal(sym) : false);
                 }
             }
             else {
    @@ -569,6 +603,7 @@ void Grammar::genYACC()
             printf("\n%s\t;", prefix);
         }
         printf("\n\n// end YACC\n");
    +    if(asHtml) printf("
    \n\n\n"); } void Grammar::genNakedGrammar() @@ -634,14 +669,14 @@ GrammarSymbol* Grammar::regex_symbol(const char* lexeme, int line , int column) return add_symbol(lexeme, line, column, LEXEME_REGULAR_EXPRESSION, SYMBOL_TERMINAL ); } -GrammarSymbol* Grammar::non_terminal_symbol(const char* lexeme, int line , int column) +GrammarSymbol* Grammar::non_terminal_symbol(const char* lexeme, int line , int column, bool update_line_col) { LALR_ASSERT( lexeme ); LALR_ASSERT( line >= 0 ); - return add_symbol(lexeme, line, column, LEXEME_NULL, SYMBOL_NON_TERMINAL ); + return add_symbol(lexeme, line, column, LEXEME_NULL, SYMBOL_NON_TERMINAL, update_line_col ); } -GrammarSymbol* Grammar::add_symbol(const char* lexeme, int line, int column, LexemeType lexeme_type, SymbolType symbol_type ) +GrammarSymbol* Grammar::add_symbol(const char* lexeme, int line, int column, LexemeType lexeme_type, SymbolType symbol_type, bool update_line_col ) { LALR_ASSERT( lexeme ); LALR_ASSERT( line >= 0 ); @@ -663,6 +698,11 @@ GrammarSymbol* Grammar::add_symbol(const char* lexeme, int line, int column, Lex GrammarSymbol* symbol = i->get(); LALR_ASSERT( symbol ); LALR_ASSERT( symbol->symbol_type() == symbol_type ); + if(update_line_col) + { + symbol->set_line( line ); + symbol->set_column( column ); + } return symbol; } diff --git a/src/lalr/Grammar.hpp b/src/lalr/Grammar.hpp index bcde285..9b08b1c 100644 --- a/src/lalr/Grammar.hpp +++ b/src/lalr/Grammar.hpp @@ -75,14 +75,14 @@ class Grammar bool is_error_recovery_off() const {return error_recovery_off_;} bool is_error_recovery_show() const {return error_recovery_show_;} void genEBNF(); - void genYACC(); + void genYACC(bool asHtml=false); void genNakedGrammar(); private: GrammarSymbol* literal_symbol(const char* lexeme, int line , int column); GrammarSymbol* regex_symbol(const char* lexeme, int line , int column); - GrammarSymbol* non_terminal_symbol(const char* lexeme, int line , int column); - GrammarSymbol* add_symbol(const char* lexeme, int line, int column, LexemeType lexeme_type, SymbolType symbol_type ); + GrammarSymbol* non_terminal_symbol(const char* lexeme, int line , int column, bool update_line_col = false ); + GrammarSymbol* add_symbol(const char* lexeme, int line, int column, LexemeType lexeme_type, SymbolType symbol_type, bool update_line_col = false ); GrammarProduction* add_production(GrammarSymbol* symbol, int line , int column); GrammarAction* add_action( const char* id ); }; diff --git a/src/lalr/GrammarCompiler.cpp b/src/lalr/GrammarCompiler.cpp index 1c30acd..9d52e05 100644 --- a/src/lalr/GrammarCompiler.cpp +++ b/src/lalr/GrammarCompiler.cpp @@ -73,7 +73,7 @@ void GrammarCompiler::labels_enabled( bool enabled ) labels_enabled_ = enabled; } -int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* error_policy, bool genEBNF, bool genYACC ) +int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* error_policy, bool genEBNF, bool genYACC, bool genYACC_HTML ) { Grammar grammar; @@ -92,6 +92,11 @@ int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* e grammar.genYACC(); return errors; } + if(genYACC_HTML) + { + grammar.genYACC(true); + return errors; + } bool isCaseInsensitive = grammar.is_case_insensitive(); GrammarGenerator generator; errors = generator.generate( grammar, error_policy ); @@ -353,8 +358,10 @@ void GrammarCompiler::populate_parser_state_machine( const Grammar& grammar, con set_symbols( symbols, symbols_size ); set_transitions( transitions, transitions_size ); set_states( states, states_size, start_state ); - parser_state_machine_->shift_reduce_count_ = generator.shift_reduce_count(); - parser_state_machine_->reduce_reduce_count_ = generator.reduce_reduce_count(); + parser_state_machine_->shift_reduce_count = generator.shift_reduce_count(); + parser_state_machine_->reduce_reduce_count = generator.reduce_reduce_count(); + parser_state_machine_->error_recovery_off = generator.is_error_recovery_off(); + parser_state_machine_->error_recovery_show = generator.is_error_recovery_show(); } #include "LexerStateMachine.hpp" @@ -367,7 +374,8 @@ void GrammarCompiler::showStats() printf(" Actions : %d\n", psm->actions_size); printf(" States : %d\n", psm->states_size); printf(" Transitions : %d\n", psm->transitions_size); - printf(" Solved conflicts : shift/reduce = %d, reduce/reduce = %d\n", psm->shift_reduce_count_, psm->reduce_reduce_count_); + printf(" Solved conflicts : shift/reduce = %d, reduce/reduce = %d\n", psm->shift_reduce_count, psm->reduce_reduce_count); + printf(" Error recovery : %d\n", psm->error_recovery_off); const LexerStateMachine* lsm = lexer_->state_machine(); if(!lsm) return; printf("Lexer state machine stats:\n"); diff --git a/src/lalr/GrammarCompiler.hpp b/src/lalr/GrammarCompiler.hpp index 4324220..1da109c 100644 --- a/src/lalr/GrammarCompiler.hpp +++ b/src/lalr/GrammarCompiler.hpp @@ -39,7 +39,7 @@ class GrammarCompiler const RegexCompiler* whitespace_lexer() const; const ParserStateMachine* parser_state_machine() const; void labels_enabled( bool enabled ); - int compile( const char* begin, const char* end, ErrorPolicy* error_policy = nullptr, bool genEBNF = false, bool genYACC = false ); + int compile( const char* begin, const char* end, ErrorPolicy* error_policy = nullptr, bool genEBNF = false, bool genYACC = false, bool genYACC_HTML = false ); void showStats(); private: diff --git a/src/lalr/GrammarGenerator.cpp b/src/lalr/GrammarGenerator.cpp index 954b79e..b11ae43 100644 --- a/src/lalr/GrammarGenerator.cpp +++ b/src/lalr/GrammarGenerator.cpp @@ -69,6 +69,8 @@ GrammarGenerator::GrammarGenerator() , errors_( 0 ) , shift_reduce_count_( 0 ) , reduce_reduce_count_( 0 ) +, error_recovery_off_( false ) +, error_recovery_show_( false ) { #ifndef LALR_NO_THREADS thread_pool_ = new ThreadPool; @@ -192,7 +194,9 @@ int GrammarGenerator::generate( Grammar& grammar, ErrorPolicy* error_policy ) whitespace_symbol_ = grammar.whitespace_symbol(); start_state_ = nullptr; errors_ = 0; - + error_recovery_off_ = grammar.is_error_recovery_off(); + error_recovery_show_ = grammar.is_error_recovery_show(); + calculate_identifiers(); check_for_undefined_symbol_errors(); check_for_unreferenced_symbol_errors(); @@ -231,14 +235,14 @@ int GrammarGenerator::generate( Grammar& grammar, ErrorPolicy* error_policy ) // @param ... // Arguments described by *format*. */ -void GrammarGenerator::error( int line, int error, const char* format, ... ) +void GrammarGenerator::error(int line, int column, int error, const char* format, ... ) { ++errors_; if ( error_policy_ ) { va_list args; va_start( args, format ); - error_policy_->lalr_error( line, 0, error, format, args ); + error_policy_->lalr_error( line, column, error, format, args ); va_end( args ); } } @@ -408,7 +412,7 @@ void GrammarGenerator::check_for_undefined_symbol_errors() LALR_ASSERT( symbol ); if ( symbol->symbol_type() == SYMBOL_NON_TERMINAL && symbol->productions().empty() && (symbol->referenced_in_rule() || !symbol->referenced_in_precedence_directive()) ) { - error( symbol->line(), PARSER_ERROR_UNDEFINED_SYMBOL, "undefined symbol '%s'", symbol->identifier().c_str(), identifier_.c_str() ); + error(symbol->line(), symbol->column(), PARSER_ERROR_UNDEFINED_SYMBOL, "undefined symbol '%s'", symbol->identifier().c_str(), identifier_.c_str()); } } } @@ -444,7 +448,8 @@ void GrammarGenerator::check_for_unreferenced_symbol_errors() if ( references == 0 ) { - error( symbol->line(), PARSER_ERROR_UNREFERENCED_SYMBOL, "unreferenced symbol '%s'/'%s'", symbol->identifier().c_str(), symbol->lexeme().c_str() ); + error(symbol->line(), symbol->column(), PARSER_ERROR_UNREFERENCED_SYMBOL, "unreferenced symbol '%s'/'%s'", + symbol->identifier().c_str(), symbol->lexeme().c_str()); } } } @@ -474,7 +479,9 @@ void GrammarGenerator::check_for_implicit_terminal_duplicate_associativity() bool non_terminal_associates = non_terminal->associativity() != ASSOCIATE_NULL; if ( terminal_associates && non_terminal_associates ) { - error( terminal->line(), PARSER_ERROR_DUPLICATE_ASSOCIATION_ON_IMPLICIT_TERMINAL, "implicit terminal '%s'/%s' specifies associativity and precedence on both forms", terminal->lexeme().c_str(), non_terminal->lexeme().c_str() ); + error(terminal->line(), terminal->column(), PARSER_ERROR_DUPLICATE_ASSOCIATION_ON_IMPLICIT_TERMINAL, + "implicit terminal '%s'/%s' specifies associativity and precedence on both forms", + terminal->lexeme().c_str(), non_terminal->lexeme().c_str()); } } } @@ -498,7 +505,7 @@ void GrammarGenerator::check_for_error_symbol_on_left_hand_side_errors() LALR_ASSERT( symbol ); if ( !symbol->productions().empty() && symbol->lexeme() == error_symbol_->lexeme() ) { - error( 1, PARSER_ERROR_ERROR_SYMBOL_ON_LEFT_HAND_SIDE, "error appears on the left hand side of a production" ); + error(symbol->line(), symbol->column(), PARSER_ERROR_ERROR_SYMBOL_ON_LEFT_HAND_SIDE, "error appears on the left hand side of a production" ); } } } @@ -575,7 +582,8 @@ void GrammarGenerator::calculate_implicit_terminal_symbols() } else if(non_terminal_symbol->associativity() != ASSOCIATE_NULL && non_terminal_symbol->productions().size()) { - error( non_terminal_symbol->line(), PARSER_ERROR_ASSOCIATIVITY_ASSIGNED_ON_NON_TERMINAL, "associativity has been assigned to a non-terminal: %s", non_terminal_symbol->identifier().c_str()); + error(non_terminal_symbol->line(), non_terminal_symbol->column(), PARSER_ERROR_ASSOCIATIVITY_ASSIGNED_ON_NON_TERMINAL, + "associativity has been assigned to a non-terminal: %s", non_terminal_symbol->identifier().c_str()); } } } @@ -968,7 +976,7 @@ void GrammarGenerator::generate_reduce_transitions() { GrammarState* state = i->get(); LALR_ASSERT( state ); - + //printf("state %d\n", state->index()); for ( set::const_iterator item = state->items().begin(); item != state->items().end(); ++item ) { const GrammarProduction* production = productions_[item->production()].get(); @@ -984,7 +992,25 @@ void GrammarGenerator::generate_reduce_transitions() { const GrammarSymbol* symbol = symbols_[index].get(); LALR_ASSERT( symbol ); - generate_reduce_transition( state, symbol, production ); + const GrammarProduction* production_curr; + size_t prod_idx = item->production()+index; + if(prod_idx < productions_.size()) + { + production_curr = productions_[prod_idx].get(); +/* + printf("\t%s : ", production->symbol()->identifier().c_str()); + short the_dot = 0; + for ( vector::const_iterator ips = production_curr->symbols().begin(); ips != production_curr->symbols().end(); ++ips ) + { + GrammarSymbol *symbol = *ips; + printf(" %s", symbol->identifier().c_str()); + if(++the_dot == item->position() ) printf(" * "); + } + printf("\n"); + */ + } + else production_curr = nullptr; + generate_reduce_transition( state, symbol, production, production_curr ? production_curr : production ); } } } @@ -1004,7 +1030,7 @@ void GrammarGenerator::generate_reduce_transitions() // @param production // The GrammarProduction that is to be reduced. */ -void GrammarGenerator::generate_reduce_transition( GrammarState* state, const GrammarSymbol* symbol, const GrammarProduction* production ) +void GrammarGenerator::generate_reduce_transition( GrammarState* state, const GrammarSymbol* symbol, const GrammarProduction* production, const GrammarProduction* curr_production ) { LALR_ASSERT( state ); LALR_ASSERT( symbol ); @@ -1021,7 +1047,15 @@ void GrammarGenerator::generate_reduce_transition( GrammarState* state, const Gr { if ( production->precedence() == 0 || symbol->precedence() == 0 || (symbol->precedence() == production->precedence() && symbol->associativity() == ASSOCIATE_NULL) ) { - error( production->line(), PARSER_ERROR_PARSE_TABLE_CONFLICT, "shift/reduce conflict for '%s' on '%s'", production->symbol()->identifier().c_str(), symbol->lexeme().c_str() ); + error( production->line(), production->column(), PARSER_ERROR_PARSE_TABLE_CONFLICT, "shift/reduce conflict for '%s' on '%s'", production->symbol()->identifier().c_str(), symbol->lexeme().c_str() ); +/* + error(curr_production->line(), curr_production->column(), + PARSER_ERROR_PARSE_TABLE_CONFLICT, "shift/reduce conflict for '%s' on '%s'\n\t=> lalr (%d:%d): shift on '%s'\n\t=> lalr (%d:%d): reduce on '%s'", + production->symbol()->identifier().c_str(), symbol->lexeme().c_str(), + transition->symbol()->line(), transition->symbol()->column(), transition->symbol()->identifier().c_str(), + production->line(), production->column(), production->symbol()->identifier().c_str()); + +*/ } else if ( production->precedence() > symbol->precedence() || (symbol->precedence() == production->precedence() && symbol->associativity() == ASSOCIATE_RIGHT) ) { @@ -1034,7 +1068,15 @@ void GrammarGenerator::generate_reduce_transition( GrammarState* state, const Gr LALR_ASSERT( transition->is_reduce() ); if ( production->precedence() == 0 || transition->precedence() == 0 || production->precedence() == transition->precedence() ) { - error( production->line(), PARSER_ERROR_PARSE_TABLE_CONFLICT, "reduce/reduce conflict for '%s' and '%s' on '%s'", production->symbol()->identifier().c_str(), transition->reduced_symbol()->identifier().c_str(), symbol->lexeme().c_str() ); + error( production->line(), production->column(), PARSER_ERROR_PARSE_TABLE_CONFLICT, "reduce/reduce conflict for '%s' and '%s' on '%s'", production->symbol()->identifier().c_str(), transition->reduced_symbol()->identifier().c_str(), symbol->lexeme().c_str() ); +/* + error(curr_production->line(), curr_production->column(), + PARSER_ERROR_PARSE_TABLE_CONFLICT, "reduce/reduce conflict for '%s' and '%s' on '%s'\n\t=> lalr (%d:%d): reduce on '%s'\n\t=> lalr (%d:%d): reduce on '%s'", + production->symbol()->identifier().c_str(), transition->reduced_symbol()->identifier().c_str(), symbol->lexeme().c_str(), + transition->symbol()->line(), transition->symbol()->column(), transition->symbol()->identifier().c_str(), + transition->production()->line(), transition->production()->column(), transition->production()->symbol()->identifier().c_str()); + +*/ } else if ( production->precedence() > transition->precedence() ) { diff --git a/src/lalr/GrammarGenerator.hpp b/src/lalr/GrammarGenerator.hpp index 08df641..195c0b7 100644 --- a/src/lalr/GrammarGenerator.hpp +++ b/src/lalr/GrammarGenerator.hpp @@ -54,6 +54,8 @@ class GrammarGenerator int errors_; ///< The number of errors that occured during parsing and generation. int shift_reduce_count_; ///< The number of shift/reduce resolved conflicts that occured during parsing and generation. int reduce_reduce_count_; ///< The number of reduce/reduce resolved conflicts that occured during parsing and generation. + bool error_recovery_off_; ///< True iff we want to turn off error recovery for debug. + bool error_recovery_show_; ///< True iff we want to show error recovery for debug. public: GrammarGenerator(); @@ -69,9 +71,11 @@ class GrammarGenerator int generate( Grammar& grammar, ErrorPolicy* error_policy ); int shift_reduce_count() const {return shift_reduce_count_;} int reduce_reduce_count() const {return reduce_reduce_count_;} + bool is_error_recovery_off() const {return error_recovery_off_;} + bool is_error_recovery_show() const {return error_recovery_show_;} private: - void error( int line, int error, const char* format, ... ); + void error( int line, int column, int error, const char* format, ... ); GrammarTransition* shift_transition( const GrammarSymbol* symbol, GrammarState* state ); GrammarTransition* reduce_transition( const GrammarSymbol* symbol, const GrammarProduction* production ); GrammarSymbolSet spontaneous_lookaheads( const GrammarItem& item ) const; @@ -97,7 +101,7 @@ class GrammarGenerator void generate_states( const GrammarSymbol* start_symbol, const GrammarSymbol* end_symbol, const std::vector>& symbols ); void generate_indices_for_states(); void generate_reduce_transitions(); - void generate_reduce_transition( GrammarState* state, const GrammarSymbol* symbol, const GrammarProduction* production ); + void generate_reduce_transition( GrammarState* state, const GrammarSymbol* symbol, const GrammarProduction* production, const GrammarProduction* curr_production ); void generate_indices_for_transitions(); }; diff --git a/src/lalr/GrammarParser.cpp b/src/lalr/GrammarParser.cpp index dd05c47..52fc92b 100644 --- a/src/lalr/GrammarParser.cpp +++ b/src/lalr/GrammarParser.cpp @@ -100,7 +100,7 @@ bool GrammarParser::match_whitespace_statement() grammar_->whitespace(); if ( match_regex() ) { - grammar_->regex( lexeme_.c_str(), line_, get_line_column(position_) ); + grammar_->regex( lexeme_.c_str(), line_, get_line_column(position_, lexeme_) ); } expect( ";" ); return true; @@ -141,7 +141,7 @@ bool GrammarParser::match_production_statement() { if ( match_identifier() ) { - grammar_->production( lexeme_.c_str(), line_, get_line_column(position_) ); + grammar_->production( lexeme_.c_str(), line_, get_line_column(position_, lexeme_)); expect( ":" ); match_expressions(); expect( ";" ); @@ -168,17 +168,17 @@ bool GrammarParser::match_symbol() } else if ( match_literal() ) { - grammar_->literal( lexeme_.c_str(), line_, get_line_column(position_) ); + grammar_->literal( lexeme_.c_str(), line_, get_line_column(position_, lexeme_) ); return true; } else if ( match_regex() ) { - grammar_->regex( lexeme_.c_str(), line_, get_line_column(position_) ); + grammar_->regex( lexeme_.c_str(), line_, get_line_column(position_, lexeme_) ); return true; } else if ( match_identifier() ) { - grammar_->identifier( lexeme_.c_str(), line_, get_line_column(position_) ); + grammar_->identifier( lexeme_.c_str(), line_, get_line_column(position_, lexeme_) ); return true; } return false; @@ -243,7 +243,7 @@ bool GrammarParser::match_action() { if ( match_identifier() ) { - grammar_->action( lexeme_.c_str(), line_, get_line_column(position_) ); + grammar_->action( lexeme_.c_str(), line_, get_line_column(position_, lexeme_) ); } expect( "]" ); return true; @@ -527,5 +527,9 @@ bool GrammarParser::is_new_line( const char* position ) int GrammarParser::get_line_column(const char* position) { return position - line_position_; +} +int GrammarParser::get_line_column(const char* position, const std::string &subtract_str_size) +{ + return get_line_column(position) - subtract_str_size.size(); } diff --git a/src/lalr/GrammarParser.hpp b/src/lalr/GrammarParser.hpp index 46d9a50..9ac9721 100644 --- a/src/lalr/GrammarParser.hpp +++ b/src/lalr/GrammarParser.hpp @@ -58,6 +58,7 @@ class GrammarParser const char* new_line( const char* position ); static bool is_new_line( const char* position ); int get_line_column(const char* position); + int get_line_column(const char* position, const std::string &subtract_str_size); }; } diff --git a/src/lalr/Parser.ipp b/src/lalr/Parser.ipp index a48c0c5..2a142c5 100644 --- a/src/lalr/Parser.ipp +++ b/src/lalr/Parser.ipp @@ -760,12 +760,16 @@ void Parser::error( bool* accepted, const ParserSymbol* symbol = reinterpret_cast( lexer_.symbol() ); const ParserState* state = !nodes_.empty() ? nodes_.back().state() : nullptr; - bool handled = false; + bool handled = state_machine_->error_recovery_off; while ( !nodes_.empty() && !handled && !*accepted && !*rejected ) { const ParserTransition* transition = find_transition( state_machine_->error_symbol, nodes_.back().state() ); if ( transition ) { + if(state_machine_->error_recovery_show) + { + printf("===>>Parser error recovering at: %d:%d\n", line, column); + } if ( transition->state ) { shift( transition, std::basic_string(), line, column ); @@ -784,7 +788,7 @@ void Parser::error( bool* accepted, } } - if ( nodes_.empty() ) + if ( nodes_.empty() || state_machine_->error_recovery_off ) { if ( symbol ) { diff --git a/src/lalr/ParserStateMachine.hpp b/src/lalr/ParserStateMachine.hpp index 79252bf..778ffd0 100644 --- a/src/lalr/ParserStateMachine.hpp +++ b/src/lalr/ParserStateMachine.hpp @@ -28,8 +28,10 @@ class ParserStateMachine int symbols_size; ///< The number of symbols. int transitions_size; ///< The total number of transitions. int states_size; ///< The number of states. - int shift_reduce_count_; ///< The number of shift/reduce resolved conflicts that occured during parsing and generation. - int reduce_reduce_count_; ///< The number of reduce/reduce resolved conflicts that occured during parsing and generation. + int shift_reduce_count; ///< The number of shift/reduce resolved conflicts that occured during parsing and generation. + int reduce_reduce_count; ///< The number of reduce/reduce resolved conflicts that occured during parsing and generation. + bool error_recovery_off; ///< For debug purposes turn off error recovery + bool error_recovery_show; ///< For debug purposes show error recovery as it happens const ParserAction* actions; ///< The parser actions for this ParserStateMachine. const ParserSymbol* symbols; ///< The symbols in the grammar for this ParserStateMachine. const ParserTransition* transitions; ///< The transitions in the state machine for this ParserStateMachine. From 2e1ef74602df65b6c59eedf84bbb41f215c9429e Mon Sep 17 00:00:00 2001 From: Domingo Alvarez Duarte Date: Tue, 14 Nov 2023 16:04:21 +0100 Subject: [PATCH 40/40] Create static.yml --- .github/workflows/static.yml | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/static.yml diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 0000000..4d9fbaa --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,43 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["playground"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Pages + uses: actions/configure-pages@v3 + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + with: + # Upload entire repository + path: './playground' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2