瞭解一個語言最好的方式就是在編輯器中按照語法規則輸入代碼,然後運行並查看結果是否符合預期。本博文內容非常重要,承上啟下,不但公開了S#語言的所有武功招式——語法規則,並提供了練功的基礎工具——編輯器,統統都是乾貨呀。 ...
ShoneSharp語言(S#)的設計和使用介紹
系列(2)— 掀開蓋頭
作者:Shone
聲明:原創文章歡迎轉載,但請註明出處,https://www.cnblogs.com/ShoneSharp。
摘要: 瞭解一個語言最好的方式就是在編輯器中按照語法規則輸入代碼,然後運行並查看結果是否符合預期。本博文內容非常重要,承上啟下,不但公開了S#語言的所有武功招式——語法規則,並提供了練功的基礎工具——編輯器,統統都是乾貨呀。
軟體: S#語言編輯解析運行器,運行環境.NET 4.0,綠色軟體,單個EXE直接運行,無副作用。網盤下載鏈接為https://pan.baidu.com/s/1dF4e08p
一、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#語言則採用慣用表達,首碼、中綴、尾碼怎麼方便怎麼來。
由於本博有點長了,編輯器詳細功能介紹放到下一節再介紹。有興趣的觀眾可以先下載軟體試試玩一下,應該還是比較簡單容易上手。
附註:由於初來乍到博客園,園齡太短,關註度太小,如果那位大拿覺得本人系列介紹將會有用,請幫轉發或頂一下,在此先謝了:-)
聲明:原創文章歡迎轉載,但請註明出處,https://www.cnblogs.com/ShoneSharp。
軟體: S#語言編輯解析運行器,運行環境.NET 4.0,綠色軟體,單個EXE直接運行,無副作用。網盤下載鏈接為https://pan.baidu.com/s/1dF4e08p