Presentation is loading. Please wait.

Presentation is loading. Please wait.

SDTs used to implement SDDs A non-cyclic SDD (having definitions of attributes) can always be implemented by a SDT (having actions that assign values to.

Similar presentations


Presentation on theme: "SDTs used to implement SDDs A non-cyclic SDD (having definitions of attributes) can always be implemented by a SDT (having actions that assign values to."— Presentation transcript:

1 SDTs used to implement SDDs A non-cyclic SDD (having definitions of attributes) can always be implemented by a SDT (having actions that assign values to attributes) by arranging that 1.the parser first builds a tree, ignoring the actions of the SDT 2.the tree is then walked, executing the actions of the SDT Two interesting cases where SDDs may be implemented by SDTs whose actions can be executed during parsing, in 1 pass, without a parse tree being constructed  S-attributed SDD and parsing is LR (deterministic bottom-up) –this is the simplest case –all actions can be grouped at the end of a production –result is a “postfix SDT”  L-attributed SDD and parsing can be LL (deterministic top-down) –if a grammar can be parsed LL, it can also be parsed LR http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction1

2 Postfix SDTs If grammar can be parsed deterministically bottom-up, & all attributes “synthetic” Then all actions of a production can be executed along with the parser’s reduce step They can all be grouped at the end of the production, forming a postfix to it http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction2 L ::= E \n E ::= E 1 + T E ::= T T ::= T 1 * F T ::= F F ::= ( E ) F ::= digit { print(E.val) } { E.val=E 1.val+T.val } { E.val=T.val } { T.val=T 1.val*F.val } { T.val = F.val } { F.val=E.val } { F.val=digit.lexval } e.g. Postfix SDT for very-simple desk calculator all attributes are synthetic, all actions occur at end of production and from the parser’s point of view they are part of the production, the grammar is LR(1).

3 Implemention issues with postfix SDTs Attributes can be stored in records/structs/dictionaries on the symbol stack, alongside LR parser states on the state stack. Furthermore the grammar symbol itself need not be kept on the symbol stack If some attribute values have unbounded size – e.g. for strings or code lists – it is best to store fixed-size pointers in the stack structures, and store the actual values elsewhere When a parser reduce occur – say for T ::= T 1 * F – the stack records containing needed values (T1’s for T1.val, F’s for F.val) will be at known offsets (-1, 0) relative to the top of stack. The result can be left on top of the stack after reduce step. With single productions, e.g. T ::= F, no change to the topmost stack entry is necessary since the item at the top must stay at the top. (but top state will usually change) http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction3

4 Parser stack manipulations made explicit http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction4 L ::= E \n E ::= E 1 + T E ::= T T ::= T 1 * F T ::= F F ::= ( E ) F ::= digit { print (stack[top-1].val; top=top-1; } { stack[top-2].val=stack[top-2].val+stack[top].val; top=top-2; } { } stack[top-2].val=stack[top-2].val*stack[top].val; top=top-2; } { } { stack[top-2].val=stack[top-1].val; top=top-2; } { } // if we may assume that val and lexval attributes // occupy the same locations in a struct T: T.val=3 * E: E.val=6 … … … … … … … top effect is to place 9 into the existing E element’s.val and make top point to it

5 SDTs with actions inside productions - 1 Where SDD is not S-attributed (it may be L-attributed or worse) then no postfix SDT can be constructed: actions inside productions will be necessary productions have the form X ::=  {a}  where  is not  If such a SDT cannot be handled during parsing – because it is worse than L- attributed while still being acyclic – then  parse, ignoring actions, and producing an explicit parse tree  then, knowing what productions have been used to parse, add extra child nodes for the particular actions within those productions  perform preorder traversal of tree, executing the actions http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction5 X  X  {a}

6 SDTs with actions inside productions - 2 If such a SDT can be handled during parsing, then  if parsing bottom-up, treat the action like a non-terminal: –invent a unique marker non-terminal for each action –such a non-terminal has one empty production –perform the action when that non-terminal is on the top of the stack  if parsing top-down –perform the action just before processing the next grammar symbol checking the next terminal, if  begins with a terminal expanding the next non-terminal, if  begins with a non-terminal http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction6 X ::=  M 39  M 39 ::= 

7 Eliminating left recursion from SDTs Grammars, and hence SDTs, cannot be used for top-down parsing if left recursive Treat actions like terminals, since order of terminals is preserved by left recursion elimination  (although if any production begins with an action, the grammar with SDT will not be possible to parse deterministically either top-down or even bottom-up, and it will then be necessary to walk a tree) General idea of left recursion elimination (without actions) is to replace left recursion by right recursion involving a new non-terminal capable of generating  http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction7 A ::= A  |  A ::= b R R ::=  R |  With actions {a} and {b} in SDD, similar transformation requires care A ::= A  {a} |  {b} A ::= b {?1} R {?2} R ::=  {?3} R {?4} |  {?5}

8 … the right-recursive version should achieve same result http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction8 Example left-recursive original SDT with only one S-attribute ‘q’ A ::= A 1 b { A.q=f(A 1.q, b.q);} | c { A.q=g(c);} For sample input ‘cbb’, flow of information is always upwards A.q=f(g(c),b.q) A.q=f(f(g(c),b.q),b.q) A A A b c b A.q=g(c) After eliminating left recursion, the shape of the parse tree will be radically different, but the end result calculated for topmost A.q should be the same

9 … needing inherited attributes http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction9 A.q=f(g(c),b.q) A.q=f(f(g(c),b.q),b.q) A A A b c b A.q=g(c) A R R R b b c  Only at this point can it be known that the correct result is f(f(g(c),b.q),b.q) A.q=R.s R.i=g(c) R.s=R 1.s R 1.i=f(g(c),b.q) R.s=R 1.s R 1.i=f(f(g(c),b.q),b.q) R.s=R.i with left recursive grammar

10 … and appropriate evaluation order Getting the actions done in the right order and with the right information available requires use of inherited attributes  values of inherited attributes must be calculated immediately before the right- recursive use of the non-terminal R Getting the result(s) back to the top node involves a new synthesized attribute(s)  values of synthesized attributes may be calculated right at the ends of productions, just as with postfix SDTs http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction10 A ::= c {R.i=g(c)} R {A.q=R.s} R ::= b {R 1.i=f(R.i, b.q)} R {R.s=R 1.s} R ::=  {R.s=R.i}


Download ppt "SDTs used to implement SDDs A non-cyclic SDD (having definitions of attributes) can always be implemented by a SDT (having actions that assign values to."

Similar presentations


Ads by Google