From: simon.marchi@polymtl.ca
To: gdb-patches@sourceware.org
Cc: Simon Marchi <simon.marchi@polymtl.ca>
Subject: [PATCH v2 17/19] gdb: move m2-exp-parser.y's support code to m2-exp-parser.c
Date: Sat, 5 Sep 2026 00:23:20 -0400 [thread overview]
Message-ID: <20260905042353.1702204-18-simon.marchi@polymtl.ca> (raw)
In-Reply-To: <20260905042353.1702204-1-simon.marchi@polymtl.ca>
From: Simon Marchi <simon.marchi@polymtl.ca>
Similar to the previous commits, but for the Modula-2 expression parser.
Like the Fortran parser, the Modula-2 parser is entered through the
m2_language::parser method rather than a free function, so add a free
function m2_parse as the entry point (like the other parsers) and turn
m2_language::parser into a thin wrapper around it, defined in m2-lang.c.
Put the parser support code inside the m2_exp_parser namespace.
Change-Id: I92669a1af7fb81cf59bfb41e2b8c63ce323652d2
---
gdb/Makefile.in | 2 +
gdb/m2-exp-parser.c | 488 ++++++++++++++++++++++++++++++++++++++++++++
gdb/m2-exp-parser.h | 67 ++++++
gdb/m2-exp-parser.y | 465 +----------------------------------------
gdb/m2-lang.c | 9 +
5 files changed, 568 insertions(+), 463 deletions(-)
create mode 100644 gdb/m2-exp-parser.c
create mode 100644 gdb/m2-exp-parser.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4289c5151fd0..1c4ba5a12d57 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1137,6 +1137,7 @@ COMMON_SFILES = \
language.c \
linespec.c \
location.c \
+ m2-exp-parser.c \
m2-lang.c \
m2-typeprint.c \
m2-valprint.c \
@@ -1518,6 +1519,7 @@ HFILES_NO_SRCDIR = \
linux-tdep.h \
location.h \
loongarch-tdep.h \
+ m2-exp-parser.h \
m2-exp.h \
m2-lang.h \
m32r-tdep.h \
diff --git a/gdb/m2-exp-parser.c b/gdb/m2-exp-parser.c
new file mode 100644
index 000000000000..821f1507aef3
--- /dev/null
+++ b/gdb/m2-exp-parser.c
@@ -0,0 +1,488 @@
+/* YACC parser support code for Modula-2 expressions, for GDB.
+
+ Copyright (C) 1986-2026 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "m2-exp-parser.h"
+#include "m2-exp-parser-gen.h"
+#include "block.h"
+#include "expression.h"
+#include "language.h"
+#include "m2-exp.h"
+#include "parser-defs.h"
+#include "value.h"
+
+/* The entry point of the bison/yacc-generated parser, defined in
+ m2-exp-parser-gen.c. Bison produces a declaration for m2_yyparse in
+ m2-exp-parser-gen.h, but byacc does not, hence this declaration. */
+
+int m2_yyparse ();
+
+/* Likewise, byacc does not produce a declaration for m2_yydebug. */
+
+extern int m2_yydebug;
+
+namespace m2_exp_parser
+{
+
+/* See m2-exp-parser.h. */
+
+parser_state *pstate;
+
+/* See m2-exp-parser.h. */
+
+int number_sign = 1;
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (int olen)
+{
+ const char *p = pstate->lexptr;
+ ULONGEST n = 0;
+ ULONGEST prevn = 0;
+ int c,i,ischar=0;
+ int base = input_radix;
+ int len = olen;
+
+ if(p[len-1] == 'H')
+ {
+ base = 16;
+ len--;
+ }
+ else if(p[len-1] == 'C' || p[len-1] == 'B')
+ {
+ base = 8;
+ ischar = p[len-1] == 'C';
+ len--;
+ }
+
+ /* Scan the number */
+ for (c = 0; c < len; c++)
+ {
+ if (p[c] == '.' && base == 10)
+ {
+ /* It's a float since it contains a point. */
+ if (!parse_float (p, len,
+ parse_m2_type (pstate)->builtin_real,
+ m2_yylval.val))
+ return ERROR;
+
+ pstate->lexptr += len;
+ return FLOAT;
+ }
+ if (p[c] == '.' && base != 10)
+ error (_("Floating point numbers must be base 10."));
+ if (base == 10 && (p[c] < '0' || p[c] > '9'))
+ error (_("Invalid digit \'%c\' in number."),p[c]);
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ n *= base;
+ if( base == 8 && (c == '8' || c == '9'))
+ error (_("Invalid digit \'%c\' in octal number."),c);
+ if (c >= '0' && c <= '9')
+ i = c - '0';
+ else
+ {
+ if (base == 16 && c >= 'A' && c <= 'F')
+ i = c - 'A' + 10;
+ else
+ return ERROR;
+ }
+ n+=i;
+ if(i >= base)
+ return ERROR;
+ if (n == 0 && prevn == 0)
+ ;
+ else if (RANGE_CHECK && prevn >= n)
+ range_error (_("Overflow on numeric constant."));
+
+ prevn=n;
+ }
+
+ pstate->lexptr = p;
+ if(*p == 'B' || *p == 'C' || *p == 'H')
+ pstate->lexptr++; /* Advance past B,C or H */
+
+ if (ischar)
+ {
+ m2_yylval.ulval = n;
+ return CHAR;
+ }
+
+ int int_bits = gdbarch_int_bit (pstate->gdbarch ());
+ bool have_signed = number_sign == -1;
+ bool have_unsigned = number_sign == 1;
+ if (have_signed && fits_in_type (number_sign, n, int_bits, true))
+ {
+ m2_yylval.lval = n;
+ return INT;
+ }
+ else if (have_unsigned && fits_in_type (number_sign, n, int_bits, false))
+ {
+ m2_yylval.ulval = n;
+ return UINT;
+ }
+ else
+ error (_("Overflow on numeric constant."));
+}
+
+/* Some tokens */
+
+static struct
+{
+ char name[2];
+ int token;
+} tokentab2[] =
+{
+ { {'<', '>'}, NOTEQUAL },
+ { {':', '='}, ASSIGN },
+ { {'<', '='}, LEQ },
+ { {'>', '='}, GEQ },
+ { {':', ':'}, COLONCOLON },
+
+};
+
+/* Some specific keywords */
+
+struct keyword {
+ char keyw[10];
+ int token;
+};
+
+static struct keyword keytab[] =
+{
+ {"OR" , OROR },
+ {"IN", IN },/* Note space after IN */
+ {"AND", LOGICAL_AND},
+ {"ABS", ABS },
+ {"ADR", ADR },
+ {"CHR", CHR },
+ {"DEC", DEC },
+ {"NOT", NOT },
+ {"DIV", DIV },
+ {"INC", INC },
+ {"MAX", MAX_FUNC },
+ {"MIN", MIN_FUNC },
+ {"MOD", MOD },
+ {"ODD", ODD },
+ {"CAP", CAP },
+ {"ORD", ORD },
+ {"VAL", VAL },
+ {"EXCL", EXCL },
+ {"HIGH", HIGH },
+ {"INCL", INCL },
+ {"SIZE", SIZE },
+ {"FLOAT", FLOAT_FUNC },
+ {"TRUNC", TRUNC },
+ {"TSIZE", SIZE },
+};
+
+/* Depth of parentheses. */
+static int paren_depth;
+
+/* See m2-exp-parser.h. */
+
+int
+m2_yylex (void)
+{
+ int c;
+ int namelen;
+ int i;
+ const char *tokstart;
+ char quote;
+
+ retry:
+
+ pstate->prev_lexptr = pstate->lexptr;
+
+ tokstart = pstate->lexptr;
+
+
+ /* See if it is a special token of length 2 */
+ for( i = 0 ; i < (int) (sizeof tokentab2 / sizeof tokentab2[0]) ; i++)
+ if (strncmp (tokentab2[i].name, tokstart, 2) == 0)
+ {
+ pstate->lexptr += 2;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ pstate->lexptr++;
+ goto retry;
+
+ case '(':
+ paren_depth++;
+ pstate->lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ pstate->lexptr++;
+ return c;
+
+ case ',':
+ if (pstate->comma_terminates && paren_depth == 0)
+ return 0;
+ pstate->lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (pstate->lexptr[1] >= '0' && pstate->lexptr[1] <= '9')
+ break; /* Falls into number code. */
+ else
+ {
+ pstate->lexptr++;
+ return DOT;
+ }
+
+/* These are character tokens that appear as-is in the YACC grammar */
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '^':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '=':
+ case '{':
+ case '}':
+ case '#':
+ case '@':
+ case '~':
+ case '&':
+ pstate->lexptr++;
+ return c;
+
+ case '\'' :
+ case '"':
+ quote = c;
+ for (namelen = 1; (c = tokstart[namelen]) != quote && c != '\0'; namelen++)
+ if (c == '\\')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ c = tokstart[++namelen];
+ }
+ }
+ if(c != quote)
+ error (_("Unterminated string or character constant."));
+ m2_yylval.sval.ptr = tokstart + 1;
+ m2_yylval.sval.length = namelen - 1;
+ pstate->lexptr += namelen + 1;
+
+ if(namelen == 2) /* Single character */
+ {
+ m2_yylval.ulval = tokstart[1];
+ return CHAR;
+ }
+ else
+ return STRING;
+ }
+
+ /* Is it a number? */
+ /* Note: We have already dealt with the case of the token '.'.
+ See case '.' above. */
+ if ((c >= '0' && c <= '9'))
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0;
+ const char *p = tokstart;
+ int toktype;
+
+ for (++p ;; ++p)
+ {
+ if (!got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!got_dot && *p == '.')
+ got_dot = 1;
+ else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ else if ((*p < '0' || *p > '9') &&
+ (*p < 'A' || *p > 'F') &&
+ (*p != 'H')) /* Modula-2 hexadecimal number */
+ break;
+ }
+ toktype = parse_number (p - tokstart);
+ if (toktype == ERROR)
+ error (_("Invalid number \"%.*s\"."), (int) (p - tokstart),
+ tokstart);
+ pstate->lexptr = p;
+ return toktype;
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error (_("Invalid character '%c' in expression."), c);
+
+ /* It's a name. See how long it is. */
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen])
+ ;
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ {
+ return 0;
+ }
+
+ pstate->lexptr += namelen;
+
+ /* Lookup special keywords */
+ for(i = 0 ; i < (int) (sizeof(keytab) / sizeof(keytab[0])) ; i++)
+ if (namelen == strlen (keytab[i].keyw)
+ && strncmp (tokstart, keytab[i].keyw, namelen) == 0)
+ return keytab[i].token;
+
+ m2_yylval.sval.ptr = tokstart;
+ m2_yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ return DOLLAR_VARIABLE;
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions. If this is not so, then ...
+ Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ std::string tmp = copy_name (m2_yylval.sval);
+ struct symbol *sym;
+
+ if (lookup_symtab (current_program_space, tmp.c_str ()) != nullptr)
+ return BLOCKNAME;
+
+ sym = lookup_symbol (tmp.c_str (), pstate->expression_context_block,
+ SEARCH_VFT, 0).symbol;
+ if (sym && sym->loc_class () == LOC_BLOCK)
+ return BLOCKNAME;
+ if (lookup_typename (pstate->language (),
+ tmp.c_str (), pstate->expression_context_block, 1))
+ return TYPENAME;
+
+ if(sym)
+ {
+ switch(sym->loc_class ())
+ {
+ case LOC_STATIC:
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_CONST:
+ case LOC_CONST_BYTES:
+ case LOC_OPTIMIZED_OUT:
+ case LOC_COMPUTED:
+ return NAME;
+
+ case LOC_TYPEDEF:
+ return TYPENAME;
+
+ case LOC_BLOCK:
+ return BLOCKNAME;
+
+ case LOC_UNDEF:
+ error (_("internal: Undefined class in m2lex()"));
+
+ case LOC_LABEL:
+ case LOC_UNRESOLVED:
+ error (_("internal: Unforeseen case in m2lex()"));
+
+ default:
+ error (_("unhandled token in m2lex()"));
+ break;
+ }
+ }
+ else
+ {
+ /* Built-in BOOLEAN type. This is sort of a hack. */
+ if (startswith (tokstart, "TRUE"))
+ {
+ m2_yylval.ulval = 1;
+ return M2_TRUE;
+ }
+ else if (startswith (tokstart, "FALSE"))
+ {
+ m2_yylval.ulval = 0;
+ return M2_FALSE;
+ }
+ }
+
+ /* Must be another type of name... */
+ return NAME;
+ }
+}
+
+/* See m2-exp-parser.h. */
+
+void
+m2_yyerror (const char *msg)
+{
+ pstate->parse_error (msg);
+}
+
+} /* namespace m2_exp_parser */
+
+/* See m2-exp-parser.h. */
+
+int
+m2_parse (struct parser_state *par_state)
+{
+ using namespace m2_exp_parser;
+
+ /* Setting up the parser state. */
+ scoped_restore pstate_restore = make_scoped_restore (&pstate);
+ gdb_assert (par_state != NULL);
+ pstate = par_state;
+ paren_depth = 0;
+
+ int result = m2_yyparse ();
+ if (!result)
+ pstate->set_operation (pstate->pop ());
+ return result;
+}
diff --git a/gdb/m2-exp-parser.h b/gdb/m2-exp-parser.h
new file mode 100644
index 000000000000..bea7155188fb
--- /dev/null
+++ b/gdb/m2-exp-parser.h
@@ -0,0 +1,67 @@
+/* YACC parser support code for Modula-2 expressions, for GDB.
+
+ Copyright (C) 1986-2026 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_M2_EXP_PARSER_H
+#define GDB_M2_EXP_PARSER_H
+
+#include "parser-defs.h"
+#include "m2-lang.h"
+
+union m2_exp_parser_YYSTYPE;
+
+namespace m2_exp_parser {
+
+/* The state of the parser, used internally when we are parsing the
+ expression. */
+
+extern parser_state *pstate;
+
+/* The sign of the number being parsed. */
+
+extern int number_sign;
+
+/* Return the Modula-2 type table for the architecture associated to PS. */
+
+static inline const struct builtin_m2_type *
+parse_m2_type (parser_state *ps)
+{
+ return builtin_m2_type (ps->gdbarch ());
+}
+
+/* Read one token, getting characters through lexptr. */
+
+/* This is where we will check to make sure that the language and the
+ operators used are compatible */
+
+int m2_yylex ();
+
+/* The error handler invoked by the generated parser. Report MSG as a
+ parse error on the current parser state. */
+
+void m2_yyerror (const char *msg);
+
+} /* namespace m2_exp_parser */
+
+/* Parse a Modula-2 expression using the lexer input and context held in
+ PAR_STATE. On success, return 0 and leave the resulting operation set
+ on PAR_STATE. On failure, return non-zero. */
+
+int m2_parse (struct parser_state *par_state);
+
+#endif /* GDB_M2_EXP_PARSER_H */
diff --git a/gdb/m2-exp-parser.y b/gdb/m2-exp-parser.y
index 0f1c62c7ae52..a10087fa03ab 100644
--- a/gdb/m2-exp-parser.y
+++ b/gdb/m2-exp-parser.y
@@ -42,33 +42,11 @@
#include "value.h"
#include "parser-defs.h"
#include "m2-lang.h"
+#include "m2-exp-parser.h"
#include "block.h"
#include "m2-exp.h"
-/* The state of the parser, used internally when we are parsing the
- expression. */
-
-static struct parser_state *pstate = NULL;
-
-int yyparse (void);
-
-static int yylex (void);
-
-static void yyerror (const char *);
-
-static int parse_number (int);
-
-/* The sign of the number being parsed. */
-static int number_sign = 1;
-
-/* Return the Modula-2 type table for the architecture associated to PS. */
-
-static inline const struct builtin_m2_type *
-parse_m2_type (parser_state *ps)
-{
- return builtin_m2_type (ps->gdbarch ());
-}
-
+using namespace m2_exp_parser;
using namespace expr;
%}
@@ -569,442 +547,3 @@ type
}
;
-
-%%
-
-/* Take care of parsing a number (anything that starts with a digit).
- Set yylval and return the token type; update lexptr.
- LEN is the number of characters in it. */
-
-/*** Needs some error checking for the float case ***/
-
-static int
-parse_number (int olen)
-{
- const char *p = pstate->lexptr;
- ULONGEST n = 0;
- ULONGEST prevn = 0;
- int c,i,ischar=0;
- int base = input_radix;
- int len = olen;
-
- if(p[len-1] == 'H')
- {
- base = 16;
- len--;
- }
- else if(p[len-1] == 'C' || p[len-1] == 'B')
- {
- base = 8;
- ischar = p[len-1] == 'C';
- len--;
- }
-
- /* Scan the number */
- for (c = 0; c < len; c++)
- {
- if (p[c] == '.' && base == 10)
- {
- /* It's a float since it contains a point. */
- if (!parse_float (p, len,
- parse_m2_type (pstate)->builtin_real,
- yylval.val))
- return ERROR;
-
- pstate->lexptr += len;
- return FLOAT;
- }
- if (p[c] == '.' && base != 10)
- error (_("Floating point numbers must be base 10."));
- if (base == 10 && (p[c] < '0' || p[c] > '9'))
- error (_("Invalid digit \'%c\' in number."),p[c]);
- }
-
- while (len-- > 0)
- {
- c = *p++;
- n *= base;
- if( base == 8 && (c == '8' || c == '9'))
- error (_("Invalid digit \'%c\' in octal number."),c);
- if (c >= '0' && c <= '9')
- i = c - '0';
- else
- {
- if (base == 16 && c >= 'A' && c <= 'F')
- i = c - 'A' + 10;
- else
- return ERROR;
- }
- n+=i;
- if(i >= base)
- return ERROR;
- if (n == 0 && prevn == 0)
- ;
- else if (RANGE_CHECK && prevn >= n)
- range_error (_("Overflow on numeric constant."));
-
- prevn=n;
- }
-
- pstate->lexptr = p;
- if(*p == 'B' || *p == 'C' || *p == 'H')
- pstate->lexptr++; /* Advance past B,C or H */
-
- if (ischar)
- {
- yylval.ulval = n;
- return CHAR;
- }
-
- int int_bits = gdbarch_int_bit (pstate->gdbarch ());
- bool have_signed = number_sign == -1;
- bool have_unsigned = number_sign == 1;
- if (have_signed && fits_in_type (number_sign, n, int_bits, true))
- {
- yylval.lval = n;
- return INT;
- }
- else if (have_unsigned && fits_in_type (number_sign, n, int_bits, false))
- {
- yylval.ulval = n;
- return UINT;
- }
- else
- error (_("Overflow on numeric constant."));
-}
-
-
-/* Some tokens */
-
-static struct
-{
- char name[2];
- int token;
-} tokentab2[] =
-{
- { {'<', '>'}, NOTEQUAL },
- { {':', '='}, ASSIGN },
- { {'<', '='}, LEQ },
- { {'>', '='}, GEQ },
- { {':', ':'}, COLONCOLON },
-
-};
-
-/* Some specific keywords */
-
-struct keyword {
- char keyw[10];
- int token;
-};
-
-static struct keyword keytab[] =
-{
- {"OR" , OROR },
- {"IN", IN },/* Note space after IN */
- {"AND", LOGICAL_AND},
- {"ABS", ABS },
- {"ADR", ADR },
- {"CHR", CHR },
- {"DEC", DEC },
- {"NOT", NOT },
- {"DIV", DIV },
- {"INC", INC },
- {"MAX", MAX_FUNC },
- {"MIN", MIN_FUNC },
- {"MOD", MOD },
- {"ODD", ODD },
- {"CAP", CAP },
- {"ORD", ORD },
- {"VAL", VAL },
- {"EXCL", EXCL },
- {"HIGH", HIGH },
- {"INCL", INCL },
- {"SIZE", SIZE },
- {"FLOAT", FLOAT_FUNC },
- {"TRUNC", TRUNC },
- {"TSIZE", SIZE },
-};
-
-
-/* Depth of parentheses. */
-static int paren_depth;
-
-/* Read one token, getting characters through lexptr. */
-
-/* This is where we will check to make sure that the language and the
- operators used are compatible */
-
-static int
-yylex (void)
-{
- int c;
- int namelen;
- int i;
- const char *tokstart;
- char quote;
-
- retry:
-
- pstate->prev_lexptr = pstate->lexptr;
-
- tokstart = pstate->lexptr;
-
-
- /* See if it is a special token of length 2 */
- for( i = 0 ; i < (int) (sizeof tokentab2 / sizeof tokentab2[0]) ; i++)
- if (strncmp (tokentab2[i].name, tokstart, 2) == 0)
- {
- pstate->lexptr += 2;
- return tokentab2[i].token;
- }
-
- switch (c = *tokstart)
- {
- case 0:
- return 0;
-
- case ' ':
- case '\t':
- case '\n':
- pstate->lexptr++;
- goto retry;
-
- case '(':
- paren_depth++;
- pstate->lexptr++;
- return c;
-
- case ')':
- if (paren_depth == 0)
- return 0;
- paren_depth--;
- pstate->lexptr++;
- return c;
-
- case ',':
- if (pstate->comma_terminates && paren_depth == 0)
- return 0;
- pstate->lexptr++;
- return c;
-
- case '.':
- /* Might be a floating point number. */
- if (pstate->lexptr[1] >= '0' && pstate->lexptr[1] <= '9')
- break; /* Falls into number code. */
- else
- {
- pstate->lexptr++;
- return DOT;
- }
-
-/* These are character tokens that appear as-is in the YACC grammar */
- case '+':
- case '-':
- case '*':
- case '/':
- case '^':
- case '<':
- case '>':
- case '[':
- case ']':
- case '=':
- case '{':
- case '}':
- case '#':
- case '@':
- case '~':
- case '&':
- pstate->lexptr++;
- return c;
-
- case '\'' :
- case '"':
- quote = c;
- for (namelen = 1; (c = tokstart[namelen]) != quote && c != '\0'; namelen++)
- if (c == '\\')
- {
- c = tokstart[++namelen];
- if (c >= '0' && c <= '9')
- {
- c = tokstart[++namelen];
- if (c >= '0' && c <= '9')
- c = tokstart[++namelen];
- }
- }
- if(c != quote)
- error (_("Unterminated string or character constant."));
- yylval.sval.ptr = tokstart + 1;
- yylval.sval.length = namelen - 1;
- pstate->lexptr += namelen + 1;
-
- if(namelen == 2) /* Single character */
- {
- yylval.ulval = tokstart[1];
- return CHAR;
- }
- else
- return STRING;
- }
-
- /* Is it a number? */
- /* Note: We have already dealt with the case of the token '.'.
- See case '.' above. */
- if ((c >= '0' && c <= '9'))
- {
- /* It's a number. */
- int got_dot = 0, got_e = 0;
- const char *p = tokstart;
- int toktype;
-
- for (++p ;; ++p)
- {
- if (!got_e && (*p == 'e' || *p == 'E'))
- got_dot = got_e = 1;
- else if (!got_dot && *p == '.')
- got_dot = 1;
- else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
- && (*p == '-' || *p == '+'))
- /* This is the sign of the exponent, not the end of the
- number. */
- continue;
- else if ((*p < '0' || *p > '9') &&
- (*p < 'A' || *p > 'F') &&
- (*p != 'H')) /* Modula-2 hexadecimal number */
- break;
- }
- toktype = parse_number (p - tokstart);
- if (toktype == ERROR)
- error (_("Invalid number \"%.*s\"."), (int) (p - tokstart),
- tokstart);
- pstate->lexptr = p;
- return toktype;
- }
-
- if (!(c == '_' || c == '$'
- || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
- /* We must have come across a bad character (e.g. ';'). */
- error (_("Invalid character '%c' in expression."), c);
-
- /* It's a name. See how long it is. */
- namelen = 0;
- for (c = tokstart[namelen];
- (c == '_' || c == '$' || (c >= '0' && c <= '9')
- || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
- c = tokstart[++namelen])
- ;
-
- /* The token "if" terminates the expression and is NOT
- removed from the input stream. */
- if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
- {
- return 0;
- }
-
- pstate->lexptr += namelen;
-
- /* Lookup special keywords */
- for(i = 0 ; i < (int) (sizeof(keytab) / sizeof(keytab[0])) ; i++)
- if (namelen == strlen (keytab[i].keyw)
- && strncmp (tokstart, keytab[i].keyw, namelen) == 0)
- return keytab[i].token;
-
- yylval.sval.ptr = tokstart;
- yylval.sval.length = namelen;
-
- if (*tokstart == '$')
- return DOLLAR_VARIABLE;
-
- /* Use token-type BLOCKNAME for symbols that happen to be defined as
- functions. If this is not so, then ...
- Use token-type TYPENAME for symbols that happen to be defined
- currently as names of types; NAME for other symbols.
- The caller is not constrained to care about the distinction. */
- {
- std::string tmp = copy_name (yylval.sval);
- struct symbol *sym;
-
- if (lookup_symtab (current_program_space, tmp.c_str ()) != nullptr)
- return BLOCKNAME;
-
- sym = lookup_symbol (tmp.c_str (), pstate->expression_context_block,
- SEARCH_VFT, 0).symbol;
- if (sym && sym->loc_class () == LOC_BLOCK)
- return BLOCKNAME;
- if (lookup_typename (pstate->language (),
- tmp.c_str (), pstate->expression_context_block, 1))
- return TYPENAME;
-
- if(sym)
- {
- switch(sym->loc_class ())
- {
- case LOC_STATIC:
- case LOC_REGISTER:
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM_ADDR:
- case LOC_LOCAL:
- case LOC_CONST:
- case LOC_CONST_BYTES:
- case LOC_OPTIMIZED_OUT:
- case LOC_COMPUTED:
- return NAME;
-
- case LOC_TYPEDEF:
- return TYPENAME;
-
- case LOC_BLOCK:
- return BLOCKNAME;
-
- case LOC_UNDEF:
- error (_("internal: Undefined class in m2lex()"));
-
- case LOC_LABEL:
- case LOC_UNRESOLVED:
- error (_("internal: Unforeseen case in m2lex()"));
-
- default:
- error (_("unhandled token in m2lex()"));
- break;
- }
- }
- else
- {
- /* Built-in BOOLEAN type. This is sort of a hack. */
- if (startswith (tokstart, "TRUE"))
- {
- yylval.ulval = 1;
- return M2_TRUE;
- }
- else if (startswith (tokstart, "FALSE"))
- {
- yylval.ulval = 0;
- return M2_FALSE;
- }
- }
-
- /* Must be another type of name... */
- return NAME;
- }
-}
-
-int
-m2_language::parser (struct parser_state *par_state) const
-{
- /* Setting up the parser state. */
- scoped_restore pstate_restore = make_scoped_restore (&pstate);
- gdb_assert (par_state != NULL);
- pstate = par_state;
- paren_depth = 0;
-
- int result = yyparse ();
- if (!result)
- pstate->set_operation (pstate->pop ());
- return result;
-}
-
-static void
-yyerror (const char *msg)
-{
- pstate->parse_error (msg);
-}
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 7bee1f36dc83..53bb8e25212e 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -25,6 +25,7 @@
#include "language.h"
#include "varobj.h"
#include "m2-lang.h"
+#include "m2-exp-parser.h"
#include "c-lang.h"
#include "valprint.h"
#include "gdbarch.h"
@@ -118,6 +119,14 @@ static m2_language m2_language_defn;
/* See language.h. */
+int
+m2_language::parser (struct parser_state *ps) const
+{
+ return m2_parse (ps);
+}
+
+/* See language.h. */
+
void
m2_language::language_arch_info (struct gdbarch *gdbarch,
struct language_arch_info *lai) const
--
2.55.0
next prev parent reply other threads:[~2026-09-05 4:28 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-05 4:23 [PATCH v2 00/19] Move C++ support code out of .y files simon.marchi
2026-09-05 4:23 ` [PATCH v2 01/19] gdb/ada-exp-parser: remove name_info struct simon.marchi
2026-09-05 4:23 ` [PATCH v2 02/19] gdb: replace parse_type macros with functions simon.marchi
2026-09-05 4:23 ` [PATCH v2 03/19] gdb: suffix flex/bison output files with -gen.c simon.marchi
2026-09-05 4:23 ` [PATCH v2 04/19] gdb: remove YY_NULL to YY_NULLPTR substitution simon.marchi
2026-09-05 4:23 ` [PATCH v2 05/19] gdb: move parser output post-processing to a script simon.marchi
2026-09-05 4:23 ` [PATCH v2 06/19] gdb: let the parser and lexer generators prefix their symbols simon.marchi
2026-09-05 4:23 ` [PATCH v2 07/19] gdb: separate cp-name-parser's symbol prefix with an underscore simon.marchi
2026-09-05 4:23 ` [PATCH v2 08/19] gdb: make $(YACC) and $(FLEX) generate headers simon.marchi
2026-09-05 4:23 ` [PATCH v2 09/19] gdb: add check for stale build generated files simon.marchi
2026-09-05 4:23 ` [PATCH v2 10/19] gdb: move cp-name-parser.y's support code to cp-name-parser.c simon.marchi
2026-09-05 4:23 ` [PATCH v2 11/19] gdb: rename LANG-exp.y to LANG-exp-parser.y simon.marchi
2026-09-05 4:23 ` [PATCH v2 12/19] gdb: move c-exp-parser.y's support code to c-exp-parser.c simon.marchi
2026-09-05 4:23 ` [PATCH v2 13/19] gdb: move ada-exp-parser.y's support code to ada-exp-parser.c simon.marchi
2026-09-08 18:28 ` Kevin Buettner
2026-09-05 4:23 ` [PATCH v2 14/19] gdb: move d-exp-parser.y's support code to d-exp-parser.c simon.marchi
2026-09-05 4:23 ` [PATCH v2 15/19] gdb: move f-exp-parser.y's support code to f-exp-parser.c simon.marchi
2026-09-05 4:23 ` [PATCH v2 16/19] gdb: move go-exp-parser.y's support code to go-exp-parser.c simon.marchi
2026-09-05 4:23 ` simon.marchi [this message]
2026-09-05 4:23 ` [PATCH v2 18/19] gdb: move p-exp-parser.y's support code to p-exp-parser.c simon.marchi
2026-09-05 4:23 ` [PATCH v2 19/19] gdb: honor "set debug parser" in the Modula-2 and Pascal parsers simon.marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260905042353.1702204-18-simon.marchi@polymtl.ca \
--to=simon.marchi@polymtl.ca \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox