EXP (e[+-]{NUM10})
POSEXP (e"+"?{NUM10})
+/* This must agree with COMPLETION_CHAR below. See the comment there
+ for the explanation. */
+COMPLETE "\001"
+NOT_COMPLETE [^\001]
+
%{
#include "diagnostics.h"
Defining YY_NO_INPUT comments it out. */
#define YY_NO_INPUT
-#undef YY_INPUT
-#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
- if ( *pstate->lexptr == '\000' ) \
- (RESULT) = YY_NULL; \
- else \
- { \
- *(BUF) = *pstate->lexptr; \
- (RESULT) = 1; \
- pstate->lexptr += 1; \
- }
+/* When completing, we'll return a special character at the end of the
+ input, to signal the completion position to the lexer. This is
+ done because flex does not have a generally useful way to detect
+ EOF in a pattern. This variable records whether the special
+ character has been emitted. */
+static bool returned_complete = false;
-static int find_dot_all (const char *);
+/* The character we use to represent the completion point. */
+#define COMPLETE_CHAR '\001'
+
+#undef YY_INPUT
+#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
+ if ( *pstate->lexptr == '\000' ) \
+ { \
+ if (pstate->parse_completion && !returned_complete) \
+ { \
+ returned_complete = true; \
+ *(BUF) = COMPLETE_CHAR; \
+ (RESULT) = 1; \
+ } \
+ else \
+ (RESULT) = YY_NULL; \
+ } \
+ else \
+ { \
+ *(BUF) = *pstate->lexptr == COMPLETE_CHAR ? ' ' : *pstate->lexptr; \
+ (RESULT) = 1; \
+ pstate->lexptr += 1; \
+ }
/* Depth of parentheses. */
static int paren_depth;
/* ATTRIBUTES */
-{TICK}[a-z][a-z_]+ { BEGIN INITIAL; return processAttribute (yytext+1); }
+{TICK}([a-z][a-z_]*)?{COMPLETE}? { BEGIN INITIAL; return processAttribute (yytext); }
/* PUNCTUATION */
"<=" { return LEQ; }
">=" { return GEQ; }
-<BEFORE_QUAL_QUOTE>"'" { BEGIN INITIAL; return '\''; }
+<BEFORE_QUAL_QUOTE>"'"/{NOT_COMPLETE} { BEGIN INITIAL; return '\''; }
-[-&*+./:<>=|;\[\]] { return yytext[0]; }
+[-&*+{}@/:<>=|;\[\]] { return yytext[0]; }
"," { if (paren_depth == 0 && pstate->comma_terminates)
{
}
}
-"."{WHITE}*all { return DOT_ALL; }
-
-"."{WHITE}*{ID} {
+"."{WHITE}*{ID}{COMPLETE}? {
yylval.sval = processId (yytext+1, yyleng-1);
+ if (yytext[yyleng - 1] == COMPLETE_CHAR)
+ return DOT_COMPLETE;
return DOT_ID;
}
-{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? {
+"."{WHITE}*{COMPLETE} {
+ yylval.sval.ptr = "";
+ yylval.sval.length = 0;
+ return DOT_COMPLETE;
+ }
+
+{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'"|{COMPLETE})? {
int all_posn = find_dot_all (yytext);
if (all_posn == -1 && yytext[yyleng-1] == '\'')
}
else if (all_posn >= 0)
yyless (all_posn);
+ bool is_completion = yytext[yyleng - 1] == COMPLETE_CHAR;
yylval.sval = processId (yytext, yyleng);
- return NAME;
+ return is_completion ? NAME_COMPLETE : NAME;
}
"::" { return COLONCOLON; }
-[{}@] { return yytext[0]; }
-
/* REGISTERS AND GDB CONVENIENCE VARIABLES */
"$"({LETTER}|{DIG}|"$")* {
{
BEGIN INITIAL;
paren_depth = 0;
+ returned_complete = false;
yyrestart (inp);
}
return FLOAT;
}
- gdb_mpz maxval (ULONGEST_MAX / base);
+ gdb_mpz maxval (ULONGEST_MAX);
if (mpz_cmp (result.val, maxval.val) > 0)
error (_("Integer literal out of range"));
- LONGEST value = result.as_integer<LONGEST> ();
+ ULONGEST value = result.as_integer<ULONGEST> ();
if ((value >> (gdbarch_int_bit (par_state->gdbarch ())-1)) == 0)
yylval.typed_val.type = type_int (par_state);
else if ((value >> (gdbarch_long_bit (par_state->gdbarch ())-1)) == 0)
return result;
}
+ bool in_quotes = false;
i = i0 = 0;
while (i0 < len)
{
- if (isalnum (name0[i0]))
+ if (name0[i0] == COMPLETE_CHAR)
+ {
+ /* Just ignore. */
+ ++i0;
+ }
+ else if (in_quotes)
+ name[i++] = name0[i0++];
+ else if (isalnum (name0[i0]))
{
name[i] = tolower (name0[i0]);
i += 1; i0 += 1;
}
- else switch (name0[i0])
+ else if (isspace (name0[i0]))
+ i0 += 1;
+ else if (name0[i0] == '\'')
{
- default:
- name[i] = name0[i0];
- i += 1; i0 += 1;
- break;
- case ' ': case '\t':
- i0 += 1;
- break;
- case '\'':
- do
- {
- name[i] = name0[i0];
- i += 1; i0 += 1;
- }
- while (i0 < len && name0[i0] != '\'');
- i0 += 1;
- break;
+ /* Copy the starting quote, but not the ending quote. */
+ if (!in_quotes)
+ name[i++] = name0[i0++];
+ in_quotes = !in_quotes;
}
+ else
+ name[i++] = name0[i0++];
}
name[i] = '\000';
static int
processAttribute (const char *str)
{
+ gdb_assert (*str == '\'');
+ ++str;
+ while (isspace (*str))
+ ++str;
+
+ int len = strlen (str);
+ if (len > 0 && str[len - 1] == COMPLETE_CHAR)
+ {
+ /* This is enforced by YY_INPUT. */
+ gdb_assert (pstate->parse_completion);
+ yylval.sval.ptr = obstack_strndup (&temp_parse_space, str, len - 1);
+ yylval.sval.length = len - 1;
+ return TICK_COMPLETE;
+ }
+
for (const auto &item : attributes)
if (strcasecmp (str, item.name) == 0)
return item.code;
return *found;
}
+bool
+ada_tick_completer::complete (struct expression *exp,
+ completion_tracker &tracker)
+{
+ completion_list output;
+ for (const auto &item : attributes)
+ {
+ if (strncasecmp (item.name, m_name.c_str (), m_name.length ()) == 0)
+ output.emplace_back (xstrdup (item.name));
+ }
+ tracker.add_completions (std::move (output));
+ return true;
+}
+
/* Back up lexptr by yyleng and then to the rightmost occurrence of
character CH, case-folded (there must be one). WARNING: since
lexptr points to the next input character that Flex has not yet