定义新的中缀运算符 [英] Defining new infix operators

查看:111
本文介绍了定义新的中缀运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以感谢C ++ 11,现在可以组合宏,用户定义的文字,lambdas等创建最接近我可以得到'语法糖'。例如

  if(A contains B)

当然很容易。

  cout<<(hello_s包含ello_s)<<< endl; 

表达式转换为bool,其中contains是一个自定义结构,右边作为参数。当然,重载的结构体operator +将自定义字符串字面量首先返回,返回自身,然后是结构体本身的操作符+。

  struct contains_struct {
string lhs;
string rhs;
void set_lhs(string lhs){this-> lhs = lhs; }
void set_rhs(string rhs){this-> rhs = rhs; }
operator bool()const {
return string :: npos!= lhs.find(rhs);
}
} contains_obj;

contains_struct& operator +(const string& lhs,const contains_struct& rhs){
contains_obj.set_lhs(lhs);
return contains_obj;
}

contains_struct& operator +(const contains_struct& lhs,const string& rhs){
contains_obj.set_rhs(rhs);
return contains_obj;
}

#define contains + contains_obj +

我想进一步。

 (x in a)执行多维数据集

这不是列表解析,但它是一个很好的例子吧?一开始我说,我必须去stackoverflow询问自定义运算符优先级,但它是直接放在括号中,因为没有人会在使用我的代码。相反,我扩展了我的另一个例子,并像包含一样,具有自定义结构的in和perform。



x可以是任何数字索引,a作为任何容器,但为了简单起见,我将x作为整数,并将a作为int的向量。现在到目前为止,它实际上没有将局部变量x作为参数,它在运算符string()函数中局部使用它。



为了简化操作,我将表达式的结果存储在一个字符串中,例如

  operator string()const {
string s =;
for(int x:lhs.rhs)
s + = to_string(rhs(x))+ string(\\\
);
return s;
}






重载类型扣除的赋值运算符



我意识到一个实际用途,返回它作为一个赋值是以下:

  struct result_struct {
vector< int>结果;
result_struct(vector< int> results){this-> results = results; }
};

...

运算符result_struct()const {
vector< int> tmp;
for(int x:lhs.rhs)
tmp.push_back(rhs(x));
return result_struct(tmp);
}

...

result_struct result_2 =(x in a)执行多维数据集;
for(int x:result_2.results)
cout<<<<< endl;






感谢milleniumbug的回答,我可以:

  struct for_obj 
{
int _lhs;
std :: vector< int> _rhs;
for_obj(int lhs,std :: vector< int> rhs)
:_lhs(lhs),_rhs(rhs){}
}

INFIX_OPERATOR(for_obj,in_op,int,std :: vector< int>)
{
return for_obj(lhs(),rhs());
}
#define in + in_op()+

INFIX_OPERATOR(int,perform_op,for_obj,std :: function< int(int)>)
{
for(int i = 0; i rhs()(lhs()._ rhs [i]
return 0;
}
#define perform + perform_op()+

。首先,我返回一个int,以便我可以将其分配给一个虚拟变量来执行。我可以总是做我以前做的result_struct事情,或者返回一个std :: function对象来调用它本身,但我会重复自己。另一个警告是,因为在宏中有这么多const,你不能修改lhs(这不允许你指定一个迭代器)。



考虑下面的工作原理如预期。

  int x = 0; 
std :: vector< int> nums = {1,2,3};
auto cube = [](int x)
{
std :: cout< x * x * x < std :: endl;
return x * x * x;
};
int i =(x in nums)执行多维数据集;






新版本

 类PerformObj {
int counter;
public:
PerformObj():counter(0){}
〜PerformObj(){}
InObj lhs;
std :: function< int(int)> rhs;

operator int()const {
return rhs(lhs.rhs [counter]);
}
} performobj;

#define perform + performobj +

PerformObj& operator +(const InObj& lhs,PerformObj& rhs){
rhs.lhs = lhs;
return rhs;
}

PerformObj& operator +(PerformObj& lhs,const std :: function< int(int)&& rhs){
lhs.rhs = rhs;
return lhs;
}

int main()
{
std :: vector< int> nums = {1,2,3};
int x = 0;

auto cube = [](int n){
return n * n * n;
};

std :: cout<< x in nums perform cube< std :: endl;
}

显式运算符std :: vector< int>()const {
std :: vector< int>温度
for(int i = 0; i temp.push_back(rhs(lhs.rhs [i]));
}
return temp;
}

int y = 0;
std :: cout<< y in static_cast< std :: vector< int>>(x in nums perform cube)执行std :: function< int(int)> ;
})<< std :: endl;






