Presentation is loading. Please wait.

Presentation is loading. Please wait.

Feedback from Assignment 1

Similar presentations


Presentation on theme: "Feedback from Assignment 1"— Presentation transcript:

1 Feedback from Assignment 1
Feedback from Assignment 1

2 Name one thing that finds bugs early
Making sure that the “run” or “execute” method for all tables that search have an error message at the end if the search fails to find anything. Readahead and ScannerReadahead self error: 'Syntax or unexpected char error' Readback and Reduce self error: 'Note to implementor: should not happen'

3 What Else Proves Useful For Debugging
Having tokens and trees be able to print themselves. But note x := #ABC. x := 'ABC'. aStream << x Puts just ABC into the stream x storeString Retrieves either OR #ABC 'ABC'

4 What Proves Useful For Debugging
Having tokens and trees be able to print themselves. In Token This way, we can tell if the label is a string or a symbol (it matters since #abc = 'abc' is false) printOn: aStream aStream << label storeString; << ': '; << symbol storeString So we can tell if it’s a string or a symbol When printed as part of a tree printOn: aStream tabs: amount aStream cr. amount timesRepeat: [aStream << ' ']. self printOn: aStream

5 What Proves Useful For Debugging
Having tokens and trees be able to print themselves. In Tree printOn: aStream self printOn: aStream tabs: 0 printOn: aStream tabs: amount aStream cr. amount timesRepeat: [aStream << ' ']. aStream << label storeString. children do: [:child | child printOn: aStream tabs: amount + 1]

6 Where It Might Have Helped You
You had to initialize the 3 parser stacks with something like empty string tokenStack: Token new label: ''; symbol: nil tableNumberStack: 1 Why? Because a readback table at some point will refer to it as a pair ('' 1). treeStack: nil Since all your labels are TYPICALLY stored as symbols, this could have impacted you. '' is not equal to #'' We could have had pair (#'' 1) in the readback table instead of pair ('' 1). Should we change the tables?

7 What I Added To Debug Your Code
In Parser: for use in the loop that executes the tables At the start of the loop, say “self log”. Then comment it out when you don’t want it anymore log | table | table := tables at: tableNumber. Transcript cr; << scanner peekToken; << ' Table '; << tableNumber; space; << table; << ' | '; << left; << ' '; << right; << ' |'. table class = ReadaheadTable ifTrue: [Transcript << ' SEARCHING FOR '; << self peek label]. table class = ReadbackTable ifTrue: [Transcript << ' SEARCHING FOR '; << (Array with: (tokenStack at: left - 1) label with: (tableNumberStack at: left - 1))]. table class = ReduceTable ifTrue: [Transcript space; << table nonterminal; << ‘SEARCHING FOR '; << (tableNumberStack at: left - 1]. table class = ShiftBackTable ifTrue: [Transcript << ' SHIFT '; << table shiftAmount]. (table class = SemanticTable and: [table action == #buildTree:]) ifTrue: [ Transcript space; << table action. table parameters do: [:parameter | Transcript space; << parameter]]. This doesn’t print everything but it’s useful It also beats putting print statements all over the place and having to remove them after.

8 What Else Proves Useful
Make sure you use collect:, select:, and collect:when: whenever you can.  simpler code Smalltalk uses the operator “,” for string concatenation and you’re used to “+”. Also, it doesn’t allow concatenating with a character (only a string) In String + anObject anObject isCharacter ifFalse: [^self, anObject]. ^self, anObject asString

9 aCollection removeIndexFrom: left to: right
Other Things To pop the stacks, you had use a loop to execute tokenStack removeLast tableNumberStack removeLast treeStack removeLast There is a “removeIndex: index” but that’s clumsy… In OrderedCollection aCollection removeIndexFrom: left to: right (no looping) removeIndexFrom: start to: end end to: start by: -1 do: [:index | removeIndex: index]

10 When Adding To A Collection
If you don’t want duplicates, you can use But you can’t tell if it did add it or not. addIfAbsent: anObject addIfIdenticalAbsent: anObject addAllIfAbsent: aCollectionOfObjects addAllIfIdenticalAbsent: aCollectionOfObjects If you want to retrieve the object there, you can use  0 if not there 1 or more if there indexOf: anObject indexOfIdentical: anObject But then you have to fetch it with “collection at: index” These can be used when constructing a state successor and asking if it’s there already… but it’s clumsy.

11 Adding More Convenient Add Methods
In OrderedCollection addIfAbsentReturningObject: object | index | index := self indexOf: object. Index > 0 ifTrue: [^self at: index]. self add: object. ^object You might also want addIfIdenticalAbsentReturningObject addIfAbsent: object ifAdded: aBlock | index | index := self indexOf: object. Index > 0 ifTrue: [^self at: index]. self add: object. aBlock value. ^object You might also want addAllIfAbsent: collection ifAdded: aBlock followSet addIfAbsent: element ifAdded: [keepLooping := true]

12 What’s Useful For Building |, -, and & FSMs
A state with instance variables builderStates1 builderState2 Implement an “=” that addIfAbsent: will use. = aState self class = aState class ifFalse: [^false]. (self builderStates1 includesAllIdentical: aState builderStates1) ifFalse: [^false]. (self builderStates2 includesAllIdentical: aState builderStates2) ifFalse: [^false]. self builderStates1 size = aState builderStates1 size ifFalse: [^false]. self builderStates2 size = aState builderStates2 size ifFalse: [^false]. ^true

13 When Building FSMs and Accumulating States
currentState := 1. states add: initialState. [currentState <= states size] whileTrue: [ state := states at: currentState. “Process state which adds more..” currentState := currentState + 1. ] states add: initialState. states do: [:state | “Process state which adds more..” ] Allowed to grow while you iterate

14 What if anything might we have forgotten?
To execute a semantic action, we needed to know that we can say anObject perform: anAction anObject perform: anAction with: p1 anObject perform: anAction with: p1 with: p2 anObject perform: anAction with: p1 with: p2 with: p3 But more generally, it’s anObject perform: anAction withArguments: aCollection

15 What Did We Need for Semantic Tables
The tables give you the general case... (SemanticTable 115 buildTree: walkOneOrMore: 64) (SemanticTable 116 indent 65) (SemanticTable 116 flipTreeFrom:to: ) My mistake for not having one in the sample grammars; e.g., like #indent #indent [] #flipTreeFrom:to: [2 5] But note that you wouldn’t see such semantic tables until you could generate the tables yourself. The existing grammar doesn’t use one.

16 Might We Have Forgotten About Scanner Grammars
They are not quite the same as parser grammars. Why not? Scanner grammars use noStack, read, keep There are NO transitions without attributes Parser grammars use stack, read, noNode There is also something more important See next slide

17 Scanner Grammars Versus Parser Grammars
Number -> ' '+. Attribute -> ('stack' | "noStack") OR Number -> " "+. Single quoted string (called Characters) Double quotes string (called String) For a scanner grammar: there is a $0 transitions, $1 transitions, $2 transitions, etc When you create FSMs for the right parts, you’ll see that they have hundreds of transitions For a parser grammar: there is only a Characters transition, or a String transition

18 Anything Else? ?

19 A Few Other Collection looping facilities are also Useful
aCollection1 with: aCollection2 do: [:oldState1 :newState2 | ... For example, if you duplicate a set of states and you want to duplicate transitions that used to go to old states but now need to go to new states... aCollection1 indexedDo: [:index :object | ... For example, if you need to do something special with the first state; e.g., index = 1

20 You could add a method to facilitate “closures”
closureUsing: aCollectionReturningBlock "self closureUsing: [:object | The last thing computed by your block must be 'a collection of other objects to add to the closure']" "Note: makes use of = for your objects indirectly via addAllIfAbsent: and returns the resulting collection." self do: [:object | self addAllIfAbsent: (aCollectionReturningBlock value: object)] identityClosureUsing: aCollectionReturningBlock "self closureUsing: [:object | The last thing computed by your block must be 'a collection of other objects to add to the closure']" "Note: makes use of == for your objects indirectly via addAllIfIdenticalAbsent: and returns the resulting collection." self do: [:object | self addAllIfIdenticalAbsent: (aCollectionReturningBlock value: object)]


Download ppt "Feedback from Assignment 1"

Similar presentations


Ads by Google