Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
richard-lyman committed Oct 12, 2016
1 parent 8321535 commit 84c845b
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 30 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.exe
amotoen
76 changes: 76 additions & 0 deletions PL.AN
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(){}


29 changes: 0 additions & 29 deletions README.md
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
109 changes: 108 additions & 1 deletion main.go
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)
}

0 comments on commit 84c845b

Please sign in to comment.