@@ -373,6 +373,34 @@ Sci_Position CheckBraceFormatSpecifier(const StyleContext &sc, LexAccessor &styl
373373	return  pos - sc.currentPos ;
374374}
375375
376+ constexpr  bool  IsMatchExpressionStart (int  ch, int  chNext) noexcept  {
377+ 	return  IsADigit (ch) || (ch == ' .'   && IsADigit (chNext))
378+ 		|| (chNext != ' ='   && AnyOf (ch, ' *'  , ' +'  , ' -'  ,  ' ~'  , ' ('  , ' ['  , ' {'  ));
379+ }
380+ 
381+ bool  IsSoftKeyword (const  char  *s, const  StyleContext &sc, LexAccessor &styler) noexcept  {
382+ 	//  match expression
383+ 	//  case pattern
384+ 	//  type identifier
385+ 	int  ch = sc.ch ;
386+ 	int  chNext = sc.chNext ;
387+ 	if  (IsWhiteSpace (sc.ch )) {
388+ 		Sci_PositionU pos = sc.currentPos  + 1 ;
389+ 		while  (pos < sc.lineStartNext ) {
390+ 			const  uint8_t  chAfter = styler[pos++];
391+ 			if  (!IsWhiteSpace (chAfter)) {
392+ 				if  (IsIdentifierStartEx (chAfter)) {
393+ 					return  true ;
394+ 				}
395+ 				ch = chAfter;
396+ 				chNext = static_cast <uint8_t >(styler[pos]);
397+ 				break ;
398+ 			}
399+ 		}
400+ 	}
401+ 	return  s[0 ] != ' t'   && IsMatchExpressionStart (ch, chNext);
402+ }
403+ 
376404constexpr  bool  IsDocCommentTag (int  state, int  chNext) noexcept  {
377405	return  IsPyString (state) && IsPyTripleQuotedString (state) && (chNext == ' p'   || chNext == ' t'   || chNext == ' r'  );
378406}
@@ -408,7 +436,6 @@ void ColourisePyDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
408436	int  chPrevNonWhite = 0 ;
409437	int  prevIndentCount = 0 ;
410438	int  indentCount = 0 ;
411- 	int  parenCount = 0 ;
412439	int  lineState = 0 ;
413440	bool  prevLineContinuation = false ;
414441	bool  lineContinuation = false ;
@@ -427,7 +454,6 @@ void ColourisePyDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
427454	if  (sc.currentLine  > 0 ) {
428455		prevLineContinuation = (styler.GetLineState (sc.currentLine  - 2 ) & PyLineStateLineContinuation) != 0 ;
429456		lineState = styler.GetLineState (sc.currentLine  - 1 );
430- 		parenCount = (lineState >> 8 ) & 0xff ;
431457		prevIndentCount = lineState >> 16 ;
432458		lineContinuation = (lineState & PyLineStateLineContinuation) != 0 ;
433459		lineState = 0 ;
@@ -460,6 +486,10 @@ void ColourisePyDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
460486						kwType = KeywordType::Function;
461487					} else  if  (StrEqualsAny (s, " class"  , " raise"  , " except"  )) {
462488						kwType = KeywordType::Class;
489+ 					} else  if  (StrEqualsAny (s, " match"  , " case"  , " type"  )) {
490+ 						if  (visibleChars != sc.LengthCurrent () || !IsSoftKeyword (s, sc, styler)) {
491+ 							sc.ChangeState (SCE_PY_IDENTIFIER);
492+ 						}
463493					}
464494				} else  if  (keywordLists[KeywordIndex_Type].InList (s)) {
465495					sc.ChangeState (SCE_PY_WORD2);
@@ -473,10 +503,13 @@ void ColourisePyDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
473503					sc.ChangeState (SCE_PY_OBJECT_FUNCTION);
474504				} else  if  (keywordLists[KeywordIndex_Class].InList (s)) {
475505					sc.ChangeState (SCE_PY_CLASS);
476- 				} else  if  (kwType != KeywordType::None) {
477- 					sc.ChangeState (static_cast <int >(kwType));
478- 				} else  if  (sc.GetLineNextChar () == ' ('  ) {
479- 					sc.ChangeState (SCE_PY_FUNCTION);
506+ 				}
507+ 				if  (sc.state  == SCE_PY_IDENTIFIER) {
508+ 					if  (kwType != KeywordType::None) {
509+ 						sc.ChangeState (static_cast <int >(kwType));
510+ 					} else  if  (sc.GetLineNextChar () == ' ('  ) {
511+ 						sc.ChangeState (SCE_PY_FUNCTION);
512+ 					}
480513				}
481514				if  (sc.state  != SCE_PY_WORD) {
482515					kwType = KeywordType::None;
@@ -801,12 +834,8 @@ void ColourisePyDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
801834				}
802835			} else  if  (IsIdentifierStartEx (sc.ch )) {
803836				sc.SetState (SCE_PY_IDENTIFIER);
804- 			} else  if  (sc.ch  == ' @'  ) {
805- 				if  (!lineContinuation && visibleChars == 0  && parenCount == 0  && IsIdentifierStartEx (sc.chNext )) {
806- 					sc.SetState (SCE_PY_DECORATOR);
807- 				} else  {
808- 					sc.SetState (SCE_PY_OPERATOR);
809- 				}
837+ 			} else  if  (sc.ch  == ' @'   && visibleChars == 0  && IsIdentifierStartEx (sc.chNext )) {
838+ 				sc.SetState (SCE_PY_DECORATOR);
810839			} else  if  (IsAGraphic (sc.ch ) && sc.ch  != ' \\ '  ) {
811840				kwType = KeywordType::None;
812841				const  bool  interpolating = !nestedState.empty ();
@@ -815,8 +844,6 @@ void ColourisePyDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
815844				if  (sc.ch  == ' {'   || sc.ch  == ' ['   || sc.ch  == ' ('  ) {
816845					if  (interpolating) {
817846						nestedState.back ().parenCount  += 1 ;
818- 					} else  {
819- 						++parenCount;
820847					}
821848				} else  if  (sc.ch  == ' }'   || sc.ch  == ' ]'   || sc.ch  == ' )'  ) {
822849					if  (interpolating) {
@@ -826,9 +853,6 @@ void ColourisePyDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
826853							--state.parenCount ;
827854						}
828855					} else  {
829- 						if  (parenCount > 0 ) {
830- 							--parenCount;
831- 						}
832856						if  (visibleChars == 0 ) {
833857							lineState |= PyLineStateMaskCloseBrace;
834858						}
@@ -865,7 +889,7 @@ void ColourisePyDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
865889					++indentCount;
866890				}
867891			}
868- 			lineState |= (indentCount << 16 ) | (parenCount <<  8 ) ;
892+ 			lineState |= (indentCount << 16 );
869893			prevIndentCount = indentCount;
870894			prevLineContinuation = lineContinuation;
871895			lineContinuation = false ;
0 commit comments