summaryrefslogtreecommitdiff
path: root/tikzit/src/common/TikzGraphAssembler.m
diff options
context:
space:
mode:
Diffstat (limited to 'tikzit/src/common/TikzGraphAssembler.m')
-rw-r--r--tikzit/src/common/TikzGraphAssembler.m243
1 files changed, 133 insertions, 110 deletions
diff --git a/tikzit/src/common/TikzGraphAssembler.m b/tikzit/src/common/TikzGraphAssembler.m
index 26bf515..5a01036 100644
--- a/tikzit/src/common/TikzGraphAssembler.m
+++ b/tikzit/src/common/TikzGraphAssembler.m
@@ -22,84 +22,72 @@
//
#import "TikzGraphAssembler.h"
+#import "TikzGraphAssembler+Parser.h"
+#import "tikzparser.h"
+#import "tikzlexer.h"
#import "NSError+Tikzit.h"
-extern int yyparse(void);
-extern int yylex(void);
-extern int yy_scan_string(const char* yy_str);
-extern void yy_delete_buffer(int b);
-extern int yylex_destroy(void);
-
-
-static NSLock *parseLock = nil;
-static id currentAssembler = nil;
-
-extern int yylineno;
-extern int yyleng;
-int lineno;
-int tokenpos;
-extern char *yystr;
-char linebuff[500];
-
-
-void yyerror(const char *str) {
- // if the error is on the first line, treat specially
- if(lineno == 1){
-// strcpy(linebuff, yytext+1);
- NSLog(@"Problem ahoy!");
- }
-
- 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
- userInfo:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSString stringWithCString:str encoding:NSUTF8StringEncoding],
- [NSNumber numberWithInt:lineno],
- [NSString stringWithCString:linebuff encoding:NSUTF8StringEncoding],
- [NSNumber numberWithInt:tokenpos],
- [NSNumber numberWithInt:yyleng],
- nil]
- forKeys: [NSArray arrayWithObjects:NSLocalizedDescriptionKey,
- @"lineNumber",
- @"syntaxString",
- @"tokenStart",
- @"tokenLength",
- nil]]];
-
- [currentAssembler invalidateWithError:error];
- }
-}
-
-int yywrap() {
- return 1;
+void yyerror(TikzGraphAssembler *assembler, const char *str) {
+ [assembler invalidateWithError:str];
}
@implementation TikzGraphAssembler
- (id)init {
+ self = nil;
+ return nil;
+}
+
+- (id)initWithGraph:(Graph*)g {
self = [super init];
+ if (self) {
+ graph = [g retain];
+ nodeMap = [[NSMutableDictionary alloc] init];
+ yylex_init (&scanner);
+ yyset_extra(self, scanner);
+ }
return self;
}
- (void)dealloc {
[graph release];
+ [nodeMap release];
[lastError release];
+ yylex_destroy (scanner);
[super dealloc];
}
-- (Graph*)graph { return graph; }
-- (NSError*)lastError { return lastError; }
-
-- (BOOL)parseTikz:(NSString *)tikz {
- return [self parseTikz:tikz forGraph:[Graph graph]];
++ (BOOL) parseTikz:(NSString*)tikz forGraph:(Graph*)gr {
+ return [self parseTikz:tikz forGraph:gr error:NULL];
+}
++ (Graph*) parseTikz:(NSString*)tikz error:(NSError**)e {
+ Graph *gr = [[Graph alloc] init];
+ if ([self parseTikz:tikz forGraph:gr error:e]) {
+ return [gr autorelease];
+ } else {
+ [gr release];
+ return nil;
+ }
+}
++ (Graph*) parseTikz:(NSString*)tikz {
+ return [self parseTikz:tikz error:NULL];
}
-- (BOOL)parseTikz:(NSString*)tikz forGraph:(Graph*)gr {
- [parseLock lock];
-
- lineno = 1;
- tokenpos = 0;
- NSRange range = [tikz rangeOfString:@"\n"];
++ (BOOL) parseTikz:(NSString*)tikz forGraph:(Graph*)gr error:(NSError**)error {
+
+ if([tikz length] == 0) {
+ // empty string -> empty graph
+ return YES;
+ }
+
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ TikzGraphAssembler *assembler = [[self alloc] initWithGraph:gr];
+ [assembler autorelease];
+
+ /*
+ lineno = 1;
+ tokenpos = 0;
+ NSRange range = [tikz rangeOfString:@"\n"];
NSString *firstLine;
if (range.length == 0) {
firstLine = tikz;
@@ -112,49 +100,50 @@ int yywrap() {
// first line too long; just terminate it at the end of the buffer
linebuff[499] = 0;
}
+ */
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- currentAssembler = self;
-
- // set the current graph
- if (graph != gr) {
- [graph release];
- graph = [gr retain];
- }
-
- // the node map keeps track of the mapping of names to nodes
- nodeMap = [[NSMutableDictionary alloc] init];
-
- // do the parsing if actual input
- if([tikz length] > 0){
- yy_scan_string([tikz UTF8String]);
- yyparse();
- yylex_destroy();
- }
-
- [nodeMap release];
- nodeMap = nil;
+ yy_scan_string([tikz UTF8String], [assembler scanner]);
+ int result = yyparse(assembler);
- currentAssembler = nil;
[pool drain];
-
- [parseLock unlock];
-
- return (graph != nil);
+ if (result == 0) {
+ return YES;
+ } else {
+ if (error) {
+ /*
+ if (lastError) {
+ *error = [[lastError retain] autorelease];
+ } else
+ */
+ if (result == 1) {
+ *error = [NSError errorWithMessage:@"Syntax error"
+ code:TZ_ERR_PARSE];
+ } else if (result == 2) {
+ *error = [NSError errorWithMessage:@"Insufficient memory"
+ code:TZ_ERR_PARSE];
+ } else {
+ *error = [NSError errorWithMessage:@"Unknown error"
+ code:TZ_ERR_PARSE];
+ }
+ }
+ return NO;
+ }
}
-- (BOOL)testTikz:(NSString *)tikz{
++ (BOOL)validateTikzPropertyNameOrValue:(NSString*)tikz {
BOOL r;
NSString * testTikz = [NSString stringWithFormat: @"{%@}", tikz];
- yy_scan_string([testTikz UTF8String]);
- yylex();
-
- r = !(yyleng < [testTikz length]);
-
+ void *scanner;
+ yylex_init (&scanner);
+ yyset_extra(nil, scanner);
+ yy_scan_string([testTikz UTF8String], scanner);
+ YYSTYPE lval;
+ yylex(&lval, scanner);
+ r = !(yyget_leng(scanner) < [testTikz length]);
+ yylex_destroy(scanner);
[testTikz autorelease];
- yylex_destroy();
return r;
}
@@ -165,32 +154,66 @@ int yywrap() {
lastError = nil;
}
-- (void)invalidateWithError:(NSError*)error {
- [self invalidate];
- lastError = [error retain];
-}
-
-+ (void)setup {
- parseLock = [[NSLock alloc] init];
-}
-
-+ (TikzGraphAssembler*)currentAssembler {
- return currentAssembler;
-}
-
-+ (TikzGraphAssembler*)assembler {
- return [[[TikzGraphAssembler alloc] init] autorelease];
-}
-
@end
@implementation TikzGraphAssembler (Parser)
+- (Graph*)graph { return graph; }
- (void)addNodeToMap:(Node*)n {
[nodeMap setObject:n forKey:[n name]];
}
- (Node*)nodeWithName:(NSString*)name {
- return [nodeMap objectForKey:name];
+ return [nodeMap objectForKey:name];
+}
+- (void) newLineStarted:(char *)text {
+ /*
+ strncpy(linebuff, yytext+1, 500);
+ linebuff[499] = 0; // ensure null-terminated
+ lineno++;
+ tokenpos = 0;
+ */
+}
+- (void) incrementPosBy:(size_t)amount {
+ //tokenpos += amount;
+}
+
+- (void) invalidateWithError:(const char *)message {
+ /*
+ // if the error is on the first line, treat specially
+ if([assembler lineNumber] == 1){
+ //strcpy(linebuff, yytext+1);
+ NSLog(@"Problem ahoy!");
+ }
+
+ NSString *pointerStrPad = [@"" stringByPaddingToLength:(tokenpos-yyleng)
+ withString:@" "
+ startingAtIndex:0];
+ NSString *pointerStr = [@"" stringByPaddingToLength:yyleng
+ withString:@"^"
+ startingAtIndex:0];
+ NSLog(@"Parse error on line %i: %s\n%s\n%@\n", lineno, str, linebuff,
+ [pointerStrPad stringByAppendingString:pointerStr]);
+ NSDictionary *userInfo =
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithUTF8String:str],
+ NSLocalizedDescriptionKey,
+ [NSNumber numberWithInt:lineno],
+ @"lineNumber",
+ [NSString stringWithUTF8String:linebuff],
+ @"syntaxString",
+ [NSNumber numberWithInt:tokenpos],
+ @"tokenStart",
+ [NSNumber numberWithInt:yyleng],
+ @"tokenLength"];
+ NSError *error =
+ [NSError errorWithDomain:@"net.sourceforge.tikzit"
+ code:TZ_ERR_PARSE
+ userInfo:userInfo];
+
+ lastError = [error retain];
+ */
+ [self invalidate];
}
+- (void*) scanner { return scanner; }
@end
// vi:ft=objc:ts=4:noet:sts=4:sw=4