refactored to use precedence LUT