diff options
| -rw-r--r-- | subex/parse.go | 154 | 
1 files changed, 37 insertions, 117 deletions
| diff --git a/subex/parse.go b/subex/parse.go index db07567..59b784d 100644 --- a/subex/parse.go +++ b/subex/parse.go @@ -4,9 +4,33 @@ import (  	"main/walk"  ) +func expectBracket(l *RuneReader, ifLeft walk.Datum, ifRight walk.Datum) walk.Datum { +	switch l.next() { +		case '(': +			return ifLeft +		case ')': +			return ifRight +		default: +			panic("Expected ( or )") +	} +} + +// Having just read termType, read in a bracket and return the corresponding walk.Datum +func parseTerminatorDatumLiteral(termType rune, l *RuneReader) walk.Datum { +	switch termType { +		case '@': +			return expectBracket(l, walk.ArrayBegin, walk.ArrayEnd) +		case '~': +			return expectBracket(l, walk.StartString{}, walk.EndString{}) +		case '#': +			return expectBracket(l, walk.MapBegin, walk.MapEnd) +		default: +			return nil +	} +} +  func parseReplacement(l *RuneReader) (output []TransducerOutput) {  	// TODO escaping -	// TODO refactor all the terminator stuff @, #, ~  	loop: for {  		r := l.next()  		switch r { @@ -20,33 +44,8 @@ func parseReplacement(l *RuneReader) (output []TransducerOutput) {  					panic("Missing slot character")  				}  				output = append(output, TransducerReplacementLoad{datum: slot}) -			case '@': -				terminal := l.next() -				if terminal == '(' { -					output = append(output, TransducerReplacementRune{datum: walk.ArrayBegin}) -				} else if terminal == ')' { -					output = append(output, TransducerReplacementRune{datum: walk.ArrayEnd}) -				} else { -					panic("Expected ( or ) after @") -				} -			case '~': -				terminal := l.next() -				if terminal == '(' { -					output = append(output, TransducerReplacementRune{datum: walk.StartString{}}) -				} else if terminal == ')' { -					output = append(output, TransducerReplacementRune{datum: walk.EndString{}}) -				} else { -					panic("Expected ( or ) after ~") -				} -			case '#': -				terminal := l.next() -				if terminal == '(' { -					output = append(output, TransducerReplacementRune{datum: walk.MapBegin}) -				} else if terminal == ')' { -					output = append(output, TransducerReplacementRune{datum: walk.MapEnd}) -				} else { -					panic("Expected ( or ) after #") -				} +			case '@', '~', '#': +				output = append(output, TransducerReplacementRune{datum: parseTerminatorDatumLiteral(r, l)})  			default:  				output = append(output, TransducerReplacementRune{datum: r})  		} @@ -68,38 +67,11 @@ func parseRangeSubex(l *RuneReader) map[walk.Datum]walk.Datum {  		} else if fromsStart == '=' {  			hasTo = true  			break -		} else if fromsStart == '@' { -			terminal := l.next() -			if terminal == '(' { -				froms = append(froms, walk.ArrayBegin) -				continue -			} else if terminal == ')' { -				froms = append(froms, walk.ArrayEnd) -				continue -			} else { -				panic("Expected ( or ) after @") -			} -		} else if fromsStart == '#' { -			terminal := l.next() -			if terminal == '(' { -				froms = append(froms, walk.MapBegin) -				continue -			} else if terminal == ')' { -				froms = append(froms, walk.MapEnd) -				continue -			} else { -				panic("Expected ( or ) after #") -			} -		} else if fromsStart == '~' { -			terminal := l.next() -			if terminal == '(' { -				froms = append(froms, walk.StartString{}) -				continue -			} else if terminal == ')' { -				froms = append(froms, walk.EndString{}) +		} else { +			datum := parseTerminatorDatumLiteral(fromsStart, l) +			if datum != nil { +				froms = append(froms, datum)  				continue -			} else { -				panic("Expected ( or ) after ~")  			}  		}  		if l.accept("-") { @@ -125,38 +97,11 @@ func parseRangeSubex(l *RuneReader) map[walk.Datum]walk.Datum {  			tosStart := l.next()  			if tosStart == ']' {  				break -			} else if tosStart == '@' { -				terminal := l.next() -				if terminal == '(' { -					tos = append(tos, walk.ArrayBegin) -					continue -				} else if terminal == ')' { -					tos = append(tos, walk.ArrayEnd) -					continue -				} else { -					panic("Expected ( or ) after @") -				} -			} else if tosStart == '#' { -				terminal := l.next() -				if terminal == '(' { -					tos = append(tos, walk.MapBegin) -					continue -				} else if terminal == ')' { -					tos = append(tos, walk.MapEnd) -					continue -				} else { -					panic("Expected ( or ) after #") -				} -			} else if tosStart == '~' { -				terminal := l.next() -				if terminal == '(' { -					tos = append(tos, walk.StartString{}) -					continue -				} else if terminal == ')' { -					tos = append(tos, walk.EndString{}) +			} else { +				datum := parseTerminatorDatumLiteral(tosStart, l) +				if datum != nil { +					tos = append(tos, datum)  					continue -				} else { -					panic("Expected ( or ) after ~")  				}  			}  			if l.accept("-") { @@ -220,33 +165,8 @@ func parseSubex(l *RuneReader, minPower int) SubexAST {  			lhs = SubexASTOutput{replacement}  		case '.':  			lhs = SubexASTCopyAny{} -		case '@': -			terminal := l.next() -			if terminal == '(' { -				lhs = SubexASTCopyRune{datum: walk.ArrayBegin} -			} else if terminal == ')' { -				lhs = SubexASTCopyRune{datum: walk.ArrayEnd} -			} else { -				panic("Expected ( or ) after @") -			} -		case '~': -			terminal := l.next() -			if terminal == '(' { -				lhs = SubexASTCopyRune{datum: walk.StartString{}} -			} else if terminal == ')' { -				lhs = SubexASTCopyRune{datum: walk.EndString{}} -			} else { -				panic("Expected ( or ) after ~") -			} -		case '#': -			terminal := l.next() -			if terminal == '(' { -				lhs = SubexASTCopyRune{datum: walk.MapBegin} -			} else if terminal == ')' { -				lhs = SubexASTCopyRune{datum: walk.MapEnd} -			} else { -				panic("Expected ( or ) after #") -			} +		case '@', '#', '~': +			lhs = SubexASTCopyRune{datum: parseTerminatorDatumLiteral(r, l)}  		default:  			lhs = SubexASTCopyRune{datum: r}  	} | 
