⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calc.ly

📁 編譯器 像YACC的編譯及語法產生器
💻 LY
字号:
> {> module Calc where> import Char> }First thing to declare is the name of your parser,and the type of the tokens the parser reads.> %name calc> %tokentype { Token }The parser will be of type [Token] -> ?, where ? is determined by theproduction rules.  Now we declare all the possible tokens:> %token >	let		{ TokenLet }>	in		{ TokenIn }>	int		{ TokenInt $$ }>	var		{ TokenVar $$ }>	'='		{ TokenEq }>	'+'		{ TokenPlus }>	'-'		{ TokenMinus }>	'*'		{ TokenTimes }>	'/'		{ TokenDiv }>	'('		{ TokenOB }>	')'		{ TokenCB }The left hand side are the names of the terminals or tokens,and the right hand side is how to pattern match them.Like yacc, we include %% here, for no real reason.> %%Now we have the production rules.> Exp :: { Exp }> Exp : let var '=' Exp in Exp	{ Let $2 $4 $6 }>     | Exp1			{ Exp1 $1 }> > Exp1 : Exp1 '+' Term		{ Plus $1 $3 }>      | Exp1 '-' Term		{ Minus $1 $3 }>      | Term			{ Term $1 }> > Term : Term '*' Factor	{ Times $1 $3 }>      | Term '/' Factor	{ Div $1 $3 }>      | Factor			{ Factor $1 }> > Factor : int			{ Int $1 }> 	 | var			{ Var $1 }> 	 | '(' Exp ')'		{ Brack $2 }We are simply returning the parsed data structure !Now we need some extra code, to support this parser,and make in complete:> {All parsers must declair this function, which is called when an error is detected.Note that currently we do no error recovery.> happyError :: [Token] -> a> happyError _ = error ("Parse error\n")Now we declare the datastructure that we are parsing.> data Exp  = Let String Exp Exp | Exp1 Exp1 > data Exp1 = Plus Exp1 Term | Minus Exp1 Term | Term Term > data Term = Times Term Factor | Div Term Factor | Factor Factor > data Factor = Int Int | Var String | Brack Exp The datastructure for the tokens...> data Token>	= TokenLet>	| TokenIn>	| TokenInt Int>	| TokenVar String>	| TokenEq>	| TokenPlus>	| TokenMinus>	| TokenTimes>	| TokenDiv>	| TokenOB>	| TokenCB.. and a simple lexer that returns this datastructure.> lexer :: String -> [Token]> lexer [] = []> lexer (c:cs) >	| isSpace c = lexer cs> 	| isAlpha c = lexVar (c:cs)>	| isDigit c = lexNum (c:cs)> lexer ('=':cs) = TokenEq : lexer cs> lexer ('+':cs) = TokenPlus : lexer cs> lexer ('-':cs) = TokenMinus : lexer cs> lexer ('*':cs) = TokenTimes : lexer cs> lexer ('/':cs) = TokenDiv : lexer cs> lexer ('(':cs) = TokenOB : lexer cs> lexer (')':cs) = TokenCB : lexer cs> lexNum cs = TokenInt (read num) : lexer rest>	where (num,rest) = span isDigit cs> lexVar cs =>    case span isAlpha cs of>	("let",rest) -> TokenLet : lexer rest>	("in",rest)  -> TokenIn : lexer rest>	(var,rest)   -> TokenVar var : lexer restTo run the program, call this in gofer, or use some codeto print it. runCalc :: String -> Exp runCalc = calc . lexerHere we test our parser. main = case runCalc "1 + 2 + 3" of {	(Exp1 (Plus (Plus (Term (Factor (Int 1))) (Factor (Int 2))) (Factor (Int 3))))  -> 	case runCalc "1 * 2 + 3" of {	(Exp1 (Plus (Term (Times (Factor (Int 1)) (Int 2))) (Factor (Int 3)))) ->	case runCalc "1 + 2 * 3" of {	(Exp1 (Plus (Term (Factor (Int 1))) (Times (Factor (Int 2)) (Int 3)))) ->	case runCalc "let x = 2 in x * (x - 2)" of {	(Let "x" (Exp1 (Term (Factor (Int 2)))) (Exp1 (Term (Times (Factor (Var "x")) (Brack (Exp1 (Minus (Term (Factor (Var "x"))) (Factor (Int 2))))))))) -> print "AndysTest works\n" ; 	_ -> quit } ; _ -> quit } ; _ -> quit } ; _ -> quit } quit = print "runCalc failed\n"> }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -