Skip to content

Commit

Permalink
write boilerplate for parser
Browse files Browse the repository at this point in the history
  • Loading branch information
robertDurst committed Jan 9, 2024
1 parent e47f1b1 commit 58c6eb3
Show file tree
Hide file tree
Showing 2 changed files with 223 additions and 147 deletions.
14 changes: 14 additions & 0 deletions spec/zodiac/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,19 @@
expect(actual).to eq(expected)
end
end

context 'when simple expression' do
xit 'returns simple expression' do
parser = described_class.new('1 + 2')

actual = parser.parse
expected = {
kind: 'PROGRAM',
cmp_stmts: []
}

expect(actual).to eq(expected)
end
end
end
end
356 changes: 209 additions & 147 deletions src/zodiac/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,153 +4,6 @@

module Zodiac
# Base parsing class for the Zodiac language.

# Here is the syntax of Ruby in pseudo BNF. For more detail, see parse.y in Ruby distribution.

# ARG : LHS `=' ARG
# | LHS OP_ASGN ARG
# | ARG `..' ARG
# | ARG `...' ARG
# | ARG `+' ARG
# | ARG `-' ARG
# | ARG `*' ARG
# | ARG `/' ARG
# | ARG `%' ARG
# | ARG `**' ARG
# | `+' ARG
# | `-' ARG
# | ARG `|' ARG
# | ARG `^' ARG
# | ARG `&' ARG
# | ARG `<=>' ARG
# | ARG `>' ARG
# | ARG `>=' ARG
# | ARG `<' ARG
# | ARG `<=' ARG
# | ARG `==' ARG
# | ARG `===' ARG
# | ARG `!=' ARG
# | ARG `=~' ARG
# | ARG `!~' ARG
# | `!' ARG
# | `~' ARG
# | ARG `<<' ARG
# | ARG `>>' ARG
# | ARG `&&' ARG
# | ARG `||' ARG
# | defined? ARG
# | PRIMARY

# PRIMARY : `(' COMPSTMT `)'
# | LITERAL
# | VARIABLE
# | PRIMARY `::' IDENTIFIER
# | `::' IDENTIFIER
# | PRIMARY `[' [ARGS] `]'
# | `[' [ARGS [`,']] `]'
# | `{' [(ARGS|ASSOCS) [`,']] `}'
# | return [`(' [CALL_ARGS] `)']
# | yield [`(' [CALL_ARGS] `)']
# | defined? `(' ARG `)'
# | FUNCTION
# | FUNCTION `{' [`|' [BLOCK_VAR] `|'] COMPSTMT `}'
# | if EXPR THEN
# COMPSTMT
# (elsif EXPR THEN COMPSTMT)*
# [else COMPSTMT]
# end
# | unless EXPR THEN
# COMPSTMT
# [else COMPSTMT]
# end
# | while EXPR DO COMPSTMT end
# | until EXPR DO COMPSTMT end
# | case COMPSTMT
# (when WHEN_ARGS THEN COMPSTMT)+
# [else COMPSTMT]
# end
# | for BLOCK_VAR in EXPR DO
# COMPSTMT
# end
# | begin
# COMPSTMT
# [rescue [ARGS] DO COMPSTMT]+
# [else COMPSTMT]
# [ensure COMPSTMT]
# end
# | class IDENTIFIER [`<' IDENTIFIER]
# COMPSTMT
# end
# | module IDENTIFIER
# COMPSTMT
# end
# | def FNAME ARGDECL
# COMPSTMT
# end
# | def SINGLETON (`.'|`::') FNAME ARGDECL
# COMPSTMT
# end

# WHEN_ARGS : ARGS [`,' `*' ARG]
# | `*' ARG

# THEN : TERM
# | then
# | TERM then

# DO : TERM
# | do
# | TERM do

# BLOCK_VAR : LHS
# | MLHS

# MLHS : MLHS_ITEM `,' [MLHS_ITEM (`,' MLHS_ITEM)*] [`*' [LHS]]
# | `*' LHS

