Name: long long 2012-01-13 22:59
I'm creating yet another fail C-family compiler.
Objectives: simple language, generics, type inference, and unambiguous grammar.
I would like to hear your opinions, any help is very appreciated.
bison parser:
%union {
char *str;
}
%right '=' "+=" "-=" "*=" "/=" "%=" "~=" "&=" "|=" "^=" "<<=" ">>="
%left ':'
%right '?'
%left '|'
%left '^'
%left '&'
%left "or"
%left "and"
%left "==" "!="
%left '<' "<=" '>' ">="
%left "<<" ">>"
%left '+' '-'
%left '*' '/' '%'
%right "not" '~' PREFIX
%left "++" "--"
%left '['
%left '.'
%right '$'
%token <str> ID INT HEX BIN DOUBLE FLOAT COMPLEX STRING CHAR
%token-table
%%
program:
| program import
| program decl
;
import: "import" module
| "import" module "as" identifier
;
module: identifier
| module '.' identifier
;
decl: declvar
| declfunc
| declstruct
;
declvar: "var" identifier
| "var" identifier '=' expr
| "def" identifier '=' expr
;
declstruct: "def" identifier '{' declattrs '}'
;
declattrs: declattr
| declattrs declattr
;
declattr: "var" identifier
| declfunc
;
declfunc: "def" identifier '(' declargs ')' block
;
declargs: declarg
| declargs ',' declarg
;
declarg: identifier
| "var" identifier
| identifier identifier
;
block: '{' '}'
| '{' stmts '}'
;
stmts: stmt
| block
| stmts stmt
| stmts block
;
stmt: declvar
| purestmt
| identifier ':' purestmt
;
purestmt: assign
| call
| if
| for
| while
| switch
| "goto" identifier
| "return" expr
;
assign: lvalue '=' expr
| lvalue "+=" expr
| lvalue "-=" expr
| lvalue "*=" expr
| lvalue "/=" expr
| lvalue "%=" expr
| lvalue "~=" expr
| lvalue "&=" expr
| lvalue "|=" expr
| lvalue "^=" expr
| lvalue "<<=" expr
| lvalue ">>=" expr
| lvalue "++"
| lvalue "--"
// | "++" lvalue %prec PREFIX
// | "--" lvalue %prec PREFIX
;
lvalue: identifier
| lvalue '.' identifier
| lvalue '[' expr ']'
| '$' lvalue
;
identifier: ID
;
expr: literal
| lvalue
| assign
| call
| '~' expr
| '@' lvalue
| '-' expr %prec PREFIX
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '%' expr
| expr '&' expr
| expr '|' expr
| expr '^' expr
| "not" expr
| expr "==" expr
| expr "!=" expr
| expr '<' expr
| expr "<=" expr
| expr '>' expr
| expr ">=" expr
| expr "<<" expr
| expr ">>" expr
| expr "and" expr
| expr "or" expr
| expr '?' expr ':' expr
| "proc" '(' declargs ')' block
| '(' expr ')'
;
literal: INT
| HEX
| BIN
| FLOAT
| DOUBLE
| COMPLEX
| STRING
| CHAR
;
call: onecall
| call '.' onecall
;
onecall: lvalue '(' args ')'
;
args:
| expr
| args ',' expr
;
if: "if" '(' expr ')' block
| "if" '(' expr ')' block "else" block
;
for : "for" '(' forarg "in" foriter ')' loop
| "for" '(' forinit ';' expr ';' forincr ')' loop
;
forarg: identifier
| "var" identifier
;
forinit: forinitarg
| forinit ',' forinitarg
;
forinitarg: assign
| "var" identifier '=' expr
;
forincr: assign
| forincr ',' assign
;
foriter: lvalue
| call
;
loop: ';'
| loopblock
;
loopblock: '{' '}'
| '{' loopstmts '}'
;
loopstmts: loopstmt
| loopstmts loopstmt
;
loopstmt: "break"
| "continue"
| loopblock
| stmt
;
while: "while" '(' expr ')' loop
| "do" loopblock "while" '(' expr ')'
;
switch: "switch" '(' expr ')' '{' cases '}'
;
cases: allcases "default" ':' stmts
;
allcases: "case" expr ':' casestmts
| allcases "case" expr ':' casestmts
;
casestmts: casestmt
| casestmts casestmt
;
casestmt: "break"
| caseblock
| stmt
;
caseblock: '{' '}'
| '{' casestmts '}'
;
Objectives: simple language, generics, type inference, and unambiguous grammar.
I would like to hear your opinions, any help is very appreciated.
bison parser:
%union {
char *str;
}
%right '=' "+=" "-=" "*=" "/=" "%=" "~=" "&=" "|=" "^=" "<<=" ">>="
%left ':'
%right '?'
%left '|'
%left '^'
%left '&'
%left "or"
%left "and"
%left "==" "!="
%left '<' "<=" '>' ">="
%left "<<" ">>"
%left '+' '-'
%left '*' '/' '%'
%right "not" '~' PREFIX
%left "++" "--"
%left '['
%left '.'
%right '$'
%token <str> ID INT HEX BIN DOUBLE FLOAT COMPLEX STRING CHAR
%token-table
%%
program:
| program import
| program decl
;
import: "import" module
| "import" module "as" identifier
;
module: identifier
| module '.' identifier
;
decl: declvar
| declfunc
| declstruct
;
declvar: "var" identifier
| "var" identifier '=' expr
| "def" identifier '=' expr
;
declstruct: "def" identifier '{' declattrs '}'
;
declattrs: declattr
| declattrs declattr
;
declattr: "var" identifier
| declfunc
;
declfunc: "def" identifier '(' declargs ')' block
;
declargs: declarg
| declargs ',' declarg
;
declarg: identifier
| "var" identifier
| identifier identifier
;
block: '{' '}'
| '{' stmts '}'
;
stmts: stmt
| block
| stmts stmt
| stmts block
;
stmt: declvar
| purestmt
| identifier ':' purestmt
;
purestmt: assign
| call
| if
| for
| while
| switch
| "goto" identifier
| "return" expr
;
assign: lvalue '=' expr
| lvalue "+=" expr
| lvalue "-=" expr
| lvalue "*=" expr
| lvalue "/=" expr
| lvalue "%=" expr
| lvalue "~=" expr
| lvalue "&=" expr
| lvalue "|=" expr
| lvalue "^=" expr
| lvalue "<<=" expr
| lvalue ">>=" expr
| lvalue "++"
| lvalue "--"
// | "++" lvalue %prec PREFIX
// | "--" lvalue %prec PREFIX
;
lvalue: identifier
| lvalue '.' identifier
| lvalue '[' expr ']'
| '$' lvalue
;
identifier: ID
;
expr: literal
| lvalue
| assign
| call
| '~' expr
| '@' lvalue
| '-' expr %prec PREFIX
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '%' expr
| expr '&' expr
| expr '|' expr
| expr '^' expr
| "not" expr
| expr "==" expr
| expr "!=" expr
| expr '<' expr
| expr "<=" expr
| expr '>' expr
| expr ">=" expr
| expr "<<" expr
| expr ">>" expr
| expr "and" expr
| expr "or" expr
| expr '?' expr ':' expr
| "proc" '(' declargs ')' block
| '(' expr ')'
;
literal: INT
| HEX
| BIN
| FLOAT
| DOUBLE
| COMPLEX
| STRING
| CHAR
;
call: onecall
| call '.' onecall
;
onecall: lvalue '(' args ')'
;
args:
| expr
| args ',' expr
;
if: "if" '(' expr ')' block
| "if" '(' expr ')' block "else" block
;
for : "for" '(' forarg "in" foriter ')' loop
| "for" '(' forinit ';' expr ';' forincr ')' loop
;
forarg: identifier
| "var" identifier
;
forinit: forinitarg
| forinit ',' forinitarg
;
forinitarg: assign
| "var" identifier '=' expr
;
forincr: assign
| forincr ',' assign
;
foriter: lvalue
| call
;
loop: ';'
| loopblock
;
loopblock: '{' '}'
| '{' loopstmts '}'
;
loopstmts: loopstmt
| loopstmts loopstmt
;
loopstmt: "break"
| "continue"
| loopblock
| stmt
;
while: "while" '(' expr ')' loop
| "do" loopblock "while" '(' expr ')'
;
switch: "switch" '(' expr ')' '{' cases '}'
;
cases: allcases "default" ':' stmts
;
allcases: "case" expr ':' casestmts
| allcases "case" expr ':' casestmts
;
casestmts: casestmt
| casestmts casestmt
;
casestmt: "break"
| caseblock
| stmt
;
caseblock: '{' '}'
| '{' casestmts '}'
;