1 / 20

95.3002

95.3002. Feedback from Assignment 1. 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.

Download Presentation

95.3002

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 95.3002 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: aStreamaStream << label storeString; << ': '; << symbol storeString So we can tell if it’s a string or a symbol When printed as part of a tree printOn: aStreamtabs: amountaStreamcr.amount timesRepeat: [aStream << ' '].self printOn: aStream

  5. What Proves Useful For Debugging • Having tokens and trees be able to print themselves. In Tree printOn: aStreamself printOn: aStream tabs: 0 printOn: aStreamtabs: amountaStreamcr.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 hadpair (#'' 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 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]]. At the start of the loop, say “self log”. Then comment it out when you don’t want it anymore 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 + anObjectanObjectisCharacterifFalse: [^self, anObject].^self, anObjectasString

  9. Other Things • To pop the stacks, you had use a loop to execute tokenStackremoveLast tableNumberStackremoveLast treeStackremoveLast • There is a “removeIndex: index” but that’s clumsy… In OrderedCollection aCollectionremoveIndexFrom: left to: right (no looping) removeIndexFrom: start to: endend 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 followSetaddIfAbsent: 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 = aStateclassifFalse: [^false].(self builderStates1 includesAllIdentical: aState builderStates1) ifFalse: [^false].(self builderStates2 includesAllIdentical: aState builderStates2) ifFalse: [^false]. self builderStates1 size = aState builderStates1 sizeifFalse: [^false]. self builderStates2 size = aState builderStates2 sizeifFalse: [^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 anObjectperform: anAction anObjectperform: anActionwith: p1 anObjectperform: anActionwith: p1 with: p2 anObjectperform: anActionwith: p1 with: p2 with: p3 • But more generally, it’s anObjectperform: anActionwithArguments: 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: 2 5 66) • 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 -> '0123456789'+. Attribute -> ('stack' | "noStack") OR Number -> "0123456789"+. 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 youwant 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)]

More Related