好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

编译原理与技术 语法制导翻译.ppt

62页
  • 卖家[上传人]:工****
  • 文档编号:588003264
  • 上传时间:2024-09-07
  • 文档格式:PPT
  • 文档大小:335.08KB
  • / 62 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • 编译原理与技术语法制导翻译9/7/20241《编译原理与技术》讲义 语法制导翻译¡属性文法lS-属性定义lL-属性定义l语法制导定义与翻译方案¡自底向上翻译lS-属性定义自底向上计算l自底向上计算继承属性¡自顶向下翻译9/7/20242《编译原理与技术》讲义 属性文法¡属性文法(Attributed Grammar)上下文无关文法上下文无关文法+属性属性+属性计算规则属性计算规则™ 属性-用来描述文法符号的语义特征,如常量的“值”、变量的类型和存储位置等e.g. 二义性表达式文法G,非终结符E有属性E.val(表达式的值)EE ‘+’ E | E ‘*’ E | ‘(‘ E ‘)’ | number™ 属性计算规则(语义规则)与产生式相关联的反映文法符号属性之间关系的“规则”9/7/20243《编译原理与技术》讲义 ¡属性文法™语法制导定义(文法+属性+语义规则)语义规则仅表明属性间“抽象”关系,不涉及具体翻译实现细节,如计算次序等™翻译方案(文法+属性+语义动作)语义规则-即语义动作,可体现若干实现的细节9/7/20244《编译原理与技术》讲义 e.g.1算术表达式的计算器 产生式 语法制导定义EE1 ‘+’ E2 E.val := E1.val + E2.valEE1 ‘*’ E2 E.val := E1.val * E2.valE’(‘ E1 ‘)’ E.val := E1.valEnumber E.val := number.lex_val9/7/20245《编译原理与技术》讲义 e.g.1算术表达式的计算器 产生式 翻译方案EE1 ‘+’ E2 { E.val := E1 .val + E2.val }EE1 ‘*’ E2 { E.val := E1.val * E2.val }E’(‘ E1 ‘)’ { E.val := E1.val }Enumber { E.val := number.lex_val }9/7/20246《编译原理与技术》讲义 属性文法¡属性的分类若产生式AX1X2…Xn,与之相关的属性计算规则b := f ( c1, c2, … )-如果属性b是产生式左部符号左部符号A的属性的属性则称其为A的的综合属性;综合属性;-如果属性b是产生式右部符号右部符号Xi的属性的属性则称其为Xi的继承属性;的继承属性;--c1, c2, … 一般是产生式右部其它符号的(综合)属性或A的继承属性;- 固有属性:终结符仅有的属性。

      如number.lex_val通常由词法程序提供9/7/20247《编译原理与技术》讲义 A.bX1.c1X2.c2X…综合属性A.b的计算A的继承属性AX1.c1X2.c2…继承属性Xk.b的计算A的继承属性Xk.bX属性依赖图9/7/20248《编译原理与技术》讲义 e.g. 2 属性依赖图:3+4×5E. val = 23E. val = 3+E. val = 20number. lex_val = 3E. val = 4×E. val = 5number. lex_val = 4number. lex_val = 59/7/20249《编译原理与技术》讲义 语义规则的计算方法¡分析树方法- 为输入串建立分析树- 由语义规则建立属性依赖图(没有属性循环依赖的)- 对依赖图进行拓扑排序,得到属性计算次序- 依次计算属性,得到“翻译”结果¡基于规则的方法- 构造编译器时,事先对产生式的语义规则进行分析,得到属性计算次序¡忽略规则的方法- 属性计算次序仅由分析方法限定如S-属性定义可以在自下而上分析时,在归约前计算如YACC中的语义动作9/7/202410《编译原理与技术》讲义 e.g. 3 属性计算次序: 3+4×5E. val = 23E. val = 3+E. val = 20number. lex_val = 3E. val = 4×E. val = 5number. lex_val = 4number. lex_val = 5123456789/7/202411《编译原理与技术》讲义 S-属性定义-语义规则仅包含综合属性计算(可以有固有属性出现)。

      -适合自底向上计算e.g. 语法树-语法树与分析树 语法树可看作分析树的浓缩也称抽象语法树而分析树可看成具体语法树9/7/202412《编译原理与技术》讲义 S  if B-expr then S1 else S2语法树 分析树语法树 vs. 分析树if-then-elseB-exprS1S2Sif B-expr then S1else S29/7/202413《编译原理与技术》讲义 a := b* -c + b * -c 语法树 分析树 语法树 vs. 分析树assigna+*b@c*b@cassignEEE+E*EbE@Ea赋值语句cE*EbE@c算符9/7/202414《编译原理与技术》讲义 DAG(去除了公共子表达式的无环有向图)a := b* -c + b * -c 语法树 vs. DAGassigna+*b@c*b@cassigna+*b@c语法树DAG9/7/202415《编译原理与技术》讲义 e.g.4 构造表达式的语法树(DAG)产生式 语义规则EE1 + E2 E.nptr := mknode(‘+’,E1.nptr, E2.nptr)EE1 - E2 E.nptr := mknode(‘-’,E1.nptr, E2.nptr)EE1 * E2 E.nptr := mknode(‘*’,E1.nptr, E2.nptr)EE1 / E2 E.nptr := mknode(‘/’,E1.nptr, E2.nptr)E( E1 ) E.nptr := E1.nptrE - E1 E.nptr := mknode(‘@’,E1.nptr, -)Enumber E.nptr := mkleaf(‘NUM’,number.lex_val)Eid E.nptr := mkleaf(‘ID’,id.entry)9/7/202416《编译原理与技术》讲义 e.g.4 构造表达式的语法树(DAG)E.nptr - E的语法树(根结点指针) mknode(op, left, right)-建立一个表达式语法树结点,它的运算符为op,左、右运算对象是left和right所指的语法树。

      如果建成DAG,则需要检查是否已存在相应内部结点op,其左右运算对象分别是left和right若没有则新建一个 mkleaf(‘NUM’,number.lex_val)- mkleaf(‘ID’,id.entry)-建立表达式语法树的叶结点建DAG也需检查是否已有相应结点9/7/202417《编译原理与技术》讲义 ¡e.g.4 构造表达式a+b*-4的属性结构树 E.nptrE.nptrE.nptr+E.nptrE.nptr*ab@E.nptr4ID aID bNUM4@ -* + 9/7/202418《编译原理与技术》讲义 ¡e.g.4 构造表达式a+b*-4的语法树(DAG) + ID a* ID b@ -NUM49/7/202419《编译原理与技术》讲义 L-属性定义-如果产生式AX1X2…Xn 的语义规则只计算1)A的综合属性,或者2)Xi的继承属性,且该属性仅依赖于产生式右部Xi的左边符号Xj(j

      9/7/202420《编译原理与技术》讲义 深度优先次序procedure dfvisit( n : node )beginfor each child m of n, from left to right do begin evaluate inherited attributes of m; dfvisit( m ) ; end; evaluate synthesized attributes of n;end9/7/202421《编译原理与技术》讲义 e.g.5 非L-属性定义的语法制导定义产生式语义规则ALML.i := l(A.i)M.i := m(L.s)A.s := f(M.s)AQRR.i := r(A.i)Q.i := q(R.s)A.s := f(Q.s)9/7/202422《编译原理与技术》讲义 翻译方案中的动作-语义动作可放在产生式右端任何位置;这也就显式地给出了动作的执行时刻可认为是在深度优先遍历中的执行时刻)e.g. 6将含有+和-运算的中缀表达式翻译为后缀形式:ET RR addop T { print( addop.lex_val) } R | T number { print( number.lex_val) }9/7/202423《编译原理与技术》讲义 e.g. 6 中缀翻译为后缀 :9-4+5ETR9print(9)-Tprint(‘-’)R4print(4)+Tprint(‘+’)5print(5)R123459/7/202424《编译原理与技术》讲义 翻译方案中的动作-设计翻译方案时,必须保证动作所引用的属性值是可用的。

      -只有综合综合属性时(S-属性定义),动作放在产生式末尾;- 若有继承属性时,动作的放置须保证:- (产生式右部)符号的继承属性必须在此符号前计算;- 动作不要引用其右边符号的综合属性;- 左部非终结符的综合属性一般放在产生式末 尾(确保它引用的属性均已计算完且可用)9/7/202425《编译原理与技术》讲义 e.g.7 翻译方案的书写S  A1 A2 { A1.in := 1 ; A2.in := 2 } A  a { print( A.in ) }改写为:S  { A1.in := 1 } A1 { A2.in := 2 } A2 A  a { print( A.in ) }9/7/202426《编译原理与技术》讲义 e.g.8 类型说明的语法制导定义(0) 产生式语义规则 DT L L.in := T.type Tint T.type := integer Treal T.type := real LL1 , id L1.in := L.in addtype(id.entry, L.in) Lid addtype(id.entry, L.in)9/7/202427《编译原理与技术》讲义 e.g.8 类型说明的语法制导定义(0)-属性传递DTLL,kL,jiint9/7/202428《编译原理与技术》讲义 e.g.8类型说明的语法制导定义(1)¡改写上述类型声明文法,使得其中的T成为L的子结点(即产生式右部),可以避免继承属性的使用。

      修改后文法如下:DL Tint Treal LL1 , id LT id9/7/202429《编译原理与技术》讲义 e.g.8类型说明的语法制导定义(2) 产生式语义规则 D L Tint T.type := integer Treal T.type := real LL1 , id L.in := L1.in addtype(id.entry, L1.in)LT id addtype(id.entry, T.type); L.in := T.type9/7/202430《编译原理与技术》讲义 e.g.8类型说明的语法制导定义(2)属性传递DTLL,kL,jiint9/7/202431《编译原理与技术》讲义 e.g.8 类型说明的语法制导定义(3)¡Pascal语言类型声明文法如下: DL : T Tint Treal LL1 , id Lid该声明文法的“问题”在于,L中声明的变量的类型T处于产生式中L的右边!若用继承属性L.in来传递类型信息T.type形成非L-属性定义。

      从而无法在完成L分析同时将有关类型信息填入符号表!可以可以考虑将考虑将T作为作为L的子结点(通过修的子结点(通过修改文法)来改变这种情况改文法)来改变这种情况9/7/202432《编译原理与技术》讲义 e.g.8 类型说明的语法制导定义(4) 产生式语义规则 D id L addtype(id.entry,L.in)Tint T.type := integer Treal T.type := real L, id L1 L.in := L1.in addtype(id.entry, L1.in)L : T L.in := T.type9/7/202433《编译原理与技术》讲义 e.g.9 翻译方案的计算次序EE+T { print( “1” ) }ET { print( “2” ) }TT*F { print( “3” ) }TF { print( “4” ) }F(E) { print( “5” ) }Fid { print( “6” ) }输入串是id*(id+id)时,该翻译方案输出什么?9/7/202434《编译原理与技术》讲义 S-属性定义的自底向上计算¡拓广分析栈,即添加属性栈,包含文法符号的综合属性。

      在归约实施前,右部各符号的综合属性(若有的话)已放在与符号位置对应的属性栈上,因此,可以先计算获得左部非终结符的综合属性然后再归约,这时从分析栈中弹出句柄,(注意,此时改变栈顶注意,此时改变栈顶top即可即可)最后,将左部符号连同其属性放入由top指示的分析栈及属性栈的位置中¡这种属性栈只能存放综合属性¡回想YACC中如何做的?9/7/202435《编译原理与技术》讲义 如果AXYZ,相关语义规则如下:A.a := f(X.x,Y.y,Z.z)显然,X.x在Val[top-2]Y.y在Val[top-1]Z.z在Val[top]A.a在Val[ntop] ,ntop = top – |句柄长度|+1Val[ ntop ] := f( val[top-2], Val[top-1], Val[top] )属性栈与分析栈ZZ.zYY.yXX.x…………分析栈属性栈Valtopbottom9/7/202436《编译原理与技术》讲义 ¡如果AB ,相关语义规则如下:A.a := B.b 显然,B.b在Val[top]A.a在Val[ntop] ,ntop = top – 1+1 = top ,即归约前后栈顶top不变,也即Val[ ntop ] 和 Val[top]对应属性栈同一个单元,所以,可以省略原语义规则对应的属性栈操作:所以,可以省略原语义规则对应的属性栈操作:Val[ntop] := Val[top]属性栈与分析栈BB.b…………分析栈属性栈Valtopbottom9/7/202437《编译原理与技术》讲义 e.g.10 计算表达式的(栈)代码产生式语义规则代码段LE ‘\n’Print( E.val )Print( Val[top-1] )EE1+TE.val := E1.val + T.valVal[ntop]:=Val[top-2]+Val[top]ETE.val := T.valTT1*FT.val := T1.val * F.valVal[ntop]:=Val[top-2]*Val[top]TFT.val := F.valF(E)F.val := E.valVal[ntop]:=Val[top-1]FdigitF.val := digit.lex_val9/7/202438《编译原理与技术》讲义 ¡如何在自底向上分析中计算继承属性?- 属性栈上仅能存放综合属性- 能否将继承属性的引用转换成综合属性?¡分析栈中符号的继承属性- 属性copy规则如果,AXY,有语义规则Y.i := X.s,翻译方案可写为: A  X { Y.i := X.s } Y 自底向上计算继承属性9/7/202439《编译原理与技术》讲义 自底向上计算继承属性- 由属性copy规则可知,Y的继承属性Y.i和X.s在属性栈上同一位置。

      这样对属性Y.i的引用可以转化为对X.s的引用若计算若计算Y的综合属性的综合属性Y.s时需要引用时需要引用Y.i,则此时,则此时Y.i(即(即X.s)就紧邻在句柄下面;)就紧邻在句柄下面;如果如果Y的句柄形成前,的句柄形成前,它的某个右部符号它的某个右部符号需使用需使用Y.i,这时,,这时,也可以直接使用也可以直接使用Y.iHow to use?))bottom………………XX.s((Y.i))……分析栈属性栈Valtop句柄(归约为Y)top-句柄长-句柄长9/7/202440《编译原理与技术》讲义 e.g.11 C声明的翻译方案 DT { L.in := T.type } L Tint { T.type := integer } Treal { T.type := real } L { L1.in := L.in } L1 , id {addtype(id.entry, L.in) } Lid { addtype(id.entry, L.in) }对于输入串:int p,q,r 分析过程如下:9/7/202441《编译原理与技术》讲义 输入串 分析栈 产生式 int p,q,r p,q,r intp,q,r T Tint ,q,r Tp ,q,r TL Lid q,r TL, ,r TL,q ,r TL LL , id r TL, TL,r TL LL , id D DTL注意:每次归约成L时,T与L的位置关系--T就在句柄的下面!9/7/202442《编译原理与技术》讲义 e.g.11 C声明的“代码段”产生式 代码段(只含综合属性)DT L Tintval[ntop]:=integer Trealval[ntop]:=real L L1 , id addtype(val[top],val[top-3])Lid addtype(val[top],val[top-1])L的继承属性L.in9/7/202443《编译原理与技术》讲义 ¡问题1:继承属性的位置在构造编译器时不可预知(或不固定),如e.g.12 产生式语义规则S  a A C C.i := A.sS  b A B CC.i := A.sC  cC.s := g(C.i)…用C  c归约时,C.i的值可能在val[top-1]或者在val[top-2]的位置上。

      解决办法是考虑将其统一引入标记非终结符 M和产生式M  模拟继承属性的计算bottomccABaAb……分析栈1分析栈2top9/7/202444《编译原理与技术》讲义 产生式语义规则S  a A CC.i := A.sS  b A B M CC.i := M.sM.i := A.sC  cC.s := g(C.i)M  M.s := M.i …引入M后,C.i 可从句柄c的下面(val[top-1])取得!属性传递: A.s  M.i  M.s  C.i  C.se.g.12 引入标记非终结符bottomAMaB…A…b……分析栈1分析栈2topcc9/7/202445《编译原理与技术》讲义 产生式代码段S  a A CS  b A B M CC  c val[ntop]:= g(val[top-1])M  val[ntop] := val[top-1]…可否将M放在S a A C产生式中?M.i9/7/202446《编译原理与技术》讲义 模拟继承属性的计算¡问题2:语义规则不是简单的属性复写拷贝。

      e.g.13 : 将例12中的S  a A C语义规则换为:产生式语义规则 S  a A CC.i := f( A.s )虽然在例12中引入了M使得“A.s”可在val[top-1]处找到,但在S的两个产生式中C.i的取值方式不同,导致C.s的计算嘛…这次可以考虑引入标记非终结符N和N9/7/202447《编译原理与技术》讲义 e.g.13 引入标记非终结符N 产生式 语义规则 S  a A N C C.i := N.s N.i := A.s NN.s := f(N.i)(其他产生式和语义规则不变)(代码段略)9/7/202448《编译原理与技术》讲义 产生式语义规则SB B.ps := 10S.ht := B.htBB1B2B1.ps := B.psB2.ps := B.ps B.ht := max(B1.ht,B2.ht)BB1 sub B2 B1.ps := B.psB2.ps := shrink(B.ps) B.ht := disp(B1.ht,B2.ht)B text B.ht := text.h × B.pse.g.14 文字排版的语法制导定义9/7/202449《编译原理与技术》讲义 S : S.ht,综合属性;待排公式的整体高度B : B.ps,继承属性; 公式(文本)中字体“点”的大小 B.ht,综合属性;公式排版高度text :text.h,文本高度max :求两个排版公式的最大高度shrink(B) :将点大小缩小为B的30%disp(B1.ht,B2.ht):向下调整B2的位置文字排版中的符号属性E1Val9/7/202450《编译原理与技术》讲义 文字排版的翻译方案(0)S { B.ps := 10 } B { S.ht := B.ht }B { B1.ps := B.ps }B1 { B2.ps := B.ps }B2 { B.ht := max(B1.ht,B2.ht) }B { B1.ps := B.ps } B1 sub { B2.ps := shrink(B.ps) }B2 { B.ht := disp(B1.ht,B2.ht) }B text { B.ht := text.h × B.ps }9/7/202451《编译原理与技术》讲义 文字排版中引入标记符号为了自底向上计算:B text { B.ht := text.h × B.ps }必须确定继承属性B.ps的(“属性栈”)位置。

      为此引入标记非终结符L、M和N及其属性,包括相应的空产生式和有关属性规则这样B.ps即可在紧靠“句柄”text下方的位置上找到L的综合属性置为B.ps的初值)SL BBB1M B2BB1 sub N B2texttext.hLL.s=10分析栈属性栈topbottom9/7/202452《编译原理与技术》讲义 S L { B.ps := L.s } L { L.s := 10 } B { S.ht := B.ht }B { B1.ps := B.ps } M { M.s := M.i } B1 { M.i := B.ps } M { B2.ps := M.s } B2 { B.ht := max(B1.ht,B2.ht) }B { B1.ps := B.ps } B1 sub { N.i := B.ps } N { N.s :=shrink(N.i) } N{ B2.ps := N.s } B2 { B.ht := disp(B1.ht,B2.ht) }B text { B.ht := text.h × B.ps }文字排版的翻译方案(1)9/7/202453《编译原理与技术》讲义 产生式代码段S L B val[ntop] := val[top] BB1 M B2 val[ntop] := max(val[top-2],val[top])BB1 sub N B2 val[ntop] := disp(val[top-3],val[top])B text val[ntop] := val[top]×val[top-1]L val[ntop] := 10M val[ntop] := val[top-1]N val[ntop] := shrink( val[top-2] )9/7/202454《编译原理与技术》讲义 (L-属性定义)自顶向下翻译¡删除翻译方案中的左递归A  A1Y { A.a := g(A1.a, Y.y) }A  X { A.a := f( X.x) } 消除左递归:A  X { R.i := f( X.x) }//传递“左”运算量 R { A.a := R.s }R  Y { R1.i := g(R.i, Y.y) } R1 { R.s := R1.s }R   { R.s := R.i }//返回结果9/7/202455《编译原理与技术》讲义 输入串XY1Y2的翻译XA.a := f( X.x)A.a := g(f( X.x), y1.y)y1A.a := g(g(f( X.x), y1.y), y2.y)y2A.aXR.i := f(X.x)Y1R.i := g(f(X.x),Y1.y)Y2R.i := g(g(f(X.x),Y1.y), Y2.y)R.sR.sR.s9/7/202456《编译原理与技术》讲义 e.g.15 删除翻译方案中左递归EE1 + T { E.nptr := mknode(‘+’,E1.nptr, T.nptr)}EE1 - T { E.nptr := mknode(‘-’,E1.nptr, T.nptr)}ET { E.nptr := T.nptr }T( E ) { T.nptr := E.nptr }Tnum { T.nptr := mkleaf(‘NUM’,num.val) }Tid { T.nptr := mkleaf(‘ID’,id.entry) }9/7/202457《编译原理与技术》讲义 删除左递归后:引入非终结符RE T { R.i := T.nptr } R { E.nptr := R.s }R + T { R1.i := mknode(‘+’, R.i, T.nptr) } //”建树“ R1 { R.s := R1.s }R - T { R1.i := mknode(‘-’, R.i, T.nptr) } R1 { R.s := R1.s }R  { R.s := R.i } //返回最终语法树(其余略)9/7/202458《编译原理与技术》讲义 (递归下降)预测翻译器的设计¡为每个非终结符A A构造用于分析和属性计算的函数(注意,在递归下降的语法分析中构造的仅是过程),这样的函数构成如下:- 参数:符号A的继承属性- 返回值:符号A的综合属性(记录)- 局部变量:A的产生式中每个符号的属性均有对应的局部量(A的继承属性除外)- 函数体形式为:(类似递归分析过程)-根据输入符号决定产生式的选择;- 对每个可能选择的产生式从左自右分析并计算属性(执行语义动作)9/7/202459《编译原理与技术》讲义 - 对每个可能选择的产生式从左自右分析并计算属性(执行语义动作):(1)终结符X,将X.x保存在相应的局部量中(如果有的话),调用match(X); (2)非终结符B,产生赋值 c := B(b1,b2,…bn),c和bi分别是B的综合属性和继承属性对应的局部变量; (3)语义动作,将代码直接拷贝到函数体中,而其中属性出现改为局部量的引用;(4)函数结尾:return A的综合属性。

      9/7/202460《编译原理与技术》讲义 e.g.16 递归翻译函数R + T { R1.i := mknode(‘+’, R.i, T.nptr) } R1 { R.s := R1.s }R - T { R1.i := mknode(‘-’, R.i, T.nptr) } R1 { R.s := R1.s }R  { R.s := R.i } 9/7/202461《编译原理与技术》讲义 node_ptr R ( node_ptr i ){node_ptr nptr, i1, s1, s ; //符号属性对应的局部量if (lookhead == ‘+’) { // R  + T Rmatch(‘+’); nptr = T();i1 = mknode( ‘+’, i, nptr ); //语义动作s1 = R ( i1 );s = s1 ; // 语义动作}else if … // R  - T Relse s = i ; // R   语义动作 return s;} 非终结符R的递归翻译函数9/7/202462《编译原理与技术》讲义 。

      点击阅读更多内容
      相关文档
      医学:08 肺门和肺段断层解剖及CT.ppt 医学:02 头部连续横断层解剖及CT、MRI.ppt 药理学(第9版)配套-第四十章 β-内酰胺类抗生素 本章小结.pptx 药理学(第9版)配套-第十一章 肾上腺素受体阻断药 本章小结.pptx 药理学(第9版)配套-第三十四章 性激素类药及避孕药.pptx 药理学(第9版)配套-第八章 胆碱受体阻断药(Ⅰ)——M胆碱受体阻断药 本章小结.pptx 学海导航2026届高考一轮总复习语文专题训练卷(九).pptx 学海导航2026届高考一轮总复习英语选必二U1默写手册.pptx 外科学(第9版)配套-第一章 绪论.pptx 外科学(第9版)配套-第五十三章 泌尿、男生殖系统肿瘤 案例分析-肾母细胞瘤.pptx 外科学(第9版)配套-第四十章 胆道疾病 案例分析-急性梗阻性化脓性胆管炎.pptx 口腔科学(第9版)配套-03=11 颞下颌关节常见病.ppt 核医学(第9版)配套-第一篇 基础篇 第二章 核医学仪器(二).pptx 核医学(第9版)配套-第二篇 临床篇 第二十三章 其他放射性核素治疗.pptx 医学:2心电图测量.ppt 妇产科学(第9版)配套-第十二章正常分娩.ppt 药理学(第9版)配套-第十章 肾上腺素受体激动药.pptx 药理学(第9版)配套-第三十一章 作用于呼吸系统的药物 本章小结.pptx 药理学(第9版)配套-第六章 胆碱受体激动药 本章小结:毛果芸香碱.pptx 药理学(第9版)配套-第二十八章 抗心绞痛药.pptx
      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.