Paste: what I have so far

Author: slava
Mode: factor
Date: Mon, 30 Mar 2009 06:59:00
Plain Text |
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: peg peg.ebnf smalltalk.ast sequences sequences.deep strings
math.parser kernel ;
IN: smalltalk.parser

! http://chronos-st.blogspot.com/2007/12/smalltalk-in-one-page.html

EBNF: parse-smalltalk

Character = .
WhitespaceCharacter = (" " | "\t" | "\n" | "\r" ) => [[ ignore ]]
DecimalDigit = [0-9]
Letter = [A-za-z]

CommentCharacter = [^"] | '""' => [[ CHAR: " ]]
Comment = '"' (CommentCharacter)*:s '"' => [[ s >string ast-comment boa ]]

OptionalWhiteSpace = (WhitespaceCharacter | Comment)* => [[ ignore swap remove ]]
Whitespace = (WhitespaceCharacter | Comment)+ => [[ ignore swap remove ]]

LetterOrDigit = DecimalDigit | Letter
Identifier = (Letter | "_"):h (LetterOrDigit | "_")*:t => [[ { h t } flatten >string ]]
Reference = Identifier

ConstantReference = 
                  "nil" => [[ ast-nil ]]
                | "false" => [[ f ]]
                | "true" => [[ t ]]
PseudoVariableReference = 
                  "self" => [[ ast-self ]]
                | "super" => [[ ast-super ]]
ReservedIdentifier = PseudoVariableReference | ConstantReference

BindableIdentifier = Identifier

UnaryMessageSelector = Identifier

Keyword = Identifier:i ":" => [[ i ":" append ]]

KeywordMessageSelector = Keyword+ => [[ concat ]]
BinarySelectorChar = "~" | "!" | "@" | "%" | "&" | "*" | "-" | "+" | "=" | "|" | "\" | "<" | ">" | "," | "?" | "/"
BinaryMessageSelector = BinarySelectorChar+ => [[ concat ]]

