Attribute Grammars intermediate syntax semantics representation - - PowerPoint PPT Presentation
Attribute Grammars intermediate syntax semantics representation - - PowerPoint PPT Presentation
Attribute Grammars intermediate syntax semantics representation Language Implementation 2 expr ::= term | term + term | term - term term ::= factor | factor * factor | factor / factor factor ::= n | ( expr ) intermediate
2
Language Implementation
intermediate representation semantics syntax
3
expr ::= term | term + term | term - term term ::= factor | factor * factor | factor / factor factor ::= n | ( expr ) eval(term1 + term2) = eval( term1 ) + eval( term2 ) eval(term1 - term2) = eval( term1 ) - eval( term2 ) eval(factor1 * factor2) = eval(factor1) * eval(factor2) eval(factor1 / factor2) = eval(factor1) / eval(factor2) eval(n) = n eval(( expr )) = eval(expr) div0(term1 + term2) = div0( term1 ) ∨ div0( term2 ) div0(term1 - term2) = div0( term1 ) ∨ div0( term2 ) div0(factor1 * factor2) = div0(factor1) ∨ div0(factor2) div0(factor1 / factor2) = div0(factor1) ∨ div0(factor2) div0(factor1 / 0) = t div0(n) = f div0(( expr )) = div0(expr)
intermediate representation (AST) semantics
4
N ::= L | L.L L ::= B | LB B ::= 0 | 1
Class Exercise
Example from “Semantics of Context Free Languages” by Donald E. Knuth in Theory of Computing Systems, 2(2), 1968, pages 127–145.
5
Grammar Production Attributes Production Rule value: v(●) length: |●| N → L1.L2 v(N) = v(L1)+v(L2)/2|L2| N → L v(N) = v(L) L → L1B v(L) = 2*v(L1)+v(B) |L| = |L1|+|B| L → B v(L) = v(B) |L| = |B| B → 0 v(B) = 0 |B| = 1 B → 1 v(B) = 1 |B| = 1
Attribute Grammar
6
Grammar Production Attributes Production Rule value: v(●) length: |●| N → L1.L2 v(N) = v(L1)+v(L2) N → L v(N) = v(L) L → L1B v(L) = v(L1)+v(B) |L| = |L1|+|B| L → B v(L) = v(B) |L| = |B| B → 0 v(B) = ??? |B| = 1 B → 1 v(B) = ??? |B| = 1
Class Exercise
7
Inherited Attributes Grammar Production Synthesized Attributes ttributes scale: s(●) Production Rule value: v(●) length: |●| s(L1) = 0 s(L2) = -|L2| N → L1.L2 v(N) = v(L1)+v(L2) s(L) = 0 N → L v(N) = v(L) s(L1) = s(L)+1 s(B) = s(L) L → L1B v(L) = v(L1)+v(B) |L| = |L1|+|B| s(B) = s(L) L → B v(L) = v(B) |L| = |B| B → 0 v(B) = 0 |B| = 1 B → 1 v(B) = 2s(B) |B| = 1
Inherited vs. Synthesized
8 BinaryNumber fields inh syn value() : double BitList fields inh scale() : int syn length() : double IntegralNumber fields integral : BitList inh integral.scale() = 0 syn value = integral.value() Bit fields inh syn RationalNumber fields integral : BitList fraction : BitList inh integral.scale() = 0 fraction.scale() = -fraction.length() syn value = integral.value() + fraction.value() PluralBitList fields bitList : BitList bit : Bit inh bitList.scale() = scale() + 1 syn value = bitList.value() + bit.value() length = bitList.length() + bit.length() Zero fields inh syn value = 0 length = 1 One fields inh syn value = 2^scale() length = 1
9
JastAdd: A DSL for Attribute Grammars
abstract BinaryNumber; IntegralNumber : BinaryNumber ::= Integral:BitList; RationalNumber : BinaryNumber ::= Integral:BitList Fraction:BitList; abstract BitList:BinaryNumber; PluralBitList : BitList ::= BitList Bit; abstract Bit : BitList; Zero:Bit ::= ; One:Bit ::= ;
example based on jastadd.org/old/examples/knuths-binary-numbers.php
Grammar / AST
abstract non-terminal class declaration non-terminal class declaration non-terminal class inheritance grammar production rule name type non-terminal field declaration
aspect BinaryNumberValue { syn double BinaryNumber.value(); eq IntegralNumber.value() = getIntegral().value(); eq RationalNumber.value() = getIntegral().value() + getFraction().value(); eq PluralBitList.value() = getBit().value() + getBitList().value(); eq Zero.value() = 0; eq One.value() = java.lang.Math.pow(2.0, scale()); syn int BitList.length(); eq PluralBitList.length() = getBitList().length() + getBit().length(); eq Zero.length() = 1; eq One.length() = 1; inh int BitList.scale(); eq IntegralNumber.getIntegral().scale() = 0; eq RationalNumber.getIntegral().scale() = 0; eq RationalNumber.getFraction().scale() = -getFraction().length(); eq PluralBitList.getBitList().scale() = scale() + 1; }
10
JastAdd: A DSL for Attribute Grammars
Attributes
example based on jastadd.org/old/examples/knuths-binary-numbers.php
synthesized attribute declaration synthesized attribute definition
aspect BinaryNumberValue { syn double BinaryNumber.value(); eq IntegralNumber.value() = getIntegral().value(); eq RationalNumber.value() = getIntegral().value() + getFraction().value(); eq PluralBitList.value() = getBit().value() + getBitList().value(); eq Zero.value() = 0; eq One.value() = java.lang.Math.pow(2.0, scale()); syn int BitList.length(); eq PluralBitList.length() = getBitList().length() + getBit().length(); eq Zero.length() = 1; eq One.length() = 1; inh int BitList.scale(); eq IntegralNumber.getIntegral().scale() = 0; eq RationalNumber.getIntegral().scale() = 0; eq RationalNumber.getFraction().scale() = -getFraction().length(); eq PluralBitList.getBitList().scale() = scale() + 1; }
10
JastAdd: A DSL for Attribute Grammars
Attributes
example based on jastadd.org/old/examples/knuths-binary-numbers.php
synthesized attribute declaration synthesized attribute definition
aspect BinaryNumberValue { syn double BinaryNumber.value(); eq IntegralNumber.value() = getIntegral().value(); eq RationalNumber.value() = getIntegral().value() + getFraction().value(); eq PluralBitList.value() = getBit().value() + getBitList().value(); eq Zero.value() = 0; eq One.value() = java.lang.Math.pow(2.0, scale()); syn int BitList.length(); eq PluralBitList.length() = getBitList().length() + getBit().length(); eq Zero.length() = 1; eq One.length() = 1; inh int BitList.scale(); eq IntegralNumber.getIntegral().scale() = 0; eq RationalNumber.getIntegral().scale() = 0; eq RationalNumber.getFraction().scale() = -getFraction().length(); eq PluralBitList.getBitList().scale() = scale() + 1; }
10
JastAdd: A DSL for Attribute Grammars
Attributes
example based on jastadd.org/old/examples/knuths-binary-numbers.php
synthesized attribute declaration synthesized attribute definition inherited attribute declaration inherited attribute definition
11
JastAdd is a DSL for: Re-writeable Circular Reference Attribute Grammars
12
state: 0; state: 1; rule: 0 **x* -> W 0; rule: 0 x*W* -> N 1; rule: 1 x*** -> N 1;
Picobot (Ad Nauseum)
Example Program
Example based on “An Introductory Tutorial on JastAdd Attribute Grammars” by Görel Hedin in Generative and Transformational Techniques in Software Engineering III, volume 6491 of Lecture Notes in Computer Science, pages 166–200. Springer Berlin / Heidelberg, 2011.
13
Program ::= Declaration*; abstract Declaration; State : Declaration ::= <Label:String>; Rule : Declaration ::= <SourceLabel:String> Pattern MoveDirection <TargetLabel:String>; Pattern ::= North:PatternDirection East:PatternDirection West:PatternDirection South:PatternDirection; abstract PatternDirection; BlockedNorth : PatternDirection; BlockedEast : PatternDirection; BlockedWest : PatternDirection; BlockedSouth : PatternDirection; Free : PatternDirection; BlockedOrFree : PatternDirection; abstract MoveDirection; MoveNorth : MoveDirection; MoveEast : MoveDirection; MoveWest : MoveDirection; MoveSouth : MoveDirection; Stay : MoveDirection;
Picobot (Ad Nauseum)
Grammar / AST
a Program has zero or more Declarations terminal field declaration
aspect Properties { inh Program Declaration.program(); eq Program.getDeclaration(int i).program() = this; syn Set<State> Program.states() { Set<State> result = new HashSet<State>(); for (Declaration d : getDeclarationList()) if (d instanceof State) result.add((State)d); return result; } coll Set<Rule> Program.rules() [new HashSet<Rule>()] with add root Program; Rule contributes this to Program.rules() for program(); }
Some Utilities
14
aspect Properties { inh Program Declaration.program(); eq Program.getDeclaration(int i).program() = this; syn Set<State> Program.states() { Set<State> result = new HashSet<State>(); for (Declaration d : getDeclarationList()) if (d instanceof State) result.add((State)d); return result; } coll Set<Rule> Program.rules() [new HashSet<Rule>()] with add root Program; Rule contributes this to Program.rules() for program(); }
Some Utilities
14 collection attribute declaration initial value commutative add operator sub-tree scope collection attribute contribution element to add contributee contributor collection attribute
Uh-Oh?
15
Program Declaration Declaration Declaration State State Rule "0" "1" "0" Pattern MoveDirection "0" Declaration Rule "0" Pattern MoveDirection "1" Declaration Rule "1" Pattern MoveDirection "1" ... MoveWest MoveNorth MoveNorth ... ...
Label Label SourceLabel SourceLabel SourceLabel TargetLabel TargetLabel TargetLabel
state: 0; state: 1; rule: 0 **x* -> W 0; rule: 0 x*W* -> N 1; rule: 1 x*** -> N 1;
16
JastAdd is a DSL for: Re-writeable Circular Reference Attribute Grammars
aspect NameAnalysis { syn State Rule.source() = lookup(getSourceLabel()); syn State Rule.target() = lookup(getTargetLabel()); syn State Declaration.lookup(String label); eq Rule.lookup(String label) { for (State s : program().states()) { State match = s.lookup(label); if (match != null) return match; } return null; } eq State.lookup(String label) = (label.equals(getLabel())) ? this : null; }
17
Reference Attributes
are really no different from “regular” attributes
aspect NameAnalysis { syn State Rule.source() = lookup(getSourceLabel()); syn State Rule.target() = lookup(getTargetLabel()); syn State Declaration.lookup(String label); eq Rule.lookup(String label) { for (State s : program().states()) { State match = s.lookup(label); if (match != null) return match; } return null; } eq State.lookup(String label) = (label.equals(getLabel())) ? this : null; }
17
Reference Attributes
are really no different from “regular” attributes
parameterized attribute
aspect NameAnalysis { syn State Rule.source() = lookup(getSourceLabel()); syn State Rule.target() = lookup(getTargetLabel()); syn State Declaration.lookup(String label); eq Rule.lookup(String label) { for (State s : program().states()) { State match = s.lookup(label); if (match != null) return match; } return null; } eq State.lookup(String label) = (label.equals(getLabel())) ? this : null; }
17
Reference Attributes
are really no different from “regular” attributes
parameterized attribute
Class Exercise: Reachability
18
state: 0; state: 1; state: 2; state: 3; rule: 0 x*** -> N 1; rule: 1 *x** -> E 2; rule: 2 ***x -> E 3; rule: 3 x*** -> E 0;
coll Set<State> State.targets() [new HashSet<State>()] with add root Program; Rule contributes target() to State.targets() for source(); syn Set<State> State.reachable(); eq State.reachable() { ??? }
1 2 3
Uh-Oh?
19
state: 0; state: 1; state: 2; state: 3; rule: 0 x*** -> N 1; rule: 1 *x** -> E 2; rule: 2 ***x -> E 3; rule: 3 x*** -> E 0;
coll Set<State> State.targets() [new HashSet<State>()] with add root Program; Rule contributes target() to State.targets() for source(); syn Set<State> State.reachable(); eq State.reachable() { Set<State> result = new HashSet<State>(); for (State s : targets()) { result.add(s); result.addAll(s.reachable()); } return result; }
1 2 3
20
JastAdd is a DSL for: Re-writeable Circular Reference Attribute Grammars
Circular Attributes
21
state: 0; state: 1; state: 2; state: 3; rule: 0 x*** -> N 1; rule: 1 *x** -> E 2; rule: 2 ***x -> E 3; rule: 3 x*** -> E 0;
coll Set<State> State.targets() [new HashSet<State>()] with add root Program; Rule contributes target() to State.targets() for source(); syn Set<State> State.reachable() circular [new HashSet<State>()]; eq State.reachable() { Set<State> result = new HashSet<State>(); for (State s : targets()) { result.add(s); result.addAll(s.reachable()); } return result; }
1 2 3
initial value
More Fun With DSLs!
22
aspect dot { syn String Program.dot() { StringBuilder sb = new StringBuilder(); sb.append("digraph picobot {\n\n"); sb.append("\trankdir=LR\n"); for (Rule rule : rules()) sb.append("\t" + rule.dot() + "\n"); sb.append("\n}"); return sb.toString(); } syn String Rule.dot() = String.format("%s -> %s [label =\"[%s]{%s}\"]", getSourceLabel(), getTargetLabel(), getPattern().dot(), getMoveDirection().dot()); syn String Pattern.dot() = String.format("%s%s%s%s", getNorth().dot(), getEast().dot(), getWest().dot(), getSouth().dot()); syn String PatternDirection.dot(); eq BlockedNorth.dot() = "N"; eq BlockedEast.dot() = "E"; eq BlockedWest.dot() = "W"; eq BlockedSouth.dot() = "S"; eq Free.dot() = "x"; eq BlockedOrFree.dot() = "*"; syn String MoveDirection.dot(); eq MoveNorth.dot() = "N"; eq MoveEast.dot() = "E"; eq MoveWest.dot() = "W"; eq MoveSouth.dot() = "S"; eq Stay.dot() = "X"; }
It’s DSLs All The Way Down
23
To implement our DSL, we used the following DSLs:
- Flex for lexing
- Beaver for parsing
- JastAdd for intermediate representation and semantics
with sub-DSLs for ASTs and grammar
- Ant for building
- Dot for visualization