• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LearnLib / automatalib / 13138848026

04 Feb 2025 02:53PM UTC coverage: 92.108% (+2.2%) from 89.877%
13138848026

push

github

mtf90
[maven-release-plugin] prepare release automatalib-0.12.0

16609 of 18032 relevant lines covered (92.11%)

1.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.59
/serialization/fsm/src/main/java/net/automatalib/serialization/fsm/parser/FSM2MealyParserIO.java
1
/* Copyright (C) 2013-2025 TU Dortmund University
2
 * This file is part of AutomataLib <https://automatalib.net>.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.automatalib.serialization.fsm.parser;
17

18
import java.io.IOException;
19
import java.io.StreamTokenizer;
20
import java.util.Collection;
21
import java.util.function.Function;
22
import java.util.stream.Collectors;
23

24
import net.automatalib.automaton.AutomatonCreator;
25
import net.automatalib.automaton.transducer.MealyMachine;
26
import net.automatalib.automaton.transducer.MutableMealyMachine;
27
import net.automatalib.automaton.transducer.impl.CompactMealy;
28
import net.automatalib.common.util.Pair;
29
import net.automatalib.exception.FormatException;
30
import net.automatalib.serialization.ModelDeserializer;
31
import org.checkerframework.checker.nullness.qual.Nullable;
32

33
/**
34
 * Parse a Mealy machine from an FSM source with straightforward edge semantics (as compared to
35
 * {@link FSM2MealyParserAlternating}).
36
 *
37
 * @param <I>
38
 *         the input type
39
 * @param <O>
40
 *         the output type
41
 * @param <A>
42
 *         the parsed automaton type
43
 */
