1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.utils.lexical;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.Reader;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24
25 import org.hipparchus.exception.DummyLocalizable;
26 import org.orekit.data.DataSource;
27 import org.orekit.errors.OrekitException;
28 import org.orekit.errors.OrekitMessages;
29 import org.orekit.files.ccsds.utils.FileFormat;
30 import org.orekit.utils.units.Unit;
31 import org.orekit.utils.units.UnitsCache;
32
33
34
35
36
37 public class KvnLexicalAnalyzer implements LexicalAnalyzer {
38
39
40 private static final String LINE_START = "^\\p{Blank}*";
41
42
43 private static final String COMMENT_KEY = "(COMMENT)\\p{Blank}*";
44
45
46 private static final String NON_COMMENT_KEY = "([A-Z][A-Z_0-9]*)\\p{Blank}*=\\p{Blank}*";
47
48
49 private static final String START_KEY = "([A-Z][A-Z_0-9]*)_START";
50
51
52 private static final String STOP_KEY = "([A-Z][A-Z_0-9]*)_STOP";
53
54
55 private static final String OPTIONAL_VALUE = "((?:(?:\\p{Graph}.*?)?))";
56
57
58 private static final String UNITS_OPERATORS = "-+*×.·/⁄^√⁺⁻";
59
60
61 private static final String UNITS_LETTERS = "A-Za-zµμ";
62
63
64 private static final String UNITS_DIGITS = "0-9⁰¹²³⁴⁵⁶⁷⁸⁹";
65
66
67 private static final String UNITS_FRACTIONS = "¼½¾⅐⅑⅒⅓⅔⅕⅖⅗⅘⅙⅚⅛⅜⅝⅞";
68
69
70 private static final String UNITS_SYMBOLS = "%°◦′'″\\\"#";
71
72
73 private static final String UNITS_PARENTHESES = "()";
74
75
76 private static final String UNITS = "(?:\\p{Blank}+\\[([" +
77 UNITS_OPERATORS + UNITS_LETTERS + UNITS_DIGITS +
78 UNITS_FRACTIONS + UNITS_SYMBOLS + UNITS_PARENTHESES +
79 "]*)\\])?";
80
81
82 private static final String LINE_END = "\\p{Blank}*$";
83
84
85 private static final Pattern COMMENT_ENTRY = Pattern.compile(LINE_START + COMMENT_KEY + OPTIONAL_VALUE + LINE_END);
86
87
88
89
90
91
92 private static final Pattern NON_COMMENT_ENTRY = Pattern.compile(LINE_START + NON_COMMENT_KEY + OPTIONAL_VALUE + UNITS + LINE_END);
93
94
95 private static final Pattern START_ENTRY = Pattern.compile(LINE_START + START_KEY + LINE_END);
96
97
98 private static final Pattern STOP_ENTRY = Pattern.compile(LINE_START + STOP_KEY + LINE_END);
99
100
101 private final DataSource source;
102
103
104 private final UnitsCache cache;
105
106
107
108
109 public KvnLexicalAnalyzer(final DataSource source) {
110 this.source = source;
111 this.cache = new UnitsCache();
112 }
113
114
115 @Override
116 public <T> T accept(final MessageParser<T> messageParser) {
117
118 messageParser.reset(FileFormat.KVN);
119
120 try (Reader reader = source.getOpener().openReaderOnce();
121 BufferedReader br = (reader == null) ? null : new BufferedReader(reader)) {
122
123 if (br == null) {
124 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, source.getName());
125 }
126
127 int lineNumber = 0;
128 for (String line = br.readLine(); line != null; line = br.readLine()) {
129 ++lineNumber;
130 if (line.trim().length() == 0) {
131 continue;
132 }
133
134 final Matcher nonComment = NON_COMMENT_ENTRY.matcher(line);
135 if (nonComment.matches()) {
136
137 final Unit units = cache.getUnits(nonComment.groupCount() > 2 ? nonComment.group(3) : null);
138 messageParser.process(new ParseToken(TokenType.ENTRY,
139 nonComment.group(1), nonComment.group(2),
140 units, lineNumber, source.getName()));
141 } else {
142 final Matcher comment = COMMENT_ENTRY.matcher(line);
143 if (comment.matches()) {
144
145 messageParser.process(new ParseToken(TokenType.ENTRY,
146 comment.group(1), comment.group(2), null,
147 lineNumber, source.getName()));
148 } else {
149 final Matcher start = START_ENTRY.matcher(line);
150 if (start.matches()) {
151
152 messageParser.process(new ParseToken(TokenType.START,
153 start.group(1), null, null,
154 lineNumber, source.getName()));
155 } else {
156 final Matcher stop = STOP_ENTRY.matcher(line);
157 if (stop.matches()) {
158
159 messageParser.process(new ParseToken(TokenType.STOP,
160 stop.group(1), null, null,
161 lineNumber, source.getName()));
162 } else {
163
164 messageParser.process(new ParseToken(TokenType.RAW_LINE,
165 null, line, null,
166 lineNumber, source.getName()));
167 }
168 }
169 }
170 }
171
172 }
173
174 return messageParser.build();
175
176 } catch (IOException ioe) {
177 throw new OrekitException(ioe, new DummyLocalizable(ioe.getMessage()));
178 }
179 }
180
181 }