View Javadoc
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 }