diff options
author | Alex Merry <dev@randomguy3.me.uk> | 2013-03-22 22:26:12 +0000 |
---|---|---|
committer | Alex Merry <dev@randomguy3.me.uk> | 2013-03-22 22:54:32 +0000 |
commit | dbd620bbaf7f28728c2686737b6a1453caaebd25 (patch) | |
tree | 8b2fd7257823983bb957ae7bc230080e9e32f7e7 /tikzit/src/common | |
parent | a38c9405313dceae0f62c965fb99ae69b06b0548 (diff) |
Rewrite the lexer to be context-aware
It turns out Flex can do modal lexing. This means that we can switch
mode for optional properties, and also for co-ordinates. As a result,
the parser is much simpler and doesn't keel over all the time on valid
input.
Diffstat (limited to 'tikzit/src/common')
-rw-r--r-- | tikzit/src/common/tikzlexer.lm | 104 | ||||
-rw-r--r-- | tikzit/src/common/tikzparser.ym | 139 |
2 files changed, 116 insertions, 127 deletions
diff --git a/tikzit/src/common/tikzlexer.lm b/tikzit/src/common/tikzlexer.lm index a9a2e51..3fd7b53 100644 --- a/tikzit/src/common/tikzlexer.lm +++ b/tikzit/src/common/tikzlexer.lm @@ -1,5 +1,10 @@ %option nounput %option yylineno +%s props +%s xcoord +%s ycoord +%s noderef +FLOAT \-?[0-9]*(\.[0-9]+)? %{ // @@ -7,6 +12,9 @@ // 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. @@ -45,48 +53,82 @@ extern int tokenpos; 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; } +<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; } -[0-9]+ { - tokenpos += yyleng; - yylval.nsstr=[NSString stringWithUTF8String:yytext]; - return NATURALNUMBER; +\([ ]*{FLOAT}[ ]*,[ ]*{FLOAT}[ ]*\) { + tokenpos += 1; + yyless(1); + BEGIN(xcoord); +} +<xcoord>{FLOAT} { + tokenpos += yyleng; + yylval.pt.x=(float)strtod(yytext,NULL); + BEGIN(ycoord); +} +<ycoord>, { tokenpos += yyleng; } +<ycoord>{FLOAT} { + tokenpos += yyleng; + yylval.pt.y=(float)strtod(yytext,NULL); +} +<ycoord>\) { + tokenpos += yyleng; + BEGIN(INITIAL); + return COORD; } -(\-?[0-9]*\.[0-9]+)|(\-?[0-9]+) { - tokenpos += yyleng; + /* when we see "[", change parsing mode */ +\[ /*syntaxhlfix]*/ { + tokenpos += yyleng; + BEGIN(props); + return LEFTBRACKET; +} +<props>= { tokenpos += yyleng; return EQUALS; } +<props>, { tokenpos += yyleng; return COMMA; } +<props>[^=,\{\] \t]([^=,\{\]]*[^=,\{\] \t])? { + tokenpos += yyleng; yylval.nsstr=[NSString stringWithUTF8String:yytext]; - return REALNUMBER; + return PROPSTRING; +} +<props>\] { + tokenpos += yyleng; + BEGIN(INITIAL); + return RIGHTBRACKET; } -\\?[a-zA-Z<>\-\'][a-zA-Z<>\-\'0-9]* { //' - tokenpos += yyleng; +\( { + tokenpos += yyleng; + BEGIN(noderef); + return LEFTPARENTHESIS; +} +<noderef>\. { + tokenpos += yyleng; + return FULLSTOP; +} +<noderef>[^\.\{\)]+ { + tokenpos += yyleng; yylval.nsstr=[NSString stringWithUTF8String:yytext]; - return LWORD; + return REFSTRING; +} +<noderef>\) { + tokenpos += yyleng; + BEGIN(INITIAL); + return RIGHTPARENTHESIS; } - -\{ { +<INITIAL,props>\{ { NSMutableString *buf = [NSMutableString string]; unsigned int brace_depth = 1; unsigned int escape = 0; diff --git a/tikzit/src/common/tikzparser.ym b/tikzit/src/common/tikzparser.ym index 2277e23..170106f 100644 --- a/tikzit/src/common/tikzparser.ym +++ b/tikzit/src/common/tikzparser.ym @@ -44,55 +44,46 @@ extern void yyerror(const char *str); %error-verbose -%token LATEXBEGIN -%token LATEXEND -%token TIKZPICTURE -%token PGFONLAYER +%token BEGIN_TIKZPICTURE_CMD +%token END_TIKZPICTURE_CMD +%token BEGIN_PGFONLAYER_CMD +%token END_PGFONLAYER_CMD +%token DRAW_CMD +%token NODE_CMD +%token PATH_CMD +%token RECTANGLE +%token NODE +%token AT +%token TO +%token SEMICOLON +%token COMMA + %token LEFTPARENTHESIS %token RIGHTPARENTHESIS %token LEFTBRACKET %token RIGHTBRACKET -%token SEMICOLON -%token COMMA %token FULLSTOP %token EQUALS -%token DRAW -%token TO -%token NODE -%token RECTANGLE -%token PATH -%token ALTNODE -%token AT -%token REALNUMBER -%token NATURALNUMBER -%token LWORD +%token COORD +%token PROPSTRING +%token REFSTRING %token DELIMITEDSTRING %type<nsstr> nodename -%type<nsstr> anchor -%type<nsstr> anchorsym %type<nsstr> optanchor -%type<nsstr> nodeid -%type<pt> coords -%type<nsstr> propsym -%type<nsstr> propsyms %type<nsstr> val -%type<nsstr> number %% -tikzpicture: LATEXBEGIN TIKZPICTURE optproperties expressions LATEXEND TIKZPICTURE; -expressions: expressions expression | ; -expression: node | edge | boundingbox | ignore; - -ignore: LATEXBEGIN PGFONLAYER DELIMITEDSTRING | LATEXEND PGFONLAYER; +tikzpicture: BEGIN_TIKZPICTURE_CMD optproperties tikzcmds END_TIKZPICTURE_CMD; +tikzcmds: tikzcmds tikzcmd | ; +tikzcmd: node | edge | boundingbox | ignore; -number: REALNUMBER { $$ = $<nsstr>1; } | NATURALNUMBER { $$ = $<nsstr>1; }; +ignore: BEGIN_PGFONLAYER_CMD DELIMITEDSTRING | END_PGFONLAYER_CMD; optproperties: LEFTBRACKET properties RIGHTBRACKET | ; properties: property extraproperties; -extraproperties: COMMA property extraproperties | property extraproperties | ; - +extraproperties: COMMA property extraproperties | ; property: val EQUALS val { @@ -108,79 +99,33 @@ property: [[a data] addObject:p]; [p release]; }; +val: PROPSTRING { $$ = $<nsstr>1; } | DELIMITEDSTRING { $$ = $<nsstr>1; }; -val: propsyms { $$ = $<nsstr>1; } | DELIMITEDSTRING { $$ = $<nsstr>1; }; -propsyms: - propsym { $$ = $<nsstr>1; } - | propsyms propsym - { - NSString *s = [$<nsstr>1 stringByAppendingFormat:@" %@", $<nsstr>2]; - $$ = s; - }; - -propsym: - LWORD { $$ = $<nsstr>1; } - | number { $$ = $<nsstr>1; } - | TO { $$ = @"to"; } - | ALTNODE { $$ = @"node"; } - | RECTANGLE { $$ = @"rectangle"; } - | AT { $$ = @"at"; } - | FULLSTOP { $$ = @"."; }; - - -nodecmd : NODE { [[TikzGraphAssembler currentAssembler] prepareNode]; }; - -nodename: LEFTPARENTHESIS nodeid RIGHTPARENTHESIS { $$ = $<nsstr>2; }; - -node: - nodecmd optproperties nodename AT coords nodelabel SEMICOLON +nodecmd: NODE_CMD { [[TikzGraphAssembler currentAssembler] prepareNode]; }; +nodename: LEFTPARENTHESIS REFSTRING RIGHTPARENTHESIS { $$ = $<nsstr>2; }; +node: nodecmd optproperties nodename AT COORD DELIMITEDSTRING SEMICOLON { TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; [[a currentNode] setName:$<nsstr>3]; [[a currentNode] setPoint:$<pt>5]; + [[a currentNode] setLabel:$<nsstr>6]; [a finishNode]; }; -nodelabel: - DELIMITEDSTRING +edgecmd : DRAW_CMD { [[TikzGraphAssembler currentAssembler] prepareEdge]; }; +edge: edgecmd optproperties source TO optedgenode target SEMICOLON { - Node *n = [[TikzGraphAssembler currentAssembler] currentNode]; - [n setLabel:$<nsstr>1]; - } - -anchor: anchorsym { $$ = $<nsstr>1; } - | anchor anchorsym - { - NSString *s = [$<nsstr>1 stringByAppendingFormat:@" %@", $<nsstr>2]; - $$ = s; + TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; + [a finishEdge]; }; -anchorsym: LWORD { $$ = $<nsstr>1; } | NATURALNUMBER { $$ = $<nsstr>1; }; - -optanchor: { $$ = @""; } | FULLSTOP anchor { $$ = $<nsstr>2; }; - -source: LEFTPARENTHESIS nodeid optanchor RIGHTPARENTHESIS +optanchor: { $$ = @""; } | FULLSTOP REFSTRING { $$ = $<nsstr>2; }; +source: LEFTPARENTHESIS REFSTRING optanchor RIGHTPARENTHESIS { TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; [a setEdgeSource:$<nsstr>2 anchor:$<nsstr>3]; }; - -nodeid: LWORD { $$ = $<nsstr>1; } | NATURALNUMBER { $$ = $<nsstr>1; }; - -coords: - LEFTPARENTHESIS number COMMA number RIGHTPARENTHESIS - { - $$ = NSMakePoint([$<nsstr>2 floatValue], [$<nsstr>4 floatValue]); - }; - -edgecmd : DRAW { [[TikzGraphAssembler currentAssembler] prepareEdge]; }; -edge: - edgecmd optproperties source TO optedgenode target SEMICOLON - { - TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; - [a finishEdge]; - }; -target: LEFTPARENTHESIS nodeid optanchor RIGHTPARENTHESIS +target: LEFTPARENTHESIS REFSTRING optanchor RIGHTPARENTHESIS { TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; [a setEdgeTarget:$<nsstr>2 @@ -194,18 +139,20 @@ target: LEFTPARENTHESIS nodeid optanchor RIGHTPARENTHESIS }; selfloop: LEFTPARENTHESIS RIGHTPARENTHESIS; -altnodecmd: ALTNODE { [[TikzGraphAssembler currentAssembler] prepareNode]; }; +edgenodecmd: NODE { [[TikzGraphAssembler currentAssembler] prepareNode]; }; optedgenode: - | altnodecmd optproperties nodelabel + | edgenodecmd optproperties DELIMITEDSTRING { - [[TikzGraphAssembler currentAssembler] finishNode]; + TikzGraphAssembler *a = [TikzGraphAssembler currentAssembler]; + [[a currentNode] setLabel:$<nsstr>3]; + [a finishNode]; } -bbox_ignoreprops: - | LEFTBRACKET LWORD LWORD LWORD LWORD RIGHTBRACKET; - +ignoreprop: val | val EQUALS val; +ignoreprops: ignoreprop ignoreprops | ; +optignoreprops: LEFTBRACKET ignoreprops RIGHTBRACKET; boundingbox: - PATH bbox_ignoreprops coords RECTANGLE coords SEMICOLON + PATH_CMD optignoreprops COORD RECTANGLE COORD SEMICOLON { Graph *g = [[TikzGraphAssembler currentAssembler] graph]; [g setBoundingBox:NSRectAroundPoints($<pt>3, $<pt>5)]; |