├── README.markdown
├── Statec.xcodeproj
└── project.pbxproj
├── Statec
├── Builder
│ ├── StatecArgument.h
│ ├── StatecArgument.m
│ ├── StatecClass.h
│ ├── StatecClass.m
│ ├── StatecCodeStatement.h
│ ├── StatecCodeStatement.m
│ ├── StatecCompilationUnit.h
│ ├── StatecCompilationUnit.m
│ ├── StatecConditionalStatement.h
│ ├── StatecConditionalStatement.m
│ ├── StatecEnumeration.h
│ ├── StatecEnumeration.m
│ ├── StatecGVBuilder.h
│ ├── StatecGVBuilder.m
│ ├── StatecHTMLBuilder.h
│ ├── StatecHTMLBuilder.m
│ ├── StatecMethod.h
│ ├── StatecMethod.m
│ ├── StatecProperty.h
│ ├── StatecProperty.m
│ ├── StatecStatement.h
│ ├── StatecStatement.m
│ ├── StatecStatementGroup.h
│ ├── StatecStatementGroup.m
│ ├── StatecType.h
│ ├── StatecType.m
│ ├── StatecTypedef.h
│ ├── StatecTypedef.m
│ ├── StatecVariable.h
│ └── StatecVariable.m
├── Categories
│ ├── NSString+StatecExtensions.h
│ └── NSString+StatecExtensions.m
├── Compiler
│ ├── StatecCompiler.h
│ └── StatecCompiler.m
├── Parser
│ ├── StatecEnter.h
│ ├── StatecEnter.m
│ ├── StatecExit.h
│ ├── StatecExit.m
│ ├── StatecInitial.h
│ ├── StatecInitial.m
│ ├── StatecMachine.h
│ ├── StatecMachine.m
│ ├── StatecParser.h
│ ├── StatecParser.m
│ ├── StatecState.h
│ ├── StatecState.m
│ ├── StatecTransition.h
│ └── StatecTransition.m
├── Statec-Prefix.pch
├── Statec.1
├── Statec.h
├── StatecEvent.h
├── StatecEvent.m
└── main.m
└── StatecRunner
├── StatecAppDelegate.h
├── StatecAppDelegate.m
├── StatecRunner-Info.plist
├── StatecRunner-Prefix.pch
├── en.lproj
├── Credits.rtf
├── InfoPlist.strings
└── MainMenu.xib
└── main.m
/README.markdown:
--------------------------------------------------------------------------------
1 | # statec
2 |
3 | ## introduction
4 |
5 | Pronounced "static", statec is an Objective-C/Foundation tool to compile Obj-C state machine classes from a little language that describes them.
6 |
7 | The goal was to have a simple, clear, language to express a state machine that compiles into an easy to use class to operate them. There are other, similar, tools available for example [SMC](http://smc.sourceforge.net/) or [Ragel](http://www.complang.org/ragel/) which are more comprehensive, support a wide range of languages, and so forth. They are good tools but they did not immediately fit my needs and thus began a monumental exercise in Yak shaving.
8 |
9 | Two days later and I have a "little language" for expressing state machines that is parsed - using a parser built with Tom Davie's [CoreParse](https://github.com/beelsebob/CoreParse) framework (itself quite young but promising) - into an intermediate representation of a machine and then converted directly into Objective-C source using an Objective-C code generator framework built as part of the framework.
10 |
11 | Similar to the approach taken by Rentzsch's [mogenerator](https://github.com/rentzsch/mogenerator) statec generates two classes for each machine, a completely generated implementation class and a user-managed class that subclasses it. The implementation provides methods to respond to state changes that the user-managed class can override to provide context specific processing.
12 |
13 | ## language
14 |
15 | The statec language is a little language for describing state machines. It has a few keywords and a simple structure, here's an example:
16 |
17 |
18 | @machine "TrafficLight" {
19 | @initial "off"
20 | @state "off" {
21 | @event "on" => "green"
22 | }
23 | @state "green" {
24 | @enter
25 | @exit
26 | @event "amber" => "amber"
27 | @event "off" => "off"
28 | }
29 | @state "amber" {
30 | @enter
31 | @exit
32 | @event "green" => "green"
33 | @event "red" => "red"
34 | }
35 | @state "red" {
36 | @enter
37 | @exit
38 | @event "amber" => "amber"
39 | }
40 | }
41 |
42 |
43 |
44 | - @machine
45 | - names the machine and contains its states. The name is used as the basis of the classes generated, in our example they would be _TrafficLightMachine (the implementation class) and TrafficLightMachine (the user class).
46 | - @initial
47 | - defines the initial state of the machine (an enter event is not generated for the machine being started in this state).
48 | - @state
49 | - defines a named state
50 | - @enter
51 | - specifies that a callback (e.g. enterGreenState) should be generated and invoked when the machine enters this state.
52 | - @exit
53 | - specifies than a callback (e.g. exitAmberState) should be generated and invoked before the machine leaves this state.
54 | - @event
55 | - defines a named event and the state the event transitions the machine into. The event name is used to name the event method in the machine (e.g. amberEvent) to cause the transition.
56 |
57 |
58 | The current behaviour is to raise an exception when an event is invoked that is not legal in the current state. In the future this might - optionally - return a condition & NSError instead.
59 |
60 | ## running
61 |
62 | The statec command line tool requires the CoreParse.framework be installed in /Library/Frameworks.
63 |
64 | The statec command line tool has three arguments:
65 |
66 | * -i <machine file>
67 | * e.g. trafficlight.smd
68 | * -d <target folder>
69 | * e.g. ~/Projects/TrafficLightSim/
70 | * -g
71 | * Generate a GraphViz digraph of the machine and, if the `dot` command is available convert it into a PNG image.
72 |
73 | The generated files should be added to your Xcode project. The *\_<Name>Machine.m* file should not be edited as this will be regenerated every time the statec command is generated. The *<Name>Machine.m* is intended for the user to edit and will not be regenerated if it exists.
74 |
75 | ## machine
76 |
77 | The generated machine does not employ a switch statement or lookup table but, rather, stateless classes that represent the states in the machine and that have methods that represent the available transitions.
78 |
79 | In our example a class `TrafficLightState` is generated along with a subclass for each state, e.g. `TrafficLightOnState`. The `TrafficLightMachine` has a state variable that points at an instance representing the current state. When an event method e.g. `greenEvent` is called on the machine it is passed to the current state class that either transitions the calling machine into a new state (optionally invoking exit & enter callbacks), or raises an exception if the transition is not legal from that state.
80 |
--------------------------------------------------------------------------------
/Statec.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | C93DC584150296B400007F09 /* StatecCompiler.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743F214D774FC003E2DBA /* StatecCompiler.m */; };
11 | C93DC5861502971200007F09 /* StatecParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743BE14D6ED3A003E2DBA /* StatecParser.m */; };
12 | C93DC5871502972A00007F09 /* StatecClass.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743C714D6EE25003E2DBA /* StatecClass.m */; };
13 | C93DC5881502972A00007F09 /* StatecMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743CD14D6F178003E2DBA /* StatecMethod.m */; };
14 | C93DC5891502972A00007F09 /* StatecVariable.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743D014D6F189003E2DBA /* StatecVariable.m */; };
15 | C93DC58A1502972A00007F09 /* StatecProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743D314D6F210003E2DBA /* StatecProperty.m */; };
16 | C93DC58B1502972A00007F09 /* StatecArgument.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743D714D7326E003E2DBA /* StatecArgument.m */; };
17 | C93DC58C1502972A00007F09 /* StatecTypedef.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743F814D802E1003E2DBA /* StatecTypedef.m */; };
18 | C93DC58D1502972A00007F09 /* StatecEnumeration.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743FB14D805C6003E2DBA /* StatecEnumeration.m */; };
19 | C93DC58E1502972A00007F09 /* StatecType.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743FE14D807A1003E2DBA /* StatecType.m */; };
20 | C93DC58F1502972A00007F09 /* StatecCompilationUnit.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A7440114D8096A003E2DBA /* StatecCompilationUnit.m */; };
21 | C93DC5901502972A00007F09 /* StatecCodeStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A7440414D826E3003E2DBA /* StatecCodeStatement.m */; };
22 | C93DC5911502972A00007F09 /* StatecStatementGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A7440714D8282F003E2DBA /* StatecStatementGroup.m */; };
23 | C93DC5921502972A00007F09 /* StatecStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A7440A14D82897003E2DBA /* StatecStatement.m */; };
24 | C93DC5931502972A00007F09 /* StatecConditionalStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = C98F6BD014D844530019E817 /* StatecConditionalStatement.m */; };
25 | C93DC5941502972A00007F09 /* StatecGVBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ED4AC314DB14C60044BE00 /* StatecGVBuilder.m */; };
26 | C93DC5951502972A00007F09 /* StatecHTMLBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ED4AC914DB25090044BE00 /* StatecHTMLBuilder.m */; };
27 | C93DC5961502973400007F09 /* NSString+StatecExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ED4ABD14DAF2620044BE00 /* NSString+StatecExtensions.m */; };
28 | C93DC5971502974100007F09 /* StatecMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743DF14D765AC003E2DBA /* StatecMachine.m */; };
29 | C93DC5981502974100007F09 /* StatecInitial.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743E214D76BF2003E2DBA /* StatecInitial.m */; };
30 | C93DC5991502974100007F09 /* StatecState.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743E514D76C02003E2DBA /* StatecState.m */; };
31 | C93DC59A1502974100007F09 /* StatecEnter.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743E814D76C13003E2DBA /* StatecEnter.m */; };
32 | C93DC59B1502974100007F09 /* StatecExit.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743EB14D76C22003E2DBA /* StatecExit.m */; };
33 | C93DC59C1502974100007F09 /* StatecEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743EE14D76C2E003E2DBA /* StatecEvent.m */; };
34 | C93DC59D1502974100007F09 /* StatecTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743F514D77826003E2DBA /* StatecTransition.m */; };
35 | C94349871503983000705EB0 /* CoreParse.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C94349861503983000705EB0 /* CoreParse.framework */; };
36 | C94349881503983600705EB0 /* CoreParse.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C94349861503983000705EB0 /* CoreParse.framework */; };
37 | C98F6BD114D844530019E817 /* StatecConditionalStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = C98F6BD014D844530019E817 /* StatecConditionalStatement.m */; };
38 | C9A743AA14D6ECDE003E2DBA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9A743A914D6ECDE003E2DBA /* Foundation.framework */; };
39 | C9A743AD14D6ECDE003E2DBA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743AC14D6ECDE003E2DBA /* main.m */; };
40 | C9A743B114D6ECDE003E2DBA /* Statec.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C9A743B014D6ECDE003E2DBA /* Statec.1 */; };
41 | C9A743BF14D6ED3A003E2DBA /* StatecParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743BE14D6ED3A003E2DBA /* StatecParser.m */; };
42 | C9A743C814D6EE25003E2DBA /* StatecClass.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743C714D6EE25003E2DBA /* StatecClass.m */; };
43 | C9A743CE14D6F178003E2DBA /* StatecMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743CD14D6F178003E2DBA /* StatecMethod.m */; };
44 | C9A743D114D6F189003E2DBA /* StatecVariable.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743D014D6F189003E2DBA /* StatecVariable.m */; };
45 | C9A743D414D6F210003E2DBA /* StatecProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743D314D6F210003E2DBA /* StatecProperty.m */; };
46 | C9A743D814D7326E003E2DBA /* StatecArgument.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743D714D7326E003E2DBA /* StatecArgument.m */; };
47 | C9A743E014D765AC003E2DBA /* StatecMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743DF14D765AC003E2DBA /* StatecMachine.m */; };
48 | C9A743E314D76BF2003E2DBA /* StatecInitial.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743E214D76BF2003E2DBA /* StatecInitial.m */; };
49 | C9A743E614D76C02003E2DBA /* StatecState.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743E514D76C02003E2DBA /* StatecState.m */; };
50 | C9A743E914D76C13003E2DBA /* StatecEnter.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743E814D76C13003E2DBA /* StatecEnter.m */; };
51 | C9A743EC14D76C22003E2DBA /* StatecExit.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743EB14D76C22003E2DBA /* StatecExit.m */; };
52 | C9A743EF14D76C2F003E2DBA /* StatecEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743EE14D76C2E003E2DBA /* StatecEvent.m */; };
53 | C9A743F314D774FC003E2DBA /* StatecCompiler.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743F214D774FC003E2DBA /* StatecCompiler.m */; };
54 | C9A743F614D77827003E2DBA /* StatecTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743F514D77826003E2DBA /* StatecTransition.m */; };
55 | C9A743F914D802E1003E2DBA /* StatecTypedef.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743F814D802E1003E2DBA /* StatecTypedef.m */; };
56 | C9A743FC14D805C7003E2DBA /* StatecEnumeration.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743FB14D805C6003E2DBA /* StatecEnumeration.m */; };
57 | C9A743FF14D807A2003E2DBA /* StatecType.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A743FE14D807A1003E2DBA /* StatecType.m */; };
58 | C9A7440214D8096B003E2DBA /* StatecCompilationUnit.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A7440114D8096A003E2DBA /* StatecCompilationUnit.m */; };
59 | C9A7440514D826E4003E2DBA /* StatecCodeStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A7440414D826E3003E2DBA /* StatecCodeStatement.m */; };
60 | C9A7440814D82830003E2DBA /* StatecStatementGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A7440714D8282F003E2DBA /* StatecStatementGroup.m */; };
61 | C9A7440B14D82897003E2DBA /* StatecStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = C9A7440A14D82897003E2DBA /* StatecStatement.m */; };
62 | C9ED4A9414DACD7D0044BE00 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9ED4A9314DACD7D0044BE00 /* Cocoa.framework */; };
63 | C9ED4A9E14DACD7D0044BE00 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C9ED4A9C14DACD7D0044BE00 /* InfoPlist.strings */; };
64 | C9ED4AA014DACD7D0044BE00 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ED4A9F14DACD7D0044BE00 /* main.m */; };
65 | C9ED4AA414DACD7D0044BE00 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = C9ED4AA214DACD7D0044BE00 /* Credits.rtf */; };
66 | C9ED4AA714DACD7D0044BE00 /* StatecAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ED4AA614DACD7D0044BE00 /* StatecAppDelegate.m */; };
67 | C9ED4AAA14DACD7D0044BE00 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = C9ED4AA814DACD7D0044BE00 /* MainMenu.xib */; };
68 | C9ED4ABE14DAF2620044BE00 /* NSString+StatecExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ED4ABD14DAF2620044BE00 /* NSString+StatecExtensions.m */; };
69 | C9ED4AC414DB14C60044BE00 /* StatecGVBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ED4AC314DB14C60044BE00 /* StatecGVBuilder.m */; };
70 | C9ED4ACA14DB25090044BE00 /* StatecHTMLBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ED4AC914DB25090044BE00 /* StatecHTMLBuilder.m */; };
71 | /* End PBXBuildFile section */
72 |
73 | /* Begin PBXContainerItemProxy section */
74 | C9ED4AAF14DACD8C0044BE00 /* PBXContainerItemProxy */ = {
75 | isa = PBXContainerItemProxy;
76 | containerPortal = C9A7439C14D6ECDE003E2DBA /* Project object */;
77 | proxyType = 1;
78 | remoteGlobalIDString = C9A743A414D6ECDE003E2DBA;
79 | remoteInfo = Statec;
80 | };
81 | /* End PBXContainerItemProxy section */
82 |
83 | /* Begin PBXCopyFilesBuildPhase section */
84 | C9A743A314D6ECDE003E2DBA /* CopyFiles */ = {
85 | isa = PBXCopyFilesBuildPhase;
86 | buildActionMask = 2147483647;
87 | dstPath = /usr/share/man/man1/;
88 | dstSubfolderSpec = 0;
89 | files = (
90 | C9A743B114D6ECDE003E2DBA /* Statec.1 in CopyFiles */,
91 | );
92 | runOnlyForDeploymentPostprocessing = 1;
93 | };
94 | C9A743B914D6ECF9003E2DBA /* Copy Frameworks */ = {
95 | isa = PBXCopyFilesBuildPhase;
96 | buildActionMask = 2147483647;
97 | dstPath = "";
98 | dstSubfolderSpec = 10;
99 | files = (
100 | );
101 | name = "Copy Frameworks";
102 | runOnlyForDeploymentPostprocessing = 0;
103 | };
104 | C9ED4AB114DACDC40044BE00 /* Copy Frameworks */ = {
105 | isa = PBXCopyFilesBuildPhase;
106 | buildActionMask = 2147483647;
107 | dstPath = "";
108 | dstSubfolderSpec = 10;
109 | files = (
110 | );
111 | name = "Copy Frameworks";
112 | runOnlyForDeploymentPostprocessing = 0;
113 | };
114 | C9ED4AB314DACDE60044BE00 /* CopyFiles */ = {
115 | isa = PBXCopyFilesBuildPhase;
116 | buildActionMask = 2147483647;
117 | dstPath = "";
118 | dstSubfolderSpec = 7;
119 | files = (
120 | );
121 | runOnlyForDeploymentPostprocessing = 0;
122 | };
123 | /* End PBXCopyFilesBuildPhase section */
124 |
125 | /* Begin PBXFileReference section */
126 | C94349861503983000705EB0 /* CoreParse.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreParse.framework; path = Library/Frameworks/CoreParse.framework; sourceTree = SDKROOT; };
127 | C98F6BCF14D844520019E817 /* StatecConditionalStatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecConditionalStatement.h; path = Builder/StatecConditionalStatement.h; sourceTree = ""; };
128 | C98F6BD014D844530019E817 /* StatecConditionalStatement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecConditionalStatement.m; path = Builder/StatecConditionalStatement.m; sourceTree = ""; };
129 | C9A743A514D6ECDE003E2DBA /* Statec */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Statec; sourceTree = BUILT_PRODUCTS_DIR; };
130 | C9A743A914D6ECDE003E2DBA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
131 | C9A743AC14D6ECDE003E2DBA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
132 | C9A743AF14D6ECDE003E2DBA /* Statec-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Statec-Prefix.pch"; sourceTree = ""; };
133 | C9A743B014D6ECDE003E2DBA /* Statec.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = Statec.1; sourceTree = ""; };
134 | C9A743BD14D6ED3A003E2DBA /* StatecParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecParser.h; path = Parser/StatecParser.h; sourceTree = ""; };
135 | C9A743BE14D6ED3A003E2DBA /* StatecParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecParser.m; path = Parser/StatecParser.m; sourceTree = ""; };
136 | C9A743C614D6EE25003E2DBA /* StatecClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecClass.h; path = Builder/StatecClass.h; sourceTree = ""; };
137 | C9A743C714D6EE25003E2DBA /* StatecClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecClass.m; path = Builder/StatecClass.m; sourceTree = ""; };
138 | C9A743CC14D6F178003E2DBA /* StatecMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecMethod.h; path = Builder/StatecMethod.h; sourceTree = ""; };
139 | C9A743CD14D6F178003E2DBA /* StatecMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecMethod.m; path = Builder/StatecMethod.m; sourceTree = ""; };
140 | C9A743CF14D6F189003E2DBA /* StatecVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecVariable.h; path = Builder/StatecVariable.h; sourceTree = ""; };
141 | C9A743D014D6F189003E2DBA /* StatecVariable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecVariable.m; path = Builder/StatecVariable.m; sourceTree = ""; };
142 | C9A743D214D6F210003E2DBA /* StatecProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecProperty.h; path = Builder/StatecProperty.h; sourceTree = ""; };
143 | C9A743D314D6F210003E2DBA /* StatecProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecProperty.m; path = Builder/StatecProperty.m; sourceTree = ""; };
144 | C9A743D514D70BB0003E2DBA /* Statec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Statec.h; sourceTree = ""; };
145 | C9A743D614D7326E003E2DBA /* StatecArgument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecArgument.h; path = Builder/StatecArgument.h; sourceTree = ""; };
146 | C9A743D714D7326E003E2DBA /* StatecArgument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecArgument.m; path = Builder/StatecArgument.m; sourceTree = ""; };
147 | C9A743DE14D765AC003E2DBA /* StatecMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecMachine.h; path = Parser/StatecMachine.h; sourceTree = ""; };
148 | C9A743DF14D765AC003E2DBA /* StatecMachine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecMachine.m; path = Parser/StatecMachine.m; sourceTree = ""; };
149 | C9A743E114D76BF2003E2DBA /* StatecInitial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecInitial.h; path = Parser/StatecInitial.h; sourceTree = ""; };
150 | C9A743E214D76BF2003E2DBA /* StatecInitial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecInitial.m; path = Parser/StatecInitial.m; sourceTree = ""; };
151 | C9A743E414D76C02003E2DBA /* StatecState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecState.h; path = Parser/StatecState.h; sourceTree = ""; };
152 | C9A743E514D76C02003E2DBA /* StatecState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecState.m; path = Parser/StatecState.m; sourceTree = ""; };
153 | C9A743E714D76C13003E2DBA /* StatecEnter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecEnter.h; path = Parser/StatecEnter.h; sourceTree = ""; };
154 | C9A743E814D76C13003E2DBA /* StatecEnter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecEnter.m; path = Parser/StatecEnter.m; sourceTree = ""; };
155 | C9A743EA14D76C22003E2DBA /* StatecExit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecExit.h; path = Parser/StatecExit.h; sourceTree = ""; };
156 | C9A743EB14D76C22003E2DBA /* StatecExit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecExit.m; path = Parser/StatecExit.m; sourceTree = ""; };
157 | C9A743ED14D76C2E003E2DBA /* StatecEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StatecEvent.h; sourceTree = ""; };
158 | C9A743EE14D76C2E003E2DBA /* StatecEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StatecEvent.m; sourceTree = ""; };
159 | C9A743F114D774FC003E2DBA /* StatecCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecCompiler.h; path = Compiler/StatecCompiler.h; sourceTree = ""; };
160 | C9A743F214D774FC003E2DBA /* StatecCompiler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecCompiler.m; path = Compiler/StatecCompiler.m; sourceTree = ""; };
161 | C9A743F414D77826003E2DBA /* StatecTransition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecTransition.h; path = Parser/StatecTransition.h; sourceTree = ""; };
162 | C9A743F514D77826003E2DBA /* StatecTransition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecTransition.m; path = Parser/StatecTransition.m; sourceTree = ""; };
163 | C9A743F714D802E1003E2DBA /* StatecTypedef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecTypedef.h; path = Builder/StatecTypedef.h; sourceTree = ""; };
164 | C9A743F814D802E1003E2DBA /* StatecTypedef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecTypedef.m; path = Builder/StatecTypedef.m; sourceTree = ""; };
165 | C9A743FA14D805C6003E2DBA /* StatecEnumeration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecEnumeration.h; path = Builder/StatecEnumeration.h; sourceTree = ""; };
166 | C9A743FB14D805C6003E2DBA /* StatecEnumeration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecEnumeration.m; path = Builder/StatecEnumeration.m; sourceTree = ""; };
167 | C9A743FD14D807A1003E2DBA /* StatecType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecType.h; path = Builder/StatecType.h; sourceTree = ""; };
168 | C9A743FE14D807A1003E2DBA /* StatecType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecType.m; path = Builder/StatecType.m; sourceTree = ""; };
169 | C9A7440014D8096A003E2DBA /* StatecCompilationUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecCompilationUnit.h; path = Builder/StatecCompilationUnit.h; sourceTree = ""; };
170 | C9A7440114D8096A003E2DBA /* StatecCompilationUnit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecCompilationUnit.m; path = Builder/StatecCompilationUnit.m; sourceTree = ""; };
171 | C9A7440314D826E2003E2DBA /* StatecCodeStatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecCodeStatement.h; path = Builder/StatecCodeStatement.h; sourceTree = ""; };
172 | C9A7440414D826E3003E2DBA /* StatecCodeStatement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecCodeStatement.m; path = Builder/StatecCodeStatement.m; sourceTree = ""; };
173 | C9A7440614D8282E003E2DBA /* StatecStatementGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecStatementGroup.h; path = Builder/StatecStatementGroup.h; sourceTree = ""; };
174 | C9A7440714D8282F003E2DBA /* StatecStatementGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecStatementGroup.m; path = Builder/StatecStatementGroup.m; sourceTree = ""; };
175 | C9A7440914D82896003E2DBA /* StatecStatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecStatement.h; path = Builder/StatecStatement.h; sourceTree = ""; };
176 | C9A7440A14D82897003E2DBA /* StatecStatement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecStatement.m; path = Builder/StatecStatement.m; sourceTree = ""; };
177 | C9ED4A9114DACD7D0044BE00 /* StatecRunner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StatecRunner.app; sourceTree = BUILT_PRODUCTS_DIR; };
178 | C9ED4A9314DACD7D0044BE00 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
179 | C9ED4A9614DACD7D0044BE00 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
180 | C9ED4A9714DACD7D0044BE00 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
181 | C9ED4A9814DACD7D0044BE00 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
182 | C9ED4A9B14DACD7D0044BE00 /* StatecRunner-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "StatecRunner-Info.plist"; sourceTree = ""; };
183 | C9ED4A9D14DACD7D0044BE00 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
184 | C9ED4A9F14DACD7D0044BE00 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
185 | C9ED4AA114DACD7D0044BE00 /* StatecRunner-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StatecRunner-Prefix.pch"; sourceTree = ""; };
186 | C9ED4AA314DACD7D0044BE00 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; };
187 | C9ED4AA514DACD7D0044BE00 /* StatecAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StatecAppDelegate.h; sourceTree = ""; };
188 | C9ED4AA614DACD7D0044BE00 /* StatecAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StatecAppDelegate.m; sourceTree = ""; };
189 | C9ED4AA914DACD7D0044BE00 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; };
190 | C9ED4ABC14DAF2620044BE00 /* NSString+StatecExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+StatecExtensions.h"; path = "Categories/NSString+StatecExtensions.h"; sourceTree = ""; };
191 | C9ED4ABD14DAF2620044BE00 /* NSString+StatecExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+StatecExtensions.m"; path = "Categories/NSString+StatecExtensions.m"; sourceTree = ""; };
192 | C9ED4AC214DB14C60044BE00 /* StatecGVBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecGVBuilder.h; path = Builder/StatecGVBuilder.h; sourceTree = ""; };
193 | C9ED4AC314DB14C60044BE00 /* StatecGVBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecGVBuilder.m; path = Builder/StatecGVBuilder.m; sourceTree = ""; };
194 | C9ED4AC814DB25090044BE00 /* StatecHTMLBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StatecHTMLBuilder.h; path = Builder/StatecHTMLBuilder.h; sourceTree = ""; };
195 | C9ED4AC914DB25090044BE00 /* StatecHTMLBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = StatecHTMLBuilder.m; path = Builder/StatecHTMLBuilder.m; sourceTree = ""; };
196 | /* End PBXFileReference section */
197 |
198 | /* Begin PBXFrameworksBuildPhase section */
199 | C9A743A214D6ECDE003E2DBA /* Frameworks */ = {
200 | isa = PBXFrameworksBuildPhase;
201 | buildActionMask = 2147483647;
202 | files = (
203 | C94349881503983600705EB0 /* CoreParse.framework in Frameworks */,
204 | C9A743AA14D6ECDE003E2DBA /* Foundation.framework in Frameworks */,
205 | );
206 | runOnlyForDeploymentPostprocessing = 0;
207 | };
208 | C9ED4A8E14DACD7D0044BE00 /* Frameworks */ = {
209 | isa = PBXFrameworksBuildPhase;
210 | buildActionMask = 2147483647;
211 | files = (
212 | C94349871503983000705EB0 /* CoreParse.framework in Frameworks */,
213 | C9ED4A9414DACD7D0044BE00 /* Cocoa.framework in Frameworks */,
214 | );
215 | runOnlyForDeploymentPostprocessing = 0;
216 | };
217 | /* End PBXFrameworksBuildPhase section */
218 |
219 | /* Begin PBXGroup section */
220 | C9A7439A14D6ECDE003E2DBA = {
221 | isa = PBXGroup;
222 | children = (
223 | C94349861503983000705EB0 /* CoreParse.framework */,
224 | C9A743AB14D6ECDE003E2DBA /* Statec */,
225 | C9ED4A9914DACD7D0044BE00 /* StatecRunner */,
226 | C9A743A814D6ECDE003E2DBA /* Frameworks */,
227 | C9A743A614D6ECDE003E2DBA /* Products */,
228 | );
229 | sourceTree = "";
230 | };
231 | C9A743A614D6ECDE003E2DBA /* Products */ = {
232 | isa = PBXGroup;
233 | children = (
234 | C9A743A514D6ECDE003E2DBA /* Statec */,
235 | C9ED4A9114DACD7D0044BE00 /* StatecRunner.app */,
236 | );
237 | name = Products;
238 | sourceTree = "";
239 | };
240 | C9A743A814D6ECDE003E2DBA /* Frameworks */ = {
241 | isa = PBXGroup;
242 | children = (
243 | C9A743A914D6ECDE003E2DBA /* Foundation.framework */,
244 | C9ED4A9314DACD7D0044BE00 /* Cocoa.framework */,
245 | C9ED4A9514DACD7D0044BE00 /* Other Frameworks */,
246 | );
247 | name = Frameworks;
248 | sourceTree = "";
249 | };
250 | C9A743AB14D6ECDE003E2DBA /* Statec */ = {
251 | isa = PBXGroup;
252 | children = (
253 | C9ED4ABB14DAF2470044BE00 /* Categories */,
254 | C9A743F014D774E2003E2DBA /* Compiler */,
255 | C9A743BC14D6ED14003E2DBA /* Builder */,
256 | C9A743BB14D6ED0C003E2DBA /* Parser */,
257 | C9A743AC14D6ECDE003E2DBA /* main.m */,
258 | C9A743B014D6ECDE003E2DBA /* Statec.1 */,
259 | C9A743AE14D6ECDE003E2DBA /* Supporting Files */,
260 | C9A743D514D70BB0003E2DBA /* Statec.h */,
261 | );
262 | path = Statec;
263 | sourceTree = "";
264 | };
265 | C9A743AE14D6ECDE003E2DBA /* Supporting Files */ = {
266 | isa = PBXGroup;
267 | children = (
268 | C9A743AF14D6ECDE003E2DBA /* Statec-Prefix.pch */,
269 | );
270 | name = "Supporting Files";
271 | sourceTree = "";
272 | };
273 | C9A743BB14D6ED0C003E2DBA /* Parser */ = {
274 | isa = PBXGroup;
275 | children = (
276 | C9A743BD14D6ED3A003E2DBA /* StatecParser.h */,
277 | C9A743BE14D6ED3A003E2DBA /* StatecParser.m */,
278 | C9A743DE14D765AC003E2DBA /* StatecMachine.h */,
279 | C9A743DF14D765AC003E2DBA /* StatecMachine.m */,
280 | C9A743E114D76BF2003E2DBA /* StatecInitial.h */,
281 | C9A743E214D76BF2003E2DBA /* StatecInitial.m */,
282 | C9A743E414D76C02003E2DBA /* StatecState.h */,
283 | C9A743E514D76C02003E2DBA /* StatecState.m */,
284 | C9A743E714D76C13003E2DBA /* StatecEnter.h */,
285 | C9A743E814D76C13003E2DBA /* StatecEnter.m */,
286 | C9A743EA14D76C22003E2DBA /* StatecExit.h */,
287 | C9A743EB14D76C22003E2DBA /* StatecExit.m */,
288 | C9A743ED14D76C2E003E2DBA /* StatecEvent.h */,
289 | C9A743EE14D76C2E003E2DBA /* StatecEvent.m */,
290 | C9A743F414D77826003E2DBA /* StatecTransition.h */,
291 | C9A743F514D77826003E2DBA /* StatecTransition.m */,
292 | );
293 | name = Parser;
294 | sourceTree = "";
295 | };
296 | C9A743BC14D6ED14003E2DBA /* Builder */ = {
297 | isa = PBXGroup;
298 | children = (
299 | C9A743C614D6EE25003E2DBA /* StatecClass.h */,
300 | C9A743C714D6EE25003E2DBA /* StatecClass.m */,
301 | C9A743CC14D6F178003E2DBA /* StatecMethod.h */,
302 | C9A743CD14D6F178003E2DBA /* StatecMethod.m */,
303 | C9A743CF14D6F189003E2DBA /* StatecVariable.h */,
304 | C9A743D014D6F189003E2DBA /* StatecVariable.m */,
305 | C9A743D214D6F210003E2DBA /* StatecProperty.h */,
306 | C9A743D314D6F210003E2DBA /* StatecProperty.m */,
307 | C9A743D614D7326E003E2DBA /* StatecArgument.h */,
308 | C9A743D714D7326E003E2DBA /* StatecArgument.m */,
309 | C9A743F714D802E1003E2DBA /* StatecTypedef.h */,
310 | C9A743F814D802E1003E2DBA /* StatecTypedef.m */,
311 | C9A743FA14D805C6003E2DBA /* StatecEnumeration.h */,
312 | C9A743FB14D805C6003E2DBA /* StatecEnumeration.m */,
313 | C9A743FD14D807A1003E2DBA /* StatecType.h */,
314 | C9A743FE14D807A1003E2DBA /* StatecType.m */,
315 | C9A7440014D8096A003E2DBA /* StatecCompilationUnit.h */,
316 | C9A7440114D8096A003E2DBA /* StatecCompilationUnit.m */,
317 | C9A7440314D826E2003E2DBA /* StatecCodeStatement.h */,
318 | C9A7440414D826E3003E2DBA /* StatecCodeStatement.m */,
319 | C9A7440614D8282E003E2DBA /* StatecStatementGroup.h */,
320 | C9A7440714D8282F003E2DBA /* StatecStatementGroup.m */,
321 | C9A7440914D82896003E2DBA /* StatecStatement.h */,
322 | C9A7440A14D82897003E2DBA /* StatecStatement.m */,
323 | C98F6BCF14D844520019E817 /* StatecConditionalStatement.h */,
324 | C98F6BD014D844530019E817 /* StatecConditionalStatement.m */,
325 | C9ED4AC214DB14C60044BE00 /* StatecGVBuilder.h */,
326 | C9ED4AC314DB14C60044BE00 /* StatecGVBuilder.m */,
327 | C9ED4AC814DB25090044BE00 /* StatecHTMLBuilder.h */,
328 | C9ED4AC914DB25090044BE00 /* StatecHTMLBuilder.m */,
329 | );
330 | name = Builder;
331 | sourceTree = "";
332 | };
333 | C9A743F014D774E2003E2DBA /* Compiler */ = {
334 | isa = PBXGroup;
335 | children = (
336 | C9A743F114D774FC003E2DBA /* StatecCompiler.h */,
337 | C9A743F214D774FC003E2DBA /* StatecCompiler.m */,
338 | );
339 | name = Compiler;
340 | sourceTree = "";
341 | };
342 | C9ED4A9514DACD7D0044BE00 /* Other Frameworks */ = {
343 | isa = PBXGroup;
344 | children = (
345 | C9ED4A9614DACD7D0044BE00 /* AppKit.framework */,
346 | C9ED4A9714DACD7D0044BE00 /* CoreData.framework */,
347 | C9ED4A9814DACD7D0044BE00 /* Foundation.framework */,
348 | );
349 | name = "Other Frameworks";
350 | sourceTree = "";
351 | };
352 | C9ED4A9914DACD7D0044BE00 /* StatecRunner */ = {
353 | isa = PBXGroup;
354 | children = (
355 | C9ED4AA514DACD7D0044BE00 /* StatecAppDelegate.h */,
356 | C9ED4AA614DACD7D0044BE00 /* StatecAppDelegate.m */,
357 | C9ED4AA814DACD7D0044BE00 /* MainMenu.xib */,
358 | C9ED4A9A14DACD7D0044BE00 /* Supporting Files */,
359 | );
360 | path = StatecRunner;
361 | sourceTree = "";
362 | };
363 | C9ED4A9A14DACD7D0044BE00 /* Supporting Files */ = {
364 | isa = PBXGroup;
365 | children = (
366 | C9ED4A9B14DACD7D0044BE00 /* StatecRunner-Info.plist */,
367 | C9ED4A9C14DACD7D0044BE00 /* InfoPlist.strings */,
368 | C9ED4A9F14DACD7D0044BE00 /* main.m */,
369 | C9ED4AA114DACD7D0044BE00 /* StatecRunner-Prefix.pch */,
370 | C9ED4AA214DACD7D0044BE00 /* Credits.rtf */,
371 | );
372 | name = "Supporting Files";
373 | sourceTree = "";
374 | };
375 | C9ED4ABB14DAF2470044BE00 /* Categories */ = {
376 | isa = PBXGroup;
377 | children = (
378 | C9ED4ABC14DAF2620044BE00 /* NSString+StatecExtensions.h */,
379 | C9ED4ABD14DAF2620044BE00 /* NSString+StatecExtensions.m */,
380 | );
381 | name = Categories;
382 | sourceTree = "";
383 | };
384 | /* End PBXGroup section */
385 |
386 | /* Begin PBXNativeTarget section */
387 | C9A743A414D6ECDE003E2DBA /* Statec */ = {
388 | isa = PBXNativeTarget;
389 | buildConfigurationList = C9A743B414D6ECDE003E2DBA /* Build configuration list for PBXNativeTarget "Statec" */;
390 | buildPhases = (
391 | C9A743A114D6ECDE003E2DBA /* Sources */,
392 | C9A743A214D6ECDE003E2DBA /* Frameworks */,
393 | C9A743A314D6ECDE003E2DBA /* CopyFiles */,
394 | C9A743B914D6ECF9003E2DBA /* Copy Frameworks */,
395 | );
396 | buildRules = (
397 | );
398 | dependencies = (
399 | );
400 | name = Statec;
401 | productName = Statec;
402 | productReference = C9A743A514D6ECDE003E2DBA /* Statec */;
403 | productType = "com.apple.product-type.tool";
404 | };
405 | C9ED4A9014DACD7D0044BE00 /* StatecRunner */ = {
406 | isa = PBXNativeTarget;
407 | buildConfigurationList = C9ED4AAD14DACD7D0044BE00 /* Build configuration list for PBXNativeTarget "StatecRunner" */;
408 | buildPhases = (
409 | C9ED4A8D14DACD7D0044BE00 /* Sources */,
410 | C9ED4A8E14DACD7D0044BE00 /* Frameworks */,
411 | C9ED4A8F14DACD7D0044BE00 /* Resources */,
412 | C9ED4AB114DACDC40044BE00 /* Copy Frameworks */,
413 | C9ED4AB314DACDE60044BE00 /* CopyFiles */,
414 | );
415 | buildRules = (
416 | );
417 | dependencies = (
418 | C9ED4AB014DACD8C0044BE00 /* PBXTargetDependency */,
419 | );
420 | name = StatecRunner;
421 | productName = StatecRunner;
422 | productReference = C9ED4A9114DACD7D0044BE00 /* StatecRunner.app */;
423 | productType = "com.apple.product-type.application";
424 | };
425 | /* End PBXNativeTarget section */
426 |
427 | /* Begin PBXProject section */
428 | C9A7439C14D6ECDE003E2DBA /* Project object */ = {
429 | isa = PBXProject;
430 | attributes = {
431 | LastUpgradeCheck = 0430;
432 | };
433 | buildConfigurationList = C9A7439F14D6ECDE003E2DBA /* Build configuration list for PBXProject "Statec" */;
434 | compatibilityVersion = "Xcode 3.2";
435 | developmentRegion = English;
436 | hasScannedForEncodings = 0;
437 | knownRegions = (
438 | en,
439 | );
440 | mainGroup = C9A7439A14D6ECDE003E2DBA;
441 | productRefGroup = C9A743A614D6ECDE003E2DBA /* Products */;
442 | projectDirPath = "";
443 | projectRoot = "";
444 | targets = (
445 | C9ED4A9014DACD7D0044BE00 /* StatecRunner */,
446 | C9A743A414D6ECDE003E2DBA /* Statec */,
447 | );
448 | };
449 | /* End PBXProject section */
450 |
451 | /* Begin PBXResourcesBuildPhase section */
452 | C9ED4A8F14DACD7D0044BE00 /* Resources */ = {
453 | isa = PBXResourcesBuildPhase;
454 | buildActionMask = 2147483647;
455 | files = (
456 | C9ED4A9E14DACD7D0044BE00 /* InfoPlist.strings in Resources */,
457 | C9ED4AA414DACD7D0044BE00 /* Credits.rtf in Resources */,
458 | C9ED4AAA14DACD7D0044BE00 /* MainMenu.xib in Resources */,
459 | );
460 | runOnlyForDeploymentPostprocessing = 0;
461 | };
462 | /* End PBXResourcesBuildPhase section */
463 |
464 | /* Begin PBXSourcesBuildPhase section */
465 | C9A743A114D6ECDE003E2DBA /* Sources */ = {
466 | isa = PBXSourcesBuildPhase;
467 | buildActionMask = 2147483647;
468 | files = (
469 | C9A743AD14D6ECDE003E2DBA /* main.m in Sources */,
470 | C9A743BF14D6ED3A003E2DBA /* StatecParser.m in Sources */,
471 | C9A743C814D6EE25003E2DBA /* StatecClass.m in Sources */,
472 | C9A743CE14D6F178003E2DBA /* StatecMethod.m in Sources */,
473 | C9A743D114D6F189003E2DBA /* StatecVariable.m in Sources */,
474 | C9A743D414D6F210003E2DBA /* StatecProperty.m in Sources */,
475 | C9A743D814D7326E003E2DBA /* StatecArgument.m in Sources */,
476 | C9A743E014D765AC003E2DBA /* StatecMachine.m in Sources */,
477 | C9A743E314D76BF2003E2DBA /* StatecInitial.m in Sources */,
478 | C9A743E614D76C02003E2DBA /* StatecState.m in Sources */,
479 | C9A743E914D76C13003E2DBA /* StatecEnter.m in Sources */,
480 | C9A743EC14D76C22003E2DBA /* StatecExit.m in Sources */,
481 | C9A743EF14D76C2F003E2DBA /* StatecEvent.m in Sources */,
482 | C9A743F314D774FC003E2DBA /* StatecCompiler.m in Sources */,
483 | C9A743F614D77827003E2DBA /* StatecTransition.m in Sources */,
484 | C9A743F914D802E1003E2DBA /* StatecTypedef.m in Sources */,
485 | C9A743FC14D805C7003E2DBA /* StatecEnumeration.m in Sources */,
486 | C9A743FF14D807A2003E2DBA /* StatecType.m in Sources */,
487 | C9A7440214D8096B003E2DBA /* StatecCompilationUnit.m in Sources */,
488 | C9A7440514D826E4003E2DBA /* StatecCodeStatement.m in Sources */,
489 | C9A7440814D82830003E2DBA /* StatecStatementGroup.m in Sources */,
490 | C9A7440B14D82897003E2DBA /* StatecStatement.m in Sources */,
491 | C98F6BD114D844530019E817 /* StatecConditionalStatement.m in Sources */,
492 | C9ED4ABE14DAF2620044BE00 /* NSString+StatecExtensions.m in Sources */,
493 | C9ED4AC414DB14C60044BE00 /* StatecGVBuilder.m in Sources */,
494 | C9ED4ACA14DB25090044BE00 /* StatecHTMLBuilder.m in Sources */,
495 | );
496 | runOnlyForDeploymentPostprocessing = 0;
497 | };
498 | C9ED4A8D14DACD7D0044BE00 /* Sources */ = {
499 | isa = PBXSourcesBuildPhase;
500 | buildActionMask = 2147483647;
501 | files = (
502 | C9ED4AA014DACD7D0044BE00 /* main.m in Sources */,
503 | C9ED4AA714DACD7D0044BE00 /* StatecAppDelegate.m in Sources */,
504 | C93DC584150296B400007F09 /* StatecCompiler.m in Sources */,
505 | C93DC5861502971200007F09 /* StatecParser.m in Sources */,
506 | C93DC5871502972A00007F09 /* StatecClass.m in Sources */,
507 | C93DC5881502972A00007F09 /* StatecMethod.m in Sources */,
508 | C93DC5891502972A00007F09 /* StatecVariable.m in Sources */,
509 | C93DC58A1502972A00007F09 /* StatecProperty.m in Sources */,
510 | C93DC58B1502972A00007F09 /* StatecArgument.m in Sources */,
511 | C93DC58C1502972A00007F09 /* StatecTypedef.m in Sources */,
512 | C93DC58D1502972A00007F09 /* StatecEnumeration.m in Sources */,
513 | C93DC58E1502972A00007F09 /* StatecType.m in Sources */,
514 | C93DC58F1502972A00007F09 /* StatecCompilationUnit.m in Sources */,
515 | C93DC5901502972A00007F09 /* StatecCodeStatement.m in Sources */,
516 | C93DC5911502972A00007F09 /* StatecStatementGroup.m in Sources */,
517 | C93DC5921502972A00007F09 /* StatecStatement.m in Sources */,
518 | C93DC5931502972A00007F09 /* StatecConditionalStatement.m in Sources */,
519 | C93DC5941502972A00007F09 /* StatecGVBuilder.m in Sources */,
520 | C93DC5951502972A00007F09 /* StatecHTMLBuilder.m in Sources */,
521 | C93DC5961502973400007F09 /* NSString+StatecExtensions.m in Sources */,
522 | C93DC5971502974100007F09 /* StatecMachine.m in Sources */,
523 | C93DC5981502974100007F09 /* StatecInitial.m in Sources */,
524 | C93DC5991502974100007F09 /* StatecState.m in Sources */,
525 | C93DC59A1502974100007F09 /* StatecEnter.m in Sources */,
526 | C93DC59B1502974100007F09 /* StatecExit.m in Sources */,
527 | C93DC59C1502974100007F09 /* StatecEvent.m in Sources */,
528 | C93DC59D1502974100007F09 /* StatecTransition.m in Sources */,
529 | );
530 | runOnlyForDeploymentPostprocessing = 0;
531 | };
532 | /* End PBXSourcesBuildPhase section */
533 |
534 | /* Begin PBXTargetDependency section */
535 | C9ED4AB014DACD8C0044BE00 /* PBXTargetDependency */ = {
536 | isa = PBXTargetDependency;
537 | target = C9A743A414D6ECDE003E2DBA /* Statec */;
538 | targetProxy = C9ED4AAF14DACD8C0044BE00 /* PBXContainerItemProxy */;
539 | };
540 | /* End PBXTargetDependency section */
541 |
542 | /* Begin PBXVariantGroup section */
543 | C9ED4A9C14DACD7D0044BE00 /* InfoPlist.strings */ = {
544 | isa = PBXVariantGroup;
545 | children = (
546 | C9ED4A9D14DACD7D0044BE00 /* en */,
547 | );
548 | name = InfoPlist.strings;
549 | sourceTree = "";
550 | };
551 | C9ED4AA214DACD7D0044BE00 /* Credits.rtf */ = {
552 | isa = PBXVariantGroup;
553 | children = (
554 | C9ED4AA314DACD7D0044BE00 /* en */,
555 | );
556 | name = Credits.rtf;
557 | sourceTree = "";
558 | };
559 | C9ED4AA814DACD7D0044BE00 /* MainMenu.xib */ = {
560 | isa = PBXVariantGroup;
561 | children = (
562 | C9ED4AA914DACD7D0044BE00 /* en */,
563 | );
564 | name = MainMenu.xib;
565 | sourceTree = "";
566 | };
567 | /* End PBXVariantGroup section */
568 |
569 | /* Begin XCBuildConfiguration section */
570 | C9A743B214D6ECDE003E2DBA /* Debug */ = {
571 | isa = XCBuildConfiguration;
572 | buildSettings = {
573 | ALWAYS_SEARCH_USER_PATHS = NO;
574 | ARCHS = "$(ARCHS_STANDARD_64_BIT)";
575 | CLANG_ENABLE_OBJC_ARC = YES;
576 | COPY_PHASE_STRIP = NO;
577 | GCC_C_LANGUAGE_STANDARD = gnu99;
578 | GCC_DYNAMIC_NO_PIC = NO;
579 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
580 | GCC_OPTIMIZATION_LEVEL = 0;
581 | GCC_PREPROCESSOR_DEFINITIONS = (
582 | "DEBUG=1",
583 | "$(inherited)",
584 | );
585 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
586 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
587 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
588 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
589 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
590 | GCC_WARN_UNUSED_VARIABLE = YES;
591 | MACOSX_DEPLOYMENT_TARGET = 10.7;
592 | ONLY_ACTIVE_ARCH = YES;
593 | SDKROOT = macosx;
594 | };
595 | name = Debug;
596 | };
597 | C9A743B314D6ECDE003E2DBA /* Release */ = {
598 | isa = XCBuildConfiguration;
599 | buildSettings = {
600 | ALWAYS_SEARCH_USER_PATHS = NO;
601 | ARCHS = "$(ARCHS_STANDARD_64_BIT)";
602 | CLANG_ENABLE_OBJC_ARC = YES;
603 | COPY_PHASE_STRIP = YES;
604 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
605 | GCC_C_LANGUAGE_STANDARD = gnu99;
606 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
607 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
608 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
609 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
610 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
611 | GCC_WARN_UNUSED_VARIABLE = YES;
612 | MACOSX_DEPLOYMENT_TARGET = 10.7;
613 | SDKROOT = macosx;
614 | };
615 | name = Release;
616 | };
617 | C9A743B514D6ECDE003E2DBA /* Debug */ = {
618 | isa = XCBuildConfiguration;
619 | buildSettings = {
620 | FRAMEWORK_SEARCH_PATHS = (
621 | "$(inherited)",
622 | "\"$(SRCROOT)\"",
623 | );
624 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
625 | GCC_PREFIX_HEADER = "Statec/Statec-Prefix.pch";
626 | PRODUCT_NAME = "$(TARGET_NAME)";
627 | };
628 | name = Debug;
629 | };
630 | C9A743B614D6ECDE003E2DBA /* Release */ = {
631 | isa = XCBuildConfiguration;
632 | buildSettings = {
633 | FRAMEWORK_SEARCH_PATHS = (
634 | "$(inherited)",
635 | "\"$(SRCROOT)\"",
636 | );
637 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
638 | GCC_PREFIX_HEADER = "Statec/Statec-Prefix.pch";
639 | PRODUCT_NAME = "$(TARGET_NAME)";
640 | };
641 | name = Release;
642 | };
643 | C9ED4AAB14DACD7D0044BE00 /* Debug */ = {
644 | isa = XCBuildConfiguration;
645 | buildSettings = {
646 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
647 | GCC_PREFIX_HEADER = "StatecRunner/StatecRunner-Prefix.pch";
648 | INFOPLIST_FILE = "StatecRunner/StatecRunner-Info.plist";
649 | PRODUCT_NAME = "$(TARGET_NAME)";
650 | WRAPPER_EXTENSION = app;
651 | };
652 | name = Debug;
653 | };
654 | C9ED4AAC14DACD7D0044BE00 /* Release */ = {
655 | isa = XCBuildConfiguration;
656 | buildSettings = {
657 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
658 | GCC_PREFIX_HEADER = "StatecRunner/StatecRunner-Prefix.pch";
659 | INFOPLIST_FILE = "StatecRunner/StatecRunner-Info.plist";
660 | PRODUCT_NAME = "$(TARGET_NAME)";
661 | WRAPPER_EXTENSION = app;
662 | };
663 | name = Release;
664 | };
665 | /* End XCBuildConfiguration section */
666 |
667 | /* Begin XCConfigurationList section */
668 | C9A7439F14D6ECDE003E2DBA /* Build configuration list for PBXProject "Statec" */ = {
669 | isa = XCConfigurationList;
670 | buildConfigurations = (
671 | C9A743B214D6ECDE003E2DBA /* Debug */,
672 | C9A743B314D6ECDE003E2DBA /* Release */,
673 | );
674 | defaultConfigurationIsVisible = 0;
675 | defaultConfigurationName = Release;
676 | };
677 | C9A743B414D6ECDE003E2DBA /* Build configuration list for PBXNativeTarget "Statec" */ = {
678 | isa = XCConfigurationList;
679 | buildConfigurations = (
680 | C9A743B514D6ECDE003E2DBA /* Debug */,
681 | C9A743B614D6ECDE003E2DBA /* Release */,
682 | );
683 | defaultConfigurationIsVisible = 0;
684 | defaultConfigurationName = Release;
685 | };
686 | C9ED4AAD14DACD7D0044BE00 /* Build configuration list for PBXNativeTarget "StatecRunner" */ = {
687 | isa = XCConfigurationList;
688 | buildConfigurations = (
689 | C9ED4AAB14DACD7D0044BE00 /* Debug */,
690 | C9ED4AAC14DACD7D0044BE00 /* Release */,
691 | );
692 | defaultConfigurationIsVisible = 0;
693 | defaultConfigurationName = Release;
694 | };
695 | /* End XCConfigurationList section */
696 | };
697 | rootObject = C9A7439C14D6ECDE003E2DBA /* Project object */;
698 | }
699 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecArgument.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecArgument.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface StatecArgument : NSObject
12 |
13 | @property (strong) NSString *type;
14 | @property (strong) NSString *name;
15 |
16 | - (id)initWithType:(NSString *)type name:(NSString *)name;
17 |
18 | - (NSString *)argumentString;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecArgument.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecArgument.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecArgument.h"
10 |
11 | @implementation StatecArgument
12 |
13 | @synthesize type = _type;
14 | @synthesize name = _name;
15 |
16 | - (id)initWithType:(NSString *)type name:(NSString *)name {
17 | self = [super init];
18 | if( self ) {
19 | _type = type;
20 | _name = name;
21 | }
22 | return self;
23 | }
24 |
25 |
26 | - (NSString *)argumentString {
27 | return [NSString stringWithFormat:@"(%@)%@", [self type], [self name]];
28 | }
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecClass.h:
--------------------------------------------------------------------------------
1 | //
2 | // SFClassModel.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class StatecMethod;
12 | @class StatecVariable;
13 | @class StatecProperty;
14 |
15 | @interface StatecClass : NSObject
16 |
17 | @property (strong) NSString *name;
18 | @property (strong) StatecClass *baseClass;
19 |
20 | @property (strong) NSMutableArray *initializers;
21 | @property (strong) NSMutableArray *properties;
22 | @property (strong) NSMutableArray *variables;
23 | @property (strong) NSMutableArray *methods;
24 |
25 | @property (strong) NSMutableArray *classDeclarations;
26 | @property (strong) NSMutableArray *headerImports;
27 | @property (strong) NSMutableArray *classImports;
28 |
29 | - (id)initWithName:(NSString *)name;
30 | - (id)initWithname:(NSString *)name baseClass:(StatecClass *)baseClass;
31 |
32 | - (void)addVariable:(StatecVariable *)variable;
33 | - (void)addProperty:(StatecProperty *)property;
34 | - (void)addInitializer:(StatecMethod *)method;
35 | - (void)addMethod:(StatecMethod *)method;
36 | - (void)addMethods:(NSArray *)methods;
37 |
38 |
39 | - (NSString *)declarationString;
40 | - (NSString *)definitionString;
41 |
42 | - (NSString *)pointerType;
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecClass.m:
--------------------------------------------------------------------------------
1 | //
2 | // SFClassModel.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecClass.h"
10 |
11 | #import "StatecMethod.h"
12 | #import "StatecProperty.h"
13 | #import "StatecVariable.h"
14 |
15 | @implementation StatecClass
16 |
17 | @synthesize name = _name;
18 | @synthesize baseClass = _baseClass;
19 |
20 | @synthesize classDeclarations = _classDeclarations;
21 | @synthesize headerImports = _headerImports;
22 | @synthesize classImports = _classImports;
23 |
24 | @synthesize initializers = _initializers;
25 | @synthesize properties = _properties;
26 | @synthesize variables = _variables;
27 | @synthesize methods = _methods;
28 |
29 |
30 | - (id)initWithName:(NSString *)name {
31 | self = [super init];
32 | if( self ) {
33 | _name = name;
34 | _classDeclarations = [NSMutableArray array];
35 | _initializers = [NSMutableArray array];
36 | _properties = [NSMutableArray array];
37 | _variables = [NSMutableArray array];
38 | _methods = [NSMutableArray array];
39 | }
40 | return self;
41 | }
42 |
43 |
44 | - (id)initWithname:(NSString *)name baseClass:(StatecClass *)baseClass {
45 | self = [self initWithName:name];
46 | if( self ) {
47 | _baseClass = baseClass;
48 | }
49 | return self;
50 | }
51 |
52 |
53 | - (NSString *)pointerType {
54 | return [NSString stringWithFormat:@"%@*", [self name]];
55 | }
56 |
57 |
58 | - (void)addVariable:(StatecVariable *)variable {
59 | [[self variables] addObject:variable];
60 | }
61 |
62 |
63 | - (void)addProperty:(StatecProperty *)property {
64 | [[self properties] addObject:property];
65 | }
66 |
67 |
68 | - (void)addInitializer:(StatecMethod *)method {
69 | [[self initializers] addObject:method];
70 | }
71 |
72 |
73 | - (void)addMethod:(StatecMethod *)method {
74 | [[self methods] addObject:method];
75 | }
76 |
77 |
78 | - (void)addMethods:(NSArray *)methods {
79 | [[self methods] addObjectsFromArray:methods];
80 | }
81 |
82 |
83 | - (NSString *)baseClassName {
84 | if( [self baseClass] ) {
85 | return [[self baseClass] name];
86 | } else {
87 | return @"NSObject";
88 | }
89 | }
90 |
91 |
92 | - (NSString *)classMethodsDeclarationString {
93 | NSMutableString *content = [NSMutableString string];
94 |
95 | for( StatecMethod *method in [self methods] ) {
96 | if( [method isClassScope] ) {
97 | [content appendString:[method declarationString]];
98 | }
99 | }
100 |
101 | return content;
102 | }
103 |
104 |
105 | - (NSString *)classMethodsDefinitionString {
106 | NSMutableString *content = [NSMutableString string];
107 |
108 | for( StatecMethod *method in [self methods] ) {
109 | if( [method isClassScope] ) {
110 | [content appendString:[method definitionString]];
111 | }
112 | }
113 |
114 | return content;
115 | }
116 |
117 |
118 | - (NSString *)instanceVariablesDeclarationString {
119 | NSMutableString *content = [NSMutableString string];
120 |
121 | for( StatecVariable *variable in [self variables] ) {
122 | if( [variable isInstanceScope] ) {
123 | [content appendString:[variable declarationString]];
124 | }
125 | }
126 |
127 | return content;
128 | }
129 |
130 |
131 | - (NSString *)initializersDeclarationString {
132 | NSMutableString *content = [NSMutableString string];
133 |
134 | for( StatecMethod *method in [self initializers] ) {
135 | [content appendString:[method declarationString]];
136 | }
137 |
138 | return content;
139 | }
140 |
141 |
142 | - (NSString *)initializersDefinitionString {
143 | NSMutableString *content = [NSMutableString string];
144 |
145 | for( StatecMethod *method in [self initializers] ) {
146 | [content appendFormat:@"%@\n",[method definitionString]];
147 | }
148 |
149 | return content;
150 | }
151 |
152 |
153 | - (NSString *)instanceMethodsDeclarationString {
154 | NSMutableString *content = [NSMutableString string];
155 |
156 | for( StatecMethod *method in [self methods] ) {
157 | if( [method isInstanceScope] ) {
158 | [content appendString:[method declarationString]];
159 | }
160 | }
161 |
162 | return content;
163 | }
164 |
165 |
166 | - (NSString *)instanceMethodsDefinitionString {
167 | NSMutableString *content = [NSMutableString string];
168 |
169 | for( StatecMethod *method in [self methods] ) {
170 | if( [method isInstanceScope] ) {
171 | [content appendFormat:@"%@\n",[method definitionString]];
172 | }
173 | }
174 |
175 | return content;
176 | }
177 |
178 |
179 | - (NSString *)propertiesDeclarationString {
180 | NSMutableString *content = [NSMutableString string];
181 |
182 | for( StatecProperty *property in [self properties] ) {
183 | [content appendString:[property declarationString]];
184 | }
185 |
186 | return content;
187 | }
188 |
189 |
190 | - (NSString *)propertiesDefinitionString {
191 | NSMutableString *content = [NSMutableString string];
192 |
193 | for( StatecProperty *property in [self properties] ) {
194 | [content appendString:[property definitionString]];
195 | }
196 |
197 | return content;
198 | }
199 |
200 |
201 | - (NSString *)declarationString {
202 | NSMutableString *content = [NSMutableString string];
203 |
204 | for( NSString *declaration in [self classDeclarations] ) {
205 | [content appendFormat:@"@class %@;",declaration];
206 | }
207 | [content appendString:@"\n"];
208 |
209 | [content appendFormat:@"@interface %@ : %@ {\n", [self name], [self baseClassName]];
210 | [content appendFormat:@"%@\n}\n", [self instanceVariablesDeclarationString]];
211 | [content appendFormat:@"%@\n", [self classMethodsDeclarationString]];
212 | [content appendFormat:@"%@\n", [self propertiesDeclarationString]];
213 | [content appendFormat:@"%@\n", [self initializersDeclarationString]];
214 | [content appendFormat:@"%@\n", [self instanceMethodsDeclarationString]];
215 | [content appendString:@"@end\n\n\n"];
216 |
217 | return content;
218 | }
219 |
220 |
221 | - (NSString *)definitionString {
222 | NSMutableString *content = [NSMutableString string];
223 |
224 | [content appendFormat:@"@implementation %@\n", [self name], [self baseClassName]];
225 | [content appendFormat:@"%@\n", [self classMethodsDefinitionString]];
226 | [content appendFormat:@"%@\n", [self propertiesDefinitionString]];
227 | [content appendFormat:@"%@\n", [self initializersDefinitionString]];
228 | [content appendFormat:@"%@\n", [self instanceMethodsDefinitionString]];
229 | [content appendString:@"@end\n\n\n"];
230 |
231 | return content;
232 | }
233 |
234 |
235 | @end
236 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecCodeStatement.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecCodeStatement.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "StatecStatement.h"
12 |
13 | @interface StatecCodeStatement : StatecStatement
14 |
15 | @property (strong) NSString *body;
16 |
17 | - (id)initWithBody:(NSString *)body;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecCodeStatement.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecCodeStatement.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecCodeStatement.h"
10 |
11 | @implementation StatecCodeStatement
12 |
13 | @synthesize body = _body;
14 |
15 | - (id)initWithBody:(NSString *)body {
16 | self = [self init];
17 | if( self ) {
18 | _body = body;
19 | }
20 | return self;
21 | }
22 |
23 | - (NSString *)statementString {
24 | return [NSString stringWithFormat:@"%@;",[self body]];
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecCompilationUnit.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecCompilationUnit.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class StatecType;
12 | @class StatecClass;
13 | @class StatecVariable;
14 |
15 | @interface StatecCompilationUnit : NSObject
16 |
17 | @property (strong) NSString *name;
18 | @property (strong) NSString *comment;
19 | @property (strong) NSMutableArray *declarationImports;
20 | @property (strong) NSMutableArray *definitionImports;
21 | @property (strong) NSMutableArray *forwardDeclarations;
22 | @property (strong) NSMutableArray *variables;
23 | @property (strong) NSMutableArray *types;
24 | @property (strong) NSMutableArray *classes;
25 | @property (strong) StatecClass *principalClass;
26 |
27 | - (id)initWithName:(NSString *)name;
28 |
29 | - (void)addDeclarationImport:(NSString *)import;
30 | - (void)addDefinitionImport:(NSString *)import;
31 | - (void)addForwardDeclaration:(NSString *)class;
32 | - (void)addVariable:(StatecVariable *)variable;
33 | - (void)addClass:(StatecClass *)class;
34 | - (void)addType:(StatecType *)type;
35 |
36 | - (NSString *)headerFileName;
37 | - (NSString *)classFileName;
38 |
39 | - (BOOL)writeDefinitions:(NSString *)path error:(NSError **)error;
40 | - (BOOL)writeDeclarations:(NSString *)path error:(NSError **)error;
41 | - (BOOL)writeFilesTo:(NSString *)folder error:(NSError **)error;
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecCompilationUnit.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecCompilationUnit.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecCompilationUnit.h"
10 |
11 | #import "Statec.h"
12 |
13 | @implementation StatecCompilationUnit
14 |
15 | @synthesize name = _name;
16 | @synthesize comment = _comment;
17 | @synthesize declarationImports = _declarationImports;
18 | @synthesize definitionImports = _definitionImports;
19 | @synthesize forwardDeclarations = _forwardDeclarations;
20 | @synthesize variables = _variables;
21 | @synthesize types = _types;
22 | @synthesize classes = _classes;
23 | @synthesize principalClass = _principalClass;
24 |
25 |
26 | - (id)initWithName:(NSString *)name {
27 | self = [self init];
28 | if( self ) {
29 | _name = name;
30 | _comment = @"";
31 | _declarationImports = [NSMutableArray arrayWithObject:@""];
32 | _definitionImports = [NSMutableArray arrayWithObject:[NSString stringWithFormat:@"%@.h",name]];
33 | _forwardDeclarations = [NSMutableArray array];
34 | _variables = [NSMutableArray array];
35 | _classes = [NSMutableArray array];
36 | _types = [NSMutableArray array];
37 | }
38 | return self;
39 | }
40 |
41 |
42 | - (void)addVariable:(StatecVariable *)variable {
43 | [_variables addObject:variable];
44 | }
45 |
46 |
47 | - (void)addClass:(StatecClass *)class {
48 | [_classes addObject:class];
49 | }
50 |
51 |
52 | - (void)addType:(StatecType *)type {
53 | [_types addObject:type];
54 | }
55 |
56 |
57 | - (void)addDeclarationImport:(NSString *)import {
58 | [[self declarationImports] addObject:import];
59 | }
60 |
61 |
62 | - (void)addDefinitionImport:(NSString *)import {
63 | [[self definitionImports] addObject:import];
64 | }
65 |
66 |
67 | - (void)addForwardDeclaration:(NSString *)class {
68 | [[self forwardDeclarations] addObject:class];
69 | }
70 |
71 |
72 | - (NSString *)headerFileName {
73 | return [NSString stringWithFormat:@"%@.h",[self name]];
74 | }
75 |
76 |
77 | - (NSString *)classFileName {
78 | return [NSString stringWithFormat:@"%@.m",[self name]];
79 | }
80 |
81 |
82 | - (NSString *)typeStatementString {
83 | NSMutableString *content = [NSMutableString string];
84 | for( StatecType *type in [self types] ) {
85 | [content appendString:[type statementString]];
86 | }
87 |
88 | return content;
89 | }
90 |
91 |
92 | - (NSString *)importStatementString:(NSArray *)imports {
93 | NSMutableString *content = [NSMutableString string];
94 |
95 | for( NSString *import in imports ) {
96 | if( [import hasPrefix:@"<"] ) {
97 | [content appendFormat:@"#import %@\n",import];
98 | } else {
99 | [content appendFormat:@"#import \"%@\"\n",import];
100 | }
101 | [content appendString:@"\n"];
102 | }
103 |
104 | return content;
105 | }
106 |
107 |
108 | - (NSString *)forwardDeclarationsString {
109 | NSMutableString *content = [NSMutableString string];
110 |
111 | for( NSString *class in [self forwardDeclarations] ) {
112 | [content appendFormat:@"@class %@;\n", class];
113 | }
114 |
115 | [content appendString:@"\n"];
116 |
117 | return content;
118 | }
119 |
120 |
121 | - (NSString *)variablesDeclarationString {
122 | NSMutableString *content = [NSMutableString string];
123 | for( StatecVariable *variable in [self variables] ) {
124 | if( [variable isGlobalScope] && ![variable isStaticScope] ) {
125 | [content appendString:[variable declarationString]];
126 | }
127 | }
128 | [content appendString:@"\n\n"];
129 | return content;
130 | }
131 |
132 |
133 | - (NSString *)variablesDefinitionString {
134 | NSMutableString *content = [NSMutableString string];
135 | for( StatecVariable *variable in [self variables] ) {
136 | if( [variable isGlobalScope] ) {
137 | [content appendString:[variable definitionString]];
138 | }
139 | }
140 | [content appendString:@"\n\n"];
141 | return content;
142 | }
143 |
144 |
145 | - (NSString *)declarationsString {
146 | NSMutableString *content = [NSMutableString string];
147 |
148 | if( ![[self comment] isEqualToString:@""] ) {
149 | [content appendFormat:@"%@\n\n", [self comment]];
150 | }
151 |
152 | [content appendString:[self importStatementString:[self declarationImports]]];
153 | [content appendString:[self forwardDeclarationsString]];
154 |
155 | [content appendString:[self variablesDeclarationString]];
156 |
157 | [content appendString:[self typeStatementString]];
158 |
159 | for( StatecClass *class in _classes ) {
160 | [content appendString:[class declarationString]];
161 | }
162 | [content appendString:@"\n"];
163 |
164 | return content;
165 | }
166 |
167 |
168 | - (NSString *)definitionsString {
169 | NSMutableString *content = [NSMutableString string];
170 |
171 | if( ![[self comment] isEqualToString:@""] ) {
172 | [content appendFormat:@"%@\n\n", [self comment]];
173 | }
174 |
175 | [content appendString:[self importStatementString:[self definitionImports]]];
176 |
177 | [content appendString:[self variablesDefinitionString]];
178 |
179 | for( StatecClass *class in [self classes] ) {
180 | [content appendString:[class definitionString]];
181 | }
182 | [content appendString:@"\n"];
183 |
184 | return content;
185 | }
186 |
187 |
188 | - (BOOL)writeDefinitions:(NSString *)path error:(NSError **)error {
189 | return [[self definitionsString] writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:error];
190 | }
191 |
192 |
193 | - (BOOL)writeDeclarations:(NSString *)path error:(NSError **)error {
194 | return [[self declarationsString] writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:error];
195 | }
196 |
197 |
198 | - (BOOL)writeFilesTo:(NSString *)folder error:(NSError **)error {
199 | if( ![self writeDeclarations:[folder stringByAppendingPathComponent:[self headerFileName]] error:error] ) {
200 | return NO;
201 | }
202 | if( ![self writeDefinitions:[folder stringByAppendingPathComponent:[self classFileName]] error:error] ) {
203 | return NO;
204 | }
205 |
206 | return YES;
207 | }
208 |
209 |
210 | @end
211 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecConditionalStatement.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecConditionalStatement.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "StatecStatement.h"
12 |
13 | @interface StatecConditionalStatement : StatecStatement
14 |
15 | @property (strong) NSString *condition;
16 | @property (strong) StatecStatement *ifTrue;
17 | @property (strong) StatecStatement *ifFalse;
18 |
19 | - (id)initWithCondition:(NSString *)condition;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecConditionalStatement.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecConditionalStatement.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecConditionalStatement.h"
10 |
11 | @implementation StatecConditionalStatement
12 |
13 | @synthesize condition = _condition;
14 | @synthesize ifTrue = _ifTrue;
15 | @synthesize ifFalse = _ifFalse;
16 |
17 | - (id)initWithCondition:(NSString *)condition {
18 | self = [self init];
19 | if( self ) {
20 | _condition = condition;
21 | }
22 | return self;
23 | }
24 |
25 |
26 | - (NSString *)statementString {
27 | NSMutableString *content = [NSMutableString string];
28 |
29 | [content appendFormat:@"if( ( %@ ) )", [self condition]];
30 | [content appendString:[[self ifTrue] statementString]];
31 | if( _ifFalse ) {
32 | [content appendString:@" else "];
33 | [content appendString:[[self ifFalse] statementString]];
34 | }
35 |
36 | return content;
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecEnumeration.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecEnumeration.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "StatecType.h"
12 |
13 | @interface StatecEnumeration : StatecType {
14 | NSMutableArray *_elements;
15 | }
16 |
17 | - (void)addElement:(NSString *)element;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecEnumeration.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecEnumeration.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecEnumeration.h"
10 |
11 | @implementation StatecEnumeration
12 |
13 | - (id)init {
14 | self = [super init];
15 | if( self ) {
16 | _elements = [NSMutableArray array];
17 | }
18 | return self;
19 | }
20 |
21 |
22 | - (void)addElement:(NSString *)element {
23 | [_elements addObject:element];
24 | }
25 |
26 |
27 | - (NSString *)statementString {
28 | NSMutableString *content = [NSMutableString string];
29 |
30 | if( [self name] ) {
31 | [content appendFormat:@"enum %@ {\n",[self name]];
32 | } else {
33 | [content appendString:@"enum {\n"];
34 | }
35 |
36 | for( NSString *element in _elements ) {
37 | [content appendFormat:@"\t%@,\n",element];
38 | }
39 |
40 | [content deleteCharactersInRange:NSMakeRange( [content length]-2, 2 )];
41 |
42 | [content appendString:@"\n}"];
43 |
44 | return content;
45 | }
46 |
47 |
48 |
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecGVBuilder.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecGVBuilder.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class StatecMachine;
12 |
13 | @interface StatecGVBuilder : NSObject
14 |
15 | - (NSString *)gvSourceFromMachine:(StatecMachine *)machine;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecGVBuilder.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecGVBuilder.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "StatecGVBuilder.h"
10 |
11 | #import "Statec.h"
12 |
13 | @implementation StatecGVBuilder
14 |
15 | - (NSString *)gvTransitions:(StatecMachine *)machine {
16 | NSMutableString *gv = [NSMutableString string];
17 |
18 | for( StatecState *state in [[machine states] allValues] ) {
19 | for( StatecEvent *event in [state events] ) {
20 | [gv appendFormat:
21 | @"%@ -> %@ [label = \"%@\"];\n",
22 | [state name],
23 | [event targetState],
24 | [event name]
25 | ];
26 | }
27 | }
28 |
29 | return gv;
30 | }
31 |
32 |
33 | - (NSString *)gvSourceFromMachine:(StatecMachine *)machine {
34 | NSMutableString *gv = [NSMutableString string];
35 |
36 | [gv appendFormat:
37 | @"digraph %@ {\n"
38 | @" rankdir=LR;\n"
39 | // @" size=\"16,8\";\n"
40 | @" node [shape = circle];\n"
41 | @" node [fontsize = 15];\n"
42 | @" node [fontfamily = inconsolata];\n"
43 | @" edge [fontsize = 15];\n"
44 | @" edge [fontfamily = inconsolata];\n"
45 | @"%@"
46 | @"}",
47 | [machine name],
48 | [self gvTransitions:machine]
49 | ];
50 |
51 | return gv;
52 | }
53 |
54 |
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecHTMLBuilder.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecHTMLBuilder.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class StatecMachine;
12 |
13 | @interface StatecHTMLBuilder : NSObject {
14 | StatecMachine *_machine;
15 | }
16 |
17 |
18 | - (id)initWithMachine:(StatecMachine *)machine;
19 |
20 | - (BOOL)writeToFolder:(NSString *)folderPath error:(NSError **)error;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecHTMLBuilder.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecHTMLBuilder.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "StatecHTMLBuilder.h"
10 |
11 | #import "Statec.h"
12 |
13 | @implementation StatecHTMLBuilder
14 |
15 | - (id)initWithMachine:(StatecMachine *)machine {
16 | self = [super init];
17 | if( self ) {
18 | _machine = machine;
19 | }
20 | return self;
21 | }
22 |
23 |
24 | - (NSString *)htmlForMachine {
25 | NSMutableString *content = [NSMutableString string];
26 |
27 | [content appendFormat:
28 | @"\n\n%@\n\n\nStates
\n\n",
29 | [_machine name]
30 | ];
31 |
32 | for( StatecState *state in [[_machine states] allValues] ) {
33 | [content appendFormat:
34 | @"State: %@ |
\n",
35 | [state name]
36 | ];
37 |
38 | NSString *enterMethodName = @"", *exitMethodName = @"";
39 | if( [state wantsEnter] ) {
40 | enterMethodName = [state enterStateMethodName];
41 | }
42 | if( [state wantsExit] ) {
43 | exitMethodName = [state exitStateMethodName];
44 | }
45 |
46 | [content appendFormat:
47 | @"%@ | %@ |
",
48 | enterMethodName,
49 | exitMethodName
50 | ];
51 |
52 | for( StatecEvent *event in [state events] ) {
53 | [content appendFormat:
54 | @"%@ | -> %@ |
",
55 | [event callbackMethodName],
56 | [event targetState]
57 | ];
58 | }
59 | }
60 |
61 | [content appendString:
62 | @"
\n\n\n"
63 | ];
64 |
65 |
66 | return content;
67 | }
68 |
69 |
70 | - (BOOL)writeToFolder:(NSString *)folderPath error:(NSError **)error {
71 | return [[self htmlForMachine] writeToFile:[folderPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.html",[_machine name]]]
72 | atomically:NO
73 | encoding:NSUTF8StringEncoding error:error];
74 | }
75 |
76 |
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecMethod.h:
--------------------------------------------------------------------------------
1 | //
2 | // SFClassMethod.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "Statec.h"
12 |
13 | @class StatecArgument;
14 | @class StatecStatementGroup;
15 |
16 | @interface StatecMethod : NSObject
17 |
18 | @property (assign) StatecScope scope;
19 | @property (strong) NSString *returnType;
20 | @property (assign) SEL selector;
21 | @property (strong) StatecStatementGroup *body;
22 | @property (strong) NSMutableArray *arguments;
23 |
24 | - (id)initWithScope:(StatecScope)scope returnType:(NSString *)returnType selector:(SEL)selector;
25 | - (id)initWithScope:(StatecScope)scope returnType:(NSString *)returnType selectorFormat:(NSString *)format, ...;
26 |
27 | - (void)addArgument:(StatecArgument *)argument;
28 |
29 | - (BOOL)isInstanceScope;
30 | - (BOOL)isClassScope;
31 |
32 | - (NSString *)declarationString;
33 | - (NSString *)definitionString;
34 |
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecMethod.m:
--------------------------------------------------------------------------------
1 | //
2 | // SFClassMethod.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecMethod.h"
10 |
11 | @implementation StatecMethod
12 |
13 | @synthesize scope = _scope;
14 | @synthesize returnType = _returnType;
15 | @synthesize selector = _selector;
16 | @synthesize body = _body;
17 | @synthesize arguments = _arguments;
18 |
19 |
20 | - (id)init {
21 | self = [super init];
22 | if( self ) {
23 | _arguments = [NSMutableArray array];
24 | _body = [StatecStatementGroup group];
25 | }
26 | return self;
27 | }
28 |
29 |
30 | - (id)initWithScope:(StatecScope)scope returnType:(NSString *)returnType selector:(SEL)selector {
31 | self = [self init];
32 | if( self ) {
33 | _scope = scope;
34 | _returnType = returnType;
35 | _selector = selector;
36 | }
37 | return self;
38 | }
39 |
40 |
41 | - (id)initWithScope:(StatecScope)scope returnType:(NSString *)returnType selectorFormat:(NSString *)format, ... {
42 | va_list args;
43 | va_start( args, format );
44 | NSString *selectorString = (__bridge_transfer NSString *)CFStringCreateWithFormatAndArguments( kCFAllocatorDefault, NULL, (__bridge CFStringRef)format, args );
45 | va_end( args );
46 | return [self initWithScope:scope returnType:returnType selector:NSSelectorFromString(selectorString)];
47 | }
48 |
49 |
50 | - (void)addArgument:(StatecArgument *)argument {
51 | [[self arguments] addObject:argument];
52 | }
53 |
54 |
55 | - (BOOL)isInstanceScope {
56 | return (StatecInstanceScope & _scope) == StatecInstanceScope;
57 | }
58 |
59 |
60 | - (BOOL)isClassScope {
61 | return ( StaticClassScope & _scope ) == StaticClassScope;
62 | }
63 |
64 |
65 | - (NSString *)scopeString {
66 | if( [self isInstanceScope] ) {
67 | return @"-";
68 | } else {
69 | return @"+";
70 | }
71 | }
72 |
73 |
74 | - (NSString *)selectorString {
75 | return NSStringFromSelector( [self selector] );
76 | }
77 |
78 |
79 | - (NSString *)signatuareString {
80 | NSMutableString *content = [NSMutableString string];
81 |
82 | [content appendString:[self scopeString]];
83 | [content appendString:@" ("];
84 | [content appendString:[self returnType]];
85 | [content appendString:@")"];
86 |
87 | NSRange range = [[self selectorString] rangeOfString:@":"];
88 | if( range.location == NSNotFound ) {
89 | [content appendString:[self selectorString]];
90 | } else {
91 |
92 | NSArray *selectorComponents = [[self selectorString] componentsSeparatedByString:@":"];
93 | if( [[selectorComponents objectAtIndex:[selectorComponents count]-1] isEqualToString:@""] ) {
94 | selectorComponents = [selectorComponents subarrayWithRange:NSMakeRange(0,[selectorComponents count]-1)];
95 | }
96 |
97 | int componentIndex = 0;
98 | for( NSString *component in selectorComponents ) {
99 | if( componentIndex > 0 ) {
100 | [content appendString:@" "];
101 | }
102 |
103 | [content appendFormat:@"%@:%@",component,[[[self arguments] objectAtIndex:componentIndex] argumentString]];
104 |
105 | componentIndex += 1;
106 | }
107 | }
108 |
109 | return content;
110 | }
111 |
112 |
113 | - (NSString *)declarationString {
114 | return [NSString stringWithFormat:@"%@;\n",[self signatuareString]];
115 | }
116 |
117 |
118 | - (NSString *)definitionString {
119 | return [NSString stringWithFormat:@"%@ %@\n",[self signatuareString],[[self body] statementString]];
120 | }
121 |
122 |
123 | @end
124 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecProperty.h:
--------------------------------------------------------------------------------
1 | //
2 | // SFPropertyModel.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface StatecProperty : NSObject
12 |
13 | @property (strong) NSMutableArray *attributes;
14 |
15 | @property (strong) NSString *type;
16 | @property (strong) NSString *name;
17 |
18 | - (id)initWithType:(NSString *)type name:(NSString *)name;
19 | - (id)initWithType:(NSString *)type name:(NSString *)name attribute:(NSString *)attribute;
20 |
21 | - (NSString *)declarationString;
22 | - (NSString *)definitionString;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecProperty.m:
--------------------------------------------------------------------------------
1 | //
2 | // SFPropertyModel.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecProperty.h"
10 |
11 | @implementation StatecProperty
12 |
13 | @synthesize attributes = _attributes;
14 | @synthesize type = _type;
15 | @synthesize name = _name;
16 |
17 |
18 | - (id)init {
19 | self = [super init];
20 | if( self ) {
21 | _attributes = [NSMutableArray array];
22 | }
23 | return self;
24 | }
25 |
26 | - (id)initWithType:(NSString *)type name:(NSString *)name {
27 | self = [self init];
28 | if( self ) {
29 | _type = type;
30 | _name = name;
31 | }
32 | return self;
33 | }
34 |
35 |
36 | - (id)initWithType:(NSString *)type name:(NSString *)name attribute:(NSString *)attribute {
37 | self = [self initWithType:type name:name];
38 | if( self ) {
39 | [_attributes addObject:attribute];
40 | }
41 | return self;
42 | }
43 |
44 |
45 | - (NSString *)attributesString {
46 | return [[self attributes] componentsJoinedByString:@","];
47 | }
48 |
49 |
50 | - (NSString *)declarationString {
51 | return [NSString stringWithFormat:@"@property (%@) %@ %@;\n", [self attributesString], [self type], [self name]];
52 | }
53 |
54 |
55 | - (NSString *)definitionString {
56 | return [NSString stringWithFormat:@"@synthesize %@ = _%@;\n", [self name], [self name]];
57 | }
58 |
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecStatement.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecStatement.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface StatecStatement : NSObject
12 |
13 | - (NSString *)statementString;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecStatement.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecStatement.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecStatement.h"
10 |
11 | @implementation StatecStatement
12 |
13 | - (NSString *)statementString {
14 | return @"// YOU SHOULD NEVER SEE THIS!";
15 | }
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecStatementGroup.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecStatementGroup.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "StatecStatement.h"
12 |
13 | @interface StatecStatementGroup : StatecStatement
14 |
15 | @property (strong) NSMutableArray *statements;
16 |
17 | + (StatecStatementGroup *)group;
18 |
19 | - (id)initWithBody:(NSString *)body;
20 | - (id)initWithFormat:(NSString *)format, ...;
21 | //- (id)initWithStatement:(StatecStatement *)statement;
22 |
23 | - (void)append:(NSString *)format, ...;
24 | - (void)addStatement:(StatecStatement *)statement;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecStatementGroup.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecStatementGroup.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecStatementGroup.h"
10 |
11 | #import "Statec.h"
12 |
13 | @implementation StatecStatementGroup
14 |
15 | @synthesize statements = _statements;
16 |
17 |
18 | + (StatecStatementGroup *)group {
19 | return [[StatecStatementGroup alloc] init];
20 | }
21 |
22 | - (id)init {
23 | self = [super init];
24 | if( self ) {
25 | _statements = [[NSMutableArray alloc] init];
26 | }
27 | return self;
28 | }
29 |
30 |
31 | - (id)initWithBody:(NSString *)body {
32 | self = [self init];
33 | if( self ) {
34 | [self append:body];
35 | // [self addStatement:[[StatecCodeStatement alloc] initWithBody:body]];
36 | }
37 | return self;
38 | }
39 |
40 |
41 | - (id)initWithFormat:(NSString *)format, ... {
42 | va_list args;
43 | va_start( args, format );
44 | NSString *body = (__bridge_transfer NSString *)CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, (__bridge CFStringRef)format, args );
45 | va_end( args );
46 | return [self initWithBody:body];
47 | }
48 |
49 |
50 | //- (id)initWithStatement:(StatecStatement *)statement {
51 | // self = [self init];
52 | // if( self ) {
53 | // [self addStatement:statement];
54 | // }
55 | // return self;
56 | //}
57 |
58 |
59 | - (void)append:(NSString *)format, ... {
60 | va_list args;
61 | va_start( args, format );
62 | NSString *formattedString = (__bridge_transfer NSString *)CFStringCreateWithFormatAndArguments( kCFAllocatorDefault, NULL, (__bridge CFStringRef)format, args );
63 | va_end( args );
64 | [[self statements] addObject:formattedString];
65 | }
66 |
67 |
68 | //- (void)addLine:(NSString *)line {
69 | // [[self statements] addObject:line];
70 | //}
71 |
72 |
73 | - (void)addStatement:(StatecStatement *)statement {
74 | [[self statements] addObject:statement];
75 | }
76 |
77 |
78 | - (NSString *)statementString {
79 | NSMutableString *content = [NSMutableString string];
80 |
81 | [content appendString:@"{\n"];
82 | for( id statement in [self statements] ) {
83 | if( [statement isKindOfClass:[StatecStatement class]] ) {
84 | [content appendString:[statement statementString]];
85 | } else {
86 | [content appendFormat:@"%@\n",statement];
87 | }
88 | }
89 | [content appendString:@"}\n"];
90 |
91 | return content;
92 | }
93 |
94 |
95 | @end
96 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecType.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecType.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface StatecType : NSObject
12 |
13 | @property (strong) NSString *name;
14 |
15 | - (id)initWithName:(NSString *)name;
16 |
17 |
18 | - (NSString *)statementString;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecType.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecType.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecType.h"
10 |
11 | @implementation StatecType
12 |
13 | @synthesize name = _name;
14 |
15 | - (id)initWithName:(NSString *)name {
16 | self = [self init];
17 | if( self ) {
18 | _name = name;
19 | }
20 | return self;
21 | }
22 |
23 |
24 | - (NSString *)statementString {
25 | return @"";
26 | }
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecTypedef.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecTypedef.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "StatecType.h"
12 |
13 | @interface StatecTypedef : StatecType
14 |
15 | @property (strong) NSString *name;
16 | @property (strong) StatecType *type;
17 |
18 | - (id)initWithName:(NSString *)name type:(StatecType *)type;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecTypedef.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecTypedef.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecTypedef.h"
10 |
11 | @implementation StatecTypedef
12 |
13 | @synthesize name = _name;
14 | @synthesize type = _type;
15 |
16 | - (id)initWithName:(NSString *)name type:(StatecType *)type {
17 | self = [self init];
18 | if( self ) {
19 | _name = name;
20 | _type = type;
21 | }
22 | return self;
23 | }
24 |
25 |
26 | - (NSString *)statementString {
27 | NSMutableString *content = [NSMutableString string];
28 | [content appendFormat:@"typedef %@ %@;\n",[[self type] statementString],[self name]];
29 | return content;
30 | }
31 |
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecVariable.h:
--------------------------------------------------------------------------------
1 | //
2 | // SFInstanceVariable.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "Statec.h"
12 |
13 | @interface StatecVariable : NSObject {
14 | }
15 |
16 |
17 | @property (assign) StatecScope scope;
18 | @property (strong) NSString *type;
19 | @property (strong) NSString *name;
20 |
21 | - (id)initWithScope:(StatecScope)scope name:(NSString *)name type:(NSString *)type;
22 |
23 | - (BOOL)isInstanceScope;
24 | - (BOOL)isGlobalScope;
25 | - (BOOL)isStaticScope;
26 |
27 | - (NSString *)declarationString;
28 | - (NSString *)definitionString;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/Statec/Builder/StatecVariable.m:
--------------------------------------------------------------------------------
1 | //
2 | // SFInstanceVariable.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecVariable.h"
10 |
11 | @implementation StatecVariable
12 |
13 | @synthesize scope = _scope;
14 | @synthesize name = _name;
15 | @synthesize type = _type;
16 |
17 | - (id)initWithScope:(StatecScope)scope name:(NSString *)name type:(NSString *)type {
18 | self = [super init];
19 | if( self ) {
20 | _scope = scope;
21 | _name = name;
22 | _type = type;
23 | }
24 | return self;
25 | }
26 |
27 |
28 | - (BOOL)isInstanceScope {
29 | return ( _scope & StatecInstanceScope ) == StatecInstanceScope;
30 | }
31 |
32 |
33 | - (BOOL)isGlobalScope {
34 | return ( _scope & StatecGlobalScope ) == StatecGlobalScope;
35 | }
36 |
37 |
38 | - (BOOL)isStaticScope {
39 | return ( _scope & StatecStaticScope ) == StatecStaticScope;
40 | }
41 |
42 |
43 | - (NSString *)declarationString {
44 | if( [self isInstanceScope] ) {
45 | return [NSString stringWithFormat:@"\t%@ %@;\n", [self type], [self name]];
46 | } else {
47 | if( !(_scope & StatecStaticScope) ) {
48 | return [NSString stringWithFormat:@"extern %@ %@;", [self type], [self name]];
49 | } else {
50 | return @"";
51 | }
52 | }
53 | }
54 |
55 |
56 | - (NSString *)definitionString {
57 | if( [self isGlobalScope] ) {
58 | if( _scope & StatecStaticScope ) {
59 | return [NSString stringWithFormat:@"static %@ %@;\n", [self type], [self name]];
60 | } else {
61 | return [NSString stringWithFormat:@"%@ %@;\n", [self type], [self name]];
62 | }
63 | } else {
64 | return @"";
65 | }
66 | }
67 |
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/Statec/Categories/NSString+StatecExtensions.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+StatecExtensions.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (StatecExtensions)
12 |
13 | - (NSString *)statecStringByCapitalisingFirstLetter;
14 | - (NSString *)statecStringByLoweringFirstLetter;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/Statec/Categories/NSString+StatecExtensions.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+StatecExtensions.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "NSString+StatecExtensions.h"
10 |
11 | @implementation NSString (StatecExtensions)
12 |
13 | - (NSString *)statecStringByCapitalisingFirstLetter {
14 | return [self stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[self substringToIndex:1] capitalizedString]];
15 | }
16 |
17 |
18 | - (NSString *)statecStringByLoweringFirstLetter {
19 | return [self stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[self substringToIndex:1] lowercaseString]];
20 | }
21 |
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Statec/Compiler/StatecCompiler.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecCompiler.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class StatecParser;
12 | @class StatecMachine;
13 | @class StatecCompilationUnit;
14 |
15 | @interface StatecCompiler : NSObject {
16 | }
17 |
18 | @property (strong) StatecParser *parser;
19 | @property (strong) StatecMachine *machine;
20 | @property (strong) StatecCompilationUnit *generatedUnit;
21 |
22 | //- (id)initWithSource:(NSString *)source;
23 |
24 | - (BOOL)parse:(NSString *)source;
25 |
26 | - (BOOL)isMachineValid:(NSArray **)issues;
27 |
28 | - (StatecCompilationUnit *)generatedMachine;
29 | - (StatecCompilationUnit *)userMachine;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Statec/Compiler/StatecCompiler.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecCompiler.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecCompiler.h"
10 |
11 | #import "Statec.h"
12 |
13 | #import "NSString+StatecExtensions.h"
14 |
15 | @implementation StatecCompiler
16 |
17 | @synthesize parser = _parser;
18 | @synthesize machine = _machine;
19 | @synthesize generatedUnit = _generatedUnit;
20 |
21 |
22 | - (id)init {
23 | self = [super init];
24 | if( self ) {
25 | _parser = [[StatecParser alloc] init];
26 | }
27 | return self;
28 | }
29 |
30 |
31 | - (BOOL)parse:(NSString *)source {
32 | StatecMachine *machine = (StatecMachine *)[[self parser] parse:source];
33 | if( machine ) {
34 | [self setMachine:machine];
35 | return YES;
36 | } else {
37 | return NO;
38 | }
39 | }
40 |
41 |
42 | - (BOOL)isMachineValid:(NSArray **)issues {
43 | return [_machine isMachineValid:issues];
44 | }
45 |
46 |
47 | /*
48 | Generate an initializer for the machine class that initializes a global instance of each of the state
49 | subclasses. Because they are stateless they can be shared by all instances of the machine.
50 | */
51 | - (StatecMethod *)classInitializer {
52 | StatecMethod *method = [[StatecMethod alloc] initWithScope:StaticClassScope returnType:@"void" selector:@selector(initialize)];
53 |
54 | [[method body] append:
55 | @"static dispatch_once_t onceToken;\n"
56 | @"dispatch_once(&onceToken, ^{\n"];
57 |
58 | for( StatecState *state in [[_machine states] allValues] ) {
59 | [[method body] append:@"%@ = [[%@ alloc] init];\n", [state stateVariableName], [state stateClassNameInMachine:_machine]];
60 | }
61 |
62 | [[method body] append:
63 | @"});"];
64 |
65 | return method;
66 | }
67 |
68 |
69 |
70 | /*
71 | Generate the initializer for the machine class. This should initialize the current state variable to point
72 | to the global instance of the state subclass for the initial state.
73 | */
74 | - (StatecMethod *)initializer:(StatecVariable *)stateVariable queueVariable:(StatecVariable *)queueVariable {
75 | StatecMethod *method = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"id" selector:@selector(init)];
76 | [[method body] append:
77 | @"self = [super init];\n"
78 | @"if( self ) {\n"
79 | @"%@ = %@;\n"
80 | @"%@ = dispatch_queue_create( %@, DISPATCH_QUEUE_SERIAL );\n"
81 | @"}\n"
82 | @"return self;\n",
83 | [stateVariable name],
84 | [[_machine initialState] stateVariableName],
85 | [queueVariable name],
86 | [NSString stringWithFormat:@"[[NSString stringWithFormat:@\"%@Machine.%%p\",self] UTF8String]",[_machine name]]
87 | ];
88 |
89 | return method;
90 | }
91 |
92 |
93 | - (StatecMethod *)deallocQueueVariable:(StatecVariable *)queueVariable {
94 | StatecMethod *method = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selectorFormat:@"dealloc"];
95 | [[method body] append:
96 | @"dispatch_release( %@ );\n", [queueVariable name]
97 | ];
98 | return method;
99 | }
100 |
101 |
102 | /*
103 | Generate a method, to be added to the machine class, to respond to a specific event.
104 |
105 | The method tests whether the current state class can respond to this event. If it can then the event is passed
106 | on to the current state class. Otherwise an exception is raised to report the illegal attempted transition.
107 | */
108 | - (StatecMethod *)eventMethodForEvent:(StatecEvent *)event state:(StatecVariable *)state queue:(StatecVariable *)queue {
109 | SEL selector = NSSelectorFromString([NSString stringWithFormat:[event callbackMethodName]]);
110 |
111 | StatecMethod *method = [[StatecMethod alloc] initWithScope:StatecInstanceScope
112 | returnType:@"void"
113 | selector:selector];
114 |
115 | NSString *stateMethodName = [NSString stringWithFormat:[event internalCallbackMethodName]];
116 | [[method body] append:
117 | @"dispatch_async( %@, ^{\n"
118 | @" [%@ %@self];"
119 | @"});\n",
120 | [queue name],
121 | [state name],
122 | stateMethodName
123 | ];
124 |
125 | return method;
126 | }
127 |
128 |
129 | /*
130 | Generate event methods which will be added to the machine class.
131 |
132 | A method for every event (across all states) is added here.
133 | */
134 | - (NSArray *)eventMethods:(StatecVariable *)stateVariable queueVariable:(StatecVariable *)queueVariable {
135 | NSMutableArray *methods = [NSMutableArray array];
136 | for( NSString *eventName in [_machine events] ) {
137 | [methods addObject:[self eventMethodForEvent:[[_machine events] objectForKey:eventName]
138 | state:stateVariable
139 | queue:queueVariable]];
140 | }
141 | return methods;
142 | }
143 |
144 |
145 | /*
146 | Generate a subclass of State to represent a concrete state in Machine.
147 | */
148 | - (StatecClass *)stateClass:(StatecState *)state baseClass:(StatecClass *)baseClass machineClass:(StatecClass *)machineClass {
149 | StatecClass *stateClass = [[StatecClass alloc] initWithname:[state stateClassNameInMachine:_machine] baseClass:baseClass];
150 |
151 | StatecMethod *initializer = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"id" selector:@selector(init)];
152 | [[initializer body] append:
153 | @"return [self initWithName:@\"%@\"];\n",
154 | [state name]
155 | ];
156 | [stateClass addInitializer:initializer];
157 |
158 | // For every event this state recognises define an event method
159 | // that traverses to the target state
160 | for( StatecEvent *event in [state events] ) {
161 | StatecMethod *eventMethod = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selectorFormat:[event internalCallbackMethodName]];
162 | [eventMethod addArgument:[[StatecArgument alloc] initWithType:[machineClass pointerType] name:@"machine"]];
163 | [[eventMethod body] append:@"[machine log:@\"Received event: %@\"];\n", [event name]];
164 | if( [state wantsExit] ) {
165 | [[eventMethod body] append:@"[machine %@];\n", [state exitStateMethodName]];
166 | }
167 |
168 | StatecState *targetState = [[_machine states] objectForKey:[event targetState]];
169 | [[eventMethod body] append:@"[machine transitionToState:%@];\n", [targetState stateVariableName]];
170 | [stateClass addMethod:eventMethod];
171 | }
172 |
173 | if( [state wantsEnter] ) {
174 | StatecMethod *enterMethod = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selector:@selector(enterFromMachine:)];
175 | [enterMethod addArgument:[[StatecArgument alloc] initWithType:[machineClass pointerType] name:@"machine"]];
176 | [[enterMethod body] append:
177 | @"[machine %@];\n", [state enterStateMethodName]
178 | ];
179 | [stateClass addMethod:enterMethod];
180 | }
181 |
182 | return stateClass;
183 | }
184 |
185 | /*
186 | Generate the Machine class.
187 | */
188 | - (StatecClass *)machineClassWithStateBaseClass:(StatecClass *)stateBaseClass {
189 | // Create the class Machine that will represent the machine itself
190 | StatecClass *machineClass = [[StatecClass alloc] initWithName:[NSString stringWithFormat:@"_%@Machine",[_machine name]]];
191 |
192 | // Add the +initialize method to create the state subclasses
193 | [machineClass addMethod:[self classInitializer]];
194 |
195 | // Add to the machine class an instance variable representing the current state
196 | StatecVariable *stateVariable = [[StatecVariable alloc] initWithScope:StatecInstanceScope
197 | name:@"_currentState"
198 | type:[stateBaseClass pointerType]];
199 | [machineClass addVariable:stateVariable];
200 |
201 | StatecMethod *getStateMethod = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:[stateBaseClass pointerType] selector:@selector(currentState)];
202 | [[getStateMethod body] append:
203 | @"return %@;\n",
204 | [stateVariable name]
205 | ];
206 | [machineClass addMethod:getStateMethod];
207 |
208 | StatecMethod *illegalTransitionMethod = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selector:@selector(illegalTransition:from:)];
209 | [illegalTransitionMethod addArgument:[[StatecArgument alloc] initWithType:@"NSString*" name:@"event"]];
210 | [illegalTransitionMethod addArgument:[[StatecArgument alloc] initWithType:[stateBaseClass pointerType] name:@"from"]];
211 | [[illegalTransitionMethod body] append:
212 | @"// Subclass can override to customise illegal transition handling\n"
213 | @"[self log:[NSString stringWithFormat:@\"Received event %%@ which is not legal in state %%@\", event, [from name]]];\n"
214 | ];
215 | [machineClass addMethod:illegalTransitionMethod];
216 |
217 | StatecMethod *logMethod = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selector:@selector(log:)];
218 | [logMethod addArgument:[[StatecArgument alloc] initWithType:@"NSString*" name:@"message"]];
219 | [[logMethod body] append:
220 | @"// Subclass can override to do the actual logging\n"
221 | ];
222 | [machineClass addMethod:logMethod];
223 |
224 | // Add to the machine class an instance variable represent a queue we will use to
225 | // serialize state changes
226 | StatecVariable *queueVariable = [[StatecVariable alloc] initWithScope:StatecInstanceScope
227 | name:@"_queue"
228 | type:@"dispatch_queue_t"];
229 | [machineClass addVariable:queueVariable];
230 |
231 | // Add to the machine class it's -init method that sets the initial state
232 | [machineClass addInitializer:[self initializer:stateVariable queueVariable:queueVariable]];
233 |
234 | // Add the dealloc method to release the queue
235 | [machineClass addMethod:[self deallocQueueVariable:queueVariable]];
236 |
237 | // Add an event method, for all events, to the machine class
238 | [machineClass addMethods:[self eventMethods:stateVariable queueVariable:queueVariable]];
239 |
240 | // For every state that wanted enter notification we provide a callback that can be overridden
241 | // by the user state machine class
242 | for( NSString *stateName in [_machine states] ) {
243 | StatecState *state = [[_machine states] objectForKey:stateName];
244 | if( [state wantsEnter] ) {
245 | StatecMethod *method = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selectorFormat:[state enterStateMethodName]];
246 | [method setBody:[[StatecStatementGroup alloc] initWithFormat:@"// Override in user machine subclass"]];
247 | [machineClass addMethod:method];
248 | }
249 | if( [state wantsExit] ) {
250 | StatecMethod *method = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selectorFormat:[state exitStateMethodName]];
251 | [method setBody:[[StatecStatementGroup alloc] initWithFormat:@"// Override in user machine subclass"]];
252 | [machineClass addMethod:method];
253 | }
254 | }
255 |
256 | StatecMethod *transitionMethod = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selector:@selector(transitionToState:)];
257 | [transitionMethod addArgument:[[StatecArgument alloc] initWithType:[stateBaseClass pointerType] name:@"state"]];
258 | [[transitionMethod body] append:
259 | @"dispatch_async( %@, ^{\n"
260 | @"%@ = state;\n"
261 | @"[state enterFromMachine:self];\n"
262 | @"});\n",
263 | [queueVariable name],
264 | [stateVariable name]
265 | ];
266 | [machineClass addMethod:transitionMethod];
267 |
268 | return machineClass;
269 | }
270 |
271 | /*
272 | Generate a class model for State which acts as a base-class for all the machine specific
273 | state classes.
274 | */
275 | - (StatecClass *)stateBaseClass {
276 | // Create the base class for the states
277 | StatecClass *class = [[StatecClass alloc] initWithName:[NSString stringWithFormat:@"%@State",[_machine name]]];
278 |
279 | // Oay this is a cheat, i shouldn't be passing two strings separated by a , for attributes
280 | [class addProperty:[[StatecProperty alloc] initWithType:@"NSString*" name:@"name" attribute:@"strong,readonly"]];
281 |
282 | StatecMethod *initializer = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"id" selector:@selector(initWithName:)];
283 | [initializer addArgument:[[StatecArgument alloc] initWithType:@"NSString*" name:@"name"]];
284 | [[initializer body] append:
285 | @"self = [super init];\n"
286 | @"if( self ) {\n"
287 | @" _name = name;\n"
288 | @"}\n"
289 | @"return self;\n"
290 | ];
291 | [class addMethod:initializer];
292 |
293 | return class;
294 | }
295 |
296 | /*
297 | Generates an array of methods that will be added to the State base-class to represent the events
298 | in the machine. The base class implements all events to provide a consistent interface that the machine
299 | can call. A default implementation is provided that raises an exception. It is expected that each state
300 | specific subclass will override this implementation for events legal for that state and, instead, cause
301 | the machine to transition to a new state.
302 | */
303 | - (NSArray *)baseEventMethods:(StatecClass *)machineClass {
304 | NSMutableArray *methods = [NSMutableArray array];
305 |
306 | // Now add to State a method for each event that raises an exception if the event is
307 | // fired. Specific subclasses will override this with a method that handles the event if
308 | // the state recognises that event.
309 | for( StatecEvent *event in [[_machine events] allValues] ) {
310 | StatecMethod *eventMethod = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selectorFormat:[event internalCallbackMethodName]];
311 | [eventMethod addArgument:[[StatecArgument alloc] initWithType:[machineClass pointerType] name:@"machine"]];
312 | [[eventMethod body] append:
313 | @"[machine illegalTransition:@\"%@\" from:self];\n",
314 | [event name]
315 | ];
316 | [methods addObject:eventMethod];
317 | }
318 |
319 | return methods;
320 | }
321 |
322 |
323 | - (StatecCompilationUnit *)generatedMachine {
324 | StatecCompilationUnit *unit = [[StatecCompilationUnit alloc] initWithName:[NSString stringWithFormat:@"_%@Machine",[_machine name]]];
325 |
326 | [unit setComment:[NSString stringWithFormat:
327 | @"// This state machine file (_%@) was generated by Statec 0.1(0)\n"
328 | @"// Copyright (c) 2012 Matt Mower \n"
329 | @"// DO NOT EDIT THIS FILE - IT IS REGENERATED EVERY TIME STATEC IS RUN\n"
330 | @"// ONLY MAKE CHANGES IN THE USER FILE %@. YOU HAVE BEEN WARNED\n",
331 | [_machine name],
332 | [_machine name]
333 | ]];
334 |
335 | StatecClass *stateBaseClass = [self stateBaseClass];
336 | [unit addClass:stateBaseClass];
337 |
338 | StatecClass *machineClass = [self machineClassWithStateBaseClass:stateBaseClass];
339 | [stateBaseClass addMethods:[self baseEventMethods:machineClass]];
340 |
341 | // Add the generic enterFromMachine: method
342 | StatecMethod *enterMethod = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selector:@selector(enterFromMachine:)];
343 | [enterMethod addArgument:[[StatecArgument alloc] initWithType:[machineClass pointerType] name:@"machine"]];
344 | [enterMethod setBody:[[StatecStatementGroup alloc] initWithFormat:@"// Subclasses will redefine if enter callbacks are required for their state\n"]];
345 | [stateBaseClass addMethod:enterMethod];
346 |
347 | // Make the machine class available to the State classes that get declared before it
348 | [unit addForwardDeclaration:[machineClass name]];
349 |
350 | // For each state in the machine make a state subclass and create a global
351 | // pointer for a staticly allocated instance of the class
352 | for( StatecState *state in [[_machine states] allValues] ) {
353 | [unit addClass:[self stateClass:state baseClass:stateBaseClass machineClass:machineClass]];
354 | StatecVariable *stateGlobalVariable = [[StatecVariable alloc] initWithScope:StatecGlobalScope|StatecStaticScope
355 | name:[state stateVariableName]
356 | type:[stateBaseClass pointerType]];
357 | [unit addVariable:stateGlobalVariable];
358 | }
359 |
360 | [unit addClass:machineClass];
361 | [unit setPrincipalClass:machineClass];
362 |
363 | _generatedUnit = unit;
364 |
365 | return unit;
366 | }
367 |
368 |
369 | - (StatecCompilationUnit *)userMachine {
370 | StatecCompilationUnit *unit = [[StatecCompilationUnit alloc] initWithName:[NSString stringWithFormat:@"%@Machine",[_machine name]]];
371 |
372 | NSMutableString *commentString = [NSMutableString string];
373 | [commentString appendFormat:
374 | @"// State Machine %@ generated by Statec v0.1 on %@\n"
375 | @"// \n",
376 | [_machine name],
377 | [NSDate date]
378 | ];
379 |
380 | [unit setComment:commentString];
381 |
382 | // Import the generated machine into the user machine
383 | [[unit declarationImports] addObject:[NSString stringWithFormat:@"_%@Machine.h",[_machine name]]];
384 |
385 | StatecClass *userClass = [[StatecClass alloc] initWithname:[NSString stringWithFormat:@"%@Machine",[_machine name]] baseClass:[[self generatedUnit] principalClass]];
386 |
387 | // For every state that wanted enter notification we provide a callback stub the user can put their code in
388 | for( NSString *stateName in [_machine states] ) {
389 | StatecState *state = [[_machine states] objectForKey:stateName];
390 | if( [state wantsEnter] ) {
391 | StatecMethod *method = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selectorFormat:[state enterStateMethodName]];
392 | [method setBody:[[StatecStatementGroup alloc] initWithFormat:@"// Your code here"]];
393 | [userClass addMethod:method];
394 | }
395 | if( [state wantsExit] ) {
396 | StatecMethod *method = [[StatecMethod alloc] initWithScope:StatecInstanceScope returnType:@"void" selectorFormat:[state exitStateMethodName]];
397 | [method setBody:[[StatecStatementGroup alloc] initWithFormat:@"// Your code here"]];
398 | [userClass addMethod:method];
399 | }
400 | }
401 |
402 | [unit addClass:userClass];
403 |
404 | return unit;
405 | }
406 |
407 |
408 | @end
409 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecEnter.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecEnter.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 |
14 | @interface StatecEnter : NSObject
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecEnter.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecEnter.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecEnter.h"
10 |
11 | @implementation StatecEnter
12 |
13 | - (id)initWithSyntaxTree:(CPSyntaxTree *)syntaxTree {
14 | self = [super init];
15 | if( self ) {
16 | }
17 | return self;
18 | }
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecExit.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecExit.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 |
14 | @interface StatecExit : NSObject
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecExit.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecExit.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecExit.h"
10 |
11 | @implementation StatecExit
12 |
13 | - (id)initWithSyntaxTree:(CPSyntaxTree *)syntaxTree {
14 | self = [super init];
15 | if( self ) {
16 | }
17 | return self;
18 | }
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecInitial.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecInitial.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 |
14 | @interface StatecInitial : NSObject
15 |
16 | @property (strong) NSString *name;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecInitial.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecInitial.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecInitial.h"
10 |
11 | @implementation StatecInitial
12 |
13 | @synthesize name = _name;
14 |
15 | - (id)initWithSyntaxTree:(CPSyntaxTree *)syntaxTree {
16 | self = [super init];
17 | if( self ) {
18 | NSAssert( 2 == [[syntaxTree children] count], @"StatecInitial must have exactly 2 children" );
19 | _name = [[[syntaxTree children] objectAtIndex:1] content];
20 | }
21 | return self;
22 | }
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecMachine.h:
--------------------------------------------------------------------------------
1 | //
2 | // Machine.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 | @class StatecState;
14 |
15 | @interface StatecMachine : NSObject
16 |
17 | @property (strong) NSString *name;
18 | @property (strong) StatecState *initialState;
19 | @property (strong) NSDictionary *states;
20 | @property (strong) NSDictionary *events;
21 |
22 | - (BOOL)isMachineValid:(NSArray **)issues;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecMachine.m:
--------------------------------------------------------------------------------
1 | //
2 | // Machine.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecMachine.h"
10 |
11 | #import "Statec.h"
12 |
13 | @implementation StatecMachine
14 |
15 | @synthesize name = _name;
16 | @synthesize initialState = _initialState;
17 | @synthesize states = _states;
18 | @synthesize events = _events;
19 |
20 | - (id)initWithSyntaxTree:(CPSyntaxTree *)syntaxTree {
21 | self = [super init];
22 | if( self ) {
23 | NSArray *children = [syntaxTree children];
24 | _name = [[children objectAtIndex:1] content];
25 |
26 | NSArray *stateList = [children objectAtIndex:4];
27 |
28 | _states = [NSMutableDictionary dictionary];
29 | for( StatecState *state in stateList ) {
30 | [_states setValue:state forKey:[state name]];
31 | }
32 |
33 | _initialState = [_states objectForKey:[[children objectAtIndex:3] name]];
34 |
35 | _events = [NSMutableDictionary dictionary];
36 |
37 | for( StatecState *state in stateList ) {
38 | for( StatecEvent *event in [state events] ) {
39 |
40 | StatecEvent *globalEvent = [_events objectForKey:[event name]];
41 | if( !globalEvent ) {
42 | globalEvent = event;
43 | [_events setValue:globalEvent forKey:[event name]];
44 | }
45 |
46 | // NSMutableArray *transitionList = [_events objectForKey:[event name]];
47 | // if( !transitionList ) {
48 | // transitionList = [NSMutableArray array];
49 | // [_events setValue:transitionList forKey:[event name]];
50 | // }
51 |
52 | StatecTransition *transition = [[StatecTransition alloc] initWithSourceState:state targetState:[_states objectForKey:[event targetState]]];
53 | [[globalEvent transitions] addObject:transition];
54 | // [transitionList addObject:transition];
55 | }
56 | }
57 | }
58 | return self;
59 | }
60 |
61 |
62 | - (NSArray *)validatesInitialStateIsDefined {
63 | for( StatecState *state in [[self states] allValues] ) {
64 | if( [[state name] isEqualToString:[[self initialState] name]] ) {
65 | return [NSArray array];
66 | }
67 | }
68 |
69 | return [NSArray arrayWithObject:[NSString stringWithFormat:@"Initial state '%@' is not defined as a state", _initialState]];
70 | }
71 |
72 |
73 | - (NSArray *)validatesEventTransitions {
74 | NSMutableArray *issues = [NSMutableArray array];
75 |
76 | for( StatecEvent *event in [[self events] allValues] ) {
77 | for( StatecTransition *transition in [event transitions] ) {
78 | NSSet *matching = [[self states] keysOfEntriesPassingTest:^BOOL(id key, id state, BOOL *stop) {
79 | return [[state name] isEqualToString:[[transition targetState] name]];
80 | }];
81 |
82 | if( [matching count] < 1 ) {
83 | [issues addObject:[NSString stringWithFormat:@"State '%@' declares event '%@' should transition to non-existent state", [[transition sourceState] name], [event name]]];
84 | }
85 | }
86 | }
87 |
88 | return issues;
89 | }
90 |
91 |
92 | - (BOOL)isMachineValid:(NSArray **)issues {
93 | NSMutableArray *issueList = [NSMutableArray array];
94 | [issueList addObjectsFromArray:[self validatesInitialStateIsDefined]];
95 | [issueList addObjectsFromArray:[self validatesEventTransitions]];
96 | if( [issueList count] > 0 ) {
97 | *issues = issueList;
98 | NSLog( @"INVALID MACHINE" );
99 | return NO;
100 | } else {
101 | NSLog( @"VALID MACHINE" );
102 | return YES;
103 | }
104 | }
105 |
106 |
107 |
108 |
109 | @end
110 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecParser.h:
--------------------------------------------------------------------------------
1 | //
2 | // MMStatecParser.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 | @class StatecParser;
14 |
15 | @protocol StatecParserDelegate
16 |
17 | - (void)parser:(StatecParser *)parser syntaxError:(NSString *)message token:(CPToken *)token expected:(NSSet *)expected;
18 | - (void)parser:(StatecParser *)parser unexpectedToken:(CPToken *)token expected:(NSSet *)expected;
19 |
20 | @end
21 |
22 |
23 | @interface StatecParser : NSObject
24 |
25 | - (CPTokeniser *)tokenizer;
26 | - (CPGrammar *)grammar;
27 | - (CPParser *)parser;
28 | - (CPTokenStream *)tokenStream:(NSString *)source;
29 | - (id)parse:(NSString *)source;
30 |
31 | @property id delegate;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecParser.m:
--------------------------------------------------------------------------------
1 | //
2 | // MMStatecParser.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecParser.h"
10 |
11 | #import
12 |
13 | @implementation StatecParser
14 |
15 | @synthesize delegate = _delegate;
16 |
17 |
18 | - (CPTokeniser *)tokenizer {
19 | CPTokeniser *tokenizer = [[CPTokeniser alloc] init];
20 |
21 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"{"]];
22 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"}"]];
23 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"=>"]];
24 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"@machine"]];
25 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"@initial"]];
26 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"@state"]];
27 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"@event"]];
28 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"@enter"]];
29 | [tokenizer addTokenRecogniser:[CPKeywordRecogniser recogniserForKeyword:@"@exit"]];
30 | [tokenizer addTokenRecogniser:[CPQuotedRecogniser quotedRecogniserWithStartQuote:@"\"" endQuote:@"\"" name:@"String"]];
31 | [tokenizer addTokenRecogniser:[CPQuotedRecogniser quotedRecogniserWithStartQuote:@"/*" endQuote:@"*/" name:@"Comment"]];
32 | [tokenizer addTokenRecogniser:[CPQuotedRecogniser quotedRecogniserWithStartQuote:@"//" endQuote:@"\n" name:@"Comment"]];
33 | [tokenizer addTokenRecogniser:[CPWhiteSpaceRecogniser whiteSpaceRecogniser]];
34 |
35 | [tokenizer setDelegate:self];
36 |
37 | return tokenizer;
38 | }
39 |
40 |
41 | - (BOOL)tokeniser:(CPTokeniser *)tokeniser shouldConsumeToken:(CPToken *)token {
42 | return YES;
43 | }
44 |
45 |
46 | - (NSArray *)tokeniser:(CPTokeniser *)tokeniser willProduceToken:(CPToken *)token {
47 | if( [token isKindOfClass:[CPWhiteSpaceToken class]] || [[token name] isEqualToString:@"Comment"] ) {
48 | return [NSArray array];
49 | } else {
50 | return [NSArray arrayWithObject:token];
51 | }
52 | }
53 |
54 |
55 | - (CPGrammar *)grammar {
56 | CPGrammar *grammar = [[CPGrammar alloc] initWithStart:@"StatecMachine"
57 | backusNaurForm:
58 | @"0 StatecMachine ::= \"@machine\" \"String\" \"{\" + \"}\" ;"
59 | @"1 StatecInitial ::= \"@initial\" \"String\" ;"
60 | @"2 StatecState ::= \"@state\" \"String\" \"{\" ? ? * \"}\" ;"
61 | @"3 StatecEnter ::= \"@enter\" ;"
62 | @"4 StatecExit ::= \"@exit\" ;"
63 | @"5 StatecEvent ::= \"@event\" \"String\" \"=>\" \"String\" ;"];
64 |
65 | return grammar;
66 | }
67 |
68 |
69 | - (CPParser *)parser {
70 | return [CPLALR1Parser parserWithGrammar:[self grammar]];
71 | }
72 |
73 |
74 | - (NSUInteger)tokeniser:(CPTokeniser *)tokeniser didNotFindTokenOnInput:(NSString *)input position:(NSUInteger)position error:(NSString **)errorMessage {
75 | *errorMessage = [NSString stringWithFormat:@"unexpected character '%c' in input", [input characterAtIndex:0]];
76 | return NSNotFound;
77 | }
78 |
79 |
80 | - (CPTokenStream *)tokenStream:(NSString *)source {
81 | return [[self tokenizer] tokenise:source];
82 | }
83 |
84 |
85 | - (CPRecoveryAction *)parser:(CPParser *)parser didEncounterErrorOnInput:(CPTokenStream *)inputStream expecting:(NSSet *)acceptableTokens {
86 | CPToken *errorToken = [inputStream peekToken];
87 |
88 | if( [errorToken isKindOfClass:[CPErrorToken class]] ) {
89 | [[self delegate] parser:self syntaxError:[(CPErrorToken*)errorToken errorMessage] token:errorToken expected:acceptableTokens];
90 | // NSLog( @"Unexpected token at line:%ld col:%ld", [errorToken lineNumber], [errorToken columnNumber] );
91 | // NSLog( @"Error:%@", [(CPErrorToken*)errorToken errorMessage] );
92 | } else {
93 | [[self delegate] parser:self unexpectedToken:errorToken expected:acceptableTokens];
94 | NSLog( @"Unexpected %@ token at line:%ld col:%ld", [errorToken name], [errorToken lineNumber], [errorToken columnNumber] );
95 | // NSLog( @"Expecting one of: %@", [tokenNames componentsJoinedByString:@","] );
96 | }
97 | return [CPRecoveryAction recoveryActionStop];
98 | }
99 |
100 |
101 |
102 | - (id)parse:(NSString *)source {
103 | NSLog( @"calling parse" );
104 | CPParser *parser = [self parser];
105 | [parser setDelegate:self];
106 |
107 | CPTokenStream *tokens = [self tokenStream:source];
108 |
109 | id result = [parser parse:tokens];
110 | return result;
111 | }
112 |
113 |
114 | @end
115 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecState.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecState.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 | @class StatecMachine;
14 |
15 |
16 | @interface StatecState : NSObject
17 |
18 | @property (strong) NSString *name;
19 | @property (assign) BOOL wantsEnter;
20 | @property (assign) BOOL wantsExit;
21 | @property (strong,readonly) NSArray *events;
22 |
23 | - (BOOL)respondsToEventName:(NSString *)eventName;
24 |
25 | - (NSString *)enterStateMethodName;
26 | - (NSString *)exitStateMethodName;
27 |
28 | - (NSString *)stateVariableName;
29 |
30 | - (NSString *)stateClassNameInMachine:(StatecMachine *)machine;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecState.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecState.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecState.h"
10 |
11 | #import "StatecEnter.h"
12 | #import "StatecExit.h"
13 | #import "StatecEvent.h"
14 | #import "StatecMachine.h"
15 |
16 | #import "NSString+StatecExtensions.h"
17 |
18 | @implementation StatecState
19 |
20 | @synthesize name = _name;
21 | @synthesize wantsEnter = _wantsEnter;
22 | @synthesize wantsExit = _wantsExit;
23 | @synthesize events = _events;
24 |
25 | - (id)initWithSyntaxTree:(CPSyntaxTree *)syntaxTree {
26 | self = [super init];
27 | if( self ) {
28 | NSArray *children = [syntaxTree children];
29 |
30 | _name = [[children objectAtIndex:1] content];
31 |
32 | NSArray *enter = [children objectAtIndex:3];
33 | if( [enter count] > 0 && [[enter objectAtIndex:0] isKindOfClass:[StatecEnter class]] ) {
34 | _wantsEnter = YES;
35 | } else {
36 | _wantsEnter = NO;
37 | }
38 |
39 | NSArray *exit = [children objectAtIndex:4];
40 | if( [exit count] > 0 && [[exit objectAtIndex:0] isKindOfClass:[StatecExit class]] ) {
41 | _wantsExit = YES;
42 | } else {
43 | _wantsExit = NO;
44 | }
45 |
46 | _events = [children objectAtIndex:5];
47 | }
48 | return self;
49 | }
50 |
51 | - (BOOL)respondsToEventName:(NSString *)eventName {
52 | for( StatecEvent *event in [self events] ) {
53 | if( [[event name] isEqualToString:eventName] ) {
54 | return YES;
55 | }
56 | }
57 |
58 | return NO;
59 | }
60 |
61 |
62 | - (NSString *)enterStateMethodName {
63 | return [NSString stringWithFormat:@"enter%@State", [[self name] statecStringByCapitalisingFirstLetter]];
64 | }
65 |
66 |
67 | - (NSString *)exitStateMethodName {
68 | return [NSString stringWithFormat:@"exit%@State", [[self name] statecStringByCapitalisingFirstLetter]];
69 | }
70 |
71 |
72 | - (NSString *)stateVariableName {
73 | return [NSString stringWithFormat:@"_%@State", [[self name] statecStringByLoweringFirstLetter]];
74 | }
75 |
76 |
77 | - (NSString *)stateClassNameInMachine:(StatecMachine *)machine {
78 | return [NSString stringWithFormat:@"%@%@State",[machine name],[[self name] statecStringByCapitalisingFirstLetter]];
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecTransition.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecTransition.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class StatecEvent;
12 | @class StatecState;
13 |
14 | @interface StatecTransition : NSObject
15 |
16 | @property (strong) StatecState *sourceState;
17 | @property (strong) StatecState *targetState;
18 |
19 | - (id)initWithSourceState:(StatecState *)sourceState targetState:(StatecState *)targetState;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/Statec/Parser/StatecTransition.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecTransition.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecTransition.h"
10 |
11 | #import "Statec.h"
12 |
13 | @implementation StatecTransition
14 |
15 | @synthesize sourceState = _sourceState;
16 | @synthesize targetState = _targetState;
17 |
18 | - (id)initWithSourceState:(StatecState *)sourceState targetState:(StatecState *)targetState {
19 | self = [super init];
20 | if( self ) {
21 | _sourceState = sourceState;
22 | _targetState = targetState;
23 | }
24 | return self;
25 | }
26 |
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Statec/Statec-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'Statec' target in the 'Statec' project
3 | //
4 |
5 | #ifdef __OBJC__
6 | #import
7 | #endif
8 |
--------------------------------------------------------------------------------
/Statec/Statec.1:
--------------------------------------------------------------------------------
1 | .\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
2 | .\"See Also:
3 | .\"man mdoc.samples for a complete listing of options
4 | .\"man mdoc for the short list of editing options
5 | .\"/usr/share/misc/mdoc.template
6 | .Dd 30/01/2012 \" DATE
7 | .Dt Statec 1 \" Program name and manual section number
8 | .Os Darwin
9 | .Sh NAME \" Section Header - required - don't modify
10 | .Nm Statec,
11 | .\" The following lines are read in generating the apropos(man -k) database. Use only key
12 | .\" words here as the database is built based on the words here and in the .ND line.
13 | .Nm Other_name_for_same_program(),
14 | .Nm Yet another name for the same program.
15 | .\" Use .Nm macro to designate other names for the documented program.
16 | .Nd This line parsed for whatis database.
17 | .Sh SYNOPSIS \" Section Header - required - don't modify
18 | .Nm
19 | .Op Fl abcd \" [-abcd]
20 | .Op Fl a Ar path \" [-a path]
21 | .Op Ar file \" [file]
22 | .Op Ar \" [file ...]
23 | .Ar arg0 \" Underlined argument - use .Ar anywhere to underline
24 | arg2 ... \" Arguments
25 | .Sh DESCRIPTION \" Section Header - required - don't modify
26 | Use the .Nm macro to refer to your program throughout the man page like such:
27 | .Nm
28 | Underlining is accomplished with the .Ar macro like this:
29 | .Ar underlined text .
30 | .Pp \" Inserts a space
31 | A list of items with descriptions:
32 | .Bl -tag -width -indent \" Begins a tagged list
33 | .It item a \" Each item preceded by .It macro
34 | Description of item a
35 | .It item b
36 | Description of item b
37 | .El \" Ends the list
38 | .Pp
39 | A list of flags and their descriptions:
40 | .Bl -tag -width -indent \" Differs from above in tag removed
41 | .It Fl a \"-a flag as a list item
42 | Description of -a flag
43 | .It Fl b
44 | Description of -b flag
45 | .El \" Ends the list
46 | .Pp
47 | .\" .Sh ENVIRONMENT \" May not be needed
48 | .\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
49 | .\" .It Ev ENV_VAR_1
50 | .\" Description of ENV_VAR_1
51 | .\" .It Ev ENV_VAR_2
52 | .\" Description of ENV_VAR_2
53 | .\" .El
54 | .Sh FILES \" File used or created by the topic of the man page
55 | .Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
56 | .It Pa /usr/share/file_name
57 | FILE_1 description
58 | .It Pa /Users/joeuser/Library/really_long_file_name
59 | FILE_2 description
60 | .El \" Ends the list
61 | .\" .Sh DIAGNOSTICS \" May not be needed
62 | .\" .Bl -diag
63 | .\" .It Diagnostic Tag
64 | .\" Diagnostic informtion here.
65 | .\" .It Diagnostic Tag
66 | .\" Diagnostic informtion here.
67 | .\" .El
68 | .Sh SEE ALSO
69 | .\" List links in ascending order by section, alphabetically within a section.
70 | .\" Please do not reference files that do not exist without filing a bug report
71 | .Xr a 1 ,
72 | .Xr b 1 ,
73 | .Xr c 1 ,
74 | .Xr a 2 ,
75 | .Xr b 2 ,
76 | .Xr a 3 ,
77 | .Xr b 3
78 | .\" .Sh BUGS \" Document known, unremedied bugs
79 | .\" .Sh HISTORY \" Document history if command behaves in a unique manner
--------------------------------------------------------------------------------
/Statec/Statec.h:
--------------------------------------------------------------------------------
1 | //
2 | // Statec.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #ifndef Statec_Statec_h
10 | #define Statec_Statec_h
11 |
12 | typedef enum {
13 | StatecInstanceScope = 1,
14 | StaticClassScope = 2,
15 | StatecGlobalScope = 4,
16 | StatecStaticScope = 8
17 | } StatecScope;
18 |
19 |
20 | #import "StatecCompilationUnit.h"
21 | #import "StatecEnumeration.h"
22 | #import "StatecType.h"
23 | #import "StatecTypedef.h"
24 | #import "StatecClass.h"
25 | #import "StatecMethod.h"
26 | #import "StatecArgument.h"
27 | #import "StatecProperty.h"
28 | #import "StatecVariable.h"
29 | #import "StatecStatement.h"
30 | #import "StatecCodeStatement.h"
31 | #import "StatecConditionalStatement.h"
32 | #import "StatecStatementGroup.h"
33 |
34 | #import "StatecParser.h"
35 | #import "StatecMachine.h"
36 | #import "StatecInitial.h"
37 | #import "StatecState.h"
38 | #import "StatecEnter.h"
39 | #import "StatecExit.h"
40 | #import "StatecEvent.h"
41 | #import "StatecTransition.h"
42 |
43 | #import "StatecCompiler.h"
44 |
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/Statec/StatecEvent.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecEvent.h
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 |
14 | @interface StatecEvent : NSObject
15 |
16 | @property (strong) NSString *name;
17 | @property (strong) NSString *targetState;
18 | @property (strong) NSMutableArray *transitions;
19 |
20 | - (NSString *)callbackMethodName;
21 | - (NSString *)internalCallbackMethodName;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Statec/StatecEvent.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecEvent.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 31/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import "StatecEvent.h"
10 |
11 | #import "NSString+StatecExtensions.h"
12 |
13 | @implementation StatecEvent
14 |
15 | @synthesize name = _name;
16 | @synthesize targetState = _targetState;
17 | @synthesize transitions = _transitions;
18 |
19 |
20 | - (id)init {
21 | self = [super init];
22 | if( self ) {
23 | _transitions = [NSMutableArray array];
24 | }
25 | return self;
26 | }
27 |
28 |
29 | - (id)initWithSyntaxTree:(CPSyntaxTree *)syntaxTree {
30 | self = [self init];
31 | if( self ) {
32 | NSAssert( 4 == [[syntaxTree children] count], @"StatecEvent must have exactly 4 children" );
33 | _name = [[[syntaxTree children] objectAtIndex:1] content];
34 | _targetState = [[[syntaxTree children] objectAtIndex:3] content];
35 | }
36 | return self;
37 | }
38 |
39 |
40 | - (NSString *)callbackMethodName {
41 | return [NSString stringWithFormat:@"%@Event", [[self name] statecStringByLoweringFirstLetter]];
42 | }
43 |
44 |
45 | - (NSString *)internalCallbackMethodName {
46 | return [NSString stringWithFormat:@"%@EventFromMachine:", [[self name] statecStringByLoweringFirstLetter]];
47 | }
48 |
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/Statec/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Statec
4 | //
5 | // Created by Matt Mower on 30/01/2012.
6 | // Copyright (c) 2012 SmartFish Software Ltd.. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 | #import "Statec.h"
14 |
15 | #import "StatecGVBuilder.h"
16 | #import "StatecHTMLBuilder.h"
17 |
18 | int main (int argc, const char * argv[])
19 | {
20 | @autoreleasepool {
21 | NSError *error;
22 |
23 | NSString *outputFolder;
24 | NSString *inputFile;
25 |
26 | BOOL overwriteUserFiles = NO, generateGraph = NO, generateHTML = NO;
27 |
28 | int ch;
29 | while( ( ch = getopt( argc, (char *const*)argv, "d:i:ogh" ) ) != -1 ) {
30 | switch( ch ) {
31 | case 'd':
32 | outputFolder = [[NSString alloc] initWithUTF8String:optarg];
33 | break;
34 | case 'i':
35 | inputFile = [[NSString alloc] initWithUTF8String:optarg];
36 | break;
37 | case 'o':
38 | overwriteUserFiles = YES;
39 | break;
40 | case 'g':
41 | generateGraph = YES;
42 | break;
43 | case 'h':
44 | generateHTML = YES;
45 | break;
46 | }
47 | }
48 |
49 | if( !outputFolder ) {
50 | outputFolder = @"./";
51 | }
52 |
53 | if( !inputFile ) {
54 | NSLog( @"No input file specified." );
55 | return -1;
56 | }
57 |
58 | inputFile = [inputFile stringByExpandingTildeInPath];
59 | outputFolder = [outputFolder stringByExpandingTildeInPath];
60 |
61 | NSFileManager *fileManager = [NSFileManager defaultManager];
62 | BOOL isDirectory;
63 | if( ![fileManager fileExistsAtPath:outputFolder isDirectory:&isDirectory] || !isDirectory ) {
64 | NSLog( @"Output folder \"%@\" does not exist, or is not a directory", outputFolder );
65 | return -1;
66 | }
67 |
68 | NSString *source = [[NSString alloc] initWithContentsOfFile:inputFile encoding:NSUTF8StringEncoding error:&error];
69 | if( !source ) {
70 | NSLog( @"Cannot read source: \"%@\" %@", inputFile, [error localizedDescription] );
71 | return -1;
72 | }
73 |
74 | StatecCompiler *compiler = [[StatecCompiler alloc] init];
75 | if( !compiler ) {
76 | NSLog( @"Cannot initialize compiler" );
77 | return -1;
78 | }
79 |
80 | if( ![compiler parse:source] ) {
81 | NSLog( @"Compiler error" );
82 | return -1;
83 | }
84 |
85 | NSArray *issues;
86 | if( ![compiler isMachineValid:&issues] ) {
87 | NSLog( @"Machine definition is invalid (%ld issues):", [issues count] );
88 | for( NSString *issue in issues ) {
89 | NSLog( @"\t%@", issue );
90 | }
91 | return -1;
92 | }
93 |
94 | StatecCompilationUnit *unit = [compiler generatedMachine];
95 | if( ![unit writeFilesTo:outputFolder error:&error] ) {
96 | NSLog( @"Cannot write class files: %@", [error localizedDescription] );
97 | return -1;
98 | }
99 |
100 | unit = [compiler userMachine];
101 | if( overwriteUserFiles || ![fileManager fileExistsAtPath:[outputFolder stringByAppendingPathComponent:[unit headerFileName]]] ) {
102 | NSLog( @"No user file exists, writing user machine." );
103 | if( ![unit writeFilesTo:outputFolder error:&error] ) {
104 | NSLog( @"Cannot write class files %@", [error localizedDescription] );
105 | return -1;
106 | }
107 | } else {
108 | NSLog( @"User machine already exists." );
109 | }
110 |
111 | if( generateGraph ) {
112 | NSString *graphFileName = [outputFolder stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.gv",[[compiler machine] name]]];
113 | StatecGVBuilder *gvBuilder = [[StatecGVBuilder alloc] init];
114 | NSString *gvSource = [gvBuilder gvSourceFromMachine:[compiler machine]];
115 | [gvSource writeToFile:graphFileName
116 | atomically:NO
117 | encoding:NSUTF8StringEncoding error:nil];
118 |
119 |
120 | NSString *pathEnv = [[[NSProcessInfo processInfo] environment] objectForKey:@"PATH"];
121 | NSArray *paths = [pathEnv componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]];
122 | for( NSString *path in paths ) {
123 | if( [fileManager fileExistsAtPath:[path stringByAppendingPathComponent:@"dot"]] ) {
124 | NSLog( @"Generating image file" );
125 | NSTask *dotTask = [NSTask launchedTaskWithLaunchPath:[path stringByAppendingPathComponent:@"dot"]
126 | arguments:[NSArray arrayWithObjects:@"-O",@"-Tpng",graphFileName,nil]];
127 | [dotTask waitUntilExit];
128 | }
129 | }
130 | }
131 |
132 | if( generateHTML ) {
133 | StatecHTMLBuilder *htmlBuilder = [[StatecHTMLBuilder alloc] initWithMachine:[compiler machine]];
134 | if( ![htmlBuilder writeToFolder:outputFolder error:&error] ) {
135 | NSLog( @"Error writing HTML output: %@", [error localizedDescription] );
136 | }
137 | }
138 |
139 | }
140 |
141 | return 0;
142 | }
143 |
144 |
--------------------------------------------------------------------------------
/StatecRunner/StatecAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatecAppDelegate.h
3 | // StatecRunner
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "StatecParser.h"
12 |
13 | @interface StatecAppDelegate : NSObject
14 |
15 | @property (assign) IBOutlet NSWindow *window;
16 |
17 | @property (assign) IBOutlet NSPanel *statusPanel;
18 |
19 | @property (strong) NSString *source;
20 | @property (strong) NSString *sourceFile;
21 | @property (strong) NSString *targetFolder;
22 | @property (strong) NSString *statusMessage;
23 |
24 | - (IBAction)pickSourceFile:(id)sender;
25 | - (IBAction)pickTargetFolder:(id)sender;
26 | - (IBAction)compile:(id)sender;
27 | - (IBAction)dismissStatus:(id)sender;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/StatecRunner/StatecAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatecAppDelegate.m
3 | // StatecRunner
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import "StatecAppDelegate.h"
10 |
11 | #import "StatecParser.h"
12 | #import "StatecCompiler.h"
13 | #import "StatecCompilationUnit.h"
14 |
15 | @implementation StatecAppDelegate
16 |
17 | @synthesize window = _window;
18 |
19 | @synthesize statusPanel = _statusPanel;
20 |
21 | @synthesize source = _source;
22 | @synthesize sourceFile = _sourceFile;
23 | @synthesize targetFolder = _targetFolder;
24 | @synthesize statusMessage = _statusMessage;
25 |
26 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
27 | [self setSourceFile:@""];
28 | [self setTargetFolder:@""];
29 | [self setStatusMessage:@""];
30 | }
31 |
32 |
33 | - (IBAction)pickSourceFile:(id)sender {
34 | NSOpenPanel *openPanel = [NSOpenPanel openPanel];
35 | [openPanel setCanChooseFiles:YES];
36 | [openPanel setCanChooseDirectories:NO];
37 | [openPanel setAllowsMultipleSelection:NO];
38 | [openPanel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) {
39 | if( NSFileHandlingPanelOKButton == result ) {
40 | NSURL *fileURL = [[openPanel URLs] objectAtIndex:0];
41 | [self setSourceFile:[fileURL path]];
42 | if( [[self targetFolder] isEqualToString:@""] ) {
43 | [self setTargetFolder:[[fileURL path] stringByDeletingLastPathComponent]];
44 | }
45 | }
46 | }];
47 | }
48 |
49 |
50 |
51 | - (IBAction)pickTargetFolder:(id)sender {
52 | NSOpenPanel *openPanel = [NSOpenPanel openPanel];
53 | [openPanel setCanChooseFiles:NO];
54 | [openPanel setCanChooseDirectories:YES];
55 | [openPanel setAllowsMultipleSelection:NO];
56 | [openPanel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) {
57 | if( NSFileHandlingPanelOKButton == result ) {
58 | NSURL *fileURL = [[openPanel URLs] objectAtIndex:0];
59 | [self setTargetFolder:[fileURL path]];
60 | }
61 | }];
62 | }
63 |
64 |
65 | - (IBAction)compile:(id)sender {
66 | NSError *error;
67 | BOOL overwriteUserFiles = NO;
68 |
69 | if( [[self sourceFile] isEqualToString:@""] ) {
70 | NSBeep();
71 | return;
72 | }
73 |
74 | if( [[self targetFolder] isEqualToString:@""] ) {
75 | NSBeep();
76 | return;
77 | }
78 |
79 | [NSApp beginSheet:[self statusPanel] modalForWindow:[self window] modalDelegate:nil didEndSelector:nil contextInfo:nil];
80 |
81 | NSFileManager *fileManager = [NSFileManager defaultManager];
82 | BOOL isDirectory;
83 | if( ![fileManager fileExistsAtPath:[self targetFolder] isDirectory:&isDirectory] || !isDirectory ) {
84 | [self setStatusMessage:[NSString stringWithFormat:@"Output folder \"%@\" does not exist, or is not a directory", [self targetFolder]]];
85 | NSBeep();
86 | return;
87 | }
88 |
89 | [self setSource:[[NSString alloc] initWithContentsOfFile:[self sourceFile] encoding:NSUTF8StringEncoding error:&error]];
90 | if( ![self source] ) {
91 | [self setStatusMessage:[NSString stringWithFormat:@"Cannot read source: \"%@\" %@", [self sourceFile], [error localizedDescription]]];
92 | NSBeep();
93 | return;
94 | }
95 |
96 | StatecCompiler *compiler = [[StatecCompiler alloc] init];
97 | if( !compiler ) {
98 | [self setStatusMessage:@"Cannot initialize compiler"];
99 | NSBeep();
100 | return;
101 | }
102 |
103 | [[compiler parser] setDelegate:self];
104 |
105 | if( ![compiler parse:[self source]] ) {
106 | NSBeep();
107 | return;
108 | }
109 |
110 |
111 | NSArray *issues;
112 | if( ![compiler isMachineValid:&issues] ) {
113 | NSMutableString *errorString = [NSMutableString stringWithFormat:@"Machine definition is invalid (%ld issues):\n", [issues count]];
114 | for( NSString *issue in issues ) {
115 | [errorString appendFormat:@"* %@\n", issue];
116 | }
117 | [self setStatusMessage:errorString];
118 | NSBeep();
119 | return;
120 | } else {
121 | [self setStatusMessage:@"Compiled machine classes"];
122 | }
123 |
124 | StatecCompilationUnit *unit = [compiler generatedMachine];
125 | if( ![unit writeFilesTo:[self targetFolder] error:&error] ) {
126 | [self setStatusMessage:[NSString stringWithFormat:@"Cannot write class files: %@", [error localizedDescription]]];
127 | NSBeep();
128 | return;
129 | } else {
130 | [self setStatusMessage:@"Written machine implementation files"];
131 | }
132 |
133 | unit = [compiler userMachine];
134 | if( overwriteUserFiles || ![fileManager fileExistsAtPath:[[self targetFolder] stringByAppendingPathComponent:[unit headerFileName]]] ) {
135 | if( ![unit writeFilesTo:[self targetFolder] error:&error] ) {
136 | [self setStatusMessage:[NSString stringWithFormat:@"Cannot write class files %@", [error localizedDescription]]];
137 | NSBeep();
138 | return;
139 | }
140 | }
141 | }
142 |
143 |
144 | - (IBAction)dismissStatus:(id)sender {
145 | [NSApp endSheet:[self statusPanel]];
146 | [[self statusPanel] orderOut:sender];
147 | }
148 |
149 |
150 | - (NSString *)sourceLineForToken:(CPToken *)token {
151 | NSUInteger startPosition;
152 | NSUInteger endPosition;
153 | [[self source] getLineStart:&startPosition end:&endPosition contentsEnd:NULL forRange:NSMakeRange( [token characterNumber], 1 )];
154 | return [[self source] substringWithRange:NSMakeRange( startPosition, endPosition-startPosition-1 )];
155 | }
156 |
157 |
158 | - (NSString *)indicatorLine:(NSUInteger)characterPosition {
159 |
160 | NSMutableString *line = [NSMutableString string];
161 | while( characterPosition-- ) {
162 | [line appendString:@"-"];
163 | };
164 | [line appendString:@"^"];
165 | return line;
166 | }
167 |
168 |
169 | - (void)parser:(StatecParser *)parser syntaxError:(NSString *)message token:(CPToken *)token expected:(NSSet *)expected {
170 | [self setStatusMessage:[NSString stringWithFormat:
171 | @"Syntax error on line %ld:%ld\n%@\n%@\n%@\nExpected: %@",
172 | [token lineNumber],
173 | [token columnNumber],
174 | [self sourceLineForToken:token],
175 | [self indicatorLine:[token columnNumber]],
176 | message,
177 | [[expected allObjects] componentsJoinedByString:@","]
178 | ]];
179 | }
180 |
181 |
182 | - (void)parser:(StatecParser *)parser unexpectedToken:(CPToken *)token expected:(NSSet *)expected {
183 | [self setStatusMessage:[NSString stringWithFormat:
184 | @"Unexpected input '%@' on line:%ld:%ld\n%@\n%@\nExpected: %@",
185 | [token name],
186 | [token lineNumber],
187 | [token columnNumber],
188 | [self sourceLineForToken:token],
189 | [self indicatorLine:[token columnNumber]],
190 | [[expected allObjects] componentsJoinedByString:@","]
191 | ]];
192 | }
193 |
194 |
195 | @end
196 |
--------------------------------------------------------------------------------
/StatecRunner/StatecRunner-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | com.mattmower.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 18
25 | LSApplicationCategoryType
26 | public.app-category.developer-tools
27 | LSMinimumSystemVersion
28 | ${MACOSX_DEPLOYMENT_TARGET}
29 | NSHumanReadableCopyright
30 | Copyright © 2012 SmartFish Software Ltd. All rights reserved.
31 | NSMainNibFile
32 | MainMenu
33 | NSPrincipalClass
34 | NSApplication
35 |
36 |
37 |
--------------------------------------------------------------------------------
/StatecRunner/StatecRunner-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'StatecRunner' target in the 'StatecRunner' project
3 | //
4 |
5 | #ifdef __OBJC__
6 | #import
7 | #endif
8 |
--------------------------------------------------------------------------------
/StatecRunner/en.lproj/Credits.rtf:
--------------------------------------------------------------------------------
1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
2 | {\colortbl;\red255\green255\blue255;}
3 | \paperw9840\paperh8400
4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
5 |
6 | \f0\b\fs24 \cf0 Engineering:
7 | \b0 \
8 | Some people\
9 | \
10 |
11 | \b Human Interface Design:
12 | \b0 \
13 | Some other people\
14 | \
15 |
16 | \b Testing:
17 | \b0 \
18 | Hopefully not nobody\
19 | \
20 |
21 | \b Documentation:
22 | \b0 \
23 | Whoever\
24 | \
25 |
26 | \b With special thanks to:
27 | \b0 \
28 | Mom\
29 | }
30 |
--------------------------------------------------------------------------------
/StatecRunner/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/StatecRunner/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // StatecRunner
4 | //
5 | // Created by Matt Mower on 02/02/2012.
6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | int main(int argc, char *argv[])
12 | {
13 | return NSApplicationMain(argc, (const char **)argv);
14 | }
15 |
--------------------------------------------------------------------------------