1 /*******************************************************************************
2 * jArduino: Arduino C++ Code Generation From Java
3 * Copyright 2020 Tony Washer
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ******************************************************************************/
17 package net.sourceforge.jarduino.message;
18
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import net.sourceforge.jarduino.ArduinoException;
23 import net.sourceforge.jarduino.message.ArduinoParser.ArduinoParserException;
24
25 /**
26 * Comments.
27 */
28 public class ArduinoComments {
29 /**
30 * The Marker.
31 */
32 static final String MARKER = "CM_";
33
34 /**
35 * The map of comments.
36 */
37 private Map<ArduinoNamedObject, String> theComments;
38
39 /**
40 * Constructor.
41 */
42 ArduinoComments() {
43 theComments = new HashMap<>();
44 }
45
46 /**
47 * Obtain the comment for an object (if any).
48 * @param pObject the object
49 * @return the comment (or null)
50 */
51 public String getCommentForObject(final ArduinoNamedObject pObject) {
52 return theComments.get(pObject);
53 }
54
55 /**
56 * Store the comment for an object.
57 * @param pObject the object
58 * @param pComment the comment
59 */
60 void storeCommentForObject(final ArduinoNamedObject pObject,
61 final String pComment) {
62 theComments.put(pObject, pComment);
63 }
64
65 /**
66 * parse the comment definition.
67 * @param pSystem the system
68 * @param pCommentDef the comment definition
69 * @throws ArduinoException on error
70 */
71 public static void parseComment(final ArduinoSystem pSystem,
72 final String pCommentDef) throws ArduinoException {
73 /* Marker is first token in header */
74 final String myMarker = ArduinoParser.nextToken(pCommentDef);
75 String myDef = ArduinoParser.stripToken(pCommentDef, myMarker);
76 if (!myMarker.equals(MARKER)) {
77 throw new ArduinoException("Invalid marker", pCommentDef);
78 }
79
80 /* Split out id/comment */
81 final int myIndex = myDef.indexOf(ArduinoChar.QUOTE);
82 if (myIndex == -1) {
83 throw new ArduinoException("Missing " + ArduinoChar.QUOTE + " separator", pCommentDef);
84 }
85 String myId = myDef.substring(0, myIndex);
86 myDef = myDef.substring(myIndex);
87
88 /* Check that the end character is semicolon */
89 final int myLen = myDef.length();
90 if (myDef.length() == 0 || myDef.charAt(myLen - 1) != ArduinoChar.SEMICOLON) {
91 throw new ArduinoException("Missing terminator", pCommentDef);
92 }
93 myDef = myDef.substring(0, myLen - 1);
94
95 /* Protect against exceptions */
96 try {
97 /* Comments is final token */
98 final String myComment = ArduinoParser.nextQuotedToken(myDef);
99
100 /* The next tokens are the object type and id */
101 final String myType = ArduinoParser.nextToken(myId);
102 myId = ArduinoParser.stripToken(myId, myType);
103
104 /* Determine the target for the comment */
105 final ArduinoNamedObject myTarget = determineTarget(pSystem, myType, myId);
106
107 /* Store the comment */
108 pSystem.storeCommentForObject(myTarget, myComment);
109
110 /* Handle parser exceptions */
111 } catch (ArduinoParserException e) {
112 throw new ArduinoException(e.getMessage() + ArduinoChar.COLON + e.getDetail(), pCommentDef);
113 }
114 }
115
116 /**
117 * Obtain the target.
118 * @param pSystem the system
119 * @param pType the target type
120 * @param pId the target id
121 * @return the object
122 * @throws ArduinoParserException on error
123 */
124 private static ArduinoNamedObject determineTarget(final ArduinoSystem pSystem,
125 final String pType,
126 final String pId) throws ArduinoParserException {
127 /* If this is a system */
128 if (pType.length() == 0) {
129 return pSystem;
130 }
131
132 /* If this is a node */
133 if (pType.equals(ArduinoNode.MARKER)) {
134 return pSystem.findNodeByName(pId);
135 }
136
137 /* MsgId is the next token */
138 final String myId = ArduinoParser.nextToken(pId);
139 final String mySignal = ArduinoParser.stripToken(pId, myId);
140 final ArduinoMessage myMessage = pSystem.findMessageById(myId);
141
142 /* If this is a message */
143 if (pType.equals(ArduinoMessage.MARKER)) {
144 return myMessage;
145 }
146
147 /* If this is a signal */
148 if (pType.equals(ArduinoSignal.MARKER)) {
149 return myMessage.findSignalByName(mySignal);
150 }
151
152 /* Unrecognised marker */
153 throw new ArduinoParserException("Invalid comment type", pType);
154 }
155 }