2つのステートマシンを組み合わせる?

私は、このフォーラムの最近のアドバイスから、無駄なプロセッサ時間と変数の使用を減らすために、可能であれば「ステートマシン」ロジックを使用してプロジェクトを再開することで得たいと考えています。

私はNick Gammonsのステートマシンからシリアルポートからの入力を処理するようになっています 'example http://www.gammon.com.au/statemachine を参照してください。これは、可能なすべてのマシン状態(本質的に2次元グリッド)に対して、すべての特殊制御文字 'イベント'の可能な組み合わせをすべて示しています。

私はDOSコマンドラインフォーマットに似た command [parameters] [options] "の形式でシリアル入力を処理するという目標を洗練しました。たとえば、 DIR" c :\ program files "/ w/s ]をクリックします。これは私に大きなBuffer []とHeader []の文字列を必要としないようにし、

したがって、私のイベント制御文字はスペース、カンマ、一重引用符、二重引用符、スラッシュ、カラジーグリターン、そして私の '状態'は NULL、COMMAND、PARAMETER、OPTIONS

OPTIONS状態は、カンマまたはスペースデリミタまたはCarraige Returnがそのオプションを適切に処理し、おそらく認識された変数にその値を保存するまで、テンポラリオプション[]文字列に文字を追加します。

COMMANDとPARAMETERの '状態'は、特殊文字が一重引用符または二重引用符の中に含まれている場合は、対応するコマンド[]とパラメータ[]文字列に文字を追加します(ペア内で使用する場合は引用符を文字列の一部として使用できます)他のタイプのもの)。

したがって、 NoQuotes、SingleQuotesおよびDoubleQuotes にCOMMAND、PARAMETERおよびOPTIONS状態の操作を変更するために必要な第2の状態マシンがあるようです。

これは、私がニューロンを使い果たした場所です。なぜなら、私が見るのは、非常に多くの可能な順列を持つ不可能な複雑な2つの機械状態の3次元グリッドだからです。

しかし、プロセッサーの能力とメモリの可用性が鶏の歯よりも乏しい時代にまでさかのぼるほとんどすべてのコマンドラインユーティリティの中心に位置しているため、これを実装する方法は非常に実用的でなければならないと考えられます。コマンドラインの解析を含め、可能な限り最善のものでなければなりませんでした。

だから誰でも入力からコマンドライン型のフォーマットを得るための実現可能なモデル(機械状態かそうでないか)を提案することができますか?

更新

ああ、私はちょうど私が前に見つけていなかった別の複雑さを見てきました。これは、オプションが必ずしも必ずしも最後ではないということです。オプションがcarraige-return、options状態区切り文字による変更は、オプション状態の変更前の状態に戻らなければなりません(phew、私はそれが意味をなさないことを望みます)。とにかく、2つの答えが既に示唆しているように、このアプローチは複雑すぎるように思われるので、それは描画ボードに戻っていると思います。

