プログラミングを学びながらの良い練習は、電卓を書くことです。これを行うために、私はBNFである種のDSLを作成し、それを改善するためにあなたの助けを求めたいと思います。このミニ言語を使用すると、名前に値と式を使用できるようになります(別名、変数と関数を作成します)。add
multiply
assign
最初にBNFを見てみましょう。
<Program> ::= <Line>(<NewLine><Line>)*
<Line> ::= {"("}<Expression>{")"}|<Assignment>
<Assignment> ::= <Identifier>"="<Expression>
<Identifier> ::= <Name>{"("<Name>(","<Name>)*")"}
<Expression> ::= <Summand>(("+"|"-")<Summand>)*
<Summand> ::= <Factor>(("*"|"/")<Factor>)*
<Factor> ::= <Number>|<Call>
<Call> ::= <Name> {"("<Expression>(","<Expression>)*")"}
<Name> ::= <Letter>(<Letter>|<Digit>)*
<Number> ::= {"+"|"-"}(<Digit>|<DigitNoZero><Digit>+)
<Digit> ::= "0"|<DigitNoZero>
<DigitNoZero> ::= "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
<Letter> ::= [a-zA-Z]
<NewLine> ::= "\n"|"\r"|"\r\n"
ご覧のとおり、このBNFはの横に空白を処理しませんNewLine
。NewLine
解析を開始する前に、解析する文字列から(もちろん以外の)すべての空白を削除する予定です。とにかくパーサーにとっては必須ではありません。
現在定義されているこの言語を使用すると問題が発生する可能性のある4つのことがあります。適切な解決策を見つけるのに役立つことを願っています。
- この文法を生成しながら、トップダウンのアプローチに従おうとしましたが、、、、の間
<Expression>
に円<Summand>
が<Factor>
あり<Call>
ます。 - 文法は変数と関数をまったく同じように扱います。ほとんどのプログラミング言語は違いを生みます。ここで差別化する必要がありますか?
- プログラミング、BNFなど、BNFを実装しようとしているときに、後で私を殺してしまうことについて、私が知らないことがいくつかあるかもしれません。しかし、私が始める前にあなたはそれを見つけることができるかもしれません。
- 私が自分自身を見つけることができなかった単純で愚かな間違いがあるかもしれません。その場合は申し訳ありません。これらの間違いがもうないことを願っています。
手と脳を使用して、次のテストケースを正常に解析できました。
"3"
"-3"
"3-3"
"a=3"
"a=3+b"
"a=3+b\nc=a+3"
"a(b,c)=b*c\ra(1+2,2*3)"
電卓をうまく書くために使用できるように、BNFの改善にご協力ください。
編集: このBNFは実際には完成していません。「2+-3」(失敗するはずですが失敗しません)と「2 +(-3)」(失敗しないはずですが失敗します)の場合は正しく処理されません。