tutorial 0 -- hello world α

The target of this tutorial is the persons those have handled BNF for yacc or yacc-like program.

The first example is hello world.

Input Grammar File

Create an input grammar file like the following and save as file name "hello0.cpg". One input grammar file corresponds to a parser.

%token Hello World;
%namespace hello_world;
%dont_use_stl;

HelloWorld<int> : [] Hello World;

At Line 1:

It defines a token. This declaration produces:

enum Token {
     token_Hello,
     token_World,
};

an enum declaration, treated as a token type*1.

At Line 2:

This declares namespace name. Output header will be surrounded by this namespace. If not specified, default is "caper_parser".

At Line 3:

This declares the parser stack uses array instead of STL. If it uses array, no dynamic allocation will be occured but the size will be limited.

At Line 5:

This is a grammar definition in BNF.

The grammar is a set of grammar rules. Grammar rules are specified in the following format:

non_terminal<non_terminal_type> : [semantic_action_name]
                             | [semantic_action_name] term
                             | [semantic_action_name] term term
                            ...
                             ;

Symbols are different from BNF, but the meanings of other items are same as in normal BNF. We will explain caper unique part in later tutorials.

This grammar is simple. That accepts if tokens 'hello' 'world' came in this order.

The top grammar rule is the root rule.


*1 If %external_token; declaration was given in another line, then this enum definition won't be outputted, class Parser requires "Token" type as a template parameter. Please use it if you want to define "Token" type in another file.

Let's genarate parser by caper!

To generate parser (.hpp file) from the above grammar, please type:

% caper hello0.cpg hello0.hpp

from command line.

Then the following code will be generated:

#ifndef HELLO_WORLD_HPP
#define HELLO_WORLD_HPP

namespace hello_world {

enum Token {
    token_eof,
    token_Hello,
    token_World,
};

template < class Value, class SemanticAction >
class Parser {
public:
    typedef Token token_type;
    typedef Value value_type;

public:
    Parser( SemanticAction& sa );

    void reset();
    bool post( token_type token, const value_type& value );
    bool accept( value_type& v );
    bool error();
};

} // namespace hello_world

#endif // #ifndef HELLO_WORLD_HPP

(Implementation was omitted)

Use the parser in your program

The following code is an example that uses the above parser from main program.

#include <iostream>
#include "hello0.hpp"

struct SemanticAction {
        void syntax_error(){}
        void stack_overflow(){}
};

int main( int, char** )
{
        SemanticAction sa;
        hello_world::Parser< int, SemanticAction > parser( sa );

        parser.post( hello_world::token_Hello, 0 );
        parser.post( hello_world::token_World, 0 );
        parser.post( hello_world::token_eof, 0 );

        return 0;
}

At Line 2:

It includes the generated parser.

At Line 4 to 7:

It defines semantic action handlers. This structure will be passed as a template parameter. class is also OK. This time defined no semantic actions but grammar error handlers are required, so the definition of void syntax_error(){} is required. Nothing code is required at the inner of syntax_error if unnecessary. The definition of stack_overflow function is also required.

At Line 11:

It generates a parser instance. The type of value associated to the token is the 1st parameter of "int". On construction, semantic action handler is passed as a parameter produced at Line 10.

The 3rd parameter of class template "Parser" was omitted. The 3rd parameter is an integer (default is 0 if STL was used for stack, or 1024 if STL was not used). When 'StackSize' is zero and STL is used for stack, the parser stack doesn't overflow (but it can raise std::bad_alloc)

At Line 12 to 14:

It gives tokens to the parser. The acceptance will be completed when Line 14 ended, but this time, the parser does nothing even if accepted.

Execution

No output.

It's outline of basic functionality of caper.