腹泻能吃什么| 破伤风感染后会出现什么症状| 表妹是什么意思| 洗手做羹汤是什么意思| 阴茎进入阴道是什么感觉| 总胆红素偏高是什么病| 做梦梦见好多蛇是什么预兆| 老人嘴唇发紫是什么原因| 今年是农历的什么年| 梦见自己换衣服是什么意思| 乌鸡汤放什么材料| 什么人不适合喝咖啡| 麻木是什么意思| 甜蜜素是什么东西| 感冒喝什么药| 魅力是什么意思| 右侧卵巢囊性回声什么意思| 映景是什么意思| 幺是什么意思| 山楂有什么功效| 子宫肌瘤吃什么中药可以消除掉| 面瘫吃什么药好得快| 大方得体是什么意思| 为什么会胰岛素抵抗| 宫颈囊肿多发是什么意思| 气加山念什么| 氨咖黄敏胶囊是治什么的| 扁桃体割了对身体有什么影响| 晚上吃芒果有什么好处和坏处| 水杯什么材质好| 早搏心律不齐吃什么药| 为什么闭眼单脚站不稳| 什么是早谢泄图片| 天罗地网是什么生肖| 童子尿能治什么病| 严重贫血吃什么补的快| 吃什么排出全身毒素| 痰多咳嗽是什么原因| 母亲节送什么颜色的康乃馨| 性感染有什么症状| 一个火一个斤念什么| 身上为什么会长小肉球| 今年闰六月有什么说法| 电瓶车充不进电是什么原因| 头部容易出汗是什么原因| ssa抗体阳性说明什么| 什么叫开门见床头| 闺蜜是什么样的关系| 甘胆酸偏高是什么原因| 尿胆红素高是什么原因| 生蚝吃了有什么好处| 梦到别人怀孕是什么意思| 游击战是什么意思| 嗓子疼吃什么水果好| 子欲养而亲不待什么意思| 白带是什么味道| 半夜是什么生肖| icloud是什么| 黄芪起什么作用| 34岁属什么的生肖| 龙抬头是什么意思| 肾窦分离是什么意思| 从容面对是什么意思| 沉沦是什么意思| 梨花是什么颜色的| 打脚是什么意思| 990是什么意思| 暄字五行属什么| 为什么喝水血糖也会高| 右肺下叶纤维灶是什么意思| 棉花什么时候传入中国| 肛门出血什么原因| 思维跳脱是什么意思| 乙酰胆碱的作用是什么| 数字2代表什么意思| 十二指肠球部溃疡吃什么药| 0和1什么意思| 对立面是什么意思| 数字8五行属什么| 浪子回头金不换是什么意思| 氟哌酸又叫什么名字| 梦见芝麻是什么意思| 吃头孢不能吃什么| 生化常规主要是检查什么的| 什么叫偏财| 血红蛋白低吃什么补最快| 病毒感染发烧吃什么药| 香芋紫是什么颜色| 吃什么补镁| 走马灯什么意思| 肾气不足吃什么药| 人为什么会长白头发| 吃什么可以止咳化痰| 为什么蚊子喜欢咬我| 膝盖小腿酸软无力是什么原因| 单纯是什么意思| 财评是什么意思| 家庭油炸用什么油好| 小孩放屁很臭是什么原因| lf是什么意思| 锰酸钾是什么颜色| 以什么之名| 电磁波是什么| 什么药治高血压效果最好| 女人内心强大说明什么| 梦见红枣树上结满红枣代表什么| 所言极是是什么意思| 革兰阳性杆菌是什么病| 荨麻疹涂什么药| 公务员是干什么工作的| 孕妇吃什么水果| 晰字五行属什么| 30度穿什么衣服合适| bn是什么颜色| wendy什么意思| 值神天德是什么意思| 完美收官是什么意思| 吃芒果后不能吃什么| 肝实质弥漫性回声改变什么意思| 小case什么意思| 高岭土是什么| 静养是什么意思| 肌酐偏高是什么意思| 凝是什么意思| 脸部麻木是什么的前兆| 18年是什么年| 左眉上方有痣代表什么| 9月14日是什么星座| 梦见自己的头发长长了是什么意思| 为什么会得神经性皮炎| 痛风买什么药| 小腹痛什么原因| 宫腔线不清晰什么意思| 甲状腺结节用什么药| 胃复安又叫什么名字| blk是什么意思| 农历七月二十什么日子| 牙补好了还会痛什么原因| 齁是什么意思| 测智力去医院挂什么科| 孕妇吃什么蔬菜对胎儿好| 窦性心动过缓是什么意思| 什么人什么天| 超声波检查是什么检查| 全身发麻是什么原因| 舌尖麻是什么原因| 龙日冲狗煞南是什么意思| 一什么手| 肚子疼是什么原因一阵一阵的| 喝枸杞水有什么好处| 指甲有竖纹吃什么药| 膝盖酸胀是什么原因| 地软有什么功效和作用| 10015是什么电话| 腹泻期间宜吃什么食物| 天庭是什么意思| 飞地是什么意思| 11月9日是什么星座| 护理学是什么| 睡醒头疼是什么原因| 7月15日是什么日子| co2是什么意思| 养肺补肺吃什么药最好| 太平天国为什么会失败| 小腿麻木是什么原因引起的| 高挑是什么意思| 为什么眼睛有红血丝| 马上好药膏主治什么| 骨头坏死是什么原因造成的| 五月掉床有什么说法| 增加性功能吃什么药| 兔子怕什么| 脚底板疼痛是什么原因| 核心抗体阳性说明什么| 酒后吐吃什么可以缓解| 白粉病用什么药| 斑鱼是什么鱼| 甘草有什么功效| 脾虚湿热吃什么药| 违反禁令标志指示什么意思| 标本是什么意思| 过梁是什么| 汉堡是什么意思| 脑梗是什么原因引起的| 脚底发烫是什么原因| 姜子牙为什么没有封神| 三花鱼是什么鱼| 执子之手与子偕老是什么意思| 1981年是什么年| 脾胃虚弱吃什么好| 胃袋是什么| 香叶是什么树叶| 艺高人胆大什么意思| 东北有什么特产| 三千大千世界什么意思| 阿托品是什么| 罢免是什么意思| 极化是什么意思| 药物过敏用什么药| 液基薄层细胞制片术是检查什么的| 映山红是什么花| 猫咪打呼噜代表什么| 什么叫射频消融| 全友床垫属于什么档次| nt是什么| 迪赛尼斯属于什么档次| 罢黜百家独尊儒术是什么意思| 严重失眠有什么方法| 居里夫人发明了什么| 女性白带发黄是什么原因| 外冷内热是什么症状| 马齿苋别名叫什么| 苯甲酸钠是什么| 欺凌是什么意思| 夏天脚出汗是什么原因| 大排是什么肉| 7月7日是什么日子| 钼靶检查是什么意思| 铁饱和度低什么原因| 清明为什么插柳枝| 什么天什么什么| 蓬蒿人是什么意思| 中筛是检查什么项目| 孩子高低肩有什么好办法纠正| 血小板偏高有什么危害| 什么叫幸福| 怀孕生化了有什么症状| 心经是什么意思| 粉刺是什么东西| 铁观音属于什么茶| 浮萍是什么植物| 白萝卜煮水喝有什么功效| 什么是排卵期怎么计算| 手串断了是什么预兆| 待定是什么意思| 心肌缺血有什么症状| 肾结石什么引起的| 尽兴而归什么意思| 房产税什么时候开始征收| 眼压是什么意思| 雷震子是什么神| 精神分裂是什么| 什么是健康管理| 扩心病是什么病| 鱼是什么结构| 吃什么对皮肤好还能美白的| 新生儿什么时候剪头发| 什么是转基因食品| 糖宝是什么虫| 狗是什么偏旁| 骏五行属什么| 欠佳是什么意思| 拿乔是什么意思| 抗炎和消炎有什么区别| 后人是什么意思| 怕老婆的男人说明什么| 六月初六是什么日子| h代表什么单位| 阿尔茨海默症是什么病| 儿童流鼻涕吃什么药| 学富五车是什么意思| 梦见租房子住是什么意思| 为什么会放屁| 什么是埋线减肥| 百度Jump to content

