From 2aa4afed415b02add73c2dd5a3e9ccab90066d04 Mon Sep 17 00:00:00 2001 From: Alex Merry Date: Sat, 23 Mar 2013 00:45:23 +0000 Subject: Make the parser more coherent We build things up in stacks in the parser, rather than relying on TikzGraphAssembler so much. This makes tikzparser.ym easier to follow (IMHO). --- tikzit/src/common/GraphElementData.h | 2 + tikzit/src/common/GraphElementData.m | 4 + tikzit/src/common/GraphElementProperty.h | 3 + tikzit/src/common/GraphElementProperty.m | 10 ++ tikzit/src/common/TikzGraphAssembler+Parser.h | 33 +++++ tikzit/src/common/TikzGraphAssembler.h | 13 -- tikzit/src/common/TikzGraphAssembler.m | 83 +++-------- tikzit/src/common/tikzlexer.lm | 44 +++--- tikzit/src/common/tikzparser.ym | 191 ++++++++++++++------------ 9 files changed, 191 insertions(+), 192 deletions(-) create mode 100644 tikzit/src/common/TikzGraphAssembler+Parser.h diff --git a/tikzit/src/common/GraphElementData.h b/tikzit/src/common/GraphElementData.h index e5ff4d7..a65e6df 100644 --- a/tikzit/src/common/GraphElementData.h +++ b/tikzit/src/common/GraphElementData.h @@ -40,6 +40,8 @@ NSMutableArray *properties; } +- (id)init; ++ (id)data; /*! @brief Set the given value for the *first* property matching this key. Add a diff --git a/tikzit/src/common/GraphElementData.m b/tikzit/src/common/GraphElementData.m index fd93a0d..a99a432 100644 --- a/tikzit/src/common/GraphElementData.m +++ b/tikzit/src/common/GraphElementData.m @@ -27,6 +27,10 @@ @implementation GraphElementData ++ (id)data { + return [[[self alloc] init] autorelease]; +} + - (id)init { [super init]; properties = [[NSMutableArray alloc] init]; diff --git a/tikzit/src/common/GraphElementProperty.h b/tikzit/src/common/GraphElementProperty.h index 3ca93dc..029e7f3 100644 --- a/tikzit/src/common/GraphElementProperty.h +++ b/tikzit/src/common/GraphElementProperty.h @@ -46,6 +46,7 @@ @result A key-matching object. */ - (id)initWithKeyMatching:(NSString*)k; ++ (id)keyMatching:(NSString*)k; /*! @brief Initialize a new atomic property. @@ -53,6 +54,7 @@ @result An atom. */ - (id)initWithAtomName:(NSString*)n; ++ (id)atom:(NSString*)n; /*! @brief Initialize a new property. @@ -61,6 +63,7 @@ @result A property. */ - (id)initWithPropertyValue:(NSString*)v forKey:(NSString*)k; ++ (id)property:(NSString*)k withValue:(NSString*)v; /*! @brief A matching function for properties. diff --git a/tikzit/src/common/GraphElementProperty.m b/tikzit/src/common/GraphElementProperty.m index 2eb6a5f..1e8ad3a 100644 --- a/tikzit/src/common/GraphElementProperty.m +++ b/tikzit/src/common/GraphElementProperty.m @@ -27,6 +27,16 @@ @implementation GraphElementProperty ++ (id)atom:(NSString*)n { + return [[[self alloc] initWithAtomName:n] autorelease]; +} ++ (id)property:(NSString*)k withValue:(NSString*)v { + return [[[self alloc] initWithPropertyValue:v forKey:k] autorelease]; +} ++ (id)keyMatching:(NSString*)k { + return [[[self alloc] initWithKeyMatching:k] autorelease]; +} + - (id)initWithAtomName:(NSString*)n { [super init]; [self setKey:n]; diff --git a/tikzit/src/common/TikzGraphAssembler+Parser.h b/tikzit/src/common/TikzGraphAssembler+Parser.h new file mode 100644 index 0000000..683e3e2 --- /dev/null +++ b/tikzit/src/common/TikzGraphAssembler+Parser.h @@ -0,0 +1,33 @@ +/* + * Copyright 2013 Alex Merry + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * TikzGraphAssember+Parser.h + * + * This file exposes some TikzGraphAssembler functions + * that are only of use to the parser. + */ + +#import "TikzGraphAssembler.h" + +@interface TikzGraphAssembler (Parser) +/** Store a node so that it can be looked up by name later */ +- (void)addNodeToMap:(Node*)n; +- (Node*)nodeWithName:(NSString*)name; +@end + +// 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 a0c8a0d..3fc4e9e 100644 --- a/tikzit/src/common/TikzGraphAssembler.h +++ b/tikzit/src/common/TikzGraphAssembler.h @@ -26,16 +26,11 @@ @interface TikzGraphAssembler : NSObject { Graph *graph; - Node *currentNode; - Edge *currentEdge; NSMutableDictionary *nodeMap; NSError *lastError; } @property (readonly) Graph *graph; -@property (readonly) GraphElementData *data; -@property (readonly) Node *currentNode; -@property (readonly) Edge *currentEdge; @property (readonly) NSError *lastError; - (BOOL)parseTikz:(NSString*)tikz; @@ -43,14 +38,6 @@ - (BOOL)testTikz:(NSString*)tikz; -- (void)prepareNode; -- (void)finishNode; - -- (void)prepareEdge; -- (void)setEdgeSource:(NSString*)edge anchor:(NSString*)anch; -- (void)setEdgeTarget:(NSString*)edge anchor:(NSString*)anch; -- (void)finishEdge; - - (void)invalidate; - (void)invalidateWithError:(NSError*)error; diff --git a/tikzit/src/common/TikzGraphAssembler.m b/tikzit/src/common/TikzGraphAssembler.m index 8400cf6..26bf515 100644 --- a/tikzit/src/common/TikzGraphAssembler.m +++ b/tikzit/src/common/TikzGraphAssembler.m @@ -77,29 +77,18 @@ int yywrap() { @implementation TikzGraphAssembler - (id)init { - [super init]; - graph = nil; - currentNode = nil; - currentEdge = nil; - nodeMap = nil; + self = [super init]; return self; } -- (Graph*)graph { return graph; } -- (NSError*)lastError { return lastError; } - -- (GraphElementData *)data { - if (currentNode != nil) { - return [currentNode data]; - } else if (currentEdge != nil) { - return [currentEdge data]; - } else { - return [graph data]; - } +- (void)dealloc { + [graph release]; + [lastError release]; + [super dealloc]; } -- (Node*)currentNode { return currentNode; } -- (Edge*)currentEdge { return currentEdge; } +- (Graph*)graph { return graph; } +- (NSError*)lastError { return lastError; } - (BOOL)parseTikz:(NSString *)tikz { return [self parseTikz:tikz forGraph:[Graph graph]]; @@ -170,55 +159,6 @@ int yywrap() { return r; } -- (void)prepareNode { - currentNode = [[Node alloc] init]; -} - -- (void)finishNode { - if (currentEdge != nil) { // this is an edge node - [currentEdge setEdgeNode:currentNode]; - } else { // this is a normal node - [graph addNode:currentNode]; - [nodeMap setObject:currentNode forKey:[currentNode name]]; - } - - [currentNode release]; - currentNode = nil; -} - -- (void)prepareEdge { - currentEdge = [[Edge alloc] init]; -} - -- (void)finishEdge { - [currentEdge setAttributesFromData]; - [graph addEdge:currentEdge]; - [currentEdge release]; - currentEdge = nil; -} - -- (void)setEdgeSource:(NSString*)edge anchor:(NSString*)anch { - Node *s = [nodeMap objectForKey:edge]; - [currentEdge setSource:s]; - [currentEdge setSourceAnchor:anch]; -} - -- (void)setEdgeTarget:(NSString*)edge anchor:(NSString*)anch { - if (![edge isEqualToString:@""]) { - [currentEdge setTarget:[nodeMap objectForKey:edge]]; - [currentEdge setTargetAnchor:anch]; - } else { - [currentEdge setTargetAnchor:anch]; - [currentEdge setTarget:[currentEdge source]]; - } -} - -- (void)dealloc { - [graph release]; - [lastError release]; - [super dealloc]; -} - - (void)invalidate { [graph release]; graph = nil; @@ -244,4 +184,13 @@ int yywrap() { @end +@implementation TikzGraphAssembler (Parser) +- (void)addNodeToMap:(Node*)n { + [nodeMap setObject:n forKey:[n name]]; +} +- (Node*)nodeWithName:(NSString*)name { + return [nodeMap objectForKey:name]; +} +@end + // vi:ft=objc:ts=4:noet:sts=4:sw=4 diff --git a/tikzit/src/common/tikzlexer.lm b/tikzit/src/common/tikzlexer.lm index 3fd7b53..ad99445 100644 --- a/tikzit/src/common/tikzlexer.lm +++ b/tikzit/src/common/tikzlexer.lm @@ -7,31 +7,25 @@ FLOAT \-?[0-9]*(\.[0-9]+)? %{ -// -// tikzparser.l -// TikZiT -// -// Copyright 2010 Chris Heunen. All rights reserved. -// Copyright 2012 Aleks Kissinger -// Copyright 2012 KJ -// Copyright 2013 Alex Merry -// -// -// This file is part of TikZiT. -// -// TikZiT is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// TikZiT is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with TikZiT. If not, see . -// +/* + * Copyright 2010 Chris Heunen + * Copyright 2010-2013 Aleks Kissinger + * Copyright 2013 K. Johan Paulsson + * Copyright 2013 Alex Merry + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #import #ifdef __APPLE__ diff --git a/tikzit/src/common/tikzparser.ym b/tikzit/src/common/tikzparser.ym index 170106f..b81b74c 100644 --- a/tikzit/src/common/tikzparser.ym +++ b/tikzit/src/common/tikzparser.ym @@ -1,34 +1,29 @@ -// %expect 3 +%error-verbose %{ -// -// tikzparser.y -// TikZiT -// -// Copyright 2010 Chris Heunen. All rights reserved. -// -// -// This file is part of TikZiT. -// -// TikZiT is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// TikZiT is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with TikZiT. If not, see . -// -#include -#include -#import -#import "TikzGraphAssembler.h" -#import "GraphElementProperty.h" - +/* + * Copyright 2010 Chris Heunen + * Copyright 2010-2013 Aleks Kissinger + * Copyright 2013 K. Johan Paulsson + * Copyright 2013 Alex Merry + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "TikzGraphAssembler+Parser.h" +#import "Edge.h" + extern char* yystr; extern int yylineno; extern int tokenpos; @@ -37,12 +32,25 @@ extern void yyerror(const char *str); %} +%code requires { +#import "GraphElementData.h" +#import "GraphElementProperty.h" +#import "Node.h" +struct noderef { + Node *node; + NSString *anchor; +}; +} + %union { NSPoint pt; NSString *nsstr; + GraphElementProperty *prop; + GraphElementData *data; + Node *node; + struct noderef noderef; }; -%error-verbose %token BEGIN_TIKZPICTURE_CMD %token END_TIKZPICTURE_CMD @@ -69,9 +77,16 @@ extern void yyerror(const char *str); %token REFSTRING %token DELIMITEDSTRING -%type nodename -%type optanchor -%type val +%type nodename +%type optanchor +%type val +%type property +%type extraproperties +%type properties +%type optproperties +%type optedgenode +%type noderef +%type optnoderef %% @@ -81,72 +96,75 @@ tikzcmd: node | edge | boundingbox | ignore; ignore: BEGIN_PGFONLAYER_CMD DELIMITEDSTRING | END_PGFONLAYER_CMD; -optproperties: LEFTBRACKET properties RIGHTBRACKET | ; -properties: property extraproperties; -extraproperties: COMMA property extraproperties | ; -property: - val EQUALS val +optproperties: + LEFTBRACKET properties RIGHTBRACKET + { $$ = $2; } + | { $$ = nil; }; +properties: property extraproperties { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - GraphElementProperty *p = [[GraphElementProperty alloc] initWithPropertyValue:$3 forKey:$1]; - [[a data] addObject:p]; - [p release]; + [$2 addObject:$1]; + $$ = $2; + }; +extraproperties: + COMMA property extraproperties + { + [$3 addObject:$2]; + $$ = $3; } + | { $$ = [GraphElementData data]; }; +property: + val EQUALS val + { $$ = [GraphElementProperty property:$1 withValue:$3]; } | val - { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - GraphElementProperty *p = [[GraphElementProperty alloc] initWithAtomName:$1]; - [[a data] addObject:p]; - [p release]; - }; + { $$ = [GraphElementProperty atom:$1]; }; val: PROPSTRING { $$ = $1; } | DELIMITEDSTRING { $$ = $1; }; -nodecmd: NODE_CMD { [[TikzGraphAssembler currentAssembler] prepareNode]; }; nodename: LEFTPARENTHESIS REFSTRING RIGHTPARENTHESIS { $$ = $2; }; -node: nodecmd optproperties nodename AT COORD DELIMITEDSTRING SEMICOLON +node: NODE_CMD optproperties nodename AT COORD DELIMITEDSTRING SEMICOLON { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - [[a currentNode] setName:$3]; - [[a currentNode] setPoint:$5]; - [[a currentNode] setLabel:$6]; - [a finishNode]; + Node *node = [Node node]; + [node setData:$2]; + [node setName:$3]; + [node setPoint:$5]; + [node setLabel:$6]; + [[TikzGraphAssembler currentAssembler] addNodeToMap:node]; + [[[TikzGraphAssembler currentAssembler] graph] addNode:node]; }; -edgecmd : DRAW_CMD { [[TikzGraphAssembler currentAssembler] prepareEdge]; }; -edge: edgecmd optproperties source TO optedgenode target SEMICOLON +optanchor: { $$ = nil; } | FULLSTOP REFSTRING { $$ = $2; }; +noderef: LEFTPARENTHESIS REFSTRING optanchor RIGHTPARENTHESIS { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - [a finishEdge]; + $$.node = [[TikzGraphAssembler currentAssembler] nodeWithName:$2]; + $$.anchor = $3; }; -optanchor: { $$ = @""; } | FULLSTOP REFSTRING { $$ = $2; }; -source: LEFTPARENTHESIS REFSTRING optanchor RIGHTPARENTHESIS - { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - [a setEdgeSource:$2 - anchor:$3]; - }; -target: LEFTPARENTHESIS REFSTRING optanchor RIGHTPARENTHESIS - { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - [a setEdgeTarget:$2 - anchor:$3]; - } - | selfloop - { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - [a setEdgeTarget:@"" - anchor:@""]; - }; -selfloop: LEFTPARENTHESIS RIGHTPARENTHESIS; - -edgenodecmd: NODE { [[TikzGraphAssembler currentAssembler] prepareNode]; }; +optnoderef: + noderef { $$ = $1; } + | LEFTPARENTHESIS RIGHTPARENTHESIS { $$.node = nil; $$.anchor = nil; } optedgenode: - | edgenodecmd optproperties DELIMITEDSTRING + { $$ = nil; } + | NODE optproperties DELIMITEDSTRING { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - [[a currentNode] setLabel:$3]; - [a finishNode]; + $$ = [Node node]; + [$$ setData:$2]; + [$$ setLabel:$3]; } +edge: DRAW_CMD optproperties noderef TO optedgenode optnoderef SEMICOLON + { + Edge *edge = [Edge edge]; + [edge setData:$2]; + [edge setSource:$3.node]; + [edge setSourceAnchor:$3.anchor]; + [edge setEdgeNode:$5]; + if ($6.node) { + [edge setTarget:$6.node]; + [edge setTargetAnchor:$6.anchor]; + } else { + [edge setTarget:$3.node]; + [edge setTargetAnchor:$3.anchor]; + } + [edge setAttributesFromData]; + [[[TikzGraphAssembler currentAssembler] graph] addEdge:edge]; + }; ignoreprop: val | val EQUALS val; ignoreprops: ignoreprop ignoreprops | ; @@ -154,8 +172,7 @@ optignoreprops: LEFTBRACKET ignoreprops RIGHTBRACKET; boundingbox: PATH_CMD optignoreprops COORD RECTANGLE COORD SEMICOLON { - Graph *g = [[TikzGraphAssembler currentAssembler] graph]; - [g setBoundingBox:NSRectAroundPoints($3, $5)]; + [[[TikzGraphAssembler currentAssembler] graph] setBoundingBox:NSRectAroundPoints($3, $5)]; }; /* vi:ft=yacc:noet:ts=4:sts=4:sw=4 -- cgit v1.2.3