1
0
Fork 0
cl-sites/w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/html/StateModelImplementation.html
2025-01-28 10:11:14 +01:00

934 lines
No EOL
64 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>1.7. Extended Example: Text Parser State Machine &mdash; Computer Systems Fundamentals</title>
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
<style>
.underline { text-decoration: underline; }
</style>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '0.4.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": {
scale: "80"
}
});
</script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
<link rel="next" title="1. Processes and OS Basics" href="ProcessesOverview.html" />
<link rel="prev" title="6. Sequence Models in UML" href="SequenceModels.html" />
</head><body>
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
<!-- Show a navbar toggler on mobile -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="defaultNavbars">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle jmu-gold rounded" href="StateModelImplementation.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
<a class="dropdown-item" tabindex="-1" href="StateModelImplementation.html#"><b>Chapter 1</b></a>
<a class="dropdown-item" href="IntroConcSysOverview.html">&nbsp;&nbsp;&nbsp;1.1. Introduction to Concurrent Systems</a>
<a class="dropdown-item" href="SysAndModels.html">&nbsp;&nbsp;&nbsp;1.2. Systems and Models</a>
<a class="dropdown-item" href="Themes.html">&nbsp;&nbsp;&nbsp;1.3. Themes and Guiding Principles</a>
<a class="dropdown-item" href="Architectures.html">&nbsp;&nbsp;&nbsp;1.4. System Architectures</a>
<a class="dropdown-item" href="StateModels.html">&nbsp;&nbsp;&nbsp;1.5. State Models in UML</a>
<a class="dropdown-item" href="SequenceModels.html">&nbsp;&nbsp;&nbsp;1.6. Sequence Models in UML</a>
<a class="dropdown-item" href="StateModelImplementation.html">&nbsp;&nbsp;&nbsp;1.7. Extended Example: State Model Implementation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
<a class="dropdown-item" href="ProcessesOverview.html">&nbsp;&nbsp;&nbsp;2.1. Processes and OS Basics</a>
<a class="dropdown-item" href="Multiprogramming.html">&nbsp;&nbsp;&nbsp;2.2. Processes and Multiprogramming</a>
<a class="dropdown-item" href="KernelMechanics.html">&nbsp;&nbsp;&nbsp;2.3. Kernel Mechanics</a>
<a class="dropdown-item" href="Syscall.html">&nbsp;&nbsp;&nbsp;2.4. System Call Interface</a>
<a class="dropdown-item" href="ProcessCycle.html">&nbsp;&nbsp;&nbsp;2.5. Process Life Cycle</a>
<a class="dropdown-item" href="UnixFile.html">&nbsp;&nbsp;&nbsp;2.6. The UNIX File Abstraction</a>
<a class="dropdown-item" href="EventsSignals.html">&nbsp;&nbsp;&nbsp;2.7. Events and Signals</a>
<a class="dropdown-item" href="Extended2Processes.html">&nbsp;&nbsp;&nbsp;2.8. Extended Example: Listing Files with Processes</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
<a class="dropdown-item" href="IPCOverview.html">&nbsp;&nbsp;&nbsp;3.1. Concurrency with IPC</a>
<a class="dropdown-item" href="IPCModels.html">&nbsp;&nbsp;&nbsp;3.2. IPC Models</a>
<a class="dropdown-item" href="Pipes.html">&nbsp;&nbsp;&nbsp;3.3. Pipes and FIFOs</a>
<a class="dropdown-item" href="MMap.html">&nbsp;&nbsp;&nbsp;3.4. Shared Memory With Memory-mapped Files</a>
<a class="dropdown-item" href="POSIXvSysV.html">&nbsp;&nbsp;&nbsp;3.5. POSIX vs. System V IPC</a>
<a class="dropdown-item" href="MQueues.html">&nbsp;&nbsp;&nbsp;3.6. Message Passing With Message Queues</a>
<a class="dropdown-item" href="ShMem.html">&nbsp;&nbsp;&nbsp;3.7. Shared Memory</a>
<a class="dropdown-item" href="IPCSems.html">&nbsp;&nbsp;&nbsp;3.8. Semaphores</a>
<a class="dropdown-item" href="Extended3Bash.html">&nbsp;&nbsp;&nbsp;3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
<a class="dropdown-item" href="SocketsOverview.html">&nbsp;&nbsp;&nbsp;4.1. Networked Concurrency</a>
<a class="dropdown-item" href="FiveLayer.html">&nbsp;&nbsp;&nbsp;4.2. The TCP/IP Internet Model</a>
<a class="dropdown-item" href="NetApps.html">&nbsp;&nbsp;&nbsp;4.3. Network Applications and Protocols</a>
<a class="dropdown-item" href="Sockets.html">&nbsp;&nbsp;&nbsp;4.4. The Socket Interface</a>
<a class="dropdown-item" href="TCPSockets.html">&nbsp;&nbsp;&nbsp;4.5. TCP Socket Programming: HTTP</a>
<a class="dropdown-item" href="UDPSockets.html">&nbsp;&nbsp;&nbsp;4.6. UDP Socket Programming: DNS</a>
<a class="dropdown-item" href="AppBroadcast.html">&nbsp;&nbsp;&nbsp;4.7. Application-Layer Broadcasting: DHCP</a>
<a class="dropdown-item" href="Extended4CGI.html">&nbsp;&nbsp;&nbsp;4.8. Extended Example: CGI Web Server</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
<a class="dropdown-item" href="InternetOverview.html">&nbsp;&nbsp;&nbsp;5.1. The Internet and Connectivity</a>
<a class="dropdown-item" href="AppLayer.html">&nbsp;&nbsp;&nbsp;5.2. Application Layer: Overlay Networks</a>
<a class="dropdown-item" href="TransLayer.html">&nbsp;&nbsp;&nbsp;5.3. Transport Layer</a>
<a class="dropdown-item" href="NetSec.html">&nbsp;&nbsp;&nbsp;5.4. Network Security Fundamentals</a>
<a class="dropdown-item" href="NetLayer.html">&nbsp;&nbsp;&nbsp;5.5. Network Layer: IP</a>
<a class="dropdown-item" href="LinkLayer.html">&nbsp;&nbsp;&nbsp;5.6. Link Layer</a>
<a class="dropdown-item" href="Wireless.html">&nbsp;&nbsp;&nbsp;5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
<a class="dropdown-item" href="Extended5DNS.html">&nbsp;&nbsp;&nbsp;5.8. Extended Example: DNS client</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
<a class="dropdown-item" href="ThreadsOverview.html">&nbsp;&nbsp;&nbsp;6.1. Concurrency with Multithreading</a>
<a class="dropdown-item" href="ProcVThreads.html">&nbsp;&nbsp;&nbsp;6.2. Processes vs. Threads</a>
<a class="dropdown-item" href="RaceConditions.html">&nbsp;&nbsp;&nbsp;6.3. Race Conditions and Critical Sections</a>
<a class="dropdown-item" href="POSIXThreads.html">&nbsp;&nbsp;&nbsp;6.4. POSIX Thread Library</a>
<a class="dropdown-item" href="ThreadArgs.html">&nbsp;&nbsp;&nbsp;6.5. Thread Arguments and Return Values</a>
<a class="dropdown-item" href="ImplicitThreads.html">&nbsp;&nbsp;&nbsp;6.6. Implicit Threading and Language-based Threads</a>
<a class="dropdown-item" href="Extended6Input.html">&nbsp;&nbsp;&nbsp;6.7. Extended Example: Keyboard Input Listener</a>
<a class="dropdown-item" href="Extended6Primes.html">&nbsp;&nbsp;&nbsp;6.8. Extended Example: Concurrent Prime Number Search</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
<a class="dropdown-item" href="SynchOverview.html">&nbsp;&nbsp;&nbsp;7.1. Synchronization Primitives</a>
<a class="dropdown-item" href="CritSect.html">&nbsp;&nbsp;&nbsp;7.2. Critical Sections and Peterson's Solution</a>
<a class="dropdown-item" href="Locks.html">&nbsp;&nbsp;&nbsp;7.3. Locks</a>
<a class="dropdown-item" href="Semaphores.html">&nbsp;&nbsp;&nbsp;7.4. Semaphores</a>
<a class="dropdown-item" href="Barriers.html">&nbsp;&nbsp;&nbsp;7.5. Barriers</a>
<a class="dropdown-item" href="Condvars.html">&nbsp;&nbsp;&nbsp;7.6. Condition Variables</a>
<a class="dropdown-item" href="Deadlock.html">&nbsp;&nbsp;&nbsp;7.7. Deadlock</a>
<a class="dropdown-item" href="Extended7Events.html">&nbsp;&nbsp;&nbsp;7.8. Extended Example: Event Log File</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
<a class="dropdown-item" href="SynchProblemsOverview.html">&nbsp;&nbsp;&nbsp;8.1. Synchronization Patterns and Problems</a>
<a class="dropdown-item" href="SynchDesign.html">&nbsp;&nbsp;&nbsp;8.2. Basic Synchronization Design Patterns</a>
<a class="dropdown-item" href="ProdCons.html">&nbsp;&nbsp;&nbsp;8.3. Producer-Consumer Problem</a>
<a class="dropdown-item" href="ReadWrite.html">&nbsp;&nbsp;&nbsp;8.4. Readers-Writers Problem</a>
<a class="dropdown-item" href="DiningPhil.html">&nbsp;&nbsp;&nbsp;8.5. Dining Philosophers Problem and Deadlock</a>
<a class="dropdown-item" href="CigSmokers.html">&nbsp;&nbsp;&nbsp;8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
<a class="dropdown-item" href="Extended8ModExp.html">&nbsp;&nbsp;&nbsp;8.7. Extended Example: Parallel Modular Exponentiation</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
<a class="dropdown-item" href="ParallelDistributedOverview.html">&nbsp;&nbsp;&nbsp;9.1. Parallel and Distributed Systems</a>
<a class="dropdown-item" href="ParVConc.html">&nbsp;&nbsp;&nbsp;9.2. Parallelism vs. Concurrency</a>
<a class="dropdown-item" href="ParallelDesign.html">&nbsp;&nbsp;&nbsp;9.3. Parallel Design Patterns</a>
<a class="dropdown-item" href="Scaling.html">&nbsp;&nbsp;&nbsp;9.4. Limits of Parallelism and Scaling</a>
<a class="dropdown-item" href="DistTiming.html">&nbsp;&nbsp;&nbsp;9.5. Timing in Distributed Environments</a>
<a class="dropdown-item" href="DistDataStorage.html">&nbsp;&nbsp;&nbsp;9.6. Reliable Data Storage and Location</a>
<a class="dropdown-item" href="DistConsensus.html">&nbsp;&nbsp;&nbsp;9.7. Consensus in Distributed Systems</a>
<a class="dropdown-item" href="Extended9Blockchain.html">&nbsp;&nbsp;&nbsp;9.8. Extended Example: Blockchain Proof-of-Work</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item disabled"><b>Appendix A</b></a>
<a class="dropdown-item" href="CLangOverview.html">&nbsp;&nbsp;&nbsp;A.1. C Language Reintroduction</a>
<a class="dropdown-item" href="Debugging.html">&nbsp;&nbsp;&nbsp;A.2. Documentation and Debugging</a>
<a class="dropdown-item" href="BasicTypes.html">&nbsp;&nbsp;&nbsp;A.3. Basic Types and Pointers</a>
<a class="dropdown-item" href="Arrays.html">&nbsp;&nbsp;&nbsp;A.4. Arrays, Structs, Enums, and Type Definitions</a>
<a class="dropdown-item" href="Functions.html">&nbsp;&nbsp;&nbsp;A.5. Functions and Scope</a>
<a class="dropdown-item" href="Pointers.html">&nbsp;&nbsp;&nbsp;A.6. Pointers and Dynamic Allocation</a>
<a class="dropdown-item" href="Strings.html">&nbsp;&nbsp;&nbsp;A.7. Strings</a>
<a class="dropdown-item" href="FunctionPointers.html">&nbsp;&nbsp;&nbsp;A.8. Function Pointers</a>
<a class="dropdown-item" href="Files.html">&nbsp;&nbsp;&nbsp;A.9. Files</a>
</div>
</li>
</ul>
</div>
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/StateModelImplementation.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="SequenceModels.html">1.6. Sequence Models in UML</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="ProcessesOverview.html">2.1. Processes and OS Basics</a>&#160;&#160;»
</div>
<br />
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
<script type="text/javascript" src="_static/js/config.js"></script>
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
<div class="container">
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "StateModelImplementation";ODSA.SETTINGS.MODULE_LONG_NAME = "Extended Example: Text Parser State Machine";ODSA.SETTINGS.MODULE_CHAPTER = "Introduction to Computer Systems"; ODSA.SETTINGS.BUILD_DATE = "2021-06-14 17:15:25"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="extended-example-text-parser-state-machine">
<h1>1.7. Extended Example: Text Parser State Machine<a class="headerlink" href="StateModelImplementation.html#extended-example-text-parser-state-machine" title="Permalink to this headline"></a></h1>
<div class="figure mb-2 align-right" id="id3" style="width: 55%">
<span id="stateparser"></span><a class="reference internal image-reference" href="_images/CSF-Images.1.12.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="A UML state model for a simple parser" src="_images/CSF-Images.1.12.png" style="width: 95%;" /></a>
<p class="caption align-center px-3"><span class="caption-text"> Figure 1.7.1: A UML state model for a simple parser</span></p>
</div>
<p>In this Extended Example, we will illustrate how to use a state machine as a parser. This is a very
simplified version of how compilers read in and parse source code. <a href="StateModelImplementation.html#stateparser">Figure 1.7.1</a>
shows the state model that we will be using to implement the parser. This parser recognizes only the
strings <code class="docutils literal notranslate"><span class="pre">&quot;int&quot;</span></code> and <code class="docutils literal notranslate"><span class="pre">&quot;integer&quot;</span></code>, rejecting everything else. Both strings are expected to end
with a space, leading to the Accept final state.</p>
<p>To reduce the size of the model, the character-recognition events (<code class="docutils literal notranslate"><span class="pre">CHAR_*</span></code>) are fired when the
corresponding character is read from the input in the correct order. For instance, parsing the
string <code class="docutils literal notranslate"><span class="pre">&quot;int&quot;</span></code> would fire three events in sequence: <code class="docutils literal notranslate"><span class="pre">CHAR_i</span></code>, <code class="docutils literal notranslate"><span class="pre">CHAR_nt</span></code>, then <code class="docutils literal notranslate"><span class="pre">CHAR_nt</span></code>. On
the other hand, parsing string <code class="docutils literal notranslate"><span class="pre">&quot;itn&quot;</span></code> would fire the events in sequence: <code class="docutils literal notranslate"><span class="pre">CHAR_i</span></code> then
<code class="docutils literal notranslate"><span class="pre">CHAR_other</span></code>, because the <code class="docutils literal notranslate"><span class="pre">'t'</span></code> would not be in the correct order. A more complete model would
use distinct events for each character, as well as separate states to represent the full ordering;
that is, <code class="docutils literal notranslate"><span class="pre">'i'</span></code> would lead to a one state, then <code class="docutils literal notranslate"><span class="pre">'n'</span></code> would lead to a second, and <code class="docutils literal notranslate"><span class="pre">'t'</span></code> would
to a third. However, such a model is more difficult to include in the space constraints of the page
here.</p>
<p>First, we complete the generic FSM handler, which we described in <a class="reference external" href="StateModelImplementation.html#cl1-1">Code Listing 1.1</a> and <a class="reference external" href="StateModelImplementation.html#cl1-2">1.2</a>. The key
difference here is that there are some additional fields added to the <code class="docutils literal notranslate"><span class="pre">fsm_t</span></code> declaration. As each
character of the input is processed, it is added to a buffer that keeps track of the string in
progress. Also, to assist the controller in determining which events are valid due to the ordering
of the characters, there are <code class="docutils literal notranslate"><span class="pre">next_valid</span></code> and <code class="docutils literal notranslate"><span class="pre">next_event</span></code> fields. For instance, when the FSM
first enters the <code class="docutils literal notranslate"><span class="pre">Int_Or_Integer</span></code> state, only the character <code class="docutils literal notranslate"><span class="pre">'i'</span></code> has been processed.
Consequently the <code class="docutils literal notranslate"><span class="pre">next_valid</span></code> character would be <code class="docutils literal notranslate"><span class="pre">'n'</span></code> and the <code class="docutils literal notranslate"><span class="pre">next_event</span></code> would be
<code class="docutils literal notranslate"><span class="pre">CHAR_nt</span></code>. However, once the <code class="docutils literal notranslate"><span class="pre">'n'</span></code> is read, the <code class="docutils literal notranslate"><span class="pre">next_valid</span></code> would change to <code class="docutils literal notranslate"><span class="pre">'t'</span></code>
accordingly. The <code class="docutils literal notranslate"><span class="pre">final</span></code> field is used by the controlling driver program to determine if the
string was read completely.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cp">#ifndef __statemodel_h__</span>
<span class="cp">#define __statemodel_h__</span>
<span class="cp">#include</span> <span class="cpf">&lt;stdbool.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;sys/types.h&gt;</span><span class="cp"></span>
<span class="cm">/* States and events should just be integers */</span>
<span class="k">typedef</span> <span class="kt">int</span> <span class="n">state_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="kt">int</span> <span class="n">event_t</span><span class="p">;</span>
<span class="cm">/* Dummy struct for circular typedefs */</span>
<span class="k">struct</span> <span class="n">fsm</span><span class="p">;</span>
<span class="cm">/* Function pointer type declaration for effects */</span>
<span class="k">typedef</span> <span class="nf">void</span> <span class="p">(</span><span class="o">*</span><span class="n">action_t</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fsm</span> <span class="o">*</span><span class="p">);</span>
<span class="cp">#define BUFFER_LENGTH 10</span>
<span class="cm">/* Generic FSM struct that could have other fields, as well */</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">fsm</span> <span class="p">{</span>
<span class="n">state_t</span> <span class="n">state</span><span class="p">;</span> <span class="cm">/* current state */</span>
<span class="kt">size_t</span> <span class="n">nevents</span><span class="p">;</span> <span class="cm">/* number of events for this FSM */</span>
<span class="cm">/* pointer to the FSM&#39;s transition function */</span>
<span class="n">state_t</span> <span class="p">(</span><span class="o">*</span><span class="n">transition</span><span class="p">)</span> <span class="p">(</span><span class="k">struct</span> <span class="n">fsm</span> <span class="o">*</span><span class="p">,</span> <span class="n">event_t</span><span class="p">,</span> <span class="n">action_t</span> <span class="o">*</span><span class="p">,</span> <span class="n">action_t</span> <span class="o">*</span><span class="p">);</span>
<span class="cm">/* helper fields to keep track of the current input and the</span>
<span class="cm"> string built so far */</span>
<span class="kt">char</span> <span class="n">input</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="n">BUFFER_LENGTH</span><span class="p">];</span>
<span class="kt">size_t</span> <span class="n">length</span><span class="p">;</span>
<span class="kt">bool</span> <span class="n">final</span><span class="p">;</span> <span class="cm">/* set on accept or reject */</span>
<span class="cm">/* special handling: since there are self-transitions that are</span>
<span class="cm"> valid a limited number of times, use these fields to keep</span>
<span class="cm"> track of the next event to fire based on expected input */</span>
<span class="kt">char</span> <span class="n">next_valid</span><span class="p">;</span>
<span class="n">event_t</span> <span class="n">next_event</span><span class="p">;</span>
<span class="p">}</span> <span class="n">fsm_t</span><span class="p">;</span>
<span class="cm">/* Invoke an event handler for a given FSM */</span>
<span class="kt">void</span> <span class="nf">handle_event</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="n">fsm</span><span class="p">,</span> <span class="n">event_t</span> <span class="n">event</span><span class="p">);</span>
<span class="cp">#endif</span>
</pre></div>
</td></tr></table></div>
<p>Next, we extend <a class="reference external" href="StateModelImplementation.html#cl1-2">Code Listing 1.2</a> so that it can also perform entry activities on state changes.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;statemodel.h&quot;</span><span class="cp"></span>
<span class="kt">void</span>
<span class="nf">handle_event</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="n">fsm</span><span class="p">,</span> <span class="n">event_t</span> <span class="n">event</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Confirm the event is valid for the given FSM */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">event</span> <span class="o">&gt;=</span> <span class="n">fsm</span><span class="o">-&gt;</span><span class="n">nevents</span><span class="p">)</span>
<span class="k">return</span><span class="p">;</span>
<span class="cm">/* Use the FSM&#39;s lookup tables; if next is -1, the event is not</span>
<span class="cm"> Defined for the current state */</span>
<span class="n">action_t</span> <span class="n">effect</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">action_t</span> <span class="n">entry</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">state_t</span> <span class="n">next</span> <span class="o">=</span> <span class="n">fsm</span><span class="o">-&gt;</span><span class="n">transition</span> <span class="p">(</span><span class="n">fsm</span><span class="p">,</span> <span class="n">event</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">effect</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">entry</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">next</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">return</span><span class="p">;</span>
<span class="cm">/* Perform the effect (if defined) */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">effect</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="n">effect</span> <span class="p">(</span><span class="n">fsm</span><span class="p">);</span>
<span class="cm">/* Perform the new state&#39;s entry action (if defined) */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">entry</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="n">entry</span> <span class="p">(</span><span class="n">fsm</span><span class="p">);</span>
<span class="cm">/* Change the state */</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">state</span> <span class="o">=</span> <span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The <code class="docutils literal notranslate"><span class="pre">&quot;parse.h&quot;</span></code> header file defines the interface to this specific FSM. To control the parser FSM,
a driver program would need access to the event names (defined by the <code class="docutils literal notranslate"><span class="pre">parse_event_t</span></code> type) and
the name of the initialization function.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cp">#ifndef __parse_h__</span>
<span class="cp">#define __parse_h__</span>
<span class="cp">#include</span> <span class="cpf">&quot;statemodel.h&quot;</span><span class="cp"></span>
<span class="cm">/* Valid events for this type of FSM */</span>
<span class="k">typedef</span> <span class="k">enum</span> <span class="p">{</span>
<span class="n">CHAR_i</span><span class="p">,</span> <span class="n">CHAR_nt</span><span class="p">,</span> <span class="n">CHAR_e</span><span class="p">,</span> <span class="n">CHAR_ger</span><span class="p">,</span> <span class="n">CHAR_other</span><span class="p">,</span> <span class="n">SPACE</span><span class="p">,</span> <span class="n">NIL</span>
<span class="p">}</span> <span class="n">parse_event_t</span><span class="p">;</span>
<span class="n">fsm_t</span> <span class="o">*</span><span class="nf">parse_init</span> <span class="p">(</span><span class="kt">void</span><span class="p">);</span>
<span class="cp">#endif</span>
</pre></div>
</td></tr></table></div>
<p>The next piece of code extends <a class="reference external" href="StateModelImplementation.html#cl1-3">Code Listing 1.3</a> with the information needed for the parser
structure. As before, theres an initialization function (<code class="docutils literal notranslate"><span class="pre">parse_init()</span></code>) that sets up the
internals of the <code class="docutils literal notranslate"><span class="pre">fsm_t</span></code>. The <code class="docutils literal notranslate"><span class="pre">append_character()</span></code> function keeps track of how many times each
particular state has been visited and what character is expected next. Again, a more verbose FSM
would not need this information. Finally, the <code class="docutils literal notranslate"><span class="pre">accept()</span></code> and <code class="docutils literal notranslate"><span class="pre">reject()</span></code> functions implement the
transition effects.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cp">#include</span> <span class="cpf">&lt;assert.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdbool.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;statemodel.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;parser.h&quot;</span><span class="cp"></span>
<span class="cm">/* Internal type definition of states */</span>
<span class="k">typedef</span> <span class="k">enum</span> <span class="p">{</span> <span class="n">ENTER</span><span class="p">,</span> <span class="n">IOI</span><span class="p">,</span> <span class="n">IO</span><span class="p">,</span> <span class="n">ACCEPT</span><span class="p">,</span> <span class="n">FAIL</span><span class="p">,</span> <span class="n">NST</span> <span class="p">}</span> <span class="n">parse_t</span><span class="p">;</span>
<span class="cp">#define NUM_STATES (NST+1)</span>
<span class="cp">#define NUM_EVENTS (NIL+1)</span>
<span class="cm">/* Prototypes for actions/effects and transition function */</span>
<span class="k">static</span> <span class="kt">void</span> <span class="nf">append_character</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">void</span> <span class="nf">accept</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">void</span> <span class="nf">reject</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="p">);</span>
<span class="k">static</span> <span class="n">state_t</span> <span class="nf">parse_transition</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="p">,</span> <span class="n">event_t</span><span class="p">,</span> <span class="n">action_t</span> <span class="o">*</span><span class="p">,</span> <span class="n">action_t</span> <span class="o">*</span><span class="p">);</span>
<span class="cm">/* Return an FSM that links to these internals */</span>
<span class="n">fsm_t</span> <span class="o">*</span>
<span class="nf">parse_init</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">fsm_t</span> <span class="o">*</span><span class="n">fsm</span> <span class="o">=</span> <span class="n">calloc</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">fsm_t</span><span class="p">));</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">nevents</span> <span class="o">=</span> <span class="n">NUM_EVENTS</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">state</span> <span class="o">=</span> <span class="n">ENTER</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">transition</span> <span class="o">=</span> <span class="n">parse_transition</span><span class="p">;</span>
<span class="cm">/* Set up internal fields for keeping track of characters */</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">input</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">memset</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">));</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">length</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span> <span class="o">=</span> <span class="sc">&#39;i&#39;</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_event</span> <span class="o">=</span> <span class="n">CHAR_i</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">final</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
<span class="k">return</span> <span class="n">fsm</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Lookup table for transitions; row=state, column=event */</span>
<span class="k">static</span> <span class="n">parse_t</span> <span class="k">const</span> <span class="n">_transition</span><span class="p">[</span><span class="n">NUM_STATES</span><span class="p">][</span><span class="n">NUM_EVENTS</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="c1">// C_i C_nt C_e C_ger C_oth SPACE</span>
<span class="p">{</span> <span class="n">IOI</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">FAIL</span><span class="p">,</span> <span class="n">NST</span> <span class="p">},</span> <span class="c1">// Enter</span>
<span class="p">{</span> <span class="n">NST</span><span class="p">,</span> <span class="n">IOI</span><span class="p">,</span> <span class="n">IO</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">FAIL</span><span class="p">,</span> <span class="n">ACCEPT</span> <span class="p">},</span> <span class="c1">// Int_Or_Integer</span>
<span class="p">{</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">IO</span><span class="p">,</span> <span class="n">FAIL</span><span class="p">,</span> <span class="n">ACCEPT</span> <span class="p">},</span> <span class="c1">// Integer_Only</span>
<span class="p">{</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span> <span class="p">},</span> <span class="c1">// Accept</span>
<span class="p">{</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span><span class="p">,</span> <span class="n">NST</span> <span class="p">},</span> <span class="c1">// Fail</span>
<span class="p">};</span>
<span class="cm">/* Lookup table for effects; row=state, column=event */</span>
<span class="k">static</span> <span class="n">action_t</span> <span class="k">const</span> <span class="n">_effect</span><span class="p">[</span><span class="n">NUM_STATES</span><span class="p">][</span><span class="n">NUM_EVENTS</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="c1">// C_i C_nt C_e C_ger C_oth SPACE</span>
<span class="p">{</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">reject</span><span class="p">,</span> <span class="nb">NULL</span> <span class="p">},</span> <span class="c1">// Enter</span>
<span class="p">{</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">reject</span><span class="p">,</span> <span class="n">accept</span> <span class="p">},</span> <span class="c1">// Int_Or_Integer</span>
<span class="p">{</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">reject</span><span class="p">,</span> <span class="n">accept</span> <span class="p">},</span> <span class="c1">// Integer_Only</span>
<span class="p">{</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span> <span class="p">},</span> <span class="c1">// Accept</span>
<span class="p">{</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span> <span class="p">},</span> <span class="c1">// Fail</span>
<span class="p">};</span>
<span class="cm">/* Lookup table for state entry actions */</span>
<span class="k">static</span> <span class="n">action_t</span> <span class="k">const</span> <span class="n">_entry</span><span class="p">[</span><span class="n">NUM_STATES</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="nb">NULL</span><span class="p">,</span> <span class="n">append_character</span><span class="p">,</span> <span class="n">append_character</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span>
<span class="p">};</span>
<span class="cm">/* Given FSM instance and event, perform the table lookups */</span>
<span class="k">static</span> <span class="n">state_t</span>
<span class="nf">parse_transition</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="n">fsm</span><span class="p">,</span> <span class="n">event_t</span> <span class="n">event</span><span class="p">,</span> <span class="n">action_t</span> <span class="o">*</span><span class="n">effect</span><span class="p">,</span> <span class="n">action_t</span> <span class="o">*</span><span class="n">entry</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* If the state/event combination is bad, return -1 */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">state</span> <span class="o">&gt;=</span> <span class="n">NST</span> <span class="o">||</span> <span class="n">event</span> <span class="o">&gt;=</span> <span class="n">NIL</span> <span class="o">||</span> <span class="n">_transition</span><span class="p">[</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">state</span><span class="p">][</span><span class="n">event</span><span class="p">]</span> <span class="o">==</span> <span class="n">NST</span><span class="p">)</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="cm">/* Look up the effect and transitions in the tables */</span>
<span class="o">*</span><span class="n">effect</span> <span class="o">=</span> <span class="n">_effect</span><span class="p">[</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">state</span><span class="p">][</span><span class="n">event</span><span class="p">];</span>
<span class="cm">/* Look up the next state in the list of entry events */</span>
<span class="n">state_t</span> <span class="n">next</span> <span class="o">=</span> <span class="n">_transition</span><span class="p">[</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">state</span><span class="p">][</span><span class="n">event</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="n">next</span> <span class="o">!=</span> <span class="n">NST</span><span class="p">)</span>
<span class="o">*</span><span class="n">entry</span> <span class="o">=</span> <span class="n">_entry</span><span class="p">[</span><span class="n">next</span><span class="p">];</span>
<span class="k">return</span> <span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Appends the current character to the buffer */</span>
<span class="k">static</span> <span class="kt">void</span>
<span class="nf">append_character</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="n">fsm</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">length</span> <span class="o">&lt;</span> <span class="n">BUFFER_LENGTH</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">[</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">length</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">fsm</span><span class="o">-&gt;</span><span class="n">input</span><span class="p">;</span>
<span class="cm">/* Helper inputs to keep track of what the next event will be */</span>
<span class="k">switch</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">input</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">case</span> <span class="sc">&#39;i&#39;</span><span class="o">:</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span> <span class="o">=</span> <span class="sc">&#39;n&#39;</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_event</span> <span class="o">=</span> <span class="n">CHAR_nt</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="sc">&#39;n&#39;</span><span class="o">:</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span> <span class="o">=</span> <span class="sc">&#39;t&#39;</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_event</span> <span class="o">=</span> <span class="n">CHAR_nt</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="sc">&#39;t&#39;</span><span class="o">:</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span> <span class="o">=</span> <span class="sc">&#39;e&#39;</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_event</span> <span class="o">=</span> <span class="n">CHAR_e</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="sc">&#39;e&#39;</span><span class="o">:</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span> <span class="n">strcmp</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="s">&quot;inte&quot;</span><span class="p">))</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span> <span class="o">=</span> <span class="sc">&#39;g&#39;</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span> <span class="o">=</span> <span class="sc">&#39;r&#39;</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_event</span> <span class="o">=</span> <span class="n">CHAR_ger</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="sc">&#39;g&#39;</span><span class="o">:</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span> <span class="o">=</span> <span class="sc">&#39;e&#39;</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_event</span> <span class="o">=</span> <span class="n">CHAR_ger</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">default</span><span class="o">:</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_event</span> <span class="o">=</span> <span class="n">NIL</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/* Prints that the string is accepted */</span>
<span class="k">static</span> <span class="kt">void</span>
<span class="nf">accept</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="n">fsm</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;ACCEPT: </span><span class="se">\&quot;</span><span class="s">%s</span><span class="se">\&quot;\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">);</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">final</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Prints that the string is rejected and at what character */</span>
<span class="k">static</span> <span class="kt">void</span>
<span class="nf">reject</span> <span class="p">(</span><span class="n">fsm_t</span> <span class="o">*</span><span class="n">fsm</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;REJECT: </span><span class="se">\&quot;</span><span class="s">%s</span><span class="se">\&quot;</span><span class="s"> at character &#39;%c&#39;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="n">fsm</span><span class="o">-&gt;</span><span class="n">input</span><span class="p">);</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">final</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The final piece of code for this parser is the main driver program. This program reads in the
command-line arguments and attempts to parse each one as beginning with either <code class="docutils literal notranslate"><span class="pre">&quot;int&quot;</span></code> or
<code class="docutils literal notranslate"><span class="pre">&quot;integer&quot;</span></code>. For each provided input, this controller will use <code class="docutils literal notranslate"><span class="pre">parse_init()</span></code> to create a new
FSM instance. The code in lines 37 48 start by checking for a space (indicating the first token
of the input has been read) or for the expected next character (based on the information stored in
the FSM). Based on these checks, line 52 fires the event and the pointer moves on to the next
character. If all characters have been read, there are three possibilities: 1) a space was found and
the match was a success 2) the match already failed, or 3) the input has matched a prefix of
<code class="docutils literal notranslate"><span class="pre">&quot;int&quot;</span></code> or <code class="docutils literal notranslate"><span class="pre">&quot;integer&quot;</span></code>, but there was no space to terminate the string. To resolve case 3, we
just need to check the strings. <a class="footnote-reference" href="StateModelImplementation.html#f6" id="id2">[1]</a></p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;statemodel.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;parser.h&quot;</span><span class="cp"></span>
<span class="kt">int</span>
<span class="nf">main</span> <span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="cm">/* Inputs to parse. Matches will be exactly &quot;int&quot;, &quot;integer&quot;,</span>
<span class="cm"> or begin with &quot;int &quot; or &quot;integer &quot;. */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">fprintf</span> <span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;Must pass at least one string argument</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">fprintf</span> <span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;Sample command line:</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">fprintf</span> <span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot; ./ext int char </span><span class="se">\&quot;</span><span class="s">i n t</span><span class="se">\&quot;</span><span class="s"> integ</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">argc</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;Processing input: </span><span class="se">\&quot;</span><span class="s">%s</span><span class="se">\&quot;\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="cm">/* Create a new parser instance for each input */</span>
<span class="n">fsm_t</span> <span class="o">*</span><span class="n">fsm</span> <span class="o">=</span> <span class="n">parse_init</span> <span class="p">();</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">walker</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="n">event_t</span> <span class="n">evt</span> <span class="o">=</span> <span class="n">NIL</span><span class="p">;</span>
<span class="cm">/* Traverse through each character in the input */</span>
<span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">walker</span> <span class="o">!=</span> <span class="sc">&#39;\0&#39;</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">input</span> <span class="o">=</span> <span class="o">*</span><span class="n">walker</span><span class="p">;</span>
<span class="cm">/* If the input is a space, check if the string</span>
<span class="cm"> match is successful. Otherwise, check if the</span>
<span class="cm"> next character matches what is expected. */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">input</span> <span class="o">==</span> <span class="sc">&#39; &#39;</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span> <span class="n">strcmp</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="s">&quot;int&quot;</span><span class="p">)</span> <span class="o">||</span> <span class="o">!</span> <span class="n">strcmp</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="s">&quot;integer&quot;</span><span class="p">))</span>
<span class="n">evt</span> <span class="o">=</span> <span class="n">SPACE</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">evt</span> <span class="o">=</span> <span class="n">CHAR_other</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">input</span> <span class="o">==</span> <span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_valid</span><span class="p">)</span>
<span class="n">evt</span> <span class="o">=</span> <span class="n">fsm</span><span class="o">-&gt;</span><span class="n">next_event</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">evt</span> <span class="o">=</span> <span class="n">CHAR_other</span><span class="p">;</span>
<span class="cm">/* The event should never be NIL because of the</span>
<span class="cm"> logic above, but this style is for consistency. */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">evt</span> <span class="o">!=</span> <span class="n">NIL</span><span class="p">)</span>
<span class="n">handle_event</span> <span class="p">(</span><span class="n">fsm</span><span class="p">,</span> <span class="n">evt</span><span class="p">);</span>
<span class="cm">/* If a string is accepted or rejected, we are done. */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">final</span><span class="p">)</span>
<span class="k">break</span><span class="p">;</span>
<span class="cm">/* Move to the next input character. */</span>
<span class="n">walker</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* At the end of the input. Either we have matched exactly</span>
<span class="cm"> &quot;int&quot; or &quot;integer&quot;, or we have matched a substring (such</span>
<span class="cm"> as &quot;inte&quot;). Substrings should be rejected. Use &#39;$&#39; to</span>
<span class="cm"> indicate an END-OF-STRING character. */</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">final</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">fsm</span><span class="o">-&gt;</span><span class="n">input</span> <span class="o">=</span> <span class="sc">&#39;$&#39;</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span> <span class="n">strcmp</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="s">&quot;int&quot;</span><span class="p">)</span> <span class="o">||</span> <span class="o">!</span> <span class="n">strcmp</span> <span class="p">(</span><span class="n">fsm</span><span class="o">-&gt;</span><span class="n">buffer</span><span class="p">,</span> <span class="s">&quot;integer&quot;</span><span class="p">))</span>
<span class="n">handle_event</span> <span class="p">(</span><span class="n">fsm</span><span class="p">,</span> <span class="n">SPACE</span><span class="p">);</span>
<span class="k">else</span>
<span class="n">handle_event</span> <span class="p">(</span><span class="n">fsm</span><span class="p">,</span> <span class="n">CHAR_other</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<table class="docutils footnote" frame="void" id="f6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="StateModelImplementation.html#id2">[1]</a></td><td>One may object at this point and ask why we didnt just compare the strings from the
beginning and avoid all of the FSM complexity. The answer is that this example is one miniscule
component of a much larger system: a compiler. The state models used for compilers are
significantly larger and distinguish keywords (such as <code class="docutils literal notranslate"><span class="pre">&quot;int&quot;</span></code>) from programmer-defined variable
names (such as <code class="docutils literal notranslate"><span class="pre">&quot;interest_rate&quot;</span></code>). Simple string comparison is not a feasible approach to such
complex work.</td></tr>
</tbody>
</table>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="SequenceModels.html">1.6. Sequence Models in UML</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="ProcessesOverview.html">2.1. Processes and OS Basics</a>&#160;&#160;»
</div>
</div>
<br />
<div class="row jmu-dark-purple-bg">
<div class="col-md-12">
<center>
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
</center>
</div>
</div>
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>