Skip to content

Commit

Permalink
Support SAS Viya, issue #787.
Browse files Browse the repository at this point in the history
  • Loading branch information
zufuliu committed Jun 30, 2024
1 parent a083cef commit 4f20795
Show file tree
Hide file tree
Showing 21 changed files with 1,150 additions and 21 deletions.
2 changes: 2 additions & 0 deletions build/CodeLite/Notepad4.project
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
<File Name="../../scintilla/lexers/LexRebol.cxx"/>
<File Name="../../scintilla/lexers/LexRuby.cxx"/>
<File Name="../../scintilla/lexers/LexRust.cxx"/>
<File Name="../../scintilla/lexers/LexSAS.cxx"/>
<File Name="../../scintilla/lexers/LexScala.cxx"/>
<File Name="../../scintilla/lexers/LexSmali.cxx"/>
<File Name="../../scintilla/lexers/LexSQL.cxx"/>
Expand Down Expand Up @@ -258,6 +259,7 @@
<File Name="../../src/EditLexers/stlResource.cpp"/>
<File Name="../../src/EditLexers/stlRuby.cpp"/>
<File Name="../../src/EditLexers/stlRust.cpp"/>
<File Name="../../src/EditLexers/stlSAS.cpp"/>
<File Name="../../src/EditLexers/stlScala.cpp"/>
<File Name="../../src/EditLexers/stlSmali.cpp"/>
<File Name="../../src/EditLexers/stlSQL.cpp"/>
Expand Down
2 changes: 2 additions & 0 deletions build/VS2017/Notepad4.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@
<ClCompile Include="..\..\scintilla\lexers\LexRebol.cxx" />
<ClCompile Include="..\..\scintilla\lexers\LexRuby.cxx" />
<ClCompile Include="..\..\scintilla\lexers\LexRust.cxx" />
<ClCompile Include="..\..\scintilla\lexers\LexSAS.cxx" />
<ClCompile Include="..\..\scintilla\lexers\LexScala.cxx" />
<ClCompile Include="..\..\scintilla\lexers\LexSmali.cxx" />
<ClCompile Include="..\..\scintilla\lexers\LexSQL.cxx" />
Expand Down Expand Up @@ -660,6 +661,7 @@
<ClCompile Include="..\..\src\EditLexers\stlResource.cpp" />
<ClCompile Include="..\..\src\EditLexers\stlRuby.cpp" />
<ClCompile Include="..\..\src\EditLexers\stlRust.cpp" />
<ClCompile Include="..\..\src\EditLexers\stlSAS.cpp" />
<ClCompile Include="..\..\src\EditLexers\stlScala.cpp" />
<ClCompile Include="..\..\src\EditLexers\stlSmali.cpp" />
<ClCompile Include="..\..\src\EditLexers\stlSQL.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions build/VS2017/Notepad4.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@
<ClCompile Include="..\..\scintilla\lexers\LexRust.cxx">
<Filter>Scintilla\lexers</Filter>
</ClCompile>
<ClCompile Include="..\..\scintilla\lexers\LexSAS.cxx">
<Filter>Scintilla\lexers</Filter>
</ClCompile>
<ClCompile Include="..\..\scintilla\lexers\LexScala.cxx">
<Filter>Scintilla\lexers</Filter>
</ClCompile>
Expand Down Expand Up @@ -588,6 +591,9 @@
<ClCompile Include="..\..\src\EditLexers\stlRust.cpp">
<Filter>Source Files\EditLexers</Filter>
</ClCompile>
<ClCompile Include="..\..\src\EditLexers\stlSAS.cpp">
<Filter>Source Files\EditLexers</Filter>
</ClCompile>
<ClCompile Include="..\..\src\EditLexers\stlScala.cpp">
<Filter>Source Files\EditLexers</Filter>
</ClCompile>
Expand Down
4 changes: 4 additions & 0 deletions doc/FileExt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,10 @@ Rust Source
rs


SAS File
sas
sps https://libguides.library.kent.edu/SAS/syntax

