Files
bison/examples/c
Akim Demaille d9cf99b6a5 multistart: use b4_accept instead of action post-processing
For each start symbol, generate a parsing function with a richer
return value than the usual of yyparse.  Reserve a place for the
returned semantic value, in order to avoid having to pass a pointer as
argument to "return" that value.  This also makes the call to the
parsing function independent of whether a given start-symbol is typed.

For instance, if the grammar file contains:

    %type <int> expression
    %start input expression

(so "input" is valueless) we get

    typedef struct
    {
      int yystatus;
    } yyparse_input_t;

    yyparse_input_t yyparse_input (void);

    typedef struct
    {
      int yyvalue;
      int yystatus;
    } yyparse_expression_t;

    yyparse_expression_t yyparse_expression (void);

This commit also changes the implementation of the parser termination:
when there are multiple start symbols, it is the initial rules that
explicitly YYACCEPT.  They do that after having exported the
start-symbol's value (if it is typed):

  switch (yyn)
    {
  case 1: /* $accept: YY_EXPRESSION expression $end  */
  { ((*yyvalue).TOK_expression) = (yyvsp[-1].TOK_expression); YYACCEPT; }
    break;

  case 2: /* $accept: YY_INPUT input $end  */
  { YYACCEPT; }
    break;

I have tried several ways to deal with termination, and this is the
one that appears the best one to me.  It is also the most natural.

* src/scan-code.h, src/scan-code.l (obstack_for_actions): New.
* src/reader.c (grammar_rule_check_and_complete): Generate the actions
of the rules for each start symbol.

* data/skeletons/bison.m4 (b4_symbol_slot): New, with safer semantics
than type and type_tag.
* data/skeletons/yacc.c (b4_accept): New.
Generates the body of the action of the start rules.
(_b4_declare_sub_yyparse): For each start symbol define a dedicated
return type for its parsing function.
Adjust the declaration of its parsing function.
(_b4_define_sub_yyparse): Adjust the definition of the function.

* examples/c/lexcalc/parse.y: Check the case of valueless symbols.
* examples/c/lexcalc/lexcalc.test: Check start symbols.
2020-09-27 09:44:18 +02:00
..
2020-09-26 18:33:48 +02:00
2020-06-01 08:29:53 +02:00
2020-06-01 08:29:53 +02:00

Examples in C

This directory contains simple examples of Bison grammar files in C.

Some of them come from the documentation, which should be installed together with Bison. The URLs are provided for convenience.

rpcalc - Reverse Polish Notation Calculator

The first example is that of a simple double-precision Reverse Polish Notation calculator (a calculator using postfix operators). This example provides a good starting point, since operator precedence is not an issue.

Extracted from the documentation: Reverse Polish Notation Calculator.

calc - Simple Calculator

This example is slightly more complex than rpcalc: it features infix operators (1 + 2, instead of 1 2 + in rpcalc), but it does so using a unambiguous grammar of the arithmetic instead of using precedence directives (%left, etc.).

mfcalc - Multi-Function Calculator

A more complete C example: a multi-function calculator. More complex than the previous example. Using precedence directives to support infix operators.

Extracted from the documentation: Multi-Function Calculator: mfcalc.

lexcalc - calculator with Flex and Bison

The calculator with precedence directives and location tracking. It uses Flex to generate the scanner.

reccalc - recursive calculator with Flex and Bison

This example builds on top of the previous one to provide a reentrant parser. Such parsers can be called concurrently in different threads, or even recursively. To demonstrate this feature, expressions in parentheses are tokenized as strings, and then recursively parsed from the parser. So (((1)+(2))*((3)+(4))) uses eight parsers, with a depth of four.

pushcalc - calculator implemented with a push parser

All the previous examples are so called "pull parsers": the user invokes the parser once, which repeatedly calls the scanner until the input is drained.

This example demonstrates the "push parsers": the user calls the scanner to fetch the next token, passes it to the parser, and repeats the operation until the input is drained.

This example is a straightforward conversion of the 'calc' example to the push-parser model.

bistromathic - all the bells and whistles

This example demonstrates best practices when using Bison.

  • Its hand-written scanner tracks locations.
  • Its interface is pure.
  • It uses %params to pass user information to the parser and scanner.
  • Its scanner uses the error token to signal lexical errors and enter error recovery.
  • Its interface is "incremental", well suited for interaction: it uses the push-parser API to feed the parser with the incoming tokens.
  • It features an interactive command line with completion based on the parser state, based on yyexpected_tokens.
  • It uses Bison's standard catalogue for internationalization of generated messages.
  • It uses a custom syntax error with location, lookahead correction and token internationalization.
  • Error messages quote the source with squiggles that underline the error:
> 123 456
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
    1 | 123 456
      |     ^~~
  • It supports debug traces with semantic values.
  • It uses named references instead of the traditional $1, $2, etc.