Compiler/syntax analyzer: Difference between revisions

m
J: simplify (tok_name and tok_type were basically redundant in this implementation)
(J: bugfix: no right associative operators (previous implementation: all binary operators were right associative))
m (J: simplify (tok_name and tok_type were basically redundant in this implementation))
Line 3,313:
Keyword_while Semicolon Comma Keyword_putc RightParen
Identifier String Integer
}}-.LF
tkref,.(tktyp)=:tktyp=:;: {{)n
tkEOI tkMul tkDiv tkMod tkAdd tkSub tkNeg tkLss tkLeq tkGtr tkGeq tkEql
tkNeq tkNot tkAnd tkOr tkPrint tkAssign tkPrint tkLpar tkIf tkLbra tkElse
tkRbra tkWhile tkSemi tkComma tkPutc tkRpar tkId tkString tkInt
}}-.LF
Line 3,325 ⟶ 3,319:
tkPrec=: 13 13 13 12 12 10 10 10 10 9 9 5 4 (tkref i.tokenize'*/%+-<<=>>==!=&&||')} tkV<._1
tkPrec=: 14 (1 0+tkref i.tokenize'-!')} tkPrec
NB. proofread |:(<"1 tkV,.tkPrec),tktyp,tkref,:tknames
ndRef=: tkref
Line 3,334 ⟶ 3,328:
}}-.LF
NB. proofread |:ndRef,:ndDisp
tok_pfx=: {{
if.'tok_'-:4{. y do. y else.'tok_',y end.
}}L:0
tok_s=: tok_pfx ;:'ln col name value text type valence precedence display'
tok=: {{
do tok_s{::~tok_s i. boxopen tok_pfx y
:
x{::~tok_s i. boxopen tok_pfx y
}}
gettoken=: {{
Line 3,354 ⟶ 3,337:
ind=. tknames i.<tok_name
tok_text=: ind{::tkref
tok_type=: ind{::tktyp
tok_valence=: ind{::tkV
tok_precedence=: ind{::tkPrec
node_display=: ndDisp{::~tktyp i.<tok_type
ndx=:ndx+1
node_display=: ndDispind{::~tktyp i.<tok_typendDisp
".each tok_s
}}
NB. syntax analyzer
parse=: {{
Line 3,369 ⟶ 3,348:
gettok''
t=.a:
whilst.-.(a:-:t)+.tok_typetok_name-:tkEOIEnd_of_input do.
t=. Sequence make_node t stmt''
end.
Line 3,376 ⟶ 3,355:
stmt=:{{)v
t=. a:
select.tok_typetok_name
case.tkIfKeyword_if do.
s=. stmt e=. paren_expr gettok''
if.tkElseKeyword_else-:tok_typetok_name
do. S=. stmt gettok''
else. S=. a: end.
t=. If make_node e If make_node s S
case.tkPutcKeyword_putc do.
e=. paren_expr gettok''
t=. Putc make_node e a:
Putc expect tkSemiSemicolon
case.tkPrintKeyword_print do.gettok''
'Print' expect tkLparLeftParen
while.do.
if.tkStringString-:tok_typetok_name
do. gettok e=. Prts make_node (String make_leaf tok_value) a:
else. e=. Prti make_node (expr 0) a: end.
t=. Sequence make_node t e
if.tkCommaComma-:tok_typetok_name
do.Comma expect tkCommaComma
else.break.end.
end.
'Print' expect tkRparRightParen
'Print' expect tkSemiSemicolon
case.tkSemiSemicolon do.gettok''
case.tkIdIdentifier do.
gettok v=. Identifier make_leaf tok_value
Assign expect tkAssignOp_assign
t=. Assign make_node v e=. expr 0
Assign expect tkSemiSemicolon
case.tkWhileKeyword_while do.
t=. While make_node e s=. stmt e=. paren_expr gettok''
case.tkLbraLeftBrace do.
'LBraceLeftBrace' expect tkLbraLeftBrace
while.-.(<tok_typetok_name) e. tkRbraRightBrace;tkEOIEnd_of_input do.
t=. Sequence make_node t stmt''
end.
'LbraceLeftBrace' expect tkRbraRightBrace
case.tkEOIEnd_of_input do.
case.do. error 'Expecting start of statement, found %s'sprintf<tok_text
end.
Line 3,421 ⟶ 3,400:
paren_expr=: {{
'paren_expr' expect tkLparLeftParen
t=. expr 0
'paren_expr' expect tkRparRightParen
t
}}
Line 3,429 ⟶ 3,408:
not_prec=: tkPrec{~tknames i.<Op_not
expr=: {{
select.tok_typetok_name
case.tkLparLeftParen do.e=. paren_expr''
case.tkAddOp_add do.gettok''
e=. expr not_prec
case.tkSubOp_subtract do.gettok''
e=. Negate make_node (expr not_prec) a:
case.tkNotOp_not do.gettok''
e=. Not make_node (expr not_prec) a:
case.tkIdIdentifier do.
gettok e=. Identifier make_leaf tok_value
case.tkIntInteger do.
gettok e=. Integer make_leaf tok_value
case.do. error 'Expecting a primary, found %s'sprintf<tok_text
end.
while.(2=tok_valence)*y<:tok_precedence>:y do.
q=. 1+tok_precedence [ op=. node_display NB. no right associative operators
gettok''
enode=. op make_node e expr q
e=. op make_node e node
end.
e
Line 3,452 ⟶ 3,432:
expect=: {{
if.y-:tok_typetok_name do. gettok'' return.end.
error '%s: Expecting "%s", found "%s"'sprintf x;(tkref{::~tktyptknames i.<y);tok_text
}}
Line 3,481 ⟶ 3,461:
case.do.assert.0
end.
}}</lang>
</lang>
 
Some quirks worth noting:
6,951

edits