# MLHS_ITEM : LHS
# | '(' MLHS ')'

# LHS : VARIABLE
# | PRIMARY `[' [ARGS] `]'
# | PRIMARY `.' IDENTIFIER

# MRHS : ARGS [`,' `*' ARG]
# | `*' ARG

# CALL_ARGS : ARGS
# | ARGS [`,' ASSOCS] [`,' `*' ARG] [`,' `&' ARG]
# | ASSOCS [`,' `*' ARG] [`,' `&' ARG]
# | `*' ARG [`,' `&' ARG]
# | `&' ARG
# | COMMAND

# ARGS : ARG (`,' ARG)*

# ARGDECL : `(' ARGLIST `)'
# | ARGLIST TERM

# ARGLIST : IDENTIFIER(`,'IDENTIFIER)*[`,'`*'[IDENTIFIER]][`,'`&'IDENTIFIER]
# | `*'IDENTIFIER[`,'`&'IDENTIFIER]
# | [`&'IDENTIFIER]

# SINGLETON : VARIABLE
# | `(' EXPR `)'

# ASSOCS : ASSOC (`,' ASSOC)*

# ASSOC : ARG `=>' ARG

# VARIABLE : VARNAME
# | nil
# | self

# LITERAL : numeric
# | SYMBOL
# | STRING
# | STRING2
# | HERE_DOC
# | REGEXP
class Parser
def initialize(raw_string)
@raw_string = raw_string
Expand Down Expand Up @@ -178,6 +31,13 @@ def parse_program

# COMPSTMT : STMT (TERM EXPR)* [TERM]
def parse_compstmt
parse_stmt

while @cur_index < @tokens.length
parse_term
parse_expr
end

{ kind: 'COMPSTMT', value: nil }
end

Expand Down Expand Up @@ -246,5 +106,207 @@ def parse_command
def parse_function
{ kind: 'FUNCTION', value: nil }
end

# THEN : TERM
# | then
# | TERM then
def parse_then
{ kind: 'THEN', value: nil }
end

# DO : TERM
# | do
# | TERM do
def parse_do
{ kind: 'DO', value: nil }
end

# BLOCK_VAR : LHS
# | MLHS
def parse_block_var
{ kind: 'BLOCK_VAR', value: nil }
end

# MLHS : MLHS_ITEM `,' [MLHS_ITEM (`,' MLHS_ITEM)*] [`*' [LHS]]
# | `*' LHS
def parse_mlhs
{ kind: 'MLHS', value: nil }
end

# ARG : LHS `=' ARG
# | LHS OP_ASGN ARG
# | ARG `..' ARG
# | ARG `...' ARG
# | ARG `+' ARG
# | ARG `-' ARG
# | ARG `*' ARG
# | ARG `/' ARG
# | ARG `%' ARG
# | ARG `**' ARG
# | `+' ARG
# | `-' ARG
# | ARG `|' ARG
# | ARG `^' ARG
# | ARG `&' ARG
# | ARG `<=>' ARG
# | ARG `>' ARG
# | ARG `>=' ARG
# | ARG `<' ARG
# | ARG `<=' ARG
# | ARG `==' ARG
# | ARG `===' ARG
# | ARG `!=' ARG
# | ARG `=~' ARG
# | ARG `!~' ARG
# | `!' ARG
# | `~' ARG
# | ARG `<<' ARG
# | ARG `>>' ARG
# | ARG `&&' ARG
# | ARG `||' ARG
# | defined? ARG
# | PRIMARY
def parse_arg
{ kind: 'ARG', value: nil }
end

