source: applications/trunk/LFC/parser/GrammarParser.rf

Last change on this file was 4080, checked in by orlov, 12 years ago
  • Names are represented as compound symbols, not (terms).
  • Property svn:eol-style set to native
File size: 3.0 KB
Line 
1$use Convert Lexer StdIO Stream;
2
3$func Main = e;
4Main =
5  <WriteLn <ParseGrammarFile "samples.g">>;
6
7$public $func ParseGrammarFile e.fname = e.grammar;
8ParseGrammarFile e.fname =
9  <ParseGrammar <File_Open e.fname>>;
10
11$func ParseGrammar stream = e.grammar;
12ParseGrammar stream =
13  $iter <SkipBlanks stream> e.grammar <ParseProduction <Get_While stream &NotBlank>> :: e.grammar,
14  <IsEnd_of_Stream stream> =
15  e.grammar;
16
17$func? NotBlank term = ;
18NotBlank term = # <IsBlank term>;
19
20$func? IsBlank term = ;
21IsBlank \{ ' '; '\t'; '\n'; '\r'; };
22
23$func SkipBlanks stream = ;
24SkipBlanks stream = <Get_While stream &IsBlank> : e;
25
26$func ParseProduction e.production = e.ast;
27ParseProduction e.production =
28  e.production : {
29    '<' e.ident '>->' e.terms = (PROD <CheckIdentifier e.ident (e.production)> <ParseTerms e.terms (e.production)>);
30    '[' e.ident ']->' e.terms = (NONTOKEN <CheckIdentifier e.ident (e.production)> <ParseTerms e.terms (e.production)>);
31    v = $error "Invalid left part in the production " e.production;
32    /*empty*/ = /*empty*/;
33};
34
35$func CheckIdentifier e.ident (e.production) = t.ast;
36CheckIdentifier e.ident (e.production) =
37  {
38    <ScanIdentifier e.ident 0 0> : e () s s = (TYPE <ToWord e.ident>);
39    $error "Invalid nonterminal name in the left part of the production " e.production;
40  };
41
42$func ParseTerms e.terms (e.production) = e.ast;
43ParseTerms {
44  e.term s.last '|' e.rest (e.production), # \{ s.last : '\\'; } =
45    (<ParseItems e.term s.last (e.production)>) <ParseTerms e.rest (e.production)>;
46  v.term (e.production) = (<ParseItems v.term (e.production)>);
47  (e.production) = $error "Empty term in the production " e.production;
48};
49
50$func ParseItems e.items (e.production) = e.ast;
51ParseItems {
52  '<' e.ident '>' e.rest (e.production) =
53    <CheckIdentifier e.ident (e.production)> <ParseItems e.rest (e.production)>;
54  e.str s.last '<' e.ident '>' e.rest (e.production), # \{ s.last : '\\'; } =
55    <ParseString e.str s.last (e.production)> <CheckIdentifier e.ident (e.production)> <ParseItems e.rest (e.production)>;
56  v.str (e.production) = <ParseString v.str (e.production)>;
57  (e) = /*empty*/;
58};
59
60$func ParseString e.str (e.production) = e.ast;
61ParseString {
62  (e) = /*empty*/;
63  s.ch e.str (e.production) = s.ch : {
64    '~' = () e.str;
65    '\\' = e.str : {
66      '|'  e.rest = ('|')  e.rest;
67      '<'  e.rest = ('<')  e.rest;
68      '>'  e.rest = ('>')  e.rest;
69      '['  e.rest = ('[')  e.rest;
70      ']'  e.rest = (']')  e.rest;
71      '_'  e.rest = (' ')  e.rest;
72      'n'  e.rest = ('\n') e.rest;
73      'r'  e.rest = ('\r') e.rest;
74      't'  e.rest = ('\t') e.rest;
75      '~'  e.rest = ('~')  e.rest;
76      '\\' e.rest = ('\\') e.rest;
77      s1 s2 s3 e.rest,
78        '01234567' : e s1 e,
79        '01234567' : e s2 e,
80        '01234567' : e s3 e =
81        (<BytesToChars <ToInt s1 s2 s3>>) e.rest;
82      e = $error "Invalid sequence after \\ in the production " e.production;
83    };
84    s = (s.ch) e.str;
85  } :: (e.chars) e.rest =
86    e.chars <ParseString e.rest (e.production)>;
87};
Note: See TracBrowser for help on using the repository browser.