精华内容
下载资源
问答
  • 中国专利 相关

    2019-09-26 16:09:20
    专利有时候并不是特别高级的东西,他是一权利,每个人都可以申请,一赋予申请者的权利; 专利的种类: 发明专利:针对产品、方法或者产品、方法的改进所提出的新的技术方案,可以申请发明专利。主要体现新颖...

    专利有时候并不是特别高级的东西,他是一种权利,每个人都可以申请,一种赋予申请者的权利;

    专利的种类:

    • 发明专利:针对产品、方法或者产品、方法的改进所提出的新的技术方案,可以申请发明专利。主要体现新颖性、创造性和实用性。取得专利的发明又分为产品发明(如机器、仪器设备、用具)和方法发明(制造方法)两大类;
    • 实用新型专利:针对产品的形状、构造或者其结合所提出的适于实用的新的技术方案,可以申请实用新型专利;
    • 外观设计专利:针对产品的形状、图案或者其结合以及色彩与形状、图案的结合所作出的富有美感并适于工业应用的新设计,可以申请外观设计专利。

    专利保护时间:

    根据《中华人民共和国专利法》,发明专利权保护20年,实用新型和外观设计专利权保护10年,均自申请日起算。

    专利优先权:

    专利优先权可分为国内优先权和国际优先权;

    • 国内优先权
      • 国内优先权,又称为“本国优先权”,是指专利申请人就相同主题的发明或者实用新型在本国第一次提出专利申请之日起12个月内,又向本国提出专利申请的,可以享有优先权。本国优先权不包括外观设计专利。
    • 国际优先权
      • 国际优先权,又称“外国优先权”,其内容是:专利申请人自发明或者实用新型在外国第一次提出专利申请之日起十二个月内,或者自外观设计在外国第一次提出专利申请之日起六个月内,又在中国就相同主题提出专利申请的,依照该外国同中国签订的协议或者共同参加的国际条约,或者依照相互承认优先权的原则,可以享有优先权。

    资源来源于网络,仅作参考,如果对您有帮助,请关注 cnblogs.com/xuyaowen 

    更多内容可以参照:http://www.cnipa.gov.cn/zhfwpt/zlsqzn_pt/zlsqspcxjs/zlsqsplc/index.htm

    转载于:https://www.cnblogs.com/xuyaowen/p/patents.html

    展开全文
  • 现在有点时间来看点东西总结些东西了,又因为前段时间片片断断地看了看JavaScript函数部分,所以抽时间总结下函数的相关部分,当然,里面有些部分都是自己理解,如果有理解不对地方还请小伙伴们吝指出。...
  • 算符优先分析用来处理表达式非常便捷,甚至...结合方式一般分两种,普通的运算都是左结合的,赋值和乘幂运算是右结合的,而Jerry支持乘幂运算。简单的表达式求值算法可以参考这篇文章,文中相关实现也是基于该算法...

        算符优先分析用来处理表达式非常便捷,甚至你可以忘记算术运算相关的一切产生式。对于算符优先分析来说最重要的东西有三:运算符的优先级、元和结合方式。优先级在任务布置时已经讲过了;元很简单,一般运算符都是二元的,只有正号和负号是一元的;结合方式一般分两种,普通的运算都是左结合的,赋值和乘幂运算是右结合的,而Jerry不支持乘幂运算。简单的表达式求值算法可以参考这篇文章,文中相关实现也是基于该算法的。

     

        算符分析器需要两个栈,一个用来存放符号,一个用来存放操作数,因此该结构可以这样实现

    /* datastruct.h */
    struct OperationAnalyser {
        memberSyntaxAnalyser
        int needFactor;
        struct Stack* opStack;
        struct Stack* numStack;
    };
    

    needFactor则表示该算符当前应该遭遇一个因子(needFactor == 1时)还是一个运算符(needFactor == 0时)。

     

        算符分析器的构造函数可以这样实现:

    void consumeToken_OpAna(void* self, struct Token* token);
    void consumeNonTerminal_OpAna(void* self, struct AbstractSyntaxNode* token);
    
    struct OperationAnalyser* newOperationAnalyser(void)
    {
        struct OperationAnalyser* opana = (struct OperationAnalyser*)
                                         allocate(sizeof(struct OperationAnalyser));
        opana->needFactor = 1;
        opana->numStack = newStack();
        opana->opStack = newStack();
        // 将一个左括号压入栈顶
    
        opana->consumeToken = consumeToken_OpAna;
        opana->consumeNonTerminal = consumeNonTerminal_OpAna;
        return opana;
    }

        上一节数据结构中,在算符优先分析器结构中有个神秘的needFactor成员我并没有给出注释,现在补述一下:这个成员指出接下来一个词法分析得到的Token是否应该某个因子的一部分,特别是读入"+""-",只有借助它来判别是正负号还是加减号。另外,它在算符优先分析中可以为错误处理提供强力帮助:由于一个算符优先分析器要么立即需要一个因子,要么立即需要一个运算符,所以词法分析获取一个Token传入该分析器以后,可以查询该Token的类型是否属于因子或者算符的First集合来判别当前Token类型是否正确。在这里

        First( 因子 ) = { PLUS, MINUS, INTEGER, REAL, LPARENT, IDENT }

        First( 算符 ) = { 各种运算符 }

    当然不必担心两者交集不为空会导致什么故障发生,这里并不是先判断该符号属于哪个集合,而是先看needFactor再分开分析,即OperationAnalyserconsumeToken函数可以实现为一个中转函数:

    void consumeToken_OpAna(void* self, struct Token* token)
    {
        struct OperationAnalyser* opana = (struct OperationAnalyser*)self;
        if(opana->needFactor) {
           consumeFactor(opana, token);
        } else {
           consumeOperator(opana, token);
        }
    }
    

    不过,有一个例外,就是所有左置的一元运算符,如NOT,它们的出现也会打乱区分工作,因此它们都应该看作 First( 因子 ) 中的成员,如consumeFactor的一种实现方式:

    void consumeFactor(struct OperationAnalyser* self,
                                        struct Token* token)
    {
        if(NOT == token->type) {
            self->opStack->push(self->opStack,
                                newOperator(token->type,
                                            /* 未实现:对应的优先级数 */ -1,
                                            unaryOperate));
            self->needFactor = 1;
        } else if(MINUS == token->type || PLUS == token->type) {
            // 将 MINUS 或 PLUS 作为一元运算符入栈
            self->needFactor = 1;
        } else if(IDENT == token->type) {
            // 弄一个识别变量的分析器 varAna 扔到 分析器栈 栈顶
            // varAna->consumeToken(varAna, token);
            return;
        } else if(INTEGER == token->type) {
            self->numStack->push(self->numStack,
                                 newIntegerNode(atoi(token->image)));
            self->needFactor = 0;
        } else if(REAL == token->type) {
            self->numStack->push(self->numStack, newRealNode(atof(token->image)));
            self->needFactor = 0;
        } else if(LPARENT == token->type) {
            // 正括号入栈
            self->needFactor = 1;
        } else {
            // 报错
        }
    } 

    这里有个小问题,就是将MINUSPLUS作为一元运算符入栈时,栈内存放的是什么?如果是一个Token*,那么一来信息太少,以后从栈中取出操作符时就无从知道它到底是一元操作符还是二元的,另外,对于提供Token*的函数,它必须知道这个Token*是否还能重用,比如如果压入的是数,那么重用是没问题的,因为Token*已经被变成了IntegerNodeRealNode,而符号就不一样,这样增加了词法的复杂度。因此,需要另一种数据结构。

    struct Operator {
        void (*operate)(struct Operator*, struct Stack*);
        AcceptType op;
        int priority;
        int rightCombination;
    };
    
    struct Operator* newOperator(AcceptType op, int priority,
                                  void (*operate)(struct Operator*, struct Stack*));
    void nullOperate(struct Operator*, struct Stack*);
    void unaryOperate(struct Operator*, struct Stack*);
    void binaryOperate(struct Operator*, struct Stack*);
    

     其中,op表示算符类型,priority表示算符优先级数,越小优先级越高,rightCombination表示是否右结合,operate成员函数则指出该算符应该如何进行运算,它应该是nullOperate(非运算),unaryOperate(一元运算),binaryOperate(二元运算)三者之一。newOperator则提供了一个构造函数。这些劳什子的可以这样实现:

    struct Operator* newOperator(AcceptType op, int priority,
                                   void (*operate)(struct Operator*, struct Stack*))
    {
        struct Operator* oper = (struct Operator*)allocate(sizeof(struct Operator));
        oper->op = op;
        oper->priority = priority;
        oper->rightCombination = (ASSIGN == op); // ... 暂时就这么办吧
        oper->operate = operate;
        return oper;
    }
    
    void nullOperate(struct Operator* oper, struct Stack* numStack)
    {
        revert(oper);
    }
    
    void unaryOperate(struct Operator* oper, struct Stack* numStack)
    {
        struct AbstractValueNode* value;
        if(MINUS == oper->op) {
            value = (struct AbstractValueNode*)(numStack->pop(numStack));
            numStack->push(numStack,
                           newOperationNode(oper->op,
                                       (struct AbstractValueNode*)newIntegerNode(0),
                                       value));
        }
        revert(oper);
    }
    
    void binaryOperate(struct Operator* oper, struct Stack* numStack)
    {
        struct AbstractValueNode* left,* right;
        right = (struct AbstractValueNode*)(numStack->pop(numStack));
        left = (struct AbstractValueNode*)(numStack->pop(numStack));
        numStack->push(numStack, newOperationNode(oper->op, left, right));
        revert(oper);
    }
    

    这样一来consumeFactor中某些分支可以这样写:

        if(MINUS == token->type || PLUS == token->type) {
            self->opStack->push(self->opStack,
                                newOperator(token->type, 0, unaryOperate));
            self->needFactor = 1;
        }
    // ... ...
        if(LPARENT == token->type) {
            self->opStack->push(self->opStack, newOperator(token->type,
                                                           0x7fffffff, /* max integer */
                                                           nullOperate));
            self->needFactor = 1;
        }

     

    接下来是consumeOperator的实现。为了不让优先级成为一个头痛的问题,这里弄一个优先级表,它的顺序对应于AcceptType中各符号:

    const int PRIORITY[] = {
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0,
        2, 2, 1, 1, 5, 3, 3, 3, 3, 3, 3,
        5, 6, 4,
        0, 0, 0x7fffffff, 0, 0, 0, 0, 0
    };
    

    这里面的0不是优先级最高的意思了(优先级数为0的正负号在构造时是手动设置的),而是表示不应该在这时出现这样的符号,当然有一个例外,就是反括号。consumeOperator可以这样部分地实现:

    void consumeOperator(struct OperationAnalyser* self,
                                          struct Token* token)
    {
        int priority = PRIORITY[token->type];
        if(0 < priority && priority < PRIORITY[LPARENT]) {
            int push = 0;
            struct Operator* topOp = (struct Operator*)
                                             (self->opStack->peek(self->opStack));
            push |= (priority < topOp->priority);
            push |= (priority == topOp->priority && topOp->rightCombination);
            while(!push) {
                topOp = (struct Operator*)(self->opStack->pop(self->opStack));
                topOp->operate(topOp, self->numStack);
                topOp = (struct Operator*)(self->opStack->peek(self->opStack));
                push |= (priority < topOp->priority);
                push |= (priority == topOp->priority && topOp->rightCombination);
            }
            self->opStack->push(self->opStack, newOperator(token->type,
                                                           priority,
                                                           binaryOperate));
            self->needFactor = 1;
        } else if(RPARENT == token->type) {
            struct Operator* topOp = (struct Operator*)
                                             (self->opStack->pop(self->opStack));
            while(nullOperate != topOp->operate) { // 注1
                topOp->operate(topOp, self->numStack);
                topOp = (struct Operator*)(self->opStack->pop(self->opStack));
            }
            topOp->operate(topOp, self->numStack);
            if(0 == self->opStack->getSize(self->opStack)) { // 注2
                // 报错
            }
            self->needFactor = 0;
        } else {
            // 终止
        }
    }
    

    前面读到一般运算符时进行的分析,思路还算清晰;后面注出的两个条件,可能形式上不是很确切。

        注1:nullOperate != topOp->operate 实际上是在查看栈顶运算符是否是正括号,因为只有正括号的operate函数才为nullOperate

        注2:0 == self->opStack->getSize(self->opStack) 判断栈底默认压入的正括号是否被弹出,如果被弹出则说明正反括号实际上是不配对的(反括号多1)。

        此外,这个循环

            push |= (priority < topOp->priority);
            push |= (priority == topOp->priority && topOp->rightCombination);
            while(!push) {
                topOp = (struct Operator*)(self->opStack->pop(self->opStack));
                topOp->operate(topOp, self->numStack);
                topOp = (struct Operator*)(self->opStack->peek(self->opStack));
                push |= (priority < topOp->priority);
                push |= (priority == topOp->priority && topOp->rightCombination);
            }
    

    其实你可以把它当作一个for循环来理解,push这个量为1时,表示当前传入的这个运算符应该被压入栈中。

        最后,读到不正确的符号时,并不能说明分析出错,也很可能是因为一个表达式已经接近完成并应该返回给分析器栈次栈顶的分析器了。

     

        最后大致提一下consumeNonTerminal_OpAna这个函数,其实它非常简单,因为算符优先分析只会委托另一分析器为之提供一个VariableNode,因此只要该分析器正确返回,那么只需

    void consumeNonTerminal_OpAna(void* self,
                                             struct AbstractSyntaxNode* node)
    {
        struct OperationAnalyser* opana = (struct OperationAnalyser*)self;
        opana->numStack->push(opana->numStack, node);
        opana->needFactor = 0;
    }
    

    就行了,而如果该分析器没有正常返回——就把错误处理给那个分析器做吧。

     

        这一篇文章中很多代码都是未完成的,因为分析器不是一个独立的结构,牵扯到很多控制结构和其他分析器。不过我会尽快给出一个方案让算符优先分析尽可能地独立出来进行测试,以减少语法分析模块整体的测试难度。

    展开全文
  • 物流业是指物品从供应地向接受地的实体流动过程,是将运输、储存、装卸、搬运、包装、流通加工、配送、信息处理等基本功能根据实际需要实施有机结合的活动的集合。物流业是一生产性服务业,为第一、二、三产业的...
  • 3.5 可否用显式括号来强制执行我所需要的计算顺序并控制相关的副作用?就算括号不行,操作符优先级是否能够控制计算顺序呢? 64 3.6 可是&&和||操作符呢?我看到过类似while((c = getchar()) != EOF && c != '\n')...
  • 3.5 可否用显式括号来强制执行我所需要的计算顺序并控制相关的副作用?就算括号不行,操作符优先级是否能够控制计算顺序呢? 3.6 可是&&和||操作符呢?我看到过类似while((c = getchar()) != EOF && c != '\n')的...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 132
精华内容 52
关键字:

两种不相关的东西结合的