#82 BNF Grammar

brian Tue 6 Jun 2006

Before I start rewriting the parser in Fan I wanted to capture the formal grammar as it stands today. I will keep this up to date in /src/compiler/fan/frontend/grammar.txt:

===========================================================================
Copyright (c) 2006, Brian Frank and Andy Frank.  All rights reserved.
Licensed under BSD, see http://www.fandev.org/license.txt for terms.

Fan BNF Grammar

  :=      is defined as
  <x>     non-terminal 
  "x"     literal
  [x]     optional
  (x)     grouping
  x*      zero or more times
  x|x     or

@author    Brian Frank
@creation  6 Jun 06
===========================================================================

---------------------------------------------------------------------------
Compilation Units
---------------------------------------------------------------------------

<compilationUnit> :=  [<imports>] <typeDefs>

<imports>         :=  <import>*
<import>          :=  "import" <id> <eos>

---------------------------------------------------------------------------
Type Defs
---------------------------------------------------------------------------

<typeDefs>       :=  <typeDef>*
<typeDef>        :=  <classDef> | <mixinDef> | <enumDef>

<classDef>       :=  <classHeader> <classBody>
<classHeader>    :=  <typeFlags> "class" [<extends>] [<mixin>]
<classBody>      :=  "{" <slotDefs> "}"

<enumDef>        :=  <enumHeader> <enumBody> 
<enumHeader>     :=  <typeFlags> "enum" [<mixin>]
<enumBody>       :=  "{" <enumDefs> <slotDefs> "}"

<mixinDef>       :=  <enumHeader> <enumBody> 
<mixinHeader>    :=  <typeFlags> "mixin" [<mixin>]
<mixinBody>      :=  "{" <slotDefs> "}"

<typeFlags>      :=  [<protection>]
<protection>     :=  "public" | "protected" | "private" | "internal"

<extends>        :=  "extends" <id>
<mixin>          :=  "mixin" <id> ("," <id>)*

---------------------------------------------------------------------------
Slot Defs
---------------------------------------------------------------------------

<enumDefs>       :=  <enumDef> ("," <enumDef>)* <eos>
<enumDef>        :=  <id> ["(" <args> ")"]

<slotDefs>       :=  <slotDef>*
<slotDef>        :=  <fieldDef> | <methodDef> | <ctorDef>

<fieldDef>       :=  <fieldFlags> [<type>] <id> [":=" <expr>] 
                     [ "{" [<fieldGetter>] [<fieldSetter>] "}" ] <eos>
<fieldFlags>     :=  [<protection>] ["readonly"] ["static"]
<fieldGetter>    :=  "get" (<eos> | <block>)
<fieldSetter>    :=  <protection> "set" (<eos> | <block>)

<methodDef>      :=  <methodFlags> <type> <id> "(" <params> ")" <methodBody>
<methodFlags>    :=  [<protection>] ["virtual"] ["override"] ["abstract"] ["static"]
<params>         :=  [<param> ("," <param>)*]
<param>          :=  <type> <id> [":=" <expr>]
<methodBody>     :=  <eos> | ( "{" <stmts> "}" )

<ctorDef>        :=  "new" <id> "(" <params> ")" [ctorChain] <methodBody>
<ctorChain>      :=  <ctorChainThis> | <ctorChainSuper>
<ctorChainThis>  :=  "this" "." <id> "(" <args> ")"
<ctorChainSuper> :=  "super" ["." <id>] "(" <args> ")"

---------------------------------------------------------------------------
Stmt
---------------------------------------------------------------------------

<block>          :=  <stmt> | ( "{" <stmts> "}" )
<stmts>          :=  <stmt>*
<stmt>           :=  <break> | <continue> | <for> | <if> | <return> | 
                     <switch> | <throw> | <while> | <exprStmt> | <localDef>
<break>          :=  "break" <eos>
<continue>       :=  "continue" <eos>                   
<for>            :=  "for" "(" [<forInit>] ";" <expr> ";" <expr> ")" <block>
<forInit>        :=  <expr> | <localDef>
<if>             :=  "if" "(" <expr> ")" <block> [ "else" <block> ]
<return>         :=  "return" [<expr>] <eos>
<throw>          :=  "throw" <expr> <eos>
<while>          :=  "while" "(" <expr> ")" <block>
<exprStmt>       :=  <expr> <eos>       
<localDef>       :=  [<type>] <id> [":=" <expr>] <eos>

