-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
infix-operator-precedence atom #10
Changes from 20 commits
372b991
1a58abd
7054119
3e6ab67
ac90964
216752e
e423b42
c96aae0
d0c9106
00be07d
6718782
1ed1cb2
85bebcc
bc33e8b
50e9f06
848fb6a
e2d55e0
5ff6b8b
30e404b
d0fc437
09a7cd8
9a210d0
de0a322
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
(in-ns 'atom-finder.classifier) | ||
(import '(org.eclipse.cdt.core.dom.ast IASTBinaryExpression IASTConditionalExpression IASTUnaryExpression) | ||
'(org.eclipse.cdt.internal.core.dom.parser.cpp CPPASTConditionalExpression CPPASTExpressionList CPPASTFieldReference)) | ||
|
||
(defmulti operator-group"Returns the name of the operator group that the node belongs to, nil not defined in this operator-group" class) | ||
(defmethod operator-group :default [node] | ||
(let [operator-group-table | ||
{CPPASTConditionalExpression :cond | ||
CPPASTExpressionList :comma | ||
CPPASTFieldReference :field_ref}] | ||
(->> node type operator-group-table))) | ||
(defmethod operator-group IASTUnaryExpression [node] | ||
(let [operator-group-table | ||
{IASTUnaryExpression/op_postFixDecr :de_incr | ||
IASTUnaryExpression/op_postFixIncr :de_incr | ||
IASTUnaryExpression/op_minus :arith_unary | ||
IASTUnaryExpression/op_plus :arith_unary | ||
IASTUnaryExpression/op_prefixDecr :de_incr | ||
IASTUnaryExpression/op_prefixIncr :de_incr | ||
IASTUnaryExpression/op_amper :pointer | ||
IASTUnaryExpression/op_star :pointer | ||
IASTUnaryExpression/op_not :not | ||
IASTUnaryExpression/op_tilde :bitwise}] | ||
(->> node .getOperator operator-group-table))) | ||
(defmethod operator-group IASTBinaryExpression [node] | ||
(if (assignment? node) | ||
:assign | ||
|
||
(let [operator-group-table | ||
{IASTBinaryExpression/op_modulo :non-asso | ||
IASTBinaryExpression/op_multiply :multiply | ||
IASTBinaryExpression/op_divide :non-asso | ||
IASTBinaryExpression/op_plus :add | ||
IASTBinaryExpression/op_minus :non-asso | ||
IASTBinaryExpression/op_shiftLeft :bitwise | ||
IASTBinaryExpression/op_shiftRight :bitwise | ||
IASTBinaryExpression/op_greaterThan :compare | ||
IASTBinaryExpression/op_greaterEqual :compare | ||
IASTBinaryExpression/op_lessThan :compare | ||
IASTBinaryExpression/op_lessEqual :compare | ||
IASTBinaryExpression/op_equals :compare | ||
IASTBinaryExpression/op_notequals :compare | ||
IASTBinaryExpression/op_binaryAnd :bitwise | ||
IASTBinaryExpression/op_binaryXor :bitwise | ||
IASTBinaryExpression/op_binaryOr :bitwise | ||
IASTBinaryExpression/op_logicalAnd :and | ||
IASTBinaryExpression/op_logicalOr :or}] | ||
(->> node .getOperator operator-group-table)))) | ||
|
||
|
||
(defn specific-confusing-operator-combination? | ||
"if the combination of groups of operators exists in this set, then the combination is confusing" | ||
[combination] | ||
(some #(= % combination) (map sort [[:de_incr :pointer] [:multiply :add] [:arith_unary :add] [:arith_unary :multiply] | ||
[:and :add] [:and :multiply] [:and :arith_unary] [:or :add] | ||
[:or :multiply] [:or :arith_unary] [:or :and] [:not :add] | ||
[:not :multiply] [:not :arith_unary] [:not :and] [:not :or] | ||
;;[:compare :and] [:compare :or] // Underclassify | ||
[:compare :not] [:compare :compare] [:pointer :add] [:cond :arith_unary] | ||
[:cond :and] [:cond :or] [:cond :not] [:cond :compare] | ||
[:cond :cond] [:non-asso :add] [:non-asso :multiply] [:non-asso :arith_unary] | ||
[:non-asso :and] [:non-asso :or] [:non-asso :not] [:non-asso :non-asso] | ||
[:field_ref :pointer]]))) | ||
|
||
(def always-confusing-operator-groups | ||
"If any of these operator groups is used along with another operator, then it is confusing" | ||
#{:bitwise :comma}) | ||
|
||
(defn confusing-operator-combination? | ||
"Is this combination of the operator groups confusing?" | ||
[combination] | ||
(or (specific-confusing-operator-combination? combination) | ||
(some (partial contains? always-confusing-operator-groups) combination))) | ||
|
||
(defn operator-group-pair? | ||
[node] | ||
(and (operator-group node) | ||
(some operator-group (children node)))) | ||
|
||
(defn group-pair | ||
"returns a collection of operator group pairs between the node and its children | ||
, if a second parameter is passed, use that as the collection instead of the children" | ||
([node] | ||
(group-pair node (children node))) | ||
|
||
([node collection] | ||
(->> collection | ||
(map operator-group) | ||
(remove nil?) | ||
(map (fn [child-group] (sort [(operator-group node) child-group])))))) | ||
|
||
;;==================================== | ||
;;For binary operator special case | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you really mean binary, not unary here?? if so, please explain more, I don't understand |
||
;;==================================== | ||
(def rvalue-unary-ops? | ||
"Is this a unary operator that can operate on an rvalue? (! - + *)" | ||
(comp #{:arith_unary :not :pointer} operator-group)) | ||
|
||
(defn unparenthesized-unary-in-children | ||
"Is this node not a bracket and constains unary operator in its children?" | ||
[node] | ||
(if (not (paren-node? node)) | ||
(filter-tree #(rvalue-unary-ops? %) node))) | ||
|
||
(defn group-pairs-in-binary-ops | ||
"Special function for returning a collection of operator group in binary operator's children, binary operator should ignore some groups of operators in its second operand" | ||
[node] | ||
(->> (concat [(get-in-tree [0] node) | ||
(if (not (rvalue-unary-ops? (get-in-tree [1] node))) | ||
(get-in-tree [1] node) nil)] | ||
|
||
(unparenthesized-unary-in-children (get-in-tree [0] node))) | ||
(map operator-group) | ||
(remove nil?) | ||
(map (fn [child-group] (sort [(operator-group node) child-group]))))) | ||
;;==================================== | ||
;; | ||
|
||
|
||
(defn operator-precedence-atom? | ||
"Is this node an operator-precedence-atom?" | ||
[node] | ||
(and | ||
(operator-group-pair? node) | ||
|
||
(not (= :assign (operator-group node))) | ||
|
||
(if (instance? IASTBinaryExpression node) | ||
(some confusing-operator-combination? (group-pairs-in-binary-ops node)) | ||
(some confusing-operator-combination? (group-pair node))))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure it's not wrong to not sort
combination
I feel like it'll actually get the wrong answer 50% of the time?Also, this function has to do 60 comparisons or something. But if you put all the operator combinations into a set and store that using
def
, then use a set lookup, it's only a single comparison. 60x speedup.