确保中小学生睡眠需要多措并举中小学生睡眠家长

From Wikipedia, the free encyclopedia
百度 只是森林狼固然取得一场漂亮的胜利,但美中不足的就是替补大将罗斯受伤。

In computer science, an operator-precedence parser is a bottom-up parser that interprets an operator-precedence grammar. For example, most calculators use operator-precedence parsers to convert from the human-readable infix notation relying on order of operations to a format that is optimized for evaluation such as Reverse Polish notation (RPN).

Edsger Dijkstra's shunting yard algorithm is commonly used to implement operator-precedence parsers.

Relationship to other parsers

[edit]

An operator-precedence parser is a simple shift-reduce parser that is capable of parsing a subset of LR(1) grammars. More precisely, the operator-precedence parser can parse all LR(1) grammars where two consecutive nonterminals and epsilon never appear in the right-hand side of any rule.

Operator-precedence parsers are not used often in practice; however they do have some properties that make them useful within a larger design. First, they are simple enough to write by hand, which is not generally the case with more sophisticated right shift-reduce parsers. Second, they can be written to consult an operator table at run time, which makes them suitable for languages that can add to or change their operators while parsing. (An example is Haskell, which allows user-defined infix operators with custom associativity and precedence; consequently, an operator-precedence parser must be run on the program after parsing of all referenced modules.)

