summaryrefslogtreecommitdiff
path: root/unoidl/source/sourceprovider-scanner.l
blob: bdedfcffc919c69abbcd84322e4d268793904746 (plain)
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

%option bison-bridge
%option bison-locations
%option extra-type="unoidl::detail::SourceProviderScannerData *"
%option never-interactive
%option nounistd
%option noyywrap
%option noinput
%option nounput
%option reentrant
%option warn
%option yylineno

%top {

#include "sal/config.h"

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>

}

%{

#include <rtl/math.h>
#include <rtl/string.hxx>
#include <rtl/ustring.hxx>
#include <rtl/textenc.h>
#include <sal/types.h>
#include <unoidl/unoidl.hxx>

#include "sourceprovider-parser-requires.hxx"
#include <sourceprovider-parser.hxx>
#include "sourceprovider-scanner.hxx"

namespace unoidl::detail {

static std::size_t sourceProviderScannerInput(
    SourceProviderScannerData * data, char * buffer, std::size_t size)
{
    assert(data != nullptr);
    if (data->sourcePosition == data->sourceEnd) {
        return YY_NULL;
    }
    assert(data->sourcePosition < data->sourceEnd);
    size = std::min<std::size_t>(size, data->sourceEnd - data->sourcePosition);
    std::memcpy(buffer, data->sourcePosition, size);
    data->sourcePosition += size;
    return size;
}

}

#define YY_INPUT(buf, result, max_size) ((result) = \
    ::unoidl::detail::sourceProviderScannerInput(yyextra, (buf), (max_size)))

namespace {

int nonZeroIntegerLiteral(
    char const * text, std::size_t length, sal_Int16 radix, sal_uInt64 * value,
    unoidl::detail::SourceProviderScannerData * data)
{
    assert(text != nullptr);
    assert(length != 0);
    assert(value != nullptr);
    assert(data != nullptr);
    std::size_t n = length;
    switch (text[length - 1]) {
    case 'L':
    case 'U':
    case 'l':
    case 'u':
        --n;
        break;
    default:
        break;
    }
    *value = OString(text, n).toUInt64(radix);
    if (*value == 0) {
        data->errorMessage = "out-of-range integer literal "
            + OUString(text, length, RTL_TEXTENCODING_ASCII_US);
        return TOK_ERROR;
    }
    return TOK_INTEGER;
}

}

%}

%x comment1 comment2 doc docdepr

DIGIT [0-9]
UPPER [A-Z]
LOWER [a-z]
ALPHA {UPPER}|{LOWER}
ALNUM {DIGIT}|{ALPHA}

%%

[ \t\r]
\n *yylloc = yylineno;

"//" BEGIN comment1;
"#" BEGIN comment1; //TODO: only at start of line
<comment1>.
<comment1>\n *yylloc = yylineno; BEGIN INITIAL;

"/*" BEGIN comment2;
"/**" BEGIN doc;
"/***" BEGIN comment2;

<comment2,doc>"*/" BEGIN INITIAL;
<docdepr>"*/" BEGIN INITIAL; return TOK_DEPRECATED;

<comment2,docdepr>.
<comment2,doc,docdepr>\n *yylloc = yylineno;
<comment2,doc,docdepr><<EOF>> {
    yyextra->errorMessage = "unterminated comment";
    return TOK_ERROR;
}

<doc>[ \t\r]
<doc>"@deprecated" BEGIN docdepr;
<doc>"*"
<doc>[^ \t\r\n*]+

[%&()*+,\-/:;<=>[\]^{|}~] return yytext[0];

"..." return TOK_ELLIPSIS;
"::" return TOK_COLONS;
"<<" return TOK_LEFTSHIFT;
">>" return TOK_RIGHTSHIFT;