IntegerLiteral = ("-" UnsignedIntegerLiteral) => [[ flatten >string string>number ]]
UnsignedIntegerLiteral = Radix:r "r" BaseNIntegerLiteral:b => [[ b >string r base> ]]  | DecimalIntegerLiteral
DecimalIntegerLiteral = DecimalDigit+ => [[ >string string>number ]]
Radix = DecimalIntegerLiteral
BaseNIntegerLiteral = LetterOrDigit+
ScaledDecimalLiteral = "-"? DecimalIntegerLiteral ("." DecimalIntegerLiteral)? "s" DecimalIntegerLiteral?
FloatingPointLiteral = "-"? DecimalIntegerLiteral ("." DecimalIntegerLiteral Exponent? | Exponent)
Exponent = ("e" | "d" | "q") ("-"? DecimalIntegerLiteral)?
CharacterLiteral = "$" Character
StringLiteral = "'" (StringLiteralCharacter | "''") "'"
StringLiteralCharacter = [^']
SymbolInArrayLiteral = (UnaryMessageSelector | KeywordMessageSelector | BinaryMessageSelector)
SymbolLiteral = "#" (ConstantReference | SymbolInArrayLiteral | StringLiteral)
ArrayLiteral = (ObjectArrayLiteral | ByteArrayLiteral)
ObjectArrayLiteral = "#" NestedObjectArrayLiteral
NestedObjectArrayLiteral = "(" OptionalWhiteSpace (LiteralArrayElement (Whitespace LiteralArrayElement)*)? OptionalWhiteSpace ")"
LiteralArrayElement = Literal | NestedObjectArrayLiteral | SymbolInArrayLiteral | ConstantReference
ByteArrayLiteral = "#[" OptionalWhiteSpace (UnsignedIntegerLiteral (Whitespace UnsignedIntegerLiteral)*)? OptionalWhiteSpace "]"

FormalBlockArgumentDeclaration = ":" BindableIdentifier
FormalBlockArgumentDeclarationList = FormalBlockArgumentDeclaration (Whitespace FormalBlockArgumentDeclaration)*
BlockLiteral = "[" (OptionalWhiteSpace FormalBlockArgumentDeclarationList OptionalWhiteSpace "|")? ExecutableCode OptionalWhiteSpace "]"

Literal = ConstantReference 
                | IntegerLiteral 
                | ScaledDecimalLiteral 
                | FloatingPointLiteral 
                | CharacterLiteral 
                | StringLiteral 
                | SymbolLiteral 
                | ArrayLiteral 
                | BlockLiteral

NestedExpression = "(" Statement OptionalWhiteSpace ")"
Operand =       Literal 
                | Reference 
                | NestedExpression

UnaryMessage = UnaryMessageSelector
UnaryMessageChain = (OptionalWhiteSpace UnaryMessage)*
BinaryMessageOperand = Operand UnaryMessageChain
BinaryMessage = BinaryMessageSelector OptionalWhiteSpace BinaryMessageOperand
BinaryMessageChain = (OptionalWhiteSpace BinaryMessage)*
KeywordMessageArgument = BinaryMessageOperand BinaryMessageChain
KeywordMessageSegment = Keyword OptionalWhiteSpace KeywordMessageArgument
KeywordMessage = KeywordMessageSegment (OptionalWhiteSpace KeywordMessageSegment)*
MessageChain = 
                UnaryMessage UnaryMessageChain BinaryMessageChain (KeywordMessage)? 
                | BinaryMessage BinaryMessageChain (KeywordMessage)?
                | KeywordMessage
CascadedMessage = ";" OptionalWhiteSpace MessageChain
Expression = Operand (OptionalWhiteSpace MessageChain (OptionalWhiteSpace CascadedMessage)*)?

AssignmentOperation = OptionalWhiteSpace BindableIdentifier OptionalWhiteSpace ":="
Statement = (AssignmentOperation)* OptionalWhiteSpace Expression
MethodReturnOperator = OptionalWhiteSpace "^"
FinalStatement = (MethodReturnOperator)? Statement
LocalVariableDeclarationList = OptionalWhiteSpace "|" OptionalWhiteSpace (BindableIdentifier (Whitespace BindableIdentifier)*)? OptionalWhiteSpace "|"
ExecutableCode = (LocalVariableDeclarationList)? ((Statement OptionalWhiteSpace ".")* FinalStatement (".")?)?

UnaryMethodHeader = UnaryMessageSelector
BinaryMethodHeader = BinaryMessageSelector OptionalWhiteSpace BindableIdentifier
KeywordMethodHeaderSegment = Keyword OptionalWhiteSpace BindableIdentifier
KeywordMethodHeader = KeywordMethodHeaderSegment (Whitespace KeywordMethodHeaderSegment)*
MethodHeader = 
                UnaryMethodHeader 
                | BinaryMethodHeader 
                | KeywordMethodHeader
MethodDeclaration = OptionalWhiteSpace MethodHeader ExecutableCode End

End = !(.)
;EBNF

Annotation: progress

Author: slava
Mode: factor
Date: Mon, 30 Mar 2009 08:37:24
Plain Text |
( scratchpad ) "(2 squared + 3 * 2) print" parse-smalltalk .
{
    T{ ast-return
        { value
            T{ ast-message-send
                { receiver
                    T{ ast-message-send
                        { receiver
                            T{ ast-message-send
                                { receiver
                                    T{ ast-message-send
                                        { receiver 2 }
                                        { selector "squared" }
                                    }
                                }
                                { selector "+" }
                                { arguments { 3 } }
                            }
                        }
                        { selector "*" }
                        { arguments { 2 } }
                    }
                }
                { selector "print" }
            }
        }
    }
}

Annotation: testcase

Author: slava
Mode: factor
Date: Mon, 30 Mar 2009 09:13:24
Plain Text |
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: peg peg.ebnf smalltalk.ast sequences sequences.deep strings
math.parser kernel arrays byte-arrays math assocs ;
IN: testing

EBNF: parse-smalltalk

WhitespaceCharacter = (" " | "\t" | "\n" | "\r" )
Letter = [A-Za-z]

OptionalWhiteSpace = (WhitespaceCharacter)*
Whitespace = (WhitespaceCharacter)+

Identifier = Letter*

UnaryMessageSelector = Identifier
Keyword = Identifier:i ":"
BinarySelectorChar =   "~" | "!" | "@" | "%" | "&" | "*" | "-" | "+"
                     | "=" | "|" | "\" | "<" | ">" | "," | "?" | "/"
BinaryMessageSelector = BinarySelectorChar+

Operand =       "(" Expression ")" | Identifier

UnaryMessage = UnaryMessageSelector
UnaryMessageOperand = UnaryMessageSend | Operand
UnaryMessageSend = UnaryMessageOperand:receiver
                   OptionalWhiteSpace UnaryMessageSelector:selector !(":")

BinaryMessage = BinaryMessageSelector OptionalWhiteSpace BinaryMessageOperand
BinaryMessageOperand = BinaryMessageSend | UnaryMessageSend | Operand
BinaryMessageSend-1 = BinaryMessageOperand:lhs
                    OptionalWhiteSpace
                    BinaryMessageSelector:selector
                    OptionalWhiteSpace
                    UnaryMessageOperand:rhs
BinaryMessageSend = (BinaryMessageSend:lhs
                    OptionalWhiteSpace
                    BinaryMessageSelector:selector
                    OptionalWhiteSpace
                    UnaryMessageOperand:rhs)
                    | BinaryMessageSend-1

KeywordMessageSegment = Keyword:k OptionalWhiteSpace BinaryMessageOperand:arg
KeywordMessageSend = BinaryMessageOperand:receiver
                     OptionalWhiteSpace
                     KeywordMessageSegment:h
                     (OptionalWhiteSpace KeywordMessageSegment:s)*:t

Expression = KeywordMessageSend | BinaryMessageSend | UnaryMessageSend | Operand

End = !(.)

Program = Expression End
;EBNF

"(a x + b) x" parse-smalltalk

Annotation: workaround

Author: doublec
Mode: factor
Date: Mon, 30 Mar 2009 10:54:31
Plain Text |
KeywordMessageSend = (BinaryMessageSend | UnaryMessageSend | Operand
):receiver
                     OptionalWhiteSpace
                     KeywordMessageSegment:h
                     (OptionalWhiteSpace KeywordMessageSegment:s)*:t

New Annotation

Summary:
Author:
Mode:
Body: