1
0
Преглед на файлове

New ChunkParser implementation that is simple, fast and not written using PetitParser.

Göran Krampe преди 13 години
родител
ревизия
35109e4947
променени са 6 файла, в които са добавени 131 реда и са изтрити 308 реда
  1. 9 12
      js/Kernel.deploy.js
  2. 17 20
      js/Kernel.js
  3. 29 152
      js/Parser.deploy.js
  4. 18 20
      js/Parser.js
  5. 12 14
      st/Kernel.st
  6. 46 90
      st/Parser.st

+ 9 - 12
js/Kernel.deploy.js

@@ -520,7 +520,7 @@ selector: 'log:block:',
 fn: function (aString, aBlock){
 var self=this;
 var result=nil;
-smalltalk.send(smalltalk.send(aString, "__comma", [" time: "]), "__comma", [smalltalk.send(smalltalk.send((smalltalk.Date || Date), "_millisecondsToRun_", [(function(){return result=smalltalk.send(aBlock, "_value", []);})]), "_printString", [])]);
+smalltalk.send((typeof console == 'undefined' ? nil : console), "_log_", [smalltalk.send(smalltalk.send(aString, "__comma", [" time: "]), "__comma", [smalltalk.send(smalltalk.send((smalltalk.Date || Date), "_millisecondsToRun_", [(function(){return result=smalltalk.send(aBlock, "_value", []);})]), "_printString", [])])]);
 return result;
 return self;}
 }),
@@ -4489,13 +4489,10 @@ smalltalk.addMethod(
 '_scanFrom_',
 smalltalk.method({
 selector: 'scanFrom:',
-fn: function (aStream){
+fn: function (aChunkParser){
 var self=this;
-var nextChunk=nil;
-var par=nil;
-smalltalk.send(self, "_log_block_", ["nextChunk build", (function(){return par=(($receiver = smalltalk.send(self['@chunkParser'], "_emptyChunk", [])).klass === smalltalk.Number) ? $receiver /smalltalk.send(self['@chunkParser'], "_chunk", []) : smalltalk.send($receiver, "__slash", [smalltalk.send(self['@chunkParser'], "_chunk", [])]);})]);
-smalltalk.send(self, "_log_block_", ["nextChunk", (function(){return nextChunk=smalltalk.send(par, "_parse_", [aStream]);})]);
-(($receiver = smalltalk.send(nextChunk, "_isEmptyChunk", [])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){smalltalk.send(self, "_compileMethod_", [smalltalk.send(nextChunk, "_contents", [])]);return smalltalk.send(self, "_scanFrom_", [aStream]);})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){smalltalk.send(self, "_compileMethod_", [smalltalk.send(nextChunk, "_contents", [])]);return smalltalk.send(self, "_scanFrom_", [aStream]);})]);
+var chunk=nil;
+(function(){while(!(function(){chunk=smalltalk.send(aChunkParser, "_nextChunk", []);return smalltalk.send(chunk, "_isEmpty", []);})()) {(function(){return smalltalk.send(self, "_compileMethod_", [chunk]);})()}})();
 return self;}
 }),
 smalltalk.ClassCategoryReader);
@@ -4509,7 +4506,7 @@ var self=this;
 var method=nil;
 method=smalltalk.send(smalltalk.send((smalltalk.Compiler || Compiler), "_new", []), "_load_forClass_", [aString, self['@class']]);
 smalltalk.send(method, "_category_", [self['@category']]);
-smalltalk.send(self, "_log_block_", ["addCompiledMethod", (function(){return smalltalk.send(self['@class'], "_addCompiledMethod_", [method]);})]);
+smalltalk.send(self['@class'], "_addCompiledMethod_", [method]);
 return self;}
 }),
 smalltalk.ClassCategoryReader);
@@ -4891,11 +4888,11 @@ smalltalk.addMethod(
 '_scanFrom_',
 smalltalk.method({
 selector: 'scanFrom:',
-fn: function (aStream){
+fn: function (aChunkParser){
 var self=this;
-var nextChunk=nil;
-nextChunk=smalltalk.send((($receiver = smalltalk.send(self['@chunkParser'], "_emptyChunk", [])).klass === smalltalk.Number) ? $receiver /smalltalk.send(self['@chunkParser'], "_chunk", []) : smalltalk.send($receiver, "__slash", [smalltalk.send(self['@chunkParser'], "_chunk", [])]), "_parse_", [aStream]);
-(($receiver = smalltalk.send(nextChunk, "_isEmptyChunk", [])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){return smalltalk.send(self, "_setComment_", [smalltalk.send(nextChunk, "_contents", [])]);})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){return smalltalk.send(self, "_setComment_", [smalltalk.send(nextChunk, "_contents", [])]);})]);
+var chunk=nil;
+chunk=smalltalk.send(aChunkParser, "_nextChunk", []);
+(($receiver = smalltalk.send(chunk, "_isEmpty", [])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){return smalltalk.send(self, "_setComment_", [chunk]);})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){return smalltalk.send(self, "_setComment_", [chunk]);})]);
 return self;}
 }),
 smalltalk.ClassCommentReader);

+ 17 - 20
js/Kernel.js

@@ -701,11 +701,11 @@ category: 'printing',
 fn: function (aString, aBlock){
 var self=this;
 var result=nil;
-smalltalk.send(smalltalk.send(aString, "__comma", [" time: "]), "__comma", [smalltalk.send(smalltalk.send((smalltalk.Date || Date), "_millisecondsToRun_", [(function(){return result=smalltalk.send(aBlock, "_value", []);})]), "_printString", [])]);
+smalltalk.send((typeof console == 'undefined' ? nil : console), "_log_", [smalltalk.send(smalltalk.send(aString, "__comma", [" time: "]), "__comma", [smalltalk.send(smalltalk.send((smalltalk.Date || Date), "_millisecondsToRun_", [(function(){return result=smalltalk.send(aBlock, "_value", []);})]), "_printString", [])])]);
 return result;
 return self;},
-source: unescape('log%3A%20aString%20block%3A%20aBlock%0A%0A%09%7C%20result%20%7C%0A%09%22console%20log%3A%22%20%20aString%2C%20%20%27%20time%3A%20%27%2C%20%28Date%20millisecondsToRun%3A%20%5Bresult%20%3A%3D%20aBlock%20value%5D%29%20printString.%0A%09%5Eresult%0A%0A'),
-messageSends: [unescape("%2C"), "printString", "millisecondsToRun:", "value"],
+source: unescape('log%3A%20aString%20block%3A%20aBlock%0A%0A%09%7C%20result%20%7C%0A%09console%20log%3A%20%20aString%2C%20%20%27%20time%3A%20%27%2C%20%28Date%20millisecondsToRun%3A%20%5Bresult%20%3A%3D%20aBlock%20value%5D%29%20printString.%0A%09%5Eresult%0A%0A'),
+messageSends: ["log:", unescape("%2C"), "printString", "millisecondsToRun:", "value"],
 referencedClasses: [smalltalk.Date]
 }),
 smalltalk.Object);
@@ -6027,16 +6027,13 @@ smalltalk.addMethod(
 smalltalk.method({
 selector: 'scanFrom:',
 category: 'fileIn',
-fn: function (aStream){
+fn: function (aChunkParser){
 var self=this;
-var nextChunk=nil;
-var par=nil;
-smalltalk.send(self, "_log_block_", ["nextChunk build", (function(){return par=(($receiver = smalltalk.send(self['@chunkParser'], "_emptyChunk", [])).klass === smalltalk.Number) ? $receiver /smalltalk.send(self['@chunkParser'], "_chunk", []) : smalltalk.send($receiver, "__slash", [smalltalk.send(self['@chunkParser'], "_chunk", [])]);})]);
-smalltalk.send(self, "_log_block_", ["nextChunk", (function(){return nextChunk=smalltalk.send(par, "_parse_", [aStream]);})]);
-(($receiver = smalltalk.send(nextChunk, "_isEmptyChunk", [])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){smalltalk.send(self, "_compileMethod_", [smalltalk.send(nextChunk, "_contents", [])]);return smalltalk.send(self, "_scanFrom_", [aStream]);})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){smalltalk.send(self, "_compileMethod_", [smalltalk.send(nextChunk, "_contents", [])]);return smalltalk.send(self, "_scanFrom_", [aStream]);})]);
+var chunk=nil;
+(function(){while(!(function(){chunk=smalltalk.send(aChunkParser, "_nextChunk", []);return smalltalk.send(chunk, "_isEmpty", []);})()) {(function(){return smalltalk.send(self, "_compileMethod_", [chunk]);})()}})();
 return self;},
-source: unescape('scanFrom%3A%20aStream%0A%09%7C%20nextChunk%20par%20%7C%0A%09self%20log%3A%20%27nextChunk%20build%27%20block%3A%20%5Bpar%20%3A%3D%20%28chunkParser%20emptyChunk%20/%20chunkParser%20chunk%29%5D.%0A%09self%20log%3A%20%27nextChunk%27%20block%3A%20%5BnextChunk%20%3A%3D%20par%20parse%3A%20aStream%5D.%0A%09nextChunk%20isEmptyChunk%20ifFalse%3A%20%5B%0A%09%20%20%20%20self%20compileMethod%3A%20nextChunk%20contents.%0A%09%20%20%20%20self%20scanFrom%3A%20aStream%5D.'),
-messageSends: ["log:block:", unescape("/"), "emptyChunk", "chunk", "parse:", "ifFalse:", "isEmptyChunk", "compileMethod:", "contents", "scanFrom:"],
+source: unescape('scanFrom%3A%20aChunkParser%0A%09%7C%20chunk%20%7C%0A%09%5Bchunk%20%3A%3D%20aChunkParser%20nextChunk.%0A%09chunk%20isEmpty%5D%20whileFalse%3A%20%5B%0A%09%20%20%20%20self%20compileMethod%3A%20chunk%5D'),
+messageSends: ["whileFalse:", "nextChunk", "isEmpty", "compileMethod:"],
 referencedClasses: []
 }),
 smalltalk.ClassCategoryReader);
@@ -6051,10 +6048,10 @@ var self=this;
 var method=nil;
 method=smalltalk.send(smalltalk.send((smalltalk.Compiler || Compiler), "_new", []), "_load_forClass_", [aString, self['@class']]);
 smalltalk.send(method, "_category_", [self['@category']]);
-smalltalk.send(self, "_log_block_", ["addCompiledMethod", (function(){return smalltalk.send(self['@class'], "_addCompiledMethod_", [method]);})]);
+smalltalk.send(self['@class'], "_addCompiledMethod_", [method]);
 return self;},
-source: unescape('compileMethod%3A%20aString%0A%09%7C%20method%20%7C%0A%09method%20%3A%3D%20Compiler%20new%20load%3A%20aString%20forClass%3A%20class.%0A%09method%20category%3A%20category.%0A%09self%20log%3A%20%27addCompiledMethod%27%20block%3A%20%5Bclass%20addCompiledMethod%3A%20method%5D'),
-messageSends: ["load:forClass:", "new", "category:", "log:block:", "addCompiledMethod:"],
+source: unescape('compileMethod%3A%20aString%0A%09%7C%20method%20%7C%0A%09method%20%3A%3D%20Compiler%20new%20load%3A%20aString%20forClass%3A%20class.%0A%09method%20category%3A%20category.%0A%09class%20addCompiledMethod%3A%20method'),
+messageSends: ["load:forClass:", "new", "category:", "addCompiledMethod:"],
 referencedClasses: [smalltalk.Compiler]
 }),
 smalltalk.ClassCategoryReader);
@@ -6565,14 +6562,14 @@ smalltalk.addMethod(
 smalltalk.method({
 selector: 'scanFrom:',
 category: 'fileIn',
-fn: function (aStream){
+fn: function (aChunkParser){
 var self=this;
-var nextChunk=nil;
-nextChunk=smalltalk.send((($receiver = smalltalk.send(self['@chunkParser'], "_emptyChunk", [])).klass === smalltalk.Number) ? $receiver /smalltalk.send(self['@chunkParser'], "_chunk", []) : smalltalk.send($receiver, "__slash", [smalltalk.send(self['@chunkParser'], "_chunk", [])]), "_parse_", [aStream]);
-(($receiver = smalltalk.send(nextChunk, "_isEmptyChunk", [])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){return smalltalk.send(self, "_setComment_", [smalltalk.send(nextChunk, "_contents", [])]);})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){return smalltalk.send(self, "_setComment_", [smalltalk.send(nextChunk, "_contents", [])]);})]);
+var chunk=nil;
+chunk=smalltalk.send(aChunkParser, "_nextChunk", []);
+(($receiver = smalltalk.send(chunk, "_isEmpty", [])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){return smalltalk.send(self, "_setComment_", [chunk]);})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){return smalltalk.send(self, "_setComment_", [chunk]);})]);
 return self;},
-source: unescape('scanFrom%3A%20aStream%0A%09%7C%20nextChunk%20%7C%0A%09nextChunk%20%3A%3D%20%28chunkParser%20emptyChunk%20/%20chunkParser%20chunk%29%20parse%3A%20aStream.%0A%09nextChunk%20isEmptyChunk%20ifFalse%3A%20%5B%0A%09%20%20%20%20self%20setComment%3A%20nextChunk%20contents%5D.'),
-messageSends: ["parse:", unescape("/"), "emptyChunk", "chunk", "ifFalse:", "isEmptyChunk", "setComment:", "contents"],
+source: unescape('scanFrom%3A%20aChunkParser%0A%09%7C%20chunk%20%7C%0A%09chunk%20%3A%3D%20aChunkParser%20nextChunk.%0A%09chunk%20isEmpty%20ifFalse%3A%20%5B%0A%09%20%20%20%20self%20setComment%3A%20chunk%5D.'),
+messageSends: ["nextChunk", "ifFalse:", "isEmpty", "setComment:"],
 referencedClasses: []
 }),
 smalltalk.ClassCommentReader);

+ 29 - 152
js/Parser.deploy.js

