File: defineterminal.cc

package info (click to toggle)
bisonc%2B%2B 6.09.02-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,984 kB
  • sloc: cpp: 9,375; ansic: 1,505; fortran: 1,134; makefile: 1,062; sh: 526; yacc: 84; lex: 60
file content (86 lines) | stat: -rw-r--r-- 3,024 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "parser.ih"

// Only with %type a symbol may already exist. 
//
// Symbols are defined by %token, %left etc. as terminals only.
//
// At a %type declaration, their types can be set, but only if their types
// haven't been set yet. 
// 
// A %type can also define an undetermined nonterminal: eventually 
// it must be defined as a nonterminal by a rule.
//
// If a %type is followed by a %token etc. then those latter directives may
// change the kind to symbol into terminal, but not their type.
// 
// This function is called by the `symbol' rule

//  Unknown symbol:
//
//  Define the terminal as UNDETERMINED with %type, otherwise as `type'
//
//  known symbol:
//  ---------------------------------------------------------------------
//                      Second: 
//              ---------------------------------------------------------
//              %token          %type (-> d_typeDirective)
//  ---------------------------------------------------------------------
//  First:
//  (%type -> UNDETERMINED)
//  ---------------------------------------------------------------------
//      %token  mult.def'd      OK, unless token's %type is specified
//                              and different from %type. If equal: warn
//
//      %type   OK, same as     OK, same as upper right
//              upper right
//  ---------------------------------------------------------------------


void Parser::defineTerminal(string const &name, Symbol::Type type)
{
    if (Symbol *sp = d_symtab.lookup(name))     // known symbol?
    {
            // known symbol: upper left alternative
        if (not sp->isUndetermined() && not d_typeDirective)
        {
            multiplyDefined(sp);
            return;
        }

        if (sp->sType().empty())
            sp->setStype(d_field);

        else if (sp->sType() == d_field)
            wmsg << 
                        '`' << name << "' type repeatedly specified as <" <<
                        d_field << ">" << endl;

        else    // type clash
            emsg << 
                        "can't redefine type <" << sp->sType() << "> of `" <<
                        name << "' to <" << d_field << ">" << endl;
    }

    else // new symbol: insert it as (provisional or definitive) terminal
        d_symtab.insert
        (
            Symtab::value_type
            (
                name, 
                d_rules.insert
                (
                    new Terminal(name, 
                                    d_typeDirective ? 
                                        Symbol::UNDETERMINED 
                                    :
                                        type, 
                                    type == Symbol::CHAR_TERMINAL ?
                                        d_scanner.number()
                                    :
                                        Terminal::DEFAULT, 
                                    d_association, d_field),
                    d_matched
                )
            )
        );
}