Revision 27387 (by pmichaud, 2008/05/07 23:50:58) * Convert a variety of <foo: xyz> into <foo: 'xyz'>. (RT#53606)
# $Id: grammar.pg 27387 2008-05-07 23:50:58Z pmichaud $

=begin overview

This is the grammar for lolcode written as a sequence of Perl 6 rules.

=end overview

grammar lolcode::Grammar is PCT::Grammar;

rule TOP {
    'HAI' <version> <statement_terminator>
    <block>
    'KTHXBYE' <statement_terminator>
    [ $ || <panic: 'Syntax error'> ]
    {*}
}

token version { \d+ [ '.' \d+ ]? }

rule statement {
    | <declare>    {*}   #= declare
    | <assign>     {*}   #= assign
    | <function>   {*}   #= function
    | <ifthen>     {*}   #= ifthen
    | <expression> {*}   #= expression
}

token statement_terminator { [ ',' | \n+ | $ ] }

rule declare {
    'I' 'HAS' 'A' <variable> [ 'ITZ' <expression> ]?
    {*}
}

rule assign {
    <variable> 'R' <expression> {*}
}

rule function {
    # $<parameters> is only getting the first parameter, not all of them
    # like I'd expect...
    'HOW' 'DUZ' 'I' <variable> ['YR' $<parameters>=<variable> [ 'AN' 'YR' $<parameters>=<variable>]* ]?<statement_terminator>
    <block>
    'IF' 'U' 'SAY' 'SO'
    {*}
}

rule ifthen {
    <expression> <statement_terminator>
    'O' 'RLY?' <statement_terminator>
    'YA' 'RLY' <statement_terminator>
    <block>
    [
      'MEBBE' <expression> <statement_terminator>
      <block>
    ]*
    [
      'NO' 'WAI' <statement_terminator>
      $<else>=<block>
    ]?
    'OIC'
    {*}
}

rule switch {
    <expression> <statement_terminator>
    'WTF?' <statement_terminator>
    [
      'OMG' <value> <statement_terminator>
      <block>
    ]+
    [
      'OMGWTF' <statement_terminator>
      <block>
    ]?
    'OIC'
}

rule block {
    [<statement> <statement_terminator>]* {*}
}

rule parameters {
    'YR' <identifier> [ 'AN' 'YR' <identifier> ]*
}

rule expression {
    [
    | $<tokens>=<operator>
    | $<tokens>=<variable>
    | $<tokens>=<value>
    | 'AN'
    | $<tokens>='MKAY'
    ]+ {*}
}

token value {
    | <float>    {*}                             #= float
    | <integer>  {*}                             #= integer
    | <boolean>  {*}                             #= boolean
    | <quote>    {*}                             #= quote
    | <bang>     {*}                             #= bang
}

token bang {
    '!' {*}
}

token operator { $<identifier>=(<.identifier> <.ws> 'OF') {*} }
token variable { <identifier> {*} }

token identifier { <!keyword> <[a..zA..Z]> \w* }

# RT #46213 : Because PGE doesn't yet know how to do longest token matching,
# order all tokens in reverse alpha order to avoid a parsing bug.
token keyword {
    [ 'YR' | 'YA' | 'WTF?' | 'WIN' | 'WAI' | 'U' | 'SO'
    | 'SAY' | 'RLY?' | 'RLY' | 'R' 
    | 'OMGWTF' | 'OMG' | 'OIC' | 'OF' | 'O' | 'NO' | 'MKAY' | 'MEBBE' | 'KTHXBYE'
    | 'ITZ' | 'IF' | 'I' | 'HOW' | 'HAS' | 'GTFO' | 'FOUND' | 'FAIL' 
    | 'AN' | 'A' ] >>
}

token integer { '-'? \d+ {*} }

token float { '-'? \d+ '.' \d+ {*} }

rule boolean { [ 'WIN' | 'FAIL' ] {*} }

rule quote {
    [ <.before '"'> <yarn_literal> ]
    {*}
}

token ws { <!ww> [
    | ^^ \h* BTW \h \N* \n+
    | ^^ \h* OBTW .*? ^^ \h* TLDR \n+
    | \h+
    ]*
}