Skip to content

Commit

Permalink
Regulate what is exported
Browse files Browse the repository at this point in the history
Regulate what is exported such that this package could be used as a
library without the CLI part.
  • Loading branch information
Ro5bert committed Oct 1, 2019
1 parent 2cce630 commit a2d73fe
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 96 deletions.
44 changes: 21 additions & 23 deletions lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
"unicode"
)

// TODO: restrict access to other packages

const (
negateSym = '!'
andSym = '&'
Expand All @@ -22,33 +20,33 @@ type lexemeType byte

func (lt lexemeType) String() string {
switch lt {
case LTFalse:
case ltFalse:
return "False"
case LTTrue:
case ltTrue:
return "True"
case LTNegate:
case ltNegate:
return "Negate"
case LTOperator:
case ltOperator:
return "Operator"
case LTOpenParen:
case ltOpenParen:
return "OpenParen"
case LTCloseParen:
case ltCloseParen:
return "CloseParen"
case LTStatement:
case ltStatement:
return "Statement"
default:
panic("lexemeType not added to String method!")
}
}

const (
LTFalse lexemeType = iota
LTTrue
LTNegate
LTOperator
LTOpenParen
LTCloseParen
LTStatement
ltFalse lexemeType = iota
ltTrue
ltNegate
ltOperator
ltOpenParen
ltCloseParen
ltStatement
)

type lexeme struct {
Expand Down Expand Up @@ -147,17 +145,17 @@ func lexStatement(n byte, l *lexer) (lexemeType, statefn, error) {
switch n {
case negateSym:
l.allowEOF = false
return LTNegate, lexStatement, nil
return ltNegate, lexStatement, nil
case '(':
l.nest()
return LTOpenParen, lexStatement, nil
return ltOpenParen, lexStatement, nil
case '0':
return LTFalse, lexOperator, nil
return ltFalse, lexOperator, nil
case '1':
return LTTrue, lexOperator, nil
return ltTrue, lexOperator, nil
}
if ('a' <= n && n <= 'z') || ('A' <= n && n <= 'Z') {
return LTStatement, lexOperator, nil
return ltStatement, lexOperator, nil
}
return 0, nil, fmt.Errorf("unexpected char '%c'; expected '%c', '(', '0', '1', or a statement", n, negateSym)
}
Expand All @@ -168,10 +166,10 @@ func lexOperator(n byte, l *lexer) (lexemeType, statefn, error) {
if !l.denest() {
return 0, nil, errors.New("unexpected closing parenthesis: no corresponding opening parenthesis")
}
return LTCloseParen, lexOperator, nil
return ltCloseParen, lexOperator, nil
case andSym, orSym, xorSym, condSym, bicondSym:
l.allowEOF = false
return LTOperator, lexStatement, nil
return ltOperator, lexStatement, nil
}
return 0, nil, fmt.Errorf("unexpected char '%c'; expected ')', '%c', '%c', '%c', '%c', or '%c'",
n, andSym, orSym, xorSym, condSym, bicondSym)
Expand Down
64 changes: 32 additions & 32 deletions lex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,45 @@ func TestLex(t *testing.T) {
expected []lexeme
}
for _, c := range []testCase{
{"a", []lexeme{{LTStatement, 'a'}}},
{"a", []lexeme{{ltStatement, 'a'}}},
{"(a)", []lexeme{
{LTOpenParen, '('},
{LTStatement, 'a'},
{LTCloseParen, ')'},
{ltOpenParen, '('},
{ltStatement, 'a'},
{ltCloseParen, ')'},
}},
{"a > b", []lexeme{
{LTStatement, 'a'},
{LTOperator, '>'},
{LTStatement, 'b'},
{ltStatement, 'a'},
{ltOperator, '>'},
{ltStatement, 'b'},
}},
{" ( a >b) & 1 ", []lexeme{
{LTOpenParen, '('},
{LTStatement, 'a'},
{LTOperator, '>'},
{LTStatement, 'b'},
{LTCloseParen, ')'},
{LTOperator, '&'},
{LTTrue, '1'},
{ltOpenParen, '('},
{ltStatement, 'a'},
{ltOperator, '>'},
{ltStatement, 'b'},
{ltCloseParen, ')'},
{ltOperator, '&'},
{ltTrue, '1'},
}},
{"!(!(a = b) | !0) > (c ^ d)", []lexeme{
{LTNegate, '!'},
{LTOpenParen, '('},
{LTNegate, '!'},
{LTOpenParen, '('},
{LTStatement, 'a'},
{LTOperator, '='},
{LTStatement, 'b'},
{LTCloseParen, ')'},
{LTOperator, '|'},
{LTNegate, '!'},
{LTFalse, '0'},
{LTCloseParen, ')'},
{LTOperator, '>'},
{LTOpenParen, '('},
{LTStatement, 'c'},
{LTOperator, '^'},
{LTStatement, 'd'},
{LTCloseParen, ')'},
{ltNegate, '!'},
{ltOpenParen, '('},
{ltNegate, '!'},
{ltOpenParen, '('},
{ltStatement, 'a'},
{ltOperator, '='},
{ltStatement, 'b'},
{ltCloseParen, ')'},
{ltOperator, '|'},
{ltNegate, '!'},
{ltFalse, '0'},
{ltCloseParen, ')'},
{ltOperator, '>'},
{ltOpenParen, '('},
{ltStatement, 'c'},
{ltOperator, '^'},
{ltStatement, 'd'},
{ltCloseParen, ')'},
}},
} {
idx := 0
Expand Down
74 changes: 37 additions & 37 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,36 @@ func idxToAlpha(idx byte) byte {
return idx + 65
}

type truth struct {
val uint64
type Truth struct {
Val uint64
shiftMap *[52]byte
names []byte
Names []byte
}

func (t truth) get(stmt byte) bool {
return t.val&(1<<t.shiftMap[alphaToIdx(stmt)]) > 0
func (t Truth) get(stmt byte) bool {
return t.Val&(1<<t.shiftMap[alphaToIdx(stmt)]) > 0
}

func (t truth) String() string {
func (t Truth) String() string {
var sb strings.Builder
sb.WriteByte('{')
for i, b := range t.names {
for i, b := range t.Names {
sb.WriteByte(b)
sb.WriteByte(':')
if t.get(b) {
sb.WriteByte('1')
} else {
sb.WriteByte('0')
}
if i < len(t.names)-1 {
if i < len(t.Names)-1 {
sb.WriteByte(',')
}
}
sb.WriteByte('}')
return sb.String()
}

func newTruth(atomics uint64) truth {
func newTruth(atomics uint64) Truth {
var shiftMap [52]byte
names := make([]byte, 0, 52)
var shift byte
Expand All @@ -60,17 +60,17 @@ func newTruth(atomics uint64) truth {
names = append(names, idxToAlpha(i))
}
}
return truth{0, &shiftMap, names}
return Truth{0, &shiftMap, names}
}

type operator func(bool, bool) bool

type stmt interface {
type Stmt interface {
fmt.Stringer
eval(truth) bool
Eval(Truth) bool
}

func surroundIfBinary(s stmt) string {
func surroundIfBinary(s Stmt) string {
if _, ok := s.(binaryStmt); ok {
return "(" + s.String() + ")"
}
Expand All @@ -79,7 +79,7 @@ func surroundIfBinary(s stmt) string {

type falseStmt struct{}

func (falseStmt) eval(truth) bool {
func (falseStmt) Eval(Truth) bool {
return false
}

Expand All @@ -89,7 +89,7 @@ func (falseStmt) String() string {

type trueStmt struct{}

func (trueStmt) eval(truth) bool {
func (trueStmt) Eval(Truth) bool {
return true
}

Expand All @@ -98,20 +98,20 @@ func (trueStmt) String() string {
}

type negatedStmt struct {
stmt
Stmt
}

func (s negatedStmt) eval(t truth) bool {
return !s.stmt.eval(t)
func (s negatedStmt) Eval(t Truth) bool {
return !s.Stmt.Eval(t)
}

func (s negatedStmt) String() string {
return "!" + surroundIfBinary(s.stmt)
return "!" + surroundIfBinary(s.Stmt)
}

type atomicStmt byte

func (s atomicStmt) eval(t truth) bool {
func (s atomicStmt) Eval(t Truth) bool {
return t.get(byte(s))
}

Expand All @@ -120,14 +120,14 @@ func (s atomicStmt) String() string {
}

type binaryStmt struct {
left stmt
left Stmt
op operator
right stmt
right Stmt
opSym string
}

func (s binaryStmt) eval(t truth) bool {
return s.op(s.left.eval(t), s.right.eval(t))
func (s binaryStmt) Eval(t Truth) bool {
return s.op(s.left.Eval(t), s.right.Eval(t))
}

func (s binaryStmt) String() string {
Expand Down Expand Up @@ -172,28 +172,28 @@ func byteToOp(b byte) operator {
}
}

func parse(input string) (stmt, truth, error) {
func Parse(input string) (Stmt, Truth, error) {
stmt, atomics, err := parseRecursive(lex(input))
return stmt, newTruth(atomics), err
}

type stmtBuilder struct {
inner stmt
inner Stmt
negated bool
}

func (sb *stmtBuilder) negate() {
sb.negated = !sb.negated
}

func (sb *stmtBuilder) build() stmt {
func (sb *stmtBuilder) build() Stmt {
if sb.negated {
return negatedStmt{sb.inner}
}
return sb.inner
}

func parseRecursive(c chan lexerResult) (stmt, uint64, error) {
func parseRecursive(c chan lexerResult) (Stmt, uint64, error) {
const (
expStmt = iota
expOpOrClose
Expand Down Expand Up @@ -228,24 +228,24 @@ forLoop:
switch state {
case expStmt:
switch lr.l.t {
case LTFalse:
case ltFalse:
pick().inner = falseStmt{}
case LTTrue:
case ltTrue:
pick().inner = trueStmt{}
case LTNegate:
case ltNegate:
// TODO: try to preserve original statement as faithfully as possible: increment negate counter instead?
pick().negate()
// continue so state is not set below the switch statement.
continue
case LTOpenParen:
case ltOpenParen:
var err error
var a uint64
pick().inner, a, err = parseRecursive(c)
if err != nil {
return nil, 0, err
}
atomics |= a
case LTStatement:
case ltStatement:
atomics |= 1 << alphaToIdx(lr.l.v)
pick().inner = atomicStmt(lr.l.v)
default:
Expand All @@ -259,19 +259,19 @@ forLoop:
}
case expOpOrClose:
switch lr.l.t {
case LTOperator:
case ltOperator:
op = byteToOp(lr.l.v)
opSym = " " + string(lr.l.v) + " "
state = expStmt
case LTCloseParen:
case ltCloseParen:
break forLoop
default:
// Lexer should guarantee this never happens.
panic(fmt.Sprintf("expected Operator or CloseParen/EOF, not %s", lr.l.t))
}
case expClose:
if lr.l.t != LTCloseParen {
// This should only ever happen if the lexeme is of type LTOperator, since the lexer does not understand
if lr.l.t != ltCloseParen {
// This should only ever happen if the lexeme is of type ltOperator, since the lexer does not understand
// that multiple operators chained together without parentheses is ambiguous.
return nil, 0, fmt.Errorf("expected CloseParen/EOF, not %s", lr.l.t)
}
Expand Down
Loading

0 comments on commit a2d73fe

Please sign in to comment.