Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Help with unambiguous grammar

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 '}'
         ;

Name: Anonymous 2012-01-14 15:35

>>42
Yes, it's just an bad example :P
Here, a parseable n-body code (translated from http://shootout.alioth.debian.org/u32/program.php?test=nbody&lang=gcc&id=1):
let PI = 3.141592653589793
let SOLAR_MASS = 4 * PI * PI
let DAYS_PER_YEAR = 365.24

def main(args : array[string]) {
    let n = parseInt(args[1])
    var system = createSystem()
   
    printf("%.9f\n", energy(system))
   
    for (var i = 0; i < n; i++) {
        advance(system, 0.01)
    }
   
    printf("%.9f\n", energy(system))
}

def createSystem() {
    var sun : Body = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS }
    var jupiter : Body = {
         4.84143144246472090e+00,
        -1.16032004402742839e+00,
        -1.03622044471123109e-01,
         1.66007664274403694e-03 * DAYS_PER_YEAR,
         7.69901118419740425e-03 * DAYS_PER_YEAR,
        -6.90460016972063023e-05 * DAYS_PER_YEAR,
         9.54791938424326609e-04 * SOLAR_MASS
    }
    var saturn : Body = {
         8.34336671824457987e+00,
         4.12479856412430479e+00,
        -4.03523417114321381e-01,
        -2.76742510726862411e-03 * DAYS_PER_YEAR,
         4.99852801234917238e-03 * DAYS_PER_YEAR,
         2.30417297573763929e-05 * DAYS_PER_YEAR,
         2.85885980666130812e-04 * SOLAR_MASS
    }
    var uranus : Body = {
         1.28943695621391310e+01,
        -1.51111514016986312e+01,
        -2.23307578892655734e-01,
         2.96460137564761618e-03 * DAYS_PER_YEAR,
         2.37847173959480950e-03 * DAYS_PER_YEAR,
        -2.96589568540237556e-05 * DAYS_PER_YEAR,
         4.36624404335156298e-05 * SOLAR_MASS
    }
    var neptune : Body = {
         1.53796971148509165e+01,
        -2.59193146099879641e+01,
         1.79258772950371181e-01,
         2.68067772490389322e-03 * DAYS_PER_YEAR,
         1.62824170038242295e-03 * DAYS_PER_YEAR,
        -9.51592254519715870e-05 * DAYS_PER_YEAR,
         5.15138902046611451e-05 * SOLAR_MASS
    }
    var system = { sun, jupiter, saturn, uranus, neptune }
    var px = 0.0
    var py = 0.0
    var pz = 0.0
    for (var body in system) {
        px += body.vx * body.mass
        py += body.vy * body.mass
        pz += body.vz * body.mass
    }
    offsetMomentum(sun, px, py, pz)
    return system
}

struct Body {
    x  : double
    y  : double
    z  : double
    vx : double
    vy : double
    vz : double
    mass : double
}

def offsetMomentum(p, x, y, z) {
    p.vx = -x / SOLAR_MASS
    p.vy = -y / SOLAR_MASS
    p.vz = -z / SOLAR_MASS
}

def advance(system, dt) {
    for (a in system) {
        for (b in system) {
            let dx = a.x - b.x
            let dy = a.y - b.y
            let dz = a.z - b.z

            let dSquared = dx * dx + dy * dy + dz * dz
            let distance = sqrt(dSquared)
            let mag = dt / (dSquared * distance)

            a.vx -= dx * b.mass * mag
            a.vy -= dy * b.mass * mag
            a.vz -= dz * b.mass * mag

            b.vx += dx * a.mass * mag
            b.vy += dy * a.mass * mag
            b.vz += dz * a.mass * mag
        }
    }
    for (body in system) {
        body.x += dt * body.vx
        body.y += dt * body.vy
        body.z += dt * body.vz
    }
}

def energy(system) {
    var e = 0.0
    for (a in system) {
        e += 0.5 * a.mass
                 * ( a.vx * a.vx
                   + a.vy * a.vy
                   + a.vz * a.vz )
        for (b in system) {
            let dx = body.x - b.x
            let dy = body.y - b.y
            let dz = body.z - b.z
            let distance = sqrt(dx*dx + dy*dy + dz*dz)
            e -= (a.mass * b.mass) / distance
        }
    }
    return e
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List