分享
 
 
 

我的编译器 EBNF的方言

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

C3语言定义(EBNF方言)

关键字:

Section

Class

End

Scanner

Parser

Rule

Label

Letter

Digit

LetterOrDigit

UpperLetter

LowerLetter

Symbol

WhiteSpace

CrLf

操作符:

=>

,

+

*

[]

!

|

其它字符:

()

;

其中Section,Class,End,Rule,Label为EBNF语言通用关键字。

Label只允许使用一个终结符作为推导。

Scanner,Parser作为特殊关键字,表示扫描器和分析器的规则。

Letter等为Scanner规则专用关键字,它将对应于其字面意义的字符类型。

=> 为推导符,表示前面的规则是由后面的产生式推导出来的。不允许出现在推导表达式中。

; 为推导结束符号,类似于c中的逻辑行结束符。

, 为连接符,也可以使用空白。

+ 为正闭包,后置运算符,表示其前面的元素的正整数次幂是可接受的。

* 星闭包,后置运算符,表示其前面的元素的自然数次幂是可接受的。

[] 可选,表示其中的元素可以匹配也可以不匹配。

() 括号,处理优先级问题。

! 非,后置运算符,扫描器规则专用。并且只允许单个字符或其或操作进行非操作。

| 或,表示可以匹配多个元素中的一个。

其中*,+,!为一元运算符。

连接和或为二元运算符。

优先级为

!>*=+>连接>或

区别Unicode字符与普通字符。

由于实现问题,扫描器的规则使用Label型的字符串表示的.NET正则表达式。而不是标准的EBNF语言的语义。主要是转换上的技术问题。

示例代码:

1. ID=>Letter+;

上面的例子是说标签ID是由字符的正闭包组成的,即一个或多个字符组成。例如:a,aaaaa,Hello….都是合法的ID,而a2,__a__都是不合法的。

2. ID=>LetterOrDigit*;

ID由字符或数字的星闭包,即0个或多个字符或数字组成。例如:φ,aa,sss,a3,a2都是合法的。

3. ID=>Letter!+;

ID由不是字符的符号组成。例如:32-9023&*)是合法的,而234af是不合法的。

4. ID=>”Hello”;

ID只有一个合法形式,即Hello,其他形式一概不合法。

5. ID=>”Hello”|”Hi”;

ID只有两个合法形式,即Hello和Hi,其他形式一概不合法。

6. ID=>”aaa”[“sss”]”ddd”;

ID可以匹配aaaddd也可以匹配aaasssddd,即sss是可选的。

注意事项:

不要把WhiteSpace关键字作为语句的开始,因为它不生成匹配代码。规则调用要放在终结符匹配之前。

这样,一个EBNF方言的基本结构已经渐渐呈现出来了。接下来我们使用C3来描述它自己。同时我们就可以看到C3的用法以及证明其可用性。

EBNF自描述:

Class Scanner '这是必不可少的,否则没有扫描器,整个编译器都没法工作。

Section Operator '操作符段,标识所有的操作符,可以使用与VB类似的单词型的操作符。

Label Trans=>"=>"; '推导符,表示右边的表达式是左边的规则的推导。

Label EndLine=>";"; '由于有些规则非常长,以及出于代码的可读性的担心,

'使用结束符来表示语句的结束,同时由于忽略空白的特性

'使其可以和C语言一样将语句分成多个行来书写以增强可读性。

Label Join=>","; '在初期的策划中,空白有意义,但在后继版本中,空白

'不再有意义,所以间隔两个单词就需要一个分隔符,由此保留。

Label Positive=>"+"; '正闭包

Label Repeat=>"*"; '星闭包

Label LOpt=>"["; '可选开始

Label ROpt=>"]"; '可选结束。可选符实际上有两个符号组成,由于也是括

'号所以也有分割/改变优先级的作用。

Label Not=>"!"; '非,只可用于扫描器的单字符或字符集。

End Section

Section KeyWord '关键字段,将所有的关键字都放在这里。

Label K_Section=>"Section"; '用于声明区段

