diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2022-09-23 14:55:58 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2022-09-23 14:55:58 +0100 | 
| commit | f3911888915f6aa96e6b28bd2a98a662faf20f47 (patch) | |
| tree | 55373234480b057e1615c0d51316be256b1d6d29 | |
| parent | 0a8690993d572a50b95dd4f1c1903ed00ddb9c2b (diff) | |
| download | subex-f3911888915f6aa96e6b28bd2a98a662faf20f47.tar | |
Adds try, maybe and join operators with !, ? and ; respectively
| -rw-r--r-- | main/parse.go | 29 | ||||
| -rw-r--r-- | main/regexast.go | 20 | ||||
| -rw-r--r-- | main/subexast.go | 36 | 
3 files changed, 79 insertions, 6 deletions
| diff --git a/main/parse.go b/main/parse.go index a9bd4b5..6cc20ea 100644 --- a/main/parse.go +++ b/main/parse.go @@ -27,7 +27,7 @@ func parseRegex(l *RuneReader, minPower int) RegexAST {  	switch r {  		case eof:  			return nil -		case ')', '*', '-', '|': +		case ')', '*', '-', '|', '?', '!':  			l.rewind()  			return nil  		case '(': @@ -54,6 +54,10 @@ func parseRegex(l *RuneReader, minPower int) RegexAST {  				lhs = RegexASTMaximise{lhs}  			case r == '-' && minPower <= 4:  				lhs = RegexASTMinimise{lhs} +			case r == '!' && minPower <= 4: +				lhs = RegexASTTry{lhs} +			case r == '?' && minPower <= 4: +				lhs = RegexASTMaybe{lhs}  			case r == '|' && minPower <= 2:  				rhs := parseRegex(l, 3)  				if rhs == nil { @@ -79,7 +83,7 @@ func parseSubex(l *RuneReader, minPower int) SubexAST {  			if !l.accept(")") {  				panic("Missing matching )")  			} -		case ')', '*', '-', '|': +		case ')', '*', '-', '|', '!', '?', ';':  			l.rewind()  			return nil  		case '$': @@ -113,16 +117,29 @@ func parseSubex(l *RuneReader, minPower int) SubexAST {  		}  		r := l.next()  		switch { -			case r == '*' && minPower <= 4: +			case r == '*' && minPower <= 8:  				lhs = SubexASTMaximise{lhs} -			case r == '-' && minPower <= 4: +			case r == '-' && minPower <= 8:  				lhs = SubexASTMinimise{lhs} -			case r == '|' && minPower <= 2: -				rhs := parseSubex(l, 3) +			case r == '!' && minPower <= 8: +				lhs = SubexASTTry{lhs} +			case r == '?' && minPower <= 8: +				lhs = SubexASTMaybe{lhs} +			case r == '|' && minPower <= 4: +				rhs := parseSubex(l, 5)  				if rhs == nil {  					panic("Missing subex after |")  				}  				lhs = SubexASTOr{lhs, rhs} +			case r == ';' && minPower <= 2: +				rhs := parseSubex(l, 3) +				if rhs == nil { +					panic("Missing subex after ;") +				} +				lhs = SubexASTJoin{ +					content: lhs, +					delimiter: rhs, +				}  			default:  				l.rewind()  				break loop diff --git a/main/regexast.go b/main/regexast.go index 0aab053..a5a60c4 100644 --- a/main/regexast.go +++ b/main/regexast.go @@ -70,3 +70,23 @@ func (ast RegexASTMinimise) compileWith(next RegexState) RegexState {  	state.second = ast.content.compileWith(state)  	return state  } + +type RegexASTTry struct { +	content RegexAST +} +func (ast RegexASTTry) compileWith(next RegexState) RegexState { +	return RegexGroupState{ +		ast.content.compileWith(next), +		next, +	} +} + +type RegexASTMaybe struct { +	content RegexAST +} +func (ast RegexASTMaybe) compileWith(next RegexState) RegexState { +	return RegexGroupState { +		next, +		ast.content.compileWith(next), +	} +} diff --git a/main/subexast.go b/main/subexast.go index 7e2f33c..54cc5fe 100644 --- a/main/subexast.go +++ b/main/subexast.go @@ -115,3 +115,39 @@ func (ast SubexASTOutput) compileWith(next SubexState) SubexState {  		next: next,  	}  } + +type SubexASTTry struct { +	content SubexAST +} +func (ast SubexASTTry) compileWith(next SubexState) SubexState { +	return SubexGroupState { +		ast.content.compileWith(next), +		next, +	} +} + +type SubexASTMaybe struct { +	content SubexAST +} +func (ast SubexASTMaybe) compileWith(next SubexState) SubexState { +	return SubexGroupState { +		next, +		ast.content.compileWith(next), +	} +} + +type SubexASTJoin struct { +	content, delimiter SubexAST +} +func (ast SubexASTJoin) compileWith(next SubexState) SubexState { +	afterContentState := &SubexGroupState { +		nil, +		next, +	} +	manyContentsState := ast.content.compileWith(afterContentState) +	afterContentState.first = ast.delimiter.compileWith(manyContentsState) +	return SubexGroupState { +		manyContentsState, +		next, +	} +} | 