我应该这样做,运算符,有后缀运算符,如字符串字面量s.contains其他字符串字面量,或做函数风格,字符串字面量s.contains(其他字符串字面量)



如何改进我的代码以使其更具扩展性?因为它是现在,它是非常污染。有没有更好/更一般化/不太笨重的方法来做到这一点?例如,要泛化表达式,以便我不需要define语句或重用代码。

解决方案

这里很难看到什么问题,假设最新的编辑有所有问题。


我应该这么做,而不是中缀运算符,有后缀
运算符,比如String literals.contains其他字符串s,or
do it function style,String literals.contains(Other string
literals)?



b $ b

是的。 字符串文字s.contains(其他字符串字面量)是最好的方式 - 简洁,清晰的C ++程序员,清晰的程序员其他语言字符串有方法),没有模板魔法也不使用宏魔术。


我如何改进我的代码,因为它是正确的
现在,它是非常污染。有没有更好的/更广泛/更少的
笨重的方法来做到这一点?例如,为了将表达式泛化为
,我不需要定义语句或重用代码。


是的!但只在一定程度上(删除了那里和这里的不必要的const):

  #define INFIX_OPERATOR(rettype,name, RT)\ 
struct name \
{\
private:\
LT * left; \
RT * right; \
\
protected:\
LT& lhs()const {return * left; } \
RT& rhs()const {return * right; } \
\
public:\
friend name operator +(LT& lhs,name& op)\
{\
.left =& lhs; \
return op; \
} \
\
好​​友姓名操作符+(姓名& \
{\
op.right =& rhs; \
return op; \
} \
\
name ():left(nullptr),right(nullptr){} \
\
operator rettype()const; \
}; \
\
inline name :: operator rettype()const

然后你可以这样创建你的infix操作符:

  #include< iostream> 
#include< string>

INFIX_OPERATOR(bool,contains_op,const std :: string,const std :: string)
{
return std :: string :: npos!= lhs (rhs());
}
#define contains + contains_op()+

int main()
{
std :: string a =hello;
std :: string b =hell;
if(a contains b)
std :: cout<< 是;
}

注意,没有办法避免#define contains指令,因为没有办法用另一个宏指令来创建宏指令。


如果有任何的实际好处是什么使用它作为真实世界代码的合理性我的意思是,你可以得到
它是什么,我使用它,禁止娱乐目的?)
说我的朋友,而不是学习C + ,想要一个简单的抽象
接口为他的Bash或Perl经验,但希望
协作,而不诉诸编译/链接外部gcc。这个
方式,他可以写'scripts'或'code'是C ++,并编译和
链接到我的程序/ libraries / interface,无论如何。


< blockquote>

您似乎尝试在另一种语言之上创建语言。准备




  • 尝试测试您的语言的时间和小时数。

  • 糟糕的诊断信息。尝试编译这个: std :: vector< void> myarr; 1 然后用宏包装。然后将其包装在另一个模板中。然后在另一个宏...你得到的想法。

  • 调试工具显示处理的代码。

  • 即使您的语言与自身完美结合,您仍然拥有C ++来处理,包括大量的规则和复杂的类型系统。 毕竟,所有抽象都是泄漏的。



如果你的朋友想在Perl中编程,只是让他做。这些语言很容易与C连接。



如果你想创建一种语言,因为其他语言不能清楚地表达你想做的,解析器生成器(Flex / Bison,ANTLR)和LLVM都很容易。



如果创建一个解析器是过度的,



$ b

这里...







$ b b

  import std.stdio; 
int main()
{
mixin(`write(Hello world);`); //`contents`是一个原始字符串文字
return 0; // so is rcontents
}

等效于:

  import std.stdio; 
int main()
{
write(Hello world);
return 0;
}

这只是一个简单的例子。你可以有你的函数来解析一个字符串:

  mixin(user1508519s_language(r ; 

1 - 这是它的外观(gcc 4.7.2):

 在从c:\__moje\prog\mingw\bin\../ lib / gcc /mingw32/4.7.2/include/ 
c ++ / bits / stl_construct.h:63:0,
来自c:\__moje\prog\mingw\bin\ ../ lib /gcc/mingw32/4.7.2/include/
c ++ / vector:63,
from#templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin \ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / ext / alloc_traits.h
:在实例化'struct __gnu_cxx :: __ alloc_traits< std :: allocator< void& >':

c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
76:28:从'struct std :: _ Vector_base< void,std :: allocator< void> >'
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
208 :11:required from'class std :: vector< void>'
#templateerrors2.cpp:5:19:required from here
c:\__moje\prog\mingw\bin\ ../lib/gcc/mingw32/4.7.2/include/c++/ext/alloc_traits.h
:189:53:错误:没有类型命名为'reference'在'class std :: allocator< void&
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / ext / alloc_traits.h
:190:53:错误:在'class std :: allocator< void>'中没有名为'const_reference'的类型
在从c:\__moje\prog\mingw\bin\../ lib / gcc / mingw32 / 4.7.2 / include /
c ++ / vector:65:0,
从#templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\\ \\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
在'class std :: vector< void>'的实例化:
#templateerrors2.cpp :5:19:从这里需要
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
292:7:错误:形成对void的引用
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
467:7:错误:形成对void
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7的引用。 2 / include / c ++ / bits / stl_vector.h:
684:7:error:无效参数类型'std :: vector< void> :: value_type {aka void}'
c:\__moje \\ \\ prog \mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
684:7:error:in declaration'void std :: vector< _Tp,_Alloc> :: resize(std :: vector<
_Tp,_Alloc> :: size_type,std :: vector< _Tp,_Alloc> :: value_type)'
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
881:7:错误:形成对void的引用
在从c:\__moje \prog\ mingw \bin\ ../ lib / gcc / mingw32 / 4.7.2 / include /
c ++ / vector:70:0,
从#templateerrors2.cpp:1:
c: \__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / vector.tcc:10
8:5:错误:形成参考to void
在从c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include /
c ++ / vector中包含的文件中:65 :0,
from#templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ /bits/stl_vector.h:
1003:7:错误:形成对void的引用
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7 .2 / include / c ++ / bits / stl_vector.h:
1179:7:错误:形成对void的引用
在从c:\__moje \prog\mingw\bin\\ \\ ../ lib / gcc / mingw32 / 4.7.2 / include /
c ++ / vector:70:0,
从#templateerrors2.cpp:1:
c:\__moje\ prog \mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / vector.tcc:21
6:5:错误:形成对void $ b $的引用bc:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / vector.tcc:43
9:5:错误:形成对void的引用
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / vector.tcc:31
6:5:错误:形成对void的引用
在从c:\__moje\prog\mingw\bin\../ lib / gcc / mingw32 / 4.7.2中包含的文件中include /
c ++ / vector:65:0,
from#templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
在'std :: _ Vector_base< _Tp,_Alloc> :: _Vector_base()的实例化中使用_Tp
= void; _Alloc = std :: allocator< void>]':
c:\__moje\prog\mingw\bin\../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / stl_vector.h:
247:15:需要从'std :: vector< _Tp,_Alloc> :: vector()[with _Tp = void; _A
lloc = std :: allocator< void>]'
#templateerrors2.cpp:5:19:从这里需要
c:\__moje\prog\mingw\bin\\ \\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
161:9:错误:无效使用'void'
c:\__moje\在'void std :: _ Vector_base< _Tp,_Alloc>的实例化中,可以使用下面的表达式来实现:void _start :: __gp || / lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h: :: _ M_deallocate(std :: _ V
ector_base< _Tp,_Alloc> :: pointer,std :: size_t)[with _Tp = void; _Alloc = std :: a
llocator< void> ;; std :: _ Vector_base< _Tp,_Alloc> :: pointer = void *; std :: size_t = u
nsigned int]':
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ /bits/stl_vector.h:
161:9:需要从'std :: _ Vector_base< _Tp,_Alloc> ::〜_Vector_base()[with _T
p = void; _Alloc = std :: allocator< void>]'
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector .h:
247:15:需要从'std :: vector< _Tp,_Alloc> :: vector()[with _Tp = void; _A
lloc = std :: allocator< void>]'
#templateerrors2.cpp:5:19:从这里需要
c:\__moje\prog\mingw\bin\\ \\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
175:4:error:'struct std :: _ Vector_base< void,std :: allocator< void& > :: _ Vector_im
pl'没有名为'deallocate'的成员
在从c:\__moje\prog\mingw\bin\../ lib / gcc / mingw32 /4.7.2/include/
c ++ / bits / stl_algobase.h:66:0,
来自c:\__moje\prog\mingw\bin\ ../ lib / gcc /mingw32/4.7.2/include/
c ++ / vector:61,
从#templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\ ../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_iterator_
base_types.h:在'struct std :: iterator_traits< void *>'的实例化中:
c:\\ \moje\prog\mingw\bin\../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_construct
.h:127:24:从'void std: :_Destroy(_ForwardIterator,_ForwardIterato
r)[with _ForwardIterator = void *]'
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_construct
.h:155:7:需要从'void std :: _ Destroy(_ForwardIterator,_ForwardIterator
,std :: allocator< _T2>&)[with _ForwardIterator = void *; _Tp = void]'
c:\__moje\prog\mingw\bin\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_vector.h:
403:9:从std :: vector <_Tp,_Alloc> ::〜vector()需要[with _Tp = void; _A
lloc = std :: allocator< void>]'
#templateerrors2.cpp:5:19:从这里需要
c:\__moje\prog\mingw\bin\\ \\ ../ lib / gcc / mingw32 / 4.7.2 / include / c ++ / bits / stl_iterator_
base_types.h:182:43:错误:形成对void
的引用


So thanks to C++11, it's now possible to combine macros, user-defined literals, lambdas, etc. to create the closest I can get to 'syntactic sugar'. An example would be

 if (A contains B)

Of course this is easy.

cout <<("hello"_s contains "ello"_s)<<endl;

The expression converts to a bool, where contains is a custom struct that takes the left-hand side and right-hand side as arguments. The struct of course overloads operator+ to take the custom string literal first, returning itself, then the operator+ for the struct itself.

struct contains_struct {
    string lhs;
    string rhs;
    void set_lhs(string lhs) { this->lhs = lhs; }
    void set_rhs(string rhs) { this->rhs = rhs; }
    operator bool() const {
        return string::npos != lhs.find(rhs);
    }
} contains_obj;

contains_struct& operator+(const string& lhs, const contains_struct& rhs) {
    contains_obj.set_lhs(lhs);
    return contains_obj;
}

contains_struct& operator+(const contains_struct& lhs, const string& rhs) {
    contains_obj.set_rhs(rhs);
    return contains_obj;
}

#define contains +contains_obj+

Now I decided I want to go further. What about

(x in a) perform cube

It's no list comprehension, but it's a pretty good example right? At first I said, well I'd have to go to stackoverflow to ask about custom operator precedence, but it's straight forward to put it in parentheses since no one in their right mind would use my code. Instead, I expanded upon my other example and have 'in' and 'perform' as custom structs, just like 'contains'.

You can go further and template it so that x can be any numerical index, and a as any container, but for simplicity, I left x as an integer and a as a vector of ints. Now so far it doesn't actually take the local variable x as an argument, it uses it locally in the operator string() function.

To simplify things, I store the results of the expression in a string, like so

operator string() const {
    string s = "";
    for (int x : lhs.rhs)
        s += to_string(rhs(x)) + string("\n");
    return s;
}


Thanks to another question: Overloading assignment operator for type deduction

I realized one practical use for returning it as an assignment is the following:

struct result_struct {
    vector<int> results;
    result_struct(vector<int> results) { this->results = results; }
};

...

    operator result_struct() const {
        vector<int> tmp;
        for (int x : lhs.rhs)
            tmp.push_back(rhs(x));
        return result_struct(tmp);
    }

...

result_struct result_2 = (x in a) perform cube;
    for (int x : result_2.results)
        cout <<x<<endl;


Thanks to milleniumbug's answer, I can do:

struct for_obj
{
    int _lhs;
    std::vector<int> _rhs;
    for_obj(int lhs, std::vector<int> rhs)
        : _lhs(lhs), _rhs(rhs) { }
};

INFIX_OPERATOR(for_obj, in_op, int, std::vector<int>)
{
    return for_obj(lhs(), rhs());
}
#define in + in_op() +

INFIX_OPERATOR(int, perform_op, for_obj, std::function<int(int)>)
{
    for (int i = 0; i < lhs()._rhs.size(); i++)
        rhs()(lhs()._rhs[i]);
    return 0;
}
#define perform + perform_op() +

