~~~ method grammar ~~~

<method definition> ::=
 <message pattern>
 [<temporaries> ]
 [<statements>]

<message pattern> ::= <unary pattern> | 
 <binary pattern> | 
 <keyword pattern>

<unary pattern> ::= unarySelector

<binary pattern> ::= binarySelector <method argument>

<keyword pattern> ::= (keyword  <method argument>)+

<temporaries> ::= '|' <temporary variable list> '|'

<temporary variable list> ::= identifier*

<block constructor> ::= '[' <block body> ']'

<block body> ::= [<block argument>* '|'] 
 [<temporaries>] [<statements>]

<block argument> ::= ':'  identifier

<statements> ::=
 (<return statement> ['.'] ) |
 (<expression> ['.' [<statements>]])

<return statement> ::= returnOperator  <expression>

<expression> ::=
  <assignment> |
  <basic expression>

<assignment> ::= <assignment target> assignmentOperator  <expression>

<basic expression> ::=
  <primary> [<messages> <cascaded messages>]

<assignment target> := identifier

<primary> ::=
  identifier |
  <literal> |
  <block constructor> |
  ( '(' <expression> ')' )


<messages> ::=
  (<unary message>+ <binary message>* [<keyword message>] ) |
  (<binary message>+ [<keyword message>] ) |
  <keyword message>

<unary message> ::= unarySelector

<binary message> ::= binarySelector <binary argument>

<binary argument> ::= <primary> <unary message>*

<keyword message> ::= (keyword <keyword argument> )+

<keyword argument> ::= <primary> <unary message>* <binary message>*

<cascaded messages> ::= (';' <messages>)*

<literal> ::=
  <number literal> |
  <string literal> |
  <character literal> |
  <symbol literal> |
  <selector literal> |
  <array literal>

<number literal> ::= ['-'] <number>

<number> ::= integer | float | scaledDecimal

<character literal> ::=  quotedCharacter

<string literal> ::= quotedString

<symbol literal> ::= hashedString

<selector literal> ::=  quotedSelector

<array literal> ::= '#(' <array element>* ')'

<array element> ::= <literal> | identifier

reserved identifiers -> nil true false self super


~~~ lexical grammar ~~~

character ::=
  "Any character in the implementation-defined character set"

whitespace ::= 
  "Any non-printing character interpreted as white space 
  including spaces, tabs, and line breaks"

digit ::= 
  '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

uppercaseAlphabetic ::=
  'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 
  'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 
  'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'

lowercaseAlphabetic ::=
  'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 
  'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 
  's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'

nonCaseLetter ::= '_'

letter ::=
  uppercaseAlphabetic |
  lowercaseAlphabetic |
  nonCaseLetter |
  "implementation defined letters"

commentDelimiter ::= '"'

nonCommentDelimiter::=
"any character that is not a commentDelimiter "

 comment :=
 commentDelimiter  nonCommentDelimiter * commentDelimiter

identifier ::= letter (letter | digit)*

keyword ::= identifier ':'

binaryCharacter ::=
  '!' | '%' | '&' | '*' | '+' | ',' | 
  '/' | '<' | '=' | '>' | '?' | '@' | 
  '\' | '~' | '|' | '-'

binarySelector ::= binaryCharacter+

returnOperator ::= '^'

assignmentOperator ::=  ':='


integer ::= decimalInteger  | radixInteger

decimalInteger ::= digits

digits ::= digit+

radixInteger ::= radixSpecifier  'r' radixDigits

radixSpecifier := digits

radixDigits ::= (digit | uppercaseAlphabetic)+


float ::=  mantissa [exponentLetter exponent]

mantissa ::= digits'.' digits

exponent ::= ['-']decimalInteger

exponentLetter ::= 'e' | 'd' | 'q'

scaledDecimal ::= scaledMantissa 's' [fractionalDigits]

scaledMantissa ::= decimalInteger | mantissa

fractionalDigits ::= decimalInteger

quotedCharacter ::= '$' character

quotedString ::= stringDelimiter stringBody stringDelimiter

stringBody ::= (nonStringDelimiter | (stringDelimiter stringDelimiter)*)

stringDelimiter ::= '''    "a single quote"

nonStringDelimiter ::= "any character except stringDelimiter"

hashedString ::= '#' quotedString

quotedSelector ::= '#' (unarySelector  |  binarySelector  | keywordSelector)

keywordSelector ::= keyword+

separator ::= (whitespace | comment)*