diff options
Diffstat (limited to 'subex/subexast.go')
-rw-r--r-- | subex/subexast.go | 343 |
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) +} |