From b31704494636c71894ec8850c570056d0b8b9bac Mon Sep 17 00:00:00 2001 From: Alex Merry Date: Sat, 23 Mar 2013 23:24:06 +0000 Subject: Fixes to the parser error-reporting code --- tikzit/src/common/TikzGraphAssembler.m | 81 +++++++++++++++++++++++----------- tikzit/src/common/tikzlexer.lm | 7 ++- tikzit/src/common/tikzparser.ym | 4 ++ 3 files changed, 63 insertions(+), 29 deletions(-) (limited to 'tikzit') diff --git a/tikzit/src/common/TikzGraphAssembler.m b/tikzit/src/common/TikzGraphAssembler.m index a6f0e3d..75fca1c 100644 --- a/tikzit/src/common/TikzGraphAssembler.m +++ b/tikzit/src/common/TikzGraphAssembler.m @@ -162,28 +162,39 @@ // points to just after end of last line ++last_line_end; } - const char *error_start = first_line_start + (yylloc->first_column - 1); - const char *error_end = last_line_start + (yylloc->last_column - 1); - if (error_start > error_end || error_end > last_line_end) { + size_t context_len = last_line_end - first_line_start; + size_t token_offset = yylloc->first_column - 1; + size_t token_len = ((last_line_start - first_line_start) + yylloc->last_column) - token_offset; + + // damn you, tabs! + // we need to convert "column offsets" into "character/byte offsets" + for (int i = 0; i < MIN(token_offset + token_len,context_len); ++i) { + if (*(first_line_start + i) == '\t') { + if (i < token_offset) + token_offset -= 7; + else + token_len -= 7; + } + } + + if (token_offset + token_len > context_len) { // error position state is corrupted - NSLog(@"Got bad error state for error \"%s\": start(%i,%i), end(%i,%i)", + NSLog(@"Got bad error state for error \"%s\": start(%i,%i), end(%i,%i)\n context_len = %d; token_offset = %d; token_len = %d", message, yylloc->first_line, yylloc->first_column, yylloc->last_line, - yylloc->last_column); + yylloc->last_column, + context_len, + token_offset, + token_len); [self setLastError:[NSError errorWithMessage:nsmsg code:TZ_ERR_PARSE]]; } else { - // +1 for null terminator - size_t error_text_len = last_line_end - first_line_start; - char *error_text = malloc (error_text_len + 1); - strncpy (error_text, first_line_start, error_text_len); - *(error_text + error_text_len) = '\0'; - - int error_start_pos = error_start - first_line_start; - int error_end_pos = error_end - first_line_start; + char *context = malloc (context_len + 1); + strncpy (context, first_line_start, context_len); + *(context + context_len) = '\0'; NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: @@ -197,11 +208,11 @@ @"endLine", [NSNumber numberWithInt:yylloc->last_column], @"endColumn", - [NSString stringWithUTF8String:error_text], + [NSString stringWithUTF8String:context], @"syntaxString", - [NSNumber numberWithInt:error_start_pos], + [NSNumber numberWithInt:token_offset], @"tokenStart", - [NSNumber numberWithInt:error_end_pos], + [NSNumber numberWithInt:token_len], @"tokenLength", nil]; [self setLastError: @@ -209,33 +220,53 @@ code:TZ_ERR_PARSE userInfo:userInfo]]; - // we can now freely edit error_text + // we can now freely edit context string // we only bother printing out the first line if (yylloc->last_line > yylloc->first_line) { - char *nlp = strchr(error_text, '\n'); + char *nlp = strchr(context, '\n'); if (nlp) { *nlp = '\0'; - error_text_len = nlp - error_text; - if (error_end_pos > error_text_len) - error_end_pos = error_text_len; + context_len = nlp - context; + if (token_offset >= context_len) { + NSLog(@"token_offset (%d) >= context_len (%d) -- what?", token_offset, context_len); + return; + } else if (token_offset + token_len > context_len) { + token_len = context_len - token_offset; + } + } else { + NSLog(@"Didn't find any newlines in context string!"); } } + size_t token_col_offset = 0; + size_t token_col_len = 0; + for (int i = 0; i < token_offset; ++i) { + if (*(context + i) == '\t') + token_col_offset += 8; + else + ++token_col_offset; + } + for (int i = token_offset; i < token_offset + token_len; ++i) { + if (*(context + i) == '\t') + token_col_len += 8; + else + ++token_col_len; + } NSString *pointerLinePadding = - [@"" stringByPaddingToLength:error_start_pos + [@"" stringByPaddingToLength:token_col_offset withString:@" " startingAtIndex:0]; NSString *pointerLineCarets = - [@"" stringByPaddingToLength:(error_end_pos - error_start_pos) + [@"" stringByPaddingToLength:token_col_len withString:@"^" startingAtIndex:0]; NSLog(@"Parse error on line %i, starting at %i: %s\n%s\n%@%@", yylloc->first_line, yylloc->first_column, message, - error_text, + context, pointerLinePadding, pointerLineCarets); - free (error_text); + free (context); } } - (void*) scanner { return scanner; } diff --git a/tikzit/src/common/tikzlexer.lm b/tikzit/src/common/tikzlexer.lm index 0785c17..4e675ad 100644 --- a/tikzit/src/common/tikzlexer.lm +++ b/tikzit/src/common/tikzlexer.lm @@ -24,9 +24,8 @@ #define YY_USER_ACTION \ yylloc->first_line = yylloc->last_line; \ - if (yylloc->last_line != 1 || yylloc->last_column != 1) \ - yylloc->first_column = yylloc->last_column + 1; \ - yylloc->last_column = yylloc->first_column + yyleng; + yylloc->first_column = yylloc->last_column + 1; \ + yylloc->last_column = yylloc->first_column + yyleng - 1; %} @@ -54,7 +53,7 @@ FLOAT \-?[0-9]*(\.[0-9]+)? [\t]+ { // tab = 8 columns // note that we have already adjusted by yyleng at this point - yylloc->last_column = yylloc->first_column + 7*yyleng; + yylloc->last_column += 7*yyleng; } \\begin\{tikzpicture\} { return BEGIN_TIKZPICTURE_CMD; } \\end\{tikzpicture\} { return END_TIKZPICTURE_CMD; } diff --git a/tikzit/src/common/tikzparser.ym b/tikzit/src/common/tikzparser.ym index 85a0fe0..d0ced92 100644 --- a/tikzit/src/common/tikzparser.ym +++ b/tikzit/src/common/tikzparser.ym @@ -62,6 +62,10 @@ void yyerror(YYLTYPE *yylloc, TikzGraphAssembler *assembler, const char *str) { } %} +%initial-action { + yylloc.first_column = yylloc.last_column = 0; +}; + %token BEGIN_TIKZPICTURE_CMD "\\begin{tikzpicture}" %token END_TIKZPICTURE_CMD "\\end{tikzpicture}" -- cgit v1.2.3