1
質問は非常にArduinoです。私は入ってくるシリアルを読んで、それをコマンドとオプションのパラメタとオプションのコントロールオプションに分けたいので、DOSコマンドラインには単に必要なシリアルフォーマットの構文例が書かれています。
追加された 著者 R.M.,
「LED1 ON」や「IRSEND」NEC 0xFFEE9123 32 "など、ローカルの「コマンド」と「arduino」が入力シリアルで見られるようにプログラムされているパラメータです。オプションは、/ c(hecksum)= nnn、/ l(ength)= nnn、/ s(ource)= nnnなどの制御情報のオプションのarduinoからarduinoへの送信用です。後で追加の大きなバッファストリングを解析する必要はなく、一度に1バイトずつ処理し、コマンドまたはパラメータまたはオプションにその場で送信します。
追加された 著者 R.M.,
相互作用する状態を渡す一般的な方法は、相互作用をそれぞれの状態に拡張することです。すなわちPARAMETERとSingleQuotes_PARAMETERのDoubleQuotes_PARAMETERを比較すると、その処理ではほとんど同じコードを共有できます。 github.com/Traumflug/Teacup_Firmware/blob/master/gcode_parse‌ .cを参照してください。 を参考にしてください。また、これは広すぎます(あなたには使用する構文がありません)、Arduinoに焦点を絞ったフォーラムの話題は実際にはありません。
追加された 著者 Dave X,
これを状態マシンと考えるもう一つの方法は、あなたの状態空間が{COMMAND、PARAMETER []、OPTIONS [] ...などの状態変数の多次元ベクトルであることです。
追加された 著者 Dave X,
一般的なDOS構文や、特定のコマンドの構文がはるかに限定されているのでしょうか?特定のコマンドでは、限られた数のパラメータとオプションしか存在せず、/ parser/stateマシンはTeacupのように/ process/state変数にそれらを並べ替えることができます。
追加された 著者 Dave X,
私は、最後のオプションの最後の文字が解析されるまで、コマンドをディスパッチできないと思います。コマンド、パラメータ、およびオプションはすべて、次の処理段階のパラメータのベクトルにすぎないはずです。移動する前にそれらをすべて集める必要があります。 「LED1 ON」の「LED1」はコマンドですか? ///更新されたQの場合、 '\ n'はシステムの状態をバイト解析からパラメータ状態のクリーンアップに変更し、コマンド状態/ oneshotを実行します。たとえば、 github.com/Traumflug/Teacup_Firmware/blob/master/&hellip を390に設定してください。
追加された 著者 Dave X,

2 答え

提案: - ステートマシンの階層を1つの大きなフラットな状態マシンに「モーシュ」(技術的な用語です!)しようとしないでください。そういうわけで、狂気がある。例えば、あなたの{NULL、COMMAND、PARAMETER、OPTIONS}の状態マシンを保持しておき、それらの状態のうちの一つで単純な文字列の収集以上のものが必要なところでは、あなたが期待する種類の入力に適したパーサーSMを呼び出してくださいその点 - 数字、引用符付き文字列、オプション指定子など

3
追加された
また、さまざまな入力タイプに対応できるが、メインSMとは別のユニバーサルパーサーを中点として考えることもできます。あなたは一度あなたが素早くいくつかのSM階層をスケッチすると(それは「円と矢のようなスケッチ」であり、「コーディング」ではそうではありません)、最もよく分かります。
追加された 著者 caryden,
私は理解していると思います(ステートマシンがすでに私の頭を隠しているかもしれないと思っても、狂気を避けるには遅すぎるかもしれません)。あなたが言うように、変更する状態としてNULL、COMMAND、PARAMETERを使用してください。 NoQuotes、SingleQuotes、Double-Quotes、場合によってはオプションがステートマシン自体を正当化するかもしれませんが、メインステートマシン内の別々のプロセスとして扱うのが最良です。
追加された 著者 R.M.,

個人的には、Nickがステートマシンでコマンドラインパターン解析を行うようにアドバイスしたとは思わない。彼の例は、コマンドライン入力に基づいて状態マシンを変更することです。
私はいくつかのコマンドラインパーサーを書いており、これを行うためにステートマシンを使用したことはありません。ステートマシンを使用するようアドバイスしません。
簡単な文字列解析がはるかに簡単です。

Edit To answer the remark below:
I would not advice to go byte by byte. I'd advice to go the line by line way. I have written a library to do read line by line and an article on how that one works. http://blog.baeyens.it/#post16
Here a link to the lib https://github.com/jantje/libraries/tree/master/SerialCommunicator.
Here is a parcing code example. It is not so interesting for you as I have it done in a stage by stage way in a very high level way of coding. https://github.com/jantje/libraries/blob/master/SerialBridgeCommunicator/SerialBridgeCommunicator.cpp#L21

Basically the algorithm is=
1 Take the first word;
2 identify the word.
3 If the command is complete ->do it
else Send the rest of the string to a specialized piece of code. (which has the same algorithm)

3
追加された
私は自分のニーズがNicksの例と同じだと思った。一度に1バイトのシリアル入力を読み込み、コマンドやパラメタやオプションをオンザフライで送信してから、カラジーリターンを読み込んだ後、後に追加の大きなバッファー文字列。しかし、私が月に撮影しているということはありません。以前はコマンドラインパーサーを使っていましたが...適切なフローチャートやアルゴリズムを使用したことはありますか?
追加された 著者 R.M.,
バイトごとに行くというアドバイスはしません。私は行ごとに行こうとアドバイスをします。
追加された 著者 jantje,