310 likes | 436 Views
Parallel Parsing with Attributes and Not: Technical Discussion. W.Pasman, 4.6.7. Overview. Strategy specification Tracking the student's actions: Chart Parser Attribute Parser. What is a Strategy. • Describes all possible paths to the solution, as sequences of rewrite rules
E N D
Parallel Parsing with Attributes and Not:Technical Discussion W.Pasman, 4.6.7
Overview Strategy specification Tracking the student's actions: Chart Parser Attribute Parser
What is a Strategy • Describes all possible paths to the solution, as sequences of rewrite rules • Some of the sequences may not be applicable to the term at hand, and therefore are not a path to the solution after all (discussed in detail soon) • Basic method to generate all these paths: repeat(rule), rule1 or rule 2, rule1 followedby rule2 or, as I do, by a context free grammar: S::=N N::=rule1 rule2 N::=rule3
Examples of Extra Primitives Parallel operator to handle multiple substitutions term:{ R=x+y+z,x=1, y=2, z=3 } rules: subX, subY, subZ strategy: S::= repeatexh(subX//subY//subZ//simplify) Not operator: for instance to implement repeatexh: repeatexh($x)::=$x repeatexh($x) repeatexh($x)::=not($x)
Attributes to enable parameterized rules. mul($matrix,$row,$k)$matrix with $row multiplied with $k Typically, the user is asked in these cases to enter the parameters
Computation and Fail in Rules Attributes empower code snippets in rules In Rewrite Rules multrow[$row,$k,$pos]: M_matrix Code[If[$k===0,$Failure, ReplacePart[M,$k*Extract[M,$row],$row]]] In Grammar Rules N::=Code[$y=(7,2)] multrow[3,4,$y] M[$y,$z]::=Code[If[$y===0,$Failure]] ...
Strategy Specification • is specific for one problem term (it might be more generic) • generates rewrite sequences that may apply to the problem term: mul[s[0],plus[0,s[0]]] rules zeroadd: plus[0,x_]x onemul: mul[s[0],x_]x strategy S::=N S | N::=zeroadd | onemul RewriteRule["zeroadd", plus[0, x_] x] RewriteRule["onemul", mul[s[0], x_] x] GrammarRule["S", {"N","S"}] GrammarRule["S", {}] GrammarRule["N", {"zeroadd"}] GrammarRule["S", {"onemul"}]
• generates rewrite sequences that may apply to the problem rules zeroadd: plus[0,x_]x onemul: mul[s[0],x_]x strategy S::=N S | N::=zeroadd | onemul 0+x=x 1*x=x This generates the rewrite sequence zeroadd onemul and that is applicable on mul[s[0],plus[0,s[0]]]: mul[s[0],plus[0,s[0]]] mul[s[0],s[0]] s[0] *(1, +(0,1) ) = *(1,1) = 1 1*(0+1) = 1*1 = 1
But this rewrite sequence zeroadd onemul is not applicable to mul[s[0],0] If a generated rewrite sequence is applicable then the solution (the result of applying the rewrite sequence to the term) is a good one.
Student Tracking: Chart Parser • Suitable for ambiguous grammars • eliminates backtracking • prevents combinatorial explosion • Breath first search • Incremental parsing: next student step takes same time • Explicit representation of all steps done in the parser • Parser at any time compactly represents succesful parses so far
Example Grammar: S::=a b. input string: a b
scanner: if item a•Nb in set and there is shift possibility for N to set X then add item aN•b to set X
add another shift do another scanner step
completer: recognise nonterminal if item I:N::=...• in set Xe and item J:N::=•... in set Xs and J is linked to I then make shiftpossibility <N,Xs,Xe>
Applicable(S) input: parser state and start terminal return: the shortest strategy that is applicable or failure if no strategy is applicable Always terminates as parsing always terminates
Not(S) Not(S) means: we can NOT parse an S More specifically, Every rewrite sequence generated by S is NOT applicable. Not(S) = not(Applicable(S))
P//Q Scan P and Q in parallel Deep permutation: P//Q means that the rewrite steps generated by P and Q can be permutated Example: P::=abc, Q::= fgh Then one permutation is afgbch
P//Q Parser Try ALL permutations of the input symbols over P and Q Expensive: potentially 2n costs in order of input length n But usually not all permutations are applicable.
Example G={S::=P//Q, P::=aa, Q::=b}, input aba Note distribution numbers. In implementation we keep all within set 0.
Position of Rewrite Rules are extended for explicit control of position of application becomes @(...) (...) is path from root to term. e.g. (1,2) is 2nd child of 1st child of root. Examples plus0atroot: plus[0,x_]@()x
Attributes for Rules $x etc are attributes: a variable similar to x_ This allows us to rules like swap[$i,$j]: M_matrix@$posM with row $i and row $j swapped plus0at[$pos]: plus[0,x_]@$posx and a grammar rule like N[$x]::=P[$x,3]
Inheriting Attributes Inheriting: passing values downward. rewriterule: swap[$i,$j]:.... item: S::=•swap[3,4] Result: rule applied as $i=3, $j=4 grammarrule: M[$y,$z]::=... item: S::=•M[3,4] Result: new item M[3,4]::=•... with local vars {$y=3,$z=4} Note, vars are local, consider M[$y,$z]::=Code[$z=5] where $z is locally manipulated in M without effect on higher levels.
Synthesizing Attributes Synthesizing: propagating local results upwards Only uninstantiated variables can be synthesized S::=M[$x] M[$x]::=Code[$x=3] or the special case, where $pos is instantiated from where the student actually applies the rule: S::=ruleplus0[$pos] ...use $pos... ruleplus0[$pos]: plus[0,x_]@$posx
Parsing Not with Attri's Not[S[$x]] still means: we can NOT parse an S[$x] (for any value of $x) • $x MUST be set at the time a rewrite rule is encountered that uses $x. • Exception: $pos may be unset in @$pos in this case, ALL possible $pos are tried separately Tricky cases: for example S::=N[$x,3] (result will be $x=3) N[$x,$x]::=...
Shared Attri + Parallel Operator Example with Problem with shared attri handling. term=times[s[0],plus[0,s[0]]] rulemult1[$pos]: times[s[0],x_]@$posx ruleplus0[$pos]: plus[0,x_]@$posx S::=M[$posofplus]//P[$posofplus] M[$posofplus]::=Code[$posofplus=(2)] rulemult1[()] $posofplus=() P[$posofplus]::=Code[$posofplus=(2)] ruleplus0[$posofplus] Idea: we want P and Q to share the var $posofplus, such that it KEEPS pointing to the plus[0,s[0]]
Parallel Issues Now take careful look S::=M[$posofplus]//P[$posofplus] M[$posofplus]::=Code[$posofplus=(2)] rulemult1[()] $posofplus=() P[$posofplus]::=Code[$posofplus=(2)] ruleplus0[$posofplus] We actually may encounter this evaluation order: Code[$posofplus=(2)] rulemult1[()] $posofplus=() Code[$posofplus=(2)] ruleplus0[$posofplus] Similar problems may occur if rulemult1[()] is executed but the subsequent $posofplus=() is delayed until after evaluation of P.
Conclusions Attributes mostly solved and implemented. One issue remains: shared attributes in parallel parsers Mechanism to automatically update shared termpointers? Extracting path (example solution) from parser seems easy Questions & Discussion ?