summaryrefslogtreecommitdiff
path: root/tikzit/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'tikzit/src/common')
-rw-r--r--tikzit/src/common/TikzGraphAssembler+Parser.h14
-rw-r--r--tikzit/src/common/TikzGraphAssembler.h23
-rw-r--r--tikzit/src/common/TikzGraphAssembler.m243
-rw-r--r--tikzit/src/common/TikzShape.m6
-rw-r--r--tikzit/src/common/tikzlexer.lm114
-rw-r--r--tikzit/src/common/tikzparser.ym30
6 files changed, 226 insertions, 204 deletions
diff --git a/tikzit/src/common/TikzGraphAssembler+Parser.h b/tikzit/src/common/TikzGraphAssembler+Parser.h
index 683e3e2..efceae9 100644
--- a/tikzit/src/common/TikzGraphAssembler+Parser.h
+++ b/tikzit/src/common/TikzGraphAssembler+Parser.h
@@ -25,9 +25,19 @@
#import "TikzGraphAssembler.h"
@interface TikzGraphAssembler (Parser)
+- (Graph*) graph;
/** Store a node so that it can be looked up by name later */
-- (void)addNodeToMap:(Node*)n;
-- (Node*)nodeWithName:(NSString*)name;
+- (void) addNodeToMap:(Node*)n;
+/** Get a previously-stored node by name */
+- (Node*) nodeWithName:(NSString*)name;
+- (void) newLineStarted:(char *)text;
+- (void) incrementPosBy:(size_t)amount;
+- (void) invalidateWithError:(const char *)message;
+- (void*) scanner;
@end
+#define YY_EXTRA_TYPE TikzGraphAssembler *
+#define YYLEX_PARAM [assembler scanner]
+void yyerror(TikzGraphAssembler *assembler, const char *str);
+
// vi:ft=objc:noet:ts=4:sts=4:sw=4
diff --git a/tikzit/src/common/TikzGraphAssembler.h b/tikzit/src/common/TikzGraphAssembler.h
index 3fc4e9e..16fdf7f 100644
--- a/tikzit/src/common/TikzGraphAssembler.h
+++ b/tikzit/src/common/TikzGraphAssembler.h
@@ -26,24 +26,19 @@
@interface TikzGraphAssembler : NSObject {
Graph *graph;
+ void *scanner;
NSMutableDictionary *nodeMap;
NSError *lastError;
+ char linebuff[500];
+ int lineno;
+ size_t tokenpos;
}
-@property (readonly) Graph *graph;
-@property (readonly) NSError *lastError;
-
-- (BOOL)parseTikz:(NSString*)tikz;
-- (BOOL)parseTikz:(NSString*)tikz forGraph:(Graph*)gr;
-
-- (BOOL)testTikz:(NSString*)tikz;
-
-- (void)invalidate;
-- (void)invalidateWithError:(NSError*)error;
-
-+ (void)setup;
-+ (TikzGraphAssembler*)currentAssembler;
-+ (TikzGraphAssembler*)assembler;
++ (BOOL) parseTikz:(NSString*)tikz forGraph:(Graph*)gr error:(NSError**)e;
++ (BOOL) parseTikz:(NSString*)tikz forGraph:(Graph*)gr;
++ (Graph*) parseTikz:(NSString*)tikz error:(NSError**)e;
++ (Graph*) parseTikz:(NSString*)tikz;
++ (BOOL)validateTikzPropertyNameOrValue:(NSString*)tikz;
@end
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
diff --git a/tikzit/src/common/TikzShape.m b/tikzit/src/common/TikzShape.m
index b5b23c3..722275c 100644
--- a/tikzit/src/common/TikzShape.m
+++ b/tikzit/src/common/TikzShape.m
@@ -35,11 +35,7 @@
error:NULL];
if (tikz == nil) return nil;
- TikzGraphAssembler *ass = [[TikzGraphAssembler alloc] init];
- [ass parseTikz:tikz];
-
- Graph *graph = [ass graph];
- [ass release];
+ Graph *graph = [TikzGraphAssembler parseTikz:tikz];
if (graph == nil) return nil;
NSRect graphBounds = ([graph hasBoundingBox]) ? [graph boundingBox] : [graph bounds];
diff --git a/tikzit/src/common/tikzlexer.lm b/tikzit/src/common/tikzlexer.lm
index ad99445..3e2e0ed 100644
--- a/tikzit/src/common/tikzlexer.lm
+++ b/tikzit/src/common/tikzlexer.lm
@@ -1,11 +1,3 @@
-%option nounput
-%option yylineno
-%s props
-%s xcoord
-%s ycoord
-%s noderef
-FLOAT \-?[0-9]*(\.[0-9]+)?
-
%{
/*
* Copyright 2010 Chris Heunen
@@ -28,96 +20,100 @@ FLOAT \-?[0-9]*(\.[0-9]+)?
*/
#import <Foundation/Foundation.h>
-#ifdef __APPLE__
-#include "y.tab.h"
-#else
-#include "tikzparser.h"
-#endif
-
-extern char linebuff[500];
-extern int lineno;
-extern int tokenpos;
+#import "tikzparser.h"
%}
+
+%option reentrant bison-bridge 8bit
+%option nounput
+%option yylineno
+%option noyywrap
+%option header-file="common/tikzlexer.h"
+
+%s props
+%s xcoord
+%s ycoord
+%s noderef
+
+FLOAT \-?[0-9]*(\.[0-9]+)?
+
%%
-%\n /* ignore end of line */;
-\n.* { strncpy(linebuff, yytext+1, 500);
- linebuff[499] = 0; // ensure null-terminated
- lineno++;
- tokenpos = 0;
- yyless(1);
- }
-<INITIAL,xcoord,ycoord,props,noderef>[ ]+ { tokenpos += yyleng; } /* ignore whitespace */;
-<INITIAL,xcoord,ycoord,props,noderef>[\t]+ { tokenpos += 8*yyleng; } /* ignore whitespace */;
-\\begin\{tikzpicture\} { tokenpos += yyleng; return BEGIN_TIKZPICTURE_CMD; }
-\\end\{tikzpicture\} { tokenpos += yyleng; return END_TIKZPICTURE_CMD; }
-\\begin\{pgfonlayer\} { tokenpos += yyleng; return BEGIN_PGFONLAYER_CMD; }
-\\end\{pgfonlayer\} { tokenpos += yyleng; return END_PGFONLAYER_CMD; }
-\\draw { tokenpos += yyleng; return DRAW_CMD; }
-\\node { tokenpos += yyleng; return NODE_CMD; }
-\\path { tokenpos += yyleng; return PATH_CMD; }
-rectangle { tokenpos += yyleng; return RECTANGLE; }
-node { tokenpos += yyleng; return NODE; }
-at { tokenpos += yyleng; return AT; }
-to { tokenpos += yyleng; return TO; }
-; { tokenpos += yyleng; return SEMICOLON; }
+
+\n.* {
+ [yyextra newLineStarted:yytext+1];
+ yyless(1);
+}
+<INITIAL,xcoord,ycoord,props,noderef>[ ]+ { [yyextra incrementPosBy:yyleng]; } /* ignore whitespace */;
+<INITIAL,xcoord,ycoord,props,noderef>[\t]+ { [yyextra incrementPosBy:8*yyleng]; } /* ignore whitespace */;
+\\begin\{tikzpicture\} { [yyextra incrementPosBy:yyleng]; return BEGIN_TIKZPICTURE_CMD; }
+\\end\{tikzpicture\} { [yyextra incrementPosBy:yyleng]; return END_TIKZPICTURE_CMD; }
+\\begin\{pgfonlayer\} { [yyextra incrementPosBy:yyleng]; return BEGIN_PGFONLAYER_CMD; }
+\\end\{pgfonlayer\} { [yyextra incrementPosBy:yyleng]; return END_PGFONLAYER_CMD; }
+\\draw { [yyextra incrementPosBy:yyleng]; return DRAW_CMD; }
+\\node { [yyextra incrementPosBy:yyleng]; return NODE_CMD; }
+\\path { [yyextra incrementPosBy:yyleng]; return PATH_CMD; }
+rectangle { [yyextra incrementPosBy:yyleng]; return RECTANGLE; }
+node { [yyextra incrementPosBy:yyleng]; return NODE; }
+at { [yyextra incrementPosBy:yyleng]; return AT; }
+to { [yyextra incrementPosBy:yyleng]; return TO; }
+; { [yyextra incrementPosBy:yyleng]; return SEMICOLON; }
\([ ]*{FLOAT}[ ]*,[ ]*{FLOAT}[ ]*\) {
- tokenpos += 1;
+ [yyextra incrementPosBy:1];
yyless(1);
BEGIN(xcoord);
}
<xcoord>{FLOAT} {
- tokenpos += yyleng;
- yylval.pt.x=(float)strtod(yytext,NULL);
+ [yyextra incrementPosBy:yyleng];
+ yylval->pt.x=(float)strtod(yytext,NULL);
BEGIN(ycoord);
}
-<ycoord>, { tokenpos += yyleng; }
+<ycoord>, { [yyextra incrementPosBy:yyleng]; }
<ycoord>{FLOAT} {
- tokenpos += yyleng;
- yylval.pt.y=(float)strtod(yytext,NULL);
+ [yyextra incrementPosBy:yyleng];
+ yylval->pt.y=(float)strtod(yytext,NULL);
}
<ycoord>\) {
- tokenpos += yyleng;
+ [yyextra incrementPosBy:yyleng];
BEGIN(INITIAL);
return COORD;
}
/* when we see "[", change parsing mode */
\[ /*syntaxhlfix]*/ {
- tokenpos += yyleng;
+ [yyextra incrementPosBy:yyleng];
BEGIN(props);
return LEFTBRACKET;
}
-<props>= { tokenpos += yyleng; return EQUALS; }
-<props>, { tokenpos += yyleng; return COMMA; }
+<props>= { [yyextra incrementPosBy:yyleng]; return EQUALS; }
+<props>, { [yyextra incrementPosBy:yyleng]; return COMMA; }
<props>[^=,\{\] \t]([^=,\{\]]*[^=,\{\] \t])? {
- tokenpos += yyleng;
- yylval.nsstr=[NSString stringWithUTF8String:yytext];
+ [yyextra incrementPosBy:yyleng];
+ yylval->nsstr=[NSString stringWithUTF8String:yytext];
return PROPSTRING;
}
<props>\] {
- tokenpos += yyleng;
+ [yyextra incrementPosBy:yyleng];
BEGIN(INITIAL);
return RIGHTBRACKET;
}
\( {
- tokenpos += yyleng;
+ [yyextra incrementPosBy:yyleng];
BEGIN(noderef);
return LEFTPARENTHESIS;
}
<noderef>\. {
- tokenpos += yyleng;
+ [yyextra incrementPosBy:yyleng];
return FULLSTOP;
}
<noderef>[^\.\{\)]+ {
- tokenpos += yyleng;
- yylval.nsstr=[NSString stringWithUTF8String:yytext];
+ [yyextra incrementPosBy:yyleng];
+ yylval->nsstr=[NSString stringWithUTF8String:yytext];
return REFSTRING;
}
<noderef>\) {
- tokenpos += yyleng;
+ [yyextra incrementPosBy:yyleng];
BEGIN(INITIAL);
return RIGHTPARENTHESIS;
}
@@ -127,7 +123,7 @@ to { tokenpos += yyleng; return TO; }
unsigned int brace_depth = 1;
unsigned int escape = 0;
while (1) {
- char c = input();
+ char c = input(yyscanner);
// eof reached before closing brace
if (c == '\0' || c == EOF) yyterminate();
@@ -147,8 +143,8 @@ to { tokenpos += yyleng; return TO; }
NSString *s = [buf copy];
yyleng += 1 + [buf length];
[s autorelease];
- yylval.nsstr = s;
- tokenpos += yyleng;
+ yylval->nsstr = s;
+ [yyextra incrementPosBy:yyleng];
return DELIMITEDSTRING;
}
diff --git a/tikzit/src/common/tikzparser.ym b/tikzit/src/common/tikzparser.ym
index 074ec2d..1183f12 100644
--- a/tikzit/src/common/tikzparser.ym
+++ b/tikzit/src/common/tikzparser.ym
@@ -1,5 +1,3 @@
-%error-verbose
-
%{
/*
* Copyright 2010 Chris Heunen
@@ -21,18 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#import "TikzGraphAssembler+Parser.h"
#import "Edge.h"
-extern char* yystr;
-extern int yylineno;
-extern int tokenpos;
-extern int yylex(void);
-extern void yyerror(const char *str);
-
%}
%code requires {
+#import "TikzGraphAssembler+Parser.h"
#import "GraphElementData.h"
#import "GraphElementProperty.h"
#import "Node.h"
@@ -42,6 +34,12 @@ struct noderef {
};
}
+%defines "common/tikzparser.h"
+%pure-parser
+%parse-param {TikzGraphAssembler *assembler}
+%error-verbose
+
+
%union {
NSPoint pt;
NSString *nsstr;
@@ -51,6 +49,10 @@ struct noderef {
struct noderef noderef;
};
+%{
+#import "tikzlexer.h"
+%}
+
%token BEGIN_TIKZPICTURE_CMD "\\begin{tikzpicture}"
%token END_TIKZPICTURE_CMD "\\end{tikzpicture}"
@@ -127,14 +129,14 @@ node: "\\node" optproperties nodename "at" COORD DELIMITEDSTRING ";"
[node setName:$3];
[node setPoint:$5];
[node setLabel:$6];
- [[TikzGraphAssembler currentAssembler] addNodeToMap:node];
- [[[TikzGraphAssembler currentAssembler] graph] addNode:node];
+ [assembler addNodeToMap:node];
+ [[assembler graph] addNode:node];
};
optanchor: { $$ = nil; } | "." REFSTRING { $$ = $2; };
noderef: "(" REFSTRING optanchor ")"
{
- $$.node = [[TikzGraphAssembler currentAssembler] nodeWithName:$2];
+ $$.node = [assembler nodeWithName:$2];
$$.anchor = $3;
};
optnoderef:
@@ -163,7 +165,7 @@ edge: "\\draw" optproperties noderef "to" optedgenode optnoderef ";"
[edge setTargetAnchor:$3.anchor];
}
[edge setAttributesFromData];
- [[[TikzGraphAssembler currentAssembler] graph] addEdge:edge];
+ [[assembler graph] addEdge:edge];
};
ignoreprop: val | val "=" val;
@@ -172,7 +174,7 @@ optignoreprops: "[" ignoreprops "]";
boundingbox:
"\\path" optignoreprops COORD "rectangle" COORD ";"
{
- [[[TikzGraphAssembler currentAssembler] graph] setBoundingBox:NSRectAroundPoints($3, $5)];
+ [[assembler graph] setBoundingBox:NSRectAroundPoints($3, $5)];
};
/* vi:ft=yacc:noet:ts=4:sts=4:sw=4