| lalr_examples | ||
| lalr_test | ||
| lalrc | ||
| .gitignore | ||
| AddLexerActionHandler.hpp | ||
| AddLexerActionHandler.ipp | ||
| AddParserActionHandler.hpp | ||
| AddParserActionHandler.ipp | ||
| assert.hpp | ||
| Associativity.hpp | ||
| build.lua | ||
| ErrorCode.hpp | ||
| ErrorPolicy.cpp | ||
| ErrorPolicy.hpp | ||
| Grammar.cpp | ||
| Grammar.hpp | ||
| GrammarAction.cpp | ||
| GrammarAction.hpp | ||
| GrammarCompiler.cpp | ||
| GrammarCompiler.hpp | ||
| GrammarGenerator.cpp | ||
| GrammarGenerator.hpp | ||
| GrammarItem.cpp | ||
| GrammarItem.hpp | ||
| GrammarParser.cpp | ||
| GrammarParser.hpp | ||
| GrammarProduction.cpp | ||
| GrammarProduction.hpp | ||
| GrammarState.cpp | ||
| GrammarState.hpp | ||
| GrammarStateLess.cpp | ||
| GrammarStateLess.hpp | ||
| GrammarSymbol.cpp | ||
| GrammarSymbol.hpp | ||
| GrammarSymbolLess.cpp | ||
| GrammarSymbolLess.hpp | ||
| GrammarTransition.cpp | ||
| GrammarTransition.hpp | ||
| lalr.build | ||
| LexemeType.hpp | ||
| Lexer.hpp | ||
| Lexer.ipp | ||
| LexerAction.hpp | ||
| LexerState.hpp | ||
| LexerStateMachine.hpp | ||
| LexerTransition.hpp | ||
| LICENSE | ||
| Parser.hpp | ||
| Parser.ipp | ||
| ParserAction.hpp | ||
| ParserNode.hpp | ||
| ParserNode.ipp | ||
| ParserState.hpp | ||
| ParserStateMachine.hpp | ||
| ParserSymbol.hpp | ||
| ParserTransition.hpp | ||
| ParserUserData.hpp | ||
| ParserUserData.ipp | ||
| PositionIterator.hpp | ||
| README.md | ||
| RegexAction.cpp | ||
| RegexAction.hpp | ||
| RegexCharacter.cpp | ||
| RegexCharacter.hpp | ||
| RegexCompiler.cpp | ||
| RegexCompiler.hpp | ||
| RegexGenerator.cpp | ||
| RegexGenerator.hpp | ||
| RegexItem.cpp | ||
| RegexItem.hpp | ||
| RegexNode.cpp | ||
| RegexNode.hpp | ||
| RegexNodeLess.cpp | ||
| RegexNodeLess.hpp | ||
| RegexNodeType.hpp | ||
| RegexParser.cpp | ||
| RegexParser.hpp | ||
| RegexState.cpp | ||
| RegexState.hpp | ||
| RegexStateLess.cpp | ||
| RegexStateLess.hpp | ||
| RegexSyntaxTree.cpp | ||
| RegexSyntaxTree.hpp | ||
| RegexToken.cpp | ||
| RegexToken.hpp | ||
| RegexTokenType.hpp | ||
| RegexTransition.cpp | ||
| RegexTransition.hpp | ||
| SymbolType.hpp | ||
| TransitionType.hpp | ||
lalr
lalr is a modern LALR(1) parser and parser generator.
Features:
- LALR(1) parser generation from a BNF grammar DSL in C++.
- Separate generation step is optional.
- Lexer actions for escape character conversion.
- Lexer actions for feedback from the parser to the lexer.
- Bind parser and lexer actions to
std::tr1::functionobjects. - Lexical tokens can be specified inline in the grammar.
- Re-entrant and thread-safe.
Example
#include <stdio.h>
#include <stdarg.h>
#include <sweet/lalr/ParserStateMachine.hpp>
#include <sweet/lalr/Parser.ipp>
#include <sweet/lalr/Grammar.hpp>
#include <string.h>
using namespace std;
using namespace sweet;
using namespace sweet::lalr;
static int add( const ParserSymbol* symbol, const ParserNode<int>* start, const ParserNode<int>* finish )
{
return start[0].get_user_data() + start[2].get_user_data();
}
static int subtract( const ParserSymbol* symbol, const ParserNode<int>* start, const ParserNode<int>* finish )
{
return start[0].get_user_data() - start[2].get_user_data();
}
static int multiply( const ParserSymbol* symbol, const ParserNode<int>* start, const ParserNode<int>* finish )
{
return start[0].get_user_data() * start[2].get_user_data();
}
static int divide( const ParserSymbol* symbol, const ParserNode<int>* start, const ParserNode<int>* finish )
{
return start[0].get_user_data() / start[2].get_user_data();
}
static int compound( const ParserSymbol* symbol, const ParserNode<int>* start, const ParserNode<int>* finish )
{
return start[1].get_user_data();
}
static int integer( const ParserSymbol* symbol, const ParserNode<int>* start, const ParserNode<int>* finish )
{
return ::atoi( start[0].get_lexeme().c_str() );
}
void parser_calculator_example()
{
const char* calculator_grammar =
"calculator { \n"
" %left '+' '-'; \n"
" %left '*' '/'; \n"
" %none integer; \n"
" %whitespace \"[ \t\r\n]*\"; \n"
" expr: \n"
" expr '+' expr [add] | \n"
" expr '-' expr [subtract] | \n"
" expr '*' expr [multiply] | \n"
" expr '/' expr [divide] | \n"
" '(' expr ')' [compound] | \n"
" integer [integer] \n"
" ; \n"
" integer: \"[0-9]+\"; \n"
"} \n"
;
GrammarCompiler compiler;
compiler.compile( calculator_grammar, calculator_grammar + strlen(calculator_grammar) );
Parser<const char*, int> parser( compiler.parser_state_machine() );
parser.parser_action_handlers()
( "add", &add )
( "subtract", &subtract )
( "multiply", &multiply )
( "divide", ÷ )
( "compound", &compound )
( "integer", &integer )
;
const char* input = "1 + 2 * (3 + 4) + 5";
parser.parse( input, input + strlen(input) );
SWEET_ASSERT( parser.accepted() );
SWEET_ASSERT( parser.full() );
SWEET_ASSERT( parser.user_data() == 20 );
}
Installation
Use lalr in your own project by adding the lalr source to your build scripts or IDE project files and compiling as C++.
lalr is built for development using Sweet Build and a C++ compiler (XCode, Visual C++, or GCC depending on operating system).
macOS
- Install Xcode
- Install Sweet Build
git clone git@github.com:cwbaker/lalr.git lalrcd lalr/srcbuild variant=release./release/bin/lalr_examples
Windows:
- Install Visual Studio 2017
- Install Sweet Build
git clone git@github.com:cwbaker/lalr.git lalrcd lalr\srcbuild variant=release.\release\bin\lalr_examples.exe
Usage
lalr is a C++ library that generates LALR(1) parsers from a BNF grammar expressed as a C++ string and built at run-time or stored in a file and built at build-time.
Generate parsers at run-time as follows:
-
Create a grammar and embed it as a string in your C++ program taking care to escape backslashes and other C++ escape characters correctly.
-
Create a
GrammarCompilerobject and callGrammarCompiler::compile()to compile the grammar into a state machine. -
Create one or more
Parserobjects from the state machine returned byGrammarCompiler::parser_state_machine(). -
Pass input to the
Parserobjects as an iterator range to have the parser use its built-in lexer and process the input all at once. Pass input as separate pairs of symbols and lexemes to drive the parser using an external lexer. -
Implement the
ErrorPolicyinterface to be notified of errors and optional debug output during parser generation and parsing.
Generate parsers at build-time using the lalrc tool:
-
Create a grammar and save it to a text file.
-
Run
lalrcto compile the grammar into a state machine in a generated C++ source file and compile and link/archive it into your executable/library. -
Create one or more
Parserobjects from the state machine referenced by name as an external symbol. -
Pass input to the
Parserobjects as an iterator range to have the parser use its built-in lexer and process the input all at once. Pass input as separate pairs of symbols and lexemes to drive the parser using an external lexer. -
Implement the
ErrorPolicyinterface to be notified of errors and optional debug output during parsing.
License
lalr is licensed under the MIT License.