1. 从表达式解析看S属性与L属性的本质区别
我第一次接触S属性和L属性是在实现一个简单的数学表达式计算器时。当时需要处理类似"3*(5+2)-4"这样的表达式,但发现不同解析方式对计算顺序和结果有巨大影响。这让我意识到属性计算顺序的重要性。
**S属性(综合属性)*就像搭积木,必须从最底层的积木开始,一层层向上构建。在表达式"3(5+2)"中,必须先计算"5+2=7",再用结果计算"3*7"。这种自底向上的计算方式天然适合栈结构,也是大多数计算器的工作方式。
# S属性风格的计算器实现示例
def eval_expression(tokens):
stack = []
for token in tokens:
if token.isdigit():
stack.append(int(token)) # 数字直接入栈
else:
b = stack.pop() # 先弹出右操作数
a = stack.pop() # 再弹出左操作数
if token == '+': stack.append(a + b)
elif token == '*': stack.append(a * b)
return stack[0]
**L属性(继承属性)**则像传家宝,属性值从父节点传递给子节点。比如在类型声明"int a,b,c"中,类型信息"int"需要沿着语法树向下传递到每个变量。这种自上而下的特性天然适合递归下降解析。
# L属性风格的类型声明处理示例
def parse_declaration(decl_type):
variables = []
while has_more_tokens():
var = parse_identifier()
var.type = decl_type # 类型信


476

被折叠的 条评论
为什么被折叠?



