парсинг — Использование ANTLR3 в программе на C ++

В настоящее время я работаю над приложением, которое принимает строку (функцию от одной переменной ‘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')+ ;

0

Решение

Файл 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);

Чувствительность к регистру зависит от вашего парсера. Эксперимент немного с этим.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]