#include <unictype.h>
#include <unistd.h>
#include <unistr.h>
-#include <uniwidth.h>
#include "language/command.h"
#include "language/lexer/macro.h"
return;
}
}
+
+/* Advances LEXER by N tokens. */
+void
+lex_get_n (struct lexer *lexer, size_t n)
+{
+ while (n-- > 0)
+ lex_get (lexer);
+}
\f
/* Issuing errors. */
ds_put_cstr (&s, ": ");
ds_put_vformat (&s, format, args);
}
- ds_put_byte (&s, '.');
+ if (ds_last (&s) != '.')
+ ds_put_byte (&s, '.');
msg (SE, "%s", ds_cstr (&s));
ds_destroy (&s);
}
}
}
-/* If LEXER is positioned at the sequence of tokens that may be parsed from S,
- skips it and returns true. Otherwise, returns false.
-
- S may consist of an arbitrary sequence of tokens, e.g. "KRUSKAL-WALLIS",
- "2SLS", or "END INPUT PROGRAM". Identifiers may be abbreviated to their
- first three letters. */
-bool
-lex_match_phrase (struct lexer *lexer, const char *s)
+static size_t
+lex_at_phrase__ (struct lexer *lexer, const char *s)
{
struct string_lexer slex;
struct token token;
- int i;
- i = 0;
+ size_t i = 0;
string_lexer_init (&slex, s, strlen (s), SEG_MODE_INTERACTIVE, true);
while (string_lexer_next (&slex, &token))
{
bool match = lex_tokens_match (lex_next (lexer, i++), &token);
token_uninit (&token);
if (!match)
- return false;
+ return 0;
}
+ return i;
+}
- while (i-- > 0)
- lex_get (lexer);
- return true;
+/* If LEXER is positioned at the sequence of tokens that may be parsed from S,
+ returns true. Otherwise, returns false.
+
+ S may consist of an arbitrary sequence of tokens, e.g. "KRUSKAL-WALLIS",
+ "2SLS", or "END INPUT PROGRAM". Identifiers may be abbreviated to their
+ first three letters. */
+bool
+lex_at_phrase (struct lexer *lexer, const char *s)
+{
+ return lex_at_phrase__ (lexer, s) > 0;
+}
+
+/* If LEXER is positioned at the sequence of tokens that may be parsed from S,
+ skips it and returns true. Otherwise, returns false.
+
+ S may consist of an arbitrary sequence of tokens, e.g. "KRUSKAL-WALLIS",
+ "2SLS", or "END INPUT PROGRAM". Identifiers may be abbreviated to their
+ first three letters. */
+bool
+lex_match_phrase (struct lexer *lexer, const char *s)
+{
+ size_t n = lex_at_phrase__ (lexer, s);
+ if (n > 0)
+ lex_get_n (lexer, n);
+ return n > 0;
}
static int
}
}
-static int
-count_columns (const char *s_, size_t length)
-{
- const uint8_t *s = CHAR_CAST (const uint8_t *, s_);
- int columns;
- size_t ofs;
- int mblen;
-
- columns = 0;
- for (ofs = 0; ofs < length; ofs += mblen)
- {
- ucs4_t uc;
-
- mblen = u8_mbtouc (&uc, s + ofs, length - ofs);
- if (uc != '\t')
- {
- int width = uc_width (uc, "UTF-8");
- if (width > 0)
- columns += width;
- }
- else
- columns = ROUND_UP (columns + 1, 8);
- }
-
- return columns + 1;
-}
-
static int
lex_token_get_first_column (const struct lex_source *src,
const struct lex_token *token)
{
- return count_columns (&src->buffer[token->line_pos - src->tail],
- token->token_pos - token->line_pos);
+ return utf8_count_columns (&src->buffer[token->line_pos - src->tail],
+ token->token_pos - token->line_pos) + 1;
}
static int
newline = memrchr (start, '\n', end - start);
if (newline != NULL)
start = newline + 1;
- return count_columns (start, end - start);
+ return utf8_count_columns (start, end - start) + 1;
}
static struct msg_location
_("Macro Expansion")));
/* Append the macro expansion tokens to the lookahead. */
- char *macro_rep = ds_steal_cstr (&s);
- size_t *ref_cnt = xmalloc (sizeof *ref_cnt);
- *ref_cnt = expansion.n;
- for (size_t i = 0; i < expansion.n; i++)
+ if (expansion.n > 0)
{
- struct lex_token *token = xmalloc (sizeof *token);
- *token = (struct lex_token) {
- .token = expansion.mts[i].token,
- .token_pos = c0->token_pos,
- .token_len = (c1->token_pos + c1->token_len) - c0->token_pos,
- .line_pos = c0->line_pos,
- .first_line = c0->first_line,
- .macro_rep = macro_rep,
- .ofs = ofs[i],
- .len = len[i],
- .ref_cnt = ref_cnt,
- };
- lex_stage_push_last (&src->merge, token);
+ char *macro_rep = ds_steal_cstr (&s);
+ size_t *ref_cnt = xmalloc (sizeof *ref_cnt);
+ *ref_cnt = expansion.n;
+ for (size_t i = 0; i < expansion.n; i++)
+ {
+ struct lex_token *token = xmalloc (sizeof *token);
+ *token = (struct lex_token) {
+ .token = expansion.mts[i].token,
+ .token_pos = c0->token_pos,
+ .token_len = (c1->token_pos + c1->token_len) - c0->token_pos,
+ .line_pos = c0->line_pos,
+ .first_line = c0->first_line,
+ .macro_rep = macro_rep,
+ .ofs = ofs[i],
+ .len = len[i],
+ .ref_cnt = ref_cnt,
+ };
+ lex_stage_push_last (&src->merge, token);
- ss_dealloc (&expansion.mts[i].syntax);
+ ss_dealloc (&expansion.mts[i].syntax);
+ }
}
+ else
+ ds_destroy (&s);
free (expansion.mts);
free (ofs);
free (len);
lex_source_get_lookahead (struct lex_source *src)
{
struct merger m = MERGER_INIT;
+ struct token out;
for (size_t i = 0; ; i++)
{
while (lex_stage_count (&src->merge) <= i && !lex_source_get_merge (src))
return false;
}
- struct token out;
int retval = merger_add (&m, &lex_stage_nth (&src->merge, i)->token,
&out);
if (!retval)
.macro_rep = macro ? first->macro_rep : NULL,
.ofs = macro ? first->ofs : 0,
.len = macro ? (last->ofs - first->ofs) + last->len : 0,
- .ref_cnt = first->ref_cnt,
+ .ref_cnt = macro ? first->ref_cnt : NULL,
};
if (t->ref_cnt)
++*t->ref_cnt;