try to understand how to generate a parser

top -> TO fundef | COLON macro | ex #

to top = 
  if (tok == TO)
    lex
    commit fundef
    1
  if (tok == COLON)
    lex
    commit macro
    1
  ex

fundef -> IDEN args EQ ex

to fundef =
  if (tok == IDEN)
    commit args
    expect EQ
    lex
    commit ex
    1
  ; else
    0

args ->
  @ IDEN args | BAR local | nil #

to args =
  while tok == IDEN
    lex
  if tok == BAR
    lex
    commit local
    1
  ; else
    1

ex ->  BB exs BE | ex1 #
  
to ex =
  if tok == BB
    lex
    commit exs
    expect BE
    lex
    1
  ; else
    ex1

exs -> @ ex1 exs | nil #

to exs =
  while ex1 {}
  1

ex1 -> 
  IF ex0 ex exelse |
  FOR IDEN ex0 ex0 ex |
  exas #

to ex1 =
  if tok == IF
    lex
    commit ex0
    commit ex
    commit exelse
    1
  if tok == FOR
    lex
    expect IDEN
    lex
    commit ex0
    commit ex0
    commit ex
    1
  ; else
    exas

exelse -> ELSE ex | nil #

to exelse =
  if tok == ELSE
    lex
    commit ex        // whether to commit the last one?
    1
  ; else
    1
    

ex0 -> term terms #

to ex0 =
  if term
    terms
  ; else
    0

terms -> @ bop term terms | nil #

to terms =
  while bop
    commit term  //must commit otherwise 1 will pile up
  1

term -> 
  NUM | ... | IDEN | LPAR ex0 RPAR #

to term =
  case tok
  NUM: lex 1
  ...
  IDEN: lex 1
  LPAR: 
    lex 
    commit ex0
    expect RPAR
    lex
    1
  else: 0

alist -> @ aitem alist | nil #

to alist =
  while aitem {}
  1

aitem -> NUM | STR | IDEN #

to aitem =
  case tok
  NUM: lex 1
  STR: lex 1
  IDEN: lex 1
  else: 0

bop ->
  PLUS | MINUS ... | LTLT #

to bop =
  case tok
  PLUS: lex 1
  MINUS: lex 1
  ...
  LTLT: lex 1
  else: 0

15 sept 2009


