-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8321535
commit 84c845b
Showing
4 changed files
with
185 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
*.exe | ||
amotoen |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
|
||
Use golang 'scanner' libs | ||
|
||
The new grammar-grammar: | ||
* Keeping the two 'special' Keywords: ':$', or End-of-input, and ':.', or Any-Rune | ||
* Dropping the ValidKeywordChar | ||
* Adding the OneOrMore Keyword | ||
* Adding the String Keyword and expanding to the Escaped* and Escapable* Keywords | ||
{ | ||
:_ (| ' ' "\t" "\r" "\n") | ||
:* (* :_) | ||
:+ (+ :_) | ||
:Grammar ['{' :* :Rule (* [:+ :Rule]) :* '}'] | ||
:Rule [:Keyword :+ :Body] | ||
:Keyword [':' (+ (% :_)] | ||
:Body (| :Keyword :Char :String :Group) | ||
:Char ['\'' (| :EscapedChar (% :EscapableChar)) '\''] | ||
:EscapedChar ['\\' :EscapableChar] | ||
:EscapableChar (| '\'' '\\') | ||
:String ['"' (+ (| :EscapedStr (% :EscapableStr))) '"'] | ||
:EscapedStr ['\\' :EscapableStr] | ||
:EscapableStr (| '\\' '"') | ||
:Group (| :Sequence :Either :ZeroOrMore :OneOrMore :AnyNot) | ||
:Sequence ['[' :* :Body (* [:* :Body]) :* ']'] | ||
:Either ['(' '|' :+ :Body (* [:* :Body]) :* ')'] | ||
:ZeroOrMore ['(' '*' :+ :Body :* ')'] | ||
:OneOrMore ['(' '+' :+ :Body :* ')'] | ||
:AnyNot ['(' '%' :+ :Body :* ')'] | ||
} | ||
|
||
There is a function that helps create an AST from a grammar and some input string. | ||
|
||
There is another function that helps walk the AST. | ||
|
||
http://play.golang.org/p/LAIo1ygttp | ||
package main | ||
|
||
import ("fmt"; "reflect") | ||
|
||
type B interface {isB()} | ||
type C int; func (c C) isB(){} | ||
type S string; func (s S) isB(){} | ||
type G interface {B;isG()} | ||
type Seq []B; func (seq Seq) isB(){}; func (seq Seq) isG(){} | ||
|
||
func NewSeq(b ...B) G { | ||
return Seq(b) | ||
} | ||
|
||
func main() { | ||
a := NewSeq(C(2), S("t")) | ||
b := NewSeq(C(1), S("s"), a) | ||
fmt.Printf("a: %#v\n", a) | ||
fmt.Printf("b: %#v\n", b) | ||
fmt.Println("Third part of b is a:", reflect.DeepEqual(b.(Seq)[2], a)) | ||
} | ||
|
||
type AST []struct{Keyword, Body} | ||
type Keyword string | ||
type Body interface { | ||
isBody() | ||
} | ||
type Group interface { | ||
Body | ||
isGroupable() | ||
} | ||
|
||
type Char rune; func (c Char) isBody(){} | ||
type String string; func (s String) isBody(){} | ||
type Sequence []Body; func (s Sequence) isBody(){}; func (s Sequence) isGroupable(){}; func NewSequence( b ...Body) Group { return Sequence(b) } | ||
type Either Body; func (e Either) isBody(){}; func (e Either) isGroupable(){} | ||
type ZeroOrMore []Body; func (z ZeroOrMore) isBody(){}; func (z ZeroOrMore) isGroupable(){}; func NewZeroOrMore( b ...Body) Group { return ZeroOrMore(b) } | ||
type OneOrMore []Body; func (o OneOrMore) isBody(){}; func (o OneOrMore) isGroupable(){}; func NewOneOrMore( b ...Body) Group { return OneOrMore(b) } | ||
type AnyNot Body; func (a AnyNot) isBody(){}; func (a AnyNot) isGroupable(){} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +0,0 @@ | ||
### Install Go | ||
- (Make sure you install the same platform of Go as you do of MinGW (32-bit or 64-bit)) | ||
- install go 32 bit [Win 32-bit installer](http://code.google.com/p/go/downloads/list?q=OpSys-Windows+Type%3DInstaller) | ||
- The default should create a dir c:\Go - this is the \<GO_INSTALL_DIR> | ||
|
||
### Install Go and MinGW | ||
This likely isn't *required*, but we're not sure which libraries we'll be using yet | ||
- (Make sure you install the same platform of Go as you do of MinGW (32-bit or 64-bit)) | ||
- install mingw [Win 32-bit default](http://sourceforge.net/projects/mingw/files/Installer/mingw-get-inst/) | ||
- This is a GUI installer - it's super simple | ||
- MAKE SURE YOU SELECT TO INSTALL MSYS - whatever else you do, at _least_ also do this | ||
- The default should create a dir c:\MinGW - this is the \<MINGW_INSTALL_DIR> | ||
- You'll need to add the \<MINGW_INSTALL_DIR>\bin folder to the system path | ||
- Press the keys Win+Pause | ||
- Click on 'Advanced system settings' | ||
- Click on 'Environment Variables' | ||
- Scroll down in the 'System variables' until you see the 'Path' variable | ||
- Select the 'Path' variable row | ||
- Click 'Edit' | ||
- Press the Home key | ||
- Type 'C:\MinGW\bin;' | ||
- Click Ok | ||
- Click Ok | ||
- Click Ok | ||
- Close the 'Control Panel Home' window | ||
|
||
### Cleaning up after Go | ||
- Sometimes libraries aren't 'cleaned' if the related library source is updated. | ||
- C:\Go\pkg\windows_386\some\libraries\folder - and delete the *.a file | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,116 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"log" | ||
"strings" | ||
) | ||
|
||
type ast []astNode | ||
|
||
type astNodeType int | ||
|
||
type astNode struct { | ||
t astNodeType | ||
s string | ||
} | ||
|
||
type context struct { | ||
r rune | ||
b bytes.Buffer | ||
a ast | ||
} | ||
|
||
type stateStep func(*context) (stateStep, bool) | ||
|
||
func l(s string, c *context) { log.Println(s, string(c.r)) } | ||
|
||
func nilStep(c *context) (stateStep, bool) { return nilStep, false } | ||
|
||
func gatherAndReturn(c *context, returnState stateStep, b bool) (stateStep, bool) { | ||
c.b.WriteRune(c.r) | ||
return returnState, b | ||
} | ||
|
||
type wrapper func(string) astNode | ||
|
||
func addAndReturn(moreThanZeroRequired bool, w wrapper, returnState stateStep) stateStep { | ||
return func(c *context) (stateStep, bool) { | ||
s := c.b.String() | ||
if moreThanZeroRequired && len(s) > 0 { // This should be different than below... | ||
c.a = append(c.a, w(s)) | ||
c.b.Reset() | ||
} else if len(s) == 0 { | ||
log.Println("len == 0") | ||
c.a = append(c.a, w(s)) | ||
c.b.Reset() | ||
} | ||
return returnState, false | ||
} | ||
} | ||
|
||
const ( | ||
word astNodeType = iota | ||
paren | ||
) | ||
|
||
func toWord(s string) astNode { | ||
return astNode{t: word, s: s} | ||
} | ||
|
||
func toParen(s string) astNode { | ||
log.Println("toParen called...") | ||
return astNode{t: paren} | ||
} | ||
|
||
func consume(c *context) (stateStep, bool) { | ||
switch c.r { | ||
case ' ': | ||
return addAndReturn(true, toWord, consume), true | ||
case '(': | ||
return parens, true | ||
default: | ||
return gatherAndReturn(c, consume, true) | ||
} | ||
} | ||
|
||
func parens(c *context) (stateStep, bool) { | ||
if c.r != ')' { | ||
return gatherAndReturn(c, parens, true) | ||
} | ||
log.Println("marking as paren...") | ||
return addAndReturn(false, toParen, consume), true | ||
} | ||
|
||
func main() { | ||
log.Println("Works!") | ||
in := "this is a (asd) string" | ||
s := bufio.NewScanner(strings.NewReader(in)) | ||
s.Split(bufio.ScanRunes) | ||
c := &context{} | ||
next := true | ||
depth := 0 | ||
previousCR := ' ' | ||
for state := consume; state != nil; { | ||
if previousCR == c.r { | ||
depth = depth + 1 | ||
} else { | ||
depth = depth - 1 | ||
} | ||
if depth > 100 { | ||
break | ||
} | ||
if next { | ||
if !s.Scan() { | ||
break | ||
} | ||
c.r = bytes.Runes(s.Bytes())[0] | ||
} | ||
state, next = state(c) | ||
previousCR = c.r | ||
} | ||
addAndReturn(true, toWord, nilStep)(c) | ||
log.Println(in) | ||
log.Println(c.a) | ||
log.Printf("%+v\n", c.a) | ||
} |