# Specialized Actions

> In general, semantic actions accept the first-last iterator pair. The action functions or functors receive the unprocessed data representing the matching production directly from the input. There are situations though where we might want to pass data in its processed form. A concrete example is the numeric parser. It is unwise to pass unprocessed data to a semantic action attached to a numeric parser and just throw away what has been done. Here, we might want to pass the actual parsed number.

> The function and functor signature of a semantic action varies depending on the parser where it is attached. The following table lists the parsers that accept unique signatures. Parsers not included in the list by default expect the generic signature as explained before.

> > Numeric Actions
> > uint_p int_p ureal_p real_p | void func(NumT val); // Signature for functions struct ftor { // Signature for functors typedef NumT arg_type; // Required for functors void operator()(NumT val) const; }; Where NumT is any primitive numeric type such as int, long, float, double, etc., or a user defined numeric type such as big_int. The parsed number is passed into the function/functor.

> > Character Actions
> > chlit, ch_p range, range_p anychar alnum, alpha cntrl, digit graph, lower print, punct space, upper xdigit chset | void func(CharT ch); Where CharT is the desired character type. A functor should have a member operator() with a compatible signature as above. The matching character is passed into the function/functor.

> > Symbol Table Actions
> > symbols | void func(IteratorT first, IteratorT last, T& data); Where first points to the current input, last points to one after the end of the input (identical to STL ranges) and data is any information associated with the matching symbol in the symbol table (see the section on Symbols above). A functor should have a member operator() with a compatible signature as above. The matching portion is passed to the function/functor. Notice that the data associated with the matching symbol is passed by reference to allow it to be modified by the function/functor.

> Extracting symbols:

> The symbol table class symbols has a member functor add. Symbols may be added dynamically to the symbol table through its member functor add. The member functor add may be attached to a parser as a semantic action:

> >     expr[sym.add]

> where expr is an expression that results to a parser and sym is a symbol table. On success, the matching portion of the input is added to the symbol table. Here's an example that extracts valid C/C++ identifiers and puts that in a symbol table sym:

> >     var_decl = lexeme[(alpha >> *(alnum | '_'))[sym.add]];

> If you intend to allow source language to add to the symbol table during a parse, you must ensure that the symbol has not already been added previously:

> >     var_decl = lexeme[((alpha >> *(alnum | '_')) - sym)[sym.add]];

> This rule ensures that the symbol has not been declared previously. The expression

> >     ((alpha >> *(alnum | '_')) - sym)

> matches any valid C/C++ identifier that has not yet been added to the symbol table sym.