Хорошее упражнение при изучении программирования - написать калькулятор. Для этого я создал DSL в BNF и хочу попросить вас о помощи, чтобы улучшить его. С этим миниязыком вы сможете add
, multiply
и assign
значения и выражения для имен (например, создавать переменные и функции).
Сначала взглянем на БНФ:
<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)"
Пожалуйста, помогите улучшить БНФ, чтобы его можно было использовать для успешного написания калькулятора.
редактирование:
Этот БНФ действительно не закончен. Он не обрабатывает случаи «2 + -3» (должен потерпеть неудачу, но не) и «2 + (- 3)» (не должен потерпеть неудачу, но делает) правильно.