44
public final class FSM2MealyParserIO<I, O, A extends MutableMealyMachine<Integer, I, ?, O>> extends AbstractFSM2MealyParser<I, O, A> {
45

46
    /**
47
     * Constructs a new FSM2MealyParserIO. Use one of the static parse() methods to actually parse an FSM source.
48
     *
49
     * @param targetInputs
50
     *         A collection containing the inputs which should constitute the input alphabet of the parsed automaton.
51
     *         If {@code null}, the inputs will be automatically gathered from the read FSM file.
52
     * @param inputParser
53
     *         the input parser.
54
     * @param outputParser
55
     *         the output parser (similar to {@code inputParser}).
56
     */
57
    private FSM2MealyParserIO(@Nullable Collection<? extends I> targetInputs,
58
                              Function<String, I> inputParser,
59
                              Function<String, O> outputParser,
60
                              AutomatonCreator<A, I> creator) {
61
        super(targetInputs, inputParser, outputParser, creator);
2✔
62
    }
2✔
63

64
    /**
65
     * Parse a transition.
66
     *
67
     * @throws FSMFormatException
68
     *         when the transition is illegal.
69
     * @throws IOException
70
     *         see {@link StreamTokenizer#nextToken()}.
71
     */
72
    @Override
73
    protected void parseTransition(StreamTokenizer streamTokenizer) throws IOException, FormatException {
74
        try {
75

76
            // check we will read a state index
77
            if (streamTokenizer.nextToken() != StreamTokenizer.TT_WORD) {
2✔
78
                throw new FSMFormatException(EXPECT_NUMBER, streamTokenizer);
×
79
            }
80

81
            // read the source state index
82
            int from = Integer.parseInt(streamTokenizer.sval);
2✔
83

84
            // check if such a state exists
85
            if (!getStates().isEmpty() && !getStates().contains(from)) {
2✔
86
                throw new FSMFormatException(String.format(NO_SUCH_STATE, from), streamTokenizer);
×
87
            }
88

89
            // check we will read a state index
90
            if (streamTokenizer.nextToken() != StreamTokenizer.TT_WORD) {
2✔
91
                throw new FSMFormatException(EXPECT_NUMBER, streamTokenizer);
×
92
            }
93

94
            // read the target state index
95
            int to = Integer.parseInt(streamTokenizer.sval);
2✔
96

97
            // check if such a state exists
98
            if (!getStates().isEmpty() && !getStates().contains(to)) {
2✔
99
                throw new FSMFormatException(String.format(NO_SUCH_STATE, to), streamTokenizer);
×
100
            }
101

102
            // check we will read an input edge label
103
            if (streamTokenizer.nextToken() != '"') {
2✔
104
                throw new FSMFormatException(EXPECT_STRING, streamTokenizer);
×
105
            }
106

107
            // read the input, and convert the input string to actual input
108
            final I input = getInputParser().apply(streamTokenizer.sval);
2✔
109

110
            // add it to the set of inputs
111
            getInputs().add(input);
2✔
112

113
            // check we will read an output edge label
114
            if (streamTokenizer.nextToken() != '"') {
2✔
115
                throw new FSMFormatException(EXPECT_STRING, streamTokenizer);
×
116
            }
117

118
            // read the output, and convert the output string to actual output
119
            final O output = getOutputParser().apply(streamTokenizer.sval);
2✔
120

121
            // create the Mealy machine transition
122
            final Pair<O, Integer> prev = getTransitions().put(Pair.of(from, input), Pair.of(output, to));
2✔
123

124
            // check for non-determinism
125
            if (prev != null) {
2✔
126
                throw new FSMFormatException(String.format(NON_DETERMINISM_DETECTED, prev), streamTokenizer);
×
127
            }
128
        } catch (NumberFormatException nfe) {
×
129
            throw new FSMFormatException(nfe, streamTokenizer);
×
130
        }
2✔
131
    }
2✔
132

133
    @Override
134
    protected void checkTransitions(StreamTokenizer streamTokenizer) {
135
        // Only if no states are defined we add all from the transitions we found.
136
        // This is necessary because states are not necessarily defined in FSMs.
137
        if (getStates().isEmpty()) {
2✔
138
            getStates().addAll(getTransitions().keySet().stream().map(Pair::getFirst).collect(Collectors.toList()));
×
139
        }
140
    }
2✔
141

142
    /**
143
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a
144
     * {@link CompactMealy}.
145
     *
146
     * @param edgeParser
147
     *         the transformer of String representatives to (same-typed) input/output symbols
148
     * @param <E>
149
     *         symbol type
150
     *
151
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
152
     */
153
    public static <E> ModelDeserializer<CompactMealy<E, E>> getParser(Function<String, E> edgeParser) {
154
        return getParser(edgeParser, edgeParser);
2✔
155
    }
156

157
    /**
158
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a
159
     * {@link CompactMealy}.
160
     *
161
     * @param inputParser
162
     *         the transformer of String representatives to input alphabet symbols
163
     * @param outputParser
164
     *         the transformer of String representatives to output alphabet symbols
165
     * @param <I>
166
     *         input symbol type
167
     * @param <O>
168
     *         output symbol type
169
     *
170
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
171
     */
172
    public static <I, O> ModelDeserializer<CompactMealy<I, O>> getParser(Function<String, I> inputParser,
173
                                                                         Function<String, O> outputParser) {
174
        return getParser(null, inputParser, outputParser);
2✔
175
    }
176

177
    /**
178
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a
179
     * {@link CompactMealy}.
180
     *
181
     * @param targetInputs
182
     *         the collection of symbols the parsing should be constrained to (may be {@code null} if unconstrained)
183
     * @param edgeParser
184
     *         the transformer of String representatives to (same-typed) input/output symbols
185
     * @param <E>
186
     *         symbol type
187
     *
188
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
189
     */
190
    public static <E> ModelDeserializer<CompactMealy<E, E>> getParser(@Nullable Collection<? extends E> targetInputs,
191
                                                                      Function<String, E> edgeParser) {
192
        return getParser(targetInputs, edgeParser, edgeParser);
2✔
193
    }
194

195
    /**
196
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a
197
     * {@link CompactMealy}.
198
     *
199
     * @param targetInputs
200
     *         the collection of symbols the parsing should be constrained to (may be {@code null} if unconstrained)
201
     * @param inputParser
202
     *         the transformer of String representatives to input alphabet symbols
203
     * @param outputParser
204
     *         the transformer of String representatives to output alphabet symbols
205
     * @param <I>
206
     *         input symbol type
207
     * @param <O>
208
     *         output symbol type
209
     *
210
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
211
     */
212
    public static <I, O> ModelDeserializer<CompactMealy<I, O>> getParser(@Nullable Collection<? extends I> targetInputs,
213
                                                                         Function<String, I> inputParser,
214
                                                                         Function<String, O> outputParser) {
215
        return getParser(targetInputs, inputParser, outputParser, new CompactMealy.Creator<>());
2✔
216
    }
217

218
    /**
219
     * Constructs a {@link ModelDeserializer} that reads a {@link MealyMachine} description and writes it into a given
220
     * {@link MutableMealyMachine}.
221
     *
222
     * @param targetInputs
223
     *         the collection of symbols the parsing should be constrained to (may be {@code null} if unconstrained)
224
     * @param inputParser
225
     *         the transformer of String representatives to input alphabet symbols
226
     * @param outputParser
227
     *         the transformer of String representatives to output alphabet symbols
228
     * @param creator
229
     *         the creator to construct the concrete automaton instance
230
     * @param <I>
231
     *         input symbol type
232
     * @param <O>
233
     *         output symbol type
234
     * @param <A>
235
     *         (concrete) automaton type
236
     *
237
     * @return a {@link ModelDeserializer} that reads a {@link MealyMachine} description
238
     */
239
    public static <I, O, A extends MutableMealyMachine<Integer, I, ?, O>> ModelDeserializer<A> getParser(@Nullable Collection<? extends I> targetInputs,
240
                                                                                                         Function<String, I> inputParser,
241
                                                                                                         Function<String, O> outputParser,
242
                                                                                                         AutomatonCreator<A, I> creator) {
243
        return new FSM2MealyParserIO<>(targetInputs, inputParser, outputParser, creator);
2✔
244
    }
245
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc