期货量化软件;赫兹量化国联期货极速版普拉特和分流场解析器
解析器采用运算符优先级我们要研究的下一个解析器类型是优先级解析器。 它们具有更紧凑的实现,因为类方法并非基于语法规则创建的(在这种情况下,每个规则都转换为单独的方法),而是采用更通用的形式,仅考虑运算符的优先级。在 EBNF 语法说明中,操作的优先级已经以隐式形式出现:其规则执行从低优先级操作到高优先级操作,直至终结实体 — 常量和变量。 这是因为在没有显式括号分组的情况下,优先级判定应是操作执行的顺序。 例如,乘法运算的优先级高于加法的优先级。 但是一元减号优先于乘法。 语法树元素越靠近根部(整个表达式),对其进行评估越靠后。为了实现解析器,我们需要两个表,每张表的数值与每个操作的优先级相对应。 值越高,优先级越高。我们有两张表,因为一元和二元运算会在算法中逻辑上分开。 实际上,我们不仅在讨论操作,且在更广泛地讨论有关在表达式中如何找到可作为前缀和后缀的符号(Wikipedia 上有更多关于操作符类型的信息)。顾名思义,前缀是操作数之前的符号(例如,“!var” 表达式中的 “!”),而中缀是操作数之间的字符(例如,表达式 ”a + b“ 中的 ‘+’)。 还有一些后缀(例如,增量运算符中的一对 “+”,在 MQL 中也可以用 — “i++”),但是我们在表达式中没有用到它们,因此我们先不考虑它们。除了一元运算符 '!','-','+' 外,前缀还可以是一个开始括号 '(' — 表示分组的开头;字母或下划线 — 表示标识符的开头;以及数字或句点 “.” — 表示数字常数的开头。我们讲述 ExpressionPrecedence 类中的表,它继承自某些基于优先级的解析器类。 所有这些解析器将与 Promise 一起操作。class ExpressionPrecedence: public AbstractExpressionProcessor<Promise *>{ protected: static uchar prefixes; static uchar infixes; static ExpressionPrecedence epinit; static void initPrecedence() { // 分组 prefixes['('] = 9; // 一元运算符 prefixes['+'] = 9; prefixes['-'] = 9; prefixes['!'] = 9; // 标识符 prefixes['_'] = 9; for(uchar c = 'a'; c <= 'z'; c++) { prefixes = 9; } // 数字 prefixes['.'] = 9; for(uchar c = '0'; c <= '9'; c++) { prefixes = 9; } // 运算符 // infixes['('] = 9; // 此处不将括号用作“函数调用”运算符 infixes['*'] = 8; infixes['/'] = 8; infixes['%'] = 8; infixes['+'] = 7; infixes['-'] = 7; infixes['>'] = 6; infixes['<'] = 6; infixes['='] = 5; infixes['!'] = 5; infixes['&'] = 4; infixes['|'] = 4; infixes['?'] = 3; infixes[':'] = 2; infixes[','] = 1; // 参数列表定界符 } ExpressionPrecedence(const bool init) { initPrecedence(); } public: ExpressionPrecedence(const string vars = NULL): AbstractExpressionProcessor(vars) {} ExpressionPrecedence(VariableTable &vt): AbstractExpressionProcessor(vt) {}}; static uchar ExpressionPrecedence::prefixes = {0};static uchar ExpressionPrecedence::infixes = {0};static ExpressionPrecedence ExpressionPrecedence::epinit(true);
页:
[1]