|
|
@@ -4,6 +4,10 @@
|
|
|
* @date 1999-01-16
|
|
|
*/
|
|
|
|
|
|
+%option reentrant bison-bridge bison-locations
|
|
|
+%option noyywrap
|
|
|
+%option case-insensitive
|
|
|
+
|
|
|
%{
|
|
|
#include "pandabase.h"
|
|
|
#include "lexerDefs.h"
|
|
|
@@ -18,182 +22,156 @@
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
-using std::istream;
|
|
|
-using std::ostream;
|
|
|
-using std::string;
|
|
|
-
|
|
|
-extern "C" int eggyywrap(void); // declared below.
|
|
|
-
|
|
|
-static int yyinput(void); // declared by flex.
|
|
|
-
|
|
|
-int eggyylex_destroy(void);
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Static variables
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-// This mutex protects all of these global variables.
|
|
|
-LightMutex egg_lock;
|
|
|
-
|
|
|
-// We'll increment line_number and col_number as we parse the file, so
|
|
|
-// that we can report the position of an error.
|
|
|
-static int line_number = 0;
|
|
|
-static int col_number = 0;
|
|
|
-
|
|
|
-// current_line holds as much of the current line as will fit. Its
|
|
|
-// only purpose is for printing it out to report an error to the user.
|
|
|
-static const int max_error_width = 1024;
|
|
|
-static char current_line[max_error_width + 1];
|
|
|
-
|
|
|
-static int error_count = 0;
|
|
|
-static int warning_count = 0;
|
|
|
-
|
|
|
-// This is the pointer to the current input stream.
|
|
|
-static istream *input_p = nullptr;
|
|
|
-
|
|
|
-// This is the name of the egg file we're parsing. We keep it so we
|
|
|
-// can print it out for error messages.
|
|
|
-static string egg_filename;
|
|
|
-
|
|
|
-// This is the initial token state returned by the lexer. It allows
|
|
|
-// the yacc grammar to start from initial points.
|
|
|
-static int initial_token;
|
|
|
+// These are declared by flex.
|
|
|
+static int yyinput(yyscan_t yyscanner);
|
|
|
+static EggLexerState *eggyyget_extra(yyscan_t scanner);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Defining the interface to the lexer.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void
|
|
|
-egg_init_lexer(istream &in, const string &filename) {
|
|
|
- input_p = ∈
|
|
|
- egg_filename = filename;
|
|
|
- line_number = 0;
|
|
|
- col_number = 0;
|
|
|
- error_count = 0;
|
|
|
- warning_count = 0;
|
|
|
- initial_token = START_EGG;
|
|
|
+egg_init_lexer_state(EggLexerState &state, std::istream &in, const std::string &filename) {
|
|
|
+ state._error_count = 0;
|
|
|
+ state._warning_count = 0;
|
|
|
+ state._input_p = ∈
|
|
|
+ state._egg_filename = filename;
|
|
|
+ state._initial_token = START_EGG;
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-egg_cleanup_lexer() {
|
|
|
- // Reset the lexer state.
|
|
|
- yylex_destroy();
|
|
|
-
|
|
|
- input_p = nullptr;
|
|
|
- egg_filename.clear();
|
|
|
+egg_cleanup_lexer_state(EggLexerState &state) {
|
|
|
+ state._input_p = nullptr;
|
|
|
+ state._egg_filename.clear();
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-egg_start_group_body() {
|
|
|
+egg_start_group_body(EggLexerState &state) {
|
|
|
/* Set the initial state to begin within a group_body context,
|
|
|
instead of at the beginning of the egg file. */
|
|
|
- initial_token = START_GROUP_BODY;
|
|
|
+ state._initial_token = START_GROUP_BODY;
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-egg_start_texture_body() {
|
|
|
- initial_token = START_TEXTURE_BODY;
|
|
|
+egg_start_texture_body(EggLexerState &state) {
|
|
|
+ state._initial_token = START_TEXTURE_BODY;
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-egg_start_primitive_body() {
|
|
|
- initial_token = START_PRIMITIVE_BODY;
|
|
|
-}
|
|
|
-
|
|
|
-int
|
|
|
-egg_error_count() {
|
|
|
- return error_count;
|
|
|
+egg_start_primitive_body(EggLexerState &state) {
|
|
|
+ state._initial_token = START_PRIMITIVE_BODY;
|
|
|
}
|
|
|
|
|
|
-int
|
|
|
-egg_warning_count() {
|
|
|
- return warning_count;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Internal support functions.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
-int
|
|
|
-eggyywrap(void) {
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
void
|
|
|
-eggyyerror(const string &msg) {
|
|
|
+eggyyerror(YYLTYPE *loc, yyscan_t scanner, const std::string &msg) {
|
|
|
+ EggLexerState *lexer_state = eggyyget_extra(scanner);
|
|
|
+
|
|
|
if (egg_cat.is_error()) {
|
|
|
- ostream &out = egg_cat.error(false);
|
|
|
+ std::ostream &out = egg_cat.error(false);
|
|
|
|
|
|
out << "\nError";
|
|
|
- if (!egg_filename.empty()) {
|
|
|
- out << " in " << egg_filename;
|
|
|
+ if (!lexer_state->_egg_filename.empty()) {
|
|
|
+ out << " in " << lexer_state->_egg_filename;
|
|
|
+ }
|
|
|
+ if (loc != nullptr) {
|
|
|
+ out
|
|
|
+ << " at line " << loc->first_line << ", column " << loc->first_column << ":\n"
|
|
|
+ << std::setiosflags(Notify::get_literal_flag())
|
|
|
+ << lexer_state->_current_line << "\n";
|
|
|
+ indent(out, loc->first_column - 1)
|
|
|
+ << "^";
|
|
|
+
|
|
|
+ int last_column;
|
|
|
+ if (loc->first_line == loc->last_line) {
|
|
|
+ last_column = loc->last_column;
|
|
|
+ } else {
|
|
|
+ last_column = strlen(lexer_state->_current_line);
|
|
|
+ }
|
|
|
+ for (int i = loc->first_column; i < last_column; ++i) {
|
|
|
+ out.put('~');
|
|
|
+ }
|
|
|
+
|
|
|
+ out
|
|
|
+ << "\n" << msg << "\n\n"
|
|
|
+ << std::resetiosflags(Notify::get_literal_flag()) << std::flush;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ out << ":\n" << msg << "\n\n" << std::flush;
|
|
|
}
|
|
|
- out
|
|
|
- << " at line " << line_number << ", column " << col_number << ":\n"
|
|
|
- << std::setiosflags(Notify::get_literal_flag())
|
|
|
- << current_line << "\n";
|
|
|
- indent(out, col_number-1)
|
|
|
- << "^\n" << msg << "\n\n"
|
|
|
- << std::resetiosflags(Notify::get_literal_flag()) << std::flush;
|
|
|
}
|
|
|
- error_count++;
|
|
|
+ lexer_state->_error_count++;
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-eggyyerror(std::ostringstream &strm) {
|
|
|
- string s = strm.str();
|
|
|
- eggyyerror(s);
|
|
|
-}
|
|
|
+eggyywarning(YYLTYPE *loc, yyscan_t scanner, const std::string &msg) {
|
|
|
+ EggLexerState *lexer_state = eggyyget_extra(scanner);
|
|
|
|
|
|
-void
|
|
|
-eggyywarning(const string &msg) {
|
|
|
if (egg_cat.is_warning()) {
|
|
|
- ostream &out = egg_cat.warning(false);
|
|
|
+ std::ostream &out = egg_cat.warning(false);
|
|
|
|
|
|
out << "\nWarning";
|
|
|
- if (!egg_filename.empty()) {
|
|
|
- out << " in " << egg_filename;
|
|
|
+ if (!lexer_state->_egg_filename.empty()) {
|
|
|
+ out << " in " << lexer_state->_egg_filename;
|
|
|
}
|
|
|
- out
|
|
|
- << " at line " << line_number << ", column " << col_number << ":\n"
|
|
|
- << std::setiosflags(Notify::get_literal_flag())
|
|
|
- << current_line << "\n";
|
|
|
- indent(out, col_number-1)
|
|
|
- << "^\n" << msg << "\n\n"
|
|
|
- << std::resetiosflags(Notify::get_literal_flag()) << std::flush;
|
|
|
- }
|
|
|
- warning_count++;
|
|
|
-}
|
|
|
+ if (loc != nullptr) {
|
|
|
+ out
|
|
|
+ << " at line " << loc->first_line << ", column " << loc->first_column << ":\n"
|
|
|
+ << std::setiosflags(Notify::get_literal_flag())
|
|
|
+ << lexer_state->_current_line << "\n";
|
|
|
+ indent(out, loc->first_column - 1)
|
|
|
+ << "^";
|
|
|
+
|
|
|
+ int last_column;
|
|
|
+ if (loc->first_line == loc->last_line) {
|
|
|
+ last_column = loc->last_column;
|
|
|
+ } else {
|
|
|
+ last_column = strlen(lexer_state->_current_line);
|
|
|
+ }
|
|
|
+ for (int i = loc->first_column; i < last_column; ++i) {
|
|
|
+ out.put('~');
|
|
|
+ }
|
|
|
|
|
|
-void
|
|
|
-eggyywarning(std::ostringstream &strm) {
|
|
|
- string s = strm.str();
|
|
|
- eggyywarning(s);
|
|
|
+ out
|
|
|
+ << "\n" << msg << "\n\n"
|
|
|
+ << std::resetiosflags(Notify::get_literal_flag()) << std::flush;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ out << ":\n" << msg << "\n\n" << std::flush;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lexer_state->_warning_count++;
|
|
|
}
|
|
|
|
|
|
// Now define a function to take input from an istream instead of a
|
|
|
// stdio FILE pointer. This is flex-specific.
|
|
|
static void
|
|
|
-input_chars(char *buffer, int &result, int max_size) {
|
|
|
- nassertv(input_p != nullptr);
|
|
|
- if (*input_p) {
|
|
|
- input_p->read(buffer, max_size);
|
|
|
- result = input_p->gcount();
|
|
|
+input_chars(YYLTYPE *yylloc, yyscan_t yyscanner, char *buffer, int &result, int max_size) {
|
|
|
+ EggLexerState &state = *yyget_extra(yyscanner);
|
|
|
+
|
|
|
+ nassertv(state._input_p != nullptr);
|
|
|
+ if (*state._input_p) {
|
|
|
+ state._input_p->read(buffer, max_size);
|
|
|
+ result = state._input_p->gcount();
|
|
|
|
|
|
- if (line_number == 0) {
|
|
|
+ if (yylloc->last_line == 0) {
|
|
|
// This is a special case. If we are reading the very first bit
|
|
|
- // from the stream, copy it into the current_line array. This
|
|
|
- // is because the \n.* rule below, which fills current_line
|
|
|
+ // from the stream, copy it into the _current_line array. This
|
|
|
+ // is because the \n.* rule below, which fills _current_line
|
|
|
// normally, doesn't catch the first line.
|
|
|
- int length = std::min(max_error_width, result);
|
|
|
- strncpy(current_line, buffer, length);
|
|
|
- current_line[length] = '\0';
|
|
|
- line_number++;
|
|
|
- col_number = 0;
|
|
|
+ size_t length = std::min(egg_max_error_width, (size_t)result);
|
|
|
+ strncpy(state._current_line, buffer, length);
|
|
|
+ state._current_line[length] = '\0';
|
|
|
+ yylloc->first_line = 1;
|
|
|
+ yylloc->last_line = 1;
|
|
|
+ yylloc->first_column = 0;
|
|
|
+ yylloc->last_column = 0;
|
|
|
|
|
|
// Truncate it at the newline.
|
|
|
- char *end = strchr(current_line, '\n');
|
|
|
+ char *end = strchr(state._current_line, '\n');
|
|
|
if (end != nullptr) {
|
|
|
*end = '\0';
|
|
|
}
|
|
|
@@ -211,7 +189,7 @@ input_chars(char *buffer, int &result, int max_size) {
|
|
|
// with a different type for result.
|
|
|
#define YY_INPUT(buffer, result, max_size) { \
|
|
|
int int_result = 0; \
|
|
|
- input_chars((buffer), int_result, (max_size)); \
|
|
|
+ input_chars(yylloc, yyscanner, (buffer), int_result, (max_size)); \
|
|
|
(result) = int_result; \
|
|
|
}
|
|
|
|
|
|
@@ -219,8 +197,8 @@ input_chars(char *buffer, int &result, int max_size) {
|
|
|
// supplied line and column numbers as appropriate. A convenience
|
|
|
// function for the scanning functions below.
|
|
|
static int
|
|
|
-read_char(int &line, int &col) {
|
|
|
- int c = yyinput();
|
|
|
+read_char(yyscan_t yyscanner, int &line, int &col) {
|
|
|
+ int c = yyinput(yyscanner);
|
|
|
if (c == '\n') {
|
|
|
line++;
|
|
|
col = 0;
|
|
|
@@ -232,78 +210,56 @@ read_char(int &line, int &col) {
|
|
|
|
|
|
// scan_quoted_string reads a string delimited by quotation marks and
|
|
|
// returns it.
|
|
|
-static string
|
|
|
-scan_quoted_string() {
|
|
|
- string result;
|
|
|
-
|
|
|
- // We don't touch the current line number and column number during
|
|
|
- // scanning, so that if we detect an error while scanning the string
|
|
|
- // (e.g. an unterminated string), we'll report the error as
|
|
|
- // occurring at the start of the string, not at the end--somewhat
|
|
|
- // more convenient for the user.
|
|
|
-
|
|
|
- // Instead of adjusting the global line_number and col_number
|
|
|
- // variables, we'll operate on our own local variables for the
|
|
|
- // interim.
|
|
|
- int line = line_number;
|
|
|
- int col = col_number;
|
|
|
+static std::string
|
|
|
+scan_quoted_string(YYLTYPE *yylloc, yyscan_t yyscanner) {
|
|
|
+ std::string result;
|
|
|
|
|
|
int c;
|
|
|
- c = read_char(line, col);
|
|
|
+ c = read_char(yyscanner, yylloc->last_line, yylloc->last_column);
|
|
|
while (c != '"' && c != 0 && c != EOF) {
|
|
|
result += c;
|
|
|
- c = read_char(line, col);
|
|
|
+ c = read_char(yyscanner, yylloc->last_line, yylloc->last_column);
|
|
|
}
|
|
|
|
|
|
if (c == 0 || c == EOF) {
|
|
|
- eggyyerror("This quotation mark is unterminated.");
|
|
|
+ eggyyerror(yylloc, yyscanner, "This quotation mark is unterminated.");
|
|
|
}
|
|
|
|
|
|
- line_number = line;
|
|
|
- col_number = col;
|
|
|
-
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
// eat_c_comment scans past all characters up until the first */
|
|
|
// encountered.
|
|
|
static void
|
|
|
-eat_c_comment() {
|
|
|
- // As above, we'll operate on our own local copies of line_number
|
|
|
- // and col_number within this function.
|
|
|
-
|
|
|
- int line = line_number;
|
|
|
- int col = col_number;
|
|
|
-
|
|
|
+eat_c_comment(YYLTYPE *yylloc, yyscan_t yyscanner) {
|
|
|
int c, last_c;
|
|
|
|
|
|
last_c = '\0';
|
|
|
- c = read_char(line, col);
|
|
|
+ c = read_char(yyscanner, yylloc->last_line, yylloc->last_column);
|
|
|
while (c != 0 && c != EOF && !(last_c == '*' && c == '/')) {
|
|
|
if (last_c == '/' && c == '*') {
|
|
|
std::ostringstream errmsg;
|
|
|
errmsg << "This comment contains a nested /* symbol at line "
|
|
|
- << line << ", column " << col-1 << "--possibly unclosed?"
|
|
|
- << std::ends;
|
|
|
- eggyywarning(errmsg);
|
|
|
+ << yylloc->last_line << ", column " << yylloc->last_column - 1
|
|
|
+ << "--possibly unclosed?" << std::ends;
|
|
|
+ eggyywarning(yylloc, yyscanner, errmsg.str());
|
|
|
}
|
|
|
last_c = c;
|
|
|
- c = read_char(line, col);
|
|
|
+ c = read_char(yyscanner, yylloc->last_line, yylloc->last_column);
|
|
|
}
|
|
|
|
|
|
if (c == 0 || c == EOF) {
|
|
|
- eggyyerror("This comment marker is unclosed.");
|
|
|
+ eggyyerror(yylloc, yyscanner, "This comment marker is unclosed.");
|
|
|
}
|
|
|
-
|
|
|
- line_number = line;
|
|
|
- col_number = col;
|
|
|
}
|
|
|
|
|
|
|
|
|
// accept() is called below as each piece is pulled off and
|
|
|
// accepted by the lexer; it increments the current column number.
|
|
|
-INLINE void accept() {
|
|
|
- col_number += yyleng;
|
|
|
+#define accept() { \
|
|
|
+ yylloc->first_line = yylloc->last_line; \
|
|
|
+ yylloc->first_column = yylloc->last_column + 1; \
|
|
|
+ yylloc->last_column += yyleng; \
|
|
|
}
|
|
|
|
|
|
%}
|
|
|
@@ -315,9 +271,9 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
|
|
|
%%
|
|
|
|
|
|
%{
|
|
|
- if (initial_token != 0) {
|
|
|
- int t = initial_token;
|
|
|
- initial_token = 0;
|
|
|
+ if (yyextra->_initial_token != 0) {
|
|
|
+ int t = yyextra->_initial_token;
|
|
|
+ yyextra->_initial_token = 0;
|
|
|
return t;
|
|
|
}
|
|
|
%}
|
|
|
@@ -326,10 +282,13 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
|
|
|
// New line. Save a copy of the line so we can print it out for the
|
|
|
// benefit of the user in case we get an error.
|
|
|
|
|
|
- strncpy(current_line, yytext+1, max_error_width);
|
|
|
- current_line[max_error_width] = '\0';
|
|
|
- line_number++;
|
|
|
- col_number=0;
|
|
|
+ strncpy(yyextra->_current_line, yytext+1, egg_max_error_width);
|
|
|
+ yyextra->_current_line[egg_max_error_width] = '\0';
|
|
|
+
|
|
|
+ yylloc->first_line++;
|
|
|
+ yylloc->last_line++;
|
|
|
+ yylloc->first_column = 0;
|
|
|
+ yylloc->last_column = 0;
|
|
|
|
|
|
// Return the whole line to the lexer, except the newline character,
|
|
|
// which we eat.
|
|
|
@@ -349,13 +308,13 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
|
|
|
"/*" {
|
|
|
// Eat C-style comments.
|
|
|
accept();
|
|
|
- eat_c_comment();
|
|
|
+ eat_c_comment(yylloc, yyscanner);
|
|
|
}
|
|
|
|
|
|
[{}] {
|
|
|
// Send curly braces as themselves.
|
|
|
accept();
|
|
|
- return eggyytext[0];
|
|
|
+ return yytext[0];
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -706,65 +665,65 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
|
|
|
{NUMERIC} {
|
|
|
// An integer or floating-point number.
|
|
|
accept();
|
|
|
- eggyylval._number = patof(eggyytext);
|
|
|
- eggyylval._string = yytext;
|
|
|
+ yylval->_number = patof(yytext);
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_NUMBER;
|
|
|
}
|
|
|
|
|
|
{HEX} {
|
|
|
// A hexadecimal integer number.
|
|
|
accept();
|
|
|
- eggyylval._ulong = strtoul(yytext+2, nullptr, 16);
|
|
|
- eggyylval._string = yytext;
|
|
|
+ yylval->_ulong = strtoul(yytext+2, nullptr, 16);
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_ULONG;
|
|
|
}
|
|
|
|
|
|
{BINARY} {
|
|
|
// A binary integer number.
|
|
|
accept();
|
|
|
- eggyylval._ulong = strtoul(yytext+2, nullptr, 2);
|
|
|
- eggyylval._string = yytext;
|
|
|
+ yylval->_ulong = strtoul(yytext+2, nullptr, 2);
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_ULONG;
|
|
|
}
|
|
|
|
|
|
"nan"{HEX} {
|
|
|
// not-a-number. These sometimes show up in egg files accidentally.
|
|
|
accept();
|
|
|
- memset(&eggyylval._number, 0, sizeof(eggyylval._number));
|
|
|
- *(unsigned long *)&eggyylval._number = strtoul(yytext+3, nullptr, 0);
|
|
|
- eggyylval._string = yytext;
|
|
|
+ memset(&yylval->_number, 0, sizeof(yylval->_number));
|
|
|
+ *(unsigned long *)&yylval->_number = strtoul(yytext+3, nullptr, 0);
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_NUMBER;
|
|
|
}
|
|
|
|
|
|
"inf" {
|
|
|
// infinity. As above.
|
|
|
accept();
|
|
|
- eggyylval._number = HUGE_VAL;
|
|
|
- eggyylval._string = yytext;
|
|
|
+ yylval->_number = HUGE_VAL;
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_NUMBER;
|
|
|
}
|
|
|
|
|
|
"-inf" {
|
|
|
// minus infinity. As above.
|
|
|
accept();
|
|
|
- eggyylval._number = -HUGE_VAL;
|
|
|
- eggyylval._string = yytext;
|
|
|
+ yylval->_number = -HUGE_VAL;
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_NUMBER;
|
|
|
}
|
|
|
|
|
|
"1.#inf" {
|
|
|
// infinity, on Win32. As above.
|
|
|
accept();
|
|
|
- eggyylval._number = HUGE_VAL;
|
|
|
- eggyylval._string = yytext;
|
|
|
+ yylval->_number = HUGE_VAL;
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_NUMBER;
|
|
|
}
|
|
|
|
|
|
"-1.#inf" {
|
|
|
// minus infinity, on Win32. As above.
|
|
|
accept();
|
|
|
- eggyylval._number = -HUGE_VAL;
|
|
|
- eggyylval._string = yytext;
|
|
|
+ yylval->_number = -HUGE_VAL;
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_NUMBER;
|
|
|
}
|
|
|
|
|
|
@@ -772,13 +731,13 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
|
|
|
["] {
|
|
|
// Quoted string.
|
|
|
accept();
|
|
|
- eggyylval._string = scan_quoted_string();
|
|
|
+ yylval->_string = scan_quoted_string(yylloc, yyscanner);
|
|
|
return EGG_STRING;
|
|
|
}
|
|
|
|
|
|
[^ \t\n\r{}"]+ {
|
|
|
// Unquoted string.
|
|
|
accept();
|
|
|
- eggyylval._string = yytext;
|
|
|
+ yylval->_string = yytext;
|
|
|
return EGG_STRING;
|
|
|
}
|