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

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