Scala Script
scala
sbt Scala Build Tool
Expand Down
3 changes: 3 additions & 0 deletions doc/Notepad4 DarkTheme.ini
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,9 @@ Operator=fore:#A349A4
Keyword=fore:#00B050
Number=fore:#F84C4C
Operator=fore:#A349A4
[SAS File]
Number=fore:#F84C4C
Operator=fore:#A349A4
[Scala Script]
Keyword=fore:#00B050
Number=fore:#F84C4C
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Latest development builds (artifacts in Release configuration for each compiler
* [REBOL](tools/lang/Rebol.r) 3 and [Red](tools/lang/Red.red)
* [Ruby](tools/lang/Ruby.rb), up to Ruby 3.2. [Screenshots](https://github.com/zufuliu/notepad4/wiki/Screenshots#ruby)
* [Rust](tools/lang/Rust.rs), up to Rust 1.38. [Screenshots](https://github.com/zufuliu/notepad4/wiki/Screenshots#rust)
* [SAS](tools/lang/SAS.sas), up to SAS Viya 2024.06.
* [Scala](tools/lang/Scala.scala), up to Scala 3.2.
* Shell Script
* [Bash](tools/lang/Bash.sh) likes (sh, bash, dash, ash, zsh, ksh), up to Bash 5.2. [Screenshots](https://github.com/zufuliu/notepad4/wiki/Screenshots#shell-script)
Expand Down
14 changes: 14 additions & 0 deletions scintilla/include/SciLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#define SCLEX_INTELHEX 118
#define SCLEX_TEKEXTHEX 119
#define SCLEX_JSON 120
#define SCLEX_SAS 125
#define SCLEX_NIM 126
#define SCLEX_CIL 127
#define SCLEX_FSHARP 132
Expand Down Expand Up @@ -1245,6 +1246,19 @@
#define SCE_JSON_ESCAPECHAR 8
#define SCE_JSON_PROPERTYNAME 9
#define SCE_JSON_KEYWORD 10
#define SCE_SAS_DEFAULT 0
#define SCE_SAS_COMMENT 1
#define SCE_SAS_COMMENTBLOCK 2
#define SCE_SAS_NUMBER 3
#define SCE_SAS_OPERATOR 4
#define SCE_SAS_STRINGDQ 5
#define SCE_SAS_STRINGSQ 6
#define SCE_SAS_IDENTIFIER 7
#define SCE_SAS_MACRO 8
#define SCE_SAS_WORD 9
#define SCE_SAS_MACRO_KEYWORD 10
#define SCE_SAS_MACRO_FUNCTION 11
#define SCE_SAS_BASIC_FUNCTION 12
#define SCE_NIM_DEFAULT 0
#define SCE_NIM_COMMENT 1
#define SCE_NIM_COMMENTDOC 2
Expand Down
33 changes: 15 additions & 18 deletions scintilla/include/SciLexer.iface
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ val SCLEX_JSON=120
#val SCLEX_INDENT=122
#val SCLEX_MAXIMA=123
#val SCLEX_STATA=124
#val SCLEX_SAS=125
val SCLEX_SAS=125
val SCLEX_NIM=126
val SCLEX_CIL=127
#val SCLEX_X12=128
Expand Down Expand Up @@ -2424,23 +2424,20 @@ val SCE_JSON_KEYWORD=10
#val SCE_STATA_GLOBAL_MACRO=10
#val SCE_STATA_MACRO=11
# Lexical states for SCLEX_SAS
#lex SAS=SCLEX_SAS SCE_SAS_
#val SCE_SAS_DEFAULT=0
#val SCE_SAS_COMMENT=1
#val SCE_SAS_COMMENTLINE=2
#val SCE_SAS_COMMENTBLOCK=3
#val SCE_SAS_NUMBER=4
#val SCE_SAS_OPERATOR=5
#val SCE_SAS_IDENTIFIER=6
#val SCE_SAS_STRING=7
#val SCE_SAS_TYPE=8
#val SCE_SAS_WORD=9
#val SCE_SAS_GLOBAL_MACRO=10
#val SCE_SAS_MACRO=11
#val SCE_SAS_MACRO_KEYWORD=12
#val SCE_SAS_BLOCK_KEYWORD=13
#val SCE_SAS_MACRO_FUNCTION=14
#val SCE_SAS_STATEMENT=15
lex SAS=SCLEX_SAS SCE_SAS_
val SCE_SAS_DEFAULT=
val SCE_SAS_COMMENT=
val SCE_SAS_COMMENTBLOCK=
val SCE_SAS_NUMBER=
val SCE_SAS_OPERATOR=
val SCE_SAS_STRINGDQ=
val SCE_SAS_STRINGSQ=
val SCE_SAS_IDENTIFIER=
val SCE_SAS_MACRO=
val SCE_SAS_WORD=
val SCE_SAS_MACRO_KEYWORD=
val SCE_SAS_MACRO_FUNCTION=
val SCE_SAS_BASIC_FUNCTION=
# Lexical states for SCLEX_NIM
lex Nim=SCLEX_NIM SCE_NIM_
val SCE_NIM_DEFAULT=
Expand Down
160 changes: 160 additions & 0 deletions scintilla/lexers/LexSAS.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// This file is part of Notepad4.
// See License.txt for details about distribution and modification.
//! Lexer for SAS.

#include <cassert>
#include <cstring>

#include <string>
#include <string_view>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

using namespace Lexilla;

namespace {

//KeywordIndex++Autogenerated -- start of section automatically generated
enum {
KeywordIndex_Keyword = 0,
KeywordIndex_Macro = 1,
KeywordIndex_Function = 2,
};
//KeywordIndex--Autogenerated -- end of section automatically generated

void ColouriseSASDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, LexerWordList keywordLists, Accessor &styler) {
int visibleChars = 0;
int indentCount = 0;
int lineState = 0;
int chPrevNonWhite = 0;

StyleContext sc(startPos, lengthDoc, initStyle, styler);

while (sc.More()) {
switch (sc.state) {
case SCE_SAS_OPERATOR:
sc.SetState(SCE_SAS_DEFAULT);
break;

case SCE_SAS_NUMBER:
if (!IsDecimalNumber(sc.chPrev, sc.ch, sc.chNext)) {
sc.SetState(SCE_SAS_DEFAULT);
}
break;

case SCE_SAS_MACRO:
case SCE_SAS_IDENTIFIER:
if (!IsIdentifierChar(sc.ch)) {
char s[128];
sc.GetCurrentLowered(s, sizeof(s));
if (sc.state == SCE_SAS_MACRO) {
if (keywordLists[KeywordIndex_Macro].InListPrefixed(s + 1, '(')) {
sc.ChangeState((sc.ch == '(') ? SCE_SAS_MACRO_FUNCTION : SCE_SAS_MACRO_KEYWORD);
}
} else if (keywordLists[KeywordIndex_Keyword].InList(s)) {
sc.ChangeState(SCE_SAS_WORD);
} else if (sc.ch == '(' && keywordLists[KeywordIndex_Function].InListPrefixed(s, '(')) {
sc.ChangeState(SCE_SAS_BASIC_FUNCTION);
}
sc.SetState(SCE_SAS_DEFAULT);
}
break;

case SCE_SAS_STRINGDQ:
case SCE_SAS_STRINGSQ:
if ((sc.state == SCE_SAS_STRINGDQ && sc.ch == '\"')
|| (sc.state == SCE_SAS_STRINGSQ && sc.ch == '\'')) {
sc.Forward();
while (IsAlpha(sc.ch)) {
sc.Forward(); // ignore constant type
}
sc.SetState(SCE_SAS_DEFAULT);
}
break;

case SCE_SAS_COMMENT:
case SCE_SAS_COMMENTBLOCK:
if (sc.atLineStart) {
lineState = PyLineStateMaskCommentLine;
}
if ((sc.state == SCE_SAS_COMMENT && sc.ch == ';') || (sc.state != SCE_SAS_COMMENT && sc.Match('*', '/'))) {
if (sc.state != SCE_SAS_COMMENT) {
sc.Forward();
}
sc.ForwardSetState(SCE_SAS_DEFAULT);
if (lineState == PyLineStateMaskCommentLine && sc.GetLineNextChar() != '\0') {
lineState = 0;
}
}
break;
}

if (sc.state == SCE_SAS_DEFAULT) {
if (sc.ch == '\"') {
sc.SetState(SCE_SAS_STRINGDQ);
} else if (sc.ch == '\'') {
sc.SetState(SCE_SAS_STRINGSQ);
} else if (sc.Match('/', '*')) {
sc.SetState(SCE_SAS_COMMENTBLOCK);
sc.Forward();
} else if (sc.Match('%', '*')) { // comment in macro
sc.SetState(SCE_SAS_COMMENT);
} else if (IsNumberStart(sc.ch, sc.chNext)) {
sc.SetState(SCE_SAS_NUMBER);
} else if (IsIdentifierStart(sc.ch) || (sc.ch == '%' && IsIdentifierStart(sc.chNext))) {
sc.SetState((sc.ch == '%') ? SCE_SAS_MACRO : SCE_SAS_IDENTIFIER);
} else if (IsAGraphic(sc.ch)) {
sc.SetState(SCE_SAS_OPERATOR);
if (sc.ch == '*' && AnyOf(chPrevNonWhite, 0, ';', '/')) {
// * ... ; at line start, after statement or comment block
sc.ChangeState(SCE_SAS_COMMENT);
} else if (visibleChars == 0 && (sc.ch == '}' || sc.ch == ']' || sc.ch == ')')) {
lineState |= PyLineStateMaskCloseBrace;
}
}
if (visibleChars == 0 && (sc.state == SCE_SAS_COMMENT || sc.state == SCE_SAS_COMMENTBLOCK)) {
lineState = PyLineStateMaskCommentLine;
}
}

if (visibleChars == 0) {
if (sc.ch == ' ') {
++indentCount;
} else if (sc.ch == '\t') {
indentCount = GetTabIndentCount(indentCount);
} else if (!isspacechar(sc.ch)) {
visibleChars++;
}
}
if (sc.ch > ' ') {
chPrevNonWhite = sc.ch;
}
if (sc.atLineEnd) {
lineState |= (indentCount << 16);
if (visibleChars == 0 && (lineState & PyLineStateMaskCommentLine) == 0) {
lineState |= PyLineStateMaskEmptyLine;
}
styler.SetLineState(sc.currentLine, lineState);
lineState = 0;
visibleChars = 0;
indentCount = 0;
chPrevNonWhite = 0;
}
sc.Forward();
}

sc.Complete();
}

}

LexerModule lmSAS(SCLEX_SAS, ColouriseSASDoc, "sas", FoldPyDoc);
2 changes: 2 additions & 0 deletions scintilla/lexlib/LexerModule.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ extern LexerModule lmRebol;
extern LexerModule lmRLang;
extern LexerModule lmRuby;
extern LexerModule lmRust;
extern LexerModule lmSAS;
extern LexerModule lmScala;
extern LexerModule lmSmali;
extern LexerModule lmSQL;
Expand Down Expand Up @@ -169,6 +170,7 @@ const LexerModule * const lexerCatalogue[] = {
&lmRLang,
&lmRuby,
&lmRust,
&lmSAS,
&lmScala,
&lmSmali,
&lmSQL,
Expand Down
7 changes: 7 additions & 0 deletions scintilla/lexlib/StyleContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,17 @@ class StyleContext final {
Sci_Position LengthCurrent() const noexcept {
return currentPos - styler.GetStartSegment();
}
char GetRelativeChar(Sci_Position n) const noexcept {
return styler.SafeGetCharAt(currentPos + n);
}
int GetRelative(Sci_Position n) const noexcept {
return styler.SafeGetUCharAt(currentPos + n);
}
#if 0
[[deprecated]]
int GetRelativeChar(Sci_Position n, char chDefault) const noexcept {
return styler.SafeGetCharAt(currentPos + n, chDefault);
}
[[deprecated]]
int GetRelative(Sci_Position n, char chDefault) const noexcept {
return styler.SafeGetUCharAt(currentPos + n, chDefault);
Expand Down
10 changes: 10 additions & 0 deletions src/EditAutoC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ static constexpr bool IsSpecialStartChar(int ch, int chPrev) noexcept {
|| (ch == '$') // variable
|| (ch == '`') // VHDL, Verilog directive
|| (ch == '\'')// VHDL attribute
|| (ch == '%') // SAS macro
|| (chPrev == '\\' && (ch == '^' || ch == ':'))// LaTeX input, Emoji input
// TODO: show emoji list after typing ':'.
|| (chPrev == '<' && ch == '/') // HTML/XML Close Tag
Expand Down Expand Up @@ -701,6 +702,7 @@ enum {
PythonKeywordIndex_Decorator = 7,
RebolKeywordIndex_Directive = 1,
RubyKeywordIndex_PredefinedVariable = 4,
SASKeywordIndex_Macro = 1,
ScalaKeywordIndex_Annotation = 3,
ScalaKeywordIndex_Scaladoc = 5,
SmaliKeywordIndex_Directive = 9,
Expand Down Expand Up @@ -1375,6 +1377,13 @@ static AddWordResult AutoC_AddSpecWord(WordList &pWList, int iCurrentStyle, int
}
break;

case NP2LEX_SAS:
if (ch == '%') {
pWList.AddList(pLex->pKeyWords->pszKeyWords[SASKeywordIndex_Macro]);
return AddWordResult_IgnoreLexer;
}
break;

case NP2LEX_SCALA:
if (ch == '@') {
if (iCurrentStyle == SCE_SCALA_DEFAULT) {
Expand Down Expand Up @@ -2731,6 +2740,7 @@ void EditToggleCommentBlock(bool alternative) noexcept {
case NP2LEX_NSIS:
case NP2LEX_RESOURCESCRIPT:
case NP2LEX_RUST:
case NP2LEX_SAS:
case NP2LEX_SCALA:
case NP2LEX_SQL:
case NP2LEX_SWIFT:
Expand Down
Loading

0 comments on commit 4f20795

Please # to comment.