"shell.st -- a tiny jolt2 shell" { import: Object } { import: Compiler } "Expression translate: aCompiler [ self println. ^aCompiler translateExpression: self ]" "----------------------------------------------------------------" "Error Recovery" "Errors in Shell >> eval:to: is recoverd with Restart block." IsRecovery := [ true ] "Set false if you need default behavior of jolt2." Object error: reason [ StdErr backtrace. StdErr cr; nextPutAll: reason; cr. (IsRecovery and: [ Shell currentRestartBlock ]) ifTrue: [ Shell currentRestartBlock value ]. { exit(1); }. ] Object _debug [ self backtrace. (IsRecovery and: [ Shell currentRestartBlock ]) ifTrue: [ Shell currentRestartBlock value ]. { exit(1); }. ] "----------------------------------------------------------------" "ShellStack is used for recursive evaluation." ShellStack := [ OrderedCollection new ] CurrentGrammar := [ ColaFunctionGrammar ] Shell : Object (parser restartBlock) "Class methods" Shell currentRestartBlock [ ^ShellStack notEmpty ifTrue: [ ShellStack last restartBlock ]] Shell currentParser [ ^ShellStack notEmpty ifTrue: [ ShellStack last parser ]] Shell main [ "This method is used on 'stand alone mode'." OS arguments isEmpty ifTrue: [^ self new evalStdIn]. OS arguments do: [ :each | self parseArgument: each]. ] Shell parseArgument: aString [ | file | (Options parseOption: aString) ifTrue: [^self]. (CompilerOptions parseOption: aString) ifTrue: [^self]. aString = '-' ifTrue: [^self new evalStdIn]. file := (File openIfPresent: aString) ifFalse: [File open: Options libdir, '/', aString]. file isNil ifTrue: [^ self error: aString, ': No such file or directory']. self new eval: file readStream to: SinkStream. ] Shell grammar: aSymbol [ CurrentGrammar := Grammar named: aSymbol ] "Instance methods" Shell restartBlock [ ^restartBlock ] Shell parser [ ^parser ] Shell eval: readStream to: writeStream [ "Evaluate from a read stream. Answer nil if an error happens." | result | ShellStack addLast: self. result := self privateEval: readStream to: writeStream. ShellStack removeLast. ^ result ] Shell privateEval: readStream to: writeStream [ | expr result | parser := (CurrentGrammar ifNil: [ ColaFunctionGrammar ]) parserOn: readStream. "xxx NOT REENTRANT! xxx" restartBlock := [ ^ nil]. [expr := parser next] whileTrue: [ result := expr eval. writeStream nextPutAll: result printString; cr]. ^ result "final answer is answered" ] Shell evalFile: scriptName [ | file | file := File openIfPresent: scriptName. file ifNil: [ ^ StdErr nextPutAll: scriptName printString, ' not found'. ]. self eval: file readStream to: SinkStream. file close. ] Shell evalStdIn [[ self eval: StdIn readStream to: StdOut] repeat ] "--------------------------------------------------------------------------------" { import: Object } { import: Expression } { import: Compiler } { import: CodeGenerator } { import: CodeGenerator-local } { import: Options } { import: ColaGrammar } { import: Parser } { import: ParsingExpression-printing } Grammar translate: aCompiler [ ^(Expression with: #'apply-grammar' with: self with: Shell currentParser) translate: aCompiler ] Grammar parse: aParser [ ^startRule ifTrue: [(startRule parse: aParser) ifTrue: [aParser result]] ] Grammar match: anObject [ ^startRule ifTrue: [startRule match: anObject] ] ParsingExpression match: anObject [ | parser | parser := Parser on: anObject. "StdOut nextPutAll: 'MATCH '; println: anObject." ^(self parse: parser) ifTrue: [parser result] ] "[Shell new main]"