Atoms, Identifiers, and Primaries

rusi rustompmody at gmail.com
Tue Apr 16 23:55:49 EDT 2013


On Apr 17, 7:57 am, Bruce McGoveran <bruce.mcgove... at gmail.com> wrote:
> These are terms that appear in section 5 (Expressions) of the Python online documentation.  I'm having some trouble understanding what, precisely, these terms mean.  I'd appreciate the forum's thoughts on these questions:
>
> 1.  Section 5.2.1 indicates that an identifier occurring as an atom is a name.  However, Section 2.3 indicates that identifiers are names.  My question:  can an identifier be anything other than a name?
>
> 2.  Section 5.3 defines primaries as the most tightly bound operations of Python.  What does this mean?  In particular, if an atom is a primary, what operation is the atom performing that leads to the label "most tightly bound"?  To put it a different way, I think of atoms as things (i.e. identifiers).  The documentation makes me think atoms actually do something, as opposed to being things (I think I have in my mind the difference between a noun and a verb as I write this).  Perhaps the doing in this case (or binding, if you like) is linking (binding) the identifier to the underlying object?  I think it might help if I had a better working notion of what a primary is.
>
> 3.  Section 5.3.1 offers this definition of an attributeref:
>     attributeref ::= primary "." identifier
>
> Now, I was at first a little concerned to see the non-terminal primary on the right hand side of the definition, since primary is defined to include attributeref in section 5.3 (so this struck me as circular).  Am I correct in thinking attributeref is defined this way to allow for situations in which the primary, whether an atom, attributeref (example:  an object on which a method is called that returns another object), subscription, slicing, or call, returns an object with property identifier?
>
> These are, I know, long-winded questions.  I appreciate in advance any thoughts the group can offer.
>
> The relevant documentation link is:  http://docs.python.org/2/reference/expressions.html#expressions
>
> Thanks,
> Bruce

The specific details of python grammar I am not deeply familiar with,
so I'll leave others to comment.
One general comment I will make is regarding your distress at what you
call 'circular'
Circular just means recursive and recursion is the bedrock for
language-design.
You cannot hope to define an infinite object such as the python
language (there are an infinite number of python programs) with a
finite specification -- a useful language definition must start and
end and preferably fit in one's pocket!
The trick is to find ways of making an inifinite object finitely
generated. So much of language design is a generalization of Peano's
method of defining (designing?) natural numbers:
a. 0 is a natural number
b. If x is a natural number then the successor of x (informally x+1)
is a natural number

Note 1. that if we take the above as a definition of natural no. then
its a recursive definition, in particular b. You can call it circular
if you like. Just drop the pejorative color.
Note 2. We need to add the 'informally' because + needs to be defined
in terms of the above definition and not the other way round, else we
get a bad case of recursion. Such a definition would run as
0 + y = y
Sx + y = S(x+y)
(read Sx as successor of x)

Coming closer to your question, consider the 3 expressions:
A: 2*x + 3*y
B: (2*x) + 3*y
C: 2*(x+3)*y

Informally we may say that A and B are the same whereas C is
different.
Formally all three are different.
Not only are they different as strings, their parse-trees are
different. Their evaluations as defined by the python interpreter may
give the same value to A and B... thats a separate question from yours
which is really a syntax question.

A is an a_expr because 2*x is an m_expr and 3*y is an m-expr
Since an m-expr is (a trivial instance of an) a_expr therefore 2*x is
an a_expr
Since one way of making an a_expr is by doing a_expr + m_expr (note
the recursion) therefore 2*x + 3*y is an a_expr

In short Ive described the derivation:
a_expr -> a_expr + m_expr -> a_expr + 3*y -> m_expr + 3*y -> 2*x + 3*y

The derivation of B would be longer involving fact that (2*x) is a
parent-form therefore atom
atom -> enclosure -> enclosure -> parenth_form -> (expr_list) ->
(expression)
-> (conditional-e) -> (or_test) -> (and_test) -> (or-exp) -> (xor->
exp) -> (and-exp) -> (shift-e) -> (a_expr)

[And now I got fedup of following the grammar but hopefully you get
the idea!]



More information about the Python-list mailing list