@@ -126,13 +126,11 @@ smalltalk.method({
 selector: 'memoizedParse:',
 fn: function (aStream){
 var self=this;
-var r=nil;
 var start=nil;
 var end=nil;
 var node=nil;
 start=smalltalk.send(aStream, "_position", []);
-smalltalk.send(self, "_log_block_", ["memoizedParse", (function(){return r=smalltalk.send(smalltalk.send(self, "_memo", []), "_at_ifPresent_ifAbsent_", [start, (function(value){smalltalk.send(aStream, "_position_", [smalltalk.send(smalltalk.send(smalltalk.send(self, "_memo", []), "_at_", [start]), "_second", [])]);return smalltalk.send(value, "_first", []);}), (function(){node=smalltalk.send(self, "_parse_", [aStream]);end=smalltalk.send(aStream, "_position", []);smalltalk.send(smalltalk.send(self, "_memo", []), "_at_put_", [start, smalltalk.send((smalltalk.Array || Array), "_with_with_", [node, end])]);return node;})]);})]);
-return r;
+return smalltalk.send(smalltalk.send(self, "_memo", []), "_at_ifPresent_ifAbsent_", [start, (function(value){smalltalk.send(aStream, "_position_", [smalltalk.send(smalltalk.send(smalltalk.send(self, "_memo", []), "_at_", [start]), "_second", [])]);return smalltalk.send(value, "_first", []);}), (function(){node=smalltalk.send(self, "_parse_", [aStream]);end=smalltalk.send(aStream, "_position", []);smalltalk.send(smalltalk.send(self, "_memo", []), "_at_put_", [start, smalltalk.send((smalltalk.Array || Array), "_with_with_", [node, end])]);return node;})]);
 return self;}
 }),
 smalltalk.PPParser);
@@ -865,184 +863,63 @@ return self;}
 smalltalk.SmalltalkParser.klass);
 
 
-smalltalk.addClass('Chunk', smalltalk.Object, ['contents'], 'Parser');
+smalltalk.addClass('ChunkParser', smalltalk.Object, ['stream'], 'Parser');
 smalltalk.addMethod(
-'_contents',
+'_stream_',
 smalltalk.method({
-selector: 'contents',
-fn: function (){
-var self=this;
-return (($receiver = self['@contents']) == nil || $receiver == undefined) ? (function(){return "";})() : $receiver;
-return self;}
-}),
-smalltalk.Chunk);
-
-smalltalk.addMethod(
-'_contents_',
-smalltalk.method({
-selector: 'contents:',
-fn: function (aString){
-var self=this;
-self['@contents']=aString;
-return self;}
-}),
-smalltalk.Chunk);
-
-smalltalk.addMethod(
-'_isEmptyChunk',
-smalltalk.method({
-selector: 'isEmptyChunk',
-fn: function (){
-var self=this;
-return false;
-return self;}
-}),
-smalltalk.Chunk);
-
-smalltalk.addMethod(
-'_isInstructionChunk',
-smalltalk.method({
-selector: 'isInstructionChunk',
-fn: function (){
-var self=this;
-return false;
-return self;}
-}),
-smalltalk.Chunk);
-
-
-
-smalltalk.addClass('InstructionChunk', smalltalk.Chunk, [], 'Parser');
-smalltalk.addMethod(
-'_isInstructionChunk',
-smalltalk.method({
-selector: 'isInstructionChunk',
-fn: function (){
-var self=this;
-return true;
-return self;}
-}),
-smalltalk.InstructionChunk);
-
-
-
-smalltalk.addClass('EmptyChunk', smalltalk.Chunk, [], 'Parser');
-smalltalk.addMethod(
-'_isEmptyChunk',
-smalltalk.method({
-selector: 'isEmptyChunk',
-fn: function (){
-var self=this;
-return true;
-return self;}
-}),
-smalltalk.EmptyChunk);
-
-
-
-smalltalk.addClass('ChunkParser', smalltalk.Object, ['parser', 'separator', 'eof', 'ws', 'chunk', 'emptyChunk', 'instructionChunk'], 'Parser');
-smalltalk.addMethod(
-'_parser',
-smalltalk.method({
-selector: 'parser',
-fn: function (){
-var self=this;
-return (($receiver = self['@parser']) == nil || $receiver == undefined) ? (function(){return self['@parser']=(($receiver = (($receiver = (($receiver = smalltalk.send(self, "_instructionChunk", [])).klass === smalltalk.Number) ? $receiver /smalltalk.send(self, "_emptyChunk", []) : smalltalk.send($receiver, "__slash", [smalltalk.send(self, "_emptyChunk", [])])).klass === smalltalk.Number) ? $receiver /smalltalk.send(self, "_chunk", []) : smalltalk.send($receiver, "__slash", [smalltalk.send(self, "_chunk", [])])).klass === smalltalk.Number) ? $receiver /smalltalk.send(self, "_eof", []) : smalltalk.send($receiver, "__slash", [smalltalk.send(self, "_eof", [])]);})() : $receiver;
-return self;}
-}),
-smalltalk.ChunkParser);
-
-smalltalk.addMethod(
-'_eof',
-smalltalk.method({
-selector: 'eof',
-fn: function (){
-var self=this;
-return (($receiver = self['@eof']) == nil || $receiver == undefined) ? (function(){return self['@eof']=smalltalk.send(smalltalk.send(smalltalk.send(self, "_ws", []), "__comma", [smalltalk.send((smalltalk.PPEOFParser || PPEOFParser), "_new", [])]), "__eq_eq_gt", [(function(node){return nil;})]);})() : $receiver;
-return self;}
-}),
-smalltalk.ChunkParser);
-
-smalltalk.addMethod(
-'_separator',
-smalltalk.method({
-selector: 'separator',
-fn: function (){
-var self=this;
-return (($receiver = self['@separator']) == nil || $receiver == undefined) ? (function(){return self['@separator']=smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send((smalltalk.String || String), "_cr", []), "__comma", [smalltalk.send((smalltalk.String || String), "_space", [])]), "__comma", [smalltalk.send((smalltalk.String || String), "_lf", [])]), "__comma", [smalltalk.send((smalltalk.String || String), "_tab", [])]), "_asChoiceParser", []);})() : $receiver;
-return self;}
-}),
-smalltalk.ChunkParser);
-
-smalltalk.addMethod(
-'_ws',
-smalltalk.method({
-selector: 'ws',
-fn: function (){
+selector: 'stream:',
+fn: function (aStream){
 var self=this;
-return (($receiver = self['@ws']) == nil || $receiver == undefined) ? (function(){return self['@ws']=smalltalk.send(smalltalk.send(self, "_separator", []), "_star", []);})() : $receiver;
+self['@stream']=aStream;
 return self;}
 }),
 smalltalk.ChunkParser);
 
 smalltalk.addMethod(
-'_chunk',
+'_nextChunk',
 smalltalk.method({
-selector: 'chunk',
+selector: 'nextChunk',
 fn: function (){
 var self=this;
-return (($receiver = self['@chunk']) == nil || $receiver == undefined) ? (function(){return self['@chunk']=smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(self, "_ws", []), "__comma", [smalltalk.send(smalltalk.send((($receiver = smalltalk.send(unescape("%21%21"), "_asParser", [])).klass === smalltalk.Number) ? $receiver /smalltalk.send(smalltalk.send(smalltalk.send(unescape("%21"), "_asParser", []), "_not", []), "__comma", [smalltalk.send((smalltalk.PPAnyParser || PPAnyParser), "_new", [])]) : smalltalk.send($receiver, "__slash", [smalltalk.send(smalltalk.send(smalltalk.send(unescape("%21"), "_asParser", []), "_not", []), "__comma", [smalltalk.send((smalltalk.PPAnyParser || PPAnyParser), "_new", [])])]), "_plus", []), "_flatten", [])]), "__comma", [smalltalk.send(unescape("%21"), "_asParser", [])]), "__eq_eq_gt", [(function(node){return smalltalk.send(smalltalk.send((smalltalk.Chunk || Chunk), "_new", []), "_contents_", [smalltalk.send(smalltalk.send(smalltalk.send(node, "_second", []), "_replace_with_", [unescape("%21%21"), unescape("%21")]), "_trimBoth", [])]);})]);})() : $receiver;
-return self;}
+try{var char=nil;
+var result=nil;
+var chunk=nil;
+result=smalltalk.send("", "_writeStream", []);
+(function(){while((function(){char=smalltalk.send(self['@stream'], "_next", []);return smalltalk.send(char, "_notNil", []);})()) {(function(){(($receiver = smalltalk.send(char, "__eq", [unescape("%21")])).klass === smalltalk.Boolean) ? ($receiver ? (function(){return (($receiver = smalltalk.send(smalltalk.send(self['@stream'], "_peek", []), "__eq", [unescape("%21")])).klass === smalltalk.Boolean) ? ($receiver ? (function(){return smalltalk.send(self['@stream'], "_next", []);})() : (function(){return (function(){throw({name: 'stReturn', selector: '_nextChunk', fn: function(){return smalltalk.send(smalltalk.send(result, "_contents", []), "_trimBoth", [])}})})();})()) : smalltalk.send($receiver, "_ifTrue_ifFalse_", [(function(){return smalltalk.send(self['@stream'], "_next", []);}), (function(){return (function(){throw({name: 'stReturn', selector: '_nextChunk', fn: function(){return smalltalk.send(smalltalk.send(result, "_contents", []), "_trimBoth", [])}})})();})]);})() : nil) : smalltalk.send($receiver, "_ifTrue_", [(function(){return (($receiver = smalltalk.send(smalltalk.send(self['@stream'], "_peek", []), "__eq", [unescape("%21")])).klass === smalltalk.Boolean) ? ($receiver ? (function(){return smalltalk.send(self['@stream'], "_next", []);})() : (function(){return (function(){throw({name: 'stReturn', selector: '_nextChunk', fn: function(){return smalltalk.send(smalltalk.send(result, "_contents", []), "_trimBoth", [])}})})();})()) : smalltalk.send($receiver, "_ifTrue_ifFalse_", [(function(){return smalltalk.send(self['@stream'], "_next", []);}), (function(){return (function(){throw({name: 'stReturn', selector: '_nextChunk', fn: function(){return smalltalk.send(smalltalk.send(result, "_contents", []), "_trimBoth", [])}})})();})]);})]);return smalltalk.send(result, "_nextPut_", [char]);})()}})();
+(function(){throw({name: 'stReturn', selector: '_nextChunk', fn: function(){return nil}})})();
+return self;
+} catch(e) {if(e.name === 'stReturn' && e.selector === '_nextChunk'){return e.fn()} throw(e)}}
 }),
 smalltalk.ChunkParser);
 
-smalltalk.addMethod(
-'_emptyChunk',
-smalltalk.method({
-selector: 'emptyChunk',
-fn: function (){
-var self=this;
-return (($receiver = self['@emptyChunk']) == nil || $receiver == undefined) ? (function(){return self['@emptyChunk']=smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(self, "_separator", []), "_plus", []), "__comma", [smalltalk.send(unescape("%21"), "_asParser", [])]), "__comma", [smalltalk.send(self, "_ws", [])]), "__eq_eq_gt", [(function(node){return smalltalk.send((smalltalk.EmptyChunk || EmptyChunk), "_new", []);})]);})() : $receiver;
-return self;}
-}),
-smalltalk.ChunkParser);
 
 smalltalk.addMethod(
-'_instructionChunk',
+'_on_',
 smalltalk.method({
-selector: 'instructionChunk',
-fn: function (){
+selector: 'on:',
+fn: function (aStream){
 var self=this;
-return (($receiver = self['@instructionChunk']) == nil || $receiver == undefined) ? (function(){return self['@instructionChunk']=smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(self, "_ws", []), "__comma", [smalltalk.send(unescape("%21"), "_asParser", [])]), "__comma", [smalltalk.send(self, "_chunk", [])]), "__eq_eq_gt", [(function(node){return smalltalk.send(smalltalk.send((smalltalk.InstructionChunk || InstructionChunk), "_new", []), "_contents_", [smalltalk.send(smalltalk.send(node, "_last", []), "_contents", [])]);})]);})() : $receiver;
+return smalltalk.send(smalltalk.send(self, "_new", []), "_stream_", [aStream]);
 return self;}
 }),
-smalltalk.ChunkParser);
+smalltalk.ChunkParser.klass);
 
 
-
-smalltalk.addClass('Importer', smalltalk.Object, ['chunkParser'], 'Parser');
-smalltalk.addMethod(
-'_chunkParser',
-smalltalk.method({
-selector: 'chunkParser',
-fn: function (){
-var self=this;
-return (($receiver = self['@chunkParser']) == nil || $receiver == undefined) ? (function(){return self['@chunkParser']=smalltalk.send(smalltalk.send((smalltalk.ChunkParser || ChunkParser), "_new", []), "_parser", []);})() : $receiver;
-return self;}
-}),
-smalltalk.Importer);
-
+smalltalk.addClass('Importer', smalltalk.Object, [], 'Parser');
 smalltalk.addMethod(
 '_import_',
 smalltalk.method({
 selector: 'import:',
 fn: function (aStream){
 var self=this;
-try{var nextChunk=nil;
+var chunk=nil;
 var result=nil;
-(function(){while(!(function(){return smalltalk.send(aStream, "_atEnd", []);})()) {(function(){nextChunk=smalltalk.send(smalltalk.send(self, "_chunkParser", []), "_parse_", [aStream]);(($receiver = nextChunk) == nil || $receiver == undefined) ? (function(){return (function(){throw({name: 'stReturn', selector: '_import_', fn: function(){return self}})})();})() : $receiver;result=smalltalk.send(smalltalk.send((smalltalk.Compiler || Compiler), "_new", []), "_loadExpression_", [smalltalk.send(nextChunk, "_contents", [])]);return (($receiver = smalltalk.send(nextChunk, "_isInstructionChunk", [])).klass === smalltalk.Boolean) ? ($receiver ? (function(){return smalltalk.send(result, "_scanFrom_", [aStream]);})() : nil) : smalltalk.send($receiver, "_ifTrue_", [(function(){return smalltalk.send(result, "_scanFrom_", [aStream]);})]);})()}})();
-return self;
-} catch(e) {if(e.name === 'stReturn' && e.selector === '_import_'){return e.fn()} throw(e)}}
+var parser=nil;
+var lastEmpty=nil;
+parser=smalltalk.send((smalltalk.ChunkParser || ChunkParser), "_on_", [aStream]);
+lastEmpty=false;
+(function(){while(!(function(){chunk=smalltalk.send(parser, "_nextChunk", []);return smalltalk.send(chunk, "_isNil", []);})()) {(function(){return (($receiver = smalltalk.send(chunk, "_isEmpty", [])).klass === smalltalk.Boolean) ? ($receiver ? (function(){return lastEmpty=true;})() : (function(){result=smalltalk.send(smalltalk.send((smalltalk.Compiler || Compiler), "_new", []), "_loadExpression_", [chunk]);return (($receiver = lastEmpty).klass === smalltalk.Boolean) ? ($receiver ? (function(){lastEmpty=false;return smalltalk.send(result, "_scanFrom_", [parser]);})() : nil) : smalltalk.send($receiver, "_ifTrue_", [(function(){lastEmpty=false;return smalltalk.send(result, "_scanFrom_", [parser]);})]);})()) : smalltalk.send($receiver, "_ifTrue_ifFalse_", [(function(){return lastEmpty=true;}), (function(){result=smalltalk.send(smalltalk.send((smalltalk.Compiler || Compiler), "_new", []), "_loadExpression_", [chunk]);return (($receiver = lastEmpty).klass === smalltalk.Boolean) ? ($receiver ? (function(){lastEmpty=false;return smalltalk.send(result, "_scanFrom_", [parser]);})() : nil) : smalltalk.send($receiver, "_ifTrue_", [(function(){lastEmpty=false;return smalltalk.send(result, "_scanFrom_", [parser]);})]);})]);})()}})();
+return self;}
 }),
 smalltalk.Importer);
 

Файловите разлики са ограничени, защото са твърде много
+ 18 - 20
js/Parser.js


+ 12 - 14
st/Kernel.st

@@ -170,7 +170,7 @@ printNl
 log: aString block: aBlock
 
 	| result |
-	"console log:"  aString,  ' time: ', (Date millisecondsToRun: [result := aBlock value]) printString.
+	console log:  aString,  ' time: ', (Date millisecondsToRun: [result := aBlock value]) printString.
 	^result
 ! !
 
@@ -2164,13 +2164,11 @@ class: aClass category: aString
 
 !ClassCategoryReader methodsFor: 'fileIn'!
 
-scanFrom: aStream
-	| nextChunk par |
-	self log: 'nextChunk build' block: [par := (chunkParser emptyChunk / chunkParser chunk)].
-	self log: 'nextChunk' block: [nextChunk := par parse: aStream].
-	nextChunk isEmptyChunk ifFalse: [
-	    self compileMethod: nextChunk contents.
-	    self scanFrom: aStream].
+scanFrom: aChunkParser
+	| chunk |
+	[chunk := aChunkParser nextChunk.
+	chunk isEmpty] whileFalse: [
+	    self compileMethod: chunk]
 ! !
 
 !ClassCategoryReader methodsFor: 'initialization'!
@@ -2186,7 +2184,7 @@ compileMethod: aString
 	| method |
 	method := Compiler new load: aString forClass: class.
 	method category: category.
-	self log: 'addCompiledMethod' block: [class addCompiledMethod: method]
+	class addCompiledMethod: method
 ! !
 
 Object subclass: #Stream
@@ -2377,11 +2375,11 @@ class: aClass
 
 !ClassCommentReader methodsFor: 'fileIn'!
 
-scanFrom: aStream
-	| nextChunk |
-	nextChunk := (chunkParser emptyChunk / chunkParser chunk) parse: aStream.
-	nextChunk isEmptyChunk ifFalse: [
-	    self setComment: nextChunk contents].
+scanFrom: aChunkParser
+	| chunk |
+	chunk := aChunkParser nextChunk.
+	chunk isEmpty ifFalse: [
+	    self setComment: chunk].
 ! !
 
 !ClassCommentReader methodsFor: 'initialization'!

+ 46 - 90
st/Parser.st

@@ -53,9 +53,9 @@ optional
 !
 
 memoizedParse: aStream
-	| r start end node |
+	| start end node |
 	start := aStream position.
-        self log: 'memoizedParse' block: [r := self memo at: start 
+       ^self memo at: start 
 	    ifPresent: [:value |
 		aStream position: (self memo at: start) second.
 		value first]
@@ -63,8 +63,7 @@ memoizedParse: aStream
 		node := self parse: aStream.
 		end := aStream position.
 		self memo at: start put: (Array with: node with: end).
-		node]].
-	^r
+		node]
 ! !
 
 !PPParser methodsFor: 'parsing'!
@@ -533,7 +532,7 @@ parser
 		    node second do: [:each | result add: each].
 		    result].
 
-	assignment := reference, ws, ':=' asParser, ws, expression
+	assignment := variable, ws, ':=' asParser, ws, expression
 		==> [:node | AssignmentNode new left: node first; right: (node at: 5)].
 
 	ret := '^' asParser, ws, expression, ws, '.' asParser optional
@@ -654,110 +653,67 @@ parse: aStream
 		parse: aStream
 ! !
 
-Object subclass: #Chunk
-	instanceVariableNames: 'contents'
-	category: 'Parser'!
-
-!Chunk methodsFor: 'accessing'!
-
-contents
-	^contents ifNil: ['']
-!
-
-contents: aString
-	contents := aString
-! !
-
-!Chunk methodsFor: 'testing'!
-
-isEmptyChunk
-	^false
-!
-
-isInstructionChunk
-	^false
-! !
-
-Chunk subclass: #InstructionChunk
-	instanceVariableNames: ''
-	category: 'Parser'!
-
-!InstructionChunk methodsFor: 'testing'!
-
-isInstructionChunk
-	^true
-! !
-
-Chunk subclass: #EmptyChunk
-	instanceVariableNames: ''
-	category: 'Parser'!
-
-!EmptyChunk methodsFor: 'testing'!
-
-isEmptyChunk
-	^true
-! !
-
 Object subclass: #ChunkParser
-	instanceVariableNames: 'parser separator eof ws chunk emptyChunk instructionChunk'
+	instanceVariableNames: 'stream'
 	category: 'Parser'!
 
-!ChunkParser methodsFor: ''!
+!ChunkParser methodsFor: 'accessing'!
 
-instructionChunk
-	^instructionChunk ifNil: [
-	    instructionChunk := self ws, '!!' asParser, self chunk
-	    ==> [:node | InstructionChunk new contents: node last contents]]
+stream: aStream
+	stream := aStream
 ! !
 
-!ChunkParser methodsFor: 'accessing'!
-
-parser
-	^parser ifNil: [
-	    parser := self instructionChunk / self emptyChunk / self chunk / self eof]
-!
+!ChunkParser methodsFor: 'reading'!
 
-eof
-	^eof ifNil: [eof := self ws, PPEOFParser new ==> [:node | nil]]
-!
+nextChunk
+	"The chunk format (Smalltalk Interchange Format or Fileout format)
+	is a trivial format but can be a bit tricky to understand:
+		- Uses the exclamation mark as delimiter of chunks.
+		- Inside a chunk a normal exclamation mark must be doubled.
+		- A non empty chunk must be a valid Smalltalk expression.
+		- A chunk on top level with a preceding empty chunk is an instruction chunk:
+			- The object created by the expression then takes over reading chunks.
 
-separator
-	^separator ifNil: [separator := (String cr, String space, String lf, String tab) asChoiceParser]
-!
+	This metod returns next chunk as a String (trimmed), empty String (all whitespace) or nil."
 
-ws
-	^ws ifNil: [ws := self separator star]
-!
+	| char result chunk |
+	result := '' writeStream.
+        [char := stream next.
+        char notNil] whileTrue: [
+                 char = '!!' ifTrue: [
+                         stream peek = '!!'
+                                ifTrue: [stream next "skipping the escape double"]
+                                ifFalse: [^result contents trimBoth  "chunk end marker found"]].
+                 result nextPut: char].
+	^nil "a chunk needs to end with !!"
+! !
 
-chunk
-	^chunk ifNil: [chunk := self ws, ('!!!!' asParser / ('!!' asParser not, PPAnyParser new)) plus flatten, '!!' asParser
-		==> [:node | Chunk new contents: (node second replace: '!!!!' with: '!!') trimBoth]]
-!
+!ChunkParser class methodsFor: 'not yet classified'!
 
-emptyChunk
-	^emptyChunk ifNil: [emptyChunk := self separator plus, '!!' asParser, self ws ==> [:node | EmptyChunk new]]
+on: aStream
+	^self new stream: aStream
 ! !
 
 Object subclass: #Importer
-	instanceVariableNames: 'chunkParser'
+	instanceVariableNames: ''
 	category: 'Parser'!
 
-!Importer methodsFor: 'accessing'!
-
-chunkParser
-	^chunkParser ifNil: [chunkParser := ChunkParser new parser]
-! !
-
 !Importer methodsFor: 'fileIn'!
 
 import: aStream
-    | nextChunk result |
-    [aStream atEnd] whileFalse: [
-        nextChunk := self chunkParser parse: aStream.
-        nextChunk ifNil: [^self].
-        result := Compiler new loadExpression: nextChunk contents.
-        nextChunk isInstructionChunk 
-            ifTrue: [result scanFrom: aStream]]
+    | chunk result parser lastEmpty |
+    parser := ChunkParser on: aStream.
+    lastEmpty := false.
+    [chunk := parser nextChunk.
+     chunk isNil] whileFalse: [
+        chunk isEmpty
+       		ifTrue: [lastEmpty := true]
+       		ifFalse: [
+        		result := Compiler new loadExpression: chunk.
+        		lastEmpty 
+            			ifTrue: [
+                                  	lastEmpty := false.
+                                  	result scanFrom: parser]]]
 ! !
 
 Object subclass: #Exporter

Някои файлове не бяха показани, защото твърде много файлове са промени