               _  (instance? IASTPreprocessorFunctionStyleMacroDefinition (.getMacroDefinition exp))
               replaced-str  (macro-replace-arg-str  exp)
               replaced-tree (macro-replace-arg-tree exp)
-              ;replaced-str  (pap write-ast (macro-replace-arg-str  exp))
-              ;replaced-tree (pap write-ast (macro-replace-arg-tree exp))
+              ;replaced-str  (pap safe-write-ast (macro-replace-arg-str  exp))
+              ;replaced-tree (pap safe-write-ast (macro-replace-arg-tree exp))
               _  (not (atom-finder.tree-diff/tree=by (juxt class expr-operator)
                        replaced-str
                        replaced-tree))

(in-ns 'atom-finder.classifier)
(import '(org.eclipse.cdt.core.dom.ast IASTNode IASTName IASTIdExpression IASTBinaryExpression IASTUnaryExpression IASTExpressionStatement IASTPreprocessorFunctionStyleMacroDefinition IASTDoStatement IASTLiteralExpression IASTPreprocessorMacroExpansion cpp.ICPPASTTemplateId IASTCastExpression IASTFunctionCallExpression IASTEqualsInitializer IASTIfStatement IASTWhileStatement IASTForStatement IASTDoStatement IASTArraySubscriptExpression)
        '(org.eclipse.cdt.internal.core.parser.scanner ASTFunctionStyleMacroDefinition ASTMacroDefinition)
        '(org.eclipse.cdt.internal.core.dom.parser.cpp CPPASTUnaryExpression)
        )

;; ExpressionWriter adds superfluous parens to cast statements.

                     #(call-method %1 (str 'set method) %2)
                     node replacements))

(s/defn -maybe-set-operands!
  [node replacements & methods]
  (->> methods
       (map #(-maybe-set-operand! %1 node replacements))
       doall
       (some identity)))

(s/defn -replace-identifier!
  "If this node is capable of causing syntax ambiguities,
   try replacing parts of it to observe the ambiguity"
  [node :- IASTNode replacements :- {s/Str IASTNode}]
  (condp instance? node
    IASTFunctionCallExpression   (-maybe-set-args!      node replacements)
    IASTExpressionList           (-maybe-set-expr-list! node replacements)
    IASTIfStatement              (-maybe-set-operands!  node replacements "ConditionExpression")
    IASTForStatement             (-maybe-set-operands!  node replacements "ConditionExpression")
    IASTWhileStatement           (-maybe-set-operands!  node replacements "Condition")
    IASTDoStatement              (-maybe-set-operands!  node replacements "Condition")
    IASTEqualsInitializer        (-maybe-set-operands!  node replacements "InitializerClause")
    IASTCastExpression           (-maybe-set-operands!  node replacements "Operand")
    IASTUnaryExpression          (-maybe-set-operands!  node replacements "Operand")
    IASTBinaryExpression         (-maybe-set-operands!  node replacements "Operand1" "Operand2")
    IASTArraySubscriptExpression (-maybe-set-operands!  node replacements "Argument" "ArrayExpression")
    IASTFieldReference           (-maybe-set-operands!  node replacements "FieldOwner" "FieldName")
    IASTConditionalExpression    (-maybe-set-operands!  node replacements "LogicalConditionExpression"
                                                         "PositiveResultExpression" "NegativeResultExpression")

      nil))

(s/defn parse-macro