"FALSE" return TOK_FALSE;
"False" return TOK_FALSE;
"TRUE" return TOK_TRUE;
"True" return TOK_TRUE;
"any" return TOK_ANY;
"attribute" return TOK_ATTRIBUTE;
"boolean" return TOK_BOOLEAN;
"bound" return TOK_BOUND;
"byte" return TOK_BYTE;
"char" return TOK_CHAR;
"const" return TOK_CONST;
"constants" return TOK_CONSTANTS;
"constrained" return TOK_CONSTRAINED;
"double" return TOK_DOUBLE;
"enum" return TOK_ENUM;
"exception" return TOK_EXCEPTION;
"float" return TOK_FLOAT;
"get" return TOK_GET;
"hyper" return TOK_HYPER;
"in" return TOK_IN;
"inout" return TOK_INOUT;
"interface" return TOK_INTERFACE;
"long" return TOK_LONG;
"maybeambiguous" return TOK_MAYBEAMBIGUOUS;
"maybedefault" return TOK_MAYBEDEFAULT;
"maybevoid" return TOK_MAYBEVOID;
"module" return TOK_MODULE;
"optional" return TOK_OPTIONAL;
"out" return TOK_OUT;
"property" return TOK_PROPERTY;
"published" return TOK_PUBLISHED;
"raises" return TOK_RAISES;
"readonly" return TOK_READONLY;
"removable" return TOK_REMOVABLE;
"sequence" return TOK_SEQUENCE;
"service" return TOK_SERVICE;
"set" return TOK_SET;
"short" return TOK_SHORT;
"singleton" return TOK_SINGLETON;
"string" return TOK_STRING;
"struct" return TOK_STRUCT;
"transient" return TOK_TRANSIENT;
"type" return TOK_TYPE;
"typedef" return TOK_TYPEDEF;
"unsigned" return TOK_UNSIGNED;
"void" return TOK_VOID;

{UPPER}("_"?{ALNUM})*|{LOWER}{ALNUM}* {
    yylval->sval = new OString(yytext);
    return TOK_IDENTIFIER;
}

({ALPHA}|"_")({ALNUM}|"_")* {
    yyextra->errorMessage = "illegal identifier "
        + OUString(yytext, yyleng, RTL_TEXTENCODING_ASCII_US);
    return TOK_ERROR;
}

0+[LUlu]? |
0[Xx]0+[LUlu]? {
    yylval->ival = 0;
    return TOK_INTEGER;
}

0[0-7]+[LUlu]? {
    return nonZeroIntegerLiteral(yytext, yyleng, 8, &yylval->ival, yyextra);
}

[1-9]{DIGIT}*[LUlu]? {
    return nonZeroIntegerLiteral(yytext, yyleng, 10, &yylval->ival, yyextra);
}

0[Xx][0-9A-Fa-f]+[LUlu]? {
    return nonZeroIntegerLiteral(
        yytext + 2, yyleng - 2, 16, &yylval->ival, yyextra);
}

{DIGIT}+[Ee][+\-]?{DIGIT}+[Ff]? |
{DIGIT}*"."{DIGIT}+([Ee][+\-]?{DIGIT}+)?[Ff]? {
    rtl_math_ConversionStatus s;
    yylval->fval = rtl_math_stringToDouble(
        yytext, yytext + yyleng, '.', 0, &s, nullptr);
    if (s == rtl_math_ConversionStatus_OutOfRange) {
        yyextra->errorMessage = "out-of-range floating-point literal "
            + OUString(yytext, yyleng, RTL_TEXTENCODING_ASCII_US);
        return TOK_ERROR;
    }
    return TOK_FLOATING;
}

{DIGIT}({ALNUM}|"_")* {
    yyextra->errorMessage = "illegal numeric literal "
        + OUString(yytext, yyleng, RTL_TEXTENCODING_ASCII_US);
    return TOK_ERROR;
}

. {
    char c = yytext[0];
    yyextra->errorMessage = c >= ' ' && c <= '~'
        ? OUString("invalid character \"" + OUStringChar(c) + "\"")
        : OUString(
            "invalid byte x"
            + OUString::number(static_cast<unsigned char>(c), 16).toAsciiUpperCase());
    return TOK_ERROR;
}

%%

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */