Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assignment 3 - Ellen Hui and Mauricio Molina (Team #5) #4

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
88dca9a
specify original picobot grammar
ellenfkh Sep 23, 2014
70cdd25
updated design.txt
mmauricio11235 Sep 24, 2014
723afc6
specified grammar for our DSL
ellenfkh Sep 24, 2014
3b00bb2
fixing whitespace, because my editor is strict :(
ellenfkh Sep 24, 2014
90ccc83
current copy of code. Requires more work
mmauricio11235 Sep 26, 2014
d08db45
update evaluation.txt
ellenfkh Sep 27, 2014
57252e0
doing some more implementations, still not compiling
ellenfkh Sep 27, 2014
89eaf31
Compiles now, but requires testing
mmauricio11235 Sep 27, 2014
a7f4819
compiling but not running. make an empty-room implementation using dsl
ellenfkh Sep 27, 2014
9a2c33b
add .swp files to .gitignore
ellenfkh Sep 27, 2014
de923e8
add StayHere, cleanup comments
ellenfkh Sep 27, 2014
0ea9018
This version goes through all defined rules
mmauricio11235 Sep 27, 2014
f074062
added print statements to find errors
mmauricio11235 Sep 27, 2014
f917209
remove whitespace
ellenfkh Sep 27, 2014
d11b85f
move everything out of myState
ellenfkh Sep 27, 2014
81ca130
clean up
ellenfkh Sep 27, 2014
4dbbbb2
merge master changes
ellenfkh Sep 27, 2014
d37f861
stuck on state 5???
ellenfkh Sep 27, 2014
fa5636f
still having probrems
ellenfkh Sep 28, 2014
86688af
it's working! get rid of mystate, map directly from state name to State
ellenfkh Sep 28, 2014
1a03b73
write maze using dsl, clean up some other stuff
ellenfkh Sep 28, 2014
b77363d
rename empty/maze files
ellenfkh Sep 28, 2014
856c890
Completed evaluation.txt and grammar-actual.txt
mmauricio11235 Sep 28, 2014
caad8ca
merge eval and grammar
ellenfkh Sep 28, 2014
ae62f9c
add comments
ellenfkh Sep 28, 2014
db76868
Merge branch 'master' of https://github.com/hmc-cs111-fall2014/piconot
ellenfkh Oct 11, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ target
.classpath
.history
.project
*.swp
20 changes: 20 additions & 0 deletions design.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
Who is the target for this design, e.g., are you assuming any knowledge on the
part of the language users?

Beginner Programmers: Assuming they understand loops and states.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your final syntax doesn't appear to have any explicit looping constructs. When you say that you assume a knowledge of loops, do you mean that you expect the user to understand that the rules are applied repetitively?


Why did you choose this design, i.e., why did you think it would be a good idea
for users to express the maze-searching computation using this syntax?

A bit more readable, but also still gets the same goal of teaching loops and states.
Same number of rules, just more organized and clear.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're a little confused about your goals for your syntax. In the first question, you say that you assume an understanding of loops and states, but here you state that your goal is to teach those concepts.

That said, the idea of providing more organization and clarity to the rules makes tons of sense!


What behaviors are easier to express in your design than in Picobot’s original
design? If there are no such behaviors, why not?

All of them are easier to express. The syntax alone makes it obvious
what each input means/does.

What behaviors are more difficult to express in your design than in Picobot’s
original design? If there are no such behaviors, why not?

Ideally, nothing would be more difficult. Same functionality in the end,
just more readable.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the very least, your syntax is more verbose, so at least the process of typing out rules could be more difficult with your syntax.

On a scale of 1–10 (where 10 is “very different”), how different is your syntax
from PicoBot’s original design?

4: For every line of picobot code, there exists an equivalent line of code for our
implementation, so it's not too different.

Is there anything you don’t like about your design?

Makes the code more verbose. Overall file will be longer, doesn't add any
power to individual rules. You'd basically be writing Picobot code in this
implementation with syntactic sugar.

57 changes: 57 additions & 0 deletions evaluation.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Names: Ellen Hui and Mauricio Molina
Date: September 28, 2014
Domain Specific Languages
Professor Ben





- New syntax for defining picobot code

We decided to change the syntax for the inner declarations from

surroundedBy "NExx" then move "W" newState "confused"

and instead merge then move into thenDo, and also remove the newState keyword
(instead adding the new state argument into the thenDo call). This also
necessitated adding parentheses, now that we have two arguments to thenDo, so w
figured we should give surroundedBy parentheses as well, for consistency.

surroundedBy("NExx") thenMove("W", "confused")

although not as clean and clear about what they're doing, it allows for a conditional structure rule creation.

inState("StateName"){ if inState("StateName"){
surroundedBy("NExx") { if(surroundedBy(Surroundings)){
thenMove("W", "confused") thenMove(Direction, newState)
} }
} }



Originally started with a myState class that would hold all the information about a state
under our implementation and handle creation of rules defined by the user. However
we ended up finding scoping issues where we could not execute code in the way that we wanted.
We attempted passing units of code through 3 methods to get it to our myClass constructor, but
ended up losing that code while passing. The solution ended up being to get rid of the myState class entirely
and simply mapped from string name to state.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good simplification. As you mention, it makes the syntax slightly less ideal-looking, but it all comes to the idea of trading off between ease of implementation and ease of use.




- Allowing user to user string names instead of requiring numbers

We mapped the string class names given by user to states using a map. While the user will use the state name they gave,
we are still using number values to define states. It is hidden from the user.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a cool improvement that makes it easier for the user to build their mental model right into the text of a program.



- On a scale of 1-10, how much would you say you changed your syntax?

We'd say we changed 3. The biggest changes were adding curly braces and parenthesis, and combining then and move into
one keyword.

- On a scale of 1-10, how difficult was it to map your syntax to semantics?

About a 6. Our biggest challenge was finding the correct architecture to hold and create rules.
A big challenge was learning the limitations of scala. In the end, our solution ended up making
our code more readable and easier to follow.
55 changes: 55 additions & 0 deletions grammar-actual.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Names: Ellen Hui and Mauricio Molina
Date: September 28, 2014
Domain Specific Languages
Professor Ben

digit = "0" | nonzero_digit ;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is nonzero_digit? You don't appear to have defined it.


upper = "A" | "B" | "C" | "D" | "E" | "F" | "G"
| "H" | "I" | "J" | "K" | "L" | "M" | "N"
| "O" | "P" | "Q" | "R" | "S" | "T" | "U"
| "V" | "W" | "X" | "Y" | "Z" ;

lower = "a" | "b" | "c" | "d" | "e" | "f" | "g"
| "h" | "i" | "j" | "k" | "l" | "m" | "n"
| "o" | "p" | "q" | "r" | "s" | "t" | "u"
| "v" | "w" | "x" | "y" | "z" ;

char = digit | upper | lower


quote = '"' ;
state = quote, char, {char}, quote ;


(*
Each direction can be a wall, "x" for nothing there, or "*" for not there.
The full surroundings of the picobot is composed of all four directions.
*)
symbol = "x" | "*" ;
north = "N" | symbol ;
east = "E" | symbol ;
west = "W" | symbol ;
south = "S" | symbol ;
surroundings = quote, north, east, west, south, quote ;

(*
Direction to move in is one of NEWS or "X" for don't move.
*)
_move_direction = "N" | "E" | "W" | "S" | "X" ;
move_direction = quote _move_direction quote ;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use parentheses for grouping, you could combine these two rules into one.


semi = ";"

(*
// what it would look like:

inState("goingWest") {
surroundedBy("N*x*") {thenMove("W", "goingWest")}
surroundedBy("x***") {thenMove("N", "goingNorth")}
surroundedBy("N*W*") {thenMove("X", "goingSouth")}
}
*)
case = "surroundedBy ", "(" , surroundings, ")", "{" , thenMove ", "(" , moveDirection, " newState ", state, ")", "}", semi, "\n";
rule = "inState ", "(" , state, ")", {\n", case, {case}, "};"
actual_grammar = {rule}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As Prof. Ben mentioned in class, the grammar represents everything that someone would have to write in order to create a program. With that in mind, it would probably be good to include things like indentation, imports, and the "object ... extends .." syntax in the grammar.

51 changes: 51 additions & 0 deletions grammar-ideal.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
digit = "0" | nonzero_digit ;

upper = "A" | "B" | "C" | "D" | "E" | "F" | "G"
| "H" | "I" | "J" | "K" | "L" | "M" | "N"
| "O" | "P" | "Q" | "R" | "S" | "T" | "U"
| "V" | "W" | "X" | "Y" | "Z" ;

lower = "a" | "b" | "c" | "d" | "e" | "f" | "g"
| "h" | "i" | "j" | "k" | "l" | "m" | "n"
| "o" | "p" | "q" | "r" | "s" | "t" | "u"
| "v" | "w" | "x" | "y" | "z" ;

char = digit | upper | lower


quote = '"' ;
state = quote, char, {char}, quote ;


(*
Each direction can be a wall, "x" for nothing there, or "*" for not there.
The full surroundings of the picobot is composed of all four directions.
*)
symbol = "x" | "*" ;
north = "N" | symbol ;
east = "E" | symbol ;
west = "W" | symbol ;
south = "S" | symbol ;
surroundings = quote, north, east, west, south, quote ;

(*
Direction to move in is one of NEWS or "X" for don't move.
*)
_move_direction = "N" | "E" | "W" | "S" | "X" ;
move_direction = quote _move_direction quote ;

semi = ";"

(*
// what it would look like:

inState "stuckOnLeft" {
surroundedBy "NExx" then move "W" newState "confused" ;
surroundedBy "Nxxx" then move "W" newState "confused" ;
surroundedBy "xxxx" then move "W" newState "notConfused" ;
};

*)
case = "surroundedBy ", surroundings, " then move ", moveDirection, " newState ", state, semi, "\n";
rule = "inState ", state, " {\n", case, {case}, "};"
ideal_grammar = {rule}
36 changes: 36 additions & 0 deletions grammar-orig.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
nonzero_digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
digit = "0" | nonzero_digit ;

(*
State is can be two-digit (nonzero, can be zero) or single-digit (including
zero)
*)
state = nonzero_digit, digit | digit ;

(*
Each direction can be a wall, "x" for nothing there, or "*" for not there.
The full surroundings of the picobot is composed of all four directions.
*)
symbol = "x" | "*" ;
north = "N" | symbol ;
east = "E" | symbol ;
west = "W" | symbol ;
south = "S" | symbol ;
surroundings = north, east, west, south ;

(*
Direction to move in is one of NEWS or "X" for don't move.
*)
move_direction = "N" | "E" | "W" | "S" | "X" ;

(*
Parser uses space to separate pieces of the rule, so we need this.
*)
space = " " ;
arrow = space, "->", space;

(*
Compose everything!
*)
rule = state, space, surroundings, arrow, move_direction, space, state ;
picobot_grammar = {rule} ;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your grammar needs some concept of a newline, or else it looks like everything would end up on one line.

128 changes: 128 additions & 0 deletions src/main/scala/piconot/DSLImplementation.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package piconot

import java.io.File
import picolib.maze.Maze
import picolib.semantics.Anything
import picolib.semantics.Blocked
import picolib.semantics.East
import picolib.semantics.GUIDisplay
import picolib.semantics.MoveDirection
import picolib.semantics.North
import picolib.semantics.Open
import picolib.semantics.Picobot
import picolib.semantics.RelativeDescription
import picolib.semantics.Rule
import picolib.semantics.South
import picolib.semantics.State
import picolib.semantics.StayHere
import picolib.semantics.Surroundings
import picolib.semantics.TextDisplay
import picolib.semantics.West
import scalafx.application.JFXApp

object DSLImplementation {
var globalRules:List[Rule] = List()

/**
* Global number will keep track of the number of states there are
*/
var numberOfStates = -1

var stringToStateMap: Map[String, State] = Map[String, State]()

// Make a Rule and add to list of global rules. All arguments should already
// be converted into picolib.semantics objects.
def createRule(currentState: State,
surroundings: Surroundings,
direction: MoveDirection,
newState: State) {

globalRules = globalRules ::: List(Rule(currentState, surroundings, direction,
newState))
}

// Initial State
var currentState:State = new State("0");

// Increment global state number (must be unique State <-> number)
def nextStateNum():String = {
numberOfStates += 1
return numberOfStates.toString()
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great use of the parentheses for a function with side effects!


// Creates a new state from state name and rules
def inState(newState: => String)(rules: => Unit) {
// Check to see if we already made this state
if (stringToStateMap.contains(newState) ) {
currentState = stringToStateMap(newState)
} else {
currentState = State(nextStateNum)
stringToStateMap += newState -> currentState
}
// Parse rules for this state
rules
}

// Variables for rules to fill in
var surr: Surroundings = Surroundings(Anything, Anything, Anything, Anything)
var direc: MoveDirection = North
var nextS: State = State("0")

// Parse the surroundings
def surroundedBy(surroundings: String)(x: => Unit) = {

// Helper to map from chars to semantics.RelativeDescription
def charToSurr(x:Char):RelativeDescription = {
x match {
case close:Char if "NEWS".contains(close) => Blocked
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clever use of string contains!

case 'x' => Open
case '*' => Anything
}
}

// Make the Surroundings object
val tmp = surroundings.toList.map(y => charToSurr(y))
val semanticSurroundings = Surroundings(tmp(0), tmp(1), tmp(2), tmp(3))
surr = semanticSurroundings

// run the thenMove part, which sets direc and nextS
x
createRule(currentState, surr,direc,nextS)
}


// parse the destination state and direction
def thenMove(direction: String, newState: String) = {

// Helper to map from input move direction to semantics.MoveDirection
def strToMoveDir(x:String):MoveDirection = {
x match {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of pattern matching! We did that too!

case "N" => North
case "E" => East
case "W" => West
case "S" => South
case "X" => StayHere
}
}

// Create new state as destination if necessary, set direc and nextS
if(stringToStateMap.contains(newState)) {
val nextState = stringToStateMap(newState)
val moveDir = strToMoveDir(direction)
direc = moveDir
nextS = nextState
} else {
val nextState = State(newState);
stringToStateMap += newState -> nextState
val moveDir = strToMoveDir(direction)
direc = moveDir
nextS = nextState

}
}

// return the rules
def getRules() = {
globalRules
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't have side effects, so it probably shouldn't have parentheses.

}
Loading