/**
* This module defines a generic strategy for placing parentheses in
* abstract syntax trees based on priority and associativity declarations.
*
* Reference
*
* Eelco Visser. Syntax Definition for Language Prototyping. PhD Thesis,
* University of Amsterdam, 1997.
*
* Typical usage: (from module Tiger-Ensugar in the tiger/tiger-front
* package)
*
* TigerParenthesize =
* !Seq([<id>])
*
* tiger-parenthesize =
* parenthesize(TigerParenthesize, tiger-priorities)
*
* tiger-priorities =
* ![(None, ["Uminus","FieldVar","Subscript"]),
* (Some("left"), ["Power"]),
* (Some("left"), ["Times","Divide"]),
* (Some("left"), ["Plus","Minus"]),
* (Some("non-assoc"), ["CPlus","CMinus","Eq","Neq","Gt","Lt","Geq","Leq"]),
* (Some("left"), ["And"]),
* (Some("left"), ["Or"]),
* (None, ["Array"]),
* (None, ["Assign"]),
* (Some("right"), ["If","While","For"])]
*
*/
module strategy/general/parenthesize
imports collection/list/common
strategies
parenthesize(paren, prios) =
where(prios; init-parenthesation-rules)
; bottomup(try(Disambiguate(paren)))
// assumes parenthesation rules are already generated
parenthesize(paren) =
bottomup(try(Disambiguate(paren)))
Disambiguate(paren) :
e@op#([l | args]) -> (op#([l' | <conc>(mid', [r'])]))
where <split-init-last> args => (mid, r)
; <try(test(<RightAssoc> (e,<id>)); paren)> l => l'
; <map(test(<GreaterThan>(e,<id>)); paren)> mid => mid'
; <try(test(<LeftAssoc> (e,<id>)); paren)> r => r'
Disambiguate(paren) :
e@op#([l]) -> (op#([l']))
where <test(<GreaterThan>(e,<id>)); paren> l => l'
/**
* Generation of the parenthesation rules.
*/
strategies
init-parenthesation-rules =
!([], <id>)
; repeat(gen-left + gen-right + gen-non-assoc + gen-none)
gen-left :
(greater, [(Some("left"), ops) | rest]) -> (<conc>(ops, greater), rest)
where <for-each-pair(GenLeftAssoc)> (ops, ops)
; <for-each-pair(GenGreaterThan; GenLeftAssoc; GenRightAssoc)> (greater, ops)
gen-right :
(greater, [(Some("right"), ops) | rest]) -> (<conc>(ops, greater), rest)
where <for-each-pair(GenRightAssoc)> (ops, ops)
; <for-each-pair(GenGreaterThan; GenLeftAssoc; GenRightAssoc)> (greater, ops)
gen-non-assoc :
(greater, [(Some("non-assoc"), ops) | rest]) -> (<conc>(ops, greater), rest)
where <for-each-pair(GenLeftAssoc; GenRightAssoc)> (ops, ops)
; <for-each-pair(GenGreaterThan; GenLeftAssoc; GenRightAssoc)> (greater, ops)
gen-none :
(greater, [(None(), ops) | rest]) -> (<conc>(ops, greater), rest)
where <for-each-pair(GenGreaterThan; GenLeftAssoc; GenRightAssoc)> (greater, ops)
GenLeftAssoc =
?(op1, op2)
; rules(
LeftAssoc : (op1#(_), op2#(_)) -> ()
)
GenRightAssoc =
?(op1, op2)
; rules(
RightAssoc : (op1#(_), op2#(_)) -> ()
)
GenGreaterThan =
?(op1, op2)
; rules(
GreaterThan : (op1#(_), op2#(_)) -> ()
)