# PRIMARY : `(' COMPSTMT `)'
# | LITERAL
# | VARIABLE
# | PRIMARY `::' IDENTIFIER
# | `::' IDENTIFIER
# | PRIMARY `[' [ARGS] `]'
# | `[' [ARGS [`,']] `]'
# | `{' [(ARGS|ASSOCS) [`,']] `}'
# | return [`(' [CALL_ARGS] `)']
# | yield [`(' [CALL_ARGS] `)']
# | defined? `(' ARG `)'
# | FUNCTION
# | FUNCTION `{' [`|' [BLOCK_VAR] `|'] COMPSTMT `}'
# | if EXPR THEN
# COMPSTMT
# (elsif EXPR THEN COMPSTMT)*
# [else COMPSTMT]
# end
# | unless EXPR THEN
# COMPSTMT
# [else COMPSTMT]
# end
# | while EXPR DO COMPSTMT end
# | until EXPR DO COMPSTMT end
# | case COMPSTMT
# (when WHEN_ARGS THEN COMPSTMT)+
# [else COMPSTMT]
# end
# | for BLOCK_VAR in EXPR DO
# COMPSTMT
# end
# | begin
# COMPSTMT
# [rescue [ARGS] DO COMPSTMT]+
# [else COMPSTMT]
# [ensure COMPSTMT]
# end
# | class IDENTIFIER [`<' IDENTIFIER]
# COMPSTMT
# end
# | module IDENTIFIER
# COMPSTMT
# end
# | def FNAME ARGDECL
# COMPSTMT
# end
# | def SINGLETON (`.'|`::') FNAME ARGDECL
# COMPSTMT
# end
def parse_primary
{ kind: 'PRIMARY', value: nil }
end

# WHEN_ARGS : ARGS [`,' `*' ARG]
# | `*' ARG
def parse_when_args
{ kind: 'WHEN_ARGS', value: nil }
end

# MLHS_ITEM : LHS
# | '(' MLHS ')'
def parse_mlhs_item
{ kind: 'MLHS_ITEM', value: nil }
end

# LHS : VARIABLE
# | PRIMARY `[' [ARGS] `]'
# | PRIMARY `.' IDENTIFIER
def parse_lhs
{ kind: 'LHS', value: nil }
end

# MRHS : ARGS [`,' `*' ARG]
# | `*' ARG
def parse_mrhs
{ kind: 'MRHS', value: nil }
end

# CALL_ARGS : ARGS
# | ARGS [`,' ASSOCS] [`,' `*' ARG] [`,' `&' ARG]
# | ASSOCS [`,' `*' ARG] [`,' `&' ARG]
# | `*' ARG [`,' `&' ARG]
# | `&' ARG
# | COMMAND
def parse_call_args
{ kind: 'CALL_ARGS', value: nil }
end

# ARGS : ARG (`,' ARG)*
def parse_args
{ kind: 'ARGS', value: nil }
end

# ARGDECL : `(' ARGLIST `)'
# | ARGLIST TERM
def parse_argdecl
{ kind: 'ARGDECL', value: nil }
end

# ARGLIST : IDENTIFIER(`,'IDENTIFIER)*[`,'`*'[IDENTIFIER]][`,'`&'IDENTIFIER]
# | `*'IDENTIFIER[`,'`&'IDENTIFIER]
# | [`&'IDENTIFIER]
def parse_arglist
{ kind: 'ARGLIST', value: nil }
end

# SINGLETON : VARIABLE
# | `(' EXPR `)'
def parse_singleton
{ kind: 'SINGLETON', value: nil }
end

# ASSOCS : ASSOC (`,' ASSOC)*
def parse_assocs
{ kind: 'ASSOCS', value: nil }
end

# ASSOC : ARG `=>' ARG
def parse_assoc
{ kind: 'ASSOC', value: nil }
end

# VARIABLE : VARNAME
# | nil
# | self
def parse_variable
{ kind: 'VARIABLE', value: nil }
end

# LITERAL : numeric
# | SYMBOL
# | STRING
# | STRING2
# | HERE_DOC
# | REGEXP
def parse_literal
{ kind: 'LITERAL', value: nil }
end
end
end

0 comments on commit 58c6eb3

Please sign in to comment.