1 /*
2  * Copyright (c) 2014-2020 Christian Schoenebeck
3  *
4  * http://www.linuxsampler.org
5  *
6  * This file is part of LinuxSampler and released under the same terms.
7  * See README file for details.
8  */
9 
10 // types shared between auto generated lexer and parser ...
11 
12 #ifndef LS_INSTRSCRIPTSPARSER_SHARED_H
13 #define LS_INSTRSCRIPTSPARSER_SHARED_H
14 
15 #include <stdio.h>
16 #include "tree.h"
17 
18 #if AC_APPLE_UNIVERSAL_BUILD
19 # include "parser.tab.h"
20 #else
21 # include "parser.h"
22 #endif
23 
24 #include "../common/global_private.h"
25 
26 struct _YYSTYPE {
27     union {
28         LinuxSampler::vmint iValue;
29         LinuxSampler::vmfloat fValue;
30         // Intentionally using C-strings instead of std::string for parser's
31         // string tokens, because any destructor based class had a negative
32         // impact on parser performance in benchmarks. Reason for this is that
33         // text tokens are the most common one while parsing, plus the parser
34         // copies the YYSTYPE struct a lot (i.e. when shifting). For C-strings
35         // coming directly from Flex, we don't have to free them. For C-strings
36         // allocated by us, use yyextra->autoFreeAfterParse(s);
37         char* sValue;
38         struct {
39             LinuxSampler::vmint iValue;
40             LinuxSampler::MetricPrefix_t prefix[2];
41             LinuxSampler::StdUnit_t unit;
42         } iUnitValue;
43         struct {
44             LinuxSampler::vmfloat fValue;
45             LinuxSampler::MetricPrefix_t prefix[2];
46             LinuxSampler::StdUnit_t unit;
47         } fUnitValue;
48     };
49     LinuxSampler::EventHandlersRef nEventHandlers;
50     LinuxSampler::EventHandlerRef nEventHandler;
51     LinuxSampler::StatementsRef nStatements;
52     LinuxSampler::StatementRef nStatement;
53     LinuxSampler::FunctionCallRef nFunctionCall;
54     LinuxSampler::ArgsRef nArgs;
55     LinuxSampler::ExpressionRef nExpression;
56     LinuxSampler::CaseBranch nCaseBranch;
57     LinuxSampler::CaseBranches nCaseBranches;
58     LinuxSampler::Qualifier_t varQualifier;
59 };
60 #define YYSTYPE _YYSTYPE
61 #define yystype YYSTYPE     ///< For backward compatibility.
62 #ifndef YYSTYPE_IS_DECLARED
63 # define YYSTYPE_IS_DECLARED ///< We tell the lexer / parser that we use our own data structure as defined above.
64 #endif
65 
66 // custom Bison location type to support raw byte positions
67 struct _YYLTYPE {
68     int first_line;
69     int first_column;
70     int last_line;
71     int last_column;
72     int first_byte;
73     int length_bytes;
74 };
75 #define YYLTYPE _YYLTYPE
76 #define YYLTYPE_IS_DECLARED 1
77 
78 // override Bison's default location passing to support raw byte positions
79 #define YYLLOC_DEFAULT(Cur, Rhs, N)                         \
80 do                                                          \
81   if (N)                                                    \
82     {                                                       \
83       (Cur).first_line   = YYRHSLOC(Rhs, 1).first_line;     \
84       (Cur).first_column = YYRHSLOC(Rhs, 1).first_column;   \
85       (Cur).last_line    = YYRHSLOC(Rhs, N).last_line;      \
86       (Cur).last_column  = YYRHSLOC(Rhs, N).last_column;    \
87       (Cur).first_byte   = YYRHSLOC(Rhs, 1).first_byte;     \
88       (Cur).length_bytes = (YYRHSLOC(Rhs, N).first_byte  -  \
89                             YYRHSLOC(Rhs, 1).first_byte) +  \
90                             YYRHSLOC(Rhs, N).length_bytes;  \
91     }                                                       \
92   else                                                      \
93     {                                                       \
94       (Cur).first_line   = (Cur).last_line   =              \
95         YYRHSLOC(Rhs, 0).last_line;                         \
96       (Cur).first_column = (Cur).last_column =              \
97         YYRHSLOC(Rhs, 0).last_column;                       \
98       (Cur).first_byte   = YYRHSLOC(Rhs, 0).first_byte;     \
99       (Cur).length_bytes = YYRHSLOC(Rhs, 0).length_bytes;   \
100     }                                                       \
101 while (0)
102 
103 // Force YYCOPY() to use copy by value.
104 //
105 // By default YYCOPY() is using __builtin_memcpy, which is slightly problematic
106 // with our YYSTYPE (see above) since it has dynamic objects as member variables
107 // and hence __builtin_memcpy would overwrite their vpointer. In practice though
108 // this is more of a theoretical fix and probably just silences compiler
109 // warnings. So in practice __builtin_memcpy would probably not cause any
110 // misbehaviours, because it is expected that Bison generated parsers only use
111 // YYCOPY() to relocate the parser's stack (that is moving objects in memory),
112 // but not for really creating duplicates of any objects.
113 //
114 // In my benchmarks I did not encounter any measurable performance difference by
115 // this change, so shutting up the compiler wins for now.
116 #define YYCOPY(To, From, Count)                 \
117     do {                                        \
118         for (YYSIZE_T i = 0; i < (Count); ++i)  \
119             (To)[i] = (From)[i];                \
120     } while (YYID (0));                         \
121 
122 #endif // LS_INSTRSCRIPTSPARSER_SHARED_H
123