aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Make.am2
-rw-r--r--src/bind-gram.y68
-rw-r--r--src/bind-lex.l58
-rw-r--r--src/diag.c18
-rw-r--r--src/format.c59
-rw-r--r--src/git-parser.c93
-rw-r--r--src/grecs-gram.y43
-rw-r--r--src/grecs-lex.l102
-rw-r--r--src/grecs-locus.h56
-rw-r--r--src/grecs.h45
-rw-r--r--src/join.c27
-rw-r--r--src/lookup.c54
-rw-r--r--src/meta1-gram.y37
-rw-r--r--src/meta1-lex.l27
-rw-r--r--src/parser.c5
-rw-r--r--src/path-parser.c172
-rw-r--r--src/preproc.c22
-rw-r--r--src/tree.c45
-rw-r--r--tests/Makefile.am9
-rw-r--r--tests/format01.at28
-rw-r--r--tests/gcf1.conf12
-rw-r--r--tests/gcffmt.c14
-rw-r--r--tests/gcfpeek.c20
-rw-r--r--tests/join.at16
-rw-r--r--tests/locus-bind.at40
-rw-r--r--tests/locus-git.at61
-rw-r--r--tests/locus-meta1.at37
-rw-r--r--tests/locus00.at30
-rw-r--r--tests/locus01.at34
-rw-r--r--tests/locus02.at32
-rw-r--r--tests/path-locus.at92
-rw-r--r--tests/set.at2
-rw-r--r--tests/testsuite.at22
33 files changed, 1034 insertions, 348 deletions
diff --git a/src/Make.am b/src/Make.am
index bc70edc..286bf4c 100644
--- a/src/Make.am
+++ b/src/Make.am
@@ -59,7 +59,7 @@ GRECS_SRC = \
$(GRECS_PARSER_GIT)\
$(GRECS_PARSER_META1)
-noinst_HEADERS =
+noinst_HEADERS = grecs-locus.h
EXTRA_DIST=\
grecs-gram.h\
diff --git a/src/bind-gram.y b/src/bind-gram.y
index c751ae1..e353a54 100644
--- a/src/bind-gram.y
+++ b/src/bind-gram.y
@@ -19,7 +19,8 @@
# include <config.h>
#endif
#include <grecs.h>
-#include <grecs-gram.h>
+#include <grecs-locus.h>
+#include <bind-gram.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
@@ -30,17 +31,16 @@ int yyerror(char *s);
static struct grecs_node *parse_tree;
extern int yy_flex_debug;
-extern int grecs_bind_new_source(const char *name);
+extern int grecs_bind_new_source(const char *name, grecs_locus_t *loc);
extern void grecs_bind_close_sources(void);
static struct grecs_value *stmtlist_to_value(struct grecs_node *node);
%}
+%error-verbose
+%locations
+
%union {
- struct {
- grecs_locus_t locus;
- char *string;
- } ident;
char *string;
grecs_value_t svalue, *pvalue;
struct grecs_list *list;
@@ -49,8 +49,7 @@ static struct grecs_value *stmtlist_to_value(struct grecs_node *node);
struct { struct grecs_node *head, *tail; } node_list;
}
-%token <ident> BIND_IDENT BIND_CONTROLS
-%token <string> BIND_STRING
+%token <string> BIND_STRING BIND_IDENT BIND_CONTROLS
%type <string> string
%type <svalue> value ctlsub
%type <pvalue> vallist tag
@@ -62,8 +61,7 @@ static struct grecs_value *stmtlist_to_value(struct grecs_node *node);
input : maybe_stmtlist
{
- parse_tree = grecs_node_create(grecs_node_root,
- &grecs_current_locus);
+ parse_tree = grecs_node_create(grecs_node_root, &@1);
parse_tree->v.texttab = grecs_text_table();
grecs_node_bind(parse_tree, $1, 1);
}
@@ -102,38 +100,44 @@ stmt : simple
simple : BIND_IDENT vallist ';'
{
- if (strcmp($1.string, "include") == 0 &&
+ if (strcmp($1, "include") == 0 &&
$2->type == GRECS_TYPE_STRING) {
- grecs_bind_new_source($2->v.string);
+ grecs_bind_new_source($2->v.string, &@1);
$$ = NULL;
} else {
- $$ = grecs_node_create(grecs_node_stmt, &$1.locus);
- $$->ident = $1.string;
+ $$ = grecs_node_create_points(grecs_node_stmt,
+ @1.beg, @2.end);
+ $$->ident = $1;
+ $$->idloc = @1;
$$->v.value = $2;
}
}
| string ';'
{
- $$ = grecs_node_create(grecs_node_stmt,
- &grecs_current_locus);
+ $$ = grecs_node_create(grecs_node_stmt, &@1);
$$->ident = $1;
+ $$->idloc = @1;
$$->v.value = NULL;
}
| '!' string ';'
{
- $$ = grecs_node_create(grecs_node_stmt,
- &grecs_current_locus);
- $$->ident = grecs_strdup("!");
- $$->v.value = grecs_malloc(sizeof($$->v.value[0]));
- $$->v.value->type = GRECS_TYPE_STRING;
- $$->v.value->v.string = $2;
+ $$ = grecs_node_create_points(grecs_node_stmt,
+ @1.beg, @2.end);
+ $$->ident = grecs_strdup("!");
+ $$->idloc = @1;
+ $$->v.value = grecs_malloc(sizeof($$->v.value[0]));
+ $$->v.value->type = GRECS_TYPE_STRING;
+ $$->v.value->locus = @2;
+ $$->v.value->v.string = $2;
}
;
block : BIND_IDENT tag '{' maybe_stmtlist '}' ';'
{
- $$ = grecs_node_create(grecs_node_block, &$1.locus);
- $$->ident = $1.string;
+ $$ = grecs_node_create_points(grecs_node_block,
+ @1.beg, @5.end);
+ $$->ident = $1;
+ $$->idloc = @1;
$$->v.value = $2;
grecs_node_bind($$, $4, 1);
}
@@ -151,8 +155,10 @@ block : BIND_IDENT tag '{' maybe_stmtlist '}' ';'
(127.0.0.1, 127.0.0.2), keys, (rndc-key))
*/
{
- $$ = grecs_node_create(grecs_node_stmt, &$1.locus);
- $$->ident = $1.string;
+ $$ = grecs_node_create_points(grecs_node_stmt,
+ @1.beg, @4.end);
+ $$->ident = $1;
+ $$->idloc = @1;
$$->v.value = grecs_value_ptr_from_static(&$3);
}
;
@@ -176,6 +182,7 @@ vallist : vlist
$$ = grecs_malloc(sizeof($$[0]));
$$->type = GRECS_TYPE_ARRAY;
+ $$->locus = @1;
$$->v.arg.c = n;
$$->v.arg.v = grecs_calloc(n,
sizeof($$->v.arg.v[0]));
@@ -201,20 +208,19 @@ vlist : value
value : string
{
$$.type = GRECS_TYPE_STRING;
+ $$.locus = @1;
$$.v.string = $1;
}
;
string : BIND_STRING
| BIND_IDENT
- {
- $$ = $1.string;
- }
;
ctlsub : ctllist ';'
{
$$.type = GRECS_TYPE_LIST;
+ $$.locus = @1;
$$.v.list = $1;
}
;
@@ -240,7 +246,7 @@ ctllist : value
int
yyerror(char *s)
{
- grecs_error(&grecs_current_locus, 0, "%s", s);
+ grecs_error(&yylloc, 0, "%s", s);
return 0;
}
@@ -249,7 +255,7 @@ grecs_bind_parser(const char *name, int traceflags)
{
int rc;
- if (grecs_bind_new_source(name))
+ if (grecs_bind_new_source(name, NULL))
return NULL;
yy_flex_debug = traceflags & GRECS_TRACE_LEX;
yydebug = traceflags & GRECS_TRACE_GRAM;
diff --git a/src/bind-lex.l b/src/bind-lex.l
index 10df618..ef1598c 100644
--- a/src/bind-lex.l
+++ b/src/bind-lex.l
@@ -22,6 +22,7 @@
with Grecs. If not, see <http://www.gnu.org/licenses/>. */
#include <grecs.h>
+#include <grecs-locus.h>
#include <bind-gram.h>
#include <unistd.h>
#include <fcntl.h>
@@ -32,6 +33,14 @@
#include <wordsplit.h>
+#define YY_USER_ACTION do { \
+ if (YYSTATE == 0) { \
+ yylloc.beg = grecs_current_locus_point; \
+ yylloc.beg.col++; \
+ } \
+ grecs_current_locus_point.col += yyleng; \
+ yylloc.end = grecs_current_locus_point; \
+ } while (0);
%}
%x COMMENT STR
@@ -45,26 +54,27 @@ P [1-9][0-9]*
"/*" BEGIN(COMMENT);
<COMMENT>[^*\n]* /* eat anything that's not a '*' */
<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
-<COMMENT>\n ++grecs_current_locus.line;
+<COMMENT>\n grecs_locus_point_advance_line(grecs_current_locus_point);
<COMMENT>"*"+"/" BEGIN(INITIAL);
/* Line directive */
^[ \t]*#[ \t]*{P}[ \t]+\".*\".*\n { grecs_parse_line_directive_cpp(yytext,
- &grecs_current_locus,
+ &yylloc,
+ &grecs_current_locus_point,
NULL); }
^[ \t]*#[ \t]*line[ \t].*\n { grecs_parse_line_directive(yytext,
- &grecs_current_locus,
+ &yylloc,
+ &grecs_current_locus_point,
NULL); }
/* End-of-line comments */
-#.*\n { grecs_current_locus.line++; }
+#.*\n { grecs_locus_point_advance_line(grecs_current_locus_point); }
#.* /* end-of-file comment */;
-"//".*\n { grecs_current_locus.line++; }
+"//".*\n { grecs_locus_point_advance_line(grecs_current_locus_point); }
"//".* /* end-of-file comment */;
/* Identifiers */
{ID} { grecs_line_begin();
grecs_line_add(yytext, yyleng);
- yylval.ident.string = grecs_line_finish();
- yylval.ident.locus = grecs_current_locus;
- return strcmp(yylval.ident.string, "controls") == 0 ?
+ yylval.string = grecs_line_finish();
+ return strcmp(yylval.string, "controls") == 0 ?
BIND_CONTROLS : BIND_IDENT;
}
/* Strings */
@@ -97,19 +107,20 @@ P [1-9][0-9]*
return BIND_STRING; }
{WS} ;
/* Other tokens */
-\n { grecs_current_locus.line++; }
+\n { grecs_locus_point_advance_line(grecs_current_locus_point); }
[,;{}()!] return yytext[0];
. { if (isascii(yytext[0]) && isprint(yytext[0]))
- grecs_error(&grecs_current_locus, 0,
+ grecs_error(&yylloc, 0,
_("stray character %c"), yytext[0]);
else
- grecs_error(&grecs_current_locus, 0, _("stray character \\%03o"),
- (unsigned char) yytext[0]); }
+ grecs_error(&yylloc, 0, _("stray character \\%03o"),
+ (unsigned char) yytext[0]); }
%%
struct bind_input_context {
ino_t i_node;
dev_t i_dev;
+ struct grecs_locus_point point;
grecs_locus_t locus; /* Current input location */
YY_BUFFER_STATE state;
FILE *input;
@@ -135,7 +146,7 @@ cmp_context(const void *a, const void *b)
}
static int
-_push_context(const char *name, ino_t i_node, dev_t i_dev)
+_push_context(const char *name, ino_t i_node, dev_t i_dev, grecs_locus_t *loc)
{
struct bind_input_context ctx, *pctx;
@@ -148,7 +159,7 @@ _push_context(const char *name, ino_t i_node, dev_t i_dev)
ctx.i_node = i_node;
pctx = grecs_list_locate(input_stack, &ctx);
if (pctx) {
- grecs_error(&grecs_current_locus, 0,
+ grecs_error(&yylloc, 0,
_("%s has already been included"), name);
grecs_error(&pctx->locus, 0,
_("this is where the previous inclusion occurred"));
@@ -158,7 +169,11 @@ _push_context(const char *name, ino_t i_node, dev_t i_dev)
pctx = grecs_malloc(sizeof(*pctx));
pctx->i_node = i_node;
pctx->i_dev = i_dev;
- pctx->locus = grecs_current_locus;
+ if (loc)
+ pctx->locus = *loc;
+ else
+ memset(&pctx->locus, 0, sizeof(pctx->locus)); /* FIXME */
+ pctx->point = grecs_current_locus_point;
pctx->state = YY_CURRENT_BUFFER;
pctx->input = yyin;
grecs_list_push(input_stack, pctx);
@@ -184,7 +199,7 @@ _pop_context()
}
i_node = pctx->i_node;
i_dev = pctx->i_dev;
- grecs_current_locus = pctx->locus;
+ grecs_current_locus_point = pctx->point;
yyin = pctx->input;
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(pctx->state);
@@ -199,10 +214,8 @@ yywrap()
}
int
-grecs_bind_new_source(const char *name)
+grecs_bind_new_source(const char *name, grecs_locus_t *loc)
{
- grecs_locus_t *loc = grecs_current_locus.file ?
- &grecs_current_locus : NULL;
struct stat st;
FILE *fp;
@@ -245,15 +258,16 @@ grecs_bind_new_source(const char *name)
grecs_free(cmd);
}
- if (_push_context(name, st.st_ino, st.st_dev)) {
+ if (_push_context(name, st.st_ino, st.st_dev, loc)) {
return 1;
}
i_node = st.st_ino;
i_dev = st.st_dev;
yyin = fp;
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
- grecs_current_locus.file = grecs_install_text(name);
- grecs_current_locus.line = 1;
+ grecs_current_locus_point.file = grecs_install_text(name);
+ grecs_current_locus_point.line = 1;
+ grecs_current_locus_point.col = 0;
return 0;
}
diff --git a/src/diag.c b/src/diag.c
index 89b38f4..e8b6940 100644
--- a/src/diag.c
+++ b/src/diag.c
@@ -18,17 +18,22 @@
# include <config.h>
#endif
#include <grecs.h>
+#include <grecs-locus.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
static void
-default_print_diag(grecs_locus_t *locus, int err, int errcode, const char *msg)
+default_print_diag(grecs_locus_t const *locus, int err, int errcode,
+ const char *msg)
{
fflush(stdout);
- if (locus)
- fprintf(stderr, "%s:%d: ", locus->file, locus->line);
+ if (locus) {
+ YY_LOCATION_PRINT(stderr, *locus);
+ fputc(':', stderr);
+ fputc(' ', stderr);
+ }
if (!err)
fprintf(stderr, "warning: ");
fprintf(stderr, "%s", msg);
@@ -37,11 +42,12 @@ default_print_diag(grecs_locus_t *locus, int err, int errcode, const char *msg)
fputc('\n', stderr);
}
-void (*grecs_print_diag_fun)(grecs_locus_t *, int, int, const char *msg) =
+void (*grecs_print_diag_fun)(grecs_locus_t const *, int, int,
+ const char *msg) =
default_print_diag;
void
-grecs_warning(grecs_locus_t *locus, int errcode, const char *fmt, ...)
+grecs_warning(grecs_locus_t const *locus, int errcode, const char *fmt, ...)
{
va_list ap;
char *buf = NULL;
@@ -56,7 +62,7 @@ grecs_warning(grecs_locus_t *locus, int errcode, const char *fmt, ...)
}
void
-grecs_error(grecs_locus_t *locus, int errcode, const char *fmt, ...)
+grecs_error(grecs_locus_t const *locus, int errcode, const char *fmt, ...)
{
va_list ap;
char *buf = NULL;
diff --git a/src/format.c b/src/format.c
index d65f712..f1a876f 100644
--- a/src/format.c
+++ b/src/format.c
@@ -31,7 +31,7 @@ grecs_data_type_string(enum grecs_data_type type)
switch (type) {
case grecs_type_void:
return "void";
-
+
case grecs_type_string:
return "string";
@@ -47,13 +47,13 @@ grecs_data_type_string(enum grecs_data_type type)
case grecs_type_time:
return "time";
-
+
case grecs_type_bool:
return "boolean";
-
+
case grecs_type_ipv4:
return "IPv4";
-
+
case grecs_type_cidr:
return "CIDR";
@@ -125,7 +125,7 @@ grecs_print_simple_statement(struct grecs_keyword *kwp, unsigned level,
FILE *stream)
{
const char *argstr;
-
+
if (kwp->docstring)
grecs_print_docstring(kwp->docstring, level, stream);
format_level(level, stream);
@@ -192,7 +192,33 @@ grecs_format_locus(grecs_locus_t *locus, struct grecs_format_closure *clos)
if (locus) {
char *str = NULL;
size_t size = 0;
- grecs_asprintf(&str, &size, "%s:%d", locus->file, locus->line);
+
+ if (locus->beg.col == 0)
+ grecs_asprintf(&str, &size, "%s:%u",
+ locus->beg.file,
+ locus->beg.line);
+ else if (strcmp(locus->beg.file, locus->end.file))
+ grecs_asprintf(&str, &size, "%s:%u.%u-%s:%u.%u",
+ locus->beg.file,
+ locus->beg.line, locus->beg.col,
+ locus->end.file,
+ locus->end.line, locus->end.col);
+ else if (locus->beg.line != locus->end.line)
+ grecs_asprintf(&str, &size, "%s:%u.%u-%u.%u",
+ locus->beg.file,
+ locus->beg.line, locus->beg.col,
+ locus->end.line, locus->end.col);
+ else if (locus->beg.col != locus->end.col)
+ grecs_asprintf(&str, &size, "%s:%u.%u-%u",
+ locus->beg.file,
+ locus->beg.line, locus->beg.col,
+ locus->end.col);
+ else
+ grecs_asprintf(&str, &size, "%s:%u.%u",
+ locus->beg.file,
+ locus->beg.line,
+ locus->beg.col);
+
clos->fmtfun(str, clos->data);
free(str);
}
@@ -203,7 +229,7 @@ grecs_format_node_path(struct grecs_node *node, int flags,
struct grecs_format_closure *clos)
{
char delim[2] = ".";
-
+
if (node->up)
grecs_format_node_path(node->up, flags, clos);
if (node->type == grecs_node_root)
@@ -277,7 +303,7 @@ grecs_format_node(struct grecs_node *node, int flags,
struct grecs_format_closure *clos)
{
const char *delim_str = NULL;
-
+
if (!(flags & _GRECS_NODE_MASK_OUTPUT)) {
errno = EINVAL;
return 1;
@@ -297,7 +323,18 @@ grecs_format_node(struct grecs_node *node, int flags,
case grecs_node_stmt:
if (flags & GRECS_NODE_FLAG_LOCUS) {
- grecs_format_locus(&node->locus, clos);
+ grecs_locus_t *locus;
+
+ if (flags & GRECS_NODE_FLAG_PATH) {
+ if (flags & GRECS_NODE_FLAG_VALUE)
+ locus = &node->locus;
+ else
+ locus = &node->idloc;
+ } else if (flags & GRECS_NODE_FLAG_VALUE)
+ locus = &node->v.value->locus;
+ else
+ locus = &node->locus;
+ grecs_format_locus(locus, clos);
delim_str = ": ";
}
if (flags & GRECS_NODE_FLAG_PATH) {
@@ -367,7 +404,3 @@ grecs_print_node(struct grecs_node *node, int flags, FILE *fp)
struct grecs_format_closure clos = { file_fmt, fp };
return grecs_format_node(node, flags, &clos);
}
-
-
-
-
diff --git a/src/git-parser.c b/src/git-parser.c
index 4ab64be..e332704 100644
--- a/src/git-parser.c
+++ b/src/git-parser.c
@@ -40,6 +40,8 @@ struct token {
char chbuf[2];
int putback;
struct grecs_list *path;
+ grecs_locus_t loc;
+ unsigned prev_col;
} tok;
#define ISSPACE(c) (strchr(" \t\r\f\n", c) != NULL)
@@ -52,10 +54,13 @@ rawinput()
if (!infile || feof(infile))
return input_char = 0;
input_char = fgetc(infile);
- if (input_char == '\n')
- grecs_current_locus.line++;
- else if (input_char < 0)
+ if (input_char == '\n') {
+ tok.prev_col = grecs_current_locus_point.col;
+ grecs_locus_point_advance_line(grecs_current_locus_point);
+ } else if (input_char < 0)
input_char == 0;
+ else
+ grecs_current_locus_point.col++;
return input_char;
}
@@ -75,8 +80,12 @@ unput()
{
if (!input_char)
return;
- if (input_char == '\n')
- grecs_current_locus.line--;
+ if (input_char == '\n') {
+ grecs_current_locus_point.line--;
+ grecs_current_locus_point.col = tok.prev_col;
+ } else
+ grecs_current_locus_point.col--;
+
ungetc(input_char, infile);
}
@@ -113,7 +122,7 @@ collect_substring()
while (rawinput()) {
if (input_char == '\\') {
if (!input()) {
- grecs_error(&grecs_current_locus, 0,
+ grecs_error(&tok.loc, 0,
"unexpected EOF in string");
break;
}
@@ -133,21 +142,39 @@ collect_substring()
}
}
+#define endpoint(t,adj) do { \
+ (t).loc.end = grecs_current_locus_point; \
+ if (adj) { \
+ if (input_char == '\n') \
+ (t).loc.end.col = (t).prev_col; \
+ else \
+ (t).loc.end.col -= (adj); \
+ } \
+ } while (0)
+
static void
gettoken(void)
{
int putback = tok.putback;
tok.putback = 0;
- if (putback)
+ if (putback) {
+ if (putback == '\n')
+ grecs_locus_point_advance_line(grecs_current_locus_point);
+ else
+ grecs_current_locus_point.col++;
return;
-
+ }
+
tok.buf = NULL;
/* Skip whitespace */
while (input() && ISSPACE(input_char))
;
+ tok.loc.beg = grecs_current_locus_point;
+
if (input_char <= 0) {
tok.type = TOK_EOF;
+ endpoint(tok, 0);
return;
}
@@ -171,7 +198,8 @@ gettoken(void)
}
if (input_char == TOK_EOF) {
- grecs_error(&grecs_current_locus, 0,
+ endpoint(tok, 0);
+ grecs_error(&tok.loc, 0,
"unexpected EOF in section header");
tok.type = TOK_ERR;
return;
@@ -179,7 +207,8 @@ gettoken(void)
if (input_char == ']')
break;
if (input_char == '\n') {
- grecs_error(&grecs_current_locus, 0,
+ endpoint(tok, 1);
+ grecs_error(&tok.loc, 0,
"unexpect newline in in section header");
tok.type = TOK_ERR;
return;
@@ -197,7 +226,8 @@ gettoken(void)
dot_delimited = input_char == '.';
else if (dot_delimited == 1) {
if (input_char != '.' && input_char != ']') {
- grecs_error(&grecs_current_locus, 0,
+ endpoint(tok, 1);
+ grecs_error(&tok.loc, 0,
"unexpected character in section header");
tok.type = TOK_ERR;
return;
@@ -207,10 +237,10 @@ gettoken(void)
p = grecs_txtacc_finish(acc, 0);
grecs_list_append(tok.path, p);
}
-
+
+ endpoint(tok, 1);
if (grecs_list_size(tok.path) == 0) {
- grecs_error(&grecs_current_locus, 0,
- "empty section header");
+ grecs_error(&tok.loc, 0, "empty section header");
tok.type = TOK_ERR;
return;
}
@@ -227,6 +257,7 @@ gettoken(void)
unput();
grecs_txtacc_grow_char(acc, 0);
tok.buf = grecs_txtacc_finish(acc, 0);
+ endpoint(tok, 0);
return;
}
@@ -234,6 +265,7 @@ gettoken(void)
tok.chbuf[1] = 0;
tok.buf = tok.chbuf;
tok.type = input_char;
+ endpoint(tok, 0);
}
static void
@@ -270,10 +302,18 @@ getvalue()
{
int len;
struct grecs_value *val = grecs_malloc(sizeof(*val));
+
while (input() && ISSPACE(input_char) && input_char != '\n')
;
+
+ val->locus.beg = grecs_current_locus_point;
+
if (input_char != '\n')
collect_value();
+ val->locus.end = grecs_current_locus_point;
+ val->locus.end.line--;
+ val->locus.end.col = tok.prev_col;
+
grecs_txtacc_grow_char(acc, 0);
tok.type = TOK_VALUE;
tok.buf = grecs_txtacc_finish(acc, 1);
@@ -296,28 +336,30 @@ read_statement(struct grecs_node *parent)
return 0;
}
if (tok.type != TOK_KEYWORD) {
- grecs_error(&grecs_current_locus, 0, "syntax error");
+ grecs_error(&tok.loc, 0, "syntax error");
error_recovery();
return 1;
}
- node = grecs_node_create(grecs_node_stmt, &grecs_current_locus);
+ node = grecs_node_create(grecs_node_stmt, &tok.loc);
node->ident = grecs_strdup(tok.buf);
-
+ node->idloc = tok.loc;
+
gettoken();
if (tok.type == TOK_EOF) {
- grecs_error(&grecs_current_locus, 0, "unexpected EOF");
+ grecs_error(&tok.loc, 0, "unexpected EOF");
grecs_node_free(node);
return 0;
}
if (tok.type != TOK_EQ) {
- grecs_error(&grecs_current_locus, 0,
+ grecs_error(&tok.loc, 0,
"expected `=', but found `%s'", tok.buf);
error_recovery();
grecs_node_free(node);
return 1;
}
node->v.value = getvalue();
+ node->locus.end = node->v.value->locus.end;
grecs_node_bind(parent, node, 1);
return 1;
}
@@ -339,8 +381,7 @@ create_subsection_node(struct grecs_node *root)
char *ident = ep->data;
p = grecs_find_node(root, ident);
if (!p) {
- p = grecs_node_create(grecs_node_block,
- &grecs_current_locus);
+ p = grecs_node_create(grecs_node_block, &tok.loc);
p->ident = grecs_strdup(ident);
grecs_node_bind(root, p, 1);
}
@@ -361,7 +402,7 @@ read_section(struct grecs_node *parent)
} else if (tok.type == TOK_KEYWORD) {
read_statement(parent);
} else {
- grecs_error(&grecs_current_locus, 0, "syntax error");
+ grecs_error(&tok.loc, 0, "syntax error");
error_recovery();
}
return 1;
@@ -378,15 +419,17 @@ grecs_git_parser(const char *name, int traceflags)
grecs_error(NULL, errno, _("cannot open `%s'"), name);
return NULL;
}
- grecs_current_locus.file = grecs_install_text(name);
- grecs_current_locus.line = 1;
+ grecs_current_locus_point.file = grecs_install_text(name);
+ grecs_current_locus_point.line = 1;
+ grecs_current_locus_point.col = 0;
acc = grecs_txtacc_create();
tok.path = grecs_list_create();
- root = grecs_node_create(grecs_node_root, &grecs_current_locus);
+ root = grecs_node_create(grecs_node_root, &tok.loc);
while (read_section(root))
;
+ root->locus.end = grecs_current_locus_point;
fclose(infile);
grecs_txtacc_free(acc);
grecs_list_free(tok.path);
diff --git a/src/grecs-gram.y b/src/grecs-gram.y
index bbe3d5e..92de6b2 100644
--- a/src/grecs-gram.y
+++ b/src/grecs-gram.y
@@ -19,6 +19,7 @@
# include <config.h>
#endif
#include <grecs.h>
+#include <grecs-locus.h>
#include <grecs-gram.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -31,11 +32,10 @@ int yyerror(char *s);
static struct grecs_node *parse_tree;
%}
+%error-verbose
+%locations
+
%union {
- struct {
- grecs_locus_t locus;
- char *string;
- } ident;
char *string;
grecs_value_t svalue, *pvalue;
struct grecs_list *list;
@@ -44,8 +44,7 @@ static struct grecs_node *parse_tree;
struct { struct grecs_node *head, *tail; } node_list;
}
-%token <ident> IDENT
-%token <string> STRING QSTRING MSTRING
+%token <string> STRING QSTRING MSTRING IDENT
%type <string> string slist
%type <list> slist0
%type <svalue> value
@@ -58,8 +57,7 @@ static struct grecs_node *parse_tree;
input : maybe_stmtlist
{
- parse_tree = grecs_node_create(grecs_node_root,
- &grecs_current_locus);
+ parse_tree = grecs_node_create(grecs_node_root, &@1);
parse_tree->v.texttab = grecs_text_table();
grecs_node_bind(parse_tree, $1, 1);
}
@@ -92,25 +90,27 @@ stmt : simple
simple : IDENT vallist ';'
{
- $$ = grecs_node_create(grecs_node_stmt,
- &$1.locus);
- $$->ident = $1.string;
+ $$ = grecs_node_create_points(grecs_node_stmt,
+ @1.beg, @2.end);
+ $$->ident = $1;
+ $$->idloc = @1;
$$->v.value = $2;
}
| IDENT ';'
{
- $$ = grecs_node_create(grecs_node_stmt,
- &$1.locus);
- $$->ident = $1.string;
+ $$ = grecs_node_create(grecs_node_stmt, &@1);
+ $$->ident = $1;
+ $$->idloc = @1;
$$->v.value = NULL;
}
;
block : IDENT tag '{' stmtlist '}' opt_sc
{
- $$ = grecs_node_create(grecs_node_block,
- &$1.locus);
- $$->ident = $1.string;
+ $$ = grecs_node_create_points(grecs_node_block,
+ @1.beg, @5.end);
+ $$->ident = $1;
+ $$->idloc = @1;
$$->v.value = $2;
grecs_node_bind($$, $4.head, 1);
}
@@ -135,6 +135,7 @@ vallist : vlist
$$ = grecs_malloc(sizeof($$[0]));
$$->type = GRECS_TYPE_ARRAY;
+ $$->locus = @1;
$$->v.arg.c = n;
$$->v.arg.v = grecs_calloc(n,
sizeof($$->v.arg.v[0]));
@@ -160,25 +161,25 @@ vlist : value
value : string
{
$$.type = GRECS_TYPE_STRING;
+ $$.locus = @1;
$$.v.string = $1;
}
| list
{
$$.type = GRECS_TYPE_LIST;
+ $$.locus = @1;
$$.v.list = $1;
}
| MSTRING
{
$$.type = GRECS_TYPE_STRING;
+ $$.locus = @1;
$$.v.string = $1;
}
;
string : STRING
| IDENT
- {
- $$ = $1.string;
- }
| slist
;