我的编译器 EBNF的方言

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的编译器。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值