В настоящее время я работаю над приложением, которое принимает строку (функцию от одной переменной ‘x’) в качестве входных данных и выводит производную этой функции. Вторая половина программы на данный момент не является проблемой, единственное, с чем я сталкиваюсь, это «чтение» функции из строки. Я использую ANTLRv3 для C, чтобы попытаться достичь этой цели, но я не могу заставить ее работать. В настоящее время мне не хватает заголовочного файла «antlr3.h», который я не могу найти нигде. Моя вторая проблема — вызов сгенерированного парсера. Каким будет код C (++) для этого (код ANTLR опубликован ниже)? Как мне заставить его работать?
Заранее спасибо,
связи
grammar Expression;
options {
language = C;
}
@header {
#ifndef PI
#define PI 3.1415926535897
#endif // PI
#ifndef E
#define E 2.7182818284590
#endif // E
#include "ExpressionTree.h"#include <vector>
#include <cstdlib>}
parse returns [Functor* func]
: e=addExp EOF {func = $e.func;}
;
addExp returns [Functor* func]
@init {std::vector<Functor*> addList;
std::vector<bool> opList;}
: e1=multExp {addList.push_back($e1.func);} (o=('+'|'-') e2=multExp {opList.push_back($o.text == '+'); addList.push_back($e2.func);})*
{
if(addList.size() == 1) {
func = addList[0];
} else {
Functor* current = addList[0];
for(int i = 0; i<opList.size(); i++) {
if(opList[i]) {
current = new Plus(current, addList[i+1]);
} else {
current = new Minus(current, addList[i+1]);
}
}
func = current;
}};
multExp returns [Functor* func]
@init {
std::vector<Functor*> mulList;
std::vector<bool> opList;}
: e1=powExp {mulList.push_back($e1.func);} (o=('*'|'/') e2=powExp {opList.push_back($o.text == '*'); mulList.push_back($e2.func);})*
{
if(mulList.size() == 1) {
func = addList[0];
} else {
Functor* current = mulList[0];
for(int i = 0; i<opList.size(); i++) {
if(opList[i]) {
current = new Times(current, mulList[i+1]);
} else {
current = new Divides(current, mulList[i+1]);
}
}
func = current;
}};
powExp returns [Functor* func]
@init {
std::vector<Functor*> expList;
}
: e1=unarExp {expList.push_back($e1.func);} ('^' e2=unarExp {expList.push_back($e2.func);})?
{
if(expList.size() == 1) {
func = expList[0];
} else {
func = new Power(expList[0], expList[1]);
}};
unarExp returns [Functor* func]
: SQRT '(' e=addExp ')' {func = new Sqrt($e.func);}
| SIN '(' e=addExp ')' {func = new Sin($e.func);}
| COS '(' e=addExp ')' {func = new Cos($e.func);}
| TAN '(' e=addExp ')' {func = new Tan($e.func);}
| EXP '(' e=addExp ')' {func = new Exp($e.func);}
| LOG '(' e=addExp ')' {func = new Log($e.func);}
| ABS '(' e=addExp ')' {func = new Abs($e.func);}
| MAX '(' e1=addExp ',' e2=addExp ')' {func = new Max($e1.func,$e2.func);}
| MIN '(' e1=addExp ',' e2=addExp ')' {func = new Min($e1.func,$e2.func);}
| e=atom {func = $e.func;}
;
atom returns [Functor* func]
: INT {func = new Constant(atoi($INT.text));}
| FLOAT {func = new Constant(atof($FLOAT.text));}
| 'pi' {func = new Constant(PI);}
| 'e' {func = new Constant(E);}
| 'x' {func = new Variable();}
| '(' e=addExp ')' {func = $e.func;}
;
SQRT: 'Sqrt';
SIN : 'Sin';
COS : 'Cos';
TAN : 'Tan';
EXP : 'Exp';
LOG : 'Log';
ABS : 'Abs';
MAX : 'Max';
MIN : 'Min';
INT : '0'..'9'+;
FLOAT : ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
| '.' ('0'..'9')+ EXPONENT?
| ('0'..'9')+ EXPONENT
;
WS : ( ' ' | '\t') {$channel=HIDDEN;};
fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
Файл antlr3.h является основным заголовочным файлом среды выполнения ANTLR. Вы можете получить это время выполнения от http://www.antlr3.org/download/C/ однако на данный момент эта страница недоступна.
Для вызова: ANTLR генерирует функцию для каждого вашего правила синтаксического анализатора, которую вы можете вызывать по отдельности. Обычно вы настраиваете свой парсер и лексер, а затем вызываете правило верхнего уровня парсера, в вашем случае, вероятно, parse ().
У меня есть парсер для языка MySQL, который я вызываю так:
_input = antlr3StringStreamNew((pANTLR3_UINT8)_text, _input_encoding, _text_length, (pANTLR3_UINT8)"mysql-script");
_input->setUcaseLA(_input, ANTLR3_TRUE); // Make input case-insensitive. String literals must all be upper case in the grammar!
_lexer = MySQLLexerNew(_input);
_tokens = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(_lexer));
_parser = MySQLParserNew(_tokens);
_ast = _parser->query(_parser);
ANTLR3_UINT32 error_count = _parser->pParser->rec->getNumberOfSyntaxErrors(_parser->pParser->rec);
if (error_count > 0)
log_debug3("%i errors found\n", error_count);
Чувствительность к регистру зависит от вашего парсера. Эксперимент немного с этим.
Других решений пока нет …