栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【sol】【1】EBNF设计 —— 谈谈以前和以后

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【sol】【1】EBNF设计 —— 谈谈以前和以后

前言

回忆逝去之后,涌上心头的是一股浓重的厌恶感,从前的自己固然美好,却显得弱小而虚伪,蝴蝶还会喜欢毛毛虫吗?雄鹰还会欣赏没毛的丑陋雏鸟吗?——《拔魔》


目录
    • 前言
    • 语言设计
      • 注释和字符串
      • ebnf
        • 1.literal
        • 2.expression
        • 3.block
    • 谈谈以前和以后

   ;
   ;
   ;

语言设计 注释和字符串

注释和字符串不算在文法里,因为已经被处理掉了。注释和字符串前后的引号都被删除了,所有字符串都设计成统一的安全字符串类型(因为字符串不同类型无论在C还是C++中都太麻烦了)。

--单行注释
--[
	多行注释
]
'h'
'hello'
"h"
"hello"

   ;
   ;
   ;

ebnf

ebnf规则,引号中的是终结符,括号是必选的,竖线是或。中括号是可选的,花括号是0及无限。无引号的英文是非终结符。

文法右式中,两个符号间可以有换行符 (空也被消除了)
既然换行可以作为endstat,那么就不能到处都有,需要用 {n} 严格限制换行的使用
endstat是statement的结尾,而iddef的结尾是 ‘n’ 或 ‘;’
所以到处都可以加 ‘n’ 或 ‘;’

1.literal
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 ')' )

   ;
   ;
   ;

2.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


   ;
   ;
   ;

3.block
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来办培训班,似乎用来画图就是自制编程语言最大的作用了。

   ;
   ;
   ;

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/846856.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号