353 lines
7.6 KiB
Smalltalk
353 lines
7.6 KiB
Smalltalk
|
"
|
|||
|
I can recognize basic structure block in ruby code (almost precisely).
|
|||
|
|
|||
|
I use indentation to determine the scope of the block. I use island to skip the rest.
|
|||
|
|
|||
|
The following structures are recognized:
|
|||
|
- modules
|
|||
|
- classes
|
|||
|
- methods
|
|||
|
"
|
|||
|
Class {
|
|||
|
#name : 'PPRubySeaGrammar',
|
|||
|
#superclass : 'PPCompositeParser',
|
|||
|
#instVars : [
|
|||
|
'primary',
|
|||
|
'kClassIS',
|
|||
|
'cpath',
|
|||
|
'superclass',
|
|||
|
'identifier',
|
|||
|
'kSelf',
|
|||
|
'word',
|
|||
|
'fname',
|
|||
|
'classDef',
|
|||
|
'methodDef',
|
|||
|
'primaryElement',
|
|||
|
'water',
|
|||
|
'operator',
|
|||
|
'program',
|
|||
|
'kDefIS',
|
|||
|
'defEndIS',
|
|||
|
'kModuleIS',
|
|||
|
'moduleDef',
|
|||
|
'eigenDef',
|
|||
|
'body',
|
|||
|
'kEndIS',
|
|||
|
'kEnd',
|
|||
|
'comment',
|
|||
|
'string',
|
|||
|
'aligns',
|
|||
|
'nl',
|
|||
|
'setIl',
|
|||
|
'onside',
|
|||
|
'restoreIl',
|
|||
|
'sol',
|
|||
|
'eol',
|
|||
|
'eof',
|
|||
|
'onsideLine'
|
|||
|
],
|
|||
|
#category : 'PetitIslands-Examples'
|
|||
|
}
|
|||
|
|
|||
|
{ #category : 'indentation' }
|
|||
|
PPRubySeaGrammar >> aligns [
|
|||
|
^ [:context |
|
|||
|
(context column == (context indentStack topIfEmpty: -1)) ifTrue: [
|
|||
|
#aligns
|
|||
|
] ifFalse: [
|
|||
|
PPFailure message: 'no alignment' at: context position
|
|||
|
]
|
|||
|
] asParser
|
|||
|
"JK: this is a hack, it improves the speed of compiled parser"
|
|||
|
propertyAt: #changesContext put: false;
|
|||
|
yourself
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> body [
|
|||
|
^ ((((primaryElement) sea: water) ==> #second) plus)
|
|||
|
==> [ :args | args select: [ :e | e isEmpty not ]]
|
|||
|
/
|
|||
|
((nil asParser sea: water) ==> [ :args | #() ])
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar - class' }
|
|||
|
PPRubySeaGrammar >> classDef [
|
|||
|
"Indentation Sensitive Class Definition"
|
|||
|
^ kClassIS,
|
|||
|
cpath trim,
|
|||
|
superclass optional,
|
|||
|
body,
|
|||
|
kEndIS
|
|||
|
|
|||
|
|
|||
|
map: [ :cl :cp :sup :content :end |
|
|||
|
| retval |
|
|||
|
retval := OrderedCollection new.
|
|||
|
content do: [ :m |
|
|||
|
retval addAll: (m collect: [:e | '::', cp, e ]).
|
|||
|
].
|
|||
|
retval.
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'whitespaces' }
|
|||
|
PPRubySeaGrammar >> comment [
|
|||
|
^ $# asParser trimBlanks, (nl negate star), nl
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> cpath [
|
|||
|
^ ('::' asParser optional , identifier, (('::' asParser , identifier) star)) flatten
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar - method' }
|
|||
|
PPRubySeaGrammar >> defEndIS [
|
|||
|
"End of Indentation Sensitive Feature"
|
|||
|
^ kEnd optional, restoreIl
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> eigenDef [
|
|||
|
^ kClassIS , '<<' asParser trim , (identifier / kSelf) ,
|
|||
|
body,
|
|||
|
kEndIS
|
|||
|
|
|||
|
map: [ :class :tmp :ref :content :end |
|
|||
|
| retval |
|
|||
|
retval := OrderedCollection new.
|
|||
|
content do: [ :m |
|
|||
|
retval addAll: (m collect: [:e | '.', ref, e ]).
|
|||
|
].
|
|||
|
retval.
|
|||
|
]
|
|||
|
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'whitespaces' }
|
|||
|
PPRubySeaGrammar >> eof [
|
|||
|
^ #eof asParser
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'whitespaces' }
|
|||
|
PPRubySeaGrammar >> eol [
|
|||
|
^ nl / eof
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> fname [
|
|||
|
^ (operator /
|
|||
|
'..' asParser / '|' asParser / 'ˆ' asParser / '&' asParser
|
|||
|
/ '<=>' asParser / '==' asParser /
|
|||
|
'===' asParser / '=~' asParser / '>'asParser / '>='asParser / '<' asParser /
|
|||
|
'<=' asParser / '+' asParser / '-' asParser /
|
|||
|
'*' asParser / '/' asParser / '%' asParser / '**' asParser / '<<' asParser /
|
|||
|
'>>' asParser / '~' asParser / '+@' asParser /
|
|||
|
'-@' asParser / '[]' asParser / '[]=' asParser)
|
|||
|
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> identifier [
|
|||
|
^ (#letter asParser / $_ asParser, word star) flatten
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'keywords' }
|
|||
|
PPRubySeaGrammar >> kClassIS [
|
|||
|
^ (($. asParser / word) previous not, setIl, 'class' asParser , ($. asParser / word) not) ==> #third
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'keywords' }
|
|||
|
PPRubySeaGrammar >> kDefIS [
|
|||
|
^ (word previous not, setIl, 'def' asParser , word not) ==> #third
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'keywords' }
|
|||
|
PPRubySeaGrammar >> kEnd [
|
|||
|
^ (word previous not, 'end' asParser , word not) ==> #second
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'keywords' }
|
|||
|
PPRubySeaGrammar >> kEndIS [
|
|||
|
"End of Indentation Sensitive Feature"
|
|||
|
^ aligns, kEnd, restoreIl
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'keywords' }
|
|||
|
PPRubySeaGrammar >> kModuleIS [
|
|||
|
^ (word previous not, setIl, 'module' asParser , word not) trim ==> #third
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'keywords' }
|
|||
|
PPRubySeaGrammar >> kSelf [
|
|||
|
^ (($. asParser / word) previous not, 'self' asParser , ($. asParser / word) not) trim ==> #second
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'whitespaces' }
|
|||
|
PPRubySeaGrammar >> line [
|
|||
|
^ (sol, nl negate star, eol) nonEmpty
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar - method' }
|
|||
|
PPRubySeaGrammar >> methodDef [
|
|||
|
^ kDefIS,
|
|||
|
('self.' asParser / (identifier, $. asParser)) flatten trim optional ,
|
|||
|
fname trim,
|
|||
|
primary,
|
|||
|
defEndIS
|
|||
|
|
|||
|
map: [ :def :static :name :content :end |
|
|||
|
| mName retval |
|
|||
|
mName := static isNil ifTrue: [ '.', name ]
|
|||
|
ifFalse: [ '.', static, name ].
|
|||
|
|
|||
|
retval := OrderedCollection new.
|
|||
|
content do: [ :e | retval addAll: (e collect: [ :e2 | mName, e2 ]) ].
|
|||
|
retval add: mName.
|
|||
|
retval
|
|||
|
]
|
|||
|
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> moduleDef [
|
|||
|
"Indentation Sensitive Class Definition"
|
|||
|
^ kModuleIS,
|
|||
|
cpath trim,
|
|||
|
body,
|
|||
|
kEndIS
|
|||
|
|
|||
|
|
|||
|
map: [ :module :cp :prim :end |
|
|||
|
| retval |
|
|||
|
retval := OrderedCollection new.
|
|||
|
prim do: [ :m |
|
|||
|
retval addAll: (m collect: [:e | '::', cp, e ]).
|
|||
|
].
|
|||
|
retval.
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'whitespaces' }
|
|||
|
PPRubySeaGrammar >> nl [
|
|||
|
^ #newline asParser
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'indentation' }
|
|||
|
PPRubySeaGrammar >> onside [
|
|||
|
^ [:context |
|
|||
|
(context column >= (context indentStack topIfEmpty: -1)) ifTrue: [
|
|||
|
#onside
|
|||
|
] ifFalse: [
|
|||
|
PPFailure message: 'offside position, not onside :(' at: context position
|
|||
|
]
|
|||
|
] asParser
|
|||
|
"JK: this is a hack, it improves the speed of compiled parser"
|
|||
|
propertyAt: #changesContext put: false;
|
|||
|
yourself
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'whitespaces' }
|
|||
|
PPRubySeaGrammar >> onsideLine [
|
|||
|
^ onside, #letter asParser, nl asParser negate star, eol
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> operator [
|
|||
|
^ (identifier , ($? asParser / $! asParser / $= asParser) optional) flatten
|
|||
|
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> primary [
|
|||
|
^ ((((primaryElement) sea: water) ==> #second) plus)
|
|||
|
==> [ :args | args select: [ :e | e isEmpty not ]]
|
|||
|
/
|
|||
|
((nil asParser sea: water) ==> [ :args | #() ])
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> primaryElement [
|
|||
|
^ onside,
|
|||
|
(classDef /
|
|||
|
moduleDef /
|
|||
|
eigenDef /
|
|||
|
methodDef)
|
|||
|
==> #second
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> program [
|
|||
|
^ primary ==> [ :res |
|
|||
|
res flatten
|
|||
|
]
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'indentation' }
|
|||
|
PPRubySeaGrammar >> restoreIl [
|
|||
|
^ [ :context | context indentStack pop ] asParser
|
|||
|
"JK: this is a hack, it improves the speed of compiled parser"
|
|||
|
propertyAt: #indentPop put: true;
|
|||
|
yourself
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'indentation' }
|
|||
|
PPRubySeaGrammar >> setIl [
|
|||
|
^ [:context |
|
|||
|
| level |
|
|||
|
level := context column.
|
|||
|
context indentStack push: level.
|
|||
|
] asParser
|
|||
|
"JK: this is a hack, it improves the speed of compiled parser"
|
|||
|
propertyAt: #indentPush put: true;
|
|||
|
yourself
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'whitespaces' }
|
|||
|
PPRubySeaGrammar >> sol [
|
|||
|
^ #startOfLine asParser
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'accessing' }
|
|||
|
PPRubySeaGrammar >> start [
|
|||
|
^ program
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> string [
|
|||
|
| doubleQuotes singleQuotes slash doubleString singleString regexp |
|
|||
|
doubleQuotes := $" asParser.
|
|||
|
singleQuotes := $' asParser.
|
|||
|
slash := $/ asParser.
|
|||
|
|
|||
|
doubleString := (doubleQuotes ,
|
|||
|
(($\ asParser , doubleQuotes) / #any asParser starLazy: doubleQuotes) ,
|
|||
|
doubleQuotes) flatten.
|
|||
|
|
|||
|
singleString := (singleQuotes ,
|
|||
|
(($\ asParser , singleQuotes) / #any asParser starLazy: singleQuotes) ,
|
|||
|
singleQuotes) flatten.
|
|||
|
|
|||
|
regexp := (slash ,
|
|||
|
(('\\' asParser) / ($\ asParser , slash) / #any asParser starLazy: slash) ,
|
|||
|
slash) flatten.
|
|||
|
|
|||
|
^ (doubleString / singleString / regexp) ==> [ :nodes | #() ]
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> superclass [
|
|||
|
^ (($< asParser trim , cpath) ==> #second)
|
|||
|
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'whitespaces' }
|
|||
|
PPRubySeaGrammar >> water [
|
|||
|
^ (#space asParser plus) / onsideLine / comment "/ string / line" / identifier / #any asParser
|
|||
|
]
|
|||
|
|
|||
|
{ #category : 'grammar' }
|
|||
|
PPRubySeaGrammar >> word [
|
|||
|
^ #word asParser / $_ asParser
|
|||
|
]
|