<switch>         :=  "switch" "(" <expr> ")" "{" <case>* [<default>] "}"
<case>           :=  "case" <expr> ":" <stmts>
<default>        :=  "default" ":" <stmts>

---------------------------------------------------------------------------
Expr
---------------------------------------------------------------------------

<expr>           :=  <assignExpr>
<assignExpr>     :=  <condOrExpr> [<assignOp> <assignExpr>]
<assignOp>       :=  "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>="  | "&=" | "^=" | "|="
<condOrExpr>     :=  <condAndExpr>  ("||" <condAndExpr>)*
<condAndExpr>    :=  <equalityExpr> ("&&" <equalityExpr>)*
<equalityExpr>   :=  <relationalExpr> (("==" | "!=" | "===" | "!==") <relationalExpr>)*
<relationalExpr> :=  <rangeExpr> (("is" | "as" | "<" | "<=" | ">" | ">=" | "<=>") <rangeExpr>)*
<rangeExpr>      :=  <bitOrExpr> ((".." | "...") <bitOrExpr>)*
<bitOrExpr>      :=  <bitAndExpr> (("^" | "|") <bitAndExpr>)*
<bitAndExpr>     :=  <shiftExpr> (("&" <shiftExpr>)*
<shiftExpr>      :=  <addExpr> (("<<" | ">>") <addExpr>)*
<addExpr>        :=  <multExpr> (("+" | "-") <multExpr>)*
<multExpr>       :=  <parenExpr> (("*" | "/" | "%") <parenExpr>)*
<parenExpr>      :=  <unaryExpr> | <castExpr> | <groupedExpr>
<castExpr>       :=  "(" <type> ")" <parenExpr>
<groupedExpr>    :=  "(" <expr> ")" <termChain>*
<unaryExpr>      :=  <prefixExpr> | <termExpr> | <postfixExpr>
<prefixExpr>     :=  ("!" | "+" | "-" | "~" | "++" | "--") <parenExpr>
<postfixExpr>    :=  <termExpr> ("++" | "--")
<termExpr>       :=  <termBase> <termChain>*
<termBase>       :=  <literal> | <idExpr> | <closure>
<termChain>      :=  <dotExpr>) | <indexExpr>
<dotExpr>        :=  "." <idExpr>
<idExpr>         :=  <id> | <callExpr>
<callExpr>       :=  <id> ["(" <args> ")"] [<closure>]
<args>           := [<expr> ("," <expr>)*]
<closure>        := <methodType> "{" <stmts> "}"
<indexExpr>      := "[" <expr> "]"
<literal>        :=  "null" | "this" | "super" | <bool> | <int> | 
                     <real> | <str> | <duration> | <list> | <map>
<list>           :=  [<type>] "[" <listItems> "]"
<listItems>      :=  "," | (<expr> ("," <expr>)*)
<map>            :=  [<mapType>] "[" <mapItems> "]"
<mapItems>       :=  ":" | (<mapPair> ("," <mapPair>)*)
<mapPair>        :=  <expr> ":" <expr>

---------------------------------------------------------------------------
Type
---------------------------------------------------------------------------

<type>           :=  <simpleType> | <listType> | <mapType> | <methodType>
<simpleType>     :=  <id>
<listType>       :=  <type> "[]"
<mapType>        :=  ["["] <type> ":" <type> ["]"]
<methodType>     :=  "|" <formals> ["->" <type> "|"
<formals>        :=  [<formal> ("," <formal>)*]
<formal>         :=  <type> <id>

---------------------------------------------------------------------------
Misc
---------------------------------------------------------------------------

<id>             := <idStart> (idChar)*
<idStart>        := A-Z | a-z | _
<idChar>         := A-Z | a-z | _ | 0-9
<eos>            := ; | \n | }

brian Tue 12 Sep 2006

I updated the grammar for mixins - a mixin now "extends" other mixins similiar to how a Java interface "extends" rather than "implements" other interfaces.

brian Thu 12 Oct 2006

Two more minor changes:

  • Real changed to Float which means literal r prefix is now f
  • Switched from "import" keyword to "using" keyword (it's a little more explicit, more versatile in other scenerios, and frees import to be used with import/export APIs)

Login or Signup to reply.