There are two caveats. First, I return an int so that I can assign it to a dummy variable to get it to execute. I could always do the result_struct thing I did before, or return a std::function object to call it by itself, but I'd be repeating myself. The other caveat is that because there are so many consts in the macro, you cannot modify the lhs (which doesn't allow you to specifiy an iterator).

All things considered, the following works as expected.

int x = 0;
std::vector<int> nums = { 1, 2, 3 };
auto cube = [] (int x)
{
    std::cout << x * x * x << std::endl;
    return x * x * x;  
};
int i = (x in nums) perform cube;


New version

class PerformObj {
    int counter;
public:
    PerformObj() : counter(0) { }
    ~PerformObj() { }
    InObj lhs;
    std::function<int(int)> rhs;

    operator int() const {
        return rhs(lhs.rhs[counter]);
    }
} performobj;

#define perform + performobj +

PerformObj& operator+(const InObj& lhs, PerformObj& rhs) {
    rhs.lhs = lhs;
    return rhs;
}

PerformObj& operator+(PerformObj& lhs, const std::function<int(int)>& rhs) {
    lhs.rhs = rhs;
    return lhs;
} 

int main()
{
    std::vector<int> nums = {1,2,3};
    int x = 0;

    auto cube = [] (int n) {
        return n * n * n;
    };

    std::cout << x in nums perform cube << std::endl;
}

explicit operator std::vector<int>() const {
    std::vector<int> temp;
    for (int i = 0; i < lhs.rhs.size(); i++) {
        temp.push_back(rhs(lhs.rhs[i]));
    }
    return temp;
}

int y = 0;
std::cout << y in static_cast<std::vector<int>>(x in nums perform cube) perform std::function<int(int)>([] (int i) -> int {
        return i;
}) << std::endl;


Should I make it so that instead of infix operators, there are postfix operators, like "String literal"s.contains "Other string literal"s, or do it function style, "String literal"s.contains("Other string literal"s)?

How would I improve my code to make it more extensible? As it is right now, it's very polluted. Is there a better/more generalized/less clunky way to do this? For example, to generalize the expressions so that I don't need define statements or to reuse code.

解决方案

It is hard to see what is the question asked here, assuming the latest edit has all the questions.

Should I make it so that instead of infix operators, there are postfix operators, like "String literal"s.contains "Other string literal"s, or do it function style, "String literal"s.contains("Other string literal"s)?

Yes. "String literal"s.contains("Other string literal"s) is the best way - concise, clear to C++ programmers, clear to programmers of other languages (Java and Python strings have methods) and no template magic nor macro magic is used.

How would I improve my code to make it more extensible? As it is right now, it's very polluted. Is there a better/more generalized/less clunky way to do this? For example, to generalize the expressions so that I don't need define statements or to reuse code.

Yep! But only to certain degree (removed the unnecessary consts over there and here):

#define INFIX_OPERATOR(rettype, name, LT, RT) \
struct name\
{\
private:\
    LT* left;\
    RT* right;\
\
protected:\
    LT& lhs() const { return *left; }\
    RT& rhs() const { return *right; }\
\
public: \
    friend name operator+(LT& lhs, name && op)\
    {\
        op.left = &lhs;\
        return op;\
    }\
\
    friend name operator+(name && op, RT& rhs)\
    {\
        op.right = &rhs;\
        return op;\
    }\
\
    name () : left(nullptr), right(nullptr) {}\
\
    operator rettype() const;\
};\
\
inline name :: operator rettype() const

And then you can create your infix operator like this:

#include <iostream>
#include <string>

INFIX_OPERATOR(bool, contains_op, const std::string, const std::string)
{
    return std::string::npos != lhs().find(rhs());
}
#define contains + contains_op() +

int main()
{
    std::string a = "hello";
    std::string b = "hell";
    if(a contains b)
        std::cout << "YES";
}

Note that there is no way to avoid #define contains directive, as there is no way to create macro directive with another macro directive.

