# Exactly the same rules as arith.gra, but now every expression has a type: # integer or real. In general, only arguments of the same type may be combined. # However, 0 is of both types, and sqrt applies to both types (and returns real). # ---------------------------------------------------------------------- # The most basic form of rule writing. 1 EXPR[sem=plus(x,y) type=t] EXPR[sem=x type=t] + TERM[sem=y type=t] 1 EXPR[sem=minus(x,y) type=t] EXPR[sem=x type=t] - TERM[sem=y type=t] 1 EXPR[sem=x type=t] TERM[sem=x type=t] # Again, the TERM rules are strictly analogous to the EXPR rules, # so we will use them to demonstrate some other notations for saying # that the two terms and the factor all have the same type. # # The multiplication rule has been split into two rules, one for # int and one for real. If one fails then the other will be used, # so 3 * 3 and pi * pi both work, not to mention 0 * 3 and 0 * pi. # We use itimes for integer multiplication and rtimes for real multiplication. 1 TERM[sem=itimes(1,3) type=1] TERM[type=int] * FACTOR[type=1] 1 TERM[sem=rtimes(1,3) type=1] TERM[type=real] * FACTOR[type=1] ## Subtle point: The following versions of the above rules would NOT work ## quite as desired, since buildattrs would assume that "int" and "real" were ## variables (just like "t" in the EXPR rules). Only identifiers that are ## used ONCE in a rule are treated as constants. ## 1 TERM[sem=itimes(1,3) type=int] TERM[type=int] * FACTOR[type=int] ## 1 TERM[sem=rtimes(1,3) type=real] TERM[type=real] * FACTOR[type=real] # Here, the first child TERM is constrained to have the same type as # the third child ("type=3"), which in turn is constrained to have the # same type as the parent ("type=0"). buildattrs does the right thing # and ensures that the parent receives the attribute. 1 TERM[sem=div(1,3)] TERM[type=3] / FACTOR[type=0] # The remaining rules make much use of the =1 notation so that the # parent can easily inherit a child's sem and type attributes without # spelling them out. 1 TERM[=1] FACTOR 1 FACTOR[=1] Num 1 FACTOR[=2] { EXPR } 1 FACTOR[sem=1(3) type=real] sqrt { EXPR } # EXPR can have either type 1 ROOT[=1] EXPR 1 Num[=1] 0 # just for fun, say 0 allows any type 1 Num[=1 type=int] 1 1 Num[=1 type=int] 2 1 Num[=1 type=int] 3 1 Num[=1 type=int] 4 1 Num[=1 type=int] 5 1 Num[=1 type=int] 6 1 Num[=1 type=int] 7 1 Num[=1 type=int] 8 1 Num[=1 type=int] 9 1 Num[=1 type=real] pi 1 Num[=1 type=real] e 1 Num[=1 type=real] 0.5