回忆逝去之后,涌上心头的是一股浓重的厌恶感,从前的自己固然美好,却显得弱小而虚伪,蝴蝶还会喜欢毛毛虫吗?雄鹰还会欣赏没毛的丑陋雏鸟吗?——《拔魔》
目录
- 前言
- 语言设计
- 注释和字符串
- ebnf
- 1.literal
- 2.expression
- 3.block
- 谈谈以前和以后
;
;
;
注释和字符串不算在文法里,因为已经被处理掉了。注释和字符串前后的引号都被删除了,所有字符串都设计成统一的安全字符串类型(因为字符串不同类型无论在C还是C++中都太麻烦了)。
--单行注释 --[ 多行注释 ] 'h' 'hello' "h" "hello"
;
;
;
ebnf规则,引号中的是终结符,括号是必选的,竖线是或。中括号是可选的,花括号是0及无限。无引号的英文是非终结符。
1.literal
文法右式中,两个符号间可以有换行符(空也被消除了)
既然换行可以作为endstat,那么就不能到处都有,需要用 {n} 严格限制换行的使用
endstat是statement的结尾,而iddef的结尾是 ‘n’ 或 ‘;’
所以到处都可以加 ‘n’ 或 ‘;’
program ::= { block }
literal ::= number | string | 'true' | 'false'
statement ::= ( iddef | assign_stat | expression | function_call | return_stat | sizeof_stat | typeof) endstat |
('break'|'exit'|'next'|'again') endstat
endstat(25) ::= ';'|'n'|')'|']'|'}'|','|':'|'?'|
'>'|'<'|'>='|'<='|'=='|'!='|'==='|'!=='|
'and'|'or'|'nand'|'nor'|'xor'|'xnor'|'elif'|'else'|
EOF
type_simple(12) ::= 'byte'|'i2'|'ui2'|'i4'|'ui4'|'i8'|'ui8'|'f4'|'f8'|
'bigf'|'string'|'bool'
type(19) ::= type_simple |'any'|'fn'|'class'|'enum'|'mach'|'list'|'dict'
typedef ::= ':' type
number ::= int_number | float_number
int_number ::= decimal_number | binary_number | oct_number | hex_number
decimal_number ::= ['+'|'-'] num_unit
float_number ::= ['+'|'-']
num_unit ['.' num_unit ]
['e'|'E' ['+'|'-'] num_unit ]
num_unit ::= '0-9' '_' { '0-9' '_' } '0-9'
binary_number ::= '0b' ('0'|'1') '_' { ('0'|'1') '_' } ('0'|'1')
oct_number ::= '0o' ('0-7') '_' { ('0-7') '_' } ('0-7')
hex_number ::= '0x' ('0-9'|'a-f'|'A-F') '_' { ('0-9'|'a-f'|'A-F') '_' } ('0-9'|'a-f'|'A-F')
string ::= (单引号中间所有|双引号中间所有) |
('' (''|'t'|'a'|'b'|'f'|'v'|单引号|双引号))
identifier ::= id_pre { id_unit }
id_list ::= identifier { ',' identifier}
id_pre ::= ('a'-'z')|('A'-'Z')|'_'
id_unit ::= id_pre | ('0'-'9')
binary_op ::= '+'|'–'|'*'|'/'|'^'|'%'|
'.+'|'.–'|'.*'|'./'|'.^'|'.%'|
'+='|'–='|'*='|'/='|'^='|'%='|
'{'|'}'|'('|')'|'['|']'|
'.'|'..'|'...'|','|
'&'|'|'|'<<'|'>>'|'~'|
'$'|'@'|'?'|':'|'->'|';'|
'!='|'!=='|'=='|'==='|'<'|'>'|'<='|'>='|
'=>'|'||'|'&&'|'::'|''|'#'|
'and'|'or'|'nand'|'nor'|'xor'|'xnor'
unary_op ::= '!'|'not'|'+'|'-'
sizeof_stat ::= 'sizeof' ( variable | '(' expression ')' )
typeof_stat ::= 'typeof' ( variable | '(' expression ')' )
;
;
;
iddef ::= ('let'|'const'|'static'|type_simple)
initial_assign_expr {',' initial_assign_expr }
('n'|';')
expression ::= judge_expr |
logic_expr |
arth_expr |
bit_arth_expr
expr_list ::= expression { ',' expression } [',']
bit_arth_expr ::= variable [ ('&'|'|'|'~'|'<<'|'>>') variable ]
arth_expr ::= bit_arth_expr { ('+'|'-'|'*'|'/'|'^'|'%'|'.+'|'.-'|'.*'|'./'|'.^'|'.%') bit_arth_expr }
judge_expr ::= arth_expr { ('>'|'<'|'>='|'<='|'=='|'!='|'==='|'!==') arth_expr }
logic_expr ::= judge_expr { ('and'|'or'|'nand'|'nor'|'xor'|'xnor') judge_expr }
simple_variable ::= identifier { ('.' simple_variable)|( '[' expression ']' ) }
variable ::= variable_unit { ('.' variable)|('[' expression ']') } |
'(' (expression | anony_funcdef | regex_expr | three_op_expr) ')' |
list_expr |
dict_expr
variable_unit ::= literal | identifier | function_call
return_stat ::= 'return' expr_list
function_call ::= variable '(' [expr_list] ')' |
[ '(' [expr_list] ')' ] '@' ( identifier | '(' variable ')' )
anony_funcdef ::= 'fn' '(' [param_list] ')' [typedef]
'{' {block|return_stat} '}'
('n'|';')
initial_assign_expr::= identifier { '=' simple_variable }
[ '=' (expression | anony_funcdef | regex_expr | three_op_expr ) ]
assign_stat ::= simple_variable ('='|'+='|'-='|'*='|'/='|'^='|'%=') expression
list_expr ::= '[' list_unit { ',' list_unit } [','] ']'
list_unit ::= list_expr|dict_expr|statement
dict_expr ::= '{' dict_unit { ',' dict_unit } [','] '}'
dict_unit ::= (int_number|string|'true'|'false') ':'
(list_expr|dict_expr|statement )
regex_expr ::= '/' 除/的所有符号 '/' [regex_expr_appendix][regex_expr_appendix][regex_expr_appendix]
regex_expr_suffix ::= 'g'|'i'|'m'
three_op_expr ::= judge_expression '?' statement ':' statement
;
;
;
block ::= (
Begin_block | End_block | if_block |
while_block | until_block | when_block |
dowhile_block | dountil_block | for_block |
functiondef_block | moduledef_block | enumdef_blcok |
class_block | machinedef_block |
{ statement }
)
('n'|';')
Begin_block ::= 'Begin' '{' block '}'
End_block ::= 'End' '{' block '}'
if_block ::= 'if' '(' judge_expr ')' ( '{' block '}' | statement )
{'elif' '(' judge_expr ')' ( '{' block '}' | statement ) }
['else' ( '{' block '}' | statement ) ]
while_block ::= 'while' '(' judge_expr ')'
( ('{' block '}') | statement )
until_block ::= 'until' '(' judge_expr ')'
( ('{' block '}') | statement )
dowhile_block ::= 'do' '{' block '}'
'while' '(' judge_expr ')'
dountil_block ::= 'do' '{' block '}'
'until' '(' judge_expr ')'
when_block ::= 'when' '(' judge_expr ')' ( ('{' block '}') | statement )
for_block ::= 'for' '(' identifier 'in'
(range_expr | variable | list_expr | dict_expr | string)
')'
( ('{' block '}') | statement )
range_expr ::= 'range' '('
(decimal_number|float_number)
[ ',' (decimal_number|float_number) ]
[ ',' (decimal_number|float_number) ]
')'
module_block ::= 'mod' identifier '{' block '}'
functiondef_block ::= 'fn' identifier '(' [param_list] ')' [typedef]
'{' (block|return_stat) '}'
param_list ::= identifier [typedef]
{',' identifier [typedef] }
[',' '...']
enumdef_block ::= 'enum' identifier '{'
identifier { ',' identifier } [',']
'}'
class_block ::= 'class' identifier [ '(' id_list ')' ]
'{' functiondef_block '}'
machinedef_block ::= 'mach' identifier '{'
identifier 'if' identifier '->' identifier 'use' identifier
{ ',' identifier 'if' identifier '->' identifier 'use' identifier }
[',']
'}'
;
;
;
刚开始是2020年1月,那时候放假了开心。契机是买了本《两周实现一门脚本语言》,虽然这书完全看不懂,语法库直接用parser,当时又不知道资源在哪。这个库怎么运作的作者也不说,用的最恶心的java实现,我实在是蚌埠住了。
然后看了一点后,我先去复习了一下黑马IT的C++数据结构课程中的前缀表达式实现计算器,就是读取一条字符串,然后用栈算个数出来。接着我改进了一下,让它可以识别浮点数和指数,又能调用单参数的函数。但是这听着好像不错啊,是个语言了!但实际上简单多了,和编译器基本没什么关系——我以前还写过编译器就是读取文件的字符串,就是字符串处理,这是一个错误。总是想着,不就是这样,不就是那样,这样会让自己偷懒不去思考,一点点的差别也会有很大的不同,差次品就算比优质品低许多也有存在的意义。
在表达式和语句的处理上,表达式算是语句的子集。在处理算术运算时,需要考虑优先级和六个基本运算符。表达式的抽象语法树到底是左结合还是右结合,不仅和当前运算符有关,也和之前的运算符有关。我当时做的第二个语言项目Suatin,其处理方式就是利用两三千的各种判断和函数和递归和lambda表达式,来更改语法树。在这个过程中我惊讶于自己能做这么复杂的事,现在让我再看我也看不懂写的什么。容易做的东西通常也没有什么价值,在制作表达式的语法分析树时我不知道优先级用在哪,每个分支都是判断具体符号!我也不知道这样和用算法相比是快还是慢(一百万个数的空for循环运行完耗费1秒)。
后来又发生了很多事,毕竟几十篇没用的编译器相关的文章摆在哪。两年里买了十几本书,好多我都看不懂写的什么也不想跟着抄(试过,结论是水平太差跟着是学不会的)。以前总想着资源好少,做了一点工作也很牛逼了吧!是的,每次跟人家说他们都以为我好牛逼,呵呵!后来手上的资源越来越多,原来做这个很简单,很多人都做过,但是激不起水花。我又能怎么办,要不还是放弃吧!
按照沉没成本的理论来说,早点离场损失的少。可是我不甘心啊!理智又告诉我,我技术又不比别人厉害,简单的事大家都玩出花了,到底该怎么办?最羡慕是还是萧井陌了,他至少能用gualang来办培训班,似乎用来画图就是自制编程语言最大的作用了。
;
;
;