Raku sandwiches an operator-precedence parser between two recursive descent parsers in order to achieve a balance of speed and dynamism. GCC's C and C++ parsers, which are hand-coded recursive descent parsers, are both sped up by an operator-precedence parser that can quickly examine arithmetic expressions. Operator-precedence parsers are also embedded within compiler-compiler-generated parsers to noticeably speed up the recursive descent approach to expression parsing.[1]

Precedence climbing method

[edit]

The precedence climbing method is a compact, efficient, and flexible algorithm for parsing expressions that was first described by Martin Richards and Colin Whitby-Strevens.[2]

An infix-notation expression grammar in EBNF format will usually look like this:

expression ::= equality-expression
equality-expression ::= additive-expression ( ( '==' | '!=' ) additive-expression ) *
additive-expression ::= multiplicative-expression ( ( '+' | '-' ) multiplicative-expression ) *
multiplicative-expression ::= primary ( ( '*' | '/' ) primary ) *
primary ::= '(' expression ')' | NUMBER | VARIABLE | '-' primary

With many levels of precedence, implementing this grammar with a predictive recursive-descent parser can become inefficient. Parsing a number, for example, can require five function calls: one for each non-terminal in the grammar until reaching primary.

An operator-precedence parser can do the same more efficiently.[1] The idea is that we can left associate the arithmetic operations as long as we find operators with the same precedence, but we have to save a temporary result to evaluate higher precedence operators. The algorithm that is presented here does not need an explicit stack; instead, it uses recursive calls to implement the stack.

The algorithm is not a pure operator-precedence parser like the Dijkstra shunting yard algorithm. It assumes that the primary nonterminal is parsed in a separate subroutine, like in a recursive descent parser.

Pseudocode

[edit]

The pseudocode for the algorithm is as follows. The parser starts at function parse_expression. Precedence levels are greater than or equal to 0.

parse_expression()
    return parse_expression_1(parse_primary(), 0)
parse_expression_1(lhs, min_precedence)
    lookahead := peek next token
    while lookahead is a binary operator whose precedence is >= min_precedence
        op := lookahead
        advance to next token
        rhs := parse_primary ()
        lookahead := peek next token
        while lookahead is a binary operator whose precedence is greater
                 than op's, or a right-associative operator
                 whose precedence is equal to op's
            rhs := parse_expression_1 (rhs, precedence of op + (1 if lookahead precedence is greater, else 0))
            lookahead := peek next token
        lhs := the result of applying op with operands lhs and rhs
    return lhs

Note that in the case of a production rule like this (where the operator can only appear once):

equality-expression ::= additive-expression  ( '==' | '!=' ) additive-expression

the algorithm must be modified to accept only binary operators whose precedence is > min_precedence.

Example execution of the algorithm