Label K_Class=>"Class"; '声明类,实际上目前的语法只有两个类,即Scanner和Parser

Label K_End=>"End"; '结束区段或类

Label K_Scanner=>"Scanner"; '

Label K_Parser=>"Parser"; '

Label K_Rule=>"Rule"; '声明一个语法规则

Label K_Label=>"Label"; '声明一个字符串常量

Section Letters

Label K_Letter=>"Letter";

Label K_Digit=>"Digit";

Label K_LOD=>"LetterOrDigit";

Label K_Upper=>"UpperLetter";

Label K_Lower=>"LowerLetter";

Label K_Symbol=>"Symbol";

Label K_WhiteSpace=>"WhiteSpace";

End Section

Label K_CrLf=>"CrLf";

End Section

Section Comment

Label LineComment=>"'"; '注释

End Section

Section Other '这个段的规则使用.NET的正则表达式而简化

'转换的复杂性

Rule ID=>("_"LetterOrDigit|Letter)("_"|LetterOrDigit)*; '"((_[\d\p{L}])|\p{L})[_\d\p{L}]*"

Rule String=>""""(""""!|"""""")*""""; '"""([^""]|"""")*"""

End Section

End Class

Class Parser

Rule Program=>ScannerDecl ParserDecl; '扫描器类在前,分析器类在后。

Rule ScannerDecl=>

"Class" "Scanner"

[OperatorSection]

[KeyWordSection]

[CommentSection]

[OtherRuleSection]

"End" "Class";

Rule OperatorSection=>

"Section" "Operator"

SCSectionDecl*

LabelDecl*

"End" "Section";

Rule KeyWordSection=>

"Section" "KeyWord"

SCSectionDecl*

LabelDecl*

"End" "Section";

Rule CommentSection=>

"Section" "Comment"

[LineComDecl]

[BlockComStart '声明了开始符就必须声明结束符,否则将被忽略。

BlockComEnd]

"End" "Section";

Rule OtherSection=>

"Section" "Other"

SCSectionDecl*

LabelDecl*

"End" "Section";

Rule LineComDecl=>"Rule" "LineComment" "=>" String; '注释符显然只能是一个字符串。

Rule BlockComStart=>"Rule" "BlockCommentStart" "=>" String;

Rule BlockComEnd=>"Rule" "BlockCommentEnd" "=>" String;

Rule SCSectionDecl=>

"Section" ID

(LabelDecl|SCRuleDecl)*

"End" "Section";

Rule SCROSectionDecl=> '只允许声明规则的Section,这是上面的规范所要求的,

'但是为了实现上的方便,实际上并没有使用。

"Section" ID

SCRuleDecl*

"End" "Section";

Rule LabelDecl=>"Label" ID "=>" String;

Rule SCRuleDecl=>"Rule" ID "=>" SCExp;

Rule SCQExp=>("(" SCExp ")")|("[" SCExp "]");

Rule SCExp=>SCOrExp["!"]["*"|"+"];

Rule SCOrExp=>SCJoinExp("|" SCJoinExp)*;

Rule SCJoinExp=>SCExpElem([","] SCExpElem)*;

Rule SCExpElem=>String|Letters|SCQExp;

'下面的是分析器的

Rule ParserDecl=>

"Class" "Parser"

(SectionDecl

|RuleDecl)*

"End" "Class";

Rule RuleDecl=>"Rule" ID "=>" Exp;

Rule QExp=>("(" Exp ")")|("[" Exp "]");

Rule Exp=>OrExp["!"]["*"|"+"];

Rule OrExp=>JoinExp("|" JoinExp)*;

Rule JoinExp=>ExpElem([","] ExpElem)*;

Rule ExpElem=>String|ID|QExp;

Rule SectionDecl=>

"Section" ID

(LabelDecl|RuleDecl)*

"End" "Section";

Rule ROSectionDecl=>'只允许声明规则的Section

"Section" ID

RuleDecl*

"End" "Section";

End Class

给出上面的EBNF自描述的目的在于既可以使人更深入的了解C3的目的、格式、含义、语法。接下来我们要着手实现这个C3的编译器。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有