From d35a186932e95b979bb947110a2e7d2cca41fcc9 Mon Sep 17 00:00:00 2001 From: Johan Paulsson Date: Sun, 27 Jan 2013 16:54:57 +0000 Subject: Better parser errors on syntax errors. Will show line number, description and where the error happened. Test function for delimited string if they will break reprising. --- tikzit/src/common/TikzGraphAssembler.h | 2 ++ tikzit/src/common/TikzGraphAssembler.m | 44 +++++++++++++++++++++---- tikzit/src/common/tikzlexer.lm | 60 ++++++++++++++++++++++------------ tikzit/src/common/tikzparser.ym | 3 ++ 4 files changed, 81 insertions(+), 28 deletions(-) (limited to 'tikzit/src/common') diff --git a/tikzit/src/common/TikzGraphAssembler.h b/tikzit/src/common/TikzGraphAssembler.h index adaf443..a0c8a0d 100644 --- a/tikzit/src/common/TikzGraphAssembler.h +++ b/tikzit/src/common/TikzGraphAssembler.h @@ -41,6 +41,8 @@ - (BOOL)parseTikz:(NSString*)tikz; - (BOOL)parseTikz:(NSString*)tikz forGraph:(Graph*)gr; +- (BOOL)testTikz:(NSString*)tikz; + - (void)prepareNode; - (void)finishNode; diff --git a/tikzit/src/common/TikzGraphAssembler.m b/tikzit/src/common/TikzGraphAssembler.m index 7d8d0e7..050b5fe 100644 --- a/tikzit/src/common/TikzGraphAssembler.m +++ b/tikzit/src/common/TikzGraphAssembler.m @@ -34,8 +34,16 @@ extern int yylex_destroy(void); static NSLock *parseLock = nil; static id currentAssembler = nil; +int yylineno; +int yyleng; +int lineno; +int tokenpos; +char *yystr; +char linebuff[500]; + + void yyerror(const char *str) { - NSLog(@"Parse error: %s", str); + NSLog(@"Parse error on line %i: %s\n%s\n%@\n", lineno, str, linebuff, [[@"" stringByPaddingToLength:(tokenpos-yyleng) withString: @" " startingAtIndex:0] stringByAppendingString:[@"" stringByPaddingToLength:yyleng withString: @"^" startingAtIndex:0]]); if (currentAssembler != nil) { NSError *error = [NSError errorWithDomain:@"net.sourceforge.tikzit" code:TZ_ERR_PARSE @@ -81,6 +89,10 @@ int yywrap() { - (BOOL)parseTikz:(NSString*)tikz forGraph:(Graph*)gr { [parseLock lock]; + + lineno = 1; + tokenpos = 0; + linebuff[0] = 0; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; currentAssembler = self; @@ -93,12 +105,14 @@ int yywrap() { // the node map keeps track of the mapping of names to nodes nodeMap = [[NSMutableDictionary alloc] init]; - - // do the parsing - yy_scan_string([tikz UTF8String]); - yyparse(); - yylex_destroy(); - + + // do the parsing if actual input + if([tikz length] > 0){ + yy_scan_string([tikz UTF8String]); + yyparse(); + yylex_destroy(); + } + [nodeMap release]; nodeMap = nil; @@ -110,6 +124,22 @@ int yywrap() { return (graph != nil); } +- (BOOL)testTikz:(NSString *)tikz{ + BOOL r; + + NSString * testTikz = [NSString stringWithFormat: @"{%@}", tikz]; + + yy_scan_string([testTikz UTF8String]); + yylex(); + + r = !(yyleng < [testTikz length]); + + [testTikz autorelease]; + yylex_destroy(); + + return r; +} + - (void)prepareNode { currentNode = [[Node alloc] init]; } diff --git a/tikzit/src/common/tikzlexer.lm b/tikzit/src/common/tikzlexer.lm index 9af0c8d..8f34ace 100644 --- a/tikzit/src/common/tikzlexer.lm +++ b/tikzit/src/common/tikzlexer.lm @@ -1,4 +1,6 @@ %option nounput +%option yylineno + %{ // // tikzparser.l @@ -30,48 +32,62 @@ #include "tikzparser.h" #endif +extern char linebuff[500]; +extern int lineno; +extern yy_size_t yyleng; +extern int tokenpos; %} %% -\n /* ignore end of line */; -[ \t]+ /* ignore whitespace */; -\\begin return LATEXBEGIN; -\\end return LATEXEND; -\{tikzpicture\} return TIKZPICTURE; -\{pgfonlayer\} return PGFONLAYER; -\( return LEFTPARENTHESIS; -\) return RIGHTPARENTHESIS; -\[ return LEFTBRACKET; -\] return RIGHTBRACKET; -; return SEMICOLON; -, return COMMA; -\. return FULLSTOP; -= return EQUALS; -\\draw return DRAW; -to return TO; -\\node return NODE; -\\path return PATH; -node return ALTNODE; -rectangle return RECTANGLE; -at return AT; +%\n /* ignore end of line */; +\n.* { strcpy(linebuff, yytext+1); + lineno++; + tokenpos = 0; + yyless(1); + } +[ ]+ { tokenpos += yyleng; } /* ignore whitespace */; +[\t]+ { tokenpos += 4*yyleng; } /* ignore whitespace */; +\\begin { tokenpos += yyleng; return LATEXBEGIN; } +\\end { tokenpos += yyleng; return LATEXEND; } +\{tikzpicture\} { tokenpos += yyleng; return TIKZPICTURE; } +\{pgfonlayer\} { tokenpos += yyleng; return PGFONLAYER; } +\( { tokenpos += yyleng; return LEFTPARENTHESIS; } +\) { tokenpos += yyleng; return RIGHTPARENTHESIS; } +\[ { tokenpos += yyleng; return LEFTBRACKET; } +\] { tokenpos += yyleng; return RIGHTBRACKET; } +; { tokenpos += yyleng; return SEMICOLON; } +, { tokenpos += yyleng; return COMMA; } +\. { tokenpos += yyleng; return FULLSTOP; } += { tokenpos += yyleng; return EQUALS; } +\\draw { tokenpos += yyleng; return DRAW; } +to { tokenpos += yyleng; return TO; } +\\node { tokenpos += yyleng; return NODE; } +\\path { tokenpos += yyleng; return PATH; } +node { tokenpos += yyleng; return ALTNODE; } +rectangle { tokenpos += yyleng; return RECTANGLE; } +at { tokenpos += yyleng; return AT; } [0-9]+ { + tokenpos += yyleng; yylval.nsstr=[NSString stringWithUTF8String:yytext]; return NATURALNUMBER; } (\-?[0-9]*\.[0-9]+)|(\-?[0-9]+) { + tokenpos += yyleng; yylval.nsstr=[NSString stringWithUTF8String:yytext]; return REALNUMBER; } \\?[a-zA-Z<>\-\'][a-zA-Z<>\-\'0-9]* { //' + tokenpos += yyleng; yylval.nsstr=[NSString stringWithUTF8String:yytext]; return LWORD; } \"[^\"]*\" /* " */ { + tokenpos += yyleng; yylval.nsstr=[NSString stringWithUTF8String:yytext]; return QUOTEDSTRING; } @@ -93,8 +109,10 @@ at return AT; } NSString *s = [buf copy]; + yyleng += 1 + [buf length]; [s autorelease]; yylval.nsstr = s; + tokenpos += yyleng; return DELIMITEDSTRING; } diff --git a/tikzit/src/common/tikzparser.ym b/tikzit/src/common/tikzparser.ym index 532b6c8..487cfd4 100644 --- a/tikzit/src/common/tikzparser.ym +++ b/tikzit/src/common/tikzparser.ym @@ -29,6 +29,9 @@ #import "TikzGraphAssembler.h" #import "GraphElementProperty.h" +extern char* yystr; +extern int yylineno; +extern int tokenpos; extern int yylex(void); extern void yyerror(const char *str); -- cgit v1.2.3