Definition of Squeak

Stefan Matthias Aust sma at kiel.netsurf.de
Thu Aug 27 23:56:13 UTC 1998


>A fine idea.  Are you volunteering?


Well, here you are :)


The following rules use EBNF notations. Terminal symbols are enclosed in
double quotes. [ ] means optional occurence, { } zero or more occurences
and | is an alternative. These are the main rules for Squeak's variant of
Smalltalk, as implemented in the class Parser. 

TODO: Define word, binary, string, number, scannerLiteral.


start = method.

method = pattern temporaries primitive statements.
NOTE: Compiler asures that no other tokens follow.

pattern = unaryPattern | binaryPattern | keywordPattern.
    
unaryPattern = unarySelector.

unarySelector = word.

binaryPattern = binarySelector argument.

binarySelector = (binary | "|").
NOTE: | isn't a binary and || isn't allowed at all; this might be an error.
    
keywordPattern = keyword argument {keyword argument}.

keyword = word ":".
NOTE: Actually, this is already detected by the scanner.
    
argument = word.
NOTE: The argument must not already been declared.
      Write access is not allowed for arguments.

temporaries = [ "|" {variable} "|" ].
NOTE: The variable must not already been declared.
      || (without whitespaces) is allowed because || isn't a binarySelector.

variable = word.

primitive = [ "<" primitiveDecl ">" ].
    
primitiveDecl = [ "primitive:" number ].
NOTE: you can omit the complete declaration. In this case, a primitive
      nil is returned. You can also use floats for the number. Both
      seems to be errors in the compiler

statements = returnStmt | expressionStmt
NOTE: if there's another statement after a return, the compiler notify
      us that it expects the block end, regardless whether we're in a
      block or not.

returnStmt = "^" expression [ "." ].

expressionStmt = [ expression {"." statements} [ "." ] ].
NOTE: If no expression is available, method bodies are replaced with
      "self" and empty blocks with "nil".

expression = (assignment | braceAssign | primaryExpr) messagePart

assignment = variable assigner expression.
NOTE: variable must be bound.

assigner = "_" | ":=".
NOTE: "_" is actually the left arrow.

braceAssign = brace assigner expression.
NOTE: I don't understand this.

primaryExpr = varExpr | blockExpr | braceExpr | "(" expression ")" | literal.

varExpr = variable
NOTE: Variable must be bound or one of the following special variables:
      false, nil, self, super, thisContext, true and homeContext.

blockExpr = "[" [ ":" argument {":" argument} "|" ] statements "]"
NOTE: The arguments may shadow other declarations.
      Write access is not allowed for arguments.

braceExpr = "{" [ expression {"." expression} ] "}".

literal = string | number | ("-" number) | scannerLiteral.
NOTE: ScanneLiterals include symbols, characters, literal arrays, etc.

messagePart = [ messagePart3 {messagePart3} cascade ].

messagePart3 = keywordMsgPart | messagePart2.
NOTE: This somewhat complex scheme is used to express the precedence
      rules of different message types.

keywordMsgPart = keywordPart {keywordPart}.
NOTE: All keywordParts are concatenated to one message send.

keywordPart = keyword primaryExpr messagePart2 {messagePart2}.

messagePart2 = binaryMsgPart | messagePart1.

binaryMsgPart = binarySelector messagePart1 {messagePart1}.

messagePart1 = unaryMessagePart.

unaryMsgPart = unarySelector.

cascade = {";" messagePart3}.
NOTE: Compiler checks whether cascade is allowed. You cannot cascade
      super sends and sends to special selectors like ifTrue: which are
      replaced by the compiler.


method = pattern temporaries primitive statements.
NOTE: Compiler asures that no other tokens follow.

pattern = unaryPattern | binaryPattern | keywordPattern.
    
unaryPattern = unarySelector.

unarySelector = word.

binaryPattern = binarySelector argument.

binarySelector = (binary | "|").
NOTE: | isn't a binary and || isn't allowed at all; this might be an error.
    
keywordPattern = keyword argument {keyword argument}.

keyword = word ":".
NOTE: Actually, this is already detected by the scanner.
    
argument = word.
NOTE: The argument must not already been declared.
      Write access is not allowed for arguments.

temporaries = [ "|" {variable} "|" ].
NOTE: The variable must not already been declared.
      || (without whitespaces) is allowed because || isn't a binarySelector.

variable = word.

primitive = [ "<" primitiveDecl ">" ].
    
primitiveDecl = [ "primitive:" number ].
NOTE: you can omit the complete declaration. In this case, a primitive
      nil is returned. You can also use floats for the number. Both
      seems to be errors in the compiler

statements = returnStmt | expressionStmt
NOTE: if there's another statement after a return, the compiler notify
      us that it expects the block end, regardless whether we're in a
      block or not.

returnStmt = "^" expression [ "." ].

expressionStmt = [ expression {"." statements} [ "." ] ].
NOTE: If no expression is available, method bodies are replaced with
      "self" and empty blocks with "nil".

expression = (assignment | braceAssign | primaryExpr) messagePart

assignment = variable assigner expression.
NOTE: variable must be bound.

assigner = "_" | ":=".
NOTE: "_" is actually the left arrow.

braceAssign = brace assigner expression.
NOTE: I don't understand this.

primaryExpr = varExpr | blockExpr | braceExpr | "(" expression ")" | literal.

varExpr = variable
NOTE: Variable must be bound or one of the following special variables:
      false, nil, self, super, thisContext, true and homeContext.

blockExpr = "[" [ ":" argument {":" argument} "|" ] statements "]"
NOTE: The arguments may shadow other declarations.
      Write access is not allowed for arguments.

braceExpr = "{" [ expression {"." expression} ] "}".

literal = string | number | ("-" number) | scannerLiteral.
NOTE: ScanneLiterals include symbols, characters, literal arrays, etc.

messagePart = [ messagePart3 {messagePart3} cascade ].

messagePart3 = keywordMsgPart | messagePart2.
NOTE: This somewhat complex scheme is used to express the precedence
      rules of different message types.

keywordMsgPart = keywordPart {keywordPart}.
NOTE: All keywordParts are concatenated to one message send.

keywordPart = keyword primaryExpr messagePart2 {messagePart2}.

messagePart2 = binaryMsgPart | messagePart1.

binaryMsgPart = binarySelector messagePart1 {messagePart1}.

messagePart1 = unaryMessagePart.

unaryMsgPart = unarySelector.

cascade = {";" messagePart3}.
NOTE: Compiler checks whether cascade is allowed. You cannot cascade
      super sends and sends to special selectors like ifTrue: which are
      replaced by the compiler.


bye
--
Stefan Matthias Aust  //  Are you ready to discover the twilight zone?





More information about the Squeak-dev mailing list