[edit]

An example execution on the expression 2 + 3 * 4 + 5 == 19 is as follows. We give precedence 0 to equality expressions, 1 to additive expressions, 2 to multiplicative expressions.

parse_expression_1 (lhs = 2, min_precedence = 0)

  • the lookahead token is +, with precedence 1. the outer while loop is entered.
  • op is + (precedence 1) and the input is advanced
  • rhs is 3
  • the lookahead token is *, with precedence 2. the inner while loop is entered.
    parse_expression_1 (lhs = 3, min_precedence = 2)
  • the lookahead token is *, with precedence 2. the outer while loop is entered.
  • op is * (precedence 2) and the input is advanced
  • rhs is 4
  • the next token is +, with precedence 1. the inner while loop is not entered.
  • lhs is assigned 3*4 = 12
  • the next token is +, with precedence 1. the outer while loop is left.
  • 12 is returned.
  • the lookahead token is +, with precedence 1. the inner while loop is not entered.
  • lhs is assigned 2+12 = 14
  • the lookahead token is +, with precedence 1. the outer while loop is not left.
  • op is + (precedence 1) and the input is advanced
  • rhs is 5
  • the next token is ==, with precedence 0. the inner while loop is not entered.
  • lhs is assigned 14+5 = 19
  • the next token is ==, with precedence 0. the outer while loop is not left.
  • op is == (precedence 0) and the input is advanced
  • rhs is 19
  • the next token is end-of-line, which is not an operator. the inner while loop is not entered.
  • lhs is assigned the result of evaluating 19 == 19, for example 1 (as in the C standard).
  • the next token is end-of-line, which is not an operator. the outer while loop is left.

1 is returned.

Pratt parsing

[edit]

Another precedence parser known as Pratt parsing was first described by Vaughan Pratt in the 1973 paper "Top Down Operator Precedence",[3] based on recursive descent. Though it predates precedence climbing, it can be viewed as a generalization of precedence climbing.[4]

Pratt designed the parser originally to implement the CGOL programming language, and it was treated in much more depth in a Masters Thesis under his supervision.[5]

Tutorials and implementations:

Alternative methods

[edit]

There are other ways to apply operator precedence rules. One is to build a tree of the original expression and then apply tree rewrite rules to it.

Such trees do not necessarily need to be implemented using data structures conventionally used for trees. Instead, tokens can be stored in flat structures, such as tables, by simultaneously building a priority list which states what elements to process in which order.

Full parenthesization

[edit]

Another approach is to first fully parenthesize the expression, inserting a number of parentheses around each operator, such that they lead to the correct precedence even when parsed with a linear, left-to-right parser. This algorithm was used in the early FORTRAN I compiler:[7]

