-
Notifications
You must be signed in to change notification settings - Fork 10
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
base: master
Are you sure you want to change the base?
Changes from 25 commits
88dca9a
70cdd25
723afc6
3b00bb2
90ccc83
d08db45
57252e0
89eaf31
a7f4819
9a2c33b
de923e8
0ea9018
f074062
f917209
d11b85f
81ca130
4dbbbb2
d37f861
fa5636f
86688af
1a03b73
b77363d
856c890
caad8ca
ae62f9c
db76868
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ target | |
.classpath | ||
.history | ||
.project | ||
*.swp |
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. | ||
|
||
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. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
|
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
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 ; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 ; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
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} |
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} ; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
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() | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
} |
There was a problem hiding this comment.
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?