What are the practical benefits of this if there are any (ignoring all rationality of using this as real world code. I mean what can you get out of it for what I'm using it for, barring recreational purposes?) Say that my friend, instead of learning C++, wants an easy abstracted interface for his Bash or Perl experience but would like to collaborate without resorting to compiling/linking outside gcc. That way, he can write 'scripts' or 'code' that is C++, and compile and link it with my programs/libraries/interface, whatever.

It seems that you are trying to create a language on top of another language. Prepare for

  • Hours and hours trying to test your language.
  • Embarrassingly bad diagnostics messages. Try to compile this: std::vector<void> myarr;1 Then wrap it with macros. And then wrap it in another template. And then in another macros... You get the idea.
  • Debugging tools showing processed code.
  • Even if your language perfectly integrates with itself, you still have C++ to take care of, with tons of rules and complicated type system. After all, all abstractions are leaky.

If your friend want to program in Perl, just let him do it. These languages are easy to interface with C.

If you're trying to create a language, because the other languages can't cleanly express what you're trying to do, parser generators (Flex/Bison, ANTLR) and LLVM make it easy.

If creating a parser is overkill, take a look at D language mixins. They accept a string created at compile time, and then compile it as if it was inserted directly.

Here...

import std.stdio;
int main()
{
    mixin(`write("Hello world");`); //`contents` is a raw string literal
    return 0;                       //so is r"contents"
}

is equivalent to:

import std.stdio;
int main()
{
    write("Hello world");
    return 0;
}

This is just a simple example. You could have your function that parses a string:

mixin(user1508519s_language(r"(x in a) perform cube"));

1 - Here is how it looks (gcc 4.7.2):

In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/bits/stl_construct.h:63:0,
                 from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:63,
                 from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ext/alloc_traits.h
: In instantiation of 'struct __gnu_cxx::__alloc_traits<std::allocator<void> >':

c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
76:28:   required from 'struct std::_Vector_base<void, std::allocator<void> >'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
208:11:   required from 'class std::vector<void>'
#templateerrors2.cpp:5:19:   required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ext/alloc_traits.h
:189:53: error: no type named 'reference' in 'class std::allocator<void>'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ext/alloc_traits.h
:190:53: error: no type named 'const_reference' in 'class std::allocator<void>'
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:65:0,
                 from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
 In instantiation of 'class std::vector<void>':
#templateerrors2.cpp:5:19:   required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
292:7: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
467:7: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
684:7: error: invalid parameter type 'std::vector<void>::value_type {aka void}'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
684:7: error: in declaration 'void std::vector<_Tp, _Alloc>::resize(std::vector<
_Tp, _Alloc>::size_type, std::vector<_Tp, _Alloc>::value_type)'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
881:7: error: forming reference to void
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:70:0,
                 from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/vector.tcc:10
8:5: error: forming reference to void
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:65:0,
                 from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
1003:7: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
1179:7: error: forming reference to void
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:70:0,
                 from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/vector.tcc:21
6:5: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/vector.tcc:43
9:5: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/vector.tcc:31
6:5: error: forming reference to void
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:65:0,
                 from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
 In instantiation of 'std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp
= void; _Alloc = std::allocator<void>]':
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
247:15:   required from 'std::vector<_Tp, _Alloc>::vector() [with _Tp = void; _A
lloc = std::allocator<void>]'
#templateerrors2.cpp:5:19:   required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
161:9: error: invalid use of 'void'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
 In instantiation of 'void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(std::_V
ector_base<_Tp, _Alloc>::pointer, std::size_t) [with _Tp = void; _Alloc = std::a
llocator<void>; std::_Vector_base<_Tp, _Alloc>::pointer = void*; std::size_t = u
nsigned int]':
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
161:9:   required from 'std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _T
p = void; _Alloc = std::allocator<void>]'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
247:15:   required from 'std::vector<_Tp, _Alloc>::vector() [with _Tp = void; _A
lloc = std::allocator<void>]'
#templateerrors2.cpp:5:19:   required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
175:4: error: 'struct std::_Vector_base<void, std::allocator<void> >::_Vector_im
pl' has no member named 'deallocate'
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/bits/stl_algobase.h:66:0,
                 from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:61,
                 from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_iterator_
base_types.h: In instantiation of 'struct std::iterator_traits<void*>':
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_construct
.h:127:24:   required from 'void std::_Destroy(_ForwardIterator, _ForwardIterato
r) [with _ForwardIterator = void*]'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_construct
.h:155:7:   required from 'void std::_Destroy(_ForwardIterator, _ForwardIterator
, std::allocator<_T2>&) [with _ForwardIterator = void*; _Tp = void]'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
403:9:   required from 'std::vector<_Tp, _Alloc>::~vector() [with _Tp = void; _A
lloc = std::allocator<void>]'
#templateerrors2.cpp:5:19:   required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_iterator_
base_types.h:182:43: error: forming reference to void

这篇关于定义新的中缀运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