The Fortran I compiler would expand each operator with a sequence of parentheses. In a simplified form of the algorithm, it would

  • replace + and with ))+(( and ))-((, respectively;
  • replace * and / with )*( and )/(, respectively;
  • add (( at the beginning of each expression and after each left parenthesis in the original expression; and
  • add )) at the end of the expression and before each right parenthesis in the original expression.

Although not obvious, the algorithm was correct, and, in the words of Knuth, “The resulting formula is properly parenthesized, believe it or not.”[8]

Example code of a simple C application that handles parenthesisation of basic math operators (+, -, *, /, ^, ( and )):

#include <stdio.h>
#include <string.h>

// The command-line argument boundary is our lexer.
int main(int argc, char *argv[]) {
  int i;
  printf("((((");
  for (i=1; i!=argc; i++) {
    // strlen(argv[i]) == 2
    if (argv[i] && !argv[i][1]) {
      switch (*argv[i]) {
          case '(': printf("((((");  continue;
          case ')': printf("))))");  continue;
          case '^': printf(")^(");   continue;
          case '*': printf("))*(("); continue;
          case '/': printf("))/(("); continue;
          case '+':
            // unary check: either first or had an operator expecting secondary argument
            if (i == 1 || strchr("(^*/+-", *argv[i-1]))
              printf("+");
            else
              printf(")))+(((");
            continue;
          case '-':
            if (i == 1 || strchr("(^*/+-", *argv[i-1]))
              printf("-");
            else
              printf(")))-(((");
            continue;
      }
    }
    printf("%s", argv[i]);
  }
  printf("))))\n");
  return 0;
}

First, you need to compile your program. Assuming your program is written in C and the source code is in a file named program.c, you would use the following command:

gcc program.c -o program

The above command tells gcc to compile program.c and create an executable named program.

Command to run the program with parameters, For example; a * b + c ^ d / e

./program a '*' b + c '^' d / e

it produces

((((a))*((b)))+(((c)^(d))/((e))))

as output on the console.

A limitation to this strategy is that unary operators must all have higher precedence than infix operators. The "negative" operator in the above code has a higher precedence than exponentiation. Running the program with this input

- a ^ 2

produces this output

((((-a)^(2))))

which is probably not what is intended.

References

[edit]
  1. ^ a b Harwell, Sam (2025-08-04). "Operator precedence parser". ANTLR3 Wiki. Retrieved 2025-08-04.
  2. ^ Richards, Martin; Whitby-Strevens, Colin (1979). BCPL — the language and its compiler. Cambridge University Press. ISBN 9780521219655.
  3. ^ Pratt, Vaughan. "Top Down Operator Precedence." Proceedings of the 1st Annual ACM SIGACT-SIGPLAN Symposium on Principles of Programming Languages (1973).
  4. ^ Norvell, Theodore. "Parsing Expressions by Recursive Descent". www.engr.mun.ca. The purpose of this post is to [... start] with precedence climbing and refactoring it to use the command pattern until we arrive at a Pratt parser. [This is the author who coined the term "precedence climbing".]
  5. ^ Van De Vanter, Michael L. "A Formalization and Correctness Proof of the CGOL Language System." (Master's Thesis). MIT Laboratory for Computer Science Technical Report MIT-LCS-TR-147 (Cambridge, Massachusetts). 1975.
  6. ^ Crockford, D (2025-08-04). "Top Down Operator Precedence".
  7. ^ Padua, David (2000). "The Fortran I Compiler" (PDF). Computing in Science & Engineering. 2 (1): 70–75. Bibcode:2000CSE.....2a..70P. doi:10.1109/5992.814661.
  8. ^ Knuth, Donald E. (1962). "A HISTORY OF WRITING COMPILERS". Computers and Automation. 11 (12). Edmund C. Berkeley: 8–14.
[edit]
白加黑是什么颜色 球蛋白偏低是什么原因 肠胃功能紊乱吃什么药 为什么不建议光子嫩肤 acca是什么专业
查雌激素挂什么科 什么是前列腺增生 轻食是什么 尿电导率低是什么意思 乙型肝炎病毒表面抗体阳性是什么意思
芽菜是什么菜 眼睛痒是怎么回事用什么药 小孩突然头疼是什么原因 单人旁的字有什么 四眼狗有什么迷信说法
产后吃什么水果好 cg是什么 86年属虎是什么命 国籍填什么 人生轨迹是什么意思
逆钟向转位什么意思hcv7jop9ns3r.cn 晴对什么adwl56.com 钊字五行属什么hcv9jop6ns1r.cn 焯是什么意思hcv8jop4ns6r.cn 不在服务区是什么意思hcv9jop2ns5r.cn
ganni是什么牌子hcv9jop0ns3r.cn 肋骨断了是什么感觉hcv8jop2ns4r.cn pv值是什么意思hcv8jop9ns0r.cn ahc是什么牌子hcv8jop0ns3r.cn 左眼皮跳代表什么hcv8jop3ns0r.cn
脑梗不能吃什么hcv8jop6ns8r.cn 3月17日是什么星座的hcv9jop6ns9r.cn 天花板是什么意思gysmod.com 嘴唇干燥是什么原因hcv9jop4ns2r.cn 荷花什么时候开hcv8jop5ns7r.cn
什么牌的笔记本电脑好hcv8jop2ns3r.cn 为什么尿液一直是黄的baiqunet.com 血压偏低是什么原因hcv8jop1ns3r.cn 什么鸡适合炖汤hcv8jop0ns0r.cn 旦角是什么意思hcv9jop0ns5r.cn
百度