ShoneSharp语言(S#)的设计和使用介绍系列(2)— 掀开盖头

来源:互联网 发布:一木成林软件 编辑:程序博客网 时间:2024/06/06 04:01


ShoneSharp语言(S#)的设计和使用介绍

系列(2)— 掀开盖头

作者:Shone

声明:原创文章欢迎转载,但请注明出处。

摘要: 了解一个语言最好的方式就是在编辑器中按照语法规则输入代码,然后运行并查看结果是否符合预期。本博文内容非常重要,承上启下,不但公开了S#语言的所有武功招式——语法规则,并提供了练功的基础工具——编辑器,统统都是干货呀。


一、S#语言揭秘

前面开篇对S#语言进行开宗明义,那么S#语言到底长怎样?是不是那回事?

今天就是来回答这个问题。

S#语言其实前期是个人业余开发的软件产品的一个核心组件,在不断使用中添加功能特性并进行优化,至今词法、语法、语义以及基础类库已比较稳定。开发过程中也深深感受到一个人的力量真的很有限,而S#语言本身架构其实很宏伟,完全可以有更好的发展。今天把之公之于众,就是想把S#语言已有的功能介绍出来,让大家交流和讨论一下,这个语言生命力如何,是否有必要存在下去?可否通过开源力量或其他方式进行发展和壮大?

了解一个语言最好的方式就是在编辑器中按照语法规则输入代码,然后运行并查看结果是否符合预期。下面就公开S#语言的所有武功招式——语法规则,并提供了练功的基础工具——编辑器。语法规则采用Gold Parsing System(http://goldparser.org/)进行定义,高手请详细研究一下,其他人可略过本节,前去下载编辑器。

S#语言秘笈:

"Name"    = 'S# Grammar'

"Version" = '2017.12.1'

"Author"  = 'Shone'

"About"   = 'ShoneSharp Language Grammar'

"Case Sensitive" = True

"Start Symbol"   = <Output>

 

{IdName Head}  = {Letter} + [_]

{IdName Tail}  = {IdName Head} + {Digit}

{Hex}          = {Digit} + ['A''B''C''D''E''F''a''b''c''d''e''f''_']

{Charx}        = {Printable} - ['`'] + {Whitespace}

{Chars}        = {Printable} - [''] + {Whitespace}

{Chars1}       = {Printable} - ['"''\'] + {Whitespace}

{Chars2}       = {Printable} - ['"'] + {Whitespace}

Number         = {Digit}*'.'?{Digit}+(['E''e']['+''-']?{digit}+)? | '0x'{Hex}+

IdName         = {IdName Head}{IdName Tail}* | '`'({Charx} | '`''`')*'`' | '@para' | '@eval' | '@if'| '@case'| '@switch'| '@each'| '@eachx'| '@for'| '@forx'| '@dup'| '@dupx'| '@iter'| '@do'| '@sum'| '@prod'| '@integal'| '@load'| '@parse'| '@call'| '@func'| '@class'| '@foreach'| '@while'| '@var'| '@default'| '@return'| '@break'| '@continue' | '@in' | '@else' | '@true' | '@false' | '@null' | '@local' | '@parent' | '@this' | '@base' | '@host'| '@import' | '@include'

String         = ''({Chars} | '''')*''

String1        = '"'({Chars1} | '\'{Printable})*'"'

String2        = '@''"'({Chars2} | '"''"')*'"'

Comment Line   = '//'

Comment Start  = '/*'

Comment End    = '*/'

OpRange        = '.$' | '.~' | '.<' | '.>' | '.#'

OpRef          = '.' | '@.' | '?.' | '?@.'

Each           = 'each' | 'eachx'

Dup            = 'dup' | 'dupx'

For            = 'for' | 'forx'

Equal          = '=' | '@=' | '=:' | '=@' | ':=' | ':@=' | ':=:' | '@=@' | '::' | '@@'

 

<LData>      ::= '===' <L1s> '==='

<L1s>        ::= <L1> <L1s>

               | <L1>

<L1>         ::= '#1' <Lb> <L2s>

               | '#1' <La>

<L2s>        ::= <L2> <L2s>

               | <L2>

<L2>         ::= '#2' <Lb> <L3s>

               | '#2' <La>            

<L3s>        ::= <L3> <L3s>

               | <L3>

<L3>         ::= '#3' <Lb> <L4s>

               | '#3' <La>

<L4s>        ::= <L4> <L4s>

               | <L4>

<L4>         ::= '#4' <Lb> <L5s>

               | '#4' <La>

<L5s>        ::= <L5> <L5s>

               | <L5>

<L5>         ::= '#5' <La>

<Lb>         ::= IdName ':'

               | <La>

<La>         ::= IdName ':' <Output>

               | <Output>

              

<Data>       ::= '---' <Ls> '---'

<Ls>         ::= <L> <Ls>

               | <L>

<L>          ::= '#1' <Arraylist>

 

<Instanceblk>::= '{' <Instances> '}'                      

<Instances> ::= <Instance> <Instances>

             | <Instance>

<Instance> ::= IdName '{' '}'

             | IdName '{' <Proplist1> '}'

             | IdName '{' <Proplist1> '}' <Instanceblk>

             | IdName <Instanceblk>

             | '<' IdName '/>'

             | '<' IdName <Proplist1> '/>'

             | '<' IdName <Proplist1> '/>' <Instanceblk>

             | '<' IdName '/>' <Instanceblk>

              

<Statement>  ::= <Clauseblock>

               | <Clause>

              

<Clauseblock>::= '{' <Clauselist> '}'              

<Clauselist> ::= <Clause> <Clauselist>

               | <Clause>

                  

<Clause>     ::= <Define>

               | 'case' <Formula> ':'

               | 'default' ':'

               | 'if' '(' <Expression> ')' <Statement>

               | 'if' '(' <Expression> ')' <Sentence> else <Statement>

               | 'if' '(' <Expression> ')' <Clauseblock> else <Statement>

               | 'for' '(' 'var' <Proplist> ';' <Expression> ';' <Changelist> ')' <Statement>

               | 'foreach' '(' 'var' IdName 'in' <Arraylist> ')' <Statement>

               | 'while' '(' <Expression> ')' <Statement>

               | 'do' <Statement> 'while' '(' <Expression> ')' ';'

               | 'switch' '(' <Formula> ')'  <Clauseblock>

               | <Sentence>

              

<Defblock>   ::= '{' <Deflist> '}'                     

<Deflist>    ::= <Define> <Deflist>

               | <Define>

              

<Define>     ::= <Defclause>

               | <Defclass> ';'

               | 'func' <Deffunc> ';'

               | 'var' <Assign> ';'

               | 'import' <Str> ';'

                              

<Defclause>  ::= 'class' IdName <Defblock>

               | 'class' IdName ':' IdName <Defblock>

               | 'func' IdName '(' ')' <Clauseblock>

               | 'func' IdName '(' <Paramlist> ')' <Clauseblock>

               | 'func' IdName '(' <Proplist> ')' <Clauseblock>

                    

<Sentence>   ::= <Change> ';'

               | 'return' <Formulalist> ';'

               | 'break' ';'

               | 'continue' ';'

                             

<Changelist> ::= <Changenode> ',' <Changelist>

               | <Changenode>

              

<Changenode> ::= <Defclause>

               | <Defclass>

               | <Deffunc>

               | <Change>

 

<Defclass>   ::= 'class' <Instance>

               | 'class' IdName ':' IdName '{' <Proplist> '}'

              

<Deffunc>    ::= IdName '(' ')' Equal <Formula>

               | IdName '(' <Paramlist> ')' Equal <Formula>

               | IdName '(' <Proplist> ')' Equal <Formula>

              

<Change>     ::= IdName '+=' <Math>

               | IdName '-=' <Math>

               | IdName '*=' <Math>

               | IdName '/=' <Math>

               | IdName '++'

               | IdName '--'

               | <Assign>

              

<Proplist1>  ::= <Assign> <Proplist1>

               | <Assign>

              

<Proplist>   ::= <Assign> ',' <Proplist>

               | <Assign>

              

<Assign>     ::= <Str>  ':' <Formula>

               | IdName Equal <Formula>

 

<Eachlist>    ::= <Each> ',' <Eachlist>

               | <Each>

<Each>        ::= IdName '@' <Formula>

 

<Caselist>   ::= <Case> ',' <Caselist>

               | <Case>

              

<Case>       ::= <Formula> '->' <Formula>

 

<Paramlist>  ::= <Param> ',' <Paramlist>

               | <Param>

<Param>      ::= IdName

 

 

<Output>     ::= <Arraylist> IdName

               | <Arraylist>

 

<Arraylist>  ::= <Formulalist> ';' <Arraylist>

               | <Formulalist>

 

<Formulalist>::= <Formula> ',' <Formulalist>

               | <Formula>

                           

<Formula>    ::= IdName '=>' <Expression>

               | '(' ')' '=>' <Expression>

               | 'func' '(' <Paramlist> ')' '=>' <Expression>

               | 'func' '(' <Proplist> ')' '=>' <Expression>

               | <Expression>

 

<Expression> ::= <Expression> '||' <Operand6>

               | <Operand6>

 

<Operand6>   ::= <Operand6> '&&' <Operand5>

               | <Operand5>

 

<Operand5>   ::= <Operand5> '==' <Operand4>

               | <Operand5> '!=' <Operand4>

               | <Operand4>

 

<Operand4>   ::= <Operand4> '<' <Math>

               | <Operand4> '>' <Math>

               | <Operand4> '<=' <Math>

               | <Operand4> '>=' <Math>

               | <Math>

 

<Math>       ::= <Math> '+' <Operand2>

               | <Math> '-' <Operand2>

               | <Operand2>

 

<Operand2>   ::= <Operand2> '*' <Operand1>

               | <Operand2> '/' <Operand1>

               | <Operand2> '%' <Operand1>

               | <Operand1>

 

<Operand1>   ::= <Operand1> '^' <Unarand>

               | <Operand1> '$' <Unarand>

               | <Operand1> '#' <Unarand>

               | <Operand1> '&' <Unarand>

               | <Operand1> '|' <Unarand>

               | <Operand1> '$$' <Unarand>

               | <Operand1> '##' <Unarand>

               | <Operand1> '??' <Unarand>

               | <Unarand>  '..' <Unarand>

               | <Unarand>  '...' <Unarand>

               | <Unarand>  '..' <Unarand> OpRange <Unarand>

               | <Unarand>  '...' <Unarand> OpRange <Unarand>

               | <Unarand>

 

<Unarand>    ::= '!' <Unarand>

               | '-' <Unarand>

               | '~' <Unarand>

               | '?' <Unarand>

               | '$' <Unarand>

               | '*' <Unarand>

               | '&' <Unarand>

               | <Referand>

 

<Referand>   ::= <Referand> '[' <Formulalist> ']'

               | <Referand> '[' <Formula> ':' <Formula> ']'

               | <Referand> Number

               | <Referand> OpRef IdName

               | <Referand> OpRef IdName '(' ')'

               | <Referand> OpRef IdName '(' <Formulalist> ')'

               | <Calland>            

 

<Calland>    ::= <Calland> '(' ')'

               | <Calland> '(' <Formulalist> ')'

               | <Calland> '(' <Proplist> ')'

               | <Value>

          

<Value>      ::= Number

               | <Key>

               | <Str>

               | IdName

               | '(' <Formula> ')'

               | '[' <Formulalist> ']'

               | '{' <Arraylist> '}'

               | '{' <Proplist> '}'

               | '[' ']'

               | '{' '}'

               | '{-}'

               | '</>'

               | '(' ')'

               | '(' <Proplist1> ')'

               | '(' <Math> ',' <Math> ')'

               | '(' <Math> ',' <Math> ',' <Math> ')'

               | '<' <Math> ',' <Math> '>'

               | '<' <Math> ',' <Math> ',' <Math> '>'

               | 'load' '(' <Output> ')'

               | 'parse' '(' <Output> ')'

               | 'call' '(' <Output> ')'

               | 'eval' '(' <Changelist> ':' <Output> ')'

               | 'para' '(' <Output> ':' <Proplist> ')'

               | 'func' '(' <Paramlist> ':' <Output> ')'

               | 'func' '(' <Proplist> ':' <Output> ')'

               | 'class' '{' <Proplist> '}'

               | 'class' ':' IdName '{' <Proplist> '}'

               | 'if' '(' <Expression> '?' <Output> ':' <Output> ')'

               | 'case' '(' <Formula> '?' <Caselist> ':' <Output> ')'

               | 'switch' '(' <Assign> '?' <Caselist> ':' <Output> ')'

               | Each '(' <Eachlist> ':' <Output> ')'

               | Each '(' <Eachlist> ';' <Expression> ':' <Output> ')'

               | Each '(' IdName ':' <Eachlist> ':' <Output> ')'

               | Dup '(' <Eachlist> ':' <Output> ')'

               | 'iter' '(' <Assign> ';' <Eachlist> ':' <Change> ')'

               | 'iter' '(' <Assign> ';' IdName ':' <Eachlist> ':' <Change> ')'

               | For '(' <Changelist> ';' <Expression> ';' <Changelist> ':' <Output> ')'

               | 'do' '(' <Assign> ';' <Changelist> ';' <Expression> ';' <Changelist> ':' <Change> ')'

               | 'sum' '(' <Assign> ',' <Math> ':' <Output> ')'

               | 'prod' '(' <Assign> ',' <Math> ':' <Output> ')'

               | 'integal' '(' <Assign> ',' <Math> ':' <Output> ')'

               | 'include' <Str>

               | <Clauseblock>

               | <Instance>

               | <LData>

               | <Data>

              

<Key>        ::= 'null'

               | 'true'

               | 'false'

               | 'local'

               | 'parent'

               | 'this'

               | 'base'

               | 'host'

                             

<Str>        ::= String

               | String1

               | String2

二、S#编辑器

上面语法看不懂,没关系,本系列将会在后续博文进行详细解释。说了半天,其他语言都有IDE,S#语言也不例外,提供集成编辑、解析和运行一体的软件工具,简称S#编辑器,文件名为ShoneSharp.exe。

是驴是马拉出来溜溜的时候到了,围观的观众也可以准备好口水或板砖了。

1) 软件下载

S#语言编辑解析运行器为Shone的原创软件,运行环境.NET 4.0,为绿色软件可直接拷贝运行,单个EXE文件无任何依赖,无注册表、广告等任何副作用。

网盘下载链接为https://pan.baidu.com/s/1dF4e08p

说明一下,ShoneSharp.exe大小接近6M,核心其实只有2M左右,其他主要为语法着色、二维显示、智能帮助等高级功能。这是目前暂时从本人已有软件产品中完全剥离出来的可独立运行功能,其实还是依赖了.NET的WPF界面库,将来如果开源的话,可能还要进行组件拆分,尽量把非界面部分全部基于最新的.NET Standard 2.0开发,以便能够实现跨平台,这是后话。

2) 软件界面

经典语言的入门程序都是编写HelloWorld,那么在S#语言中是啥样?运行S#编辑器软件,输入"Hello, world. 您好,我来了!",右下角就直接显示代码的运行结果,如果是几何代码还可以看到相应图形,如下图。

                       

什么没有print,没有Console.Write,怎么能输出呢?这里再强调一下,S#语言最有特色的地方就是“数据即程序、程序即数据”,这点和LISP有点像,不过LISP采用(前缀表达,S#语言则采用惯用表达,前缀、中缀、后缀怎么方便怎么来。

由于本博有点长了,编辑器详细功能介绍放到下一节再介绍。有兴趣的观众可以先下载软件试试玩一下,应该还是比较简单容易上手。