Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex/subexast.go
diff options
context:
space:
mode:
Diffstat (limited to 'subex/subexast.go')
-rw-r--r--subex/subexast.go343
1 files changed, 236 insertions, 107 deletions
diff --git a/subex/subexast.go b/subex/subexast.go
index cef853b..655a783 100644
--- a/subex/subexast.go
+++ b/subex/subexast.go
@@ -46,6 +46,25 @@ func (ast SubexASTStoreValues) String() string {
return fmt.Sprintf("$%c(%v)", ast.Slot, ast.Match)
}
+type SubexASTStoreRunes struct {
+ Match SubexAST
+ Slot rune
+}
+func (ast SubexASTStoreRunes) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ id := slotMap.getRuneId(ast.Slot)
+ newNext := ast.Match.compileWith(&SubexStoreRunesEndState {
+ slot: id,
+ next: next,
+ }, slotMap, inType, RuneType)
+
+ return &SubexCaptureRunesBeginState {
+ next: newNext,
+ }
+}
+func (ast SubexASTStoreRunes) String() string {
+ return fmt.Sprintf("(%v)$%c", ast.Match, ast.Slot)
+}
+
// Try to run the first subex, if it fails then backtrack and use the second
type SubexASTOr struct {
First, Second SubexAST
@@ -132,9 +151,6 @@ type SubexASTRepeat struct {
Acceptable []ConvexRange
}
func (ast SubexASTRepeat) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
- if inType != outType {
- panic("Invalid types")
- }
var state SubexState = &SubexDeadState{}
for _, convex := range ast.Acceptable {
state = &SubexGroupState {state, convex.compile(ast.Content, next, slotMap, inType, outType)}
@@ -151,7 +167,7 @@ type SubexASTCopyScalar struct {
}
func (ast SubexASTCopyScalar) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyScalar")
}
return &SubexCopyState{
filter: selectScalarFilter {ast.Scalar},
@@ -165,7 +181,7 @@ func (ast SubexASTCopyScalar) String() string {
type SubexASTCopyAnyRune struct {}
func (ast SubexASTCopyAnyRune) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != RuneType || outType != RuneType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyAnyRune")
}
return &SubexCopyRuneState {
next: next,
@@ -173,7 +189,7 @@ func (ast SubexASTCopyAnyRune) compileWith(next SubexState, slotMap *SlotMap, in
}
}
func (ast SubexASTCopyAnyRune) String() string {
- return "."
+ return ".RUNE"
}
type SubexASTCopyRune struct {
@@ -181,19 +197,22 @@ type SubexASTCopyRune struct {
}
func (ast SubexASTCopyRune) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != RuneType || outType != RuneType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyRune")
}
return &SubexCopyRuneState {
next: next,
filter: selectRuneFilter {ast.rune},
}
}
+func (ast SubexASTCopyRune) String() string {
+ return string(ast.rune)
+}
// Read in a single atom that must be a boolean and output it unchanged
type SubexASTCopyBool struct {}
func (ast SubexASTCopyBool) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyBool")
}
return &SubexCopyState {
next: next,
@@ -208,7 +227,7 @@ func (ast SubexASTCopyBool) String() string {
type SubexASTCopyNumber struct {}
func (ast SubexASTCopyNumber) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyNumber")
}
return &SubexCopyState {
next: next,
@@ -219,11 +238,23 @@ func (ast SubexASTCopyNumber) String() string {
return "%"
}
+// Read in a null, bool, number, string or empty array or map and output it unchanged
+type SubexASTCopyAnySimpleValue struct {}
+func (ast SubexASTCopyAnySimpleValue) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ if inType != ValueType || outType != ValueType {
+ panic("Invalid types for SubexASTCopyAnySimpleValue")
+ }
+ return &SubexCopyState {
+ next: next,
+ filter: simpleValueFilter{},
+ }
+}
+
// Read in any single Atom and output it unchanged
type SubexASTCopyAnyValue struct {}
func (ast SubexASTCopyAnyValue) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyAnyValue")
}
return &SubexCopyState {
next: next,
@@ -279,64 +310,56 @@ func (ast SubexASTOutput) String() string {
}
*/
-type OutputValueAST interface {
- compile(slotMap *SlotMap) OutputValue
+type SubexASTOutputValueLiteral struct {
+ literal walk.Scalar
}
-
-type OutputValueLoadAST struct {
- slot rune
-}
-func (ast OutputValueLoadAST) compile(slotMap *SlotMap) OutputValue {
- return OutputValueLoad {
- slotMap.getId(ast.slot),
+func (ast SubexASTOutputValueLiteral) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ if outType != ValueType {
+ panic("Invalid outType for SubexASTOutputValueLiteral")
}
-}
-
-type OutputValueLiteralAST struct {
- scalar walk.Scalar
-}
-func (ast OutputValueLiteralAST) compile(slotMap *SlotMap) OutputValue {
- return OutputValueLiteral {
- ast.scalar,
+ return &SubexOutputValueLiteralState {
+ literal: ast.literal,
+ next: next,
}
}
-type SubexASTOutputValues struct {
- Replacement []OutputValueAST
+type SubexASTOutputValueLoad struct {
+ slot rune
}
-func (ast SubexASTOutputValues) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+func (ast SubexASTOutputValueLoad) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if outType != ValueType {
- panic("Invalid outType")
+ panic("Invalid outType for SubexASTOutputValueLoad")
}
- var content []OutputValue
- for _, el := range ast.Replacement {
- content = append(content, el.compile(slotMap))
- }
- return &SubexOutputValuesState {
- content: content,
+ return &SubexOutputValueLoadState {
+ slot: slotMap.getId(ast.slot),
next: next,
}
}
-type OutputRuneAST interface {
- compile(slotMap *SlotMap) OutputRune
+type SubexASTOutputRuneLiteral struct {
+ literal rune
}
-
-type OutputRuneLoadAST struct {
- slot rune
-}
-func (ast OutputRuneLoadAST) compile(slotMap *SlotMap) OutputRune {
- return OutputRuneLoad {slotMap.getRuneId(ast.slot)}
+func (ast SubexASTOutputRuneLiteral) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ if outType != RuneType {
+ panic("Invalid outType for SubexASTOutputRuneLiteral")
+ }
+ return &SubexOutputRuneLiteralState {
+ literal: ast.literal,
+ next: next,
+ }
}
-type OutputRuneLiteralAST struct {
- r rune
-}
-func (ast OutputRuneLiteralAST) compile (slotMap *SlotMap) OutputRune {
- return OutputRuneLiteral {ast.r}
+type SubexASTOutputRuneLoad struct {
+ slot rune
}
-
-type SubexASTOutputRunes struct {
+func (ast SubexASTOutputRuneLoad) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ if outType != RuneType {
+ panic("Invalid outType for SubexASTOutputRuneLoad")
+ }
+ return &SubexOutputRuneLoadState {
+ slot: slotMap.getRuneId(ast.slot),
+ next: next,
+ }
}
// Run each input Atom through a map to produce an output Atom
@@ -361,7 +384,7 @@ type SubexASTSum struct {
}
func (ast SubexASTSum) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTSum")
}
return &SubexCaptureBeginState {
next: ast.Content.compileWith(&SubexArithmeticEndState {
@@ -380,7 +403,7 @@ type SubexASTProduct struct {
}
func (ast SubexASTProduct) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTProduct")
}
return &SubexCaptureBeginState {
next: ast.Content.compileWith(&SubexArithmeticEndState {
@@ -400,7 +423,7 @@ type SubexASTNegate struct {
}
func (ast SubexASTNegate) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTNegate")
}
return &SubexCaptureBeginState {
next: ast.Content.compileWith(&SubexArithmeticEndState {
@@ -446,9 +469,10 @@ func (ast SubexASTEmpty) String() string {
// Discards the output from the content subex
type SubexASTDiscard struct {
Content SubexAST
+ InnerOutType Type
}
func (ast SubexASTDiscard) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
- newNext := ast.Content.compileWith(&SubexDiscardState {next}, slotMap, inType, outType)
+ newNext := ast.Content.compileWith(&SubexDiscardState {next}, slotMap, inType, ast.InnerOutType)
if inType == ValueType {
return &SubexCaptureBeginState {
next: newNext,
@@ -463,65 +487,170 @@ func (ast SubexASTDiscard) String() string {
return fmt.Sprintf("(%v)$_", ast.Content)
}
-// Go into an array, pass the content each of the values in the array to eat and then leave the array
-type SubexASTEnterArray struct {
+type SubexASTDestructure struct {
+ Destructure Structure
+ Structure Structure
Content SubexAST
}
-func (ast SubexASTEnterArray) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
- if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTEnterArray")
- }
- return &SubexCaptureBeginState {
- next: &SubexCopyState {
- filter: anyArrayFilter{},
- next: &SubexDiscardState {
- next: &SubexIncrementNestState {
- next: &SubexCaptureBeginState {
- next: ast.Content.compileWith(
- &SubexDiscardTerminalState {
- terminal: walk.ArrayEnd,
- next: &SubexDecrementNestState {
- next: &SubexConstructArrayState {next: next},
- },
- },
- slotMap,
- ValueType,
- ValueType,
- ),
- },
- },
+func (ast SubexASTDestructure) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ var innerOutType Type
+ var construct SubexState
+ switch ast.Structure {
+ case NoneStructure:
+ innerOutType = outType
+ construct = next
+ case StringStructure:
+ innerOutType = RuneType
+ construct = &SubexConstructStringState {
+ next: next,
+ }
+ case ArrayStructure:
+ innerOutType = ValueType
+ construct = &SubexConstructArrayState {
+ next: next,
+ }
+ case ArrayValuesStructure:
+ innerOutType = ValueType
+ construct = &SubexConstructArrayValuesState {
+ next: next,
+ }
+ case MapStructure:
+ innerOutType = ValueType
+ construct = &SubexConstructMapState {
+ next: next,
+ }
+ default:
+ panic("Invalid ast structure")
+ }
+
+ var innerInType Type
+ var destructFooter SubexState
+ switch ast.Destructure {
+ case NoneStructure:
+ innerInType = inType
+ destructFooter = construct
+ case StringStructure:
+ innerInType = RuneType
+ destructFooter = &SubexDiscardTerminalState {
+ terminal: walk.StringEnd,
+ next: &SubexDecrementNestState {
+ next: construct,
+ },
+ }
+ case ArrayStructure:
+ innerInType = ValueType
+ destructFooter = &SubexDiscardTerminalState {
+ terminal: walk.ArrayEnd,
+ next: &SubexDecrementNestState {
+ next: construct,
},
- },
+ }
+ case ArrayValuesStructure:
+ innerInType = ValueType
+ destructFooter = &SubexDiscardTerminalState {
+ terminal: walk.ArrayEnd,
+ next: &SubexDecrementNestState {
+ next: construct,
+ },
+ }
+ case MapStructure:
+ innerInType = ValueType
+ destructFooter = &SubexDiscardTerminalState {
+ terminal: walk.MapEnd,
+ next: &SubexDecrementNestState {
+ next: construct,
+ },
+ }
+ default:
+ panic("Invalid ast destructure")
}
-}
-type SubexASTEnterString struct {
- Content SubexAST
-}
-func (ast SubexASTEnterString) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
- if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTEnterString")
+ inner := ast.Content.compileWith(
+ destructFooter,
+ slotMap,
+ innerInType,
+ innerOutType,
+ )
+
+ var beginConstruct SubexState
+ switch ast.Structure {
+ case NoneStructure:
+ beginConstruct = inner
+ case StringStructure:
+ beginConstruct = &SubexCaptureRunesBeginState {
+ next: inner,
+ }
+ case ArrayStructure:
+ beginConstruct = &SubexCaptureBeginState {
+ next: inner,
+ }
+ case ArrayValuesStructure:
+ beginConstruct = &SubexCaptureBeginState {
+ next: inner,
+ }
+ case MapStructure:
+ beginConstruct = &SubexCaptureBeginState {
+ next: inner,
+ }
+ default:
+ panic("Invalid ast structure")
}
- return &SubexCaptureBeginState {
- next: &SubexCopyState {
- filter: anyStringFilter{},
- next: &SubexDiscardState {
- next: &SubexIncrementNestState {
- next: &SubexCaptureRunesBeginState {
- next: ast.Content.compileWith(
- &SubexDiscardTerminalState {
- terminal: walk.StringEnd,
- next: &SubexDecrementNestState {
- next: &SubexConstructStringState {next: next},
- },
- },
- slotMap,
- RuneType,
- RuneType,
- ),
+
+ switch ast.Destructure {
+ case NoneStructure:
+ return beginConstruct
+ case StringStructure:
+ return &SubexCaptureBeginState {
+ next: &SubexCopyState {
+ filter: anyStringFilter{},
+ next: &SubexDiscardState {
+ next: &SubexIncrementNestState {
+ keys: true,
+ next: beginConstruct,
},
},
},
- },
+ }
+ case ArrayStructure:
+ return &SubexCaptureBeginState {
+ next: &SubexCopyState {
+ filter: anyArrayFilter{},
+ next: &SubexDiscardState {
+ next: &SubexIncrementNestState {
+ keys: true,
+ next: beginConstruct,
+ },
+ },
+ },
+ }
+ case ArrayValuesStructure:
+ return &SubexCaptureBeginState {
+ next: &SubexCopyState {
+ filter: anyArrayFilter{},
+ next: &SubexDiscardState {
+ next: &SubexIncrementNestState {
+ keys: false,
+ next: beginConstruct,
+ },
+ },
+ },
+ }
+ case MapStructure:
+ return &SubexCaptureBeginState {
+ next: &SubexCopyState {
+ filter: anyMapFilter{},
+ next: &SubexDiscardState {
+ next: &SubexIncrementNestState {
+ keys: true,
+ next: beginConstruct,
+ },
+ },
+ },
+ }
+ default:
+ panic("Invalid destructure in ast")
}
}
+func (ast SubexASTDestructure) String() string {
+ return fmt.Sprintf("%v(%v)%v", ast.Destructure, ast.Content, ast.Structure)
+}